|
|
1.1 root 1: /*
2: * This is the host adaptor specific portion of the
3: * Adaptec AHA154x driver.
4: *
5: * $Log: /usr/src/sys/i8086/drv/RCS/aha.c,v $
6: * Revision 1.2 91/05/01 04:54:43 root
7: * Debug code and kalloc arg fixes.
8: *
9: * Revision 1.1 91/04/30 11:01:41 root
10: * Shipped with COH 3.1.0
11: *
12: */
13: #include <sys/coherent.h>
14: #include <sys/buf.h>
15: #include <sys/sched.h>
16:
17: #include <sys/scsiwork.h>
18: #include <sys/aha154x.h>
19:
20: extern saddr_t sds; /* System Data Selector */
21: static paddr_t sds_physical; /* as physical address */
22: static short aha_i_o_base;
23: static char aha_loaded; /* did load() find a host adaptor? */
24: static char dev_bit_map[8]; /* one byte per SCSI-ID; one bit per LUN */
25: char drive_info[MAX_SCSI_ID * MAX_LUN]; /* "per drive" info/flags */
26:
27: void aha_intr(); /* interrupt service routine */
28:
29: #define MIN_MAILBOX 1
30: int MAX_MAILBOX = { 8 }; /* tunable value */
31:
32: static scsi_work_t *scsi_work_queue;
33: static mailentry *mailbox_in, *mailbox_out;
34: static char *aha_err_msg = { "no message" };
35:
36: static long aha_timeout[] = {
37: #define TIMEOUT_PRESENT 0
38: 0x30000L,
39: #define TIMEOUT_SENDCMD 1
40: 0x10000L,
41: #define TIMEOUT_POLL 2
42: 0x100L,
43: };
44:
45: #if 0
46: static
47: OUTB( port, value )
48: short port;
49: { printf( "<O(%x,%x)>", port, value );
50: outb( port, value ); }
51: INB( port )
52: short port;
53: { register i = inb(port);
54: printf( "<I(%x)=%x>", port, i );
55: return i; }
56: #else
57: #define OUTB( port, value ) outb( port, value )
58: #define INB(port) inb(port)
59: #endif
60:
61: #if VERBOSE
62: #define SETMSG(msg) aha_err_msg = msg
63:
64: static
65: char *aha_last_msg()
66: {
67: return aha_err_msg;
68: }
69:
70: #else
71:
72: #define SETMSG(msg)
73: static
74: char *aha_last_msg()
75: {
76: return "error messages not verbose";
77: }
78: #endif
79:
80: static
81: int no_mem()
82: {
83: printf("aha154x: out of kernel memory\n");
84: }
85:
86: int aha_set_base( base )
87: {
88: register i;
89:
90: i = aha_i_o_base;
91: aha_i_o_base = base;
92: return i;
93: }
94:
95: int aha_get_base()
96: {
97: return aha_i_o_base;
98: }
99:
100: aha_process( ccb )
101: ccb_t *ccb;
102: {
103: register scsi_work_t *sw = ccb->ccb_sw;
104: register BUF *bp;
105:
106: #if VERBOSE
107: printf( "aha_process: ccb %x ", ccb );
108: printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
109: aha_ccb_print( ccb );
110: #endif
111: if( ccb->ccb_sw == 0 ) {
112: #if VERBOSE
113: printf( "process: ccb %x with NULL sw\n", ccb );
114: #endif
115: ++ccb->opcode;
116: wakeup( ccb );
117: return;
118: }
119:
120: bp = sw->sw_bp;
121: #if VERBOSE
122: printf( "bp = %x\n", bp );
123: #endif
124: if( (ccb->hoststatus != 0) || (ccb->targetstatus != 0) ) {
125: if( --sw->sw_retry > 0
126: || (ccb->targetstatus == CHECK_TARGET_STATUS
127: && ccb->cmd_status[12] == SENSE_UNIT_ATTENTION)) {
128: int s = sphi();
129: if( scsi_work_queue->sw_actf == NULL ) {
130: scsi_work_queue->sw_actf = sw;
131: } else {
132: scsi_work_queue->sw_actl->sw_actf = sw;
133: }
134: scsi_work_queue->sw_actl = sw;
135: spl(s);
136: aha_start();
137: return;
138: }
139: bp->b_flag |= BFERR;
140: } else
141: bp->b_resid = 0;
142: #if VERBOSE
143: printf( "bp flag = %o\n", bp->b_flag );
144: #endif
145: bdone( bp );
146: kfree( sw );
147: kfree( ccb );
148: }
149:
150: static
151: int aha_1out( value )
152: {
153: register i;
154:
155: while( (i = INB(aha_i_o_base + AHA_STATUS) & AHA_CDOPFULL) != 0 )
156: if( (i & AHA_INVDCMD)
157: || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE) )
158: return -1;
159: OUTB( aha_i_o_base + AHA_WRITE, value );
160: return 0;
161: }
162:
163: static
164: int aha_1in()
165: {
166: register i;
167:
168: while( (i = INB(aha_i_o_base + AHA_STATUS) & AHA_DIPFULL) == 0 )
169: if( (i & AHA_INVDCMD)
170: || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE) )
171: return -1;
172: return INB( aha_i_o_base + AHA_READ ) & 0xFF;
173: }
174:
175: static
176: void aha_cmd_out( value )
177: {
178: register long l;
179: register int i;
180:
181: for( l = aha_timeout[TIMEOUT_SENDCMD]; --l > 0; )
182: if( ((i=INB(aha_i_o_base + AHA_STATUS))
183: & AHA_SCSIIDLE ) != 0 ) {
184: aha_1out( value );
185: return;
186: }
187: #if VERBOSE
188: else
189: printf( "aha: cmd_out status = %x\r", i );
190: #endif
191: SETMSG( "timeout sending cmd byte" );
192: printf( "aha154x: timeout sending cmd byte\n" );
193: }
194:
195: static
196: int aha_poll()
197: {
198: register i;
199: register l = aha_timeout[TIMEOUT_POLL];
200: while( (--l > 0 )
201: && ((i = INB(aha_i_o_base + AHA_INTERRUPT)) & AHA_CMD_DONE) == 0 )
202: ;
203: if( l == 0 )
204: printf( "aha154x: aha_poll timed out\n" );
205:
206: i = INB(aha_i_o_base + AHA_STATUS);
207: OUTB( aha_i_o_base + AHA_CONTROL, AHA_INTRRESET );
208: return i;
209: }
210:
211: static
212: void aha_get_data( vec, cnt )
213: char *vec;
214: int cnt;
215: {
216: while( --cnt >= 0 )
217: *vec++ = aha_1in();
218: aha_poll();
219: }
220:
221: static
222: int aha_present()
223: {
224: long l;
225:
226: if( INB(aha_i_o_base) == 0xFF ) {
227: SETMSG( "no adapter found at io base" );
228: return -3;
229: }
230: for( l = aha_timeout[TIMEOUT_PRESENT];
231: (--l > 0) && (INB(aha_i_o_base + AHA_STATUS) & AHA_SELFTEST); )
232: ;
233: if( l == 0 ) {
234: SETMSG( "selftest not completed" );
235: return -1;
236: }
237: if( INB(aha_i_o_base + AHA_STATUS) & AHA_DIAGFAIL ) {
238: SETMSG( "diagnostics failed" );
239: return -2;
240: }
241: if( INB(aha_i_o_base + AHA_STATUS) & AHA_INITMAIL ) {
242: SETMSG( "mailbox initialization needed" );
243: return 1;
244: }
245: if( INB(aha_i_o_base + AHA_STATUS) & AHA_SCSIIDLE ) {
246: SETMSG( "adaptor okay, idle" );
247: return 0;
248: }
249: SETMSG( "unknown status at start" );
250: return -4;
251: }
252:
253: static
254: void aha_l_to_p3( value, vec )
255: paddr_t value;
256: unsigned char *vec;
257: {
258: register i;
259:
260: for( i = 3; --i >= 0; ) {
261: vec[i] = value & 0xFF;
262: value >>= 8;
263: }
264: }
265:
266: static
267: char *aha_p3_to_v( vec )
268: unsigned char *vec;
269: {
270: paddr_t adr;
271:
272: adr = vec[0];
273: adr <<= 16;
274: adr |= (vec[1]<<8) | vec[2];
275: adr -= sds_physical;
276: return (char *)adr;
277: }
278:
279: aha_device_info()
280: {
281: register i;
282: static char buf[256];
283:
284: aha_cmd_out( AHA_DO_GET_DEVICES );
285: aha_get_data( &buf[0], 8 );
286: for( i = 0; i < 8; ++i )
287: if( buf[i] != 0 )
288: printf( "[%d] %x ", i, buf[i] );
289: printf( "\n" );
290: }
291:
292: int aha_unload( ireq )
293: {
294: #if VERBOSE
295: printf( "aha_unload: %x\n", ireq );
296: #endif
297: /*
298: * we should really verify that everything
299: * out there gets flushed.
300: */
301: if (!aha_loaded)
302: return;
303: if( mailbox_out ) {
304: kfree( mailbox_out );
305: mailbox_out = 0;
306: }
307: clrivec( ireq );
308: }
309:
310: int aha_load( dma, ireq, base, head )
311: scsi_work_t *head;
312: {
313: register int i;
314: unsigned char adr[4];
315:
316: #if VERBOSE
317: printf( "aha_load( %d, %d, 0x%x );\n", dma, ireq, base );
318: #endif
319: aha_set_base(base);
320: if( mailbox_out == 0 ) {
321: if( (mailbox_out =
322: kalloc(2 * MAX_MAILBOX * sizeof(mailentry))) == 0 ) {
323: no_mem();
324: return -1;
325: } else
326: mailbox_in = &mailbox_out[MAX_MAILBOX];
327: }
328:
329: for( i = 0; i < MAX_MAILBOX; ++i )
330: mailbox_out[i].cmd = mailbox_in[i].cmd = 0;
331:
332: sds_physical = VTOP2( 0, sds );
333: aha_l_to_p3( VTOP2( mailbox_out, sds ), &adr[1] );
334: adr[0] = MAX_MAILBOX;
335:
336: /*
337: * setup HW
338: */
339: setivec( ireq, aha_intr );
340: outb( 0xD6, 0xC1 ); /* DMA is currently hard coded for */
341: outb( 0xD4, 0x01 ); /* DMA channel 5 */
342:
343:
344: OUTB( aha_i_o_base+AHA_CONTROL, AHA_HARDRESET );
345: if (aha_present() < 0) {
346: printf("aha154x: initialization error or host adaptor not ");
347: printf("found at 0x%x\n", aha_i_o_base);
348: return -1;
349: }
350: aha_cmd_out( AHA_DO_MAILBOX_INIT );
351: for( i = 0; i < 4; ++i )
352: aha_1out( adr[i] );
353: scsi_work_queue = head;
354: ++aha_loaded;
355: return MAX_MAILBOX;
356: }
357:
358: aha_command( sc )
359: register scsi_cmd_t *sc;
360: {
361: register i;
362: register ccb_t *ccb;
363:
364: short count = sc->blklen;
365: long block = sc->block;
366:
367: ccb = (ccb_t *) kalloc(sizeof (ccb_t));
368: if (ccb == (ccb_t *) 0) {
369: no_mem();
370: return -1;
371: }
372: #if VERBOSE
373: printf( "aha_command( SCSI ID %d, LUN %d, c %x, b %D",
374: sc->unit >> 2, sc->unit & 0x3, sc->cmd, sc->block );
375: printf( " [%d] @%x:%x )\n",
376: sc->buflen, sc->buffer );
377: #endif
378: ccb->ccb_sw = 0;
379: ccb->opcode = 0; /* SCSI_INITIATOR*/
380: ccb->target = (sc->unit & 0x1C) << 3; /* SCSI ID */
381: ccb->target |= sc->unit & 0x3; /* LUN */
382: if( (ccb->cmd_status[0] = sc->cmd) == ScmdWRITEXTENDED ) {
383: ccb->target |= AHA_CCB_DATA_OUT;
384: } else { /* READEXT, READCAP, INQUIRY */
385: ccb->target |= AHA_CCB_DATA_IN;
386: }
387: ccb->cmd_status[1] = 0;
388: ccb->cmd_status[2] = block;
389: ccb->cmd_status[3] = block >>16;
390: ccb->cmd_status[4] = block >> 8;
391: ccb->cmd_status[5] = block;
392: ccb->cmd_status[6] = 0;
393: ccb->cmd_status[7] = count / 512;
394: ccb->cmd_status[8] = count;
395: ccb->cmd_status[9] = 0;
396: ccb->cmdlen = 10;
397: ccb->senselen = MAX_SENSEDATA;
398:
399: aha_l_to_p3( (long)sc->buflen, ccb->datalen );
400: aha_l_to_p3( sc->buffer, ccb->dataptr );
401: aha_l_to_p3( VTOP2( ccb, sds ), mailbox_out[0].adr );
402: #if VERBOSE
403: aha_ccb_print( ccb );
404: #endif
405: mailbox_out[0].cmd = MBO_TO_START;
406: aha_1out( AHA_DO_SCSI_START );
407: while( ccb->opcode == 0 )
408: sleep( ccb, CVBLKIO, IVBLKIO, SVBLKIO );
409:
410: #if VERBOSE
411: printf( "done with status = %d, %d\n",
412: ccb->hoststatus, ccb->targetstatus );
413: #endif
414: if( (ccb->targetstatus == CHECK_TARGET_STATUS)
415: && (ccb->cmd_status[12] != SENSE_UNIT_ATTENTION) ) {
416: printf( "aha: SCSI ID %d LUN %d. SCSI sense =",
417: (sc->unit >> 2), sc->unit & 0x3 );
418: for( i = 0; i < ccb->senselen; ++i )
419: printf( " %x", ccb->cmd_status[10+i] );
420: printf( "\n" );
421: }
422: i = ccb->hoststatus | ccb->targetstatus;
423: kfree( ccb );
424: return i;
425: }
426:
427: ccb_t *buildccb( sw )
428: register scsi_work_t *sw;
429: {
430: register ccb_t *ccb;
431: ccb = (ccb_t *)kalloc(sizeof(ccb_t));
432:
433: #if VERBOSE
434: printf( "build: drv = %x, bno = %D ",
435: sw->sw_drv, sw->sw_bno );
436: #endif
437: ccb->ccb_sw = sw;
438: ccb->opcode = 0; /* SCSI INITIATOR */
439: ccb->target = (sw->sw_drv & 0x1C) << 3; /* SCSI ID */
440: ccb->target |= (sw->sw_drv) & 0x3; /* LUN */
441: if( sw->sw_bp->b_req == BREAD ) {
442: ccb->target |= AHA_CCB_DATA_IN;
443: ccb->cmd_status[0] = ScmdREADEXTENDED;
444: } else {
445: ccb->target |= AHA_CCB_DATA_OUT;
446: ccb->cmd_status[0] = ScmdWRITEXTENDED;
447: }
448: ccb->cmd_status[2] = 0;
449: ccb->cmd_status[3] = sw->sw_bno >>16;
450: ccb->cmd_status[4] = sw->sw_bno >> 8;
451: ccb->cmd_status[5] = sw->sw_bno;
452: ccb->cmd_status[6] = 0;
453: ccb->cmd_status[7] = sw->sw_bp->b_count / (512*256L);
454: ccb->cmd_status[8] = sw->sw_bp->b_count / 512;
455: ccb->cmd_status[9] = 0;
456: ccb->cmdlen = 10;
457: ccb->senselen = MAX_SENSEDATA;
458:
459: aha_l_to_p3( (long)sw->sw_bp->b_count, ccb->datalen );
460: aha_l_to_p3( vtop(sw->sw_bp->b_faddr), ccb->dataptr );
461: return ccb;
462: #if 0
463: /* start of ioctl code */
464: if( f == SASI_CMD_IN )
465: ccb->target |= AHA_CCB_DATA_IN;
466: else if( f == SASI_CMD_OUT )
467: ccb->target |= AHA_CCB_DATA_OUT;
468: else
469: ccb->target |= AHA_CCB_DATA_IN
470: |AHA_CCB_DATA_OUT;
471: #endif
472: }
473:
474: aha_start()
475: {
476: register i, s, n = 0;
477: scsi_work_t *sw;
478: static char locked;
479:
480: s = sphi();
481: if( locked ) {
482: spl(s);
483: return;
484: }
485: ++locked;
486: spl(s);
487:
488: while( (sw = scsi_work_queue->sw_actf) != NULL ) {
489: for( i = MIN_MAILBOX; i < MAX_MAILBOX; ++i )
490: if( mailbox_out[i].cmd == MBO_IS_FREE ) {
491: register ccb_t *ccb;
492: int s;
493:
494: ++n;
495: ccb = buildccb( sw );
496: #if VERBOSE
497: aha_ccb_print( ccb );
498: #endif
499: aha_l_to_p3( VTOP2( ccb, sds ),
500: mailbox_out[i].adr );
501: mailbox_out[i].cmd = MBO_TO_START;
502: #if VERBOSE
503: printf( "MBO[%d] = %x:%x:%x:%x, ccb = %x ",
504: i, mailbox_out[i].cmd,
505: mailbox_out[i].adr[0],
506: mailbox_out[i].adr[1],
507: mailbox_out[i].adr[2], ccb );
508: printf("sw=%x bp=%x\n", ccb->ccb_sw, ccb->ccb_sw->sw_bp);
509: #endif
510: aha_1out( AHA_DO_SCSI_START );
511:
512: s = sphi();
513: sw = scsi_work_queue->sw_actf = sw->sw_actf;
514: if( sw == NULL )
515: scsi_work_queue->sw_actl = NULL;
516: spl(s);
517:
518: if( sw == NULL )
519: break;
520: }
521: if( i == MAX_MAILBOX )
522: break;
523: }
524: --locked;
525: return n;
526: }
527:
528: int aha_completed()
529: {
530: register i, n;
531:
532: for( n = 0, i = 0; i < MAX_MAILBOX; ++i )
533: if( mailbox_in[i].cmd != MBI_IS_FREE ) {
534: #if VERBOSE
535: printf( "aha: mail[%d] = %x:%x:%x:%x\n",
536: i, mailbox_in[i].cmd,
537: mailbox_in[i].adr[0],
538: mailbox_in[i].adr[1],
539: mailbox_in[i].adr[2] );
540: #endif
541: defer( aha_process,
542: aha_p3_to_v( mailbox_in[i].adr ) );
543: mailbox_in[i].cmd = MBI_IS_FREE;
544: ++n;
545: }
546: return n;
547: }
548:
549: void aha_intr()
550: {
551: register i;
552:
553: #if VERBOSE
554: printf( "aha_interrupt routine\n" );
555: #endif
556: if( ((i = INB(aha_i_o_base+AHA_INTERRUPT)) & AHA_ANY_INTER) == 0 )
557: printf( "aha: spurious interrupt %x\n", i );
558: #if VERBOSE
559: printf( "aha_interrupt: %x\n", i );
560: #endif
561: switch( i & AHA_ALL_INTERRUPTS ) {
562: case AHA_RESETED:
563: #if VERBOSE
564: printf( "aha: reseted\n" );
565: #endif
566: break;
567: case AHA_CMD_DONE:
568: #if VERBOSE
569: printf( "aha: adapter command completed\n" );
570: #endif
571: break;
572: case AHA_MBO_EMPTY:
573: #if VERBOSE
574: printf( "aha: MAILBOX emptied\n" );
575: #endif
576: defer( aha_start, (char *)0 );
577: break;
578: case AHA_MBI_STORED:
579: #if VERBOSE
580: printf( "aha: MAILBOX in stored\n" );
581: #endif
582: aha_completed();
583: break;
584: default:
585: printf( "aha: multiple interrupts not yet handled\n" );
586: }
587: outb( aha_i_o_base+AHA_CONTROL, AHA_INTRRESET );
588: }
589:
590: aha_ioctl()
591: {
592: printf( "aha_ioctl: Not implemented\n" );
593: }
594:
595: #if VERBOSE
596: static unsigned char vec[256];
597:
598: static aha_ports_are() {
599: printf( "aha_ports_are: %x %x %x\n",
600: INB(aha_i_o_base+0),
601: INB(aha_i_o_base+1),
602: INB(aha_i_o_base+2) );
603: }
604:
605: static aha_inquiry_is() {
606: printf( "aha_inquiry:" );
607: printf( "... aha_present = %d, ", aha_present() );
608: printf( "%s\n", aha_last_msg() );
609: aha_cmd_out( AHA_DO_INQUIRY );
610:
611: aha_get_data( &vec[0], 4 );
612: printf( " board id '%c'", vec[0] );
613: printf( ", options '%c'", vec[1] );
614: printf( ", HW '%c'", vec[2] );
615: printf( ", FW '%c'\n", vec[3] );
616: }
617:
618: void aha_setup_is() {
619: register i;
620:
621: printf( "Setup and Data:\n" );
622: aha_cmd_out( AHA_DO_GET_SETUP );
623: aha_cmd_out( 16 );
624: aha_get_data( &vec[0], 16 );
625: printf( " Data Xfer %s Sync (J1)\n", (vec[0]&1) ? "is" : "not" );
626: printf( " Parity %s Enabled (J1)\n", (vec[0]&2) ? "is" : "not" );
627: switch( vec[1] ) {
628: case AHA_SPEED_5_0_MB:
629: printf( " 5.0 Mb/sec.\n" ); break;
630: case AHA_SPEED_6_7_MB:
631: printf( " 6.7 Mb/sec.\n" ); break;
632: case AHA_SPEED_8_0_MB:
633: printf( " 8.0 Mb/sec.\n" ); break;
634: case AHA_SPEED_10_MB:
635: printf( " 10 Mb/sec.\n" ); break;
636: case AHA_SPEED_5_7_MB:
637: printf( " 5.7 Mb/sec.\n" ); break;
638: default:
639: if( vec[1] & 0x80 )
640: printf( " Pulse Read %d, Write %d, Strobe off %d\n",
641: 50*(2+(vec[1]>>4)&0x7), 50*(2+(vec[1]&7)),
642: vec[1] & 0x80 ? 150 : 100 );
643: }
644: printf( " Bus Time ON %d, OFF %d\n", vec[2], vec[3] );
645: printf( " %d Mailboxes at %x|%x|%x\n", vec[4],
646: vec[5], vec[6], vec[7] );
647: for( i = 0; i < 8; ++i )
648: if( vec[i+8] )
649: printf( " Target [%d] = Sync Neg %x\n", i, vec[i+8] );
650: }
651:
652: static aha_mailboxes_are( n, adr )
653: mailentry *adr;
654: {
655: register i;
656:
657: printf( "addresses for mailbox is %x:%x\n", (long)adr );
658: for( i = 0; i < n; ++i, ++adr )
659: printf( " mbo[%x] = %x %x|%x|%x\n",
660: i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2] );
661: for( i = 0; i < n; ++i, ++adr )
662: printf( " mbi[%x] = %x %x|%x|%x\n",
663: i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2] );
664: }
665:
666: void aha_status()
667: {
668: aha_ports_are();
669: aha_inquiry_is();
670: aha_devices_are();
671: aha_setup_is();
672: aha_mailboxes_are( MAX_MAILBOX, mailbox_out );
673: }
674:
675: aha_ccb_print( ccb )
676: ccb_t *ccb;
677: {
678: register i;
679: register unsigned char *cp;
680:
681: printf( "ccb @%x, sw @%x, bp @%x, flag %o\n",
682: ccb, ccb->ccb_sw, ccb->ccb_sw->sw_bp,
683: ccb->ccb_sw->sw_bp->b_flag );
684: printf( "op %d, ", ccb->opcode );
685: printf( "target ID=%d, ", (ccb->target>>5) & 0x7 );
686: printf( "LUN=%d, ", (ccb->target & 0x7) );
687: printf( "dir=%s%s\n", (ccb->target&AHA_CCB_DATA_IN)?"IN":"",
688: (ccb->target&AHA_CCB_DATA_OUT)?"OUT":"" );
689: printf( "data len %x|%x|%x, adr %x|%x|%x\n",
690: ccb->datalen[0],ccb->datalen[1],ccb->datalen[2],
691: ccb->dataptr[0],ccb->dataptr[1],ccb->dataptr[2] );
692: printf( "status host=%x, target=%x\n",
693: ccb->hoststatus, ccb->targetstatus );
694: printf( "cmddata[%d]:", ccb->cmdlen );
695: for( i = 0, cp = ccb->cmd_status; i < ccb->cmdlen; ++i )
696: printf( " %x", *cp++ );
697: printf( "\nrequest sense[%d]:", ccb->senselen );
698: for( i = 0; i < ccb->senselen; ++i )
699: printf( " %x", *cp++ );
700: if( i = cp[-1] ) {
701: printf( "\n + " );
702: while( --i >= 0 )
703: printf( " %x", *cp++ );
704: }
705: printf( "\n" );
706: }
707:
708: #endif /* VERBOSE */
709:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.