#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
termreg_t* pointer = (termreg_t*) deviceRegister;
unsigned int relDevStatus;
int num;
// 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;
}
// Compute the index position for the device in the device_semaphores[] array
int deviceNum = 2 * device + num;
int index = (line - 3) * 8 + deviceNum;
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);
}