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

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