Subject: Re: general {82,164,165}50 UART driver
To: Onno van der Linden <onno@simplex.nl>
From: Chris G Demetriou <Chris_G_Demetriou@UX2.SP.CS.CMU.EDU>
List: tech-kern
Date: 05/29/1996 21:40:30
> After Chris' justified complaints about the i386ness of an ISA serial driver
> that I made available for anonymous ftp I gave it some thoughts.
>
> Here are a couple of remarks about a NetBSD driver for the {82,164,165}50 UART.
> Four ports currently use this chip: i386, hp300, alpha and amiga with zorro(?)
> board.
The way i think about it, right now there's the ISA 'com' driver and
the hp300 'dca' driver. There will in all likelyhood be other users
of the ISA 'com' driver in the future.
> (1) handle *everything* in the interrupt routine itself.
> hp300 uses this strategy. i386 used to do this until 1.1.
This is pretty much a lose.
> (2) receive the data, put it in queue and let a higher level
> routine handle the rest (mainly line->l_rint). compoll()
> is the higher level routine that does this. It's periodically
> called from softclock() and reads all the queues for all the
> serial lines and put the contents into the buffers at the tty layer.
> the current isa driver in /sys/dev/isa/com.c uses this strategy.
This is, too.
> (3) receive the data, put it in a queue and generate a software interrupt
> (setsofttty()). comsoft() is the higher level routine that handles
> this software interrupt. It checks all the queues etc. etc.
> the serial driver available from ftp.fwi.uva.nl uses this strategy
This makes sense.
> (1) is out of the question on i386 because it drops too many characters
> at higher speeds.
> (2) is possible for all ports. Currently the isa driver isn't receiving
> data at a high enough intr level for the i386 to handle higher speeds well.
> (3) is currently not possible on the alpha. They have no such thing as
> setsofttty(). There's however support in /sys/arch/alpha/alpha/machdep.c
> for software interrupts in the do_sir routine.
It's not a problem on the alpha; the code is easy to add. that's not
the real problem, though. (My main objection was not to this, though
suggesting that I add this to the alpha port after the 'feature
freeze' is a non-starter, from my point of view. Read on... 8-)
> A big question about the "higher level" routine (compoll() or comsoft())
> still is whether to run at spltty() for most of the time (just like the
> z8530 driver) or to minimize it like the current isa driver.
_THIS_ is the big problem.
If the implementation is such that the 'higher level' routine runs at
spltty() most of the time, on architectures which can't cleanly
control their interrupt priorities it ends up that (1) above, inlining
everything in the interrupt routine, is more efficient.
You're going to lose in any case if the 'higher level' routine runs at
spltty(), but at you'll lose less if all of the processing is done
in-line in the interrupt handler.
Now, it's possible to do something less losing, a hybrid of
what's currently done in the ISA driver and what was done in your new
driver, e.g. something along the lines of delaying processing to a
software interrupt, then processing characters like:
while (chars left to do) {
get char from our queue;
s = spltty()
run line input routine
splx(s);
}
However, _that_ has the following problems:
(1) it does a _LOT_ of spl frobbing, which may end up being
expensive because of overuse.
(2) it defeats any hope of optimization of the line input
routine to handle multiple characters.
I think that it may be 'correct' to require line input processing to
happen at spltty() (so that network interrupts are blocked, as well,
for ttys that double as network interfaces), but i'm not familiar with
that bit of code and haven't thought about it much.
The problem that the snippet above solves is that it drops IPL
frequently, so that interrupt handling can be done on ports like the
Alpha where spltty() will actually block TTY hardware and other device
interrupts.
> Conclusions:
> (1) define IPL_SER (interrupt level for the serial driver) for each
> architecture. IPL_SER would be IPL_HIGH on the i386.
> run the interrupt routine at IPL_SER.
This seems necessary, though it's not clear why you'd want to define
it globally as the 'serial port hardware interrupt processing level'
for a given architecture.
it's really not "IPL_SER", it's IPL_GODDAMNED_STUPID_NS16X50_SERIAL_HARDWARE.
Other, smarter, serial devices may well want to interrupt at lower
levels, because they don't suffer the same dain bramage.
> (2a) change my driver (the one on ftp.fwi.uva.nl) to use the
> softclock interrupt routine for comsoft() instead of
> the tty software interrupt.
>
> or
>
> (2b) if possible, add a bit of code to alpha/machdep.c for tty software
> interrupts in do_sir() and call comsoft() from there.
> It looks like the hp300 needs this too.
>
> Question:
> Should I go for (2a) or (2b) ?
> or
> Which is "better" 'software interrupts' or 'periodic checks via softclock()' ?
Software interrupts are better, by far.
chris