* added compilers lcc and bcc (linux86)
[mascara-docs.git] / i86 / mtx / mtx / samples / SERIAL / s.c
blob6bc0e7f6edcb03c8bf5c880f676d2a31978ffb4b
1 /****************************************************************************
2 serial.c file for SERIAL DRIVER
3 Each serial terminal is represented by a stty struct consisting of
4 INPUT section = a circular buffer with incount chars
5 OUTPUT section = a circular buffer with outcount chars
6 Process and interrupt handler synchronize by sleep()/wakeup()
7 ***************************************************************************/
9 /**************** CONSTANTS ***********************/
10 #define BUFLEN 80
11 #define NSTTY 2 /* number of serial ports */
13 /* offset from serial ports base */
14 #define DATA 0 /* Data reg for Rx, Tx */
15 #define DIVL 0 /* When used as divisor */
16 #define DIVH 1 /* to generate baud rate */
17 #define IER 1 /* Interrupt Enable reg */
18 #define IIR 2 /* Interrupt ID rer */
19 #define LCR 3 /* Line Control reg */
20 #define MCR 4 /* Modem Control reg */
21 #define LSR 5 /* Line Status reg */
22 #define MSR 6 /* Modem Status reg */
24 /**** The serial terminal data structure ****/
25 typedef struct stty {
27 /* I/O port base address */
28 int port;
30 /* input buffer */
31 char inbuf[BUFLEN];
32 int inhead, intail, incount;
34 /* output buffer */
35 char outbuf[BUFLEN];
36 int outhead, outtail, outcount;
38 // coontrol section: (erase, kill, interrupt keys, etc)
39 // NOT shown
41 } STTY;
43 STTY stty[NSTTY]; // actual stty data structure; one per terminal
45 /************ serial ports initialization ***************/
47 char *message[2] = { "Serial Port 0 Ready\n\r\007", "Serial Port 1 Ready\n\r\007"};
49 int sinit() // init() function
51 int i;
52 STTY *t;
54 /* initialize stty[] and serial port control registers */
56 for (i = 0; i < NSTTY; i++){
57 t = &stty[i];
59 /* initialize data structures and pointers */
60 if (i==0)
61 t->port = 0x3F8; /* COM1 base address */
62 else
63 t->port = 0x2F8; /* COM2 base address */
65 printf("sinit : port %x\n", t->port);
66 t->inhead = t->intail = t->incount = 0;
67 t->outhead = t->outtail = t->outcount = 0;
69 lock(); // CLI; no interrupts
70 out_byte(t->port+IER, 0x00); /* disable serial port interrupts */
72 out_byte(t->port+LCR, 0x80); /* ready to use 3f9,3f8 as divisor */
73 out_byte(t->port+DIVH, 0x00);
74 out_byte(t->port+DIVL, 12); /* divisor = 12 ===> 9600 bauds */
76 /******** term 9600 /dev/ttyS0: 8 bits/char, no parity *************/
77 out_byte(t->port+LCR, 0x03);
79 /*******************************************************************
80 Writing to 3fc ModemControl tells modem : DTR, then RTS ==>
81 let modem respond as a DCE. Here we must let the (crossed)
82 cable tell the TVI terminal that the "DCE" has DSR and CTS.
83 So we turn the port's DTR and RTS on.
84 ********************************************************************/
86 out_byte(t->port+MCR, 0x0B); /* 1011 ==> INTERRUPT, RTS, DTR on */
87 out_byte(t->port+IER, 0x01); /* Enable Rx interrupt, Tx off */
89 unlock();
91 enable_irq(4-i); // COM1: IRQ4; COM2: IRQ3
93 /* show greeting message */
94 sputline(i, message[i]);
98 //==================== LOWER HALF ROUTINES (Interrupt handlers) =======================
99 int s0handler()
101 shandler(0);
104 int s1handler()
106 shandler(1);
109 int shandler(port) int port;
111 STTY *t;
112 int IntID, LineStatus, ModemStatus, intType, c;
114 t = &stty[port]; /* IRQ 4 interrupt : COM1 = stty[0] */
116 IntID = in_byte(t->port+IIR); /* read InterruptID Reg */
117 LineStatus= in_byte(t->port+LSR); /* read LineStatus Reg */
118 ModemStatus=in_byte(t->port+MSR); /* read ModemStatus Reg */
120 intType = IntID & 7; /* mask out all except the lowest 3 bits */
121 switch(intType){
122 case 6 : do_errors(t); break; /* 110 = errors */
123 case 4 : do_rx(t); break; /* 100 = rx interrupt */
124 case 2 : do_tx(t); break; /* 010 = tx interrupt */
125 case 0 : do_modem(t); break; /* 000 = modem interrupt */
127 out_byte(0x20, 0x20); /* reenable the 8259 controller */
130 int do_errors() { printf("under construction\n"); }
132 int do_modem() { printf("don't have a modem\n"); }
134 int do_rx(t) STTY *t; /* rx interrupt */
136 int c;
138 c = in_byte(t->port) & 0x7F; /* read the ASCII char from port */
140 printf("\n%x rx_interrupt : c=%c", t->port, c);
142 if (t->incount >= BUFLEN){ // if input buf is full, discard
143 out_byte(t->port, 007); // but sound warning beep
144 return;
147 t->inbuf[t->inhead++] = c; /* put char into circular inbuf[] */
148 t->inhead %= BUFLEN; /* advance inhead */
149 t->incount++;
151 wakeup(&t->incount); // wakeup process that may be sleeping
154 int do_tx(t) STTY *t; // tx_interrupt
156 int c;
158 if (t->outcount==0){ // nothing to do
159 out_byte(t->port+IER, 0x01);
160 return;
162 c = t->outbuf[t->outtail++];
163 t->outtail %= BUFLEN;
164 t->outcount--;
166 out_byte(t->port, c);
168 wakeup(&t->outcount);
171 /**************** Upper half routines CALLED BY process **************:
172 sgetc()/sputs() which interact with Interrupt handlers
173 **********************************************************************/
175 int sgetc(port) int port;
177 STTY *t;
178 int c;
180 t = &stty[port];
182 while (t->incount==0)
183 sleep(&t->incount);
185 lock(); /* disable interrupts */
186 c = t->inbuf[t->intail++];
187 t->intail %= BUFLEN;
188 t->incount--;
189 unlock();
190 return(c);
193 int sputc(port, c) int port, c;
195 STTY *t = &stty[port];
197 while(t->outcount==BUFLEN)
198 sleep(&t->outcount);
200 lock();
201 if (t->outcount==0){
202 out_byte(t->port, c);
203 out_byte(t->port+IER, 0x03);
205 else{
206 t->outbuf[t->outhead++] = c;
207 t->outhead %= BUFLEN;
208 t->outcount++;
210 unlock();
212 /********************* END OF SERIAL DRIVER *************************************/
215 /***** line mode functions sgetline()/sputline() based on sgetc()/sputc() ************/
217 int sgetline(port, line) int port; char *line;
219 while ( (*line = sgetc(port)) != '\r'){
220 line++;
222 *(line) = 0; /* change \r to null char */
223 return strlen(line);
226 int sputline(port, line) int port; char *line;
228 while (*line){
229 sputc(port, *line);
230 line++;
234 /******* User Interface fucntions to serial ports ************/
235 int sgets()
237 char line[64];
238 int port;
240 printf("enter port # (0|1):");
241 port = getc() - '0';
242 printf("port=%d\n", port);
244 sputline(port, "enter a line from serial terminal : ");
245 sgetline(port, line);
246 printf("\nline=%s\n", line);
247 sputline(port, line);
248 sputline(port,"\n\r");
251 int sputs()
253 char line[64];
254 int port;
256 printf("enter port # (0|1):");
257 port = getc() - '0';
259 printf("enter a line : ");
260 gets(line);
261 strcat(line, "\n\r");
262 printf("to serial port %d: line=%s\n", port, line);
264 sputline(port, line);
265 printf("done\n");