}
// Otherwise use a heuristic to determine translation type.
- u16 heads = GET_GLOBAL(drive_g->pchs.heads);
- u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders);
- u16 spt = GET_GLOBAL(drive_g->pchs.spt);
+ u16 heads = GET_GLOBAL(drive_g->pchs.head);
+ u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinder);
+ u16 spt = GET_GLOBAL(drive_g->pchs.sector);
u64 sectors = GET_GLOBAL(drive_g->sectors);
u64 psectors = (u64)heads * cylinders * spt;
if (!heads || !cylinders || !spt || psectors > sectors)
u8 translation = get_translation(drive_g);
SET_GLOBAL(drive_g->translation, translation);
- u16 heads = GET_GLOBAL(drive_g->pchs.heads);
- u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders);
- u16 spt = GET_GLOBAL(drive_g->pchs.spt);
+ u16 heads = GET_GLOBAL(drive_g->pchs.head);
+ u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinder);
+ u16 spt = GET_GLOBAL(drive_g->pchs.sector);
u64 sectors = GET_GLOBAL(drive_g->sectors);
const char *desc = NULL;
cylinders = 1024;
dprintf(1, "drive %p: PCHS=%u/%d/%d translation=%s LCHS=%d/%d/%d s=%d\n"
, drive_g
- , drive_g->pchs.cylinders, drive_g->pchs.heads, drive_g->pchs.spt
+ , drive_g->pchs.cylinder, drive_g->pchs.head, drive_g->pchs.sector
, desc
, cylinders, heads, spt
, (u32)sectors);
- SET_GLOBAL(drive_g->lchs.heads, heads);
- SET_GLOBAL(drive_g->lchs.cylinders, cylinders);
- SET_GLOBAL(drive_g->lchs.spt, spt);
+ SET_GLOBAL(drive_g->lchs.head, heads);
+ SET_GLOBAL(drive_g->lchs.cylinder, cylinders);
+ SET_GLOBAL(drive_g->lchs.sector, spt);
}
if (hdid > 1)
return;
- u16 nlc = GET_GLOBAL(drive_g->lchs.cylinders);
- u16 nlh = GET_GLOBAL(drive_g->lchs.heads);
- u16 nlspt = GET_GLOBAL(drive_g->lchs.spt);
+ u16 nlc = GET_GLOBAL(drive_g->lchs.cylinder);
+ u16 nlh = GET_GLOBAL(drive_g->lchs.head);
+ u16 nls = GET_GLOBAL(drive_g->lchs.sector);
- u16 npc = GET_GLOBAL(drive_g->pchs.cylinders);
- u16 nph = GET_GLOBAL(drive_g->pchs.heads);
- u16 npspt = GET_GLOBAL(drive_g->pchs.spt);
+ u16 npc = GET_GLOBAL(drive_g->pchs.cylinder);
+ u16 nph = GET_GLOBAL(drive_g->pchs.head);
+ u16 nps = GET_GLOBAL(drive_g->pchs.sector);
struct fdpt_s *fdpt = &get_ebda_ptr()->fdpt[hdid];
fdpt->precompensation = 0xffff;
fdpt->landing_zone = npc;
fdpt->cylinders = nlc;
fdpt->heads = nlh;
- fdpt->sectors = nlspt;
+ fdpt->sectors = nls;
- if (nlc != npc || nlh != nph || nlspt != npspt) {
+ if (nlc != npc || nlh != nph || nls != nps) {
// Logical mapping present - use extended structure.
// complies with Phoenix style Translated Fixed Disk Parameter
// Table (FDPT)
fdpt->phys_cylinders = npc;
fdpt->phys_heads = nph;
- fdpt->phys_sectors = npspt;
+ fdpt->phys_sectors = nps;
fdpt->a0h_signature = 0xa0;
// Checksum structure.
****************************************************************/
struct chs_s {
- u16 heads; // # heads
- u16 cylinders; // # cylinders
- u16 spt; // # sectors / track
+ u16 head;
+ u16 cylinder;
+ u16 sector;
u16 pad;
};
SET_INT13ET(regs, buffer_segment, GET_LOW(CDEmu.buffer_segment));
SET_INT13ET(regs, load_segment, GET_LOW(CDEmu.load_segment));
SET_INT13ET(regs, sector_count, GET_LOW(CDEmu.sector_count));
- SET_INT13ET(regs, cylinders, GET_LOW(CDEmu.lchs.cylinders));
- SET_INT13ET(regs, sectors, GET_LOW(CDEmu.lchs.spt));
- SET_INT13ET(regs, heads, GET_LOW(CDEmu.lchs.heads));
+ SET_INT13ET(regs, cylinders, GET_LOW(CDEmu.lchs.cylinder));
+ SET_INT13ET(regs, sectors, GET_LOW(CDEmu.lchs.sector));
+ SET_INT13ET(regs, heads, GET_LOW(CDEmu.lchs.head));
// If we have to terminate emulation
if (regs->al == 0x00) {
switch (media) {
case 0x01: // 1.2M floppy
- CDEmu.lchs.spt = 15;
- CDEmu.lchs.cylinders = 80;
- CDEmu.lchs.heads = 2;
+ CDEmu.lchs.sector = 15;
+ CDEmu.lchs.cylinder = 80;
+ CDEmu.lchs.head = 2;
break;
case 0x02: // 1.44M floppy
- CDEmu.lchs.spt = 18;
- CDEmu.lchs.cylinders = 80;
- CDEmu.lchs.heads = 2;
+ CDEmu.lchs.sector = 18;
+ CDEmu.lchs.cylinder = 80;
+ CDEmu.lchs.head = 2;
break;
case 0x03: // 2.88M floppy
- CDEmu.lchs.spt = 36;
- CDEmu.lchs.cylinders = 80;
- CDEmu.lchs.heads = 2;
+ CDEmu.lchs.sector = 36;
+ CDEmu.lchs.cylinder = 80;
+ CDEmu.lchs.head = 2;
break;
}
} else {
u8 cyllow = GET_FARVAR(boot_segment, mbr->partitions[0].last.cyllow);
u8 heads = GET_FARVAR(boot_segment, mbr->partitions[0].last.heads);
- CDEmu.lchs.spt = sptcyl & 0x3f;
- CDEmu.lchs.cylinders = ((sptcyl<<2)&0x300) + cyllow + 1;
- CDEmu.lchs.heads = heads + 1;
+ CDEmu.lchs.sector = sptcyl & 0x3f;
+ CDEmu.lchs.cylinder = ((sptcyl<<2)&0x300) + cyllow + 1;
+ CDEmu.lchs.head = heads + 1;
}
// everything is ok, so from now on, the emulation is active
// 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);
+ res.cylinder = GET_LOW(CDEmu.lchs.cylinder);
+ res.head = GET_LOW(CDEmu.lchs.head);
+ res.sector = GET_LOW(CDEmu.lchs.sector);
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);
+ res.cylinder = GET_GLOBAL(drive_g->lchs.cylinder);
+ res.head = GET_GLOBAL(drive_g->lchs.head);
+ res.sector = GET_GLOBAL(drive_g->lchs.sector);
return res;
}
dop.count = count;
struct chs_s chs = getLCHS(drive_g);
- u16 nlc=chs.cylinders, nlh=chs.heads, nlspt=chs.spt;
+ u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector;
// sanity check on cyl heads, sec
- if (cylinder >= nlc || head >= nlh || sector > nlspt) {
+ if (cylinder >= nlc || head >= nlh || sector > nls) {
warn_invalid(regs);
disk_ret(regs, DISK_RET_EPARAM);
return;
}
// translate lchs to lba
- dop.lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt)
+ dop.lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nls)
+ (u32)sector - 1);
dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx);
debug_stub(regs);
struct chs_s chs = getLCHS(drive_g);
- u16 nlh=chs.heads, nlspt=chs.spt;
+ u16 nlh=chs.head, nls=chs.sector;
u8 num_sectors = regs->al;
u8 head = regs->dh;
- if (head >= nlh || num_sectors == 0 || num_sectors > nlspt) {
+ if (head >= nlh || num_sectors == 0 || num_sectors > nls) {
disk_ret(regs, DISK_RET_EPARAM);
return;
}
{
// Get logical geometry from table
struct chs_s chs = getLCHS(drive_g);
- u16 nlc=chs.cylinders, nlh=chs.heads, nlspt=chs.spt;
+ u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector;
nlc--;
nlh--;
u8 count;
regs->al = 0;
regs->ch = nlc & 0xff;
- regs->cl = ((nlc >> 2) & 0xc0) | (nlspt & 0x3f);
+ regs->cl = ((nlc >> 2) & 0xc0) | (nls & 0x3f);
regs->dh = nlh;
disk_ret(regs, DISK_RET_SUCCESS);
// Get logical geometry from table
struct chs_s chs = getLCHS(drive_g);
- u16 nlc=chs.cylinders, nlh=chs.heads, nlspt=chs.spt;
+ u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector;
// Compute sector count seen by int13
- u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nlspt;
+ u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nls;
regs->cx = lba >> 16;
regs->dx = lba & 0xffff;
regs->ah = 3; // hard disk accessible
// EDD 1.x
u8 type = GET_GLOBAL(drive_g->type);
- u16 npc = GET_GLOBAL(drive_g->pchs.cylinders);
- u16 nph = GET_GLOBAL(drive_g->pchs.heads);
- u16 npspt = GET_GLOBAL(drive_g->pchs.spt);
+ u16 npc = GET_GLOBAL(drive_g->pchs.cylinder);
+ u16 nph = GET_GLOBAL(drive_g->pchs.head);
+ u16 nps = GET_GLOBAL(drive_g->pchs.sector);
u64 lba = GET_GLOBAL(drive_g->sectors);
u16 blksize = GET_GLOBAL(drive_g->blksize);
dprintf(DEBUG_HDL_13, "disk_1348 size=%d t=%d chs=%d,%d,%d lba=%d bs=%d\n"
- , size, type, npc, nph, npspt, (u32)lba, blksize);
+ , size, type, npc, nph, nps, (u32)lba, blksize);
SET_FARVAR(seg, param_far->size, 26);
if (type == DTYPE_ATA_ATAPI) {
SET_FARVAR(seg, param_far->spt, 0xffffffff);
SET_FARVAR(seg, param_far->sector_count, (u64)-1);
} else {
- if (lba > (u64)npspt*nph*0x3fff) {
+ if (lba > (u64)nps*nph*0x3fff) {
SET_FARVAR(seg, param_far->infos, 0x00); // geometry is invalid
SET_FARVAR(seg, param_far->cylinders, 0x3fff);
} else {
SET_FARVAR(seg, param_far->cylinders, (u32)npc);
}
SET_FARVAR(seg, param_far->heads, (u32)nph);
- SET_FARVAR(seg, param_far->spt, (u32)npspt);
+ SET_FARVAR(seg, param_far->spt, (u32)nps);
SET_FARVAR(seg, param_far->sector_count, lba);
}
SET_FARVAR(seg, param_far->blksize, blksize);
// found disk (ata)
port->drive.type = DTYPE_AHCI;
port->drive.blksize = DISK_SECTOR_SIZE;
- port->drive.pchs.cylinders = buffer[1];
- port->drive.pchs.heads = buffer[3];
- port->drive.pchs.spt = buffer[6];
+ port->drive.pchs.cylinder = buffer[1];
+ port->drive.pchs.head = buffer[3];
+ port->drive.pchs.sector = buffer[6];
u64 sectors;
if (buffer[83] & (1 << 10)) // word 83 - lba48 support
adrive_g->drive.type = DTYPE_ATA;
adrive_g->drive.blksize = DISK_SECTOR_SIZE;
- adrive_g->drive.pchs.cylinders = buffer[1];
- adrive_g->drive.pchs.heads = buffer[3];
- adrive_g->drive.pchs.spt = buffer[6];
+ adrive_g->drive.pchs.cylinder = buffer[1];
+ adrive_g->drive.pchs.head = buffer[3];
+ adrive_g->drive.pchs.sector = buffer[6];
u64 sectors;
if (buffer[83] & (1 << 10)) // word 83 - lba48 support
if (cylinders && geomdata.heads &&
drive->sectors <= 0xFFFFFFFFULL &&
((u32)drive->sectors % (geomdata.heads * cylinders) == 0)) {
- drive->pchs.cylinders = cylinders;
- drive->pchs.heads = geomdata.heads;
- drive->pchs.spt = (u32)drive->sectors / (geomdata.heads * cylinders);
+ drive->pchs.cylinder = cylinders;
+ drive->pchs.head = geomdata.heads;
+ drive->pchs.sector = (u32)drive->sectors / (geomdata.heads * cylinders);
}
}
}
int i;
for (i=1; i<ARRAY_SIZE(FloppyInfo); i++) {
struct chs_s *c = &FloppyInfo[i].chs;
- if (c->cylinders * c->heads * c->spt * DISK_SECTOR_SIZE == size)
+ if (c->cylinder * c->head * c->sector * DISK_SECTOR_SIZE == size)
return i;
}
return -1;
if (stype==ftype
|| (GET_GLOBAL(FloppyInfo[stype].floppy_size)
!= GET_GLOBAL(FloppyInfo[ftype].floppy_size))
- || (GET_GLOBAL(FloppyInfo[stype].chs.heads)
- > GET_GLOBAL(FloppyInfo[ftype].chs.heads))
- || (GET_GLOBAL(FloppyInfo[stype].chs.cylinders)
- > GET_GLOBAL(FloppyInfo[ftype].chs.cylinders))
- || (GET_GLOBAL(FloppyInfo[stype].chs.spt)
- > GET_GLOBAL(FloppyInfo[ftype].chs.spt)))
+ || (GET_GLOBAL(FloppyInfo[stype].chs.head)
+ > GET_GLOBAL(FloppyInfo[ftype].chs.head))
+ || (GET_GLOBAL(FloppyInfo[stype].chs.cylinder)
+ > GET_GLOBAL(FloppyInfo[ftype].chs.cylinder))
+ || (GET_GLOBAL(FloppyInfo[stype].chs.sector)
+ > GET_GLOBAL(FloppyInfo[ftype].chs.sector)))
continue;
data_rate = GET_GLOBAL(FloppyInfo[stype].data_rate);
ret = floppy_drive_readid(floppyid, data_rate, 0);
SET_BDA(floppy_last_data_rate, (old_data_rate<<2) | (data_rate<<6));
u8 media = (stype == 1 ? 0x04 : (stype == 2 ? 0x05 : 0x07));
u8 fms = (data_rate<<6) | FMS_MEDIA_DRIVE_ESTABLISHED | media;
- if (GET_GLOBAL(FloppyInfo[stype].chs.cylinders)
- < GET_GLOBAL(FloppyInfo[ftype].chs.cylinders))
+ if (GET_GLOBAL(FloppyInfo[stype].chs.cylinder)
+ < GET_GLOBAL(FloppyInfo[ftype].chs.cylinder))
fms |= FMS_DOUBLE_STEPPING;
SET_BDA(floppy_media_state[floppyid], fms);
* Floppy handlers
****************************************************************/
-static void
-lba2chs(struct disk_op_s *op, u8 *track, u8 *sector, u8 *head)
+static struct chs_s
+lba2chs(struct disk_op_s *op)
{
+ struct chs_s res = { };
u32 lba = op->lba;
u32 tmp = lba + 1;
- u16 nlspt = GET_GLOBAL(op->drive_g->lchs.spt);
- *sector = tmp % nlspt;
+ u16 nls = GET_GLOBAL(op->drive_g->lchs.sector);
+ res.sector = tmp % nls;
- tmp /= nlspt;
- u16 nlh = GET_GLOBAL(op->drive_g->lchs.heads);
- *head = tmp % nlh;
+ tmp /= nls;
+ u16 nlh = GET_GLOBAL(op->drive_g->lchs.head);
+ res.head = tmp % nlh;
tmp /= nlh;
- *track = tmp;
+ res.cylinder = tmp;
+
+ return res;
}
// diskette controller reset
static int
floppy_read(struct disk_op_s *op)
{
- u8 track, sector, head;
- lba2chs(op, &track, §or, &head);
+ struct chs_s chs = lba2chs(op);
// send read-normal-data command (9 bytes) to controller
u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
struct floppy_pio_s pio;
pio.cmdlen = 9;
pio.data[0] = 0xe6; // e6: read normal data
- pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
- pio.data[2] = track;
- pio.data[3] = head;
- pio.data[4] = sector;
+ pio.data[1] = (chs.head << 2) | floppyid; // HD DR1 DR2
+ pio.data[2] = chs.cylinder;
+ pio.data[3] = chs.head;
+ pio.data[4] = chs.sector;
pio.data[5] = FLOPPY_SIZE_CODE;
- pio.data[6] = sector + op->count - 1; // last sector to read on track
+ pio.data[6] = chs.sector + op->count - 1; // last sector to read on track
pio.data[7] = FLOPPY_GAPLEN;
pio.data[8] = FLOPPY_DATALEN;
static int
floppy_write(struct disk_op_s *op)
{
- u8 track, sector, head;
- lba2chs(op, &track, §or, &head);
+ struct chs_s chs = lba2chs(op);
// send write-normal-data command (9 bytes) to controller
u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
struct floppy_pio_s pio;
pio.cmdlen = 9;
pio.data[0] = 0xc5; // c5: write normal data
- pio.data[1] = (head << 2) | floppyid; // HD DR1 DR2
- pio.data[2] = track;
- pio.data[3] = head;
- pio.data[4] = sector;
+ pio.data[1] = (chs.head << 2) | floppyid; // HD DR1 DR2
+ pio.data[2] = chs.cylinder;
+ pio.data[3] = chs.head;
+ pio.data[4] = chs.sector;
pio.data[5] = FLOPPY_SIZE_CODE;
- pio.data[6] = sector + op->count - 1; // last sector to write on track
+ pio.data[6] = chs.sector + op->count - 1; // last sector to write on track
pio.data[7] = FLOPPY_GAPLEN;
pio.data[8] = FLOPPY_DATALEN;
if (res)
goto fail;
- u8 track, sector, head;
- lba2chs(op, &track, §or, &head);
+ struct chs_s chs = lba2chs(op);
// ??? should track be new val from return_status[3] ?
u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
- set_diskette_current_cyl(floppyid, track);
+ set_diskette_current_cyl(floppyid, chs.cylinder);
return DISK_RET_SUCCESS;
fail:
op->count = 0; // no sectors read
goto fail;
}
- vdrive_g->drive.pchs.cylinders = cfg.cylinders;
- vdrive_g->drive.pchs.heads = cfg.heads;
- vdrive_g->drive.pchs.spt = cfg.sectors;
+ vdrive_g->drive.pchs.cylinder = cfg.cylinders;
+ vdrive_g->drive.pchs.head = cfg.heads;
+ vdrive_g->drive.pchs.sector = cfg.sectors;
char *desc = znprintf(MAXDESCSIZE, "Virtio disk PCI:%x:%x",
pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf));