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