The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/umass_scsipi.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: umass_scsipi.c,v 1.19 2003/10/17 00:20:28 mycroft Exp $        */
    2 
    3 /*
    4  * Copyright (c) 2001, 2003 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Lennart Augustsson (lennart@augustsson.net) at
    9  * Carlstedt Research & Technology and by Charles M. Hamnnum.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 #include <sys/cdefs.h>
   41 __KERNEL_RCSID(0, "$NetBSD: umass_scsipi.c,v 1.19 2003/10/17 00:20:28 mycroft Exp $");
   42 
   43 #include "atapibus.h"
   44 #include "scsibus.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/kernel.h>
   49 #include <sys/conf.h>
   50 #include <sys/buf.h>
   51 #include <sys/device.h>
   52 #include <sys/ioctl.h>
   53 #include <sys/malloc.h>
   54 
   55 /* SCSI & ATAPI */
   56 #include <sys/scsiio.h>
   57 #include <dev/scsipi/scsi_all.h>
   58 #include <dev/scsipi/scsipi_all.h>
   59 #include <dev/scsipi/scsiconf.h>
   60 
   61 #include <dev/scsipi/atapiconf.h>
   62 
   63 #include <dev/scsipi/scsipi_disk.h>
   64 #include <dev/scsipi/scsi_disk.h>
   65 #include <dev/scsipi/scsi_changer.h>
   66 
   67 #include <sys/disk.h>           /* XXX */
   68 #include <dev/scsipi/sdvar.h>   /* XXX */
   69 
   70 /* USB */
   71 #include <dev/usb/usb.h>
   72 #include <dev/usb/usbdi.h>
   73 #include <dev/usb/usbdi_util.h>
   74 #include <dev/usb/usbdevs.h>
   75 
   76 #include <dev/usb/umassvar.h>
   77 #include <dev/usb/umass_scsipi.h>
   78 
   79 struct umass_scsipi_softc {
   80         struct umassbus_softc   base;
   81 
   82         struct atapi_adapter    sc_atapi_adapter;
   83 #define sc_adapter sc_atapi_adapter._generic
   84         struct scsipi_channel sc_channel;
   85         usbd_status             sc_sync_status;
   86         struct scsipi_sense     sc_sense_cmd;
   87 };
   88 
   89 
   90 #define SHORT_INQUIRY_LENGTH    36 /* XXX */
   91 
   92 #define UMASS_ATAPI_DRIVE       0
   93 
   94 Static void umass_scsipi_request(struct scsipi_channel *,
   95                                  scsipi_adapter_req_t, void *);
   96 Static void umass_scsipi_minphys(struct buf *bp);
   97 Static int umass_scsipi_ioctl(struct scsipi_channel *, u_long,
   98                               caddr_t, int, usb_proc_ptr );
   99 Static int umass_scsipi_getgeom(struct scsipi_periph *periph,
  100                                 struct disk_parms *, u_long sectors);
  101 
  102 Static void umass_scsipi_cb(struct umass_softc *sc, void *priv,
  103                             int residue, int status);
  104 Static void umass_scsipi_sense_cb(struct umass_softc *sc, void *priv,
  105                                   int residue, int status);
  106 
  107 Static struct umass_scsipi_softc *umass_scsipi_setup(struct umass_softc *sc);
  108 
  109 Static int scsipiprint(void *aux, const char *pnp);
  110 
  111 #if NATAPIBUS > 0
  112 Static void umass_atapi_probe_device(struct atapibus_softc *, int);
  113 
  114 const struct scsipi_bustype umass_atapi_bustype = {
  115         SCSIPI_BUSTYPE_ATAPI,
  116         atapi_scsipi_cmd,
  117         atapi_interpret_sense,
  118         atapi_print_addr,
  119         scsi_kill_pending,
  120 };
  121 #endif
  122 
  123 
  124 #if NSCSIBUS > 0
  125 int
  126 umass_scsi_attach(struct umass_softc *sc)
  127 {
  128         struct umass_scsipi_softc *scbus;
  129 
  130         scbus = umass_scsipi_setup(sc);
  131 
  132         scbus->sc_channel.chan_bustype = &scsi_bustype;
  133         scbus->sc_channel.chan_ntargets = 2;
  134         scbus->sc_channel.chan_nluns = sc->maxlun + 1;
  135         scbus->sc_channel.chan_id = scbus->sc_channel.chan_ntargets - 1;
  136         DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: SCSI\n",
  137                              USBDEVNAME(sc->sc_dev)));
  138 
  139         sc->sc_refcnt++;
  140         scbus->base.sc_child =
  141             config_found(&sc->sc_dev, &scbus->sc_channel, scsipiprint);
  142         if (--sc->sc_refcnt < 0)
  143                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  144 
  145         return (0);
  146 }
  147 #endif
  148 
  149 #if NATAPIBUS > 0
  150 int
  151 umass_atapi_attach(struct umass_softc *sc)
  152 {
  153         struct umass_scsipi_softc *scbus;
  154 
  155         scbus = umass_scsipi_setup(sc);
  156         scbus->sc_atapi_adapter.atapi_probe_device =  umass_atapi_probe_device;
  157 
  158         scbus->sc_channel.chan_bustype = &umass_atapi_bustype;
  159         scbus->sc_channel.chan_ntargets = 2;
  160         scbus->sc_channel.chan_nluns = 1;
  161 
  162         scbus->sc_channel.chan_defquirks |= sc->sc_busquirks;
  163         DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n",
  164                              USBDEVNAME(sc->sc_dev)));
  165 
  166         sc->sc_refcnt++;
  167         scbus->base.sc_child =
  168             config_found(&sc->sc_dev, &scbus->sc_channel, scsipiprint);
  169         if (--sc->sc_refcnt < 0)
  170                 usb_detach_wakeup(USBDEV(sc->sc_dev));
  171 
  172         return (0);
  173 }
  174 #endif
  175 
  176 Static struct umass_scsipi_softc *
  177 umass_scsipi_setup(struct umass_softc *sc)
  178 {
  179         struct umass_scsipi_softc *scbus;
  180 
  181         scbus = malloc(sizeof *scbus, M_DEVBUF, M_WAITOK | M_ZERO);
  182         sc->bus = &scbus->base;
  183 
  184         /* Only use big commands for USB SCSI devices. */
  185         sc->sc_busquirks |= PQUIRK_ONLYBIG;
  186 
  187         /* Fill in the adapter. */
  188         memset(&scbus->sc_adapter, 0, sizeof(scbus->sc_adapter));
  189         scbus->sc_adapter.adapt_dev = &sc->sc_dev;
  190         scbus->sc_adapter.adapt_nchannels = 1;
  191         scbus->sc_adapter.adapt_request = umass_scsipi_request;
  192         scbus->sc_adapter.adapt_minphys = umass_scsipi_minphys;
  193         scbus->sc_adapter.adapt_ioctl = umass_scsipi_ioctl;
  194         scbus->sc_adapter.adapt_getgeom = umass_scsipi_getgeom;
  195 
  196         /* Fill in the channel. */
  197         memset(&scbus->sc_channel, 0, sizeof(scbus->sc_channel));
  198         scbus->sc_channel.chan_adapter = &scbus->sc_adapter;
  199         scbus->sc_channel.chan_channel = 0;
  200         scbus->sc_channel.chan_flags = SCSIPI_CHAN_OPENINGS | SCSIPI_CHAN_NOSETTLE;
  201         scbus->sc_channel.chan_openings = 1;
  202         scbus->sc_channel.chan_max_periph = 1;
  203         scbus->sc_channel.chan_defquirks |= sc->sc_busquirks;
  204 
  205         return (scbus);
  206 }
  207 
  208 Static int
  209 scsipiprint(void *aux, const char *pnp)
  210 {
  211         struct scsipi_channel *chan = aux;
  212 
  213         if (chan->chan_bustype->bustype_type == SCSIPI_BUSTYPE_SCSI) {
  214 #if NSCSIBUS > 0
  215                 return (scsiprint(aux, pnp));
  216 #else
  217                 if (pnp)
  218                         aprint_normal("scsibus at %s", pnp);
  219                 return (UNCONF);
  220 #endif
  221         } else {
  222 #if NATAPIBUS > 0
  223                 return (atapiprint(aux, pnp));
  224 #else
  225                 if (pnp)
  226                         aprint_normal("atapibus at %s", pnp);
  227                 return (UNCONF);
  228 #endif
  229         }
  230 }
  231 
  232 Static void
  233 umass_scsipi_request(struct scsipi_channel *chan,
  234                 scsipi_adapter_req_t req, void *arg)
  235 {
  236         struct scsipi_adapter *adapt = chan->chan_adapter;
  237         struct scsipi_periph *periph;
  238         struct scsipi_xfer *xs;
  239         struct umass_softc *sc = (void *)adapt->adapt_dev;
  240         struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus;
  241         struct scsipi_generic *cmd;
  242         int cmdlen;
  243         int dir;
  244 #ifdef UMASS_DEBUG
  245         microtime(&sc->tv);
  246 #endif
  247         switch(req) {
  248         case ADAPTER_REQ_RUN_XFER:
  249                 xs = arg;
  250                 periph = xs->xs_periph;
  251                 DIF(UDMASS_UPPER, periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS);
  252 
  253                 DPRINTF(UDMASS_CMD, ("%s: umass_scsi_cmd: at %lu.%06lu: %d:%d "
  254                     "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n",
  255                     USBDEVNAME(sc->sc_dev), sc->tv.tv_sec, sc->tv.tv_usec,
  256                     periph->periph_target, periph->periph_lun,
  257                     xs, xs->cmd->opcode, xs->datalen,
  258                     periph->periph_quirks, xs->xs_control & XS_CTL_POLL));
  259 #if defined(USB_DEBUG) && defined(SCSIPI_DEBUG)
  260                 if (umassdebug & UDMASS_SCSI)
  261                         show_scsipi_xs(xs);
  262                 else if (umassdebug & ~UDMASS_CMD)
  263                         show_scsipi_cmd(xs);
  264 #endif
  265 
  266                 if (sc->sc_dying) {
  267                         xs->error = XS_DRIVER_STUFFUP;
  268                         goto done;
  269                 }
  270 
  271 #ifdef UMASS_DEBUG
  272                 if (chan->chan_bustype->bustype_type == SCSIPI_BUSTYPE_ATAPI ?
  273                     periph->periph_target != UMASS_ATAPI_DRIVE :
  274                     periph->periph_target == chan->chan_id) {
  275                         DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n",
  276                             USBDEVNAME(sc->sc_dev),
  277                             periph->periph_target));
  278                         xs->error = XS_DRIVER_STUFFUP;
  279                         goto done;
  280                 }
  281 #endif
  282 
  283                 cmd = xs->cmd;
  284                 cmdlen = xs->cmdlen;
  285 
  286                 dir = DIR_NONE;
  287                 if (xs->datalen) {
  288                         switch (xs->xs_control &
  289                             (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
  290                         case XS_CTL_DATA_IN:
  291                                 dir = DIR_IN;
  292                                 break;
  293                         case XS_CTL_DATA_OUT:
  294                                 dir = DIR_OUT;
  295                                 break;
  296                         }
  297                 }
  298 
  299                 if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) {
  300                         printf("umass_cmd: large datalen, %d\n", xs->datalen);
  301                         xs->error = XS_DRIVER_STUFFUP;
  302                         goto done;
  303                 }
  304 
  305                 if (xs->xs_control & XS_CTL_POLL) {
  306                         /* Use sync transfer. XXX Broken! */
  307                         DPRINTF(UDMASS_SCSI,
  308                             ("umass_scsi_cmd: sync dir=%d\n", dir));
  309                         sc->sc_xfer_flags = USBD_SYNCHRONOUS;
  310                         scbus->sc_sync_status = USBD_INVAL;
  311                         sc->sc_methods->wire_xfer(sc, periph->periph_lun, cmd,
  312                                                   cmdlen, xs->data,
  313                                                   xs->datalen, dir,
  314                                                   xs->timeout, 0, xs);
  315                         sc->sc_xfer_flags = 0;
  316                         DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n",
  317                                               scbus->sc_sync_status));
  318                         switch (scbus->sc_sync_status) {
  319                         case USBD_NORMAL_COMPLETION:
  320                                 xs->error = XS_NOERROR;
  321                                 break;
  322                         case USBD_TIMEOUT:
  323                                 xs->error = XS_TIMEOUT;
  324                                 break;
  325                         default:
  326                                 xs->error = XS_DRIVER_STUFFUP;
  327                                 break;
  328                         }
  329                         goto done;
  330                 } else {
  331                         DPRINTF(UDMASS_SCSI,
  332                             ("umass_scsi_cmd: async dir=%d, cmdlen=%d"
  333                                       " datalen=%d\n",
  334                                       dir, cmdlen, xs->datalen));
  335                         sc->sc_methods->wire_xfer(sc, periph->periph_lun, cmd,
  336                                                   cmdlen, xs->data,
  337                                                   xs->datalen, dir,
  338                                                   xs->timeout,
  339                                                   umass_scsipi_cb, xs);
  340                         return;
  341                 }
  342 
  343                 /* Return if command finishes early. */
  344  done:
  345                 scsipi_done(xs);
  346                 return;
  347         default:
  348                 /* Not supported, nothing to do. */
  349                 ;
  350         }
  351 }
  352 
  353 Static void
  354 umass_scsipi_minphys(struct buf *bp)
  355 {
  356 #ifdef DIAGNOSTIC
  357         if (bp->b_bcount <= 0) {
  358                 printf("umass_scsipi_minphys count(%ld) <= 0\n",
  359                        bp->b_bcount);
  360                 bp->b_bcount = UMASS_MAX_TRANSFER_SIZE;
  361         }
  362 #endif
  363         if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE)
  364                 bp->b_bcount = UMASS_MAX_TRANSFER_SIZE;
  365         minphys(bp);
  366 }
  367 
  368 int
  369 umass_scsipi_ioctl(struct scsipi_channel *chan, u_long cmd, caddr_t arg,
  370                    int flag, usb_proc_ptr p)
  371 {
  372         /*struct umass_softc *sc = link->adapter_softc;*/
  373         /*struct umass_scsipi_softc *scbus = sc->bus;*/
  374 
  375         switch (cmd) {
  376 #if 0
  377         case SCBUSIORESET:
  378                 ccb->ccb_h.status = CAM_REQ_INPROG;
  379                 umass_reset(sc, umass_cam_cb, (void *) ccb);
  380                 return (0);
  381 #endif
  382         default:
  383                 return (ENOTTY);
  384         }
  385 }
  386 
  387 Static int
  388 umass_scsipi_getgeom(struct scsipi_periph *periph, struct disk_parms *dp,
  389                      u_long sectors)
  390 {
  391         struct umass_softc *sc =
  392             (void *)periph->periph_channel->chan_adapter->adapt_dev;
  393 
  394         /* If it's not a floppy, we don't know what to do. */
  395         if (sc->sc_cmd != UMASS_CPROTO_UFI)
  396                 return (0);
  397 
  398         switch (sectors) {
  399         case 1440:
  400                 /* Most likely a single density 3.5" floppy. */
  401                 dp->heads = 2;
  402                 dp->sectors = 9;
  403                 dp->cyls = 80;
  404                 return (1);
  405         case 2880:
  406                 /* Most likely a double density 3.5" floppy. */
  407                 dp->heads = 2;
  408                 dp->sectors = 18;
  409                 dp->cyls = 80;
  410                 return (1);
  411         default:
  412                 return (0);
  413         }
  414 }
  415 
  416 Static void
  417 umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status)
  418 {
  419         struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus;
  420         struct scsipi_xfer *xs = priv;
  421         struct scsipi_periph *periph = xs->xs_periph;
  422         int cmdlen;
  423         int s;
  424 #ifdef UMASS_DEBUG
  425         struct timeval tv;
  426         u_int delta;
  427         microtime(&tv);
  428         delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 + tv.tv_usec - sc->tv.tv_usec;
  429 #endif
  430 
  431         DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu, delta=%u: xs=%p residue=%d"
  432             " status=%d\n", tv.tv_sec, tv.tv_usec, delta, xs, residue, status));
  433 
  434         xs->resid = residue;
  435 
  436         switch (status) {
  437         case STATUS_CMD_OK:
  438                 xs->error = XS_NOERROR;
  439                 break;
  440 
  441         case STATUS_CMD_UNKNOWN:
  442                 /* FALLTHROUGH */
  443         case STATUS_CMD_FAILED:
  444                 /* fetch sense data */
  445                 sc->sc_sense = 1;
  446                 memset(&scbus->sc_sense_cmd, 0, sizeof(scbus->sc_sense_cmd));
  447                 scbus->sc_sense_cmd.opcode = REQUEST_SENSE;
  448                 scbus->sc_sense_cmd.byte2 = periph->periph_lun <<
  449                     SCSI_CMD_LUN_SHIFT;
  450                 scbus->sc_sense_cmd.length = sizeof(xs->sense);
  451 
  452                 if (sc->sc_cmd == UMASS_CPROTO_UFI ||
  453                     sc->sc_cmd == UMASS_CPROTO_ATAPI)
  454                         cmdlen = UFI_COMMAND_LENGTH;    /* XXX */
  455                 else
  456                         cmdlen = sizeof(scbus->sc_sense_cmd);
  457                 sc->sc_methods->wire_xfer(sc, periph->periph_lun,
  458                                           &scbus->sc_sense_cmd, cmdlen,
  459                                           &xs->sense, sizeof(xs->sense),
  460                                           DIR_IN, xs->timeout,
  461                                           umass_scsipi_sense_cb, xs);
  462                 return;
  463 
  464         case STATUS_WIRE_FAILED:
  465                 xs->error = XS_RESET;
  466                 break;
  467 
  468         default:
  469                 panic("%s: Unknown status %d in umass_scsipi_cb",
  470                         USBDEVNAME(sc->sc_dev), status);
  471         }
  472 
  473         DPRINTF(UDMASS_CMD,("umass_scsipi_cb: at %lu.%06lu: return xs->error="
  474             "%d, xs->xs_status=0x%x xs->resid=%d\n",
  475              tv.tv_sec, tv.tv_usec,
  476              xs->error, xs->xs_status, xs->resid));
  477 
  478         s = splbio();
  479         scsipi_done(xs);
  480         splx(s);
  481 }
  482 
  483 /*
  484  * Finalise a completed autosense operation
  485  */
  486 Static void
  487 umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue,
  488                       int status)
  489 {
  490         struct scsipi_xfer *xs = priv;
  491         int s;
  492 
  493         DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: xs=%p residue=%d "
  494                 "status=%d\n", xs, residue, status));
  495 
  496         sc->sc_sense = 0;
  497         switch (status) {
  498         case STATUS_CMD_OK:
  499         case STATUS_CMD_UNKNOWN:
  500                 /* getting sense data succeeded */
  501                 if (residue == 0 || residue == 14)/* XXX */
  502                         xs->error = XS_SENSE;
  503                 else
  504                         xs->error = XS_SHORTSENSE;
  505                 break;
  506         default:
  507                 DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n",
  508                         USBDEVNAME(sc->sc_dev), status));
  509                 xs->error = XS_DRIVER_STUFFUP;
  510                 break;
  511         }
  512 
  513         xs->xs_status |= XS_STS_DONE;
  514 
  515         DPRINTF(UDMASS_CMD,("umass_scsipi_sense_cb: return xs->error=%d, "
  516                 "xs->xs_status=0x%x xs->resid=%d\n", xs->error, xs->xs_status,
  517                 xs->resid));
  518 
  519         s = splbio();
  520         scsipi_done(xs);
  521         splx(s);
  522 }
  523 
  524 #if NATAPIBUS > 0
  525 Static void
  526 umass_atapi_probe_device(struct atapibus_softc *atapi, int target)
  527 {
  528         struct scsipi_channel *chan = atapi->sc_channel;
  529         struct scsipi_periph *periph;
  530         struct scsipibus_attach_args sa;
  531         char vendor[33], product[65], revision[17];
  532         struct scsipi_inquiry_data inqbuf;
  533 
  534         DPRINTF(UDMASS_SCSI,("umass_atapi_probe_device: atapi=%p target=%d\n",
  535                              atapi, target));
  536 
  537         if (target != UMASS_ATAPI_DRIVE)        /* only probe drive 0 */
  538                 return;
  539 
  540         /* skip if already attached */
  541         if (scsipi_lookup_periph(chan, target, 0) != NULL)
  542                 return;
  543 
  544         periph = scsipi_alloc_periph(M_NOWAIT);
  545         if (periph == NULL) {
  546                 printf("%s: can't allocate link for drive %d\n",
  547                        atapi->sc_dev.dv_xname, target);
  548                 return;
  549         }
  550 
  551         DIF(UDMASS_UPPER, periph->periph_dbflags |= 1); /* XXX 1 */
  552         periph->periph_channel = chan;
  553         periph->periph_switch = &atapi_probe_periphsw;
  554         periph->periph_target = target;
  555         periph->periph_quirks = chan->chan_defquirks;
  556 
  557         DPRINTF(UDMASS_SCSI, ("umass_atapi_probe_device: doing inquiry\n"));
  558         /* Now go ask the device all about itself. */
  559         memset(&inqbuf, 0, sizeof(inqbuf));
  560         if (scsipi_inquire(periph, &inqbuf,
  561             XS_CTL_DISCOVERY | XS_CTL_DATA_ONSTACK) != 0) {
  562                 DPRINTF(UDMASS_SCSI, ("umass_atapi_probe_device: "
  563                     "scsipi_inquire failed\n"));
  564                 free(periph, M_DEVBUF);
  565                 return;
  566         }
  567 
  568         scsipi_strvis(vendor, 33, inqbuf.vendor, 8);
  569         scsipi_strvis(product, 65, inqbuf.product, 16);
  570         scsipi_strvis(revision, 17, inqbuf.revision, 4);
  571 
  572         sa.sa_periph = periph;
  573         sa.sa_inqbuf.type = inqbuf.device;
  574         sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?
  575             T_REMOV : T_FIXED;
  576         if (sa.sa_inqbuf.removable)
  577                 periph->periph_flags |= PERIPH_REMOVABLE;
  578         sa.sa_inqbuf.vendor = vendor;
  579         sa.sa_inqbuf.product = product;
  580         sa.sa_inqbuf.revision = revision;
  581         sa.sa_inqptr = NULL;
  582 
  583         DPRINTF(UDMASS_SCSI, ("umass_atapi_probedev: doing atapi_probedev on "
  584                               "'%s' '%s' '%s'\n", vendor, product, revision));
  585         atapi_probe_device(atapi, target, periph, &sa);
  586         /* atapi_probe_device() frees the periph when there is no device.*/
  587 }
  588 #endif

Cache object: a9025d81f645524f39f11fc6ee7a88bc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.