sc.c revision 1.2 1 1.2 tsutsui /* $NetBSD: sc.c,v 1.2 2013/01/13 04:39:28 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.1 tsutsui #define NSC 1
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.1 tsutsui struct scsi_softc *hs = &scsi_softc[hc->hp_unit];
115 1.1 tsutsui
116 1.1 tsutsui hc->hp_ipl = SCSI_IPL;
117 1.1 tsutsui hs->sc_hc = hc;
118 1.1 tsutsui
119 1.1 tsutsui hs->sc_flags = 0;
120 1.1 tsutsui hs->sc_phase = BUS_FREE_PHASE;
121 1.1 tsutsui hs->sc_target = SCSI_ID;
122 1.1 tsutsui
123 1.1 tsutsui hs->sc_cdb = NULL;
124 1.1 tsutsui hs->sc_cdblen = 0;
125 1.1 tsutsui hs->sc_buf = NULL;
126 1.1 tsutsui hs->sc_len = 0;
127 1.1 tsutsui hs->sc_lock = NULL;
128 1.1 tsutsui
129 1.1 tsutsui hs->sc_stat = 0;
130 1.1 tsutsui hs->sc_msg[0] = 0;
131 1.1 tsutsui
132 1.1 tsutsui screset(hc->hp_unit);
133 1.1 tsutsui return(1);
134 1.1 tsutsui }
135 1.1 tsutsui
136 1.1 tsutsui void
137 1.1 tsutsui screset(int unit)
138 1.1 tsutsui {
139 1.1 tsutsui struct scsi_softc *hs = &scsi_softc[unit];
140 1.1 tsutsui struct scsidevice *hd = (struct scsidevice *)hs->sc_hc->hp_addr;
141 1.1 tsutsui
142 1.1 tsutsui printf("sc%d: ", unit);
143 1.1 tsutsui
144 1.1 tsutsui /*
145 1.1 tsutsui * Disable interrupts then reset the FUJI chip.
146 1.1 tsutsui */
147 1.1 tsutsui
148 1.1 tsutsui hd->scsi_sctl = SCTL_DISABLE | SCTL_CTRLRST;
149 1.1 tsutsui hd->scsi_scmd = 0;
150 1.1 tsutsui hd->scsi_pctl = 0;
151 1.1 tsutsui hd->scsi_temp = 0;
152 1.1 tsutsui hd->scsi_tch = 0;
153 1.1 tsutsui hd->scsi_tcm = 0;
154 1.1 tsutsui hd->scsi_tcl = 0;
155 1.1 tsutsui hd->scsi_ints = 0;
156 1.1 tsutsui
157 1.1 tsutsui /* We can use Asynchronous Transfer only */
158 1.1 tsutsui printf("async");
159 1.1 tsutsui
160 1.1 tsutsui /*
161 1.1 tsutsui * Configure MB89352 with its SCSI address, all
162 1.1 tsutsui * interrupts enabled & appropriate parity.
163 1.1 tsutsui */
164 1.1 tsutsui hd->scsi_bdid = SCSI_ID;
165 1.1 tsutsui hd->scsi_sctl = SCTL_DISABLE | SCTL_ABRT_ENAB|
166 1.1 tsutsui SCTL_PARITY_ENAB | SCTL_RESEL_ENAB |
167 1.1 tsutsui SCTL_INTR_ENAB;
168 1.1 tsutsui printf(", parity");
169 1.1 tsutsui
170 1.1 tsutsui DELAY(400);
171 1.1 tsutsui hd->scsi_sctl &= ~SCTL_DISABLE;
172 1.1 tsutsui
173 1.1 tsutsui printf(", scsi id %d\n", SCSI_ID);
174 1.1 tsutsui }
175 1.1 tsutsui
176 1.1 tsutsui
177 1.1 tsutsui /*
178 1.1 tsutsui * SPC Arbitration/Selection routine
179 1.1 tsutsui */
180 1.1 tsutsui
181 1.1 tsutsui int
182 1.1 tsutsui issue_select(struct scsidevice *hd, u_char target)
183 1.1 tsutsui {
184 1.1 tsutsui hd->scsi_pctl = 0;
185 1.1 tsutsui hd->scsi_temp = (1 << SCSI_ID) | (1 << target);
186 1.1 tsutsui
187 1.1 tsutsui /* select timeout is hardcoded to 2ms */
188 1.1 tsutsui hd->scsi_tch = 0;
189 1.1 tsutsui hd->scsi_tcm = 32;
190 1.1 tsutsui hd->scsi_tcl = 4;
191 1.1 tsutsui
192 1.1 tsutsui hd->scsi_scmd = SCMD_SELECT;
193 1.1 tsutsui
194 1.1 tsutsui return (1);
195 1.1 tsutsui }
196 1.1 tsutsui
197 1.1 tsutsui
198 1.1 tsutsui /*
199 1.1 tsutsui * SPC Manual Transfer routines
200 1.1 tsutsui */
201 1.1 tsutsui
202 1.1 tsutsui /* not yet */
203 1.1 tsutsui
204 1.1 tsutsui
205 1.1 tsutsui /*
206 1.1 tsutsui * SPC Program Transfer routines
207 1.1 tsutsui */
208 1.1 tsutsui
209 1.1 tsutsui void
210 1.1 tsutsui ixfer_start(struct scsidevice *hd, int len, u_char phase, int wait)
211 1.1 tsutsui {
212 1.1 tsutsui hd->scsi_tch = ((len & 0xff0000) >> 16);
213 1.1 tsutsui hd->scsi_tcm = ((len & 0x00ff00) >> 8);
214 1.1 tsutsui hd->scsi_tcl = (len & 0x0000ff);
215 1.1 tsutsui hd->scsi_pctl = phase;
216 1.1 tsutsui hd->scsi_scmd = SCMD_XFR | SCMD_PROG_XFR;
217 1.1 tsutsui }
218 1.1 tsutsui
219 1.1 tsutsui void
220 1.1 tsutsui ixfer_out(struct scsidevice *hd, int len, u_char *buf)
221 1.1 tsutsui {
222 1.1 tsutsui for(; len > 0; len--) {
223 1.1 tsutsui while (hd->scsi_ssts & SSTS_DREG_FULL) {
224 1.1 tsutsui DELAY(5);
225 1.1 tsutsui }
226 1.1 tsutsui hd->scsi_dreg = *buf++;
227 1.1 tsutsui }
228 1.1 tsutsui }
229 1.1 tsutsui
230 1.1 tsutsui void
231 1.1 tsutsui ixfer_in(struct scsidevice *hd, int len, u_char *buf)
232 1.1 tsutsui {
233 1.1 tsutsui for (; len > 0; len--) {
234 1.1 tsutsui while (hd->scsi_ssts & SSTS_DREG_EMPTY) {
235 1.1 tsutsui DELAY(5);
236 1.1 tsutsui }
237 1.1 tsutsui *buf++ = hd->scsi_dreg;
238 1.1 tsutsui }
239 1.1 tsutsui }
240 1.1 tsutsui
241 1.1 tsutsui
242 1.1 tsutsui /*
243 1.1 tsutsui * SPC drive routines
244 1.1 tsutsui */
245 1.1 tsutsui
246 1.1 tsutsui int
247 1.1 tsutsui scrun(int ctlr, int slave, u_char *cdb, int cdblen, u_char *buf, int len,
248 1.1 tsutsui volatile int *lock)
249 1.1 tsutsui {
250 1.1 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr];
251 1.1 tsutsui struct scsidevice *hd = (struct scsidevice *) hs->sc_hc->hp_addr;
252 1.1 tsutsui
253 1.1 tsutsui if (hd->scsi_ssts & (SSTS_INITIATOR|SSTS_TARGET|SSTS_BUSY))
254 1.1 tsutsui return(0);
255 1.1 tsutsui
256 1.1 tsutsui hs->sc_flags = 0;
257 1.1 tsutsui hs->sc_phase = ARB_SEL_PHASE;
258 1.1 tsutsui hs->sc_target = slave;
259 1.1 tsutsui
260 1.1 tsutsui hs->sc_cdb = cdb;
261 1.1 tsutsui hs->sc_cdblen = cdblen;
262 1.1 tsutsui hs->sc_buf = buf;
263 1.1 tsutsui hs->sc_len = len;
264 1.1 tsutsui hs->sc_lock = lock;
265 1.1 tsutsui
266 1.1 tsutsui hs->sc_stat = 0;
267 1.1 tsutsui hs->sc_msg[0] = 0;
268 1.1 tsutsui
269 1.1 tsutsui *(hs->sc_lock) = SC_IN_PROGRESS;
270 1.1 tsutsui issue_select(hd, hs->sc_target);
271 1.1 tsutsui
272 1.1 tsutsui return(1);
273 1.1 tsutsui }
274 1.1 tsutsui
275 1.1 tsutsui int
276 1.1 tsutsui scfinish(int ctlr)
277 1.1 tsutsui {
278 1.1 tsutsui struct scsi_softc *hs = &scsi_softc[ctlr];
279 1.1 tsutsui int status = hs->sc_stat;
280 1.1 tsutsui
281 1.1 tsutsui hs->sc_flags = 0;
282 1.1 tsutsui hs->sc_phase = BUS_FREE_PHASE;
283 1.1 tsutsui hs->sc_target = SCSI_ID;
284 1.1 tsutsui
285 1.1 tsutsui hs->sc_cdb = NULL;
286 1.1 tsutsui hs->sc_cdblen = 0;
287 1.1 tsutsui hs->sc_buf = NULL;
288 1.1 tsutsui hs->sc_len = 0;
289 1.1 tsutsui hs->sc_lock = NULL;
290 1.1 tsutsui
291 1.1 tsutsui hs->sc_stat = 0;
292 1.1 tsutsui hs->sc_msg[0] = 0;
293 1.1 tsutsui
294 1.1 tsutsui return(status);
295 1.1 tsutsui }
296 1.1 tsutsui
297 1.1 tsutsui void
298 1.1 tsutsui scabort(struct scsi_softc *hs, struct scsidevice *hd)
299 1.1 tsutsui {
300 1.1 tsutsui int len;
301 1.1 tsutsui u_char junk;
302 1.1 tsutsui
303 1.1 tsutsui printf("sc%d: abort phase=0x%x, ssts=0x%x, ints=0x%x\n",
304 1.1 tsutsui hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts,
305 1.1 tsutsui hd->scsi_ints);
306 1.1 tsutsui
307 1.1 tsutsui if (hd->scsi_ints != 0)
308 1.1 tsutsui hd->scsi_ints = hd->scsi_ints;
309 1.1 tsutsui
310 1.1 tsutsui if (hd->scsi_psns == 0 || (hd->scsi_ssts & SSTS_INITIATOR) == 0)
311 1.1 tsutsui /* no longer connected to scsi target */
312 1.1 tsutsui return;
313 1.1 tsutsui
314 1.1 tsutsui /* get the number of bytes remaining in current xfer + fudge */
315 1.1 tsutsui len = (hd->scsi_tch << 16) | (hd->scsi_tcm << 8) | hd->scsi_tcl;
316 1.1 tsutsui
317 1.1 tsutsui /* for that many bus cycles, try to send an abort msg */
318 1.1 tsutsui for (len += 1024; (hd->scsi_ssts & SSTS_INITIATOR) && --len >= 0; ) {
319 1.1 tsutsui hd->scsi_scmd = SCMD_SET_ATN;
320 1.1 tsutsui
321 1.1 tsutsui while ((hd->scsi_psns & PSNS_REQ) == 0) {
322 1.1 tsutsui if (! (hd->scsi_ssts & SSTS_INITIATOR))
323 1.1 tsutsui goto out;
324 1.1 tsutsui DELAY(1);
325 1.1 tsutsui }
326 1.1 tsutsui
327 1.1 tsutsui if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE)
328 1.1 tsutsui hd->scsi_scmd = SCMD_RST_ATN;
329 1.1 tsutsui hd->scsi_pctl = hs->sc_phase = hd->scsi_psns & PHASE;
330 1.1 tsutsui
331 1.1 tsutsui if (hd->scsi_psns & PHASE_IO) {
332 1.1 tsutsui /* one of the input phases - read & discard a byte */
333 1.1 tsutsui hd->scsi_scmd = SCMD_SET_ACK;
334 1.1 tsutsui while (hd->scsi_psns & PSNS_REQ)
335 1.1 tsutsui DELAY(1);
336 1.1 tsutsui junk = hd->scsi_temp;
337 1.1 tsutsui } else {
338 1.1 tsutsui /* one of the output phases - send an abort msg */
339 1.1 tsutsui hd->scsi_temp = MSG_ABORT;
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 }
344 1.1 tsutsui
345 1.1 tsutsui hd->scsi_scmd = SCMD_RST_ACK;
346 1.1 tsutsui }
347 1.1 tsutsui out:
348 1.1 tsutsui /*
349 1.1 tsutsui * Either the abort was successful & the bus is disconnected or
350 1.1 tsutsui * the device didn't listen. If the latter, announce the problem.
351 1.1 tsutsui * Either way, reset the card & the SPC.
352 1.1 tsutsui */
353 1.1 tsutsui if (len < 0 && hs)
354 1.1 tsutsui printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n",
355 1.1 tsutsui hs->sc_hc->hp_unit, hd->scsi_psns, hd->scsi_ssts);
356 1.1 tsutsui }
357 1.1 tsutsui
358 1.1 tsutsui
359 1.1 tsutsui /*
360 1.1 tsutsui * SCSI Command Handler
361 1.1 tsutsui */
362 1.1 tsutsui
363 1.1 tsutsui int
364 1.1 tsutsui scsi_test_unit_rdy(int ctlr, int slave, int unit)
365 1.1 tsutsui {
366 1.1 tsutsui static struct scsi_cdb6 cdb = { CMD_TEST_UNIT_READY };
367 1.1 tsutsui int status;
368 1.1 tsutsui volatile int lock;
369 1.1 tsutsui
370 1.1 tsutsui #ifdef DEBUG
371 1.1 tsutsui printf("scsi_test_unit_rdy( %d, %d, %d): Start\n", ctlr, slave, unit);
372 1.1 tsutsui #endif
373 1.1 tsutsui
374 1.1 tsutsui cdb.lun = unit;
375 1.1 tsutsui
376 1.1 tsutsui if (!(scrun(ctlr, slave, (void *)&cdb, 6, NULL, 0, &lock))) {
377 1.1 tsutsui #ifdef DEBUG
378 1.1 tsutsui printf("scsi_test_unit_rdy: Command Transfer Failed.\n");
379 1.1 tsutsui #endif
380 1.1 tsutsui return(-1);
381 1.1 tsutsui }
382 1.1 tsutsui
383 1.1 tsutsui while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
384 1.1 tsutsui DELAY(10);
385 1.1 tsutsui
386 1.1 tsutsui status = scfinish(ctlr);
387 1.1 tsutsui
388 1.1 tsutsui if (lock == SC_IO_COMPLETE) {
389 1.1 tsutsui #ifdef DEBUG
390 1.1 tsutsui printf("scsi_test_unit_rdy: Status -- 0x%x\n", status);
391 1.1 tsutsui #endif
392 1.1 tsutsui return(status);
393 1.1 tsutsui } else {
394 1.1 tsutsui return(lock);
395 1.1 tsutsui }
396 1.1 tsutsui }
397 1.1 tsutsui
398 1.1 tsutsui int
399 1.1 tsutsui scsi_request_sense(int ctlr, int slave, int unit, u_char *buf, unsigned int len)
400 1.1 tsutsui {
401 1.1 tsutsui static struct scsi_cdb6 cdb = { CMD_REQUEST_SENSE };
402 1.1 tsutsui int status;
403 1.1 tsutsui volatile int lock;
404 1.1 tsutsui
405 1.1 tsutsui #ifdef DEBUG
406 1.1 tsutsui printf("scsi_request_sense: Start\n");
407 1.1 tsutsui #endif
408 1.1 tsutsui
409 1.1 tsutsui /* Request Sense$N>l9g!"E>Aw$5$l$k%G!<%?D9$O%?!<%2368H$K0MB8$7!" */
410 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!#*/
411 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 */
412 1.1 tsutsui /* $r8GDj$7$F!"#S#P#C$N=hM}%7!<%1%s%9$rJx$5$J$$$h$&$K$7$F$$$k!# */
413 1.1 tsutsui
414 1.1 tsutsui /* %F!<@(#)sc.c 8.1f%K373H$N>uBV$rD4$Y$k$?$a!"Addtional Sens Field$r%"%/%;%9$9$k */
415 1.1 tsutsui /* I,MW$,$"$k$N$G6/10/93P%$%98.1i%$%PB&$Glen$r7hDj$9$k$3$H$K$9$k */
416 1.1 tsutsui
417 1.1 tsutsui cdb.lun = unit;
418 1.1 tsutsui cdb.len = len;
419 1.1 tsutsui
420 1.1 tsutsui if (!(scrun(ctlr, slave, (void *)&cdb, 6, buf, len, &lock))) {
421 1.1 tsutsui #ifdef DEBUG
422 1.1 tsutsui printf("scsi_request_sense: Command Transfer Failed.\n");
423 1.1 tsutsui #endif
424 1.1 tsutsui return(-1);
425 1.1 tsutsui }
426 1.1 tsutsui
427 1.1 tsutsui while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
428 1.1 tsutsui DELAY(10);
429 1.1 tsutsui
430 1.1 tsutsui status = scfinish(ctlr);
431 1.1 tsutsui
432 1.1 tsutsui if (lock == SC_IO_COMPLETE) {
433 1.1 tsutsui #ifdef DEBUG
434 1.1 tsutsui printf("scsi_request_sense: Status -- 0x%x\n", status);
435 1.1 tsutsui #endif
436 1.1 tsutsui return(status);
437 1.1 tsutsui } else {
438 1.1 tsutsui return(lock);
439 1.1 tsutsui }
440 1.1 tsutsui }
441 1.1 tsutsui
442 1.1 tsutsui int
443 1.1 tsutsui scsi_immed_command(int ctlr, int slave, int unit, struct scsi_fmt_cdb *cdb,
444 1.1 tsutsui u_char *buf, unsigned int len)
445 1.1 tsutsui {
446 1.1 tsutsui int status;
447 1.1 tsutsui volatile int lock;
448 1.1 tsutsui
449 1.1 tsutsui #ifdef DEBUG
450 1.1 tsutsui printf("scsi_immed_command( %d, %d, %d, cdb(%d), buf, %d): Start\n",
451 1.1 tsutsui ctlr, slave, unit, cdb->len, len);
452 1.1 tsutsui #endif
453 1.1 tsutsui
454 1.1 tsutsui cdb->cdb[1] |= unit << 5;
455 1.1 tsutsui
456 1.1 tsutsui if (!(scrun(ctlr, slave, (void *)&cdb->cdb[0], cdb->len, buf, len, &lock))) {
457 1.1 tsutsui #ifdef DEBUG
458 1.1 tsutsui printf("scsi_immed_command: Command Transfer Failed.\n");
459 1.1 tsutsui #endif
460 1.1 tsutsui return(-1);
461 1.1 tsutsui }
462 1.1 tsutsui
463 1.1 tsutsui while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED))
464 1.1 tsutsui DELAY(10);
465 1.1 tsutsui
466 1.1 tsutsui status = scfinish(ctlr);
467 1.1 tsutsui
468 1.1 tsutsui if (lock == SC_IO_COMPLETE) {
469 1.1 tsutsui #ifdef DEBUG
470 1.1 tsutsui printf("scsi_immed_command: Status -- 0x%x\n", status);
471 1.1 tsutsui #endif
472 1.1 tsutsui return(status);
473 1.1 tsutsui } else {
474 1.1 tsutsui return(lock);
475 1.1 tsutsui }
476 1.1 tsutsui }
477 1.1 tsutsui
478 1.1 tsutsui int
479 1.1 tsutsui scsi_format_unit(int ctlr, int slave, int unit)
480 1.1 tsutsui {
481 1.1 tsutsui static struct scsi_cdb6 cdb = { CMD_FORMAT_UNIT, 0, 0, 0, 0, 0 };
482 1.1 tsutsui int status;
483 1.1 tsutsui volatile int lock;
484 1.1 tsutsui #ifdef DEBUG
485 1.1 tsutsui int count = 0;
486 1.1 tsutsui #endif
487 1.1 tsutsui
488 1.1 tsutsui #ifdef DEBUG
489 1.1 tsutsui printf("scsi_format_unit( %d, %d, %d): Start\n", ctlr, slave, unit);
490 1.1 tsutsui #endif
491 1.1 tsutsui
492 1.1 tsutsui cdb.lun = unit;
493 1.1 tsutsui
494 1.1 tsutsui if (!(scrun(ctlr, slave, (void *)&cdb, 6, (u_char *) 0, 0, &lock))) {
495 1.1 tsutsui #ifdef DEBUG
496 1.1 tsutsui printf("scsi_format_unit: Command Transfer Failed.\n");
497 1.1 tsutsui #endif
498 1.1 tsutsui return(-1);
499 1.1 tsutsui }
500 1.1 tsutsui
501 1.1 tsutsui while ((lock == SC_IN_PROGRESS) || (lock == SC_DISCONNECTED)) {
502 1.1 tsutsui DELAY(1000000);
503 1.1 tsutsui #ifdef DEBUG
504 1.1 tsutsui if ((++count % 60) == 0)
505 1.1 tsutsui printf("scsi_format_unit: %d\n", count / 60);
506 1.1 tsutsui #endif
507 1.1 tsutsui }
508 1.1 tsutsui
509 1.1 tsutsui status = scfinish(ctlr);
510 1.1 tsutsui
511 1.1 tsutsui if (lock == SC_IO_COMPLETE) {
512 1.1 tsutsui #ifdef DEBUG
513 1.1 tsutsui printf("scsi_format_unit: Status -- 0x%x\n", status);
514 1.1 tsutsui #endif
515 1.1 tsutsui return(status);
516 1.1 tsutsui } else {
517 1.1 tsutsui return(lock);
518 1.1 tsutsui }
519 1.1 tsutsui }
520 1.1 tsutsui
521 1.1 tsutsui
522 1.1 tsutsui /*
523 1.1 tsutsui * Interrupt Routine
524 1.1 tsutsui */
525 1.1 tsutsui
526 1.1 tsutsui int
527 1.1 tsutsui scintr(void)
528 1.1 tsutsui {
529 1.1 tsutsui struct scsi_softc *hs;
530 1.1 tsutsui struct scsidevice *hd;
531 1.1 tsutsui u_char ints, temp;
532 1.1 tsutsui int i;
533 1.1 tsutsui u_char *buf;
534 1.1 tsutsui int len;
535 1.1 tsutsui
536 1.1 tsutsui for (i = 0; i < NSC; i++) {
537 1.1 tsutsui hs = &scsi_softc[i];
538 1.1 tsutsui hd = (struct scsidevice *) hs->sc_hc->hp_addr;
539 1.1 tsutsui if ((ints = hd->scsi_ints) != 0)
540 1.1 tsutsui goto get_intr;
541 1.1 tsutsui }
542 1.1 tsutsui
543 1.1 tsutsui /* Unknown Interrupt occured */
544 1.1 tsutsui return -1;
545 1.1 tsutsui
546 1.1 tsutsui
547 1.1 tsutsui /*
548 1.1 tsutsui * Interrupt
549 1.1 tsutsui */
550 1.1 tsutsui
551 1.1 tsutsui get_intr:
552 1.1 tsutsui #ifdef DEBUG
553 1.1 tsutsui printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x 0x%x\n",
554 1.1 tsutsui ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns,
555 1.1 tsutsui hs->sc_phase);
556 1.1 tsutsui #endif
557 1.1 tsutsui if (ints & INTS_RESEL) {
558 1.1 tsutsui if (hs->sc_phase == BUS_FREE_PHASE) {
559 1.1 tsutsui temp = hd->scsi_temp & ~(1 << SCSI_ID);
560 1.1 tsutsui for (i = 0; temp != 1; i++) {
561 1.1 tsutsui temp >>= 1;
562 1.1 tsutsui }
563 1.1 tsutsui hs->sc_target = i;
564 1.1 tsutsui *(hs->sc_lock) = SC_IN_PROGRESS;
565 1.1 tsutsui } else
566 1.1 tsutsui goto abort;
567 1.1 tsutsui } else if (ints & INTS_DISCON) {
568 1.1 tsutsui if ((hs->sc_msg[0] == MSG_CMD_COMPLETE) || (hs->sc_msg[0] == MSG_DISCONNECT)) {
569 1.1 tsutsui hs->sc_phase = BUS_FREE_PHASE;
570 1.1 tsutsui hs->sc_target = SCSI_ID;
571 1.1 tsutsui if (hs->sc_msg[0] == MSG_CMD_COMPLETE)
572 1.1 tsutsui /* SCSI IO complete */
573 1.1 tsutsui *(hs->sc_lock) = SC_IO_COMPLETE;
574 1.1 tsutsui else
575 1.1 tsutsui /* Cisconnected from Target */
576 1.1 tsutsui *(hs->sc_lock) = SC_DISCONNECTED;
577 1.1 tsutsui hd->scsi_ints = ints;
578 1.1 tsutsui return 0;
579 1.1 tsutsui } else
580 1.1 tsutsui goto abort;
581 1.1 tsutsui } else if (ints & INTS_CMD_DONE) {
582 1.1 tsutsui if (hs->sc_phase == BUS_FREE_PHASE)
583 1.1 tsutsui goto abort;
584 1.1 tsutsui else if (hs->sc_phase == MESG_IN_PHASE) {
585 1.1 tsutsui hd->scsi_scmd = SCMD_RST_ACK;
586 1.1 tsutsui hd->scsi_ints = ints;
587 1.1 tsutsui hs->sc_phase = hd->scsi_psns & PHASE;
588 1.1 tsutsui return 0;
589 1.1 tsutsui }
590 1.1 tsutsui if (hs->sc_flags & SC_SEL_TIMEOUT)
591 1.1 tsutsui hs->sc_flags &= ~SC_SEL_TIMEOUT;
592 1.1 tsutsui } else if (ints & INTS_SRV_REQ) {
593 1.1 tsutsui if (hs->sc_phase != MESG_IN_PHASE)
594 1.1 tsutsui goto abort;
595 1.1 tsutsui } else if (ints & INTS_TIMEOUT) {
596 1.1 tsutsui if (hs->sc_phase == ARB_SEL_PHASE) {
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 hs->sc_phase = BUS_FREE_PHASE;
600 1.1 tsutsui hs->sc_target = SCSI_ID;
601 1.1 tsutsui /* Such SCSI Device is not conected. */
602 1.1 tsutsui *(hs->sc_lock) = SC_DEV_NOT_FOUND;
603 1.1 tsutsui hd->scsi_ints = ints;
604 1.1 tsutsui return 0;
605 1.1 tsutsui } else {
606 1.1 tsutsui /* wait more 250 usec */
607 1.1 tsutsui hs->sc_flags |= SC_SEL_TIMEOUT;
608 1.1 tsutsui hd->scsi_temp = 0;
609 1.1 tsutsui hd->scsi_tch = 0;
610 1.1 tsutsui hd->scsi_tcm = 0x06;
611 1.1 tsutsui hd->scsi_tcl = 0x40;
612 1.1 tsutsui hd->scsi_ints = ints;
613 1.1 tsutsui return 0;
614 1.1 tsutsui }
615 1.1 tsutsui } else
616 1.1 tsutsui goto abort;
617 1.1 tsutsui } else
618 1.1 tsutsui goto abort;
619 1.1 tsutsui
620 1.1 tsutsui hd->scsi_ints = ints;
621 1.1 tsutsui
622 1.1 tsutsui /*
623 1.1 tsutsui * Next SCSI Transfer
624 1.1 tsutsui */
625 1.1 tsutsui
626 1.1 tsutsui while ((hd->scsi_psns & PSNS_REQ) == 0) {
627 1.1 tsutsui DELAY(1);
628 1.1 tsutsui }
629 1.1 tsutsui
630 1.1 tsutsui hs->sc_phase = hd->scsi_psns & PHASE;
631 1.1 tsutsui
632 1.1 tsutsui if ((hs->sc_phase == DATA_OUT_PHASE) || (hs->sc_phase == DATA_IN_PHASE)) {
633 1.1 tsutsui len = hs->sc_len;
634 1.1 tsutsui buf = hs->sc_buf;
635 1.1 tsutsui } else if (hs->sc_phase == CMD_PHASE) {
636 1.1 tsutsui len = hs->sc_cdblen;
637 1.1 tsutsui buf = hs->sc_cdb;
638 1.1 tsutsui } else if (hs->sc_phase == STATUS_PHASE) {
639 1.1 tsutsui len = 1;
640 1.1 tsutsui buf = &hs->sc_stat;
641 1.1 tsutsui } else {
642 1.1 tsutsui len = 1;
643 1.1 tsutsui buf = hs->sc_msg;
644 1.1 tsutsui }
645 1.1 tsutsui
646 1.1 tsutsui ixfer_start(hd, len, hs->sc_phase, 0);
647 1.1 tsutsui if (hs->sc_phase & PHASE_IO)
648 1.1 tsutsui ixfer_in(hd, len, buf);
649 1.1 tsutsui else
650 1.1 tsutsui ixfer_out(hd, len, buf);
651 1.1 tsutsui
652 1.1 tsutsui return 0;
653 1.1 tsutsui
654 1.1 tsutsui /*
655 1.1 tsutsui * SCSI Abort
656 1.1 tsutsui */
657 1.1 tsutsui abort:
658 1.1 tsutsui /* SCSI IO failed */
659 1.1 tsutsui scabort(hs, hd);
660 1.1 tsutsui hd->scsi_ints = ints;
661 1.1 tsutsui *(hs->sc_lock) = SC_IO_FAILED;
662 1.1 tsutsui return -1;
663 1.1 tsutsui }
664