10. The Serial group of Modules

This is the code that works our serial emulation. This needs to be very fast if we are to convince DOS that we have a very fast serial port.

10.1. Remarks in base/serial/ser_defs.h

Extensions to serial debugging.

SER_DEBUG_MAIN (0 or 1) - extra debug output on the most critical information.

SER_DEBUG_HEAVY (0 or 1) - super-heavy extra debug output, including all ports reads and writes, and every character received and transmitted!

SER_DEBUG_INTERRUPT (0 or 1) - additional debug output related to serial interrupt code, including flagging serial interrupts, or PIC-driven code.

SER_DEBUG_FOSSIL_RW (0 or 1) - heavy FOSSIL debug output, including all reads and writes.

SER_DEBUG_FOSSIL_STATUS (0 or 1) - super-heavy FOSSIL debug output, including all status checks.

You must recompile dosemu everytime one of these constants are modified. Just type 'make' in the dosemu dir and it will recompile the changes only.


IMPORTANT INFO about com[] variable array structure used in serial.c

Most of the serial variables are stored in the com[] array. The com[] array is a structure in itself. Take a look at the 'serial_t' struct declaration in the serial.h module for more info about this. Only the most commonly referenced global variables are listed here:

config.num_ser Number of serial ports active. com[x].base_port The base port address of emulated serial port. com[x].real_comport The COM port number. com[x].interrupt The PIC interrupt level (based on IRQ number) com[x].mouse Flag mouse (to enable extended features) com[x].fd File descriptor for port device com[x].dev[] Filename of port port device com[x].dev_locked Flag whether device has been locked

The arbritary example variable 'x' in com[x] can have a minimum value of 0 and a maximum value of (config.numser - 1). There can be no gaps for the value 'x', even though gaps between actual COM ports are permitted. It is strongly noted that the 'x' does not equal the COM port number. This example code illustrates the fact, and how the com[] array works:

for (i = 0; i < config.numser; i++) s_printf("COM port number %d has a base address of %x", com[i].real_comport, com[i].base_port);

10.2. Functions in base/serial/ser_init.c

These are the functions defined in base/serial/ser_init.c.

10.2.1. serial_init

This is the master serial initialization function that is called upon startup of DOSEMU to initialize ALL the emulated UARTs for all configured serial ports. The UART is initialized via the initialize_uart function, which opens the serial ports and defines variables for the specific UART.

If the port is a mouse, the port is only initialized when i

10.3. Items for Fixing in base/serial/ser_init.c

This needs more work before it is implemented into /etc/dosemu.conf as an 'rtscts' option.

10.4. Functions in base/serial/ser_ports.c

These are the functions defined in base/serial/ser_ports.c.

10.4.1. do_serial_in

The following function returns a value from an I/O port. The port is an I/O address such as 0x3F8 (the base port address of COM1). There are 8 I/O addresses for each serial port which ranges from the base port (ie 0x3F8) to the base port plus seven (ie 0x3FF). [num = abritary port number for serial line, address = I/O port address]

10.4.2. do_serial_out

The following function writes a value to an I/O port. The port is an I/O address such as 0x3F8 (the base port address of COM1). [num = abritary port number for serial line, address = I/O port address, val = value to write to I/O port address]

10.5. Items for Fixing in base/serial/ser_ports.c

Should clearing UART cause THRE int if it's enabled? */


Fix the calculation assumption


Is this safe to put this here? */


Is this safe to put this here? */

10.6. Functions in base/serial/ser_irq.c

These are the functions defined in base/serial/ser_irq.c.

10.6.1. serial_int_engine

This function is the serial interrupts scheduler. Its purpose is to update interrupt status and/or invoke a requested serial interrupt. If interrupts are not enabled, the Interrupt Identification Register is still updated and the function returns. See pic_serial_run() below it is executed right at the instant the interrupt is actually invoked.

Since it is not possible to run the interrupt on the spot, it triggers the interrupt via the pic_request() function (which is in pic.c) and sets a flag that an interrupt is going to be occur soon.

Please read pic_serial_run() for more information about interrupts. [num = port, int_requested = the requested serial interrupt]

10.6.2. pic_serial_run

This function is called by the priority iunterrupt controller when a serial interrupt occurs. It executes the highest priority serial interrupt for that port. (Priority order is: RLSI, RDI, THRI, MSI)

Because it is theoretically possible for things to change between the interrupt trigger and the actual interrupt, some checks must be repeated.

10.6.3. serial_run

This is the main housekeeping function, which should be called about 20 to 100 times per second. The more frequent, the better, up to a certain point. However, it should be self-compensating if it executes 10 times or even 1000 times per second. Serial performance increases with frequency of execution of serial_run.

Serial mouse performance becomes more smooth if the time between calls to serial_run are smaller.

10.7. Remarks in base/serial/ser_irq.c

Linux code hackers: How do I detect a break signal without having to rely on Linux signals? Can I peek a 'break state bit'? Also, how do I 'turn on' and 'turn off' the break state, via an ioctl() or tcsetattr(), rather than using POSIX tcsendbrk()?

10.8. Items for Fixing in base/serial/ser_irq.c

how do we cancel a PIC interrupt, when we have come this far?


Perhaps this can be modified to limit max chain length?

10.9. Functions in base/serial/int14.c

These are the functions defined in base/serial/int14.c.

10.9.1. int14

The following function executes a BIOS interrupt 0x14 function. This code by Mark Rejhon replaced some very buggy, old int14 interface a while back. These routines are not flawless since it does not wait for a character during receive, and this may confuse some programs.

10.10. New Ideas for base/serial/int14.c

If any of you coders are ambitious, try thinking of the following: - Converting this into inline assembler and use direct port access

10.11. Items for Fixing in base/serial/fossil.c

This really should be write-with-wait. */

10.12. Items for Fixing in include/serial.h

Why does a RX_BUFFER_SIZE of 256 cause slower performance than a size of 128?