This source file includes following definitions.
- umass_scsi_attach
- umass_atapi_attach
- umass_scsi_setup
- umass_scsi_cmd
- umass_scsi_minphys
- umass_scsi_cb
- umass_scsi_sense_cb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include "atapiscsi.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/kernel.h>
45 #include <sys/conf.h>
46 #include <sys/buf.h>
47 #include <sys/device.h>
48 #include <sys/ioctl.h>
49 #include <sys/malloc.h>
50
51 #include <dev/usb/usb.h>
52 #include <dev/usb/usbdi.h>
53 #include <dev/usb/usbdi_util.h>
54 #include <dev/usb/usbdevs.h>
55
56 #include <dev/usb/umassvar.h>
57 #include <dev/usb/umass_scsi.h>
58
59 #include <scsi/scsi_all.h>
60 #include <scsi/scsiconf.h>
61 #include <scsi/scsi_disk.h>
62 #include <machine/bus.h>
63
64 struct umass_scsi_softc {
65 struct umassbus_softc base;
66 struct scsi_link sc_link;
67 struct scsi_adapter sc_adapter;
68
69 struct scsi_sense sc_sense_cmd;
70 };
71
72
73 #define UMASS_SCSIID_HOST 0x00
74 #define UMASS_SCSIID_DEVICE 0x01
75
76 #define UMASS_ATAPI_DRIVE 0
77
78 int umass_scsi_cmd(struct scsi_xfer *);
79 void umass_scsi_minphys(struct buf *);
80
81 void umass_scsi_cb(struct umass_softc *sc, void *priv, int residue,
82 int status);
83 void umass_scsi_sense_cb(struct umass_softc *sc, void *priv, int residue,
84 int status);
85 struct umass_scsi_softc *umass_scsi_setup(struct umass_softc *);
86
87 struct scsi_device umass_scsi_dev = { NULL, NULL, NULL, NULL, };
88
89 #if NATAPISCSI > 0
90 struct scsi_device umass_atapiscsi_dev = { NULL, NULL, NULL, NULL, };
91 #endif
92
93 int
94 umass_scsi_attach(struct umass_softc *sc)
95 {
96 struct scsibus_attach_args saa;
97 struct umass_scsi_softc *scbus;
98
99 scbus = umass_scsi_setup(sc);
100 scbus->sc_link.adapter_target = UMASS_SCSIID_HOST;
101 scbus->sc_link.luns = sc->maxlun + 1;
102 scbus->sc_link.flags &= ~SDEV_ATAPI;
103 scbus->sc_link.flags |= SDEV_UMASS;
104 scbus->sc_link.device = &umass_scsi_dev;
105
106 bzero(&saa, sizeof(saa));
107 saa.saa_sc_link = &scbus->sc_link;
108
109 DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: SCSI\n"
110 "sc = 0x%x, scbus = 0x%x\n",
111 sc->sc_dev.dv_xname, sc, scbus));
112
113 sc->sc_refcnt++;
114 scbus->base.sc_child =
115 config_found((struct device *)sc, &saa, scsiprint);
116 if (--sc->sc_refcnt < 0)
117 usb_detach_wakeup(&sc->sc_dev);
118
119 return (0);
120 }
121
122 #if NATAPISCSI > 0
123 int
124 umass_atapi_attach(struct umass_softc *sc)
125 {
126 struct scsibus_attach_args saa;
127 struct umass_scsi_softc *scbus;
128
129 scbus = umass_scsi_setup(sc);
130 scbus->sc_link.adapter_target = UMASS_SCSIID_HOST;
131 scbus->sc_link.luns = 1;
132 scbus->sc_link.openings = 1;
133 scbus->sc_link.flags |= SDEV_ATAPI;
134 scbus->sc_link.device = &umass_atapiscsi_dev;
135
136 bzero(&saa, sizeof(saa));
137 saa.saa_sc_link = &scbus->sc_link;
138
139 DPRINTF(UDMASS_USB, ("%s: umass_attach_bus: ATAPI\n"
140 "sc = 0x%x, scbus = 0x%x\n",
141 sc->sc_dev.dv_xname, sc, scbus));
142
143 sc->sc_refcnt++;
144 scbus->base.sc_child = config_found((struct device *)sc,
145 &saa, scsiprint);
146 if (--sc->sc_refcnt < 0)
147 usb_detach_wakeup(&sc->sc_dev);
148
149 return (0);
150 }
151 #endif
152
153 struct umass_scsi_softc *
154 umass_scsi_setup(struct umass_softc *sc)
155 {
156 struct umass_scsi_softc *scbus;
157
158 scbus = malloc(sizeof(struct umass_scsi_softc), M_DEVBUF, M_WAITOK);
159 memset(&scbus->sc_link, 0, sizeof(struct scsi_link));
160 memset(&scbus->sc_adapter, 0, sizeof(struct scsi_adapter));
161
162 sc->bus = (struct umassbus_softc *)scbus;
163
164
165 scbus->sc_adapter.scsi_cmd = umass_scsi_cmd;
166 scbus->sc_adapter.scsi_minphys = umass_scsi_minphys;
167
168
169 scbus->sc_link.adapter_buswidth = 2;
170 scbus->sc_link.adapter = &scbus->sc_adapter;
171 scbus->sc_link.adapter_softc = sc;
172 scbus->sc_link.openings = 1;
173 scbus->sc_link.quirks |= SDEV_ONLYBIG | sc->sc_busquirks;
174
175 return (scbus);
176 }
177
178 int
179 umass_scsi_cmd(struct scsi_xfer *xs)
180 {
181 struct scsi_link *sc_link = xs->sc_link;
182 struct umass_softc *sc = sc_link->adapter_softc;
183
184 struct scsi_generic *cmd;
185 int cmdlen, dir, s;
186
187 #ifdef UMASS_DEBUG
188 microtime(&sc->tv);
189 #endif
190
191 DIF(UDMASS_UPPER, sc_link->flags |= SCSIDEBUG_LEVEL);
192
193 DPRINTF(UDMASS_CMD, ("%s: umass_scsi_cmd: at %lu.%06lu: %d:%d "
194 "xs=%p cmd=0x%02x datalen=%d (quirks=0x%x, poll=%d)\n",
195 sc->sc_dev.dv_xname, sc->tv.tv_sec, sc->tv.tv_usec,
196 sc_link->target, sc_link->lun, xs, xs->cmd->opcode,
197 xs->datalen, sc_link->quirks, xs->flags & SCSI_POLL));
198
199 #if defined(USB_DEBUG) && defined(SCSIDEBUG)
200 if (umassdebug & UDMASS_SCSI)
201 show_scsi_xs(xs);
202 else if (umassdebug & ~UDMASS_CMD)
203 show_scsi_cmd(xs);
204 #endif
205
206 if (sc->sc_dying) {
207 xs->error = XS_DRIVER_STUFFUP;
208 goto done;
209 }
210
211 #if defined(UMASS_DEBUG)
212 if (sc_link->target != UMASS_SCSIID_DEVICE) {
213 DPRINTF(UDMASS_SCSI, ("%s: wrong SCSI ID %d\n",
214 sc->sc_dev.dv_xname, sc_link->target));
215 xs->error = XS_DRIVER_STUFFUP;
216 goto done;
217 }
218 #endif
219
220 cmd = xs->cmd;
221 cmdlen = xs->cmdlen;
222
223 dir = DIR_NONE;
224 if (xs->datalen) {
225 switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
226 case SCSI_DATA_IN:
227 dir = DIR_IN;
228 break;
229 case SCSI_DATA_OUT:
230 dir = DIR_OUT;
231 break;
232 }
233 }
234
235 if (xs->datalen > UMASS_MAX_TRANSFER_SIZE) {
236 printf("umass_cmd: large datalen, %d\n", xs->datalen);
237 xs->error = XS_DRIVER_STUFFUP;
238 goto done;
239 }
240
241 if (xs->flags & SCSI_POLL) {
242 DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: sync dir=%d\n", dir));
243 usbd_set_polling(sc->sc_udev, 1);
244 sc->sc_xfer_flags = USBD_SYNCHRONOUS;
245 sc->polled_xfer_status = USBD_INVAL;
246 sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, cmdlen,
247 xs->data, xs->datalen, dir,
248 xs->timeout, umass_scsi_cb, xs);
249 sc->sc_xfer_flags = 0;
250 DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done err=%d\n",
251 sc->polled_xfer_status));
252 if (xs->error == XS_NOERROR) {
253 switch (sc->polled_xfer_status) {
254 case USBD_NORMAL_COMPLETION:
255 xs->error = XS_NOERROR;
256 break;
257 case USBD_TIMEOUT:
258 xs->error = XS_TIMEOUT;
259 break;
260 default:
261 xs->error = XS_DRIVER_STUFFUP;
262 break;
263 }
264 }
265 usbd_set_polling(sc->sc_udev, 0);
266 DPRINTF(UDMASS_SCSI, ("umass_scsi_cmd: done, error=%d\n",
267 xs->error));
268 } else {
269 DPRINTF(UDMASS_SCSI,
270 ("umass_scsi_cmd: async dir=%d, cmdlen=%d"
271 " datalen=%d\n",
272 dir, cmdlen, xs->datalen));
273 sc->sc_methods->wire_xfer(sc, sc_link->lun, cmd, cmdlen,
274 xs->data, xs->datalen, dir,
275 xs->timeout, umass_scsi_cb, xs);
276 return (SUCCESSFULLY_QUEUED);
277 }
278
279
280 done:
281 xs->flags |= ITSDONE;
282
283 s = splbio();
284 scsi_done(xs);
285 splx(s);
286 if (xs->flags & SCSI_POLL)
287 return (COMPLETE);
288 else
289 return (SUCCESSFULLY_QUEUED);
290 }
291
292 void
293 umass_scsi_minphys(struct buf *bp)
294 {
295 if (bp->b_bcount > UMASS_MAX_TRANSFER_SIZE)
296 bp->b_bcount = UMASS_MAX_TRANSFER_SIZE;
297
298 minphys(bp);
299 }
300
301 void
302 umass_scsi_cb(struct umass_softc *sc, void *priv, int residue, int status)
303 {
304 struct umass_scsi_softc *scbus = (struct umass_scsi_softc *)sc->bus;
305 struct scsi_xfer *xs = priv;
306 struct scsi_link *link = xs->sc_link;
307 int cmdlen;
308 int s;
309 #ifdef UMASS_DEBUG
310 struct timeval tv;
311 u_int delta;
312 microtime(&tv);
313 delta = (tv.tv_sec - sc->tv.tv_sec) * 1000000 +
314 tv.tv_usec - sc->tv.tv_usec;
315 #endif
316
317 DPRINTF(UDMASS_CMD,
318 ("umass_scsi_cb: at %lu.%06lu, delta=%u: xs=%p residue=%d"
319 " status=%d\n", tv.tv_sec, tv.tv_usec, delta, xs, residue,
320 status));
321
322 xs->resid = residue;
323
324 switch (status) {
325 case STATUS_CMD_OK:
326 xs->error = XS_NOERROR;
327 break;
328
329 case STATUS_CMD_UNKNOWN:
330 DPRINTF(UDMASS_CMD, ("umass_scsi_cb: status cmd unknown\n"));
331
332 if (xs->sc_link->quirks & ADEV_NOSENSE) {
333
334
335
336
337 if (residue == 0) {
338 xs->error = XS_NOERROR;
339 break;
340 }
341
342
343
344
345
346
347 if (xs->cmd->opcode == INQUIRY &&
348 residue < xs->datalen) {
349 xs->error = XS_NOERROR;
350 break;
351 }
352
353 xs->error = XS_DRIVER_STUFFUP;
354 break;
355 }
356
357 case STATUS_CMD_FAILED:
358 DPRINTF(UDMASS_CMD, ("umass_scsi_cb: status cmd failed for "
359 "scsi op 0x%02x\n", xs->cmd->opcode));
360
361 sc->sc_sense = 1;
362 memset(&scbus->sc_sense_cmd, 0, sizeof(scbus->sc_sense_cmd));
363 scbus->sc_sense_cmd.opcode = REQUEST_SENSE;
364 scbus->sc_sense_cmd.byte2 = link->lun << SCSI_CMD_LUN_SHIFT;
365 scbus->sc_sense_cmd.length = sizeof(xs->sense);
366
367 cmdlen = sizeof(scbus->sc_sense_cmd);
368 sc->sc_methods->wire_xfer(sc, link->lun,
369 &scbus->sc_sense_cmd, cmdlen,
370 &xs->sense, sizeof(xs->sense),
371 DIR_IN, xs->timeout,
372 umass_scsi_sense_cb, xs);
373 return;
374
375 case STATUS_WIRE_FAILED:
376 xs->error = XS_RESET;
377 break;
378
379 default:
380 panic("%s: Unknown status %d in umass_scsi_cb",
381 sc->sc_dev.dv_xname, status);
382 }
383
384 if (xs->flags & SCSI_POLL)
385 return;
386
387 xs->flags |= ITSDONE;
388
389 DPRINTF(UDMASS_CMD,("umass_scsi_cb: at %lu.%06lu: return error=%d, "
390 "status=0x%x resid=%d\n",
391 tv.tv_sec, tv.tv_usec,
392 xs->error, xs->status, xs->resid));
393
394 s = splbio();
395 scsi_done(xs);
396 splx(s);
397 }
398
399
400
401
402 void
403 umass_scsi_sense_cb(struct umass_softc *sc, void *priv, int residue,
404 int status)
405 {
406 struct scsi_xfer *xs = priv;
407 int s;
408
409 DPRINTF(UDMASS_CMD,("umass_scsi_sense_cb: xs=%p residue=%d "
410 "status=%d\n", xs, residue, status));
411
412 sc->sc_sense = 0;
413 switch (status) {
414 case STATUS_CMD_OK:
415 case STATUS_CMD_UNKNOWN:
416
417 if (residue == 0 || residue == 14)
418 xs->error = XS_SENSE;
419 else
420 xs->error = XS_SHORTSENSE;
421 break;
422 default:
423 DPRINTF(UDMASS_SCSI, ("%s: Autosense failed, status %d\n",
424 sc->sc_dev.dv_xname, status));
425 xs->error = XS_DRIVER_STUFFUP;
426 break;
427 }
428
429 xs->flags |= ITSDONE;
430
431 DPRINTF(UDMASS_CMD,("umass_scsi_sense_cb: return xs->error=%d, "
432 "xs->flags=0x%x xs->resid=%d\n", xs->error, xs->status,
433 xs->resid));
434
435 s = splbio();
436 scsi_done(xs);
437 splx(s);
438 }
439