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