00001 // disk.h 00002 // Data structures to emulate a physical disk. A physical disk 00003 // can accept (one at a time) requests to read/write a disk sector; 00004 // when the request is satisfied, the CPU gets an interrupt, and 00005 // the next request can be sent to the disk. 00006 // 00007 // Disk contents are preserved across machine crashes, but if 00008 // a file system operation (eg, create a file) is in progress when the 00009 // system shuts down, the file system may be corrupted. 00010 // 00011 // DO NOT CHANGE -- part of the machine emulation 00012 // 00013 // Copyright (c) 1992-1993 The Regents of the University of California. 00014 // All rights reserved. See copyright.h for copyright notice and limitation 00015 // of liability and disclaimer of warranty provisions. 00016 00017 #ifndef DISK_H 00018 #define DISK_H 00019 00020 #include "copyright.h" 00021 #include "utility.h" 00022 #include "callback.h" 00023 00024 // The following class defines a physical disk I/O device. The disk 00025 // has a single surface, split up into "tracks", and each track split 00026 // up into "sectors" (the same number of sectors on each track, and each 00027 // sector has the same number of bytes of storage). 00028 // 00029 // Addressing is by sector number -- each sector on the disk is given 00030 // a unique number: track * SectorsPerTrack + offset within a track. 00031 // 00032 // As with other I/O devices, the raw physical disk is an asynchronous device -- 00033 // requests to read or write portions of the disk return immediately, 00034 // and an interrupt is invoked later to signal that the operation completed. 00035 // 00036 // The physical disk is in fact simulated via operations on a UNIX file. 00037 // 00038 // To make life a little more realistic, the simulated time for 00039 // each operation reflects a "track buffer" -- RAM to store the contents 00040 // of the current track as the disk head passes by. The idea is that the 00041 // disk always transfers to the track buffer, in case that data is requested 00042 // later on. This has the benefit of eliminating the need for 00043 // "skip-sector" scheduling -- a read request which comes in shortly after 00044 // the head has passed the beginning of the sector can be satisfied more 00045 // quickly, because its contents are in the track buffer. Most 00046 // disks these days now come with a track buffer. 00047 // 00048 // The track buffer simulation can be disabled by compiling with -DNOTRACKBUF 00049 00050 const int SectorSize = 128; // number of bytes per disk sector 00051 const int SectorsPerTrack = 32; // number of sectors per disk track 00052 const int NumTracks = 32; // number of tracks per disk 00053 const int NumSectors = (SectorsPerTrack * NumTracks); 00054 // total # of sectors per disk 00055 00056 class Disk : public CallBackObj { 00057 public: 00058 Disk(CallBackObj *toCall); // Create a simulated disk. 00059 // Invoke toCall->CallBack() 00060 // when each request completes. 00061 ~Disk(); // Deallocate the disk. 00062 00063 void ReadRequest(int sectorNumber, char* data); 00064 // Read/write an single disk sector. 00065 // These routines send a request to 00066 // the disk and return immediately. 00067 // Only one request allowed at a time! 00068 void WriteRequest(int sectorNumber, char* data); 00069 00070 void CallBack(); // Invoked when disk request 00071 // finishes. In turn calls, callWhenDone. 00072 00073 int ComputeLatency(int newSector, bool writing); 00074 // Return how long a request to 00075 // newSector will take: 00076 // (seek + rotational delay + transfer) 00077 00078 private: 00079 int fileno; // UNIX file number for simulated disk 00080 char diskname[32]; // name of simulated disk's file 00081 CallBackObj *callWhenDone; // Invoke when any disk request finishes 00082 bool active; // Is a disk operation in progress? 00083 int lastSector; // The previous disk request 00084 int bufferInit; // When the track buffer started 00085 // being loaded 00086 00087 int TimeToSeek(int newSector, int *rotate); // time to get to the new track 00088 int ModuloDiff(int to, int from); // # sectors between to and from 00089 void UpdateLast(int newSector); 00090 }; 00091 00092 #endif // DISK_H