2 * Acess2 IDE Harddisk Driver
11 #include <tpl_drv_common.h>
15 #define MAX_ATA_DISKS 4
16 #define SECTOR_SIZE 512
17 #define MAX_DMA_SECTORS (0x1000 / SECTOR_SIZE)
19 #define IDE_PRI_BASE 0x1F0
20 #define IDE_SEC_BASE 0x170
22 #define IDE_PRDT_LAST 0x8000
25 \brief Commands to be sent to HDD_CMD
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;
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];
61 Uint16 Unused7[256-104];
64 Uint8 BootCode[0x1BE];
67 Uint8 Unused1; // Also CHS Start
68 Uint16 StartHi; // Also CHS Start
70 Uint8 Unused2; // Also CHS Length
71 Uint16 LengthHi; // Also CHS Length
74 } __attribute__ ((packed)) Parts[4];
75 Uint16 BootFlag; // = 0xAA 55
76 } __attribute__ ((packed)) tMBR;
89 tATA_Partition *Partitions;
95 static void ATA_SetupPartitions();
97 int ATA_ScanDisk(int Disk);
98 void ATA_ParseGPT(int Disk);
99 void ATA_ParseMBR(int Disk);
100 void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length);
101 Uint16 ATA_GetBasePort(int Disk);
102 char *ATA_ReadDir(tVFS_Node *Node, int Pos);
103 tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name);
104 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer);
105 int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data);
106 Uint ATA_Read(Uint64 Address, Uint Count, void *Buffer, Uint Argument);
107 int ATA_ReadRaw(Uint8 Disk, Uint64 Address, Uint64 Count, void *Buffer);
108 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
109 void ATA_IRQHandlerPri(int unused);
110 void ATA_IRQHandlerSec(int unused);
111 Uint8 ATA_int_BusMasterReadByte(int Ofs);
112 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
113 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
116 MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL);
117 tDevFS_Driver gATA_DriverInfo = {
122 .Flags = VFS_FFLAG_DIRECTORY,
123 .ACLs = &gVFS_ACL_EveryoneRX,
124 .ReadDir = ATA_ReadDir,
125 .FindDir = ATA_FindDir
128 tATA_Disk gATA_Disks[MAX_ATA_DISKS];
130 tVFS_Node **gATA_Nodes;
131 Uint16 gATA_BusMasterBase = 0;
132 Uint8 *gATA_BusMasterBasePtr = 0;
133 int gATA_IRQPri = 14;
134 int gATA_IRQSec = 15;
135 int giaATA_ControllerLock[2] = {0}; //!< Spinlocks for each controller
136 Uint8 gATA_Buffers[2][4096] __attribute__ ((section(".padata")));
137 int gaATA_IRQs[2] = {0};
138 tPRDT_Ent gATA_PRDTs[2] = {
139 {0, 512, IDE_PRDT_LAST},
140 {0, 512, IDE_PRDT_LAST}
145 * \fn int ATA_Install()
152 if(ret != 1) return ret;
154 ATA_SetupPartitions();
158 if( DevFS_AddDevice( &gATA_DriverInfo ) == 0 )
165 * \fn int ATA_SetupIO()
166 * \brief Sets up the ATA controller's DMA mode
175 // Get IDE Controller's PCI Entry
176 ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1);
177 LOG("ent = %i\n", ent);
178 gATA_BusMasterBase = PCI_GetBAR4( ent );
179 LOG("gATA_BusMasterBase = 0x%x\n", gATA_BusMasterBase);
180 if( gATA_BusMasterBase == 0 ) {
181 Warning("It seems that there is no Bus Master Controller on this machine, get one");
185 if( !(gATA_BusMasterBase & 1) )
187 if( gATA_BusMasterBase < 0x100000 )
188 gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase);
190 gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
193 IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
194 IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec );
196 gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] );
197 gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] );
199 LOG("gATA_PRDTs = {0x%x, 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
201 addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[0] );
202 ATA_int_BusMasterWriteDWord(4, addr);
203 addr = MM_GetPhysAddr( (Uint)&gATA_PRDTs[1] );
204 ATA_int_BusMasterWriteDWord(12, addr);
211 * \fn static void ATA_SetupPartitions()
213 static void ATA_SetupPartitions()
216 for( i = 0; i < MAX_ATA_DISKS; i ++ )
218 if( !ATA_ScanDisk(i) ) {
219 gATA_Disks[i].Name[0] = '\0'; // Mark as unused
226 * \fn void ATA_SetupVFS()
227 * \brief Sets up the ATA drivers VFS information and registers with DevFS
233 // Count number of nodes needed
235 for( i = 0; i < MAX_ATA_DISKS; i++ )
237 if(gATA_Disks[i].Name[0] == '\0') continue; // Ignore
239 giATA_NumNodes += gATA_Disks[i].NumPartitions;
242 // Allocate Node space
243 gATA_Nodes = malloc( giATA_NumNodes * sizeof(void*) );
247 for( i = 0; i < MAX_ATA_DISKS; i++ )
249 if(gATA_Disks[i].Name[0] == '\0') continue; // Ignore
250 gATA_Nodes[ k++ ] = &gATA_Disks[i].Node;
251 for( j = 0; j < gATA_Disks[i].NumPartitions; j ++ )
252 gATA_Nodes[ k++ ] = &gATA_Disks[i].Partitions[j].Node;
255 gATA_DriverInfo.RootNode.Size = giATA_NumNodes;
259 * \fn int ATA_ScanDisk(int Disk)
261 int ATA_ScanDisk(int Disk)
264 tIdentify *identify = (void*)buf;
265 tMBR *mbr = (void*)buf;
271 base = ATA_GetBasePort( Disk );
273 // Send Disk Selector
274 if(Disk == 1 || Disk == 3)
281 val = inb(base+7); // Read status
282 if(val == 0) return 0; // Disk does not exist
284 // Poll until BSY clears and DRQ sets or ERR is set
285 while( ((val & 0x80) || !(val & 0x08)) && !(val & 1)) val = inb(base+7);
287 if(val & 1) return 0; // Error occured, so return false
290 for(i=0;i<256;i++) buf[i] = inw(base);
292 // Populate Disk Structure
293 if(identify->Sectors48 != 0)
294 gATA_Disks[ Disk ].Sectors = identify->Sectors48;
296 gATA_Disks[ Disk ].Sectors = identify->Sectors28;
299 if( gATA_Disks[ Disk ].Sectors / (2048*1024) )
300 Log("Disk %i: 0x%llx Sectors (%i GiB)", Disk,
301 gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / (2048*1024));
302 else if( gATA_Disks[ Disk ].Sectors / 2048 )
303 Log("Disk %i: 0x%llx Sectors (%i MiB)", Disk,
304 gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2048);
306 Log("Disk %i: 0x%llx Sectors (%i KiB)", Disk,
307 gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2);
310 gATA_Disks[ Disk ].Name[0] = 'A'+Disk;
311 gATA_Disks[ Disk ].Name[1] = '\0';
313 // Get pointer to vfs node and populate it
314 node = &gATA_Disks[ Disk ].Node;
315 node->Size = gATA_Disks[Disk].Sectors * SECTOR_SIZE;
316 node->NumACLs = 0; // Means Superuser only can access it
317 node->Inode = (Disk << 8) | 0xFF;
318 node->ImplPtr = gATA_Disks[ Disk ].Name;
320 node->ATime = node->MTime
321 = node->CTime = now();
323 node->Read = ATA_ReadFS;
324 //node->Write = ATA_WriteFS;
325 node->IOCtl = ATA_IOCtl;
328 // --- Scan Partitions ---
330 ATA_ReadDMA( Disk, 0, 1, mbr );
332 // Check for a GPT table
333 if(mbr->Parts[0].SystemID == 0xEE)
335 else // No? Just parse the MBR
342 * \fn void ATA_ParseGPT(int Disk)
343 * \brief Parses the GUID Partition Table
345 void ATA_ParseGPT(int Disk)
347 ///\todo Support GPT Disks
348 Warning("GPT Disks are currently unsupported");
352 * \fn void ATA_ParseMBR(int Disk)
354 void ATA_ParseMBR(int Disk)
361 ATA_ReadDMA( Disk, 0, 1, &mbr );
364 gATA_Disks[Disk].NumPartitions = 0;
366 for( i = 0; i < 4; i ++ )
368 if( mbr.Parts[i].SystemID == 0 ) continue;
370 mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 // LBA 28
371 || mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 // LBA 48
374 if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) {
375 if(extendedLBA != 0) {
376 Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
379 extendedLBA = mbr.Parts[i].LBAStart;
383 gATA_Disks[Disk].NumPartitions ++;
386 // Invalid Partition, so don't count it
388 while(extendedLBA != 0)
390 if( ATA_ReadDMA( Disk, extendedLBA, 1, &mbr ) != 0 )
391 break; // Stop on Errors
395 if( mbr.Parts[0].SystemID == 0 ) continue;
396 if( mbr.Parts[0].Boot == 0x0 || mbr.Parts[0].Boot == 0x80 // LBA 28
397 || mbr.Parts[0].Boot == 0x1 || mbr.Parts[0].Boot == 0x81 // LBA 48
400 if(mbr.Parts[0].SystemID == 0xF || mbr.Parts[0].SystemID == 0x7)
401 extendedLBA = mbr.Parts[0].LBAStart;
403 gATA_Disks[Disk].NumPartitions ++;
406 if( mbr.Parts[1].SystemID == 0 ) continue;
407 if( mbr.Parts[1].Boot == 0x0 || mbr.Parts[1].Boot == 0x80 // LBA 28
408 || mbr.Parts[1].Boot == 0x1 || mbr.Parts[1].Boot == 0x81 // LBA 48
411 if(mbr.Parts[1].SystemID == 0xF || mbr.Parts[1].SystemID == 0x7) {
412 if(extendedLBA == 0) {
413 Warning("Disk %i has twp forward link in the extended partition",
417 extendedLBA = mbr.Parts[1].LBAStart;
420 if(extendedLBA != 0) {
421 Warning("Disk %i lacks a forward link in the extended partition",
425 gATA_Disks[Disk].NumPartitions ++;
430 // Create patition array
431 gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) );
433 // --- Fill Partition Info ---
435 for( i = 0; i < 4; i ++ )
437 if( mbr.Parts[i].SystemID == 0 ) continue;
438 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) // LBA 28
440 if( mbr.Parts[1].SystemID == 0xF || mbr.Parts[1].SystemID == 5 ) {
441 if(extendedLBA != 0) {
442 Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
445 extendedLBA = mbr.Parts[1].LBAStart;
449 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, i,
450 mbr.Parts[i].LBAStart, mbr.Parts[i].LBALength
455 if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) // LBA 48
457 if( mbr.Parts[i].SystemID == 0xF || mbr.Parts[i].SystemID == 5 ) {
458 if(extendedLBA != 0) {
459 Warning("Disk %i has multiple extended partitions, ignoring rest", Disk);
462 extendedLBA = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
465 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, i,
466 (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart,
467 (mbr.Parts[i].LengthHi << 16) | mbr.Parts[i].LBALength
471 // Invalid Partition, so don't count it
473 // Scan extended partition
474 while(extendedLBA != 0)
476 if( ATA_ReadDMA( Disk, extendedLBA, 1, &mbr ) != 0 )
477 break; // Stop on Errors
481 // Check first entry (should be partition)
482 if( mbr.Parts[0].SystemID != 0)
484 if( mbr.Parts[0].Boot == 0x0 || mbr.Parts[0].Boot == 0x80 ) // LBA 28
486 // Forward Link to next Extended partition entry
487 if(mbr.Parts[0].SystemID == 0xF || mbr.Parts[0].SystemID == 0x7)
488 extendedLBA = mbr.Parts[0].LBAStart;
490 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, k,
491 mbr.Parts[0].LBAStart, mbr.Parts[0].LBALength
496 else if( mbr.Parts[0].Boot == 0x1 || mbr.Parts[0].Boot == 0x81 ) // LBA 48
498 if(mbr.Parts[0].SystemID == 0xF || mbr.Parts[0].SystemID == 0x7)
499 extendedLBA = (mbr.Parts[0].StartHi << 16) | mbr.Parts[0].LBAStart;
501 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, k,
502 (mbr.Parts[0].StartHi << 16) | mbr.Parts[0].LBAStart,
503 (mbr.Parts[0].LengthHi << 16) | mbr.Parts[0].LBALength
510 // Check second entry (should be forward link)
511 if( mbr.Parts[1].SystemID != 0)
513 if(mbr.Parts[1].Boot == 0x0 || mbr.Parts[1].Boot == 0x80 ) // LBA 28
515 if(mbr.Parts[1].SystemID == 0xF || mbr.Parts[1].SystemID == 0x7) {
516 if(extendedLBA == 0) {
517 Warning("Disk %i has twp forward link in the extended partition",
521 extendedLBA = mbr.Parts[1].LBAStart;
525 if(extendedLBA != 0) {
526 Warning("Disk %i lacks a forward link in the extended partition",
530 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, k,
531 mbr.Parts[1].LBAStart, mbr.Parts[1].LBALength
537 else if( mbr.Parts[1].Boot == 0x1 || mbr.Parts[1].Boot == 0x81 ) // LBA 48
539 if(mbr.Parts[1].SystemID == 0xF || mbr.Parts[1].SystemID == 0x7) {
540 if(extendedLBA == 0) {
541 Warning("Disk %i has twp forward link in the extended partition",
545 extendedLBA = (mbr.Parts[1].StartHi << 16) | mbr.Parts[1].LBAStart;
549 if(extendedLBA != 0) {
550 Warning("Disk %i lacks a forward link in the extended partition",
554 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, k,
555 (mbr.Parts[1].StartHi << 16) | mbr.Parts[1].LBAStart,
556 (mbr.Parts[1].LengthHi << 16) | mbr.Parts[1].LBALength
566 * \fn void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length)
567 * \brief Fills a parition's information structure
569 void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length)
571 ENTER("pPart iDisk iNum XStart XLength", Part, Disk, Num, Start, Length);
573 Part->Length = Length;
574 Part->Name[0] = 'A'+Disk;
576 Part->Name[1] = '1'+Num/10;
577 Part->Name[2] = '1'+Num%10;
578 Part->Name[3] = '\0';
580 Part->Name[1] = '1'+Num;
581 Part->Name[2] = '\0';
583 Part->Node.NumACLs = 0; // Only root can read/write raw block devices
584 Part->Node.Inode = (Disk << 8) | Num;
585 Part->Node.ImplPtr = Part->Name;
587 Part->Node.Read = ATA_ReadFS;
588 Part->Node.IOCtl = ATA_IOCtl;
589 LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
594 * \fn Uint16 ATA_GetPortBase(int Disk)
595 * \brief Returns the base port for a given disk
597 Uint16 ATA_GetBasePort(int Disk)
601 case 0: case 1: return IDE_PRI_BASE;
602 case 2: case 3: return IDE_SEC_BASE;
608 * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos)
610 char *ATA_ReadDir(tVFS_Node *Node, int Pos)
612 if(Pos >= giATA_NumNodes || Pos < 0) return NULL;
613 return strdup( gATA_Nodes[Pos]->ImplPtr );
617 * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
619 tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
622 // Check first character
623 if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS)
626 if(Name[1] == '\0') return &gATA_Disks[Name[0]-'A'].Node;
629 if(Name[1] < '0' || '9' < Name[1]) return NULL;
630 if(Name[2] == '\0') { // <= 9
631 part = Name[1] - '0';
633 return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
636 if('0' > Name[2] || '9' < Name[2]) return NULL;
637 if(Name[3] != '\0') return NULL;
639 part = (Name[1] - '0') * 10;
640 part += Name[2] - '0';
642 return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
647 * \fn Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
649 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
651 //Log("ATA_ReadFS: (Node=%p, Offset=0x%llx, Length=0x%llx, Buffer=%p)", Node, Offset, Length, Buffer);
652 return DrvUtil_ReadBlock(Offset, Length, Buffer, ATA_Read, SECTOR_SIZE, Node->Inode);
656 * \fn Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
658 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
664 * \fn int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
665 * \brief IO Control Funtion
667 int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
671 case DRV_IOCTL_TYPE: return DRV_TYPE_DISK;
676 // --- Disk Access ---
678 * \fn Uint ATA_Read(Uint64 Address, Uint Count, void *Buffer, Uint Argument)
680 Uint ATA_Read(Uint64 Address, Uint Count, void *Buffer, Uint Argument)
683 int disk = Argument >> 8;
684 int part = Argument & 0xFF;
689 if( Address >= gATA_Disks[disk].Sectors ) return 0;
690 if( Address + Count > gATA_Disks[disk].Sectors )
691 Count = gATA_Disks[disk].Sectors - Address;
693 ret = ATA_ReadRaw(disk, Address, Count, Buffer);
699 if( Address >= gATA_Disks[disk].Partitions[part].Length ) return 0;
700 if( Address + Count > gATA_Disks[disk].Partitions[part].Length )
701 Count = gATA_Disks[disk].Partitions[part].Length - Address;
705 gATA_Disks[disk].Partitions[part].Start + Address,
709 if(ret == 1) return Count;
715 * \fn int ATA_ReadRaw(Uint8 Disk, Uint64 Address, Uint64 Count, void *Buffer)
717 int ATA_ReadRaw(Uint8 Disk, Uint64 Address, Uint64 Count, void *Buffer)
722 // Pass straight on to ATA_ReadDMAPage if we can
723 if(Count <= MAX_DMA_SECTORS)
724 return ATA_ReadDMA(Disk, Address, Count, Buffer);
726 // Else we will have to break up the transfer
728 while(Count > MAX_DMA_SECTORS)
730 ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
732 if(ret != 1) return ret;
734 Count -= MAX_DMA_SECTORS;
735 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
738 return ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset);
742 * \fn int ATA_ReadDMAPage(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
744 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
746 int cont = (Disk>>1)&1; // Controller ID
750 // Check if the count is small enough
751 if(Count > MAX_DMA_SECTORS) return 0;
753 // Get exclusive access to the disk controller
754 LOCK( &giaATA_ControllerLock[ cont ] );
757 gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
760 base = ATA_GetBasePort(Disk);
763 outb(base+0x01, 0x00);
764 if( Address > 0x0FFFFFFF ) // Use LBA48
766 outb(base+0x6, 0x40 | (disk << 4));
767 outb(base+0x2, 0 >> 8); // Upper Sector Count
768 outb(base+0x3, Address >> 24); // Low 2 Addr
769 outb(base+0x3, Address >> 28); // Mid 2 Addr
770 outb(base+0x3, Address >> 32); // High 2 Addr
774 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
777 outb(base+0x02, (Uint8) Count); // Sector Count
778 outb(base+0x03, (Uint8) Address); // Low Addr
779 outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr
780 outb(base+0x05, (Uint8) (Address >> 16)); // High Addr
781 if( Address > 0x0FFFFFFF )
782 outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48)
784 outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
787 gaATA_IRQs[cont] = 0;
790 ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
792 // Wait for transfer to complete
793 while( gaATA_IRQs[cont] == 0 ) Threads_Yield();
796 ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
798 // Copy to destination buffer
799 memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
801 // Release controller lock
802 RELEASE( &giaATA_ControllerLock[ cont ] );
808 * \fn void ATA_IRQHandlerPri(int unused)
810 void ATA_IRQHandlerPri(int unused)
814 // IRQ bit set for Primary Controller
815 val = ATA_int_BusMasterReadByte( 0x2 );
817 //Log(" ATA_IRQHandlerPri: IRQ hit (val = 0x%x)", val);
818 ATA_int_BusMasterWriteByte( 0x2, 4 );
825 * \fn void ATA_IRQHandlerSec(int unused)
827 void ATA_IRQHandlerSec(int unused)
830 // IRQ bit set for Secondary Controller
831 val = ATA_int_BusMasterReadByte( 0xA );
833 //Log(" ATA_IRQHandlerSec: IRQ hit (val = 0x%x)", val);
834 ATA_int_BusMasterWriteByte( 0xA, 4 );
841 * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs)
843 Uint8 ATA_int_BusMasterReadByte(int Ofs)
845 if( gATA_BusMasterBase & 1 )
846 return inb( (gATA_BusMasterBase & ~1) + Ofs );
848 return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
852 * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
853 * \brief Writes a byte to a Bus Master Register
855 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
857 if( gATA_BusMasterBase & 1 )
858 outb( (gATA_BusMasterBase & ~1) + Ofs, Value );
860 *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
864 * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
865 * \brief Writes a dword to a Bus Master Register
867 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
870 if( gATA_BusMasterBase & 1 )
871 outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
873 *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;