diskdevice-model.c
来自「一个用在mips体系结构中的操作系统」· C语言 代码 · 共 1,659 行 · 第 1/4 页
C
1,659 行
* until it hits firstSector (see also EndDiskXfer). */ ds->firstCachedSector = (ulong) min(ds->currentDiskXfer, ds->firstSector); INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_XFER, endCtrllerTime); } ds->wantBus = endCtrllerTime; DDEventRequest(CONSIDERBUSXFER, endCtrllerTime, disk); }}/* @SUBTITLE "SendBufferMesg: Give a buffer to the Controller()" *//* Give a buffer to the Controller() so that disk transfers can take place */PRIVATE voidSendBufferMesg(int disk, TICS eventTime){ TICS grabTime = 0; /* time it took to grab the bus */ DEBUG_TRACE(("SendBufferMesg\t%d\t@%s: nextDiskXfer = %lu\n", disk, time_print(eventTime), dstatus[disk].nextDiskXfer)); if (GrabBus(disk, &grabTime, eventTime)) { DDEventRequest(ENDBUFFERMESG, (eventTime + grabTime + COMMANDTIME_t), disk); if (grabTime > 0) { INDEX_TIME_EVENT(EV_BUSSTATE, dstatus[disk].busId, BUSSTATE_GRAB, eventTime); } INDEX_TIME_EVENT(EV_BUSSTATE, dstatus[disk].busId, BUSSTATE_COMMAND, eventTime + grabTime); } else { DEBUG_TRACE(("SendBufferMesg: Waiting for bus\n")); WaitForBus(disk, SENDBUFFERMESG, eventTime); } }/* @SUBTITLE "EndBufferMesg: Finish sending the buffer" */ /* Finish sending the buffer and consider a bus transfer. */PRIVATE voidEndBufferMesg(int disk, TICS eventTime){ struct diskstatus *ds = &(dstatus[disk]); DEBUG_TRACE(("EndBufferMesg\t%d\t@%s: nextDiskXfer = %lu\n", disk, time_print(eventTime), ds->nextDiskXfer)); /* give the bus to the next event on the bus queue */ PassBus(disk, eventTime); ds->haveBuffer = TRUE; /* If the controller is not waiting for disk transfer to finish, we can now consider a bus transfer */ if (ds->restartController == NEVER) { DEBUG_TRACE(("\t")); ConsiderBusXfer(disk, eventTime); }}/* @SUBTITLE "SendSyncCommand: ask disk to sync" *//* Scheduled by DiskDriverSync() to synchronize the disk. */PRIVATE voidSendSyncCommand(int disk, TICS eventTime){ TICS grabTime = 0; /* time it took to grab the bus */ DEBUG_TRACE(("SendSyncCommand\t%d\t@%s: nextDiskXfer = %lu\n", disk, time_print(eventTime), dstatus[disk].nextDiskXfer)); if (GrabBus(disk, &grabTime, eventTime)) { DDEventRequest(ENDSYNCCOMMAND, (eventTime + grabTime + COMMANDTIME_t), disk); if (grabTime > 0) { INDEX_TIME_EVENT(EV_BUSSTATE, dstatus[disk].busId, BUSSTATE_GRAB, eventTime); } INDEX_TIME_EVENT(EV_BUSSTATE, dstatus[disk].busId, BUSSTATE_COMMAND, eventTime + grabTime); } else { DEBUG_TRACE(("SendSyncCommand: Waiting for bus\n")); WaitForBus(disk, SENDSYNCCOMMAND, eventTime); } }/* @SUBTITLE "EndSyncCommand: set flag to wakeup when disk done" *//* Scheduled by SendSyncCommand() to synchronize * the disk by setting a flag so EndDiskXfer can wake * the DiskDriverSync up. */PRIVATE voidEndSyncCommand(int disk, TICS eventTime){ struct diskstatus *ds = &(dstatus[disk]); DEBUG_TRACE(("EndSyncCommand\t%d\t@%s: nextDiskXfer = %lu\n", disk, time_print(eventTime), ds->nextDiskXfer)); /* give the bus to the next event on the bus queue */ PassBus(disk, eventTime); /* only set sync flag when we have outstanding disk operations */ if (ds->currentDiskXfer < ds-> currentBusXfer) { ds->wantSync = TRUE; DEBUG_TRACE(("\tdisk %d want last EndDiskXfer to SendDoneMessage\n", disk)); } else { ds->wantSync = FALSE; /* done syncing coz we didn't have to sync in the first place */ DDEventRequest(SENDDONEMESSAGE, eventTime, disk); }}/* @SUBTITLE "DiskMove: move disk head before disk xfer" *//* Compute the time to move the disk head, then schedule StartDiskXfer at * the move-completion time. */PRIVATE voidDiskMove(int disk, TICS eventTime){ struct diskstatus *ds = &(dstatus[disk]); TICS endMoveTime; endMoveTime = MoveTime_t(disk, ds->nextDiskXfer, eventTime); ds->activeRead = ds->reading; /* so we know a StartDiskXfer is coming */ DEBUG_TRACE(("DiskMove \t%d\t@%s: nextDiskXfer = %lu\n", disk, time_print(eventTime), ds->nextDiskXfer)); DDEventRequest(STARTDISKXFER, endMoveTime, disk); INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_MOVE, eventTime); SUM_ARRAY_METRIC(stats.diskmoves, disk, 1.0);}/* @SUBTITLE "StartDiskXfer: start one-sector disk xfer" *//* * Start a disk transfer event given the disk and the called time. * The disk is at the beginning of nextSector at the given eventTime. * * !! StartDiskXfer() should only advance ds->nextDiskXfer. It should * !! by no means change ds->currentDiskXfer. */PRIVATE voidStartDiskXfer(int disk, TICS eventTime){ TICS abstime; struct diskstatus *ds = &(dstatus[disk]); DEBUG_TRACE(("StartDiskXfer \t%d\t@%s: nextDiskXfer = %lu\n", disk, time_print(eventTime), ds->nextDiskXfer)); if (ds->done) { INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_IDLE, eventTime); return; } if (ds->cancelPrefetch) { ds->cancelPrefetch = FALSE; ds->activeRead = FALSE; DDEventRequest(DISKMOVE, eventTime, disk); /* move to new request */ } else { if (ds->reading) /* reading */ { /* try to enqueue the next sector onto the queue */ if (!CACHE_FULL(disk)) { ds->nextDiskXfer++; abstime = DSECTORXFER_t(eventTime); ds->prefetchReq = DDEventRequest(ENDDISKXFER, abstime, disk); INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_XFER, eventTime); } else { /* cache is full */ ds->activeRead = FALSE; ds->needMove = TRUE; INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_IDLE, eventTime); } } else /* writing */ { /* there is nothing to be written onto the disk */ if (ds->nextDiskXfer == ds->currentBusXfer) { ds->needMove = TRUE; /* not yet */ INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_IDLE, eventTime); } else { ds->nextDiskXfer++; abstime = DSECTORXFER_t(eventTime); ds->prefetchReq = DDEventRequest(ENDDISKXFER, abstime, disk); INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_XFER, eventTime); } } }}/* @SUBTITLE "EndDiskXfer: end of one sector; start another" *//* * Just finished transferring nextSector to/from queue. So, consider * starting another sector xfer, and possibly a bus transfer. * * !! EndDiskXfer() should only advance ds->currentDiskXfer. It should * !! by no means change ds->nextDiskXfer. */PRIVATE voidEndDiskXfer(int disk, TICS eventTime){ struct diskstatus *ds = &(dstatus[disk]); DEBUG_TRACE(("EndDiskXfer \t%d\t@%s: nextDiskXfer = %lu\n", disk, time_print(eventTime), ds->nextDiskXfer)); ds->prefetchReq = NULL; /* EndDiskXfer has been pulled off the heap */ if (ds->done) { INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_IDLE, eventTime); return; } if (ds->cancelPrefetch) { ds->cancelPrefetch = FALSE; ds->activeRead = FALSE; DDEventRequest(DISKMOVE, eventTime, disk); /* move to new request */ } else { if (ds->reading) /* reading */ { ds->currentDiskXfer++; if (!ds->activeBusXfer) { DEBUG_TRACE(("\t")); ConsiderBusXfer(disk, eventTime); } /* start next sector */ DDEventRequest(STARTDISKXFER, MoveNextTime_t(disk, ds->nextDiskXfer, eventTime), disk); } else /* writing */ { ds->currentDiskXfer++; /* when writes get extended, sometimes fCS gets behind */ /* (see end of controller() for explanation) */ ds->firstCachedSector = (ulong) min(ds->currentDiskXfer, ds->firstSector);#ifndef SOLO if ((ds->lastSector - ds->firstSector + 1) > CACHE_SLOTS) { /* Size of transfer is larger than the cache * To keep the transfer moving, we need to update * the firstCachedSector field to reflect what * has been transferred to the disk */ ds->firstCachedSector = (ulong) max(ds->currentDiskXfer, ds->firstCachedSector); }#endif if (!ds->activeBusXfer) { DEBUG_TRACE(("\t")); ConsiderBusXfer(disk, eventTime); } /* start disk transfer again if we are not done */ if (ds->nextDiskXfer <= ds->lastSector) DDEventRequest(STARTDISKXFER, MoveNextTime_t(disk, ds->nextDiskXfer, eventTime), disk); else { INDEX_TIME_EVENT(EV_DISKSTATE, disk, DISKSTATE_IDLE, eventTime);#ifdef IMMEDIATE_REPORT if (ds->restartController != NEVER) DDEventRequest(CONTROLLER, max(ds->restartController, eventTime), disk); else if (ds->wantSync) DDEventRequest(SENDDONEMESSAGE, eventTime, disk); #else DDEventRequest(SENDDONEMESSAGE, eventTime, disk);#endif /* IMMEDIATE_REPORT */ } } }}/* @SUBTITLE "ConsiderBusXfer: consider starting a bus xfer" */PRIVATE voidConsiderBusXfer(int disk, TICS eventTime){ struct diskstatus *ds = &(dstatus[disk]); ulong readySectors; /* sectors that are ready */ boolean lastSectorReady = FALSE; boolean start = FALSE; TICS grabTime = 0; /* time it took to grab the bus */ DEBUG_TRACE(("ConsiderBusXfer\t%d\t@%s: nextBusXfer = %lu\n", disk, time_print(eventTime), ds->nextBusXfer)); if (eventTime >= ds->wantBus && !ds->activeBusXfer && ds->haveBuffer) { if (ds->reading) { lastSectorReady = (ds->currentDiskXfer > ds->lastSector); readySectors = (ds->currentDiskXfer - ds->nextBusXfer); start = ((readySectors >= READFENCE) || lastSectorReady || CACHE_FULL(disk)); } else { lastSectorReady = (ds->nextBusXfer > ds->lastSector); readySectors = (ds->currentBusXfer - ds->nextDiskXfer); start = ((readySectors <= WRITEFENCE) && !lastSectorReady && !CACHE_FULL(disk)); } if (start) { ds->activeBusXfer = TRUE; /* somehow, we WILL start it */ if (GrabBus(disk, &grabTime, eventTime)) { DDEventRequest(STARTBUSXFER, (eventTime + grabTime), disk); if (grabTime > 0) INDEX_TIME_EVENT(EV_BUSSTATE, ds->busId, BUSSTATE_GRAB, eventTime); } else { DEBUG_TRACE(("ConsiderBusXfer: waiting for bus\n")); WaitForBus(disk, STARTBUSXFER, eventTime); } } } }#ifndef SOLOextern int SimhdGetDiskNum(int);PRIVATE voidDmaDone(int encoded_ctrl_unit) { int diskNum = SimhdGetDiskNum(encoded_ctrl_unit); AdvanceTime(); EndBusXfer(diskNum, GetTime());}#endif /* @SUBTITLE "StartBusXfer: start one-sector bus xfer" *//* * Start a bus transfer at the given eventTime. * * !! StartBusXfer() should only advance ds->nextBusXfer. It should by * !! no means change ds->currentBusXfer. */PRIVATE voidStartBusXfer(int disk, TICS eventTime){ struct diskstatus *ds = &(dstatus[disk]); TICS finish; INVARIANT4(disk == *(ds->busOwner), "StartBusXfer: I (disk %d) do not own the bus, disk %d does\n", disk, *(ds->busOwner)); DEBUG_TRACE(("StartBusXfer \t%d\t@%s: nextBusXfer = %lu\n", disk, time_print(eventTime), ds->nextBusXfer)); INDEX_TIME_EVENT(EV_BUSSTATE, ds->busId, BUSSTATE_DATA, eventTime); finish = BSECTORXFER_t(eventTime); /* find the finish time of the xfer */ ds->nextBusXfer++;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?