|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)si.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 "si.h"
10:
11: #if NSI > 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 sictlrs[NSI];
47: #define SINUM(si) (si - sictlrs)
48:
49: int siprobe(), sislave(), siattach(), sigo(), sidone(), sipoll();
50: int siustart(), sistart(), si_getstatus();
51: int si_off(), si_cmd(), si_cmdwait(), si_reset(), si_dmacnt();
52:
53: struct mb_ctlr *siinfo[NSI];
54: extern struct mb_device *sdinfo[];
55: struct mb_driver sidriver = {
56: siprobe, sislave, siattach, sigo, sidone, sipoll,
57: sizeof (struct scsi_si_reg), "sd", sdinfo, "si", siinfo, MDR_BIODMA,
58: };
59:
60: /* routines available to devices specific portion of scsi driver */
61: struct scsi_ctlr_subr sisubr = {
62: siustart, sistart, sidone, si_cmd, si_getstatus, si_cmdwait,
63: si_off, si_reset, si_dmacnt, sigo,
64: };
65:
66: extern int scsi_debug; /* generic debug information */
67: extern int scsi_ntype;
68: extern struct scsi_unit_subr scsi_unit_subr[];
69:
70: int scsi_disre_enable = 0; /* enable disconnect/reconnect */
71: int scsi_dis_debug = 0; /* disconnect debug info */
72: int scsi_resel_debug = 0; /* reselection debug info */
73: int scsi_reset_debug = 0; /* scsi bus reset debug information */
74:
75: /*
76: * Determine existence of SCSI host adapter.
77: */
78: siprobe(reg, ctlr)
79: register struct scsi_si_reg *reg;
80: register int ctlr;
81: {
82: register struct scsi_ctlr *c;
83:
84: /* probe for different scsi host adaptor interfaces */
85: c = &sictlrs[ctlr];
86:
87: /*
88: * Check for sbc - NCR 5380 Scsi Bus Ctlr chip.
89: * sbc is common to sun3/50 onboard scsi and vme
90: * scsi board.
91: */
92: if (peekc(®->sbc_rreg.cbsr) == -1) {
93: return (0);
94: }
95:
96: /*
97: * Determine whether the host adaptor interface is onboard or vme.
98: */
99: if (cpu == CPU_SUN3_50) {
100: /* probe for sun3/50 dma interface */
101: if (peek(®->udc_rdata) == -1)
102: return (0);
103: c->c_flags = SCSI_ONBOARD;
104: } else {
105: /*
106: * Probe for vme scsi card but make sure it is not
107: * the SC host adaptor interface. SI vme scsi host
108: * adaptor occupies 2K bytes in the vme address space.
109: * SC vme scsi host adaptor occupies 4K bytes in the
110: * vme address space. So, peek past 2K bytes to
111: * determine which host adaptor is there.
112: */
113: if (peek(®->dma_addr) == -1)
114: return (0);
115: if (peek((int)reg+0x800) != -1)
116: return (0);
117: c->c_flags = 0;
118: }
119:
120: /* allocate memory for sense information */
121: c->c_sense = (struct scsi_sense *) rmalloc(iopbmap,
122: (long) sizeof (struct scsi_sense));
123: if (c->c_sense == NULL) {
124: printf("siprobe: no iopb memory for sense.\n");
125: return (0);
126: }
127:
128: /* init controller information */
129: c->c_flags |= SCSI_PRESENT;
130: if (scsi_disre_enable)
131: c->c_flags |= SCSI_EN_DISCON;
132: c->c_sir = reg;
133: c->c_ss = &sisubr;
134: si_reset(c);
135: return (sizeof (struct scsi_si_reg));
136: }
137:
138:
139: /*
140: * See if a slave exists.
141: * Since it may exist but be powered off, we always say yes.
142: */
143: /*ARGSUSED*/
144: sislave(md, reg)
145: register struct mb_device *md;
146: register struct scsi_si_reg *reg;
147: {
148: register struct scsi_unit *un;
149: register int type;
150:
151: /*
152: * This kludge allows autoconfig to print out "sd" for
153: * disks and "st" for tapes. The problem is that there
154: * is only one md_driver for scsi devices.
155: */
156: type = TYPE(md->md_flags);
157: if (type >= scsi_ntype) {
158: panic("sislave: unknown type in md_flags");
159: }
160:
161: /* link unit to its controller */
162: un = (struct scsi_unit *)(*scsi_unit_subr[type].ss_unit_ptr)(md);
163: if (un == 0) {
164: panic("sislave: md_flags scsi type not configured in\n");
165: }
166: un->un_c = &sictlrs[md->md_ctlr];
167: md->md_driver->mdr_dname = scsi_unit_subr[type].ss_devname;
168: return (1);
169: }
170:
171: /*
172: * Attach device (boot time).
173: */
174: siattach(md)
175: register struct mb_device *md;
176: {
177: register int type = TYPE(md->md_flags);
178: register struct mb_ctlr *mc = md->md_mc;
179: register struct scsi_ctlr *c = &sictlrs[md->md_ctlr];
180:
181: if (type >= scsi_ntype) {
182: panic("siattach: unknown type in md_flags");
183: }
184: (*scsi_unit_subr[type].ss_attach)(md);
185:
186: if (c->c_flags & SCSI_ONBOARD) {
187: return;
188: }
189:
190: /*
191: * Initialize interrupt vector and address modifier register.
192: * Address modifier specifies standard supervisor data access
193: * with 24 bit vme addresses. May want to change this in the
194: * future to handle 32 bit vme addresses.
195: */
196: if (mc->mc_intr) {
197: /* setup for vectored interrupts - we will pass ctlr ptr */
198: c->c_sir->iv_am = (mc->mc_intr->v_vec & 0xff) |
199: VME_SUPV_DATA_24;
200: (*mc->mc_intr->v_vptr) = (int)c;
201: }
202: }
203:
204: /*
205: * SCSI unit start routine.
206: * Called by SCSI device drivers.
207: */
208: siustart(un)
209: register struct scsi_unit *un;
210: {
211: register struct buf *dp;
212: register struct mb_ctlr *mc;
213: register int s;
214:
215: mc = un->un_mc;
216: dp = &un->un_utab;
217: /*
218: * Caller guarantees: dp->b_actf != NULL && dp->b_active == 0
219: * Note: dp->b_active == 1 on a reconnect.
220: */
221: /*
222: * Put device on ready queue for bus.
223: */
224: if (mc->mc_tab.b_actf == NULL) {
225: mc->mc_tab.b_actf = dp;
226: } else {
227: mc->mc_tab.b_actl->b_forw = dp;
228: }
229: dp->b_forw = NULL;
230: mc->mc_tab.b_actl = dp;
231: dp->b_active = 1;
232: dp->b_un.b_addr = (caddr_t) un;
233: }
234:
235: /*
236: * Set up a scsi operation.
237: */
238: sistart(un)
239: register struct scsi_unit *un;
240: {
241: register struct mb_ctlr *mc;
242: register struct buf *bp, *dp;
243:
244: mc = un->un_mc;
245: dp = mc->mc_tab.b_actf; /* != NULL guaranteed by caller */
246: un = (struct scsi_unit *) dp->b_un.b_addr;
247: bp = dp->b_actf;
248: for (;;) {
249: if (bp == NULL) { /* no more blocks for this device */
250: un->un_utab.b_active = 0;
251: dp = mc->mc_tab.b_actf = dp->b_forw;
252: if (dp == NULL) { /* no more devices for this ctlr */
253: si_idle(un->un_c);
254: return;
255: }
256: un = (struct scsi_unit *) dp->b_un.b_addr;
257: bp = dp->b_actf;
258: } else {
259: if ((*un->un_ss->ss_start)(bp, un)) {
260: mc->mc_tab.b_active = 1;
261: un->un_c->c_un = un;
262: if (bp == &un->un_sbuf &&
263: ((un->un_flags & SC_UNF_DVMA) == 0)) {
264: sigo(mc);
265: } else {
266: (void) mbgo(mc);
267: }
268: return;
269: }
270: dp->b_actf = bp = bp->av_forw;
271: }
272: }
273: }
274:
275: /*
276: * Start up a scsi operation.
277: * Called via mbgo after buffer is in memory.
278: */
279: sigo(mc)
280: register struct mb_ctlr *mc;
281: {
282: register struct scsi_unit *un;
283: register struct scsi_ctlr *c;
284: register struct buf *bp, *dp;
285: register int unit;
286:
287: c = &sictlrs[mc->mc_ctlr];
288: dp = mc->mc_tab.b_actf;
289: if (dp == NULL || dp->b_actf == NULL) {
290: panic("sigo queueing error 1");
291: }
292: bp = dp->b_actf;
293: un = c->c_un;
294: if (dp != &un->un_utab) {
295: panic("sigo queueing error 2");
296: }
297: un->un_baddr = MBI_ADDR(mc->mc_mbinfo);
298: if ((unit = un->un_md->md_dk) >= 0) {
299: dk_busy |= 1<<unit;
300: dk_xfer[unit]++;
301: dk_wds[unit] += bp->b_bcount >> 6;
302: }
303: (*un->un_ss->ss_mkcdb)(c, un);
304: if (si_cmd(c, un, 1) == 0) {
305: (*un->un_ss->ss_intr)(c, 0, SE_FATAL);
306: si_off(un);
307: }
308: }
309:
310: /*
311: * Handle a polling SCSI bus interrupt.
312: */
313: sipoll()
314: {
315: register struct scsi_ctlr *c;
316: register int serviced = 0;
317:
318: for (c = sictlrs; c < &sictlrs[NSI]; c++) {
319: if ((c->c_flags & SCSI_PRESENT) == 0)
320: continue;
321: if ((c->c_sir->csr &
322: (SI_CSR_SBC_IP | SI_CSR_DMA_IP | SI_CSR_DMA_CONFLICT))
323: == 0) {
324: continue;
325: }
326: serviced = 1;
327: siintr(c);
328: }
329: return (serviced);
330: }
331:
332: /*
333: * Clean up queues, free resources, and start next I/O
334: * all done after I/O finishes
335: * Called by mbdone after moving read data from Mainbus
336: */
337: sidone(mc)
338: register struct mb_ctlr *mc;
339: {
340: register struct buf *bp, *dp;
341: register struct scsi_unit *un;
342: register struct scsi_ctlr *c;
343:
344: bp = mc->mc_tab.b_actf->b_actf;
345: c = &sictlrs[mc->mc_ctlr];
346: un = c->c_un;
347:
348: /* advance controller queue */
349: dp = mc->mc_tab.b_actf;
350: mc->mc_tab.b_active = 0;
351: mc->mc_tab.b_actf = dp->b_forw;
352:
353: /* advance unit queue */
354: dp->b_active = 0;
355: dp->b_actf = bp->av_forw;
356:
357: iodone(bp);
358:
359: /* start next I/O on unit */
360: if (dp->b_actf)
361: siustart(un);
362:
363: /* start next I/O on controller */
364: if (mc->mc_tab.b_actf && mc->mc_tab.b_active == 0) {
365: sistart(un);
366: } else {
367: c->c_un = NULL;
368: si_idle(c);
369: }
370: }
371:
372: /*ARGSUSED*/
373: si_off(un)
374: register struct scsi_unit *un;
375: {
376:
377: #ifdef notdef
378: /* if done to root real bad things happen... */
379: un->un_present = 0;
380: printf("scsi unit %d/%d offline\n", un->un_target, un->un_lun);
381: if (un->un_md->md_dk > 0) {
382: dk_mspw[un->un_md->md_dk]=0;
383: }
384: #endif
385: }
386:
387: /*
388: * Pass a command to the SCSI bus.
389: */
390: si_cmd(c, un, intr)
391: register struct scsi_ctlr *c;
392: register struct scsi_unit *un;
393: register int intr;
394: {
395: register u_char *cp;
396: register int i;
397: register int errct;
398: register struct scsi_si_reg *sir = c->c_sir;
399:
400: errct = 0;
401: do {
402: /* disallow disconnects if waiting for command completion */
403: if (intr == 0) {
404: c->c_flags &= ~SCSI_EN_DISCON;
405: } else {
406: if (scsi_disre_enable)
407: c->c_flags |= SCSI_EN_DISCON;
408: else
409: c->c_flags &= ~SCSI_EN_DISCON;
410: un->un_wantint = 1;
411: }
412:
413: /*
414: * For vme host adaptor interface, dma enable bit may
415: * be set to allow reconnect interrupts to come in.
416: * This must be disabled before arbitration/selection
417: * of target is done. Don't worry about re-enabling
418: * dma. If arb/sel fails, then si_idle() will re-enable.
419: * If arb/sel succeeds then handling of command will
420: * re-enable.
421: * Also, disallow sbc to accept reconnect attempts.
422: * Again, si_idle() will re-enable this if arb/sel fails.
423: * If arb/sel succeeds then we do not want to allow
424: * reconnects anyway.
425: */
426: if ((c->c_flags & SCSI_ONBOARD) == 0) {
427: sir->csr &= ~SI_CSR_DMA_EN;
428: }
429: sir->sbc_wreg.ser = 0;
430: c->c_flags &= ~SCSI_EN_RECON;
431:
432: /* performing target selection */
433: if (si_arb_sel(c, un) == 0) {
434: goto bad;
435: }
436:
437: /*
438: * Must split dma setup into 2 parts due to sun3/50
439: * which requires bcr to be set before target
440: * changes phase on scsi bus to data phase.
441: *
442: * Three fields in the per scsi unit structure
443: * hold information pertaining to the current dma
444: * operation: un_dma_curdir, un_dma_curaddr, and
445: * un_dma_curcnt. These fields are used to track
446: * the amount of data dma'd especially when disconnects
447: * and reconnects occur.
448: * If the current command does not involve dma,
449: * these fields are set appropriately.
450: */
451: if (un->un_dma_count > 0) {
452: if ((c->c_cdb.cmd == SC_READ) ||
453: (c->c_cdb.cmd == SC_REQUEST_SENSE)) {
454: un->un_dma_curdir = SI_RECV_DATA;
455: sir->csr &= ~SI_CSR_SEND;
456: } else {
457: un->un_dma_curdir = SI_SEND_DATA;
458: sir->csr |= SI_CSR_SEND;
459: }
460: /* save current dma info for disconnect */
461: un->un_dma_curaddr = un->un_dma_addr;
462: un->un_dma_curcnt = un->un_dma_count;
463:
464: /* tape has scsi id of 4 */
465: if ((un->un_target == 4) && scsi_dis_debug) {
466: printf("si_cmd: cmd= %x, addr= %x, cnt= %x\n",
467: c->c_cdb.cmd, un->un_dma_curaddr,
468: un->un_dma_curcnt);
469: }
470:
471: /* reset fifo */
472: sir->csr &= ~SI_CSR_FIFO_RES;
473: sir->csr |= SI_CSR_FIFO_RES;
474:
475: /* must init bcr before target goes into data phase */
476: sir->bcr = un->un_dma_curcnt;
477:
478: /*
479: * Currently we don't use all 24 bits of the
480: * count register on the vme interface. To do
481: * this changes are required other places, e.g.
482: * in the scsi_unit structure the fields
483: * un_dma_curcnt and un_dma_count would need to
484: * be changed.
485: */
486: if ((c->c_flags & SCSI_ONBOARD) == 0) {
487: sir->bcrh = 0;
488: }
489: } else {
490: un->un_dma_curdir = SI_NO_DATA;
491: un->un_dma_curaddr = 0;
492: un->un_dma_curcnt = 0;
493: }
494:
495: cp = (u_char *) &c->c_cdb;
496: if (scsi_debug) {
497: printf("si%d: si_cmd: target %d issuing command ",
498: SINUM(c), un->un_target);
499: for (i = 0; i < sizeof (struct scsi_cdb); i++) {
500: printf("%x ", *cp++);
501: }
502: printf("\n");
503: cp = (u_char *) &c->c_cdb;
504: }
505:
506: /* put scsi command out on scsi bus */
507: if (si_putdata(c, PHASE_COMMAND, cp, sizeof(struct scsi_cdb))
508: == 0) {
509: errct++;
510: } else {
511: /* do final dma setup and start dma operation */
512: if (un->un_dma_count > 0) {
513: if (c->c_flags & SCSI_ONBOARD)
514: si_ob_dma_setup(c, un);
515: else
516: si_vme_dma_setup(c, un);
517: } else if (un->un_wantint) {
518: /*
519: * If this command does not involve
520: * any dma, we must set things up
521: * so we get an interrupt when the
522: * target is ready to give us status.
523: * The interrupt we get is a phase
524: * mismatch, however, to get this
525: * interrupt the sbc must be in dma
526: * mode. Also, the vme scsi card does
527: * not generate any interrupts unless
528: * dma is enabled in the csr.
529: */
530: sir->sbc_wreg.mr |= SBC_MR_DMA;
531: sir->sbc_wreg.tcr = TCR_UNSPECIFIED;
532: if ((c->c_flags & SCSI_ONBOARD) == 0) {
533: sir->csr &= ~SI_CSR_SEND;
534: sir->csr |= SI_CSR_DMA_EN;
535: }
536: }
537: return (1);
538: }
539: } while (errct < SI_NUM_RETRIES);
540:
541: /* clear fields if we were not able to issue scsi cmd */
542: printf("si_cmd: too many errors\n");
543: if (un->un_dma_count != 0) {
544: un->un_dma_curdir = 0;
545: un->un_dma_curaddr = 0;
546: un->un_dma_curcnt = 0;
547: sir->bcr = 0;
548: sir->csr &= ~SI_CSR_SEND;
549: }
550: bad:
551: un->un_wantint = 0;
552: si_idle(c);
553: return (0);
554: }
555:
556: /*
557: * Perform the SCSI arbitration and selection phases.
558: */
559: si_arb_sel(c, un)
560: register struct scsi_ctlr *c;
561: register struct scsi_unit *un;
562: {
563: register struct scsi_si_reg *sir = c->c_sir;
564: register u_char *icrp = &sir->sbc_wreg.icr;
565: register u_char *mrp = &sir->sbc_wreg.mr;
566: register int j;
567: register u_char icr;
568: u_char id;
569:
570: /* wait for scsi bus to become free */
571: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_BSY, 0) == 0) {
572: printf("si_arb_sel: continuously busy\n");
573: si_reset(c);
574: return (0);
575: }
576:
577: /* arbitrate for the scsi bus */
578: sir->sbc_wreg.odr = SI_HOST_ID;
579: for (j = 0; j < SI_NUM_RETRIES; j++) {
580: *mrp |= SBC_MR_ARB;
581:
582: /* wait for sbc to begin arbitration */
583: if (si_sbc_wait((caddr_t)icrp, SBC_ICR_AIP, 1) == 0) {
584: /* problem with sbc if arb never begins */
585: /*
586: * Current bug in Emulex MT02 firmware.
587: * It does not go through the reselection timeout
588: * procedure documented in the scsi protocol spec.
589: */
590: if ((sir->sbc_rreg.cbsr & SBC_CBSR_SEL) &&
591: (sir->sbc_rreg.cbsr & SBC_CBSR_IO) &&
592: (sir->sbc_rreg.cdr & SI_HOST_ID)) {
593: printf("si_arb_sel: REselect, flgs %x\n",
594: c->c_flags);
595: if (scsi_resel_debug) halt("");
596: } else {
597: printf("si_arb_sel: AIP never set, ??\n");
598: }
599:
600: *mrp &= ~SBC_MR_ARB;
601: return (0);
602: /* si_reset(c); */
603: }
604:
605: /* check to see if we won arbitration */
606: DELAY(SI_ARBITRATION_DELAY);
607: if ((*icrp & SBC_ICR_LA) == 0) {
608: if ( ((sir->sbc_rreg.cdr & ~SI_HOST_ID)
609: < SI_HOST_ID) &&
610: ((*icrp & SBC_ICR_LA) == 0)) {
611: /* won arbitration */
612: icr = *icrp & ~SBC_ICR_AIP;
613: *icrp = icr | SBC_ICR_ATN;
614: icr = *icrp & ~SBC_ICR_AIP;
615: *icrp = icr | SBC_ICR_SEL;
616: DELAY(SI_BUS_CLEAR_DELAY + SI_BUS_SETTLE_DELAY);
617: break;
618: }
619: }
620:
621: /* lost arbitration, clear arbitration mode */
622: *mrp &= ~SBC_MR_ARB;
623: }
624:
625: /* couldn't win arbitration */
626: if (j == SI_NUM_RETRIES) {
627: /* should never happen since we have highest pri scsi id */
628: *mrp &= ~SBC_MR_ARB;
629: *icrp = 0;
630: printf("si_arb_sel: couldn't win arbitration\n");
631: return (0);
632: }
633:
634: /* won arbitration, perform selection */
635: sir->sbc_wreg.odr = (1 << un->un_target) | SI_HOST_ID;
636: icr = *icrp & ~SBC_ICR_AIP;
637: *icrp = icr | SBC_ICR_DATA | SBC_ICR_BUSY;
638: *mrp &= ~SBC_MR_ARB;
639:
640: /* wait for target to acknowledge selection */
641: *icrp &= ~SBC_ICR_BUSY;
642: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_BSY, 1) == 0) {
643: if (scsi_debug)
644: printf("si_arb_sel: cbsr bsy never set\n");
645: si_reset(c);
646: return (0);
647: }
648: *icrp &= ~(SBC_ICR_SEL | SBC_ICR_DATA);
649:
650: /* send target identify message */
651: if (c->c_flags & SCSI_EN_DISCON)
652: id = SC_DR_IDENTIFY | c->c_cdb.lun;
653: else
654: id = SC_IDENTIFY | c->c_cdb.lun;
655: if (si_putdata(c, PHASE_MSG_OUT, &id, 1) == 0) {
656: if (scsi_debug)
657: printf("si_arb_sel: put of ID MSG %x failed\n", id);
658: }
659: *icrp = 0;
660: return (1);
661: }
662:
663: /*
664: * Set up the SCSI control logic for a dma transfer for vme host adaptor.
665: */
666: si_vme_dma_setup(c, un)
667: register struct scsi_ctlr *c;
668: register struct scsi_unit *un;
669: {
670: register struct scsi_si_reg *sir = c->c_sir;
671:
672: /* setup starting dma address and number bytes to dma */
673: sir->dma_addr = un->un_dma_curaddr;
674: sir->dma_count = un->un_dma_curcnt;
675:
676: /* set up byte packing control info */
677: if (sir->dma_addr & 0x2) {
678: /* setup word dma transfers across vme bus */
679: sir->csr |= SI_CSR_BPCON;
680: } else {
681: /* setup longword dma transfers across vme bus */
682: sir->csr &= ~SI_CSR_BPCON;
683: }
684:
685: if (scsi_debug) {
686: printf("si_vme_dma_setup: addr %x, cnt %x, csr %x\n",
687: sir->dma_addr, sir->dma_count, sir->csr);
688: }
689:
690: /* init sbc for dma transfer */
691: si_sbc_dma_setup(sir, un->un_dma_curdir);
692:
693: /* enable dma - this must be the last step */
694: sir->csr |= SI_CSR_DMA_EN;
695: }
696:
697: /*
698: * Set up the SCSI control logic for a dma transfer for onboard host
699: * adaptor.
700: */
701: si_ob_dma_setup(c, un)
702: register struct scsi_ctlr *c;
703: register struct scsi_unit *un;
704: {
705: register struct scsi_si_reg *sir = c->c_sir;
706: register struct udc_table *udct = &c->c_udct;
707: register int addr;
708:
709: /* set up udc dma information */
710: addr = un->un_dma_curaddr;
711: if (addr < DVMA_OFFSET)
712: addr += DVMA_OFFSET;
713: udct->haddr = ((addr & 0xff0000) >> 8) | UDC_ADDR_INFO;
714: udct->laddr = addr & 0xffff;
715: udct->hcmr = UDC_CMR_HIGH;
716: udct->count = un->un_dma_curcnt / 2; /* #bytes -> #words */
717: if (un->un_dma_curdir == SI_RECV_DATA) {
718: udct->rsel = UDC_RSEL_RECV;
719: udct->lcmr = UDC_CMR_LRECV;
720: } else {
721: udct->rsel = UDC_RSEL_SEND;
722: udct->lcmr = UDC_CMR_LSEND;
723: if (un->un_dma_curcnt & 1) {
724: udct->count++;
725: }
726: }
727:
728: /* initialize udc chain address register */
729: sir->udc_raddr = UDC_ADR_CAR_HIGH;
730: DELAY(SI_UDC_WAIT);
731: sir->udc_rdata = ((int)udct & 0xff0000) >> 8;
732: DELAY(SI_UDC_WAIT);
733: sir->udc_raddr = UDC_ADR_CAR_LOW;
734: DELAY(SI_UDC_WAIT);
735: sir->udc_rdata = (int)udct & 0xffff;
736:
737: if (scsi_debug) {
738: printf("si_ob_dma_setup: udct= %x, %x -> %x\n", udct,
739: un->un_dma_curaddr, addr);
740: }
741:
742: /* initialize udc master mode register */
743: DELAY(SI_UDC_WAIT);
744: sir->udc_raddr = UDC_ADR_MODE;
745: DELAY(SI_UDC_WAIT);
746: sir->udc_rdata = UDC_MODE;
747:
748: /* issue channel interrupt enable command, in case of error, to udc */
749: DELAY(SI_UDC_WAIT);
750: sir->udc_raddr = UDC_ADR_COMMAND;
751: DELAY(SI_UDC_WAIT);
752: sir->udc_rdata = UDC_CMD_CIE;
753:
754: /* issue start chain command to udc */
755: DELAY(SI_UDC_WAIT);
756: sir->udc_rdata = UDC_CMD_STRT_CHN;
757:
758: /* put sbc in dma mode and start dma transfer */
759: si_sbc_dma_setup(sir, un->un_dma_curdir);
760: }
761:
762: /*
763: * Setup and start the sbc for a dma operation.
764: */
765: si_sbc_dma_setup(sir, dir)
766: register struct scsi_si_reg *sir;
767: register int dir;
768: {
769: sir->sbc_wreg.mr |= SBC_MR_DMA;
770: if (dir == SI_RECV_DATA) {
771: sir->sbc_wreg.tcr = TCR_DATA_IN;
772: sir->sbc_wreg.ircv = 0;
773: } else {
774: sir->sbc_wreg.tcr = TCR_DATA_OUT;
775: sir->sbc_wreg.icr = SBC_ICR_DATA;
776: sir->sbc_wreg.send = 0;
777: }
778: }
779:
780: /*
781: * Cleanup up the SCSI control logic after a dma transfer.
782: */
783: si_dma_cleanup(c)
784: register struct scsi_ctlr *c;
785: {
786: register struct scsi_si_reg *sir = c->c_sir;
787:
788: /* disable dma controller */
789: if (c->c_flags & SCSI_ONBOARD) {
790: sir->udc_raddr = UDC_ADR_COMMAND;
791: DELAY(SI_UDC_WAIT);
792: sir->udc_rdata = UDC_CMD_RESET;
793: } else {
794: sir->dma_addr = 0;
795: sir->dma_count = 0;
796: }
797:
798: /* reset fifo */
799: sir->csr &= ~SI_CSR_FIFO_RES;
800: sir->csr |= SI_CSR_FIFO_RES;
801:
802: /* take sbc out of dma mode and reset bcr */
803: sir->sbc_wreg.icr = 0;
804: sir->sbc_wreg.mr &= ~SBC_MR_DMA;
805: sir->sbc_wreg.tcr = 0;
806: sir->bcr = 0;
807: }
808:
809: /*
810: * Handle special dma receive situations, e.g. an odd number of bytes
811: * in a dma transfer.
812: * The Sun3/50 onboard interface has different situations which
813: * must be handled than the vme interface.
814: */
815: si_dma_recv(c)
816: register struct scsi_ctlr *c;
817: {
818: register struct scsi_si_reg *sir = c->c_sir;
819: register struct scsi_unit *un = c->c_un;
820: register int offset;
821:
822: offset = un->un_dma_curaddr + (un->un_dma_curcnt - sir->bcr);
823:
824: /* handle the onboard scsi situations */
825: if (c->c_flags & SCSI_ONBOARD) {
826: sir->udc_raddr = UDC_ADR_COUNT;
827:
828: /* wait for the fifo to empty */
829: if (si_wait((u_short *)&sir->csr, SI_CSR_FIFO_EMPTY, 1) == 0) {
830: printf("si_dma_recv: fifo never emptied\n");
831: return (0);
832: }
833:
834: /* handle odd byte */
835: if ((un->un_dma_curcnt - sir->bcr) & 1) {
836: DVMA[offset - 1] = (sir->fifo_data & 0xff00) >> 8;
837:
838: /*
839: * The udc may not dma the last word from the fifo_data
840: * register into memory due to how the hardware turns
841: * off the udc at the end of the dma operation.
842: */
843: } else if (((sir->udc_rdata*2) - sir->bcr) == 2) {
844: DVMA[offset - 2] = (sir->fifo_data & 0xff00) >> 8;
845: DVMA[offset - 1] = sir->fifo_data & 0x00ff;
846: }
847:
848: /* handle the vme scsi situations */
849: } else if ((sir->csr & SI_CSR_LOB) != 0) {
850: /*
851: * Grabs last few bytes which may not have been dma'd.
852: * Worst case is when longword dma transfers are being done
853: * and there are 3 bytes leftover.
854: * If BPCON bit is set then longword dmas were being done,
855: * otherwise word dmas were being done.
856: */
857: if ((sir->csr & SI_CSR_BPCON) == 0) {
858: switch (sir->csr & SI_CSR_LOB) {
859: case SI_CSR_LOB_THREE:
860: DVMA[offset - 3] = (sir->bpr & 0xff000000) >> 24;
861: DVMA[offset - 2] = (sir->bpr & 0x00ff0000) >> 16;
862: DVMA[offset - 1] = (sir->bpr & 0x0000ff00) >> 8;
863: break;
864:
865: case SI_CSR_LOB_TWO:
866: DVMA[offset - 2] = (sir->bpr & 0xff000000) >> 24;
867: DVMA[offset - 1] = (sir->bpr & 0x00ff0000) >> 16;
868: break;
869:
870: case SI_CSR_LOB_ONE:
871: DVMA[offset - 1] = (sir->bpr & 0xff000000) >> 24;
872: break;
873: }
874: } else {
875: DVMA[offset - 1] = (sir->bpr & 0x0000ff00) >> 8;
876: }
877: }
878: return (1);
879: }
880:
881:
882: /*
883: * Handle a scsi interrupt.
884: */
885: siintr(c)
886: register struct scsi_ctlr *c;
887: {
888: register struct scsi_si_reg *sir = c->c_sir;
889: register struct scsi_unit *un = c->c_un;
890: register int bsr;
891: register int status;
892: register int resid;
893: register int dma_cleanup;
894: register int i;
895: int disconnect;
896: u_char msg;
897: struct buf *dp;
898: int reset_occurred;
899:
900: /* set misc flags */
901: status = SE_NO_ERROR;
902: resid = 0;
903: dma_cleanup = 0;
904: disconnect = 0;
905: reset_occurred = 0;
906:
907: /*
908: * For vme host adaptor interface, must disable dma before
909: * accessing any registers other than the csr or the
910: * SI_CSR_DMA_CONFLICT bit in the csr will be set.
911: */
912: if ((c->c_flags & SCSI_ONBOARD) == 0) {
913: sir->csr &= ~SI_CSR_DMA_EN;
914: }
915:
916: /* check for dma related errors */
917: if (sir->csr & (SI_CSR_DMA_IP | SI_CSR_DMA_CONFLICT)) {
918: if (sir->csr & SI_CSR_DMA_BUS_ERR) {
919: printf("siintr: bus error during dma\n");
920: } else if (sir->csr & SI_CSR_DMA_CONFLICT) {
921: printf("siintr: invalid reg access during dma\n");
922: } else {
923: if (c->c_flags & SCSI_ONBOARD)
924: printf("siintr: dma ip, unknown reason\n");
925: else
926: printf("siintr: dma overrun\n");
927: }
928: /*
929: * Either we were waiting for an interrupt on a phase change
930: * on the scsi bus, an interrupt on a reconnect attempt,
931: * or an interrupt upon completion of a real dma operation.
932: * Each of these situations must be handled appropriately.
933: */
934: if (sir->sbc_rreg.tcr == TCR_UNSPECIFIED) {
935: sir->sbc_wreg.mr &= ~SBC_MR_DMA;
936: } else if (un == NULL) {
937: si_reset(c);
938: si_idle(c);
939: return;
940: } else {
941: dma_cleanup = 1;
942: }
943: status = SE_FATAL;
944:
945: /* check for interrupt from sbc */
946: } else if (sir->csr & SI_CSR_SBC_IP) {
947:
948: /* grab the bsr and find out why sbc interrupted */
949: bsr = sir->sbc_rreg.bsr;
950:
951: /* acknowledge sbc interrupt */
952: msg = sir->sbc_rreg.clr;
953:
954: /*
955: * Check for sbc end of operation interrupt.
956: * This is the normal interrupt upon completion
957: * of a dma operation. Very soon after this
958: * interrupt is generated a phase mismatch
959: * should occur on the scsi bus as the target
960: * changes from the data in/out phase to the
961: * status phase.
962: */
963: if (bsr & SBC_BSR_EDMA) {
964: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.bsr,
965: SBC_BSR_PMTCH, 0) == 0) {
966: dma_cleanup = 1;
967: status = SE_FATAL;
968: printf("si: scsi sbc dma end op\n");
969: goto done;
970: }
971: goto phmismatch;
972:
973: /* check for phase mismatch */
974: } else if ((bsr & SBC_BSR_PMTCH) == 0) {
975: phmismatch:
976: if ((sir->sbc_rreg.mr & SBC_MR_DMA) == 0) {
977: if (c->c_flags & SCSI_EN_RECON)
978: goto recon;
979: else
980: goto discon;
981: }
982:
983: /*
984: * Handle fake dma mode which is used when we
985: * want an interrupt when target changes scsi
986: * bus to status phase.
987: */
988: sir->sbc_wreg.mr &= ~SBC_MR_DMA;
989: if (sir->sbc_rreg.tcr == TCR_UNSPECIFIED) {
990: sir->sbc_wreg.tcr = 0;
991: } else {
992: /* need to reset some registers after a dma */
993: dma_cleanup = 1;
994:
995: /* handle special dma recv situations */
996: if (un->un_dma_curdir == SI_RECV_DATA) {
997: if (si_dma_recv(c) == 0) {
998: status = SE_RETRYABLE;
999: }
1000: }
1001: }
1002:
1003: discon:
1004: /* check for disconnect */
1005: if ((sir->sbc_rreg.cbsr & SBC_CBSR_REQ) &&
1006: ((sir->sbc_rreg.cbsr & CBSR_PHASE_BITS) ==
1007: PHASE_MSG_IN)) {
1008: if (scsi_debug || scsi_dis_debug)
1009: printf("siintr: DISconnect\n");
1010: if (si_disconnect(c)) {
1011: disconnect = 1;
1012: }
1013: }
1014: goto done;
1015: }
1016:
1017: recon:
1018: /* check for reconnect attempt */
1019: if ((sir->sbc_rreg.cbsr & SBC_CBSR_SEL) &&
1020: (sir->sbc_rreg.cbsr & SBC_CBSR_IO) &&
1021: (sir->sbc_rreg.cdr & SI_HOST_ID)) {
1022: if (scsi_debug || scsi_dis_debug)
1023: printf("siintr: REconnect\n");
1024: si_reconnect(c);
1025: return;
1026: }
1027:
1028: /*
1029: * Scsi bus reset occurred. Put registers in correct
1030: * state. Must cleanup disconnected tasks which will
1031: * never reconnect due to the scsi bus reset.
1032: */
1033: if (scsi_debug)
1034: printf("siintr: got scsi bus reset\n");
1035: sir->csr = 0;
1036: DELAY(10);
1037: sir->csr = SI_CSR_INTR_EN|SI_CSR_SCSI_RES|SI_CSR_FIFO_RES;
1038: sir->sbc_wreg.mr = SBC_MR_EEI;
1039: c->c_flags &= ~SCSI_EN_RECON;
1040: if (c->c_disqh != NULL) {
1041: c->c_flags |= SCSI_FLUSH_DISQ;
1042: c->c_flush = c->c_disqt;
1043: }
1044: status = SE_FATAL;
1045: reset_occurred = 1;
1046:
1047: /* flush disconnect tasks now if possible */
1048: if ((un == NULL) && c->c_disqh) {
1049: si_idle(c);
1050: return;
1051: }
1052: }
1053:
1054: done:
1055: /* cleanup after a dma operation */
1056: if (dma_cleanup) {
1057: resid = sir->bcr;
1058: si_dma_cleanup(c);
1059: }
1060:
1061: /* pass interrupt info to unit */
1062: if (un && un->un_wantint && (disconnect == 0)) {
1063: un->un_wantint = 0;
1064: if (status == SE_NO_ERROR) {
1065: if (si_getstatus(un, 0) == 0) {
1066: status = SE_RETRYABLE;
1067: }
1068: } else if (reset_occurred == 0) {
1069: si_reset(c);
1070: }
1071: (*un->un_ss->ss_intr)(c, resid, status);
1072: }
1073:
1074: if (disconnect) {
1075: /* start next I/O activity on controller */
1076: if ((un->un_mc->mc_tab.b_actf) &&
1077: (un->un_mc->mc_tab.b_active == 0)) {
1078: sistart(un);
1079: } else {
1080: /* enable reconnect attempts */
1081: sir->sbc_wreg.ser = SI_HOST_ID;
1082: c->c_flags |= SCSI_EN_RECON;
1083: if ((c->c_flags & SCSI_ONBOARD) == 0) {
1084: sir->csr &= ~SI_CSR_SEND;
1085: sir->csr |= SI_CSR_DMA_EN;
1086: }
1087: }
1088: }
1089: }
1090:
1091: /*
1092: * Handle target disconnecting.
1093: */
1094: si_disconnect(c)
1095: register struct scsi_ctlr *c;
1096: {
1097: register struct scsi_unit *un = c->c_un;
1098: register struct mb_ctlr *mc = un->un_mc;
1099: register struct buf *dp;
1100: register struct scsi_si_reg *sir = c->c_sir;
1101: register u_char msg;
1102:
1103: /* get disconnect message(s) */
1104: msg = si_getdata(c, PHASE_MSG_IN);
1105: if (msg == SC_SAVE_DATA_PTR) {
1106: msg = si_getdata(c, PHASE_MSG_IN);
1107: }
1108: if (msg != SC_DISCONNECT) {
1109: return (0);
1110: }
1111:
1112: /* save dma info for reconnect */
1113: if (un->un_dma_curdir != SI_NO_DATA) {
1114:
1115: /* debug information */
1116: if (c->c_flags & SCSI_ONBOARD) {
1117: if (scsi_dis_debug) {
1118: sir->udc_raddr = UDC_ADR_COUNT;
1119: printf("\tdiscon: udc_cnt %x\n",
1120: sir->udc_rdata);
1121: }
1122: if ((un->un_dma_curaddr & 0xffff) != c->c_udct.laddr) {
1123: printf("discon: caddr= %x, udc= %x\n",
1124: un->un_dma_curaddr, c->c_udct.laddr);
1125: }
1126: }
1127: if (scsi_dis_debug) {
1128: printf("\taddr= %x, cnt= %x, bcr= %x, sr= %x, baddr= %x\n",
1129: un->un_dma_curaddr, un->un_dma_curcnt,
1130: sir->bcr, sir->csr, un->un_baddr);
1131: }
1132:
1133: /*
1134: * Save dma information so dma can be restarted when
1135: * a reconnect occurs.
1136: */
1137: un->un_dma_curaddr += un->un_dma_curcnt - sir->bcr;
1138: un->un_dma_curcnt = sir->bcr;
1139: }
1140:
1141: /*
1142: * Remove this disconnected task from the ctlr ready queue and save
1143: * on disconnect queue until a reconnect is done.
1144: * Advance controller queue. Remove mainbus resource alloc info.
1145: */
1146: dp = mc->mc_tab.b_actf;
1147: mc->mc_tab.b_active = 0;
1148: mc->mc_tab.b_actf = dp->b_forw;
1149: mc->mc_mbinfo = 0;
1150: if (c->c_disqh == NULL)
1151: c->c_disqh = dp;
1152: else
1153: c->c_disqt->b_forw = dp;
1154: dp->b_forw = NULL;
1155: c->c_disqt = dp;
1156: c->c_un = NULL;
1157: return (1);
1158: }
1159:
1160: /*
1161: * Complete reselection phase and reconnect to target.
1162: *
1163: * NOTE: this routine cannot use si_getdata() to get identify msg
1164: * from reconnecting target due to sun3/50 scsi interface. The bcr
1165: * must be setup before the target changes scsi bus to data phase
1166: * if the command being reconnected involves dma (which we do not
1167: * know until we get the identify msg). Thus we cannot acknowledge
1168: * the identify msg until some setup of the host adaptor registers
1169: * is done.
1170: */
1171: si_reconnect(c)
1172: register struct scsi_ctlr *c;
1173: {
1174: register struct scsi_si_reg *sir = c->c_sir;
1175: register struct buf *dp;
1176: register struct buf *pdp;
1177: register struct scsi_unit *un;
1178: register int i;
1179: register u_char msg;
1180: register u_char lun;
1181: register u_char cdr;
1182:
1183: /* get reselecting target scsi id */
1184: cdr = sir->sbc_rreg.cdr & ~SI_HOST_ID;
1185:
1186: /* make sure there are only 2 scsi id's set */
1187: for (i=0; i < 8; i++) {
1188: if (cdr & (1<<i))
1189: break;
1190: }
1191: cdr &= ~(1<<i);
1192: if (cdr != 0) {
1193: printf("si_recon: > 2 scsi ids\n");
1194: return;
1195: }
1196:
1197: /* acknowledge reselection */
1198: sir->sbc_wreg.icr = SBC_ICR_BUSY;
1199: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_SEL, 0) == 0) {
1200: printf("si_recon: target never rel SEL\n");
1201: si_reset(c);
1202: return;
1203: }
1204: sir->sbc_wreg.icr = 0;
1205:
1206: /* setup for getting identify message from reconnecting target */
1207: sir->sbc_wreg.tcr = TCR_MSG_IN;
1208: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) {
1209: printf("si_recon: REQ not active\n");
1210: si_reset(c);
1211: return;
1212: }
1213: if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) {
1214: printf("si_recon: phase mismatch\n");
1215: si_reset(c);
1216: return;
1217: }
1218:
1219: /* grab identify message */
1220: msg = sir->sbc_rreg.cdr;
1221: sir->sbc_wreg.tcr = 0;
1222: if ((msg != SC_IDENTIFY) && (msg != SC_DR_IDENTIFY)) {
1223: printf("si: recon, not id msg\n");
1224: si_reset(c);
1225: return;
1226: }
1227: lun = msg & 0x07;
1228:
1229: /* search disconnect q for reconnecting task */
1230: for (dp = c->c_disqh, pdp = NULL; dp; pdp = dp, dp = dp->b_forw) {
1231: un = (struct scsi_unit *)dp->b_un.b_addr;
1232: if ((un->un_target == i) && (un->un_lun == lun))
1233: break;
1234: }
1235: if (dp == NULL) {
1236: printf("si: recon, never found dis unit\n");
1237: si_reset(c);
1238: return;
1239: }
1240:
1241: /* make sure there is no active I/O */
1242: if (un->un_mc->mc_tab.b_actf != NULL) {
1243: printf("si: recon, other I/O active\n");
1244: si_reset(c);
1245: return;
1246: }
1247:
1248: /* disable other reconnection attempts */
1249: sir->sbc_wreg.ser = 0;
1250: c->c_flags &= ~SCSI_EN_RECON;
1251:
1252: /* remove entity from disconnect q */
1253: if (dp == c->c_disqh)
1254: c->c_disqh = dp->b_forw;
1255: else
1256: pdp->b_forw = dp->b_forw;
1257: if (dp == c->c_disqt)
1258: c->c_disqt = pdp;
1259: dp->b_forw = NULL;
1260:
1261: /* requeue on controller queue */
1262: siustart(un);
1263: un->un_mc->mc_tab.b_active = 1;
1264: c->c_un = un;
1265:
1266: /* restart disconnect activity */
1267: if (un->un_dma_curdir != SI_NO_DATA) {
1268: /* restore mainbus resource allocation info */
1269: un->un_mc->mc_mbinfo = un->un_baddr;
1270:
1271: /* do initial dma setup */
1272: if (un->un_dma_curdir == SI_RECV_DATA)
1273: sir->csr &= ~SI_CSR_SEND;
1274: else
1275: sir->csr |= SI_CSR_SEND;
1276: sir->csr &= ~SI_CSR_FIFO_RES;
1277: sir->csr |= SI_CSR_FIFO_RES;
1278: sir->bcr = un->un_dma_curcnt;
1279: if ((c->c_flags & SCSI_ONBOARD) == 0) {
1280: sir->bcrh = 0;
1281: }
1282:
1283: if (scsi_dis_debug) {
1284: printf("\taddr= %x, cnt= %x, bcr= %x, sr= %x, baddr= %x\n",
1285: un->un_dma_curaddr, un->un_dma_curcnt, sir->bcr,
1286: sir->csr, un->un_baddr);
1287: }
1288:
1289: }
1290:
1291: /* we can finally acknowledge identify message */
1292: sir->sbc_wreg.icr = SBC_ICR_ACK;
1293: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) {
1294: printf("si_recon: REQ not INactive\n");
1295: si_reset(c);
1296: return;
1297: }
1298: sir->sbc_wreg.icr = 0;
1299:
1300: /* may get restore pointers message */
1301: if ((sir->sbc_rreg.cbsr & SBC_CBSR_REQ) &&
1302: ((sir->sbc_rreg.cbsr & CBSR_PHASE_BITS) == PHASE_MSG_IN)) {
1303: msg = si_getdata(c, PHASE_MSG_IN);
1304: }
1305:
1306: /* do final setup for dma operation and start dma */
1307: if (un->un_dma_curdir != SI_NO_DATA) {
1308: if (c->c_flags & SCSI_ONBOARD)
1309: si_ob_dma_setup(c, un);
1310: else
1311: si_vme_dma_setup(c, un);
1312: } else if (un->un_wantint) {
1313: sir->sbc_wreg.mr |= SBC_MR_DMA;
1314: sir->sbc_wreg.tcr = TCR_UNSPECIFIED;
1315: if ((c->c_flags & SCSI_ONBOARD) == 0) {
1316: sir->csr &= ~SI_CSR_SEND;
1317: sir->csr |= SI_CSR_DMA_EN;
1318: }
1319: }
1320: }
1321:
1322: /*
1323: * No current activity for the scsi bus. May need to flush some
1324: * disconnected tasks if a scsi bus reset occurred before the
1325: * target reconnected, since a scsi bus reset causes targets to
1326: * "forget" about any disconnected activity.
1327: * Also, enable reconnect attempts.
1328: */
1329: si_idle(c)
1330: register struct scsi_ctlr *c;
1331: {
1332: register struct scsi_si_reg *sir = c->c_sir;
1333: register struct buf *dp;
1334: register struct scsi_unit *un;
1335: register int i;
1336: register int resid;
1337:
1338: if (c->c_flags & SCSI_FLUSHING) {
1339: if (scsi_reset_debug)
1340: printf("si_idle: flushing, flags %x\n", c->c_flags);
1341: return;
1342: }
1343:
1344: /* flush disconnect tasks if a reconnect will never occur */
1345: if (c->c_flags & SCSI_FLUSH_DISQ) {
1346: if (scsi_reset_debug) {
1347: printf("si_idle: flush: flags= %x, disqh= %x, disqt= %x\n",
1348: c->c_flags, c->c_disqh, c->c_disqt);
1349: }
1350:
1351: /* now in process of flushing tasks */
1352: c->c_flags &= ~SCSI_FLUSH_DISQ;
1353: c->c_flags |= SCSI_FLUSHING;
1354:
1355: for (dp = c->c_disqh; dp && c->c_flush; dp = c->c_disqh) {
1356: /* keep track of last task to flush */
1357: if (c->c_flush == c->c_disqh)
1358: c->c_flush = NULL;
1359:
1360: /* remove tasks from disconnect q */
1361: un = (struct scsi_unit *)dp->b_un.b_addr;
1362: c->c_disqh = dp->b_forw;
1363: dp->b_forw = NULL;
1364:
1365: /* requeue on controller q */
1366: siustart(un);
1367: un->un_mc->mc_tab.b_active = 1;
1368: c->c_un = un;
1369:
1370: /* inform device routines of error */
1371: if (un->un_dma_curdir != SI_NO_DATA) {
1372: un->un_mc->mc_mbinfo = un->un_baddr;
1373: resid = un->un_dma_curcnt;
1374: } else {
1375: resid = 0;
1376: }
1377: (*un->un_ss->ss_intr)(c, resid, SE_FATAL);
1378: }
1379: if (c->c_disqh == NULL) {
1380: c->c_disqt = NULL;
1381: }
1382: c->c_flags &= ~SCSI_FLUSHING;
1383: }
1384:
1385: /* enable reconnect attempts */
1386: sir->sbc_wreg.ser = SI_HOST_ID;
1387: c->c_flags |= SCSI_EN_RECON;
1388: if ((c->c_flags & SCSI_ONBOARD) == 0) {
1389: sir->csr &= ~SI_CSR_SEND;
1390: sir->csr |= SI_CSR_DMA_EN;
1391: }
1392: }
1393:
1394: /*
1395: * Get status bytes from scsi bus.
1396: */
1397: si_getstatus(un, recurse)
1398: register struct scsi_unit *un;
1399: {
1400: register struct scsi_ctlr *c = un->un_c;
1401: register u_char *cp = (u_char *)&c->c_scb;
1402: struct scsi_cdb save_cdb;
1403: struct scsi_scb save_scb;
1404: register int i;
1405: register int b;
1406: register int save_dma_addr;
1407: register int save_dma_count;
1408: register int save_reg_dma_count;
1409: int resid;
1410: short retval = 1;
1411: int s;
1412:
1413: /* get all the status bytes */
1414: for (i = 0;;) {
1415: b = si_getdata(c, PHASE_STATUS);
1416: if (b < 0) {
1417: break;
1418: }
1419: if (i < STATUS_LEN) {
1420: cp[i++] = b;
1421: }
1422: }
1423:
1424: /* get command complete message */
1425: b = si_getdata(c, PHASE_MSG_IN);
1426: if (b != SC_COMMAND_COMPLETE) {
1427: if (scsi_debug) {
1428: printf("Invalid SCSI message: %x\n", b);
1429: printf("Status bytes (%d):", i);
1430: for (b = 0; b < i; b++) {
1431: printf(" %x", cp[b]);
1432: }
1433: printf("\n");
1434: }
1435: return (0);
1436: }
1437: if (scsi_debug) {
1438: printf("si%d: si_getstatus: Got status (%d) ", SINUM(c), i);
1439: for (b = 0; b < i; b++) {
1440: printf(" %x", cp[b]);
1441: }
1442: printf("\n");
1443: }
1444: if (c->c_scb.busy) {
1445: return (0);
1446: }
1447:
1448: /* check for sense data */
1449: if (c->c_scb.chk) {
1450: if (recurse) {
1451: printf("scsi: chk on sense: invalid\n");
1452: return (0);
1453: }
1454:
1455: /* save information while we get sense */
1456: save_cdb = c->c_cdb;
1457: save_scb = c->c_scb;
1458: save_dma_addr = un->un_dma_addr;
1459: save_dma_count = un->un_dma_count;
1460: save_reg_dma_count = c->c_sir->bcr;
1461:
1462: /* set up for getting sense */
1463: c->c_cdb.cmd = SC_REQUEST_SENSE;
1464: c->c_cdb.lun = un->un_lun;
1465: cdbaddr(&c->c_cdb, 0);
1466: c->c_cdb.count = sizeof(struct scsi_sense);
1467: un->un_dma_addr = (int)c->c_sense - (int)DVMA;
1468: un->un_dma_count = sizeof(struct scsi_sense);
1469:
1470: /* get sense */
1471: if ((s=0),si_cmd(c, un, 0) == 0 ||
1472: (s=1),si_cmdwait(c) == 0 ||
1473: (s=2),si_getstatus(un, 1) == 0) {
1474: printf("scsi: cannot get sense %d\n", s);
1475: si_off(un);
1476: retval = 0;
1477: }
1478:
1479: /* restore pre sense information */
1480: c->c_cdb = save_cdb;
1481: c->c_scb = save_scb;
1482: un->un_dma_addr = save_dma_addr;
1483: un->un_dma_count = save_dma_count;
1484: c->c_sir->bcr = save_reg_dma_count;
1485: }
1486: return (retval);
1487: }
1488:
1489: /*
1490: * Wait for a scsi dma request to complete.
1491: * Disconnects were disabled in si_cmd() when polling for command completion.
1492: */
1493: si_cmdwait(c)
1494: register struct scsi_ctlr *c;
1495: {
1496: register struct scsi_si_reg *sir = c->c_sir;
1497: register struct scsi_unit *un = c->c_un;
1498: register u_char junk;
1499:
1500: /* wait for dma transfer to complete */
1501: if (si_wait((u_short *)&sir->csr, SI_CSR_DMA_ACTIVE, 0) == 0) {
1502: printf("si_cmdwait: DMA_ACTIVE still on\n");
1503: si_reset(c);
1504: return (0);
1505: }
1506:
1507: /* if command does not involve dma activity, then we are finished */
1508: if (un->un_dma_curdir == SI_NO_DATA) {
1509: return (1);
1510: }
1511:
1512: /* wait for indication of dma completion */
1513: if (si_wait((u_short *)&sir->csr,
1514: SI_CSR_SBC_IP|SI_CSR_DMA_IP|SI_CSR_DMA_CONFLICT, 1) == 0) {
1515: printf("si_cmdwait: dma op never completed\n");
1516: si_reset(c);
1517: return (0);
1518: }
1519:
1520: /*
1521: * For vme host adaptor interface, must disable dma before
1522: * accessing any registers other than the csr or a dma
1523: * conflict error will occur.
1524: */
1525: if ((c->c_flags & SCSI_ONBOARD) == 0) {
1526: sir->csr &= ~SI_CSR_DMA_EN;
1527: }
1528:
1529: /* make sure dma completely complete */
1530: if ((sir->csr & SI_CSR_SBC_IP) == 0) {
1531: if (sir->csr & SI_CSR_DMA_BUS_ERR) {
1532: printf("si_cmdwait: bus error during dma\n");
1533: } else if (sir->csr & SI_CSR_DMA_CONFLICT) {
1534: printf("si_cmdwait: invalid reg access during dma\n");
1535: } else {
1536: if (c->c_flags & SCSI_ONBOARD)
1537: printf("si_cmdwait: dma ip, unknown reason\n");
1538: else
1539: printf("si_cmdwait: dma overrun\n");
1540: }
1541: si_reset(c);
1542: return (0);
1543: }
1544:
1545: /* handle special dma recv situations */
1546: if (un->un_dma_curdir == SI_RECV_DATA) {
1547: if (si_dma_recv(c) == 0) {
1548: si_reset(c);
1549: return (0);
1550: }
1551: }
1552:
1553: /* ack sbc interrupt and cleanup */
1554: junk = sir->sbc_rreg.clr;
1555: si_dma_cleanup(c);
1556: return (1);
1557: }
1558:
1559: /*
1560: * Wait for a condition to be (de)asserted on the scsi bus.
1561: */
1562: si_sbc_wait(reg, cond, set)
1563: register caddr_t reg;
1564: register u_char cond;
1565: register int set;
1566: {
1567: register int i;
1568: register u_char regval;
1569:
1570: for (i = 0; i < SI_WAIT_COUNT; i++) {
1571: regval = *reg;
1572: if ((set == 1) && (regval & cond)) {
1573: return (1);
1574: }
1575: if ((set == 0) && !(regval & cond)) {
1576: return (1);
1577: }
1578: DELAY(10);
1579: }
1580: return (0);
1581: }
1582:
1583: /*
1584: * Wait for a condition to be (de)asserted.
1585: */
1586: si_wait(reg, cond, set)
1587: register u_short *reg;
1588: register u_short cond;
1589: register int set;
1590: {
1591: register int i;
1592: register u_short regval;
1593:
1594: for (i = 0; i < SI_WAIT_COUNT; i++) {
1595: regval = *reg;
1596: if ((set == 1) && (regval & cond)) {
1597: return (1);
1598: }
1599: if ((set == 0) && !(regval & cond)) {
1600: return (1);
1601: }
1602: DELAY(10);
1603: }
1604: return (0);
1605: }
1606:
1607: /*
1608: * Put data onto the scsi bus.
1609: */
1610: si_putdata(c, phase, data, num)
1611: register struct scsi_ctlr *c;
1612: register u_short phase;
1613: register u_char *data;
1614: register int num;
1615: {
1616: register struct scsi_si_reg *sir = c->c_sir;
1617: register int i;
1618:
1619: /* set up tcr so a phase match will occur */
1620: if (phase == PHASE_COMMAND) {
1621: sir->sbc_wreg.tcr = TCR_COMMAND;
1622: } else if (phase == PHASE_MSG_OUT) {
1623: sir->sbc_wreg.tcr = TCR_MSG_OUT;
1624: } else {
1625: if (scsi_debug)
1626: printf("si_putdata %d phase not supported\n", phase);
1627: return (0);
1628: }
1629:
1630: /* put all desired bytes onto scsi bus */
1631: for (i = 0; i < num; i++ ) {
1632:
1633: /* wait for target to request a byte */
1634: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1)
1635: == 0) {
1636: if (scsi_debug)
1637: printf("si: putdata, REQ not active\n");
1638: si_reset(c);
1639: return (0);
1640: }
1641:
1642: /* make sure phase match occurred */
1643: if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) {
1644: if (phase != PHASE_MSG_OUT) {
1645: if (scsi_debug)
1646: printf("si: putdata, phase mismatch\n");
1647: si_reset(c);
1648: } else {
1649: sir->sbc_wreg.tcr = 0;
1650: }
1651: return (0);
1652: }
1653:
1654: /* load data */
1655: sir->sbc_wreg.odr = *data++;
1656: sir->sbc_wreg.icr = SBC_ICR_DATA;
1657:
1658: /* complete req/ack handshake */
1659: sir->sbc_wreg.icr |= SBC_ICR_ACK;
1660: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0)
1661: == 0) {
1662: if (scsi_debug)
1663: printf("si: putdata, req not INactive\n");
1664: si_reset(c);
1665: return (0);
1666: }
1667: sir->sbc_wreg.icr = 0;
1668: }
1669: sir->sbc_wreg.tcr = 0;
1670: return (1);
1671: }
1672:
1673: /*
1674: * Get data from the scsi bus.
1675: */
1676: si_getdata(c, phase)
1677: register struct scsi_ctlr *c;
1678: register u_short phase;
1679: {
1680: register struct scsi_si_reg *sir = c->c_sir;
1681: register u_char data;
1682:
1683: /* check for valid phase */
1684: if (phase == PHASE_STATUS) {
1685: sir->sbc_wreg.tcr = TCR_STATUS;
1686: } else if (phase == PHASE_MSG_IN) {
1687: sir->sbc_wreg.tcr = TCR_MSG_IN;
1688: } else {
1689: if (scsi_debug)
1690: printf("si: getdata %d phase not supported\n", phase);
1691: return (-1);
1692: }
1693:
1694: /* wait for target request */
1695: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) {
1696: if (scsi_debug) {
1697: printf("si: getdata, REQ not active, cbsr %x\n",
1698: sir->sbc_rreg.cbsr);
1699: }
1700: sir->sbc_wreg.tcr = 0;
1701: return (-1);
1702: }
1703:
1704: /* check for correct phase on scsi bus */
1705: if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) {
1706: if (phase != PHASE_STATUS) {
1707: if (scsi_debug) {
1708: printf("si: getdata, bad phase\n");
1709: }
1710: si_reset(c);
1711: } else {
1712: sir->sbc_wreg.tcr = 0;
1713: }
1714: return (-1);
1715: }
1716:
1717: /* grab data and complete req/ack handshake */
1718: data = sir->sbc_rreg.cdr;
1719: sir->sbc_wreg.icr = SBC_ICR_ACK;
1720: if (si_sbc_wait((caddr_t)&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) {
1721: if (scsi_debug)
1722: printf("si: getdata, REQ not inactive\n");
1723: si_reset(c);
1724: return (-1);
1725: }
1726: sir->sbc_wreg.icr = 0;
1727: sir->sbc_wreg.tcr = 0;
1728: return (data);
1729: }
1730:
1731: /*
1732: * Reset SCSI control logic and bus.
1733: */
1734: si_reset(c)
1735: register struct scsi_ctlr *c;
1736: {
1737: register struct scsi_si_reg *sir = c->c_sir;
1738: register u_char junk;
1739:
1740: if (scsi_debug) {
1741: printf("scsi reset, sr= %x, bcr= %x\n", sir->csr, sir->bcr);
1742: }
1743:
1744: /* reset scsi control logic */
1745: sir->bcr = 0;
1746: sir->csr = 0;
1747: DELAY(10);
1748: sir->csr = SI_CSR_SCSI_RES|SI_CSR_FIFO_RES;
1749: if ((c->c_flags & SCSI_ONBOARD) == 0) {
1750: sir->dma_addr = 0;
1751: sir->dma_count = 0;
1752: }
1753:
1754: /* issue scsi bus reset (make sure interrupts from sbc are disabled) */
1755: sir->sbc_wreg.icr = SBC_ICR_RST;
1756: DELAY(10);
1757: sir->sbc_wreg.icr = 0;
1758: junk = sir->sbc_rreg.clr;
1759:
1760: /* enable sbc interrupts */
1761: sir->csr |= SI_CSR_INTR_EN;
1762: sir->sbc_wreg.mr = SBC_MR_EEI;
1763:
1764: /* reconnection attempts are no longer enabled */
1765: c->c_flags &= ~SCSI_EN_RECON;
1766:
1767: /* disconnect queue needs to be flushed */
1768: if (c->c_disqh != NULL) {
1769: c->c_flags |= SCSI_FLUSH_DISQ;
1770: c->c_flush = c->c_disqt;
1771: }
1772: }
1773:
1774: /*
1775: * Return residual count for a dma.
1776: */
1777: si_dmacnt(c)
1778: register struct scsi_ctlr *c;
1779: {
1780: if (c->c_flags & SCSI_ONBOARD) {
1781: return (c->c_sir->bcr);
1782: } else {
1783: return ( ((c->c_sir->bcrh) << 16) | (c->c_sir->bcr) );
1784: }
1785: }
1786:
1787: #endif NSI > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.