#include "../h/sysSupport.h"
#include "../h/syscall.h"
#include "../h/libraries.h"
extern swap_t swapPoolTable[POOLSIZE];
extern int supportDeviceSemaphore[3][UPROCMAX]; // 3 device semaphores for printer, terminal receiver and terminal transmitter
extern int flashSemaphores[UPROCMAX];
extern int master_sem;
void GeneralException_Handler()
{
support_t* supportPointer = (support_t*) SYSCALL(GETSUPPORTPTR, 0, 0, 0); // Get access to the support info of the current process
int exceptionCode = GET_EXEC_CODE(supportPointer->sup_exceptState[GENERALEXCEPT].cause);
if (exceptionCode >= 9) {
Terminate_SYS9(supportPointer);
return;
}
int sysnumber = (int) supportPointer->sup_exceptState[GENERALEXCEPT].reg_a0;
supportPointer->sup_exceptState[GENERALEXCEPT].pc_epc = supportPointer->sup_exceptState[GENERALEXCEPT].pc_epc + 4;
switch (sysnumber)
{
case TERMINATE:
Terminate_SYS9(supportPointer);
break;
case GET_TOD:
Get_Tod_SYS10(supportPointer);
break;
case WRITEPRINTER:
Write_To_Printer_SYS11(supportPointer);
break;
case WRITETERMINAL:
Write_to_Terminal_SYS12(supportPointer);
break;
case READTERMINAL:
Read_From_Terminal_SYS13(supportPointer);
break;
default:
Terminate_SYS9(supportPointer);
break;
}
LDST((state_t*) &(supportPointer->sup_exceptState[GENERALEXCEPT]));
}
/*
void Terminate_SYS9(support_t* sPtr)
{
SYSCALL(VERHOGEN, (int) &master_sem, 0, 0);
deleteSwTbEntries(sPtr->sup_asid); // Clear entries in the swap pool table
// Any device semaphore being held should be released
for (int device = 0; device < 3; device++) {
if (sPtr->sup_asid - 1 <= 0) {
SYSCALL(VERHOGEN, (int) &(supportDeviceSemaphore[device][(sPtr->sup_asid) - 1]), 0, 0);
}
}
if (flashSemaphores[(sPtr->sup_asid) - 1] <= 0) {
SYSCALL(VERHOGEN, (int) &(flashSemaphores[(sPtr->sup_asid) - 1]), 0, 0);
}
}
*/
void Terminate_SYS9(support_t* sPtr) // sys2 wrapper
{
// cleaning the entries on the swap table
deleteSwTbEntries(sPtr->sup_asid);
// checking if the process to be terminated is holding any mutex semaphore
// in that case use a SYS4 to free it and terminate it with sys2
for (int i = 0; i < SUPP_SEM_N; i++)
{
if (supportDeviceSemaphore[i][sPtr->sup_asid - 1] <= 0) // i is the device semaphore line, asid represents the device
SYSCALL(VERHOGEN, (int) &supportDeviceSemaphore[i][sPtr->sup_asid - 1], 0, 0);
}
if (flashSemaphores[sPtr->sup_asid - 1] <= 0)
SYSCALL(VERHOGEN, (int) &flashSemaphores[sPtr->sup_asid - 1], 0, 0);
// waking up the test proc
SYSCALL(VERHOGEN, (int) &master_sem, 0, 0);
SYSCALL(TERMPROCESS, 0, 0, 0);
}
void Get_Tod_SYS10(support_t* sPtr)
{
unsigned int timeofDay;
STCK(timeofDay); // population of timeofDay with current time of day
sPtr->sup_exceptState[1].reg_v0 = (unsigned int) timeofDay;
}
void Write_To_Printer_SYS11(support_t* sPtr)
{
// Get the address of the device register associated with the printer
devreg_t* deviceRegister = GET_DEV_ADDR(6, ((sPtr->sup_asid) - 1));
// Gain mutual exclusion on the printer device semaphore
SYSCALL(PASSEREN, (int) &(supportDeviceSemaphore[0][(sPtr->sup_asid) - 1]), 0, 0);
int stringLength = (int) sPtr->sup_exceptState[1].reg_a2; // length of the passed string
char* s_addr = (char*) sPtr->sup_exceptState[1].reg_a1; // address of the first character of the string
int charTransmitted = 0;
unsigned int printerStatus;
// Transmit all characters in length
for (charTransmitted = 0; charTransmitted < stringLength; charTransmitted++) {
deviceRegister->dtp.data0 = *s_addr;
DISABLE_INTERRUPTS_COMMAND; // ATOMIC
deviceRegister->dtp.command = 2;
SYSCALL(IOWAIT, 6, (sPtr->sup_asid) - 1, 0);
ENABLE_INTERRUPTS_COMMAND; // ATOMIC END
printerStatus = deviceRegister->dtp.status;
if (printerStatus != 1) {
// Error
printerStatus = printerStatus*(-1);
break;
}
//No error
s_addr = s_addr + 1;
charTransmitted = charTransmitted + 1;
}
sPtr->sup_exceptState->reg_v0 = charTransmitted;
SYSCALL(VERHOGEN, (int) &(supportDeviceSemaphore[0][(sPtr->sup_asid) - 1]), 0, 0);
}
// Communicate with the TERMINAL device
void Write_to_Terminal_SYS12(support_t* sPtr)
{
devreg_t* deviceRegister = GET_DEV_ADDR(7, ((sPtr->sup_asid) - 1));
SYSCALL(PASSERN, (memaddr) &supportDeviceSemaphore[1][(sPtr->sup_asid) - 1], 0, 0); // Gain mutual exclusion
int stringLength = (int) sPtr->sup_exceptState[1].reg_a2;
char* s_addr = (char*) sPtr->sup_exceptState[1].reg_a1;
int charTransmitted = 0;
unsigned int terminalStatus;
if( (memaddr) s_addr >= 0x80000000 && stringLength >=0 && stringLength <=128) {
for (charTransmitted = 0; charTransmitted < stringLength; charTransmitted++) {
DISABLE_INTERRUPTS_COMMAND;
deviceRegister->term.transm_command = ((unsigned int) *s_addr << 8) | 2;
// Constructs a transmitter command by embedding the address in the
// higher-order bits and a specific command (2) in the lower-order bits, then assigns it to the device register
terminalStatus = SYSCALL(IOWAIT, 7, (sPtr->sup_asid) - 1, 0);
ENABLE_INTERRUPTS_COMMAND;
if ((terminalStatus & 0xFF) != 5) {
// error
terminalStatus = terminalStatus * (-1);
break;
}
// not error
s_addr = s_addr + 1;
//charTransmitted = charTransmitted + 1; //I changed this (incrementing is already being done in the for loop (while loop would have required this)
}
}
else {
Terminate_SYS9(sPtr); //I changed code here (added the missing else condition)
}
sPtr->sup_exceptState[1].reg_v0 = charTransmitted;
SYSCALL(VERHOGEN, (int) &supportDeviceSemaphore[1][(sPtr->sup_asid) - 1], 0, 0);
}
void Read_From_Terminal_SYS13(support_t* sPtr)
{
devreg_t* deviceRegister = GET_DEV_ADDR(7, ((sPtr->sup_asid) - 1));
SYSCALL(PASSERN, (int) &supportDeviceSemaphore[2][(sPtr->sup_asid) - 1], 0, 0); // Gain mutual exclusion
char* s_addr = (char*) sPtr->sup_exceptState[1].reg_a1; // address of the first character in the string
int charTransmitted = 0;
unsigned int terminalStatus;
if( (memaddr) s_addr >= 0x80000000) { //I changed this (added this missing if)
while(1) { // terminates when new line is read
DISABLE_INTERRUPTS_COMMAND;
deviceRegister->term.recv_command = 2;
terminalStatus = SYSCALL(IOWAIT, 7, (sPtr->sup_asid) - 1, 1);
ENABLE_INTERRUPTS_COMMAND;
if ((terminalStatus & 0xFF) != 5) {
// failed read operation
charTransmitted = ((terminalStatus >> 8) & 0xFF) * (-1);
break;
}
else {
// successful read operation
charTransmitted = charTransmitted + 1;
*s_addr = (terminalStatus >> 8) & 0xFF;
char currentChar = *s_addr;
s_addr = s_addr + 1;
if (currentChar == '\n') {
break;
}
}
}
}
else {
Terminate_SYS9(sPtr); //I changed code here (added the missing else condition)
}
sPtr->sup_exceptState[1].reg_v0 = charTransmitted;
SYSCALL(VERHOGEN, (int) &supportDeviceSemaphore[2][(sPtr->sup_asid) - 1], 0, 0); //I changed this .. & was missing
}
// Clear all those entries in the swap pool table that are related to a specific process whose ASID
// matches the asid value passed in
void deleteSwTbEntries(int asid)
{
for (int i = 0; i < POOLSIZE; i++) {
if (swapPoolTable[i].sw_asid == asid) {
swapPoolTable[i].sw_asid = NOPROC;
}
}
}