1 /* $NetBSD: atapiconf.c,v 1.35 2000/04/02 23:38:19 augustss Exp $ */ 2 3 /* 4 * Copyright (c) 1996 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/types.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/malloc.h> 36 #include <sys/device.h> 37 #include <sys/buf.h> 38 #include <sys/proc.h> 39 40 #include <dev/ata/atareg.h> 41 #include <dev/ata/atavar.h> 42 #include <dev/scsipi/scsipi_all.h> 43 #include <dev/scsipi/atapi_all.h> 44 #include <dev/scsipi/atapiconf.h> 45 46 #include "locators.h" 47 48 #define SILENT_PRINTF(flags,string) if (!(flags & A_SILENT)) printf string 49 #define MAX_TARGET 1 50 51 int atapibusmatch __P((struct device *, struct cfdata *, void *)); 52 int atapibussubmatch __P((struct device *, struct cfdata *, void *)); 53 void atapibusattach __P((struct device *, struct device *, void *)); 54 int atapibusactivate __P((struct device *, enum devact)); 55 int atapibusdetach __P((struct device *, int flags)); 56 57 int atapi_probe_bus __P((int, int)); 58 59 struct cfattach atapibus_ca = { 60 sizeof(struct atapibus_softc), atapibusmatch, atapibusattach, 61 atapibusdetach, atapibusactivate, 62 }; 63 64 extern struct cfdriver atapibus_cd; 65 66 int atapibusprint __P((void *, const char *)); 67 68 struct scsi_quirk_inquiry_pattern atapi_quirk_patterns[] = { 69 {{T_CDROM, T_REMOV, 70 "ALPS ELECTRIC CO.,LTD. DC544C", "", "SW03D"}, ADEV_NOTUR}, 71 {{T_CDROM, T_REMOV, 72 "BCD-16X 1997-04-25", "", "VER 2.2"}, SDEV_NOSTARTUNIT}, 73 {{T_CDROM, T_REMOV, 74 "BCD-24X 1997-06-27", "", "VER 2.0"}, SDEV_NOSTARTUNIT}, 75 {{T_CDROM, T_REMOV, 76 "CR-2801TE", "", "1.07"}, ADEV_NOSENSE}, 77 {{T_CDROM, T_REMOV, 78 "CREATIVECD3630E", "", "AC101"}, ADEV_NOSENSE}, 79 {{T_CDROM, T_REMOV, 80 "FX320S", "", "q01"}, ADEV_NOSENSE}, 81 {{T_CDROM, T_REMOV, 82 "GCD-R580B", "", "1.00"}, ADEV_LITTLETOC}, 83 {{T_CDROM, T_REMOV, 84 "HITACHI CDR-7730", "", "0008a"}, ADEV_NOSENSE}, 85 {{T_CDROM, T_REMOV, 86 "MATSHITA CR-574", "", "1.02"}, ADEV_NOCAPACITY}, 87 {{T_CDROM, T_REMOV, 88 "MATSHITA CR-574", "", "1.06"}, ADEV_NOCAPACITY}, 89 {{T_CDROM, T_REMOV, 90 "Memorex CRW-2642", "", "1.0g"}, ADEV_NOSENSE}, 91 {{T_CDROM, T_REMOV, 92 "NEC CD-ROM DRIVE:273", "", "4.21"}, ADEV_NOTUR}, 93 {{T_CDROM, T_REMOV, 94 "SANYO CRD-256P", "", "1.02"}, ADEV_NOCAPACITY}, 95 {{T_CDROM, T_REMOV, 96 "SANYO CRD-254P", "", "1.02"}, ADEV_NOCAPACITY}, 97 {{T_CDROM, T_REMOV, 98 "SANYO CRD-S54P", "", "1.08"}, ADEV_NOCAPACITY}, 99 {{T_CDROM, T_REMOV, 100 "CD-ROM CDR-S1", "", "1.70"}, ADEV_NOCAPACITY}, /* Sanyo */ 101 {{T_CDROM, T_REMOV, 102 "CD-ROM CDR-N16", "", "1.25"}, ADEV_NOCAPACITY}, /* Sanyo */ 103 {{T_CDROM, T_REMOV, 104 "UJDCD8730", "", "1.14"}, ADEV_NODOORLOCK}, /* Acer */ 105 }; 106 107 int 108 atapibusmatch(parent, cf, aux) 109 struct device *parent; 110 struct cfdata *cf; 111 void *aux; 112 { 113 struct ata_atapi_attach *aa_link = aux; 114 115 if (aa_link == NULL) 116 return (0); 117 if (aa_link->aa_type != T_ATAPI) 118 return (0); 119 if (cf->cf_loc[ATAPICF_CHANNEL] != aa_link->aa_channel && 120 cf->cf_loc[ATAPICF_CHANNEL] != ATAPICF_CHANNEL_DEFAULT) 121 return 0; 122 return (1); 123 } 124 125 int 126 atapibussubmatch(parent, cf, aux) 127 struct device *parent; 128 struct cfdata *cf; 129 void *aux; 130 { 131 struct scsipibus_attach_args *sa = aux; 132 struct scsipi_link *sc_link = sa->sa_sc_link; 133 134 if (cf->cf_loc[ATAPIBUSCF_DRIVE] != ATAPIBUSCF_DRIVE_DEFAULT && 135 cf->cf_loc[ATAPIBUSCF_DRIVE] != sc_link->scsipi_atapi.drive) 136 return (0); 137 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 138 } 139 140 void 141 atapibusattach(parent, self, aux) 142 struct device *parent, *self; 143 void *aux; 144 { 145 struct atapibus_softc *sc_ab = (struct atapibus_softc *)self; 146 struct ata_atapi_attach *aa_link = aux; 147 struct scsipi_link *sc_link_proto; 148 int nbytes; 149 150 printf("\n"); 151 152 /* Initialize shared data. */ 153 scsipi_init(); 154 155 sc_link_proto = malloc(sizeof(struct scsipi_link), 156 M_DEVBUF, M_NOWAIT); 157 if (sc_link_proto == NULL) 158 panic("atapibusattach : can't allocate scsipi link proto\n"); 159 memset(sc_link_proto, 0, sizeof(struct scsipi_link)); 160 161 sc_link_proto->type = BUS_ATAPI; 162 sc_link_proto->openings = aa_link->aa_openings; 163 sc_link_proto->scsipi_atapi.channel = aa_link->aa_channel; 164 sc_link_proto->adapter_softc = parent; 165 sc_link_proto->adapter = aa_link->aa_bus_private; 166 sc_link_proto->scsipi_atapi.atapibus = sc_ab->sc_dev.dv_unit; 167 sc_link_proto->scsipi_cmd = atapi_scsipi_cmd; 168 sc_link_proto->scsipi_interpret_sense = atapi_interpret_sense; 169 sc_link_proto->sc_print_addr = atapi_print_addr; 170 sc_link_proto->scsipi_kill_pending = 171 ((struct atapi_adapter*)aa_link->aa_bus_private)->atapi_kill_pending; 172 173 174 sc_ab->adapter_link = sc_link_proto; 175 sc_ab->sc_drvs = aa_link->aa_drv_data; 176 177 nbytes = 2 * sizeof(struct scsipi_link **); 178 sc_ab->sc_link = (struct scsipi_link **)malloc(nbytes, M_DEVBUF, 179 M_NOWAIT); 180 if (sc_ab->sc_link == NULL) 181 panic("scsibusattach: can't allocate target links"); 182 memset(sc_ab->sc_link, 0, nbytes); 183 atapi_probe_bus(sc_ab->sc_dev.dv_unit, -1); 184 } 185 186 int 187 atapibusactivate(self, act) 188 struct device *self; 189 enum devact act; 190 { 191 struct atapibus_softc *sc = (struct atapibus_softc *)self; 192 struct scsipi_link *sc_link; 193 int target, error = 0, s; 194 195 s = splbio(); 196 switch (act) { 197 case DVACT_ACTIVATE: 198 error = EOPNOTSUPP; 199 break; 200 201 case DVACT_DEACTIVATE: 202 for (target = 0; target <= MAX_TARGET; target++) { 203 sc_link = sc->sc_link[target]; 204 if (sc_link == NULL) 205 continue; 206 error = config_deactivate(sc_link->device_softc); 207 if (error != 0) 208 goto out; 209 } 210 break; 211 } 212 out: 213 splx(s); 214 return (error); 215 } 216 217 int 218 atapibusdetach(self, flags) 219 struct device *self; 220 int flags; 221 { 222 struct atapibus_softc *sc = (struct atapibus_softc *)self; 223 struct scsipi_link *sc_link; 224 int target, error; 225 226 for (target = 0; target <= MAX_TARGET; target++) { 227 sc_link = sc->sc_link[target]; 228 if (sc_link == NULL) 229 continue; 230 error = config_detach(sc_link->device_softc, flags); 231 if (error != 0) 232 return (error); 233 234 /* 235 * We have successfully detached the child. Drop the 236 * direct reference for the child so that wdcdetach 237 * won't call detach routine twice. 238 */ 239 #ifdef DIAGNOSTIC 240 if (sc_link->device_softc != sc->sc_drvs[target].drv_softc) 241 panic("softc mismatch"); 242 #endif 243 sc->sc_drvs[target].drv_softc = NULL; 244 245 free(sc_link, M_DEVBUF); 246 sc->sc_link[target] = NULL; 247 } 248 return (0); 249 } 250 251 int 252 atapi_probe_bus(bus, target) 253 int bus, target; 254 { 255 int maxtarget, mintarget; 256 struct atapibus_softc *atapi; 257 int error; 258 struct atapi_adapter *atapi_adapter; 259 260 if (bus < 0 || bus >= atapibus_cd.cd_ndevs) 261 return (ENXIO); 262 atapi = atapibus_cd.cd_devs[bus]; 263 if (atapi == NULL) 264 return (ENXIO); 265 266 if (target == -1) { 267 maxtarget = 1; 268 mintarget = 0; 269 } else { 270 if (target < 0 || target > 1) 271 return (ENXIO); 272 maxtarget = mintarget = target; 273 } 274 if ((error = scsipi_adapter_addref(atapi->adapter_link)) != 0) 275 return (error); 276 atapi_adapter = (struct atapi_adapter*)atapi->adapter_link->adapter; 277 for (target = mintarget; target <= maxtarget; target++) 278 atapi_adapter->atapi_probedev(atapi, target); 279 scsipi_adapter_delref(atapi->adapter_link); 280 return (0); 281 } 282 283 void * 284 atapi_probedev(atapi, target, sc_link, sa) 285 struct atapibus_softc *atapi; 286 int target; 287 struct scsipi_link *sc_link; 288 struct scsipibus_attach_args *sa; 289 { 290 struct cfdata *cf; 291 struct scsi_quirk_inquiry_pattern *finger; 292 int priority; 293 294 /* Fill generic parts of the link. */ 295 sc_link->active = 0; 296 sc_link->scsipi_atapi.drive = target; 297 sc_link->device = NULL; 298 TAILQ_INIT(&sc_link->pending_xfers); 299 #if defined(SCSIDEBUG) && DEBUGTYPE == BUS_ATAPI 300 if (DEBUGTARGET == -1 || target == DEBUGTARGET) 301 sc_link->flags |= DEBUGLEVEL; 302 #endif /* SCSIDEBUG */ 303 finger = (struct scsi_quirk_inquiry_pattern *)scsipi_inqmatch( 304 &sa->sa_inqbuf, (caddr_t)atapi_quirk_patterns, 305 sizeof(atapi_quirk_patterns) / 306 sizeof(atapi_quirk_patterns[0]), 307 sizeof(atapi_quirk_patterns[0]), &priority); 308 if (priority != 0) 309 sc_link->quirks |= finger->quirks; 310 311 if ((cf = config_search(atapibussubmatch, &atapi->sc_dev, 312 sa)) != 0) { 313 atapi->sc_link[target] = sc_link; 314 return (config_attach(&atapi->sc_dev, cf, 315 sa, atapibusprint)); 316 } else { 317 atapibusprint(sa, atapi->sc_dev.dv_xname); 318 printf(" not configured\n"); 319 free(sc_link, M_DEVBUF); 320 return (NULL); 321 } 322 } 323 324 int 325 atapibusprint(aux, pnp) 326 void *aux; 327 const char *pnp; 328 { 329 struct scsipibus_attach_args *sa = aux; 330 struct scsipi_inquiry_pattern *inqbuf; 331 char *dtype; 332 333 if (pnp != NULL) 334 printf("%s", pnp); 335 336 inqbuf = &sa->sa_inqbuf; 337 338 dtype = scsipi_dtype(inqbuf->type & SID_TYPE); 339 printf(" drive %d: <%s, %s, %s> type %d %s %s", 340 sa->sa_sc_link->scsipi_atapi.drive,inqbuf->vendor, 341 inqbuf->product, inqbuf->revision, inqbuf->type, dtype, 342 inqbuf->removable ? "removable" : "fixed"); 343 return (UNCONF); 344 } 345