sc.c revision 1.4.2.2 1 1.4.2.2 yamt /* $NetBSD: sc.c,v 1.4.2.2 2013/01/23 00:05:54 yamt Exp $ */
2 1.4.2.2 yamt
3 1.4.2.2 yamt /*
4 1.4.2.2 yamt * Copyright (c) 1992 OMRON Corporation.
5 1.4.2.2 yamt *
6 1.4.2.2 yamt * This code is derived from software contributed to Berkeley by
7 1.4.2.2 yamt * OMRON Corporation.
8 1.4.2.2 yamt *
9 1.4.2.2 yamt * Redistribution and use in source and binary forms, with or without
10 1.4.2.2 yamt * modification, are permitted provided that the following conditions
11 1.4.2.2 yamt * are met:
12 1.4.2.2 yamt * 1. Redistributions of source code must retain the above copyright
13 1.4.2.2 yamt * notice, this list of conditions and the following disclaimer.
14 1.4.2.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
15 1.4.2.2 yamt * notice, this list of conditions and the following disclaimer in the
16 1.4.2.2 yamt * documentation and/or other materials provided with the distribution.
17 1.4.2.2 yamt * 3. All advertising materials mentioning features or use of this software
18 1.4.2.2 yamt * must display the following acknowledgement:
19 1.4.2.2 yamt * This product includes software developed by the University of
20 1.4.2.2 yamt * California, Berkeley and its contributors.
21 1.4.2.2 yamt * 4. Neither the name of the University nor the names of its contributors
22 1.4.2.2 yamt * may be used to endorse or promote products derived from this software
23 1.4.2.2 yamt * without specific prior written permission.
24 1.4.2.2 yamt *
25 1.4.2.2 yamt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 1.4.2.2 yamt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 1.4.2.2 yamt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 1.4.2.2 yamt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 1.4.2.2 yamt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 1.4.2.2 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 1.4.2.2 yamt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.4.2.2 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.4.2.2 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.4.2.2 yamt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.4.2.2 yamt * SUCH DAMAGE.
36 1.4.2.2 yamt *
37 1.4.2.2 yamt * @(#)sc.c 8.1 (Berkeley) 6/10/93
38 1.4.2.2 yamt */
39 1.4.2.2 yamt /*
40 1.4.2.2 yamt * Copyright (c) 1992, 1993
41 1.4.2.2 yamt * The Regents of the University of California. All rights reserved.
42 1.4.2.2 yamt *
43 1.4.2.2 yamt * This code is derived from software contributed to Berkeley by
44 1.4.2.2 yamt * OMRON Corporation.
45 1.4.2.2 yamt *
46 1.4.2.2 yamt * Redistribution and use in source and binary forms, with or without
47 1.4.2.2 yamt * modification, are permitted provided that the following conditions
48 1.4.2.2 yamt * are met:
49 1.4.2.2 yamt * 1. Redistributions of source code must retain the above copyright
50 1.4.2.2 yamt * notice, this list of conditions and the following disclaimer.
51 1.4.2.2 yamt * 2. Redistributions in binary form must reproduce the above copyright
52 1.4.2.2 yamt * notice, this list of conditions and the following disclaimer in the
53 1.4.2.2 yamt * documentation and/or other materials provided with the distribution.
54 1.4.2.2 yamt * 3. Neither the name of the University nor the names of its contributors
55 1.4.2.2 yamt * may be used to endorse or promote products derived from this software
56 1.4.2.2 yamt * without specific prior written permission.
57 1.4.2.2 yamt *
58 1.4.2.2 yamt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 1.4.2.2 yamt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 1.4.2.2 yamt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 1.4.2.2 yamt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 1.4.2.2 yamt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 1.4.2.2 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 1.4.2.2 yamt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 1.4.2.2 yamt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 1.4.2.2 yamt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 1.4.2.2 yamt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 1.4.2.2 yamt * SUCH DAMAGE.
69 1.4.2.2 yamt *
70 1.4.2.2 yamt * @(#)sc.c 8.1 (Berkeley) 6/10/93
71 1.4.2.2 yamt */
72 1.4.2.2 yamt
73 1.4.2.2 yamt /*
74 1.4.2.2 yamt * sc.c -- SCSI Protocole Controller (SPC) driver
75 1.4.2.2 yamt * remaked by A.Fujita, MAR-11-199
76 1.4.2.2 yamt */
77 1.4.2.2 yamt
78 1.4.2.2 yamt
79 1.4.2.2 yamt #define NSC 2
80 1.4.2.2 yamt
81 1.4.2.2 yamt #include <sys/param.h>
82 1.4.2.2 yamt #include <luna68k/stand/boot/samachdep.h>
83 1.4.2.2 yamt #include <luna68k/stand/boot/scsireg.h>
84 1.4.2.2 yamt #include <luna68k/stand/boot/device.h>
85 1.4.2.2 yamt #include <luna68k/stand/boot/scsivar.h>
86 1.4.2.2 yamt
87 1.4.2.2 yamt #define SCSI_IPL 2
88 1.4.2.2 yamt #define SCSI_ID 7
89 1.4.2.2 yamt
90 1.4.2.2 yamt static int scinit(void *);
91 1.4.2.2 yamt static void screset(int);
92 1.4.2.2 yamt static int issue_select(struct scsidevice *, u_char);
93 1.4.2.2 yamt static void ixfer_start(struct scsidevice *, int, u_char, int);
94 1.4.2.2 yamt static void ixfer_out(struct scsidevice *, int, u_char *);
95 1.4.2.2 yamt static void ixfer_in(struct scsidevice *, int, u_char *);
96 1.4.2.2 yamt static int scrun(int, int, u_char *, int, u_char *, int, volatile int *);
97 1.4.2.2 yamt static int scfinish(int);
98 1.4.2.2 yamt static void scabort(struct scsi_softc *, struct scsidevice *);
99 1.4.2.2 yamt
100 1.4.2.2 yamt struct driver scdriver = {
101 1.4.2.2 yamt scinit, "sc", scintr,
102 1.4.2.2 yamt };
103 1.4.2.2 yamt
104 1.4.2.2 yamt struct scsi_softc scsi_softc[NSC];
105 1.4.2.2 yamt
106 1.4.2.2 yamt /*
107 1.4.2.2 yamt * Initialize SPC & Data Structure
108 1.4.2.2 yamt */
109 1.4.2.2 yamt
110 1.4.2.2 yamt int
111 1.4.2.2 yamt scinit(void *arg)
112 1.4.2.2 yamt {
113 1.4.2.2 yamt struct hp_ctlr *hc = arg;
114 1.4.2.2 yamt struct scsi_softc *hs;
115 1.4.2.2 yamt int unit;
116 1.4.2.2 yamt
117 1.4.2.2 yamt unit = hc->hp_unit;
118 1.4.2.2 yamt if (unit < 0 || unit >= NSC)
119 1.4.2.2 yamt return 0;
120 1.4.2.2 yamt
121 1.4.2.2 yamt hs = &scsi_softc[unit];
122 1.4.2.2 yamt
123 1.4.2.2 yamt hc->hp_ipl = SCSI_IPL;
124 1.4.2.2 yamt hs->sc_hc = hc;
125 1.4.2.2 yamt
126 1.4.2.2 yamt hs->sc_flags = 0;
127 1.4.2.2 yamt hs->sc_phase = BUS_FREE_PHASE;
128 1.4.2.2 yamt hs->sc_target = SCSI_ID;
129 1.4.2.2 yamt
130 1.4.2.2 yamt hs->sc_cdb = NULL;
131 1.4.2.2 yamt hs->sc_cdblen = 0;
132 1.4.2.2 yamt hs->sc_buf = NULL;
133 1.4.2.2 yamt hs->sc_len = 0;
134 1.4.2.2 yamt hs->sc_lock = NULL;
135 1.4.2.2 yamt
136 1.4.2.2 yamt hs->sc_stat = 0;
137 1.4.2.2 yamt hs->sc_msg[0] = 0;
138 1.4.2.2 yamt
139 1.4.2.2 yamt screset(hc->hp_unit);
140 1.4.2.2 yamt return(1);
141 1.4.2.2 yamt }
142 1.4.2.2 yamt
143 1.4.2.2 yamt void
144 1.4.2.2 yamt screset(int unit)
145 1.4.2.2 yamt {
146 1.4.2.2 yamt struct scsi_softc *hs = &scsi_softc[unit];
147 1.4.2.2 yamt struct scsidevice *hd = (struct scsidevice *)hs->sc_hc->hp_addr;
148 1.4.2.2 yamt
149 1.4.2.2 yamt printf("sc%d: ", unit);
150 1.4.2.2 yamt
151 1.4.2.2 yamt /*
152 1.4.2.2 yamt * Disable interrupts then reset the FUJI chip.
153 1.4.2.2 yamt */
154 1.4.2.2 yamt
155 1.4.2.2 yamt hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
156 1.4.2.2 yamt hd->scsi_scmd = 0;
157 1.4.2.2 yamt hd->scsi_pctl = 0;
158 1.4.2.2 yamt hd->scsi_temp = 0;
159 1.4.2.2 yamt hd->scsi_tch = 0;
160 1.4.2.2 yamt hd->scsi_tcm = 0;
161 1.4.2.2 yamt hd->scsi_tcl = 0;
162 1.4.2.2 yamt hd->scsi_ints = 0;
163 1.4.2.2 yamt
164 1.4.2.2 yamt /* We can use Asynchronous Transfer only */
165 1.4.2.2 yamt printf("async");
166 1.4.2.2 yamt
167 1.4.2.2 yamt /*
168 1.4.2.2 yamt * Configure MB89352 with its SCSI address, all
169 1.4.2.2 yamt * interrupts enabled & appropriate parity.
170 1.4.2.2 yamt */
171 1.4.2.2 yamt hd->scsi_bdid = SCSI_ID;
172 1.4.2.2 yamt hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
173 1.4.2.2 yamt SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
174 1.4.2.2 yamt SCTL_INTR_ENAB;
175 1.4.2.2 yamt printf(", parity");
176 1.4.2.2 yamt
177 1.4.2.2 yamt DELAY(400);
178 1.4.2.2 yamt hd->scsi_sctl &= ~SCTL_DISABLE;
179 1.4.2.2 yamt
180 1.4.2.2 yamt printf(", scsi id %d\n", SCSI_ID);
181 1.4.2.2 yamt }
182 1.4.2.2 yamt
183 1.4.2.2 yamt
184 1.4.2.2 yamt /*
185 1.4.2.2 yamt * SPC Arbitration/Selection routine
186 1.4.2.2 yamt */
187 1.4.2.2 yamt
188 1.4.2.2 yamt int
189 1.4.2.2 yamt issue_select(struct scsidevice *hd, u_char target)
190 1.4.2.2 yamt {
191 1.4.2.2 yamt hd->scsi_pctl = 0;
192 1.4.2.2 yamt hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
193 1.4.2.2 yamt
194 1.4.2.2 yamt /* select timeout is hardcoded to 2ms */
195 1.4.2.2 yamt hd->scsi_tch = 0;
196 1.4.2.2 yamt hd->scsi_tcm = 32;
197 1.4.2.2 yamt hd->scsi_tcl = 4;
198 1.4.2.2 yamt
199 1.4.2.2 yamt hd->scsi_scmd = SCMD_SELECT;
200 1.4.2.2 yamt
201 1.4.2.2 yamt return (1);
202 1.4.2.2 yamt }
203 1.4.2.2 yamt
204 1.4.2.2 yamt
205 1.4.2.2 yamt /*
206 1.4.2.2 yamt * SPC Manual Transfer routines
207 1.4.2.2 yamt */
208 1.4.2.2 yamt
209 1.4.2.2 yamt /* not yet */
210 1.4.2.2 yamt
211 1.4.2.2 yamt
212 1.4.2.2 yamt /*
213 1.4.2.2 yamt * SPC Program Transfer routines
214 1.4.2.2 yamt */
215 1.4.2.2 yamt
216 1.4.2.2 yamt void
217 1.4.2.2 yamt ixfer_start(struct scsidevice *hd, int len, u_char phase, int wait)
218 1.4.2.2 yamt {
219 1.4.2.2 yamt hd->scsi_tch = ((len & 0xff0000) >> 16);
220 1.4.2.2 yamt hd->scsi_tcm = ((len & 0x00ff00) >> 8);
221 1.4.2.2 yamt hd->scsi_tcl = (len & 0x0000ff);
222 1.4.2.2 yamt hd->scsi_pctl = phase;
223 1.4.2.2 yamt hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
224 1.4.2.2 yamt }
225 1.4.2.2 yamt
226 1.4.2.2 yamt void
227 1.4.2.2 yamt ixfer_out(struct scsidevice *hd, int len, u_char *buf)
228 1.4.2.2 yamt {
229 1.4.2.2 yamt for(; len > 0; len--) {
230 1.4.2.2 yamt while (hd->scsi_ssts & SSTS_DREG_FULL) {
231 1.4.2.2 yamt DELAY(5);
232 1.4.2.2 yamt }
233 1.4.2.2 yamt hd->scsi_dreg = *buf++;
234 1.4.2.2 yamt }
235 1.4.2.2 yamt }
236 1.4.2.2 yamt
237 1.4.2.2 yamt void
238 1.4.2.2 yamt ixfer_in(struct scsidevice *hd, int len, u_char *buf)
239 1.4.2.2 yamt {
240 1.4.2.2 yamt for (; len > 0; len--) {
241 1.4.2.2 yamt while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
242 1.4.2.2 yamt DELAY(5);
243 1.4.2.2 yamt }
244 1.4.2.2 yamt *buf++ = hd->scsi_dreg;
245 1.4.2.2 yamt }
246 1.4.2.2 yamt }
247 1.4.2.2 yamt
248 1.4.2.2 yamt
249 1.4.2.2 yamt /*
250 1.4.2.2 yamt * SPC drive routines
251 1.4.2.2 yamt */
252 1.4.2.2 yamt
253 1.4.2.2 yamt int
254 1.4.2.2 yamt scrun(int ctlr, int slave, u_char *cdb, int cdblen, u_char *buf, int len,
255 1.4.2.2 yamt volatile int *lock)
256 1.4.2.2 yamt {
257 1.4.2.2 yamt struct scsi_softc *hs = &scsi_softc[ctlr];
258 1.4.2.2 yamt struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr;
259 1.4.2.2 yamt
260 1.4.2.2 yamt if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
261 1.4.2.2 yamt return(0);
262 1.4.2.2 yamt
263 1.4.2.2 yamt hs->sc_flags = 0;
264 1.4.2.2 yamt hs->sc_phase = ARB_SEL_PHASE;
265 1.4.2.2 yamt hs->sc_target = slave;
266 1.4.2.2 yamt
267 1.4.2.2 yamt hs->sc_cdb = cdb;
268 1.4.2.2 yamt hs->sc_cdblen = cdblen;
269 1.4.2.2 yamt hs->sc_buf = buf;
270 1.4.2.2 yamt hs->sc_len = len;
271 1.4.2.2 yamt hs->sc_lock = lock;
272 1.4.2.2 yamt
273 1.4.2.2 yamt hs->sc_stat = 0;
274 1.4.2.2 yamt hs->sc_msg[0] = 0;
275 1.4.2.2 yamt
276 1.4.2.2 yamt *(hs->sc_lock) = SC_IN_PROGRESS;
277 1.4.2.2 yamt issue_select(hd, hs->sc_target);
278 1.4.2.2 yamt
279 1.4.2.2 yamt return(1);
280 1.4.2.2 yamt }
281 1.4.2.2 yamt
282 1.4.2.2 yamt int
283 1.4.2.2 yamt scfinish(int ctlr)
284 1.4.2.2 yamt {
285 1.4.2.2 yamt struct scsi_softc *hs = &scsi_softc[ctlr];
286 1.4.2.2 yamt int status = hs->sc_stat;
287 1.4.2.2 yamt
288 1.4.2.2 yamt hs->sc_flags = 0;
289 1.4.2.2 yamt hs->sc_phase = BUS_FREE_PHASE;
290 1.4.2.2 yamt hs->sc_target = SCSI_ID;
291 1.4.2.2 yamt
292 1.4.2.2 yamt hs->sc_cdb = NULL;
293 1.4.2.2 yamt hs->sc_cdblen = 0;
294 1.4.2.2 yamt hs->sc_buf = NULL;
295 1.4.2.2 yamt hs->sc_len = 0;
296 1.4.2.2 yamt hs->sc_lock = NULL;
297 1.4.2.2 yamt
298 1.4.2.2 yamt hs->sc_stat = 0;
299 1.4.2.2 yamt hs->sc_msg[0] = 0;
300 1.4.2.2 yamt
301 1.4.2.2 yamt return(status);
302 1.4.2.2 yamt }
303 1.4.2.2 yamt
304 1.4.2.2 yamt void
305 1.4.2.2 yamt scabort(struct scsi_softc *hs, struct scsidevice *hd)
306 1.4.2.2 yamt {
307 1.4.2.2 yamt int len;
308 1.4.2.2 yamt u_char junk;
309 1.4.2.2 yamt
310 1.4.2.2 yamt printf("sc%d: abort phase=0x%x, ssts=0x%x, ints=0x%x\n",
311 1.4.2.2 yamt hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts,
312 1.4.2.2 yamt hd->scsi_ints);
313 1.4.2.2 yamt
314 1.4.2.2 yamt if (hd->scsi_ints != 0)
315 1.4.2.2 yamt hd->scsi_ints = hd->scsi_ints;
316 1.4.2.2 yamt
317 1.4.2.2 yamt if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
318 1.4.2.2 yamt /* no longer connected to scsi target */
319 1.4.2.2 yamt return;
320 1.4.2.2 yamt
321 1.4.2.2 yamt /* get the number of bytes remaining in current xfer + fudge */
322 1.4.2.2 yamt len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
323 1.4.2.2 yamt
324 1.4.2.2 yamt /* for that many bus cycles, try to send an abort msg */
325 1.4.2.2 yamt for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
326 1.4.2.2 yamt hd->scsi_scmd = SCMD_SET_ATN;
327 1.4.2.2 yamt
328 1.4.2.2 yamt while ((hd->scsi_psns & PSNS_REQ) == 0) {
329 1.4.2.2 yamt if (! (hd->scsi_ssts & SSTS_INITIATOR))
330 1.4.2.2 yamt goto out;
331 1.4.2.2 yamt DELAY(1);
332 1.4.2.2 yamt }
333 1.4.2.2 yamt
334 1.4.2.2 yamt if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
335 1.4.2.2 yamt hd->scsi_scmd = SCMD_RST_ATN;
336 1.4.2.2 yamt hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
337 1.4.2.2 yamt
338 1.4.2.2 yamt if (hd->scsi_psns & PHASE_IO) {
339 1.4.2.2 yamt /* one of the input phases - read & discard a byte */
340 1.4.2.2 yamt hd->scsi_scmd = SCMD_SET_ACK;
341 1.4.2.2 yamt while (hd->scsi_psns & PSNS_REQ)
342 1.4.2.2 yamt DELAY(1);
343 1.4.2.2 yamt junk = hd->scsi_temp;
344 1.4.2.2 yamt } else {
345 1.4.2.2 yamt /* one of the output phases - send an abort msg */
346 1.4.2.2 yamt hd->scsi_temp = MSG_ABORT;
347 1.4.2.2 yamt hd->scsi_scmd = SCMD_SET_ACK;
348 1.4.2.2 yamt while (hd->scsi_psns & PSNS_REQ)
349 1.4.2.2 yamt DELAY(1);
350 1.4.2.2 yamt }
351 1.4.2.2 yamt
352 1.4.2.2 yamt hd->scsi_scmd = SCMD_RST_ACK;
353 1.4.2.2 yamt }
354 1.4.2.2 yamt out:
355 1.4.2.2 yamt /*
356 1.4.2.2 yamt * Either the abort was successful & the bus is disconnected or
357 1.4.2.2 yamt * the device didn't listen. If the latter, announce the problem.
358 1.4.2.2 yamt * Either way, reset the card & the SPC.
359 1.4.2.2 yamt */
360 1.4.2.2 yamt if (len < 0 && hs)
361 1.4.2.2 yamt printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n",
362 1.4.2.2 yamt hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
363 1.4.2.2 yamt }
364 1.4.2.2 yamt
365 1.4.2.2 yamt
366 1.4.2.2 yamt /*
367 1.4.2.2 yamt * SCSI Command Handler
368 1.4.2.2 yamt */
369 1.4.2.2 yamt
370 1.4.2.2 yamt int
371 1.4.2.2 yamt scsi_test_unit_rdy(int ctlr, int slave, int unit)
372 1.4.2.2 yamt {
373 1.4.2.2 yamt static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
374 1.4.2.2 yamt int status;
375 1.4.2.2 yamt volatile int lock;
376 1.4.2.2 yamt
377 1.4.2.2 yamt #ifdef DEBUG
378 1.4.2.2 yamt printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, slave, unit);
379 1.4.2.2 yamt #endif
380 1.4.2.2 yamt
381 1.4.2.2 yamt cdb.lun = unit;
382 1.4.2.2 yamt
383 1.4.2.2 yamt if (!(scrun(ctlr, slave, (void *)&cdb, 6, NULL, 0, &lock))) {
384 1.4.2.2 yamt #ifdef DEBUG
385 1.4.2.2 yamt printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
386 1.4.2.2 yamt #endif
387 1.4.2.2 yamt return(-1);
388 1.4.2.2 yamt }
389 1.4.2.2 yamt
390 1.4.2.2 yamt while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
391 1.4.2.2 yamt DELAY(10);
392 1.4.2.2 yamt
393 1.4.2.2 yamt status = scfinish(ctlr);
394 1.4.2.2 yamt
395 1.4.2.2 yamt if (lock == SC_IO_COMPLETE) {
396 1.4.2.2 yamt #ifdef DEBUG
397 1.4.2.2 yamt printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
398 1.4.2.2 yamt #endif
399 1.4.2.2 yamt return(status);
400 1.4.2.2 yamt } else {
401 1.4.2.2 yamt return(lock);
402 1.4.2.2 yamt }
403 1.4.2.2 yamt }
404 1.4.2.2 yamt
405 1.4.2.2 yamt int
406 1.4.2.2 yamt scsi_request_sense(int ctlr, int slave, int unit, u_char *buf, unsigned int len)
407 1.4.2.2 yamt {
408 1.4.2.2 yamt static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
409 1.4.2.2 yamt int status;
410 1.4.2.2 yamt volatile int lock;
411 1.4.2.2 yamt
412 1.4.2.2 yamt #ifdef DEBUG
413 1.4.2.2 yamt printf("scsi_request_sense: Start\n");
414 1.4.2.2 yamt #endif
415 1.4.2.2 yamt
416 1.4.2.2 yamt /* Request Sense$N>l9g!"E>Aw$5$l$k%G!<%?D9$O%?!<%2368H$K0MB8$7!" */
417 1.4.2.2 yamt /* %;%s%9%G!<%?$N#8/usr/src/sys/luna68k/stand/SCCS/s.sc.c$%HL\$NAddtional Sens Length$K$h$jF0E*$K7hDj$9$k!#*/
418 1.4.2.2 yamt /* $3$3$G$O%G!<%?!<E>Aw?t$rcdb$NAllocation Length$K:GDcD9$G$"$k#8/usr/src/sys/luna68k/stand/SCCS/s.sc.c$%H */
419 1.4.2.2 yamt /* $r8GDj$7$F!"#S#P#C$N=hM}%7!<%1%s%9$rJx$5$J$$$h$&$K$7$F$$$k!# */
420 1.4.2.2 yamt
421 1.4.2.2 yamt /* %F!<@(#)sc.c 8.1f%K373H$N>uBV$rD4$Y$k$?$a!"Addtional Sens Field$r%"%/%;%9$9$k */
422 1.4.2.2 yamt /* I,MW$,$"$k$N$G6/10/93P%$%98.1i%$%PB&$Glen$r7hDj$9$k$3$H$K$9$k */
423 1.4.2.2 yamt
424 1.4.2.2 yamt cdb.lun = unit;
425 1.4.2.2 yamt cdb.len = len;
426 1.4.2.2 yamt
427 1.4.2.2 yamt if (!(scrun(ctlr, slave, (void *)&cdb, 6, buf, len, &lock))) {
428 1.4.2.2 yamt #ifdef DEBUG
429 1.4.2.2 yamt printf("scsi_request_sense: Command Transfer Failed.\n");
430 1.4.2.2 yamt #endif
431 1.4.2.2 yamt return(-1);
432 1.4.2.2 yamt }
433 1.4.2.2 yamt
434 1.4.2.2 yamt while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
435 1.4.2.2 yamt DELAY(10);
436 1.4.2.2 yamt
437 1.4.2.2 yamt status = scfinish(ctlr);
438 1.4.2.2 yamt
439 1.4.2.2 yamt if (lock == SC_IO_COMPLETE) {
440 1.4.2.2 yamt #ifdef DEBUG
441 1.4.2.2 yamt printf("scsi_request_sense: Status -- 0x%x\n", status);
442 1.4.2.2 yamt #endif
443 1.4.2.2 yamt return(status);
444 1.4.2.2 yamt } else {
445 1.4.2.2 yamt return(lock);
446 1.4.2.2 yamt }
447 1.4.2.2 yamt }
448 1.4.2.2 yamt
449 1.4.2.2 yamt int
450 1.4.2.2 yamt scsi_immed_command(int ctlr, int slave, int unit, struct scsi_fmt_cdb *cdb,
451 1.4.2.2 yamt u_char *buf, unsigned int len)
452 1.4.2.2 yamt {
453 1.4.2.2 yamt int status;
454 1.4.2.2 yamt volatile int lock;
455 1.4.2.2 yamt
456 1.4.2.2 yamt #ifdef DEBUG
457 1.4.2.2 yamt printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
458 1.4.2.2 yamt ctlr, slave, unit, cdb->len, len);
459 1.4.2.2 yamt #endif
460 1.4.2.2 yamt
461 1.4.2.2 yamt cdb->cdb[1] |= unit << 5;
462 1.4.2.2 yamt
463 1.4.2.2 yamt if (!(scrun(ctlr, slave, (void *)&cdb->cdb[0], cdb->len, buf, len, &lock))) {
464 1.4.2.2 yamt #ifdef DEBUG
465 1.4.2.2 yamt printf("scsi_immed_command: Command Transfer Failed.\n");
466 1.4.2.2 yamt #endif
467 1.4.2.2 yamt return(-1);
468 1.4.2.2 yamt }
469 1.4.2.2 yamt
470 1.4.2.2 yamt while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
471 1.4.2.2 yamt DELAY(10);
472 1.4.2.2 yamt
473 1.4.2.2 yamt status = scfinish(ctlr);
474 1.4.2.2 yamt
475 1.4.2.2 yamt if (lock == SC_IO_COMPLETE) {
476 1.4.2.2 yamt #ifdef DEBUG
477 1.4.2.2 yamt printf("scsi_immed_command: Status -- 0x%x\n", status);
478 1.4.2.2 yamt #endif
479 1.4.2.2 yamt return(status);
480 1.4.2.2 yamt } else {
481 1.4.2.2 yamt return(lock);
482 1.4.2.2 yamt }
483 1.4.2.2 yamt }
484 1.4.2.2 yamt
485 1.4.2.2 yamt int
486 1.4.2.2 yamt scsi_format_unit(int ctlr, int slave, int unit)
487 1.4.2.2 yamt {
488 1.4.2.2 yamt static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };
489 1.4.2.2 yamt int status;
490 1.4.2.2 yamt volatile int lock;
491 1.4.2.2 yamt #ifdef DEBUG
492 1.4.2.2 yamt int count = 0;
493 1.4.2.2 yamt #endif
494 1.4.2.2 yamt
495 1.4.2.2 yamt #ifdef DEBUG
496 1.4.2.2 yamt printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, slave, unit);
497 1.4.2.2 yamt #endif
498 1.4.2.2 yamt
499 1.4.2.2 yamt cdb.lun = unit;
500 1.4.2.2 yamt
501 1.4.2.2 yamt if (!(scrun(ctlr, slave, (void *)&cdb, 6, (u_char *) 0, 0, &lock))) {
502 1.4.2.2 yamt #ifdef DEBUG
503 1.4.2.2 yamt printf("scsi_format_unit: Command Transfer Failed.\n");
504 1.4.2.2 yamt #endif
505 1.4.2.2 yamt return(-1);
506 1.4.2.2 yamt }
507 1.4.2.2 yamt
508 1.4.2.2 yamt while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
509 1.4.2.2 yamt DELAY(1000000);
510 1.4.2.2 yamt #ifdef DEBUG
511 1.4.2.2 yamt if ((++count % 60) == 0)
512 1.4.2.2 yamt printf("scsi_format_unit: %d\n", count / 60);
513 1.4.2.2 yamt #endif
514 1.4.2.2 yamt }
515 1.4.2.2 yamt
516 1.4.2.2 yamt status = scfinish(ctlr);
517 1.4.2.2 yamt
518 1.4.2.2 yamt if (lock == SC_IO_COMPLETE) {
519 1.4.2.2 yamt #ifdef DEBUG
520 1.4.2.2 yamt printf("scsi_format_unit: Status -- 0x%x\n", status);
521 1.4.2.2 yamt #endif
522 1.4.2.2 yamt return(status);
523 1.4.2.2 yamt } else {
524 1.4.2.2 yamt return(lock);
525 1.4.2.2 yamt }
526 1.4.2.2 yamt }
527 1.4.2.2 yamt
528 1.4.2.2 yamt
529 1.4.2.2 yamt /*
530 1.4.2.2 yamt * Interrupt Routine
531 1.4.2.2 yamt */
532 1.4.2.2 yamt
533 1.4.2.2 yamt int
534 1.4.2.2 yamt scintr(void)
535 1.4.2.2 yamt {
536 1.4.2.2 yamt struct scsi_softc *hs;
537 1.4.2.2 yamt struct scsidevice *hd;
538 1.4.2.2 yamt u_char ints, temp;
539 1.4.2.2 yamt int i;
540 1.4.2.2 yamt u_char *buf;
541 1.4.2.2 yamt int len;
542 1.4.2.2 yamt
543 1.4.2.2 yamt for (i = 0; i < NSC; i++) {
544 1.4.2.2 yamt hs = &scsi_softc[i];
545 1.4.2.2 yamt hd = (struct scsidevice *) hs->sc_hc->hp_addr;
546 1.4.2.2 yamt if ((ints = hd->scsi_ints) != 0)
547 1.4.2.2 yamt goto get_intr;
548 1.4.2.2 yamt }
549 1.4.2.2 yamt
550 1.4.2.2 yamt /* Unknown Interrupt occured */
551 1.4.2.2 yamt return -1;
552 1.4.2.2 yamt
553 1.4.2.2 yamt
554 1.4.2.2 yamt /*
555 1.4.2.2 yamt * Interrupt
556 1.4.2.2 yamt */
557 1.4.2.2 yamt
558 1.4.2.2 yamt get_intr:
559 1.4.2.2 yamt #ifdef DEBUG
560 1.4.2.2 yamt printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x 0x%x\n",
561 1.4.2.2 yamt ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns,
562 1.4.2.2 yamt hs->sc_phase);
563 1.4.2.2 yamt #endif
564 1.4.2.2 yamt if (ints & INTS_RESEL) {
565 1.4.2.2 yamt if (hs->sc_phase == BUS_FREE_PHASE) {
566 1.4.2.2 yamt temp = hd->scsi_temp & ~(1 << SCSI_ID);
567 1.4.2.2 yamt for (i = 0; temp != 1; i++) {
568 1.4.2.2 yamt temp >>= 1;
569 1.4.2.2 yamt }
570 1.4.2.2 yamt hs->sc_target = i;
571 1.4.2.2 yamt *(hs->sc_lock) = SC_IN_PROGRESS;
572 1.4.2.2 yamt } else
573 1.4.2.2 yamt goto abort;
574 1.4.2.2 yamt } else if (ints & INTS_DISCON) {
575 1.4.2.2 yamt if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || (hs->sc_msg[0] == MSG_DISCONNECT)) {
576 1.4.2.2 yamt hs->sc_phase = BUS_FREE_PHASE;
577 1.4.2.2 yamt hs->sc_target = SCSI_ID;
578 1.4.2.2 yamt if (hs->sc_msg[0] == MSG_CMD_COMPLETE)
579 1.4.2.2 yamt /* SCSI IO complete */
580 1.4.2.2 yamt *(hs->sc_lock) = SC_IO_COMPLETE;
581 1.4.2.2 yamt else
582 1.4.2.2 yamt /* Cisconnected from Target */
583 1.4.2.2 yamt *(hs->sc_lock) = SC_DISCONNECTED;
584 1.4.2.2 yamt hd->scsi_ints = ints;
585 1.4.2.2 yamt return 0;
586 1.4.2.2 yamt } else
587 1.4.2.2 yamt goto abort;
588 1.4.2.2 yamt } else if (ints & INTS_CMD_DONE) {
589 1.4.2.2 yamt if (hs->sc_phase == BUS_FREE_PHASE)
590 1.4.2.2 yamt goto abort;
591 1.4.2.2 yamt else if (hs->sc_phase == MESG_IN_PHASE) {
592 1.4.2.2 yamt hd->scsi_scmd = SCMD_RST_ACK;
593 1.4.2.2 yamt hd->scsi_ints = ints;
594 1.4.2.2 yamt hs->sc_phase = hd->scsi_psns & PHASE;
595 1.4.2.2 yamt return 0;
596 1.4.2.2 yamt }
597 1.4.2.2 yamt if (hs->sc_flags & SC_SEL_TIMEOUT)
598 1.4.2.2 yamt hs->sc_flags &= ~SC_SEL_TIMEOUT;
599 1.4.2.2 yamt } else if (ints & INTS_SRV_REQ) {
600 1.4.2.2 yamt if (hs->sc_phase != MESG_IN_PHASE)
601 1.4.2.2 yamt goto abort;
602 1.4.2.2 yamt } else if (ints & INTS_TIMEOUT) {
603 1.4.2.2 yamt if (hs->sc_phase == ARB_SEL_PHASE) {
604 1.4.2.2 yamt if (hs->sc_flags & SC_SEL_TIMEOUT) {
605 1.4.2.2 yamt hs->sc_flags &= ~SC_SEL_TIMEOUT;
606 1.4.2.2 yamt hs->sc_phase = BUS_FREE_PHASE;
607 1.4.2.2 yamt hs->sc_target = SCSI_ID;
608 1.4.2.2 yamt /* Such SCSI Device is not conected. */
609 1.4.2.2 yamt *(hs->sc_lock) = SC_DEV_NOT_FOUND;
610 1.4.2.2 yamt hd->scsi_ints = ints;
611 1.4.2.2 yamt return 0;
612 1.4.2.2 yamt } else {
613 1.4.2.2 yamt /* wait more 250 usec */
614 1.4.2.2 yamt hs->sc_flags |= SC_SEL_TIMEOUT;
615 1.4.2.2 yamt hd->scsi_temp = 0;
616 1.4.2.2 yamt hd->scsi_tch = 0;
617 1.4.2.2 yamt hd->scsi_tcm = 0x06;
618 1.4.2.2 yamt hd->scsi_tcl = 0x40;
619 1.4.2.2 yamt hd->scsi_ints = ints;
620 1.4.2.2 yamt return 0;
621 1.4.2.2 yamt }
622 1.4.2.2 yamt } else
623 1.4.2.2 yamt goto abort;
624 1.4.2.2 yamt } else
625 1.4.2.2 yamt goto abort;
626 1.4.2.2 yamt
627 1.4.2.2 yamt hd->scsi_ints = ints;
628 1.4.2.2 yamt
629 1.4.2.2 yamt /*
630 1.4.2.2 yamt * Next SCSI Transfer
631 1.4.2.2 yamt */
632 1.4.2.2 yamt
633 1.4.2.2 yamt while ((hd->scsi_psns & PSNS_REQ) == 0) {
634 1.4.2.2 yamt DELAY(1);
635 1.4.2.2 yamt }
636 1.4.2.2 yamt
637 1.4.2.2 yamt hs->sc_phase = hd->scsi_psns & PHASE;
638 1.4.2.2 yamt
639 1.4.2.2 yamt if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) {
640 1.4.2.2 yamt len = hs->sc_len;
641 1.4.2.2 yamt buf = hs->sc_buf;
642 1.4.2.2 yamt } else if (hs->sc_phase == CMD_PHASE) {
643 1.4.2.2 yamt len = hs->sc_cdblen;
644 1.4.2.2 yamt buf = hs->sc_cdb;
645 1.4.2.2 yamt } else if (hs->sc_phase == STATUS_PHASE) {
646 1.4.2.2 yamt len = 1;
647 1.4.2.2 yamt buf = &hs->sc_stat;
648 1.4.2.2 yamt } else {
649 1.4.2.2 yamt len = 1;
650 1.4.2.2 yamt buf = hs->sc_msg;
651 1.4.2.2 yamt }
652 1.4.2.2 yamt
653 1.4.2.2 yamt ixfer_start(hd, len, hs->sc_phase, 0);
654 1.4.2.2 yamt if (hs->sc_phase & PHASE_IO)
655 1.4.2.2 yamt ixfer_in(hd, len, buf);
656 1.4.2.2 yamt else
657 1.4.2.2 yamt ixfer_out(hd, len, buf);
658 1.4.2.2 yamt
659 1.4.2.2 yamt return 0;
660 1.4.2.2 yamt
661 1.4.2.2 yamt /*
662 1.4.2.2 yamt * SCSI Abort
663 1.4.2.2 yamt */
664 1.4.2.2 yamt abort:
665 1.4.2.2 yamt /* SCSI IO failed */
666 1.4.2.2 yamt scabort(hs, hd);
667 1.4.2.2 yamt hd->scsi_ints = ints;
668 1.4.2.2 yamt *(hs->sc_lock) = SC_IO_FAILED;
669 1.4.2.2 yamt return -1;
670 1.4.2.2 yamt }
671