📄 floppyctrlr.cxx
字号:
uint32_t cyl = sec / mediaInfo->secsPerCyl; sec -= (cyl * mediaInfo->secsPerCyl); uint32_t hd = sec / mediaInfo->secsPerTrack; sec -= (cyl * mediaInfo->secsPerTrack); assert((ioCount % EROS_SECTOR_SIZE) == 0); /* move to cylinder of request */ FdSeek(u, cyl, hd); uint32_t xfer = ioCount; uint32_t topSec = sec + xfer / EROS_SECTOR_SIZE; if (topSec > mediaInfo->secsPerTrack) topSec = mediaInfo->secsPerTrack; xfer = (topSec - sec) * EROS_SECTOR_SIZE; /* FIX: bad sectors may require a change of plans here. */ if (!started) ior->CommitUnitRequest(uior); uint32_t xferSecs = 0; switch(ior->cmd) { case IOCMD::Read: { /* We hand it how much we want to move, it hands back how * much it WILL move: */ xfer = DMA::read(FloppyDmaChan, ioAddr, xfer); assert ((xfer % EROS_SECTOR_SIZE) == 0); /* can't happen :-) */ xferSecs = xfer / EROS_SECTOR_SIZE; FdReadWrite(false, u, cyl, hd, sec, xferSecs); DMA::flush(FloppyDmaChan); /* if unit or dma error, fail the request with error code */ break; } case IOCMD::Write: { /* We hand it how much we want to move, it hands back how * much it WILL move: */ xfer = DMA::write(FloppyDmaChan, ioAddr, xfer); assert ((xfer % EROS_SECTOR_SIZE) == 0); /* can't happen :-) */ xferSecs = xfer / EROS_SECTOR_SIZE; FdReadWrite(true, u, cyl, hd, sec, xferSecs); DMA::flush(FloppyDmaChan); /* if unit or dma error, fail the request with error code */ break; } case IOCMD::None: /* This should not happen! */ break; case IOCMD::FormatTrack: /* temporary placeholder to keep compiler happy */ assert(false); break; } ioCount -= xfer; ioAddr += xfer; ioSec += xferSecs; } ior->FinishUnitRequest(uior, IOR::OK); unit[u]->RemoveRequest(uior); } } printf("FloppyCtrlr going idle\n"); WakeUpAtTick(wakeTime); SleepOn(IdleQ, Thread::Stall); Yield(true); } }voidProbe(struct AutoConf* ac){ /* Machine::WireInterrupt(IntFloppy, ... ); */ ac->present = false;}static void StartCtrlr(uint32_t /* unit */){ IdleQ.WakeAll();}static voidAttach(struct AutoConf* /* ac */){ TheFloppyCtrlr.unit[0] = new DiskUnit("fda0", StartCtrlr, 0); TheFloppyCtrlr.unit[0]->bootMount = false; /* assume first drive is a 1.44 */ TheFloppyCtrlr.unit[0]->mediaInfo = &MediaParams[4]; for(int i= 1; i <=FloppyCtrlr::NUNITS;i++) TheFloppyCtrlr.unit[i] = 0; /* assume the other drives do */ /* not exist */ TheFloppyCtrlr.Wakeup();}void FloppyCtrlr::FdSeek(uint32_t u, uint32_t cyl, uint32_t hd){ for(int tries = 0; tries < 2; tries++) { /* Activate the drive control pins: */ dor &= ~3; dor |= u; outb(NECREG::DOR, dor); Delay(1); /* 1 ms settling time */ OutFloppyCtrlr(NECCMD::SEEK); OutFloppyCtrlr((hd<<2)|u); OutFloppyCtrlr(cyl); WakeUpIn(500); /* half-second timeout on floppy seeks */#if 0 SleepOn(IDT::GetInterruptQueue(IntFloppy), Thread::Stall);#endif Yield(); /* verify correct track */ OutFloppyCtrlr(NECCMD::SENSEI); if (GetResults() != 2) { /* controller is hosed - resetting it should restart the requests. */ Reset(); fatal("FDC::seek_intr(): Floppy not responding"); return; } /* if failed, seek again... * update current location info */ uint32_t sr0 = results[0]; if ((sr0 & (SR0::EquipChk | SR0::IC | SR0::SeekEnd)) == SR0::SeekEnd) { /* Completed successfully */ unit[u]->curCyl = results[1]; /* update the unit structure */ return; /* exit, we suceeded */ }#if 0 else { /* recalibrate. If this was the first try, we will try again. */ }#endif } /* if we made it here, we could not find the data */}void FloppyCtrlr::FdReadWrite(bool iswrite, uint32_t u, uint32_t cyl, uint32_t hd, uint32_t sec, uint32_t /* xferSecs */){ bool done = true; int tries= 0; do { done = true; /* Activate the drive control pins: */ dor &= ~3; dor |= u; outb(NECREG::DOR, dor); Delay(1); /* we would simply want to sleep here, right? */ OutFloppyCtrlr(iswrite? NECCMD::WRITE : NECCMD::READ); OutFloppyCtrlr((hd<<2)|u); OutFloppyCtrlr(cyl); OutFloppyCtrlr(hd); OutFloppyCtrlr(sec+1); OutFloppyCtrlr(0x2u); /* 512 byte sector size */ OutFloppyCtrlr(unit[u]->mediaInfo->secsPerTrack); /* sectors per track */ OutFloppyCtrlr(unit[u]->mediaInfo->fmt_gap); OutFloppyCtrlr(0xff); /* DTL?? */ /* check to see if it worked */ if (GetResults() != 7) { /* controller is hosed - resetting it should restart the requests. */ Reset(); fatal("FDC::rw_intr(): Floppy not responding"); /* exit function */ return; } uint32_t sr0 = results[0];#if 0 /* We should not have interrupted or run off the end of the * drive. We should not have needed to seek. */ if ((sr0 & SR0::IC) == 0) { /* We now need to decide if we are done with the operation or * not. If the operation went over a track boundary, we need * to hack track, head, sector, and nsec and start over: */ unit[u]->mediaInfo->secsPerTrack -= secsToXfer; if (unit[u]->mediaInfo->secsPerTrack) { du.start += secsToXfer; iokva += (secsToXfer * EROS_SECTOR_SIZE); } }#endif /* FIX: Seeking is probably panicworthy. */ if (sr0 & (SR0::EquipChk | SR0::SeekEnd | SR0::IC)) fatal("FDC: Unexpected seek\n"); uint8_t sr1 = results[1]; /* A CRC error just means a bad sector. We should retry: */ if (sr1 & (SR1::BadCrc | SR1::NoData)) { done = false; }#if 0 /* An overrun or going past end of cylinder is (for the moment) * a fatal problem. Something is wrong with the kernel: */ if (DMA::get_residue(DMAC::FLOPPY) || (sr1 & (SR1::Overrun | SR1::CylEnd))) fatal(0,"DMA Overrun by fd%d\n", unit);#endif tries++; } while((tries < READ_WRITE_TRIES) && !done);} /* DMAC is commented out, since I cannot find it. *//* void FloppyCtrlr::FdWrite(uint32_t /* u */, uint32_t /* cyl */, uint32_t /* hd */, * uint32_t /* sec */, uint32_t /* xferSecs */) { * } */void FloppyCtrlr::OutFloppyCtrlr(uint8_t b){#ifdef FDCIODEBUG printf("FDC::OutFDC(%x)\n", b);#endif uint8_t r = 0; for (int i = 0; i < 10000; i++) { r = inb(NECREG::STATUS); r &= (STATUS::Master | STATUS::ReqRead); if (r == STATUS::Master) { outb(NECREG::DATA, b); return; } } fatal("FDC::OutFDC() failed. Status Reg = %x\n", r);}int FloppyCtrlr::GetResults(){ int i, n = 0; for (i = 0 ; i < 1000 ; i++) { uint8_t r = inb(NECREG::STATUS); r &= (STATUS::Master|STATUS::ReqRead|STATUS::CmdBusy); if (r == STATUS::Master) { /* not busy, ready for commands */ return n; } if (r == (STATUS::Master|STATUS::ReqRead|STATUS::CmdBusy)) { if (n >= 8) { fatal("FDC::GetResults(): too many answers\n"); break; } results[n] = inb(NECREG::DATA);#ifdef FDCIODEBUG printf("results[%d] = 0x%x\n", n, results[n]);#endif n++; } } fatal("FDC::getStatus(): couldn't get status\n"); return -1;}void FloppyCtrlr::Reset(/* unit */){ fatal("FloppyCtrlr::Reset(): Drive in unknown state, reset");} /* reset the drive. *//* MOTOR (MIS)MANAGEMENT: */void FloppyCtrlr::StartMotor(uint32_t unit){ printf("Time to start motor, unit %d\n", unit);}void FloppyCtrlr::StopMotor(uint32_t unit){ printf("Time to stop motor, unit %d\n", unit);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -