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

📄 oofdc.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 3 页
字号:
	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::StartIO(uint8_t unit){  DiskUnit& du = GetUnit(unit);    uint8_t hd, sec, cyl;  uint32_t secsPerCyl;    assert(du.curReq);    DiskIoReq* ioReq = du.curReq->ioReq;    #ifdef FDCDEBUG  Diag::printf("FDC::StartIO(%d): enter. status=%d req = %x, cmd == %s)\n",	       unit, (int) du.ioState, du.curReq, du.curReq->cmdName());#endif    if (!du.attached)    Diag::fatal(0,"Attempt to access detached/absent unit %s\n",		du.Name());  for (;;) {    /* If we are actually going to do some work, configure the     * controller appropriately:     */    switch (du.ioState) {    case IosReady:    case IosNeedRecal:    case IosRecalDone:    case IosSeekDone:      ConfigureFDC();		/* set up for I/O */      /* Activate the drive control pins: */      dor &= ~3;      dor |= unit;      outb(NECREG::DOR, dor);      Stall(100);    }        switch (du.ioState) {    case IosSpunDown:    case IosSpinUpWait:#ifdef FDCDEBUG      Diag::printf("FDC::startCurrentOp(): still spinning up\n");#endif      /* nothing to do at the moment */      return;    case IosSpinDownWait:      du.timer.Cancel();        case IosReady:      if (!du.curReq) {	du.ioState = IosSpinDownWait;	du.timer.SleepFor(MOTOR_SHUT_WAIT);	return;      }          case IosNeedRecal:    case IosRecalWait:    case IosRecalDone:    case IosSeekWait:    case IosSeekDone:    case IosReadWait:    case IosReadDone:    case IosWriteWait:    case IosWriteDone:    case IosFormatWait:    case IosFormatDone:    }  }    char cmdstr[9];		/* command string to send */  char *cmdbyte = cmdstr;    /* Media is present and spinning.  If not calibrated, do so: */  if (!du.calibrated) {#ifdef FDCDEBUG    Diag::printf("FDC::startCurrentOp(): Recalibrate\n");#endif	/* recall the floppy arm to track 0: */        lastCmd = CmdRecal;    *cmdbyte++ = NECCMD::RECALIBRATE;    *cmdbyte++ = unit;    goto sendcmd;  }    /* 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 = start;  cyl = sec / secsPerCyl;  sec -= (cyl * secsPerCyl);  hd = sec/curParams->nSec;  sec -= hd * curParams->nSec;  #ifdef FDCDEBUG2  Diag::printf("FDC::startCurrentOp(): start %d nsec %d "	       "[cyl %d hd %d sec %d]\n",	       start, nsec, cyl, hd, sec);#endif    /* if necessary, seek to the appropriate cylinder.  It appears   * that if the seek does not actually move the arm, the head value   * does not get updated, so only check the cylinder, not the head.   */  if (du.curcyl != cyl ) {#ifdef FDCDEBUG    Diag::printf("FDC::startCurrentOp(): Seek\n");#endif    lastCmd = CmdSeek;    *cmdbyte++ = NECCMD::SEEK;    *cmdbyte++ = (hd<<2)|unit;    *cmdbyte++ = cyl;    goto sendcmd;  } else {	/* Seek has completed, so any pending errors should be	 * canceled:	 */    nError = 0;  }  #if 0  /* If the operation was merely a seek command, we should not get   * 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]);}#if 0class FDC : public DiskCtrlr {  enum {    NUM_UNITS = 2,		/* floppy controller has up to 4 */				/* units, but for now support only 2 */  };  #if 0  enum UnitCommands {    CmdNone,    CmdReset,    CmdRecal,    CmdSeek,    CmdRead,    CmdWrite,  };#endif    DiskUnit units[NUM_UNITS];	        /* Because the floppy has removable media, the media parameters       * can change, and may change from use to use.       */  FloppyInfo *unitParams[4];	/* Current media parameters */  FloppyInfo *curParams;	/* How FDC is currently programmed */    DiskUnit& GetUnit(uint8_t whichUnit);  void StartRequest(uint8_t unit);        /* COMMANDS */    void Reset();      /* CONTROLLER IO */    uint8_t dor;  uint32_t secsToXfer;		/* used in read/write operations */    int nresults;			/* number of results from last operation */  uint8_t results[8];		/* actual result values */  void OutFDC(uint8_t);  int GetResults();    void ConfigureFDC();        /* INTERRUPT HANDLING */    virtual void OnEvent(Event&);    void ResetIntr(FixRegs *);  void SeekIntr(FixRegs *);  void RwIntr(FixRegs *);      /* MOTOR CONTROL */    enum {    MOTOR_SHUT_WAIT = 10000,    MOTOR_START_WAIT = 40,  };    virtual void Spinup(uint8_t unit);  virtual void Spindown(uint8_t unit);  virtual bool Attach(uint8_t unit); /* return true if succeeded */  virtual void Detach(uint8_t unit);  void OnIdle(uint8_t unit);  public:  FDC(AutoConf::ID id);    virtual void Probe();  virtual void Attach();  virtual const char* UnitName(uint8_t unit);  uint32_t GetCylinder(uint8_t unit, uint32_t sec);};FDC TheFDC(AutoConf::FDCA);static Timer timer(&TheFDC);DiskUnit& FDC::GetUnit(uint8_t whichUnit){  assert(whichUnit < NUM_UNITS);  return units[whichUnit];}FDC::FDC(AutoConf::ID id): DiskCtrlr(id, NUM_UNITS, McMem1M){  int i;  dor = 0;    for(i = 0; i < NUM_UNITS; i++) {    units[i].unitNo = i;    units[i].ctrlr = this;  }}voidFDC::Reset(){#ifdef FDCDEBUG  Diag::printf("FDC::reset(): enter\n");#endif    ctrlrStatus = CtrlrBusy;    IDT::Disable();		/* CRITICAL REGION */    lastCmd = CmdReset;    dor = 0;			/* Reset FDC, Motors off */    outb(NECREG::DOR, dor);  Stall(100);    dor = DOR::Reset|DOR::DmaGate; /* re-enable the part */  outb(NECREG::DOR, dor);  IDT::Enable();		/* END CRITICAL REGION */}void FDC::Probe(){  /* FIX: This may or may not actually be present.  A real probe   * routine is called for!   */  present = true;}void FDC::Attach(){  int i;    ctrlrStatus = CtrlrIdle;  IDT::RegisterHandler(IntFloppy, this);/*  IDT::EnableIRQ(IRQ6); */        /* For the moment, we do not support more than 2 floppy drives.       * Someday I will have to fix this.       */    for (i = 0; i < NUM_UNITS; i++) {    uint32_t type = CMOS::fdType(i);    DiskUnit& du = GetUnit(i);    du.type = type;    if (du.type) {      du.unitState = DiskCtrlr::UsPresent;      du.isRemovable = true;      /* Floppies only automount if they are the boot drive. */      du.bootAttach = (i == SysConfig.boot.drive) ? true : false;      du.multiFormat = true;    }        Diag::printf("%s: %s\n", UnitName(i), FloppyParams[type].name);  }    Reset();    attached = true;  Diag::printf("FDC::init() complete\n");}/* FIX: a lot of this strategy routine is very disk-centric.  When we * get around to tapes we need to do something about this. *//* The generic controller logic has committed us to doing something, * and has properly initialized the request block.  Start the actual * operation.  Controller is already marked "busy". */void FDC::StartRequest(){  assert(unit < NUM_UNITS);    uint8_t hd, sec, cyl;  uint32_t secsPerCyl;    assert(req);  DiskIoReq* ioReq = req->ioReq;      DiskUnit& du = GetUnit(unit);  #ifdef FDCDEBUG  Diag::printf("FDC::startRequest(): enter. unit=%d status=%d req = %x, cmd == %s)\n",	       unit, (int) du.status, req, req->cmdName());#endif    if (!du.unitState < DiskCtrlr::UsAttached)    Diag::fatal(0,"Attempt to access detached/absent unit %s\n", UnitName(unit));#if 0  if (!du.mediaPresent)    Diag::printf("No media in drive %s\n", UnitName(unit));#endif  if (du.status == DiskUnit::UnitIdle) {      /* We are racing with the disk motor logic to cancel the       * spindown. If we win, we end up in the ready state.  If not,       * the motor logic will place the drive in the Offline state.       */      IDT::Disable();      if (du.spinning)	du.status = DiskUnit::UnitActive;      else	Spinup(unit);      IDT::Enable();#ifdef FDCMOTOR      Diag::printf("FDC::startCurrentOp(): Unit %d Spindown canceled\n",		   unit);#endif  }  /* At this point, drive is either spinning up or we are ready to   * initiate.   */  /* OK if unit is still spinning up. */  if (du.status == DiskUnit::UnitSpinUp) {#ifdef FDCDEBUG    Diag::printf("FDC::startCurrentOp(): still spinning up\n");#endif    return;  }    ConfigureFDC();		/* set up for I/O */        /* Activate the drive control pins: */  dor &= ~3;  dor |= unit;  outb(NECREG::DOR, dor);  Stall(100);    char cmdstr[9];		/* command string to send */  char *cmdbyte = cmdstr;    /* Media is present and spinning.  If not calibrated, do so: */  if (!du.calibrated) {#ifdef FDCDEBUG    Diag::printf("FDC::startCurrentOp(): Recalibrate\n");#endif	/* recall the floppy arm to track 0: */        lastCmd = CmdRecal;    *cmdbyte++ = NECCMD::RECALIBRATE;    *cmdbyte++ = unit;    goto sendcmd;  }    /* 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 = start;  cyl = sec / secsPerCyl;  sec -= (cyl * secsPerCyl);  hd = sec/curParams->nSec;  sec -= hd * curParams->nSec;  #ifdef FDCDEBUG2  Diag::printf("FDC::startCurrentOp(): start %d nsec %d "	       "[cyl %d hd %d sec %d]\n",	       start, nsec, cyl, hd, sec);#endif    /* if necessary, seek to the appropriate cylinder.  It appears   * that if the seek does not actually move the arm, the head value   * does not get updated, so only check the cylinder, not the head.   */  if (du.curcyl != cyl ) {#ifdef FDCDEBUG    Diag::printf("FDC::startCurrentOp(): Seek\n");#endif    lastCmd = CmdSeek;    *cmdbyte++ = NECCMD::SEEK;    *cmdbyte++ = (hd<<2)|unit;    *cmdbyte++ = cyl;    goto sendcmd;  } else {	/* Seek has completed, so any pending errors should be	 * canceled:	 */    nError = 0;  }  #if 0  /* If the operation was merely a seek command, we should not get

⌨️ 快捷键说明

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