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

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