diff options
author | tg <tg@FreeBSD.org> | 2001-10-02 11:28:59 +0000 |
---|---|---|
committer | tg <tg@FreeBSD.org> | 2001-10-02 11:28:59 +0000 |
commit | 5a5faeb1fdc45ba96f1845430e14e114bf638d07 (patch) | |
tree | 15ee4fccd16594c90a39dddc748220e18b5aa6f0 /usr.bin/doscmd/int14.c | |
parent | b377b771103513eea4b0a6853c82cc12a35fc3e7 (diff) | |
download | FreeBSD-src-5a5faeb1fdc45ba96f1845430e14e114bf638d07.zip FreeBSD-src-5a5faeb1fdc45ba96f1845430e14e114bf638d07.tar.gz |
- First shot at PIC emulation;
- better 8250 emulation;
- fake vertical retrace bit in Input Status #1 register
(this was lost in the VGA emu rewrite).
Submitted by: Igor Serikov <bt@turtle.pangeatech.com>
Diffstat (limited to 'usr.bin/doscmd/int14.c')
-rw-r--r-- | usr.bin/doscmd/int14.c | 582 |
1 files changed, 372 insertions, 210 deletions
diff --git a/usr.bin/doscmd/int14.c b/usr.bin/doscmd/int14.c index 56c9576..a9c9a68 100644 --- a/usr.bin/doscmd/int14.c +++ b/usr.bin/doscmd/int14.c @@ -42,44 +42,221 @@ #include <unistd.h> #include "doscmd.h" +#include "AsyncIO.h" #include "com.h" -struct com_data_struct com_data[N_COMS_MAX]; - -/* XXX where does struct queue come from? */ -static struct queue *create_queue(unsigned char); -static int queue_not_empty(struct queue *); -static int reset_irq_request(unsigned char); -static int set_irq_request(unsigned char); -static int test_irq_request(unsigned char); -static int write_div_latches(struct com_data_struct *); - -static struct queue * -create_queue(unsigned char irq) { return NULL; } - -static int -queue_not_empty(struct queue *qp) {return 0;} +#define N_BYTES 1024 + +struct com_data_struct { + int fd; /* BSD/386 file descriptor */ + char *path; /* BSD/386 pathname */ + int addr; /* ISA I/O address */ + unsigned char irq; /* ISA IRQ */ + unsigned char inbuf[N_BYTES]; /* input buffer */ + unsigned char outbuf[N_BYTES];/* output buffer */ + int ids; /* input data size */ + int ods; /* output data size */ + int emptyint; + struct termios tty; + unsigned char div_latch[2]; /* mirror of 16550 R0':R1' + read/write */ + unsigned char int_enable; /* mirror of 16550 R1 read/write */ + unsigned char fifo_ctrl; /* mirror of 16550 R2 write only */ + unsigned char line_ctrl; /* mirror of 16550 R3 read/write */ + unsigned char modem_ctrl; /* mirror of 16550 R4 read/write */ + unsigned char modem_stat; /* mirror of 16550 R6 read/write */ + unsigned char uart_spare; /* mirror of 16550 R7 read/write */ +}; + +#define DIV_LATCH_LOW 0 +#define DIV_LATCH_HIGH 1 -static int -reset_irq_request(unsigned char irq) {return 0;} +struct com_data_struct com_data[N_COMS_MAX]; +static unsigned char com_port_in(int port); +static void com_port_out(int port, unsigned char val); +static void com_set_line(struct com_data_struct *cdsp, + unsigned char port, unsigned char param); + +static void +manage_int(struct com_data_struct *cdsp) +{ + if ((cdsp->int_enable & IE_RCV_DATA) && cdsp->ids > 0) { + hardint(cdsp->irq); + debug(D_PORT, "manage_int: hardint rd\n"); + return; + } + if ((cdsp->int_enable & IE_TRANS_HLD) && cdsp->emptyint) { + hardint(cdsp->irq); + debug(D_PORT, "manage_int: hardint wr\n"); + return; + } + unpend (cdsp->irq); +} + static int -set_irq_request(unsigned char irq) {return 0;} - +has_enough_data(struct com_data_struct *cdsp) +{ + switch (cdsp->fifo_ctrl & (FC_FIFO_EN | FC_FIFO_SZ_MASK)) { + case FC_FIFO_EN | FC_FIFO_4B: + return cdsp->ids >= 4; + case FC_FIFO_EN | FC_FIFO_8B: + return cdsp->ids >= 8; + case FC_FIFO_EN | FC_FIFO_14B: + return cdsp->ids >= 14; + } + return cdsp->ids; +} + +static void +input(struct com_data_struct *cdsp, int force_read) +{ + int nbytes; + + if (cdsp->ids < N_BYTES && (force_read || !has_enough_data(cdsp))) { + nbytes = read(cdsp->fd, &cdsp->inbuf[cdsp->ids], + N_BYTES - cdsp->ids); + debug(D_PORT, "read of fd %d on '%s' returned %d (%s)\n", + cdsp->fd, cdsp->path, nbytes, + nbytes == -1 ? strerror(errno) : ""); + if (nbytes != -1) + cdsp->ids += nbytes; + } +} + +static void +output(struct com_data_struct *cdsp) +{ + int nbytes; + + if (cdsp->ods > 0) { + nbytes = write(cdsp->fd, &cdsp->outbuf[0], cdsp->ods); + debug(D_PORT, "write of fd %d on '%s' returned %d (%s)\n", + cdsp->fd, cdsp->path, nbytes, + nbytes == -1 ? strerror(errno) : ""); + if (nbytes != -1) { + cdsp->ods -= nbytes; + memmove (&cdsp->outbuf[0], + &cdsp->outbuf[nbytes], cdsp->ods); + if ((cdsp->int_enable & IE_TRANS_HLD) + && cdsp->ods == 0) + cdsp->emptyint = 1; + } + } +} + +static void +flush_out(void* arg) +{ + struct com_data_struct *cdsp = (struct com_data_struct*)arg; + output(cdsp); + manage_int(cdsp); +} + +/* + * We postponed flush till the end of interrupt processing + * (see int.c). + */ static int -test_irq_request(unsigned char irq) {return 0;} - +write_char(struct com_data_struct *cdsp, char c) +{ + int r = 0; + cdsp->emptyint = 0; + if (cdsp->ods >= N_BYTES) + output(cdsp); + if (cdsp->ods < N_BYTES) { + cdsp->outbuf[cdsp->ods ++] = c; + if (!isinhardint(cdsp->irq)) + output(cdsp); + r = 1; + } + manage_int(cdsp); + return r; +} + static int -write_div_latches(struct com_data_struct *cdsp) {return 0;} +read_char(struct com_data_struct *cdsp) +{ + int c = -1; + + input(cdsp, 0); + + if (cdsp->ids > 0) { + c = cdsp->inbuf[0]; + cdsp->ids --; + memmove(&cdsp->inbuf[0], &cdsp->inbuf[1], cdsp->ids); + } + + manage_int(cdsp); + + debug(D_PORT, "read_char: %x\n", c); + return c; +} + +static void +new_ii(struct com_data_struct *cdsp) +{ + if ((cdsp->int_enable & IE_TRANS_HLD) && cdsp->ods == 0) + cdsp->emptyint = 1; + manage_int(cdsp); +} + +static unsigned char +get_status(struct com_data_struct *cdsp) +{ + unsigned char s = (LS_X_DATA_E | LS_X_HOLD_E); + if (cdsp->ids > 0) + s |= LS_RCV_DATA_RD; + if (cdsp->ods > 0) { + s &= ~LS_X_DATA_E; + if (cdsp->ods >= N_BYTES) + s &= ~LS_X_HOLD_E; + } + debug(D_PORT, "get_status: %x\n", (unsigned)s); + return s; +} + +static unsigned char +get_int_id(struct com_data_struct *cdsp) +{ + unsigned char s = II_PEND_INT; + if (cdsp->fifo_ctrl & FC_FIFO_EN) + s |= II_FIFOS_EN; + if ((cdsp->int_enable & IE_RCV_DATA) && cdsp->ids > 0) { + if (has_enough_data(cdsp)) + s = (s & ~II_PEND_INT) | II_RCV_DATA; + else + s = (s & ~II_PEND_INT) | II_TO; + } else + if ((cdsp->int_enable & IE_TRANS_HLD) && cdsp->emptyint) { + cdsp->emptyint = 0; + s = (s & ~II_PEND_INT) | II_TRANS_HLD; + } + debug(D_PORT, "get_int_id: %x\n", (unsigned)s); + return s; +} + +static void +com_async(int fd, int cond, void *arg, regcontext_t *REGS) +{ + struct com_data_struct *cdsp = (struct com_data_struct*) arg; + + debug(D_PORT, "com_async: %X.\n", cond); + + if (cond & AS_RD) + input(cdsp, 1); + if (cond & AS_WR) + output(cdsp); + manage_int(cdsp); +} void int14(regcontext_t *REGS) { struct com_data_struct *cdsp; - int nbytes; - char c; + int i; - debug (D_PORT, "int14: dl = 0x%02X, al = 0x%02X.\n", R_DL, R_AL); + debug(D_PORT, "int14: dl = 0x%02X, al = 0x%02X.\n", R_DL, R_AL); if (R_DL >= N_COMS_MAX) { if (vflag) dump_regs(REGS); @@ -89,39 +266,27 @@ int14(regcontext_t *REGS) switch (R_AH) { case 0x00: /* Initialize Serial Port */ -#if 0 /* hold off: try to defeat stupid DOS defaults */ com_set_line(cdsp, R_DL + 1, R_AL); - R_AH = LS_X_SHFT_E | LS_X_HOLD_E; + R_AH = get_status(cdsp); R_AL = 0; -#endif 0 break; case 0x01: /* Write Character */ - errno = 0; - c = R_AL; - nbytes = write(cdsp->fd, &c, 1); - debug (D_PORT, "write of 0x%02x to fd %d on '%s' returned %d %s\n", - R_AL, cdsp->fd, cdsp->path, nbytes, strerror(errno)); - if (nbytes == 1) { - R_AH = LS_X_SHFT_E | LS_X_HOLD_E; + if (write_char(cdsp, R_AL)) { + R_AH = get_status(cdsp); R_AL = 0; } else { - debug(D_PORT, "int14: lost output character 0x%02x\n", - R_AL); + debug(D_PORT, "int14: lost output character 0x%02x\n", R_AL); R_AH = LS_SW_TIME_OUT; R_AL = 0; } break; case 0x02: /* Read Character */ - errno = 0; - nbytes = read(cdsp->fd, &c, 1); - debug (D_PORT, "read of fd %d on '%s' returned %d byte 0x%02x %s\n", - cdsp->fd, cdsp->path, nbytes, c, - errno ? strerror(errno) : ""); - if (nbytes == 1) { - R_AH = LS_X_SHFT_E | LS_X_HOLD_E; - R_AL = c; + i = read_char(cdsp); + if (i != -1) { + R_AH = get_status(cdsp); + R_AL = (char)i; } else { R_AH = LS_SW_TIME_OUT; R_AL = 0x60; @@ -129,7 +294,8 @@ int14(regcontext_t *REGS) break; case 0x03: /* Status Request */ - R_AX = (LS_X_SHFT_E | LS_X_HOLD_E) << 8; + R_AH = get_status(cdsp); + R_AL = 0; break; case 0x04: /* Extended Initialization */ @@ -159,119 +325,181 @@ int14(regcontext_t *REGS) /* called when doscmd initializes a single line */ -void +static void com_set_line(struct com_data_struct *cdsp, unsigned char port, unsigned char param) { struct stat stat_buf; - int reg_num; - - debug (D_PORT, "com_set_line: cdsp = %8p, port = 0x%04x," + int mode = 0; /* read | write */ + int reg_num, ret_val, spd, speed; + u_int8_t div_hi, div_lo; + + debug(D_PORT, "com_set_line: cdsp = %8p, port = 0x%04x," "param = 0x%04X.\n", cdsp, port, param); if (cdsp->fd > 0) { - debug (D_PORT, "Re-initialize serial port com%d\n", port); - (void)close(cdsp->fd); + debug(D_PORT, "Re-initialize serial port com%d\n", port); + _RegisterIO(cdsp->fd, 0, 0, 0); + (void)close(cdsp->fd); } else { - debug (D_PORT, "Initialize serial port com%d\n", port); + debug(D_PORT, "Initialize serial port com%d\n", port); } - + stat(cdsp->path, &stat_buf); if (!S_ISCHR(stat_buf.st_mode) || ((cdsp->fd = open(cdsp->path, O_RDWR | O_NONBLOCK, 0666)) == -1)) { - - debug (D_PORT, - "Could not initialize serial port com%d on path '%s'\n", - port, cdsp->path); + + debug(D_PORT, + "Could not initialize serial port com%d on path '%s'\n", + port, cdsp->path); return; } - - cdsp->flags = 0x00; - cdsp->last_char_read = 0x00; -#if 0 + + cdsp->ids = cdsp->ods = cdsp->emptyint = 0; + cdsp->int_enable = 0; + cdsp->fifo_ctrl = 0; + cdsp->modem_ctrl = 0; + cdsp->modem_stat = 0; + cdsp->uart_spare = 0; + if ((param & PARITY_EVEN) == PARITY_NONE) - tty.c_iflag = IGNBRK | IGNPAR | IXON | IXOFF /* | IXANY */; + cdsp->tty.c_iflag = IGNBRK | IGNPAR /* | IXON | IXOFF | IXANY */; else - tty.c_iflag = IGNBRK | IXON | IXOFF /* | IXANY */; - tty.c_oflag = 0; - tty.c_lflag = 0; - tty.c_cc[VTIME] = 0; - tty.c_cc[VMIN] = 1; - tty.c_cflag = CREAD | CLOCAL | HUPCL; + cdsp->tty.c_iflag = IGNBRK /* | IXON | IXOFF | IXANY */; + cdsp->tty.c_oflag = 0; + cdsp->tty.c_lflag = 0; + cdsp->tty.c_cc[VTIME] = 0; + cdsp->tty.c_cc[VMIN] = 0; + cdsp->tty.c_cflag = CREAD | CLOCAL | HUPCL; /* MCL WHY CLOCAL ??????; but, gets errno EIO on writes, else */ - if ((param & TXLEN_8BITS) == TXLEN_8BITS) - tty.c_cflag |= CS8; - else - tty.c_cflag |= CS7; - if ((param & STOPBIT_2) == STOPBIT_2) - tty.c_cflag |= CSTOPB; + if ((param & TXLEN_8BITS) == TXLEN_8BITS) { + cdsp->tty.c_cflag |= CS8; + cdsp->line_ctrl |= 3; + } else { + cdsp->tty.c_cflag |= CS7; + cdsp->line_ctrl |= 2; + } + if ((param & STOPBIT_2) == STOPBIT_2) { + cdsp->tty.c_cflag |= CSTOPB; + cdsp->line_ctrl |= LC_STOP_B; + } else { + cdsp->tty.c_cflag &= ~CSTOPB; + cdsp->line_ctrl &= ~LC_STOP_B; + } switch (param & PARITY_EVEN) { - case (PARITY_ODD): - tty.c_cflag |= (PARENB | PARODD); - break; - case (PARITY_EVEN): - tty.c_cflag |= PARENB; - break; - case (PARITY_NONE): - default: - break; + case PARITY_ODD: + cdsp->tty.c_cflag |= (PARENB | PARODD); + cdsp->line_ctrl &= ~LC_EVEN_P; + cdsp->line_ctrl |= LC_PAR_E; + break; + case PARITY_EVEN: + cdsp->tty.c_cflag |= PARENB; + cdsp->line_ctrl |= LC_EVEN_P | LC_PAR_E; + break; + case PARITY_NONE: + cdsp->line_ctrl &= ~LC_PAR_E; + default: + break; } switch (param & BITRATE_9600) { - case (BITRATE_110): + case BITRATE_110: speed = B110; + spd = 110; break; - case (BITRATE_150): + case BITRATE_150: speed = B150; + spd = 150; break; - case (BITRATE_300): + case BITRATE_300: speed = B300; + spd = 300; break; - case (BITRATE_600): + case BITRATE_600: speed = B600; + spd = 600; break; - case (BITRATE_1200): + case BITRATE_1200: speed = B1200; + spd = 1200; break; - case (BITRATE_2400): + case BITRATE_2400: speed = B2400; + spd = 2400; break; - case (BITRATE_4800): + case BITRATE_4800: speed = B4800; + spd = 4800; break; - case (BITRATE_9600): + case BITRATE_9600: speed = B9600; + spd = 9600; break; } - debug (D_PORT, "com_set_line: going with cflag 0x%X iflag 0x%X speed %d.\n", - tty.c_cflag, tty.c_iflag, speed); + debug(D_PORT, + "com_set_line: going with cflag 0x%X iflag 0x%X speed %d.\n", + cdsp->tty.c_cflag, cdsp->tty.c_iflag, speed); + div_lo = (115200 / spd) & 0x00ff; + div_hi = (115200 / spd) & 0xff00; + cdsp->div_latch[DIV_LATCH_LOW] = div_lo; + cdsp->div_latch[DIV_LATCH_HIGH] = div_hi; errno = 0; - ret_val = cfsetispeed(&tty, speed); - debug (D_PORT, "com_set_line: cfsetispeed returned 0x%X.\n", ret_val); + ret_val = cfsetispeed(&cdsp->tty, speed); + debug(D_PORT, "com_set_line: cfsetispeed returned 0x%X.\n", ret_val); errno = 0; - ret_val = cfsetospeed(&tty, speed); - debug (D_PORT, "com_set_line: cfsetospeed returned 0x%X.\n", ret_val); + ret_val = cfsetospeed(&cdsp->tty, speed); + debug(D_PORT, "com_set_line: cfsetospeed returned 0x%X.\n", ret_val); errno = 0; - ret_val = tcsetattr(cdsp->fd, 0, &tty); - debug (D_PORT, "com_set_line: tcsetattr returned 0x%X.\n", ret_val); - + ret_val = tcsetattr(cdsp->fd, 0, &cdsp->tty); + debug(D_PORT, "com_set_line: tcsetattr returned 0x%X (%s).\n", + ret_val, ret_val == -1 ? strerror(errno) : ""); errno = 0; ret_val = fcntl(cdsp->fd, F_SETFL, O_NDELAY); - debug (D_PORT, "fcntl of 0x%X, 0x%X to fd %d returned %d errno %d\n", - F_SETFL, O_NDELAY, cdsp->fd, ret_val, errno); + debug(D_PORT, "fcntl of 0x%X, 0x%X to fd %d returned %d errno %d\n", + F_SETFL, O_NDELAY, cdsp->fd, ret_val, errno); errno = 0; ret_val = ioctl(cdsp->fd, TIOCFLUSH, &mode); - debug (D_PORT, "ioctl of 0x%02x to fd %d on 0x%X returned %d errno %d\n", - TIOCFLUSH, cdsp->fd, mode, ret_val, errno); -#endif + debug(D_PORT, "ioctl of 0x%02lx to fd %d on 0x%X returned %d errno %d\n", + TIOCFLUSH, cdsp->fd, mode, ret_val, errno); for (reg_num = 0; reg_num < N_OF_COM_REGS; reg_num++) { - define_input_port_handler(cdsp->addr + reg_num, - com_port_in); - define_output_port_handler(cdsp->addr + reg_num, - com_port_out); + define_input_port_handler(cdsp->addr + reg_num, com_port_in); + define_output_port_handler(cdsp->addr + reg_num, com_port_out); } - cdsp->com_queue = create_queue(cdsp->irq); debug(D_PORT, "com%d: attached '%s' at addr 0x%04x irq %d\n", - port, cdsp->path, cdsp->addr, cdsp->irq); + port, cdsp->path, cdsp->addr, cdsp->irq); + + set_eoir(cdsp->irq, flush_out, cdsp); + _RegisterIO(cdsp->fd, com_async, cdsp, 0); } +static void +try_set_speed(struct com_data_struct *cdsp) +{ + unsigned divisor, speed; + int ret_val; + + divisor = (unsigned) cdsp->div_latch[DIV_LATCH_HIGH] << 8 + | (unsigned) cdsp->div_latch[DIV_LATCH_LOW]; + + debug(D_PORT, "try_set_speed: divisor = %u\n", divisor); + + if (divisor == 0) + return; + + speed = 115200 / divisor; + if (speed == 0) + return; + + errno = 0; + ret_val = cfsetispeed(&cdsp->tty, speed); + debug(D_PORT, "try_set_speed: cfsetispeed returned 0x%X.\n", ret_val); + + errno = 0; + ret_val = cfsetospeed(&cdsp->tty, speed); + debug(D_PORT, "try_set_speed: cfsetospeed returned 0x%X.\n", ret_val); + + errno = 0; + ret_val = tcsetattr(cdsp->fd, 0, &cdsp->tty); + debug(D_PORT, "try_set_speed: tcsetattr returned 0x%X (%s).\n", ret_val, + ret_val == -1 ? strerror (errno) : ""); +} /* called when config.c initializes a single line */ void @@ -279,16 +507,19 @@ init_com(int port, char *path, int addr, unsigned char irq) { struct com_data_struct *cdsp; - debug (D_PORT, "init_com: port = 0x%04x, addr = 0x%04X, irq = %d.\n", - port, addr, irq); + debug(D_PORT, "init_com: port = 0x%04x, addr = 0x%04X, irq = %d.\n", + port, addr, irq); cdsp = &(com_data[port]); cdsp->path = path; /* XXX DEBUG strcpy? */ cdsp->addr = addr; cdsp->irq = irq; cdsp->fd = -1; com_set_line(cdsp, port + 1, TXLEN_8BITS | BITRATE_9600); -} + /* update BIOS variables */ + nserial++; + *(u_int16_t *)&BIOSDATA[0x00 + 2 * port] = (u_int16_t)addr; +} /* called when DOS wants to read directly from a physical port */ unsigned char @@ -297,7 +528,7 @@ com_port_in(int port) struct com_data_struct *cdsp; unsigned char rs; unsigned char i; - int nbytes; + int r; /* search for a valid COM ???or MOUSE??? port */ for (i = 0; i < N_COMS_MAX; i++) { @@ -307,7 +538,7 @@ com_port_in(int port) } } if (i == N_COMS_MAX) { - debug (D_PORT, "com port 0x%04x not found\n", port); + debug(D_PORT, "com port 0x%04x not found\n", port); return 0xff; } @@ -317,45 +548,24 @@ com_port_in(int port) if (cdsp->line_ctrl & LC_DIV_ACC) rs = cdsp->div_latch[DIV_LATCH_LOW]; else { -#if 0 - if (queue_not_empty(cdsp->com_queue)) { - rs = get_char_q(cdsp->com_queue); - cdsp->last_char_read = rs; - if (queue_not_empty(cdsp->com_queue) && - (cdsp->int_enable & IE_RCV_DATA) != 0) { - debug(D_PORT, - "com_port_in: setting irq %d because bytes yet to be read.\n", - cdsp->irq); - set_irq_request(cdsp->irq); - } - } else -#else - errno = 0; - nbytes = read(cdsp->fd, &rs, 1); - debug (D_PORT, "read of fd %d on '%s' returned %d byte 0x%02x errno %d\n", - cdsp->fd, cdsp->path, nbytes, rs, errno); - if (nbytes != 1) -#endif - rs = cdsp->last_char_read; + rs = 0x60; + r = read_char(cdsp); + if (r != -1) + rs = (unsigned char)r; } break; /* 0x03F9 - (interrupt enable) or (divisor latch HI) */ - case 1: + case 1: if (cdsp->line_ctrl & LC_DIV_ACC) rs = cdsp->div_latch[DIV_LATCH_HIGH]; else rs = cdsp->int_enable; - + break; + /* 0x03FA - interrupt identification register */ case 2: - /* rs = cdsp->int_id; * XXX DEBUG not initialized */ - rs = 0; - if ((queue_not_empty(cdsp->com_queue)) - && (test_irq_request(cdsp->irq) != 0)) - rs |= II_PEND_INT | II_RCV_DATA; - if ((cdsp->fifo_ctrl & FC_FIFO_EN) == FC_FIFO_EN) - rs |= II_FIFOS_EN; + rs = get_int_id(cdsp); break; /* 0x03FB - line control register */ @@ -370,11 +580,7 @@ com_port_in(int port) /* 0x03FD - line status register */ case 5: - rs = LS_X_SHFT_E | LS_X_HOLD_E; - /* if (queue_not_empty(cdsp->com_queue)) */ - ioctl(cdsp->fd, FIONREAD, &nbytes); - if (nbytes > 0) - rs |= LS_RCV_DATA_RD; + rs = get_status(cdsp); break; /* 0x03FE - modem status register */ @@ -395,13 +601,11 @@ com_port_in(int port) return rs; } - /* called when DOS wants to write directly to a physical port */ void com_port_out(int port, unsigned char val) { struct com_data_struct *cdsp; - int nbytes; int i; /* search for a valid COM ???or MOUSE??? port */ @@ -412,7 +616,7 @@ com_port_out(int port, unsigned char val) } } if (i == N_COMS_MAX) { - debug (D_PORT, "com port 0x%04x not found\n", port); + debug(D_PORT, "com port 0x%04x not found\n", port); return; } @@ -421,17 +625,9 @@ com_port_out(int port, unsigned char val) case 0: if (cdsp->line_ctrl & LC_DIV_ACC) { cdsp->div_latch[DIV_LATCH_LOW] = val; - cdsp->flags |= DIV_LATCH_LOW_WRITTEN; - write_div_latches(cdsp); + try_set_speed(cdsp); } else { - errno = 0; - nbytes = write(cdsp->fd, &val, 1); - debug (D_PORT, "write of 0x%02x to fd %d on '%s' returned %d errno %d\n", - val, cdsp->fd, cdsp->path, nbytes, errno); - if (nbytes != 1) - debug(D_PORT, - "int14: lost output character 0x%02x\n", - val); + write_char(cdsp, val); } break; @@ -439,23 +635,24 @@ com_port_out(int port, unsigned char val) case 1: if (cdsp->line_ctrl & LC_DIV_ACC) { cdsp->div_latch[DIV_LATCH_HIGH] = val; - cdsp->flags |= DIV_LATCH_HIGH_WRITTEN; - write_div_latches(cdsp); + try_set_speed(cdsp); } else { cdsp->int_enable = val; - if ((val & IE_RCV_DATA) == 0) { - reset_irq_request(cdsp->irq); - } else { - if (queue_not_empty(cdsp->com_queue)) { - set_irq_request(cdsp->irq); - } - } + new_ii(cdsp); } break; /* 0x03FA - FIFO control register */ case 2: - cdsp->fifo_ctrl = val; + cdsp->fifo_ctrl = val & (FC_FIFO_EN | FC_FIFO_SZ_MASK); + if (val & FC_FIFO_CRV) + cdsp->ids = 0; + if (val & FC_FIFO_CTR) { + cdsp->ods = 0; + cdsp->emptyint = 1; + } + input(cdsp, 1); + manage_int(cdsp); break; /* 0x03FB - line control register */ @@ -470,7 +667,7 @@ com_port_out(int port, unsigned char val) /* 0x03FD - line status register */ case 5: - cdsp->line_stat = val; + /* read-only */ break; /* 0x03FE - modem status register */ @@ -489,38 +686,3 @@ com_port_out(int port, unsigned char val) break; } } - -#if 0 -/* - * called when BSD has bytes ready (as discovered via select) for DOS - */ -static void do_com_input(int fd) -{ - struct com_data_struct *cdsp; - unsigned char buffer[BUFSIZE]; - int i, nbytes; - - dp = search_com_device_by_fd(fd); - if (dp == NULL) - return; - do { - nbytes = read(cdsp->fd, buffer, BUFSIZE); - if (nbytes > 0) { - debug(D_PORT, "do_com_input: read %d bytes from fd %d (aka %d): ", - nbytes, fd, cdsp->fd); - for (i = 0; i < nbytes; i++) { - put_char_q(cdsp->com_queue, buffer[i]); - if (cdsp->int_enable & IE_RCV_DATA) { - debug(D_PORT, "\n"); - debug(D_PORT, "do_com_input: setting irq %d because %d bytes read.\n", - dp->irq, nbytes); - debug(D_PORT, "do_com_input: "); - set_irq_request(dp->irq); - } - debug(D_PORT, "%02x ", buffer[i]); - } - debug(D_PORT, "\n"); - } - } while (nbytes == BUFSIZE); -} -#endif 0 |