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

📄 ofdc.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
   * this is that the token runs just ahead of the unit index in   * DiskCtrlr::StartIO().    */  if (!du.GetNextRequest()) {    curUnit ++;    if (curUnit == nUnits)      curUnit -= nUnits;    return false;  }    /* If we have something to do, we can start it if we have the token   * or if we need to start the motor.   */  if (unit == curUnit)    return true;  if (du.ioState == DiskCtrlr::IosSpunDown)    return true;  return false;}voidFDC::OnKeyCall(){  Diag::fatal(0, "FDC::OnKeyCall called\n");}voidFDC::OnKeyCall(uint8_t unit){  Diag::fatal(0, "FDC::OnKeyCall(%d) called\n", unit);}DiskUnit& FDC::GetUnit(uint8_t whichUnit){  assert(whichUnit < NUM_UNITS);  return *(units[whichUnit]);}voidFDC::OutFDC(uint8_t b){#ifdef FDCIODEBUG  Diag::printf("FDC::OutFDC(%x)\n", b);#endif  uint8_t r;  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;    }  }    Diag::fatal(0,"FDC::OutFDC() failed. Status Reg = %x\n", r);}intFDC::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) {	Diag::fatal(0,"FDC::GetResults(): too many answers\n");	break;      }      results[n] = inb(NECREG::DATA);#ifdef FDCIODEBUG      Diag::printf("results[%d] = 0x%x\n", n, results[n]);#endif      n++;    }  }    Diag::fatal(0,"FDC::getStatus(): couldn't get status\n");  return -1;}void FDC::StartMount(uint8_t unit){  Diag::fatal(0, "FDC::StartMount(unit) not yet implemented\n");}void FDC::StartIO(uint8_t unit){  DiskUnit& du = GetUnit(unit);  bool iswrite = true;    uint8_t hd, sec, cyl;  uint32_t secsPerCyl;    UnitIoReq* req = du.GetNextRequest();  DiskIoReq* ioReq = req->ioReq;    #ifdef FDCDEBUG  Diag::printf("FDC::StartIO(%d): enter. status=%d req = %x, cmd == %s)\n",	       unit, (int) du.ioState, req, req->cmdName());#endif    if (!du.IsAttached())    Diag::fatal(0,"Attempt to access detached/absent unit %s\n",		du.Name());  /* compute the head, cyl, and sec for this operation.  We need   * to recompute this in every pass because the last operation   * may have been a partially complete I/O operation that hit the   * end of a cylinder boundary.   */    secsPerCyl = curParams->nHd * curParams->nSec;  sec = du.start;  cyl = sec / secsPerCyl;  sec -= (cyl * secsPerCyl);  hd = sec/curParams->nSec;  sec -= hd * curParams->nSec;  /* Compute number of sectors to transfer: */  uint32_t secsToXfer = min(du.nsec, curParams->nSec - sec);    for (;;) {    /* If we are actually going to start an I/O action, configure the     * controller appropriately:     */    switch (du.ioState) {    case IosStartRecal:    case IosStartSense:    case IosStartSeek:    case IosStartRead:    case IosStartWrite:#if 0    case IosStartFormat:#endif      ConfigureFDC(unit);	/* set up for I/O */      /* Activate the drive control pins: */      dor &= ~3;      dor |= unit;      outb(NECREG::DOR, dor);      Stall(100);    }        switch (du.ioState) {    case IosRecalWait:    case IosSenseWait:    case IosSeekWait:    case IosReadWait:    case IosWriteWait:#if 0    case IosFormatWait:#endif    case IosSpinUpWait:      return;    case IosSpinDownWait:      /* If we are starting an operation, and the drive is waiting to       * spin down, cancel the spindown timer and hope we get there       * before the spindown happens.  From here, we'll either end up       * in the IosReady state or the        */      du.timer.Cancel();      /* If we beat the spindown, we still know the cylinder position,       * so go ahead and do the seek.       */      if (du.ioState == IosSpinDownWait)	du.ioState = IosStartIO;      break;        case IosSpunDown:      du.ioState = IosSpinUpWait;      dor |= (0x10 << unit);      outb(NECREG::DOR, dor);        du.timer.SleepFor(MOTOR_START_WAIT);      return;          case IosReady:      if (!req) {	du.ioState = IosSpinDownWait;	du.timer.SleepFor(MOTOR_SHUT_WAIT);	return;      }          case IosStartIO:      if (du.curCyl != cyl) {	du.ioState = IosSeekWait;      }      else {	switch(ioReq->cmd) {	case IoReq::OpObjectRead:	case IoReq::OpFormatDetect:	  du.ioState = IosStartRead;	  break;	case IoReq::OpObjectWrite:	  du.ioState = IosStartWrite;	  break;#if 0	case IoReq::OpFormatTrack:	  du.ioState = IosStartFormat;	  break;#endif	}      }      break;    case IosStartRecal:      OutFDC(NECCMD::RECALIBRATE);      OutFDC(unit);      break;    case IosStartSense:      OutFDC(NECCMD::READID);      OutFDC((hd<<2)|unit);      du.ioState = IosSenseWait;      break;          case IosStartSeek:      OutFDC(NECCMD::SEEK);      OutFDC((hd<<2)|unit);      OutFDC(cyl);      du.ioState = IosSeekWait;      break;    case IosStartRead:      iswrite = false;      /* FALL THROUGH */    case IosStartWrite:      {	dmakva = DMA::setup(DMAC::FLOPPY, iokva, secsToXfer *			    EROS_SECTOR_SIZE, iswrite ? DMA::WRITE : DMA::READ);    	OutFDC(iswrite ? NECCMD::WRITE : NECCMD::READ);	OutFDC((hd<<2)|unit);	OutFDC(cyl);	OutFDC(hd);	OutFDC(sec+1);	OutFDC(0x2u);		/* 512 byte sector size */	OutFDC(curParams->nSec); /* sectors per track */	OutFDC(curParams->fmt_gap);	OutFDC(0xff);		/* DTL?? */      }#if 0    case IosStartFormat:#endif    case IosSenseDone:      {	if (GetResults() != 7) {	  /* controller is hosed - resetting it should restart the requests. */	  Reset();	  Diag::fatal(0,"FDC::rw_intr(): Floppy not responding");	}  	du.ioState = IosStartIO;		Word sr0 = results[0];	if ((sr0 & SR0::IC) == 0) {	  du.nError += 4;	  du.ioState = IosStartRecal;	}	break;      }    case IosRecalDone:    case IosSeekDone:      {	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");	}  	Word sr0 = results[0];  	if ((sr0 & (SR0::EquipChk | SR0::IC | SR0::SeekEnd)) == SR0::SeekEnd) {	  /* Completed successfully */	  du.curCyl = results[1];	  du.ioState = IosStartIO;	}	else {	  /* Seek did not complete, so bump the error count for that: */	  du.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))	    du.nError += 4;	  du.ioState = IosStartSeek;	}      	break;          }    case IosReadDone:    case IosWriteDone:      {	if (GetResults() != 7) {	  /* controller is hosed - resetting it should restart the requests. */	  Reset();	  Diag::fatal(0,"FDC::rw_intr(): Floppy not responding");	}  	/* Assume we completed this operation until we determine otherwise: */	du.ioState = IosCompleted;      	Word 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:	   */		  du.nsec -= secsToXfer;	  if (du.nsec) {	    du.ioState = IosStartIO;	    du.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)) {	  du.nError += 2;	/* allow five retries */	  du.ioState = IosStartIO;	}  	/* 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)))	  Diag::fatal(0,"DMA Overrun by fd%d\n", unit);        }#if 0    case IosFormatDone:#endif    case IosXferData:#if 0      /* 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);#endif        case IosError:    case IosCompleted:      break;    }    if (du.nError > MAX_ERROR)      du.ioState = IosError;  }}voidFDC::ConfigureFDC(uint8_t unit){  DiskUnit& du = GetUnit(unit);    if (curParams == &FloppyParams[du.format])    return;    curParams = &FloppyParams[du.format];  #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);}

⌨️ 快捷键说明

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