Subject: BOCA - ioAT66 driver for NetBSD-1.3 (long)
To: None <tech-kern@NetBSD.ORG>
From: Lucio de Re <lucio@proxima.alt.za>
List: tech-kern
Date: 01/07/1998 17:30:46
BOCA make a very poorly documented unintelligent serial card, they call 
the ioAT66, with six 16550-look-alike UARTS.

I have modified the existing BOCA driver for this particular card, and, 
within certain restrictions into which I will delve below, it seems to 
work correctly.

Is there any interest out there for this particular driver?  I managed 
to streamline some of the existing code, possibly not to any great 
degree, and it may be worth retrofitting the changes to the other 
multiport card drivers...  Let me know, anyone.

Now for some of the issues that were raised, probably through too 
little understanding on my part of how device drivers and the CONFIG 
utility are meant to interact:

1. Each individual UART on the ioAT66 can be configured to one of two
I/O ports and one of two interrupt request levels, the first interrupt 
level is fixed and unique (on the adapter) for that port, while the 
alternative is one of two choices, and the choice is the same for all 
ports.  This second IRQ is, in other words, shared by all ports that 
have been set to share it.

2. To complicate the issue, one of the fixed IRQs is "4", which also 
happens to be one of the two choices (the other is "5") for the shared 
interrupt. This allows some very peculiar configurations.

3. In addition, there is a STATUS register that reports which port 
currently requires interrupt servicing.  I have not checked this, but I 
am pretty certain that this notification is independent of the 
selection of a shared or individually specified interrupt level.  The 
adapter manual lies rather forcefully about the polarity of the 
indication: a one bit, despite BOCA's protestations, represents an 
actively interrupting UART and the two unused bits are permanently zero.

4. The first four UARTs may be set to the conventional COM1 through 
COM4 ports, although the choice of IRQ10 and IRQ11 is less traditional. 
The next two ports have more unconventional addresses and fixed IRQs.  
I only noticed recently that one can use the shared IRQ for any one 
UART and that by choosing the shared IRQ to be "5" one gets yet one 
more configuration option.  I was baffled by the fact that in a 
previous configuration, I could not successfully use the fourth port, 
but of course it clashed with IRQ 11 which is used, I think, by the PCI 
bus/SCSI controller combination.  I presume I can configure port 4 to 
use the shared IRQ and set the latter to "5" and I will have all 6 
ports available.

Now, all this being said, I could not determine how to write the driver 
so that, between the actual adapter settings and the contents of the 
CONFIG file, it would be possible to use each port, irrespective of how 
it was configured.  The potential pitfalls are:

(a) The device driver has no mechanism to discriminate between standard 
COM ports and those on the adapter it services.  If the driver attempts 
to service COM1 and it is not an adapter port, it will fail to do so 
because the interrupt indicator flag in the STATUS register for that 
port will not be set.  Unless the NetBSD kernel chains interrupt 
handlers so that the correct handler is called on such a failure, the 
standard UART ports will become unusable.  And this presupposes that 
the conventional handler was configured correctly, earlier - 
another possibility is to include the standard ports in the ioAT66 
driver, trigger interrupts at probe time, determine which cause the 
STATUS register to report and which don't and attach two slightly 
different interrupt handlers to the two different groups.

(b) Only with such convoluted probing is it possible to determine the 
actual adapter configuration, and here is the point: I chose to make 
certain assumptions about the configuration of the adapter, so as to 
minimise the likelihood of misconfigurations.  The first assumption is 
that conventional ports are paired with (nearly) conventional IRQs: 
COM1 and COM2 are taken to be standard, COM3 and COM4 nearly so, and 
COM5 and COM6 merely extrapolate on this.  The alternate ports are all 
taken to use the chosen shared IRQ and aren't even considered for 
probing if the IRQ specification in the configuration is left out.  The 
alternative port is tested first, making it possible for other drivers 
to manage the conventional ports if they are excluded on the adapter.

(c) Any number of adapter configuration can trash this scheme, for 
example, to match a current configuration, the third port would have to 
be set up as 0x248/5 instead of 0x2E8/5, the latter would be forced to 
0x2E8/11 and clash.

(d) The only alternative would be to find some means of describing in 
the CONFIG file, the properties of individual slaves, not so much their 
I/O address, where the choices are limited and mutually exclusive, but 
the rather the selected IRQ (god forbid that this should then be wrong 
:-(

(e) Another useful specification might, in this case, be whether we 
want to incorporate the standard ports - we can handle them, as long as 
we don't expect the STATUS register to give us any indication about 
them - or, equally important, whether we should ignore them even if we 
happen to detect them.

In summary, there are two options: a more complex mechanism to describe 
adapters (I guess that's where PnP was meant to help) or the ability to 
perform rather complex tests, including triggering and intercepting 
interrupts, at adapter probing time.  I think the former option 
stretches into dangerous territory, while the latter could provide 
additional robustness to other drivers.  I'm not comfortable with 
exploring this avenue, but with sufficient encouragment and support, I 
may embark on it.

In the meantime, it has been fun to get this far, it would be a pleasure 
to be able to contribute where so far I have only been a spectator.
-- 
Lucio de Re (lucio@proxima.alt.za)
Disclaimer: I'm working at getting my opinions to agree with me.