- int cont = (Disk>>1)&1; // Controller ID
- int disk = Disk & 1;
- Uint16 base;
- Sint64 timeoutTime;
-
- // Check if the count is small enough
- if(Count > MAX_DMA_SECTORS) return 1;
-
- // Get exclusive access to the disk controller
- Mutex_Acquire( &glaATA_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
- {
- // Magic, Disk, High Address nibble
- outb(base+0x06, 0xE0 | (disk << 4) | ((Address >> 24) & 0x0F));
- }
-
- 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)
-
- // 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
- timeoutTime = now() + ATA_TIMEOUT;
- while( gaATA_IRQs[cont] == 0 && now() < timeoutTime)
- {
- HALT();
- }
-
- // Complete Transfer
- ATA_int_BusMasterWriteByte( cont << 3, 0 ); // Write and stop
-
- // If the IRQ is unset, return error
- if( gaATA_IRQs[cont] == 0 ) {
- // Release controller lock
- Mutex_Release( &glaATA_ControllerLock[ cont ] );
- return 1; // Error
- }
- else {
- Mutex_Release( &glaATA_ControllerLock[ cont ] );
- return 0;
- }