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/scsipi/atapiconf.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: atapiconf.c,v 1.95 2022/04/09 23:38:32 riastradh Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1996, 2001 Manuel Bouyer.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __KERNEL_RCSID(0, "$NetBSD: atapiconf.c,v 1.95 2022/04/09 23:38:32 riastradh Exp $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/malloc.h>
   33 #include <sys/device.h>
   34 #include <sys/buf.h>
   35 #include <sys/proc.h>
   36 #include <sys/kthread.h>
   37 #include <sys/atomic.h>
   38 
   39 #include <dev/scsipi/scsipi_all.h>
   40 #include <dev/scsipi/scsipiconf.h>
   41 #include <dev/scsipi/atapiconf.h>
   42 
   43 #include "locators.h"
   44 
   45 #define SILENT_PRINTF(flags,string) if (!(flags & A_SILENT)) printf string
   46 #define MAX_TARGET 1
   47 
   48 const struct scsipi_periphsw atapi_probe_periphsw = {
   49         NULL,
   50         NULL,
   51         NULL,
   52         NULL,
   53 };
   54 
   55 static int      atapibusmatch(device_t, cfdata_t, void *);
   56 static void     atapibusattach(device_t, device_t, void *);
   57 static int      atapibusdetach(device_t, int flags);
   58 static void     atapibuschilddet(device_t, device_t);
   59 
   60 static int      atapibussubmatch(device_t, cfdata_t, const int *, void *);
   61 
   62 static int      atapi_probe_bus(struct atapibus_softc *, int);
   63 
   64 static int      atapibusprint(void *, const char *);
   65 
   66 CFATTACH_DECL3_NEW(atapibus, sizeof(struct atapibus_softc),
   67     atapibusmatch, atapibusattach, atapibusdetach, NULL, NULL,
   68     atapibuschilddet, DVF_DETACH_SHUTDOWN);
   69 
   70 extern struct cfdriver atapibus_cd;
   71 
   72 static const struct scsi_quirk_inquiry_pattern atapi_quirk_patterns[] = {
   73         {{T_CDROM, T_REMOV,
   74          "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, PQUIRK_NOTUR},
   75         {{T_CDROM, T_REMOV,
   76          "CR-2801TE", "", "1.07"},              PQUIRK_NOSENSE},
   77         {{T_CDROM, T_REMOV,
   78          "CREATIVECD3630E", "", "AC101"},       PQUIRK_NOSENSE},
   79         {{T_CDROM, T_REMOV,
   80          "FX320S", "", "q01"},                  PQUIRK_NOSENSE},
   81         {{T_CDROM, T_REMOV,
   82          "GCD-R580B", "", "1.00"},              PQUIRK_LITTLETOC},
   83         {{T_CDROM, T_REMOV,
   84          "HITACHI CDR-7730", "", "0008a"},      PQUIRK_NOSENSE},
   85         {{T_CDROM, T_REMOV,
   86          "MATSHITA CR-574", "", "1.02"},        PQUIRK_NOCAPACITY},
   87         {{T_CDROM, T_REMOV,
   88          "MATSHITA CR-574", "", "1.06"},        PQUIRK_NOCAPACITY},
   89         {{T_CDROM, T_REMOV,
   90          "Memorex CRW-2642", "", "1.0g"},       PQUIRK_NOSENSE},
   91         {{T_CDROM, T_REMOV,
   92          "NEC                 CD-ROM DRIVE:273", "", "4.21"}, PQUIRK_NOTUR},
   93         {{T_CDROM, T_REMOV,
   94          "SANYO CRD-256P", "", "1.02"},         PQUIRK_NOCAPACITY},
   95         {{T_CDROM, T_REMOV,
   96          "SANYO CRD-254P", "", "1.02"},         PQUIRK_NOCAPACITY},
   97         {{T_CDROM, T_REMOV,
   98          "SANYO CRD-S54P", "", "1.08"},         PQUIRK_NOCAPACITY},
   99         {{T_CDROM, T_REMOV,
  100          "CD-ROM  CDR-S1", "", "1.70"},         PQUIRK_NOCAPACITY}, /* Sanyo */
  101         {{T_CDROM, T_REMOV,
  102          "CD-ROM  CDR-N16", "", "1.25"},        PQUIRK_NOCAPACITY}, /* Sanyo */
  103 };
  104 
  105 int
  106 atapiprint(void *aux, const char *pnp)
  107 {
  108         if (pnp)
  109                 aprint_normal("atapibus at %s", pnp);
  110         return (UNCONF);
  111 }
  112 
  113 static int
  114 atapibusmatch(device_t parent, cfdata_t cf, void *aux)
  115 {
  116         struct scsipi_channel *chan = aux;
  117 
  118         if (chan == NULL)
  119                 return (0);
  120 
  121         if (SCSIPI_BUSTYPE_TYPE(chan->chan_bustype->bustype_type) !=
  122             SCSIPI_BUSTYPE_ATAPI)
  123                 return (0);
  124 
  125         return (1);
  126 }
  127 
  128 static int
  129 atapibussubmatch(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
  130 {
  131         struct scsipibus_attach_args *sa = aux;
  132         struct scsipi_periph *periph = sa->sa_periph;
  133 
  134         if (cf->cf_loc[ATAPIBUSCF_DRIVE] != ATAPIBUSCF_DRIVE_DEFAULT &&
  135             cf->cf_loc[ATAPIBUSCF_DRIVE] != periph->periph_target)
  136                 return (0);
  137         return (config_match(parent, cf, aux));
  138 }
  139 
  140 static void
  141 atapibusattach(device_t parent, device_t self, void *aux)
  142 {
  143         struct atapibus_softc *sc = device_private(self);
  144         struct scsipi_channel *chan = aux;
  145 
  146         sc->sc_channel = chan;
  147         sc->sc_dev = self;
  148 
  149         chan->chan_name = device_xname(sc->sc_dev);
  150         chan->chan_id = -1;
  151 
  152         /* ATAPI has no LUNs. */
  153         chan->chan_nluns = 1;
  154         aprint_naive("\n");
  155         aprint_normal(": %d targets\n", chan->chan_ntargets);
  156 
  157         if (atomic_inc_uint_nv(&chan_running(chan)) == 1)
  158                 mutex_init(chan_mtx(chan), MUTEX_DEFAULT, IPL_BIO);
  159 
  160         cv_init(&chan->chan_cv_thr, "scshut");
  161         cv_init(&chan->chan_cv_comp, "sccomp");
  162         cv_init(&chan->chan_cv_xs, "xscmd");
  163 
  164         /* Initialize the channel. */
  165         chan->chan_init_cb = NULL;
  166         chan->chan_init_cb_arg = NULL;
  167         scsipi_channel_init(chan);
  168 
  169         if (!pmf_device_register(self, NULL, NULL))
  170                 aprint_error_dev(self, "couldn't establish power handler\n");
  171 
  172         /* Probe the bus for devices. */
  173         atapi_probe_bus(sc, -1);
  174 }
  175 
  176 static void
  177 atapibuschilddet(device_t self, device_t child)
  178 {
  179         struct atapibus_softc *sc = device_private(self);
  180         struct scsipi_channel *chan = sc->sc_channel;
  181         struct scsipi_periph *periph;
  182         int target;
  183 
  184         mutex_enter(chan_mtx(chan));
  185         for (target = 0; target < chan->chan_ntargets; target++) {
  186                 periph = scsipi_lookup_periph_locked(chan, target, 0);
  187                 if (periph == NULL || periph->periph_dev != child)
  188                         continue;
  189                 scsipi_remove_periph(chan, periph);
  190                 scsipi_free_periph(periph);
  191                 break;
  192         }
  193         mutex_exit(chan_mtx(chan));
  194 }
  195 
  196 /* same as scsibusdetach */
  197 static int
  198 atapibusdetach(device_t self, int flags)
  199 {
  200         struct atapibus_softc *sc = device_private(self);
  201         struct scsipi_channel *chan = sc->sc_channel;
  202         int error = 0;
  203 
  204         /*
  205          * Detach all of the periphs.
  206          */
  207         error = scsipi_target_detach(chan, -1, -1, flags);
  208         if (error)
  209                 return error;
  210 
  211         pmf_device_deregister(self);
  212 
  213         /*
  214          * Shut down the channel.
  215          */
  216         scsipi_channel_shutdown(chan);
  217 
  218         cv_destroy(&chan->chan_cv_xs);
  219         cv_destroy(&chan->chan_cv_comp);
  220         cv_destroy(&chan->chan_cv_thr);
  221 
  222         membar_release();
  223         if (atomic_dec_uint_nv(&chan_running(chan)) == 0) {
  224                 membar_acquire();
  225                 mutex_destroy(chan_mtx(chan));
  226         }
  227 
  228         return 0;
  229 }
  230 
  231 static int
  232 atapi_probe_bus(struct atapibus_softc *sc, int target)
  233 {
  234         struct scsipi_channel *chan = sc->sc_channel;
  235         int maxtarget, mintarget;
  236         int error;
  237         struct atapi_adapter *atapi_adapter;
  238 
  239         KASSERT(chan->chan_ntargets >= 1);
  240 
  241         if (target == -1) {
  242                 maxtarget = chan->chan_ntargets - 1;
  243                 mintarget = 0;
  244         } else {
  245                 if (target < 0 || target >= chan->chan_ntargets)
  246                         return (ENXIO);
  247                 maxtarget = mintarget = target;
  248         }
  249 
  250         if ((error = scsipi_adapter_addref(chan->chan_adapter)) != 0)
  251                 return (error);
  252         atapi_adapter = (struct atapi_adapter*)chan->chan_adapter;
  253         for (target = mintarget; target <= maxtarget; target++)
  254                 atapi_adapter->atapi_probe_device(sc, target);
  255         scsipi_adapter_delref(chan->chan_adapter);
  256         return (0);
  257 }
  258 
  259 void *
  260 atapi_probe_device(struct atapibus_softc *sc, int target,
  261     struct scsipi_periph *periph, struct scsipibus_attach_args *sa)
  262 {
  263         struct scsipi_channel *chan = sc->sc_channel;
  264         const struct scsi_quirk_inquiry_pattern *finger;
  265         cfdata_t cf;
  266         int priority, quirks;
  267 
  268         finger = scsipi_inqmatch(
  269             &sa->sa_inqbuf, (const void *)atapi_quirk_patterns,
  270             sizeof(atapi_quirk_patterns) /
  271                 sizeof(atapi_quirk_patterns[0]),
  272             sizeof(atapi_quirk_patterns[0]), &priority);
  273 
  274         if (finger != NULL)
  275                 quirks = finger->quirks;
  276         else
  277                 quirks = 0;
  278 
  279         /*
  280          * Now apply any quirks from the table.
  281          */
  282         periph->periph_quirks |= quirks;
  283 
  284         if ((cf = config_search(sc->sc_dev, sa,
  285                                 CFARGS(.submatch =
  286                                            atapibussubmatch))) != NULL) {
  287                 scsipi_insert_periph(chan, periph);
  288                 /*
  289                  * XXX Can't assign periph_dev here, because we'll
  290                  * XXX need it before config_attach() returns.  Must
  291                  * XXX assign it in periph driver.
  292                  */
  293                 return config_attach(sc->sc_dev, cf, sa, atapibusprint,
  294                     CFARGS_NONE);
  295         } else {
  296                 atapibusprint(sa, device_xname(sc->sc_dev));
  297                 aprint_normal(" not configured\n");
  298                 scsipi_free_periph(periph);
  299                 return NULL;
  300         }
  301 }
  302 
  303 static int
  304 atapibusprint(void *aux, const char *pnp)
  305 {
  306         struct scsipibus_attach_args *sa = aux;
  307         struct scsipi_inquiry_pattern *inqbuf;
  308         const char *dtype;
  309 
  310         if (pnp != NULL)
  311                 aprint_normal("%s", pnp);
  312 
  313         inqbuf = &sa->sa_inqbuf;
  314 
  315         dtype = scsipi_dtype(inqbuf->type & SID_TYPE);
  316         aprint_normal(" drive %d: <%s, %s, %s> %s %s",
  317             sa->sa_periph->periph_target, inqbuf->vendor,
  318             inqbuf->product, inqbuf->revision, dtype,
  319             inqbuf->removable ? "removable" : "fixed");
  320         return (UNCONF);
  321 }

Cache object: dd1596f93607e6bb83d668e2457be986


[ 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.