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

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