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

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