xref: /netbsd-src/sys/dev/scsipi/atapiconf.c (revision ef3476fb5721c4ddb85643c5ce2f7cbbc30a2820)
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
atapiprint(void * aux,const char * pnp)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
atapibusmatch(device_t parent,cfdata_t cf,void * aux)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
atapibussubmatch(device_t parent,cfdata_t cf,const int * ldesc,void * aux)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
atapibusattach(device_t parent,device_t self,void * aux)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
atapibuschilddet(device_t self,device_t child)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
atapibusdetach(device_t self,int flags)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
atapi_probe_bus(struct atapibus_softc * sc,int target)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 *
atapi_probe_device(struct atapibus_softc * sc,int target,struct scsipi_periph * periph,struct scsipibus_attach_args * sa)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
atapibusprint(void * aux,const char * pnp)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  }
322