aboutsummaryrefslogtreecommitdiffstats
path: root/src/block.c
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2015-07-07 08:35:51 -0400
committerKevin O'Connor <kevin@koconnor.net>2015-07-14 14:40:07 -0400
commitc7fa7890200afd86e42813ce1bdbc1b32fcfccc5 (patch)
treec01188faa94cf16e4961f4c888a73a1875340bd8 /src/block.c
parent7f50afc71f8a48c27100e14bb57fac6f26181242 (diff)
downloadseabios-c7fa7890200afd86e42813ce1bdbc1b32fcfccc5.tar.gz
block: Split process_op() command dispatch up into multiple functions
Introduce process_op_32(), process_op_16(), and process_op_both() and split the disk driver command dispatch by its runtime mode requirements. This makes it more clear which modes each driver runs in. It also reduces the call32() boiler-plate code. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'src/block.c')
-rw-r--r--src/block.c125
1 files changed, 69 insertions, 56 deletions
diff --git a/src/block.c b/src/block.c
index a9b98516..e534319d 100644
--- a/src/block.c
+++ b/src/block.c
@@ -464,10 +464,10 @@ fill_edd(u16 seg, struct int13dpt_s *param_far, struct drive_s *drive_gf)
/****************************************************************
- * 16bit calling interface
+ * Disk driver dispatch
****************************************************************/
-int VISIBLE32FLAT
+static int
process_atapi_op(struct disk_op_s *op)
{
switch (op->command) {
@@ -479,72 +479,85 @@ process_atapi_op(struct disk_op_s *op)
}
}
-// Execute a disk_op request.
-int
-process_op(struct disk_op_s *op)
+// Command dispatch for disk drivers that run in both 16bit and 32bit mode
+static int
+process_op_both(struct disk_op_s *op)
{
- ASSERT16();
- int ret, origcount = op->count;
- if (origcount * GET_GLOBALFLAT(op->drive_gf->blksize) > 64*1024) {
- op->count = 0;
- return DISK_RET_EBOUNDARY;
- }
- u8 type = GET_GLOBALFLAT(op->drive_gf->type);
- switch (type) {
- case DTYPE_FLOPPY:
- ret = process_floppy_op(op);
- break;
- case DTYPE_ATA:
- ret = process_ata_op(op);
- break;
- case DTYPE_RAMDISK:
- ret = process_ramdisk_op(op);
- break;
- case DTYPE_CDEMU:
- ret = process_cdemu_op(op);
- break;
- case DTYPE_VIRTIO_BLK: ;
- extern void _cfunc32flat_process_virtio_blk_op(void);
- ret = call32(_cfunc32flat_process_virtio_blk_op
- , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM);
- break;
- case DTYPE_AHCI: ;
- extern void _cfunc32flat_process_ahci_op(void);
- ret = call32(_cfunc32flat_process_ahci_op
- , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM);
- break;
+ switch (GET_GLOBALFLAT(op->drive_gf->type)) {
case DTYPE_ATA_ATAPI:
- ret = process_atapi_op(op);
- break;
- case DTYPE_AHCI_ATAPI: ;
- extern void _cfunc32flat_process_atapi_op(void);
- ret = call32(_cfunc32flat_process_atapi_op
- , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM);
- break;
- case DTYPE_SDCARD: ;
- extern void _cfunc32flat_process_sdcard_op(void);
- ret = call32(_cfunc32flat_process_sdcard_op
- , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM);
- break;
+ return process_atapi_op(op);
case DTYPE_USB:
case DTYPE_UAS:
case DTYPE_LSI_SCSI:
case DTYPE_ESP_SCSI:
case DTYPE_MEGASAS:
- ret = scsi_process_op(op);
- break;
+ return scsi_process_op(op);
+ default:
+ if (!MODESEGMENT)
+ return DISK_RET_EPARAM;
+ // In 16bit mode and driver not found - try in 32bit mode
+ extern void _cfunc32flat_process_op_32(void);
+ return call32(_cfunc32flat_process_op_32
+ , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM);
+ }
+}
+
+// Command dispatch for disk drivers that only run in 32bit mode
+int VISIBLE32FLAT
+process_op_32(struct disk_op_s *op)
+{
+ ASSERT32FLAT();
+ switch (op->drive_gf->type) {
+ case DTYPE_VIRTIO_BLK:
+ return process_virtio_blk_op(op);
+ case DTYPE_AHCI:
+ return process_ahci_op(op);
+ case DTYPE_AHCI_ATAPI:
+ return process_atapi_op(op);
+ case DTYPE_SDCARD:
+ return process_sdcard_op(op);
case DTYPE_USB_32:
case DTYPE_UAS_32:
case DTYPE_VIRTIO_SCSI:
- case DTYPE_PVSCSI: ;
- extern void _cfunc32flat_scsi_process_op(void);
- ret = call32(_cfunc32flat_scsi_process_op
- , (u32)MAKE_FLATPTR(GET_SEG(SS), op), DISK_RET_EPARAM);
- break;
+ case DTYPE_PVSCSI:
+ return scsi_process_op(op);
default:
- ret = DISK_RET_EPARAM;
- break;
+ return process_op_both(op);
}
+}
+
+// Command dispatch for disk drivers that only run in 16bit mode
+static int
+process_op_16(struct disk_op_s *op)
+{
+ ASSERT16();
+ switch (GET_GLOBALFLAT(op->drive_gf->type)) {
+ case DTYPE_FLOPPY:
+ return process_floppy_op(op);
+ case DTYPE_ATA:
+ return process_ata_op(op);
+ case DTYPE_RAMDISK:
+ return process_ramdisk_op(op);
+ case DTYPE_CDEMU:
+ return process_cdemu_op(op);
+ default:
+ return process_op_both(op);
+ }
+}
+
+// Execute a disk_op_s request.
+int
+process_op(struct disk_op_s *op)
+{
+ int ret, origcount = op->count;
+ if (origcount * GET_GLOBALFLAT(op->drive_gf->blksize) > 64*1024) {
+ op->count = 0;
+ return DISK_RET_EBOUNDARY;
+ }
+ if (MODESEGMENT)
+ ret = process_op_16(op);
+ else
+ ret = process_op_32(op);
if (ret && op->count == origcount)
// If the count hasn't changed on error, assume no data transferred.
op->count = 0;