Subject: kern/8842: [dM] add "scsictl detach"
To: None <gnats-bugs@gnats.netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: netbsd-bugs
Date: 11/21/1999 14:40:01
>Number:         8842
>Category:       kern
>Synopsis:       [dM] add "scsictl detach"
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 21 14:39:01 1999
>Last-Modified:
>Originator:     der Mouse
>Organization:
Dis-
>Release:        1.4J
>Environment:
	Any with scsictl(8); I use these most on /sparc machines (SS1+,
	IPX).
>Description:
	scsictl has a "scan" operation to scan a bus for new devices,
	but no way to remove existing devices.  These patches add an
	ioctl SCBUSIODETACH to do this for sd and cd (could be done for
	other devices attaching to scsibusses by small tweaks to their
	drivers, similar to what's done here for sd and cd), and
	support for scsictl(8) to use it.
>How-To-Repeat:
	N/A
>Fix:

#! /bin/sh
#
# Shar: Shell Archiver
#
# This archive created Sun Nov 21 17:30:34 1999
# Run this through sh to create:
#	sbin/
#	sbin/scsictl/
#	sbin/scsictl/scsictl.8
#	sbin/scsictl/scsictl.c
#	sys/
#	sys/dev/
#	sys/dev/scsipi/
#	sys/dev/scsipi/cd_scsi.c
#	sys/dev/scsipi/scsiconf.c
#	sys/dev/scsipi/sd_scsi.c
#	sys/sys/
#	sys/sys/scsiio.h
mkdir sbin>/dev/null 2>&1
mkdir sbin/scsictl>/dev/null 2>&1
echo x - sbin/scsictl/scsictl.8 \(757 characters\)
sed 's/^X//' > sbin/scsictl/scsictl.8 << \EOF
X+++ NEW/sbin/scsictl/scsictl.8	Thu Jan  1 00:00:00 1970
X@@ -118,6 +118,22 @@
X arguments specify which SCSI target and lun on the bus is to be scanned.
X Either may be wildcarded by specifying
X .Dq any .
X+.Pp
X+.Nm detach
X+.Ar target
X+.Ar lun
X+.Pp
X+Detach the device at the specified
X+.Ar target
X+and
X+.Ar lun
X+(which must be fully specified; no wildcarding is supported).
X+.Pp
X+.Sq detach
X+is a bus command, rather than a device command, both to allow detaching
X+devices that refuse to allow themselves to be opened and because to
X+detach the device itself, it would have to be opened, and detaching
X+open devices is Hard.
X .Sh FILES
X /dev/scsibus* - for commands operating on SCSI busses
X .Sh SEE ALSO
EOF
if test 757 -ne "`wc -c < sbin/scsictl/scsictl.8`"
then
echo shar: error transmitting sbin/scsictl/scsictl.8 \(should have been 757 characters\)
fi
echo x - sbin/scsictl/scsictl.c \(1343 characters\)
sed 's/^X//' > sbin/scsictl/scsictl.c << \EOF
X+++ NEW/sbin/scsictl/scsictl.c	Thu Jan  1 00:00:00 1970
X@@ -93,10 +93,12 @@
X 
X void	bus_reset __P((int, char *[]));
X void	bus_scan __P((int, char *[]));
X+void	bus_detach __P((int, char *[]));
X 
X struct command bus_commands[] = {
X 	{ "reset",	" bus",				bus_reset },
X 	{ "scan",	" bus target lun",		bus_scan },
X+	{ "detach",	" bus target lun",		bus_detach },
X 	{ NULL,		NULL,				NULL },
X };
X 
X@@ -407,4 +409,37 @@
X 		err(1, "SCBUSIOSCAN");
X 
X 	return;
X+}
X+
X+/*
X+ * bus_detach:
X+ *
X+ *	Detach a device from a SCSI bus.
X+ *	In a sense this should be a device command, but doing it this way
X+ *	  (a) makes it possible to detach devices that can't be opened
X+ *	  and (b) is necessary because to ioctl the device, it has to be
X+ *	  open, and detaching open devices is Hard.
X+ */
X+void
X+bus_detach(argc, argv)
X+	int argc;
X+	char *argv[];
X+{
X+	struct scbusiodetach_args args;
X+	char *cp;
X+
X+	/* Must have two args: target lun */
X+	if (argc != 2)
X+		usage();
X+
X+	args.sa_target = strtol(argv[0], &cp, 10);
X+	if (*cp != '\0' || args.sa_target < 0)
X+		errx(1, "invalid target: %s\n", argv[0]);
X+
X+	args.sa_lun = strtol(argv[1], &cp, 10);
X+	if (*cp != '\0' || args.sa_lun < 0)
X+		errx(1, "invalid lun: %s\n", argv[1]);
X+
X+	if (ioctl(fd, SCBUSIODETACH, &args) != 0)
X+		err(1, "SCBUSIODETACH");
X }
EOF
if test 1343 -ne "`wc -c < sbin/scsictl/scsictl.c`"
then
echo shar: error transmitting sbin/scsictl/scsictl.c \(should have been 1343 characters\)
fi
mkdir sys>/dev/null 2>&1
mkdir sys/dev>/dev/null 2>&1
mkdir sys/dev/scsipi>/dev/null 2>&1
echo x - sys/dev/scsipi/cd_scsi.c \(1033 characters\)
sed 's/^X//' > sys/dev/scsipi/cd_scsi.c << \EOF
X+++ NEW/sys/dev/scsipi/cd_scsi.c	Thu Jan  1 00:00:00 1970
X@@ -79,13 +79,14 @@
X 
X int	cd_scsibus_match __P((struct device *, struct cfdata *, void *));
X void	cd_scsibus_attach __P((struct device *, struct device *, void *));
X+int	cd_scsibus_detach __P((struct device *, int));
X int	cd_scsibus_get_mode __P((struct cd_softc *,
X 	    struct scsi_cd_mode_data *, int, int, int));
X int	cd_scsibus_set_mode __P((struct cd_softc *,
X 	    struct scsi_cd_mode_data *, int, int));
X 
X struct cfattach cd_scsibus_ca = {
X-	sizeof(struct cd_softc), cd_scsibus_match, cd_scsibus_attach
X+	sizeof(struct cd_softc), cd_scsibus_match, cd_scsibus_attach, cd_scsibus_detach
X };
X 
X 
X@@ -163,6 +164,17 @@
X 	/* should I get the SCSI_CAP_PAGE here ? */
X }
X 
X+int
X+cd_scsibus_detach(cd, flags)
X+	struct device *cd;
X+	int flags;
X+{
X+	if (((struct cd_softc *)cd)->sc_link->flags & SDEV_OPEN)
X+		return(EBUSY);
X+	flags = flags;
X+	return(0);
X+}
X+
X /*
X  * Get the requested page into the buffer given
X  */
EOF
if test 1033 -ne "`wc -c < sys/dev/scsipi/cd_scsi.c`"
then
echo shar: error transmitting sys/dev/scsipi/cd_scsi.c \(should have been 1033 characters\)
fi
echo x - sys/dev/scsipi/scsiconf.c \(2212 characters\)
sed 's/^X//' > sys/dev/scsipi/scsiconf.c << \EOF
X+++ NEW/sys/dev/scsipi/scsiconf.c	Thu Jan  1 00:00:00 1970
X@@ -89,6 +89,7 @@
X  */
X int scsi_probedev __P((struct scsibus_softc *, int, int));
X int scsi_probe_bus __P((int bus, int target, int lun));
X+int scsi_detach_device __P((int bus, int target, int lun));
X 
X struct scsipi_device probe_switch = {
X 	NULL,
X@@ -744,6 +745,58 @@
X 	return (docontinue);
X }
X 
X+/*
X+ * (Try to) detach a device from its scsibus.
X+ * All three numbers must be specified; no wildcards here!
X+ *
X+ * ENXIO if it ain't there
X+ * EIO for attempts to detach the adapter itself
X+ */
X+int
X+scsi_detach_device(bus, target, lun)
X+	int bus, target, lun;
X+{
X+	struct scsibus_softc *scsi;
X+	struct scsipi_link *link;
X+	int err;
X+
X+	/* Check the bus number, get the softc */
X+	if ((bus < 0) || (bus >= scsibus_cd.cd_ndevs))
X+		return(ENXIO);
X+	scsi = scsibus_cd.cd_devs[bus];
X+	if (scsi == 0)
X+		return(ENXIO);
X+
X+	/* Basic sanity check */
X+	if ((target < 0) || (lun < 0))
X+		return(ENXIO);
X+
X+	/* Can't detach the adapter! */
X+	if (target == scsi->adapter_link->scsipi_scsi.adapter_target)
X+		return(EIO);
X+
X+	/* Target ID/LUN in range? */
X+	if ((target > scsi->sc_maxtarget) || (lun > scsi->sc_maxlun))
X+		return(ENXIO);
X+
X+	/* Get the link, make sure there's something there */
X+	link = scsi->sc_link[target][lun];
X+	if (link == 0)
X+		return(ENXIO);
X+
X+	/* Try to do the detach */
X+	err = config_detach(link->device_softc,0);
X+	if (err)
X+		return(err);
X+
X+	/* Clear the bus's pointer, and free */
X+	scsi->sc_link[target][lun] = 0;
X+	free(link,M_DEVBUF);
X+
X+	/* Done; return success */
X+	return(0);
X+}
X+
X /****** Entry points for user control of the SCSI bus. ******/
X 
X int
X@@ -805,6 +858,7 @@
X 	switch (cmd) {
X 	case SCBUSIOSCAN:
X 	case SCBUSIORESET:
X+	case SCBUSIODETACH:
X 		if ((flag & FWRITE) == 0)
X 			return (EBADF);
X 	}
X@@ -818,6 +872,15 @@
X 		/* XXX Change interface to this function. */
X 		error = scsi_probe_busses(minor(dev), a->sa_target,
X 		    a->sa_lun);
X+		break;
X+	    }
X+
X+	case SCBUSIODETACH:
X+	    {
X+		struct scbusiodetach_args *a =
X+		    (struct scbusiodetach_args *)addr;
X+
X+		error = scsi_detach_device(minor(dev),a->sa_target,a->sa_lun);
X 		break;
X 	    }
X 
EOF
if test 2212 -ne "`wc -c < sys/dev/scsipi/scsiconf.c`"
then
echo shar: error transmitting sys/dev/scsipi/scsiconf.c \(should have been 2212 characters\)
fi
echo x - sys/dev/scsipi/sd_scsi.c \(926 characters\)
sed 's/^X//' > sys/dev/scsipi/sd_scsi.c << \EOF
X+++ NEW/sys/dev/scsipi/sd_scsi.c	Thu Jan  1 00:00:00 1970
X@@ -73,9 +73,10 @@
X 
X int	sd_scsibus_match __P((struct device *, struct cfdata *, void *));
X void	sd_scsibus_attach __P((struct device *, struct device *, void *));
X+int	sd_scsibus_detach __P((struct device *, int));
X 
X struct cfattach sd_scsibus_ca = {
X-	sizeof(struct sd_softc), sd_scsibus_match, sd_scsibus_attach
X+	sizeof(struct sd_softc), sd_scsibus_match, sd_scsibus_attach, sd_scsibus_detach
X };
X 
X struct scsipi_inquiry_pattern sd_scsibus_patterns[] = {
X@@ -152,6 +153,18 @@
X 		sd->flags |= SDF_ANCIENT;
X 
X 	sdattach(parent, sd, sc_link, &sd_scsibus_ops);
X+}
X+
X+int
X+sd_scsibus_detach(sd, flags)
X+	struct device *sd;
X+	int flags;
X+{
X+	if (((struct sd_softc *)sd)->sc_link->flags & SDEV_OPEN)
X+		return(EBUSY);
X+	sd_scsibus_flush((struct sd_softc *)sd,0);
X+	flags = flags;
X+	return(0);
X }
X 
X static int
EOF
if test 926 -ne "`wc -c < sys/dev/scsipi/sd_scsi.c`"
then
echo shar: error transmitting sys/dev/scsipi/sd_scsi.c \(should have been 926 characters\)
fi
mkdir sys/sys>/dev/null 2>&1
echo x - sys/sys/scsiio.h \(413 characters\)
sed 's/^X//' > sys/sys/scsiio.h << \EOF
X+++ NEW/sys/sys/scsiio.h	Thu Jan  1 00:00:00 1970
X@@ -90,4 +90,11 @@
X 
X #define	SCBUSIORESET	_IO('U', 1)	/* reset SCSI bus */
X 
X+/* (Try to) detach a device. */
X+struct scbusiodetach_args {
X+	int	sa_target;	/* target to detach */
X+	int	sa_lun;		/* lun to detach */
X+};
X+#define SCBUSIODETACH	_IOW('U', 2, struct scbusiodetach_args)
X+
X #endif /* _SYS_SCSIIO_H_ */
EOF
if test 413 -ne "`wc -c < sys/sys/scsiio.h`"
then
echo shar: error transmitting sys/sys/scsiio.h \(should have been 413 characters\)
fi
exit 0
# end of shell archive
>Audit-Trail:
>Unformatted: