• PCI IRQ

    From J. Curtis@21:1/5 to All on Thu Nov 23 06:17:20 2023
    I have some PCI spec 2.1 motherboards (mid 1990s). I wanted multiple
    serial cards sharing a single IRQ.

    With 5 or more PCI slots, at least two are hard wired to share an INT
    pin. Easy solution for two cards sharing one IRQ. Just find which slots
    share the pin, and there you go.

    Beyond that, you can move cards around and tweak BIOS setup options.
    Maybe you get lucky, maybe not.

    Reprogramming the PCI IRQs is a lot of trouble, according to some web
    sites. But if you have a PCI 2.1 BIOS, the PCI 2.1 spec document, and
    the PCI 2.1 BIOS spec document, it's easy: use the INT 1A interface.

    I wrote some code. It's for Borland C++ 3.1, but it's small enough to
    easily port.

    Run "pd >pi.txt"

    Edit the output file and change IRQs (last column) as desired.

    Run "pi" to update the IRQs.

    Beware of hardwired slot sharing. Both must be updated with the same
    values. Experiment and see.




    ---- build.bat

    bcc -Tt pd.c
    bcc pi.c
    del *.obj


    ---- pd.c

    # pragma inline

    # include <stdio.h>
    # include <stdlib.h>
    # include <dos.h>

    int
    detect (void)
    {
    unsigned long tag;
    int spec, max;

    asm {
    .386;

    xor edx, edx;
    mov ax, 0xb101;
    int 0x1a;
    jc nope;
    or ah, ah;
    jnz nope;
    mov tag, edx;
    mov spec, bx;
    mov ch, 0;
    mov max, cx;

    .8086;
    }

    if (tag != 0x20494350)
    goto nope;

    if (spec < 0x210)
    goto nope;

    return max;

    nope:
    return -1;
    }

    unsigned int
    read_word (int bdf, int reg)
    {
    _BX = bdf;
    _DI = reg & 0xfe;
    _AX = 0xb109;
    geninterrupt (0x1a);
    return _CX;
    }

    void
    list (int max)
    {
    unsigned int irq, pin;
    int vid, did, type;
    register int bdf, bus, dev, fun;

    for (bus = 0; bus <= max; bus++) {
    for (dev = 0; dev < 32; dev++) {
    for (fun = 0; fun < 8; fun++) {
    bdf = bus << 8 | dev << 3 | fun;

    if ((vid = read_word (bdf, 0)) == -1) {
    if (fun > 0)
    continue;
    break;
    }

    type = read_word (bdf, 0xe);
    if (type & 1) /* omit bridge */
    continue;

    irq = read_word (bdf, 0x3c);
    pin = (irq & 0xff00) >> 8;
    if (!pin)
    continue;

    irq &= 0x00ff;
    did = read_word (bdf, 2);

    printf ("%04x %04x ", vid, did);
    printf ("%2x:%02x:%1x ", bus, dev, fun);
    printf ("%1d %2d\n", pin, irq);

    if (fun == 0 && !(type & 1 << 7))
    break;
    }
    }
    }
    }

    void
    main (void)
    {
    int max;

    if ((max = detect ()) == -1) {
    printf ("no PCI BIOS 2.1\n");
    exit (1);
    }

    list (max);

    exit (0);
    }


    ---- pi.c

    # include <stdio.h>
    # include <stdlib.h>
    # include <dos.h>

    void
    write_irq (int bdf, int pin, int irq)
    {
    asm push ds;
    _BX = bdf;
    _CH = irq;
    _CL = pin + 9;
    _DS = _AX = 0xf000;
    _AX = 0xb10f;
    geninterrupt (0x1a);
    asm pop ds;

    _BX = bdf;
    _CL = irq;
    _DI = 0x3c;
    _AX = 0xb10b;
    geninterrupt (0x1a);
    }

    void
    main (void)
    {
    static FILE *file;
    static int b, d, f, p, i;

    file = fopen ("pi.txt", "rt");

    while (fscanf (file, "%*x %*x %x:%x:%x %d %d", &b, &d, &f, &p, &i) == 5) {
    printf ("%2x:%02x:%1x %1d %2d\n", b, d, f, p, i);
    write_irq (b << 8 | d << 3 | f, p, i);
    }

    exit (0);
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)