⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 oofdc.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
   * this far before the interrupt handler declares it done.   */  assert (ioReq->cmd != DiskIoReq::OpSeek);#endif    /* START THE I/O OPERATION: */      /* Compute number of sectors to transfer: */  secsToXfer = min(nsec, curParams->nSec - sec);  #ifdef FDCDEBUG  Diag::printf("FDC::startCurrentOp(): xfer %d secs\n", secsToXfer);#endif  assert(iokva);    assert (ioReq->cmd == IoReq::OpObjectRead ||	  ioReq->cmd == IoReq::OpObjectWrite);    {    int iswrite = (ioReq->cmd == IoReq::OpObjectWrite);        dmakva = DMA::setup(DMAC::FLOPPY, iokva, secsToXfer *			EROS_SECTOR_SIZE, iswrite ? DMA::WRITE : DMA::READ);        lastCmd = iswrite ? CmdWrite : CmdRead;    *cmdbyte++ = iswrite ? NECCMD::WRITE : NECCMD::READ;    *cmdbyte++ = (hd<<2)|unit;    *cmdbyte++ = cyl;    *cmdbyte++ = hd;    *cmdbyte++ = sec+1;    *cmdbyte++ = 0x2u;		/* 512 byte sector size */    *cmdbyte++ = curParams->nSec; /* sectors per track */    *cmdbyte++ = curParams->fmt_gap; /* sectors per track */    *cmdbyte++ = 0xff;		   /* DTL?? */  }   sendcmd:  int count = cmdbyte - cmdstr;  int i;  for (i = 0; i < count; i++)    OutFDC(cmdstr[i]);}voidFDC::ConfigureFDC(){  assert(unitParams[unit]);  if (curParams == unitParams[unit])    return;    curParams = unitParams[unit];  #ifdef FDCDEBUG2  Diag::printf("Specify drive parameters\n");#endif    OutFDC(NECCMD::SPECIFY);  OutFDC(curParams->spec1);  OutFDC(6);			/* head unload time */  #ifdef FDCDEBUG2  Diag::printf("And data rate\n");#endif    outb(NECREG::DCR, curParams->dataRate & 3);}const char*FDC::UnitName(uint8_t unit){  static char *name = "fdXX\0";  name[2] = ConfigTable[id].name[2];  name[3] = '0' + unit;  return name;}voidFDC::OnEvent(Event& e){  if (e.kind == Event::Interrupt) {    /* Reset is not really an operation. */    if (lastCmd == CmdReset)      ResetIntr(e.fr);    else {      if (!req)	Diag::fatal(0,"Unexpected floppy interrupt\n");        assert(req);        switch(lastCmd) {      case CmdReset:	Diag::fatal(0,"Fielded FDC reset interrupt in wrong place\n");	break;      case CmdRecal:      case CmdSeek:	SeekIntr(e.fr);	break;      case CmdRead:      case CmdWrite:	RwIntr(e.fr);	break;      }      /* if command has completed. call the completion routine: */      if (ioReq->cmd == IoReq::OpDone) {#ifdef FDCDEBUG	Diag::printf("FDC::do_intr(): command complete. cte= 0x%x\n", ioReq->cte);#endif	ctrlrStatus = CtrlrIdle;    	KernThread::SetReady(ioReq->ioThread);      }      else	ctrlrStatus = CtrlrMore;      /* retry the current op */      KernThread::SetReady(Thread::DiskDaemon);    }  }  else {			/* timer went off */#ifdef FDCMOTOR    Diag::printf("FDC::OnTimer(): Motor timer went off\n");#endif      uint8_t u;      for (u = 0; u < NUM_UNITS; u++) {      DiskUnit& du = GetUnit(u);      /* No need to check if unit present.  If not present, cannot be       * in spinup state.  If not present, cannot be spinning.       */          if (du.status == DiskUnit::UnitSpinUp) {	du.spinning = true;	du.calibrated = false;	du.status = DiskUnit::UnitActive;	assert(du.unitPresent);      #ifdef FDCMOTOR	Diag::printf("FDC::OnTimer(): unit %d spun up\n", u);#endif	ctrlrStatus = CtrlrMore;	KernThread::SetReady(Thread::DiskDaemon);      }      else if (du.status == DiskUnit::UnitIdle && du.spinning) {#ifdef FDCMOTOR	Diag::printf("FDC::OnTimer(): unit %d spun down\n", u);#endif	assert(du.unitPresent);	Spindown(u);      }    }#if 0    dor &= ~(DOR::Motor0|DOR::Motor1|DOR::Motor2|DOR::Motor3);      outb(NECREG::DOR, dor);        for (u = 0; u < NUM_UNITS; u++) {      DiskUnit& du = GetUnit(u);      du.status = DiskUnit::Offline;    }    #endif  }}voidFDC::ResetIntr(FixRegs *fr){  int i;  #ifdef FDCDEBUG2  Diag::printf("FDC::reset_intr(): Run a sensei after RESET\n");#endif  for (i = 0; i < NUM_UNITS; i++) {    DiskUnit& du = GetUnit(i);    /* sense the drive status */    OutFDC(NECCMD::SENSEI);    if (GetResults() != 2)      Diag::fatal(0,"Improper results from FDC reset\n");    /* if the unit is present, it is now offline */    if (units[i].unitPresent)      units[i].spinning = false;    /* set floppy parameters to the default for the particular     * media type.     */    unitParams[i] = &FloppyParams[du.type];  }    unit = 0;  curParams = 0;  ctrlrStatus = CtrlrIdle;    KernThread::SetReady(Thread::DiskDaemon);  /*  IDT::ResetPIC(); */    return;}voidFDC::SeekIntr(FixRegs *fr){#ifdef FDCDEBUG  Diag::printf("FDC::seek_intr(): curcmd == %d\n", lastCmd);#endif    OutFDC(NECCMD::SENSEI);    if (GetResults() != 2) {      /* controller is hosed - resetting it should restart the requests. */    Reset();    Diag::fatal(0,"FDC::seek_intr(): Floppy not responding");  }    uint32_t sr0 = results[0];        /* We should have completed the seek: */  if (!(sr0 & SR0::SeekEnd))    nError += 2;        /* We should not have aborted or run off the end of the       * drive. In the event that we did, give it one more try       * because we might be recalibrating a drive with > 80       * cylinders someday:       */    if (sr0 & (SR0::EquipChk | SR0::IC))    nError += 4;    if (nError > MAX_ERROR) {    Diag::fatal(0, "Error count exceeded\n");    req->OnIntrCompletion(IOR::Range);  }    if (nError)    return;      DiskUnit& du = GetUnit(unit);    du.curcyl = results[1];#if 0  du.curhd = (results[0] & 0x4) ? 1 : 0;#endif  #ifdef FDCDEBUG  Diag::printf("Post seek: unit %d curcyl=%d\n", unit, du.curcyl);#endif  if (du.calibrated == false) {    assert(du.curcyl == 0);    du.calibrated = true;  }#if 0  if (ioReq->cmd == DiskIoReq::OpSeek)    req->Completed();#endif}voidFDC::RwIntr(FixRegs *fr){#ifdef FDCDEBUG  Diag::printf("FDC::rw_intr(): curcmd == %d\n", lastCmd);#endif    if (GetResults() != 7) {    /* controller is hosed - resetting it should restart the requests. */    Reset();    Diag::fatal(0,"FDC::rw_intr(): Floppy not responding");  }    uint32_t sr0 = results[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:     */        /* Bounce buffer copy.  Probably shouldn't be done with interrupts     * disabled, but until I rebuild the I/O subsystem this is     * the simplest solution.     */        if (dmakva != iokva)      bcopy(dmakva, iokva, nsec * EROS_SECTOR_SIZE);        nsec -= secsToXfer;    start += secsToXfer;    iokva += (secsToXfer * EROS_SECTOR_SIZE);  }        /* FIX: Seeking is probably panicworthy. */  if (sr0 & (SR0::EquipChk | SR0::SeekEnd | SR0::IC))    Diag::fatal(0,"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))    nError += 2;		/* allow five retries */    if (nError > MAX_ERROR) {    req->OnIntrCompletion(IOR::Range);    return;  }        /* An overrun or going past end of cylinder is a fatal       * problem. Something is wrong with the kernel:       */  if (DMA::get_residue(DMAC::FLOPPY) ||      (sr1 & (SR1::Overrun | SR1::CylEnd)))    Diag::fatal(0,"DMA Overrun by fd%d\n", unit);    if (!nsec) {#ifdef FDCDEBUG    Diag::printf("Op completed\n");#ifdef PARANOID    uint32_t* puint32_t = (Word *) UserMem.CTEtoPage(req->cte);    int i;    for (i = 0; i < 8; i++)      Diag::printf("0x%x ", *pWord++);    Diag::printf("\n");#endif#endif    req->OnIntrCompletion(IOR::OK);    KernThread::SetReady(Thread::DiskDaemon);  }}    /* MOTOR CONTROL *  * An FDC has some number of associated diskettes, each of which has a * motor whose state must unfortunately be modeled. *  * The spin variable has the following values: *  *    1   Motor is spinning *    0   Motor is off *   -1   Motor will be spinning when the timer goes off *  */voidFDC::Spinup(uint8_t unit){  /* Because the spinup timer could go off while we are here, this   * is a critical region:   */  #ifdef FDCMOTOR  Diag::printf("FDC::SpinUp(%d): enter\n", unit);#endif    DiskUnit& du = GetUnit(unit);    assert(du.spinning == false);  #ifdef FDCMOTOR  Diag::printf("FDC::SpinUp(): %s: spinning up\n", UnitName(unit));#endif    du.status = DiskUnit::UnitSpinUp;    dor |= (0x10 << unit);    /* Spin control.  Bet you thought only marketing did that. */  outb(NECREG::DOR, dor);    timer.SleepFor(MOTOR_START_WAIT);}voidFDC::OnIdle(uint8_t unit){#ifdef FDCMOTOR  Diag::printf("FDC::OnIdle(): OnIdle called.\n");#endif  DiskUnit& du = GetUnit(unit);  if (du.unitPresent == false)    Diag::fatal(0, "FDC::OnIdle(): Tried to idle offline unit %d\n", unit);    IDT::Disable();		/* CRITICAL REGION */  if (!timer.active)    timer.SleepFor(MOTOR_SHUT_WAIT);  du.status = DiskUnit::UnitIdle;  IDT::Enable();		/* END CRITICAL REGION */}voidFDC::Spindown(uint8_t unit){  DiskUnit& du = GetUnit(unit);  dor &= ~(DOR::Motor0 << unit);  outb(NECREG::DOR, dor);  du.spinning = false;}/* Since floppies are not partitionable, this is fairly simple. */boolFDC::Attach(uint8_t unit){  DiskUnit& du = GetUnit(unit);  /* Attaching media that are not present should succeed trivially. */  if (!du.unitPresent) {    Diag::printf("unit %d is not present\n", unit);    return true;  }  if (!du.mediaPresent) {    Diag::printf("unit %d - no media\n", unit);    return true;  }  /* do not attach redundantly... */  if (du.attached) {    Diag::printf("unit %d is attached\n", unit);    return true;  }  /* Force a read of sector 0, whose side effect will be to do   * autoformat detection:   */    Diag::printf("Reading raw page 0 from unit %d\n", du.unitNo);  CoreObject* bootSector = du.ReadRawPage(0);  if (!bootSector)    return false;  UserMem.releasePage(bootSector);  Diag::printf("Released raw page 0 from unit %d\n", du.unitNo);  DiskVolume* pVol = DiskVolume::AllocVolume();  Diag::printf("DiskVolume structure allocated\n");  pVol->diskUnit = &units[unit];  pVol->start = 0;  pVol->hostPartition = 0;  pVol->isErosVolume = false;	/* until we know otherwise */  if (unit == SysConfig.boot.drive)    pVol->isBootVolume = true;  pVol->Announce();  du.attached = true;  return true;}voidFDC::Detach(uint8_t unit){  Diag::fatal(0, "FDC::detach() not implemented yet\n");}uint32_tFDC::GetCylinder(uint8_t unit, uint32_t sec){  uint32_t secsPerCyl = unitParams[unit]->nHd * unitParams[unit]->nSec;  return sec/secsPerCyl;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -