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