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