On 5 Feb 2022 at 0:48, G.W. Haywood via Freedos-user wrote:
> As I
> said in my OP I had to modify some of the cards because they couldn't
> share interrupts properly, by cutting traces and inserting switching
> diodes to do the 'wired or' kind of thing.
> 
Yes. I recall ISA multiport boards by Advantech that had and extra 
"register", implemented by a CPLD, that worked like a 3rd-level PIC.
Not merely a status register with a bitwise flag per UART channel.
Whenever you got an IRQ from such a card, you'd have to ACK to your 
AT-PIC and *then* an extra ACK to that card's own "sharing register". 
It was a way to implement sharing of edge-triggered IRQ's properly. 
And it wasn't very well documented if I recall. Advantech would 
provide its own library which did work, as long as you could link 
that to your software. If you couldn't recompile, bad luck for you. 
The library was pretty small, I recall trying to reverse it with a 
disassembler...
The vendors of such hardware probably protected their "intellectual 
property" that way.
And indeed I had an inkling to implement "simple OR logic" - which is 
not the correct way to share edge-triggered interrupts, but if you 
have have a way of polling the ports every now and then outside of 
the dedicated ISR, you can avoid losing keystrokes from your 
terminal.

> Yes, I get PCI card addresses/interrupts from 'lspci' on a Linux box.
>
If you try booting with "noapic" and maybe "acpi=off", you should see 
your PCI IRQ's assigned to numbers below 16. I've even seen setups 
with a broken BIOS (DSDT) and PCI-e, where turning on "noapic" would 
result in a combination of "legacy ISA and legacy PCI" IRQ's below 
16, combined with MSI used for PCI-e peripherals that supported that 
:-)

Which obviously does not help you to re-route a particular APIC GSI 
to IRQ3/4, if that's your whole point...

I've done a bit of googling and found some relevant details.

To re-route some particular IRQ line (APIC input) e.g. to IRQ3 or 
rather its ISR vector, I can see two different theoretical 
possibilities:

A) reprogram the relevant IO-APIC 

B) make a TSR that installs an ISR for the "boot IRQ" line (= under 
16) that your PCI board gets from the BIOS, and from that ISR, call 
the original ISR of IRQ3 (or whatever it is that you're trying to 
mimick).

In detail:

A) reprogram the relevant IO-APIC 

Unless you're using server boards, we're realistically we're speaking 
the chipset-integrated IO-APIC. This particular APIC is an on-chip 
part of the south bridge, since about i815. The IO-APIC is a neighbor 
of the AT-PIC (two pieces of the i8259 cascaded) and they have some 
umbilical interconnection - although in fact, I guess any extra 
IO-APIC's integrated in PCI bridges ultimately produce the same 
overall behavior...

First, mind the difference between:

- an IO-APIC = the one that receives the IRQ "wires" from PCI devices 
and passes the IRQ events further, based on how it is programmed.
This is what we'll need to mess with.

- a CPU local APIC = one per core, the receiving end of various sorts 
of interrupts, the one actually arranging the jump to an ISR vector 
on that particular CPU core. Not sure if we need to touch this or 
not.

A modern PC system has both kinds of APIC's, even if there's just a 
single CPU core. The APIC system architecture supports multiple 
cores, and you'll find references to that in all the docs, including 
some elements in the APIC configuration registers. In DOS, all your 
software likely runs on the BSP = "BootStrap Processor", i.e. the 
"default CPU core" that ends up running your DOS when BIOS hands over 
control after POST.

I've found a pretty neat and compact description of what an IO-APIC 
is, at osdev.org - including a register map:
    https://wiki.osdev.org/IOAPIC
At the end of that wiki article, there is a link to an Intel MPS spec 
in PDF (already from web-archive) - it contains a block diagram of a 
multi-CPU multi-APIC system, in its original form, with the APIC 
IRQ's being delivered over a dedicated "APIC bus".
Since then, there's been a change, nowadays the APIC IRQ's are 
delivered inband over the system bus (DMI, which is just an 
obfuscated PCI-e) which doesn't have to worry you, as that particular 
detail is transparent to you as a programmer.

Looking at the IO APIC register map, it's clear that if you know or 
can find out the right GSI (row in the table), you can tell the APIC 
what *vector* to call at which CPU, as identified by an APIC ID 
(which is apparently just an ordinal number - the BSP probably has an 
APIC ID = 0).
But, this is not all.

Apparently, the "just after POST" state of IRQ routing, where only 
IRQ's under 16 are used (and heavily shared) is not implemented by 
means of a corresponding configuration of the APIC mapping of the 
GSI's to ISR vectors in CPU cores.
Rather, that "legacy mode" is a whole separate arrangement, where the 
IRQ's are in a so called "boot IRQ mode". Apparently, in this mode, 
the particular GSI (IO-APIC input pin) has the "mask bit set" - which 
does not mean, that the GSI is completely disabled, it is just not 
mapped to a vector by its respective APIC entry. Instead, that GSI 
gets forwarded to the nearby i8259. The IRQ braid of a single PCI bus 
segment typically gets wire-OR'ed with some higher "legacy ISA" i8259 
IRQ's, such as 10,11,14 and 15. This "legacy boot IRQ" arrangement 
does not allow you to re-route the "boot IRQ" to a different IRQ slot 
(ISR vector). It merely mimicks the "pre-APIC" style of routing and 
sharing of PCI interrupts in prior PC chipsets.

The legacy "boot IRQ" scheme in an APIC is described in this lkml 
thread:
https://groups.google.com/g/linux.kernel/c/0CZSA3ZtToE?pli=1
and I just hope I understand it correctly.
The debate really only gets interesting at the end, after maybe 80% 
of the thread. There are some of the most famous Linux kernel 
maintainers debating the weird feature of the IO APIC that a "masked" 
interrupt input really means "fallen back to the boot IRQ mode".

It would seem easy enough just to specify the desired IRQ vector in 
the IO-APIC configuration, but I fear that it may need a 
corresponding preparation in the LAPIC of the BSP CPU core.
The LAPIC can be disabled/enabled in the respective MSR (see the 
Intel PDF mentioned below). Not sure if it's enabled by the BIOS, and 
thus, if you merely reprogram the IO-APIC to use direct delivery of a 
particular GSI to the desired IRQ 3 vector, if a corresponding config 
in the LAPIC is needed: enable LAPIC, maybe set up some IDT's 
(protected mode stuff), not sure if you can then exit such a program 
(or stay resident) and leave the mapping that way... Seems to me that 
DPMI / protected mode have some specific workarounds (a translation 
layer) for legacy DOS interrupt services...

If you'd appreciate further reading about the local APIC, get a PDF 
called
"Intel 64 and IA-32 Architectures Software DeveloperĀ“s Manual"
https://www.intel.com/content/www/us/en/developer/articles/technical/i
ntel-sdm.html
- get the combined volume set and search for occurrences of "APIC 
base" or APIC_BASE. Just skim the context where this is mentioned.

Apparently, while the local APICs' base addresses can be found from 
the IA32_APIC_BASE MSR (using a rdmsr instruction), the IO-APIC base 
can only be obtained from ACPI tables (again you possibly don't want 
this) or from the older MP-tables = MPS = "MultiProcessor System" 
BIOS API. And, the IO-APIC/LAPIC registers are memory-mapped, which 
means that you'll probably need DPMI even to take a look into the 
APIC.

The old MPS BIOS API is possibly less arcane than ACPI, but MPS is 
pretty old too - I'm wondering if it's even available in modern 
ACPI/UEFI machines.
Even ACPI has passed through several generations. There are some 
open-source tools for wading through your ACPI tables and maybe even 
fixing bugs in them:
  https://acpica.org/downloads
See also perhaps:
  https://unix.stackexchange.com/a/529295/246780
To me, the complexity of ACPI is sheer and humiliating.
Probably much too complex to try and save old DOS software.
At the very least, rather than try tackling ACPI on my own,
I'd try to take inspiration from the examples given by Michael 
Chourdakis in his work on multi-CPU tricks in DOS.
  

B) software-based rerouting of IRQ's:

You need to hook the respective vector for the actual IRQ that your 
PCI board is using, i.e. "register" your ISR in the old fashioned way 
for that IRQ, and in your ISR, just call the existing IRQ3's ISR. If 
memory serves, iret works pretty much the same as a plain 'ret'.
You'd probably get IRQ3 acked to the AT-PIC "even though IRQ3 has not 
physically fired", which should not be a problem (the i8259 is too 
stupid to be distressed by this) and your own "redirecting ISR" would 
have to ACK its respective actual IRQ to the i8259.
Might as well work, you'd just send two ACKs per ISR invocation for 
the redirected IRQ.
I've never done this and cannot offer any detailed instructions...

Actually, I just seem to have spotted a pitfall: for the SW-based 
rerouting to have a chance of working, your legacy ISR for e.g. COM3 
must already be in place (registered), when you want to forward some 
other IRQ's by a custom ISR. If you just implement this as a TSR that 
gets to know the IRQ3 ISR address on startup, you're in trouble, 
because you need to load that TSR first, before starting your main 
program, i.e. before the IRQ3 ISR gets registered with the AT-PIC. 
Makes me wonder if the TSR could wait for a moment in the background, 
before trying to "chainload" the IRQ3 ISR.


To sum up, I cannot see any easy prospects for "transparent IRQ 
redirection". If you have the source code of your production app, 
your safest bet is probably just to hook the right IRQ, available to 
you transparently by means of the "boot IRQ" mode if your system is 
new enough to have an APIC.


BTW, PCISCAN utils have been mentioned... I believe a PCISCAN.EXE for 
DOS by Bart Lagerweij might be available here:
https://web.archive.org/web/20071030190746if_/http://download.nu2.nu/n
u2files/utils.cab
Its output is not nearly as detailed as Linux lspci, and I don't 
recall anymore 
if pciscan.exe shows at least the IRQ.


BTW2, Pascal is not my pot of tea either.
I'm a hobbyist fan of C/C++ with snippets of asm.
We had Borland Pascal at school in the nineties, and this PCI-1716 
driver that I've included is just an odd experiment that never got 
used in production. It talks to the PCI BIOS in ASM, which is why I 
provided a copy.

Yes I've also done some primitive text-mode utilities for Linux, in 
Curses... and although Unicode has nice "line-drawing characters", I 
just used these three:   + - | 
:-)

Frank



_______________________________________________
Freedos-user mailing list
Freedos-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freedos-user

Reply via email to