skiselev / 8088_bios

BIOS for Intel 8088 based computers
GNU General Public License v3.0
513 stars 61 forks source link

Further tweaks from Homebrew8088 support testing #55

Closed hak-foo closed 9 months ago

hak-foo commented 9 months ago
  1. The Homebrew8088 build target now uses the built-in AT keyboard support, which seems to work and also supports the lock LEDs. The old logic, I think, basically convinced the AT-style controller to behave XT-like enough that other XT BIOSes could handle it.
  2. I set up the logic to talk to the RTC to use "out DX, AL" and made the port configurable. This supports cards like https://www.tindie.com/products/spark2k06/rtc-isa-8-bits-very-low-profile-2/ which could be set to a port other than 0x70.
  3. The definition for hard coded floppy drives is now in config.inc, so it's easier to customize.
  4. Code to differentiate between the NEC V20 and V40 for the power-up message. (This is based on experimentation rather than a spec; the V40 seems to allow you to write and read back ports in the 0xFFE0-FFF0 range, while the V20 doesn't.)
  5. An attempt to estimate CPU clock speed, just because modern BIOSes usually show it. I would not at all be insulted if this was discarded or optional, since it's a both imprecise and sort of a space hog, but it is fun. The io_wait_latch code was made available outside specific defines, since it's used here to get data from the timer.
skiselev commented 9 months ago

Thank you!

skiselev commented 9 months ago

I did a bit of rework to this code, see: https://github.com/skiselev/8088_bios/commit/99e874d2816cfb0c3ea54ddc142a90cfaa1d1762 A few questions and comments:

hak-foo commented 9 months ago

Let me try to clarify the comments on the V20. When I tested, I saw some of the ports FFF0 and above were letting you write and read back, but not all, so I described it as "scattered". I guess I was interpreting the FDC responding as the CPU. :/

The V40 datasheets define a specific meaning for ports FFF0 and above, even though it appears to accept writes down to FFE0, so I figured these are less likely to be a problem than trying to write to a register that has an intended use.

On the NMI mask, looking at the schematic (https://github.com/homebrew8088/8088-PC-Compatible/blob/main/Schematics/4%20Slot%20Main%20Board.pdf), it seems like it was designed to use bit 5 of port 0x61 (which seems to be I/O check enable on a normal PC) as NMI Enable. Since there's no parity or 8087 support, and it seems like the only thing that actually routes to the NMI circuit is "I/O Check" on the ISA bus, this may be a "cheat" there.

Regarding the RTC, the HB8088 does not have a "official" RTC. I used spark2k06's board, which was apparently intended for the Micro8088, but which was available configured with different port numbers when I ordered it. So I figured it was possible that other people would also have that same RTC, but not at port 0x70. I ordered mine as 2A0, probably because a lot of the XT-era cards used ports above 100 and it "seemed" vacant when I ordered.

skiselev commented 9 months ago

Thanks for clarifications!

I am still wondering if there are other ways to detect V40 without poking the I/O ports. There is an old thread here, but I don't see anything but a request to identify V40 CPU: https://forum.vcfed.org/index.php?threads/cpu-fpu-detection-program-routines.27198/

Another thing is here, again, it says that "V40 and V50 detection method is known but not implemented." https://github.com/MobyGamer/TOPBENCH/blob/master/CPU215/DOC/TMI0SDGL.DOC

wrljet commented 9 months ago

I am still wondering if there are other ways to detect V40 without poking the I/O ports.

Back decades ago when I worked at Qualitas on 386MAX, we had endless trouble identifying stuff like this, and in particular there were motherboards that controlled the A20 Gate in their own ways. We poked a lot of ports.

One time this resulted in bricking some customer motherboards that had Flash BIOSes, and hadn't fully decoded their I/O ports.

skiselev commented 9 months ago

@hak-foo I have a suggestion regarding V40 detection: As I said earlier, since most ISA cards only decode 10 lower bits of the address, so the 0xFFF0-0xFFFF I/O port range would be mapped to the FDC addresses at 0x3F0-0x3F7 and COM1 UART addresses at 0x3F8-0x3FF. With that being said, FDCs normally don't implement port 0x3F6. So perhaps 0xFFF6 port can be used for V40 detection instead of 0xFFE0 . It looks that 0xFFF6 maps to WCY2 register in V40. I think only lower 4 bits of that port are used, so I am not sure if V40 would store all the bits. To be on the safe side, I'd just modify these 4 bits. Something like:

mov dx,0FFF6h
in al,dx
mov ah,al ; store the original value in AH
xor al,0Fh ; invert lower 4 bits
out dx,al
in al,dx
xor al,0Fh ; invert again (should get the original value)
cmp al,ah
jne .not_v40
out dx,al ; write the original value
in dx,al
cmp al,ah ; compare again
jne .not_v40
jmp .v40
.not_v40:
hak-foo commented 9 months ago

I finally got a chance to test the proposed change. It seems to work on my machine with both the V20 and V40 CPU cards. There is a typo in the sample code (IN AL, DX instead of DX, AL) but otherwise it makes sense.

The code I was working with didn't have a .v40 label for that code path, so I just built a similar block like .not_v40 to fall through to.

pop dx
mov si, msg_cpu_nec_v40
call print
jmp .cpu_freq

On a conceptual level, I think the pokes to FFF6 look benign. On a V20, we can assume that FFF6 -> 3F6 falls into the gap of the FDC and doesn't do anything important. On a V40, we initialize to FFF6 to 01 (zero-wait DMA and 1WS refresh, but refresh is disabled), and the toggled version would be 0E (3WS DMA, 2WS refresh), which seems like it would be even safer timing if the test didn't clean up after itself for some reason.