Fiddling with ATA driver to try and fix RHW issues
[tpg/acess2.git] / Modules / Storage / ATA / main.c
1 /*
2  * Acess2 IDE Harddisk Driver
3  * - main.c
4  */
5 #define DEBUG   1
6 #include <acess.h>
7 #include <modules.h>
8 #include <vfs.h>
9 #include <fs_devfs.h>
10 #include <drv_pci.h>
11 #include <tpl_drv_common.h>
12 #include <tpl_drv_disk.h>
13 #include "common.h"
14
15 // === STRUCTURES ===
16 typedef struct
17 {
18         Uint32  PBufAddr;
19         Uint16  Bytes;
20         Uint16  Flags;
21 } __attribute__ ((packed))      tPRDT_Ent;
22 typedef struct
23 {
24         Uint16  Flags;          // 1
25         Uint16  Usused1[9];     // 10
26         char    SerialNum[20];  // 20
27         Uint16  Usused2[3];     // 23
28         char    FirmwareVer[8]; // 27
29         char    ModelNumber[40];        // 47
30         Uint16  SectPerInt;     // 48 - AND with 0xFF to get true value;
31         Uint16  Unused3;        // 49
32         Uint16  Capabilities[2];        // 51
33         Uint16  Unused4[2];     // 53
34         Uint16  ValidExtData;   // 54
35         Uint16  Unused5[5];      // 59
36         Uint16  SizeOfRWMultiple;       // 60
37         Uint32  Sectors28;      // 62
38         Uint16  Unused6[100-62];
39         Uint64  Sectors48;
40         Uint16  Unused7[256-104];
41 } __attribute__ ((packed))      tIdentify;
42
43 // === IMPORTS ===
44 extern void     ATA_ParseMBR(int Disk, tMBR *MBR);
45
46 // === PROTOTYPES ===
47  int    ATA_Install();
48  int    ATA_SetupIO();
49 void    ATA_SetupPartitions();
50 void    ATA_SetupVFS();
51  int    ATA_ScanDisk(int Disk);
52 void    ATA_ParseGPT(int Disk);
53 void    ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length);
54 Uint16  ATA_GetBasePort(int Disk);
55 // Filesystem Interface
56 char    *ATA_ReadDir(tVFS_Node *Node, int Pos);
57 tVFS_Node       *ATA_FindDir(tVFS_Node *Node, char *Name);
58 Uint64  ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
59 Uint64  ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
60  int    ATA_IOCtl(tVFS_Node *Node, int Id, void *Data);
61 // Read/Write Interface/Quantiser
62 Uint    ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
63 Uint    ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
64 // Read/Write DMA
65  int    ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
66  int    ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
67 // IRQs
68 void    ATA_IRQHandlerPri(int unused);
69 void    ATA_IRQHandlerSec(int unused);
70 // Controller IO
71 Uint8   ATA_int_BusMasterReadByte(int Ofs);
72 void    ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
73 void    ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
74
75 // === GLOBALS ===
76 MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL, "PCI", NULL);
77 tDevFS_Driver   gATA_DriverInfo = {
78         NULL, "ata",
79         {
80                 .NumACLs = 1,
81                 .Size = -1,
82                 .Flags = VFS_FFLAG_DIRECTORY,
83                 .ACLs = &gVFS_ACL_EveryoneRX,
84                 .ReadDir = ATA_ReadDir,
85                 .FindDir = ATA_FindDir
86         }
87 };
88 tATA_Disk       gATA_Disks[MAX_ATA_DISKS];
89  int    giATA_NumNodes;
90 tVFS_Node       **gATA_Nodes;
91 Uint16  gATA_BusMasterBase = 0;
92 Uint8   *gATA_BusMasterBasePtr = 0;
93  int    gATA_IRQPri = 14;
94  int    gATA_IRQSec = 15;
95  int    giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller
96 Uint8   gATA_Buffers[2][(MAX_DMA_SECTORS+0xFFF)&~0xFFF] __attribute__ ((section(".padata")));
97 volatile int    gaATA_IRQs[2] = {0};
98 tPRDT_Ent       gATA_PRDTs[2] = {
99         {0, 512, IDE_PRDT_LAST},
100         {0, 512, IDE_PRDT_LAST}
101 };
102
103 // === CODE ===
104 /**
105  * \fn int ATA_Install()
106  */
107 int ATA_Install()
108 {
109         int     ret;
110
111         ret = ATA_SetupIO();
112         if(ret) return ret;
113
114         ATA_SetupPartitions();
115
116         ATA_SetupVFS();
117
118         if( DevFS_AddDevice( &gATA_DriverInfo ) == 0 )
119                 return MODULE_ERR_MISC;
120
121         return MODULE_ERR_OK;
122 }
123
124 /**
125  * \fn int ATA_SetupIO()
126  * \brief Sets up the ATA controller's DMA mode
127  */
128 int ATA_SetupIO()
129 {
130          int    ent;
131         tPAddr  addr;
132
133         ENTER("");
134
135         // Get IDE Controller's PCI Entry
136         ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1);
137         LOG("ent = %i", ent);
138         gATA_BusMasterBase = PCI_GetBAR4( ent );
139         if( gATA_BusMasterBase == 0 ) {
140                 Log_Warning("ATA", "It seems that there is no Bus Master Controller on this machine. Get one");
141                 // TODO: Use PIO mode instead
142                 LEAVE('i', MODULE_ERR_NOTNEEDED);
143                 return MODULE_ERR_NOTNEEDED;
144         }
145         
146         // Map memory
147         if( !(gATA_BusMasterBase & 1) )
148         {
149                 if( gATA_BusMasterBase < 0x100000 )
150                         gATA_BusMasterBasePtr = (void*)(KERNEL_BASE | (tVAddr)gATA_BusMasterBase);
151                 else
152                         gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
153                 LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
154         }
155         else {
156                 // Bit 0 is left set as a flag to other functions
157                 LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1);
158         }
159
160         // Register IRQs and get Buffers
161         IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
162         IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec );
163
164         gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[0] );
165         gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[1] );
166
167         LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
168
169         addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[0] );
170         LOG("addr = 0x%x", addr);
171         ATA_int_BusMasterWriteDWord(4, addr);
172         addr = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[1] );
173         LOG("addr = 0x%x", addr);
174         ATA_int_BusMasterWriteDWord(12, addr);
175
176         // Enable controllers
177         outb(IDE_PRI_BASE+1, 1);
178         outb(IDE_SEC_BASE+1, 1);
179
180         // return
181         LEAVE('i', MODULE_ERR_OK);
182         return MODULE_ERR_OK;
183 }
184
185 /**
186  * \fn void ATA_SetupPartitions()
187  */
188 void ATA_SetupPartitions()
189 {
190          int    i;
191         for( i = 0; i < MAX_ATA_DISKS; i ++ )
192         {
193                 if( !ATA_ScanDisk(i) ) {
194                         gATA_Disks[i].Name[0] = '\0';   // Mark as unused
195                         continue;
196                 }
197         }
198 }
199
200 /**
201  * \fn void ATA_SetupVFS()
202  * \brief Sets up the ATA drivers VFS information and registers with DevFS
203  */
204 void ATA_SetupVFS()
205 {
206          int    i, j, k;
207
208         // Count number of nodes needed
209         giATA_NumNodes = 0;
210         for( i = 0; i < MAX_ATA_DISKS; i++ )
211         {
212                 if(gATA_Disks[i].Name[0] == '\0')       continue;       // Ignore
213                 giATA_NumNodes ++;
214                 giATA_NumNodes += gATA_Disks[i].NumPartitions;
215         }
216
217         // Allocate Node space
218         gATA_Nodes = malloc( giATA_NumNodes * sizeof(void*) );
219
220         // Set nodes
221         k = 0;
222         for( i = 0; i < MAX_ATA_DISKS; i++ )
223         {
224                 if(gATA_Disks[i].Name[0] == '\0')       continue;       // Ignore
225                 gATA_Nodes[ k++ ] = &gATA_Disks[i].Node;
226                 for( j = 0; j < gATA_Disks[i].NumPartitions; j ++ )
227                         gATA_Nodes[ k++ ] = &gATA_Disks[i].Partitions[j].Node;
228         }
229
230         gATA_DriverInfo.RootNode.Size = giATA_NumNodes;
231 }
232
233 /**
234  * \fn int ATA_ScanDisk(int Disk)
235  */
236 int ATA_ScanDisk(int Disk)
237 {
238         union {
239                 Uint16  buf[256];
240                 tIdentify       identify;
241                 tMBR    mbr;
242         }       data;
243         Uint16  base;
244         Uint8   val;
245          int    i;
246         tVFS_Node       *node;
247
248         ENTER("iDisk", Disk);
249
250         base = ATA_GetBasePort( Disk );
251
252         LOG("base = 0x%x", base);
253
254         if( 0xFF == inb(base+7) ) {
255                 LOG("Floating bus");
256                 LEAVE('i', 0);
257                 return 0;
258         }
259
260         // Send Disk Selector
261         if(Disk == 1 || Disk == 3)
262                 outb(base+6, 0xB0);
263         else
264                 outb(base+6, 0xA0);
265
266         // Send IDENTIFY
267         outb(base+7, 0xEC);
268         val = inb(base+7);      // Read status
269         if(val == 0) {
270                 LEAVE('i', 0);
271                 return 0;       // Disk does not exist
272         }
273
274         // Poll until BSY clears and DRQ sets or ERR is set
275         while( ((val & 0x80) || !(val & 0x08)) && !(val & 1))   val = inb(base+7);
276
277         if(val & 1) {
278                 LEAVE('i', 0);
279                 return 0;       // Error occured, so return false
280         }
281
282         // Read Data
283         for(i=0;i<256;i++)      data.buf[i] = inw(base);
284
285         // Populate Disk Structure
286         if(data.identify.Sectors48 != 0)
287                 gATA_Disks[ Disk ].Sectors = data.identify.Sectors48;
288         else
289                 gATA_Disks[ Disk ].Sectors = data.identify.Sectors28;
290
291
292         LOG("gATA_Disks[ %i ].Sectors = 0x%x", Disk, gATA_Disks[ Disk ].Sectors);
293
294         {
295                 Uint64  val = gATA_Disks[ Disk ].Sectors / 2;
296                 char    *units = "KiB";
297                 if( val > 4*1024 ) {
298                         val /= 1024;
299                         units = "MiB";
300                 }
301                 else if( val > 4*1024 ) {
302                         val /= 1024;
303                         units = "GiB";
304                 }
305                 else if( val > 4*1024 ) {
306                         val /= 1024;
307                         units = "TiB";
308                 }
309                 Log_Log("ATA", "Disk %i: 0x%llx Sectors (%i %s)", Disk,
310                         gATA_Disks[ Disk ].Sectors, val, units);
311         }
312
313         // Create Name
314         gATA_Disks[ Disk ].Name[0] = 'A'+Disk;
315         gATA_Disks[ Disk ].Name[1] = '\0';
316
317         // Get pointer to vfs node and populate it
318         node = &gATA_Disks[ Disk ].Node;
319         node->Size = gATA_Disks[Disk].Sectors * SECTOR_SIZE;
320         node->NumACLs = 0;      // Means Superuser only can access it
321         node->Inode = (Disk << 8) | 0xFF;
322         node->ImplPtr = gATA_Disks[ Disk ].Name;
323
324         node->ATime = node->MTime
325                 = node->CTime = now();
326
327         node->Read = ATA_ReadFS;
328         node->Write = ATA_WriteFS;
329         node->IOCtl = ATA_IOCtl;
330
331         // --- Scan Partitions ---
332         LOG("Reading MBR");
333         // Read Boot Sector
334         ATA_ReadDMA( Disk, 0, 1, &data.mbr );
335
336         // Check for a GPT table
337         if(data.mbr.Parts[0].SystemID == 0xEE)
338                 ATA_ParseGPT(Disk);
339         else    // No? Just parse the MBR
340                 ATA_ParseMBR(Disk, &data.mbr);
341         
342         ATA_ReadDMA( Disk, 1, 1, &data );
343         Debug_HexDump("ATA_ScanDisk", &data, 512);
344
345         LEAVE('i', 0);
346         return 1;
347 }
348
349 /**
350  * \fn void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length)
351  * \brief Fills a parition's information structure
352  */
353 void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length)
354 {
355         ENTER("pPart iDisk iNum XStart XLength", Part, Disk, Num, Start, Length);
356         Part->Start = Start;
357         Part->Length = Length;
358         Part->Name[0] = 'A'+Disk;
359         if(Num >= 10) {
360                 Part->Name[1] = '1'+Num/10;
361                 Part->Name[2] = '1'+Num%10;
362                 Part->Name[3] = '\0';
363         } else {
364                 Part->Name[1] = '1'+Num;
365                 Part->Name[2] = '\0';
366         }
367         Part->Node.NumACLs = 0; // Only root can read/write raw block devices
368         Part->Node.Inode = (Disk << 8) | Num;
369         Part->Node.ImplPtr = Part->Name;
370
371         Part->Node.Read = ATA_ReadFS;
372         Part->Node.Write = ATA_WriteFS;
373         Part->Node.IOCtl = ATA_IOCtl;
374         Log_Notice("ATA", "Note '%s' at 0x%llx, 0x%llx long", Part->Name, Part->Start, Part->Length);
375         LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
376         LEAVE('-');
377 }
378
379 /**
380  * \fn void ATA_ParseGPT(int Disk)
381  * \brief Parses the GUID Partition Table
382  */
383 void ATA_ParseGPT(int Disk)
384 {
385         ///\todo Support GPT Disks
386         Warning("GPT Disks are currently unsupported");
387 }
388
389 /**
390  * \fn Uint16 ATA_GetPortBase(int Disk)
391  * \brief Returns the base port for a given disk
392  */
393 Uint16 ATA_GetBasePort(int Disk)
394 {
395         switch(Disk)
396         {
397         case 0: case 1:         return IDE_PRI_BASE;
398         case 2: case 3:         return IDE_SEC_BASE;
399         }
400         return 0;
401 }
402
403 /**
404  * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos)
405  */
406 char *ATA_ReadDir(tVFS_Node *Node, int Pos)
407 {
408         if(Pos >= giATA_NumNodes || Pos < 0)    return NULL;
409         return strdup( gATA_Nodes[Pos]->ImplPtr );
410 }
411
412 /**
413  * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
414  */
415 tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
416 {
417          int    part;
418         tATA_Disk       *disk;
419         
420         // Check first character
421         if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS)
422                 return NULL;
423         disk = &gATA_Disks[Name[0]-'A'];
424         // Raw Disk
425         if(Name[1] == '\0') {
426                 if( disk->Sectors == 0 && disk->Name[0] == '\0')
427                         return NULL;
428                 return &disk->Node;
429         }
430
431         // Partitions
432         if(Name[1] < '0' || '9' < Name[1])      return NULL;
433         if(Name[2] == '\0') {   // <= 9
434                 part = Name[1] - '0';
435                 part --;
436                 return &disk->Partitions[part].Node;
437         }
438         // > 9
439         if('0' > Name[2] || '9' < Name[2])      return NULL;
440         if(Name[3] != '\0')     return NULL;
441
442         part = (Name[1] - '0') * 10;
443         part += Name[2] - '0';
444         part --;
445         return &disk->Partitions[part].Node;
446
447 }
448
449 /**
450  * \fn Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
451  */
452 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
453 {
454          int    disk = Node->Inode >> 8;
455          int    part = Node->Inode & 0xFF;
456
457         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
458
459         // Raw Disk Access
460         if(part == 0xFF)
461         {
462                 if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE ) {
463                         LEAVE('i', 0);
464                         return 0;
465                 }
466                 if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
467                         Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
468         }
469         // Partition
470         else
471         {
472                 if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE ) {
473                         LEAVE('i', 0);
474                         return 0;
475                 }
476                 if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
477                         Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset;
478                 Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE;
479         }
480
481         {
482                 int ret = DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_ReadRaw, SECTOR_SIZE, disk);
483                 Debug_HexDump("ATA_ReadFS", Buffer, Length);
484                 LEAVE('i', ret);
485                 return ret;
486         }
487 }
488
489 /**
490  * \fn Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
491  */
492 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
493 {
494          int    disk = Node->Inode >> 8;
495          int    part = Node->Inode & 0xFF;
496
497         // Raw Disk Access
498         if(part == 0xFF)
499         {
500                 if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
501                         return 0;
502                 if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
503                         Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
504         }
505         // Partition
506         else
507         {
508                 if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
509                         return 0;
510                 if( Offset + Length > gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
511                         Length = gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE - Offset;
512                 Offset += gATA_Disks[disk].Partitions[part].Start * SECTOR_SIZE;
513         }
514
515         Log("ATA_WriteFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer);
516         Debug_HexDump("ATA_WriteFS", Buffer, Length);
517         return DrvUtil_WriteBlock(Offset, Length, Buffer, ATA_ReadRaw, ATA_WriteRaw, SECTOR_SIZE, disk);
518 }
519
520 /**
521  * \fn int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
522  * \brief IO Control Funtion
523  */
524 int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
525 {
526         switch(Id)
527         {
528         case DRV_IOCTL_TYPE:    return DRV_TYPE_DISK;
529         }
530         return 0;
531 }
532
533 // --- Disk Access ---
534 /**
535  * \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
536  */
537 Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
538 {
539          int    ret;
540         Uint    offset;
541         Uint    done = 0;
542
543         // Pass straight on to ATA_ReadDMAPage if we can
544         if(Count <= MAX_DMA_SECTORS)
545         {
546                 ret = ATA_ReadDMA(Disk, Address, Count, Buffer);
547                 if(ret == 0)    return 0;
548                 return Count;
549         }
550
551         // Else we will have to break up the transfer
552         offset = 0;
553         while(Count > MAX_DMA_SECTORS)
554         {
555                 ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
556                 // Check for errors
557                 if(ret != 1)    return done;
558                 // Change Position
559                 done += MAX_DMA_SECTORS;
560                 Count -= MAX_DMA_SECTORS;
561                 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
562         }
563
564         ret = ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset);
565         if(ret != 1)    return 0;
566         return done+Count;
567 }
568
569 /**
570  * \fn Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
571  */
572 Uint ATA_WriteRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
573 {
574          int    ret;
575         Uint    offset;
576         Uint    done = 0;
577
578         // Pass straight on to ATA_WriteDMA, if we can
579         if(Count <= MAX_DMA_SECTORS)
580         {
581                 ret = ATA_WriteDMA(Disk, Address, Count, Buffer);
582                 if(ret == 0)    return 0;
583                 return Count;
584         }
585
586         // Else we will have to break up the transfer
587         offset = 0;
588         while(Count > MAX_DMA_SECTORS)
589         {
590                 ret = ATA_WriteDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
591                 // Check for errors
592                 if(ret != 1)    return done;
593                 // Change Position
594                 done += MAX_DMA_SECTORS;
595                 Count -= MAX_DMA_SECTORS;
596                 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
597         }
598
599         ret = ATA_WriteDMA(Disk, Address+offset, Count, Buffer+offset);
600         if(ret != 1)    return 0;
601         return done+Count;
602 }
603
604 /**
605  * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
606  */
607 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
608 {
609          int    cont = (Disk>>1)&1;     // Controller ID
610          int    disk = Disk & 1;
611         Uint16  base;
612         Uint8   val;
613
614         ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
615
616         // Check if the count is small enough
617         if(Count > MAX_DMA_SECTORS) {
618                 Warning("Passed too many sectors for a bulk DMA read (%i > %i)",
619                         Count, MAX_DMA_SECTORS);
620                 LEAVE('i');
621                 return 0;
622         }
623
624         // Get exclusive access to the disk controller
625         LOCK( &giaATA_ControllerLock[ cont ] );
626
627         // Set Size
628         gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
629
630         // Get Port Base
631         base = ATA_GetBasePort(Disk);
632
633         // Reset IRQ Flag
634         gaATA_IRQs[cont] = 0;
635
636         // Set up transfer
637         outb(base+0x01, 0x00);
638         if( Address > 0x0FFFFFFF )      // Use LBA48
639         {
640                 outb(base+0x6, 0x40 | (disk << 4));
641                 outb(base+0x2, 0 >> 8); // Upper Sector Count
642                 outb(base+0x3, Address >> 24);  // Low 2 Addr
643                 outb(base+0x4, Address >> 28);  // Mid 2 Addr
644                 outb(base+0x5, Address >> 32);  // High 2 Addr
645         }
646         else
647         {
648                 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); // Magic, Disk, High addr
649         }
650
651         outb(base+0x02, (Uint8) Count);         // Sector Count
652         outb(base+0x03, (Uint8) Address);               // Low Addr
653         outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
654         outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
655
656         LOG("Starting Transfer");
657         if( Address > 0x0FFFFFFF )
658                 outb(base+0x07, HDD_DMA_R48);   // Read Command (LBA48)
659         else
660                 outb(base+0x07, HDD_DMA_R28);   // Read Command (LBA28)
661         // Start transfer
662         ATA_int_BusMasterWriteByte( cont << 3, 9 );     // Read and start
663
664         // Wait for transfer to complete
665         val = 0;
666         while( gaATA_IRQs[cont] == 0 && !(val & 0x4) ) {
667                 val = ATA_int_BusMasterReadByte( (cont << 3) + 2 );
668                 //LOG("val = 0x%02x", val);
669                 Threads_Yield();
670         }
671
672         // Complete Transfer
673         ATA_int_BusMasterWriteByte( cont << 3, 8 );     // Read and stop
674
675         val = inb(base+0x7);
676         LOG("Status byte = 0x%02x", val);
677
678         LOG("Transfer Completed & Acknowledged");
679
680         // Copy to destination buffer
681         memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
682
683         // Release controller lock
684         RELEASE( &giaATA_ControllerLock[ cont ] );
685
686         LEAVE('i', 1);
687         return 1;
688 }
689
690 /**
691  * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
692  */
693 int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
694 {
695          int    cont = (Disk>>1)&1;     // Controller ID
696          int    disk = Disk & 1;
697         Uint16  base;
698
699         // Check if the count is small enough
700         if(Count > MAX_DMA_SECTORS)     return 0;
701
702         // Get exclusive access to the disk controller
703         LOCK( &giaATA_ControllerLock[ cont ] );
704
705         // Set Size
706         gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
707
708         // Get Port Base
709         base = ATA_GetBasePort(Disk);
710
711         // Set up transfer
712         outb(base+0x01, 0x00);
713         if( Address > 0x0FFFFFFF )      // Use LBA48
714         {
715                 outb(base+0x6, 0x40 | (disk << 4));
716                 outb(base+0x2, 0 >> 8); // Upper Sector Count
717                 outb(base+0x3, Address >> 24);  // Low 2 Addr
718                 outb(base+0x3, Address >> 28);  // Mid 2 Addr
719                 outb(base+0x3, Address >> 32);  // High 2 Addr
720         }
721         else
722         {
723                 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
724         }
725
726         outb(base+0x02, (Uint8) Count);         // Sector Count
727         outb(base+0x03, (Uint8) Address);               // Low Addr
728         outb(base+0x04, (Uint8) (Address >> 8));        // Middle Addr
729         outb(base+0x05, (Uint8) (Address >> 16));       // High Addr
730         if( Address > 0x0FFFFFFF )
731                 outb(base+0x07, HDD_DMA_W48);   // Write Command (LBA48)
732         else
733                 outb(base+0x07, HDD_DMA_W28);   // Write Command (LBA28)
734
735         // Reset IRQ Flag
736         gaATA_IRQs[cont] = 0;
737
738         // Copy to output buffer
739         memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
740
741         // Start transfer
742         ATA_int_BusMasterWriteByte( cont << 3, 1 );     // Write and start
743
744         // Wait for transfer to complete
745         while( gaATA_IRQs[cont] == 0 )  Threads_Yield();
746
747         // Complete Transfer
748         ATA_int_BusMasterWriteByte( cont << 3, 0 );     // Write and stop
749
750         // Release controller lock
751         RELEASE( &giaATA_ControllerLock[ cont ] );
752
753         return 1;
754 }
755
756 /**
757  * \fn void ATA_IRQHandlerPri(int unused)
758  */
759 void ATA_IRQHandlerPri(int unused)
760 {
761         Uint8   val;
762
763         // IRQ bit set for Primary Controller
764         val = ATA_int_BusMasterReadByte( 0x2 );
765         LOG("IRQ val = 0x%x", val);
766         if(val & 4) {
767                 LOG("IRQ hit (val = 0x%x)", val);
768                 ATA_int_BusMasterWriteByte( 0x2, 4 );
769                 gaATA_IRQs[0] = 1;
770                 return ;
771         }
772 }
773
774 /**
775  * \fn void ATA_IRQHandlerSec(int unused)
776  */
777 void ATA_IRQHandlerSec(int unused)
778 {
779         Uint8   val;
780         // IRQ bit set for Secondary Controller
781         val = ATA_int_BusMasterReadByte( 0xA );
782         LOG("IRQ val = 0x%x", val);
783         if(val & 4) {
784                 LOG("IRQ hit (val = 0x%x)", val);
785                 ATA_int_BusMasterWriteByte( 0xA, 4 );
786                 gaATA_IRQs[1] = 1;
787                 return ;
788         }
789 }
790
791 /**
792  * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs)
793  */
794 Uint8 ATA_int_BusMasterReadByte(int Ofs)
795 {
796         if( gATA_BusMasterBase & 1 )
797                 return inb( (gATA_BusMasterBase & ~1) + Ofs );
798         else
799                 return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
800 }
801
802 /**
803  * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
804  * \brief Writes a byte to a Bus Master Register
805  */
806 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
807 {
808         if( gATA_BusMasterBase & 1 )
809                 outb( (gATA_BusMasterBase & ~1) + Ofs, Value );
810         else
811                 *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
812 }
813
814 /**
815  * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
816  * \brief Writes a dword to a Bus Master Register
817  */
818 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
819 {
820
821         if( gATA_BusMasterBase & 1 )
822                 outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
823         else
824                 *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;
825 }

UCC git Repository :: git.ucc.asn.au