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

📄 hd.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
  int node, u, c;    if (restoreFromChkpt) {     /* For now, only support restoring the disk devices on the        rmtaccess server which is servicing the checkpoint restore --        supporting 'fallback' is slightly tricky given the current        code structure, so I'm not implementing it for now */     if (Simcpt_IsRemote()) {        rmtdiskfd = Simrmt_diskinit(NULL);        if (rmtdiskfd < 0)           CPUError("Can't contact remote disk machine\n");        if (Simcpt_Restore("diskdev") != 0)           CPUError("Can't contact remote disk machine\n");     } else {                    if (DevFileDir[0] == '$') {           rmtdiskfd = Simrmt_diskinit(DevFileDir);           if (rmtdiskfd < 0)              CPUError("Can't contact remote disk machine\n");        }        if (Simcpt_Restore("diskdev") != 0) {           CPUError("Can't restore disk devices\n");        }     }       for (node = 0; node < nnode; node++) {       if (!dks[node]) continue;       for (c = 0; c < nctrl[node]; c++) {	 if (!dks[node][c]) continue;	 for (u = 0; u < nunit[node][c]; u++) {	   if (!dks[node][c][u]) continue;	   DKS(node,c,u).cmd[0] = CMD_NONE;	/* no SCSI command pending */	 }       }     }  } else {     if (DevFileDir[0] == '$') {        rmtdiskfd = Simrmt_diskinit(DevFileDir);        if (rmtdiskfd < 0) {           CPUError("Can't contact remote disk machine\n");        }     }  }}static intSimhdOpenCOWDisk(int node, int ctrl, int unit, SimhdSaveInfo *hd){  off_t size;    if (rmtdiskfd < 0) {    hd->dfd = open(hd->filename, O_RDONLY , 0);    if (hd->dfd < 0) {        if (errno != ENOENT) {         CPUWarning("Simhd: could not open %s COW, errno=%d\n",                    hd->filename, errno);       }       return -1;    } else {      struct stat filestats;      size = DetermineDeviceSize(hd->dfd);      if (size < 1024*1024) {	 CPUError("SimHD: DISK is smaller than 1MB (%d bytes) !!!\n",		  size);      }      fstat(hd->dfd, &filestats);      /* If we're restoring from a checkpoint, check fize size and 	 creation time against checkpointed values */      if ((hd->fileSize > 0) && (hd->fileSize != size)) {	Sim_Warning("Simhd: Size of disk %s checkpoint is based on "		    "has changed!\n", DKS_filename(node,ctrl,unit));      }      hd->fileSize = size;      if ((hd->modifyTime > 0) && (hd->modifyTime != filestats.st_mtime)) {	Sim_Warning("Simhd: DISK file checkpoint is based on "		    "has been modified!\nThis might not work...\n");      } else {	hd->modifyTime = filestats.st_mtime;      }      Sim_Warning("%s opened using Copy On Write.\n",		  DKS_diskname(node,ctrl,unit));    }  } else {    DiskFileInfo df;    int retval;    /* If we have a filename for the disk (checkpoint restore), pass it        to the remote access server; if not, hd->filename should be null. */    bzero((char *) &df, sizeof(df));    ASSERT( strlen(hd->filename)+1  < sizeof(df.filename));    strcpy(df.filename,hd->filename);        retval = Simrmt_diskcmd(rmtdiskfd, NETDISK_ATTACH,                            node, ctrl, unit,			    0, strlen(df.filename)+1, (byte *)&df);    if (retval < 0) {      CPUWarning("Open of %s failed on rmtaccess server\n",		 DKS_diskname(node,ctrl,unit));      return retval;    }    strcpy(hd->filename,df.filename);    hd->fileSize = size = df.fileSize;    hd->modifyTime = df.modifyTime;    Sim_Warning("%s remotely open using Copy On Write.\n",		DKS_diskname(node,ctrl,unit));  }  hd->writeable = (char)0;  hd->doCheckSum = hd->checkSum = 0;  /* The modify map is not allocated until */  /* we actually change the disk, this is  */  /* to optimize checkpointing.   */  size = (size + (SIM_DISK_SHADOW_BLKSIZE-1)) & ~(SIM_DISK_SHADOW_BLKSIZE-1);  {      int pageSize = getpagesize();     hd->modifyMapSize = size/SectorSize/8 + 1; /* 8 extra */     hd->modifyMapSize = (hd->modifyMapSize+pageSize-1) & ~(pageSize-1);  }  hd->modifyMap = NULL;  hd->sfd = 0;  hd->shadowOffset = NULL;  hd->nextWriteOffset = 0;  return 0;}static intSimhdOpenDisk(int node, int ctrl, int unit, SimhdSaveInfo *hd){  int retval = 0;  if (rmtdiskfd < 0) {    hd->dfd = open(hd->filename, O_RDWR , 0);    if (hd->dfd < 0) {       retval = SimhdOpenCOWDisk(node, ctrl, unit, hd);      if (retval < 0) {#if !defined(IRIX6_4) && !defined(SIM_X86)	Sim_Warning("%s not opened! file=%s\n",		    hd->diskname, hd->filename);#endif      }    } else {      CPUWarning("WARNING: %s opened read-write.\n"		 "WARNING: remember to umount before checkpointing!!!\n",		  DKS_diskname(node,ctrl,unit));      DKS(node,ctrl,unit).hdcpt.accessed = 1;      hd->writeable = (char)1;    }    if (hd->dfd <= 0) {      retval = -1;    }  } else {    /* Rmtaccess disks must be opened COW */    retval = SimhdOpenCOWDisk(node, ctrl, unit, hd);  }  return retval;}static voidSimhdDoCmd(int node, int ctrl, int unit){  SimhdSaveInfo *hd     = &DKS(node,ctrl,unit).hdcpt.simhdStats;  int            retval = 0;  int cmd;  char *op;  ASSERT(0 <= ctrl && ctrl < nctrl[node]       &&	 0 <= unit && unit < nunit[node][ctrl] &&	 !DKS(node,ctrl,unit).done);  /* check whether this disk is opened for the first time */  if ((rmtdiskfd >= 0) && !DKS(node,ctrl,unit).hdcpt.accessed) {    /* Opening a disk for the first time via rmtaccess --        don't provide a pathname, attempt to open COW. */     if (!strncmp(hd->filename,"NOTDEF",strlen("NOTDEF"))) {        retval = -1;     } else {        retval = SimhdOpenCOWDisk(node, ctrl, unit, hd);        DKS(node,ctrl,unit).hdcpt.accessed = 1;     }  } else if ((rmtdiskfd <  0) && (hd->dfd <= 0)) {    /* assign this disk a name (if it doesn't have one) */    disk_name(node, ctrl, unit);    retval = SimhdOpenDisk(node, ctrl, unit, hd);    DKS(node,ctrl,unit).hdcpt.accessed = 1;  }  if (retval < 0 && DKS(node,ctrl,unit).cmd[0] != CMD_INQUIRY ) {    DKS(node,ctrl,unit).bytesTransferred = 0;    DKS(node,ctrl,unit).errnoVal         = errno;    DKS(node,ctrl,unit).done             = 1;    DTRACE('b', node, ctrl, unit);    return;  }  /* interpret the SCSI command and do required setup. The actual data   * transfer doesn't take place here, but in the SimhdIOHandler.   */  DoScsiCmd(node, ctrl, unit);    cmd = DKS(node,ctrl,unit).cmd[0];  if (cmd != CMD_NONE) {     char id[10];     op = scsiOpcode[cmd];     ASSERT(op != NULL);     sprintf(id, "%i.%i.%i", node, ctrl, unit);     Tcl_SetVar2(TCLInterp, "ScsiRequest", "disk", id, 0);     Tcl_SetVar2(TCLInterp, "ScsiRequest", "command", op, 0);     AnnExec(AnnFind("scsi", op));     Tcl_UnsetVar(TCLInterp, "ScsiRequest", 0);  }  DTRACE(DKS(node,ctrl,unit).done ? 'd' : 'e', node, ctrl, unit);}/* * Data handler: does the actual I/O to disk. Is called by the * DMA routines (see comments in dma.h). */static voidSimhdIOHandler(DMARequest* req){  int           node = DECODE_NODE(req->arg);  int           ctrl = DECODE_CTRL(req->arg);  int           unit = DECODE_UNIT(req->arg);  Device*       dksp = &DKS(node,ctrl,unit);  unsigned long offset;  int           fd;  int           remote;  ASSERT(req->dmaLen > 0);  if (req->isDMAWrite) {    /** disk input **/    if (dksp->c.currPtr < dksp->c.dataBuffer+SectorSize) {      /* data has already been read into dataBuffer */      dksp->c.currPtr += req->dmaLen;    } else {      /* must fetch a new sector */       if (dksp->hdcpt.simhdStats.writeable) {          /* this is a writable disk */          fd = dksp->hdcpt.simhdStats.dfd;          offset = (dksp->c.currSector)*SectorSize;          if (lseek(fd, offset, SEEK_SET) == -1)             CPUError("Can't seek for %s in RD\n",		      DKS_diskname(node,ctrl,unit));          if (read(fd, dksp->c.dataBuffer, SectorSize) != SectorSize)             CPUWarning("Can't read from %s\n",		      DKS_diskname(node,ctrl,unit));       } else {          remote = SimhdFindSector(node,ctrl,unit,				   dksp->c.currSector,&fd,&offset,1);          if (remote) {             int retval = Simrmt_diskcmd(rmtdiskfd, NETDISK_READ,                                         node, ctrl, unit,					 dksp->c.currSector, SectorSize,                                         dksp->c.dataBuffer);             if (retval < 0) CPUError("Simhd: error in remote read\n");          } else {             int bytesRead;             if (lseek(fd, offset, SEEK_SET) == -1)                CPUError("Can't seek for %s in RD\n",			 DKS_diskname(node,ctrl,unit));             bytesRead = read(fd, dksp->c.dataBuffer, SectorSize);             if (bytesRead != SectorSize) {                CPUWarning("%s: Only read %d bytes at offset %lld \n",                           DKS_diskname(node,ctrl,unit),			   bytesRead,(uint64)offset);                bzero(dksp->c.dataBuffer+bytesRead,SectorSize-bytesRead);             }          }       }      /* update current read state */      dksp->c.currSector++;      dksp->c.currPtr = dksp->c.dataBuffer + req->dmaLen;    }    req->data = dksp->c.currPtr - req->dmaLen;  } else {    /** disk output **/    ASSERT(req->data == dksp->c.currPtr);    dksp->c.currPtr += req->dmaLen;    if (dksp->c.currPtr < dksp->c.dataBuffer+SectorSize) {      /* buffer up data until one sector filled */      ASSERT(req->remainingLen > 0); /* make sure whole sectors written */    } else {      /* buffer filled up, write to disk */      ASSERT(dksp->c.currPtr == dksp->c.dataBuffer+SectorSize);      if (dksp->hdcpt.simhdStats.writeable) {	 int len;         /* this is a writable disk */         fd = dksp->hdcpt.simhdStats.dfd;         offset = (dksp->c.currSector)*SectorSize;         if (lseek(fd, offset, SEEK_SET) == -1)            CPUError("Can't seek for %s in RD\n",		     DKS_diskname(node,ctrl,unit));         len = write(fd, dksp->c.dataBuffer, SectorSize);	 if (len != SectorSize) {             CPUError("Can't write to %s. only %d written out of %d. errno=%d offset=%ld\n", 		     DKS_diskname(node,ctrl,unit),len,SectorSize,errno,(uint64)offset);	 }      } else {         SimhdFindSector(node,ctrl,unit, dksp->c.currSector, &fd, &offset, 0);         if (lseek(fd, offset, SEEK_SET) == -1)            CPUError("Can't seek for %s in WR\n",		     DKS_diskname(node,ctrl,unit));         if (write(fd, dksp->c.dataBuffer, SectorSize) != SectorSize)            CPUWarning("Can't write to shadow file for %s\n",                       DKS_diskname(node,ctrl,unit));      }      /* update current write state */      dksp->c.currSector++;      dksp->c.currPtr = dksp->c.dataBuffer;    }    req->data = dksp->c.currPtr;  }  ASSERT(dksp->c.currPtr <= dksp->c.dataBuffer+SectorSize);}/* * Start disk i/o. Arguments are: *  - (ctrl,unit) = disk *  - cmd         = SCSI command *  - pages       = array of page pointers for transfer *  - offset      = offset into first page */void sim_disk_startio(int node, int ctrl, int unit,		      unsigned char cmd[SIM_DISK_CMD_SIZE], /*SCSI cmd*/		      PA            pages[SIM_DISK_MAX_DMA_LENGTH],		      int           offset){   int i;  char *op;  int cpuNum = CPUVec.CurrentCpuNum();  enum {DISK_MODEL_FIXED_DMA,     /* Fixed latency read/write */	DISK_MODEL_HP,            /* Realistic latency read/write */	DISK_MODEL_SENSE          /* sense-->DMA */  } diskModel;   performingSimpleIO = 0;  ASSERT(0 <= node && node < nnode              &&	 0 <= ctrl && ctrl < nctrl[node]        &&	 0 <= unit && unit <= nunit[node][ctrl] &&	 offset >= 0 && offset < NBPP && 	 DKS(node,ctrl,unit).done == 0);  if (!DKS(node,ctrl,unit).isReady) {    Sim_Warning("simhd_startio: device not ready\n");    DKS(node,ctrl,unit).errnoVal = -1;    DKS(node,ctrl,unit).done     = 1;    /* raise interrupt to signal operation done */    if (int_f) int_f(node, ctrl, unit, 1);    return;  }  /* XXXXXXXXXXX   * Unfortunately, the kernel does not give a list of phsysical   * pages to us. If the buffer was originally in kseg0, the actual   * physical address (not paged aligned) is given to us).    * simscsi.c (line 674) should eventually be fixed. For now,    * we align the pages ourselves   *   * Actually, it would be even better if we had physical   * addresses. For now we convert it here.   * XXXXXXXXXXX   */  for (i=0; i < SIM_DISK_MAX_DMA_LENGTH && pages[i]; i++ ) { #if defined(SIM_ALPHA) || defined(SIM_X86)     DKS(node,ctrl,unit).pAddr[i] =  ((PA)pages[i] & ~(NBPP-1));#else    DKS(node,ctrl,unit).pAddr[i] =       K0_TO_PHYS(((VA)pages[i] & ~(NBPP-1)));#endif  }  if( i >= SIM_DISK_MAX_DMA_LENGTH )    CPUError("DMA size of %i pages too large.", i);  DKS(node,ctrl,unit).pAddr[i] = 0;  DKS(node,ctrl,unit).offset   = offset;#ifdef DEBUG_HD  CPUPrint("\nSim_disk: %s %08x %08x %08x %08x offs=%x\n",	   DKS_diskname(node,ctrl,unit),	   pages[0], pages[1], pages[2], pages[3], offset);#endif    /*   * Decode the command and execute it, if it doesn't require a data   * transfer. Otherwise (for I/O commands), set up parameters. Actual   * I/O will be kicked below.   */  for (i = 0; i < SIM_DISK_CMD_SIZE; i++) DKS(node,ctrl,unit).cmd[i] = cmd[i];  SimhdDoCmd(node,ctrl,unit);  if (DKS(node,ctrl,unit).done) {    /* raise interrupt to signal operation done */    if (int_f) int_f(node,ctrl, unit, 1);    return;  }    /*    * Set up DMA request area   */  DKS(node,ctrl,unit).dmaReq.isDMAWrite  = DKS(node,ctrl,unit).isRead;  DKS(node,ctrl,unit).dmaReq.pAddrs      = &DKS(node,ctrl,unit).pAddr[0];  DKS(node,ctrl,unit).dmaReq.offset      = DKS(node,ctrl,unit).offset;  DKS(node,ctrl,unit).dmaReq.amountMoved = 0;  DKS(node,ctrl,unit).dmaReq.handler     = SimhdIOHandler;  DKS(node,ctrl,unit).dmaReq.data        = DKS(node,ctrl,unit).c.dataBuffer;  DKS(node,ctrl,unit).dmaReq.arg         = ENCODE(node,ctrl,unit);  /* XXXXXXX Hack: check this execCpu bussiness*/  DKS(node,ctrl,unit).c.execCpu          = (HP_DISK_SCALING(0) > 0 ? 0 :cpuNum);  DKS(node,ctrl,unit).c.currPtr          = DKS(node,ctrl,unit).c.dataBuffer +                              (DKS(node,ctrl,unit).isRead ? SectorSize : 0);  DKS(node,ctrl,unit).c.currSector       = DKS(node,ctrl,unit).sectorNum;  /* invalidate cache / tc since this command involves I/O */  CPUVec.DMAInval(M_FROM_CPU(node), DKS(node,ctrl,unit).pAddr);  /* select a disk model */  if( DKS(node,ctrl,unit).sectorNum < 0 ) {     /* CMD_MODE_SENSE command - who cares about timing?? */    diskModel = DISK_MODEL_SENSE;    DKS(node,ctrl,unit).c.currPtr = DKS(node,ctrl,unit).c.dataBuffer;  } else    diskModel = (strcmp(DISK_MODEL(0), "HP") != 0) ?                DISK_MODEL_FIXED_DMA : DISK_MODEL_HP;       #if defined(MAGIC_CTRL) && defined(MAGIC_UNIT)  if (ctrl == MAGIC_DISK                                 &&      unit == MAGIC_UNIT                                 &&      MAGIC_DISK_SECTOR                                  &&      DKS(node,ctrl,unit).sectorNum == MAGIC_DISK_SECTOR &&      diskModel == DISK_MODEL_HP )    /* Magic sector is turbo-charged */    diskModel = DISK_MODEL_FIXED_DMA;#endif     if( DKS(node,ctrl,unit).sectorNum >= 0 ) {    op = (DKS(node,ctrl,unit).isRead ? "RD":"WR");  } else    op = "SYS";#if defined(SIM_ALPHA)  LogEntry("DISK-req",cpuNum,	   "disk %i.%i %s size %li sector %li off=0x%x dma=[",	   ctrl, unit, op,	   DKS(node,ctrl,unit).sizeInSectors, DKS(node,ctrl,unit).sectorNum,	   DKS(node,ctrl,unit).offset);#else

⌨️ 快捷键说明

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