|
|
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: *
1.1.1.2 ! root 40: * from: @(#)scsi.c 7.4 (Berkeley) 5/7/91
! 41: * scsi.c,v 1.2 1993/05/22 07:59:21 cgd Exp
1.1 root 42: */
43:
44: /*
45: * SCSI bus driver for standalone programs.
46: */
47:
48: #include <sys/param.h>
49: #include <sys/reboot.h>
50: #include "../dev/device.h"
51: #include "../dev/scsireg.h"
52: #include "scsivar.h"
53:
54: #include "saio.h"
55: #include "samachdep.h"
56:
57: struct scsi_softc scsi_softc[NSCSI];
58:
59: #define scsiunit(x) ((x) >> 3)
60: #define scsislave(x) ((x) & 7)
61:
62: void scsireset();
63: int scsi_cmd_wait = 500;
64: int scsi_data_wait = 300000;
65:
66: scsiinit()
67: {
68: extern struct hp_hw sc_table[];
69: register struct hp_hw *hw;
70: register struct scsi_softc *hs;
71: register int i, addr;
72: static int first = 1;
73:
74: i = 0;
75: for (hw = sc_table; i < NSCSI && hw < &sc_table[MAXCTLRS]; hw++) {
76: if (!HW_ISSCSI(hw))
77: continue;
78: hs = &scsi_softc[i];
79: hs->sc_addr = hw->hw_kva;
80: scsireset(i);
81: if (howto & RB_ASKNAME)
82: printf("scsi%d at sc%d\n", i, hw->hw_sc);
83: /*
84: * Adjust devtype on first call. This routine assumes that
85: * adaptor is in the high byte of devtype.
86: */
87: if (first && ((devtype >> 24) & 0xff) == hw->hw_sc) {
88: devtype = (devtype & 0x00ffffff) | (i << 24);
89: first = 0;
90: }
91: hs->sc_alive = 1;
92: i++;
93: }
94: }
95:
96: scsialive(unit)
97: register int unit;
98: {
99: unit = scsiunit(unit);
100: if (unit >= NSCSI || scsi_softc[unit].sc_alive == 0)
101: return (0);
102: return (1);
103: }
104:
105: void
106: scsireset(unit)
107: register int unit;
108: {
109: volatile register struct scsidevice *hd;
110: register struct scsi_softc *hs;
111: u_int i;
112:
113: unit = scsiunit(unit);
114: hs = &scsi_softc[unit];
115: hd = (struct scsidevice *)hs->sc_addr;
116: hd->scsi_id = 0xFF;
117: DELAY(100);
118: /*
119: * Disable interrupts then reset the FUJI chip.
120: */
121: hd->scsi_csr = 0;
122: hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
123: hd->scsi_scmd = 0;
124: hd->scsi_tmod = 0;
125: hd->scsi_pctl = 0;
126: hd->scsi_temp = 0;
127: hd->scsi_tch = 0;
128: hd->scsi_tcm = 0;
129: hd->scsi_tcl = 0;
130: hd->scsi_ints = 0;
131:
132: /*
133: * Configure the FUJI chip with its SCSI address, all
134: * interrupts enabled & appropriate parity.
135: */
136: i = (~hd->scsi_hconf) & 0x7;
137: hs->sc_scsi_addr = 1 << i;
138: hd->scsi_bdid = i;
139: if (hd->scsi_hconf & HCONF_PARITY)
140: hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
141: SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
142: SCTL_INTR_ENAB | SCTL_PARITY_ENAB;
143: else
144: hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB |
145: SCTL_SEL_ENAB | SCTL_RESEL_ENAB |
146: SCTL_INTR_ENAB;
147: hd->scsi_sctl &=~ SCTL_DISABLE;
148: }
149:
150:
151: int
152: scsiabort(hs, hd)
153: register struct scsi_softc *hs;
154: volatile register struct scsidevice *hd;
155: {
156: printf("scsi error: scsiabort\n");
157: return (0);
158: }
159:
160: static int
161: issue_select(hd, target, our_addr)
162: volatile register struct scsidevice *hd;
163: u_char target, our_addr;
164: {
165: if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
166: return (1);
167:
168: if (hd->scsi_ints & INTS_DISCON)
169: hd->scsi_ints = INTS_DISCON;
170:
171: hd->scsi_pctl = 0;
172: hd->scsi_temp = (1 << target) | our_addr;
173: /* select timeout is hardcoded to 2ms */
174: hd->scsi_tch = 0;
175: hd->scsi_tcm = 32;
176: hd->scsi_tcl = 4;
177:
178: hd->scsi_scmd = SCMD_SELECT;
179: return (0);
180: }
181:
182: static int
183: wait_for_select(hd)
184: volatile register struct scsidevice *hd;
185: {
186: u_char ints;
187:
188: while ((ints = hd->scsi_ints) == 0)
189: DELAY(1);
190: hd->scsi_ints = ints;
191: return (!(hd->scsi_ssts & SSTS_INITIATOR));
192: }
193:
194: static int
195: ixfer_start(hd, len, phase, wait)
196: volatile register struct scsidevice *hd;
197: int len;
198: u_char phase;
199: register int wait;
200: {
201:
202: hd->scsi_tch = len >> 16;
203: hd->scsi_tcm = len >> 8;
204: hd->scsi_tcl = len;
205: hd->scsi_pctl = phase;
206: hd->scsi_tmod = 0; /*XXX*/
207: hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
208:
209: /* wait for xfer to start or svc_req interrupt */
210: while ((hd->scsi_ssts & SSTS_BUSY) == 0) {
211: if (hd->scsi_ints || --wait < 0)
212: return (0);
213: DELAY(1);
214: }
215: return (1);
216: }
217:
218: static int
219: ixfer_out(hd, len, buf)
220: volatile register struct scsidevice *hd;
221: int len;
222: register u_char *buf;
223: {
224: register int wait = scsi_data_wait;
225:
226: for (; len > 0; --len) {
227: while (hd->scsi_ssts & SSTS_DREG_FULL) {
228: if (hd->scsi_ints || --wait < 0)
229: return (len);
230: DELAY(1);
231: }
232: hd->scsi_dreg = *buf++;
233: }
234: return (0);
235: }
236:
237: static int
238: ixfer_in(hd, len, buf)
239: volatile register struct scsidevice *hd;
240: int len;
241: register u_char *buf;
242: {
243: register int wait = scsi_data_wait;
244:
245: for (; len > 0; --len) {
246: while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
247: if (hd->scsi_ints || --wait < 0) {
248: while (! (hd->scsi_ssts & SSTS_DREG_EMPTY)) {
249: *buf++ = hd->scsi_dreg;
250: --len;
251: }
252: return (len);
253: }
254: DELAY(1);
255: }
256: *buf++ = hd->scsi_dreg;
257: }
258: return (len);
259: }
260:
261: static int
262: scsiicmd(hs, target, cbuf, clen, buf, len, xferphase)
263: struct scsi_softc *hs;
264: int target;
265: u_char *cbuf;
266: int clen;
267: u_char *buf;
268: int len;
269: u_char xferphase;
270: {
271: volatile register struct scsidevice *hd =
272: (struct scsidevice *)hs->sc_addr;
273: int i;
274: u_char phase, ints;
275: register int wait;
276:
277: /* select the SCSI bus (it's an error if bus isn't free) */
278: if (issue_select(hd, target, hs->sc_scsi_addr))
279: return (0);
280: if (wait_for_select(hd))
281: return (0);
282: /*
283: * Wait for a phase change (or error) then let the device
284: * sequence us through the various SCSI phases.
285: */
286: phase = CMD_PHASE;
287: while (1) {
288: wait = scsi_cmd_wait;
289: switch (phase) {
290:
291: case CMD_PHASE:
292: if (ixfer_start(hd, clen, phase, wait))
293: if (ixfer_out(hd, clen, cbuf))
294: goto abort;
295: phase = xferphase;
296: break;
297:
298: case DATA_IN_PHASE:
299: if (len <= 0)
300: goto abort;
301: wait = scsi_data_wait;
302: if (ixfer_start(hd, len, phase, wait) ||
303: !(hd->scsi_ssts & SSTS_DREG_EMPTY))
304: ixfer_in(hd, len, buf);
305: phase = STATUS_PHASE;
306: break;
307:
308: case DATA_OUT_PHASE:
309: if (len <= 0)
310: goto abort;
311: wait = scsi_data_wait;
312: if (ixfer_start(hd, len, phase, wait))
313: if (ixfer_out(hd, len, buf))
314: goto abort;
315: phase = STATUS_PHASE;
316: break;
317:
318: case STATUS_PHASE:
319: wait = scsi_data_wait;
320: if (ixfer_start(hd, sizeof(hs->sc_stat), phase, wait) ||
321: !(hd->scsi_ssts & SSTS_DREG_EMPTY))
322: ixfer_in(hd, sizeof(hs->sc_stat), &hs->sc_stat);
323: phase = MESG_IN_PHASE;
324: break;
325:
326: case MESG_IN_PHASE:
327: if (ixfer_start(hd, sizeof(hs->sc_msg), phase, wait) ||
328: !(hd->scsi_ssts & SSTS_DREG_EMPTY)) {
329: ixfer_in(hd, sizeof(hs->sc_msg), &hs->sc_msg);
330: hd->scsi_scmd = SCMD_RST_ACK;
331: }
332: phase = BUS_FREE_PHASE;
333: break;
334:
335: case BUS_FREE_PHASE:
336: return (1);
337:
338: default:
339: printf("unexpected scsi phase %d\n", phase);
340: goto abort;
341: }
342: /* wait for last command to complete */
343: while ((ints = hd->scsi_ints) == 0) {
344: if (--wait < 0)
345: goto abort;
346: DELAY(1);
347: }
348: hd->scsi_ints = ints;
349: if (ints & INTS_SRV_REQ)
350: phase = hd->scsi_psns & PHASE;
351: else if (ints & INTS_DISCON)
352: return (1);
353: else if ((ints & INTS_CMD_DONE) == 0) {
354: goto abort;
355: }
356: }
357: abort:
358: scsiabort(hs, hd);
359: return (0);
360: }
361:
362: int
363: scsi_test_unit_rdy(unit)
364: {
365: int ctlr = scsiunit(unit);
366: int slave = scsislave(unit);
367: register struct scsi_softc *hs = &scsi_softc[ctlr];
368: static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
369:
370: if (scsiicmd(hs, slave, &cdb, sizeof(cdb), (u_char *)0, 0,
371: STATUS_PHASE) == 0)
372: return (0);
373:
374: return (hs->sc_stat == 0);
375: }
376:
377: int
378: scsi_request_sense(unit, buf, len)
379: int unit;
380: u_char *buf;
381: unsigned len;
382: {
383: int ctlr = scsiunit(unit);
384: int slave = scsislave(unit);
385: register struct scsi_softc *hs = &scsi_softc[ctlr];
386: static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
387:
388: cdb.len = len;
389: return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
390: }
391:
392: int
393: scsi_read_capacity(unit, buf, len)
394: int unit;
395: u_char *buf;
396: unsigned len;
397: {
398: int ctlr = scsiunit(unit);
399: int slave = scsislave(unit);
400: register struct scsi_softc *hs = &scsi_softc[ctlr];
401: static struct scsi_cdb10 cdb = { CMD_READ_CAPACITY };
402:
403: return (scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE));
404: }
405:
406: int
407: scsi_tt_read(unit, buf, len, blk, nblk)
408: int unit;
409: u_char *buf;
410: u_int len;
411: daddr_t blk;
412: u_int nblk;
413: {
414: int ctlr = scsiunit(unit);
415: int slave = scsislave(unit);
416: register struct scsi_softc *hs = &scsi_softc[ctlr];
417: struct scsi_cdb10 cdb;
418: int stat;
419:
420: bzero(&cdb, sizeof(cdb));
421: cdb.cmd = CMD_READ_EXT;
422: cdb.lbah = blk >> 24;
423: cdb.lbahm = blk >> 16;
424: cdb.lbalm = blk >> 8;
425: cdb.lbal = blk;
426: cdb.lenh = nblk >> (8 + DEV_BSHIFT);
427: cdb.lenl = nblk >> DEV_BSHIFT;
428: stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_IN_PHASE);
429: if (stat == 0)
430: return (1);
431: return (hs->sc_stat);
432: }
433:
434: int
435: scsi_tt_write(unit, buf, len, blk, nblk)
436: int unit;
437: u_char *buf;
438: u_int len;
439: daddr_t blk;
440: u_int nblk;
441: {
442: int ctlr = scsiunit(unit);
443: int slave = scsislave(unit);
444: register struct scsi_softc *hs = &scsi_softc[ctlr];
445: struct scsi_cdb10 cdb;
446: int stat;
447:
448: bzero(&cdb, sizeof(cdb));
449: cdb.cmd = CMD_WRITE_EXT;
450: cdb.lbah = blk >> 24;
451: cdb.lbahm = blk >> 16;
452: cdb.lbalm = blk >> 8;
453: cdb.lbal = blk;
454: cdb.lenh = nblk >> (8 + DEV_BSHIFT);
455: cdb.lenl = nblk >> DEV_BSHIFT;
456: stat = scsiicmd(hs, slave, &cdb, sizeof(cdb), buf, len, DATA_OUT_PHASE);
457: if (stat == 0)
458: return (1);
459: return (hs->sc_stat);
460: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.