From 4524bf778adc70d7af0f74982110454f5d447b70 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Wed, 31 Dec 2008 00:31:03 -0500 Subject: [PATCH] Use new 'struct disk_op_s' to issue ata requests. Using the struct at all callers reduces the parameter assignments. Replace ata_op_s with new disk_op_s and update all users. Unify basic/extended_access methods to use new send_disk_op() func. Remove cdrom_read_emu -- integrate logic into callers. Remove ata.h -- move all defs to disk.h --- src/ata.c | 93 ++++++++++++++++++++++------------------------------- src/ata.h | 23 ------------- src/boot.c | 1 - src/cdrom.c | 28 ++++++++-------- src/disk.c | 87 ++++++++++++++++++++++++++++--------------------- src/disk.h | 25 ++++++++++++-- src/post.c | 1 - 7 files changed, 125 insertions(+), 133 deletions(-) delete mode 100644 src/ata.h diff --git a/src/ata.c b/src/ata.c index 3694c3b..81d00cd 100644 --- a/src/ata.c +++ b/src/ata.c @@ -5,7 +5,6 @@ // // This file may be distributed under the terms of the GNU GPLv3 license. -#include "ata.h" // ATA_* #include "types.h" // u8 #include "ioport.h" // inb #include "util.h" // dprintf @@ -16,6 +15,7 @@ #include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER #include "pci_regs.h" // PCI_INTERRUPT_LINE #include "disk.h" // struct ata_s +#include "atabits.h" // ATA_CB_STAT #define TIMEOUT 0 #define BSY 1 @@ -136,13 +136,6 @@ ata_reset(int driveid) * ATA send command ****************************************************************/ -struct ata_op_s { - u64 lba; - void *far_buffer; - u16 driveid; - u16 count; -}; - struct ata_pio_command { u8 feature; u8 sector_count; @@ -318,21 +311,21 @@ ata_transfer(int driveid, int iswrite, int count, int blocksize } static noinline int -ata_transfer_disk(const struct ata_op_s *op, int iswrite) +ata_transfer_disk(const struct disk_op_s *op) { - return ata_transfer(op->driveid, iswrite, op->count, IDE_SECTOR_SIZE - , 0, 0, op->far_buffer); + return ata_transfer(op->driveid, op->command == ATA_CMD_WRITE_SECTORS + , op->count, IDE_SECTOR_SIZE, 0, 0, op->far_buffer); } static noinline int -ata_transfer_cdrom(const struct ata_op_s *op) +ata_transfer_cdrom(const struct disk_op_s *op) { return ata_transfer(op->driveid, 0, op->count, CDROM_SECTOR_SIZE , 0, 0, op->far_buffer); } static noinline int -ata_transfer_emu(const struct ata_op_s *op, int before, int after) +ata_transfer_cdemu(const struct disk_op_s *op, int before, int after) { int vcount = op->count * 4 - before - after; int ret = ata_transfer(op->driveid, 0, op->count, CDROM_SECTOR_SIZE @@ -351,7 +344,7 @@ ata_transfer_emu(const struct ata_op_s *op, int before, int after) ****************************************************************/ static noinline int -send_cmd_disk(const struct ata_op_s *op, u16 command) +send_cmd_disk(const struct disk_op_s *op) { u8 slave = op->driveid % 2; u64 lba = op->lba; @@ -359,7 +352,7 @@ send_cmd_disk(const struct ata_op_s *op, u16 command) struct ata_pio_command cmd; memset(&cmd, 0, sizeof(cmd)); - cmd.command = command; + cmd.command = op->command; if (op->count >= (1<<8) || lba + op->count >= (1<<28)) { cmd.sector_count2 = op->count >> 8; cmd.lba_low2 = lba >> 24; @@ -383,20 +376,12 @@ send_cmd_disk(const struct ata_op_s *op, u16 command) // Read/write count blocks from a harddrive. __always_inline int -ata_cmd_data(int driveid, u16 command, u64 lba, u16 count, void *far_buffer) +ata_cmd_data(struct disk_op_s *op) { - struct ata_op_s op; - op.driveid = driveid; - op.lba = lba; - op.count = count; - op.far_buffer = far_buffer; - - int ret = send_cmd_disk(&op, command); + int ret = send_cmd_disk(op); if (ret) return ret; - - int iswrite = command == ATA_CMD_WRITE_SECTORS; - return ata_transfer_disk(&op, iswrite); + return ata_transfer_disk(op); } @@ -438,7 +423,7 @@ send_atapi_cmd(int driveid, u8 *cmdbuf, u8 cmdlen, u16 blocksize) // Low-level cdrom read atapi command transmit function. static int -send_cmd_cdrom(const struct ata_op_s *op) +send_cmd_cdrom(const struct disk_op_s *op) { u8 atacmd[12]; memset(atacmd, 0, sizeof(atacmd)); @@ -457,49 +442,39 @@ send_cmd_cdrom(const struct ata_op_s *op) // Read sectors from the cdrom. __always_inline int -cdrom_read(int driveid, u32 lba, u32 count, void *far_buffer) +cdrom_read(struct disk_op_s *op) { - struct ata_op_s op; - op.driveid = driveid; - op.lba = lba; - op.count = count; - op.far_buffer = far_buffer; - - int ret = send_cmd_cdrom(&op); + int ret = send_cmd_cdrom(op); if (ret) return ret; - return ata_transfer_cdrom(&op); + return ata_transfer_cdrom(op); } // Pretend the cdrom has 512 byte sectors (instead of 2048) and read // sectors. __always_inline int -cdrom_read_512(int driveid, u32 vlba, u32 vcount, void *far_buffer) +cdrom_read_512(struct disk_op_s *op) { + u32 vlba = op->lba; + u32 vcount = op->count; + u32 lba = op->lba = vlba / 4; u32 velba = vlba + vcount - 1; - u32 lba = vlba / 4; u32 elba = velba / 4; - int count = elba - lba + 1; + op->count = elba - lba + 1; int before = vlba % 4; int after = 3 - (velba % 4); - struct ata_op_s op; - op.driveid = driveid; - op.lba = lba; - op.count = count; - op.far_buffer = far_buffer; - dprintf(16, "cdrom_read_512: id=%d vlba=%d vcount=%d buf=%p lba=%d elba=%d" " count=%d before=%d after=%d\n" - , driveid, vlba, vcount, far_buffer, lba, elba - , count, before, after); + , op->driveid, vlba, vcount, op->far_buffer, lba, elba + , op->count, before, after); - int ret = send_cmd_cdrom(&op); + int ret = send_cmd_cdrom(op); if (ret) return ret; - return ata_transfer_emu(&op, before, after); + return ata_transfer_cdemu(op, before, after); } // Send a simple atapi command to a drive. @@ -568,9 +543,13 @@ init_drive_atapi(int driveid) // Now we send a IDENTIFY command to ATAPI device u8 buffer[0x0200]; memset(buffer, 0, sizeof(buffer)); - u16 ret = ata_cmd_data(driveid, ATA_CMD_IDENTIFY_DEVICE_PACKET - , 1, 1 - , MAKE_FARPTR(GET_SEG(SS), (u32)buffer)); + struct disk_op_s dop; + dop.driveid = driveid; + dop.command = ATA_CMD_IDENTIFY_DEVICE_PACKET; + dop.count = 1; + dop.lba = 1; + dop.far_buffer = MAKE_FARPTR(GET_SEG(SS), (u32)buffer); + u16 ret = ata_cmd_data(&dop); if (ret != 0) BX_PANIC("ata-detect: Failed to detect ATAPI device\n"); @@ -746,9 +725,13 @@ init_drive_ata(int driveid) // Now we send a IDENTIFY command to ATA device u8 buffer[0x0200]; memset(buffer, 0, sizeof(buffer)); - u16 ret = ata_cmd_data(driveid, ATA_CMD_IDENTIFY_DEVICE - , 1, 1 - , MAKE_FARPTR(GET_SEG(SS), (u32)buffer)); + struct disk_op_s dop; + dop.driveid = driveid; + dop.command = ATA_CMD_IDENTIFY_DEVICE; + dop.count = 1; + dop.lba = 1; + dop.far_buffer = MAKE_FARPTR(GET_SEG(SS), (u32)buffer); + u16 ret = ata_cmd_data(&dop); if (ret) BX_PANIC("ata-detect: Failed to detect ATA device\n"); diff --git a/src/ata.h b/src/ata.h deleted file mode 100644 index 59b01d3..0000000 --- a/src/ata.h +++ /dev/null @@ -1,23 +0,0 @@ -// Low level ATA disk definitions -// -// Copyright (C) 2008 Kevin O'Connor -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This file may be distributed under the terms of the GNU GPLv3 license. - -#ifndef __ATA_H -#define __ATA_H - -#include "types.h" // u16 -#include "atabits.h" // ATA_CB_DH_DEV1 - -// Function definitions -void ata_reset(int driveid); -int ata_cmd_data(int driveid, u16 command, u64 lba, u16 count, void *far_buffer); -int ata_cmd_packet(int driveid, u8 *cmdbuf, u8 cmdlen - , u32 length, void *far_buffer); -int cdrom_read(int driveid, u32 lba, u32 count, void *far_buffer); -int cdrom_read_512(int driveid, u32 lba, u32 count, void *far_buffer); -void hard_drive_setup(); - -#endif /* __ATA_H */ diff --git a/src/boot.c b/src/boot.c index df3647d..bc13f79 100644 --- a/src/boot.c +++ b/src/boot.c @@ -8,7 +8,6 @@ #include "util.h" // irq_enable #include "biosvar.h" // GET_EBDA #include "config.h" // CONFIG_* -#include "ata.h" // ata_detect #include "disk.h" // cdrom_boot #include "bregs.h" // struct bregs #include "boot.h" // struct ipl_s diff --git a/src/cdrom.c b/src/cdrom.c index 00ecc71..dbf4379 100644 --- a/src/cdrom.c +++ b/src/cdrom.c @@ -7,9 +7,9 @@ #include "disk.h" // cdrom_13 #include "util.h" // memset -#include "ata.h" // ATA_CMD_READ_SECTORS #include "bregs.h" // struct bregs #include "biosvar.h" // GET_EBDA +#include "atabits.h" // ATA_TYPE_ATAPI /**************************************************************** @@ -180,15 +180,6 @@ cdrom_13(struct bregs *regs, u8 device) * CD emulation ****************************************************************/ -// Read a series of 512 byte sectors from the cdrom starting at the -// image offset. -__always_inline int -cdrom_read_emu(u16 biosid, u32 vlba, u32 count, void *far_buffer) -{ - u32 ilba = GET_EBDA(cdemu.ilba); - return cdrom_read_512(biosid, ilba * 4 + vlba, count, far_buffer); -} - // read disk drive parameters static void cdemu_1308(struct bregs *regs, u8 device) @@ -443,8 +434,12 @@ cdrom_boot() // Read the Boot Record Volume Descriptor u8 buffer[2048]; - ret = cdrom_read(device, 0x11, 1 - , MAKE_FARPTR(GET_SEG(SS), (u32)buffer)); + struct disk_op_s dop; + dop.driveid = device; + dop.lba = 0x11; + dop.count = 1; + dop.far_buffer = MAKE_FARPTR(GET_SEG(SS), (u32)buffer); + ret = cdrom_read(&dop); if (ret) return 3; @@ -458,8 +453,8 @@ cdrom_boot() u32 lba = *(u32*)&buffer[0x47]; // And we read the Boot Catalog - ret = cdrom_read(device, lba, 1 - , MAKE_FARPTR(GET_SEG(SS), (u32)buffer)); + dop.lba = lba; + ret = cdrom_read(&dop); if (ret) return 7; @@ -497,7 +492,10 @@ cdrom_boot() SET_EBDA2(ebda_seg, cdemu.ilba, lba); // And we read the image in memory - ret = cdrom_read_emu(device, 0, nbsectors, MAKE_FARPTR(boot_segment, 0)); + dop.lba = lba * 4; + dop.count = nbsectors; + dop.far_buffer = MAKE_FARPTR(boot_segment, 0); + ret = cdrom_read_512(&dop); if (ret) return 12; diff --git a/src/disk.c b/src/disk.c index 010b14c..e72be9d 100644 --- a/src/disk.c +++ b/src/disk.c @@ -9,10 +9,10 @@ #include "biosvar.h" // SET_BDA #include "config.h" // CONFIG_* #include "util.h" // debug_enter -#include "ata.h" // ATA_* #include "pic.h" // eoi_pic2 #include "bregs.h" // struct bregs #include "pci.h" // pci_bdf_to_bus +#include "atabits.h" // ATA_CB_STAT /**************************************************************** @@ -39,29 +39,57 @@ __disk_stub(const char *fname, int lineno, struct bregs *regs) #define DISK_STUB(regs) \ __disk_stub(__func__, __LINE__, (regs)) +static __always_inline int +send_disk_op(struct disk_op_s *op) +{ + dprintf(DEBUG_HDL_13, "disk_op d=%d lba=%d buf=%p count=%d cmd=%d\n" + , op->driveid, (u32)op->lba, op->far_buffer + , op->count, op->command); + + irq_enable(); + + int status; + if (op->command == CMD_CDEMU_READ) + status = cdrom_read_512(op); + else if (op->command == CMD_CDROM_READ) + status = cdrom_read(op); + else + status = ata_cmd_data(op); + + irq_disable(); + + return status; +} + static void basic_access(struct bregs *regs, u8 device, u16 command) { + 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; } - u16 count = regs->al; + dop.count = regs->al; u16 cylinder = regs->ch | ((((u16) regs->cl) << 2) & 0x300); u16 sector = regs->cl & 0x3f; u16 head = regs->dh; - if (count > 128 || count == 0 || sector == 0) { + if (dop.count > 128 || dop.count == 0 || sector == 0) { dprintf(1, "int13_harddisk: function %02x, parameter out of range!\n" , regs->ah); disk_ret(regs, DISK_RET_EPARAM); @@ -84,22 +112,14 @@ basic_access(struct bregs *regs, u8 device, u16 command) } // translate lchs to lba - u32 lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) - + (u32)sector - 1); + dop.lba += (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) + + (u32)sector - 1); u16 segment = regs->es; u16 offset = regs->bx; - void *far_buffer = MAKE_FARPTR(segment, offset); - - irq_enable(); + dop.far_buffer = MAKE_FARPTR(segment, offset); - int status; - if (type == ATA_TYPE_ATA) - status = ata_cmd_data(device, command, lba, count, far_buffer); - else - status = cdrom_read_emu(device, lba, count, far_buffer); - - irq_disable(); + int status = send_disk_op(&dop); // Set nb of sector transferred regs->al = GET_EBDA(sector_count); @@ -115,15 +135,21 @@ basic_access(struct bregs *regs, u8 device, u16 command) static void extended_access(struct bregs *regs, u8 device, u16 command) { + struct disk_op_s dop; // Get lba and check. - u64 lba = GET_INT13EXT(regs, lba); + dop.lba = GET_INT13EXT(regs, lba); + dop.command = command; + dop.driveid = device; u8 type = GET_GLOBAL(ATA.devices[device].type); - if (type == ATA_TYPE_ATA - && lba >= GET_GLOBAL(ATA.devices[device].sectors)) { - dprintf(1, "int13_harddisk: function %02x. LBA out of range\n" - , regs->ah); - disk_ret(regs, DISK_RET_EPARAM); - return; + if (type == ATA_TYPE_ATA) { + if (dop.lba >= GET_GLOBAL(ATA.devices[device].sectors)) { + dprintf(1, "int13_harddisk: function %02x. LBA out of range\n" + , regs->ah); + disk_ret(regs, DISK_RET_EPARAM); + return; + } + } else { + dop.command = CMD_CDROM_READ; } if (!command) { @@ -134,21 +160,10 @@ extended_access(struct bregs *regs, u8 device, u16 command) u16 segment = GET_INT13EXT(regs, segment); u16 offset = GET_INT13EXT(regs, offset); - void *far_buffer = MAKE_FARPTR(segment, offset); - u16 count = GET_INT13EXT(regs, count); + dop.far_buffer = MAKE_FARPTR(segment, offset); + dop.count = GET_INT13EXT(regs, count); - dprintf(DEBUG_HDL_13, "extacc lba=%d buf=%p count=%d\n" - , (u32)lba, far_buffer, count); - - irq_enable(); - - int status; - if (type == ATA_TYPE_ATA) - status = ata_cmd_data(device, command, lba, count, far_buffer); - else - status = cdrom_read(device, lba, count, far_buffer); - - irq_disable(); + int status = send_disk_op(&dop); SET_INT13EXT(regs, count, GET_EBDA(sector_count)); diff --git a/src/disk.h b/src/disk.h index d091c7f..6c69dca 100644 --- a/src/disk.h +++ b/src/disk.h @@ -103,6 +103,22 @@ void __disk_ret(const char *fname, int lineno, struct bregs *regs, u8 code); __disk_ret(__func__, __LINE__, (regs), (code)) +/**************************************************************** + * Disk command request + ****************************************************************/ + +struct disk_op_s { + u64 lba; + void *far_buffer; + u16 count; + u8 driveid; + u8 command; +}; + +#define CMD_CDROM_READ 1 +#define CMD_CDEMU_READ 2 + + /**************************************************************** * Global storage ****************************************************************/ @@ -153,6 +169,13 @@ struct ata_s { // ata.c extern struct ata_s ATA; +int ata_cmd_data(struct disk_op_s *op); +int cdrom_read(struct disk_op_s *op); +int cdrom_read_512(struct disk_op_s *op); +int ata_cmd_packet(int driveid, u8 *cmdbuf, u8 cmdlen + , u32 length, void *far_buffer); +void ata_reset(int driveid); +void hard_drive_setup(); // floppy.c extern struct floppy_ext_dbt_s diskette_param_table2; @@ -165,11 +188,9 @@ void disk_13(struct bregs *regs, u8 device); void disk_13XX(struct bregs *regs, u8 device); // cdrom.c -int cdrom_read_emu(u16 device, u32 lba, u32 count, void *far_buffer); void cdrom_13(struct bregs *regs, u8 device); void cdemu_13(struct bregs *regs); void cdemu_134b(struct bregs *regs); int cdrom_boot(); - #endif // disk.h diff --git a/src/post.c b/src/post.c index c2a9b62..b53bc75 100644 --- a/src/post.c +++ b/src/post.c @@ -10,7 +10,6 @@ #include "cmos.h" // CMOS_* #include "util.h" // memset #include "biosvar.h" // struct bios_data_area_s -#include "ata.h" // hard_drive_setup #include "disk.h" // floppy_drive_setup #include "memmap.h" // add_e820 #include "pic.h" // pic_setup -- 2.25.1