From 8085f5ea2509dda5986116c05c19e4981833ea1e Mon Sep 17 00:00:00 2001 From: Davis Johnson Date: Wed, 21 Jul 2021 18:44:35 -0700 Subject: [PATCH] ID32: Fix DP unit busy test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The problem turned out to be a call to sim_is_active() from id_dp.c with an invalid pointer. This surprised me some since this isn’t a module that changed significantly. In normal disk operation the driver accesses the disk address (sometimes called file address in the hardware docs) before accessing the controller address. The simh disk emulator (dp.c) sets a current disk variable, dp_svun, to the current disk address when a disk is accessed. It gets set to 0 initially and under some other circumstances. The address of passed to sim_is_active() is calculated, in part, by subtracting the controller address from the disk address. This results in a bigish negative offset from the beginning of an array if dp_svun is 0. The diagnostic sends a disarm-disable (x’c0’) command to every device address, from 0 to x’3ff’. This hits the controller before the disk, exercising the error. This same thing happened in v38-1, but sim_is_active() did not dereference the pointer passed to it, but scanned an array for that pointer value. The current version does dereference the pointer. My crude fix, which does not make me happy, is to replace the call sim_is_active(uptr) with (dp_svun && sim_is_active(uptr)). This does give behavior identical to v38-1 and allows me to proceed. --- Interdata/id_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Interdata/id_dp.c b/Interdata/id_dp.c index b36c9e3f..52cda9b2 100644 --- a/Interdata/id_dp.c +++ b/Interdata/id_dp.c @@ -297,7 +297,7 @@ switch (op) { /* case IO op */ } u = (dp_svun - dp_dib.dno - o_DP0) / o_DP0; /* get unit */ uptr = dp_dev.units + u; /* ignore if busy */ - if (!(dp_sta & STC_IDL) || sim_is_active (uptr)) + if (!(dp_sta & STC_IDL) || (dp_svun && sim_is_active (uptr))) break; dp_cmd = f; /* save cmd */ if (dp_cmd == CMC_WR) /* write: bsy=0 else */