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