diff -u /root/doscmd-20040330/bios.c ./bios.c --- /root/doscmd-20040330/bios.c Fri May 5 19:34:31 2006 +++ ./bios.c Fri May 5 19:39:27 2006 @@ -297,7 +297,10 @@ ivec[0x12] = vec; register_callback(vec, int12, "int 12"); - vec = insert_softint_trampoline(); + if(fossil) + vec = insert_fossil_softint_trampoline(); + else + vec = insert_softint_trampoline(); ivec[0x14] = vec; register_callback(vec, int14, "int 14"); diff -u /root/doscmd-20040330/callback.c ./callback.c --- /root/doscmd-20040330/callback.c Fri May 5 19:34:31 2006 +++ ./callback.c Fri May 5 19:39:27 2006 @@ -76,6 +76,25 @@ 2, 0, }; +/* + * From the FOSSIL spec: + * The driver has a "signature" that can be used to determine whether it is + * present in memory. At offset 6 in the INT 14h service routine is a word, + * 1954h, followed by a byte that specifies the maximum function number + * supported by the driver. This is to make it possible to determine when a + * driver is present and what level of functionality it provides. + */ +u_char fossil_softint_trampoline[] = { + 0xf4, /* HLT */ + 0xfb, /* STI */ + 0xca, /* RETF 2 */ + 2, + 0, + 0, + 0x54, + 0x19, + 0x1b, /* Max. Supported FOSSIL AH */ +}; u_char hardint_trampoline[] = { 0xf4, /* HLT */ 0xcf, /* IRET */ @@ -102,6 +121,13 @@ { return (insert_generic_trampoline( sizeof(softint_trampoline), softint_trampoline)); +} + +u_long +insert_fossil_softint_trampoline(void) +{ + return (insert_generic_trampoline( + sizeof(fossil_softint_trampoline), fossil_softint_trampoline)); } u_long diff -u /root/doscmd-20040330/callback.h ./callback.h --- /root/doscmd-20040330/callback.h Fri May 5 19:34:31 2006 +++ ./callback.h Fri May 5 19:39:27 2006 @@ -9,5 +9,6 @@ callback_t find_callback(u_long); u_long insert_generic_trampoline(size_t, u_char *); u_long insert_softint_trampoline(void); +u_long insert_fossil_softint_trampoline(void); u_long insert_hardint_trampoline(void); u_long insert_null_trampoline(void); diff -u /root/doscmd-20040330/doscmd.c ./doscmd.c --- /root/doscmd-20040330/doscmd.c Fri May 5 19:34:31 2006 +++ ./doscmd.c Fri May 5 19:39:27 2006 @@ -511,7 +511,7 @@ FILE *fp; char *col; - while ((c = getopt(argc, argv, "234AbCc:Dd:EGHIi:kLMOo:Pp:RrS:TtU:vVxXYz")) != -1) { + while ((c = getopt(argc, argv, "234AbCc:Dd:EFGHIi:kLMOo:Pp:RrS:TtU:vVxXYz")) != -1) { switch (c) { case '2': debug_flags |= D_TRAPS2; @@ -551,6 +551,9 @@ break; case 'E': debug_flags |= D_EXEC; + break; + case 'F': + fossil = 1; break; case 'G': debug_flags |= D_VIDEO; diff -u /root/doscmd-20040330/doscmd.h ./doscmd.h --- /root/doscmd-20040330/doscmd.h Fri May 5 19:34:31 2006 +++ ./doscmd.h Fri May 5 19:39:27 2006 @@ -224,6 +224,9 @@ extern int search_floppy(int i); extern void disk_bios_init(void); +/* int14.c */ +extern int fossil; + /* int16.c */ void int16(regcontext_t *); diff -u /root/doscmd-20040330/int14.c ./int14.c --- /root/doscmd-20040330/int14.c Fri May 5 19:34:31 2006 +++ ./int14.c Fri May 5 20:23:09 2006 @@ -46,6 +46,9 @@ #include "AsyncIO.h" #include "com.h" +/* exports */ +int fossil = 0; + #define N_BYTES 1024 struct com_data_struct { @@ -58,7 +61,9 @@ int ids; /* input data size */ int ods; /* output data size */ int emptyint; + int fossil_mode; /* FOSSIL has been enabled */ struct termios tty; + unsigned char param; /* Copy of init params */ unsigned char div_latch[2]; /* mirror of 16550 R0':R1' read/write */ unsigned char int_enable; /* mirror of 16550 R1 read/write */ @@ -257,7 +262,7 @@ struct com_data_struct *cdsp; int i; - debug(D_PORT, "int14: dl = 0x%02X, al = 0x%02X.\n", R_DL, R_AL); + debug(D_PORT, "int14: ah = 0x%02X, dl = 0x%02X, al = 0x%02X.\n", R_AH, R_DL, R_AL); if (R_DL >= N_COMS_MAX) { if (vflag) dump_regs(REGS); @@ -269,16 +274,31 @@ case 0x00: /* Initialize Serial Port */ com_set_line(cdsp, R_DL + 1, R_AL); R_AH = get_status(cdsp); - R_AL = 0; + if (cdsp->fossil_mode) { + R_AL = 0x08; + R_AL |= 0x80; + } + else + R_AL = 0; break; case 0x01: /* Write Character */ if (write_char(cdsp, R_AL)) { - R_AH = get_status(cdsp); + R_AH = get_status(cdsp); + if (cdsp->fossil_mode) { + R_AL = 0x08; + R_AL |= 0x80; + } + else R_AL = 0; } else { - debug(D_PORT, "int14: lost output character 0x%02x\n", R_AL); - R_AH = LS_SW_TIME_OUT; + debug(D_PORT, "int14: lost output character 0x%02x\n", R_AL); + R_AH = LS_SW_TIME_OUT; + if (cdsp->fossil_mode) { + R_AL = 0x08; + R_AL |= 0x80; + } + else R_AL = 0; } break; @@ -296,28 +316,193 @@ case 0x03: /* Status Request */ R_AH = get_status(cdsp); - R_AL = 0; + if (cdsp->fossil_mode) { + R_AL = 0x08; + R_AL |= 0x80; + } + else + R_AL = 0; break; case 0x04: /* Extended Initialization */ - R_AX = (LS_SW_TIME_OUT) << 8; + if (fossil) { + cdsp->fossil_mode = 1; + R_AX = 0x1954; + R_BL = 0x1b; /* Max supported FOSSIL AH */ + R_BH = 5; + } + else + R_AX = (LS_SW_TIME_OUT) << 8; break; - case 0x05: /* Modem Control Register operations */ - switch (R_AH) { - case 0x00: /* Read Modem Control Register */ + case 0x05: /* Modem Control Register operations/FOSSIL deinit */ + if (fossil && cdsp->fossil_mode) + cdsp->fossil_mode = 0; + else { + switch (R_AH) { + case 0x00: /* Read Modem Control Register */ R_AX = (LS_SW_TIME_OUT) << 8; break; - case 0x01: /* Write Modem Control Register */ + case 0x01: /* Write Modem Control Register */ R_AX = (LS_SW_TIME_OUT) << 8; break; - default: + default: unknown_int3(0x14, 0x05, R_AL, REGS); break; + } } break; + + case 0x06: /* FOSSIL raise/lower DTR */ + if(cdsp->fossil_mode) { + switch (R_AL) { + case 0: + ioctl(cdsp->fd, TIOCCDTR); + break; + case 1: + ioctl(cdsp->fd, TIOCSDTR); + break; + } + break; + } + + case 0x08: /* FOSSIL Flush output buffer */ + if(cdsp->fossil_mode) { + flush_out(cdsp); + break; + } + + case 0x09: /* FOSSIL Purge output buffer */ + if(cdsp->fossil_mode) { + cdsp->ods = 0; + break; + } + + case 0x0a: /* FOSSIL Purge input buffer */ + if(cdsp->fossil_mode) { + cdsp->ids = 0; + break; + } + + case 0x0b: /* FOSSIL Transmit no wait */ + if(cdsp->fossil_mode) { + if (cdsp->ods < N_BYTES) { + if (write_char(cdsp, R_AL)) + R_AX = 1; + else + R_AX = 0; + } + else + R_AX = 0; + break; + } + + case 0x0c: /* FOSSIL Non-destructive read-ahead */ + if(cdsp->fossil_mode) { + if(cdsp->ods) { + R_AH = 0; + R_AL = cdsp->inbuf[0]; + } else + R_AX = 0xffff; + break; + } + + case 0x0f: /* FOSSIL Set flow control */ + if(cdsp->fossil_mode) { + if(R_AL & 0x01) /* Enable output Xon/Xoff */ + cdsp->tty.c_iflag |= IXON; + else + cdsp->tty.c_iflag &= ~(IXON); + + if(R_AL & 0x02) /* Enable CTR/RTS */ + cdsp->tty.c_cflag |= CCTS_OFLOW|CRTS_IFLOW; + else + cdsp->tty.c_iflag &= ~(CCTS_OFLOW|CRTS_IFLOW); + + if(R_AL & 0x08) /* Enable input Xon/Xoff */ + cdsp->tty.c_iflag |= IXOFF; + else + cdsp->tty.c_iflag &= ~(IXOFF); + + tcsetattr(cdsp->fd, 0, &cdsp->tty); + break; + } + + case 0x18: /* FOSSIL Read block */ + if(cdsp->fossil_mode) { + int rd = R_CX; + + input(cdsp, 0); + if(rd > cdsp->ids) + rd=cdsp->ids; + if(rd) { + memmove((char *)MAKEPTR(R_ES, R_DI), cdsp->inbuf, rd); + if(rd < cdsp->ids) + memmove(cdsp->inbuf, cdsp->inbuf + rd, N_BYTES - rd); + cdsp->ids -= rd; + R_AX = rd; + } else + R_AX = 0; + break; + } + + case 0x19: /* FOSSIL Write block */ + if(cdsp->fossil_mode) { + int wr = R_CX; + if(wr > N_BYTES - cdsp->ods) + wr=N_BYTES - cdsp->ods; + if(wr) { + memcpy(cdsp->outbuf + cdsp->ods, (char *)MAKEPTR(R_ES, R_DI), wr); + cdsp->ods += wr; + output(cdsp); + R_AX = wr; + } else + R_AX = 0; + break; + } + + case 0x1a: /* FOSSIL Break begin/end */ + if(cdsp->fossil_mode) { + switch(R_AL) { + case 0: + ioctl(cdsp->fd, TIOCCBRK); + break; + case 1: + ioctl(cdsp->fd, TIOCSBRK); + break; + } + break; + } + + case 0x1b: /* FOSSIL Driver information */ + if(cdsp->fossil_mode) { + unsigned char *p; + int bufpos=0; + int info_size=19; + const char *id_string="doscmd FOSSIL"; + p = (unsigned char *)MAKEPTR(R_ES, R_DI); + p[bufpos++]=info_size&0xff; + p[bufpos++]=(info_size>>8)&0xff; + p[bufpos++]=5; + p[bufpos++]=0; + PUTVEC(*(u_short *)p, *(ushort *)(p + sizeof(u_short)), (u_long)id_string); + bufpos+=sizeof(u_short)*2; + p[bufpos++]=N_BYTES & 0xff; + p[bufpos++]=(N_BYTES>>8) & 0xff; + p[bufpos++]=(N_BYTES - cdsp->ids) & 0xff; + p[bufpos++]=((N_BYTES - cdsp->ids) >> 8) & 0xff; + p[bufpos++]=N_BYTES & 0xff; + p[bufpos++]=(N_BYTES>>8) & 0xff; + p[bufpos++]=(N_BYTES - cdsp->ods) & 0xff; + p[bufpos++]=((N_BYTES - cdsp->ods) >> 8) & 0xff; + p[bufpos++]=80; + p[bufpos++]=25; + p[bufpos++]=cdsp->param & BITRATE_9600; + break; + } + default: unknown_int2(0x14, R_AH, REGS); break; @@ -353,6 +538,7 @@ port, cdsp->path); return; } + cdsp->param = param; cdsp->ids = cdsp->ods = cdsp->emptyint = 0; cdsp->int_enable = 0; @@ -402,12 +588,24 @@ } switch (param & BITRATE_9600) { case BITRATE_110: - speed = B110; - spd = 110; + if (fossil) { + speed = B19200; + spd = 19200; + } + else { + speed = B110; + spd = 110; + } break; case BITRATE_150: - speed = B150; - spd = 150; + if (fossil) { + speed = B38400; + spd = 38400; + } + else { + speed = B150; + spd = 150; + } break; case BITRATE_300: speed = B300;