/******************************************************************************* * void floppy_reset() * * This resets the floppy (duh!) into a known condition. * * Date: December 31, 2004 * *****************************************************************************/ void floppy_reset() { outportb(FDC_DOR, 0); floppy_mtick = 0; floppy_motor = false; /*disable interrupt*/ outportb(FDC_DRS, 0); /*reenable interrupts*/ outportb(FDC_DOR, 0x0C); /*the reset triggered an interrupt, wait for it to be handled*/ floppy_done = true; floppy_wait(true); /*specify driv timings*/ floppy_sendbyte(CMD_SPECIFY); floppy_sendbyte(0xDF); floppy_sendbyte(0x02); /*clear the "disk change" status */ floppy_seek(1); floppy_recalibrate(); floppy_dchange = false; }
/******************************************************************************* * void floppy_recalibrate() * * This recalibrates the FDC. * * Date: December 31, 2004 * *****************************************************************************/ void floppy_recalibrate() { /*turn the motor on*/ floppy_motor_start(); /*send command bytes*/ floppy_sendbyte(CMD_RECAL); floppy_sendbyte(0); /*wait until seek if finished*/ floppy_wait(true); /*turn the motor off*/ floppy_motor_stop(); }
/******************************************************************************* * void floppy_seek(int track) * * This causes the floppy head to seek to the given track so that data can either * be written or read from it. * * Parameters: * 1) int track * This is the track that we want to seek to. * * Date: December 31, 2004 * *****************************************************************************/ bool floppy_seek(int track) { ///check to see if we've already seeked to 'track' if (floppy_track == track) return true; ///send command bytes floppy_sendbyte(CMD_SEEK); floppy_sendbyte(0); floppy_sendbyte(track); ///wait until seek is finished if (!floppy_wait(true)) return false; ///timeout ///wait for the head to settle sleep(FLOPPY_SLEEP_TIME); ///make sure that seek worked if ((floppy_sr0 != 0x20) || (floppy_track != track)) return false; else return true; }
int floppy_rw_sector(uint_t drive, uint8_t sector, uint8_t head, uint8_t cylinder, uintptr_t buffer, int write) { int a; alku: if (drive >= MAX_DRIVES || !floppy_drives[drive].type) { return -1; } if (inportb(FLOPPY_FIRST + DIGITAL_INPUT_REGISTER) & 0x80) { /* disk was changed */ floppy_seek_track(drive, 1); floppy_calibrate(drive); floppy_motor_off(drive); if (inportb(FLOPPY_FIRST + DIGITAL_INPUT_REGISTER) & 0x80) { kprintf("FDD: No floppy in fd%u\n", drive); return -2; } else { kprintf("FDD: Floppy changed, trying again...\n"); goto alku; } } if (floppy_seek_track(drive, cylinder)) if (floppy_seek_track(drive, cylinder)) if (floppy_seek_track(drive, cylinder)) { return -1; /* three seeks? */ } /* floppy_seek_track actually starts motor already, but... */ floppy_motor_on(drive); if (!(inportb(FLOPPY_FIRST + MAIN_STATUS_REGISTER) & 0x20)) { panic("Non-dma floppy transfer?\n"); } /* block size */ floppy_init_dma(buffer, 512, write); kwait(0, 1000 * floppy_params.head_settle_time); floppy_wait(); prepare_wait_irq(FLOPPY_IRQ); floppy_command(write ? WRITE_DATA : READ_DATA); floppy_command((head << 2) | drive); floppy_command(cylinder); floppy_command(head); floppy_command(sector); floppy_command(floppy_params.bytes_per_sector); /*sector size = 128*2^size*/ floppy_command(floppy_params.sectors_per_track); /*last sector*/ floppy_command(floppy_params.gap_length); /*27 default gap3 value*/ floppy_command(floppy_params.data_length); /*default value for data length*/ //kprintf("FDD: BPS: %u, SPT: %u, GL: %u, DL: %u\n", floppy_params.bytes_per_sector, floppy_params.sectors_per_track, floppy_params.gap_length, floppy_params.data_length); wait_irq(FLOPPY_IRQ); //kprintf("We got values "); for (a = 0; a < 7; a++) { /* TODO: Put these values somewhere? */ floppy_wait_data(); inportb(FLOPPY_FIRST + DATA_FIFO); //kprintf("%d ", inportb(FLOPPY_FIRST + DATA_FIFO)); } //kprintf(" from floppy controller after reading\n"); floppy_prepare_motor_off(drive); return 0; }
void floppy_command(uint8_t command) { floppy_wait(); outportb(FLOPPY_FIRST + DATA_FIFO, command); }
/******************************************************************************* * bool floppy_rw(int block, unsigned char *blockbuff, * unsigned char read, unsigned long nosectors) * * Since the read and write to a floppy disk is not that much different, most of * the code is the same. The only difference is dependent on what the 'read' * variable is set as. * * Parameters: * 1) int block * This is the block that we want to read. * 2) unsigned char *blockbuff * This is the buffer that we want it read into or written out to. The size * of this buffer should be 512 * nosectors, as each sector read in is 512 * bytes * 3) unsigned char read * Are we going to read or write to this block. * 4) unsigned long nosectors * The number of sectors that we want to be read in. * * Return value: * This returns where or not the read/write was successfull. * * Date: December 31, 2004 * *****************************************************************************/ bool floppy_rw(int block, unsigned char *blockbuff, unsigned char read, unsigned long nosectors) { int head; int track; int sector; int tries; int copycount=0; unsigned char *p_track_buffer = (unsigned char*)floppy_dma_address; unsigned char *p_block_buffer = blockbuff; ///convert logical address into physical address floppy_block2hts(block , &head, &track, §or); ///start the floppy motor floppy_motor_start(); if (!read && blockbuff) ///copy data from the data buffer into the track buffer for (copycount=0; copycount<(nosectors*512); copycount++) *(p_track_buffer++) = *(p_block_buffer++); for (tries = 0; tries < 3; tries++) { ///check for disk change if (inportb(FDC_DIR) & 0x80) { floppy_dchange = true; floppy_seek(1); floppy_recalibrate(); floppy_motor_stop(); ERROR_MSG(("FDC: Disk change detected. Trying again.")); return floppy_rw(block, blockbuff, read, nosectors); } ///move head to the right track if (!floppy_seek(track)) { floppy_motor_stop(); ERROR_MSG(("FDC: Seek error")); return false; } ///program data rate (500Kb/s) outportb(FDC_CCR, 0); ///send command if (read) { dma_xfer(2, (unsigned long)floppy_dma_address, nosectors*512, false); floppy_sendbyte(CMD_READ); } else { dma_xfer(2, (unsigned long)floppy_dma_address, nosectors*512, true); floppy_sendbyte(CMD_WRITE); } floppy_sendbyte(head << 2); floppy_sendbyte(track); floppy_sendbyte(head); floppy_sendbyte(sector); floppy_sendbyte(2); floppy_sendbyte(floppy_geometry.spt); if (floppy_geometry.spt == DG144_SPT) floppy_sendbyte(DG144_GAP3RW); else floppy_sendbyte(DG168_GAP3RW); floppy_sendbyte(0xff); ///wait for commmand completion if (!floppy_wait(true)) { ERROR_MSG(("Timed out, trying operation again after reset")); floppy_reset(); return floppy_rw(block, blockbuff, read, nosectors); } ///let's see if the transfer worked if ((floppy_status[0] & 0xC0) == 0) break; ///it didn't work. try again floppy_recalibrate(); } floppy_motor_stop(); if (read && blockbuff) { ///copy data from track buffer into data buffer p_block_buffer = blockbuff; p_track_buffer = (unsigned char *)floppy_dma_address; for (copycount = 0; copycount <(nosectors*512); copycount++) { *p_block_buffer = *p_track_buffer; p_block_buffer++; p_track_buffer++; } } return (tries != 3); }