/** @brief (SYS8) Perform a P operation on a device semaphore. @param interruptLine Interrupt line. @param deviceNumber Device number. @param reading : TRUE in case of reading; FALSE else. @return Return the device's Status Word. */ EXTERN unsigned int waitIO(int interruptLine, int deviceNumber, int reading) { U32 status; switch (interruptLine) { case INT_DISK: devPasseren(&Semaphores.disk[deviceNumber]); break; case INT_TAPE: devPasseren(&Semaphores.tape[deviceNumber]); break; case INT_UNUSED: devPasseren(&Semaphores.network[deviceNumber]); break; case INT_PRINTER: devPasseren(&Semaphores.printer[deviceNumber]); break; case INT_TERMINAL: devPasseren((reading)? &Semaphores.terminalR[deviceNumber] : &Semaphores.terminalT[deviceNumber]); break; default: PANIC(); /* Anomaly */ } /* [Case 1] The device is not the terminal */ if (interruptLine != INT_TERMINAL) status = ((dtpreg_t *) DEV_REG_ADDR(interruptLine, deviceNumber))->status; /* [Case 2] The device is the terminal */ else { termreg_t *terminal = (termreg_t *) DEV_REG_ADDR(interruptLine, deviceNumber); /* Distinguish between receiving and transmitting */ status = (reading)? terminal->recv_status : terminal->transm_status; } return status; }
//disk, tape, network, printer interrupt handler void dtnp_interrupt(int int_line){ dtpreg_t *dev_g; int i; unsigned int status; //valore da far ritornare alla SYS8 memaddr *interrupt_line = (memaddr*) CDEV_BITMAP_ADDR(int_line); //ottengo la linea di interrupt int dev_num = pending_interrupt_device(interrupt_line); //ottengo il device su cui pende l'interrupt dev_g = (dtpreg_t*) DEV_REG_ADDR(int_line, dev_num); dev_g->command = DEV_C_ACK; //passo l'acknowledgement i = devSemIndex(int_line, dev_num) ; if( devSem[i] < 1 ){ //se ci sono dei processi bloccati sul semaforo status = dev_g->status; //li libero e passo loro lo status register e il tempo di gestione verhogen( &devSem[i] , 1 , status, getTODLO() - interruptStart); devStatus[i] = 0; } else{ //se nessuno sta aspettando l'interrupt salvo lo status register e il tempo di gestione dell'interrupt // per quando qualcuno li richiederà devStatus[i] = dev_g->status; interruptTime[i] = getTODLO() - interruptStart; } }
//gestore degli interrupt per i terminali void terminal_interrupt(){ termreg_t *dev_t; int i ; memaddr *interrupt_line = (memaddr*) CDEV_BITMAP_ADDR(IL_TERMINAL); //ottengo la linea di interrupt per i terminali int dev_num = pending_interrupt_device(interrupt_line); //ottengo il terminale su cui pende l'interrupt dev_t = (termreg_t*) DEV_REG_ADDR(IL_TERMINAL, dev_num); //ottengo il registro del terminale unsigned int status ; //valore da far ritornare alla SYS8 status_iprint = dev_t->transm_status; if( (dev_t->transm_status & DEV_TERM_STATUS ) == DEV_TTRS_S_CHARTRSM){ //trattasi di una scrittura, priorità più alta della lettura status = dev_t->transm_status; i = devSemIndex(IL_TERMINAL+1, dev_num); dev_t->transm_command = DEV_C_ACK; //acknowledgement if( devSem[i] < 1 ){ //se ci sono dei processi bloccati sul semaforo verhogen(&devSem[i], 1, status, getTODLO() - interruptStart); //li libero e passo loro lo status register devStatus[i] = 0; } else{ //se nessuno sta aspettando l'interrupt salvo lo status register per quando qualcuno lo richiederà devStatus[i] = dev_t->transm_status; interruptTime[i] = getTODLO() - interruptStart; //tempo impegato a gestire l'interrupt } } else if( (dev_t->recv_status & DEV_TERM_STATUS) == DEV_TRCV_S_CHARRECV ){ //trattasi di una lettura status = dev_t->recv_status; i = devSemIndex(IL_TERMINAL, dev_num); dev_t->recv_command = DEV_C_ACK; //acknowledgement if( devSem[i] < 1 ){ verhogen(&devSem[i], 1,status, getTODLO() - interruptStart); //come sopra devStatus[i] = 0; } else{ devStatus[i] = dev_t->recv_status; interruptTime[i] = getTODLO() - interruptStart; //tempo impegato a gestire l'interrupt } } }
#define ST_BUSY 3 #define ST_TRANSMITTED 5 #define CMD_ACK 1 #define CMD_TRANSMIT 2 #define CHAR_OFFSET 8 #define TERM_STATUS_MASK 0xFF typedef unsigned int u32; static void term_puts(const char *str); static int term_putchar(char c); static u32 tx_status(termreg_t *tp); static termreg_t *term0_reg = (termreg_t *) DEV_REG_ADDR(IL_TERMINAL, 0); void test(char *test_name, int (*f)(void)) { term_puts(test_name); term_puts(": "); term_puts((*f)() ? "OK\n" : "FAIL\n"); } int test_initProc(void) { int i; int success = 1; pcb_t *p1, *p2;