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