Re: [PATCH 0/6] x86: PIRQ/ELCR-related fixes and updates

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Maciej,

14.09.2021 12:24, Maciej W. Rozycki:
  Would you be able to share a disassembly of the piece of BIOS code in
question?  I can read x86 assembly, so maybe the interpretation of the
10/28/41/89 cookie can be inferred from it.  The high nibble looks
remarkably like a bit lane selector and swizzling is clearly visible, but

Ok, I've solved the puzzle.
High nibble is a ready-to-use bitmask for chipset reg 0x44 (so indeed, it is 1 << X). Now, in low nibble, bit 0 selects one of two (0x42 or 0x43) chipset registers and further bit 3 selects one of two halves, and bits 1 and 2 are apparently ignored. So actually, 10-28-41-89 is then just a freaky representation of simple 1-2-3-4 numbering. Good news it is exactly the numbering I chose when converting from $IRT to the supported $PIR format, and then it just worked (Some more details about my testing with this converted table where reported in my followup messages a bit earlier, you have probably seen them already).

Here is the relevant code with my remarks:

f9c1d: test al, 0x01 // Here AL bit 0 = Edge/Level CMOS setting.
f9c1f: pushf
f9c20: mov ah, dh // Here DH = PIRQ from $IRT table.
f9c22: shr ah, 4 // PIRQ's high nibble is a mask to set/clr E/L bit in reg 44 (1 << X)
f9c25: mov al, 0x44  // AH is ignored.
f9c27: call read_chipset_reg_AL // Register value returned in AL
f9c2a: or al, ah
f9c2c: popf
f9c2d: jnz .+4 (9c33)
f9c2f: not ah
f9c31: and al, ah
f9c33: mov ah, al
f9c35: mov al, 0x44 // Write AH to chipset register number 0x44.
f9c37: call write_chipset_reg_AL
f9c3a: mov al, 0x42
f9c3c: mov ah, dh
f9c3e: and ah, 0x01
f9c41: add al, ah    // PIRQ's bit 0 is reg 42/43 selector (X >> 1)
f9c43: mov ah, al    // AH is ignored
f9c45: call read_chipset_reg_AL // Register value returned in AL
f9c48: test dh, 0x08 // PIRQ's bit 3 is reg's nibble selector (X & 1)
f9c4b: jz .+3 (9c50) // Here 0 value selects lower nibble.
f9c4d: ror al, 0x04
f9c50: and al, 0xf0
f9c52: or al, dl     // Here DL contains wanted IRQ number to set.
f9c54: test dh, 0x08
f9c57: jz.+3 (9c5c)
f9c59: ror al, 0x04
f9c5c: xchg ah, al
f9c5e: call write_chipset_reg_AL

I fail to guess the algorithm from this pattern.  Given that the PIRQ
routing handler is chipset-specific we could try interpreting just the
high nibble, but would it work for the next system with the same chipset?

This is certainly unclear. However, 10-28-41-89 can be arithmetically verified for consistency against the numbering scheme described above. So a respective test could be added somewhere. Also, prime numbers 1 to 4 could probably be treated as valid numbering, too. Everything else should probably be refused unless some other numbering scheme pops up.

  Also who is the BIOS vendor?  Maybe they would be able to tell us
something about the "$IRT" BIOS service.

It is some regular AMIBIOS (American Megatrends) from 486 era, for EXP8449 motherboard, here is a manual I found for it:

https://www.elhvb.com/mobokive/Archive/Oldman.ixbt.com/mb/Expertboard_8449/exp84491.pdf

  Datasheets are not always right, but this one is the best source we have
for this chipset.

Well, my testing has shown that practically, with your patch all works fine, including IRQ sharing. So other than this unclear numbering problem, I think it can be considered correct and usefull.


Thank you,

Regards,
Nikolai


   Maciej





[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux