Author: trasz
Date: Fri Sep  4 09:57:03 2009
New Revision: 196826
URL: http://svn.freebsd.org/changeset/base/196826

Log:
  Make umass(4) pass device USB serial number to CAM, making it possible
  to e.g. retrieve it using camcontrol(8).
  
  Reviewed by:  scottl, hps (earlier version)
  Obtained from:        Wheel Sp. z o.o. (http://www.wheel.pl)

Modified:
  head/sys/dev/usb/storage/umass.c

Modified: head/sys/dev/usb/storage/umass.c
==============================================================================
--- head/sys/dev/usb/storage/umass.c    Fri Sep  4 09:48:18 2009        
(r196825)
+++ head/sys/dev/usb/storage/umass.c    Fri Sep  4 09:57:03 2009        
(r196826)
@@ -124,6 +124,7 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
+#include <dev/usb/usb_device.h>
 #include "usbdevs.h"
 
 #include <cam/cam.h>
@@ -2978,6 +2979,28 @@ umass_cam_action(struct cam_sim *sim, un
                                if (sc->sc_transfer.cmd_data[0] == INQUIRY) {
 
                                        /*
+                                        * Umass devices don't generally report 
their serial numbers
+                                        * in the usual SCSI way.  Emulate it 
here.
+                                        */
+                                       if ((sc->sc_transfer.cmd_data[1] & 
SI_EVPD) &&
+                                           sc->sc_transfer.cmd_data[2] == 
SVPD_UNIT_SERIAL_NUMBER &&
+                                           sc->sc_udev != NULL &&
+                                           sc->sc_udev->serial != NULL &&
+                                           sc->sc_udev->serial[0] != '\0') {
+                                               struct 
scsi_vpd_unit_serial_number *vpd_serial;
+
+                                               vpd_serial = (struct 
scsi_vpd_unit_serial_number *)ccb->csio.data_ptr;
+                                               vpd_serial->length = 
strlen(sc->sc_udev->serial);
+                                               if (vpd_serial->length > 
sizeof(vpd_serial->serial_num))
+                                                       vpd_serial->length = 
sizeof(vpd_serial->serial_num);
+                                               memcpy(vpd_serial->serial_num, 
sc->sc_udev->serial, vpd_serial->length);
+                                               ccb->csio.scsi_status = 
SCSI_STATUS_OK;
+                                               ccb->ccb_h.status = CAM_REQ_CMP;
+                                               xpt_done(ccb);
+                                               goto done;
+                                       }
+
+                                       /*
                                         * Handle EVPD inquiry for broken 
devices first
                                         * NO_INQUIRY also implies 
NO_INQUIRY_EVPD
                                         */
@@ -3193,6 +3216,29 @@ umass_cam_cb(struct umass_softc *sc, uni
                        maxsector = scsi_4btoul(rcap->addr) - 1;
                        scsi_ulto4b(maxsector, rcap->addr);
                }
+               /*
+                * We have to add SVPD_UNIT_SERIAL_NUMBER to the list
+                * of pages supported by the device - otherwise, CAM
+                * will never ask us for the serial number if the
+                * device cannot handle that by itself.
+                */
+               if (ccb->ccb_h.func_code == XPT_SCSI_IO &&
+                   sc->sc_transfer.cmd_data[0] == INQUIRY &&
+                   (sc->sc_transfer.cmd_data[1] & SI_EVPD) &&
+                   sc->sc_transfer.cmd_data[2] == SVPD_SUPPORTED_PAGE_LIST &&
+                   sc->sc_udev != NULL &&
+                   sc->sc_udev->serial != NULL &&
+                   sc->sc_udev->serial[0] != '\0') {
+                       struct ccb_scsiio *csio;
+                       struct scsi_vpd_supported_page_list *page_list;
+
+                       csio = &ccb->csio;
+                       page_list = (struct scsi_vpd_supported_page_list 
*)csio->data_ptr;
+                       if (page_list->length + 1 < SVPD_SUPPORTED_PAGES_SIZE) {
+                               page_list->list[page_list->length] = 
SVPD_UNIT_SERIAL_NUMBER;
+                               page_list->length++;
+                       }
+               }
                xpt_done(ccb);
                break;
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to