|
|
1.1 root 1: /*
2: * @(#)si.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc.
3: */
4: #include <sys/types.h>
5: #include <sys/inode.h>
6: #include <sys/buf.h>
7: #include <sun/dklabel.h>
8: #include <sun/dkio.h>
9: #include <sundev/screg.h>
10: #include <sundev/sireg.h>
11: #include <sundev/scsi.h>
12: #include "saio.h"
13: #include <machine/sunromvec.h>
14: #include <machine/idprom.h>
15:
16: /*
17: * Low-level routines common to all devices on the SCSI bus.
18: */
19:
20: /*
21: * Interface to the routines in this module is via a second "sip"
22: * structure contained in the caller's local variables.
23: *
24: * This "sip" must be initialized with sip->si_boottab = sidriver
25: * and must then be devopen()ed before any I/O can be done.
26: *
27: * The device must be closed with devclose().
28: */
29:
30:
31: /* how si addresses look to the si vme scsi dma hardware */
32: #define SI_VME_DMA_ADDR(x) (((int)x)&0x000FFFFF)
33:
34: /* how si addresses look to the sun3/50 scsi dma hardware */
35: #define SI_OB_DMA_ADDR(x) (((int)x)&0x00FFFFFF)
36: struct sidma {
37: struct udc_table udct; /* dma information for udc */
38: };
39:
40: /*
41: * The interfaces we export
42: */
43: extern char *devalloc();
44: extern char *resalloc();
45: extern int nullsys();
46: int siopen();
47:
48: struct boottab sidriver =
49: {"sd", nullsys, nullsys, siopen, nullsys,
50: nullsys, "", 0};
51:
52:
53: #define SI_VME_BASE 0x200000
54: #define SI_OB_BASE 0x140000
55: #define SI_SIZE 0x4000
56:
57: /*
58: * Probe for si host adaptor interface.
59: * Return 1 if found one, 0 otherwise.
60: */
61: int
62: siprobe(sip)
63: register struct saioreq *sip;
64: {
65: register struct scsi_si_reg *sir;
66: struct idprom id;
67: register int base;
68: register int scsi_nstd;
69: register int ctlr;
70: enum MAPTYPES space;
71:
72: /* determine type of si interface */
73: if (idprom(IDFORM_1, &id) == IDFORM_1) {
74: if (id.id_machine == IDM_SUN3_M25) {
75: return (1);
76: } else {
77: base = SI_VME_BASE;
78: space = MAP_VME24A16D;
79: scsi_nstd = 2;
80: }
81: } else {
82: return (0);
83: }
84:
85: /* get base address of registers */
86: if (sip->si_ctlr < scsi_nstd) {
87: ctlr = base + (sip->si_ctlr * SI_SIZE);
88: } else {
89: return (0);
90: }
91:
92: /* now map it in */
93: if ((sir = (struct scsi_si_reg *)devalloc(space, ctlr,
94: sizeof(struct scsi_si_reg))) == 0) {
95: return (0);
96: }
97:
98: /*
99: * SI vme scsi host adaptor occupies 2K bytes in the vme
100: * address space. SC vme scsi host adaptor occupies 4K
101: * bytes in the vme address space.
102: * peek past 2K bytes to determine which host adaptor is there.
103: */
104: if (peek((int)sir+0x800) == -1) {
105: return (1);
106: } else {
107: return (0);
108: }
109: }
110:
111: /*
112: * Open the SCSI host adapter.
113: */
114: int
115: siopen(sip)
116: register struct saioreq *sip;
117: {
118: register struct scsi_si_reg *sir;
119: struct idprom id;
120: register int base;
121: register int scsi_nstd;
122: enum MAPTYPES space;
123:
124: /* determine type of si interface */
125: if (idprom(IDFORM_1, &id) == IDFORM_1) {
126: if (id.id_machine == IDM_SUN3_M25) {
127: base = SI_OB_BASE;
128: space = MAP_OBIO;
129: scsi_nstd = 1;
130: } else {
131: base = SI_VME_BASE;
132: space = MAP_VME24A16D;
133: scsi_nstd = 2;
134: }
135: } else {
136: return (-1);
137: }
138:
139: /* get base address of registers */
140: if (sip->si_ctlr < scsi_nstd) {
141: sip->si_ctlr = base + (sip->si_ctlr * SI_SIZE);
142: } else {
143: return (-1);
144: }
145:
146: /* now map it in */
147: sip->si_devaddr = devalloc(space, sip->si_ctlr,
148: sizeof(struct scsi_si_reg));
149: if (sip->si_devaddr == 0) {
150: return (-1);
151: }
152:
153: /* allocate dma resources */
154: if (base == SI_OB_BASE) {
155: sip->si_dmaaddr = resalloc(RES_DMAMEM, sizeof(struct sidma));
156: if (sip->si_dmaaddr == 0) {
157: return (-1);
158: }
159: } else {
160: sip->si_dmaaddr = 0;
161: }
162:
163: /* reset registers */
164: sir = (struct scsi_si_reg *) sip->si_devaddr;
165: sir->csr = 0;
166: DELAY(10);
167: sir->csr = SI_CSR_SCSI_RES | SI_CSR_FIFO_RES;
168: sir->bcr = 0;
169: if (base == SI_VME_BASE) {
170: sir->dma_addr = 0;
171: sir->dma_count = 0;
172: sir->iv_am = VME_SUPV_DATA_24;
173: }
174: return (0);
175: }
176:
177:
178: /*
179: * Write a command to the SCSI bus.
180: *
181: * The supplied sip is the one opened by siopen().
182: * DMA is done based on sip->si_ma and sip->si_cc.
183: *
184: * Returns -1 for error, otherwise returns the residual count not DMAed
185: * (zero for success).
186: *
187: * FIXME, this must be accessed via a boottab vector,
188: * to allow host adap to switch.
189: * Must pass cdb, scb in sip somewhere...
190: */
191: int
192: sidoit(cdb, scb, sip)
193: struct scsi_cdb *cdb;
194: struct scsi_scb *scb;
195: register struct saioreq *sip;
196: {
197: register struct scsi_si_reg *sir;
198: register char *cp;
199: register int i;
200: register int b;
201: register int ob;
202: u_char junk;
203:
204: /* get to scsi control logic registers */
205: sir = (struct scsi_si_reg *) sip->si_devaddr;
206: if (sip->si_dmaaddr) {
207: ob = 1;
208: } else {
209: ob = 0;
210: }
211:
212: i = 100000;
213: for(;;) {
214: if ((sir->sbc_rreg.cbsr & SBC_CBSR_BSY) == 0) {
215: break;
216: }
217: if (i-- <= 0) {
218: si_reset(sir, ob);
219: return (-1);
220: }
221: }
222:
223: /* select target */
224: sir->sbc_wreg.odr = (1 << sip->si_unit) | SI_HOST_ID;
225: sir->sbc_wreg.icr = SBC_ICR_DATA;
226: sir->sbc_wreg.icr |= SBC_ICR_SEL;
227:
228: /* wait for target to acknowledge our selection */
229: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_BSY, 1) == 0) {
230: sc_error("sel, cbsr bsy never set");
231: goto failed;
232: }
233: sir->sbc_wreg.icr = 0;
234:
235: /* do initial dma setup */
236: sir->bcr = 0; /* also reset dma_count for vme */
237: if (sip->si_cc > 0) {
238: if ((cdb->cmd == SC_READ) || (cdb->cmd == SC_REQUEST_SENSE)) {
239: sir->csr &= ~SI_CSR_SEND;
240: } else {
241: sir->csr |= SI_CSR_SEND;
242: }
243: sir->csr &= ~SI_CSR_FIFO_RES;
244: sir->csr |= SI_CSR_FIFO_RES;
245: sir->bcr = sip->si_cc;
246: if (ob == 0)
247: sir->bcrh = 0;
248: }
249:
250: /* put command onto scsi bus */
251: cp = (char *)cdb;
252: if (si_putbyte(sir, PHASE_COMMAND, cp, sizeof(struct scsi_cdb)) == 0) {
253: sc_error("put of cmd onto scsi bus failed");
254: goto failed;
255: }
256:
257: /* finish dma setup and wait for dma completion */
258: if (sip->si_cc > 0) {
259: if (ob) {
260: si_ob_dma_setup(sir,
261: &(((struct sidma *)sip->si_dmaaddr)->udct), cdb->cmd,
262: sip->si_cc, sip->si_ma);
263: } else {
264: if ((int)sip->si_ma & 1) {
265: sc_error("dma begins on odd address");
266: goto failed;
267: } else if ((int)sip->si_ma & 2) {
268: sir->csr |= SI_CSR_BPCON;
269: } else {
270: sir->csr &= ~SI_CSR_BPCON;
271: }
272: sir->dma_addr = SI_VME_DMA_ADDR(sip->si_ma);
273: sir->dma_count = sip->si_cc;
274: }
275:
276: /* setup sbc and start dma */
277: sir->sbc_wreg.mr |= SBC_MR_DMA;
278: if ((cdb->cmd == SC_READ) || (cdb->cmd == SC_REQUEST_SENSE)) {
279: sir->sbc_wreg.tcr = TCR_DATA_IN;
280: sir->sbc_wreg.ircv = 0;
281: } else {
282: sir->sbc_wreg.tcr = TCR_DATA_OUT;
283: sir->sbc_wreg.icr = SBC_ICR_DATA;
284: sir->sbc_wreg.send = 0;
285: }
286: if (ob == 0) {
287: sir->csr |= SI_CSR_DMA_EN;
288: }
289:
290: /* wait for dma completion */
291: if (si_wait(&sir->csr,
292: SI_CSR_SBC_IP|SI_CSR_DMA_IP|SI_CSR_DMA_CONFLICT, 1)
293: == 0) {
294: sc_error("dma never completed");
295: if (ob == 0) {
296: sir->csr &= ~SI_CSR_DMA_EN;
297: }
298: si_dma_cleanup(sir, ob);
299: goto failed;
300: }
301: if (ob == 0) {
302: sir->csr &= ~SI_CSR_DMA_EN;
303: }
304:
305: /* check reason for dma completion */
306: if (sir->csr & SI_CSR_SBC_IP) {
307: /* dma operation should end with a phase mismatch */
308: si_sbc_wait(&sir->sbc_rreg.bsr, SBC_BSR_PMTCH, 0);
309: } else {
310: if (sir->csr & SI_CSR_DMA_CONFLICT) {
311: sc_error("invalid reg access during dma");
312: } else if (sir->csr & SI_CSR_DMA_BUS_ERR) {
313: sc_error("bus error during dma");
314: } else {
315: if (ob)
316: sc_error("unknown dma failure");
317: else
318: sc_error("dma overrun");
319: }
320: si_dma_cleanup(sir, ob);
321: goto failed;
322: }
323:
324: /* handle special dma recv situations */
325: if ((cdb->cmd == SC_READ) || (cdb->cmd == SC_REQUEST_SENSE)) {
326: if (ob) {
327: sir->udc_raddr = UDC_ADR_COUNT;
328: if (si_wait(&sir->csr, SI_CSR_FIFO_EMPTY, 1) == 0) {
329: sc_error("fifo never emptied");
330: si_dma_cleanup(sir, ob);
331: goto failed;
332: }
333: /* if odd byte recv, must grab last byte by hand */
334: if ((sip->si_cc - sir->bcr) & 1) {
335: cp = sip->si_ma + (sip->si_cc - sir->bcr) - 1;
336: *cp = (sir->fifo_data & 0xff00) >> 8;
337:
338: /* udc may not dma last word */
339: } else if (((sir->udc_rdata*2) - sir->bcr) == 2) {
340: cp = sip->si_ma + (sip->si_cc - sir->bcr);
341: *(cp - 2) = (sir->fifo_data & 0xff00) >> 8;
342: *(cp - 1) = sir->fifo_data & 0x00ff;
343: }
344:
345: } else if ((sir->csr & SI_CSR_LOB) != 0) {
346: cp = sip->si_ma + (sip->si_cc - sir->bcr);
347: if ((sir->csr & SI_CSR_BPCON) == 0) {
348: switch (sir->csr & SI_CSR_LOB) {
349: case SI_CSR_LOB_THREE:
350: *(cp - 3) = (sir->bpr & 0xff000000) >> 24;
351: *(cp - 2) = (sir->bpr & 0x00ff0000) >> 16;
352: *(cp - 1) = (sir->bpr & 0x0000ff00) >> 8;
353: break;
354: case SI_CSR_LOB_TWO:
355: *(cp - 2) = (sir->bpr & 0xff000000) >> 24;
356: *(cp - 1) = (sir->bpr & 0x00ff0000) >> 16;
357: break;
358: case SI_CSR_LOB_ONE:
359: *(cp - 1) = (sir->bpr & 0xff000000) >> 24;
360: break;
361: }
362: } else {
363: *(cp - 1) = (sir->bpr & 0x0000ff00) >> 8;
364: }
365: }
366: }
367:
368: /* clear sbc interrupt */
369: junk = sir->sbc_rreg.clr;
370:
371: /* cleanup after a dma operation */
372: si_dma_cleanup(sir, ob);
373: }
374:
375: /* get status */
376: cp = (char *)scb;
377: for (i = 0;;) {
378: b = si_getbyte(sir, PHASE_STATUS);
379: if (b == -1) {
380: break;
381: }
382: if (i < STATUS_LEN) {
383: cp[i++] = b;
384: }
385: }
386: b = si_getbyte(sir, PHASE_MSG_IN);
387: if (b != SC_COMMAND_COMPLETE) {
388: if (b >= 0) { /* if not, si_getbyte already printed msg */
389: sc_error("invalid message");
390: }
391: goto failed;
392: }
393: return (sip->si_cc - sir->bcr);
394:
395: failed:
396: si_reset(sir, ob);
397: return (-1);
398: }
399:
400: si_ob_dma_setup(sir, udct, cmd, cc, ma)
401: register struct scsi_si_reg *sir;
402: register struct udc_table *udct;
403: register u_char cmd;
404: register int cc;
405: register char *ma;
406: {
407: /* setup udc dma info */
408: udct->haddr = ((SI_OB_DMA_ADDR(ma) & 0xff0000) >> 8) |
409: UDC_ADDR_INFO;
410: udct->laddr = SI_OB_DMA_ADDR(ma) & 0xffff;
411: udct->hcmr = UDC_CMR_HIGH;
412: udct->count = cc / 2;
413: if ((cmd == SC_READ) || (cmd == SC_REQUEST_SENSE)) {
414: udct->rsel = UDC_RSEL_RECV;
415: udct->lcmr = UDC_CMR_LRECV;
416: } else {
417: udct->rsel = UDC_RSEL_SEND;
418: udct->lcmr = UDC_CMR_LSEND;
419: if (cc & 1) {
420: udct->count++;
421: }
422: }
423:
424: /* initialize chain address register */
425: DELAY(SI_UDC_WAIT);
426: sir->udc_raddr = UDC_ADR_CAR_HIGH;
427: DELAY(SI_UDC_WAIT);
428: sir->udc_rdata = ((int)udct & 0xff0000) >> 8;
429: DELAY(SI_UDC_WAIT);
430: sir->udc_raddr = UDC_ADR_CAR_LOW;
431: DELAY(SI_UDC_WAIT);
432: sir->udc_rdata = (int)udct & 0xffff;
433:
434: /* initialize master mode register */
435: DELAY(SI_UDC_WAIT);
436: sir->udc_raddr = UDC_ADR_MODE;
437: DELAY(SI_UDC_WAIT);
438: sir->udc_rdata = UDC_MODE;
439:
440: /* issue start chain command */
441: DELAY(SI_UDC_WAIT);
442: sir->udc_raddr = UDC_ADR_COMMAND;
443: DELAY(SI_UDC_WAIT);
444: sir->udc_rdata = UDC_CMD_STRT_CHN;
445: }
446:
447: /*
448: * Reset some register information after a dma operation.
449: */
450: si_dma_cleanup(sir, ob)
451: register struct scsi_si_reg *sir;
452: register int ob;
453: {
454: if (ob) {
455: sir->udc_raddr = UDC_ADR_COMMAND;
456: DELAY(SI_UDC_WAIT);
457: sir->udc_rdata = UDC_CMD_RESET;
458: } else {
459: sir->csr &- ~SI_CSR_DMA_EN;
460: sir->dma_addr = 0;
461: }
462: sir->sbc_wreg.mr &= ~SBC_MR_DMA;
463: sir->sbc_wreg.icr = 0;
464: sir->sbc_wreg.tcr = 0;
465: }
466:
467: /*
468: * Wait for a condition to be (de)asserted.
469: */
470: si_wait(reg, cond, set)
471: register u_short *reg;
472: register u_short cond;
473: register int set;
474: {
475: register int i;
476: register u_short regval;
477:
478: for (i = 0; i < 1000000; i++) {
479: regval = *reg;
480: if ((set == 1) && (regval & cond)) {
481: return (1);
482: }
483: if ((set == 0) && !(regval & cond)) {
484: return (1);
485: }
486: DELAY(600);
487: }
488: return (0);
489: }
490:
491: /*
492: * Wait for a condition to be (de)asserted on the scsi bus.
493: */
494: si_sbc_wait(reg, cond, set)
495: register caddr_t reg;
496: register u_char cond;
497: register int set;
498: {
499: register int i;
500: register u_char regval;
501:
502: for (i = 0; i < 1000000; i++) {
503: regval = *reg;
504: if ((set == 1) && (regval & cond)) {
505: return (1);
506: }
507: if ((set == 0) && !(regval & cond)) {
508: return (1);
509: }
510: DELAY(600);
511: }
512: return (0);
513: }
514:
515: /*
516: * Put a byte onto the scsi bus.
517: */
518: si_putbyte(sir, phase, data, numbytes)
519: register struct scsi_si_reg *sir;
520: register u_short phase;
521: register u_char *data;
522: register int numbytes;
523: {
524: register int i;
525:
526: /* set up tcr so a phase match will occur */
527: if (phase == PHASE_COMMAND) {
528: sir->sbc_wreg.tcr = TCR_COMMAND;
529: } else if (phase == PHASE_MSG_OUT) {
530: sir->sbc_wreg.tcr = TCR_MSG_OUT;
531: } else {
532: sc_error("putbyte, bad phase specified");
533: return (0);
534: }
535:
536: /* put all desired bytes onto scsi bus */
537: for (i = 0; i < numbytes; i++) {
538: /* wait for target to request a byte */
539: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) {
540: sc_error("putbyte: target never set REQ");
541: return (0);
542: }
543:
544: /* load data for transfer */
545: sir->sbc_wreg.odr = *data++;
546: sir->sbc_wreg.icr = SBC_ICR_DATA;
547:
548: /* make sure phase match occurred */
549: if ((sir->sbc_rreg.bsr & SBC_BSR_PMTCH) == 0) {
550: sc_error("putbyte: phase mismatch");
551: return (0);
552: }
553:
554: /* complete req/ack handshake */
555: sir->sbc_wreg.icr |= SBC_ICR_ACK;
556: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) {
557: sc_error("putbyte: target never released REQ");
558: return (0);
559: }
560: sir->sbc_wreg.icr = 0;
561: }
562: sir->sbc_wreg.tcr = 0;
563: return (1);
564: }
565:
566: /*
567: * Get a byte from the scsi bus.
568: */
569: si_getbyte(sir, phase)
570: register struct scsi_si_reg *sir;
571: register u_short phase;
572: {
573: register u_char data;
574:
575: /* set up tcr so a phase match will occur */
576: if (phase == PHASE_STATUS) {
577: sir->sbc_wreg.tcr = TCR_STATUS;
578: } else if (phase == PHASE_MSG_IN) {
579: sir->sbc_wreg.tcr = TCR_MSG_IN;
580: } else {
581: sc_error("getbyte, bad phase specified");
582: return (-1);
583: }
584:
585: /* wait for target request */
586: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 1) == 0) {
587: sc_error("getbyte: target never set REQ");
588: sir->sbc_wreg.tcr = 0;
589: return (-1);
590: }
591:
592: /* check for correct information phase on scsi bus */
593: if (phase != (sir->sbc_rreg.cbsr & CBSR_PHASE_BITS)) {
594: if (phase != PHASE_STATUS) {
595: sc_error("getbyte: phase mismatch");
596: }
597: sir->sbc_wreg.tcr = 0;
598: return (-1);
599: }
600:
601: /* grab data */
602: data = sir->sbc_rreg.cdr;
603: sir->sbc_wreg.icr = SBC_ICR_ACK;
604:
605: /* complete req/ack handshake */
606: if (si_sbc_wait(&sir->sbc_rreg.cbsr, SBC_CBSR_REQ, 0) == 0) {
607: sc_error("getbyte: target never released REQ");
608: sir->sbc_wreg.icr = 0;
609: sir->sbc_wreg.tcr = 0;
610: return (-1);
611: }
612: sir->sbc_wreg.icr = 0;
613: sir->sbc_wreg.tcr = 0;
614: return (data);
615: }
616:
617: /*
618: * Reset SCSI control logic.
619: */
620: si_reset(sir, ob)
621: register struct scsi_si_reg *sir;
622: register int ob;
623: {
624: register u_char junk;
625:
626: /* reset bcr, fifo, udc, and sbc */
627: sir->bcr = 0;
628: sir->csr = 0;
629: DELAY(10);
630: sir->csr = SI_CSR_SCSI_RES|SI_CSR_FIFO_RES;
631: if (ob == 0) {
632: sir->dma_addr = 0;
633: sir->dma_count = 0;
634: }
635:
636: /* issue scsi bus reset */
637: sir->sbc_wreg.icr = SBC_ICR_RST;
638: DELAY(50);
639: sir->sbc_wreg.icr = 0;
640: junk = sir->sbc_rreg.clr;
641: DELAY(10000000);
642: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.