📄 hd.c
字号:
LogEntry("DISK-req",cpuNum, "disk %i.%i %s size %lli sector %lli off=0x%x dma=[", ctrl, unit, op, DKS(node,ctrl,unit).sizeInSectors, DKS(node,ctrl,unit).sectorNum, DKS(node,ctrl,unit).offset);#endif for(i=0;i<8 && DKS(node,ctrl,unit).pAddr[i]; i++) { CPUPrint(" 0x%llx", (uint64)DKS(node,ctrl,unit).pAddr[i]); } if (DKS(node,ctrl,unit).pAddr[i]) { CPUPrint(" ....]\n"); } else { CPUPrint(" ]\n"); } DTRACE('c',node,ctrl,unit); switch( diskModel ) { case DISK_MODEL_SENSE: DMATransfer( DKS(node,ctrl,unit).bytesTransferred, (CPUVec.CycleCount ? CPUVec.CycleCount(DKS(node,ctrl,unit).c.execCpu) : 0 ), DiskDoneRoutine, ENCODE(node,ctrl,unit)); break; case DISK_MODEL_HP: DiskModelRequest(M_FROM_CPU(node), DKS(node,ctrl,unit).dmodel_no, DKS(node,ctrl,unit).sectorNum, DKS(node,ctrl,unit).sizeInSectors, !DKS(node,ctrl,unit).isRead, DMATransfer, DiskDoneRoutine, ENCODE(node,ctrl,unit)); break; case DISK_MODEL_FIXED_DMA: FixedLatencyDisk(ENCODE(node,ctrl,unit)); break; default: ASSERT(0); } DTRACE('x',node,ctrl,unit);}/* * Root disk access from the ALPHA simos console */void sim_disk_simpleIO(long op,long unit,long count,long pAddr,long block){ int i; int node = 0; int ctrl = 0; long x; performingSimpleIO = 1; sim_disk_touch(node, ctrl, unit); DKS(node,ctrl,unit).offset = pAddr & (NBPP-1); DKS(node,ctrl,unit).pAddr[0] = pAddr & ~(NBPP-1); x = (long) DKS(node,ctrl,unit).pAddr[0] + NBPP; for(i=1;i<SIM_DISK_MAX_DMA_LENGTH && x<(pAddr+count);i++) { DKS(node,ctrl,unit).pAddr[i] = x; x += PAGE_SIZE; } DKS(node,ctrl,unit).pAddr[i] = 0; if( i >= SIM_DISK_MAX_DMA_LENGTH ) CPUError("DMA size of %i pages too large.", i);#ifdef DEBUG_HD CPUPrint("\nSim_disk: DISK%d.%d.%d %08x %08x %08x %08x offs=%x\n", 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. */ SimhdDoCmd(node,ctrl,unit); if (op==0x13) { DKS(node,ctrl,unit).isRead = 1; } else { ASSERT(0); } DKS(node,ctrl,unit).sectorNum = block; DKS(node,ctrl,unit).sizeInSectors = count / SectorSize; /* * 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 = 0; 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; /* * Gross hack. does the job * Alpha SRM Console I/O implementation provides synchronous I/O. * Implemented here by forcing it to take 0 cycles. */ { int fixedLat = machines.machine[0].FixedDiskDelay; int usesMemRef = CPUVec.useMemRef; CPUVec.useMemRef = FALSE; machines.machine[0].FixedDiskDelay = 0; FixedLatencyDisk(ENCODE(node,ctrl,unit)); machines.machine[0].FixedDiskDelay = fixedLat; CPUVec.useMemRef = usesMemRef; } ASSERT( DKS(node,ctrl,unit).dmaReq.amountMoved == count); DKS(node,ctrl,unit).done = 0;} /* * DiskDoneRoutine - Callback routine for when a DISK I/O has finished. */static voidDiskDoneRoutine(int encoded_ctrl_unit){ int node = DECODE_NODE(encoded_ctrl_unit); int ctrl = DECODE_CTRL(encoded_ctrl_unit); int unit = DECODE_UNIT(encoded_ctrl_unit); int cpu; if (performingSimpleIO) { /* no acks, just move on */ return; } /* Shouldn't calculate this here, but do it to print out log entry */ if (inCellMode) { cpu = (node / CPUS_PER_CELL(0)) * CPUS_PER_CELL(0); /* cpu 0 in cell */ } else { cpu = NUM_CPUS(M_FROM_CPU(node)) * M_FROM_CPU(node); } ASSERT(0 <= node && node < nnode && 0 <= ctrl && ctrl < nctrl[node] && 0 <= unit && unit < nunit[node][ctrl] && !DKS(node,ctrl,unit).done && DKS(node,ctrl,unit).dmaReq.amountMoved == DKS(node,ctrl,unit).bytesTransferred); { char id[10]; sprintf(id, "%i.%i.%i", node, ctrl, unit); Tcl_SetVar2(TCLInterp, "ScsiRequest", "disk", id, 0); Tcl_SetVar2(TCLInterp, "ScsiRequest", "command", "ack", 0); AnnExec(AnnFind("scsi", "ack")); Tcl_UnsetVar(TCLInterp, "ScsiRequest", 0); } LogEntry("DISK-ack", cpu, "disk %i.%i.%i\n", node, ctrl, unit); DTRACE('r', node, ctrl, unit); DKS(node,ctrl,unit).done = 1; /* operation done */ /* raise interrupt to signal operation done */ if (int_f) int_f(node, ctrl, unit, 1);}/* * DMATransfer - Model the DMA transfer from the disk. */static void DMATransfer( int len, SimTime finishTime, void (*done)(int), int encoded_ctrl_unit){ int node = DECODE_NODE(encoded_ctrl_unit); int ctrl = DECODE_CTRL(encoded_ctrl_unit); int unit = DECODE_UNIT(encoded_ctrl_unit); int cpu; DMARequest *dmaReq = &DKS(node,ctrl,unit).dmaReq; if (inCellMode) { cpu = (node / CPUS_PER_CELL(0)) * CPUS_PER_CELL(0); /* 0 in cell */ } else { cpu = NUM_CPUS(M_FROM_CPU(node)) * M_FROM_CPU(node); } DTRACE('g', node, ctrl, unit); ASSERT( 0 <= ctrl && ctrl < nctrl[node] && 0 <= unit && unit < nunit[node][ctrl]); ASSERT( dmaReq->remainingLen == 0 ); dmaReq->remainingLen = len; /* * Compute start address and rate for DMA, we are given the length. */ /* XXX We can pass only one argument to the "done" callback. * Hence, the node/controller/unit will be encoded into a single int. * * First argument would be DKS(node,ctrl,unit).c.intrCpu if we * supported the interruptNode field of the DevDiskRegisters * struct. The OS writes that field before every scsi transfer, * but the writes are ignored in simmagic.c:disk_handler. * * I'm a little scared to couple this up because we've seen * race conditions in the os simscsi.c in the past. For now * ensure that all interrupts for a given node go to the first * cpu of that node. * * The first argument also ends up being the responsible node for * the DMAs when the firewall is checked. * * Note: We assume here that controller N attached to node N! * This file really shouldn't know which cpu is being interrupted; * that is done in simmagic (or the real magic) and computed under * int_f. */ DMAdoTransfer( cpu, dmaReq, finishTime, done, encoded_ctrl_unit, DKS(node,ctrl,unit).c.execCpu );}/* * FixedLatencyDisk - Model the DMA of a fixed latency disk. */static voidFixedLatencyDisk(int encoded_ctrl_unit){ int node = DECODE_NODE(encoded_ctrl_unit); int ctrl = DECODE_CTRL(encoded_ctrl_unit); int unit = DECODE_UNIT(encoded_ctrl_unit); DMARequest *dmaReq = &DKS(node,ctrl,unit).dmaReq; SimTime reqTime,dmaSectorTime; SimTime now = CPUVec.CycleCount(DKS(node,ctrl,unit).c.execCpu); /* note: the above was formerly intrCpu, but that caused problems * if the intr and exec CPU's times were skewed in Embra... */ reqTime = FIXED_DISK_DELAY(0) * 1000 * CPU_CLOCK; dmaSectorTime= reqTime/DKS(node,ctrl,unit).sizeInSectors; DTRACE('f',node,ctrl,unit); ASSERT(0 <= node && node < nnode && 0 <= ctrl && ctrl < nctrl[node] && 0 <= unit && unit < nunit[node][ctrl]); if( inFixedLatency[node][ctrl][unit] ) { /* this must be DMA done routine callback from 0 latency DMA */ inFixedLatency[node][ctrl][unit]++; return; } while( 1 ) { if (dmaReq->amountMoved == DKS(node,ctrl,unit).sizeInSectors*SectorSize) { /* DMA'ed the whole thing. Signal that we are done. */ DiskDoneRoutine(ENCODE(node,ctrl,unit)); return; } ASSERT( dmaReq->amountMoved < DKS(node,ctrl,unit).sizeInSectors*SectorSize); /* Launch the next sector worth of DMA. * a disk read (isRead) is a DMA write (isDMAWrite) !!! * Do not negate!!! */ inFixedLatency[node][ctrl][unit] = 1; DMATransfer( SectorSize, now + dmaSectorTime, FixedLatencyDisk, ENCODE(node,ctrl,unit)); if(inFixedLatency[node][ctrl][unit] == 1 ) { inFixedLatency[node][ctrl][unit] = 0; break; } /* we must be in 0 latency DMA model, and the DMA scheduled above has finished, so loop around to do next sector */ inFixedLatency[node][ctrl][unit] = 0; }}/* * I/O complete. Tells disk device that OS is done with this i/o. */void sim_disk_iodone(int node, int ctrl, int unit){ ASSERT(0 <= node && node < nnode && 0 <= ctrl && ctrl < nctrl[node] && 0 <= unit && unit < nunit[node][ctrl] && DKS(node,ctrl,unit).done); /* clear interrupt for this disk */ if (int_f) int_f(node,ctrl,unit, 0); DTRACE('D',node,ctrl,unit); DKS(node,ctrl,unit).done = 0;}void sim_disk_status(int node, int ctrl, int unit, int* done, int* bytes_tr, int* errno_val){ ASSERT(0 <= node && node < nnode && 0 <= ctrl && ctrl < nctrl[node] && 0 <= unit && unit < nunit[node][ctrl] ); *done = DKS(node,ctrl,unit).done; *bytes_tr = DKS(node,ctrl,unit).bytesTransferred; *errno_val = DKS(node,ctrl,unit).errnoVal;}/* * Do SCSI command * * Side effect: * - for commands requiring a data transfer: sets up parameters * - for other commands: performs them, sets results and done field. */static voidDoScsiCmd(int node, int ctrl, int unit){#define UNSUPPORTED(TEXT) \ CPUWarning("Unsupported SCSI command " TEXT); goto error; struct mode_sense_data msd; switch (DKS(node,ctrl,unit).cmd[0]) { case CMD_SEEK: UNSUPPORTED("seek"); case CMD_RDEFECTS: UNSUPPORTED("read defects"); case CMD_ADD_DEFECTS: UNSUPPORTED("add defects"); case CMD_REQ_SENSE: UNSUPPORTED("request sense"); case CMD_SEND_DIAG: UNSUPPORTED("send diag"); case CMD_MODE_SELECT: UNSUPPORTED("mode select"); case CMD_PREVREM: UNSUPPORTED("prev rem"); case CMD_FORMAT: UNSUPPORTED("format"); case CMD_STARTUNIT: UNSUPPORTED("start unit"); case CMD_ERASE: UNSUPPORTED("erase"); case CMD_READ: DKS(node,ctrl,unit).isRead = 1; DKS(node,ctrl,unit).sectorNum = (DKS(node,ctrl,unit).cmd[2] << 24) + (DKS(node,ctrl,unit).cmd[3] << 16) + (DKS(node,ctrl,unit).cmd[4] << 8) + (DKS(node,ctrl,unit).cmd[5] << 0); DKS(node,ctrl,unit).sizeInSectors = (DKS(node,ctrl,unit).cmd[7] << 8) + (DKS(node,ctrl,unit).cmd[8] << 0); DKS(node,ctrl,unit).errnoVal = 0; /* will succeed */ DKS(node,ctrl,unit).bytesTransferred = DKS(node,ctrl,unit).sizeInSectors * SectorSize; return; case CMD_READ_6: DKS(node,ctrl,unit).isRead = 1; DKS(node,ctrl,unit).sectorNum = ((DKS(node,ctrl,unit).cmd[1]& 0x1f) << 16) + (DKS(node,ctrl,unit).cmd[2] << 8) + (DKS(node,ctrl,unit).cmd[3]); DKS(node,ctrl,unit).sizeInSectors = (DKS(node,ctrl,unit).cmd[4]); if (DKS(node,ctrl,unit).sizeInSectors == 0) { CPUWarning("Suspicious sizeInSectors in simhd \n"); DKS(node,ctrl,unit).sizeInSectors = 256; } DKS(node,ctrl,unit).errnoVal = 0; /* will succeed */ DKS(node,ctrl,unit).bytesTransferred = DKS(node,ctrl,unit).sizeInSectors * SectorSize; return; case CMD_WRITE: DKS(node,ctrl,unit).isRead = 0; DKS(node,ctrl,unit).sectorNum = (DKS(node,ctrl,unit).cmd[2] << 24) + (DKS(node,ctrl,unit).cmd[3] << 16) + (DKS(node,ctrl,unit).cmd[4] << 8) + (DKS(node,ctrl,unit).cmd[5] << 0); DKS(node,ctrl,unit).sizeInSectors = (DKS(node,ctrl,unit).cmd[7] << 8) + (DKS(node,ctrl,unit).cmd[8] << 0); DKS(node,ctrl,unit).errnoVal = 0; /* will succeed */ DKS(node,ctrl,unit).bytesTransferred = DKS(node,ctrl,unit).sizeInSectors * SectorSize; return; case CMD_WRITE_6: DKS(node,ctrl,unit).isRead = 0; DKS(node,ctrl,unit).sectorNum = (((DKS(node,ctrl,unit).cmd[1] << 3) >> 3) << 16) + (DKS(node,ctrl,unit).cmd[2] << 8) + (DKS(node,ctrl,unit).cmd[3]); DKS(node,ctrl,unit).sizeInSectors = (DKS(node,ctrl,unit).cmd[4]); if (DKS(node,ctrl,unit).sizeInSectors == 0) { CPUWarning("Suspicious sizeInSectors in simhd \n"); DKS(node,ctrl,unit).sizeInSectors = 256; } DKS(node,ctrl,unit).errnoVal = 0; /* will succeed */ DKS(node,ctrl,unit).bytesTransferred = DKS(node,ctrl,unit).sizeInSectors * SectorSize; return; case CMD_READCAPACITY:#if defined(SIM_ALPHA) || defined(IRIX6_4) || defined(SIM_X86) { /* * Use DMA --- alpha port */ uint64 size = (rmtdiskfd >= 0) ? Simrmt_diskcmd(rmtdiskfd, NETDISK_PROBE, node, ctrl, unit, 0,0,(byte *) 0) : DetermineDeviceSize(DKS(node,ctrl,unit).hdcpt.simhdStats.dfd); DIR_READ_CAP_DATA cap; size = size / SectorSize; DKS(node,ctrl,unit).errnoVal = 0; DKS(node,ctrl,unit).bytesTransferred = sizeof(DIR_READ_CAP_DATA); DKS(node,ctrl,unit).sectorNum = -1; /* signal this is sense */ bzero((char *)&cap,sizeof(cap)); cap.lbn3 = (size >>24) & 0xff; cap.lbn2 = (size >>16) & 0xff; cap.lbn1 = (size >> 8) & 0xff; cap.lbn0 = (size >> 0) & 0xff; cap.block_len3 = 0; cap.block_len2 = 0; cap.block_len1 = (SectorSize >> 8) & 0xff; cap.block_len0 = (SectorSize >> 0) & 0xff; bcopy((char *)&cap, DKS(node,ctrl,unit).c.dataBuffer, sizeof(cap)); CPUPrint("hd.c:: READCAPACITY unit=%d size=%d (0x%x,0x%x,0x%x,0x%x)\n", unit,size,cap.lbn3, cap.lbn2, cap.lbn1,cap.lbn0); }#else /* SIM_ALPHA ||IRIX6_4 */ { DKS(node,ctrl,unit).bytesTransferred = (rmtdiskfd >= 0) ? Simrmt_diskcmd(rmtdiskfd, NETDISK_PROBE, node, ctrl, unit, 0,0,(byte *) 0) : (int)lseek(DKS(node,ctrl,unit).hdcpt.simhdStats.dfd, 0, SEEK_END); if (DKS(node,ctrl,unit).bytesTransferred <= 0) { if (rmtdiskfd < 0) perror("Lseeking disk in CMD_READCAPACITY"); DKS(node,ctrl,unit).errnoVal = errno; goto error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -