16 Data= 0, /* xmit/rcv buffer */
17 Iena= 1, /* interrupt enable */
18 Ircv= (1<<0), /* for char rcv'd */
19 Ixmt= (1<<1), /* for xmit buffer empty */
20 Irstat=(1<<2), /* for change in rcv'er status */
21 Imstat=(1<<3), /* for change in modem status */
22 Istat= 2, /* interrupt flag (read) */
23 Tctl= 2, /* test control (write) */
24 Format= 3, /* byte format */
25 Bits8= (3<<0), /* 8 bits/byte */
26 Stop2= (1<<2), /* 2 stop bits */
27 Pena= (1<<3), /* generate parity */
28 Peven= (1<<4), /* even parity */
29 Pforce=(1<<5), /* force parity */
30 Break= (1<<6), /* generate a break */
31 Dra= (1<<7), /* address the divisor */
32 Mctl= 4, /* modem control */
33 Dtr= (1<<0), /* data terminal ready */
34 Rts= (1<<1), /* request to send */
35 Ri= (1<<2), /* ring */
36 Inton= (1<<3), /* turn on interrupts */
37 Loop= (1<<4), /* loop back */
38 Lstat= 5, /* line status */
39 Inready=(1<<0), /* receive buffer full */
40 Oerror=(1<<1), /* receiver overrun */
41 Perror=(1<<2), /* receiver parity error */
42 Ferror=(1<<3), /* rcv framing error */
43 Outready=(1<<5), /* output buffer empty */
44 Mstat= 6, /* modem status */
45 Ctsc= (1<<0), /* clear to send changed */
46 Dsrc= (1<<1), /* data set ready changed */
47 Rire= (1<<2), /* rising edge of ring indicator */
48 Dcdc= (1<<3), /* data carrier detect changed */
49 Cts= (1<<4), /* complement of clear to send line */
50 Dsr= (1<<5), /* complement of data set ready line */
51 Ring= (1<<6), /* complement of ring indicator line */
52 Dcd= (1<<7), /* complement of data carrier detect line */
53 Scratch=7, /* scratchpad */
54 Dlsb= 0, /* divisor lsb */
55 Dmsb= 1, /* divisor msb */
61 typedef struct Uart Uart;
65 uchar sticky[8]; /* sticky write register values */
68 void (*rx)(int); /* routine to take a received character */
69 int (*tx)(void); /* routine to get a character to transmit */
78 #define UartFREQ 1843200
80 #define uartwrreg(u,r,v) outb((u)->port + r, (u)->sticky[r] | (v))
81 #define uartrdreg(u,r) inb((u)->port + r)
84 * set the baud rate by calculating and setting the baudrate
85 * generator constant. This will work with fairly non-standard
89 uartsetbaud(Uart *up, int rate)
93 brconst = (UartFREQ+8*rate-1)/(16*rate);
95 uartwrreg(up, Format, Dra);
96 outb(up->port+Dmsb, (brconst>>8) & 0xff);
97 outb(up->port+Dlsb, brconst & 0xff);
98 uartwrreg(up, Format, 0);
105 uartdtr(Uart *up, int n)
108 up->sticky[Mctl] |= Dtr;
110 up->sticky[Mctl] &= ~Dtr;
111 uartwrreg(up, Mctl, 0);
118 uartrts(Uart *up, int n)
121 up->sticky[Mctl] |= Rts;
123 up->sticky[Mctl] &= ~Rts;
124 uartwrreg(up, Mctl, 0);
128 uartintr(Ureg*, void *arg)
135 for(loops = 0; loops < 1024; loops++){
136 s = uartrdreg(up, Istat);
138 case 6: /* receiver line status */
139 l = uartrdreg(up, Lstat);
146 case 4: /* received data available */
148 ch = inb(up->port+Data);
153 case 2: /* transmitter empty */
158 outb(up->port+Data, ch);
163 case 0: /* modem status */
164 uartrdreg(up, Mstat);
170 print("weird modem interrupt #%2.2ux\n", s);
174 panic("uartintr: 0x%2.2ux", uartrdreg(up, Istat));
178 * turn on a port's interrupts. set DTR and RTS
186 up->sticky[Iena] = 0;
188 up->sticky[Iena] |= Ixmt;
190 up->sticky[Iena] |= Ircv|Irstat;
191 uartwrreg(up, Iena, 0);
194 * turn on DTR and RTS
201 uartdisable(Uart* up)
204 * Disable interrupts.
206 up->sticky[Iena] = 0;
207 uartwrreg(up, Iena, 0);
213 uartspecial(int port, void (*rx)(int), int (*tx)(void), int baud)
221 vector = VectorUART0;
226 vector = VectorUART1;
233 if(uart != nil && uart != up)
239 setvec(vector, uartintr, up);
243 * set rate to 9600 baud.
246 * interrupts enabled.
248 uartsetbaud(up, 9600);
249 up->sticky[Format] = Bits8;
250 uartwrreg(up, Format, 0);
251 up->sticky[Mctl] |= Inton;
252 uartwrreg(up, Mctl, 0x0);
258 uartsetbaud(up, baud);
267 if((up = uart) == nil)
269 for(i = 0; i < 100; i++){
270 if(uartrdreg(up, Lstat) & Outready)
274 outb(up->port+Data, c);
278 uartputs(IOQ *q, char *s, int n)
283 if((up = uart) == nil)
291 if(up->txbusy == 0 && (c = q->getc(q)) != -1){
304 if((up = uart) == nil)
306 for(timeo = 0; timeo < 2000 && up->txbusy; timeo++)