From 661be5d1ebe99fa3f8bd2c9a22278ab2b0db2826 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Thu, 8 Aug 2024 10:10:06 -1000 Subject: [PATCH] Qbus MicroVAXen: Fix Qbus Address reference passed in by some OS boot code Problem reported in https://github.com/open-simh/simh/issues/409 There are key differences between the MicroVAX I and MicroVAX II. Specifically, the MicroVAX I is a machine with direct Qbus memory and no QBA (Qbus Adapter) which is part of all later MicroVAXen and corresponds to the UBA (Unibus Adapter) on systems with Unibuxes. Among possibly other things, these Adapters primarily provide the translation between the CPU's system memory and addresses on the respective bus (Qbus or Unibus). These Adapters provide a set of mapping registers which map the respective bus addresses to desired locations in CPU memory which allows for "Scatter/Gather" memory transfers. The MicroVAX I, having its memory directly on the Qbus, has no CPU specific way to implement "Scatter/Gather" for I/O device for memory transfers very much needed in systems with virtual memory. On this system, the Scatter/Gather functionality is provided directly within the MSCP controller which is simulated by the pdp11_rq.c module. On Qbus MicroVAXen with Qbus Adapters, the boot rom initializes all the Qbus mapping registers such that Qbus addresses map directly to CPU RAM addresses. This simplifies boot code which don't turn on Virtual Memory (and thus the need for Scatter/Gather) until later stages of the operating system boot. The Ultrix boot we're dealing with plays games with the mapping registers somewhat early in the boot, and requests a transfer of 0x2000 bytes (words maybe) to an address of 0x010000c8. Note that this would be the address from the point of view of the controller on the Qbus. This value is actually beyond the end of the 22bit Qbus address space (0x003fffff). The controller therefore previously returned a non-existent memory error. It would seem that instructions performing this I/O request are ones which were loaded by an earlier read and thus the bug really should be there, but since this code actually worked on real hardware, accomodating that behavior belongs in the simulator. Meanwhile, when this transfer has happened, the QBA Mapping registers have been changed from their initial values that mapped 1-1 Qbus addresses to RAM. The proper approach is therefore merely to ignore any bits in the transfer address beyond the 22bits of the Qbus address space. Interesting that all other operating systems (or boot code) never presented a buffer address beyond the maximum 22bit Qbus address. --- PDP11/pdp11_rq.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/PDP11/pdp11_rq.c b/PDP11/pdp11_rq.c index 7aaedae0..cf1a59b4 100644 --- a/PDP11/pdp11_rq.c +++ b/PDP11/pdp11_rq.c @@ -153,6 +153,7 @@ extern int32 MMR2; #define RQ_NUMBY 512 /* bytes per block */ #define RQ_MAXFR (1 << 16) /* max xfer */ #define RQ_MAPXFER (1u << 31) /* mapped xfer */ +#define RQ_MAXQBADDR 0x3FFFFF /* Max Qbus Address */ #define RQ_M_PFN 0x1FFFFF /* map entry PFN */ #define UNIT_V_ONL (DKUF_V_UF + 0) /* online */ @@ -2214,7 +2215,7 @@ if (ba & RQ_MAPXFER) { /* mapped xfer? */ return 0; } #endif -return Map_ReadB (ba, bc, buf); /* unmapped xfer */ +return Map_ReadB (ba & RQ_MAXQBADDR, bc, buf); /* unmapped xfer */ } /* Read word buffer from memory */ @@ -2240,7 +2241,7 @@ if (ba & RQ_MAPXFER) { /* mapped xfer? */ return 0; } #endif -return Map_ReadW (ba, bc, buf); /* unmapped xfer */ +return Map_ReadW (ba & RQ_MAXQBADDR, bc, buf); /* unmapped xfer */ } /* Write word buffer to memory */ @@ -2266,7 +2267,7 @@ if (ba & RQ_MAPXFER) { /* mapped xfer? */ return 0; } #endif -return Map_WriteW (ba, bc, buf); /* unmapped xfer */ +return Map_WriteW (ba & RQ_MAXQBADDR, bc, buf); /* unmapped xfer */ } /* Unit service for data transfer commands */