X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Ffloppy.c;h=efe9592f5927060b1fff17ff502316372529b78f;hb=f54c150090ff38a73ef64a5d20fdfa0d9c403972;hp=5e70df2284035eacb1d7063dc9880120c5eaea5c;hpb=f076a3eeb9a0185b06a2abbba8c798a7761b2bdf;p=seabios.git diff --git a/src/floppy.c b/src/floppy.c index 5e70df2..efe9592 100644 --- a/src/floppy.c +++ b/src/floppy.c @@ -11,55 +11,69 @@ #include "biosvar.h" // struct bregs #include "util.h" // irq_disable #include "cmos.h" // inb_cmos +#include "pic.h" // unmask_pic1 -#define BX_FLOPPY_ON_CNT 37 /* 2 seconds */ +#define DEBUGF1(fmt, args...) bprintf(0, fmt , ##args) +#define DEBUGF(fmt, args...) -////.org 0xefc7 -// Since no provisions are made for multiple drive types, most -// values in this table are ignored. I set parameters for 1.44M -// floppy here -char diskette_param_table[11] = { - 0xAF, - 0x02, // head load time 0000001, DMA used - 0x25, - 0x02, - 18, - 0x1B, - 0xFF, - 0x6C, - 0xF6, - 0x0F, - 0x08, -}; +#define BX_FLOPPY_ON_CNT 37 /* 2 seconds */ // 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 -char diskette_param_table2[14] VISIBLE = { - 0xAF, - 0x02, // head load time 0000001, DMA used - 0x25, - 0x02, - 18, - 0x1B, - 0xFF, - 0x6C, - 0xF6, - 0x0F, - 0x08, - 79, // maximum track - 0, // data transfer rate - 4, // drive type in cmos +struct floppy_ext_dbt_s diskette_param_table2 VISIBLE16 = { + .dbt = { + .specify1 = 0xAF, + .specify2 = 0x02, // head load time 0000001, DMA used + .shutoff_ticks = 0x25, + .bps_code = 0x02, + .sectors = 18, + .interblock_len = 0x1B, + .data_len = 0xFF, + .gap_len = 0x6C, + .fill_byte = 0xF6, + .settle_time = 0x0F, + .startup_time = 0x08, + }, + .max_track = 79, // maximum track + .data_rate = 0, // data transfer rate + .drive_type = 4, // drive type in cmos }; -// Oddities: -// Return codes vary greatly - AL not cleared consistenlty, BDA return -// status not set consistently, sometimes panics. -// Extra outb(0x000a, 0x02) in read? -// Does not disable interrupts on failure paths. -// numfloppies used before set in int_1308 -// int_1305 verifies track but doesn't use it? +void +floppy_drive_setup() +{ + if (! CONFIG_FLOPPY_SUPPORT) + 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++; + } + 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); +} static inline void set_diskette_current_cyl(u8 drive, u8 cyl) @@ -130,9 +144,12 @@ floppy_prepare_controller(u8 drive) if (prev_reset == 0) { irq_enable(); u8 v; - do { + for (;;) { v = GET_BDA(floppy_recalibration_status); - } while ((v & FRS_TIMEOUT) == 0); + if (v & FRS_TIMEOUT) + break; + cpu_relax(); + } irq_disable(); v &= ~FRS_TIMEOUT; @@ -152,22 +169,22 @@ floppy_pio(u8 *cmd, u8 cmdlen) irq_enable(); u8 v; - do { + for (;;) { if (!GET_BDA(floppy_motor_counter)) { irq_disable(); floppy_reset_controller(); return DISK_RET_ETIMEOUT; } v = GET_BDA(floppy_recalibration_status); - } while (!(v & FRS_TIMEOUT)); + if (v & FRS_TIMEOUT) + break; + cpu_relax(); + } irq_disable(); v &= ~FRS_TIMEOUT; SET_BDA(floppy_recalibration_status, v); - if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) - BX_PANIC("int13_diskette: ctrl not ready\n"); - return 0; } @@ -195,7 +212,7 @@ floppy_cmd(struct bregs *regs, u16 count, u8 *cmd, u8 cmdlen) // read mode_register = 0x46; - DEBUGF("floppy dma c2"); + //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); @@ -217,6 +234,10 @@ floppy_cmd(struct bregs *regs, u16 count, u8 *cmd, u8 cmdlen) if (ret) return ret; + // check port 3f4 for accessibility to status bytes + if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) + BX_PANIC("int13_diskette: ctrl not ready\n"); + // read 7 return status bytes from controller u8 i; for (i=0; i<7; i++) { @@ -343,19 +364,24 @@ floppy_media_sense(u8 drive) return rv; } -static inline void -floppy_ret(struct bregs *regs, u8 code) +#define floppy_ret(regs, code) \ + __floppy_ret(__func__, (regs), (code)) + +void +__floppy_ret(const char *fname, struct bregs *regs, u8 code) { - regs->ah = code; SET_BDA(floppy_last_status, code); - set_cf(regs, code); + if (code) + __set_code_fail(fname, regs, code); + else + set_code_success(regs); } static inline void floppy_fail(struct bregs *regs, u8 code) { - regs->al = 0; // no sectors read floppy_ret(regs, code); + regs->al = 0; // no sectors read } static u16 @@ -363,6 +389,7 @@ 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; } @@ -414,7 +441,6 @@ floppy_1302(struct bregs *regs, u8 drive) if (head > 1 || sector == 0 || num_sectors == 0 || track > 79 || num_sectors > 72) { - BX_INFO("int13_diskette: read/write/verify: parameter out of range\n"); floppy_fail(regs, DISK_RET_EPARAM); return; } @@ -462,7 +488,6 @@ floppy_1303(struct bregs *regs, u8 drive) if (head > 1 || sector == 0 || num_sectors == 0 || track > 79 || num_sectors > 72) { - BX_INFO("int13_diskette: read/write/verify: parameter out of range\n"); floppy_fail(regs, DISK_RET_EPARAM); return; } @@ -487,8 +512,8 @@ floppy_1303(struct bregs *regs, u8 drive) if (data[0] & 0xc0) { if (data[1] & 0x02) { + set_fail(regs); regs->ax = 0x0300; - set_cf(regs, 1); return; } BX_PANIC("int13_diskette_function: read error\n"); @@ -514,7 +539,6 @@ floppy_1304(struct bregs *regs, u8 drive) if (head > 1 || sector == 0 || num_sectors == 0 || track > 79 || num_sectors > 72) { - BX_INFO("int13_diskette: read/write/verify: parameter out of range\n"); floppy_fail(regs, DISK_RET_EPARAM); return; } @@ -538,7 +562,6 @@ floppy_1305(struct bregs *regs, u8 drive) u8 head = regs->dh; if (head > 1 || num_sectors == 0 || num_sectors > 18) { - BX_INFO("int13_diskette: read/write/verify: parameter out of range\n"); floppy_fail(regs, DISK_RET_EPARAM); return; } @@ -560,8 +583,8 @@ floppy_1305(struct bregs *regs, u8 drive) if (data[0] & 0xc0) { if (data[1] & 0x02) { + set_fail(regs); regs->ax = 0x0300; - set_cf(regs, 1); return; } BX_PANIC("int13_diskette_function: read error\n"); @@ -592,7 +615,7 @@ floppy_1308(struct bregs *regs, u8 drive) regs->es = 0; regs->di = 0; regs->dl = num_floppies; - set_cf(regs, 0); + set_success(regs); return; } @@ -659,7 +682,7 @@ floppy_1308(struct bregs *regs, u8 drive) /* set es & di to point to 11 byte diskette param table in ROM */ regs->es = SEG_BIOS; - regs->di = (u16)diskette_param_table2; + regs->di = (u32)&diskette_param_table2; /* disk status not changed upon success */ } @@ -669,15 +692,15 @@ floppy_1315(struct bregs *regs, u8 drive) { DEBUGF("floppy f15\n"); if (drive > 1) { + set_fail(regs); regs->ah = 0; // only 2 drives supported // set_diskette_ret_status here ??? - set_cf(regs, 1); return; } u8 drive_type = get_drive_type(drive); regs->ah = (drive_type != 0); - set_cf(regs, 0); + set_success(regs); } // get diskette change line status @@ -695,39 +718,39 @@ floppy_1316(struct bregs *regs, u8 drive) static void floppy_13XX(struct bregs *regs, u8 drive) { - BX_INFO("int13_diskette: unsupported AH=%02x\n", GET_AH()); floppy_ret(regs, DISK_RET_EPARAM); } void floppy_13(struct bregs *regs, u8 drive) { - if (CONFIG_FLOPPY_SUPPORT) { - 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; - } - } else { + 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; } } // INT 0Eh Diskette Hardware ISR Entry Point -void VISIBLE -handle_0e(struct bregs *regs) +void VISIBLE16 +handle_0e() { - debug_enter(regs); + debug_isr(DEBUG_ISR_0e); if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) { outb(0x08, PORT_FD_DATA); // sense interrupt status while ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) @@ -736,7 +759,7 @@ handle_0e(struct bregs *regs) inb(PORT_FD_DATA); } while ((inb(PORT_FD_STATUS) & 0xc0) == 0xc0); } - eoi_master_pic(); + eoi_pic1(); // diskette interrupt has occurred SETBITS_BDA(floppy_recalibration_status, FRS_TIMEOUT); }