diff options
author | 2006-11-26 09:29:07 +0000 | |
---|---|---|
committer | 2006-11-26 09:29:07 +0000 | |
commit | 059071676bfa736ffc7a23f957b12afdce141755 (patch) | |
tree | 8ceba7803eb1ca34e29b1d22711b1eb9dcbde6b9 | |
parent | sync (diff) | |
download | wireguard-openbsd-059071676bfa736ffc7a23f957b12afdce141755.tar.xz wireguard-openbsd-059071676bfa736ffc7a23f957b12afdce141755.zip |
provide scsi_detach_bus, _target, and _lun to wrap up config_detach for
scsi devices. the midlayer keeps some state for each device that is
attached which needs to be cleaned up on detach, hence this wrapper.
-rw-r--r-- | sys/scsi/scsiconf.c | 78 | ||||
-rw-r--r-- | sys/scsi/scsiconf.h | 6 |
2 files changed, 82 insertions, 2 deletions
diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 3028dbe54bf..0725b902ad0 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.c,v 1.117 2006/10/21 07:36:15 dlg Exp $ */ +/* $OpenBSD: scsiconf.c,v 1.118 2006/11/26 09:29:07 dlg Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* @@ -297,6 +297,82 @@ scsi_probe_lun(struct scsibus_softc *sc, int target, int lun) return (scsi_probedev(sc, target, lun)); } +int +scsi_detach_bus(struct scsibus_softc *sc, int flags) +{ + struct scsi_link *alink = sc->adapter_link; + int i, err, rv; + + for (i = 0; i < alink->adapter_buswidth; i++) { + if (sc->sc_link[i] == NULL) + continue; + + err = scsi_detach_target(sc, i, flags); + if (err != 0) + rv = err; + } + + return (rv); +} + +int +scsi_detach_target(struct scsibus_softc *sc, int target, int flags) +{ + struct scsi_link *alink = sc->adapter_link; + int i, err, rv; + + if (target < 0 || target >= alink->adapter_buswidth || + target == alink->adapter_target) + return (ENXIO); + + for (i = 0; i < alink->luns; i++) { /* nicer backwards? */ + if (sc->sc_link[target][i] == NULL) + continue; + + err = scsi_detach_lun(sc, target, i, flags); + if (err != 0) + rv = err; + } + + return (rv); +} + +int +scsi_detach_lun(struct scsibus_softc *sc, int target, int lun, int flags) +{ + struct scsi_link *alink = sc->adapter_link; + struct scsi_link *link; + int rv; + + if (target < 0 || target >= alink->adapter_buswidth || + target == alink->adapter_target || + lun < 0 || lun >= alink->luns) + return (ENXIO); + + if (sc->sc_link[target] == NULL) + return (ENXIO); + + link = sc->sc_link[target][lun]; + if (link == NULL) + return (ENXIO); + + if (((flags & DETACH_FORCE) == 0) && link->flags & SDEV_OPEN) + return (EBUSY); + + /* detaching a device from scsibus is a two step process... */ + + /* 1. detach the device */ + rv = config_detach(link->device_softc, flags); + if (rv != 0) + return (rv); + + /* 2. free up its state in the midlayer */ + free(link, M_DEVBUF); + sc->sc_link[target][lun] = NULL; + + return (0); +} + void scsi_strvis(u_char *dst, u_char *src, int len) { diff --git a/sys/scsi/scsiconf.h b/sys/scsi/scsiconf.h index ffdf1d49a9a..143226f6204 100644 --- a/sys/scsi/scsiconf.h +++ b/sys/scsi/scsiconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.h,v 1.76 2006/10/21 07:36:15 dlg Exp $ */ +/* $OpenBSD: scsiconf.h,v 1.77 2006/11/26 09:29:07 dlg Exp $ */ /* $NetBSD: scsiconf.h,v 1.35 1997/04/02 02:29:38 mycroft Exp $ */ /* @@ -350,6 +350,10 @@ int scsi_probe_bus(struct scsibus_softc *); int scsi_probe_target(struct scsibus_softc *, int); int scsi_probe_lun(struct scsibus_softc *, int, int); +int scsi_detach_bus(struct scsibus_softc *, int); +int scsi_detach_target(struct scsibus_softc *, int, int); +int scsi_detach_lun(struct scsibus_softc *, int, int, int); + static __inline void _lto2b(u_int32_t val, u_int8_t *bytes); static __inline void _lto3b(u_int32_t val, u_int8_t *bytes); static __inline void _lto4b(u_int32_t val, u_int8_t *bytes); |