-
-/**
- * \fn int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
- */
-int ATA_ReadDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
-{
- int cont = (Disk>>1)&1; // Controller ID
- int disk = Disk & 1;
- Uint16 base;
-
- ENTER("iDisk XAddress iCount pBuffer", Disk, Address, Count, Buffer);
-
- // Check if the count is small enough
- if(Count > MAX_DMA_SECTORS) {
- Warning("Passed too many sectors for a bulk DMA read (%i > %i)",
- Count, MAX_DMA_SECTORS);
- LEAVE('i');
- return 0;
- }
-
- // Get exclusive access to the disk controller
- LOCK( &giaATA_ControllerLock[ cont ] );
-
- // Set Size
- gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
-
- // Get Port Base
- base = ATA_GetBasePort(Disk);
-
- // Reset IRQ Flag
- gaATA_IRQs[cont] = 0;
-
- // Set up transfer
- outb(base+0x01, 0x00);
- if( Address > 0x0FFFFFFF ) // Use LBA48
- {
- outb(base+0x6, 0x40 | (disk << 4));
- outb(base+0x2, 0 >> 8); // Upper Sector Count
- outb(base+0x3, Address >> 24); // Low 2 Addr
- outb(base+0x3, Address >> 28); // Mid 2 Addr
- outb(base+0x3, Address >> 32); // High 2 Addr
- }
- else
- {
- outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
- }
-
- outb(base+0x02, (Uint8) Count); // Sector Count
- outb(base+0x03, (Uint8) Address); // Low Addr
- outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr
- outb(base+0x05, (Uint8) (Address >> 16)); // High Addr
-
- LOG("Starting Transfer");
- #if START_BEFORE_CMD
- // Start transfer
- ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
- if( Address > 0x0FFFFFFF )
- outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48)
- else
- outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
- #else
- if( Address > 0x0FFFFFFF )
- outb(base+0x07, HDD_DMA_R48); // Read Command (LBA48)
- else
- outb(base+0x07, HDD_DMA_R28); // Read Command (LBA28)
- // Start transfer
- ATA_int_BusMasterWriteByte( cont << 3, 9 ); // Read and start
- #endif
-
- // Wait for transfer to complete
- //ATA_int_BusMasterWriteByte( (cont << 3) + 2, 0x4 );
- while( gaATA_IRQs[cont] == 0 ) {
- //Uint8 val = ATA_int_BusMasterReadByte( (cont << 3) + 2, 0x4 );
- //LOG("val = 0x%02x", val);
- Threads_Yield();
- }
-
- // Complete Transfer
- ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
-
- LOG("Transfer Completed & Acknowledged");
-
- // Copy to destination buffer
- memcpy( Buffer, gATA_Buffers[cont], Count*SECTOR_SIZE );
-
- // Release controller lock
- RELEASE( &giaATA_ControllerLock[ cont ] );
-
- LEAVE('i', 1);
- return 1;
-}
-
-/**
- * \fn int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
- */
-int ATA_WriteDMA(Uint8 Disk, Uint64 Address, Uint Count, void *Buffer)
-{
- int cont = (Disk>>1)&1; // Controller ID
- int disk = Disk & 1;
- Uint16 base;
-
- // Check if the count is small enough
- if(Count > MAX_DMA_SECTORS) return 0;
-
- // Get exclusive access to the disk controller
- LOCK( &giaATA_ControllerLock[ cont ] );
-
- // Set Size
- gATA_PRDTs[ cont ].Bytes = Count * SECTOR_SIZE;
-
- // Get Port Base
- base = ATA_GetBasePort(Disk);
-
- // Set up transfer
- outb(base+0x01, 0x00);
- if( Address > 0x0FFFFFFF ) // Use LBA48
- {
- outb(base+0x6, 0x40 | (disk << 4));
- outb(base+0x2, 0 >> 8); // Upper Sector Count
- outb(base+0x3, Address >> 24); // Low 2 Addr
- outb(base+0x3, Address >> 28); // Mid 2 Addr
- outb(base+0x3, Address >> 32); // High 2 Addr
- }
- else
- {
- outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F)); //Disk,Magic,High addr
- }
-
- outb(base+0x02, (Uint8) Count); // Sector Count
- outb(base+0x03, (Uint8) Address); // Low Addr
- outb(base+0x04, (Uint8) (Address >> 8)); // Middle Addr
- outb(base+0x05, (Uint8) (Address >> 16)); // High Addr
- if( Address > 0x0FFFFFFF )
- outb(base+0x07, HDD_DMA_W48); // Write Command (LBA48)
- else
- outb(base+0x07, HDD_DMA_W28); // Write Command (LBA28)
-
- // Reset IRQ Flag
- gaATA_IRQs[cont] = 0;
-
- // Copy to output buffer
- memcpy( gATA_Buffers[cont], Buffer, Count*SECTOR_SIZE );
-
- // Start transfer
- ATA_int_BusMasterWriteByte( cont << 3, 1 ); // Write and start
-
- // Wait for transfer to complete
- while( gaATA_IRQs[cont] == 0 ) Threads_Yield();
-
- // Complete Transfer
- ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
-
- // Release controller lock
- RELEASE( &giaATA_ControllerLock[ cont ] );
-
- return 1;
-}
-
-/**
- * \fn void ATA_IRQHandlerPri(int unused)
- */
-void ATA_IRQHandlerPri(int unused)
-{
- Uint8 val;
-
- // IRQ bit set for Primary Controller
- val = ATA_int_BusMasterReadByte( 0x2 );
- LOG("IRQ val = 0x%x", val);
- if(val & 4) {
- LOG("IRQ hit (val = 0x%x)", val);
- ATA_int_BusMasterWriteByte( 0x2, 4 );
- gaATA_IRQs[0] = 1;
- return ;
- }
-}
-
-/**
- * \fn void ATA_IRQHandlerSec(int unused)
- */
-void ATA_IRQHandlerSec(int unused)
-{
- Uint8 val;
- // IRQ bit set for Secondary Controller
- val = ATA_int_BusMasterReadByte( 0xA );
- LOG("IRQ val = 0x%x", val);
- if(val & 4) {
- LOG("IRQ hit (val = 0x%x)", val);
- ATA_int_BusMasterWriteByte( 0xA, 4 );
- gaATA_IRQs[1] = 1;
- return ;
- }
-}
-
-/**
- * \fn Uint8 ATA_int_BusMasterReadByte(int Ofs)
- */
-Uint8 ATA_int_BusMasterReadByte(int Ofs)
-{
- if( gATA_BusMasterBase & 1 )
- return inb( (gATA_BusMasterBase & ~1) + Ofs );
- else
- return *(Uint8*)(gATA_BusMasterBasePtr + Ofs);
-}
-
-/**
- * \fn void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
- * \brief Writes a byte to a Bus Master Register
- */
-void ATA_int_BusMasterWriteByte(int Ofs, Uint8 Value)
-{
- if( gATA_BusMasterBase & 1 )
- outb( (gATA_BusMasterBase & ~1) + Ofs, Value );
- else
- *(Uint8*)(gATA_BusMasterBasePtr + Ofs) = Value;
-}
-
-/**
- * \fn void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
- * \brief Writes a dword to a Bus Master Register
- */
-void ATA_int_BusMasterWriteDWord(int Ofs, Uint32 Value)
-{
-
- if( gATA_BusMasterBase & 1 )
- outd( (gATA_BusMasterBase & ~1) + Ofs, Value );
- else
- *(Uint32*)(gATA_BusMasterBasePtr + Ofs) = Value;
-}