X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Ffloppy.c;h=383744a22d9d8fa5debc025053d4d2af2463de5c;hb=refs%2Fheads%2Fcoreboot;hp=efe9592f5927060b1fff17ff502316372529b78f;hpb=f54c150090ff38a73ef64a5d20fdfa0d9c403972;p=seabios.git diff --git a/src/floppy.c b/src/floppy.c index efe9592..383744a 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -1,114 +1,175 @@ // 16bit code to access floppy drives. // -// Copyright (C) 2008 Kevin O'Connor +// Copyright (C) 2008,2009 Kevin O'Connor // Copyright (C) 2002 MandrakeSoft S.A. // -// This file may be distributed under the terms of the GNU GPLv3 license. +// This file may be distributed under the terms of the GNU LGPLv3 license. #include "types.h" // u8 #include "disk.h" // DISK_RET_SUCCESS -#include "config.h" // CONFIG_FLOPPY_SUPPORT -#include "biosvar.h" // struct bregs -#include "util.h" // irq_disable +#include "config.h" // CONFIG_FLOPPY +#include "biosvar.h" // SET_BDA +#include "util.h" // wait_irq #include "cmos.h" // inb_cmos -#include "pic.h" // unmask_pic1 - -#define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args) -#define DEBUGF(fmt, args...) - -#define BX_FLOPPY_ON_CNT 37 /* 2 seconds */ +#include "pic.h" // eoi_pic1 +#include "bregs.h" // struct bregs +#include "boot.h" // boot_add_floppy +#include "pci.h" // pci_to_bdf +#include "pci_ids.h" // PCI_CLASS_BRIDGE_ISA + +#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors +#define FLOPPY_DATALEN 0xff // Not used - because size code is 0x02 +#define FLOPPY_MOTOR_TICKS 37 // ~2 seconds +#define FLOPPY_FILLBYTE 0xf6 +#define FLOPPY_GAPLEN 0x1B +#define FLOPPY_FORMAT_GAPLEN 0x6c // New diskette parameter table adding 3 parameters from IBM // Since no provisions are made for multiple drive types, most // values in this table are ignored. I set parameters for 1.44M // floppy here -struct floppy_ext_dbt_s diskette_param_table2 VISIBLE16 = { +struct floppy_ext_dbt_s diskette_param_table2 VAR16VISIBLE = { .dbt = { - .specify1 = 0xAF, - .specify2 = 0x02, // head load time 0000001, DMA used - .shutoff_ticks = 0x25, - .bps_code = 0x02, + .specify1 = 0xAF, // step rate 12ms, head unload 240ms + .specify2 = 0x02, // head load time 4ms, DMA used + .shutoff_ticks = FLOPPY_MOTOR_TICKS, // ~2 seconds + .bps_code = FLOPPY_SIZE_CODE, .sectors = 18, - .interblock_len = 0x1B, - .data_len = 0xFF, - .gap_len = 0x6C, - .fill_byte = 0xF6, - .settle_time = 0x0F, - .startup_time = 0x08, + .interblock_len = FLOPPY_GAPLEN, + .data_len = FLOPPY_DATALEN, + .gap_len = FLOPPY_FORMAT_GAPLEN, + .fill_byte = FLOPPY_FILLBYTE, + .settle_time = 0x0F, // 15ms + .startup_time = 0x08, // 1 second }, .max_track = 79, // maximum track .data_rate = 0, // data transfer rate .drive_type = 4, // drive type in cmos }; +// Since no provisions are made for multiple drive types, most +// values in this table are ignored. I set parameters for 1.44M +// floppy here +struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7) = { + .specify1 = 0xAF, + .specify2 = 0x02, + .shutoff_ticks = FLOPPY_MOTOR_TICKS, + .bps_code = FLOPPY_SIZE_CODE, + .sectors = 18, + .interblock_len = FLOPPY_GAPLEN, + .data_len = FLOPPY_DATALEN, + .gap_len = FLOPPY_FORMAT_GAPLEN, + .fill_byte = FLOPPY_FILLBYTE, + .settle_time = 0x0F, + .startup_time = 0x08, +}; + +struct floppyinfo_s { + struct chs_s chs; + u8 config_data; + u8 media_state; +}; + +struct floppyinfo_s FloppyInfo[] VAR16VISIBLE = { + // Unknown + { {0, 0, 0}, 0x00, 0x00}, + // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors + { {2, 40, 9}, 0x00, 0x25}, + // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors + { {2, 80, 15}, 0x00, 0x25}, + // 3 - 720KB, 3.5" - 2 heads, 80 tracks, 9 sectors + { {2, 80, 9}, 0x00, 0x17}, + // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors + { {2, 80, 18}, 0x00, 0x17}, + // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors + { {2, 80, 36}, 0xCC, 0xD7}, + // 6 - 160k, 5.25" - 1 heads, 40 tracks, 8 sectors + { {1, 40, 8}, 0x00, 0x27}, + // 7 - 180k, 5.25" - 1 heads, 40 tracks, 9 sectors + { {1, 40, 9}, 0x00, 0x27}, + // 8 - 320k, 5.25" - 2 heads, 40 tracks, 8 sectors + { {2, 40, 8}, 0x00, 0x27}, +}; + +struct drive_s * +init_floppy(int floppyid, int ftype) +{ + if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) { + dprintf(1, "Bad floppy type %d\n", ftype); + return NULL; + } + + struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g)); + if (!drive_g) { + warn_noalloc(); + return NULL; + } + memset(drive_g, 0, sizeof(*drive_g)); + drive_g->cntl_id = floppyid; + drive_g->type = DTYPE_FLOPPY; + drive_g->blksize = DISK_SECTOR_SIZE; + drive_g->floppy_type = ftype; + drive_g->sectors = (u64)-1; + + memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs + , sizeof(FloppyInfo[ftype].chs)); + return drive_g; +} + +static void +addFloppy(int floppyid, int ftype) +{ + struct drive_s *drive_g = init_floppy(floppyid, ftype); + if (!drive_g) + return; + char *desc = znprintf(MAXDESCSIZE, "Floppy [drive %c]", 'A' + floppyid); + struct pci_device *pci = pci_find_class(PCI_CLASS_BRIDGE_ISA); /* isa-to-pci bridge */ + int prio = bootprio_find_fdc_device(pci, PORT_FD_BASE, floppyid); + boot_add_floppy(drive_g, desc, prio); +} + void -floppy_drive_setup() +floppy_setup(void) { - if (! CONFIG_FLOPPY_SUPPORT) + if (! CONFIG_FLOPPY) return; dprintf(3, "init floppy drives\n"); - u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - u8 out = 0; - u8 num_floppies = 0; - if (type & 0xf0) { - out |= 0x07; - num_floppies++; - } - if (type & 0x0f) { - out |= 0x70; - num_floppies++; + if (CONFIG_COREBOOT) { + // XXX - disable floppies on coreboot for now. + } else { + u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); + if (type & 0xf0) + addFloppy(0, type >> 4); + if (type & 0x0f) + addFloppy(1, type & 0x0f); } - SET_BDA(floppy_harddisk_info, out); - - // Update equipment word bits for floppy - if (num_floppies == 1) - // 1 drive, ready for boot - SETBITS_BDA(equipment_list_flags, 0x01); - else if (num_floppies == 2) - // 2 drives, ready for boot - SETBITS_BDA(equipment_list_flags, 0x41); outb(0x02, PORT_DMA1_MASK_REG); - // Enable IRQ6 (handle_0e) - unmask_pic1(PIC1_IRQ6); + enable_hwirq(6, FUNC16(entry_0e)); } -static inline void -set_diskette_current_cyl(u8 drive, u8 cyl) +// Find a floppy type that matches a given image size. +int +find_floppy_type(u32 size) { - if (drive) - SET_BDA(floppy_track1, cyl); - else - SET_BDA(floppy_track0, cyl); + int i; + for (i=1; icylinders * c->heads * c->spt * DISK_SECTOR_SIZE == size) + return i; + } + return -1; } -static u16 -get_drive_type(u8 drive) -{ - // check CMOS to see if drive exists - u8 drive_type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - if (drive == 0) - drive_type >>= 4; - else - drive_type &= 0x0f; - return drive_type; -} -static u16 -floppy_media_known(u8 drive) -{ - if (!(GET_BDA(floppy_recalibration_status) & (1<es >> 12; // upper 4 bits - u16 base_es = regs->es << 4; // lower 16bits contributed by ES - u16 base_address = base_es + regs->bx; // lower 16 bits of address - // contributed by ES:BX - if (base_address < base_es) - // in case of carry, adjust page by 1 - page++; + u32 addr = (u32)op->buf_fl; // check for 64K boundary overrun - u16 last_addr = base_address + count; - if (last_addr < base_address) + u16 end = count - 1; + u32 last_addr = addr + end; + if ((addr >> 16) != (last_addr >> 16)) return DISK_RET_EBOUNDARY; u8 mode_register = 0x4a; // single mode, increment, autoinit disable, @@ -215,28 +266,28 @@ floppy_cmd(struct bregs *regs, u16 count, u8 *cmd, u8 cmdlen) //DEBUGF("floppy dma c2\n"); outb(0x06, PORT_DMA1_MASK_REG); outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop - outb(base_address, PORT_DMA_ADDR_2); - outb(base_address>>8, PORT_DMA_ADDR_2); + outb(addr, PORT_DMA_ADDR_2); + outb(addr>>8, PORT_DMA_ADDR_2); outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop - outb(count, PORT_DMA_CNT_2); - outb(count>>8, PORT_DMA_CNT_2); + outb(end, PORT_DMA_CNT_2); + outb(end>>8, PORT_DMA_CNT_2); // port 0b: DMA-1 Mode Register // transfer type=write, channel 2 outb(mode_register, PORT_DMA1_MODE_REG); // port 81: DMA-1 Page Register, channel 2 - outb(page, PORT_DMA_PAGE_2); + outb(addr>>16, PORT_DMA_PAGE_2); outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2 - u8 ret = floppy_pio(cmd, cmdlen); + int ret = floppy_pio(cmd, cmdlen); if (ret) - return ret; + return DISK_RET_ETIMEOUT; // check port 3f4 for accessibility to status bytes if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) - BX_PANIC("int13_diskette: ctrl not ready\n"); + return DISK_RET_ECONTROLLER; // read 7 return status bytes from controller u8 i; @@ -246,30 +297,36 @@ floppy_cmd(struct bregs *regs, u16 count, u8 *cmd, u8 cmdlen) SET_BDA(floppy_return_status[i], v); } - return 0; + return DISK_RET_SUCCESS; +} + + +/**************************************************************** + * Floppy media sense + ****************************************************************/ + +static inline void +set_diskette_current_cyl(u8 floppyid, u8 cyl) +{ + SET_BDA(floppy_track[floppyid], cyl); } static void -floppy_drive_recal(u8 drive) +floppy_drive_recal(u8 floppyid) { // send Recalibrate command (2 bytes) to controller u8 data[12]; data[0] = 0x07; // 07: Recalibrate - data[1] = drive; // 0=drive0, 1=drive1 + data[1] = floppyid; // 0=drive0, 1=drive1 floppy_pio(data, 2); - SETBITS_BDA(floppy_recalibration_status, 1<floppy_type); + SET_BDA(floppy_last_data_rate, GET_GLOBAL(FloppyInfo[ftype].config_data)); + u8 floppyid = GET_GLOBAL(drive_g->cntl_id); + SET_BDA(floppy_media_state[floppyid] + , GET_GLOBAL(FloppyInfo[ftype].media_state)); + return DISK_RET_SUCCESS; } -#define floppy_ret(regs, code) \ - __floppy_ret(__func__, (regs), (code)) - -void -__floppy_ret(const char *fname, struct bregs *regs, u8 code) +static int +check_recal_drive(struct drive_s *drive_g) { - SET_BDA(floppy_last_status, code); - if (code) - __set_code_fail(fname, regs, code); - else - set_code_success(regs); -} + u8 floppyid = GET_GLOBAL(drive_g->cntl_id); + if ((GET_BDA(floppy_recalibration_status) & (1<al = 0; // no sectors read + // Recalibrate drive. + floppy_drive_recal(floppyid); + + // Sense media. + return floppy_media_sense(drive_g); } -static u16 -check_drive(struct bregs *regs, u8 drive) -{ - // see if drive exists - if (drive > 1 || !get_drive_type(drive)) { - // XXX - return type doesn't match - floppy_fail(regs, DISK_RET_ETIMEOUT); - return 1; - } - // see if media in drive, and type is known - if (floppy_media_known(drive) == 0 && floppy_media_sense(drive) == 0) { - floppy_fail(regs, DISK_RET_EMEDIA); - return 1; - } - return 0; -} +/**************************************************************** + * Floppy handlers + ****************************************************************/ -// diskette controller reset static void -floppy_1300(struct bregs *regs, u8 drive) +lba2chs(struct disk_op_s *op, u8 *track, u8 *sector, u8 *head) { - if (drive > 1) { - floppy_ret(regs, DISK_RET_EPARAM); - return; - } - if (!get_drive_type(drive)) { - floppy_ret(regs, DISK_RET_ETIMEOUT); - return; - } - set_diskette_current_cyl(drive, 0); // current cylinder - floppy_ret(regs, DISK_RET_SUCCESS); + u32 lba = op->lba; + + u32 tmp = lba + 1; + u16 nlspt = GET_GLOBAL(op->drive_g->lchs.spt); + *sector = tmp % nlspt; + + tmp /= nlspt; + u16 nlh = GET_GLOBAL(op->drive_g->lchs.heads); + *head = tmp % nlh; + + tmp /= nlh; + *track = tmp; } -// Read Diskette Status -static void -floppy_1301(struct bregs *regs, u8 drive) +// diskette controller reset +static int +floppy_reset(struct disk_op_s *op) { - u8 v = GET_BDA(floppy_last_status); - regs->ah = v; - set_cf(regs, v); + u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); + set_diskette_current_cyl(floppyid, 0); // current cylinder + return DISK_RET_SUCCESS; } // Read Diskette Sectors -static void -floppy_1302(struct bregs *regs, u8 drive) +static int +floppy_read(struct disk_op_s *op) { - if (check_drive(regs, drive)) - return; - - u8 num_sectors = regs->al; - u8 track = regs->ch; - u8 sector = regs->cl; - u8 head = regs->dh; + int res = check_recal_drive(op->drive_g); + if (res) + goto fail; - if (head > 1 || sector == 0 || num_sectors == 0 - || track > 79 || num_sectors > 72) { - floppy_fail(regs, DISK_RET_EPARAM); - return; - } + u8 track, sector, head; + lba2chs(op, &track, §or, &head); // send read-normal-data command (9 bytes) to controller + u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); u8 data[12]; data[0] = 0xe6; // e6: read normal data - data[1] = (head << 2) | drive; // HD DR1 DR2 + data[1] = (head << 2) | floppyid; // HD DR1 DR2 data[2] = track; data[3] = head; data[4] = sector; - data[5] = 2; // 512 byte sector size - data[6] = sector + num_sectors - 1; // last sector to read on track - data[7] = 0; // Gap length - data[8] = 0xff; // Gap length + data[5] = FLOPPY_SIZE_CODE; + data[6] = sector + op->count - 1; // last sector to read on track + data[7] = FLOPPY_GAPLEN; + data[8] = FLOPPY_DATALEN; - u16 ret = floppy_cmd(regs, (num_sectors * 512) - 1, data, 9); - if (ret) { - floppy_fail(regs, ret); - return; - } + res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9); + if (res) + goto fail; if (data[0] & 0xc0) { - floppy_fail(regs, DISK_RET_ECONTROLLER); - return; + res = DISK_RET_ECONTROLLER; + goto fail; } // ??? should track be new val from return_status[3] ? - set_diskette_current_cyl(drive, track); - // AL = number of sectors read (same value as passed) - floppy_ret(regs, DISK_RET_SUCCESS); + set_diskette_current_cyl(floppyid, track); + return DISK_RET_SUCCESS; +fail: + op->count = 0; // no sectors read + return res; } // Write Diskette Sectors -static void -floppy_1303(struct bregs *regs, u8 drive) +static int +floppy_write(struct disk_op_s *op) { - if (check_drive(regs, drive)) - return; + int res = check_recal_drive(op->drive_g); + if (res) + goto fail; - u8 num_sectors = regs->al; - u8 track = regs->ch; - u8 sector = regs->cl; - u8 head = regs->dh; - - if (head > 1 || sector == 0 || num_sectors == 0 - || track > 79 || num_sectors > 72) { - floppy_fail(regs, DISK_RET_EPARAM); - return; - } + u8 track, sector, head; + lba2chs(op, &track, §or, &head); // send write-normal-data command (9 bytes) to controller + u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); u8 data[12]; data[0] = 0xc5; // c5: write normal data - data[1] = (head << 2) | drive; // HD DR1 DR2 + data[1] = (head << 2) | floppyid; // HD DR1 DR2 data[2] = track; data[3] = head; data[4] = sector; - data[5] = 2; // 512 byte sector size - data[6] = sector + num_sectors - 1; // last sector to write on track - data[7] = 0; // Gap length - data[8] = 0xff; // Gap length + data[5] = FLOPPY_SIZE_CODE; + data[6] = sector + op->count - 1; // last sector to write on track + data[7] = FLOPPY_GAPLEN; + data[8] = FLOPPY_DATALEN; - u8 ret = floppy_cmd(regs, (num_sectors * 512) - 1, data, 9); - if (ret) { - floppy_fail(regs, ret); - return; - } + res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9); + if (res) + goto fail; if (data[0] & 0xc0) { - if (data[1] & 0x02) { - set_fail(regs); - regs->ax = 0x0300; - return; - } - BX_PANIC("int13_diskette_function: read error\n"); + if (data[1] & 0x02) + res = DISK_RET_EWRITEPROTECT; + else + res = DISK_RET_ECONTROLLER; + goto fail; } // ??? should track be new val from return_status[3] ? - set_diskette_current_cyl(drive, track); - // AL = number of sectors read (same value as passed) - floppy_ret(regs, DISK_RET_SUCCESS); + set_diskette_current_cyl(floppyid, track); + return DISK_RET_SUCCESS; +fail: + op->count = 0; // no sectors read + return res; } // Verify Diskette Sectors -static void -floppy_1304(struct bregs *regs, u8 drive) +static int +floppy_verify(struct disk_op_s *op) { - if (check_drive(regs, drive)) - return; - - u8 num_sectors = regs->al; - u8 track = regs->ch; - u8 sector = regs->cl; - u8 head = regs->dh; + int res = check_recal_drive(op->drive_g); + if (res) + goto fail; - if (head > 1 || sector == 0 || num_sectors == 0 - || track > 79 || num_sectors > 72) { - floppy_fail(regs, DISK_RET_EPARAM); - return; - } + u8 track, sector, head; + lba2chs(op, &track, §or, &head); // ??? should track be new val from return_status[3] ? - set_diskette_current_cyl(drive, track); - // AL = number of sectors verified (same value as passed) - floppy_ret(regs, DISK_RET_SUCCESS); + u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); + set_diskette_current_cyl(floppyid, track); + return DISK_RET_SUCCESS; +fail: + op->count = 0; // no sectors read + return res; } // format diskette track -static void -floppy_1305(struct bregs *regs, u8 drive) +static int +floppy_format(struct disk_op_s *op) { - DEBUGF("floppy f05\n"); - - if (check_drive(regs, drive)) - return; - - u8 num_sectors = regs->al; - u8 head = regs->dh; + int ret = check_recal_drive(op->drive_g); + if (ret) + return ret; - if (head > 1 || num_sectors == 0 || num_sectors > 18) { - floppy_fail(regs, DISK_RET_EPARAM); - return; - } + u8 head = op->lba; // send format-track command (6 bytes) to controller + u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id); u8 data[12]; data[0] = 0x4d; // 4d: format track - data[1] = (head << 2) | drive; // HD DR1 DR2 - data[2] = 2; // 512 byte sector size - data[3] = num_sectors; // number of sectors per track - data[4] = 0; // Gap length - data[5] = 0xf6; // Fill byte + data[1] = (head << 2) | floppyid; // HD DR1 DR2 + data[2] = FLOPPY_SIZE_CODE; + data[3] = op->count; // number of sectors per track + data[4] = FLOPPY_FORMAT_GAPLEN; + data[5] = FLOPPY_FILLBYTE; - u8 ret = floppy_cmd(regs, (num_sectors * 4) - 1, data, 6); - if (ret) { - floppy_fail(regs, ret); - return; - } + ret = floppy_cmd(op, op->count * 4, data, 6); + if (ret) + return ret; if (data[0] & 0xc0) { - if (data[1] & 0x02) { - set_fail(regs); - regs->ax = 0x0300; - return; - } - BX_PANIC("int13_diskette_function: read error\n"); - } - - set_diskette_current_cyl(drive, 0); - floppy_ret(regs, 0); -} - -// read diskette drive parameters -static void -floppy_1308(struct bregs *regs, u8 drive) -{ - DEBUGF("floppy f08\n"); - - u8 drive_type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE); - u8 num_floppies = 0; - if (drive_type & 0xf0) - num_floppies++; - if (drive_type & 0x0f) - num_floppies++; - - if (drive > 1) { - regs->ax = 0; - regs->bx = 0; - regs->cx = 0; - regs->dx = 0; - regs->es = 0; - regs->di = 0; - regs->dl = num_floppies; - set_success(regs); - return; + if (data[1] & 0x02) + return DISK_RET_EWRITEPROTECT; + return DISK_RET_ECONTROLLER; } - if (drive == 0) - drive_type >>= 4; - else - drive_type &= 0x0f; - - regs->bh = 0; - regs->bl = drive_type; - regs->ah = 0; - regs->al = 0; - regs->dl = num_floppies; - - switch (drive_type) { - case 0: // none - regs->cx = 0; - regs->dh = 0; // max head # - break; - - case 1: // 360KB, 5.25" - regs->cx = 0x2709; // 40 tracks, 9 sectors - regs->dh = 1; // max head # - break; - - case 2: // 1.2MB, 5.25" - regs->cx = 0x4f0f; // 80 tracks, 15 sectors - regs->dh = 1; // max head # - break; - - case 3: // 720KB, 3.5" - regs->cx = 0x4f09; // 80 tracks, 9 sectors - regs->dh = 1; // max head # - break; - - case 4: // 1.44MB, 3.5" - regs->cx = 0x4f12; // 80 tracks, 18 sectors - regs->dh = 1; // max head # - break; - - case 5: // 2.88MB, 3.5" - regs->cx = 0x4f24; // 80 tracks, 36 sectors - regs->dh = 1; // max head # - break; - - case 6: // 160k, 5.25" - regs->cx = 0x2708; // 40 tracks, 8 sectors - regs->dh = 0; // max head # - break; - - case 7: // 180k, 5.25" - regs->cx = 0x2709; // 40 tracks, 9 sectors - regs->dh = 0; // max head # - break; - - case 8: // 320k, 5.25" - regs->cx = 0x2708; // 40 tracks, 8 sectors - regs->dh = 1; // max head # - break; - - default: // ? - BX_PANIC("floppy: int13: bad floppy type\n"); - } - - /* set es & di to point to 11 byte diskette param table in ROM */ - regs->es = SEG_BIOS; - regs->di = (u32)&diskette_param_table2; - /* disk status not changed upon success */ + set_diskette_current_cyl(floppyid, 0); + return DISK_RET_SUCCESS; } -// read diskette drive type -static void -floppy_1315(struct bregs *regs, u8 drive) +int +process_floppy_op(struct disk_op_s *op) { - DEBUGF("floppy f15\n"); - if (drive > 1) { - set_fail(regs); - regs->ah = 0; // only 2 drives supported - // set_diskette_ret_status here ??? - return; - } - u8 drive_type = get_drive_type(drive); - - regs->ah = (drive_type != 0); - set_success(regs); -} + if (!CONFIG_FLOPPY) + return 0; -// get diskette change line status -static void -floppy_1316(struct bregs *regs, u8 drive) -{ - DEBUGF("floppy f16\n"); - if (drive > 1) { - floppy_ret(regs, DISK_RET_EPARAM); - return; + switch (op->command) { + case CMD_RESET: + return floppy_reset(op); + case CMD_READ: + return floppy_read(op); + case CMD_WRITE: + return floppy_write(op); + case CMD_VERIFY: + return floppy_verify(op); + case CMD_FORMAT: + return floppy_format(op); + default: + op->count = 0; + return DISK_RET_EPARAM; } - floppy_ret(regs, DISK_RET_ECHANGED); } -static void -floppy_13XX(struct bregs *regs, u8 drive) -{ - floppy_ret(regs, DISK_RET_EPARAM); -} -void -floppy_13(struct bregs *regs, u8 drive) -{ - if (! CONFIG_FLOPPY_SUPPORT) { - // Minimal stubs - switch (regs->ah) { - case 0x01: floppy_1301(regs, drive); break; - default: floppy_13XX(regs, drive); break; - } - return; - } - switch (regs->ah) { - case 0x00: floppy_1300(regs, drive); break; - case 0x01: floppy_1301(regs, drive); break; - case 0x02: floppy_1302(regs, drive); break; - case 0x03: floppy_1303(regs, drive); break; - case 0x04: floppy_1304(regs, drive); break; - case 0x05: floppy_1305(regs, drive); break; - case 0x08: floppy_1308(regs, drive); break; - case 0x15: floppy_1315(regs, drive); break; - case 0x16: floppy_1316(regs, drive); break; - default: floppy_13XX(regs, drive); break; - } -} +/**************************************************************** + * HW irqs + ****************************************************************/ // INT 0Eh Diskette Hardware ISR Entry Point void VISIBLE16 -handle_0e() +handle_0e(void) { debug_isr(DEBUG_ISR_0e); + if (! CONFIG_FLOPPY) + goto done; + if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) { outb(0x08, PORT_FD_DATA); // sense interrupt status while ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) @@ -759,15 +596,20 @@ handle_0e() inb(PORT_FD_DATA); } while ((inb(PORT_FD_STATUS) & 0xc0) == 0xc0); } - eoi_pic1(); // diskette interrupt has occurred SETBITS_BDA(floppy_recalibration_status, FRS_TIMEOUT); + +done: + eoi_pic1(); } // Called from int08 handler. void -floppy_tick() +floppy_tick(void) { + if (! CONFIG_FLOPPY) + return; + // time to turn off drive(s)? u8 fcount = GET_BDA(floppy_motor_counter); if (fcount) {