void disableAllIRQ( void ) { outByte( (word)0x21u, 0xFFu ); ioWait(); outByte( (word)0xA1u, 0xFFu ); ioWait(); }
void enableAllIRQ( void ) { outByte( (word)0x21u, 0 ); ioWait(); outByte( (word)0xA1u, 0 ); ioWait(); }
void sendEOI( void ) { outByte( (word)0x20u, (byte)0x20u ); ioWait(); outByte( (word)0xA0u, (byte)0x20u ); ioWait(); }
void X86AtaDevice::identify() const { // Set features register. 0 = PIO, 1 = DMA. outb(_ioPort + 1, 0); outb(_controlPort, 0); // select device outb(_ioPort + kAtaRegisterDriveSelect, 0xA0 | _slaveBit << 4); ioWait(); switch (type()) { case Type::PATAPI: case Type::SATAPI: // send IDENTIFY PACKET DEVICE outb(_ioPort + 0x07, 0xA1); break; case Type::PATA: case Type::SATA: // send IDENTIFY DEVICE outb(_ioPort + 0x07, 0xEC); break; case Type::Unknown: return; } ioWait(); // read in status waitUntilReady(false); // read in device information uint16_t identity[256]; pioRead(identity, 256); _descriptor.readIdentity(identity); _identified = true; if (type() == Type::PATAPI) { uint16_t data[4]; performPioAtapiOperation(AtapiCommand::readCapacityCommand(), data, sizeof(data)); _descriptor.readAtapiCapacity(data); } }
void disableIRQ( unsigned int irq ) { byte data; if( irq > 15 ) return; if( irq < 8 ) { data = inByte( (word)0x21 ); ioWait(); outByte( (word)0x21, data | (byte)(1u << irq)); ioWait(); } else { data = inByte( (word)0xA1 ); ioWait(); outByte( (word)0xA1, data | (byte)(1u << (irq-8))); ioWait(); } }
void enableIRQ( unsigned int irq ) { byte data; if( irq > 15 ) return; if( irq < 8 ) { data = inByte( (word)0x21u ); ioWait(); outByte( (word)0x21u, data & (byte)~(1u << irq)); ioWait(); } else { data = inByte( (word)0xA1u ); ioWait(); outByte( (word)0xA1u, data & (byte)~(1u << (irq-8))); ioWait(); } }
X86AtaDevice::Type X86AtaDevice::type() const { softReset(); /* waits until master drive is ready again */ outb(_ioPort + kAtaRegisterDriveSelect, 0xA0 | _slaveBit<<4); ioWait(); /* wait 400ns for drive select to work */ uint8_t cl = inb(_ioPort + kAtaRegisterCylinderLow); /* get the "signature bytes" */ uint8_t ch = inb(_ioPort + kAtaRegisterCylinderHigh); /* differentiate ATA, ATAPI, SATA and SATAPI */ if (cl==0x14 && ch==0xEB) return Type::PATAPI; if (cl==0x69 && ch==0x96) return Type::SATAPI; if (cl==0 && ch == 0) return Type::PATA; if (cl==0x3c && ch==0xc3) return Type::SATA; return Type::Unknown; }
uint8_t X86AtaDevice::waitUntilReady(bool errorCheck) const { uint8_t status = 0; ioWait(); status = waitForStatus(-1); if (errorCheck) { status = inb(_ioPort + kAtaRegisterStatus); if (status & kAtaStatusBitError) return 1; if (status & kAtaStatusBitDriveFault) return 1; if (!(status & kAtaStatusBitDRQ)) return 1; } return 0; }
bool X86AtaDevice::readInternal(uint64_t address, uint16_t *buf, size_t sectors) { const size_t maxByteCount = sectorSize() * sectors; outb(_ioPort + kAtaRegisterDriveSelect, 0xA0 | _slaveBit << 4); ioWait(); switch (type()) { case Type::PATAPI: case Type::SATAPI: // send READ(12) return performPioAtapiOperation(AtapiCommand::read12Command(address, sectors), buf, maxByteCount); case Type::PATA: case Type::SATA: // should send something, but for now... kernel->panic("Attempted to read from unsupported ATA device."); return false; default: return false; } }
void X86AtaDevice::softReset() const { outb(_controlPort, 0x04); ioWait(); outb(_controlPort, 0x00); }