|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)sc.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: #include "sc.h"
10:
11: #if NSC > 0
12: /*
13: * Generic scsi routines.
14: */
15:
16: #include "../h/param.h"
17: #include "../h/systm.h"
18: #include "../h/dk.h"
19: #include "../h/buf.h"
20: #include "../h/conf.h"
21: #include "../h/dir.h"
22: #include "../h/user.h"
23: #include "../h/map.h"
24: #include "../h/vmmac.h"
25: /*
26: *#include "../h/ioctl.h"
27: *#include "../h/uio.h"
28: *#include "../h/kernel.h"
29: */
30: #include "../h/dkbad.h"
31:
32: #include "../machine/pte.h"
33: #include "../machine/psl.h"
34: #include "../machine/mmu.h"
35: #include "../machine/cpu.h"
36: #include "../machine/scb.h"
37:
38: #include "../sun/dklabel.h"
39: #include "../sun/dkio.h"
40:
41: #include "../sundev/mbvar.h"
42: #include "../sundev/screg.h"
43: #include "../sundev/sireg.h"
44: #include "../sundev/scsi.h"
45:
46: struct scsi_ctlr scctlrs[NSC];
47: #define SCNUM(sc) (sc - scctlrs)
48:
49: int scprobe(), scslave(), scattach(), scgo(), scdone(), scpoll();
50: int scustart(), scstart(), sc_cmd(), sc_getstatus(), sc_cmdwait();
51: int sc_off(), sc_reset(), sc_dmacnt();
52:
53: struct mb_ctlr *scinfo[NSC];
54: extern struct mb_device *sdinfo[];
55: struct mb_driver scdriver = {
56: scprobe, scslave, scattach, scgo, scdone, scpoll,
57: sizeof (struct scsi_ha_reg), "sd", sdinfo, "sc", scinfo, MDR_BIODMA,
58: };
59:
60: /* routines available to devices for mainbus scsi host adaptor */
61: struct scsi_ctlr_subr scsubr = {
62: scustart, scstart, scdone, sc_cmd, sc_getstatus, sc_cmdwait,
63: sc_off, sc_reset, sc_dmacnt, scgo,
64: };
65:
66: extern int scsi_debug;
67: extern int scsi_ntype;
68: extern struct scsi_unit_subr scsi_unit_subr[];
69:
70: /*
71: * Determine existence of SCSI host adapter.
72: */
73: scprobe(reg, ctlr)
74: register struct scsi_ha_reg *reg;
75: register int ctlr;
76: {
77: register struct scsi_ctlr *c;
78:
79: /* probe for different scsi host adaptor interfaces */
80: c = &scctlrs[ctlr];
81: if (peekc((char *)®->dma_count) == -1) {
82: return (0);
83: }
84: reg->dma_count = 0x6789;
85: if (reg->dma_count != 0x6789) {
86: return (0);
87: }
88:
89: /* allocate memory for sense information */
90: c->c_sense = (struct scsi_sense *) rmalloc(iopbmap,
91: (long) sizeof (struct scsi_sense));
92: if (c->c_sense == NULL) {
93: printf("scprobe: no iopb memory for sense.\n");
94: return (0);
95: }
96:
97: /* init controller information */
98: c->c_flags = SCSI_PRESENT;
99: c->c_har = reg;
100: c->c_ss = &scsubr;
101: sc_reset(c);
102: return (sizeof (struct scsi_ha_reg));
103: }
104:
105: /*
106: * See if a slave exists.
107: * Since it may exist but be powered off, we always say yes.
108: */
109: /*ARGSUSED*/
110: scslave(md, reg)
111: struct mb_device *md;
112: register struct scsi_ha_reg *reg;
113: {
114: register struct scsi_unit *un;
115: register int type;
116:
117: /*
118: * This kludge allows autoconfig to print out "sd" for
119: * disks and "st" for tapes. The problem is that there
120: * is only one md_driver for scsi devices.
121: */
122: type = TYPE(md->md_flags);
123: if (type >= scsi_ntype) {
124: panic("scslave: unknown type in md_flags");
125: }
126:
127: /* link unit to its controller */
128: un = (struct scsi_unit *)(*scsi_unit_subr[type].ss_unit_ptr)(md);
129: if (un == 0) {
130: panic("scslave: md_flags scsi type not configured in\n");
131: }
132: un->un_c = &scctlrs[md->md_ctlr];
133: md->md_driver->mdr_dname = scsi_unit_subr[type].ss_devname;
134: return (1);
135: }
136:
137: /*
138: * Attach device (boot time).
139: */
140: scattach(md)
141: register struct mb_device *md;
142: {
143: register struct mb_ctlr *mc = md->md_mc;
144: register struct scsi_ctlr *c = &scctlrs[md->md_ctlr];
145: register int type = TYPE(md->md_flags);
146:
147: if (type >= scsi_ntype) {
148: panic("scattach: unknown type in md_flags");
149: }
150: (*scsi_unit_subr[type].ss_attach)(md);
151:
152: /*
153: * Initialize interrupt register
154: */
155: if (mc->mc_intr) {
156: /* set up for vectored interrupts - we will pass ctlr ptr */
157: c->c_har->intvec = mc->mc_intr->v_vec;
158: *(mc->mc_intr->v_vptr) = (int)c;
159: } else {
160: /* use auto-vectoring */
161: c->c_har->intvec = AUTOBASE + mc->mc_intpri;
162: }
163: }
164:
165: /*
166: * SCSI unit start routine.
167: * Called by SCSI device drivers.
168: */
169: scustart(un)
170: register struct scsi_unit *un;
171: {
172: register struct buf *dp;
173: register struct mb_ctlr *mc;
174:
175: mc = un->un_mc;
176: dp = &un->un_utab;
177: /*
178: * Caller guarantees: dp->b_actf != NULL && dp->b_active == 0
179: */
180: /*
181: * Put device on ready queue for bus.
182: */
183: if (mc->mc_tab.b_actf == NULL) {
184: mc->mc_tab.b_actf = dp;
185: } else {
186: mc->mc_tab.b_actl->b_forw = dp;
187: }
188: dp->b_forw = NULL;
189: mc->mc_tab.b_actl = dp;
190: dp->b_active = 1;
191: dp->b_un.b_addr = (caddr_t) un;
192: }
193:
194: /*
195: * Set up a transfer for the bus.
196: */
197: scstart(un)
198: register struct scsi_unit *un;
199: {
200: register struct mb_ctlr *mc;
201: register struct buf *bp, *dp;
202:
203: mc = un->un_mc;
204: dp = mc->mc_tab.b_actf; /* != NULL guaranteed by caller */
205: un = (struct scsi_unit *) dp->b_un.b_addr;
206: bp = dp->b_actf;
207: for (;;) {
208: if (bp == NULL) { /* no more blocks for this device */
209: un->un_utab.b_active = 0;
210: dp = mc->mc_tab.b_actf = dp->b_forw;
211: if (dp == NULL) { /* no more devices for this ctlr */
212: return;
213: }
214: un = (struct scsi_unit *) dp->b_un.b_addr;
215: bp = dp->b_actf;
216: } else {
217: if ((*un->un_ss->ss_start)(bp, un)) {
218: mc->mc_tab.b_active = 1;
219: un->un_c->c_un = un;
220: if (bp == &un->un_sbuf &&
221: ((un->un_flags & SC_UNF_DVMA) == 0)) {
222: scgo(mc);
223: } else {
224: (void) mbgo(mc);
225: }
226: return;
227: }
228: dp->b_actf = bp = bp->av_forw;
229: }
230: }
231: }
232:
233: /*
234: * Start up a transfer
235: * Called via mbgo after buffer is in memory
236: */
237: scgo(mc)
238: register struct mb_ctlr *mc;
239: {
240: register struct scsi_unit *un;
241: register struct scsi_ctlr *c;
242: register struct buf *bp, *dp;
243: register int unit;
244:
245: c = &scctlrs[mc->mc_ctlr];
246: dp = mc->mc_tab.b_actf;
247: if (dp == NULL || dp->b_actf == NULL) {
248: panic("scgo queueing error 1");
249: }
250: bp = dp->b_actf;
251: un = c->c_un;
252: if (dp != &un->un_utab) {
253: panic("scgo queueing error 2");
254: }
255: un->un_baddr = MBI_ADDR(mc->mc_mbinfo);
256: if ((unit = un->un_md->md_dk) >= 0) {
257: dk_busy |= 1<<unit;
258: dk_xfer[unit]++;
259: dk_wds[unit] += bp->b_bcount >> 6;
260: }
261: (*un->un_ss->ss_mkcdb)(c, un);
262: if (sc_cmd(c, un, 1) == 0) {
263: (*un->un_ss->ss_intr)(c, 0, SE_RETRYABLE);
264: sc_off(un);
265: }
266: }
267:
268: /*
269: * Pass a command to the SCSI bus.
270: */
271: sc_cmd(c, un, intr)
272: register struct scsi_ctlr *c;
273: register struct scsi_unit *un;
274: register int intr;
275: {
276: register u_char *cp;
277: register int i, errct;
278: register u_short icr_mode;
279:
280: errct = 0;
281: do {
282: /* make sure scsi bus is not continuously busy */
283: for (i = WAIT_COUNT; i > 0; i--) {
284: if (!(c->c_har->icr & ICR_BUSY))
285: break;
286: DELAY(10);
287: }
288: if (i == 0) {
289: sc_reset(c);
290: return (0);
291: }
292:
293: /* select target and wait for response */
294: c->c_har->data = (1 << un->un_target) | HOST_ADDR;
295: c->c_har->icr = ICR_SELECT;
296:
297: /* target never responded to selection */
298: if (sc_wait(c, ICR_BUSY) == 0) {
299: c->c_har->data = 0;
300: c->c_har->icr = 0;
301: return (0);
302: }
303: /*
304: * may need to map between the CPU's kernel context address
305: * and the device's DVMA bus address
306: */
307: c->c_har->dma_addr = un->un_dma_addr;
308: c->c_har->dma_count = ~un->un_dma_count; /* hardware is funny */
309: icr_mode = ICR_DMA_ENABLE;
310: if (intr) {
311: icr_mode |= ICR_INTERRUPT_ENABLE;
312: un->un_wantint = 1;
313: }
314: if (! (un->un_dma_count & 1)) {
315: icr_mode |= ICR_WORD_MODE;
316: }
317: c->c_har->icr = icr_mode;
318: cp = (u_char *) &c->c_cdb;
319: if (scsi_debug) {
320: printf("sc%d: sc_cmd: target %d issuing command ",
321: SCNUM(c), un->un_target);
322: for (i = 0; i < sizeof (struct scsi_cdb); i++) {
323: printf("%x ", *cp++);
324: }
325: printf("\n");
326: cp = (u_char *) &c->c_cdb;
327: }
328: for (i = 0; i < sizeof (struct scsi_cdb); i++) {
329: if (sc_putbyte(c, ICR_COMMAND, *cp++) == 0) {
330: errct++;
331: break;
332: }
333: }
334: if (i == sizeof (struct scsi_cdb)) {
335: return (1);
336: }
337: } while (errct < 5);
338: printf("sc_cmd: unrecoverable errors\n");
339: return (0);
340: }
341:
342: /*
343: * Handle a scsi bus interrupt for the mainbus scsi.
344: */
345: scintr(c)
346: register struct scsi_ctlr *c;
347: {
348: register int resid;
349: register struct scsi_unit *un;
350:
351: un = c->c_un;
352: if (un->un_wantint == 0) {
353: if (c->c_har->icr & ICR_BUS_ERROR) {
354: printf("scsi bus error (unwanted interrupt)\n");
355: } else {
356: printf("scsi: unwanted interrupt\n");
357: }
358: sc_reset(c);
359: return;
360: }
361: un->un_wantint = 0;
362: resid = ~c->c_har->dma_count;
363: if (c->c_har->icr & ICR_BUS_ERROR) {
364: printf("scsi bus error. icr %x resid %d\n",
365: c->c_har->icr, resid);
366: sc_reset(c);
367: (*c->c_un->un_ss->ss_intr)(c, resid, SE_FATAL);
368: return;
369: }
370: if (c->c_har->icr & ICR_ODD_LENGTH) {
371: if ((c->c_cdb.cmd == SC_READ) ||
372: (c->c_cdb.cmd == SC_REQUEST_SENSE)) {
373: DVMA[un->un_baddr + un->un_dma_count - resid] =
374: c->c_har->data;
375: resid--;
376: } else if (c->c_cdb.cmd == SC_WRITE) {
377: resid++;
378: } else {
379: printf("scsi: odd length without xfer\n");
380: }
381: }
382: if (resid < 0) {
383: panic("scsi resid");
384: }
385: if (sc_getstatus(c->c_un, 0) == 0) {
386: (*c->c_un->un_ss->ss_intr)(c, resid, SE_RETRYABLE);
387: } else {
388: (*c->c_un->un_ss->ss_intr)(c, resid, SE_NO_ERROR);
389: }
390: }
391:
392: /*
393: * Handle a polling SCSI bus interrupt.
394: */
395: scpoll()
396: {
397: register struct scsi_ctlr *c;
398: register int serviced = 0;
399:
400: for (c = scctlrs; c < &scctlrs[NSC]; c++) {
401: if ((c->c_flags & SCSI_PRESENT) == 0)
402: continue;
403: if ((c->c_har->icr & (ICR_INTERRUPT_REQUEST | ICR_BUS_ERROR))
404: == 0) {
405: continue;
406: }
407: serviced = 1;
408: scintr(c);
409: }
410: return (serviced);
411: }
412:
413: /*
414: * Clean up queues, free resources, and start next I/O
415: * all done after I/O finishes
416: * Called by mbdone after moving read data from Mainbus
417: */
418: scdone(mc)
419: register struct mb_ctlr *mc;
420: {
421: register struct buf *bp, *dp;
422: register struct scsi_unit *un;
423: register struct scsi_ctlr *c;
424:
425: bp = mc->mc_tab.b_actf->b_actf;
426: c = &scctlrs[mc->mc_ctlr];
427: un = c->c_un;
428:
429: /* advance controller queue */
430: dp = mc->mc_tab.b_actf;
431: mc->mc_tab.b_active = 0;
432: mc->mc_tab.b_actf = dp->b_forw;
433:
434: /* advance unit queue */
435: dp->b_active = 0;
436: dp->b_actf = bp->av_forw;
437:
438: iodone(bp);
439:
440: /* start next I/O on unit */
441: if (dp->b_actf)
442: scustart(un);
443:
444: /* start next I/O on controller */
445: if (mc->mc_tab.b_actf && mc->mc_tab.b_active == 0)
446: scstart(un);
447: }
448:
449: /*ARGSUSED*/
450: sc_off(un)
451: struct scsi_unit *un;
452: {
453:
454: #ifdef notdef
455: /* if done to root real bad things happen... */
456: un->un_present = 0;
457: printf("scsi unit %d/%d offline\n", un->un_target, un->un_lun);
458: if (un->un_md->md_dk > 0) {
459: dk_mspw[un->un_md->md_dk]=0;
460: }
461: #endif
462: }
463:
464: /*
465: * Wait for a condition on the scsi bus.
466: */
467: sc_wait(c, cond)
468: register struct scsi_ctlr *c;
469: {
470: register struct scsi_ha_reg *har = c->c_har;
471: register int i, icr;
472:
473: for (i = 0; i < WAIT_COUNT; i++) {
474: icr = har->icr;
475: if ((icr & cond) == cond) {
476: return (1);
477: }
478: if (icr & ICR_BUS_ERROR) {
479: break;
480: }
481: DELAY(10);
482: }
483: return (0);
484: }
485:
486: /*
487: * Wait for the completion of a scsi command.
488: */
489: sc_cmdwait(c)
490: register struct scsi_ctlr *c;
491: {
492: if (sc_wait(c, ICR_INTERRUPT_REQUEST) == 0) {
493: sc_reset(c);
494: return(0);
495: } else {
496: return(1);
497: }
498: }
499:
500: /*
501: * Put a byte into the scsi command register.
502: */
503: sc_putbyte(c, bits, data)
504: register struct scsi_ctlr *c;
505: register u_short bits;
506: register u_char data;
507: {
508: register struct scsi_ha_reg *har = c->c_har;
509: register int icr;
510:
511: if (sc_wait(c, ICR_REQUEST) == 0) {
512: sc_reset(c);
513: return (0);
514: }
515: icr = har->icr;
516: if ((icr & ICR_BITS) != bits) {
517: #ifdef SCSI_DEBUG
518: printf("sc_putbyte error.\n");
519: sc_pr_icr("icr is ", icr);
520: sc_pr_icr("waiting for", bits);
521: #endif SCSI_DEBUG
522: sc_reset(c);
523: return (0);
524: }
525: har->cmd_stat = data;
526: return (1);
527: }
528:
529: /*
530: * Get a byte from the scsi command/status register.
531: */
532: sc_getbyte(c, bits)
533: register struct scsi_ctlr *c;
534: {
535: register struct scsi_ha_reg *har = c->c_har;
536: register int icr;
537:
538: if (sc_wait(c, ICR_REQUEST) == 0) {
539: sc_reset(c);
540: return (-1);
541: }
542: icr = har->icr;
543: if ((icr & ICR_BITS) != bits) {
544: if (bits == ICR_STATUS) {
545: return (-1); /* no more status */
546: }
547: #ifdef SCSI_DEBUG
548: printf("sc_getbyte error.\n");
549: sc_pr_icr("icr is ", icr);
550: sc_pr_icr("waiting for", bits);
551: #endif SCSI_DEBUG
552: sc_reset(c);
553: return (-1);
554: }
555: return (har->cmd_stat);
556: }
557:
558: sc_dmacnt(c)
559: register struct scsi_ctlr *c;
560: {
561: return (~c->c_har->dma_count);
562: }
563:
564: sc_reset(c)
565: register struct scsi_ctlr *c;
566: {
567: register struct scsi_ha_reg *har = c->c_har;
568:
569: har->icr = ICR_RESET;
570: DELAY(50);
571: har->icr = 0;
572: #ifdef SCSI_DEBUG
573: printf("scsi host adapter reset\n");
574: #endif SCSI_DEBUG
575: }
576:
577: /*
578: * Get status bytes from scsi bus.
579: */
580: sc_getstatus(un, recurse)
581: register struct scsi_unit *un;
582: {
583: register struct scsi_ctlr *c = un->un_c;
584: register u_char *cp = (u_char *)&c->c_scb;
585: struct scsi_cdb save_cdb;
586: struct scsi_scb save_scb;
587: register int i;
588: register int b;
589: register int save_dma_addr;
590: register int save_dma_count;
591: register int save_reg_dma_count;
592: int resid;
593: short retval = 1;
594: int s;
595:
596: /* get all the status bytes */
597: for (i = 0;;) {
598: b = sc_getbyte(c, ICR_STATUS);
599: if (b < 0) {
600: break;
601: }
602: if (i < STATUS_LEN) {
603: cp[i++] = b;
604: }
605: }
606:
607: /* get command complete message */
608: b = sc_getbyte(c, ICR_MESSAGE_IN);
609: if (b != SC_COMMAND_COMPLETE) {
610: if (scsi_debug) {
611: printf("Invalid SCSI message: %x\n", b);
612: printf("Status bytes:");
613: for (b = 0; b < i; b++) {
614: printf(" %x", cp[b]);
615: }
616: printf("\n");
617: }
618: return (0);
619: }
620: if (scsi_debug) {
621: printf("sc%d: sc_getstatus: Got status ", SCNUM(c));
622: for (b = 0; b < i; b++) {
623: printf(" %x", cp[b]);
624: }
625: printf("\n");
626: }
627: if (c->c_scb.busy) {
628: return (0);
629: }
630:
631: /* check for sense data */
632: if (c->c_scb.chk) {
633: if (recurse) {
634: printf("scsi: chk on sense: invalid\n");
635: return (0);
636: }
637:
638: /* save information while we get sense */
639: save_cdb = c->c_cdb;
640: save_scb = c->c_scb;
641: save_dma_addr = un->un_dma_addr;
642: save_dma_count = un->un_dma_count;
643: save_reg_dma_count = c->c_har->dma_count;
644:
645: /* set up for getting sense */
646: c->c_cdb.cmd = SC_REQUEST_SENSE;
647: c->c_cdb.lun = un->un_lun;
648: cdbaddr(&c->c_cdb, 0);
649: c->c_cdb.count = sizeof(struct scsi_sense);
650: un->un_dma_addr = (int)c->c_sense - (int)DVMA;
651: un->un_dma_count = sizeof(struct scsi_sense);
652:
653: /* get sense */
654: if ((s=0),sc_cmd(c, un, 0) == 0 ||
655: (s=1),sc_cmdwait(c) == 0 ||
656: (s=2),sc_getstatus(un, 1) == 0) {
657: printf("scsi: cannot get sense %d\n", s);
658: sc_off(un);
659: retval = 0;
660: }
661: resid = ~c->c_har->dma_count;
662: if (resid < 0) {
663: printf("scsi: dma_count %x resid %d",
664: c->c_har->dma_count, resid);
665: panic("scsi sense count too big.");
666: }
667:
668: /* restore pre sense information */
669: c->c_cdb = save_cdb;
670: c->c_scb = save_scb;
671: un->un_dma_addr = save_dma_addr;
672: un->un_dma_count = save_dma_count;
673: c->c_har->dma_count = save_reg_dma_count;
674: }
675: return (retval);
676: }
677:
678: #ifdef SCSI_DEBUG
679: /*
680: * Print out the scsi host adapter interface control register.
681: */
682: sc_pr_icr(cp, i)
683: register char *cp;
684: {
685: printf("\t%s: %x ", cp, i);
686: if (i & ICR_PARITY_ERROR)
687: printf("Parity err ");
688: if (i & ICR_BUS_ERROR)
689: printf("Bus err ");
690: if (i & ICR_ODD_LENGTH)
691: printf("Odd len ");
692: if (i & ICR_INTERRUPT_REQUEST)
693: printf("Int req ");
694: if (i & ICR_REQUEST) {
695: printf("Req ");
696: switch (i & ICR_BITS) {
697: case 0:
698: printf("Data out ");
699: break;
700: case ICR_INPUT_OUTPUT:
701: printf("Data in ");
702: break;
703: case ICR_COMMAND_DATA:
704: printf("Command ");
705: break;
706: case ICR_COMMAND_DATA | ICR_INPUT_OUTPUT:
707: printf("Status ");
708: break;
709: case ICR_MESSAGE | ICR_COMMAND_DATA:
710: printf("Msg out ");
711: break;
712: case ICR_MESSAGE | ICR_COMMAND_DATA | ICR_INPUT_OUTPUT:
713: printf("Msg in ");
714: break;
715: default:
716: printf("DCM: %x ", i & ICR_BITS);
717: break;
718: }
719: }
720: if (i & ICR_PARITY)
721: printf("Parity ");
722: if (i & ICR_BUSY)
723: printf("Busy ");
724: if (i & ICR_SELECT)
725: printf("Sel ");
726: if (i & ICR_RESET)
727: printf("Reset ");
728: if (i & ICR_PARITY_ENABLE)
729: printf("Par ena ");
730: if (i & ICR_WORD_MODE)
731: printf("Word mode ");
732: if (i & ICR_DMA_ENABLE)
733: printf("Dma ena ");
734: if (i & ICR_INTERRUPT_ENABLE)
735: printf("Int ena ");
736: printf("\n");
737: }
738:
739: /*
740: * Print out status completion block.
741: */
742: sc_pr_scb(scbp)
743: register struct scsi_scb *scbp;
744: {
745: register u_char *cp;
746:
747: cp = (u_char *) scbp;
748: printf("scb: %x", cp[0]);
749: if (scbp->ext_st1) {
750: printf(" %x", cp[1]);
751: if (scbp->ext_st2) {
752: printf(" %x", cp[2]);
753: }
754: }
755: if (scbp->is) {
756: printf(" intermediate status");
757: }
758: if (scbp->busy) {
759: printf(" busy");
760: }
761: if (scbp->cm) {
762: printf(" condition met");
763: }
764: if (scbp->chk) {
765: printf(" check");
766: }
767: if (scbp->ext_st1 && scbp->ha_er) {
768: printf(" host adapter detected error");
769: }
770: printf("\n");
771: }
772: #endif SCSI_DEBUG
773: #endif NSC > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.