xref: /netbsd-src/sys/dev/usb/umass_scsipi.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /*	$NetBSD: umass_scsipi.c,v 1.69 2021/08/07 16:19:17 thorpej Exp $	*/
2 
3 /*
4  * Copyright (c) 2001, 2003, 2012 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Lennart Augustsson (lennart@augustsson.net) at
9  * Carlstedt Research & Technology, Charles M. Hamnnum and Matthew R. Green.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: umass_scsipi.c,v 1.69 2021/08/07 16:19:17 thorpej Exp $");
35 
36 #ifdef _KERNEL_OPT
37 #include "opt_usb.h"
38 #endif
39 
40 #include "atapibus.h"
41 #include "scsibus.h"
42 
43 #include <sys/param.h>
44 #include <sys/buf.h>
45 #include <sys/bufq.h>
46 #include <sys/conf.h>
47 #include <sys/device.h>
48 #include <sys/disk.h>		/* XXX */
49 #include <sys/ioctl.h>
50 #include <sys/kernel.h>
51 #include <sys/kmem.h>
52 #include <sys/lwp.h>
53 #include <sys/malloc.h>
54 #include <sys/systm.h>
55 
56 /* SCSI & ATAPI */
57 #include <sys/scsiio.h>
58 #include <dev/scsipi/scsi_spc.h>
59 #include <dev/scsipi/scsi_all.h>
60 #include <dev/scsipi/scsipi_all.h>
61 #include <dev/scsipi/scsiconf.h>
62 
63 #include <dev/scsipi/atapiconf.h>
64 
65 #include <dev/scsipi/scsipi_disk.h>
66 #include <dev/scsipi/scsi_disk.h>
67 #include <dev/scsipi/scsi_changer.h>
68 
69 #include <dev/scsipi/sdvar.h>	/* XXX */
70 
71 /* USB */
72 #include <dev/usb/usb.h>
73 #include <dev/usb/usbdi.h>
74 #include <dev/usb/usbdi_util.h>
75 #include <dev/usb/usbdevs.h>
76 #include <dev/usb/usbhist.h>
77 
78 #include <dev/usb/umassvar.h>
79 #include <dev/usb/umass_scsipi.h>
80 
81 struct umass_scsipi_softc {
82 	struct umassbus_softc	base;
83 
84 	struct atapi_adapter	sc_atapi_adapter;
85 #define sc_adapter sc_atapi_adapter._generic
86 	struct scsipi_channel sc_channel;
87 	usbd_status		sc_sync_status;
88 	struct scsi_request_sense	sc_sense_cmd;
89 };
90 
91 
92 #define SHORT_INQUIRY_LENGTH    36 /* XXX */
93 
94 #define UMASS_ATAPI_DRIVE	0
95 
96 Static void umass_scsipi_request(struct scsipi_channel *,
97 				 scsipi_adapter_req_t, void *);
98 Static void umass_scsipi_minphys(struct buf *);
99 Static int umass_scsipi_ioctl(struct scsipi_channel *, u_long,
100 			      void *, int, proc_t *);
101 Static int umass_scsipi_getgeom(struct scsipi_periph *,
102 				struct disk_parms *, u_long);
103 
104 Static void umass_null_cb(struct umass_softc *, void *,
105 			  int, int);
106 Static void umass_scsipi_cb(struct umass_softc *, void *,
107 			    int, int);
108 Static void umass_scsipi_sense_cb(struct umass_softc *, void *,
109 				  int, int);
110 
111 Static struct umass_scsipi_softc *umass_scsipi_setup(struct umass_softc *);
112 
113 #if NATAPIBUS > 0
114 Static void umass_atapi_probe_device(struct atapibus_softc *, int);
115 
116 const struct scsipi_bustype umass_atapi_bustype = {
117 	.bustype_type = SCSIPI_BUSTYPE_ATAPI,
118 	.bustype_cmd = atapi_scsipi_cmd,
119 	.bustype_interpret_sense = atapi_interpret_sense,
120 	.bustype_printaddr = atapi_print_addr,
121 	.bustype_kill_pending = scsi_kill_pending,
122 	.bustype_async_event_xfer_mode = NULL,
123 };
124 #endif
125 
126 
127 #if NSCSIBUS > 0
128 int
129 umass_scsi_attach(struct umass_softc *sc)
130 {
131 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
132 	struct umass_scsipi_softc *scbus;
133 
134 	scbus = umass_scsipi_setup(sc);
135 
136 	scbus->sc_channel.chan_bustype = &scsi_bustype;
137 	scbus->sc_channel.chan_ntargets = 2;
138 	scbus->sc_channel.chan_nluns = sc->maxlun + 1;
139 	scbus->sc_channel.chan_id = scbus->sc_channel.chan_ntargets - 1;
140 	DPRINTFM(UDMASS_USB, "sc %#jx: SCSI", (uintptr_t)sc, 0, 0, 0);
141 
142 	mutex_enter(&sc->sc_lock);
143 	sc->sc_refcnt++;
144 	mutex_exit(&sc->sc_lock);
145 	scbus->base.sc_child =
146 	    config_found(sc->sc_dev, &scbus->sc_channel, scsiprint,
147 			 CFARGS(.iattr = "scsi"));
148 	mutex_enter(&sc->sc_lock);
149 	if (--sc->sc_refcnt < 0)
150 		cv_broadcast(&sc->sc_detach_cv);
151 	mutex_exit(&sc->sc_lock);
152 
153 
154 	return 0;
155 }
156 
157 void
158 umass_scsi_detach(struct umass_softc *sc)
159 {
160 	struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus;
161 
162 	kmem_free(scbus, sizeof(*scbus));
163 	sc->bus = NULL;
164 }
165 #endif
166 
167 #if NATAPIBUS > 0
168 int
169 umass_atapi_attach(struct umass_softc *sc)
170 {
171 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
172 	struct umass_scsipi_softc *scbus;
173 
174 	scbus = umass_scsipi_setup(sc);
175 	scbus->sc_atapi_adapter.atapi_probe_device =  umass_atapi_probe_device;
176 
177 	scbus->sc_channel.chan_bustype = &umass_atapi_bustype;
178 	scbus->sc_channel.chan_ntargets = 2;
179 	scbus->sc_channel.chan_nluns = 1;
180 
181 	scbus->sc_channel.chan_defquirks |= sc->sc_busquirks;
182 	DPRINTFM(UDMASS_USB, "sc %#jxp: ATAPI", (uintptr_t)sc, 0, 0, 0);
183 
184 	mutex_enter(&sc->sc_lock);
185 	sc->sc_refcnt++;
186 	mutex_exit(&sc->sc_lock);
187 	scbus->base.sc_child =
188 	    config_found(sc->sc_dev, &scbus->sc_channel, atapiprint,
189 			 CFARGS(.iattr = "atapi"));
190 	mutex_enter(&sc->sc_lock);
191 	if (--sc->sc_refcnt < 0)
192 		cv_broadcast(&sc->sc_detach_cv);
193 	mutex_exit(&sc->sc_lock);
194 
195 	return 0;
196 }
197 
198 void
199 umass_atapi_detach(struct umass_softc *sc)
200 {
201 	struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus;
202 
203 	kmem_free(scbus, sizeof(*scbus));
204 	sc->bus = NULL;
205 }
206 #endif
207 
208 Static struct umass_scsipi_softc *
209 umass_scsipi_setup(struct umass_softc *sc)
210 {
211 	struct umass_scsipi_softc *scbus;
212 
213 	scbus = kmem_zalloc(sizeof(*scbus), KM_SLEEP);
214 	sc->bus = &scbus->base;
215 
216 	/* Only use big commands for USB SCSI devices. */
217 	/* Do not ask for timeouts.  */
218 	sc->sc_busquirks |= PQUIRK_ONLYBIG|PQUIRK_NOREPSUPPOPC;
219 
220 	/* Fill in the adapter. */
221 	memset(&scbus->sc_adapter, 0, sizeof(scbus->sc_adapter));
222 	scbus->sc_adapter.adapt_dev = sc->sc_dev;
223 	scbus->sc_adapter.adapt_nchannels = 1;
224 	scbus->sc_adapter.adapt_request = umass_scsipi_request;
225 	scbus->sc_adapter.adapt_minphys = umass_scsipi_minphys;
226 	scbus->sc_adapter.adapt_ioctl = umass_scsipi_ioctl;
227 	scbus->sc_adapter.adapt_getgeom = umass_scsipi_getgeom;
228 	scbus->sc_adapter.adapt_flags = SCSIPI_ADAPT_MPSAFE;
229 
230 	/* Fill in the channel. */
231 	memset(&scbus->sc_channel, 0, sizeof(scbus->sc_channel));
232 	scbus->sc_channel.chan_adapter = &scbus->sc_adapter;
233 	scbus->sc_channel.chan_channel = 0;
234 	scbus->sc_channel.chan_flags = SCSIPI_CHAN_OPENINGS | SCSIPI_CHAN_NOSETTLE;
235 	scbus->sc_channel.chan_openings = 1;
236 	scbus->sc_channel.chan_max_periph = 1;
237 	scbus->sc_channel.chan_defquirks |= sc->sc_busquirks;
238 
239 	return scbus;
240 }
241 
242 Static void
243 umass_scsipi_request(struct scsipi_channel *chan,
244 		scsipi_adapter_req_t req, void *arg)
245 {
246 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
247 	struct scsipi_adapter *adapt = chan->chan_adapter;
248 	struct scsipi_periph *periph;
249 	struct scsipi_xfer *xs;
250 	struct umass_softc *sc = device_private(adapt->adapt_dev);
251 	struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus;
252 	struct scsipi_generic *cmd;
253 	int cmdlen;
254 	int dir;
255 #ifdef UMASS_DEBUG
256 	microtime(&sc->tv);
257 #endif
258 	switch(req) {
259 	case ADAPTER_REQ_RUN_XFER:
260 		xs = arg;
261 		periph = xs->xs_periph;
262 		DIF(UDMASS_UPPER, periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS);
263 
264 		DPRINTFM(UDMASS_CMD, "sc %#jxp: %jd:%jd xs=%#jxp",
265 		    (uintptr_t)sc, periph->periph_target, periph->periph_lun,
266 		    (uintptr_t)xs);
267 		DPRINTFM(UDMASS_CMD, "cmd=0x%02jx datalen=%jd (quirks=%#jx, "
268 		    "poll=%jd)", xs->cmd->opcode, xs->datalen,
269 		    periph->periph_quirks, !!(xs->xs_control & XS_CTL_POLL));
270 #if defined(UMASS_DEBUG) && defined(SCSIPI_DEBUG)
271 		if (umassdebug & UDMASS_SCSI)
272 			show_scsipi_xs(xs);
273 		else if (umassdebug & ~UDMASS_CMD)
274 			show_scsipi_cmd(xs);
275 #endif
276 
277 		if (sc->sc_dying) {
278 			xs->error = XS_DRIVER_STUFFUP;
279 			goto done;
280 		}
281 
282 #ifdef UMASS_DEBUG
283 		if (SCSIPI_BUSTYPE_TYPE(chan->chan_bustype->bustype_type) ==
284 		    SCSIPI_BUSTYPE_ATAPI ?
285 		    periph->periph_target != UMASS_ATAPI_DRIVE :
286 		    periph->periph_target == chan->chan_id) {
287 			DPRINTFM(UDMASS_SCSI, "sc %#jx: wrong SCSI ID %jd",
288 			    (uintptr_t)sc, periph->periph_target, 0, 0);
289 			xs->error = XS_DRIVER_STUFFUP;
290 			goto done;
291 		}
292 #endif
293 
294 		cmd = xs->cmd;
295 		cmdlen = xs->cmdlen;
296 
297 		dir = DIR_NONE;
298 		if (xs->datalen) {
299 			switch (xs->xs_control &
300 			    (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
301 			case XS_CTL_DATA_IN:
302 				dir = DIR_IN;
303 				break;
304 			case XS_CTL_DATA_OUT:
305 				dir = DIR_OUT;
306 				break;
307 			}
308 		}
309 
310 		if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) {
311 			printf("umass_cmd: large datalen, %d\n", xs->datalen);
312 			xs->error = XS_DRIVER_STUFFUP;
313 			goto done;
314 		}
315 
316 		if (xs->xs_control & XS_CTL_POLL) {
317 			/* Use sync transfer. XXX Broken! */
318 			DPRINTFM(UDMASS_SCSI, "sync dir=%jd\n", dir, 0, 0, 0);
319 			scbus->sc_sync_status = USBD_INVAL;
320 			sc->sc_methods->wire_xfer(sc, periph->periph_lun, cmd,
321 						  cmdlen, xs->data,
322 						  xs->datalen, dir,
323 						  xs->timeout, USBD_SYNCHRONOUS,
324 						  umass_null_cb, xs);
325 			DPRINTFM(UDMASS_SCSI, "done err=%jd",
326 			    scbus->sc_sync_status, 0, 0, 0);
327 			switch (scbus->sc_sync_status) {
328 			case USBD_NORMAL_COMPLETION:
329 				xs->error = XS_NOERROR;
330 				break;
331 			case USBD_TIMEOUT:
332 				xs->error = XS_TIMEOUT;
333 				break;
334 			default:
335 				xs->error = XS_DRIVER_STUFFUP;
336 				break;
337 			}
338 			goto done;
339 		} else {
340 			DPRINTFM(UDMASS_SCSI, "async dir=%jd, cmdlen=%jd"
341 			    " datalen=%jd", dir, cmdlen, xs->datalen, 0);
342 			sc->sc_methods->wire_xfer(sc, periph->periph_lun, cmd,
343 						  cmdlen, xs->data,
344 						  xs->datalen, dir,
345 						  xs->timeout, 0,
346 						  umass_scsipi_cb, xs);
347 			return;
348 		}
349 
350 		/* Return if command finishes early. */
351  done:
352 		scsipi_done(xs);
353 		return;
354 	default:
355 		/* Not supported, nothing to do. */
356 		;
357 	}
358 }
359 
360 Static void
361 umass_scsipi_minphys(struct buf *bp)
362 {
363 #ifdef DIAGNOSTIC
364 	if (bp->b_bcount <= 0) {
365 		printf("umass_scsipi_minphys count(%d) <= 0\n",
366 		       bp->b_bcount);
367 		bp->b_bcount = UMASS_MAX_TRANSFER_SIZE;
368 	}
369 #endif
370 	if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE)
371 		bp->b_bcount = UMASS_MAX_TRANSFER_SIZE;
372 	minphys(bp);
373 }
374 
375 int
376 umass_scsipi_ioctl(struct scsipi_channel *chan, u_long cmd,
377     void *arg, int flag, proc_t *p)
378 {
379 	/*struct umass_softc *sc = link->adapter_softc;*/
380 	/*struct umass_scsipi_softc *scbus = sc->bus;*/
381 
382 	switch (cmd) {
383 #if 0
384 	case SCBUSIORESET:
385 		ccb->ccb_h.status = CAM_REQ_INPROG;
386 		umass_reset(sc, umass_cam_cb, (void *) ccb);
387 		return 0;
388 #endif
389 	default:
390 		return ENOTTY;
391 	}
392 }
393 
394 Static int
395 umass_scsipi_getgeom(struct scsipi_periph *periph, struct disk_parms *dp,
396 		     u_long sectors)
397 {
398 	struct umass_softc *sc =
399 	    device_private(periph->periph_channel->chan_adapter->adapt_dev);
400 
401 	/* If it's not a floppy, we don't know what to do. */
402 	if (sc->sc_cmd != UMASS_CPROTO_UFI)
403 		return 0;
404 
405 	switch (sectors) {
406 	case 1440:
407 		/* Most likely a single density 3.5" floppy. */
408 		dp->heads = 2;
409 		dp->sectors = 9;
410 		dp->cyls = 80;
411 		return 1;
412 	case 2880:
413 		/* Most likely a double density 3.5" floppy. */
414 		dp->heads = 2;
415 		dp->sectors = 18;
416 		dp->cyls = 80;
417 		return 1;
418 	default:
419 		return 0;
420 	}
421 }
422 
423 Static void
424 umass_null_cb(struct umass_softc *sc, void *priv, int residue, int status)
425 {
426 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
427 }
428 
429 Static void
430 umass_scsipi_cb(struct umass_softc *sc, void *priv, int residue, int status)
431 {
432 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
433 	struct umass_scsipi_softc *scbus = (struct umass_scsipi_softc *)sc->bus;
434 	struct scsipi_xfer *xs = priv;
435 	struct scsipi_periph *periph = xs->xs_periph;
436 	int cmdlen, senselen;
437 #ifdef UMASS_DEBUG
438 	struct timeval tv;
439 	u_int delta;
440 	microtime(&tv);
441 	delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 + tv.tv_usec - sc->tv.tv_usec;
442 	DPRINTFM(UDMASS_CMD, "delta=%ju: xs=%#jx residue=%jd status=%jd",
443 	    delta, (uintptr_t)xs, residue, status);
444 #endif
445 
446 
447 	xs->resid = residue;
448 
449 	switch (status) {
450 	case STATUS_CMD_OK:
451 		xs->error = XS_NOERROR;
452 		break;
453 
454 	case STATUS_CMD_UNKNOWN:
455 		/* FALLTHROUGH */
456 	case STATUS_CMD_FAILED:
457 		/* fetch sense data */
458 		sc->sc_sense = 1;
459 		memset(&scbus->sc_sense_cmd, 0, sizeof(scbus->sc_sense_cmd));
460 		scbus->sc_sense_cmd.opcode = SCSI_REQUEST_SENSE;
461 		scbus->sc_sense_cmd.byte2 = periph->periph_lun <<
462 		    SCSI_CMD_LUN_SHIFT;
463 
464 		if (sc->sc_cmd == UMASS_CPROTO_UFI ||
465 		    sc->sc_cmd == UMASS_CPROTO_ATAPI)
466 			cmdlen = UFI_COMMAND_LENGTH;	/* XXX */
467 		else
468 			cmdlen = sizeof(scbus->sc_sense_cmd);
469 		if (periph->periph_version < 0x04) /* SPC-2 */
470 			senselen = 18;
471 		else
472 			senselen = sizeof(xs->sense);
473 		scbus->sc_sense_cmd.length = senselen;
474 		sc->sc_methods->wire_xfer(sc, periph->periph_lun,
475 					  &scbus->sc_sense_cmd, cmdlen,
476 					  &xs->sense, senselen,
477 					  DIR_IN, xs->timeout, 0,
478 					  umass_scsipi_sense_cb, xs);
479 		return;
480 
481 	case STATUS_WIRE_FAILED:
482 		xs->error = XS_RESET;
483 		break;
484 
485 	case STATUS_TIMEOUT:
486 		xs->error = XS_TIMEOUT;
487 		break;
488 
489 	default:
490 		panic("%s: Unknown status %d in umass_scsipi_cb",
491 			device_xname(sc->sc_dev), status);
492 	}
493 
494 	DPRINTFM(UDMASS_CMD, "return xs->error=%jd, xs->xs_status=%#jx"
495 	    " xs->resid=%jd", xs->error, xs->xs_status, xs->resid, 0);
496 
497 	scsipi_done(xs);
498 }
499 
500 /*
501  * Finalise a completed autosense operation
502  */
503 Static void
504 umass_scsipi_sense_cb(struct umass_softc *sc, void *priv, int residue,
505 		      int status)
506 {
507 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
508 	struct scsipi_xfer *xs = priv;
509 	size_t extra;
510 
511 	DPRINTFM(UDMASS_CMD, "sc %#jx: xs=%#jx residue=%jd status=%jd",
512 	    (uintptr_t)sc, (uintptr_t)xs, residue, status);
513 
514 	sc->sc_sense = 0;
515 	switch (status) {
516 	case STATUS_CMD_OK:
517 	case STATUS_CMD_UNKNOWN:
518 		/* getting sense data succeeded */
519 		extra = sizeof(xs->sense.scsi_sense)
520 		      - sizeof(xs->sense.scsi_sense.extra_bytes);
521 		if (residue <= extra)
522 			xs->error = XS_SENSE;
523 		else
524 			xs->error = XS_SHORTSENSE;
525 		break;
526 	default:
527 		DPRINTFM(UDMASS_SCSI, "sc %#jx: Autosense failed, status %jd",
528 		    (uintptr_t)sc, status, 0, 0);
529 		xs->error = XS_DRIVER_STUFFUP;
530 		break;
531 	}
532 
533 	DPRINTFM(UDMASS_CMD, "return xs->error=%jd, xs->xs_status=%#jx"
534 	    " xs->resid=%jd", xs->error, xs->xs_status, xs->resid, 0);
535 
536 	scsipi_done(xs);
537 }
538 
539 #if NATAPIBUS > 0
540 Static void
541 umass_atapi_probe_device(struct atapibus_softc *atapi, int target)
542 {
543 	UMASSHIST_FUNC(); UMASSHIST_CALLED();
544 	struct scsipi_channel *chan = atapi->sc_channel;
545 	struct scsipi_periph *periph;
546 	struct scsipibus_attach_args sa;
547 	char vendor[33], product[65], revision[17];
548 	struct scsipi_inquiry_data inqbuf;
549 
550 	DPRINTFM(UDMASS_SCSI, "atapi=%#jx target=%jd", (uintptr_t)atapi,
551 	    target, 0, 0);
552 
553 	if (target != UMASS_ATAPI_DRIVE)	/* only probe drive 0 */
554 		return;
555 
556 	/* skip if already attached */
557 	if (scsipi_lookup_periph(chan, target, 0) != NULL) {
558 		return;
559 	}
560 
561 	periph = scsipi_alloc_periph(M_WAITOK);
562 	DIF(UDMASS_UPPER, periph->periph_dbflags |= 1); /* XXX 1 */
563 	periph->periph_channel = chan;
564 	periph->periph_switch = &atapi_probe_periphsw;
565 	periph->periph_target = target;
566 	periph->periph_quirks = chan->chan_defquirks;
567 
568 	DPRINTFM(UDMASS_SCSI, "doing inquiry", 0, 0, 0, 0);
569 	/* Now go ask the device all about itself. */
570 	memset(&inqbuf, 0, sizeof(inqbuf));
571 	if (scsipi_inquire(periph, &inqbuf, XS_CTL_DISCOVERY) != 0) {
572 		DPRINTFM(UDMASS_SCSI, "scsipi_inquire failed", 0, 0, 0, 0);
573 		free(periph, M_DEVBUF);
574 		return;
575 	}
576 
577 	strnvisx(vendor, sizeof(vendor), inqbuf.vendor, 8,
578 	    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
579 	strnvisx(product, sizeof(product), inqbuf.product, 16,
580 	    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
581 	strnvisx(revision, sizeof(revision), inqbuf.revision, 4,
582 	    VIS_TRIM|VIS_SAFE|VIS_OCTAL);
583 
584 	sa.sa_periph = periph;
585 	sa.sa_inqbuf.type = inqbuf.device;
586 	sa.sa_inqbuf.removable = inqbuf.dev_qual2 & SID_REMOVABLE ?
587 	    T_REMOV : T_FIXED;
588 	if (sa.sa_inqbuf.removable)
589 		periph->periph_flags |= PERIPH_REMOVABLE;
590 	sa.sa_inqbuf.vendor = vendor;
591 	sa.sa_inqbuf.product = product;
592 	sa.sa_inqbuf.revision = revision;
593 	sa.sa_inqptr = NULL;
594 
595 	atapi_probe_device(atapi, target, periph, &sa);
596 	/* atapi_probe_device() frees the periph when there is no device.*/
597 }
598 #endif
599