Date: Tue, 29 Mar 94 07:54:48 -0700 From: jan kok To: djgpp AT sun DOT soe DOT clarkson DOT edu Subject: problem using X00 utility with djgcc x00 is a utility (get from ftp.clarkson.edu /pub/msdos/fossil) that replaces the int14 BIOS code (serial port, etc. drivers) with interrupt-mode drivers. I'm having trouble making it work reliably. The main problem is that it stops receiving characters from the serial port after receiving a random, variable number (a couple dozen) of characters. After stopping receiving characters, the keyboard input still works ok. Reinitializing the serial port makes it receive some more, but it will stop receiving again. I think the problem might be due to using djgcc (version 109) and the 32-bit address environment. Although I don't need to pass any 32-bit addresses to x00 to make it fail, I am still pretty suspicious, because some of the x00 commands (such as 0x18 (read block) or 0x1B (get driver info)) require passing a pointer to a buffer, by putting the pointer into es:di. I don't see how this can work, if the address is > 1MB, because es is a 16-bit register. Is there a way in the djgcc environment to allocate some memory in the bottom 1MB, in case I want to use one of the commands which needs a pointer? Could the problem be an incompatibility of x00 with a 32-bit environment, or am I doing something else wrong? The odd thing is, that the x00 package provides an interface to Microsoft C, including the huge model. I don't know if that works, though. The serial card that I'm using has a UM82C862F which is a combination IDE, floppy, printer, dual serial, and Hollerith card reader interface. x00 thinks it's a couple of 16450s at the usual COM1 and COM2 addresses and IRQs. QuickLinkII (communication program) and MS-Kermit have no problem communicating with it. What is exception 13 (are where are the exception numbers documented?) Thanks, - Jan --------------------- reg.h ------------------- typedef struct { unsigned ax; unsigned bx; unsigned cx; unsigned dx; unsigned si; unsigned di; unsigned bp; unsigned es; } REGISTERS; ---------------------------------------------- /* int14.s */ /* This file creates a function "int14" which can be called from C. It provides an interface to the int 14 BIOS call. */ .globl _int14 _int14: /* Create new stack frame, save caller's registers. */ pushl %ebp movl %esp, %ebp pushl %ebx pushl %ecx pushl %edx pushl %esi pushl %edi pushl %es /* Get the arg to int14, which is a ptr to a "REGISTERS" structure. */ movl 8(%ebp), %eax pushl %eax /* Save it for later... */ /* Move data from structure into registers. */ /* ebp and esi are never used as args to int14. */ /* pushl 28(%eax) */ push $0 pop %es /* gets exception 13 if use pushl 28(%eax) above. */ movl 20(%eax), %edi movl 12(%eax), %edx movl 8(%eax), %ecx movl 4(%eax), %ebx movl (%eax), %eax /* Call serial port routine. */ int $0x14 /* Move regs to REGISTERS structure. */ /* Nothing is ever returned in edi, esi or ebp. */ xchg %eax, (%esp) popl (%eax) /* eax from int14 goes to structure. */ movl %ebx, 4(%eax) movl %ecx, 8(%eax) movl %edx, 12(%eax) /* Restore caller's registers. */ /* This function has no return value, so no need to set eax. */ popl %es popl %edi popl %esi popl %edx popl %ecx popl %ebx leave ret ----------------- test program ----------------- #include "reg.h" #include #include #define X00OK 0x1954 #define Initialize 0x1c /* x00 driver takes both 0x4 and 0x1c*/ #define Deinitialize (Initialize+1) #define FP_OFF(x) (((int)x) & 15) #define FP_SEG(x) (((int)x) >> 4) REGISTERS regs; int port = 1; #define INFOLEN 20 /* Call the x00 driver with given function code. /* See the files x00ref.doc and fossil.cht for more info on x00. /* Note, I wasn't able to get Block Read command to work (bug in int14.s ?), /* so I used Peek Ahead instead. */ void x00port(code) { regs.ax = code << 8; regs.dx = port; int14(®s); } /* Initialize serial port. */ void initport() { regs.bx = 0; /* No ^C processing. */ x00port(Initialize); if (regs.ax != X00OK) { printf("Serial port initialization failed. Please make sure x00 driver is installed.\n"); exit(1); } regs.ax = (0 << 8) /* Set Baud Rate. */ + (0 << 5) /* 19200 baud. */ + (8-5); /* 8 bits. */ regs.dx = port; int14(®s); x00port(0xf); /* Disable flow control. */ x00port(0xa); /* Purge Input Buffer. */ } main() { int i; int key; char infobuf[INFOLEN]; initport(); regs.bx = 0; /* No ^C processing. */ regs.dx = 0xff; /* Initialize keyboard. */ regs.ax = Initialize << 8; int14(®s); if (regs.ax != X00OK) { printf("Keyboard initialization failed.\n"); exit(1); } printf("go!\n"); #if 1 /* This loop implements a terminal emulator (for debugging). */ while (1) { x00port(0x20); /* Read With No Wait serial port. */ if (regs.ax != 0xffff) { /* If a char has arrived from serial port, print it. */ printf("%c", regs.ax); fflush(stdout); } x00port(0xd); /* Peek Ahead keyboard. */ if (regs.ax != 0xffff) { /* If a key was typed, get it, echo it, and send it to serial port. ^C exits this program. */ x00port(0xe); /* Read Keyboard. */ key = regs.ax & 0xff; /* x00 leaves garbage in upper byte. */ if (key == 3) /* ^C - exit */ break; if (key != 13 && (key < 32 || key > 126)) /* Not a printable character, echo its hex code. */ printf("<0x%x>", key); else printf("%c", key); fflush(stdout); /* Make char echo immediately. */ switch (key) { case 'i': /* Display x00 info. */ regs.cx = INFOLEN; /* ??????????? es is a 16-bit register. How could this work??????????? */ regs.es = FP_SEG(infobuf); regs.di = FP_OFF(infobuf); printf("infobuf=0x%x regs.es=0x%x regs.di=0x%x\n", infobuf, regs.es, regs.di); sleep(1); x00port(0x1b); /* Get x00 info. */ for (i = 0; i < INFOLEN; i++) printf("%x ", 0xff & infobuf[i]); printf("\n"); break; case 'r': /* Reinit serial port. */ initport(); break; case 's': /* Print status. */ x00port(0x3); printf("status = 0x%x\n", regs.ax); break; case 't': /* Transmit a string. */ for (i='a'; i <= 'a'; i++) { regs.ax = 0xb << 8 /* Transmit Char, No Wait. */ + i; /* The char to transmit. */ regs.dx = port; int14(®s); if (regs.ax == 0) printf("\7Xmit buf full\n"); } break; case 'u': system("xu s"); break; default: regs.ax = 0xb << 8 /* Transmit Char, No Wait. */ + key; /* The char to transmit. */ regs.dx = port; int14(®s); if (regs.ax == 0) printf("\7Xmit buf full\n"); } /* Switch. */ } /* If keyboard char. */ } /* Main while loop. */ #endif regs.ax = Deinitialize << 8; regs.dx = 0xff; /* Deactivate keyboard. */ int14(®s); x00port(Deinitialize); /* Deactivate Port. */ }