Re: I/O bus reset to fix CMD MSCP controllers (and probably others)
Hans Rosenfeld <[email protected]>
| Newsgroups | gmane.os.netbsd.ports.vax |
|---|---|
| Message-ID | <[email protected]> |
Hi, I was able to root-cause the issue. It was introduced in r1.11 of uba_mainbus.c when scanning for Qbus/Unibus memories was added. When NetBSD is booted from a MSCP controller, the boot loader sets up the Qbus map to provide the controller with a small command/response ring in memory to be used for I/O. Once the kernel is loaded and uba(4) is attaching, the Qbus map is cleared while scanning for memories. It appears that sudden loss of access to the command/response ring causes the firmware of these CMD controllers to drop dead. As a result, these controllers don't react in a reasonable time (100ms by the spec) when their IP register is written to re-initialze the controller. Even though uda(4)'s udamatch() waits up to 10s for a sign of life from the controller, that's usually not enough for it to wake up and it is assumed to be absent. Which, of course, causes the kernel to fail booting as the boot device can't be found. This needs to be addressed both in the kernel and the bootloader. We can work around this issue in the kernel by restoring the Qbus map registers to their original values after we've used them for detecting Qbus memories. The code to do that is already there but commented out, it just needs uncommenting. To fix this properly, the standalone ra.c driver in the boot loader should provide a close() entry point which clears the IP register to issue a controller reset. Thus when the kernel is loaded, the firmware of the MSCP controller is again in reset state and can't get confused anymore by the initialization of the Qbus map in uba(4). In case anyone wants to review them, I've attached two patches, one with a kernel workaround and another with a proper fix for the boot loader. I intend to commit them some time next week and request pullups into -10. Hans -- %SYSTEM-F-ANARCHISM, The operating system has been overthrown
0001-vax-uba-fix-detection-of-CMD-CQD-22x-MSCP-controller.patch
(text/plain, 3.3 KB)
From 1410af92e0515d6419d2b8495d5ad2827cadfa15 Mon Sep 17 00:00:00 2001 From: Hans Rosenfeld <[email protected]> Date: Fri, 16 May 2025 11:25:29 +0200 Subject: [PATCH 1/2] vax/uba: fix detection of CMD CQD-22x MSCP controllers Certain models of CMD MSCP controllers fail to be detected by uda(4) if they have been booted from. This failure mode has been introduced in revision 1.11 of uba_mainbus.c, when scanning for Qbus/Unibus memories was added. They are deteced fine when NetBSD is booted from any other device such as over the network. When NetBSD is booted from a MSCP controller, the boot loader sets up the Qbus map to provide the controller with a small command/response ring in memory to be used for I/O. Once the kernel is loaded and uba(4) is attaching, the Qbus map is cleared while scanning for memories. It appears that sudden loss of access to the command/response ring causes the firmware of these CMD controllers to drop dead. As a result, these controllers don't react in a reasonable time (100ms by the spec) when their IP register is written to re-initialze the controller. Even though uda(4)'s udamatch() waits up to 10s for a sign of life from the controller, that's usually not enough for it to wake up and it is assumed to be absent. Which, of course, causes the kernel to fail booting as the boot device can't be found. This needs to be addressed both in the kernel and the bootloader. We can work around this issue in the kernel by restoring the Qbus map registers to their original values after we've used them for detecting Qbus memories. The code to do that is already there but commented out, it just needs uncommenting. --- sys/arch/vax/uba/uba_mainbus.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sys/arch/vax/uba/uba_mainbus.c b/sys/arch/vax/uba/uba_mainbus.c index 391057aab1d6..ec15b070e502 100644 --- a/sys/arch/vax/uba/uba_mainbus.c +++ b/sys/arch/vax/uba/uba_mainbus.c @@ -119,7 +119,7 @@ qba_attach(device_t parent, device_t self, void *aux) vaddr_t vaddr; int *mapp; int pgnum; - //int val; + int val; int start; aprint_normal(": Q22\n"); @@ -142,30 +142,30 @@ qba_attach(device_t parent, device_t self, void *aux) uba_dma_init(sc); mapp = (int *)vax_map_physmem(QBAMAP, QBASIZE/VAX_NBPG); - //val = 0; - + val = 0; + for (paddr = QBAMEM, pgnum = 0, start = -1; paddr < QBAMEM + QBASIZE - 8192; paddr += VAX_NBPG, pgnum += 1) { - //val = mapp[pgnum]; + val = mapp[pgnum]; mapp[pgnum] = 0; vaddr = vax_map_physmem(paddr, 1); if (badaddr((void *)vaddr, 2) == 0) { if (start < 0) start = pgnum; } else if (start >= 0) { - aprint_normal("sgmap exclusion at %#x - %#x\n", + aprint_normal("sgmap exclusion at %#x - %#x\n", start*VAX_NBPG, pgnum*VAX_NBPG - 1); vax_sgmap_reserve(start*VAX_NBPG, (pgnum - start)*VAX_NBPG, &sc->uv_sgmap); start = -1; } vax_unmap_physmem(vaddr, 1); - //mapp[pgnum] = val; + mapp[pgnum] = val; } vax_unmap_physmem((vaddr_t)mapp, QBASIZE/VAX_NBPG); if (start >= 0) { - aprint_normal("sgmap exclusion at %#x - %#x\n", + aprint_normal("sgmap exclusion at %#x - %#x\n", start*VAX_NBPG, pgnum*VAX_NBPG - 1); vax_sgmap_reserve(start*VAX_NBPG, (pgnum - start)*VAX_NBPG, &sc->uv_sgmap); -- 2.48.1
0002-vax-boot-fix-detection-of-CMD-CQD-22x-MSCP-controlle.patch
(text/plain, 3.6 KB)
From 73498e559c65049dc57bb4c27e321f8fb8545aa6 Mon Sep 17 00:00:00 2001 From: Hans Rosenfeld <[email protected]> Date: Thu, 22 May 2025 10:14:00 +0200 Subject: [PATCH 2/2] vax/boot: fix detection of CMD CQD-22x MSCP controllers Certain models of CMD MSCP controllers fail to be detected by uda(4) if they have been booted from. This failure mode has been introduced in revision 1.11 of uba_mainbus.c, when scanning for Qbus/Unibus memories was added. They are deteced fine when NetBSD is booted from any other device such as over the network. When NetBSD is booted from a MSCP controller, the boot loader sets up the Qbus map to provide the controller with a small command/response ring in memory to be used for I/O. Once the kernel is loaded and uba(4) is attaching, the Qbus map is cleared while scanning for memories. It appears that sudden loss of access to the command/response ring causes the firmware of these CMD controllers to drop dead. As a result, these controllers don't react in a reasonable time (100ms by the spec) when their IP register is written to re-initialze the controller. Even though uda(4)'s udamatch() waits up to 10s for a sign of life from the controller, that's usually not enough for it to wake up and it is assumed to be absent. Which, of course, causes the kernel to fail booting as the boot device can't be found. This needs to be addressed both in the kernel and the bootloader. To fix this properly, the standalone ra.c driver in the boot loader should provide a close() entry point which clears the IP register to issue a controller reset. Thus when the kernel is loaded, the firmware of the MSCP controller is again in reset state and can't get confused anymore by the initialization of the Qbus map in uba(4). --- sys/arch/vax/boot/boot/conf.c | 2 +- sys/arch/vax/boot/boot/ra.c | 9 +++++++++ sys/arch/vax/boot/boot/vaxstand.h | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sys/arch/vax/boot/boot/conf.c b/sys/arch/vax/boot/boot/conf.c index dd750f9f9ad4..5f407e438b1d 100644 --- a/sys/arch/vax/boot/boot/conf.c +++ b/sys/arch/vax/boot/boot/conf.c @@ -48,7 +48,7 @@ struct devsw devsw[]={ SADEV("hp",hpstrategy, hpopen, nullsys, noioctl), SADEV("qe",nostrategy, qeopen, qeclose, noioctl), /* DEQNA */ SADEV("ctu",ctustrategy, ctuopen, nullsys, noioctl), - SADEV("ra",rastrategy, raopen, nullsys, noioctl), + SADEV("ra",rastrategy, raopen, raclose, noioctl), SADEV("mt",rastrategy, raopen, nullsys, noioctl), SADEV("rom",romstrategy, romopen, nullsys, noioctl), SADEV("rd",mfmstrategy, mfmopen, nullsys, noioctl), diff --git a/sys/arch/vax/boot/boot/ra.c b/sys/arch/vax/boot/boot/ra.c index b1c2ac33b387..ad4cba212a74 100644 --- a/sys/arch/vax/boot/boot/ra.c +++ b/sys/arch/vax/boot/boot/ra.c @@ -307,3 +307,12 @@ rastrategy(void *f, int func, daddr_t dblk, *rsize = size; return 0; } + +int +raclose(struct open_file *f) +{ + /* Reset controller by starting a soft initialization */ + *ra_ip = 0; + + return 0; +} diff --git a/sys/arch/vax/boot/boot/vaxstand.h b/sys/arch/vax/boot/boot/vaxstand.h index 5c1f69ac8d8f..21fe8e0654bb 100644 --- a/sys/arch/vax/boot/boot/vaxstand.h +++ b/sys/arch/vax/boot/boot/vaxstand.h @@ -50,7 +50,8 @@ int ubmap(int mapno, int vaddr, int size); /* device calls */ int raopen(struct open_file *, int, int, int, int), - rastrategy(void *, int, daddr_t, size_t, void *, size_t *); + rastrategy(void *, int, daddr_t, size_t, void *, size_t *), + raclose(struct open_file *); int hpopen(struct open_file *, int, int, int, int), hpstrategy(void *, int, daddr_t, size_t, void *, size_t *); int ctuopen(struct open_file *, int, int, int, int), -- 2.48.1