|
|
1.1 root 1: /*
2: * This is the host adaptor specific portion of the
3: * Adaptec AHA154x driver.
4: *
5: * $Log: aha.c,v $
6: * Revision 1.9 93/04/16 06:57:55 bin
7: * Hal: kernel 76 update
8: *
9: * Revision 1.1 93/03/18 10:31:13 root
10: * r74
11: *
12: * Revision 1.1 91/04/30 11:01:41 root
13: * Shipped with COH 3.1.0
14: *
15: */
16: #include <sys/coherent.h>
17: #include <sys/buf.h>
18: #include <sys/sched.h>
19:
20: #include <sys/scsiwork.h>
21: #include <sys/aha154x.h>
22:
23: #ifdef _I386
24: extern char *palloc();
25: #endif /* _I386 */
26:
27: #ifndef _I386
28: extern saddr_t sds; /* System Data Selector */
29: static paddr_t sds_physical; /* as physical address */
30: #endif /* _I386 */
31: static short aha_i_o_base;
32: static char aha_loaded; /* did load() find a host adaptor? */
33: static char dev_bit_map[8]; /* one byte per SCSI-ID; one bit per LUN */
34: char drive_info[MAX_SCSI_ID * MAX_LUN]; /* "per drive" info/flags */
35:
36: void aha_intr(); /* interrupt service routine */
37:
38: #define MIN_MAILBOX 1
39: int MAX_MAILBOX = { 8 }; /* tunable value */
40:
41: static scsi_work_t *scsi_work_queue;
42: static mailentry *mailbox_in, *mailbox_out;
43: static char *aha_err_msg = { "no message" };
44:
45: static long aha_timeout[] = {
46: #define TIMEOUT_PRESENT 0
47: 0x30000L,
48: #define TIMEOUT_SENDCMD 1
49: 0x10000L,
50: #define TIMEOUT_POLL 2
51: 0x100L
52: };
53:
54: /*
55: * NIGEL: The 'ccb_t' structure defined in <sys/aha154x.h> has data for the
56: * SCSI controller, at least at the base. Presumably the 'ccb_sw' member is
57: * not for the SCSI controller, so data after the 'cmd_status' member is
58: * for the driver. The 'buffer' member is not used....
59: *
60: * Below I create a wrapper structure that separates driver-private data from
61: * the Adaptec 'ccb' like the original author should have written. This allows
62: * the 'ccb' to be threaded on a work list, and would obviate the need for the
63: * stupid machinery in "i386/mem_cache.c" (although not even that would be
64: * needed had page management been done right...)
65: *
66: * The primary motivation for this is to allow ccb's to be deallocated safely.
67: * The 286 version of the driver deallocated the structures in aha_process (),
68: * which was deferred from aha_intr (). The 4.0 version can not do that because
69: * due to the large size of the buffer cache a defer-table overflow might
70: * result. We compromise by creating a deferred work list and threading the
71: * ccb's on that and only deferring the 'start work' operation. Since
72: * aha_process () does no actual work but merely calls bdone () then frees the
73: * data, we create a 'free list' of ccb's and a deferred routine to free them,
74: * and leave aha_process () to call bdone () at interrupt level to give maximum
75: * throughput.
76: *
77: * You are now passing the Hack City limits. You are now in the Interdicted
78: * Zone.
79: */
80:
81: #include <stddef.h> /* import offsetof () */
82:
83: typedef struct driver_ccb drv_ccb_t;
84:
85: struct driver_ccb {
86: ccb_t aha_ccb; /* the driver CCB */
87: drv_ccb_t * next; /* for threading on work list */
88: };
89:
90: static drv_ccb_t * free_list; /* ccb's to free */
91: static int free_active; /* nonzero if cleanup routine active */
92:
93: /*
94: * There are two low-level allocators in use, one for 3.2 and one for 4.0,
95: * and rather than #ifdef the usage we call them via a macro below.
96: */
97:
98: #ifdef _I386
99: #define AHA_ALLOC(size) palloc (size)
100: #define AHA_FREE(size) pfree (size)
101: #else
102: #define AHA_ALLOC(size) kalloc (size)
103: #define AHA_FREE(size) kfree (size)
104: #endif
105:
106:
107: /*
108: * Cleanup routine for free list, called via defer () from ccb_free ().
109: *
110: * Many fields of active ccb's are filled in with other dynamically allocated
111: * structures; this code has responsibility for freeing all of them.
112: */
113: void
114: ccb_cleanup ()
115: {
116: drv_ccb_t * work;
117: int s;
118:
119: s = sphi ();
120: while ((work = free_list) != NULL) {
121: free_list = work->next;
122: spl (s);
123:
124: #ifdef _I386
125: /*
126: * The following code is insane; the DSL stuff should be part
127: * of this ccb system. This will be fixed when a total revamp
128: * of memory management occurs, and the "mem_cache.c" stuff
129: * gets spaced.
130: *
131: * In the original code, the ccb_forget () was done after the
132: * ccb was totally freed. I put it here to save conditionals.
133: */
134: dsl_free (work->aha_ccb.dataptr);
135: ccb_forget (& work->aha_ccb);
136: #endif
137:
138: if (work->aha_ccb.ccb_sw != NULL)
139: AHA_FREE (work->aha_ccb.ccb_sw);
140: AHA_FREE (work);
141:
142: s = sphi ();
143: }
144:
145: free_active = 0; /* defer () needed to reschedule */
146: spl (s);
147: }
148:
149:
150: /*
151: * Allocate a ccb and return a pointer to it. Call from base level only.
152: * The scsi_work_t * value passed here is remembered so that when the ccb
153: * is deallocated it will be too. In addition, code in aha_process () uses
154: * this stored value to map back from a ccb to a buffer-cache entry.
155: */
156: ccb_t *
157: ccb_alloc (sw)
158: scsi_work_t * sw;
159: {
160: drv_ccb_t * drvccb;
161:
162: if ((drvccb = (drv_ccb_t *) AHA_ALLOC (sizeof (* drvccb))) == NULL)
163: return NULL;
164:
165: /*
166: * Remember the 'sw' value. Note that this really should be put in
167: * our wrapper structure, but that is to be fixed later.
168: */
169:
170: drvccb->aha_ccb.ccb_sw = sw;
171:
172: /*
173: * Return a pointer to the inner adaptec ccb.
174: */
175:
176: return & drvccb->aha_ccb;
177: }
178:
179:
180: /*
181: * Return a ccb to the free pool. Callable from base or interrupt level. All
182: * the dynamically allocated member data of the ccb should be freed by this
183: * routine.
184: */
185: void
186: ccb_free (ccb)
187: ccb_t * ccb;
188: {
189: int s;
190: drv_ccb_t * work;
191:
192: /*
193: * Perform a portable downcast from the aha_ccb to the base structure.
194: */
195:
196: work = (drv_ccb_t *) ((char *) ccb - offsetof (drv_ccb_t, aha_ccb));
197:
198: s = sphi ();
199: work->next = free_list;
200: free_list = work;
201:
202: if (free_active == 0) {
203: defer (ccb_cleanup, 0);
204: free_active = 1;
205: }
206: spl (s);
207: }
208:
209:
210: /*
211: * Map from a ccb to the 'scsi_work_t' that was memoized when the ccb was
212: * allocated.
213: */
214:
215: #define ccb_to_scsiwork(ccb) (ccb->ccb_sw)
216:
217: /*
218: * NIGEL: Welcome back to Hack City. Beware of mutant code!
219: */
220:
221: #if 0
222: static
223: OUTB(port, value)
224: short port;
225: { printf("<O(%x,%x)>", port, value);
226: outb(port, value); }
227: INB(port)
228: short port;
229: { register int i = inb(port);
230: printf("<I(%x)=%x>", port, i);
231: return i; }
232: #else
233: #define OUTB(port, value) outb(port, value)
234: #define INB(port) inb(port)
235: #endif
236:
237: #ifdef TRACER
238: #define SETMSG(msg) aha_err_msg = msg
239:
240: static char *
241: aha_last_msg()
242: {
243: T_PIGGY(0x8000, return aha_err_msg;);
244:
245: return "error messages not verbose";
246: }
247:
248: #else /* TRACER */
249:
250: #define SETMSG(msg)
251: static char *
252: aha_last_msg()
253: {
254: return "error messages not verbose";
255: }
256: #endif /* TRACER */
257:
258: static
259: int
260: no_mem()
261: {
262: printf("aha154x: out of kernel memory\n");
263: }
264:
265: int
266: aha_set_base(base)
267: {
268: register int i;
269:
270: i = aha_i_o_base;
271: aha_i_o_base = base;
272: return i;
273: }
274:
275: int
276: aha_get_base()
277: {
278: return aha_i_o_base;
279: }
280:
281: aha_process(ccb)
282: ccb_t *ccb;
283: {
284: register scsi_work_t *sw;
285: register BUF *bp;
286:
287: if ((sw = ccb_to_scsiwork (ccb)) == NULL) {
288: ccb->opcode = AHA_OP_INVALID;
289: wakeup(ccb);
290: return;
291: }
292:
293: bp = sw->sw_bp;
294:
295: if((ccb->hoststatus != 0) || (ccb->targetstatus != 0)) {
296: if(--sw->sw_retry > 0
297: || (ccb->targetstatus == CHECK_TARGET_STATUS
298: && ccb->cmd_status[12] == SENSE_UNIT_ATTENTION)) {
299: int s = sphi();
300: if(scsi_work_queue->sw_actf == NULL) {
301: scsi_work_queue->sw_actf = sw;
302: } else {
303: scsi_work_queue->sw_actl->sw_actf = sw;
304: }
305: scsi_work_queue->sw_actl = sw;
306: spl(s);
307: aha_start();
308: return;
309: }
310: bp->b_flag |= BFERR;
311: } else {
312: bp->b_resid = 0;
313: }
314:
315: bdone(bp);
316: ccb_free(ccb);
317: }
318:
319: static
320: int aha_1out(value)
321: {
322: register int i;
323:
324: while((i = INB(aha_i_o_base + AHA_STATUS) & AHA_CDOPFULL) != 0)
325: if((i & AHA_INVDCMD)
326: || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE))
327: return -1;
328: OUTB(aha_i_o_base + AHA_WRITE, value);
329: return 0;
330: }
331:
332: static
333: int aha_1in()
334: {
335: register int i;
336:
337: while((i = INB(aha_i_o_base + AHA_STATUS) & AHA_DIPFULL) == 0)
338: if((i & AHA_INVDCMD)
339: || (INB(aha_i_o_base+AHA_INTERRUPT) & AHA_CMD_DONE))
340: return -1;
341: return INB(aha_i_o_base + AHA_READ) & 0xFF;
342: }
343:
344: static
345: void aha_cmd_out(value)
346: {
347: register long l;
348: register int i;
349:
350: for(l = aha_timeout[TIMEOUT_SENDCMD]; --l > 0;) {
351: if(((i=INB(aha_i_o_base + AHA_STATUS))
352: & AHA_SCSIIDLE) != 0) {
353: aha_1out(value);
354: return;
355: }
356: }
357: SETMSG("timeout sending cmd byte");
358: printf("aha154x: timeout sending cmd byte\n");
359: }
360:
361: static
362: int aha_poll()
363: {
364: register int i;
365: register int l = aha_timeout[TIMEOUT_POLL];
366: while((--l > 0)
367: && ((i = INB(aha_i_o_base + AHA_INTERRUPT)) & AHA_CMD_DONE) == 0)
368: ;
369: if(l == 0)
370: printf("aha154x: aha_poll timed out\n");
371:
372: i = INB(aha_i_o_base + AHA_STATUS);
373: OUTB(aha_i_o_base + AHA_CONTROL, AHA_INTRRESET);
374: return i;
375: }
376:
377: static
378: void aha_get_data(vec, cnt)
379: char *vec;
380: int cnt;
381: {
382: while(--cnt >= 0)
383: *vec++ = aha_1in();
384: aha_poll();
385: }
386:
387: static
388: int aha_present()
389: {
390: long l;
391:
392: if(INB(aha_i_o_base) == 0xFF) {
393: SETMSG("no adapter found at io base");
394: return -3;
395: }
396: for(l = aha_timeout[TIMEOUT_PRESENT];
397: (--l > 0) && (INB(aha_i_o_base + AHA_STATUS) & AHA_SELFTEST);)
398: ;
399: if(l == 0) {
400: SETMSG("selftest not completed");
401: return -1;
402: }
403: if(INB(aha_i_o_base + AHA_STATUS) & AHA_DIAGFAIL) {
404: SETMSG("diagnostics failed");
405: return -2;
406: }
407: if(INB(aha_i_o_base + AHA_STATUS) & AHA_INITMAIL) {
408: SETMSG("mailbox initialization needed");
409: return 1;
410: }
411: if(INB(aha_i_o_base + AHA_STATUS) & AHA_SCSIIDLE) {
412: SETMSG("adaptor okay, idle");
413: return 0;
414: }
415: SETMSG("unknown status at start");
416: return -4;
417: }
418:
419: void
420: aha_l_to_p3(value, vec)
421: paddr_t value;
422: P3 vec;
423: {
424: register int i;
425:
426: for(i = 3; --i >= 0;) {
427: vec[i] = value & 0xFF;
428: value >>= 8;
429: }
430: }
431:
432: long
433: aha_p3_to_l(vec)
434: P3 vec;
435: {
436: register int i;
437: register long retval;
438:
439: retval = 0;
440: for(i = 0; i < 3; ++i) {
441: retval <<= 8;
442: retval |= vec[i];
443: }
444:
445: return(retval);
446: } /* aha_p3_to_l() */
447:
448: #ifndef _I386 /* All of aha_p3_to_v(). */
449: static char *
450: aha_p3_to_v(vec)
451: P3 vec;
452: {
453: paddr_t adr;
454:
455: adr = vec[0];
456: adr <<= 16;
457: adr |= (vec[1]<<8) | vec[2];
458: adr -= sds_physical;
459: return (char *)adr;
460: }
461: #endif /* _I386 */
462:
463: aha_device_info()
464: {
465: register int i;
466: static char buf[256];
467:
468: aha_cmd_out(AHA_DO_GET_DEVICES);
469: aha_get_data(&buf[0], 8);
470: for(i = 0; i < 8; ++i)
471: if(buf[i] != 0)
472: printf("[%d] %x ", i, buf[i]);
473: printf("\n");
474: }
475:
476: int aha_unload(ireq)
477: {
478: /*
479: * we should really verify that everything
480: * out there gets flushed.
481: */
482: if (!aha_loaded)
483: return;
484: if(mailbox_out) {
485: AHA_FREE (mailbox_out);
486: mailbox_out = 0;
487: }
488: clrivec(ireq);
489: }
490:
491: int aha_load(dma, ireq, base, head)
492: scsi_work_t *head;
493: {
494: register int i;
495: unsigned char adr[4];
496:
497: aha_set_base(base);
498: if(mailbox_out == 0) {
499: if ((mailbox_out =
500: AHA_ALLOC (2 * MAX_MAILBOX * sizeof(mailentry))) == 0) {
501: no_mem();
502: return -1;
503: } else {
504: mailbox_in = &mailbox_out[MAX_MAILBOX];
505: }
506: }
507:
508: for(i = 0; i < MAX_MAILBOX; ++i)
509: mailbox_out[i].cmd = mailbox_in[i].cmd = 0;
510:
511: #ifdef _I386
512: aha_l_to_p3(vtop(mailbox_out), &adr[1]);
513: #else /* _I386 */
514: sds_physical = VTOP2(0, sds);
515: aha_l_to_p3(VTOP2(mailbox_out, sds), &adr[1]);
516: #endif /* _I386 */
517:
518: adr[0] = MAX_MAILBOX;
519:
520: /*
521: * setup HW
522: */
523: setivec(ireq, aha_intr);
524:
525: outb(0xD6, 0xC1); /* DMA is currently hard coded for */
526: outb(0xD4, 0x01); /* DMA channel 5 */
527:
528:
529: OUTB(aha_i_o_base+AHA_CONTROL, AHA_HARDRESET);
530: if (aha_present() < 0) {
531: printf("aha154x: initialization error or host adaptor not ");
532: printf("found at 0x%x\n", aha_i_o_base);
533: return -1;
534: }
535: aha_cmd_out(AHA_DO_MAILBOX_INIT);
536: for(i = 0; i < 4; ++i)
537: aha_1out(adr[i]);
538: scsi_work_queue = head;
539: ++aha_loaded;
540: return MAX_MAILBOX;
541: }
542:
543: aha_command(sc)
544: register scsi_cmd_t *sc;
545: {
546: register int i;
547: /* register */ ccb_t *ccb;
548:
549: short count = sc->blklen;
550: long block = sc->block;
551:
552: if ((ccb = ccb_alloc (NULL)) == NULL) {
553: no_mem();
554: return -1;
555: }
556:
557: #ifdef _I386
558: ccb->opcode = AHA_OP_SIC_SG; /* SCSI_INITIATOR*/
559: #else /* _I386 */
560: ccb->opcode = AHA_OP_SIC; /* SCSI_INITIATOR*/
561: #endif /* _I386 */
562: ccb->target = (sc->unit & 0x1C) << 3; /* SCSI ID */
563: ccb->target |= sc->unit & 0x3; /* LUN */
564: if((ccb->cmd_status[0] = sc->cmd) == ScmdWRITEXTENDED) {
565: ccb->target |= AHA_CCB_DATA_OUT;
566: } else { /* READEXT, READCAP, INQUIRY */
567: ccb->target |= AHA_CCB_DATA_IN;
568: }
569: ccb->cmd_status[1] = 0;
570: ccb->cmd_status[2] = block;
571: ccb->cmd_status[3] = block >>16;
572: ccb->cmd_status[4] = block >> 8;
573: ccb->cmd_status[5] = block;
574: ccb->cmd_status[6] = 0;
575: ccb->cmd_status[7] = count / 512;
576: ccb->cmd_status[8] = count;
577: ccb->cmd_status[9] = 0;
578: ccb->cmdlen = 10;
579: ccb->senselen = MAX_SENSEDATA;
580:
581: #ifdef _I386
582: dsl_gen(ccb->dataptr, ccb->datalen, sc->buffer, (long)sc->buflen);
583: aha_l_to_p3(vtop(ccb), mailbox_out[0].adr);
584: ccb_remember(ccb, mailbox_out[0].adr);
585: #else /* _I386 */
586: aha_l_to_p3((long)sc->buflen, ccb->datalen);
587: aha_l_to_p3(sc->buffer, ccb->dataptr);
588: aha_l_to_p3(VTOP2(ccb, sds), mailbox_out[0].adr);
589: #endif /* _I386 */
590:
591: mailbox_out[0].cmd = MBO_TO_START;
592:
593: /* Start the AHA-154x scanning the mailboxes. */
594: aha_1out(AHA_DO_SCSI_START);
595:
596: /* Wait for this ccb to finish. */
597: while(ccb->opcode != AHA_OP_INVALID) {
598: #ifdef _I386
599: x_sleep(ccb, pridisk, slpriNoSig, "aha:ccb");
600: #else
601: v_sleep(ccb, CVBLKIO, IVBLKIO, SVBLKIO, "aha:ccb");
602: #endif
603: /* The AHA-154x driver is waiting for a ccb to complete. */
604: }
605:
606: if((ccb->targetstatus == CHECK_TARGET_STATUS)
607: && (ccb->cmd_status[12] != SENSE_UNIT_ATTENTION)) {
608: printf("aha: SCSI ID %d LUN %d. SCSI sense =",
609: (sc->unit >> 2), sc->unit & 0x3);
610: for(i = 0; i < ccb->senselen; ++i)
611: printf(" %x", ccb->cmd_status[10+i]);
612: printf("\n");
613: }
614: i = ccb->hoststatus | ccb->targetstatus;
615:
616: /*
617: * NIGEL: If you are worried that the ccb memory is not getting freed
618: * soon enough, add a parameter to ccb_cleanup () to flag whether it
619: * should clear the active flag and call it directly here.
620: */
621: ccb_free(ccb);
622:
623: return i;
624: }
625:
626: ccb_t *buildccb(sw)
627: register scsi_work_t *sw;
628: {
629: register ccb_t *ccb;
630:
631: if ((ccb = ccb_alloc(sw)) == NULL)
632: return NULL;
633:
634: #ifdef _I386
635: ccb->opcode = AHA_OP_SIC_SG; /* SCSI_INITIATOR*/
636: #else /* _I386 */
637: ccb->opcode = AHA_OP_SIC; /* SCSI_INITIATOR*/
638: #endif /* _I386 */
639:
640: ccb->target = (sw->sw_drv & 0x1C) << 3; /* SCSI ID */
641: ccb->target |= (sw->sw_drv) & 0x3; /* LUN */
642: if(sw->sw_bp->b_req == BREAD) {
643: ccb->target |= AHA_CCB_DATA_IN;
644: ccb->cmd_status[0] = ScmdREADEXTENDED;
645: } else {
646: ccb->target |= AHA_CCB_DATA_OUT;
647: ccb->cmd_status[0] = ScmdWRITEXTENDED;
648: }
649: ccb->cmd_status[2] = 0;
650: ccb->cmd_status[3] = sw->sw_bno >>16;
651: ccb->cmd_status[4] = sw->sw_bno >> 8;
652: ccb->cmd_status[5] = sw->sw_bno;
653: ccb->cmd_status[6] = 0;
654: ccb->cmd_status[7] = sw->sw_bp->b_count / (512*256L);
655: ccb->cmd_status[8] = sw->sw_bp->b_count / 512;
656: ccb->cmd_status[9] = 0;
657: ccb->cmdlen = 10;
658: ccb->senselen = MAX_SENSEDATA;
659:
660: #ifdef _I386
661: dsl_gen(ccb->dataptr, ccb->datalen,
662: sw->sw_bp->b_paddr, (long)sw->sw_bp->b_count);
663: #else /* _I386 */
664: aha_l_to_p3((long)sw->sw_bp->b_count, ccb->datalen);
665: aha_l_to_p3(vtop(sw->sw_bp->b_faddr), ccb->dataptr);
666: #endif /* _I386 */
667: /*
668: * The ccb's returned here are going to be freed by aha_process ().
669: */
670: return ccb;
671: #if 0
672: /* start of ioctl code */
673: if(f == SASI_CMD_IN)
674: ccb->target |= AHA_CCB_DATA_IN;
675: else if(f == SASI_CMD_OUT)
676: ccb->target |= AHA_CCB_DATA_OUT;
677: else
678: ccb->target |= AHA_CCB_DATA_IN
679: |AHA_CCB_DATA_OUT;
680: #endif
681: }
682:
683: aha_start()
684: {
685: register int i, s, n = 0;
686: scsi_work_t *sw;
687: static char locked;
688:
689: s = sphi();
690: if(locked) {
691: spl(s);
692: return;
693: }
694: ++locked;
695: spl(s);
696:
697: while((sw = scsi_work_queue->sw_actf) != NULL) {
698: for(i = MIN_MAILBOX; i < MAX_MAILBOX; ++i)
699: if(mailbox_out[i].cmd == MBO_IS_FREE) {
700: register ccb_t *ccb;
701: int s;
702:
703: ++n;
704: if ((ccb = buildccb (sw)) == NULL) {
705: /*
706: * NIGEL: Earlier kernels did not
707: * diagnose this!
708: */
709: goto out_of_mem;
710: }
711: #ifdef _I386
712: aha_l_to_p3(vtop(ccb),
713: mailbox_out[i].adr);
714: ccb_remember(ccb, mailbox_out[i].adr);
715: #else /* _I386 */
716: aha_l_to_p3(VTOP2(ccb, sds),
717: mailbox_out[i].adr);
718: #endif /* _I386 */
719: mailbox_out[i].cmd = MBO_TO_START;
720:
721: aha_1out(AHA_DO_SCSI_START);
722:
723: s = sphi();
724: sw = scsi_work_queue->sw_actf = sw->sw_actf;
725: if(sw == NULL)
726: scsi_work_queue->sw_actl = NULL;
727: spl(s);
728:
729: if(sw == NULL)
730: break;
731: }
732: if(i == MAX_MAILBOX)
733: break;
734: }
735: out_of_mem:
736: --locked;
737: return n;
738: }
739:
740: int
741: aha_completed()
742: {
743: register int i, n;
744:
745: for(n = 0, i = 0; i < MAX_MAILBOX; ++i)
746: if(mailbox_in[i].cmd != MBI_IS_FREE) {
747: /*
748: * NIGEL: Earlier kernels deferred these, but with the
749: * ccb_free ()/ccb_alloc () system that is no longer
750: * necessary in either 4.x or 3.x systems.
751: */
752: #ifdef _I386
753: aha_process(ccb_recall(mailbox_in[i].adr));
754: #else /* _I386 */
755: aha_process(aha_p3_to_v(mailbox_in[i].adr));
756: #endif /* _I386 */
757: mailbox_in[i].cmd = MBI_IS_FREE;
758: ++n;
759: }
760: return n;
761: }
762:
763: void
764: aha_intr()
765: {
766: register int i;
767:
768: if(((i = INB(aha_i_o_base+AHA_INTERRUPT)) & AHA_ANY_INTER) == 0)
769: printf("aha: spurious interrupt %x\n", i);
770:
771: switch(i & AHA_ALL_INTERRUPTS) {
772: case AHA_RESETED:
773: break;
774: case AHA_CMD_DONE:
775: break;
776: case AHA_MBO_EMPTY:
777: defer(aha_start, (char *)0);
778: break;
779: case AHA_MBI_STORED:
780: aha_completed();
781: break;
782: default:
783: printf("aha: multiple interrupts not yet handled\n");
784: }
785: outb(aha_i_o_base+AHA_CONTROL, AHA_INTRRESET);
786: }
787:
788: aha_ioctl()
789: {
790: printf("aha_ioctl: Not implemented\n");
791: }
792:
793: #ifdef TRACER
794: static unsigned char vec[256];
795:
796: static aha_ports_are() {
797: printf("aha_ports_are: %x %x %x\n",
798: INB(aha_i_o_base+0),
799: INB(aha_i_o_base+1),
800: INB(aha_i_o_base+2));
801: }
802:
803: static aha_inquiry_is() {
804: printf("aha_inquiry:");
805: printf("... aha_present = %d, ", aha_present());
806: printf("%s\n", aha_last_msg());
807: aha_cmd_out(AHA_DO_INQUIRY);
808:
809: aha_get_data(&vec[0], 4);
810: printf(" board id '%c'", vec[0]);
811: printf(", options '%c'", vec[1]);
812: printf(", HW '%c'", vec[2]);
813: printf(", FW '%c'\n", vec[3]);
814: }
815:
816: void aha_setup_is() {
817: register int i;
818:
819: printf("Setup and Data:\n");
820: aha_cmd_out(AHA_DO_GET_SETUP);
821: aha_cmd_out(16);
822: aha_get_data(&vec[0], 16);
823: printf(" Data Xfer %s Sync (J1)\n", (vec[0]&1) ? "is" : "not");
824: printf(" Parity %s Enabled (J1)\n", (vec[0]&2) ? "is" : "not");
825: switch(vec[1]) {
826: case AHA_SPEED_5_0_MB:
827: printf(" 5.0 Mb/sec.\n"); break;
828: case AHA_SPEED_6_7_MB:
829: printf(" 6.7 Mb/sec.\n"); break;
830: case AHA_SPEED_8_0_MB:
831: printf(" 8.0 Mb/sec.\n"); break;
832: case AHA_SPEED_10_MB:
833: printf(" 10 Mb/sec.\n"); break;
834: case AHA_SPEED_5_7_MB:
835: printf(" 5.7 Mb/sec.\n"); break;
836: default:
837: if(vec[1] & 0x80)
838: printf(" Pulse Read %d, Write %d, Strobe off %d\n",
839: 50*(2+(vec[1]>>4)&0x7), 50*(2+(vec[1]&7)),
840: vec[1] & 0x80 ? 150 : 100);
841: }
842: printf(" Bus Time ON %d, OFF %d\n", vec[2], vec[3]);
843: printf(" %d Mailboxes at %x|%x|%x\n", vec[4],
844: vec[5], vec[6], vec[7]);
845: for(i = 0; i < 8; ++i)
846: if(vec[i+8])
847: printf(" Target [%d] = Sync Neg %x\n", i, vec[i+8]);
848: }
849:
850: static aha_mailboxes_are(n, adr)
851: mailentry *adr;
852: {
853: register int i;
854:
855: printf("addresses for mailbox is %x:%x\n", (long)adr);
856: for(i = 0; i < n; ++i, ++adr)
857: printf(" mbo[%x] = %x %x|%x|%x\n",
858: i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2]);
859: for(i = 0; i < n; ++i, ++adr)
860: printf(" mbi[%x] = %x %x|%x|%x\n",
861: i, adr->cmd, adr->adr[0], adr->adr[1], adr->adr[2]);
862: }
863:
864: void aha_status()
865: {
866: aha_ports_are();
867: aha_inquiry_is();
868: /* aha_devices_are(); */ /* This appears to have never existed. */
869: aha_setup_is();
870: aha_mailboxes_are(MAX_MAILBOX, mailbox_out);
871: }
872:
873: aha_ccb_print(ccb)
874: ccb_t *ccb;
875: {
876: register int i;
877: register unsigned char *cp;
878:
879: printf("aha_ccb_print(ccb: %x)", ccb);
880: if (0 != ccb) {
881: printf(", sw: %x", ccb->ccb_sw);
882: if (0 != ccb->ccb_sw) {
883: printf(", bp: %x", ccb->ccb_sw->sw_bp);
884: if (0 != ccb->ccb_sw->sw_bp) {
885: printf(", flag: %x",
886: ccb->ccb_sw->sw_bp->b_flag);
887: }
888: }
889: printf(", op %d, ", ccb->opcode);
890: printf("target ID=%d, ", (ccb->target>>5) & 0x7);
891: printf("LUN=%d, ", (ccb->target & 0x7));
892: printf("dir=%s%s\n", (ccb->target&AHA_CCB_DATA_IN)?"IN":"",
893: (ccb->target&AHA_CCB_DATA_OUT)?"OUT":"");
894: printf("data len %x|%x|%x, adr %x|%x|%x\n",
895: ccb->datalen[0],ccb->datalen[1],ccb->datalen[2],
896: ccb->dataptr[0],ccb->dataptr[1],ccb->dataptr[2]);
897: printf("status host=%x, target=%x\n",
898: ccb->hoststatus, ccb->targetstatus);
899: printf("cmddata[%d]:", ccb->cmdlen);
900: for(i = 0, cp = ccb->cmd_status; i < ccb->cmdlen; ++i)
901: printf(" %x", *cp++);
902: printf("\nrequest sense[%d]:", ccb->senselen);
903: for(i = 0; i < ccb->senselen; ++i)
904: printf(" %x", *cp++);
905: if(i = cp[-1]) {
906: printf("\n + ");
907: while(--i >= 0)
908: printf(" %x", *cp++);
909: }
910: printf("\n");
911: }
912: }
913:
914: #endif /* TRACER */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.