Module Name: src Committed By: tsutsui Date: Wed Nov 23 18:53:22 UTC 2022
Modified Files: src/sys/arch/hp300/dev: rd.c Log Message: Fix "rd(4) at punits not configured on HPDisk are misprobed" problem. - check not only stat value returned by C_QSTAT command against each punit but also desc.d_name returned by C_DESC command because it looks HPDisk responds to commands against punits supported but not-configured punits at 1-3 - prepare rdreset_unit() function to manage reset punit ops during probe without valid softc The stragety is taken from OpenBSD with several modification. Tested on 425t with real 9122D and HPDisk emulating two 7937H drives. Should be pulled up to netbsd-9. To generate a diff of this commit: cvs rdiff -u -r1.111 -r1.112 src/sys/arch/hp300/dev/rd.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/hp300/dev/rd.c diff -u src/sys/arch/hp300/dev/rd.c:1.111 src/sys/arch/hp300/dev/rd.c:1.112 --- src/sys/arch/hp300/dev/rd.c:1.111 Mon Nov 21 16:22:37 2022 +++ src/sys/arch/hp300/dev/rd.c Wed Nov 23 18:53:22 2022 @@ -1,4 +1,4 @@ -/* $NetBSD: rd.c,v 1.111 2022/11/21 16:22:37 tsutsui Exp $ */ +/* $NetBSD: rd.c,v 1.112 2022/11/23 18:53:22 tsutsui Exp $ */ /*- * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rd.c,v 1.111 2022/11/21 16:22:37 tsutsui Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rd.c,v 1.112 2022/11/23 18:53:22 tsutsui Exp $"); #include "opt_useleds.h" @@ -427,6 +427,7 @@ static const int numrdname2id = __arrayc static int rdident(device_t, struct rd_softc *, struct hpibbus_attach_args *); static void rdreset(struct rd_softc *); +static void rdreset_unit(int, int, int); static void rdustart(struct rd_softc *); static int rdgetinfo(dev_t); static void rdrestart(void *); @@ -490,36 +491,8 @@ static int rdmatch(device_t parent, cfdata_t cf, void *aux) { struct hpibbus_attach_args *ha = aux; - struct rd_clearcmd ccmd; - int ctlr, slave, punit; - int rv; - uint8_t stat; - - rv = rdident(parent, NULL, ha); - - if (rv == 0) - return 0; - - /* - * The supported device ID is probed. - * Check if the specified physical unit is actually supported - * by brandnew HP-IB emulator devices like HPDisk and HPDrive etc. - */ - ctlr = device_unit(parent); - slave = ha->ha_slave; - punit = ha->ha_punit; - if (punit == 0) - return 1; - ccmd.c_unit = C_SUNIT(punit); - ccmd.c_cmd = C_CLEAR; - hpibsend(ctlr, slave, C_TCMD, &ccmd, sizeof(ccmd)); - hpibswait(ctlr, slave); - hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); - if (stat != 0) - return 0; - - return 1; + return rdident(parent, NULL, ha); } static void @@ -608,29 +581,45 @@ rdident(device_t parent, struct rd_softc return 0; /* - * If we're just probing for the device, that's all the - * work we need to do. + * The supported dvice ID is probed. + * Check if the specified physical unit is actually supported + * by brandnew HP-IB emulator devices like HPDisk and HPDrive etc. */ - if (sc == NULL) - return 1; - /* * Reset device and collect description */ - rdreset(sc); + memset(&desc, 0, sizeof(desc)); + stat = 0; + rdreset_unit(ctlr, slave, ha->ha_punit); cmd[0] = C_SUNIT(ha->ha_punit); cmd[1] = C_SVOL(0); cmd[2] = C_DESC; hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd)); hpibrecv(ctlr, slave, C_EXEC, &desc, sizeof(desc)); hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); + + if (stat != 0 || desc.d_name == 0) { + /* + * No valid response from the specified punit. + * + * Note it looks HPDisk responds to commands against + * supported but not-configured punits at 1 to 3. + */ + return 0; + } + + /* + * If we're just probing for the device, that's all the + * work we need to do. + */ + if (sc == NULL) + return 1; + memset(name, 0, sizeof(name)); - if (stat == 0) { - n = desc.d_name; - for (i = 5; i >= 0; i--) { - name[i] = (n & 0xf) + '0'; - n >>= 4; - } + n = desc.d_name; + for (i = 5; i >= 0; i--) { + name[i] = (n & 0xf) + '0'; + n >>= 4; } #ifdef DEBUG @@ -711,36 +700,48 @@ rdident(device_t parent, struct rd_softc static void rdreset(struct rd_softc *sc) { - int ctlr = device_unit(device_parent(sc->sc_dev)); - int slave = sc->sc_slave; + int ctlr, slave, punit; + + ctlr = device_unit(device_parent(sc->sc_dev)); + slave = sc->sc_slave; + punit = sc->sc_punit; + rdreset_unit(ctlr, slave, punit); +#ifdef DEBUG + sc->sc_stats.rdresets++; +#endif +} + +static void +rdreset_unit(int ctlr, int slave, int punit) +{ + struct rd_ssmcmd ssmc; + struct rd_srcmd src; + struct rd_clearcmd clear; u_char stat; - sc->sc_clear.c_unit = C_SUNIT(sc->sc_punit); - sc->sc_clear.c_cmd = C_CLEAR; - hpibsend(ctlr, slave, C_TCMD, &sc->sc_clear, sizeof(sc->sc_clear)); + clear.c_unit = C_SUNIT(punit); + clear.c_cmd = C_CLEAR; + hpibsend(ctlr, slave, C_TCMD, &clear, sizeof(clear)); hpibswait(ctlr, slave); hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); - sc->sc_src.c_unit = C_SUNIT(RDCTLR); - sc->sc_src.c_nop = C_NOP; - sc->sc_src.c_cmd = C_SREL; - sc->sc_src.c_param = C_REL; - hpibsend(ctlr, slave, C_CMD, &sc->sc_src, sizeof(sc->sc_src)); + src.c_unit = C_SUNIT(RDCTLR); + src.c_nop = C_NOP; + src.c_cmd = C_SREL; + src.c_param = C_REL; + hpibsend(ctlr, slave, C_CMD, &src, sizeof(src)); hpibswait(ctlr, slave); hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); - sc->sc_ssmc.c_unit = C_SUNIT(sc->sc_punit); - sc->sc_ssmc.c_cmd = C_SSM; - sc->sc_ssmc.c_refm = REF_MASK; - sc->sc_ssmc.c_fefm = FEF_MASK; - sc->sc_ssmc.c_aefm = AEF_MASK; - sc->sc_ssmc.c_iefm = IEF_MASK; - hpibsend(ctlr, slave, C_CMD, &sc->sc_ssmc, sizeof(sc->sc_ssmc)); + ssmc.c_unit = C_SUNIT(punit); + ssmc.c_cmd = C_SSM; + ssmc.c_refm = REF_MASK; + ssmc.c_fefm = FEF_MASK; + ssmc.c_aefm = AEF_MASK; + ssmc.c_iefm = IEF_MASK; + hpibsend(ctlr, slave, C_CMD, &ssmc, sizeof(ssmc)); hpibswait(ctlr, slave); hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat)); -#ifdef DEBUG - sc->sc_stats.rdresets++; -#endif } /*