Date: Sat, 18 Mar 1995 16:18:46 +1000 From: Bruce Evans <bde@zeta.org.au> To: freebsd-hackers@freefall.cdrom.com, uhclem@nemesis.lonestar.org Subject: Re: Multiport serial cards Message-ID: <199503180618.QAA10402@godzilla.zeta.org.au>
next in thread | raw e-mail | index | archive | help
>[1]A 1-char "FIFO" as found on 8250's should be adequate provided you have >[1]no bus-hogging devices. sio can handle continuous data in both directions >[1]at once at 115.2 on 2 ports (but not 3) on a 486DX/33 with 8250's. The >[1]system load for this is about 60% (too high for continuous use). A >[1]486DX2/66 with 16550's can probably handle about 6 times as many ports. >It should be worse than that. 1/2880 cps = 347usec/character >and if you have four ports on a board that means a characters is available >on that board every 86usec worst case (the best case is 347usec). >And divide the times by two if the data is moving in both directions >(43usec worst - 173.5usec best). The factor of 6 is partly from assuming 16550's so that the worst case latency requirement can be reduced by a factor of 16 if desired. sio currently sets the fifo trigger level to 14 (code to reduce it if an overrun occurs was found to be braindamaged and is currently disabled), so the worse case latency requirement is only reduced by a factor of 16 - 14) = 2. Other overheads would become more restrictive than latency if the fifo trigger level was set lower than 14. That's part of the reson why a DX2/66 with 16550's can only be expected to be 6 times better. The latency doesn't scale linearly with the number of boards. A latency of about 327usec could be made to work if required. The driver would have to read one character from each of 4 ports within (347 - 327) = 20usec of receiving the interrupt. This is possible, but it would increase overhead to look for serial events in the right order. The worst case for the current sio order is about 30usec per port instead of 5usec (25 extra for transmitting 16 chars). Latency is less of a problem than efficiency so I've optimized efficiency. (I've also optimized too much for the non- multiport case because that's all I have :-). The latency for output is smaller than for input. Output has less overhead, and can wait (at the cost of throughput). The driver has to be careful not to let output processing increase input latency too much. All this assumes that only one driver requires low latency and that polling all ports is acceptable (it is acceptable for xx(x)50s on the isa bus because the interface is braindamaged enough to require lots of polling even for one port). If there is more than one, then giving each a fair share is like the problem of looking for serial events in the right order, but harder. >If you are using 8250s and must service an interrupt every 86usec, it >just isn't going to work. The ISA bus timing (I/O cycle is two 8.3MHz >clocks long plus wait states and chip access-recovery timing) even >becomes a limiting factor. This was challenging on 8088's, but the same techniques that make interrupt driven serial i/o at 19200bps possible on 8088's make it easy on anything faster than a 386/20. The ISA bus timing indeed becomes the limiting factor. I didn't notice it on a 386/20, but on 486's my rule for writing efficient serial drivers is to minimise the number of i/o's and don't worry much about minimising the number of integer instructions. >How long does it take for the kernel to even >poll the 8259 and figure out which interrupt it is? The kernel might also >want to save some state and a few other things before jumping to a driver. It actually polls the UARTs. Polling the 8259 isn't necessary because interrupts are vectored. Non-shared interrupts may be more efficient because no polling is required to decide the device. OTOH it may be good to poll the 8259 and/or other UARTs before returning from an interrupt. Currently, the UART that caused the interrupt has to be polled before returning because of edge triggered interrupt braindamage. I'd like to be able to poll the relevant 8259 instead, so as to poll all the other devices on the same 8259 for free, but the same edge trigger braindamage stops the 8259 from keeping useful information for the interrupt that is currently in service (the interrupt request register gives the latched value). The kernel saves a smaller than usual amount of state before entering the serial driver. The i386 saves a lot more state (too much) before giving control to the kernel. The worst case is when interrupts were disabled for some reason (most often for the kernel entering another handler) before a serial interrupt can be accepted. The average latency is 5-10usec on a DX2/66 and the worst case is (I hope) < 20usec. >I promise that you aren't going to keep up with constant serial interrupts >every 86usec (or less) in an ISA system. Not without some intelligent This is routine... >The 8250's simply won't be reliable unless you ban all disk or tape >I/O, and some brands of video boards that have to turn interrupts >off for a msec or so here and there. ...at least with non-braindamaged other hardware :-). Fortunately, braindamaged other hardware doesn't seem to be very common: disk: - scsi drivers never disable interrupts (except ncr5380.c disables interrupts and then busy-waits :-(:-(). - the wd driver never disables interrupts. Not disabling them apparently causes problems for some drive/controllers under linux, so this may be a bug. The linux disk driver now disables them by default, so everyone with 16450's suffers from serial overruns to allow the broken drive/controllers to work. - even the mcd driver only disables interrupts for about 10usec :-) (while it does a sequence of outb's). - some busmastering devices hog the bus, and of course the number of cycles available for processing is reduced while DMA is occurring). tape: - scsi drivers never disable interrupts (except see above). video: - syscons.c never disables interrupts. This may be a bug. - the X server disables interrupts for a looong time while starting up. A 20K fifo would be necessary to fix this. other: - joy.c disables interrupts and then polls. Hard to avoid :-(. - other drivers in sys/i386/isa either don't disable interrupts, or disable them only for short periods (< 10usec). Anyway, for a special application, just don't run braindamaged h/w simultaneously. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199503180618.QAA10402>