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

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