|
|
1.1 root 1: /*
2: * @(#)sc.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc.
3: */
4:
5: #include <sys/param.h>
6: #include <sys/inode.h>
7: #include <sun/dklabel.h>
8: #include <sun/dkio.h>
9: #include <sys/buf.h>
10: #include <sundev/screg.h>
11: #include <sundev/sireg.h>
12: #include <sundev/scsi.h>
13: #include <machine/sunromvec.h>
14: #include <machine/idprom.h>
15: #include "saio.h"
16:
17: /*
18: * Low-level routines common to all devices on the SCSI bus
19: */
20:
21: /*
22: * Interface to the routines in this module is via a second "sip"
23: * structure contained in the caller's local variables.
24: *
25: * This "sip" must be initialized with sip->si_boottab = scdriver
26: * and must then be devopen()ed before any I/O can be done.
27: *
28: * The device must be closed with devclose().
29: */
30:
31: /* How our addrs look to the SCSI DMA hardware */
32: #define SCSI_DMA_ADDR(x) (((int)x)&0x000FFFFF)
33:
34: /*
35: * The interfaces we export
36: */
37: extern int nullsys();
38: int scopen();
39:
40: struct boottab scdriver =
41: {"sd", nullsys, nullsys, scopen, nullsys,
42: nullsys, "", 0};
43:
44: char seqerr_msg[] = "sequence error"; /* Saves dup copy of string */
45:
46: /*
47: * Record an error message from scsi
48: */
49: sc_error(msg)
50: char *msg;
51: {
52: printf("scsi: %s\n", msg);
53: }
54:
55: #define SCSI_MULTI_BASE 0x80000
56: #define SCSI_VME_BASE 0x200000
57: #define SCSI_SIZE 0x4000 /* incr to next board - OK for VME ? */
58: #define SCSI_NSTD 2 /* # of standard address boards */
59:
60: /*
61: * Open the SCSI host adapter.
62: * Note that the Multibus address and the VME address
63: * are totally different, although both are controller '0'.
64: * More fon goes here for the model 25.
65: */
66: int
67: scopen(sip)
68: register struct saioreq *sip;
69: {
70: register struct scsi_ha_reg *har;
71: struct idprom id;
72: register int base;
73: enum MAPTYPES space;
74: char *devalloc();
75:
76: if (idprom(IDFORM_1, &id) == IDFORM_1 &&
77: id.id_machine == IDM_SUN2_MULTI) {
78: base = SCSI_MULTI_BASE;
79: space = MAP_MBMEM;
80: } else {
81: base = SCSI_VME_BASE;
82: space = MAP_VME24A16D;
83: }
84: if (sip->si_ctlr < SCSI_NSTD)
85: sip->si_ctlr = base + sip->si_ctlr * SCSI_SIZE;
86: /* now map it in */
87: sip->si_devaddr = devalloc(space, sip->si_ctlr,
88: sizeof (struct scsi_ha_reg));
89: if (sip->si_devaddr == 0)
90: return (-1);
91:
92: har = (struct scsi_ha_reg *) sip->si_devaddr;
93: har->icr = 0;
94: return 0;
95: }
96:
97:
98: /*
99: * Write a command to the SCSI bus.
100: *
101: * The supplied sip is the one opened by scopen().
102: * DMA is done based on sip->si_ma and sip->si_cc.
103: *
104: * Returns -1 for error, otherwise returns the residual count not DMAed
105: * (zero for success).
106: *
107: * FIXME, this must be accessed via a boottab vector,
108: * to allow host adap to switch.
109: * Must pass cdb, scb in sip somewhere...
110: */
111: int
112: scdoit(cdb, scb, sip)
113: register struct scsi_cdb *cdb;
114: register struct scsi_scb *scb;
115: register struct saioreq *sip;
116: {
117: register char *cp;
118: register int i, b;
119: register struct scsi_ha_reg *har;
120:
121: har = (struct scsi_ha_reg *) sip->si_devaddr;
122:
123: /* select controller */
124: har->data = 1 << sip->si_unit; /* Set target on SCSI bus */
125:
126: i = 100000;
127: for(;;) {
128: if ((har->icr & ICR_BUSY) == 0) {
129: break;
130: }
131: if (i-- <= 0) {
132: sc_error("bus continuously busy");
133: har->icr = ICR_RESET;
134: DELAY(50);
135: har->icr = 0;
136: return (-1);
137: }
138: }
139: har->icr = ICR_SELECT;
140: if (sc_wait(har, ICR_BUSY) == 0) {
141: /*
142: * No response to select. Reset bus and get out.
143: */
144: sc_error("no such controller on SCSI bus");
145: har->icr = ICR_RESET;
146: DELAY(50);
147: har->icr = 0;
148: return (-1);
149: }
150: /* pass command */
151: har->icr = ICR_WORD_MODE | ICR_DMA_ENABLE;
152: har->dma_addr = SCSI_DMA_ADDR(sip->si_ma);
153: har->dma_count = ~sip->si_cc;
154: cp = (char *) cdb;
155: for (i = 0; i < sizeof (struct scsi_cdb); i++) {
156: if (sc_putbyte(har, ICR_COMMAND, *cp++) == 0) {
157: return (-1);
158: }
159: }
160: /* wait for command completion */
161: if (sc_wait(har, ICR_INTERRUPT_REQUEST) == 0) {
162: return (-1);
163: }
164: /* handle odd length dma transfer, adjust dma count */
165: if (har->icr & ICR_ODD_LENGTH) {
166: if ((cdb->cmd == SC_REQUEST_SENSE) || (cdb->cmd == SC_READ)) {
167: cp = (char *)sip->si_ma + sip->si_cc - 1;
168: *cp = (char)har->data;
169: har->dma_count = ~(~har->dma_count - 1);
170: } else {
171: har->dma_count = ~(~har->dma_count + 1);
172: }
173: }
174: /* get status */
175: cp = (char *) scb;
176: i = 0;
177: for (;;) {
178: b = sc_getbyte(har, ICR_STATUS);
179: if (b == -1) {
180: break;
181: }
182: if (i < STATUS_LEN) {
183: cp[i++] = b;
184: }
185: }
186: b = sc_getbyte(har, ICR_MESSAGE_IN);
187: if (b != SC_COMMAND_COMPLETE) {
188: if (b >= 0) { /* if not, sc_getbyte already printed msg */
189: sc_error("invalid message");
190: }
191: return (-1);
192: }
193: return (sip->si_cc - ~har->dma_count);
194: }
195:
196:
197: /*
198: * Wait for a condition on the scsi bus.
199: */
200: int
201: sc_wait(har, cond)
202: register struct scsi_ha_reg *har;
203: {
204: register int icr, count;
205:
206: if (cond == ICR_INTERRUPT_REQUEST) {
207: count = 1000000;
208: } else {
209: count = 10000;
210: }
211: while (((icr = har->icr) & cond) != cond) {
212: if (--count <= 0) {
213: sc_error("timeout");
214: return (0);
215: }
216: if (icr & ICR_BUS_ERROR) {
217: sc_error("bus error");
218: return (0);
219: }
220: DELAY(5000);
221: }
222: return (1);
223: }
224:
225:
226: /*
227: * Put a byte into the scsi command register.
228: */
229: int
230: sc_putbyte(har, bits, c)
231: register struct scsi_ha_reg *har;
232: {
233: if (sc_wait(har, ICR_REQUEST) == 0) {
234: return (0);
235: }
236: if ((har->icr & ICR_BITS) != bits) {
237: sc_error(seqerr_msg);
238: return (0);
239: }
240: har->cmd_stat = c;
241: return (1);
242: }
243:
244:
245: /*
246: * Get a byte from the scsi command/status register.
247: * <bits> defines the bits we want to see on in the ICR.
248: * If <bits> is wrong, we print a message -- unless <bits> is ICR_STATUS.
249: * This hack is because scdoit keeps calling getbyte until it sees a non-
250: * status byte; this is not an error in sequence as long as the next byte
251: * has MESSAGE_IN tags. FIXME.
252: */
253: int
254: sc_getbyte(har, bits)
255: register struct scsi_ha_reg *har;
256: {
257: if (sc_wait(har, ICR_REQUEST) == 0) {
258: return (-1);
259: }
260: if ((har->icr & ICR_BITS) != bits) {
261: if (bits != ICR_STATUS) sc_error(seqerr_msg); /* Hack hack */
262: return (-1);
263: }
264: return (har->cmd_stat);
265: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.