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
//
// 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
#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
* 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;
}
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
****************************************************************/
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;
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;
// 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);
}
// 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));
// 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.
// 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");
// 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");
+++ /dev/null
-// Low level ATA disk definitions
-//
-// Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
-// 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 */
#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
#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
/****************************************************************
* 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)
// 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;
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;
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;
#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
/****************************************************************
#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);
}
// 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);
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) {
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));
__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
****************************************************************/
// 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;
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
#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