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 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 // 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);
109 Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk);
110 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
113 void ATA_IRQHandlerPri(int unused);
114 void ATA_IRQHandlerSec(int unused);
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);
121 MODULE_DEFINE(0, 0x0032, i386ATA, ATA_Install, NULL);
122 tDevFS_Driver gATA_DriverInfo = {
127 .Flags = VFS_FFLAG_DIRECTORY,
128 .ACLs = &gVFS_ACL_EveryoneRX,
129 .ReadDir = ATA_ReadDir,
130 .FindDir = ATA_FindDir
133 tATA_Disk gATA_Disks[MAX_ATA_DISKS];
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}
150 * \fn int ATA_Install()
157 if(ret != 1) return ret;
159 ATA_SetupPartitions();
163 if( DevFS_AddDevice( &gATA_DriverInfo ) == 0 )
170 * \fn int ATA_SetupIO()
171 * \brief Sets up the ATA controller's DMA mode
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");
190 if( !(gATA_BusMasterBase & 1) )
192 if( gATA_BusMasterBase < 0x100000 )
193 gATA_BusMasterBasePtr = (void*)(0xC0000000|gATA_BusMasterBase);
195 gATA_BusMasterBasePtr = (void*)( MM_MapHWPage( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
198 IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
199 IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec );
201 gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[0] );
202 gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (Uint)&gATA_Buffers[1] );
204 LOG("gATA_PRDTs = {0x%x, 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
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);
216 * \fn void ATA_SetupPartitions()
218 void ATA_SetupPartitions()
221 for( i = 0; i < MAX_ATA_DISKS; i ++ )
223 if( !ATA_ScanDisk(i) ) {
224 gATA_Disks[i].Name[0] = '\0'; // Mark as unused
231 * \fn void ATA_SetupVFS()
232 * \brief Sets up the ATA drivers VFS information and registers with DevFS
238 // Count number of nodes needed
240 for( i = 0; i < MAX_ATA_DISKS; i++ )
242 if(gATA_Disks[i].Name[0] == '\0') continue; // Ignore
244 giATA_NumNodes += gATA_Disks[i].NumPartitions;
247 // Allocate Node space
248 gATA_Nodes = malloc( giATA_NumNodes * sizeof(void*) );
252 for( i = 0; i < MAX_ATA_DISKS; i++ )
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;
260 gATA_DriverInfo.RootNode.Size = giATA_NumNodes;
264 * \fn int ATA_ScanDisk(int Disk)
266 int ATA_ScanDisk(int Disk)
269 tIdentify *identify = (void*)buf;
270 tMBR *mbr = (void*)buf;
276 base = ATA_GetBasePort( Disk );
278 // Send Disk Selector
279 if(Disk == 1 || Disk == 3)
286 val = inb(base+7); // Read status
287 if(val == 0) return 0; // Disk does not exist
289 // Poll until BSY clears and DRQ sets or ERR is set
290 while( ((val & 0x80) || !(val & 0x08)) && !(val & 1)) val = inb(base+7);
292 if(val & 1) return 0; // Error occured, so return false
295 for(i=0;i<256;i++) buf[i] = inw(base);
297 // Populate Disk Structure
298 if(identify->Sectors48 != 0)
299 gATA_Disks[ Disk ].Sectors = identify->Sectors48;
301 gATA_Disks[ Disk ].Sectors = identify->Sectors28;
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);
311 Log("Disk %i: 0x%llx Sectors (%i KiB)", Disk,
312 gATA_Disks[ Disk ].Sectors, gATA_Disks[ Disk ].Sectors / 2);
315 gATA_Disks[ Disk ].Name[0] = 'A'+Disk;
316 gATA_Disks[ Disk ].Name[1] = '\0';
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;
325 node->ATime = node->MTime
326 = node->CTime = now();
328 node->Read = ATA_ReadFS;
329 //node->Write = ATA_WriteFS;
330 node->IOCtl = ATA_IOCtl;
333 // --- Scan Partitions ---
335 ATA_ReadDMA( Disk, 0, 1, mbr );
337 // Check for a GPT table
338 if(mbr->Parts[0].SystemID == 0xEE)
340 else // No? Just parse the MBR
347 * \fn void ATA_ParseGPT(int Disk)
348 * \brief Parses the GUID Partition Table
350 void ATA_ParseGPT(int Disk)
352 ///\todo Support GPT Disks
353 Warning("GPT Disks are currently unsupported");
357 * \fn void ATA_ParseMBR(int Disk)
359 void ATA_ParseMBR(int Disk)
366 ATA_ReadDMA( Disk, 0, 1, &mbr );
369 gATA_Disks[Disk].NumPartitions = 0;
371 for( i = 0; i < 4; i ++ )
373 if( mbr.Parts[i].SystemID == 0 ) continue;
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
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);
384 extendedLBA = mbr.Parts[i].LBAStart;
388 gATA_Disks[Disk].NumPartitions ++;
391 // Invalid Partition, so don't count it
393 while(extendedLBA != 0)
395 if( ATA_ReadDMA( Disk, extendedLBA, 1, &mbr ) != 0 )
396 break; // Stop on Errors
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
405 if(mbr.Parts[0].SystemID == 0xF || mbr.Parts[0].SystemID == 0x7)
406 extendedLBA = mbr.Parts[0].LBAStart;
408 gATA_Disks[Disk].NumPartitions ++;
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
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",
422 extendedLBA = mbr.Parts[1].LBAStart;
425 if(extendedLBA != 0) {
426 Warning("Disk %i lacks a forward link in the extended partition",
430 gATA_Disks[Disk].NumPartitions ++;
435 // Create patition array
436 gATA_Disks[Disk].Partitions = malloc( gATA_Disks[Disk].NumPartitions * sizeof(tATA_Partition) );
438 // --- Fill Partition Info ---
440 for( i = 0; i < 4; i ++ )
442 if( mbr.Parts[i].SystemID == 0 ) continue;
443 if( mbr.Parts[i].Boot == 0x0 || mbr.Parts[i].Boot == 0x80 ) // LBA 28
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);
450 extendedLBA = mbr.Parts[1].LBAStart;
454 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, i,
455 mbr.Parts[i].LBAStart, mbr.Parts[i].LBALength
460 if( mbr.Parts[i].Boot == 0x1 || mbr.Parts[i].Boot == 0x81 ) // LBA 48
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);
467 extendedLBA = (mbr.Parts[i].StartHi << 16) | mbr.Parts[i].LBAStart;
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
476 // Invalid Partition, so don't count it
478 // Scan extended partition
479 while(extendedLBA != 0)
481 if( ATA_ReadDMA( Disk, extendedLBA, 1, &mbr ) != 0 )
482 break; // Stop on Errors
486 // Check first entry (should be partition)
487 if( mbr.Parts[0].SystemID != 0)
489 if( mbr.Parts[0].Boot == 0x0 || mbr.Parts[0].Boot == 0x80 ) // LBA 28
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;
495 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, k,
496 mbr.Parts[0].LBAStart, mbr.Parts[0].LBALength
501 else if( mbr.Parts[0].Boot == 0x1 || mbr.Parts[0].Boot == 0x81 ) // LBA 48
503 if(mbr.Parts[0].SystemID == 0xF || mbr.Parts[0].SystemID == 0x7)
504 extendedLBA = (mbr.Parts[0].StartHi << 16) | mbr.Parts[0].LBAStart;
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
515 // Check second entry (should be forward link)
516 if( mbr.Parts[1].SystemID != 0)
518 if(mbr.Parts[1].Boot == 0x0 || mbr.Parts[1].Boot == 0x80 ) // LBA 28
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",
526 extendedLBA = mbr.Parts[1].LBAStart;
530 if(extendedLBA != 0) {
531 Warning("Disk %i lacks a forward link in the extended partition",
535 ATA_int_MakePartition( &gATA_Disks[Disk].Partitions[j], Disk, k,
536 mbr.Parts[1].LBAStart, mbr.Parts[1].LBALength
542 else if( mbr.Parts[1].Boot == 0x1 || mbr.Parts[1].Boot == 0x81 ) // LBA 48
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",
550 extendedLBA = (mbr.Parts[1].StartHi << 16) | mbr.Parts[1].LBAStart;
554 if(extendedLBA != 0) {
555 Warning("Disk %i lacks a forward link in the extended partition",
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
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
574 void ATA_int_MakePartition(tATA_Partition *Part, int Disk, int Num, Uint64 Start, Uint64 Length)
576 ENTER("pPart iDisk iNum XStart XLength", Part, Disk, Num, Start, Length);
578 Part->Length = Length;
579 Part->Name[0] = 'A'+Disk;
581 Part->Name[1] = '1'+Num/10;
582 Part->Name[2] = '1'+Num%10;
583 Part->Name[3] = '\0';
585 Part->Name[1] = '1'+Num;
586 Part->Name[2] = '\0';
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;
592 Part->Node.Read = ATA_ReadFS;
593 Part->Node.IOCtl = ATA_IOCtl;
594 LOG("Made '%s' (&Node=%p)", Part->Name, &Part->Node);
599 * \fn Uint16 ATA_GetPortBase(int Disk)
600 * \brief Returns the base port for a given disk
602 Uint16 ATA_GetBasePort(int Disk)
606 case 0: case 1: return IDE_PRI_BASE;
607 case 2: case 3: return IDE_SEC_BASE;
613 * \fn char *ATA_ReadDir(tVFS_Node *Node, int Pos)
615 char *ATA_ReadDir(tVFS_Node *Node, int Pos)
617 if(Pos >= giATA_NumNodes || Pos < 0) return NULL;
618 return strdup( gATA_Nodes[Pos]->ImplPtr );
622 * \fn tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
624 tVFS_Node *ATA_FindDir(tVFS_Node *Node, char *Name)
627 // Check first character
628 if(Name[0] < 'A' || Name[0] > 'A'+MAX_ATA_DISKS)
631 if(Name[1] == '\0') return &gATA_Disks[Name[0]-'A'].Node;
634 if(Name[1] < '0' || '9' < Name[1]) return NULL;
635 if(Name[2] == '\0') { // <= 9
636 part = Name[1] - '0';
638 return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
641 if('0' > Name[2] || '9' < Name[2]) return NULL;
642 if(Name[3] != '\0') return NULL;
644 part = (Name[1] - '0') * 10;
645 part += Name[2] - '0';
647 return &gATA_Disks[Name[0]-'A'].Partitions[part].Node;
652 * \fn Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
654 Uint64 ATA_ReadFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
656 int disk = Node->Inode >> 8;
657 int part = Node->Inode & 0xFF;
662 if( Offset >= gATA_Disks[disk].Sectors * SECTOR_SIZE )
664 if( Offset + Length > gATA_Disks[disk].Sectors*SECTOR_SIZE )
665 Length = gATA_Disks[disk].Sectors*SECTOR_SIZE - Offset;
670 if( Offset >= gATA_Disks[disk].Partitions[part].Length * SECTOR_SIZE )
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;
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);
682 * \fn Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
684 Uint64 ATA_WriteFS(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)
690 * \fn int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
691 * \brief IO Control Funtion
693 int ATA_IOCtl(tVFS_Node *Node, int Id, void *Data)
697 case DRV_IOCTL_TYPE: return DRV_TYPE_DISK;
702 // --- Disk Access ---
704 * \fn Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
706 Uint ATA_ReadRaw(Uint64 Address, Uint Count, void *Buffer, Uint Disk)
712 // Pass straight on to ATA_ReadDMAPage if we can
713 if(Count <= MAX_DMA_SECTORS)
715 ret = ATA_ReadDMA(Disk, Address, Count, Buffer);
716 if(ret == 0) return 0;
720 // Else we will have to break up the transfer
722 while(Count > MAX_DMA_SECTORS)
724 ret = ATA_ReadDMA(Disk, Address+offset, MAX_DMA_SECTORS, Buffer+offset);
726 if(ret != 1) return done;
728 done += MAX_DMA_SECTORS;
729 Count -= MAX_DMA_SECTORS;
730 offset += MAX_DMA_SECTORS*SECTOR_SIZE;
733 ret = ATA_ReadDMA(Disk, Address+offset, Count, Buffer+offset);
734 if(ret != 1) return 0;
739 * \fn int ATA_ReadDMAPage(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
741 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
743 int cont = (Disk>>1)&1; // Controller ID
747 // Check if the count is small enough
748 if(Count > MAX_DMA_SECTORS) return 0;
750 // Get exclusive access to the disk controller
751 LOCK( &giaATA_ControllerLock[ cont ] );
754 gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
757 base = ATA_GetBasePort(Disk);
760 outb(base+0x01, 0x00);
761 if( Address > 0x0FFFFFFF ) // Use LBA48
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
771 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
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)
781 outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
784 gaATA_IRQs[cont] = 0;
787 ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
789 // Wait for transfer to complete
790 while( gaATA_IRQs[cont] == 0 ) Threads_Yield();
793 ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
795 // Copy to destination buffer
796 memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
798 // Release controller lock
799 RELEASE( &giaATA_ControllerLock[ cont ] );
805 * \fn void ATA_IRQHandlerPri(int unused)
807 void ATA_IRQHandlerPri(int unused)
811 // IRQ bit set for Primary Controller
812 val = ATA_int_BusMasterReadByte( 0x2 );
814 //Log(" ATA_IRQHandlerPri: IRQ hit (val = 0x%x)", val);
815 ATA_int_BusMasterWriteByte( 0x2, 4 );
822 * \fn void ATA_IRQHandlerSec(int unused)
824 void ATA_IRQHandlerSec(int unused)
827 // IRQ bit set for Secondary Controller
828 val = ATA_int_BusMasterReadByte( 0xA );
830 //Log(" ATA_IRQHandlerSec: IRQ hit (val = 0x%x)", val);
831 ATA_int_BusMasterWriteByte( 0xA, 4 );
838 * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs)
840 Uint8 ATA_int_BusMasterReadByte(int Ofs)
842 if( gATA_BusMasterBase & 1 )
843 return inb( (gATA_BusMasterBase & ~1) + Ofs );
845 return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
849 * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
850 * \brief Writes a byte to a Bus Master Register
852 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
854 if( gATA_BusMasterBase & 1 )
855 outb( (gATA_BusMasterBase & ~1) + Ofs, Value );
857 *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
861 * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
862 * \brief Writes a dword to a Bus Master Register
864 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
867 if( gATA_BusMasterBase & 1 )
868 outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
870 *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;