DOS中调用INT13中断操作磁盘 tc3.0
来源:互联网 发布:snmp开发java 编辑:程序博客网 时间:2024/06/06 03:52
通过调用中断操作磁盘,进行扇区操作。
/* disk.cpp * * Source file for implementation of CDisk, * * Authors: perry* Date : February 21, 2011 * class : CDisk * * History: * 2011/02/21 perry created. */CDisk::CDisk(uint16_t driver) : m_int13ext_ver(0), m_valid(false), m_drive(0){ union REGS regs; struct SREGS sregs; // try multiple times, if error. for ( int i = 0; i < CALL_INT_TRIES; i++ ) { regs.h.ah = 0x41; regs.x.bx = 0x55aa; regs.h.dl = driver | 0x80; // confirm ext int 13 can be support. int86x(0x13, ®s, ®s, &sregs); if ( regs.x.cflag || regs.x.bx != 0xaa55 ) continue; // 01h = 1.x // 20h = 2.0 / EDD-1.0 // 21h = 2.1 / EDD-1.1 // 30h = EDD-3.0 m_int13ext_ver = regs.h.ah; break; } regs.h.ah = 0x08; regs.h.dl = driver | 0x80; int86x(0x13, ®s, ®s, &sregs); if ( regs.h.dl <= driver ) { fprintf(stderr, "%d: drive not found\n", driver); return; } if ( regs.x.cflag ) {#ifdef _DEBUG CException * exp = NULL; exp = new CExceptInt13(regs.h.ah); exp->show(); exp->destroy();#endif return; } m_drive = driver; m_valid = true; m_cylinder_count = ((((int)regs.h.cl << 2) & 0x300) | regs.h.ch) + 1; m_head_count = regs.h.dh + 1; m_sector_count = regs.h.cl & 0x3f;}bool CDisk::callBios_CHS( uint16_t cmd, uint16_t cylinder, uint16_t head, uint16_t sector, uint16_t count, CBufferT<uint8_t> _FAR & buff){ union REGS regs; struct SREGS sregs; if ( sector < 1 ) return false; sector &= 0x3f; if ( cylinder > 0xff ) sector |= (cylinder >> 0x02) & 0xc0; segread(&sregs); // set up packet. regs.x.bx = FP_OFF((void _FAR *)buff); sregs.es = FP_SEG((void _FAR *)buff); // set up registers for INT 13h AH = 02/03h. regs.h.ch = cylinder; // low eight bits of cylinder number regs.h.cl = sector; // start sector and high two bits of cylinder regs.h.dh = head; // head regs.h.dl = m_drive | 0x80; // drive number // try multiple times, if error. for ( int i = 0; i < CALL_INT_TRIES; i++ ) { switch ( cmd ) { case DISK_RESET: regs.h.ah = 0x00; // reset. break; case DISK_STATUS: regs.h.ah = 0x01; // status. break; case DISK_READ: regs.h.ah = 0x02; // read. break; case DISK_WRITE: regs.h.ah = 0x03; // write. break; case DISK_VERIFY: regs.h.ah = 0x04; // verify. break; default:#ifdef _DEBUG fprintf(stderr, "%d, invalid command.\n", cmd);#endif return false; } // set sector count. regs.h.al = count; // call BIOS interrup int86x(0x13, ®s, ®s, &sregs); // call succeed. if ( !regs.x.cflag && !regs.h.ah ) return true;#ifdef _DEBUG // CF set on error CException * exp = NULL; exp = new CExceptInt13(regs.h.ah); exp->show(); exp->destroy();#endif // reset disk regs.h.ah = 0; // call BIOS interrup int86x(0x13, ®s, ®s, &sregs); } return false;}bool CDisk::callBios_LBA( uint16_t cmd, uint64_t lba, uint16_t count, CBufferT<uint8_t> _FAR & buff){ union REGS regs; struct SREGS sregs; struct lba_addr_pkt packet; segread(&sregs); // set up packet. sregs.ds = FP_SEG(&packet); regs.x.si = FP_OFF(&packet); packet.pkt_len = sizeof(lba_addr_pkt); packet.nsects = count; packet.buf_off = FP_OFF((void _FAR *)buff); packet.buf_seg = FP_SEG((void _FAR *)buff); packet.lba = lba; // set up registers for INT 13h AH = 02/03h. regs.h.ah = 0x42; // extended read. regs.h.dl = m_drive | 0x80; // drive number // try multiple times, if error. for ( int i = 0; i < CALL_INT_TRIES; i++ ) { switch ( cmd ) { case DISK_RESET: regs.h.ah = 0x00; // reset. break; case DISK_STATUS: regs.h.ah = 0x01; // status. break; case DISK_READ: regs.h.ah = 0x42; // read. regs.h.al = 0x00; /* AL = write flags ---v1.0,2.0--- bit 0: verify write bits 7-1 reserved (0) ---v2.1+ --- 00h,01h write without verify 02h write with verify */ break; case DISK_WRITE: regs.h.ah = 0x43; // write. break; case DISK_VERIFY: regs.h.ah = 0x04; // verify. break; default:#ifdef _DEBUG fprintf(stderr, "%d, invalid command.\n", cmd);#endif return false; } // call BIOS interrup int86x(0x13, ®s, ®s, &sregs); // call succeed. if ( !regs.x.cflag && !regs.h.ah ) return true;#ifdef _DEBUG // CF set on error CException * exp = NULL; exp = new CExceptInt13Ex(regs.h.ah); exp->show(); exp->destroy();#endif // reset disk regs.h.ah = 0; // call BIOS interrup int86x(0x13, ®s, ®s, &sregs); } return false;}bool CDisk::readSectors( uint32_t lba31_0, uint32_t lba63_32, uint16_t count, CBufferT<uint8_t> _FAR & buff){ uint64_t lba; // using 64 bit address. lba.dwords.dw1 = lba31_0; lba.dwords.dw2 = lba63_32; return readSectors(lba, count, buff);}bool CDisk::writeSectors( uint32_t lba31_0, uint32_t lba63_32, uint16_t count, CBufferT<uint8_t> _FAR & buff){ uint64_t lba; // using 64 bit address. lba.dwords.dw1 = lba31_0; lba.dwords.dw2 = lba63_32; return writeSectors(lba, count, buff);}bool CDisk::readSectors( uint64_t lba, uint16_t count, CBufferT<uint8_t> _FAR & buff){ if ( !isValid() ) return false; // the number of sector must be greater than zero. if ( count < 1 ) {#ifdef _DEBUG fprintf(stderr, "number of sectors must be greater than 0; (%d).\n", count);#endif return false; } // check size of buffer. if ( buff.length() < (count * SECTOR_PER_BYTES) ) {#ifdef _DEBUG fprintf(stderr, "size of buffer too small; %d < (%d * %d).\n", buff.length(), count, SECTOR_PER_BYTES);#endif return false; } // clear buffer buff.clear(); // if support ext int13. using LBA mode. if ( m_int13ext_ver > 0 ) {#ifdef _DEBUG fprintf(stdout, "DISK_READ LBA %04x.\n", m_int13ext_ver);#endif if ( callBios_LBA(DISK_READ, lba, count, buff) ) return true; } // CHS params. uint16_t cylinder, head, sector; // translate a LBA value to an CHS value. if ( !LBA2CHS(lba, &cylinder, &head, §or) ) return false;#ifdef _DEBUG fprintf(stdout, "DISK_READ CHS.\n");#endif // using CHS mode to read sectors. return callBios_CHS(DISK_READ, cylinder, head, sector, count, buff);}bool CDisk::writeSectors( uint64_t lba, uint16_t count, CBufferT<uint8_t> _FAR & buff){ if ( !isValid() ) return false; // the number of sector must be greater than zero. if ( count < 1 ) {#ifdef _DEBUG fprintf(stderr, "number of sectors must be greater than 0; (%d).\n", count);#endif return false; } // check size of buffer. if ( buff.length() < (count * SECTOR_PER_BYTES) ) {#ifdef _DEBUG fprintf(stderr, "size of buffer too small; %d < (%d * %d).\n", buff.length(), count, SECTOR_PER_BYTES);#endif return false; } // if support ext int13. using LBA mode. if ( m_int13ext_ver > 0 ) {#ifdef _DEBUG fprintf(stdout, "DISK_WRITE LBA %04x.\n", m_int13ext_ver);#endif if ( callBios_LBA(DISK_WRITE, lba, count, buff) ) return true; } // CHS params. uint16_t cylinder, head, sector;#ifdef _DEBUG fprintf(stdout, "DISK_WRITE CHS.\n");#endif // translate a LBA value to an CHS value. if ( !LBA2CHS(lba, &cylinder, &head, §or) ) return false; // using CHS mode to read sectors. return callBios_CHS(DISK_WRITE, cylinder, head, sector, count, buff);}bool CDisk::LBA2CHS( uint64_t lba, uint16_t _FAR * pCylinder, uint16_t _FAR * pHead, uint16_t _FAR * pSector){ uint32_t temp1 = m_head_count * m_sector_count, temp2; if ( !temp1 ) return false; temp2 = lba.dwords.dw1 % temp1; *pCylinder = (uint16_t)((lba.dwords.dw1 - temp2) / temp1); *pHead = (uint16_t)(temp2 / m_sector_count); *pSector = (uint16_t)(temp2 % m_sector_count + 1); return true;}bool CDisk::CHS2LBA( uint16_t cylinder, uint16_t head, uint16_t sector, uint64_t _FAR * plba){ if ( sector < 1 ) return false; plba->dwords.dw1 = ((cylinder * m_head_count + head) * m_sector_count) + sector - 1; plba->dwords.dw2 = 0; return true;}bool CDisk::saveSectors( uint32_t lba, uint16_t num, const CString _FAR & file){ if ( !isValid() ) return false; CBufferT buff(SECTOR_PER_BYTES); bool result = true; CFile ffout(file); for ( int i = 0; i < num; i++ ) { if ( !readSectors(lba + i, 0, 1, buff) ) {#ifdef _DEBUG fprintf(stderr, "FAIL ==> readSectors\n");#endif result = false; break; } if ( ffout.write(buff) != SECTOR_PER_BYTES ) {#ifdef _DEBUG fprintf(stderr, "FAIL ==> ffout.Write\n");#endif result = false; break; } }#ifdef _DEBUG if ( !result ) fprintf(stdout, "FAIL ==> saveSectors\n"); else fprintf(stdout, "PASS ==> saveSectors\n");#endif return result;}bool CDisk::saveSectors( uint32_t lba, uint16_t num, CBufferT _FAR & buff){ if ( !isValid() ) return false; if ( buff.length() < (num * SECTOR_PER_BYTES) ) return false; return readSectors(lba, 0, num, buff);}bool CDisk::fillSectors( uint32_t lba, uint16_t num, const CString _FAR & file){ if ( !isValid() ) return false; CBufferT buff(SECTOR_PER_BYTES); bool result = true; CFile ffin(file, O_RDONLY | O_BINARY); for ( int i = 0; i < num; i++ ) { // zero buffer buff.clear(); // read data from file. if ( ffin.read(buff) != SECTOR_PER_BYTES ) {#ifdef _DEBUG fprintf(stderr, "FAIL ==> ffin.Read\n");#endif result = false; break; } // write buffer to sector. if ( !writeSectors(lba + i, 0, 1, buff) ) {#ifdef _DEBUG fprintf(stderr, "FAIL ==> writeSectors\n");#endif result = false; break; } }#ifdef _DEBUG if ( !result ) fprintf(stdout, "FAIL ==> fillSectors\n"); else fprintf(stdout, "PASS ==> fillSectors\n");#endif return result;}bool CDisk::fillSectors( uint32_t lba, uint16_t num, uint8_t val){ if ( !isValid() ) return false; CBufferT buff(SECTOR_PER_BYTES); bool result = true; // fill buffer buff.clear(); for ( int i = 0; i < num; i++ ) { if ( !writeSectors(lba + i, 0, 1, buff) ) {#ifdef _DEBUG fprintf(stderr, "FAIL ==> writeSectors\n");#endif result = false; break; } }#ifdef _DEBUG if ( !result ) fprintf(stdout, "FAIL ==> fillSectors\n"); else fprintf(stdout, "PASS ==> fillSectors\n");#endif return result;}const char* CDisk::toString(void){ return "CDisk";}
- DOS中调用INT13中断操作磁盘 tc3.0
- INT13中断详解
- INT13 INT19 中断作用
- INT13中断详解
- tc3.0中创建工程
- 基本INT13调用
- COM通讯例子(MS-DOS, TC3.0编译)
- 俄罗斯方块的源码,运行平台:DOS+TC3.0
- TC3.0
- TC3.0中graphics.h链接错误的解决办法
- 在 Win7 下运行 TC 2.0 / TC3.0 / BC 3.1 / QB 4.5 等 DOS 开发工具
- 初识TC3.0
- BIOS中断调用与DOS功能调用
- DOS命令(2) 磁盘操作类命令
- 在dos中操作
- dos中操作数据库
- DOS系统功能调用与BIOS中断调用
- DOS系统功能调用与BIOS中断调用
- 暴风影音第五代发布:左眼技术画质超越DVD
- 不用安装oracle客户端也可以用plsql连接远程oracle
- oracle rac overview
- 应付会计信息传送至总帐
- 最短路径研究综述
- DOS中调用INT13中断操作磁盘 tc3.0
- Oracle存储过程
- C++中注释多行快捷键设置
- CAD命令标志
- MySQL数据库服务器端核心参数详解和推荐
- 信号量和进程共享内存的小例子
- 队列(queue)之基础实现
- 操作系统计数器
- 敌兵布阵 1166 HDU 线段树