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

Cache object: caa60395c4aa89b520f00f77dc8b6825


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