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

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