aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--com.c259
-rw-r--r--comdrtst.c125
-rw-r--r--comdrtsw.c73
-rw-r--r--comhan.c40
-rw-r--r--comprtts.c113
-rw-r--r--dcb.c65
-rw-r--r--load.c2
-rw-r--r--main.c36
-rw-r--r--mpx.h83
-rw-r--r--printer.c157
-rw-r--r--prtdrtst.c68
-rw-r--r--qtest.c19
-rw-r--r--sys_sppt.c148
13 files changed, 1132 insertions, 56 deletions
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 <dos.h>
+#include <stdio.h>
+#include <string.h>
+#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 <stdio.h>
+#include <dos.h>
+
+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 <stdio.h>
+#include <dos.h>;
+
+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 <dos.h>
+#include <stdio.h>
+#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 <stdio.h>
+#include <dos.h>;
+
+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 <stdio.h>
+#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;
+}