[Brandon University crest][The famous "Halfway Tree" of the Prairies, between Winnipeg and Brandon]


KModel
 


Site Map

  Kmodel Home  
  - Download
  - Installation
  - Javadoc

  Hardware Model
  - Serial  
  - Timer  
  - Disk  

  Kernel Design  
  - Modules  
  - User Process  
  - Kernel Entry  
  - Kernel Call  
  - Handles  
  - Signals

  Components  
  - Processes  
  - Console  
  - Timer  
  - Disk  

  File System  
  - Disk Layout
  - Buffer Cache
  - Inode Cache
  - Standard Files
  - Vnodes

  Study Questions  

 

   

Disk Controller

The 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:

  • SR - Status Register
  • CR - Control Register
  • LBNR - Logical Block Number Register
  • MAR - Memory Address Register
  • MLR - Memory Length Register
public class Disk {
    public static final int SR = 0;
    public static final int SR_READY = 1;
    public static final int CR = 1;
    public static final int CR_INT_ENABLE = 1;
    public static final int CR_READ = 2;
    public static final int CR_WRITE = 4;
    public static final int LBNR = 2;
    public static final int MAR = 3;
    public static final int MLR = 4;
    
    private Disk() {
    }
}

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
[=]