6 #define UART1_BASE 0x3f8
7 #define UART2_BASE 0x2f8
22 /* interrupt enable register bits */
28 /* fifo control register bits */
29 #define FIFO_ENABLE 0x01
30 #define FIFO_RECV_CLEAR 0x02
31 #define FIFO_SEND_CLEAR 0x04
33 #define FIFO_TRIG_4 0x40
34 #define FIFO_TRIG_8 0x80
35 #define FIFO_TRIG_14 0xc0
37 /* interrupt id register bits */
38 #define IID_PENDING 0x01
42 #define IID_FIFO_EN 0xc0
44 #define IID_SOURCE 0xe
50 #define IID_STATUS 0x6
52 /* line control register bits */
53 #define LCTL_BITS_8 0x03
54 #define LCTL_STOP_2 0x04
55 #define LCTL_DLAB 0x80
56 #define LCTL_8N1 LCTL_BITS_8
57 #define LCTL_8N2 (LCTL_BITS_8 | LCTL_STOP_2)
59 /* modem control register bits */
62 #define MCTL_OUT1 0x04
63 #define MCTL_OUT2 0x08
64 #define MCTL_LOOP 0x10
66 /* line status register bits */
68 #define LST_ERR_OVER 0x02
69 #define LST_ERR_PARITY 0x04
70 #define LST_ERR_FRAME 0x08
71 #define LST_ERR_BRK 0x10
72 #define LST_TREG_EMPTY 0x20
73 #define LST_TIDLE 0x40
74 #define LST_ERROR 0x80
76 /* modem status register bits */
77 #define MST_DELTA_CTS 0x01
78 #define MST_DELTA_DSR 0x02
80 #define MST_DELTA_DCD 0x08
86 /* interrupt controller stuff */
87 #define PIC1_CMD_PORT 0x20
88 #define PIC1_DATA_PORT 0x21
89 #define PIC2_CMD_PORT 0xa0
90 #define PIC2_DATA_PORT 0xa1
93 #define COM_FMT_8N1 LCTL_8N1
94 #define COM_FMT_8N2 LCTL_8N2
101 int inbuf_ridx, inbuf_widx;
104 #define BNEXT(x) (((x) + 1) & 0xff)
105 #define BEMPTY(b) (b##_ridx == b##_widx)
108 static int have_recv(int base);
109 static void recv_intr(void);*/
111 static struct serial_port ports[2];
114 static int uart_base[] = {UART1_BASE, UART2_BASE};
115 /*static int uart_irq[] = {UART1_IRQ, UART2_IRQ};*/
117 int ser_open(int pidx, int baud, unsigned int mode)
119 unsigned short div = 115200 / baud;
124 if(pidx < 0 || pidx > 1) {
125 printf("ser_open: invalid serial port: %d\n", pidx);
129 if(ports[pidx].base) {
130 printf("ser_open: port %d already open!\n", pidx);
133 memset(ports + pidx, 0, sizeof ports[pidx]);
135 base = uart_base[pidx];
136 /*intr = uart_irq[pidx] | 8;*/
144 /*prev_if = disable_intr();*/
145 /* TODO set interrupt handler */
146 /* unmask the appropriate interrupt */
147 /*outb(inb(PIC1_DATA_PORT) & ~(1 << uart_irq[pidx]), PIC1_DATA_PORT);*/
149 outb(LCTL_DLAB, base + UART_LCTL);
150 outb(div & 0xff, base + UART_DIVLO);
151 outb((div >> 8) & 0xff, base + UART_DIVHI);
152 outb(fmt, base + UART_LCTL); /* fmt should be LCTL_8N1, LCTL_8N2 etc */
153 outb(FIFO_ENABLE | FIFO_SEND_CLEAR | FIFO_RECV_CLEAR, base + UART_FIFO);
154 outb(MCTL_DTR | MCTL_RTS | MCTL_OUT2, base + UART_MCTL);
155 /*outb(INTR_RECV, base + UART_INTR);
157 restore_intr(prev_if);*/
159 ports[pidx].base = base;
160 /*ports[pidx].intr = intr;*/
161 ports[pidx].blocking = 1;
166 void ser_close(int fd)
168 if(--num_open == 0) {
169 /*int prev_if = disable_intr();*/
170 /*outb(0, ports[fd].base + UART_INTR);*/
171 outb(0, ports[fd].base + UART_MCTL);
172 /*restore_intr(prev_if);*/
178 int ser_block(int fd)
180 ports[fd].blocking = 1;
184 int ser_nonblock(int fd)
186 ports[fd].blocking = 0;
190 int ser_pending(int fd)
192 return !BEMPTY(ports[fd].inbuf);
195 /* if msec < 0: wait for ever */
196 int ser_wait(int fd, long msec)
199 while(!(res = ser_pending(fd))) {
205 static int can_send(int fd)
207 int base = ports[fd].base;
208 return inb(base + UART_LSTAT) & LST_TREG_EMPTY;
211 void ser_putc(int fd, char c)
213 int base = ports[fd].base;
214 while(!can_send(fd));
215 while((inb(base + UART_MSTAT) & MST_CTS) == 0);
216 outb(c, base + UART_DATA);
221 struct serial_port *p = ports + fd;
225 while(!(have = ser_pending(fd)));
227 have = ser_pending(fd);
231 c = p->inbuf[p->inbuf_ridx];
232 p->inbuf_ridx = BNEXT(p->inbuf_ridx);
237 int ser_write(int fd, const char *buf, int count)
241 ser_putc(fd, *buf++);
246 int ser_read(int fd, char *buf, int count)
249 while(n < count && (c = ser_getc(fd)) != -1) {
256 char *ser_getline(int fd, char *buf, int bsz)
258 static char linebuf[512];
260 int i, rd, size, offs;
262 size = sizeof linebuf - widx;
263 while(size && (rd = ser_read(fd, linebuf + widx, size)) > 0) {
270 for(i=0; i<widx; i++) {
271 if(linebuf[i] == '\r' || linebuf[i] == '\n') {
272 size = i >= bsz ? bsz - 1 : i;
273 memcpy(buf, linebuf, size);
277 memmove(linebuf, linebuf + offs, widx - offs);
286 static int have_recv(int base)
288 unsigned short stat = inb(base + UART_LSTAT);
289 if(stat & LST_ERROR) {
290 printf("serial receive error\n");
293 return stat & LST_DRDY;
296 static void __interrupt __far recv_intr()
301 int base = uart_base[i];
302 struct serial_port *p = ports + i;
304 while(((idreg = inb(base + UART_IID)) & IID_PENDING) == 0) {
305 while(have_recv(base)) {
306 c = inb(base + UART_DATA);
308 p->inbuf[p->inbuf_widx] = inb(base + UART_DATA);
309 p->inbuf_widx = BNEXT(p->inbuf_widx);
311 if(p->inbuf_widx == p->inbuf_ridx) {
312 /* we overflowed, drop the oldest */
313 p->inbuf_ridx = BNEXT(p->inbuf_ridx);
319 outb(OCW2_EOI, PIC1_CMD_PORT);