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

📄 ide_ide.cxx

📁 C++ 编写的EROS RTOS
💻 CXX
📖 第 1 页 / 共 2 页
字号:
    req->req_start += nsec;  req->req_ioaddr += (EROS_SECTOR_SIZE * nsec);  req->req_nsec -= nsec;  req->nError = 0;  req->nsec -= nsec;#ifdef IDE_DEBUG  MsgLog::printf("Rd Residual at 0x%08x: %d sectors at %d nsec %d\n",		 req->req_ioaddr, req->req_nsec, req->req_start,		 req->nsec); #endif  return (req->req_nsec) ? false : true;}boolide_hwif::WriteIntr(){  uint8_t status = Get8(IDE_STATUS);  if (!OK_STAT(status,DRIVE_READY,BAD_W_STAT)) {    drive[cur_drive].Error("write intr", status);    return true;  }  Request *req = group->curReq;    uint32_t nsec = req->nsec;    req->req_start += nsec;  req->req_ioaddr += (EROS_SECTOR_SIZE * nsec);  req->req_nsec -= nsec;  req->nError = 0;  req->nsec -= nsec;#ifdef IDE_DEBUG  MsgLog::printf("Wr Residual at 0x%08x: %d sectors at %d nsec %d\n",		 req->req_ioaddr, req->req_nsec, req->req_start,		 req->nsec); #endif  /* If the drive is ready and there is more to do, ship off the next   * sector, else we will have to reschedule it later.   */  if (req->req_nsec && (status & DRQ_STAT)) {    assert( status & DRQ_STAT );    drive[cur_drive].OutputData((void*) req->req_ioaddr,				EROS_SECTOR_SIZE >> 2);    return false;		/* let the interrupt handler pointer stand */  }  return true;}/* This interrupt hits when the disk is ready for the next multisector * block write.  If we get the block size we want (4096), we won't * ever be writing more than 4096 bytes, but conceivably a * user-initiated raw disk I/O might, so we need to be prepared for * that case. */boolide_hwif::MultWriteIntr(){  uint8_t status = Get8(IDE_STATUS);  if (!OK_STAT(status,DRIVE_READY,BAD_W_STAT)) {    drive[cur_drive].Error("multwrite intr", status);    return true;  }  Request *req = group->curReq;    uint32_t nsec = req->nsec;    req->req_start += nsec;  req->req_ioaddr += (EROS_SECTOR_SIZE * nsec);  req->req_nsec -= nsec;  req->nError = 0;  req->nsec -= nsec;#ifdef IDE_DEBUG  MsgLog::printf("MWr Residual at 0x%08x: %d sectors at %d nsec %d\n",		 req->req_ioaddr, req->req_nsec, req->req_start,		 req->nsec); #endif    /* If the drive is ready and there is more to do, ship off the next   * block, else we will have to reschedule it later.   */  if (req->req_nsec && (status & DRQ_STAT)) {    assert( status & DRQ_STAT );    drive[cur_drive].MultWrite(req);    return false;		/* let the interrupt handler pointer stand */  }  return true;}voidide_hwif::OnIntr(IntAction* ia){  ide_hwif *pHwif = (ide_hwif*) ia->drvr_ptr;  if (pHwif->int_handler == 0) {    uint8_t status = pHwif->Get8(IDE_STATUS);    pHwif->drive[0].DumpStatus("orphaned interrupt", status, 0);#if 0    pHwif->drive[0].flags.b.recal = 1;    pHwif->drive[1].flags.b.recal = 1;    halt();#endif  }  /* Call pointer to member that happens to be member of pHwif */  if ( (pHwif->*(pHwif->int_handler))() ) {#ifdef IDE_DEBUG    MsgLog::printf("OnIntr() Set int handler to 0\n");#endif    pHwif->int_handler = 0;    pHwif->next = readyChain;    readyChain = pHwif;    ActivateTask();  }}voidide_hwif::StartIO(){  group->StartIO();}/* FIX: This needs a much more sophisticated selection policy.  Right * now it does round-robin issuance among all of the HWIF's in a group * to prevent starvation. On drives with write-back buffers this isn't * a big problem, but most drives still use write-through logic, and * on these drives the current policy results in bad rotational * delays.  At 7200 RPM, the on-paper mean rotational delay is * 60/(7200*2) or about 4.2 ms.  Since we write blocks sequentially, * it is damn likely that we will get close to worst case rotational * delay of 8ms (I need to measure this). *  * A better policy would be to have the StartIO() routine examine the * next request on the same drive and see if that request falls on the * same PHYSICAL cylinder **and track** as the previous request.  If * so, it should endeavour to issue the request eagerly. *  * There is no point doing more than a track on a modern drive -- head * to head delays closely approximate track to track delays, and we * might as well switch to the next interface. *  * Even better would be to do request merging, coalescing adjacent I/O * operations into a single operation using chained DMA.  This would * make maximal use of the disk cache and the rotational advantage. */voidide_group::StartIO(){  assert(this);    do {    if (curReq == 0) {      for (uint32_t i = 0; i < HWIFS_PER_GROUP; i++) {	uint32_t which_hwif = (cur_hwif + i + 1) % HWIFS_PER_GROUP;	if (hwif[which_hwif] == 0)	  continue;	curReq = hwif[which_hwif]->GetNextRequest();	if (curReq) {	  cur_hwif = which_hwif;	  break;	}      }    }    if (curReq == 0)      return;  #if defined(IDE_DEBUG)    MsgLog::dprintf(false, "Start cur_hwif = 0x%08x, req=0x%08x dio=0x%08x\n",		    hwif[cur_hwif], curReq, curReq->dio);#endif    } while ( hwif[cur_hwif]->StartRequest(curReq) );}Request*ide_hwif::GetNextRequest(){  /* The point of this madness is to cycle through the configured   * drives exactly once, while still doing round-robin initiation.   */    for (uint32_t i = 0; i < MAX_DRIVE; i++) {    uint32_t unit = (cur_drive + i + 1) % MAX_DRIVE;    if ( drive[unit].present && !drive[unit].rq.IsEmpty() ) {      cur_drive = unit;      return drive[unit].rq.GetNextRequest();    }  }  return 0;}/* Return true when request is completed. */boolide_hwif::StartRequest(Request* req){  /* We don't do split-seek on IDE drives, so just go ahead and commit   * the request.   */  assert(this);  assert(req);  if (inDuplexWait)    return false;    if ( int_handler ) {#if defined(IDE_DEBUG)    MsgLog::dprintf(true, "HWIF already active (handler=0x%08x)\n", &int_handler);#endif    return false;  }    if ( ! req->Commit(this, &drive[req->unit]) ) {    /* stalled by another controller */#if defined(IDE_DEBUG)    MsgLog::dprintf(true, "Stalled by another controller\n");#endif    return false;  }  if ( req->IsCompleted() ) {    RequestQueue& rq = drive[req->unit].rq;        assert (req == group->curReq);    req->Finish();    assert ( rq.ContainsRequest(req) );    rq.RemoveRequest(req);    group->curReq = 0;#if defined(IDE_DEBUG)    if (req->cmd == IoCmd::Plug)      MsgLog::printf("IDE%d: plug passes\n", req->unit);    MsgLog::dprintf(false, "Finish current request. More? %c\n",		    rq.IsEmpty() ? 'n' : 'y');#endif    return true;  }  #ifdef IDE_DEBUG  MsgLog::dprintf(false, "Calling DoRequest w/ req=0x%08x...\n", req);#endif  drive[req->unit].DoRequest(req);  return false;}voidide_hwif::Probe(){  if (noprobe) {    MsgLog::printf("Skipping probe on IDE interface %d\n", ndx);    return;  }  if (ioBase == BIOS_HD_BASE) {    /* Check the CMOS configuration settings.  If a CMOS configuration     * is found, then this is either BIOS drive 0x80 or 0x81, and the     * interface is register compatible with the prehistoric register     * interface.  This implies that the drive in question is NOT, for     * example, a OPTION_SCSI drive.     *      * FIX: On newer BIOS, CMOS appears to store info for four drives.     * How to get it if present?     */    uint8_t cmos_hds = CMOS::cmosByte(0x12);    if (cmos_hds)      present = true;		/* HW interface present */        uint8_t cmos_hd0 = (cmos_hds >> 4) & 0xfu;    uint8_t cmos_hd1 = cmos_hds & 0xfu;    /* If the drives are listed in the CMOS, extract their geometry     * from the BIOS tables.     */    if (cmos_hd0) {      /*        * form a longword representing all this gunk:       *       6 bit zero       *	10 bit cylinder       *	 8 bit head       *	 8 bit sector       */      drive[0].b_chs.cyl = SysConfig.driveGeom[0].cyls;      drive[0].b_chs.hd = SysConfig.driveGeom[0].heads;      drive[0].b_chs.sec = SysConfig.driveGeom[0].secs;      drive[0].l_chs = drive[0].b_chs;      MsgLog::printf("ide0: c/h/s=%d/%d/%d\n",		     drive[0].b_chs.cyl,		     drive[0].b_chs.hd,		     drive[0].b_chs.sec);            drive[0].present = true;    }    if (cmos_hd1) {      drive[1].b_chs.cyl = SysConfig.driveGeom[1].cyls;      drive[1].b_chs.hd = SysConfig.driveGeom[1].heads;      drive[1].b_chs.sec = SysConfig.driveGeom[1].secs;      drive[1].l_chs = drive[1].b_chs;      MsgLog::printf("ide1: c/h/s=%d/%d/%d\n",		     drive[1].b_chs.cyl,		     drive[1].b_chs.hd,		     drive[1].b_chs.sec);            drive[1].present = true;    }  }  if (IoRegion::IsAvailable(ioBase, 8) == false ||      IoRegion::IsAvailable(ioBase + IDE_CTL_ALTSTATUS, 2) == false) {    for (uint32_t unit = 0; unit < MAX_DRIVE; unit++) {      if (drive[unit].present)	MsgLog::fatal("IDE: hwif %d drive %d present but ports in use\n",		      ndx, unit);    }    MsgLog::printf("IDE hwif %d ports in use - skipping probe\n",		   ndx);    present = false;    return;  }  for (uint32_t unit = 0; unit < MAX_DRIVE; unit++) {    drive[unit].Probe();    if (drive[unit].present && !present) {      present = true;      IoRegion::Allocate(ioBase, 8, "ide");      IoRegion::Allocate(ioBase + IDE_CTL_ALTSTATUS, 2, "ide");    }  }  if (!present)    return;  if (!irq)    irq = ide_irq[ndx];  MsgLog::printf("Registering IDE driver (this=0x%08x)...\n", this);  Register();  if (!irq) {    MsgLog::printf("ide%d disabled: no IRQ\n", ndx);    /* FIX: should unregister */    return;  }  {    uint8_t result=Get8(IDE_CTL_ALTSTATUS);    MsgLog::printf("Before int register. Alt status : 0x%02x\n", result);  }  IntAction *ia = new IntAction(irq, ide_name[ndx], ide_hwif::OnIntr);  ia->drvr_ptr = this;    IRQ::WireExclusive(ia);  MsgLog::printf("Check pending interrupt: IRQ %d\n", irq);  IRQ::Enable(irq);#if 0  MsgLog::printf("Intentional halt...\n");  halt();#endif}static boolProbe(struct AutoConf* /* ac */){  IDE::InitChipsets();  for (int ctrlr = 0; ctrlr < MAX_HWIF; ctrlr++)    hwif_tbl[ctrlr].Probe();#if 0  /* assume first drive is a 1.44 */  TheHardDiskCtrlr.unit[0]->mediaInfo  = &MediaParams[4];  for(int i= 1; i <=HardDiskCtrlr::NUNITS;i++)    TheHardDiskCtrlr.unit[i] = 0; /* assume the other drives do */				/* not exist */    TheHardDiskCtrlr.Wakeup();#endif  return true;}static boolAttach(struct AutoConf* /* ac */){  return true;}

⌨️ 快捷键说明

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