?? old-fdc.c
字號:
} else res = FDC_ERROR; /* Seek error */ if (tries != 2) recalibrate(fdd); /* Error, try again... */ } /* Copy data from the DMA buffer into the caller's buffer */ if ((res == FDC_OK) && buffer) fd32_memcpy_from_lowmem(buffer, dma_sel, 0, 512 * num_sectors); motor_down(fdd); busy = 0; return res;}/* Writes sectors to the floppy, up to the end of the cylinder. */int fdc_write(Fdd *fdd, const Chs *chs, const BYTE *buffer, unsigned num_sectors){ unsigned tries; int res = FDC_ERROR; if (fdd->dp->cmos_type == 0) return FDC_ERROR; /* Drive not available */ /* TODO: Place a timeout for Busy check */ while (busy); /* Wait while the floppy driver is already busy: BUSY WAIT! */ busy = 1; motor_on(fdd); specify(fdd); fd32_memcpy_to_lowmem(dma_sel, 0, buffer, 512 * num_sectors); for (tries = 0; tries < 3; tries++) { /* Move head to right track */ if (fdc_seek(fdd, chs->c) == FDC_OK) { /* If changeline is active, no disk is in drive */ if (fd32_inb(fdd->fdc->base_port + FDC_DIR) & 0x80) { LOG_PRINTF(("[FDC] fdc_write: no disk in drive\n")); res = FDC_NODISK; break; } res = fdc_xfer(fdd, chs, dma_addr, num_sectors, FDC_WRITE); if (res == FDC_OK) break; } else res = FDC_ERROR; /* Seek error */ if (tries != 2) recalibrate(fdd); /* Error, try again... */ } motor_down(fdd); busy = 0; return res;}/* Transfers data between a whole cylinder (both tracks of disk sides) and *//* and the DMA buffer, as fast as possible. *//* We get the current head position with READID, so we can start to *//* transfer sectors from the first sector passing below the head. When the *//* disk completes a revolution, we finish transferring the first sectors. *//* If buffer is NULL, the read data is discarded (may be used to probe). */static int fdc_xfer_cylinder(Fdd *fdd, unsigned cyl, FdcTransfer op){ unsigned tries; /* Count how many retries */ Chs chs = { cyl, 0, 1 }; /* Passed to fdc_xfer to read sectors */ Chs cur; /* Current position returned by READID */ unsigned sec_in_cyl; /* Zero-based sector we start to read */ int res = FDC_ERROR; /* This function's result... */ motor_on(fdd); specify(fdd); for (tries = 0; tries < 3; tries++) { /* Move head to right track */ if (fdc_seek(fdd, cyl) == FDC_OK) { /* If changeline is active, no disk is in drive */ if (fd32_inb(fdd->fdc->base_port + FDC_DIR) & 0x80) { LOG_PRINTF(("[FDC] fdc_Xfer_cylinder: no disk in drive\n")); res = FDC_NODISK; break; } readid(fdd, &cur); LOG_PRINTF(("[FDC] fdc_xfer_cylinder: readid=%u,%u,%u\n", cur.c, cur.h, cur.s)); /* Transfer from the current sector of head 0 to the end of cylinder */ cur.s++; /* The sector we read the Id is gone. Advance a bit */ sec_in_cyl = cur.s - 1; if (cur.s > fdd->fmt->sec_per_trk) { cur.h++; cur.s -= fdd->fmt->sec_per_trk; } chs.h = cur.h; chs.s = cur.s; LOG_PRINTF(("[FDC] fdc_xfer_cylinder: first round:%u sectors from %u\n", fdd->fmt->sec_per_trk * 2 - sec_in_cyl, sec_in_cyl)); res = fdc_xfer(fdd, &chs, dma_addr + 512 * sec_in_cyl, fdd->fmt->sec_per_trk * 2 - sec_in_cyl, op); /* Read the first sectors, that we missed in the previous revolution */ if ((res == FDC_OK) && (sec_in_cyl > 0)) { chs.h = 0; chs.s = 1; LOG_PRINTF(("[FDC] fdc_read_cylinder: second round:%u sectors from 0\n", sec_in_cyl)); res = fdc_xfer(fdd, &chs, dma_addr, sec_in_cyl, op); } if (res == FDC_OK) break; } else res = FDC_ERROR; /* Seek error */ if (tries != 2) recalibrate(fdd); /* Error, try again... */ } motor_down(fdd); return res;}/* Reads a whole cylinder (both tracks of disk sides) as fast as possible. *//* See fdc_xfer_cylinder for comments. *//* If buffer is NULL, the read data is discarded (may be used to probe). */int fdc_read_cylinder(Fdd *fdd, unsigned cyl, BYTE *buffer){ int res; if (fdd->dp->cmos_type == 0) return FDC_ERROR; /* Drive not available */ /* TODO: Place a timeout for Busy check */ while (busy); /* Wait while the floppy driver is already busy: BUSY WAIT! */ busy = 1; res = fdc_xfer_cylinder(fdd, cyl, FDC_READ); if ((res == FDC_OK) && buffer) fd32_memcpy_from_lowmem(buffer, dma_sel, 0, 512 * fdd->fmt->sec_per_trk * 2); busy = 0; return res;}/* Writes a whole cylinder (both tracks of disk sides) as fast as possible. *//* See fdc_read_cylinder for comments. */int fdc_write_cylinder(Fdd *fdd, unsigned cyl, const BYTE *buffer){ int res; if (fdd->dp->cmos_type == 0) return FDC_ERROR; /* Drive not available */ /* TODO: Place a timeout for Busy check */ while (busy); /* Wait while the floppy driver is already busy: BUSY WAIT! */ busy = 1; fd32_memcpy_to_lowmem(dma_sel, 0, buffer, 512 * fdd->fmt->sec_per_trk * 2); res = fdc_xfer_cylinder(fdd, cyl, FDC_WRITE); busy = 0; return res;}/* Ckecks for the specified disk format, by reading the last sector of the *//* last track of the last side of the specified format. *//* Returns zero if format is supported, or a negative value if not. */static int probe_format(Fdd *fdd, unsigned format){ Chs chs = { 0, 0, 0 }; int res; fdd->fmt = &floppy_formats[format]; chs.s = fdd->fmt->sec_per_trk; res = fdc_read(fdd, &chs, NULL, 1); LOG_PRINTF(("[FDC] probe_format: fdc_read returned %i\n", res)); if (res < 0) return res; LOG_PRINTF(("%s format detected\n", fdd->fmt->name)); return FDC_OK;}/* Checks disk geometry. Call this after any disk change. *//* Returns 0 on success. */int fdc_log_disk(Fdd *fdd){ unsigned k; if (fdd->dp->cmos_type == 0) return FDC_ERROR; /* Drive not available */ fdd->fmt = &floppy_formats[fdd->dp->native_fmt]; reset_fdc(fdd->fdc); reset_drive(fdd); /* If changeline is active, no disk is in drive */ motor_on(fdd); if (fd32_inb(fdd->fdc->base_port + FDC_DIR) & 0x80) { LOG_PRINTF(("[FDC] fdc_log_disk: no disk in drive\n")); motor_down(fdd); return FDC_NODISK; } fdd->flags &= ~DF_CHANGED; for (k = 0; k < 8; k++) if (probe_format(fdd, fdd->dp->detect[k]) == 0) { /* Finetune the probed format with boot sector informations */ int res = floppy_bootsector(fdd, floppy_formats, 32); if (res >= 0) fdd->fmt = &floppy_formats[res]; return FDC_OK; } motor_down(fdd); fdd->flags |= DF_CHANGED; /* Must log the disk again the next time */ return FDC_ERROR; /* If we arrive here, the autodetection failed */}/* Initializes a drive to a known state */static int setup_drive(Fdc *fdc, unsigned drive, unsigned cmos_type){ fdc->drive[drive].fdc = fdc; fdc->drive[drive].dp = &default_drive_params[0]; /* No need to initialize fdc->drive[drive].fmt */ fdc->drive[drive].number = drive; fdc->drive[drive].flags = 0; fdc->drive[drive].track = 0; fdc->drive[drive].spin_down = -1; if ((cmos_type > 0) && (cmos_type <= 6)) { fd32_message("[FLOPPY] Drive %u set to %s\n", drive, default_drive_params[cmos_type].name); fdc->drive[drive].dp = &default_drive_params[cmos_type]; fdc->drive[drive].flags = DF_CHANGED; } return FDC_OK;}#endif/* Initializes the low-level driver *///int fdc_setup(FdcSetupCallback *setup_cb)int fdc_setup(void){ unsigned k; unsigned cmos_drive0; unsigned cmos_drive1; int res; //WORD dma_seg, dma_off; /* Setup IRQ and DMA */ /* TODO: Provide a way to save the old IRQ6 handler */ //fd32_irq_bind(6, irq6); LOG_PRINTF(("IRQ6 handler installed\n")); /* TODO: Find a decent size for the DMA buffer */ //dma_sel = fd32_dmamem_get(512 * 18 * 2, &dma_seg, &dma_off); //if (dma_sel == 0) return FDC_ERROR; /* Unable to allocate DMA buffer */ //dma_addr = ((DWORD) dma_seg << 4) + (DWORD) dma_off; //LOG_PRINTF(("DMA buffer allocated at physical address %08lxh\n", dma_addr)); /* Reset primary controller */ pri_fdc.base_port = FDC_BPRI; printk("bef reset fdc\n"); reset_fdc(&pri_fdc); sendbyte(pri_fdc.base_port, CMD_VERSION); res = getbyte(pri_fdc.base_port); //LOG_PRINTF(("Byte got from CMD_VERSION: %x\n", res)); printk("Byte got from CMD_VERSION: %x\n", res); asm("int $0x25\n\t"::); // check irq 6 switch (res) { case 0x80: fd32_message("[FLOPPY] NEC765 FDC found on base port %x\n", pri_fdc.base_port); break; case 0x90: fd32_message("[FLOPPY] Enhanced FDC found on base port %x\n", pri_fdc.base_port); break; default : fd32_message("[FLOPPY] FDC not found on base port %x\n", pri_fdc.base_port); } #ifdef MYFDC /* Read floppy drives types from CMOS memory (up to two drives). */ /* They are supposed to belong to the primary FDC. */ fd32_outb(0x70, 0x10); k = fd32_inb(0x71); cmos_drive0 = k >> 4; cmos_drive1 = k & 0x0F; setup_drive(&pri_fdc, 0, cmos_drive0); setup_drive(&pri_fdc, 1, cmos_drive1); for (res = FDC_OK, k = 0; k < MAXDRIVES; k++) if (pri_fdc.drive[k].dp->cmos_type) if (setup_cb(&pri_fdc.drive[k]) < 0) res = -1; #ifdef HAS2FDCS setup_drive(&sec_fdc, 0, 0); setup_drive(&sec_fdc, 1, 0); sec_fdc.base_port = FDC_BSEC; reset_fdc(&sec_fdc); for (k = 0; k < MAXDRIVES; k++) if (setup_cb(&sec_fdc.drive[k]) < 0) res = -1; #endif #endif return res;}#ifdef MYFDC /* Frees low-level driver resources */void fdc_dispose(void){ /* TODO: How to restore old handler? */// fd32_irq_bind(6, &old_irq6);// LOG_PRINTF(("IRQ6 handler uninstalled\n")); /* TODO: Find a decent size for the DMA buffer */ fd32_dmamem_free(dma_sel, 512 * 18 * 2); LOG_PRINTF(("DMA buffer freed\n")); fd32_outb(pri_fdc.base_port + FDC_DOR, 0x0C); /* Stop motor forcefully */}#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -