2 * Acess2 IDE Harddisk Driver
5 * Disk Input/Output control
9 #include <modules.h> // Needed for error codes
14 #define IO_DELAY() do{inb(0x80); inb(0x80); inb(0x80); inb(0x80);}while(0)
22 Uint32 PBufAddr; // Physical Buffer Address
23 Uint16 Bytes; // Size of transfer entry
24 Uint16 Flags; // Flags
25 } __attribute__ ((packed)) tPRDT_Ent;
28 * \brief Structure returned by the ATA IDENTIFY command
33 Uint16 Usused1[9]; // 10
34 char SerialNum[20]; // 20
35 Uint16 Usused2[3]; // 23
36 char FirmwareVer[8]; // 27
37 char ModelNumber[40]; // 47
38 Uint16 SectPerInt; // 48 - Low byte only
40 Uint16 Capabilities[2]; // 51
41 Uint16 Unused4[2]; // 53
42 Uint16 ValidExtData; // 54
43 Uint16 Unused5[5]; // 59
44 Uint16 SizeOfRWMultiple; // 60
45 Uint32 Sectors28; // LBA 28 Sector Count
46 Uint16 Unused6[100-62];
47 Uint64 Sectors48; // LBA 48 Sector Count
48 Uint16 Unused7[256-104];
49 } __attribute__ ((packed)) tIdentify;
52 int ATA_SetupIO(void);
53 Uint64 ATA_GetDiskSize(int Disk);
54 Uint16 ATA_GetBasePort(int Disk);
56 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer);
57 int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer);
59 void ATA_IRQHandlerPri(int UNUSED(IRQ));
60 void ATA_IRQHandlerSec(int UNUSED(IRQ));
62 Uint8 ATA_int_BusMasterReadByte(int Ofs);
63 Uint32 ATA_int_BusMasterReadDWord(int Ofs);
64 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value);
65 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value);
68 // - BusMaster IO Addresses
69 Uint32 gATA_BusMasterBase; //!< True Address (IO/MMIO)
70 Uint8 *gATA_BusMasterBasePtr; //!< Paging Mapped MMIO (If needed)
74 volatile int gaATA_IRQs[2] = {0};
75 // - Locks to avoid tripping
76 tSpinlock giaATA_ControllerLock[2];
78 Uint8 gATA_Buffers[2][(MAX_DMA_SECTORS+0xFFF)&~0xFFF] __attribute__ ((section(".padata")));
80 tPRDT_Ent gATA_PRDTs[2] = {
81 {0, 512, IDE_PRDT_LAST},
82 {0, 512, IDE_PRDT_LAST}
84 tPAddr gaATA_PRDT_PAddrs[2];
88 * \brief Sets up the ATA controller's DMA mode
96 // Get IDE Controller's PCI Entry
97 ent = PCI_GetDeviceByClass(0x0101, 0xFFFF, -1);
99 gATA_BusMasterBase = PCI_GetBAR4( ent );
100 if( gATA_BusMasterBase == 0 ) {
101 Log_Warning("ATA", "It seems that there is no Bus Master Controller on this machine. Get one");
102 // TODO: Use PIO mode instead
103 LEAVE('i', MODULE_ERR_NOTNEEDED);
104 return MODULE_ERR_NOTNEEDED;
108 if( !(gATA_BusMasterBase & 1) )
110 if( gATA_BusMasterBase < 0x100000 )
111 gATA_BusMasterBasePtr = (void*)(KERNEL_BASE | (tVAddr)gATA_BusMasterBase);
113 gATA_BusMasterBasePtr = (void*)( MM_MapHWPages( gATA_BusMasterBase, 1 ) + (gATA_BusMasterBase&0xFFF) );
114 LOG("gATA_BusMasterBasePtr = %p", gATA_BusMasterBasePtr);
117 // Bit 0 is left set as a flag to other functions
118 LOG("gATA_BusMasterBase = 0x%x", gATA_BusMasterBase & ~1);
121 // Register IRQs and get Buffers
122 IRQ_AddHandler( gATA_IRQPri, ATA_IRQHandlerPri );
123 IRQ_AddHandler( gATA_IRQSec, ATA_IRQHandlerSec );
125 gATA_PRDTs[0].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[0] );
126 gATA_PRDTs[1].PBufAddr = MM_GetPhysAddr( (tVAddr)&gATA_Buffers[1] );
128 LOG("gATA_PRDTs = {PBufAddr: 0x%x, PBufAddr: 0x%x}", gATA_PRDTs[0].PBufAddr, gATA_PRDTs[1].PBufAddr);
130 gaATA_PRDT_PAddrs[0] = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[0] );
131 LOG("gaATA_PRDT_PAddrs[0] = 0x%x", gaATA_PRDT_PAddrs[0]);
132 ATA_int_BusMasterWriteDWord(4, gaATA_PRDT_PAddrs[0]);
134 gaATA_PRDT_PAddrs[1] = MM_GetPhysAddr( (tVAddr)&gATA_PRDTs[1] );
135 LOG("gaATA_PRDT_PAddrs[1] = 0x%x", gaATA_PRDT_PAddrs[1]);
136 ATA_int_BusMasterWriteDWord(12, gaATA_PRDT_PAddrs[1]);
138 // Enable controllers
139 outb(IDE_PRI_BASE+1, 1);
140 outb(IDE_SEC_BASE+1, 1);
143 LEAVE('i', MODULE_ERR_OK);
144 return MODULE_ERR_OK;
148 * \brief Get the size (in sectors) of a disk
149 * \param Disk Disk to get size of
150 * \return Number of sectors reported
152 * Does an ATA IDENTIFY
154 Uint64 ATA_GetDiskSize(int Disk)
163 ENTER("iDisk", Disk);
165 base = ATA_GetBasePort( Disk );
167 // Send Disk Selector
168 if(Disk & 1) // Slave
174 // Check for a floating bus
175 if( 0xFF == inb(base+7) ) {
181 // Check for the controller
182 // - Write to two RW ports and attempt to read back
183 outb(base+0x02, 0x66);
184 outb(base+0x03, 0xFF);
185 if(inb(base+0x02) != 0x66 || inb(base+0x03) != 0xFF) {
186 LOG("No controller");
192 outb(base+7, HDD_IDENTIFY);
194 val = inb(base+7); // Read status
195 LOG("val = 0x%02x", val);
198 return 0; // Disk does not exist
201 // Poll until BSY clears and DRQ sets or ERR is set
202 while( ((val & 0x80) || !(val & 0x08)) && !(val & 1))
205 // Check for an error
208 return 0; // Error occured, so return false
212 for( i = 0; i < 256; i++ )
213 data.buf[i] = inw(base);
215 // Return the disk size
216 if(data.identify.Sectors48 != 0)
217 return data.identify.Sectors48;
219 return data.identify.Sectors28;
223 * \fn Uint16 ATA_GetPortBase(int Disk)
224 * \brief Returns the base port for a given disk
226 Uint16 ATA_GetBasePort(int Disk)
230 case 0: case 1: return IDE_PRI_BASE;
231 case 2: case 3: return IDE_SEC_BASE;
237 * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
239 int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
241 int cont = (Disk>>1)&1; // Controller ID
246 ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
248 // Check if the count is small enough
249 if(Count > MAX_DMA_SECTORS) {
250 Warning("Passed too many sectors for a bulk DMA read (%i > %i)",
251 Count, MAX_DMA_SECTORS);
256 // Get exclusive access to the disk controller
257 LOCK( &giaATA_ControllerLock[ cont ] );
260 gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
263 base = ATA_GetBasePort(Disk);
266 gaATA_IRQs[cont] = 0;
269 if( Address > 0x0FFFFFFF ) // Use LBA48
271 outb(base+0x6, 0x40 | (disk << 4));
272 outb(base+0x2, 0 >> 8); // Upper Sector Count
273 outb(base+0x3, Address >> 24); // Low 2 Addr
274 outb(base+0x4, Address >> 28); // Mid 2 Addr
275 outb(base+0x5, Address >> 32); // High 2 Addr
279 // Magic, Disk, High Address nibble
280 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F));
283 outb(base+0x01, 0x01); //?
284 outb(base+0x02, (Uint8) Count); // Sector Count
285 outb(base+0x03, (Uint8) Address); // Low Addr
286 outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr
287 outb(base+0x05, (Uint8) (Address >> 16)); // High Addr
289 LOG("Starting Transfer");
291 // HACK: Ensure the PRDT is reset
292 ATA_int_BusMasterWriteDWord(cont*8+4, gaATA_PRDT_PAddrs[cont]);
294 LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes);
295 if( Address > 0x0FFFFFFF )
296 outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48)
298 outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
301 ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
303 // Wait for transfer to complete
304 while( gaATA_IRQs[cont] == 0 ) Threads_Yield();
307 ATA_int_BusMasterWriteByte( cont << 3, 8 ); // Read and stop
310 LOG("Status byte = 0x%02x", val);
312 LOG("gATA_PRDTs[%i].Bytes = %i", cont, gATA_PRDTs[cont].Bytes);
313 LOG("Transfer Completed & Acknowledged");
315 // Copy to destination buffer
316 memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
318 // Release controller lock
319 RELEASE( &giaATA_ControllerLock[ cont ] );
326 * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
327 * \brief Write up to \a MAX_DMA_SECTORS to a disk
328 * \param Disk Disk ID to write to
329 * \param Address LBA of first sector
330 * \param Count Number of sectors to write (must be >= \a MAX_DMA_SECTORS)
331 * \param Buffer Source buffer for data
333 int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, const void *Buffer)
335 int cont = (Disk>>1)&1; // Controller ID
339 // Check if the count is small enough
340 if(Count > MAX_DMA_SECTORS) return 0;
342 // Get exclusive access to the disk controller
343 LOCK( &giaATA_ControllerLock[ cont ] );
346 gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
349 base = ATA_GetBasePort(Disk);
352 outb(base+0x01, 0x00);
353 if( Address > 0x0FFFFFFF ) // Use LBA48
355 outb(base+0x6, 0x40 | (disk << 4));
356 outb(base+0x2, 0 >> 8); // Upper Sector Count
357 outb(base+0x3, Address >> 24); // Low 2 Addr
358 outb(base+0x3, Address >> 28); // Mid 2 Addr
359 outb(base+0x3, Address >> 32); // High 2 Addr
363 // Magic, Disk, High Address nibble
364 outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F));
367 outb(base+0x02, (Uint8) Count); // Sector Count
368 outb(base+0x03, (Uint8) Address); // Low Addr
369 outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr
370 outb(base+0x05, (Uint8) (Address >> 16)); // High Addr
371 if( Address > 0x0FFFFFFF )
372 outb(base+0x07, HDD_DMA_W48); // Write Command (LBA48)
374 outb(base+0x07, HDD_DMA_W28); // Write Command (LBA28)
377 gaATA_IRQs[cont] = 0;
379 // Copy to output buffer
380 memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
383 ATA_int_BusMasterWriteByte( cont << 3, 1 ); // Write and start
385 // Wait for transfer to complete
386 while( gaATA_IRQs[cont] == 0 ) Threads_Yield();
389 ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
391 // Release controller lock
392 RELEASE( &giaATA_ControllerLock[ cont ] );
398 * \brief Primary ATA Channel IRQ handler
400 void ATA_IRQHandlerPri(int UNUSED(IRQ))
404 // IRQ bit set for Primary Controller
405 val = ATA_int_BusMasterReadByte( 0x2 );
406 LOG("IRQ val = 0x%x", val);
408 LOG("IRQ hit (val = 0x%x)", val);
409 ATA_int_BusMasterWriteByte( 0x2, 4 );
416 * \brief Second ATA Channel IRQ handler
418 void ATA_IRQHandlerSec(int UNUSED(IRQ))
421 // IRQ bit set for Secondary Controller
422 val = ATA_int_BusMasterReadByte( 0xA );
423 LOG("IRQ val = 0x%x", val);
425 LOG("IRQ hit (val = 0x%x)", val);
426 ATA_int_BusMasterWriteByte( 0xA, 4 );
433 * \brief Read an 8-bit value from a Bus Master register
434 * \param Ofs Register offset
436 Uint8 ATA_int_BusMasterReadByte(int Ofs)
438 if( gATA_BusMasterBase & 1 )
439 return inb( (gATA_BusMasterBase & ~1) + Ofs );
441 return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
445 * \brief Read an 32-bit value from a Bus Master register
446 * \param Ofs Register offset
448 Uint32 ATA_int_BusMasterReadDWord(int Ofs)
450 if( gATA_BusMasterBase & 1 )
451 return ind( (gATA_BusMasterBase & ~1) + Ofs );
453 return *(Uint32*)(gATA_BusMasterBasePtr + Ofs);
457 * \brief Writes a byte to a Bus Master Register
458 * \param Ofs Register Offset
459 * \param Value Value to write
461 void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
463 if( gATA_BusMasterBase & 1 )
464 outb( (gATA_BusMasterBase & ~1) + Ofs, Value );
466 *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
470 * \brief Writes a 32-bit value to a Bus Master Register
471 * \param Ofs Register offset
472 * \param Value Value to write
474 void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
476 if( gATA_BusMasterBase & 1 )
477 outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
479 *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;