aboutsummaryrefslogtreecommitdiff
path: root/src/disk.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2009-08-09 13:08:21 -0400
committerKevin O'Connor <kevin@koconnor.net>2009-08-09 13:08:21 -0400
commit1625a75974b23b950edf637b5068b9007f2d6fac (patch)
treec9d25f039e96aa086410ef285bb97b166c59fac5 /src/disk.c
parenta4d70aa537a48fd6ab645435be94246c4e41a2e7 (diff)
downloadseabios-hppa-1625a75974b23b950edf637b5068b9007f2d6fac.zip
seabios-hppa-1625a75974b23b950edf637b5068b9007f2d6fac.tar.gz
seabios-hppa-1625a75974b23b950edf637b5068b9007f2d6fac.tar.bz2
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.
Diffstat (limited to 'src/disk.c')
-rw-r--r--src/disk.c126
1 files changed, 73 insertions, 53 deletions
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;
}