Custom-OS-Kernel / phase3 / devinterrupt_handler.c
devinterrupt_handler.c
Raw
#include "../h/devinterrupt_handler.h"

extern pcb_t* currentProcess; // pointer to the current executing process
extern int processCount;
extern int device_semaphores[49]; // 49 device semaphores
extern int softBlockCount; // number of soft blocked processes
extern pcb_t* readyQueue; // tail pointer to the queue of ready pcbs
extern cpu_t startTime;
int interruptStartTime;

void InterruptHandler(unsigned int cause)
{
    STCK(interruptStartTime); //this is to record the time at which the interrupt happened

    // Extract bits 8 to 15 directly
    unsigned int ipField = (cause >> 8) & 0xFF;
    
    // Check if bit 0 is set; if so, call PANIC()
    if (ipField & (1 << 0)) {
        PANIC();
    } else {
        // Check bits 1 through 7 for active interrupts
        for (int i = 1; i < 8; i++) {
            if (ipField & (1 << i)) {
                InterruptLineHandler(i);
            }
        }
    }
}


void InterruptLineHandler(int line)
{
    if (line == 1) {
        // PLT timer
        currentProcess->p_time = currentProcess->p_time + (CURRENT_TOD - startTime); 
        currentProcess->p_s = *((state_t*) BIOSDATAPAGE);
        insertProcQ(&readyQueue, currentProcess);
        Scheduler();
    } else if (line == 2){
        // Interval time exception
        LDIT(100000);
        // Unblock all pcbs blocked on the pseudo-clock semaphore
        while (headBlocked(&device_semaphores[48]) != NULL) {
            pcb_t* unblockedPcb = removeBlocked(&device_semaphores[48]);
            if (unblockedPcb != NULL) {
                unblockedPcb->p_semAdd = NULL;
                unblockedPcb->p_time = (unblockedPcb->p_time) + (CURRENT_TOD - startTime);
                insertProcQ(&readyQueue, unblockedPcb);
                softBlockCount--;
            }
        } 

        device_semaphores[48] = 0; // reset the pseudo-clock semaphore to 0
        
        if (currentProcess == NULL) Scheduler();  /* passing control to the current process (if there is one) */
        else LDST((state_t *) 0x0FFFF000);

    } else {
        // Peripheral device interrupt
        memaddr* lineBitMapAddr = (memaddr*)(0x10000040 + ((line - 3)* 0x4));

        // For each bit that is set to 1, call NonTimerHandler
        for (int i = 0; i < 8; i++) {
            if ((*lineBitMapAddr) & (1 << i)) {
                NonTimerHandler(line, i);
            }
        }
    }
}


void NonTimerHandler(int line, int device)
{

    // Compute the address of the device register for the device that generated the interrupt
    devreg_t* deviceRegister = (devreg_t*) (0x10000054 + ((line - 3) * 0x80) + (device * 0x10));
    // Declare a pointer variable called termReg of type termreg_t to point to the computed address
    unsigned int relDevStatus;
    int num;

    if (line == 7) {
        // terminal device
        termreg_t* pointer = (termreg_t*) deviceRegister;

        // Check if the terminal is a transmitter
        if (pointer->recv_status == 1) {
            relDevStatus = pointer->transm_status;
            pointer->transm_command = 1; // Acknowledge transmitter interrupt
            num = 0;
        } else {
            relDevStatus = pointer->recv_status;
            pointer->recv_command = 1; // Acknowledge receiver interrupt
            num = 1;
        }
        device = 2 * device + num;
    } else if (line > 2 && line < 7) {
        // Disk, flash, network, or printer
        //relDevStatus = deviceRegister->dtp.status;
        deviceRegister->dtp.command = 1; // Acknowledge interrupt
        relDevStatus = deviceRegister->dtp.status;
        num = 0;
    } else {
    }

    // Compute the index position for the device in the device_semaphores[] array
    //device = 2 * device + num; //I changed this and relocated it under the line==7 (in other cases device should be whatever was passed to the function)
    int index = (line - 3) * 8 + device;

    device_semaphores[index]++;
    pcb_t* removedPcb = removeBlocked(&device_semaphores[index]);
    if (removedPcb != NULL) {
        // process is successfully unblocked
        removedPcb->p_time = removedPcb->p_time + (CURRENT_TOD - interruptStartTime);
        removedPcb->p_s.reg_v0 = relDevStatus;
        removedPcb->p_semAdd = NULL;
        insertProcQ(&readyQueue, removedPcb);
        softBlockCount--;   
    }

    if (currentProcess == NULL) Scheduler();  /* passing control to the current process (if there is one) */
    else LDST((state_t *) 0x0FFFF000);
}