From: Kevin O'Connor Date: Sun, 9 Aug 2009 17:08:21 +0000 (-0400) Subject: Separate cdemu disk accesses from regular disk accesses. X-Git-Tag: rel-0.4.2~28 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=1625a75974b23b950edf637b5068b9007f2d6fac;p=seabios.git Separate cdemu disk accesses from regular disk accesses. Breakup basic_access() into basic_access, cdemu_access, and legacy_lba. Also, check for verify and seek calls in __send_disk_op instead of all callers. Also, send_disk_op returns sector count in dop.count instead of via ebda. --- diff --git a/src/cdrom.c b/src/cdrom.c index 8ccbeea..b96afa0 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -180,6 +180,18 @@ cdrom_13(struct bregs *regs, u8 device) * CD emulation ****************************************************************/ +static void +cdemu_1302(struct bregs *regs, u8 device) +{ + cdemu_access(regs, device, ATA_CMD_READ_SECTORS); +} + +static void +cdemu_1304(struct bregs *regs, u8 device) +{ + cdemu_access(regs, device, 0); +} + // read disk drive parameters static void cdemu_1308(struct bregs *regs, u8 device) @@ -217,11 +229,9 @@ cdemu_13(struct bregs *regs) device += GET_EBDA2(ebda_seg, cdemu.device_spec); switch (regs->ah) { - // These functions are the same as for hard disks - case 0x02: - case 0x04: - disk_13(regs, device); - break; + case 0x02: cdemu_1302(regs, device); break; + case 0x04: cdemu_1304(regs, device); break; + case 0x08: cdemu_1308(regs, device); break; // These functions are the same as standard CDROM. case 0x00: @@ -239,8 +249,6 @@ cdemu_13(struct bregs *regs) cdrom_13(regs, device); break; - case 0x08: cdemu_1308(regs, device); break; - default: disk_13XX(regs, device); break; } } diff --git a/src/disk.c b/src/disk.c index 898fe49..e56bcd0 100644 --- a/src/disk.c +++ b/src/disk.c @@ -40,6 +40,7 @@ __disk_stub(struct bregs *regs, int lineno, const char *fname) #define DISK_STUB(regs) \ __disk_stub((regs), __LINE__, __func__) +// Execute a "disk_op_s" request - this runs on a stack in the ebda. static int __send_disk_op(struct disk_op_s *op_far, u16 op_seg) { @@ -55,6 +56,9 @@ __send_disk_op(struct disk_op_s *op_far, u16 op_seg) irq_enable(); int status; + if (!dop.command) + // If verify or seek + status = 0; if (dop.command == CMD_CDEMU_READ) status = cdrom_read_512(&dop); else if (dop.command == CMD_CDROM_READ) @@ -64,9 +68,16 @@ __send_disk_op(struct disk_op_s *op_far, u16 op_seg) irq_disable(); + // Update count with total sectors transferred. + SET_FARVAR(op_seg, op_far->count, GET_EBDA(sector_count)); + + if (status) + dprintf(1, "disk_op cmd %d error %d!\n", dop.command, status); + return status; } +// Execute a "disk_op_s" request by jumping to a stack in the ebda. static int send_disk_op(struct disk_op_s *op) { @@ -76,39 +87,20 @@ send_disk_op(struct disk_op_s *op) return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op); } -static void -basic_access(struct bregs *regs, u8 device, u16 command) +// Obtain the requested disk lba from an old-style chs request. +static int +legacy_lba(struct bregs *regs, struct disk_op_s *op, u16 nlc, u16 nlh, u16 nlspt) { - struct disk_op_s dop; - dop.lba = 0; - dop.driveid = device; - u8 type = GET_GLOBAL(ATA.devices[device].type); - u16 nlc, nlh, nlspt; - if (type == ATA_TYPE_ATA) { - nlc = GET_GLOBAL(ATA.devices[device].lchs.cylinders); - nlh = GET_GLOBAL(ATA.devices[device].lchs.heads); - nlspt = GET_GLOBAL(ATA.devices[device].lchs.spt); - dop.command = command; - } else { - // Must be cd emulation. - u16 ebda_seg = get_ebda_seg(); - nlc = GET_EBDA2(ebda_seg, cdemu.cylinders); - nlh = GET_EBDA2(ebda_seg, cdemu.heads); - nlspt = GET_EBDA2(ebda_seg, cdemu.spt); - dop.lba = GET_EBDA2(ebda_seg, cdemu.ilba) * 4; - dop.command = CMD_CDEMU_READ; - } - - dop.count = regs->al; - u16 cylinder = regs->ch | ((((u16) regs->cl) << 2) & 0x300); - u16 sector = regs->cl & 0x3f; - u16 head = regs->dh; + op->count = regs->al; + u16 cylinder = regs->ch | ((((u16)regs->cl) << 2) & 0x300); + u16 sector = regs->cl & 0x3f; + u16 head = regs->dh; - if (dop.count > 128 || dop.count == 0 || sector == 0) { + if (op->count > 128 || op->count == 0 || sector == 0) { dprintf(1, "int13_harddisk: function %02x, parameter out of range!\n" , regs->ah); disk_ret(regs, DISK_RET_EPARAM); - return; + return -1; } // sanity check on cyl heads, sec @@ -117,37 +109,73 @@ basic_access(struct bregs *regs, u8 device, u16 command) " range %04x/%04x/%04x!\n" , regs->ah, cylinder, head, sector); disk_ret(regs, DISK_RET_EPARAM); - return; - } - - if (!command) { - // If verify or seek - disk_ret(regs, DISK_RET_SUCCESS); - return; + return -1; } // translate lchs to lba - dop.lba += (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) - + (u32)sector - 1); + op->lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) + + (u32)sector - 1); u16 segment = regs->es; u16 offset = regs->bx; - dop.buf_fl = MAKE_FLATPTR(segment, offset); + op->buf_fl = MAKE_FLATPTR(segment, offset); + + return 0; +} + +// Perform read/write/verify using old-style chs accesses +static void +basic_access(struct bregs *regs, u8 device, u16 command) +{ + struct disk_op_s dop; + dop.driveid = device; + dop.command = command; + u16 nlc = GET_GLOBAL(ATA.devices[device].lchs.cylinders); + u16 nlh = GET_GLOBAL(ATA.devices[device].lchs.heads); + u16 nlspt = GET_GLOBAL(ATA.devices[device].lchs.spt); + int ret = legacy_lba(regs, &dop, nlc, nlh, nlspt); + if (ret) + return; int status = send_disk_op(&dop); - // Set nb of sector transferred - regs->al = GET_EBDA(sector_count); + regs->al = dop.count; - if (status != 0) { - dprintf(1, "int13_harddisk: function %02x, error %d!\n" - , regs->ah, status); + if (status) { disk_ret(regs, DISK_RET_EBADTRACK); return; } disk_ret(regs, DISK_RET_SUCCESS); } +// Perform cdemu read/verify +void +cdemu_access(struct bregs *regs, u8 device, u16 command) +{ + struct disk_op_s dop; + dop.driveid = device; + dop.command = (command == ATA_CMD_READ_SECTORS ? CMD_CDEMU_READ : 0); + u16 ebda_seg = get_ebda_seg(); + u16 nlc = GET_EBDA2(ebda_seg, cdemu.cylinders); + u16 nlh = GET_EBDA2(ebda_seg, cdemu.heads); + u16 nlspt = GET_EBDA2(ebda_seg, cdemu.spt); + int ret = legacy_lba(regs, &dop, nlc, nlh, nlspt); + if (ret) + return; + dop.lba += GET_EBDA2(ebda_seg, cdemu.ilba) * 4; + + int status = send_disk_op(&dop); + + regs->al = dop.count; + + if (status) { + disk_ret(regs, DISK_RET_EBADTRACK); + return; + } + disk_ret(regs, DISK_RET_SUCCESS); +} + +// Perform read/write/verify using new-style "int13ext" accesses. static void extended_access(struct bregs *regs, u8 device, u16 command) { @@ -168,12 +196,6 @@ extended_access(struct bregs *regs, u8 device, u16 command) dop.command = CMD_CDROM_READ; } - if (!command) { - // If verify or seek - disk_ret(regs, DISK_RET_SUCCESS); - return; - } - u16 segment = GET_INT13EXT(regs, segment); u16 offset = GET_INT13EXT(regs, offset); dop.buf_fl = MAKE_FLATPTR(segment, offset); @@ -181,11 +203,9 @@ extended_access(struct bregs *regs, u8 device, u16 command) int status = send_disk_op(&dop); - SET_INT13EXT(regs, count, GET_EBDA(sector_count)); + SET_INT13EXT(regs, count, dop.count); - if (status != 0) { - dprintf(1, "int13_harddisk: function %02x, error %d!\n" - , regs->ah, status); + if (status) { disk_ret(regs, DISK_RET_EBADTRACK); return; } diff --git a/src/disk.h b/src/disk.h index 8e9f1cb..b4d8444 100644 --- a/src/disk.h +++ b/src/disk.h @@ -224,6 +224,7 @@ void floppy_tick(); // disk.c void disk_13(struct bregs *regs, u8 device); void disk_13XX(struct bregs *regs, u8 device); +void cdemu_access(struct bregs *regs, u8 device, u16 command); // cdrom.c void cdrom_13(struct bregs *regs, u8 device);