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