Subject: Re: detaching SCSI devices
To: Jason Thorpe <thorpej@nas.nasa.gov>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: tech-kern
Date: 07/08/1999 18:38:56
>> We have the ability to attach new SCSI devices, via scsictl's "scan"
>> bus command. [...detach...]
> Send me a copy please.
Under separate cover. (This message is going to tech-kern too.)
> This is on my todo list to do in a generic fashion, but I'd like to
> see how you implemented it :-)
"scsictl /dev/scsibus0 detach 2 0", eg. I had to do it as a scsibus
command rather than a device command because to do it as a device
command you have to detach a device even though it's open, which (while
probably possible - delay the detach until last close?) was more hair
than I wanted to get into. Initially I just did the detach anyway, but
that crashed when closing the device (not surprising, since the
scsipi_link had been freed). Now, you can't detach a device that's
open, and since that makes it useless as a device command, it's a
bus-only thing.
As for how, well, it's pretty simple unless I missed something. The
meat of it is in scsiconf.c. It does occur to me that config_detach
should take more care with FSTATE_STAR devices; it should be possible
to free up more than just the last-used unit, so that if you have
sd0-sd5 and dettach (in order) sd3, sd4, sd5, then it reclaims all
three units. Doing this right would be a little interesting, but
shouldn't be too bad....
Anyhow, here's the scsiconf.c stuff. Jason, I'll mail you a patch kit
corresponding to my current draft state separately.
--- OLD/sys/dev/scsipi/scsiconf.c Thu Jan 1 00:00:00 1970
+++ NEW/sys/dev/scsipi/scsiconf.c Thu Jan 1 00:00:00 1970
@@ -89,6 +89,7 @@
*/
int scsi_probedev __P((struct scsibus_softc *, int, int));
int scsi_probe_bus __P((int bus, int target, int lun));
+int scsi_detach_device __P((int bus, int target, int lun));
struct scsipi_device probe_switch = {
NULL,
@@ -744,6 +745,58 @@
return (docontinue);
}
+/*
+ * (Try to) detach a device from its scsibus.
+ * All three numbers must be specified; no wildcards here!
+ *
+ * ENXIO if it ain't there
+ * EIO for attempts to detach the adapter itself
+ */
+int
+scsi_detach_device(bus, target, lun)
+ int bus, target, lun;
+{
+ struct scsibus_softc *scsi;
+ struct scsipi_link *link;
+ int err;
+
+ /* Check the bus number, get the softc */
+ if ((bus < 0) || (bus >= scsibus_cd.cd_ndevs))
+ return(ENXIO);
+ scsi = scsibus_cd.cd_devs[bus];
+ if (scsi == 0)
+ return(ENXIO);
+
+ /* Basic sanity check */
+ if ((target < 0) || (lun < 0))
+ return(ENXIO);
+
+ /* Can't detach the adapter! */
+ if (target == scsi->adapter_link->scsipi_scsi.adapter_target)
+ return(EIO);
+
+ /* Target ID/LUN in range? */
+ if ((target > scsi->sc_maxtarget) || (lun > scsi->sc_maxlun))
+ return(ENXIO);
+
+ /* Get the link, make sure there's something there */
+ link = scsi->sc_link[target][lun];
+ if (link == 0)
+ return(ENXIO);
+
+ /* Try to do the detach */
+ err = config_detach(link->device_softc,0);
+ if (err)
+ return(err);
+
+ /* Clear the bus's pointer, and free */
+ scsi->sc_link[target][lun] = 0;
+ free(link,M_DEVBUF);
+
+ /* Done; return success */
+ return(0);
+}
+
/****** Entry points for user control of the SCSI bus. ******/
int
@@ -805,6 +858,7 @@
switch (cmd) {
case SCBUSIOSCAN:
case SCBUSIORESET:
+ case SCBUSIODETACH:
if ((flag & FWRITE) == 0)
return (EBADF);
}
@@ -818,6 +872,15 @@
/* XXX Change interface to this function. */
error = scsi_probe_busses(minor(dev), a->sa_target,
a->sa_lun);
+ break;
+ }
+
+ case SCBUSIODETACH:
+ {
+ struct scbusiodetach_args *a =
+ (struct scbusiodetach_args *)addr;
+
+ error = scsi_detach_device(minor(dev),a->sa_target,a->sa_lun);
break;
}
The rest are frills (for example, I had to tweak sd_scsi.c to have a
detach function; ideally all the _scsi attachments should have one).
der Mouse
mouse@rodents.montreal.qc.ca
7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B