Setting up the Brainboxes serial PCI card UC-246 with a BB16PCI958 chip on Linux (OpenSuse 11.0) We can do this by using the command "setserial". First, I discovered that some stupid programmer decided that the Linux kernel should support a maximum of 4 serial ports. So, when you want to use setserial, and you don't want to hack the kernel, make sure that you use ttyS0, ttyS1, tttyS2 or ttyS3. On most pc's, ttyS2 and ttyS3 are available (they are not used by the onboard hardware). Because the card id is not recognised by the kernel, we have to use setserial. In order to use setserial we need the know the io port address and interrupt of the card and the uart type. The first two can be found by the command lspci -v On my pc it gives the following output (run this command as root): 04:01.0 Multiport serial controller: Brain Boxes Device 0aa2 (rev 01) Subsystem: Brain Boxes Device 0403 Flags: medium devsel, IRQ 17 Memory at dfafff80 (32-bit, non-prefetchable) [size=128] I/O ports at dc80 [size=128] I/O ports at dc40 [size=64] I/O ports at dc30 [size=16] Memory at dfafff40 (32-bit, non-prefetchable) [size=64] Memory at dfafff30 (32-bit, non-prefetchable) [size=16] Capabilities: [40] Power Management version 2 Keep in mind that these addresses and interrupt are dynamically chosen by the PCI-controller in your pc. Fortunately, they stay the same as long as we don't change the hardware configuration. Putting the card into another PCI-slot can change the interrupt and/or address as well! An employee of Brainboxes wrote me that I have to select the address of the second io-port and that the card will emulate a 16C750 UART with a 64 bytes FIFO. http://www.brainboxes.com/Resources/j/j/n/BB16PCI958.pdf http://focus.ti.com/lit/ds/symlink/tl16c750.pdf So, the resulting setserial command (as root) will be (in my case): setserial /dev/ttyS2 port 0xdc40 irq 17 uart 16750 ^fourport Now, the card works. Are we happy? No, we are not happy because this way, the card will use a FIFO buffersize of 64 bytes instead of 128 and unfortunately, Linux does not allow us (without hacking the driver) to change the FIFO interrupt trigger level like we can do on windows after installing the windows driver from Brainboxes. Linux sets the RX interrupt trigger level at 32 bytes which is not sufficient for this application. /usr/include/linux/serial_reg.h #define UART_FCR 2 /* Out: FIFO Control Register */ #define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ #define UART_FCR7_64BYTE 0x20 /* Go into 64 byte mode (TI16C750) */ #define UART_FCR_R_TRIG_10 0x80 /usr/src/linux-2.6.25.20-0.5/drivers/serial/8250.c [PORT_16750] = { .name = "TI16750", .fifo_size = 64, .tx_loadsz = 64, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 | UART_FCR7_64BYTE, .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE, }, This is not the fault of Linux, it's the fault of Brainboxes who should supply a Linux driver that supports the 128 byte FIFO and let us configure the RX interrupt trigger level. The reason we do need the full 128 byte FIFO and the configurable interrupt trigger level, is that in this application the RX FIFO get overrun. The ADC-box produces a continuous datastream of 9220 bytes per second. Port params are 115K2 8N1 no flowcontrol. With a normal comport (16c550A with a FIFO buffersize of 16 bytes), an interrupt will occur when there are 14 bytes in the FIFO. At the time the operatingsystem is ready to call the serial port driver, more bytes have arrived, overwriting the older bytes in the FIFO. This is because the serialdriver needs to service the uart within 0.3 milli-Seconds after an interrupt took place. On windows and using the Brainboxes card, I was able to get rid of the RX overruns by adjusting the RX interrupt trigger level to 15% of the FIFO buffer size (19 bytes?). That means that when there are 19 bytes in the FIFO, an interrupt will be generated. This way, there is still place for 109 bytes before the FIFO get overrun (128 - 19 = 109). And that means more time for the operatingsystem when it is very busy(multitasking, whatever). With this setting the serialdriver needs to service the uart within 12 milli-Seconds after an interrupt took place. On Linux, I had less frequent "sync errors" with the normal onboard serial port (/dev/ttyS0) than with the UC-246 serial PCI-card. Probably because the onboard serial port has it's own exclusive hardware interrupt line. A PCI device shares it's interrupt with other devices. In my case, when using the standard onboard serial port on Linux, I got sync errors only when I inserted an USB-stick into to the pc... On windows, on the other hand, it was impossible to use this application with the standard onboard serial port.