*/
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include "config.h"
#include "serial.h"
#include "asmops.h"
#define COM_FMT_8N1 LCTL_8N1
#define COM_FMT_8N2 LCTL_8N2
+#define INBUF_SIZE 16
+#define BNEXT(x) (((x) + 1) & (INBUF_SIZE - 1))
+#define BEMPTY(b) (b##_ridx == b##_widx)
+
struct serial_port {
int base, intr;
int blocking;
+ int ref;
- char inbuf[256];
+ char inbuf[INBUF_SIZE];
int inbuf_ridx, inbuf_widx;
};
-#define BNEXT(x) (((x) + 1) & 0xff)
-#define BEMPTY(b) (b##_ridx == b##_widx)
static int have_recv(int base);
static void recv_intr();
int ser_open(int pidx, int baud, unsigned int mode)
{
unsigned short div = 115200 / baud;
- int base, intr;
+ int i, fd, base, intr;
unsigned int fmt;
if(pidx < 0 || pidx > 1) {
return -1;
}
- if(ports[pidx].base) {
- printf("ser_open: port %d already open!\n", pidx);
- return -1;
+ for(i=0; i<num_open; i++) {
+ if(ports[i].base == uart_base[pidx]) {
+ /* the port is already open, return the same fd and increment ref */
+ ports[i].ref++;
+ return i;
+ }
}
- memset(ports + pidx, 0, sizeof ports[pidx]);
+
+ fd = num_open++;
+ memset(ports + fd, 0, sizeof ports[pidx]);
base = uart_base[pidx];
intr = uart_irq[pidx];
outp(base + UART_MCTL, MCTL_DTR | MCTL_RTS | MCTL_OUT2);
outp(base + UART_INTR, INTR_RECV);
- ports[pidx].base = base;
- ports[pidx].intr = intr;
- ports[pidx].blocking = 1;
- ++num_open;
- return pidx;
+ ports[fd].base = base;
+ ports[fd].intr = intr;
+ ports[fd].blocking = 1;
+ ports[fd].ref = 1;
+ return fd;
}
void ser_close(int fd)
{
- if(--num_open == 0) {
+ if(!ports[fd].ref) return;
+
+ if(--ports[fd].ref == 0) {
outp(ports[fd].base + UART_INTR, 0);
outp(ports[fd].base + UART_MCTL, 0);
+ ports[fd].base = 0;
}
-
- ports[fd].base = 0;
}
int ser_block(int fd)
char *ser_getline(int fd, char *buf, int bsz)
{
- static char linebuf[512];
static int widx;
+ char linebuf[512];
int i, rd, size, offs;
size = sizeof linebuf - widx;