static int cdemu_read(struct disk_op_s *op) { struct drive_s *drive_g; drive_g = GLOBALFLAT2GLOBAL(GET_LOW(CDEmu.emulated_drive_gf)); struct disk_op_s dop; dop.drive_g = drive_g; dop.command = op->command; dop.lba = GET_LOW(CDEmu.ilba) + op->lba / 4; int count = op->count; op->count = 0; u8 *cdbuf_fl = GET_GLOBAL(bounce_buf_fl); if (op->lba & 3) { // Partial read of first block. dop.count = 1; dop.buf_fl = cdbuf_fl; int ret = process_op(&dop); if (ret) return ret; u8 thiscount = 4 - (op->lba & 3); if (thiscount > count) thiscount = count; count -= thiscount; memcpy_fl(op->buf_fl, cdbuf_fl + (op->lba & 3) * 512, thiscount * 512); op->buf_fl += thiscount * 512; op->count += thiscount; dop.lba++; } if (count > 3) { // Read n number of regular blocks. dop.count = count / 4; dop.buf_fl = op->buf_fl; int ret = process_op(&dop); op->count += dop.count * 4; if (ret) return ret; u8 thiscount = count & ~3; count &= 3; op->buf_fl += thiscount * 512; dop.lba += thiscount / 4; } if (count) { // Partial read on last block. dop.count = 1; dop.buf_fl = cdbuf_fl; int ret = process_op(&dop); if (ret) return ret; u8 thiscount = count; memcpy_fl(op->buf_fl, cdbuf_fl, thiscount * 512); op->count += thiscount; } return DISK_RET_SUCCESS; }
struct drive_s * getDrive(u8 exttype, u8 extdriveoffset) { if (extdriveoffset >= ARRAY_SIZE(IDMap[0])) return NULL; struct drive_s *drive_gf = GET_GLOBAL(IDMap[exttype][extdriveoffset]); if (!drive_gf) return NULL; return GLOBALFLAT2GLOBAL(drive_gf); }
// read disk drive parameters static void noinline disk_1308(struct bregs *regs, struct drive_s *drive_g) { u16 ebda_seg = get_ebda_seg(); // Get logical geometry from table u16 nlc, nlh, nlspt; fillLCHS(drive_g, &nlc, &nlh, &nlspt); nlc--; nlh--; u8 count; if (regs->dl < EXTSTART_HD) { // Floppy count = GET_GLOBAL(FloppyCount); if (CONFIG_CDROM_EMU && drive_g == GLOBALFLAT2GLOBAL(GET_GLOBAL(cdemu_drive_gf))) regs->bx = GET_EBDA2(ebda_seg, cdemu.media) * 2; else regs->bx = GET_GLOBAL(drive_g->floppy_type); // set es & di to point to 11 byte diskette param table in ROM regs->es = SEG_BIOS; regs->di = (u32)&diskette_param_table2; } else if (regs->dl < EXTSTART_CD) { // Hard drive count = GET_BDA(hdcount); nlc--; // last sector reserved } else { // Not supported on CDROM disk_ret(regs, DISK_RET_EPARAM); return; } if (CONFIG_CDROM_EMU && GET_EBDA2(ebda_seg, cdemu.active)) { u8 emudrive = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive); if (((emudrive ^ regs->dl) & 0x80) == 0) // Note extra drive due to emulation. count++; if (regs->dl < EXTSTART_HD && count > 2) // Max of two floppy drives. count = 2; } regs->al = 0; regs->ch = nlc & 0xff; regs->cl = ((nlc >> 2) & 0xc0) | (nlspt & 0x3f); regs->dh = nlh; disk_ret(regs, DISK_RET_SUCCESS); regs->dl = count; }
// Get the cylinders/heads/sectors for the given drive. static void fillLCHS(struct drive_s *drive_g, u16 *nlc, u16 *nlh, u16 *nlspt) { if (CONFIG_CDROM_EMU && drive_g == GLOBALFLAT2GLOBAL(GET_GLOBAL(cdemu_drive_gf))) { // Emulated drive - get info from ebda. (It's not possible to // populate the geometry directly in the driveid because the // geometry is only known after the bios segment is made // read-only). u16 ebda_seg = get_ebda_seg(); *nlc = GET_EBDA2(ebda_seg, cdemu.lchs.cylinders); *nlh = GET_EBDA2(ebda_seg, cdemu.lchs.heads); *nlspt = GET_EBDA2(ebda_seg, cdemu.lchs.spt); return; } *nlc = GET_GLOBAL(drive_g->lchs.cylinders); *nlh = GET_GLOBAL(drive_g->lchs.heads); *nlspt = GET_GLOBAL(drive_g->lchs.spt); }
// Get the cylinders/heads/sectors for the given drive. static struct chs_s getLCHS(struct drive_s *drive_g) { struct chs_s res = { }; if (CONFIG_CDROM_EMU && drive_g == GLOBALFLAT2GLOBAL(GET_GLOBAL(cdemu_drive_gf))) { // Emulated drive - get info from CDEmu. (It's not possible to // populate the geometry directly in the driveid because the // geometry is only known after the bios segment is made // read-only). res.cylinders = GET_LOW(CDEmu.lchs.cylinders); res.heads = GET_LOW(CDEmu.lchs.heads); res.spt = GET_LOW(CDEmu.lchs.spt); return res; } res.cylinders = GET_GLOBAL(drive_g->lchs.cylinders); res.heads = GET_GLOBAL(drive_g->lchs.heads); res.spt = GET_GLOBAL(drive_g->lchs.spt); return res; }