Annotation of src/sys/dev/scsipi/scsipi_base.c, Revision 1.47
1.47 ! bouyer 1: /* $NetBSD: scsipi_base.c,v 1.46 2001/06/26 15:32:02 bouyer Exp $ */
1.2 bouyer 2:
1.8 mycroft 3: /*-
1.39 bouyer 4: * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
1.8 mycroft 5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
1.39 bouyer 8: * by Charles M. Hannum; by Jason R. Thorpe of the Numerical Aerospace
9: * Simulation Facility, NASA Ames Research Center.
1.2 bouyer 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: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
1.8 mycroft 21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
1.2 bouyer 26: *
1.8 mycroft 27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
1.2 bouyer 38: */
39:
1.13 bouyer 40: #include "opt_scsi.h"
41:
1.2 bouyer 42: #include <sys/types.h>
43: #include <sys/param.h>
44: #include <sys/systm.h>
45: #include <sys/kernel.h>
46: #include <sys/buf.h>
47: #include <sys/uio.h>
48: #include <sys/malloc.h>
1.6 thorpej 49: #include <sys/pool.h>
1.2 bouyer 50: #include <sys/errno.h>
51: #include <sys/device.h>
52: #include <sys/proc.h>
1.39 bouyer 53: #include <sys/kthread.h>
1.2 bouyer 54:
55: #include <dev/scsipi/scsipi_all.h>
56: #include <dev/scsipi/scsipi_disk.h>
57: #include <dev/scsipi/scsipiconf.h>
58: #include <dev/scsipi/scsipi_base.h>
59:
1.39 bouyer 60: #include <dev/scsipi/scsi_all.h>
61: #include <dev/scsipi/scsi_message.h>
62:
63: int scsipi_complete __P((struct scsipi_xfer *));
64: void scsipi_request_sense __P((struct scsipi_xfer *));
65: int scsipi_enqueue __P((struct scsipi_xfer *));
66: void scsipi_run_queue __P((struct scsipi_channel *chan));
67:
68: void scsipi_completion_thread __P((void *));
69:
70: void scsipi_get_tag __P((struct scsipi_xfer *));
71: void scsipi_put_tag __P((struct scsipi_xfer *));
72:
73: int scsipi_get_resource __P((struct scsipi_channel *));
74: void scsipi_put_resource __P((struct scsipi_channel *));
75: __inline int scsipi_grow_resources __P((struct scsipi_channel *));
76:
77: void scsipi_async_event_max_openings __P((struct scsipi_channel *,
78: struct scsipi_max_openings *));
79: void scsipi_async_event_xfer_mode __P((struct scsipi_channel *,
80: struct scsipi_xfer_mode *));
81: void scsipi_async_event_channel_reset __P((struct scsipi_channel *));
82:
1.6 thorpej 83: struct pool scsipi_xfer_pool;
84:
1.2 bouyer 85: /*
1.39 bouyer 86: * scsipi_init:
87: *
88: * Called when a scsibus or atapibus is attached to the system
89: * to initialize shared data structures.
1.6 thorpej 90: */
91: void
92: scsipi_init()
93: {
94: static int scsipi_init_done;
95:
96: if (scsipi_init_done)
97: return;
98: scsipi_init_done = 1;
99:
100: /* Initialize the scsipi_xfer pool. */
101: pool_init(&scsipi_xfer_pool, sizeof(struct scsipi_xfer), 0,
102: 0, 0, "scxspl", 0, NULL, NULL, M_DEVBUF);
103: }
104:
105: /*
1.39 bouyer 106: * scsipi_channel_init:
107: *
108: * Initialize a scsipi_channel when it is attached.
109: */
110: int
111: scsipi_channel_init(chan)
112: struct scsipi_channel *chan;
113: {
114: size_t nbytes;
115: int i;
116:
117: /* Initialize shared data. */
118: scsipi_init();
119:
120: /* Initialize the queues. */
121: TAILQ_INIT(&chan->chan_queue);
122: TAILQ_INIT(&chan->chan_complete);
123:
124: nbytes = chan->chan_ntargets * sizeof(struct scsipi_periph **);
125: chan->chan_periphs = malloc(nbytes, M_DEVBUF, M_NOWAIT);
126: if (chan->chan_periphs == NULL)
127: return (ENOMEM);
128:
129:
130: nbytes = chan->chan_nluns * sizeof(struct scsipi_periph *);
131: for (i = 0; i < chan->chan_ntargets; i++) {
132: chan->chan_periphs[i] = malloc(nbytes, M_DEVBUF, M_NOWAIT);
133: if (chan->chan_periphs[i] == NULL) {
134: while (--i >= 0) {
135: free(chan->chan_periphs[i], M_DEVBUF);
136: }
137: return (ENOMEM);
138: }
139: memset(chan->chan_periphs[i], 0, nbytes);
140: }
141:
142: /*
143: * Create the asynchronous completion thread.
144: */
145: kthread_create(scsipi_create_completion_thread, chan);
146: return (0);
147: }
148:
149: /*
150: * scsipi_channel_shutdown:
151: *
152: * Shutdown a scsipi_channel.
153: */
154: void
155: scsipi_channel_shutdown(chan)
156: struct scsipi_channel *chan;
157: {
158:
159: /*
160: * Shut down the completion thread.
161: */
162: chan->chan_flags |= SCSIPI_CHAN_SHUTDOWN;
163: wakeup(&chan->chan_complete);
164:
165: /*
166: * Now wait for the thread to exit.
167: */
168: while (chan->chan_thread != NULL)
169: (void) tsleep(&chan->chan_thread, PRIBIO, "scshut", 0);
170: }
171:
172: /*
173: * scsipi_insert_periph:
174: *
175: * Insert a periph into the channel.
176: */
177: void
178: scsipi_insert_periph(chan, periph)
179: struct scsipi_channel *chan;
180: struct scsipi_periph *periph;
181: {
182: int s;
183:
184: s = splbio();
185: chan->chan_periphs[periph->periph_target][periph->periph_lun] = periph;
186: splx(s);
187: }
188:
189: /*
190: * scsipi_remove_periph:
191: *
192: * Remove a periph from the channel.
193: */
194: void
195: scsipi_remove_periph(chan, periph)
196: struct scsipi_channel *chan;
197: struct scsipi_periph *periph;
198: {
199: int s;
200:
201: s = splbio();
202: chan->chan_periphs[periph->periph_target][periph->periph_lun] = NULL;
203: splx(s);
204: }
205:
206: /*
207: * scsipi_lookup_periph:
208: *
209: * Lookup a periph on the specified channel.
210: */
211: struct scsipi_periph *
212: scsipi_lookup_periph(chan, target, lun)
213: struct scsipi_channel *chan;
214: int target, lun;
215: {
216: struct scsipi_periph *periph;
217: int s;
218:
219: if (target >= chan->chan_ntargets ||
220: lun >= chan->chan_nluns)
221: return (NULL);
222:
223: s = splbio();
224: periph = chan->chan_periphs[target][lun];
225: splx(s);
226:
227: return (periph);
228: }
229:
230: /*
231: * scsipi_get_resource:
232: *
233: * Allocate a single xfer `resource' from the channel.
234: *
235: * NOTE: Must be called at splbio().
236: */
237: int
238: scsipi_get_resource(chan)
239: struct scsipi_channel *chan;
240: {
241: struct scsipi_adapter *adapt = chan->chan_adapter;
242:
243: if (chan->chan_flags & SCSIPI_CHAN_OPENINGS) {
244: if (chan->chan_openings > 0) {
245: chan->chan_openings--;
246: return (1);
247: }
248: return (0);
249: }
250:
251: if (adapt->adapt_openings > 0) {
252: adapt->adapt_openings--;
253: return (1);
254: }
255: return (0);
256: }
257:
258: /*
259: * scsipi_grow_resources:
260: *
261: * Attempt to grow resources for a channel. If this succeeds,
262: * we allocate one for our caller.
263: *
264: * NOTE: Must be called at splbio().
265: */
266: __inline int
267: scsipi_grow_resources(chan)
268: struct scsipi_channel *chan;
269: {
270:
271: if (chan->chan_flags & SCSIPI_CHAN_CANGROW) {
272: scsipi_adapter_request(chan, ADAPTER_REQ_GROW_RESOURCES, NULL);
273: return (scsipi_get_resource(chan));
274: }
275:
276: return (0);
277: }
278:
279: /*
280: * scsipi_put_resource:
281: *
282: * Free a single xfer `resource' to the channel.
283: *
284: * NOTE: Must be called at splbio().
285: */
286: void
287: scsipi_put_resource(chan)
288: struct scsipi_channel *chan;
289: {
290: struct scsipi_adapter *adapt = chan->chan_adapter;
291:
292: if (chan->chan_flags & SCSIPI_CHAN_OPENINGS)
293: chan->chan_openings++;
294: else
295: adapt->adapt_openings++;
296: }
297:
298: /*
299: * scsipi_get_tag:
300: *
301: * Get a tag ID for the specified xfer.
302: *
303: * NOTE: Must be called at splbio().
304: */
305: void
306: scsipi_get_tag(xs)
307: struct scsipi_xfer *xs;
308: {
309: struct scsipi_periph *periph = xs->xs_periph;
310: int word, bit, tag;
311:
312: for (word = 0; word < PERIPH_NTAGWORDS; word++) {
313: bit = ffs(periph->periph_freetags[word]);
314: if (bit != 0)
315: break;
316: }
317: #ifdef DIAGNOSTIC
318: if (word == PERIPH_NTAGWORDS) {
319: scsipi_printaddr(periph);
320: printf("no free tags\n");
321: panic("scsipi_get_tag");
322: }
323: #endif
324:
325: bit -= 1;
326: periph->periph_freetags[word] &= ~(1 << bit);
327: tag = (word << 5) | bit;
328:
329: /* XXX Should eventually disallow this completely. */
330: if (tag >= periph->periph_openings) {
331: scsipi_printaddr(periph);
332: printf("WARNING: tag %d greater than available openings %d\n",
333: tag, periph->periph_openings);
334: }
335:
336: xs->xs_tag_id = tag;
337: }
338:
339: /*
340: * scsipi_put_tag:
341: *
342: * Put the tag ID for the specified xfer back into the pool.
343: *
344: * NOTE: Must be called at splbio().
1.2 bouyer 345: */
1.39 bouyer 346: void
347: scsipi_put_tag(xs)
348: struct scsipi_xfer *xs;
349: {
350: struct scsipi_periph *periph = xs->xs_periph;
351: int word, bit;
352:
353: word = xs->xs_tag_id >> 5;
354: bit = xs->xs_tag_id & 0x1f;
355:
356: periph->periph_freetags[word] |= (1 << bit);
357: }
1.2 bouyer 358:
1.39 bouyer 359: /*
360: * scsipi_get_xs:
361: *
362: * Allocate an xfer descriptor and associate it with the
363: * specified peripherial. If the peripherial has no more
364: * available command openings, we either block waiting for
365: * one to become available, or fail.
366: */
1.2 bouyer 367: struct scsipi_xfer *
1.39 bouyer 368: scsipi_get_xs(periph, flags)
369: struct scsipi_periph *periph;
370: int flags;
1.2 bouyer 371: {
372: struct scsipi_xfer *xs;
373: int s;
374:
1.39 bouyer 375: SC_DEBUG(periph, SCSIPI_DB3, ("scsipi_get_xs\n"));
1.6 thorpej 376:
1.24 thorpej 377: /*
378: * If we're cold, make sure we poll.
379: */
380: if (cold)
381: flags |= XS_CTL_NOSLEEP | XS_CTL_POLL;
382:
1.39 bouyer 383: #ifdef DIAGNOSTIC
384: /*
385: * URGENT commands can never be ASYNC.
386: */
387: if ((flags & (XS_CTL_URGENT|XS_CTL_ASYNC)) ==
388: (XS_CTL_URGENT|XS_CTL_ASYNC)) {
389: scsipi_printaddr(periph);
390: printf("URGENT and ASYNC\n");
391: panic("scsipi_get_xs");
392: }
393: #endif
394:
1.2 bouyer 395: s = splbio();
1.39 bouyer 396: /*
397: * Wait for a command opening to become available. Rules:
398: *
399: * - All xfers must wait for an available opening.
400: * Exception: URGENT xfers can proceed when
401: * active == openings, because we use the opening
402: * of the command we're recovering for.
403: * - if the periph has sense pending, only URGENT & REQSENSE
404: * xfers may proceed.
405: *
406: * - If the periph is recovering, only URGENT xfers may
407: * proceed.
408: *
409: * - If the periph is currently executing a recovery
410: * command, URGENT commands must block, because only
411: * one recovery command can execute at a time.
412: */
413: for (;;) {
414: if (flags & XS_CTL_URGENT) {
415: if (periph->periph_active > periph->periph_openings)
416: goto wait_for_opening;
417: if (periph->periph_flags & PERIPH_SENSE) {
418: if ((flags & XS_CTL_REQSENSE) == 0)
419: goto wait_for_opening;
420: } else {
421: if ((periph->periph_flags &
422: PERIPH_RECOVERY_ACTIVE) != 0)
423: goto wait_for_opening;
424: periph->periph_flags |= PERIPH_RECOVERY_ACTIVE;
425: }
426: break;
427: }
428: if (periph->periph_active >= periph->periph_openings ||
429: (periph->periph_flags & PERIPH_RECOVERING) != 0)
430: goto wait_for_opening;
431: periph->periph_active++;
432: break;
433:
434: wait_for_opening:
435: if (flags & XS_CTL_NOSLEEP) {
1.2 bouyer 436: splx(s);
1.39 bouyer 437: return (NULL);
1.2 bouyer 438: }
1.39 bouyer 439: SC_DEBUG(periph, SCSIPI_DB3, ("sleeping\n"));
440: periph->periph_flags |= PERIPH_WAITING;
441: (void) tsleep(periph, PRIBIO, "getxs", 0);
1.2 bouyer 442: }
1.39 bouyer 443: SC_DEBUG(periph, SCSIPI_DB3, ("calling pool_get\n"));
1.6 thorpej 444: xs = pool_get(&scsipi_xfer_pool,
1.24 thorpej 445: ((flags & XS_CTL_NOSLEEP) != 0 ? PR_NOWAIT : PR_WAITOK));
1.39 bouyer 446: if (xs == NULL) {
447: if (flags & XS_CTL_URGENT) {
448: if ((flags & XS_CTL_REQSENSE) == 0)
449: periph->periph_flags &= ~PERIPH_RECOVERY_ACTIVE;
450: } else
451: periph->periph_active--;
452: scsipi_printaddr(periph);
453: printf("unable to allocate %sscsipi_xfer\n",
454: (flags & XS_CTL_URGENT) ? "URGENT " : "");
1.2 bouyer 455: }
1.6 thorpej 456: splx(s);
1.2 bouyer 457:
1.39 bouyer 458: SC_DEBUG(periph, SCSIPI_DB3, ("returning\n"));
1.6 thorpej 459:
1.7 scottr 460: if (xs != NULL) {
1.30 thorpej 461: callout_init(&xs->xs_callout);
1.39 bouyer 462: memset(xs, 0, sizeof(*xs));
463: xs->xs_periph = periph;
1.24 thorpej 464: xs->xs_control = flags;
1.37 fvdl 465: xs->xs_status = 0;
1.39 bouyer 466: s = splbio();
467: TAILQ_INSERT_TAIL(&periph->periph_xferq, xs, device_q);
468: splx(s);
1.7 scottr 469: }
1.3 enami 470: return (xs);
1.2 bouyer 471: }
472:
473: /*
1.39 bouyer 474: * scsipi_put_xs:
475: *
476: * Release an xfer descriptor, decreasing the outstanding command
477: * count for the peripherial. If there is a thread waiting for
478: * an opening, wake it up. If not, kick any queued I/O the
479: * peripherial may have.
1.6 thorpej 480: *
1.39 bouyer 481: * NOTE: Must be called at splbio().
1.2 bouyer 482: */
1.3 enami 483: void
1.39 bouyer 484: scsipi_put_xs(xs)
1.2 bouyer 485: struct scsipi_xfer *xs;
486: {
1.39 bouyer 487: struct scsipi_periph *periph = xs->xs_periph;
488: int flags = xs->xs_control;
489:
490: SC_DEBUG(periph, SCSIPI_DB3, ("scsipi_free_xs\n"));
1.2 bouyer 491:
1.39 bouyer 492: TAILQ_REMOVE(&periph->periph_xferq, xs, device_q);
493: pool_put(&scsipi_xfer_pool, xs);
494:
495: #ifdef DIAGNOSTIC
496: if ((periph->periph_flags & PERIPH_RECOVERY_ACTIVE) != 0 &&
497: periph->periph_active == 0) {
498: scsipi_printaddr(periph);
499: printf("recovery without a command to recovery for\n");
500: panic("scsipi_put_xs");
501: }
502: #endif
503:
504: if (flags & XS_CTL_URGENT) {
505: if ((flags & XS_CTL_REQSENSE) == 0)
506: periph->periph_flags &= ~PERIPH_RECOVERY_ACTIVE;
507: } else
508: periph->periph_active--;
509: if (periph->periph_active == 0 &&
510: (periph->periph_flags & PERIPH_WAITDRAIN) != 0) {
511: periph->periph_flags &= ~PERIPH_WAITDRAIN;
512: wakeup(&periph->periph_active);
1.16 thorpej 513: }
1.2 bouyer 514:
1.39 bouyer 515: if (periph->periph_flags & PERIPH_WAITING) {
516: periph->periph_flags &= ~PERIPH_WAITING;
517: wakeup(periph);
1.2 bouyer 518: } else {
1.39 bouyer 519: if (periph->periph_switch->psw_start != NULL) {
520: SC_DEBUG(periph, SCSIPI_DB2,
1.3 enami 521: ("calling private start()\n"));
1.39 bouyer 522: (*periph->periph_switch->psw_start)(periph);
1.2 bouyer 523: }
524: }
1.15 thorpej 525: }
526:
527: /*
1.39 bouyer 528: * scsipi_channel_freeze:
529: *
530: * Freeze a channel's xfer queue.
531: */
532: void
533: scsipi_channel_freeze(chan, count)
534: struct scsipi_channel *chan;
535: int count;
536: {
537: int s;
538:
539: s = splbio();
540: chan->chan_qfreeze += count;
541: splx(s);
542: }
543:
544: /*
545: * scsipi_channel_thaw:
546: *
547: * Thaw a channel's xfer queue.
548: */
549: void
550: scsipi_channel_thaw(chan, count)
551: struct scsipi_channel *chan;
552: int count;
553: {
554: int s;
555:
556: s = splbio();
557: chan->chan_qfreeze -= count;
558: /*
559: * Don't let the freeze count go negative.
560: *
561: * Presumably the adapter driver could keep track of this,
562: * but it might just be easier to do this here so as to allow
563: * multiple callers, including those outside the adapter driver.
564: */
565: if (chan->chan_qfreeze < 0) {
566: chan->chan_qfreeze = 0;
567: }
568: splx(s);
1.44 bouyer 569: /*
570: * Kick the channel's queue here. Note, we may be running in
571: * interrupt context (softclock or HBA's interrupt), so the adapter
572: * driver had better not sleep.
573: */
574: if (chan->chan_qfreeze == 0)
575: scsipi_run_queue(chan);
1.39 bouyer 576: }
577:
578: /*
579: * scsipi_channel_timed_thaw:
580: *
1.44 bouyer 581: * Thaw a channel after some time has expired. This will also
582: * run the channel's queue if the freeze count has reached 0.
1.39 bouyer 583: */
584: void
585: scsipi_channel_timed_thaw(arg)
586: void *arg;
587: {
588: struct scsipi_channel *chan = arg;
589:
590: scsipi_channel_thaw(chan, 1);
591: }
592:
593: /*
594: * scsipi_periph_freeze:
595: *
596: * Freeze a device's xfer queue.
597: */
598: void
599: scsipi_periph_freeze(periph, count)
600: struct scsipi_periph *periph;
601: int count;
602: {
603: int s;
604:
605: s = splbio();
606: periph->periph_qfreeze += count;
607: splx(s);
608: }
609:
610: /*
611: * scsipi_periph_thaw:
612: *
613: * Thaw a device's xfer queue.
614: */
615: void
616: scsipi_periph_thaw(periph, count)
617: struct scsipi_periph *periph;
618: int count;
619: {
620: int s;
621:
622: s = splbio();
623: periph->periph_qfreeze -= count;
624: if (periph->periph_qfreeze == 0 &&
625: (periph->periph_flags & PERIPH_WAITING) != 0)
626: wakeup(periph);
627: splx(s);
628: }
629:
630: /*
631: * scsipi_periph_timed_thaw:
632: *
633: * Thaw a device after some time has expired.
634: */
635: void
636: scsipi_periph_timed_thaw(arg)
637: void *arg;
638: {
639: struct scsipi_periph *periph = arg;
640:
641: callout_stop(&periph->periph_callout);
642: scsipi_periph_thaw(periph, 1);
643:
644: /*
645: * Kick the channel's queue here. Note, we're running in
646: * interrupt context (softclock), so the adapter driver
647: * had better not sleep.
648: */
649: scsipi_run_queue(periph->periph_channel);
650: }
651:
652: /*
653: * scsipi_wait_drain:
654: *
655: * Wait for a periph's pending xfers to drain.
1.15 thorpej 656: */
657: void
1.39 bouyer 658: scsipi_wait_drain(periph)
659: struct scsipi_periph *periph;
1.15 thorpej 660: {
661: int s;
662:
663: s = splbio();
1.39 bouyer 664: while (periph->periph_active != 0) {
665: periph->periph_flags |= PERIPH_WAITDRAIN;
666: (void) tsleep(&periph->periph_active, PRIBIO, "sxdrn", 0);
1.15 thorpej 667: }
668: splx(s);
1.23 thorpej 669: }
670:
671: /*
1.39 bouyer 672: * scsipi_kill_pending:
673: *
674: * Kill off all pending xfers for a periph.
1.23 thorpej 675: *
1.39 bouyer 676: * NOTE: Must be called at splbio().
1.23 thorpej 677: */
678: void
1.39 bouyer 679: scsipi_kill_pending(periph)
680: struct scsipi_periph *periph;
1.23 thorpej 681: {
682:
1.39 bouyer 683: (*periph->periph_channel->chan_bustype->bustype_kill_pending)(periph);
684: #ifdef DIAGNOSTIC
685: if (TAILQ_FIRST(&periph->periph_xferq) != NULL)
686: panic("scsipi_kill_pending");
687: #endif
688: scsipi_wait_drain(periph);
1.2 bouyer 689: }
690:
691: /*
1.39 bouyer 692: * scsipi_interpret_sense:
693: *
694: * Look at the returned sense and act on the error, determining
695: * the unix error number to pass back. (0 = report no error)
696: *
697: * NOTE: If we return ERESTART, we are expected to haved
698: * thawed the device!
1.13 bouyer 699: *
1.39 bouyer 700: * THIS IS THE DEFAULT ERROR HANDLER FOR SCSI DEVICES.
1.13 bouyer 701: */
702: int
703: scsipi_interpret_sense(xs)
704: struct scsipi_xfer *xs;
705: {
706: struct scsipi_sense_data *sense;
1.39 bouyer 707: struct scsipi_periph *periph = xs->xs_periph;
1.13 bouyer 708: u_int8_t key;
709: u_int32_t info;
710: int error;
711: #ifndef SCSIVERBOSE
712: static char *error_mes[] = {
713: "soft error (corrected)",
714: "not ready", "medium error",
715: "non-media hardware failure", "illegal request",
716: "unit attention", "readonly device",
717: "no data found", "vendor unique",
718: "copy aborted", "command aborted",
719: "search returned equal", "volume overflow",
720: "verify miscompare", "unknown error key"
721: };
722: #endif
723:
724: sense = &xs->sense.scsi_sense;
1.39 bouyer 725: #ifdef SCSIPI_DEBUG
726: if (periph->periph_flags & SCSIPI_DB1) {
1.13 bouyer 727: int count;
1.39 bouyer 728: scsipi_printaddr(periph);
729: printf(" sense debug information:\n");
730: printf("\tcode 0x%x valid 0x%x\n",
1.13 bouyer 731: sense->error_code & SSD_ERRCODE,
732: sense->error_code & SSD_ERRCODE_VALID ? 1 : 0);
1.39 bouyer 733: printf("\tseg 0x%x key 0x%x ili 0x%x eom 0x%x fmark 0x%x\n",
1.13 bouyer 734: sense->segment,
735: sense->flags & SSD_KEY,
736: sense->flags & SSD_ILI ? 1 : 0,
737: sense->flags & SSD_EOM ? 1 : 0,
738: sense->flags & SSD_FILEMARK ? 1 : 0);
1.39 bouyer 739: printf("\ninfo: 0x%x 0x%x 0x%x 0x%x followed by %d "
740: "extra bytes\n",
1.13 bouyer 741: sense->info[0],
742: sense->info[1],
743: sense->info[2],
744: sense->info[3],
745: sense->extra_len);
1.39 bouyer 746: printf("\textra: ");
1.13 bouyer 747: for (count = 0; count < ADD_BYTES_LIM(sense); count++)
748: printf("0x%x ", sense->cmd_spec_info[count]);
749: printf("\n");
750: }
1.39 bouyer 751: #endif
752:
1.13 bouyer 753: /*
1.39 bouyer 754: * If the periph has it's own error handler, call it first.
1.13 bouyer 755: * If it returns a legit error value, return that, otherwise
756: * it wants us to continue with normal error processing.
757: */
1.39 bouyer 758: if (periph->periph_switch->psw_error != NULL) {
759: SC_DEBUG(periph, SCSIPI_DB2,
1.13 bouyer 760: ("calling private err_handler()\n"));
1.39 bouyer 761: error = (*periph->periph_switch->psw_error)(xs);
762: if (error != EJUSTRETURN)
763: return (error);
1.13 bouyer 764: }
765: /* otherwise use the default */
766: switch (sense->error_code & SSD_ERRCODE) {
767: /*
768: * If it's code 70, use the extended stuff and
769: * interpret the key
770: */
771: case 0x71: /* delayed error */
1.39 bouyer 772: scsipi_printaddr(periph);
1.13 bouyer 773: key = sense->flags & SSD_KEY;
774: printf(" DEFERRED ERROR, key = 0x%x\n", key);
775: /* FALLTHROUGH */
776: case 0x70:
777: if ((sense->error_code & SSD_ERRCODE_VALID) != 0)
778: info = _4btol(sense->info);
779: else
780: info = 0;
781: key = sense->flags & SSD_KEY;
782:
783: switch (key) {
784: case SKEY_NO_SENSE:
785: case SKEY_RECOVERED_ERROR:
786: if (xs->resid == xs->datalen && xs->datalen) {
787: /*
788: * Why is this here?
789: */
790: xs->resid = 0; /* not short read */
791: }
792: case SKEY_EQUAL:
793: error = 0;
794: break;
795: case SKEY_NOT_READY:
1.39 bouyer 796: if ((periph->periph_flags & PERIPH_REMOVABLE) != 0)
797: periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
1.24 thorpej 798: if ((xs->xs_control & XS_CTL_IGNORE_NOT_READY) != 0)
1.13 bouyer 799: return (0);
1.19 bouyer 800: if (sense->add_sense_code == 0x3A &&
1.46 bouyer 801: sense->add_sense_code_qual == 0x00) {
1.19 bouyer 802: error = ENODEV; /* Medium not present */
1.46 bouyer 803: if (xs->xs_control & XS_CTL_SILENT_NODEV)
804: return (error);
805: } else
1.19 bouyer 806: error = EIO;
1.24 thorpej 807: if ((xs->xs_control & XS_CTL_SILENT) != 0)
1.19 bouyer 808: return (error);
1.13 bouyer 809: break;
810: case SKEY_ILLEGAL_REQUEST:
1.24 thorpej 811: if ((xs->xs_control &
812: XS_CTL_IGNORE_ILLEGAL_REQUEST) != 0)
1.13 bouyer 813: return (0);
1.24 thorpej 814: /*
815: * Handle the case where a device reports
816: * Logical Unit Not Supported during discovery.
817: */
818: if ((xs->xs_control & XS_CTL_DISCOVERY) != 0 &&
819: sense->add_sense_code == 0x25 &&
820: sense->add_sense_code_qual == 0x00)
821: return (EINVAL);
822: if ((xs->xs_control & XS_CTL_SILENT) != 0)
1.13 bouyer 823: return (EIO);
824: error = EINVAL;
825: break;
826: case SKEY_UNIT_ATTENTION:
1.20 bouyer 827: if (sense->add_sense_code == 0x29 &&
1.39 bouyer 828: sense->add_sense_code_qual == 0x00) {
829: /* device or bus reset */
830: return (ERESTART);
831: }
832: if ((periph->periph_flags & PERIPH_REMOVABLE) != 0)
833: periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
1.24 thorpej 834: if ((xs->xs_control &
835: XS_CTL_IGNORE_MEDIA_CHANGE) != 0 ||
1.13 bouyer 836: /* XXX Should reupload any transient state. */
1.39 bouyer 837: (periph->periph_flags &
838: PERIPH_REMOVABLE) == 0) {
1.13 bouyer 839: return (ERESTART);
1.39 bouyer 840: }
1.24 thorpej 841: if ((xs->xs_control & XS_CTL_SILENT) != 0)
1.13 bouyer 842: return (EIO);
843: error = EIO;
844: break;
845: case SKEY_WRITE_PROTECT:
846: error = EROFS;
847: break;
848: case SKEY_BLANK_CHECK:
849: error = 0;
850: break;
851: case SKEY_ABORTED_COMMAND:
852: error = ERESTART;
853: break;
854: case SKEY_VOLUME_OVERFLOW:
855: error = ENOSPC;
856: break;
857: default:
858: error = EIO;
859: break;
860: }
861:
862: #ifdef SCSIVERBOSE
1.32 augustss 863: if (key && (xs->xs_control & XS_CTL_SILENT) == 0)
1.13 bouyer 864: scsipi_print_sense(xs, 0);
865: #else
866: if (key) {
1.39 bouyer 867: scsipi_printaddr(periph);
1.13 bouyer 868: printf("%s", error_mes[key - 1]);
869: if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
870: switch (key) {
871: case SKEY_NOT_READY:
872: case SKEY_ILLEGAL_REQUEST:
873: case SKEY_UNIT_ATTENTION:
874: case SKEY_WRITE_PROTECT:
875: break;
876: case SKEY_BLANK_CHECK:
877: printf(", requested size: %d (decimal)",
878: info);
879: break;
880: case SKEY_ABORTED_COMMAND:
1.39 bouyer 881: if (xs->xs_retries)
1.13 bouyer 882: printf(", retrying");
883: printf(", cmd 0x%x, info 0x%x",
884: xs->cmd->opcode, info);
885: break;
886: default:
887: printf(", info = %d (decimal)", info);
888: }
889: }
890: if (sense->extra_len != 0) {
891: int n;
892: printf(", data =");
893: for (n = 0; n < sense->extra_len; n++)
894: printf(" %02x",
895: sense->cmd_spec_info[n]);
896: }
897: printf("\n");
898: }
899: #endif
900: return (error);
901:
902: /*
903: * Not code 70, just report it
904: */
905: default:
1.39 bouyer 906: #if defined(SCSIDEBUG) || defined(DEBUG)
1.28 mjacob 907: {
908: static char *uc = "undecodable sense error";
909: int i;
910: u_int8_t *cptr = (u_int8_t *) sense;
1.39 bouyer 911: scsipi_printaddr(periph);
1.28 mjacob 912: if (xs->cmd == &xs->cmdstore) {
913: printf("%s for opcode 0x%x, data=",
914: uc, xs->cmdstore.opcode);
915: } else {
916: printf("%s, data=", uc);
917: }
918: for (i = 0; i < sizeof (sense); i++)
919: printf(" 0x%02x", *(cptr++) & 0xff);
920: printf("\n");
921: }
922: #else
1.39 bouyer 923:
924: scsipi_printaddr(periph);
1.17 mjacob 925: printf("Sense Error Code 0x%x",
926: sense->error_code & SSD_ERRCODE);
1.13 bouyer 927: if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
928: struct scsipi_sense_data_unextended *usense =
929: (struct scsipi_sense_data_unextended *)sense;
930: printf(" at block no. %d (decimal)",
931: _3btol(usense->block));
932: }
933: printf("\n");
1.28 mjacob 934: #endif
1.13 bouyer 935: return (EIO);
936: }
937: }
938:
939: /*
1.39 bouyer 940: * scsipi_size:
941: *
942: * Find out from the device what its capacity is.
1.2 bouyer 943: */
944: u_long
1.39 bouyer 945: scsipi_size(periph, flags)
946: struct scsipi_periph *periph;
1.2 bouyer 947: int flags;
948: {
949: struct scsipi_read_cap_data rdcap;
950: struct scsipi_read_capacity scsipi_cmd;
951:
952: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
953: scsipi_cmd.opcode = READ_CAPACITY;
954:
955: /*
956: * If the command works, interpret the result as a 4 byte
957: * number of blocks
958: */
1.39 bouyer 959: if (scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
1.3 enami 960: sizeof(scsipi_cmd), (u_char *)&rdcap, sizeof(rdcap),
1.38 enami 961: SCSIPIRETRIES, 20000, NULL,
962: flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK) != 0) {
1.39 bouyer 963: scsipi_printaddr(periph);
1.2 bouyer 964: printf("could not get size\n");
1.3 enami 965: return (0);
1.2 bouyer 966: }
967:
1.3 enami 968: return (_4btol(rdcap.addr) + 1);
1.2 bouyer 969: }
970:
971: /*
1.39 bouyer 972: * scsipi_test_unit_ready:
973: *
974: * Issue a `test unit ready' request.
1.2 bouyer 975: */
1.3 enami 976: int
1.39 bouyer 977: scsipi_test_unit_ready(periph, flags)
978: struct scsipi_periph *periph;
1.2 bouyer 979: int flags;
980: {
981: struct scsipi_test_unit_ready scsipi_cmd;
982:
983: /* some ATAPI drives don't support TEST_UNIT_READY. Sigh */
1.39 bouyer 984: if (periph->periph_quirks & PQUIRK_NOTUR)
1.3 enami 985: return (0);
1.2 bouyer 986:
987: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
988: scsipi_cmd.opcode = TEST_UNIT_READY;
989:
1.39 bouyer 990: return (scsipi_command(periph,
1.3 enami 991: (struct scsipi_generic *)&scsipi_cmd, sizeof(scsipi_cmd),
1.29 bouyer 992: 0, 0, SCSIPIRETRIES, 10000, NULL, flags));
1.2 bouyer 993: }
994:
995: /*
1.39 bouyer 996: * scsipi_inquire:
997: *
998: * Ask the device about itself.
1.2 bouyer 999: */
1.3 enami 1000: int
1.39 bouyer 1001: scsipi_inquire(periph, inqbuf, flags)
1002: struct scsipi_periph *periph;
1.2 bouyer 1003: struct scsipi_inquiry_data *inqbuf;
1004: int flags;
1005: {
1006: struct scsipi_inquiry scsipi_cmd;
1007:
1008: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1009: scsipi_cmd.opcode = INQUIRY;
1010: scsipi_cmd.length = sizeof(struct scsipi_inquiry_data);
1011:
1.39 bouyer 1012: return (scsipi_command(periph,
1.3 enami 1013: (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
1014: (u_char *) inqbuf, sizeof(struct scsipi_inquiry_data),
1.29 bouyer 1015: SCSIPIRETRIES, 10000, NULL, XS_CTL_DATA_IN | flags));
1.2 bouyer 1016: }
1017:
1018: /*
1.39 bouyer 1019: * scsipi_prevent:
1020: *
1021: * Prevent or allow the user to remove the media
1.2 bouyer 1022: */
1.3 enami 1023: int
1.39 bouyer 1024: scsipi_prevent(periph, type, flags)
1025: struct scsipi_periph *periph;
1.2 bouyer 1026: int type, flags;
1027: {
1028: struct scsipi_prevent scsipi_cmd;
1029:
1.39 bouyer 1030: if (periph->periph_quirks & PQUIRK_NODOORLOCK)
1.3 enami 1031: return (0);
1.2 bouyer 1032:
1033: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1034: scsipi_cmd.opcode = PREVENT_ALLOW;
1035: scsipi_cmd.how = type;
1.39 bouyer 1036:
1037: return (scsipi_command(periph,
1.3 enami 1038: (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
1.29 bouyer 1039: 0, 0, SCSIPIRETRIES, 5000, NULL, flags));
1.2 bouyer 1040: }
1041:
1042: /*
1.39 bouyer 1043: * scsipi_start:
1044: *
1045: * Send a START UNIT.
1.2 bouyer 1046: */
1.3 enami 1047: int
1.39 bouyer 1048: scsipi_start(periph, type, flags)
1049: struct scsipi_periph *periph;
1.2 bouyer 1050: int type, flags;
1051: {
1052: struct scsipi_start_stop scsipi_cmd;
1.18 bouyer 1053:
1.39 bouyer 1054: if (periph->periph_quirks & PQUIRK_NOSTARTUNIT)
1.18 bouyer 1055: return 0;
1.2 bouyer 1056:
1057: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1058: scsipi_cmd.opcode = START_STOP;
1059: scsipi_cmd.byte2 = 0x00;
1060: scsipi_cmd.how = type;
1.39 bouyer 1061:
1062: return (scsipi_command(periph,
1.3 enami 1063: (struct scsipi_generic *) &scsipi_cmd, sizeof(scsipi_cmd),
1.29 bouyer 1064: 0, 0, SCSIPIRETRIES, (type & SSS_START) ? 60000 : 10000,
1065: NULL, flags));
1.41 bouyer 1066: }
1067:
1068: /*
1069: * scsipi_mode_sense, scsipi_mode_sense_big:
1070: * get a sense page from a device
1071: */
1072:
1073: int
1074: scsipi_mode_sense(periph, byte2, page, data, len, flags, retries, timeout)
1075: struct scsipi_periph *periph;
1076: int byte2, page, len, flags, retries, timeout;
1077: struct scsipi_mode_header *data;
1078: {
1079: struct scsipi_mode_sense scsipi_cmd;
1080: int error;
1081:
1082: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1083: scsipi_cmd.opcode = MODE_SENSE;
1084: scsipi_cmd.byte2 = byte2;
1085: scsipi_cmd.page = page;
1086: if (scsipi_periph_bustype(periph) == SCSIPI_BUSTYPE_ATAPI)
1087: _lto2b(len, scsipi_cmd.u_len.atapi.length);
1088: else
1089: scsipi_cmd.u_len.scsi.length = len & 0xff;
1090: error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
1091: sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
1092: flags | XS_CTL_DATA_IN);
1093: SC_DEBUG(periph, SCSIPI_DB2,
1094: ("scsipi_mode_sense: error=%d\n", error));
1095: return (error);
1096: }
1097:
1098: int
1099: scsipi_mode_sense_big(periph, byte2, page, data, len, flags, retries, timeout)
1100: struct scsipi_periph *periph;
1101: int byte2, page, len, flags, retries, timeout;
1102: struct scsipi_mode_header_big *data;
1103: {
1104: struct scsipi_mode_sense_big scsipi_cmd;
1105: int error;
1106:
1107: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1108: scsipi_cmd.opcode = MODE_SENSE_BIG;
1109: scsipi_cmd.byte2 = byte2;
1110: scsipi_cmd.page = page;
1111: _lto2b(len, scsipi_cmd.length);
1112: error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
1113: sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
1114: flags | XS_CTL_DATA_IN);
1115: SC_DEBUG(periph, SCSIPI_DB2,
1116: ("scsipi_mode_sense_big: error=%d\n", error));
1117: return (error);
1118: }
1119:
1120: int
1121: scsipi_mode_select(periph, byte2, data, len, flags, retries, timeout)
1122: struct scsipi_periph *periph;
1123: int byte2, len, flags, retries, timeout;
1124: struct scsipi_mode_header *data;
1125: {
1126: struct scsipi_mode_select scsipi_cmd;
1127: int error;
1128:
1129: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1130: scsipi_cmd.opcode = MODE_SELECT;
1131: scsipi_cmd.byte2 = byte2;
1132: if (scsipi_periph_bustype(periph) == SCSIPI_BUSTYPE_ATAPI)
1133: _lto2b(len, scsipi_cmd.u_len.atapi.length);
1134: else
1135: scsipi_cmd.u_len.scsi.length = len & 0xff;
1136: error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
1137: sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
1138: flags | XS_CTL_DATA_OUT);
1139: SC_DEBUG(periph, SCSIPI_DB2,
1140: ("scsipi_mode_select: error=%d\n", error));
1141: return (error);
1142: }
1143:
1144: int
1145: scsipi_mode_select_big(periph, byte2, data, len, flags, retries, timeout)
1146: struct scsipi_periph *periph;
1147: int byte2, len, flags, retries, timeout;
1148: struct scsipi_mode_header_big *data;
1149: {
1150: struct scsipi_mode_select_big scsipi_cmd;
1151: int error;
1152:
1153: bzero(&scsipi_cmd, sizeof(scsipi_cmd));
1154: scsipi_cmd.opcode = MODE_SELECT_BIG;
1155: scsipi_cmd.byte2 = byte2;
1156: _lto2b(len, scsipi_cmd.length);
1157: error = scsipi_command(periph, (struct scsipi_generic *)&scsipi_cmd,
1158: sizeof(scsipi_cmd), (void *)data, len, retries, timeout, NULL,
1159: flags | XS_CTL_DATA_OUT);
1160: SC_DEBUG(periph, SCSIPI_DB2,
1161: ("scsipi_mode_select: error=%d\n", error));
1162: return (error);
1.2 bouyer 1163: }
1164:
1165: /*
1.39 bouyer 1166: * scsipi_done:
1167: *
1168: * This routine is called by an adapter's interrupt handler when
1169: * an xfer is completed.
1.2 bouyer 1170: */
1.3 enami 1171: void
1.2 bouyer 1172: scsipi_done(xs)
1173: struct scsipi_xfer *xs;
1174: {
1.39 bouyer 1175: struct scsipi_periph *periph = xs->xs_periph;
1176: struct scsipi_channel *chan = periph->periph_channel;
1177: int s, freezecnt;
1178:
1179: SC_DEBUG(periph, SCSIPI_DB2, ("scsipi_done\n"));
1180: #ifdef SCSIPI_DEBUG
1181: if (periph->periph_dbflags & SCSIPI_DB1)
1182: show_scsipi_cmd(xs);
1183: #endif
1184:
1185: s = splbio();
1186: /*
1187: * The resource this command was using is now free.
1188: */
1189: scsipi_put_resource(chan);
1190: xs->xs_periph->periph_sent--;
1191:
1192: /*
1193: * If the command was tagged, free the tag.
1194: */
1195: if (XS_CTL_TAGTYPE(xs) != 0)
1196: scsipi_put_tag(xs);
1197: else
1198: periph->periph_flags &= ~PERIPH_UNTAG;
1199:
1200: /* Mark the command as `done'. */
1201: xs->xs_status |= XS_STS_DONE;
1202:
1203: #ifdef DIAGNOSTIC
1204: if ((xs->xs_control & (XS_CTL_ASYNC|XS_CTL_POLL)) ==
1205: (XS_CTL_ASYNC|XS_CTL_POLL))
1206: panic("scsipi_done: ASYNC and POLL");
1207: #endif
1208:
1209: /*
1210: * If the xfer had an error of any sort, freeze the
1211: * periph's queue. Freeze it again if we were requested
1212: * to do so in the xfer.
1213: */
1214: freezecnt = 0;
1215: if (xs->error != XS_NOERROR)
1216: freezecnt++;
1217: if (xs->xs_control & XS_CTL_FREEZE_PERIPH)
1218: freezecnt++;
1219: if (freezecnt != 0)
1220: scsipi_periph_freeze(periph, freezecnt);
1221:
1222: /*
1223: * record the xfer with a pending sense, in case a SCSI reset is
1224: * received before the thread is waked up.
1225: */
1226: if (xs->error == XS_BUSY && xs->status == SCSI_CHECK) {
1227: periph->periph_flags |= PERIPH_SENSE;
1228: periph->periph_xscheck = xs;
1229: }
1230:
1231: /*
1232: * If this was an xfer that was not to complete asynchrnously,
1233: * let the requesting thread perform error checking/handling
1234: * in its context.
1235: */
1236: if ((xs->xs_control & XS_CTL_ASYNC) == 0) {
1237: splx(s);
1238: /*
1239: * If it's a polling job, just return, to unwind the
1240: * call graph. We don't need to restart the queue,
1241: * because pollings jobs are treated specially, and
1242: * are really only used during crash dumps anyway
1243: * (XXX or during boot-time autconfiguration of
1244: * ATAPI devices).
1245: */
1246: if (xs->xs_control & XS_CTL_POLL)
1247: return;
1248: wakeup(xs);
1249: goto out;
1250: }
1251:
1252: /*
1253: * Catch the extremely common case of I/O completing
1254: * without error; no use in taking a context switch
1255: * if we can handle it in interrupt context.
1256: */
1257: if (xs->error == XS_NOERROR) {
1258: splx(s);
1259: (void) scsipi_complete(xs);
1260: goto out;
1261: }
1262:
1263: /*
1264: * There is an error on this xfer. Put it on the channel's
1265: * completion queue, and wake up the completion thread.
1266: */
1267: TAILQ_INSERT_TAIL(&chan->chan_complete, xs, channel_q);
1268: splx(s);
1269: wakeup(&chan->chan_complete);
1270:
1271: out:
1272: /*
1273: * If there are more xfers on the channel's queue, attempt to
1274: * run them.
1275: */
1276: scsipi_run_queue(chan);
1277: }
1278:
1279: /*
1280: * scsipi_complete:
1281: *
1282: * Completion of a scsipi_xfer. This is the guts of scsipi_done().
1283: *
1284: * NOTE: This routine MUST be called with valid thread context
1285: * except for the case where the following two conditions are
1286: * true:
1287: *
1288: * xs->error == XS_NOERROR
1289: * XS_CTL_ASYNC is set in xs->xs_control
1290: *
1291: * The semantics of this routine can be tricky, so here is an
1292: * explanation:
1293: *
1294: * 0 Xfer completed successfully.
1295: *
1296: * ERESTART Xfer had an error, but was restarted.
1297: *
1298: * anything else Xfer had an error, return value is Unix
1299: * errno.
1300: *
1301: * If the return value is anything but ERESTART:
1302: *
1303: * - If XS_CTL_ASYNC is set, `xs' has been freed back to
1304: * the pool.
1305: * - If there is a buf associated with the xfer,
1306: * it has been biodone()'d.
1307: */
1308: int
1309: scsipi_complete(xs)
1310: struct scsipi_xfer *xs;
1311: {
1312: struct scsipi_periph *periph = xs->xs_periph;
1313: struct scsipi_channel *chan = periph->periph_channel;
1.2 bouyer 1314: struct buf *bp;
1.31 enami 1315: int error, s;
1.2 bouyer 1316:
1.39 bouyer 1317: #ifdef DIAGNOSTIC
1318: if ((xs->xs_control & XS_CTL_ASYNC) != 0 && xs->bp == NULL)
1319: panic("scsipi_complete: XS_CTL_ASYNC but no buf");
1320: #endif
1321: /*
1322: * If command terminated with a CHECK CONDITION, we need to issue a
1323: * REQUEST_SENSE command. Once the REQUEST_SENSE has been processed
1324: * we'll have the real status.
1325: * Must be processed at splbio() to avoid missing a SCSI bus reset
1326: * for this command.
1327: */
1328: s = splbio();
1329: if (xs->error == XS_BUSY && xs->status == SCSI_CHECK) {
1330: /* request sense for a request sense ? */
1331: if (xs->xs_control & XS_CTL_REQSENSE) {
1332: scsipi_printaddr(periph);
1.47 ! bouyer 1333: printf("request sense for a request sense ?\n");
1.39 bouyer 1334: /* XXX maybe we should reset the device ? */
1335: /* we've been frozen because xs->error != XS_NOERROR */
1336: scsipi_periph_thaw(periph, 1);
1337: splx(s);
1.47 ! bouyer 1338: if (xs->resid < xs->datalen) {
! 1339: printf("we read %d bytes of sense anyway:\n",
! 1340: xs->datalen - xs->resid);
! 1341: scsipi_print_sense_data((void *)xs->data, 0);
! 1342: }
1.39 bouyer 1343: return EINVAL;
1344: }
1345: scsipi_request_sense(xs);
1346: }
1347: splx(s);
1.2 bouyer 1348: /*
1.3 enami 1349: * If it's a user level request, bypass all usual completion
1.39 bouyer 1350: * processing, let the user work it out..
1.3 enami 1351: */
1.24 thorpej 1352: if ((xs->xs_control & XS_CTL_USERCMD) != 0) {
1.39 bouyer 1353: SC_DEBUG(periph, SCSIPI_DB3, ("calling user done()\n"));
1354: if (xs->error != XS_NOERROR)
1355: scsipi_periph_thaw(periph, 1);
1356: scsipi_user_done(xs);
1357: SC_DEBUG(periph, SCSIPI_DB3, ("returned from user done()\n "));
1358: return 0;
1359: }
1360:
1361:
1362: switch (xs->error) {
1363: case XS_NOERROR:
1364: error = 0;
1365: break;
1366:
1367: case XS_SENSE:
1368: case XS_SHORTSENSE:
1369: error = (*chan->chan_bustype->bustype_interpret_sense)(xs);
1370: break;
1.2 bouyer 1371:
1.39 bouyer 1372: case XS_RESOURCE_SHORTAGE:
1.9 scottr 1373: /*
1.39 bouyer 1374: * XXX Should freeze channel's queue.
1375: */
1376: scsipi_printaddr(periph);
1377: printf("adapter resource shortage\n");
1378: /* FALLTHROUGH */
1379:
1380: case XS_BUSY:
1381: if (xs->error == XS_BUSY && xs->status == SCSI_QUEUE_FULL) {
1382: struct scsipi_max_openings mo;
1383:
1384: /*
1385: * We set the openings to active - 1, assuming that
1386: * the command that got us here is the first one that
1387: * can't fit into the device's queue. If that's not
1388: * the case, I guess we'll find out soon enough.
1389: */
1390: mo.mo_target = periph->periph_target;
1391: mo.mo_lun = periph->periph_lun;
1.42 bouyer 1392: if (periph->periph_active < periph->periph_openings)
1393: mo.mo_openings = periph->periph_active - 1;
1394: else
1395: mo.mo_openings = periph->periph_openings - 1;
1.39 bouyer 1396: #ifdef DIAGNOSTIC
1397: if (mo.mo_openings < 0) {
1398: scsipi_printaddr(periph);
1399: printf("QUEUE FULL resulted in < 0 openings\n");
1400: panic("scsipi_done");
1401: }
1402: #endif
1403: if (mo.mo_openings == 0) {
1404: scsipi_printaddr(periph);
1405: printf("QUEUE FULL resulted in 0 openings\n");
1406: mo.mo_openings = 1;
1407: }
1408: scsipi_async_event(chan, ASYNC_EVENT_MAX_OPENINGS, &mo);
1409: error = ERESTART;
1410: } else if (xs->xs_retries != 0) {
1411: xs->xs_retries--;
1412: /*
1413: * Wait one second, and try again.
1414: */
1415: if (xs->xs_control & XS_CTL_POLL)
1416: delay(1000000);
1417: else {
1418: scsipi_periph_freeze(periph, 1);
1419: callout_reset(&periph->periph_callout,
1420: hz, scsipi_periph_timed_thaw, periph);
1421: }
1422: error = ERESTART;
1423: } else
1424: error = EBUSY;
1425: break;
1426:
1427: case XS_REQUEUE:
1428: error = ERESTART;
1429: break;
1430:
1431: case XS_TIMEOUT:
1432: if (xs->xs_retries != 0) {
1433: xs->xs_retries--;
1434: error = ERESTART;
1435: } else
1436: error = EIO;
1437: break;
1438:
1439: case XS_SELTIMEOUT:
1440: /* XXX Disable device? */
1441: error = EIO;
1442: break;
1443:
1444: case XS_RESET:
1445: if (xs->xs_control & XS_CTL_REQSENSE) {
1446: /*
1447: * request sense interrupted by reset: signal it
1448: * with EINTR return code.
1449: */
1450: error = EINTR;
1451: } else {
1452: if (xs->xs_retries != 0) {
1453: xs->xs_retries--;
1454: error = ERESTART;
1455: } else
1456: error = EIO;
1.31 enami 1457: }
1.39 bouyer 1458: break;
1459:
1460: default:
1461: scsipi_printaddr(periph);
1462: printf("invalid return code from adapter: %d\n", xs->error);
1463: error = EIO;
1464: break;
1.2 bouyer 1465: }
1466:
1.39 bouyer 1467: s = splbio();
1468: if (error == ERESTART) {
1.2 bouyer 1469: /*
1.39 bouyer 1470: * If we get here, the periph has been thawed and frozen
1471: * again if we had to issue recovery commands. Alternatively,
1472: * it may have been frozen again and in a timed thaw. In
1473: * any case, we thaw the periph once we re-enqueue the
1474: * command. Once the periph is fully thawed, it will begin
1475: * operation again.
1.2 bouyer 1476: */
1.39 bouyer 1477: xs->error = XS_NOERROR;
1478: xs->status = SCSI_OK;
1479: xs->xs_status &= ~XS_STS_DONE;
1480: xs->xs_requeuecnt++;
1481: error = scsipi_enqueue(xs);
1482: if (error == 0) {
1483: scsipi_periph_thaw(periph, 1);
1484: splx(s);
1485: return (ERESTART);
1486: }
1.2 bouyer 1487: }
1488:
1489: /*
1.39 bouyer 1490: * scsipi_done() freezes the queue if not XS_NOERROR.
1491: * Thaw it here.
1.2 bouyer 1492: */
1.39 bouyer 1493: if (xs->error != XS_NOERROR)
1494: scsipi_periph_thaw(periph, 1);
1.2 bouyer 1495:
1.40 bouyer 1496:
1497: if (periph->periph_switch->psw_done)
1498: periph->periph_switch->psw_done(xs);
1.39 bouyer 1499: if ((bp = xs->bp) != NULL) {
1.2 bouyer 1500: if (error) {
1501: bp->b_error = error;
1502: bp->b_flags |= B_ERROR;
1503: bp->b_resid = bp->b_bcount;
1504: } else {
1505: bp->b_error = 0;
1506: bp->b_resid = xs->resid;
1507: }
1.39 bouyer 1508: biodone(bp);
1.2 bouyer 1509: }
1.39 bouyer 1510:
1511: if (xs->xs_control & XS_CTL_ASYNC)
1512: scsipi_put_xs(xs);
1513: splx(s);
1514:
1515: return (error);
1516: }
1517:
1518: /*
1519: * Issue a request sense for the given scsipi_xfer. Called when the xfer
1520: * returns with a CHECK_CONDITION status. Must be called in valid thread
1521: * context and at splbio().
1522: */
1523:
1524: void
1525: scsipi_request_sense(xs)
1526: struct scsipi_xfer *xs;
1527: {
1528: struct scsipi_periph *periph = xs->xs_periph;
1529: int flags, error;
1530: struct scsipi_sense cmd;
1531:
1532: periph->periph_flags |= PERIPH_SENSE;
1533:
1534: /* if command was polling, request sense will too */
1535: flags = xs->xs_control & XS_CTL_POLL;
1536: /* Polling commands can't sleep */
1537: if (flags)
1538: flags |= XS_CTL_NOSLEEP;
1539:
1540: flags |= XS_CTL_REQSENSE | XS_CTL_URGENT | XS_CTL_DATA_IN |
1541: XS_CTL_THAW_PERIPH | XS_CTL_FREEZE_PERIPH;
1542:
1543: bzero(&cmd, sizeof(cmd));
1544: cmd.opcode = REQUEST_SENSE;
1545: cmd.length = sizeof(struct scsipi_sense_data);
1546:
1547: error = scsipi_command(periph,
1548: (struct scsipi_generic *) &cmd, sizeof(cmd),
1549: (u_char*)&xs->sense.scsi_sense, sizeof(struct scsipi_sense_data),
1550: 0, 1000, NULL, flags);
1551: periph->periph_flags &= ~PERIPH_SENSE;
1552: periph->periph_xscheck = NULL;
1553: switch(error) {
1554: case 0:
1555: /* we have a valid sense */
1556: xs->error = XS_SENSE;
1557: return;
1558: case EINTR:
1559: /* REQUEST_SENSE interrupted by bus reset. */
1560: xs->error = XS_RESET;
1561: return;
1562: case EIO:
1563: /* request sense coudn't be performed */
1.2 bouyer 1564: /*
1.39 bouyer 1565: * XXX this isn't quite rigth but we don't have anything
1566: * better for now
1.2 bouyer 1567: */
1.39 bouyer 1568: xs->error = XS_DRIVER_STUFFUP;
1569: return;
1570: default:
1571: /* Notify that request sense failed. */
1572: xs->error = XS_DRIVER_STUFFUP;
1573: scsipi_printaddr(periph);
1574: printf("request sense failed with error %d\n", error);
1575: return;
1576: }
1577: }
1578:
1579: /*
1580: * scsipi_enqueue:
1581: *
1582: * Enqueue an xfer on a channel.
1583: */
1584: int
1585: scsipi_enqueue(xs)
1586: struct scsipi_xfer *xs;
1587: {
1588: struct scsipi_channel *chan = xs->xs_periph->periph_channel;
1589: struct scsipi_xfer *qxs;
1590: int s;
1591:
1592: s = splbio();
1593:
1594: /*
1595: * If the xfer is to be polled, and there are already jobs on
1596: * the queue, we can't proceed.
1597: */
1598: if ((xs->xs_control & XS_CTL_POLL) != 0 &&
1599: TAILQ_FIRST(&chan->chan_queue) != NULL) {
1600: splx(s);
1601: xs->error = XS_DRIVER_STUFFUP;
1602: return (EAGAIN);
1.2 bouyer 1603: }
1.39 bouyer 1604:
1.9 scottr 1605: /*
1.39 bouyer 1606: * If we have an URGENT xfer, it's an error recovery command
1607: * and it should just go on the head of the channel's queue.
1.9 scottr 1608: */
1.39 bouyer 1609: if (xs->xs_control & XS_CTL_URGENT) {
1610: TAILQ_INSERT_HEAD(&chan->chan_queue, xs, channel_q);
1611: goto out;
1612: }
1613:
1614: /*
1615: * If this xfer has already been on the queue before, we
1616: * need to reinsert it in the correct order. That order is:
1617: *
1618: * Immediately before the first xfer for this periph
1619: * with a requeuecnt less than xs->xs_requeuecnt.
1620: *
1621: * Failing that, at the end of the queue. (We'll end up
1622: * there naturally.)
1623: */
1624: if (xs->xs_requeuecnt != 0) {
1625: for (qxs = TAILQ_FIRST(&chan->chan_queue); qxs != NULL;
1626: qxs = TAILQ_NEXT(qxs, channel_q)) {
1627: if (qxs->xs_periph == xs->xs_periph &&
1628: qxs->xs_requeuecnt < xs->xs_requeuecnt)
1629: break;
1630: }
1631: if (qxs != NULL) {
1632: TAILQ_INSERT_AFTER(&chan->chan_queue, qxs, xs,
1633: channel_q);
1634: goto out;
1635: }
1636: }
1637: TAILQ_INSERT_TAIL(&chan->chan_queue, xs, channel_q);
1638: out:
1639: if (xs->xs_control & XS_CTL_THAW_PERIPH)
1640: scsipi_periph_thaw(xs->xs_periph, 1);
1641: splx(s);
1642: return (0);
1643: }
1644:
1645: /*
1646: * scsipi_run_queue:
1647: *
1648: * Start as many xfers as possible running on the channel.
1649: */
1650: void
1651: scsipi_run_queue(chan)
1652: struct scsipi_channel *chan;
1653: {
1654: struct scsipi_xfer *xs;
1655: struct scsipi_periph *periph;
1656: int s;
1657:
1658: for (;;) {
1.31 enami 1659: s = splbio();
1.39 bouyer 1660:
1661: /*
1662: * If the channel is frozen, we can't do any work right
1663: * now.
1664: */
1665: if (chan->chan_qfreeze != 0) {
1666: splx(s);
1667: return;
1668: }
1669:
1670: /*
1671: * Look for work to do, and make sure we can do it.
1672: */
1673: for (xs = TAILQ_FIRST(&chan->chan_queue); xs != NULL;
1674: xs = TAILQ_NEXT(xs, channel_q)) {
1675: periph = xs->xs_periph;
1676:
1677: if ((periph->periph_sent >= periph->periph_openings) ||
1678: periph->periph_qfreeze != 0 ||
1679: (periph->periph_flags & PERIPH_UNTAG) != 0)
1680: continue;
1681:
1682: if ((periph->periph_flags &
1683: (PERIPH_RECOVERING | PERIPH_SENSE)) != 0 &&
1684: (xs->xs_control & XS_CTL_URGENT) == 0)
1685: continue;
1686:
1687: /*
1688: * We can issue this xfer!
1689: */
1690: goto got_one;
1691: }
1692:
1693: /*
1694: * Can't find any work to do right now.
1695: */
1.22 pk 1696: splx(s);
1.39 bouyer 1697: return;
1698:
1699: got_one:
1700: /*
1701: * Have an xfer to run. Allocate a resource from
1702: * the adapter to run it. If we can't allocate that
1703: * resource, we don't dequeue the xfer.
1704: */
1705: if (scsipi_get_resource(chan) == 0) {
1706: /*
1707: * Adapter is out of resources. If the adapter
1708: * supports it, attempt to grow them.
1709: */
1710: if (scsipi_grow_resources(chan) == 0) {
1711: /*
1712: * Wasn't able to grow resources,
1713: * nothing more we can do.
1714: */
1715: if (xs->xs_control & XS_CTL_POLL) {
1716: scsipi_printaddr(xs->xs_periph);
1717: printf("polling command but no "
1718: "adapter resources");
1719: /* We'll panic shortly... */
1720: }
1721: splx(s);
1722:
1723: /*
1724: * XXX: We should be able to note that
1725: * XXX: that resources are needed here!
1726: */
1727: return;
1728: }
1729: /*
1730: * scsipi_grow_resources() allocated the resource
1731: * for us.
1732: */
1733: }
1734:
1735: /*
1736: * We have a resource to run this xfer, do it!
1737: */
1738: TAILQ_REMOVE(&chan->chan_queue, xs, channel_q);
1739:
1740: /*
1741: * If the command is to be tagged, allocate a tag ID
1742: * for it.
1743: */
1744: if (XS_CTL_TAGTYPE(xs) != 0)
1745: scsipi_get_tag(xs);
1746: else
1747: periph->periph_flags |= PERIPH_UNTAG;
1748: periph->periph_sent++;
1749: splx(s);
1750:
1751: scsipi_adapter_request(chan, ADAPTER_REQ_RUN_XFER, xs);
1.22 pk 1752: }
1.39 bouyer 1753: #ifdef DIAGNOSTIC
1754: panic("scsipi_run_queue: impossible");
1755: #endif
1.2 bouyer 1756: }
1757:
1.39 bouyer 1758: /*
1759: * scsipi_execute_xs:
1760: *
1761: * Begin execution of an xfer, waiting for it to complete, if necessary.
1762: */
1.2 bouyer 1763: int
1764: scsipi_execute_xs(xs)
1765: struct scsipi_xfer *xs;
1766: {
1.39 bouyer 1767: struct scsipi_periph *periph = xs->xs_periph;
1768: struct scsipi_channel *chan = periph->periph_channel;
1769: int async, poll, retries, error, s;
1.2 bouyer 1770:
1.24 thorpej 1771: xs->xs_status &= ~XS_STS_DONE;
1.2 bouyer 1772: xs->error = XS_NOERROR;
1773: xs->resid = xs->datalen;
1.39 bouyer 1774: xs->status = SCSI_OK;
1775:
1776: #ifdef SCSIPI_DEBUG
1777: if (xs->xs_periph->periph_dbflags & SCSIPI_DB3) {
1778: printf("scsipi_execute_xs: ");
1779: show_scsipi_xs(xs);
1780: printf("\n");
1781: }
1782: #endif
1.2 bouyer 1783:
1784: /*
1.39 bouyer 1785: * Deal with command tagging:
1.3 enami 1786: *
1.39 bouyer 1787: * - If the device's current operating mode doesn't
1788: * include tagged queueing, clear the tag mask.
1.3 enami 1789: *
1.39 bouyer 1790: * - If the device's current operating mode *does*
1791: * include tagged queueing, set the tag_type in
1792: * the xfer to the appropriate byte for the tag
1793: * message.
1794: */
1795: if ((PERIPH_XFER_MODE(periph) & PERIPH_CAP_TQING) == 0 ||
1796: (xs->xs_control & XS_CTL_REQSENSE)) {
1797: xs->xs_control &= ~XS_CTL_TAGMASK;
1798: xs->xs_tag_type = 0;
1799: } else {
1800: /*
1801: * If the request doesn't specify a tag, give Head
1802: * tags to URGENT operations and Ordered tags to
1803: * everything else.
1804: */
1805: if (XS_CTL_TAGTYPE(xs) == 0) {
1806: if (xs->xs_control & XS_CTL_URGENT)
1807: xs->xs_control |= XS_CTL_HEAD_TAG;
1808: else
1809: xs->xs_control |= XS_CTL_ORDERED_TAG;
1810: }
1811:
1812: switch (XS_CTL_TAGTYPE(xs)) {
1813: case XS_CTL_ORDERED_TAG:
1814: xs->xs_tag_type = MSG_ORDERED_Q_TAG;
1815: break;
1816:
1817: case XS_CTL_SIMPLE_TAG:
1818: xs->xs_tag_type = MSG_SIMPLE_Q_TAG;
1819: break;
1820:
1821: case XS_CTL_HEAD_TAG:
1822: xs->xs_tag_type = MSG_HEAD_OF_Q_TAG;
1823: break;
1824:
1825: default:
1826: scsipi_printaddr(periph);
1827: printf("invalid tag mask 0x%08x\n",
1828: XS_CTL_TAGTYPE(xs));
1829: panic("scsipi_execute_xs");
1830: }
1.2 bouyer 1831: }
1.45 bjh21 1832:
1833: /* If the adaptor wants us to poll, poll. */
1834: if (chan->chan_adapter->adapt_flags & SCSIPI_ADAPT_POLL_ONLY)
1835: xs->xs_control |= XS_CTL_POLL;
1.39 bouyer 1836:
1837: /*
1838: * If we don't yet have a completion thread, or we are to poll for
1839: * completion, clear the ASYNC flag.
1840: */
1841: if (chan->chan_thread == NULL || (xs->xs_control & XS_CTL_POLL) != 0)
1842: xs->xs_control &= ~XS_CTL_ASYNC;
1843:
1.24 thorpej 1844: async = (xs->xs_control & XS_CTL_ASYNC);
1.39 bouyer 1845: poll = (xs->xs_control & XS_CTL_POLL);
1846: retries = xs->xs_retries; /* for polling commands */
1847:
1.2 bouyer 1848: #ifdef DIAGNOSTIC
1.39 bouyer 1849: if (async != 0 && xs->bp == NULL)
1850: panic("scsipi_execute_xs: XS_CTL_ASYNC but no buf");
1.2 bouyer 1851: #endif
1.39 bouyer 1852:
1853: /*
1854: * Enqueue the transfer. If we're not polling for completion, this
1855: * should ALWAYS return `no error'.
1856: */
1857: try_again:
1858: error = scsipi_enqueue(xs);
1859: if (error) {
1860: if (poll == 0) {
1861: scsipi_printaddr(periph);
1862: printf("not polling, but enqueue failed with %d\n",
1863: error);
1864: panic("scsipi_execute_xs");
1865: }
1866:
1867: scsipi_printaddr(periph);
1868: printf("failed to enqueue polling command");
1869: if (retries != 0) {
1870: printf(", retrying...\n");
1871: delay(1000000);
1872: retries--;
1873: goto try_again;
1874: }
1875: printf("\n");
1876: goto free_xs;
1877: }
1878:
1879: restarted:
1880: scsipi_run_queue(chan);
1881:
1882: /*
1883: * The xfer is enqueued, and possibly running. If it's to be
1884: * completed asynchronously, just return now.
1885: */
1886: if (async)
1887: return (EJUSTRETURN);
1888:
1889: /*
1890: * Not an asynchronous command; wait for it to complete.
1891: */
1892: s = splbio();
1893: while ((xs->xs_status & XS_STS_DONE) == 0) {
1894: if (poll) {
1895: scsipi_printaddr(periph);
1896: printf("polling command not done\n");
1897: panic("scsipi_execute_xs");
1898: }
1899: (void) tsleep(xs, PRIBIO, "xscmd", 0);
1900: }
1901: splx(s);
1902:
1903: /*
1904: * Command is complete. scsipi_done() has awakened us to perform
1905: * the error handling.
1906: */
1907: error = scsipi_complete(xs);
1908: if (error == ERESTART)
1909: goto restarted;
1910:
1911: /*
1912: * Command completed successfully or fatal error occurred. Fall
1913: * into....
1914: */
1915: free_xs:
1916: s = splbio();
1917: scsipi_put_xs(xs);
1918: splx(s);
1919:
1920: /*
1921: * Kick the queue, keep it running in case it stopped for some
1922: * reason.
1923: */
1924: scsipi_run_queue(chan);
1925:
1926: return (error);
1927: }
1928:
1929: /*
1930: * scsipi_completion_thread:
1931: *
1932: * This is the completion thread. We wait for errors on
1933: * asynchronous xfers, and perform the error handling
1934: * function, restarting the command, if necessary.
1935: */
1936: void
1937: scsipi_completion_thread(arg)
1938: void *arg;
1939: {
1940: struct scsipi_channel *chan = arg;
1941: struct scsipi_xfer *xs;
1942: int s;
1943:
1944: for (;;) {
1.11 scottr 1945: s = splbio();
1.39 bouyer 1946: xs = TAILQ_FIRST(&chan->chan_complete);
1947: if (xs == NULL &&
1948: (chan->chan_flags & SCSIPI_CHAN_SHUTDOWN) == 0) {
1949: (void) tsleep(&chan->chan_complete, PRIBIO,
1950: "sccomp", 0);
1951: splx(s);
1952: continue;
1953: }
1954: if (chan->chan_flags & SCSIPI_CHAN_SHUTDOWN) {
1955: splx(s);
1956: break;
1957: }
1958: TAILQ_REMOVE(&chan->chan_complete, xs, channel_q);
1.2 bouyer 1959: splx(s);
1960:
1.39 bouyer 1961: /*
1962: * Have an xfer with an error; process it.
1963: */
1964: (void) scsipi_complete(xs);
1.2 bouyer 1965:
1.39 bouyer 1966: /*
1967: * Kick the queue; keep it running if it was stopped
1968: * for some reason.
1969: */
1970: scsipi_run_queue(chan);
1.2 bouyer 1971: }
1972:
1.39 bouyer 1973: chan->chan_thread = NULL;
1974:
1975: /* In case parent is waiting for us to exit. */
1976: wakeup(&chan->chan_thread);
1977:
1978: kthread_exit(0);
1.2 bouyer 1979: }
1980:
1.39 bouyer 1981: /*
1982: * scsipi_create_completion_thread:
1983: *
1984: * Callback to actually create the completion thread.
1985: */
1986: void
1987: scsipi_create_completion_thread(arg)
1988: void *arg;
1.2 bouyer 1989: {
1.39 bouyer 1990: struct scsipi_channel *chan = arg;
1991: struct scsipi_adapter *adapt = chan->chan_adapter;
1.2 bouyer 1992:
1.39 bouyer 1993: if (kthread_create1(scsipi_completion_thread, chan,
1994: &chan->chan_thread, "%s:%d", adapt->adapt_dev->dv_xname,
1995: chan->chan_channel)) {
1996: printf("%s: unable to create completion thread for "
1997: "channel %d\n", adapt->adapt_dev->dv_xname,
1998: chan->chan_channel);
1999: panic("scsipi_create_completion_thread");
2000: }
2001: }
1.2 bouyer 2002:
1.39 bouyer 2003: /*
2004: * scsipi_async_event:
2005: *
2006: * Handle an asynchronous event from an adapter.
2007: */
2008: void
2009: scsipi_async_event(chan, event, arg)
2010: struct scsipi_channel *chan;
2011: scsipi_async_event_t event;
2012: void *arg;
2013: {
2014: int s;
2015:
2016: s = splbio();
2017: switch (event) {
2018: case ASYNC_EVENT_MAX_OPENINGS:
2019: scsipi_async_event_max_openings(chan,
2020: (struct scsipi_max_openings *)arg);
1.2 bouyer 2021: break;
2022:
1.39 bouyer 2023: case ASYNC_EVENT_XFER_MODE:
2024: scsipi_async_event_xfer_mode(chan,
2025: (struct scsipi_xfer_mode *)arg);
2026: break;
2027: case ASYNC_EVENT_RESET:
2028: scsipi_async_event_channel_reset(chan);
1.2 bouyer 2029: break;
1.39 bouyer 2030: }
2031: splx(s);
2032: }
2033:
2034: /*
2035: * scsipi_print_xfer_mode:
2036: *
2037: * Print a periph's capabilities.
2038: */
2039: void
2040: scsipi_print_xfer_mode(periph)
2041: struct scsipi_periph *periph;
2042: {
2043: int period, freq, speed, mbs;
2044:
2045: if ((periph->periph_flags & PERIPH_MODE_VALID) == 0)
2046: return;
1.2 bouyer 2047:
1.39 bouyer 2048: printf("%s: ", periph->periph_dev->dv_xname);
2049: if (periph->periph_mode & PERIPH_CAP_SYNC) {
2050: period = scsipi_sync_factor_to_period(periph->periph_period);
1.43 enami 2051: printf("sync (%d.%dns offset %d)",
1.39 bouyer 2052: period / 10, period % 10, periph->periph_offset);
2053: } else
1.43 enami 2054: printf("async");
1.39 bouyer 2055:
2056: if (periph->periph_mode & PERIPH_CAP_WIDE32)
2057: printf(", 32-bit");
2058: else if (periph->periph_mode & PERIPH_CAP_WIDE16)
2059: printf(", 16-bit");
2060: else
2061: printf(", 8-bit");
2062:
2063: if (periph->periph_mode & PERIPH_CAP_SYNC) {
2064: freq = scsipi_sync_factor_to_freq(periph->periph_period);
2065: speed = freq;
2066: if (periph->periph_mode & PERIPH_CAP_WIDE32)
2067: speed *= 4;
2068: else if (periph->periph_mode & PERIPH_CAP_WIDE16)
2069: speed *= 2;
2070: mbs = speed / 1000;
2071: if (mbs > 0)
2072: printf(" (%d.%03dMB/s)", mbs, speed % 1000);
2073: else
2074: printf(" (%dKB/s)", speed % 1000);
2075: }
2076:
2077: printf(" transfers");
2078:
2079: if (periph->periph_mode & PERIPH_CAP_TQING)
2080: printf(", tagged queueing");
2081:
2082: printf("\n");
2083: }
2084:
2085: /*
2086: * scsipi_async_event_max_openings:
2087: *
2088: * Update the maximum number of outstanding commands a
2089: * device may have.
2090: */
2091: void
2092: scsipi_async_event_max_openings(chan, mo)
2093: struct scsipi_channel *chan;
2094: struct scsipi_max_openings *mo;
2095: {
2096: struct scsipi_periph *periph;
2097: int minlun, maxlun;
2098:
2099: if (mo->mo_lun == -1) {
2100: /*
2101: * Wildcarded; apply it to all LUNs.
2102: */
2103: minlun = 0;
2104: maxlun = chan->chan_nluns - 1;
2105: } else
2106: minlun = maxlun = mo->mo_lun;
2107:
2108: for (; minlun <= maxlun; minlun++) {
2109: periph = scsipi_lookup_periph(chan, mo->mo_target, minlun);
2110: if (periph == NULL)
2111: continue;
2112:
2113: if (mo->mo_openings < periph->periph_openings)
2114: periph->periph_openings = mo->mo_openings;
2115: else if (mo->mo_openings > periph->periph_openings &&
2116: (periph->periph_flags & PERIPH_GROW_OPENINGS) != 0)
2117: periph->periph_openings = mo->mo_openings;
2118: }
2119: }
2120:
2121: /*
2122: * scsipi_async_event_xfer_mode:
2123: *
2124: * Update the xfer mode for all periphs sharing the
2125: * specified I_T Nexus.
2126: */
2127: void
2128: scsipi_async_event_xfer_mode(chan, xm)
2129: struct scsipi_channel *chan;
2130: struct scsipi_xfer_mode *xm;
2131: {
2132: struct scsipi_periph *periph;
2133: int lun, announce, mode, period, offset;
2134:
2135: for (lun = 0; lun < chan->chan_nluns; lun++) {
2136: periph = scsipi_lookup_periph(chan, xm->xm_target, lun);
2137: if (periph == NULL)
2138: continue;
2139: announce = 0;
2140:
2141: /*
2142: * Clamp the xfer mode down to this periph's capabilities.
2143: */
2144: mode = xm->xm_mode & periph->periph_cap;
2145: if (mode & PERIPH_CAP_SYNC) {
2146: period = xm->xm_period;
2147: offset = xm->xm_offset;
2148: } else {
2149: period = 0;
2150: offset = 0;
1.2 bouyer 2151: }
2152:
1.39 bouyer 2153: /*
2154: * If we do not have a valid xfer mode yet, or the parameters
2155: * are different, announce them.
2156: */
2157: if ((periph->periph_flags & PERIPH_MODE_VALID) == 0 ||
2158: periph->periph_mode != mode ||
2159: periph->periph_period != period ||
2160: periph->periph_offset != offset)
2161: announce = 1;
2162:
2163: periph->periph_mode = mode;
2164: periph->periph_period = period;
2165: periph->periph_offset = offset;
2166: periph->periph_flags |= PERIPH_MODE_VALID;
2167:
2168: if (announce)
2169: scsipi_print_xfer_mode(periph);
2170: }
2171: }
2172:
2173: /*
2174: * scsipi_set_xfer_mode:
2175: *
2176: * Set the xfer mode for the specified I_T Nexus.
2177: */
2178: void
2179: scsipi_set_xfer_mode(chan, target, immed)
2180: struct scsipi_channel *chan;
2181: int target, immed;
2182: {
2183: struct scsipi_xfer_mode xm;
2184: struct scsipi_periph *itperiph;
2185: int lun, s;
2186:
2187: /*
2188: * Go to the minimal xfer mode.
2189: */
2190: xm.xm_target = target;
2191: xm.xm_mode = 0;
2192: xm.xm_period = 0; /* ignored */
2193: xm.xm_offset = 0; /* ignored */
2194:
2195: /*
2196: * Find the first LUN we know about on this I_T Nexus.
2197: */
2198: for (lun = 0; lun < chan->chan_nluns; lun++) {
2199: itperiph = scsipi_lookup_periph(chan, target, lun);
2200: if (itperiph != NULL)
2201: break;
2202: }
2203: if (itperiph != NULL)
2204: xm.xm_mode = itperiph->periph_cap;
1.12 thorpej 2205:
1.39 bouyer 2206: /*
2207: * Now issue the request to the adapter.
2208: */
2209: s = splbio();
2210: scsipi_adapter_request(chan, ADAPTER_REQ_SET_XFER_MODE, &xm);
2211: splx(s);
1.2 bouyer 2212:
1.39 bouyer 2213: /*
2214: * If we want this to happen immediately, issue a dummy command,
2215: * since most adapters can't really negotiate unless they're
2216: * executing a job.
2217: */
2218: if (immed != 0 && itperiph != NULL) {
2219: (void) scsipi_test_unit_ready(itperiph,
2220: XS_CTL_DISCOVERY | XS_CTL_IGNORE_ILLEGAL_REQUEST |
2221: XS_CTL_IGNORE_NOT_READY |
2222: XS_CTL_IGNORE_MEDIA_CHANGE);
1.2 bouyer 2223: }
1.39 bouyer 2224: }
1.2 bouyer 2225:
1.39 bouyer 2226: /*
2227: * scsipi_channel_reset:
2228: *
2229: * handle scsi bus reset
2230: * called at splbio
2231: */
2232: void
2233: scsipi_async_event_channel_reset(chan)
2234: struct scsipi_channel *chan;
2235: {
2236: struct scsipi_xfer *xs, *xs_next;
2237: struct scsipi_periph *periph;
2238: int target, lun;
2239:
2240: /*
2241: * Channel has been reset. Also mark as reset pending REQUEST_SENSE
2242: * commands; as the sense is not available any more.
2243: * can't call scsipi_done() from here, as the command has not been
2244: * sent to the adapter yet (this would corrupt accounting).
2245: */
2246:
2247: for (xs = TAILQ_FIRST(&chan->chan_queue); xs != NULL; xs = xs_next) {
2248: xs_next = TAILQ_NEXT(xs, channel_q);
2249: if (xs->xs_control & XS_CTL_REQSENSE) {
2250: TAILQ_REMOVE(&chan->chan_queue, xs, channel_q);
2251: xs->error = XS_RESET;
2252: if ((xs->xs_control & XS_CTL_ASYNC) != 0)
2253: TAILQ_INSERT_TAIL(&chan->chan_complete, xs,
2254: channel_q);
2255: }
2256: }
2257: wakeup(&chan->chan_complete);
2258: /* Catch xs with pending sense which may not have a REQSENSE xs yet */
2259: for (target = 0; target < chan->chan_ntargets; target++) {
2260: if (target == chan->chan_id)
2261: continue;
2262: for (lun = 0; lun < chan->chan_nluns; lun++) {
2263: periph = chan->chan_periphs[target][lun];
2264: if (periph) {
2265: xs = periph->periph_xscheck;
2266: if (xs)
2267: xs->error = XS_RESET;
2268: }
2269: }
2270: }
1.2 bouyer 2271: }
2272:
1.39 bouyer 2273:
1.14 thorpej 2274: /*
1.39 bouyer 2275: * scsipi_adapter_addref:
2276: *
2277: * Add a reference to the adapter pointed to by the provided
2278: * link, enabling the adapter if necessary.
1.14 thorpej 2279: */
2280: int
1.39 bouyer 2281: scsipi_adapter_addref(adapt)
2282: struct scsipi_adapter *adapt;
1.14 thorpej 2283: {
2284: int s, error = 0;
2285:
2286: s = splbio();
1.39 bouyer 2287: if (adapt->adapt_refcnt++ == 0 && adapt->adapt_enable != NULL) {
2288: error = (*adapt->adapt_enable)(adapt->adapt_dev, 1);
1.14 thorpej 2289: if (error)
1.39 bouyer 2290: adapt->adapt_refcnt--;
1.14 thorpej 2291: }
2292: splx(s);
2293: return (error);
2294: }
2295:
2296: /*
1.39 bouyer 2297: * scsipi_adapter_delref:
2298: *
2299: * Delete a reference to the adapter pointed to by the provided
2300: * link, disabling the adapter if possible.
1.14 thorpej 2301: */
2302: void
1.39 bouyer 2303: scsipi_adapter_delref(adapt)
2304: struct scsipi_adapter *adapt;
1.14 thorpej 2305: {
2306: int s;
2307:
2308: s = splbio();
1.39 bouyer 2309: if (adapt->adapt_refcnt-- == 1 && adapt->adapt_enable != NULL)
2310: (void) (*adapt->adapt_enable)(adapt->adapt_dev, 0);
1.14 thorpej 2311: splx(s);
2312: }
2313:
1.39 bouyer 2314: struct scsipi_syncparam {
2315: int ss_factor;
2316: int ss_period; /* ns * 10 */
2317: } scsipi_syncparams[] = {
2318: { 0x0a, 250 },
2319: { 0x0b, 303 },
2320: { 0x0c, 500 },
2321: };
2322: const int scsipi_nsyncparams =
2323: sizeof(scsipi_syncparams) / sizeof(scsipi_syncparams[0]);
2324:
2325: int
2326: scsipi_sync_period_to_factor(period)
2327: int period; /* ns * 10 */
2328: {
2329: int i;
2330:
2331: for (i = 0; i < scsipi_nsyncparams; i++) {
2332: if (period <= scsipi_syncparams[i].ss_period)
2333: return (scsipi_syncparams[i].ss_factor);
2334: }
2335:
2336: return ((period / 10) / 4);
2337: }
2338:
2339: int
2340: scsipi_sync_factor_to_period(factor)
2341: int factor;
2342: {
2343: int i;
2344:
2345: for (i = 0; i < scsipi_nsyncparams; i++) {
2346: if (factor == scsipi_syncparams[i].ss_factor)
2347: return (scsipi_syncparams[i].ss_period);
2348: }
2349:
2350: return ((factor * 4) * 10);
2351: }
2352:
2353: int
2354: scsipi_sync_factor_to_freq(factor)
2355: int factor;
2356: {
2357: int i;
2358:
2359: for (i = 0; i < scsipi_nsyncparams; i++) {
2360: if (factor == scsipi_syncparams[i].ss_factor)
2361: return (10000000 / scsipi_syncparams[i].ss_period);
2362: }
2363:
2364: return (10000000 / ((factor * 4) * 10));
2365: }
2366:
2367: #ifdef SCSIPI_DEBUG
1.2 bouyer 2368: /*
2369: * Given a scsipi_xfer, dump the request, in all it's glory
2370: */
2371: void
2372: show_scsipi_xs(xs)
2373: struct scsipi_xfer *xs;
2374: {
1.3 enami 2375:
1.2 bouyer 2376: printf("xs(%p): ", xs);
1.24 thorpej 2377: printf("xs_control(0x%08x)", xs->xs_control);
2378: printf("xs_status(0x%08x)", xs->xs_status);
1.39 bouyer 2379: printf("periph(%p)", xs->xs_periph);
2380: printf("retr(0x%x)", xs->xs_retries);
1.2 bouyer 2381: printf("timo(0x%x)", xs->timeout);
2382: printf("cmd(%p)", xs->cmd);
2383: printf("len(0x%x)", xs->cmdlen);
2384: printf("data(%p)", xs->data);
2385: printf("len(0x%x)", xs->datalen);
2386: printf("res(0x%x)", xs->resid);
2387: printf("err(0x%x)", xs->error);
2388: printf("bp(%p)", xs->bp);
2389: show_scsipi_cmd(xs);
2390: }
2391:
2392: void
2393: show_scsipi_cmd(xs)
2394: struct scsipi_xfer *xs;
2395: {
2396: u_char *b = (u_char *) xs->cmd;
1.3 enami 2397: int i = 0;
1.2 bouyer 2398:
1.39 bouyer 2399: scsipi_printaddr(xs->xs_periph);
2400: printf(" command: ");
1.2 bouyer 2401:
1.24 thorpej 2402: if ((xs->xs_control & XS_CTL_RESET) == 0) {
1.2 bouyer 2403: while (i < xs->cmdlen) {
2404: if (i)
2405: printf(",");
2406: printf("0x%x", b[i++]);
2407: }
2408: printf("-[%d bytes]\n", xs->datalen);
2409: if (xs->datalen)
2410: show_mem(xs->data, min(64, xs->datalen));
2411: } else
2412: printf("-RESET-\n");
2413: }
2414:
2415: void
2416: show_mem(address, num)
2417: u_char *address;
2418: int num;
2419: {
2420: int x;
2421:
2422: printf("------------------------------");
2423: for (x = 0; x < num; x++) {
2424: if ((x % 16) == 0)
2425: printf("\n%03d: ", x);
2426: printf("%02x ", *address++);
2427: }
2428: printf("\n------------------------------\n");
2429: }
1.39 bouyer 2430: #endif /* SCSIPI_DEBUG */
CVSweb <webmaster@jp.NetBSD.org>