00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 #include "copyright.h"
00017 #include "disk.h"
00018 #include "debug.h"
00019 #include "sysdep.h"
00020 #include "main.h"
00021 
00022 
00023 
00024 
00025 
00026 const int MagicNumber = 0x456789ab;
00027 const int MagicSize = sizeof(int);
00028 const int DiskSize = (MagicSize + (NumSectors * SectorSize));
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 Disk::Disk(CallBackObj *toCall)
00041 {
00042     int magicNum;
00043     int tmp = 0;
00044 
00045     DEBUG(dbgDisk, "Initializing the disk.");
00046     callWhenDone = toCall;
00047     lastSector = 0;
00048     bufferInit = 0;
00049     
00050     sprintf(diskname,"DISK_%d",kernel->hostName);
00051     fileno = OpenForReadWrite(diskname, FALSE);
00052     if (fileno >= 0) {                  
00053         Read(fileno, (char *) &magicNum, MagicSize);
00054         ASSERT(magicNum == MagicNumber);
00055     } else {                            
00056         fileno = OpenForWrite(diskname);
00057         magicNum = MagicNumber;  
00058         WriteFile(fileno, (char *) &magicNum, MagicSize); 
00059 
00060         
00061         Lseek(fileno, DiskSize - sizeof(int), 0);       
00062         WriteFile(fileno, (char *)&tmp, sizeof(int));  
00063     }
00064     active = FALSE;
00065 }
00066 
00067 
00068 
00069 
00070 
00071 
00072 
00073 Disk::~Disk()
00074 {
00075     Close(fileno);
00076 }
00077 
00078 
00079 
00080 
00081 
00082 
00083 static void
00084 PrintSector (bool writing, int sector, char *data)
00085 {
00086     int *p = (int *) data;
00087 
00088     if (writing)
00089         cerr << "Writing sector: " << sector << "\n"; 
00090     else
00091         cerr << "Reading sector: " << sector << "\n"; 
00092     for (unsigned int i = 0; i < (SectorSize/sizeof(int)); i++) {
00093         cerr << p[i] << " ";
00094     }
00095     cout << "\n"; 
00096 }
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 void
00114 Disk::ReadRequest(int sectorNumber, char* data)
00115 {
00116     int ticks = ComputeLatency(sectorNumber, FALSE);
00117 
00118     ASSERT(!active);                            
00119     ASSERT((sectorNumber >= 0) && (sectorNumber < NumSectors));
00120     
00121     DEBUG(dbgDisk, "Reading from sector " << sectorNumber);
00122     Lseek(fileno, SectorSize * sectorNumber + MagicSize, 0);
00123     Read(fileno, data, SectorSize);
00124     if (debug->IsEnabled('d'))
00125         PrintSector(FALSE, sectorNumber, data);
00126     
00127     active = TRUE;
00128     UpdateLast(sectorNumber);
00129     kernel->stats->numDiskReads++;
00130     kernel->interrupt->Schedule(this, ticks, DiskInt);
00131 }
00132 
00133 void
00134 Disk::WriteRequest(int sectorNumber, char* data)
00135 {
00136     int ticks = ComputeLatency(sectorNumber, TRUE);
00137 
00138     ASSERT(!active);
00139     ASSERT((sectorNumber >= 0) && (sectorNumber < NumSectors));
00140     
00141     DEBUG(dbgDisk, "Writing to sector " << sectorNumber);
00142     Lseek(fileno, SectorSize * sectorNumber + MagicSize, 0);
00143     WriteFile(fileno, data, SectorSize);
00144     if (debug->IsEnabled('d'))
00145         PrintSector(TRUE, sectorNumber, data);
00146     
00147     active = TRUE;
00148     UpdateLast(sectorNumber);
00149     kernel->stats->numDiskWrites++;
00150     kernel->interrupt->Schedule(this, ticks, DiskInt);
00151 }
00152 
00153 
00154 
00155 
00156 
00157 
00158 void
00159 Disk::CallBack ()
00160 { 
00161     active = FALSE;
00162     callWhenDone->CallBack();
00163 }
00164 
00165 
00166 
00167 
00168 
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 int
00177 Disk::TimeToSeek(int newSector, int *rotation) 
00178 {
00179     int newTrack = newSector / SectorsPerTrack;
00180     int oldTrack = lastSector / SectorsPerTrack;
00181     int seek = abs(newTrack - oldTrack) * SeekTime;
00182                                 
00183     int over = (kernel->stats->totalTicks + seek) % RotationTime; 
00184                                 
00185                                 
00186 
00187     *rotation = 0;
00188     if (over > 0)               
00189         *rotation = RotationTime - over;
00190     return seek;
00191 }
00192 
00193 
00194 
00195 
00196 
00197 
00198 
00199 int 
00200 Disk::ModuloDiff(int to, int from)
00201 {
00202     int toOffset = to % SectorsPerTrack;
00203     int fromOffset = from % SectorsPerTrack;
00204 
00205     return ((toOffset - fromOffset) + SectorsPerTrack) % SectorsPerTrack;
00206 }
00207 
00208 
00209 
00210 
00211 
00212 
00213 
00214 
00215 
00216 
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 
00225 
00226 
00227 
00228 
00229 int
00230 Disk::ComputeLatency(int newSector, bool writing)
00231 {
00232     int rotation;
00233     int seek = TimeToSeek(newSector, &rotation);
00234     int timeAfter = kernel->stats->totalTicks + seek + rotation;
00235 
00236 #ifndef NOTRACKBUF      // turn this on if you don't want the track buffer stuff
00237     
00238     if ((writing == FALSE) && (seek == 0) 
00239                 && (((timeAfter - bufferInit) / RotationTime) 
00240                         > ModuloDiff(newSector, bufferInit / RotationTime))) {
00241         DEBUG(dbgDisk, "Request latency = " << RotationTime);
00242         return RotationTime; 
00243     }
00244 #endif
00245 
00246     rotation += ModuloDiff(newSector, timeAfter / RotationTime) * RotationTime;
00247 
00248     DEBUG(dbgDisk, "Request latency = " << (seek + rotation + RotationTime));
00249     return(seek + rotation + RotationTime);
00250 }
00251 
00252 
00253 
00254 
00255 
00256 
00257 
00258 void
00259 Disk::UpdateLast(int newSector)
00260 {
00261     int rotate;
00262     int seek = TimeToSeek(newSector, &rotate);
00263     
00264     if (seek != 0)
00265         bufferInit = kernel->stats->totalTicks + seek + rotate;
00266     lastSector = newSector;
00267     DEBUG(dbgDisk, "Updating last sector = " << lastSector << " , " << bufferInit);
00268 }