![]() | ![]() |
|
||||||||||||||||||||||||||||||
|
Disk ControllerThe Disk device is programmed to move a block of data in either direction between a file representing a disk image and some region of an array of bytes representing memory. The device has five ports on the bus:
The disk device is used by waiting until the SR reports the device to be ready. Then values are written into the LBNR, MAR and MLR. Finally, a transfer request -- read or write -- is written into the CR. When the transfer is complete, an interrupt is generated. The disk thread waits for a request and executes it. class DiskThread extends Thread {
boolean request;
public void run() {
for (;;) {
waitRequest();
if ((reg[spec.Disk.CR] & spec.Disk.CR_READ) == spec.Disk.CR_READ)
read();
if ((reg[spec.Disk.CR] & spec.Disk.CR_WRITE) == spec.Disk.CR_WRITE)
write();
}
}
public synchronized void waitRequest() {
if (!request) {
try {
wait();
} catch(java.lang.InterruptedException ie) {
}
}
request = false;
}
public synchronized void makeRequest() {
request = true;
notify();
}
}
The boolean request field and the synchronized methods waitRequest and makeRequest act as a binary semaphore to synchronize the run loop with bus-initiated requests. read() and write() are methods of DiskController. DiskThread is a contained class so it can access the read and write methods of DiskController. Alternatively, read() and write() could be methods of DiskThread, but DiskThread would still have to be contained in DiskController in order to access the port registers. Synchronization occurs when a command is written into the CR. The thread that calls makeRequest() is that of the active process in the kernel, having made its way through the bus and to this point. That thread returns immediately and blocks while waiting for an interrupt to signal completion. The DiskThread proceeds asynchronously and ultimately generates that interrupt. public void writePort(int index, int data) {
switch (index) {
case spec.Disk.SR:
break;
case spec.Disk.CR:
reg[spec.Disk.CR] = data;
if ((data & spec.Disk.CR_READ) == spec.Disk.CR_READ)
diskDevice.makeRequest();
if ((data & spec.Disk.CR_WRITE) == spec.Disk.CR_WRITE)
diskDevice.makeRequest();
break;
case spec.Disk.LBNR:
reg[spec.Disk.LBNR] = data;
break;
case spec.Disk.MAR:
reg[spec.Disk.MAR] = data;
break;
case spec.Disk.MLR:
reg[spec.Disk.MLR] = data;
break;
}
}
The code for read() is similar to that of write(). The disk image is manipulated through an instance of RandomAccessClass held in the field raf. protected void write() {
int mar = reg[spec.Disk.MAR];
int lbn = reg[spec.Disk.LBNR];
int mlr = reg[spec.Disk.MLR];
try {
raf.seek(blksize * lbn);
raf.write(hardware.Memory.mem.b, mar, blksize);
if ((reg[spec.Disk.CR] & spec.Disk.CR_INT_ENABLE)
== spec.Disk.CR_INT_ENABLE)
interrupter.hardwareInterrupt(intno);
} catch (java.io.IOException ioe) {
System.out.println("DiskController.read: " + ioe.getMessage());
System.exit(1);
}
}
|
|||||||||||||||||||||||||||||
Last update 01/24/05
Copyright © Gerald Dueck
[=]