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