2 * Acess2 IDE Harddisk Driver
5 * Disk Input/Output control
9 #include <modules.h> // Needed for error codes
16 #define IO_DELAY() do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0)
19 #define IDE_PRI_BASE 0x1F0
20 #define IDE_PRI_CTRL 0x3F6
21 #define IDE_SEC_BASE 0x170
22 #define IDE_SEC_CTRL 0x376
24 #define IDE_PRDT_LAST 0x8000
27 \brief Commands to be sent to HDD_CMD
47 Uint32 PBufAddr; // Physical Buffer Address
48 Uint16 Bytes; // Size of transfer entry
49 Uint16 Flags; // Flags
50 } __attribute__ ((packed)) tPRDT_Ent;
53 * \brief Structure returned by the ATA IDENTIFY command
58 Uint16 Usused1[9]; // 10
59 char SerialNum[20]; // 20
60 Uint16 Usused2[3]; // 23
61 char FirmwareVer[8]; // 27
62 char ModelNumber[40]; // 47
63 Uint16 SectPerInt; // 48 - Low byte only
65 Uint16 Capabilities[2]; // 51
66 Uint16 Unused4[2]; // 53
67 Uint16 ValidExtData; // 54
68 Uint16 Unused5[5]; // 59
69 Uint16 SizeOfRWMultiple; // 60
70 Uint32 Sectors28; // LBA 28 Sector Count
71 Uint16 Unused6[100-62];
72 Uint64 Sectors48; // LBA 48 Sector Count
73 Uint16 Unused7[256-104];
74 } __attribute__ ((packed)) tIdentify;
77 int ATA_SetupIO(void);
78 Uint64 ATA_GetDiskSize(int Disk);
79 Uint16 ATA_GetBasePort(int Disk);
81 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
82 int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer);
84 void ATA_IRQHandlerPri(int UNUSED(IRQ), void *UNUSED(Ptr));
85 void ATA_IRQHandlerSec(int UNUSED(IRQ), void *UNUSED(Ptr));
87 Uint8 ATA_int_BusMasterReadByte(int Ofs);
88 Uint32 ATA_int_BusMasterReadDWord(int Ofs);
89 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
90 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
93 // - BusMaster IO Addresses
94 Uint32 gATA_BusMasterBase; //!< True Address (IO/MMIO)
95 Uint8 *gATA_BusMasterBasePtr; //!< Paging Mapped MMIO (If needed)
99 volatile int gaATA_IRQs[2] = {0};
100 tThread *gATA_WaitingThreads[2];
101 // - Locks to avoid tripping
102 tMutex glaATA_ControllerLock[2];
104 void *gATA_Buffers[2];
106 tPRDT_Ent gATA_PRDTs[2] = {
107 {0, 512, IDE_PRDT_LAST},
108 {0, 512, IDE_PRDT_LAST}
110 tPAddr gaATA_PRDT_PAddrs[2];
114 * \brief Sets up the ATA controller's DMA mode
116 int ATA_SetupIO(void)
122 // Get IDE Controller's PCI Entry
123 ent = PCI_GetDeviceByClass(0x010100, 0xFFFF00, -1);
124 LOG("ent = %i", ent);
125 gATA_BusMasterBase = PCI_GetBAR(ent, 4);
126 if( gATA_BusMasterBase == 0 ) {
127 Log_Warning("ATA", "Unable to find a Bus Master DMA controller");
128 // TODO: Use PIO mode instead
129 LEAVE('i', MODULE_ERR_NOTNEEDED);
130 return MODULE_ERR_NOTNEEDED;
133 LOG("BAR5 = 0x%x", PCI_GetBAR(ent, 5));
134 LOG("IRQ = %i", PCI_GetIRQ(ent));
136 // Ensure controllers are present where we think they should be
137 for( int i = 0; i < 2; i ++ )
139 Uint16 base = ATA_GetBasePort( i*2 );
140 // Send Disk Selector
143 // Check for a floating bus
144 if( 0xFF == inb(base+7) ) {
145 Log_Error("ATA", "Floating bus at address 0x%x", base+7);
146 LEAVE('i', MODULE_ERR_MISC);
147 return MODULE_ERR_MISC;
150 // Check for the controller
151 // - Write to two RW ports and attempt to read back
152 outb(base+0x02, 0x66);
153 outb(base+0x03, 0xFF);
154 if(inb(base+0x02) != 0x66 || inb(base+0x03) != 0xFF) {
155 Log_Error("ATA", "Unable to write to 0x%x/0x%x", base+2, base+3);
162 if( gATA_BusMasterBase & 1 )
164 gATA_BusMasterBase &= ~1;
165 LOG("gATA_BusMasterBase = IO 0x%x", gATA_BusMasterBase);
170 gATA_BusMasterBasePtr = MM_MapHWPages( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF);
171 LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
174 // Register IRQs and get Buffers
175 IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri, NULL );
176 IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec, NULL );
179 gATA_Buffers[0] = (void*)MM_AllocDMA(1, 32, &paddr);
180 gATA_PRDTs[0].PBufAddr = paddr;
181 gATA_Buffers[1] = (void*)MM_AllocDMA(1, 32, &paddr);
182 gATA_PRDTs[1].PBufAddr = paddr;
184 LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
186 // TODO: Ensure that this is within 32-bits
187 gaATA_PRDT_PAddrs[0] = MM_GetPhysAddr( &gATA_PRDTs[0] );
188 gaATA_PRDT_PAddrs[1] = MM_GetPhysAddr( &gATA_PRDTs[1] );
189 LOG("gaATA_PRDT_PAddrs = {0x%P, 0x%P}", gaATA_PRDT_PAddrs[0], gaATA_PRDT_PAddrs[1]);
191 if( gaATA_PRDT_PAddrs[0] >> 32 || gaATA_PRDT_PAddrs[1] >> 32 ) {
192 Log_Error("ATA", "Physical addresses of PRDTs are not in 32-bits (%P and %P)",
193 gaATA_PRDT_PAddrs[0], gaATA_PRDT_PAddrs[1]);
194 LEAVE('i', MODULE_ERR_MISC);
195 return MODULE_ERR_MISC;
198 ATA_int_BusMasterWriteDWord(4, gaATA_PRDT_PAddrs[0]);
199 ATA_int_BusMasterWriteDWord(12, gaATA_PRDT_PAddrs[1]);
201 // Enable controllers
202 outb(IDE_PRI_BASE+1, 1);
203 outb(IDE_SEC_BASE+1, 1);
204 outb(IDE_PRI_CTRL, 0);
205 outb(IDE_SEC_CTRL, 0);
207 // Make sure interrupts are ACKed
208 ATA_int_BusMasterWriteByte(2, 0x4);
209 ATA_int_BusMasterWriteByte(10, 0x4);
212 LEAVE('i', MODULE_ERR_OK);
213 return MODULE_ERR_OK;
217 * \brief Get the size (in sectors) of a disk
218 * \param Disk Disk to get size of
219 * \return Number of sectors reported
221 * Does an ATA IDENTIFY
223 Uint64 ATA_GetDiskSize(int Disk)
232 ENTER("iDisk", Disk);
234 base = ATA_GetBasePort( Disk );
236 // Send Disk Selector
238 outb(base+6, 0xA0 | (Disk & 1) << 4);
242 outb(base+7, HDD_IDENTIFY);
244 val = inb(base+7); // Read status
245 LOG("val = 0x%02x", val);
248 return 0; // Disk does not exist
251 // Poll until BSY clears or ERR is set
253 while( (val & 0x80) && !(val & 1) )
255 LOG("BSY unset (0x%x)", val);
256 // and, wait for DRQ to set
257 while( !(val & 0x08) && !(val & 1))
259 LOG("DRQ set (0x%x)", val);
261 // Check for an error
264 return 0; // Error occured, so return false
268 for( int i = 0; i < 256; i++ )
269 data.buf[i] = inw(base);
271 // Return the disk size
272 if(data.identify.Sectors48 != 0) {
273 LEAVE('X', data.identify.Sectors48);
274 return data.identify.Sectors48;
277 LEAVE('x', data.identify.Sectors28);
278 return data.identify.Sectors28;
283 * \fn Uint16 ATA_GetPortBase(int Disk)
284 * \brief Returns the base port for a given disk
286 Uint16 ATA_GetBasePort(int Disk)
290 case 0: case 1: return IDE_PRI_BASE;
291 case 2: case 3: return IDE_SEC_BASE;
296 int ATA_DoDMA(Uint8 Disk, Uint64 Address, Uint Count, int bWrite, void *Buffer)
298 int cont = (Disk>>1)&1; // Controller ID
301 int bUseBounceBuffer;
303 ENTER("iDisk XAddress iCount bbWrite pBuffer", Disk, Address, Count, bWrite, Buffer);
305 // Check if the count is small enough
306 if(Count > MAX_DMA_SECTORS) {
307 Log_Warning("ATA", "Passed too many sectors for a bulk DMA (%i > %i)",
308 Count, MAX_DMA_SECTORS);
313 // Hack to make debug hexdump noticable
315 memset(Buffer, 0xFF, Count*SECTOR_SIZE);
318 // Get exclusive access to the disk controller
319 Mutex_Acquire( &glaATA_ControllerLock[ cont ] );
322 gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
324 // Detemine if the transfer can be done directly
325 tPAddr buf_ps = MM_GetPhysAddr(Buffer);
326 tPAddr buf_pe = MM_GetPhysAddr((char*)Buffer + Count * SECTOR_SIZE - 1);
327 if( buf_pe == buf_ps + Count * SECTOR_SIZE - 1 ) {
331 // Over 32-bits, need to copy anyway
332 bUseBounceBuffer = 1;
333 LOG("%P over 32-bit, using bounce buffer", buf_pe);
338 // TODO: Handle splitting the read into two?
339 bUseBounceBuffer = 1;
340 LOG("%P + 0x%x != %P, using bounce buffer", buf_ps, Count * SECTOR_SIZE, buf_pe);
343 // Set up destination / source buffers
344 if( bUseBounceBuffer ) {
345 gATA_PRDTs[cont].PBufAddr = MM_GetPhysAddr(gATA_Buffers[cont]);
347 memcpy(gATA_Buffers[cont], Buffer, Count * SECTOR_SIZE);
350 gATA_PRDTs[cont].PBufAddr = MM_GetPhysAddr(Buffer);
354 base = ATA_GetBasePort(Disk);
357 gaATA_IRQs[cont] = 0;
360 // TODO: What the ____ does this do?
363 outb(IDE_PRI_CTRL, 4);
365 outb(IDE_PRI_CTRL, 0);
368 outb(IDE_SEC_CTRL, 4);
370 outb(IDE_SEC_CTRL, 0);
375 if( Address > 0x0FFFFFFF ) // Use LBA48
377 outb(base+0x6, 0x40 | (disk << 4));
379 outb(base+0x2, 0 >> 8); // Upper Sector Count
380 outb(base+0x3, Address >> 24); // Low 2 Addr
381 outb(base+0x4, Address >> 28); // Mid 2 Addr
382 outb(base+0x5, Address >> 32); // High 2 Addr
386 // Magic, Disk, High Address nibble
387 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F));
388 //outb(base+0x06, 0xA0 | (disk << 4) | ((Address >> 24) & 0x0F));
392 //outb(base+0x01, 0x01); //?
393 outb(base+0x02, Count & 0xFF); // Sector Count
394 outb(base+0x03, Address & 0xFF); // Low Addr
395 outb(base+0x04, (Address >> 8) & 0xFF); // Middle Addr
396 outb(base+0x05, (Address >> 16) & 0xFF); // High Addr
398 LOG("Starting Transfer");
400 // HACK: Ensure the PRDT is reset
401 ATA_int_BusMasterWriteDWord(cont*8+4, gaATA_PRDT_PAddrs[cont]);
402 ATA_int_BusMasterWriteByte(cont*8, 4); // Reset IRQ
404 LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes);
405 if( Address > 0x0FFFFFFF )
406 outb(base+0x07, bWrite ? HDD_DMA_W48 : HDD_DMA_R48); // Command (LBA48)
408 outb(base+0x07, bWrite ? HDD_DMA_W28 : HDD_DMA_R28); // Command (LBA28)
410 // Intialise timeout timer
411 Threads_ClearEvent(THREAD_EVENT_SHORTWAIT|THREAD_EVENT_TIMER);
412 tTimer *timeout = Time_AllocateTimer(NULL, NULL);
413 Time_ScheduleTimer(timeout, ATA_TIMEOUT);
414 gATA_WaitingThreads[cont] = Proc_GetCurThread();
417 ATA_int_BusMasterWriteByte( cont * 8, (bWrite ? 0 : 8) | 1 ); // Write(0)/Read(8) and start
419 // Wait for transfer to complete
420 Uint32 ev = Threads_WaitEvents(THREAD_EVENT_SHORTWAIT|THREAD_EVENT_TIMER);
421 Time_FreeTimer(timeout);
423 if( ev & THREAD_EVENT_TIMER ) {
424 Log_Notice("ATA", "Timeout of %i ms exceeded", ATA_TIMEOUT);
428 ATA_int_BusMasterWriteByte( cont * 8, (bWrite ? 0 : 8) ); // Write/Read and stop
432 Uint8 val = inb(base+0x7);
433 LOG("Status byte = 0x%02x, Controller Status = 0x%02x",
434 val, ATA_int_BusMasterReadByte(cont * 8 + 2));
440 if( gaATA_IRQs[cont] == 0 )
442 if( ATA_int_BusMasterReadByte(cont * 8 + 2) & 0x4 ) {
443 Log_Error("ATA", "BM Status reports an interrupt, but none recieved");
444 ATA_int_BusMasterWriteByte(cont*8 + 2, 4); // Clear interrupt
449 Debug_HexDump("ATA", Buffer, 512);
452 // Release controller lock
453 Mutex_Release( &glaATA_ControllerLock[ cont ] );
455 "Timeout on disk %i (%s sector 0x%llx)",
456 Disk, bWrite ? "Writing" : "Reading", Address);
462 LOG("Transfer Completed & Acknowledged");
464 // Copy to destination buffer (if bounce was used and it was a read)
465 if( bUseBounceBuffer && !bWrite )
466 memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
467 // Release controller lock
468 Mutex_Release( &glaATA_ControllerLock[ cont ] );
475 * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
476 * \return Boolean Failure
478 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
480 return ATA_DoDMA(Disk, Address, Count, 0, Buffer);
485 * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
486 * \brief Write up to \a MAX_DMA_SECTORS to a disk
487 * \param Disk Disk ID to write to
488 * \param Address LBA of first sector
489 * \param Count Number of sectors to write (must be >= \a MAX_DMA_SECTORS)
490 * \param Buffer Source buffer for data
491 * \return Boolean Failure
493 int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer)
495 return ATA_DoDMA(Disk, Address, Count, 1, (void*)Buffer);
499 * \brief Primary ATA Channel IRQ handler
501 void ATA_IRQHandlerPri(int UNUSED(IRQ), void *UNUSED(Ptr))
505 // IRQ bit set for Primary Controller
506 val = ATA_int_BusMasterReadByte( 0x2 );
507 LOG("IRQ val = 0x%x", val);
510 LOG("IRQ hit (val = 0x%x)", val);
511 ATA_int_BusMasterWriteByte( 0x2, 4 );
513 Threads_PostEvent(gATA_WaitingThreads[0], THREAD_EVENT_SHORTWAIT);
519 * \brief Second ATA Channel IRQ handler
521 void ATA_IRQHandlerSec(int UNUSED(IRQ), void *UNUSED(Ptr))
524 // IRQ bit set for Secondary Controller
525 val = ATA_int_BusMasterReadByte( 0xA );
526 LOG("IRQ val = 0x%x", val);
528 LOG("IRQ hit (val = 0x%x)", val);
529 ATA_int_BusMasterWriteByte( 0xA, 4 );
531 Threads_PostEvent(gATA_WaitingThreads[1], THREAD_EVENT_SHORTWAIT);
537 * \brief Read an 8-bit value from a Bus Master register
538 * \param Ofs Register offset
540 Uint8 ATA_int_BusMasterReadByte(int Ofs)
542 if( gATA_BusMasterBasePtr )
543 return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
545 return inb( gATA_BusMasterBase + Ofs );
549 * \brief Read an 32-bit value from a Bus Master register
550 * \param Ofs Register offset
552 Uint32 ATA_int_BusMasterReadDWord(int Ofs)
554 if( gATA_BusMasterBasePtr )
555 return *(Uint32*)(gATA_BusMasterBasePtr + Ofs);
557 return ind( gATA_BusMasterBase + Ofs );
561 * \brief Writes a byte to a Bus Master Register
562 * \param Ofs Register Offset
563 * \param Value Value to write
565 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
567 if( gATA_BusMasterBasePtr )
568 *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
570 outb( gATA_BusMasterBase + Ofs, Value );
574 * \brief Writes a 32-bit value to a Bus Master Register
575 * \param Ofs Register offset
576 * \param Value Value to write
578 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
580 if( gATA_BusMasterBasePtr )
581 *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;
583 outd( gATA_BusMasterBase + Ofs, Value );