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

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