From 2b30f30a330ee9bc9feb9ec4e55c8b6f3e6eb8fe Mon Sep 17 00:00:00 2001 From: Ben Burwell Date: Wed, 1 Apr 2015 20:29:53 -0400 Subject: as of 2013-11-18 --- com.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ comdrtst.c | 125 +++++++++++++++++++++++++++++ comdrtsw.c | 73 +++++++++++++++++ comhan.c | 40 +++++++++- comprtts.c | 113 +++++++++++++++++++++++++++ dcb.c | 65 ++++++++++++++++ load.c | 2 +- main.c | 36 --------- mpx.h | 83 +++++++++++++++++--- printer.c | 157 +++++++++++++++++++++++++++++++++++++ prtdrtst.c | 68 ++++++++++++++++ qtest.c | 19 +++++ sys_sppt.c | 148 +++++++++++++++++++++++++++++++++-- 13 files changed, 1132 insertions(+), 56 deletions(-) create mode 100644 com.c create mode 100644 comdrtst.c create mode 100644 comdrtsw.c create mode 100644 comprtts.c create mode 100644 dcb.c create mode 100644 printer.c create mode 100644 prtdrtst.c create mode 100644 qtest.c diff --git a/com.c b/com.c new file mode 100644 index 0000000..5ddba08 --- /dev/null +++ b/com.c @@ -0,0 +1,259 @@ +/** + * MPX OS + * CSI350 Operating Systems + * Fall 2013 + * Averill Morash, Ben Burwell + * COM.C + */ + +#include +#include +#include +#include "mpx.h"; + + +void interrupt (*vect0c)(); +dcb com; + +int com_opened; + +int com_open(int * flag, int rate) { + unsigned char imr; + unsigned char mcr; + unsigned char ier; + unsigned char lcr; + + disable(); + + if (com_opened == NULL || com_opened == 0) { + com_opened = 1; + } else { + return -2; + } + + // modify the interrupt vector table + vect0c = getvect(0x0c); + setvect(0x0c, &com_int); + + // set baud rate + // first we need to set bit 7 of LCR + // to be 1 so that we can set the baud + // rate divisor. + lcr = inportb(LCR); + lcr = lcr | 0x80; + outportb(LCR, lcr); + + // Now we can access the divisor. + // Clock rate is 1.8432 MHz. We want + // 1200 bps/baud. + // 1843200 / (1200 * 16) = 96 = 0x0060 + // So the MSB is 0x00 and the LSB is 0x60 + + if (rate != 1200) { + return -3; + } + + outport(BRDR_MSB, 0x00); + outportb(BRDR_LSB, 0x60); + + // Now set the LCR + lcr = inportb(LCR); + + // b7, b3, b2 = 0 + lcr = lcr & 0x73; + + // b0, b1 = 1 + lcr = lcr | 0x03; + + outportb(LCR, lcr); + + // set IMR to allow COM interrupts + // set b4 = 0 + imr = inportb(IMR); + imr = imr & 0xef; + outportb(IMR, imr); + + // set MCR to enable interrupts from + // the UART + // on MCR, b3 = 1 + mcr = inportb(MCR); + mcr = mcr | 0x08; + outportb(MCR, mcr); + + // use IER to indicate which serial + // interrupts are enabled + // b0 = 1, b1 = 0 + ier = inportb(IER); + ier = ier | 0x01; + ier = ier & 0xfd; + outportb(IER, ier); + + // set up the DCB + com.event_flag = flag; + dcb_init(&com); + + // enable interrupts + enable(); + + return 0; +} + +void com_close() { + disable(); + setvect(0x0c, vect0c); + enable(); +} + +void interrupt com_int() { + int iir; + int ret = 0; //0 indicates not finished, 1 indicated finshed + + // check IIR to see what caused the interrupt + iir = inportb(IIR); + // only look at bits 1, 2 + iir = iir & 0x06; // 0000-0110 + + if (iir == 0x02) { // 0000-0010 + ret = com_write_int(); + } else if (iir == 0x04) { // 0000-0100 + ret = com_read_int(); + } else { + // something is wrong + return; + } + + if (ret == 1) { + IO_complete(); + } + + // write end of interrupt to 8259 + outportb(0x20, 0x20); + + return; + +} + +int com_read(char far * buffer, int far * length) { + + char dq; + int i; + + if (&com == NULL) { + // com not yet open + return -1; + } + + // check for invalid length + if (*length < 1) { + return -3; + } + + // check if DCB is free + if (com.current_op != NO_OP) { + // previous IO not yet complete + // TODO: we should block this process + return -2; + } + + com.buffer = buffer; + com.length = length; + com.current_op = READ_OP; + com.count = 0; + + strcpy(buffer, ""); + + i = 0; + + while (com.ring_count > 0 && strlen(buffer) < *length) { + + dq = dcb_dequeue(&com); + //strcat(buffer, &dq); + buffer[i] = dq; + i++; + } + + buffer[i] = '\0'; + com.count = i; + + return 0; +} + +int com_write(char far * buffer, int far * length) { + int ier; + + // check that com has been initialized + if (&com == NULL) { + return -1; + } + + // check that com is not busy + if (com.current_op != NO_OP) { + return -2; + } + + // check that the length is valid + if (*length < 1) { + return -3; + } + + // initialize DCB + com.buffer = buffer; + com.length = length; + com.current_op = WRITE_OP; + com.count = 0; + + // enable THR interrupts + ier = inportb(IER); + // bit 1 should be 1 + ier = ier | 0x02; + outportb(IER, ier); + + return 0; +} + +int com_read_int() { + char rbr; + + rbr = inportb(RBR); + + if (com.current_op == READ_OP && com.count < *(com.length)) { + if (rbr == 0x0d || com.count == (*(com.length) - 1)) { + com.buffer[com.count] = '\0'; + com.count++; + *com.length = com.count; + com.current_op = NO_OP; + *(com.event_flag) = 1; + return 1; + } else { + com.buffer[com.count] = rbr; + com.count++; + } + } else { + dcb_enqueue(&com, rbr); + } + + return 0; +} + +int com_write_int() { + int ier; + + // if there are more characters to write + if (*(com.length) > com.count) { + // write a character + outportb(THR, com.buffer[com.count]); + com.count++; + return 0; + } else { + // no chars to write + // disable THR interrupts + ier = inportb(IER); + ier = ier & 0xfd; + outportb(IER, ier); + + // set event flag + com.current_op = NO_OP; + *(com.event_flag) = 1; + return 1; + } +} diff --git a/comdrtst.c b/comdrtst.c new file mode 100644 index 0000000..e5fd8c6 --- /dev/null +++ b/comdrtst.c @@ -0,0 +1,125 @@ +/*********************************************************************** +* +* Name: comdrtst +* +* Purpose: Test program for comdrive read and write +* +* Algorithm: Tests both comdrive for both input (com_read) +* and output (com_write) +* +***************************************************************************/ + +#include +#include + +extern int com_read(char far *buff, int far *len); +extern int com_write(char far *buff, int far *len); + + +int main() +{ + int e_flag; + int tmp; + int rc; + char buffer[100]; + char prompt[20]; + + int length; + + rc = com_open(&e_flag,1200); + + /* if bad return code, display value and exit */ + if (rc != 0) + { + printf("\nrc(com_open) = %d",rc); + exit(); + } + + strcpy(buffer,""); + while (strcmp(buffer,"quit") != 0) + { + /* command prompt on com port */ + length = 16; + e_flag = 0; + rc = com_write("\015\012Enter string: ",&length); + + /* if bad return code, display value and exit */ + if (rc != 0) + { + printf("\nrc(com_write) = %x",rc); + exit(); + } + + /* loop until write complete */ + while (e_flag == 0) + printf("wait for write\n"); + + /* read string */ + length = 30; + e_flag = 0; + rc = com_read(buffer,&length); + + /* if bad return code, display value and exit */ + + if (rc != 0) + { + printf("\nrc(com_read) = %x",rc); + exit(); + } + + /* loop until read is done */ + while (e_flag == 0) + printf("wait - reading\n"); + + + + /* display string entered */ + e_flag = 0; + tmp = 22; + rc = com_write("\015\012string entered was: ",&tmp); + + /* if bad return code, display value and exit */ + if (rc != 0) + { + printf("\nrc(com_write) = %x",rc); + exit(); + } + + /* loop until write is done */ + while (e_flag == 0) + printf("wait for string to be written\n"); + + + e_flag = 0; + rc = com_write(buffer,&length); + + /* if bad return code, display value and exit */ + if (rc != 0) + { + printf("\nrc(com_write) = %x",rc); + } + /* loop until write is done */ + while (e_flag == 0); +} + + length = 29; + e_flag = 0; + rc = com_write ("\015\012Com Driver Test Completed\015\012",&length); + + /* if bad return code, display value and exit */ + if (rc != 0) + { + printf("\nrc(com_write) = %x",rc); + } + + /* loop until last write is done */ + while (e_flag == 0); + + com_close(); + return 0; + } + +int IO_complete(int device, int *stkptr) +{ + return 0; +} diff --git a/comdrtsw.c b/comdrtsw.c new file mode 100644 index 0000000..f8a99b3 --- /dev/null +++ b/comdrtsw.c @@ -0,0 +1,73 @@ +/*********************************************************************** +* +* Name: comdrtsw +* +* Purpose: Test program for write portion of comdrive +* +* Algorithm: Tests com_open(), com_write(), and com_close() +* +************************************************************************/ + +#include +#include ; + +extern int com_read(char far *buff, int far *len); +extern int com_write(char far *buff, int far *len); + +int main() + { + int e_flag; + int tmp; + int rc; + char buffer[100]; + int length; + + /* open com port */ + + rc = com_open(&e_flag,1200); + if ( rc != 0) + { + printf("\nrc(open) = %d",rc); + exit(); + } + + /* prepare test string */ + strcpy(buffer,"This is a test of the com_write procedure .. 1234567890......\015\012"); + length = 64; + + /* print test string 25 times */ + for (tmp = 1; tmp <25; tmp++) + { + e_flag = 0; /* Clear event flag */ + rc = com_write(buffer,&length); /* Start COM write */ + if (rc != 0) + { + printf("\nrc(write) = %d",rc); + exit(); + } + + /* Loop until com write is done. */ + /* This look like an infinite loop */ + while (e_flag == 0) + printf("waiting %d\n",tmp); + } + + e_flag = 0; + length = 28; + rc = com_write("End of Com Driver Test ...\015\012",&length); + if (rc != 0) + { + printf("\nrc(write) = %d",rc); + exit(); + } + + /* loop until com write is done */ + while (e_flag == 0); + + com_close(); + } + +int IO_complete(int device, int *stkptr) +{ + return 0; +} diff --git a/comhan.c b/comhan.c index 7d02799..0f5812f 100644 --- a/comhan.c +++ b/comhan.c @@ -30,8 +30,9 @@ #define CMD_TERMINATE 14 #define CMD_SETPRI 15 #define CMD_DISPATCH 16 +#define CLOCK 17 -#define NUM_CMDS 17 +#define NUM_CMDS 18 int length; /* Length of the command line. */ unsigned sp_save; /* A stack save for mod 4 dispatch. */ @@ -44,12 +45,12 @@ char *cmds[] = { "version", "date", "directory", "stop", "help", "prompt", "alias", "show", "allocate", "free", "load", "resume", "run", "suspend", "terminate", "setpriority", - "dispatch", NULL}; + "dispatch", "clock", NULL}; char *aliases[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", - " ", NULL}; + " ", " ", NULL}; /* * comhan() This is the command handler for the MPX OS. @@ -91,6 +92,7 @@ void comhan() { case CMD_TERMINATE: cmd_terminate(args); break; case CMD_SETPRI: cmd_setpri(args); break; case CMD_DISPATCH: cmd_dispatch(); break; + case CLOCK: cmd_clock(args); break; default: printf("Can't recognize.\n"); break; @@ -123,7 +125,7 @@ int get_cmd(char cmd[]){ int set_args(char buffer[], char *args[]) { /* use string tok to set the contents of args from buffer and return the number of args (will go into argc) */ - char separators[5] = " =/,"; //Characters that separate tokens + char separators[5] = " =/,:"; //Characters that separate tokens int i = 0; //loop control args[i] = strtok(buffer, separators); //Get first token @@ -236,6 +238,7 @@ void cmd_help(char *args[]) { help[CMD_TERMINATE] = "terminate name Terminates the process called name"; help[CMD_SETPRI] = "setpriority name=ppp Sets the priority of process name"; help[CMD_DISPATCH] = "dispatch Runs each process once"; + help[CLOCK] = "clock [stop|start] Perform clock operations"; // print header printf( " Name Use \n"); @@ -698,3 +701,32 @@ void cmd_dispatch() { dispatch(); return; } + +/* + * stop, start, set, or show the clock based on args[1] + */ +void cmd_clock(char *args[]){ + int hr, m, s; + int ret; + // decide what clock operation to perform + if (strcmp(args[1], "stop") == 0) { + stop_clock(); + return; + } else if (strcmp(args[1], "start") == 0) { + start_clock(); + return; + } else if (strcmp(args[1], "") == 0) { + read_clock(&hr, &m, &s); + printf("The current time is %d:%d:%d\n", hr, m, s); + return; + } else { + // the remaining case is to set the clock + // parse the input - should be "hh:mm:ss" + ret = set_clock(atoi(args[1]), atoi(args[2]), atoi(args[3])); + // call sys_sppt's set_clock(hr, mn, s) + // if set_clock returns -1 print error message + if (ret == -1) { + printf("Error setting clock\n"); + } + } +} diff --git a/comprtts.c b/comprtts.c new file mode 100644 index 0000000..1b996d1 --- /dev/null +++ b/comprtts.c @@ -0,0 +1,113 @@ +/*********************************************************************** +* +* Name: comprtts +* +* Purpose: Test program for both comdrive and prtdrive +* +* Algorithm: Tests both comdriver and prtdriver with overlapped +* out put to both devices. +* +*************************************************************************/ + +int prt_flag; +int com_flag; +int tmp; +int rc; +char buffer[100]; +char prompt[20]; +int length; +extern int com_read(char far *buff, int far *len); +extern int com_write(char far *buff, int far *len); +extern int prt_write(char far *buff,int far *len); + + +int main() +{ + + rc = prt_open(&prt_flag); + rc = com_open(&com_flag,1200); + + + strcpy(buffer,""); + + while (strcmp(buffer,"quit") != 0) + { + /* command prompt on com port */ + length = 16; + com_flag = 0; + rc = com_write("\015\012Enter string: ",&length); + + /* loop until write complete */ + while (com_flag == 0) + printf("Writing prompt to Enter string\n"); + + + /* read string */ + + length = 40; + com_flag = 0; + rc = com_read(buffer,&length); + + + /* loop until read is done */ + + while (com_flag == 0) + printf("Reading string from serial port\n"); + + /* display string entered */ + + com_flag = 0; + tmp = 22; + rc = com_write("\015\012string entered was: ",&tmp); + + /* display string entered */ + prt_flag = 0; + tmp = 22; + rc = prt_write("\015\012string entered was: ",&tmp); + + + while ((com_flag == 0) || (prt_flag == 0)) + printf(" com_flag:%3d prt_flag:%3d \n",com_flag,prt_flag); + + com_flag = 0; + rc = com_write(buffer,&length); + + + prt_flag = 0; + rc = prt_write(buffer,&length); + + + while ((com_flag == 0) || (prt_flag == 0)) + printf(" com_flag:%3d prt_flag:%3d \n",com_flag,prt_flag); + + } + + length = 33; + com_flag = 0; + rc = com_write ("\015\012Com/prt driver test completed\015\012",&length); + + /* if bad return code, display value and exit */ + if (rc != 0) + { + printf("\nrc(com_write) = %x",rc); + } + + length = 34; + prt_flag = 0; + rc = prt_write("\015\012Com/prt driver test completed\015\012\n",&length); + + + /* loop until last writes are done */ + while ((com_flag == 0) || (prt_flag == 0)) + printf(" com_flag:%3d prt_flag:%3d \n",com_flag,prt_flag); + + com_close(); + prt_close(); + } + +int IO_complete(int device, int *stkptr) +{ + return 0; +} + + diff --git a/dcb.c b/dcb.c new file mode 100644 index 0000000..e2c1e4c --- /dev/null +++ b/dcb.c @@ -0,0 +1,65 @@ +/** + * MPX OS + * Operating Systems - Fall 2013 + * Averill Morash, Ben Burwell + */ + +#include "mpx.h" + +/** + * Returns the character at the front of the ring queue + * associated with the dcb, or '\0' if the queue is empty. + */ +char dcb_dequeue(dcb *d) { + char c; + + if (d->ring_count == 0) { + return '\0'; + } + + c = d->ring[d->ring_front]; + + if (d->ring_front == d->ring_size - 1) { + d->ring_front = 0; + } else { + d->ring_front++; + } + + d->ring_count--; + + return c; +} + +/** + * Adds the given character to the end of the ring queue + * in the given dcb if there is room + */ +void dcb_enqueue(dcb *d, char c) { + if (d->ring_count >= d->ring_size) { + return; + } + + if (d->ring_rear == d->ring_size - 1) { + d->ring_rear = 0; + } else { + d->ring_rear++; + } + + d->ring[d->ring_rear] = c; + + d->ring_count++; + + return; +} + +/** + * Set up a dcb's circular queue, and set the current_op to NO_OP + */ +void dcb_init(dcb *d) { + d->ring_front = 0; + d->ring_rear = -1; + d->ring_size = INPUT_BUFFER_MAX; + d->ring_count = 0; + d->current_op = NO_OP; + return; +} diff --git a/load.c b/load.c index dc39115..0d2067a 100644 --- a/load.c +++ b/load.c @@ -60,7 +60,7 @@ int load(unsigned *load_addr,char pname[]) /* SEGMENT REGISTER VALUE CALL */ segregs = &segr; - segread(segregs); /* returns current segme disablter values */ + segread(segregs); /* returns current segment register values */ strcpy(fname, pname); strcat(fname, ".MPX"); diff --git a/main.c b/main.c index a5346b1..dac79aa 100644 --- a/main.c +++ b/main.c @@ -65,42 +65,6 @@ int main(void) { // initialize the currently running process cop = NULL; - // initialize the mod3 test pcbs - /* - pcb_addr = get_pcb(pcb_list); - build_pcb(pcb_addr, "test1", APP_PROCESS, READY, NOT_SUSPENDED, 0, _CS, - (unsigned)test1, _DS, 0x200); - insert_pcb(&ready_queue, pcb_addr, 0); - - pcb_addr = get_pcb(pcb_list); - build_pcb(pcb_addr, "test2",APP_PROCESS, READY, NOT_SUSPENDED, 0, _CS, - (unsigned)test2, _DS, 0x200); - insert_pcb(&ready_queue, pcb_addr, 0); - - pcb_addr = get_pcb(pcb_list); - build_pcb(pcb_addr, "test3", APP_PROCESS, READY, NOT_SUSPENDED, 0, _CS, - (unsigned)test3, _DS, 0x200); - insert_pcb(&ready_queue, pcb_addr, 0); - - pcb_addr = get_pcb(pcb_list); - build_pcb(pcb_addr, "test4", APP_PROCESS, READY, NOT_SUSPENDED, 0, _CS, - (unsigned)test4, _DS, 0x200); - insert_pcb(&ready_queue, pcb_addr, 0); - - pcb_addr = get_pcb(pcb_list); - build_pcb(pcb_addr, "test5", APP_PROCESS, READY, NOT_SUSPENDED, 0, _CS, - (unsigned)test5, _DS, 0x200); - insert_pcb(&ready_queue, pcb_addr, 0); - - - // initialize the system stack - _SP = (unsigned) &sys_stack[STACK_SIZE -1]; - - //get the show on the road! - sys_init(); - dispatch(); - */ - sys_init(); comhan(); /* Execute the command handler */ sys_exit(); diff --git a/mpx.h b/mpx.h index 70e70a1..305e2a0 100644 --- a/mpx.h +++ b/mpx.h @@ -12,8 +12,7 @@ #define EXIT_CODE 0 /* Process requesting termination. code. */ #define CON 1 /* The console device - keyboard & monitor. */ #define PRT 2 /* The printer device - LPT1. */ -#define COM 3 /* The serial port - COM1. -#define */ +#define COM 3 /* The serial port - COM1. */ /* MPX System request types. */ @@ -63,6 +62,43 @@ struct pcbstruct { }; typedef struct pcbstruct pcb; +#define INPUT_BUFFER_MAX 40 +#define NO_OP 0 +#define READ_OP 1 +#define WRITE_OP 2 + +#define MCR 0x3fc +#define IER 0x3f9 +#define LCR 0x3fb +#define RBR 0x3f8 +#define THR 0x3f8 +#define BRDR_LSB 0x3f8 +#define BRDR_MSB 0x3f9 +#define IIR 0x3fa + +#define IMR 0x21 /* Port address of IMR */ +#define CMR 0x43 /* Command mode register */ +#define IRQ0 0x01 /* Mask for Timer */ +#define CLOCK_ENABLE (0xff - IRQ0) /* Mask to clear Timer bit */ +#define CLOCK_DISABLE (0x00 + 1) /* Mask to set Timer bit */ + +/* Device Control Block */ +struct dcb_struct { + unsigned current_op; + unsigned * event_flag; + far int * length; + far char * buffer; + int count; + far char * c_buffer; + char ring[INPUT_BUFFER_MAX]; + int ring_front; + int ring_rear; + int ring_count; + int ring_size; +}; + +typedef struct dcb_struct dcb; + /* Function prototypes. */ /* main.c */ @@ -89,6 +125,7 @@ void cmd_suspend(char *[]); void cmd_terminate(char *[]); void cmd_setpri(char *[]); void cmd_dispatch(); +void cmd_clock(char *[]); void sys_req(int,int,char *,int *); /* MPX system request function. */ int directory(dir *, int); /* Support function to load the */ @@ -107,27 +144,53 @@ int insert_pcb(pcb**, pcb *, int); int remove_pcb(pcb**, pcb *); /** - * TestN.C + * DCB.c */ -void test1(void); -void test2(void); -void test3(void); -void test4(void); -void test5(void); - +void dcb_enqueue(dcb*, char); +char dcb_dequeue(dcb*); +void dcb_init(dcb*); /** * Sys_sppt.c */ void sys_inti(void); void sys_exit(void); +void clock_open(void); +void clock_close(void); +void stop_clock(void); +void start_clock(void); +int set_clock(int, int, int); +void read_clock(int*, int*, int*); void interrupt dispatch(void); void interrupt sys_call(void); +void interrupt clock_int(void); /** * Load.c */ int load(unsigned *,char []); +/** + * Com.c + */ +int com_open(int *, int); +void com_close(void); +void interrupt com_int(void); +int com_read(char far *, int far *); +int com_write(char far *, int far *); +int com_read_int(); +int com_write_int(); + +/** + * Printer.c + */ +#define PCR 0x3be +#define PDR 0x3bc + +int prt_open(int *); +int prt_write(char far *, int *); +int prt_close(void); +void interrupt prt_int(void); + /* * Global variable EXTERN directives. * @@ -137,7 +200,7 @@ int load(unsigned *,char []); * is declared in a *.c file. */ #define DIR_SIZE 20 - +extern dcb com; extern dir direct[]; /* Array of directory entries - see direct.c */ extern int directory(dir *direct, int dir_size); extern pcb * pcb_list; diff --git a/printer.c b/printer.c new file mode 100644 index 0000000..840d811 --- /dev/null +++ b/printer.c @@ -0,0 +1,157 @@ +/** + * Operating Systems + * Mod 6 + * Averill and Ben + * Writing awesome printer stuff. + */ + +#include +#include +#include "mpx.h"; + +void interrupt (*vect0f)(); +dcb prt; + +int prt_opened; + +int prt_open(int * prt_flag) { + unsigned char imr; + unsigned char pcr; + + disable(); + + if (prt_opened == NULL || prt_opened == 0) { + prt_opened = 1; + } else { + return -2; + } + + // set up vector interrupt + vect0f = getvect(0x0f); + setvect(0x0f, &prt_int); + + // enable printer interrupts on 8259 + imr = inportb(IMR); + imr = imr & 0x7f; //0111-1111 + outportb(IMR, imr); + + // clear init bit (b2), set select bit (b3) + // 0000 1010 + outportb(PCR, 0x0a); + + // initialize a printer control block + prt.current_op = NO_OP; + prt.event_flag = prt_flag; + prt.count = 0; + + enable(); + return 0; +} + +int prt_write(char far *buffer, int *length) { + unsigned char pcr; + + disable(); + // check that prt isn't busy + if (prt.current_op != NO_OP) { + return -2; + } + + // check that length is valid + if (*length < 1) { + return -3; + } + + //save buffer and length in prt dcb + prt.buffer = buffer; + prt.length = length; + prt.current_op = WRITE_OP; + prt.count = 0; + + // enable printer interrupts on PCR + // 0001 1010 + outportb(PCR, 0x1a); + + // strobe printer + // 0001 1011 + outportb(PCR, 0x1d); + + // print a null + // NOTE: something is not right here because when i print something + // other than a null it still doesn't print + outportb(PDR, 0x00); + + // unstrobe printer + // 0001 1010 + outportb(PCR, 0x1c); + + enable(); + return 0; +} + +int prt_close() { + unsigned char pcr; + unsigned char imr; + + disable(); + + // reset printer + // set init bit (b2) to 1 all else clear + // 0000 0100 + outportb(PCR, 0x04); + + //disable printer interrupts + imr = inportb(IMR); + imr = imr | 0x80; + outportb(IMR, imr); + + // restore ms-dos's printer interrupt vector + setvect(0x0f, vect0f); + + enable(); + return 0; +} + +void interrupt prt_int() { + unsigned char pcr; + int *lst_stk; + float temp; + + lst_stk = _BP; + + // if no more char to write + if (prt.count == *(prt.length)) { + // disable printer interrupts at PCR + // clear b4 on PCR + pcr = inportb(PCR); + pcr = pcr & 0xef; // 1110-1111 + outportb(PCR, pcr); + + // set event flag + prt.current_op = NO_OP; + *(prt.event_flag) = 1; + + // call io-complete + // TODO: the book says (pg 86) that there should be stuff passed to io-complete + IO_complete(2, lst_stk); + + // send end of interrupt signal + outportb(0x20, 0x20); + } else { + + // strobe printer + // 0001 1101 + outportb(PCR, 0x1d); + + // write char to PDR + outportb(PDR, prt.buffer[prt.count]); + prt.count++; + + // unstrobe printer + // 0001 1100 + outportb(PCR, 0x1c); + } + + // send EOI + outportb(0x20, 0x20); +} \ No newline at end of file diff --git a/prtdrtst.c b/prtdrtst.c new file mode 100644 index 0000000..52de3af --- /dev/null +++ b/prtdrtst.c @@ -0,0 +1,68 @@ +/*********************************************************************** +* +* Name: prtdrtst +* +* Purpose: Test program for prtdrive +* +* Algorithm: Tests prt_open, prt_write, and prt_close of prtdrive +* +**************************************************************************/ + +#include +#include ; + +int main() +{ + int e_flag; + int tmp; + int rc; + char buffer[100]; + int length; + extern int prt_write(char far *buff,int far *len); + + /* open printer */ + rc = 1; + rc = prt_open(&e_flag); + if ( rc != 0) { + printf("\nrc(open) = %d",rc); + exit(); + } + + /* prepare test string */ + strcpy(buffer,"This is a test of the printer driver ... 1234567890 ...........\015\012"); + length = 65; + + /* print test string 25 times */ + for (tmp = 1; tmp < 26; tmp++) { + e_flag = 0; + rc = prt_write(buffer,&length); + if (rc != 0) { + printf("\nrc(write) = %d",rc); + } + + /* loop until printer done */ + while (e_flag == 0) + printf("waiting %d\n",tmp); + } + + + + e_flag = 0; + length = 29; + rc = prt_write("End of Printer Driver Test\015\012\n",&length); + if (rc != 0) { + printf("\nrc(write) = %d",rc); + } + + /* loop until printer done */ + while (e_flag == 0) + printf("Waiting for Printer test to finish\n"); + + prt_close(); + return 0; +} + +int IO_complete(int device, int *stkptr) +{ + return 0; +} diff --git a/qtest.c b/qtest.c new file mode 100644 index 0000000..a0e97d0 --- /dev/null +++ b/qtest.c @@ -0,0 +1,19 @@ +#include +#include "mpx.h" + +int main() { + dcb com; + char c; + + dcb_init(&com); + + for (c = 'a'; c <= 'z'; c++) { + dcb_enqueue(&com, c); + } + + for (c = 'a'; c <= 'z' + 2; c++) { + printf("Dequeueing %c \n", dcb_dequeue(&com)); + } + + return 0; +} \ No newline at end of file diff --git a/sys_sppt.c b/sys_sppt.c index 80ae62d..7facead 100644 --- a/sys_sppt.c +++ b/sys_sppt.c @@ -20,23 +20,31 @@ #include "mpx.h" void interrupt (*vect60)(); /* Storage for DOS int 60h */ - /* interrupt vector. */ + /* interrupt vector. */ +void interrupt (*vect08)(); /* Storage for DOS int 08h */ + /* interrupt vector. */ +unsigned long clock; /* The clock counter */ void sys_init() { /* set up interrupt vector for MPX sys_calls */ - vect60 = getvect(0x60); setvect(0x60,&sys_call); + + // set up the clock + clock_open(); } void sys_exit() { - /* restore interrupt vector 60 and exit */ + // restore the clock + clock_close(); - setvect(0x60,vect60); - exit(); + /* restore interrupt vector 60 and exit */ + setvect(0x60,vect60); + + exit(); } @@ -83,3 +91,133 @@ void interrupt sys_call() dispatch(); } + +/* + * Set up MXP clock + */ +void clock_open() { + unsigned char imr; + + disable(); + /* set up interrupt vector for timer interrupts */ + vect08 = getvect(0x08); + setvect(0x08,&clock_int); + + // set the timer mode + outportb(CMR, 0x36); + outportb(0x40, 0); + outportb(0x40, 0); + + // set the count clock + clock = 0L; + + // enable timer interrupts + imr = inportb(IMR); // Get current IMR + imr = imr & CLOCK_ENABLE; // Clear timer bit + outportb(IMR, imr); // Set new IMR + + enable(); +} + +/* + * Restore the MS DOS clock + */ +void clock_close() { + disable(); + setvect(0x08,vect08); + enable(); +} + +void interrupt clock_int() { + disable(); + // if it's been 24 hours, reset clock to 0 + if (clock >= 1572462L) { + clock = 0L; + } else { + clock++; + } + outportb(0x20, 0x20); + enable(); +} + +void stop_clock() { + unsigned char imr; + disable(); + + imr = inportb(IMR); // Get the old imr + imr = imr | CLOCK_DISABLE; // Disable timer interrupts + outportb(IMR, imr); // Set the new imr + + enable(); +} + +/* + * Enables the timer interrupt + */ +void start_clock() { + unsigned char imr; + disable(); + + imr = inportb(IMR); // Get the old imr + imr = imr & CLOCK_ENABLE; // Enable timer interrupts + outportb(IMR, imr); // Set the new imr + + enable(); +} + +/* + * Sets the value of the clock + */ +int set_clock(int hr, int m, int s) { + unsigned long ticks; + + // Validate input + if (hr > 23 || hr < 0 || m > 59 || m < 0 || s > 59 || s < 0) { + return -1; + } + + // set clock + ticks = 0L; + ticks = ((unsigned long)hr * 3600L * 91L / 5L); + ticks += ((unsigned long)m * 60L * 91L / 5L); + ticks += ((unsigned long)s * 91L / 5L); + + disable(); + clock = ticks; + enable(); + + return 0; +} + +/* + * Gets the value of the clock + */ +void read_clock(int *hr, int *m, int *s) { + unsigned long ticks; + long total_seconds = 0L; + int l_hr = 0; + int l_m = 0; //local vars for hr, m + + disable(); + ticks = clock; + enable(); + + total_seconds = ticks * 10L; + total_seconds = total_seconds / 182L; + + //count the whole hours + while (total_seconds >= 3600L) { + l_hr++; + total_seconds = total_seconds - 3600L; + } + + //count the whole minutes + while (total_seconds >= 60L) { + l_m++; + total_seconds = total_seconds - 60L; + } + + *hr = l_hr; + *m = l_m; + *s = total_seconds; +} -- cgit v1.2.3