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 | |
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')
-rw-r--r-- | usr.bin/doscmd/AsyncIO.c | 254 | ||||
-rw-r--r-- | usr.bin/doscmd/AsyncIO.h | 18 | ||||
-rw-r--r-- | usr.bin/doscmd/com.h | 59 | ||||
-rw-r--r-- | usr.bin/doscmd/config.c | 4 | ||||
-rw-r--r-- | usr.bin/doscmd/doscmd.c | 14 | ||||
-rw-r--r-- | usr.bin/doscmd/doscmd.h | 20 | ||||
-rw-r--r-- | usr.bin/doscmd/int.c | 300 | ||||
-rw-r--r-- | usr.bin/doscmd/int14.c | 582 | ||||
-rw-r--r-- | usr.bin/doscmd/signal.c | 7 | ||||
-rw-r--r-- | usr.bin/doscmd/timer.c | 3 | ||||
-rw-r--r-- | usr.bin/doscmd/trap.c | 11 | ||||
-rw-r--r-- | usr.bin/doscmd/tty.c | 52 | ||||
-rw-r--r-- | usr.bin/doscmd/video.c | 6 |
13 files changed, 741 insertions, 589 deletions
diff --git a/usr.bin/doscmd/AsyncIO.c b/usr.bin/doscmd/AsyncIO.c index 649e073..e92fc55 100644 --- a/usr.bin/doscmd/AsyncIO.c +++ b/usr.bin/doscmd/AsyncIO.c @@ -61,7 +61,7 @@ static fd_set fdset; /* File Descriptors to select on */ typedef struct { - void (*func)(void *, regcontext_t *); + void (*func)(int, int, void *, regcontext_t *); /* Function to call on data arrival */ void (*failure)(void *); /* Function to call on failure */ void *arg; /* Argument to above functions */ @@ -71,17 +71,13 @@ typedef struct { } Async; static Async handlers[OPEN_MAX]; -static int in_handler = 0; static void CleanIO(void); static void HandleIO(struct sigframe *sf); void -_RegisterIO(fd, func, arg, failure) -int fd; -void (*func)(void *, regcontext_t *); -void *arg; -void (*failure)(void *); +_RegisterIO(int fd, void (*func)(int, int, void *, regcontext_t *), + void *arg, void (*failure)(void *)) { static int firsttime = 1; Async *as; @@ -167,181 +163,99 @@ printf("Closed file descriptor %d\n", x); } } -static void -HandleIO(struct sigframe *sf) +static void HandleIO(struct sigframe *sf) { - ++in_handler; + static struct timeval tv; + fd_set readset, writeset; + int x, fd; + +again: + readset = writeset = fdset; + if ((x = select(FD_SETSIZE, &readset, &writeset, 0, &tv)) < 0) { + /* + * If we failed because of a BADFiledes, go find + * which one(s), fail them out and then try a + * new select to see if any of the good ones are + * okay. + */ + if (errno == EBADF) { + CleanIO(); + if (FD_ISZERO(&fdset)) + return; + goto again; + } + perror("select"); + return; + } - for (;;) { - static struct timeval tv; - fd_set readset; - int x; - int fd; + /* + * If we run out of fds to look at, break out of the loop + * and exit the handler. + */ + if (x == 0) + return; - readset = fdset; - if ((x = select(FD_SETSIZE, &readset, 0, 0, &tv)) < 0) { - /* - * If we failed becuase of a BADFiledes, go find - * which one(s), fail them out and then try a - * new select to see if any of the good ones are - * okay. - */ - if (errno == EBADF) { - CleanIO(); - if (FD_ISZERO(&fdset)) - break; - continue; - } - perror("select"); - break; + /* + * If there is at least 1 fd saying it has something for + * us, then loop through the sets looking for those + * bits, stopping when we have handleed the number it has + * asked for. + */ + for (fd = 0; x && fd < OPEN_MAX; fd ++) { + Async *as; + int cond; + + cond = 0; + + if (FD_ISSET(fd, &readset)) { + cond |= AS_RD; + x --; + } + if (FD_ISSET(fd, &writeset)) { + cond |= AS_WR; + x --; } + if (cond == 0) + continue; + /* - * If we run out of fds to look at, break out of the loop - * and exit the handler. + * Is suppose it is possible that one of the previous + * I/O requests changed the fdset. + * We do know that SIGIO is turned off right now, + * so it is safe to checkit. */ - if (!x) - break; - + if (!FD_ISSET(fd, &fdset)) { + continue; + } + as = &handlers[fd]; + /* - * If there is at least 1 fd saying it has something for - * us, then loop through the sets looking for those - * bits, stopping when we have handleed the number it has - * asked for. + * as in above, maybe someone locked us... + * we are in dangerous water now if we are + * multi-tasked */ - for (fd = 0; x && fd < OPEN_MAX; ++fd) { - Async *as; - - if (!FD_ISSET(fd, &readset)) { - continue; - } - --x; - - /* - * Is suppose it is possible that one of the previous - * io requests changed the fdset. - * We do know that SIGIO is turned off right now, - * so it is safe to checkit. - */ - if (!FD_ISSET(fd, &fdset)) { - continue; - } - as = &handlers[fd]; - - /* - * as in above, maybe someone locked us... - * we are in dangerous water now if we are - * multi-tasked - */ - if (as->lockcnt) { -/*@*/ fprintf(stderr, "Selected IO on locked %d\n",fd); - continue; - } - /* - * Okay, now if there exists a handler, we should - * call it. We must turn back on SIGIO if there - * are possibly other people waiting for it. - */ - if (as->func) { - int afd; - Async *aas; - - /* - * STEP 1: Lock out all "members" - */ - aas = handlers; -if (0) - for (afd = 0; afd < OPEN_MAX; ++afd, ++aas) { - if (FD_ISSET(afd, &as->members)) { - if (aas->func) { - if (as->lockcnt++ == 0) { - FD_CLR(afd, &fdset); - CLRASYNC(afd); - } - - } - } - } - - /* - * STEP 2: Renable SIGIO so other FDs can - * use a hit. - _UnblockIO(); - */ - - /* - * STEP 3: Call the handler - */ - (*handlers[fd].func)(handlers[fd].arg, - (regcontext_t *)&sf->sf_uc); - - /* - * STEP 4: Just turn SIGIO off. No check. - _BlockIO(); - */ - - /* - * STEP 5: Unlock all "members" - */ - aas = handlers; -if (0) - for (afd = 0; afd < OPEN_MAX; ++afd, ++aas) { - if (FD_ISSET(afd, &as->members)) { - if (aas->func) { - if (--as->lockcnt == 0) { - FD_SET(afd, &fdset); - SETASYNC(afd); - } - } - } - } - } else { - /* - * Otherwise deregister this guy. - */ - _RegisterIO(fd, 0, 0, 0); - } + if (as->lockcnt) { + fprintf(stderr, "Selected IO on locked %d\n",fd); + continue; } /* - * If we did not process all the fd's, then we should - * break out of the probable infinite loop. + * Okay, now if there exists a handler, we should + * call it. We must turn back on SIGIO if there + * are possibly other people waiting for it. */ - if (x) { - break; + if (as->func) { + (*handlers[fd].func)(fd, cond, handlers[fd].arg, + (regcontext_t*)&sf->sf_uc); + } else { + /* + * Otherwise deregister this guy. + */ + _RegisterIO(fd, 0, 0, 0); } } - - --in_handler; -} - -static int stackp = 0; - -void -_BlockIO() -{ - sigset_t set; - - if (stackp >= 64) { - fprintf(stderr, "Signal stack count too deep\n"); - abort(); - } - if (stackp++ == 0) { - sigaddset(&set, SIGIO); - sigprocmask(SIG_BLOCK, &set, 0); - } -} - -void -_UnblockIO() -{ - sigset_t set; - - if (stackp <= 0) { - fprintf(stderr, "Negative signal stack count\n"); - abort(); - } - if (--stackp == 0) { - sigaddset(&set, SIGIO); - sigprocmask(SIG_UNBLOCK, &set, 0); - } + /* + * If we did not process all the fd's, then we should + * break out of the probable infinite loop. + */ } diff --git a/usr.bin/doscmd/AsyncIO.h b/usr.bin/doscmd/AsyncIO.h index cb867a3..f1c96a1 100644 --- a/usr.bin/doscmd/AsyncIO.h +++ b/usr.bin/doscmd/AsyncIO.h @@ -35,17 +35,13 @@ #if defined(__cplusplus) extern "C" { #endif -void _RegisterIO(int, void (*)(void *, regcontext_t *), - void *, void (*)(void *)); -void _AssociateIO(int, int); -void _DeAssociateIO(int, int); -void _LockIO(int); -int _UnlockIO(int); -int _LevelIO(int); -int _DetachIO(int); -int _EndIO(int, int); -void _BlockIO(void); -void _UnblockIO(void); +enum { + AS_RD = 1, + AS_WR = 2 +}; + +void _RegisterIO(int, void (*)(int, int, void *, regcontext_t *), + void *, void (*)(void *)); #if defined(__cplusplus) } #endif diff --git a/usr.bin/doscmd/com.h b/usr.bin/doscmd/com.h index b2281d9..495ca88 100644 --- a/usr.bin/doscmd/com.h +++ b/usr.bin/doscmd/com.h @@ -34,13 +34,11 @@ /* com.h for doscmd int14.c */ -#define BUFSIZE 1024 - /* NS16550A register definitions */ /* interrupt enable register */ -#define IE_NOP 0xF0 /* not used */ +#define IE_NOP 0xF0 /* Not used */ #define IE_MODEM_STAT 0x08 /* modem status int. */ #define IE_LINE_STAT 0x04 /* receiver-line status int. */ #define IE_TRANS_HLD 0x02 /* transmitter holding register empty int. */ @@ -49,12 +47,13 @@ /* interrupt identification register */ #define II_FIFOS_EN 0xC0 /* if FIFOs are enabled */ -#define II_NOP 0x38 /* not used */ -#define II_INT_ID 0x06 /* mask: bits see below */ +#define II_NOP 0x30 /* not used */ +#define II_INT_ID 0x0E /* mask: bits see below */ #define II_PEND_INT 0x01 /* 1=no interrupt pending */ /* bit masks for II_INT_ID */ +#define II_TO 0x0C #define II_LINE_STAT 0x06 #define II_RCV_DATA 0x04 #define II_TRANS_HLD 0x02 @@ -62,6 +61,13 @@ /* FIFO control reg */ +#define FC_FIFO_SZ_MASK 0xC0 +#define FC_FIFO_1B 0x80 +#define FC_FIFO_4B 0x40 +#define FC_FIFO_8B 0x80 +#define FC_FIFO_14B 0xC0 +#define FC_FIFO_CTR 0x04 +#define FC_FIFO_CRV 0x02 #define FC_FIFO_EN 0x01 /* line control register */ @@ -77,8 +83,8 @@ /* line status register */ #define LS_NOP 0x80 /* not used */ -#define LS_X_SHFT_E 0x40 /* 0=data transfer, 1=transmitter idle */ -#define LS_X_HOLD_E 0x20 /* 0=ready, 1=transferring character */ +#define LS_X_DATA_E 0x40 /* 1=empty */ +#define LS_X_HOLD_E 0x20 /* 1=empty */ #define LS_BREAK 0x10 /* break received */ #define LS_FRM_ERR 0x08 /* framing error */ #define LS_PAR_ERR 0x04 /* parity error */ @@ -96,31 +102,6 @@ #define MS_DELTA_DSR 0x02 /* Data Set Ready changed state */ #define MS_DELTA_CTS 0x01 /* Clear To Send changed state */ -/* data structure definitions */ - -#define N_OF_COM_REGS 8 - -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 flags; /* some general software flags */ - - struct queue *com_queue; /* XXX DEBUG obsolete MCL? */ - - unsigned char div_latch[2]; /* mirror of 16550 R0':R1' read/write */ - unsigned char last_char_read; /* mirror of 16550 R0 read only */ - unsigned char int_enable; /* mirror of 16550 R1 read/write */ - unsigned char int_id; /* mirror of 16550 R2 read only */ - 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 line_stat; /* mirror of 16550 R5 read/write */ - unsigned char modem_stat; /* mirror of 16550 R6 read/write */ - unsigned char uart_spare; /* mirror of 16550 R7 read/write */ -}; - /* DOS definitions -- parameters */ #define BITRATE_110 0x00 @@ -139,25 +120,15 @@ struct com_data_struct { #define TXLEN_7BITS 0x02 #define TXLEN_8BITS 0x03 +#define N_OF_COM_REGS 8 + /* DOS definitions -- return codes */ #define LS_SW_TIME_OUT LS_NOP /* return value used by DOS */ -/* miscellaneous definitions */ - -#define DIV_LATCH_LOW 0 -#define DIV_LATCH_HIGH 1 - -#define DIV_LATCH_LOW_WRITTEN 0x01 -#define DIV_LATCH_HIGH_WRITTEN 0x02 -#define DIV_LATCH_BOTH_WRITTEN 0x03 - /* routine declarations */ void int14(regcontext_t *REGS); -void com_set_line(struct com_data_struct *, unsigned char, unsigned char); void init_com(int, char *, int, unsigned char); -u_char com_port_in(int); -void com_port_out(int, unsigned char); /* end of file com.h */ diff --git a/usr.bin/doscmd/config.c b/usr.bin/doscmd/config.c index fd2332b..492d31d 100644 --- a/usr.bin/doscmd/config.c +++ b/usr.bin/doscmd/config.c @@ -221,8 +221,8 @@ init_hard: errno = 0; irq = (unsigned char)strtol(av[4], '\0', 0); /* XXX DEBUG ISA-specific */ - if ((errno != 0) || (irq < 1) || (irq > 15)) { - fprintf(stderr, "Usage: assign com[1-4] path addr irq\n"); + if ((errno != 0) || (irq < 2) || (irq > 7)) { + fprintf(stderr, "Usage: assign com[1-4] path addr irq[2-7]\n"); quit(1); } init_com(port, av[2], addr, irq); diff --git a/usr.bin/doscmd/doscmd.c b/usr.bin/doscmd/doscmd.c index 5b189e2..fbccef8 100644 --- a/usr.bin/doscmd/doscmd.c +++ b/usr.bin/doscmd/doscmd.c @@ -69,9 +69,6 @@ int timer_disable = 0; struct timeval boot_time; unsigned long *ivec = (unsigned long *)0; -u_long pending[256]; /* pending interrupts */ -int n_pending; - #ifndef USE_VM86 #define PRB_V86_FORMAT 0x4242 @@ -118,6 +115,14 @@ main(int argc, char **argv) regcontext_t *REGS = (regcontext_t *)&uc.uc_mcontext; int fd; int i; + sigset_t sigset; + + sigemptyset(&sigset); + sigaddset(&sigset, SIGIO); + sigaddset(&sigset, SIGALRM); + sigprocmask(SIG_BLOCK, &sigset, 0); + + init_ints(); debugf = stderr; /* XXX should only be for tty mode */ @@ -194,9 +199,6 @@ main(int argc, char **argv) } } #endif - for (i = 0; i < 256; i++) - pending[i] = 0; - n_pending = 0; if (booting) { /* are we booting? */ setup_boot(REGS); diff --git a/usr.bin/doscmd/doscmd.h b/usr.bin/doscmd/doscmd.h index 2269708..c1ed260 100644 --- a/usr.bin/doscmd/doscmd.h +++ b/usr.bin/doscmd/doscmd.h @@ -202,11 +202,14 @@ extern int i386dis(unsigned short, unsigned short, unsigned char *, char *, int); /* int.c */ -extern void softint(int intnum); -extern void hardint(int intnum); - -extern void delay_interrupt(int intnum, void (*func)(int)); -extern void resume_interrupt(void); +void init_ints(void); +int isinhardint(int); +void softint(int); +void hardint(int); +void resume_interrupt(void); +void unpend(int); +void send_eoi(void); +void set_eoir(int, void (*)(void *), void *); /* int10.c */ extern void int10(regcontext_t *); @@ -300,9 +303,4 @@ extern void initHMA(void); extern void xms_init(void); extern u_long xms_maxsize; -/****************************** dirty below here *****************************/ - -extern u_long pending[]; /* pending interrupts */ -extern int n_pending; - -extern int nmice; +/****************************** dirty below here *****************************/extern int nmice; diff --git a/usr.bin/doscmd/int.c b/usr.bin/doscmd/int.c index d124fbd..8638ca8 100644 --- a/usr.bin/doscmd/int.c +++ b/usr.bin/doscmd/int.c @@ -3,8 +3,199 @@ ** ** $FreeBSD$ */ + +/* + * Notes: + * 1) Second PIC is not implemented. + * 2) Interrupt priority management is not implemented. + * 3) What should be read from port 0x20? + * + * "within interrupt processing" means the following is true: + * 1) Hardware interrupt <irql> is delivered by hardint(). + * 2) Next interrupt <irql> is not possible yet by either: + * a) V_IF; + * b) Interrupt mask; + * c) Current irql. + * + * Related functions: + * int isinhardint(int irql) + * void set_eoir(int irql, void(*eoir)(void*), void* arg); + * + */ + #include "doscmd.h" +struct IRQ { + int pending; + int busy; + int within; + void (*eoir) (void* arg); + void* arg; +}; + +static unsigned char IM; +static int Irql; +static struct IRQ Irqs[8]; + +#define int_allowed(n) ((IM & 1 << (n)) == 0 && Irql > (n)) + +void +set_eoir(int irql, void(*eoir)(void*), void* arg) +{ + Irqs [irql].eoir = eoir; + Irqs [irql].arg = arg; +} + +int +isinhardint(int irql) +{ + return Irqs[irql].within; +} + +static void +set_vip(void) +{ + regcontext_t *REGS = saved_regcontext; + int irql; + + if (R_EFLAGS & PSL_VIF) { + R_EFLAGS &= ~PSL_VIP; + return; + } + + for (irql = 0; irql < 8; irql ++) + if (int_allowed(irql) && (Irqs[irql].within || Irqs[irql].pending)) { + R_EFLAGS |= PSL_VIP; + return; + } + + R_EFLAGS &= ~PSL_VIP; +} + +void +resume_interrupt(void) +{ + regcontext_t *REGS = saved_regcontext; + int irql; + + if (R_EFLAGS & PSL_VIF) { + for (irql = 0; irql < 8; irql ++) + if (Irqs[irql].within && int_allowed(irql)) { + Irqs[irql].within = 0; + if (Irqs[irql].eoir) + Irqs[irql].eoir(Irqs[irql].arg); + } + + for (irql = 0; irql < 8; irql ++) + if (Irqs[irql].pending && int_allowed(irql)) { + Irqs[irql].pending = 0; + hardint(irql); + break; + } + } + set_vip(); +} + +void +send_eoi(void) +{ + if (Irql >= 8) + return; + + Irqs[Irql].busy = 0; + + while (++Irql < 8) + if (Irqs [Irql].busy) + break; + + resume_interrupt(); +} + +/* +** Cause a hardware interrupt to happen immediately after +** we return to vm86 mode +*/ +void +hardint(int irql) +{ + regcontext_t *REGS = saved_regcontext; + u_long vec = ivec[8 + irql]; + + /* + ** if we're dead, or there's no vector, or the saved registers + ** are invalid + */ + if (dead || !saved_valid || vec == 0) + return; + + /* + ** if the vector points into the BIOS, or the handler at the + ** other end is just an IRET, don't bother + */ + if ((vec >> 16) == 0xf000 || *(u_char *)VECPTR(vec) == 0xcf) + return; + + if (!int_allowed (irql)) { + Irqs[irql].pending = 1; + return; + } + + if ((R_EFLAGS & PSL_VIF) == 0) { + Irqs[irql].pending = 1; + R_EFLAGS |= PSL_VIP; + return; + } + + debug(D_TRAPS | (8 + irql), "Int%02x [%04lx:%04lx]\n", + 8 + irql, vec >> 16, vec & 0xffff); + + Irql = irql; + Irqs[Irql].busy = 1; + if (Irqs[Irql].eoir) + Irqs[Irql].within = 1; + + PUSH((R_FLAGS & ~PSL_I) | (R_EFLAGS & PSL_VIF ? PSL_I : 0), REGS); + PUSH(R_CS, REGS); + PUSH(R_IP, REGS); + R_EFLAGS &= ~PSL_VIF; /* XXX disable interrupts */ + PUTVEC(R_CS, R_IP, vec); +} + +void +unpend(int irql) +{ + if (!Irqs[irql].pending) + return; + Irqs[irql].pending = 0; + set_vip(); +} + +static unsigned char +irqc_in(int port) +{ + return 0x60; /* What should be here? */ +} + +static void +irqc_out(int port, unsigned char val) +{ + if (val == 0x20) + send_eoi(); +} + +static unsigned char +imr_in(int port) +{ + return IM; +} + +static void +imr_out(int port, unsigned char val) +{ + IM = val; + resume_interrupt(); +} + /* ** Cause a software interrupt to happen immediately after we ** return to vm86 mode @@ -29,111 +220,32 @@ softint(int intnum) if ((vec >> 16) == 0xf000 || *(u_char *)VECPTR(vec) == 0xcf) return; -#if 0 - /* - * software interrupts are always taken - */ - if ((R_EFLAGS & PSL_VIF) == 0) { - delay_interrupt(intnum, softint); - return; - } -#endif - - debug(D_TRAPS|intnum, "INT%x [%04lx:%04lx]\n", + debug(D_TRAPS | intnum, "INT %02x [%04lx:%04lx]\n", intnum, vec >> 16, vec & 0xffff); PUSH((R_FLAGS & ~PSL_I) | (R_EFLAGS & PSL_VIF ? PSL_I : 0), REGS); PUSH(R_CS, REGS); PUSH(R_IP, REGS); -#if 1 R_EFLAGS &= ~PSL_VIF; /* XXX disable interrupts? */ -#else - R_EFLAGS |= PSL_VIF; -#endif PUTVEC(R_CS, R_IP, vec); } -/* -** Cause a hardware interrupt to happen immediately after -** we return to vm86 mode -*/ void -hardint(int intnum) -{ - regcontext_t *REGS = saved_regcontext; - u_long vec = ivec[intnum]; - - /* - * XXXXX - * We should simulate the IRQ mask in the PIC. - */ - - /* - ** if we're dead, or there's no vector, or the saved registers - ** are invalid - */ - if (dead || !saved_valid || vec == 0) - return; - - /* - ** if the vector points into the BIOS, or the handler at the - ** other end is just an IRET, don't bother - */ - if ((vec >> 16) == 0xf000 || *(u_char *)VECPTR(vec) == 0xcf) - return; - - if ((R_EFLAGS & PSL_VIF) == 0) { - delay_interrupt(intnum, hardint); - return; - } - - debug(D_TRAPS|intnum, "INT%x [%04lx:%04lx]\n", - intnum, vec >> 16, vec & 0xffff); - - PUSH((R_FLAGS & ~PSL_I) | (R_EFLAGS & PSL_VIF ? PSL_I : 0), REGS); - PUSH(R_CS, REGS); - PUSH(R_IP, REGS); -#if 1 - R_EFLAGS &= ~PSL_VIF; /* XXX disable interrupts */ -#else - R_EFLAGS |= PSL_VIF; -#endif - PUTVEC(R_CS, R_IP, vec); -} - -typedef void (*foo_t)(int); - -void -resume_interrupt(void) +init_ints(void) { int i; - regcontext_t *REGS = saved_regcontext; - - n_pending--; - if (n_pending == 0) - R_EFLAGS &= ~PSL_VIP; - for (i = 0; i < 256; i++) { - if (pending[i]) { - ((foo_t)(pending[i]))(i); - pending[i] = 0; - break; - } - } -} - - -void -delay_interrupt(int intnum, void (*func)(int)) -{ - regcontext_t *REGS = saved_regcontext; - -#if 0 -printf("DELAY [%x/%d]\n", intnum, n_pending); -#endif - if (pending[intnum] == 0) { - pending[intnum] = (u_long)func; - n_pending++; + for (i = 0; i < 8; i++) { + Irqs[i].busy = 0; + Irqs[i].pending = 0; + Irqs[i].within = 0; } - R_EFLAGS |= PSL_VIP; -} + + IM = 0x00; + Irql = 8; + + define_input_port_handler(0x20, irqc_in); + define_output_port_handler(0x20, irqc_out); + define_input_port_handler(0x21, imr_in); + define_output_port_handler(0x21, imr_out); +} 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 diff --git a/usr.bin/doscmd/signal.c b/usr.bin/doscmd/signal.c index 97a11fe..11f669b 100644 --- a/usr.bin/doscmd/signal.c +++ b/usr.bin/doscmd/signal.c @@ -84,12 +84,10 @@ generichandler(struct sigframe sf) #error BSD/OS sigframe/trapframe kernel interface not currently supported. #endif -void -setsignal(int s, void (*h)(struct sigframe *)) +void setsignal(int s, void (*h)(struct sigframe *)) { static int first = 1; struct sigaction sa; - sigset_t set; if (first) { struct sigaltstack sstack; @@ -110,8 +108,5 @@ setsignal(int s, void (*h)(struct sigframe *)) sigaddset(&sa.sa_mask, SIGALRM); sa.sa_flags = SA_ONSTACK; sigaction(s, &sa, NULL); - - sigaddset(&set, s); - sigprocmask(SIG_UNBLOCK, &set, 0); } } diff --git a/usr.bin/doscmd/timer.c b/usr.bin/doscmd/timer.c index 7f40725..90e69de 100644 --- a/usr.bin/doscmd/timer.c +++ b/usr.bin/doscmd/timer.c @@ -13,7 +13,8 @@ int08(regcontext_t *REGS) *(u_long *)&BIOSDATA[0x6c] -= 24*60*6*182; BIOSDATA[0x70]++; /* # times past mn */ } - + /* What is the real BIOS' sequence? */ + send_eoi(); softint(0x1c); } diff --git a/usr.bin/doscmd/trap.c b/usr.bin/doscmd/trap.c index 678d22d..4eb8688 100644 --- a/usr.bin/doscmd/trap.c +++ b/usr.bin/doscmd/trap.c @@ -321,13 +321,10 @@ sigbus(struct sigframe *sf) resettrace(REGS); if ((R_EFLAGS & (PSL_VIP | PSL_VIF)) == (PSL_VIP | PSL_VIF)) { - if (n_pending < 1) { - fatal("Pending interrupts out of sync\n"); - exit(1); - } resume_interrupt(); goto out; } + /* printf("%p\n", addr); fflush(stdout); */ debug (D_TRAPS2, "%04x:%04x [%02x %02x %02x] ", R_CS, R_IP, (int)addr[0], (int)addr[1], (int)addr[2]); @@ -516,7 +513,7 @@ sigbus(struct sigframe *sf) out: if (tmode) - tracetrap(REGS); + tracetrap(REGS); } #endif /* USE_VM86 */ @@ -601,11 +598,9 @@ sigalrm(struct sigframe *sf) if (tmode) resettrace(REGS); -/* debug(D_ALWAYS,"tick %d", update_counter); */ update_counter = 0; /* remember we've updated */ video_update((regcontext_t *)®S->sc); - hardint(0x08); -/* debug(D_ALWAYS,"\n"); */ + hardint(0x00); if (tmode) tracetrap(REGS); diff --git a/usr.bin/doscmd/tty.c b/usr.bin/doscmd/tty.c index eda368e..41e9792 100644 --- a/usr.bin/doscmd/tty.c +++ b/usr.bin/doscmd/tty.c @@ -125,16 +125,16 @@ static struct termios tty_cook, tty_raw; #define col (CursCol0) /* Local functions */ -static void _kbd_event(void *, regcontext_t *); +static void _kbd_event(int, int, void *, regcontext_t *); static void Failure(void *); static void SetVREGCur(void); -static void debug_event(void *, regcontext_t *); +static void debug_event(int, int, void *, regcontext_t *); static unsigned char inb_port60(int); static int inrange(int, int, int); -static void kbd_event(int); +static void kbd_event(int, int, void *, regcontext_t *); static u_short read_raw_kbd(int, u_short *); static void setgc(u_short); -static void video_async_event(void *, regcontext_t *); +static void video_async_event(int, int, void *, regcontext_t *); #ifndef NO_X static void dac2rgb(XColor *, int); @@ -234,10 +234,10 @@ console_denit(void *arg) } void -_kbd_event(void *pfd, regcontext_t *REGS) +_kbd_event(int fd, int cond, void *arg, regcontext_t *REGS) { - int fd = *(int *)pfd; - + if (!(cond & AS_RD)) + return; printf("_kbd_event: fd=%d\n", fd); kbd_read = 1; } @@ -317,19 +317,17 @@ console_init() } #if 0 - _RegisterIO(0, debug_event, 0, Failure); - _RegisterIO(fd, kbd_event, fd, Failure); + _RegisterIO(STDIN_FILENO, debug_event, 0, Failure); + _RegisterIO(fd, kbd_event, 0, Failure); #endif - _RegisterIO(fd, _kbd_event, &fd, Failure); + _RegisterIO(fd, _kbd_event, 0, Failure); } void video_setborder(int color) { #ifndef NO_X - _BlockIO(); XSetWindowBackground(dpy, win, pixels[color & 0xf]); - _UnblockIO(); #endif } void @@ -360,7 +358,7 @@ video_update(regcontext_t *REGS) static int icnt = 3; if (kbd_read) - kbd_event(kbd_fd); + kbd_event(kbd_fd, AS_RD, 0, REGS); if (--icnt == 0) { icnt = 3; @@ -651,7 +649,7 @@ struct { }; void -debug_event(void *pfd, regcontext_t *REGS) +debug_event(int fd, int cond, void *arg, regcontext_t *REGS) { static char ibuf[1024]; static int icnt = 0; @@ -660,6 +658,9 @@ debug_event(void *pfd, regcontext_t *REGS) static u_short cnt = 16 * 8; char *ep; int r; + + if (!(cond & AS_RD)) + return; r = read(STDIN_FILENO, ibuf + icnt, sizeof(ibuf) - icnt); if (r <= 0) @@ -777,13 +778,16 @@ inb_port60(int port) } void -kbd_event(int fd) +kbd_event(int fd, int cond, void *arg, regcontext_t *REGS) { + if (!(cond & AS_RD)) + return; + kbd_read = 0; printf("kbd_event: fd=%d\n", fd); if ((break_code = read_raw_kbd(fd, &scan_code)) != 0xffff) - hardint(0x09); + hardint(0x01); } void @@ -795,10 +799,11 @@ int09(REGISTERS) break_code = 0; scan_code = 0xffff; #if 0 - kbd_event(kbd_fd, sc); + kbd_event(kbd_fd, 0, sc, REGS); #endif } } + send_eoi(); } u_short @@ -974,12 +979,14 @@ printf("FORCED REDRAW\n"); } void -video_async_event(void *pfd, regcontext_t *REGS) +video_async_event(int fd, int cond, void *arg, regcontext_t *REGS) { #ifndef NO_X int int9 = 0; - int fd = *(int *)pfd; + if (!(cond & AS_RD)) + return; + for (;;) { int x; fd_set fdset; @@ -1012,7 +1019,7 @@ video_async_event(void *pfd, regcontext_t *REGS) case 0: XFlush(dpy); if (int9) - hardint(0x09); + hardint(0x01); return; default: if (FD_ISSET(fd, &fdset)) { @@ -1967,10 +1974,9 @@ init_window() err(1, "Could not open display ``%s''\n", XDisplayName(NULL)); xfd = ConnectionNumber(dpy); - _RegisterIO(xfd, video_async_event, &xfd, Failure); + _RegisterIO(xfd, video_async_event, 0, Failure); if (debug_flags & D_DEBUGIN) _RegisterIO(0, debug_event, 0, Failure); - _BlockIO(); /* Create window, but defer setting a size and GC. */ win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, @@ -1996,8 +2002,6 @@ init_window() XStoreName(dpy, win, "DOS"); - _UnblockIO(); - /* Get the default visual and depth for later use. */ depth = DefaultDepth(dpy, DefaultScreen(dpy)); visual = DefaultVisual(dpy, DefaultScreen(dpy)); diff --git a/usr.bin/doscmd/video.c b/usr.bin/doscmd/video.c index bd14804..3874a8c 100644 --- a/usr.bin/doscmd/video.c +++ b/usr.bin/doscmd/video.c @@ -138,6 +138,7 @@ video_inb(int port) return gdc_index; case VGA_InputStatus1Port: set_atc_index = 1; + VGA_InputStatus1 = (VGA_InputStatus1 + 1) & 15; return VGA_InputStatus1; default: return 0; @@ -259,6 +260,7 @@ video_init() define_input_port_handler(TSC_DataPort, video_inb); define_input_port_handler(GDC_IndexPort, video_inb); define_input_port_handler(GDC_DataPort, video_inb); + define_input_port_handler(VGA_InputStatus1Port, video_inb); define_output_port_handler(CRTC_IndexPortColor, video_outb); define_output_port_handler(CRTC_DataPortColor, video_outb); @@ -364,6 +366,8 @@ init_vga(void) vplane1 = vram + 0x10000; vplane2 = vram + 0x20000; vplane3 = vram + 0x30000; + + VGA_InputStatus1 = 0; } /* @@ -450,7 +454,6 @@ init_mode(int mode) BIOS_DpyRows = DpyRows; BIOS_CharHeight = CharHeight; - _BlockIO(); /* Load 'pixels[]' from default DAC values. */ update_pixels(); @@ -460,7 +463,6 @@ init_mode(int mode) /* Resize window if necessary. */ resize_window(); - _UnblockIO(); /* Mmap video memory for the graphics modes. Write access to 0xa0000 - 0xaffff will generate a T_PAGEFAULT trap in VM86 mode (aside: why not a |