|
|
1.1 root 1: /*
2: * Copyright (c) 1988 University of Utah.
3: * Copyright (c) 1990 The Regents of the University of California.
4: * All rights reserved.
5: *
6: * This code is derived from software contributed to Berkeley by
7: * Van Jacobson of Lawrence Berkeley Laboratory and the Systems
8: * Programming Group of the University of Utah Computer Science Department.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
38: * from: Utah $Hdr: scsi.c 1.3 90/01/27$
39: *
40: * @(#)scsi.c 7.4 (Berkeley) 5/7/91
41: */
42:
43: /*
44: * SCSI bus driver for standalone programs.
45: */
46:
47: #include <sys/param.h>
48: #include <sys/reboot.h>
49: #include "../dev/device.h"
50: #include "../dev/scsireg.h"
51: #include "scsivar.h"
52:
53: #include "saio.h"
54: #include "samachdep.h"
55:
56: struct scsi_softc scsi_softc[NSCSI];
57:
58: #define scsiunit(x) ((x) >> 3)
59: #define scsislave(x) ((x) & 7)
60:
61: void scsireset();
62: int scsi_cmd_wait = 500;
63: int scsi_data_wait = 300000;
64:
65: scsiinit()
66: {
67: extern struct hp_hw sc_table[];
68: register struct hp_hw *hw;
69: register struct scsi_softc *hs;
70: register int i, addr;
71: static int first = 1;
72:
73: i = 0;
74: for (hw = sc_table; i < NSCSI && hw < &sc_table[MAXCTLRS]; hw++) {
75: if (!HW_ISSCSI(hw))
76: continue;
77: hs = &scsi_softc[i];
78: hs->sc_addr = hw->hw_kva;
79: scsireset(i);
80: if (howto & RB_ASKNAME)
81: printf("scsi%d at sc%d\n", i, hw->hw_sc);
82: /*
83: * Adjust devtype on first call. This routine assumes that
84: * adaptor is in the high byte of devtype.
85: */
86: if (first && ((devtype >> 24) & 0xff) == hw->hw_sc) {
87: devtype = (devtype & 0x00ffffff) | (i << 24);
88: first = 0;
89: }
90: hs->sc_alive = 1;
91: i++;
92: }
93: }
94:
95: scsialive(unit)
96: register int unit;
97: {
98: unit = scsiunit(unit);
99: if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0)
100: return (0);
101: return (1);
102: }
103:
104: void
105: scsireset(unit)
106: register int unit;
107: {
108: volatile register struct scsidevice *hd;
109: register struct scsi_softc *hs;
110: u_int i;
111:
112: unit = scsiunit(unit);
113: hs = &scsi_softc[unit];
114: hd = (struct scsidevice *)hs->sc_addr;
115: hd->scsi_id = 0xFF;
116: DELAY(100);
117: /*
118: * Disable interrupts then reset the FUJI chip.
119: */
120: hd->scsi_csr = 0;
121: hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
122: hd->scsi_scmd = 0;
123: hd->scsi_tmod = 0;
124: hd->scsi_pctl = 0;
125: hd->scsi_temp = 0;
126: hd->scsi_tch = 0;
127: hd->scsi_tcm = 0;
128: hd->scsi_tcl = 0;
129: hd->scsi_ints = 0;
130:
131: /*
132: * Configure the FUJI chip with its SCSI address, all
133: * interrupts enabled & appropriate parity.
134: */
135: i = (~hd->scsi_hconf) & 0x7;
136: hs->sc_scsi_addr = 1 << i;
137: hd->scsi_bdid = i;
138: if (hd->scsi_hconf & HCONF_PARITY)
139: hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
140: SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
141: SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
142: else
143: hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
144: SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
145: SCTL_INTR_ENAB;
146: hd->scsi_sctl &=~ SCTL_DISABLE;
147: }
148:
149:
150: int
151: scsiabort(hs, hd)
152: register struct scsi_softc *hs;
153: volatile register struct scsidevice *hd;
154: {
155: printf("scsi error: scsiabort\n");
156: return (0);
157: }
158:
159: static int
160: issue_select(hd, target, our_addr)
161: volatile register struct scsidevice *hd;
162: u_char target, our_addr;
163: {
164: if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
165: return (1);
166:
167: if (hd->scsi_ints & INTS_DISCON)
168: hd->scsi_ints = INTS_DISCON;
169:
170: hd->scsi_pctl = 0;
171: hd->scsi_temp = (1 << target) | our_addr;
172: /* select timeout is hardcoded to 2ms */
173: hd->scsi_tch = 0;
174: hd->scsi_tcm = 32;
175: hd->scsi_tcl = 4;
176:
177: hd->scsi_scmd = SCMD_SELECT;
178: return (0);
179: }
180:
181: static int
182: wait_for_select(hd)
183: volatile register struct scsidevice *hd;
184: {
185: u_char ints;
186:
187: while ((ints = hd->scsi_ints) == 0)
188: DELAY(1);
189: hd->scsi_ints = ints;
190: return (!(hd->scsi_ssts & SSTS_INITIATOR));
191: }
192:
193: static int
194: ixfer_start(hd, len, phase, wait)
195: volatile register struct scsidevice *hd;
196: int len;
197: u_char phase;
198: register int wait;
199: {
200:
201: hd->scsi_tch = len >> 16;
202: hd->scsi_tcm = len >> 8;
203: hd->scsi_tcl = len;
204: hd->scsi_pctl = phase;
205: hd->scsi_tmod = 0; /*XXX*/
206: hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
207:
208: /* wait for xfer to start or svc_req interrupt */
209: while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
210: if (hd->scsi_ints || --wait < 0)
211: return (0);
212: DELAY(1);
213: }
214: return (1);
215: }
216:
217: static int
218: ixfer_out(hd, len, buf)
219: volatile register struct scsidevice *hd;
220: int len;
221: register u_char *buf;
222: {
223: register int wait = scsi_data_wait;
224:
225: for (; len > 0; --len) {
226: while (hd->scsi_ssts & SSTS_DREG_FULL) {
227: if (hd->scsi_ints || --wait < 0)
228: return (len);
229: DELAY(1);
230: }
231: hd->scsi_dreg = *buf++;
232: }
233: return (0);
234: }
235:
236: static int
237: ixfer_in(hd, len, buf)
238: volatile register struct scsidevice *hd;
239: int len;
240: register u_char *buf;
241: {
242: register int wait = scsi_data_wait;
243:
244: for (; len > 0; --len) {
245: while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
246: if (hd->scsi_ints || --wait < 0) {
247: while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
248: *buf++ = hd->scsi_dreg;
249: --len;
250: }
251: return (len);
252: }
253: DELAY(1);
254: }
255: *buf++ = hd->scsi_dreg;
256: }
257: return (len);
258: }
259:
260: static int
261: scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
262: struct scsi_softc *hs;
263: int target;
264: u_char *cbuf;
265: int clen;
266: u_char *buf;
267: int len;
268: u_char xferphase;
269: {
270: volatile register struct scsidevice *hd =
271: (struct scsidevice *)hs->sc_addr;
272: int i;
273: u_char phase, ints;
274: register int wait;
275:
276: /* select the SCSI bus (it's an error if bus isn't free) */
277: if (issue_select(hd, target, hs->sc_scsi_addr))
278: return (0);
279: if (wait_for_select(hd))
280: return (0);
281: /*
282: * Wait for a phase change (or error) then let the device
283: * sequence us through the various SCSI phases.
284: */
285: phase = CMD_PHASE;
286: while (1) {
287: wait = scsi_cmd_wait;
288: switch (phase) {
289:
290: case CMD_PHASE:
291: if (ixfer_start(hd, clen, phase, wait))
292: if (ixfer_out(hd, clen, cbuf))
293: goto abort;
294: phase = xferphase;
295: break;
296:
297: case DATA_IN_PHASE:
298: if (len <= 0)
299: goto abort;
300: wait = scsi_data_wait;
301: if (ixfer_start(hd, len, phase, wait) ||
302: !(hd->scsi_ssts & SSTS_DREG_EMPTY))
303: ixfer_in(hd, len, buf);
304: phase = STATUS_PHASE;
305: break;
306:
307: case DATA_OUT_PHASE:
308: if (len <= 0)
309: goto abort;
310: wait = scsi_data_wait;
311: if (ixfer_start(hd, len, phase, wait))
312: if (ixfer_out(hd, len, buf))
313: goto abort;
314: phase = STATUS_PHASE;
315: break;
316:
317: case STATUS_PHASE:
318: wait = scsi_data_wait;
319: if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
320: !(hd->scsi_ssts & SSTS_DREG_EMPTY))
321: ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat);
322: phase = MESG_IN_PHASE;
323: break;
324:
325: case MESG_IN_PHASE:
326: if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
327: !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
328: ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg);
329: hd->scsi_scmd = SCMD_RST_ACK;
330: }
331: phase = BUS_FREE_PHASE;
332: break;
333:
334: case BUS_FREE_PHASE:
335: return (1);
336:
337: default:
338: printf("unexpected scsi phase %d\n", phase);
339: goto abort;
340: }
341: /* wait for last command to complete */
342: while ((ints = hd->scsi_ints) == 0) {
343: if (--wait < 0)
344: goto abort;
345: DELAY(1);
346: }
347: hd->scsi_ints = ints;
348: if (ints & INTS_SRV_REQ)
349: phase = hd->scsi_psns & PHASE;
350: else if (ints & INTS_DISCON)
351: return (1);
352: else if ((ints & INTS_CMD_DONE) == 0) {
353: goto abort;
354: }
355: }
356: abort:
357: scsiabort(hs, hd);
358: return (0);
359: }
360:
361: int
362: scsi_test_unit_rdy(unit)
363: {
364: int ctlr = scsiunit(unit);
365: int slave = scsislave(unit);
366: register struct scsi_softc *hs = &scsi_softc[ctlr];
367: static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
368:
369: if (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0,
370: STATUS_PHASE) == 0)
371: return (0);
372:
373: return (hs->sc_stat == 0);
374: }
375:
376: int
377: scsi_request_sense(unit, buf, len)
378: int unit;
379: u_char *buf;
380: unsigned len;
381: {
382: int ctlr = scsiunit(unit);
383: int slave = scsislave(unit);
384: register struct scsi_softc *hs = &scsi_softc[ctlr];
385: static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
386:
387: cdb.len = len;
388: return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
389: }
390:
391: int
392: scsi_read_capacity(unit, buf, len)
393: int unit;
394: u_char *buf;
395: unsigned len;
396: {
397: int ctlr = scsiunit(unit);
398: int slave = scsislave(unit);
399: register struct scsi_softc *hs = &scsi_softc[ctlr];
400: static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY };
401:
402: return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
403: }
404:
405: int
406: scsi_tt_read(unit, buf, len, blk, nblk)
407: int unit;
408: u_char *buf;
409: u_int len;
410: daddr_t blk;
411: u_int nblk;
412: {
413: int ctlr = scsiunit(unit);
414: int slave = scsislave(unit);
415: register struct scsi_softc *hs = &scsi_softc[ctlr];
416: struct scsi_cdb10 cdb;
417: int stat;
418:
419: bzero(&cdb, sizeof(cdb));
420: cdb.cmd = CMD_READ_EXT;
421: cdb.lbah = blk >> 24;
422: cdb.lbahm = blk >> 16;
423: cdb.lbalm = blk >> 8;
424: cdb.lbal = blk;
425: cdb.lenh = nblk >> (8 + DEV_BSHIFT);
426: cdb.lenl = nblk >> DEV_BSHIFT;
427: stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
428: if (stat == 0)
429: return (1);
430: return (hs->sc_stat);
431: }
432:
433: int
434: scsi_tt_write(unit, buf, len, blk, nblk)
435: int unit;
436: u_char *buf;
437: u_int len;
438: daddr_t blk;
439: u_int nblk;
440: {
441: int ctlr = scsiunit(unit);
442: int slave = scsislave(unit);
443: register struct scsi_softc *hs = &scsi_softc[ctlr];
444: struct scsi_cdb10 cdb;
445: int stat;
446:
447: bzero(&cdb, sizeof(cdb));
448: cdb.cmd = CMD_WRITE_EXT;
449: cdb.lbah = blk >> 24;
450: cdb.lbahm = blk >> 16;
451: cdb.lbalm = blk >> 8;
452: cdb.lbal = blk;
453: cdb.lenh = nblk >> (8 + DEV_BSHIFT);
454: cdb.lenl = nblk >> DEV_BSHIFT;
455: stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
456: if (stat == 0)
457: return (1);
458: return (hs->sc_stat);
459: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.