📄 idedriver.cpp
字号:
/*! \file IDEDriver.cpp \brief IDEDriver Copyright (c) 2004 HigePon WITHOUT ANY WARRANTY \author HigePon \version $Revision: 1.1 $ \date create:2004/07/04 update:$Date: 2004/07/04 10:21:56 $*/#include "IDEDriver.h"#include <monapi.h>/*---------------------------------------------------------------------- IDEDriver----------------------------------------------------------------------*/IDEDriver::IDEDriver() : deviceOK(false){ this->ide[0].registers[ATA_DTR] = 0x1f0; this->ide[0].registers[ATA_ERR] = 0x1f1; this->ide[0].registers[ATA_SCR] = 0x1f2; this->ide[0].registers[ATA_SNR] = 0x1f3; this->ide[0].registers[ATA_CLR] = 0x1f4; this->ide[0].registers[ATA_CHR] = 0x1f5; this->ide[0].registers[ATA_DHR] = 0x1f6; this->ide[0].registers[ATA_STR] = 0x1f7; this->ide[0].registers[ATA_ASR] = 0x3f6; this->ide[0].selectedDevice = -1; this->ide[1].registers[ATA_DTR] = 0x170; this->ide[1].registers[ATA_ERR] = 0x171; this->ide[1].registers[ATA_SCR] = 0x172; this->ide[1].registers[ATA_SNR] = 0x173; this->ide[1].registers[ATA_CLR] = 0x174; this->ide[1].registers[ATA_CHR] = 0x175; this->ide[1].registers[ATA_DHR] = 0x176; this->ide[1].registers[ATA_STR] = 0x177; this->ide[1].registers[ATA_ASR] = 0x376; this->ide[1].selectedDevice = -1; /* soft reset */ outp8(&ide[0], ATA_DCR, 0x06); sleep(5); /* disable interrupt */ outp8(&ide[0], ATA_DCR, 0x02); sleep(5); setDevice(PRIMARY, MASTER);}IDEDriver::~IDEDriver(){}int IDEDriver::open(){ return 0;}int IDEDriver::close(){ return 0;}int IDEDriver::read(dword lba, void* buf, int size){ if (!this->deviceOK) return 10; return read(&ide[whichIde], whichDevice, lba, (size + 512 - 1) / 512, buf);}int IDEDriver::write(dword lba, void* buf, int size){ printf("IDEDriver#write not implemented\n"); return 0;}int IDEDriver::ioctl(void* p){ printf("IDEDriver#ioctl not implemented\n"); return 0;}int IDEDriver::setDevice(int ide, int device){ if (ide != PRIMARY && ide != SECONDARY) return 1; if (device != MASTER && device != SLAVE) return 2; whichIde = ide; whichDevice = device; deviceOK = true; return 0;}void IDEDriver::outp8(IDEController* ide, int reg, byte value){ ::outp8(ide->registers[reg], value);}byte IDEDriver::inp8(IDEController* ide, int reg){ return ::inp8(ide->registers[reg]);}word IDEDriver::inp16(IDEController* ide, int reg){ return ::inp16(ide->registers[reg]);}bool IDEDriver::waitBusyClear(IDEController* ide){ dword i; for (i = 0; i < ATA_TIMEOUT; i++) { byte status = inp8(ide, ATA_ASR); if ((status & BIT_BSY) == 0) break; } return (i != ATA_TIMEOUT);}bool IDEDriver::waitDrdySet(IDEController* ide){ dword i; for (i = 0; i < ATA_TIMEOUT; i++) { byte status = inp8(ide, ATA_ASR); if (status & BIT_DRDY) break; } return (i != ATA_TIMEOUT);}bool IDEDriver::selectDevice(IDEController* ide, int device){ dword i; if (ide->selectedDevice == device) return true; for (i = 0; i < ATA_TIMEOUT; i++) { byte data = inp8(ide, ATA_ASR); if ((data & BIT_BSY) == 0 && (data & BIT_DRQ) == 0) break; } /* time out */ if (i == ATA_TIMEOUT) return false; /* select device */ outp8(ide, ATA_DHR, device << 4); sleep(1); for (i = 0; i < ATA_TIMEOUT; i++) { byte data = inp8(ide, ATA_ASR); if ((data & BIT_BSY) == 0 && (data & BIT_DRQ) == 0) break; } /* time out */ if (i == ATA_TIMEOUT) return false; ide->selectedDevice = device; return true;}word IDEDriver::getSignature(IDEController* ide, int device){ dword l; byte c; byte c1 = 0xff; /* unknown signature */ byte c2 = 0xff; /* unknown signature */ bool timeout; for (l = 0; l < RETRY_MAX; l++) { /* select device */ outp8(ide, ATA_DHR, device << 4); sleep(1); c = inp8(ide, ATA_STR); if (c == 0xff) break; timeout = !waitBusyClear(ide); if (timeout) break; c = inp8(ide, ATA_DHR); if ((c & (device << 4)) == (device << 4)) { c1 = inp8(ide, ATA_CLR); c2 = inp8(ide, ATA_CHR); break; } } return c1 | (c2 << 8);}void IDEDriver::read(IDEController* ide, word length, void* buf){ word* p = (word*)buf; if (p == NULL) { for (int i = 0; i < length; i++) { inp16(ide, ATA_DTR); } } else { for (int i = 0; i < length; i++, p++) { *p = inp16(ide, ATA_DTR); } }}int IDEDriver::sendPioDataInCommand(IDEController* ide, ATACommand* command, word count, void* buf){ word* p; p = (word*)buf; /* select deviece */ if (ide->selectedDevice != command->device) { if (!selectDevice(ide, command->device)) return 1; } else { outp8(ide, ATA_DHR, command->device >> 4); } outp8(ide, ATA_DCR, 0x02); /* not use interrupt */ outp8(ide, ATA_FTR, command->feature); /* feature */ outp8(ide, ATA_SCR, command->sectorCount); /* sector count */ outp8(ide, ATA_SNR, command->sectorNumber); /* sector number */ outp8(ide, ATA_CLR, command->cylinderLow); /* cylinderLow */ outp8(ide, ATA_CHR, command->cylinderHigh); /* cylinderHigh */ /* drdy check */ if (command->drdyCheck && !waitDrdySet(ide)) return 2; outp8(ide, ATA_CMR, command->command); /* command */ sleep(1); /* read atlternate status once */ inp8(ide, ATA_ASR); /* read */ for (int i = 0; i < count; i++, p+=256) { if (!waitBusyClear(ide)) return -1; byte status = inp8(ide, ATA_STR); /* command error */ if ((status & BIT_ERR) != 0) return -2; /* data not ready */ if ((status & BIT_DRQ) == 0) return -3; /* data read */ read(ide, 256, p); } inp8(ide, ATA_ASR); byte status = inp8(ide, ATA_STR); if (status & BIT_ERR) { byte error = inp8(ide, ATA_ERR); return 0x1000 | error; } return 0;}int IDEDriver::identify(IDEController* ide, int device, int type, void* buf){ ATACommand com; int result; /* feature, sector count, sector number, cylinder is 0 */ memset(&com, 0, sizeof(ATACommand)); com.device = DEV_HEAD_OBS | (device << 4); if (type == DEVICE_ATA) { com.drdyCheck = 1; com.command = 0xec; /* Identify device */ } else { com.drdyCheck = 0; com.command = 0xa1; /* Identify Packet device */ } /* command execute */ result = sendPioDataInCommand(ide, &com, 1, buf); if (result == -3) return 1; /* device not exist */ else if (result > 0 && (result & BIT_ABRT) != 0) return 2; /* abort */ else if (result > 0) return 3; /* error */ else if (result < 0) return 4; /* timeout or device select error */ return 0;}int IDEDriver::getDeviceType(int ide, int device){ if (ide != PRIMARY && ide != SECONDARY) return DEVICE_NON; if (device != MASTER && device != SLAVE) return DEVICE_NON; return judgeDevice(&(this->ide[ide]), device);}int IDEDriver::judgeDevice(IDEController* ide, int device){ dword i; char buf[1024]; int type; word sigature = getSignature(ide, device); switch(sigature) { case 0xEB14: type = DEVICE_ATAPI; break; case 0: type = DEVICE_ATA; break; default: return DEVICE_NON; } /* unknown device */ if (!waitBusyClear(ide)) return DEVICE_UNKNOWN; for (i = 0; i < RETRY_MAX; i++) { /* try idetify 2 times */ sleep(5); int id1 = identify(ide, device, type, buf); sleep(5); int id2 = identify(ide, device, type, buf); /* retry */ if (id1 != id2) continue; if (id1 == 3 || id1 == 4) continue; if (id1 == 0) return type; } return DEVICE_UNKNOWN;}int IDEDriver::read(IDEController* ide, int device, dword lba, byte blocknum, void* buff){ ATACommand com; word cylinder; /* feature, sector count, sector number, cylinder is 0 */ memset(&com, 0, sizeof(ATACommand)); com.sectorCount = blocknum; com.sectorNumber = lba & 0xff; cylinder = (lba >> 8) & 0xffff; com.cylinderLow = cylinder & 0xff; com.cylinderHigh = (cylinder) >> 8 & 0xff; com.device = DEV_HEAD_OBS | LBA_FLG | (device << 4) | ((lba >> 24) & 0xf); com.command = 0x20; com.drdyCheck = 1; return sendPioDataInCommand(ide, &com, blocknum, buff);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -