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