1 /* $OpenBSD: siop.c,v 1.34 2004/04/25 01:49:12 krw Exp $ */
2 /* $NetBSD: siop.c,v 1.65 2002/11/08 22:04:41 bouyer Exp $ */
3
4 /*
5 * Copyright (c) 2000 Manuel Bouyer.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Manuel Bouyer.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34 /* SYM53c7/8xx PCI-SCSI I/O Processors driver */
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/malloc.h>
40 #include <sys/buf.h>
41 #include <sys/kernel.h>
42
43 #include <machine/endian.h>
44 #include <machine/bus.h>
45
46 #include <dev/microcode/siop/siop.out>
47
48 #include <scsi/scsi_all.h>
49 #include <scsi/scsi_message.h>
50 #include <scsi/scsiconf.h>
51
52 #include <dev/ic/siopreg.h>
53 #include <dev/ic/siopvar_common.h>
54 #include <dev/ic/siopvar.h>
55
56 #ifndef SIOP_DEBUG
57 #undef SIOP_DEBUG
58 #endif
59 #undef SIOP_DEBUG
60 #undef SIOP_DEBUG_DR
61 #undef SIOP_DEBUG_INTR
62 #undef SIOP_DEBUG_SCHED
63 #undef DUMP_SCRIPT
64
65 #define SIOP_STATS
66
67 #ifndef SIOP_DEFAULT_TARGET
68 #define SIOP_DEFAULT_TARGET 7
69 #endif
70
71 /* number of cmd descriptors per block */
72 #define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct siop_xfer))
73
74 /* Number of scheduler slot (needs to match script) */
75 #define SIOP_NSLOTS 40
76
77 void siop_reset(struct siop_softc *);
78 void siop_handle_reset(struct siop_softc *);
79 int siop_handle_qtag_reject(struct siop_cmd *);
80 void siop_scsicmd_end(struct siop_cmd *);
81 void siop_start(struct siop_softc *);
82 void siop_timeout(void *);
83 int siop_scsicmd(struct scsi_xfer *);
84 void siop_dump_script(struct siop_softc *);
85 void siop_morecbd(struct siop_softc *);
86 struct siop_lunsw *siop_get_lunsw(struct siop_softc *);
87 void siop_add_reselsw(struct siop_softc *, int);
88 void siop_update_scntl3(struct siop_softc *, struct siop_common_target *);
89
90 struct cfdriver siop_cd = {
91 NULL, "siop", DV_DULL
92 };
93
94 struct scsi_adapter siop_adapter = {
95 siop_scsicmd,
96 siop_minphys,
97 NULL,
98 NULL,
99 };
100
101 struct scsi_device siop_dev = {
102 NULL,
103 NULL,
104 NULL,
105 NULL,
106 };
107
108 #ifdef SIOP_STATS
109 static int siop_stat_intr = 0;
110 static int siop_stat_intr_shortxfer = 0;
111 static int siop_stat_intr_sdp = 0;
112 static int siop_stat_intr_done = 0;
113 static int siop_stat_intr_xferdisc = 0;
114 static int siop_stat_intr_lunresel = 0;
115 static int siop_stat_intr_qfull = 0;
116 void siop_printstats(void);
117 #define INCSTAT(x) x++
118 #else
119 #define INCSTAT(x)
120 #endif
121
122 static __inline__ void siop_script_sync(struct siop_softc *, int);
123 static __inline__ void
siop_script_sync(sc,ops)124 siop_script_sync(sc, ops)
125 struct siop_softc *sc;
126 int ops;
127 {
128 if ((sc->sc_c.features & SF_CHIP_RAM) == 0)
129 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
130 PAGE_SIZE, ops);
131 }
132
133 static __inline__ u_int32_t siop_script_read(struct siop_softc *, u_int);
134 static __inline__ u_int32_t
siop_script_read(sc,offset)135 siop_script_read(sc, offset)
136 struct siop_softc *sc;
137 u_int offset;
138 {
139 if (sc->sc_c.features & SF_CHIP_RAM) {
140 return bus_space_read_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
141 offset * 4);
142 } else {
143 return letoh32(sc->sc_c.sc_script[offset]);
144 }
145 }
146
147 static __inline__ void siop_script_write(struct siop_softc *, u_int,
148 u_int32_t);
149 static __inline__ void
siop_script_write(sc,offset,val)150 siop_script_write(sc, offset, val)
151 struct siop_softc *sc;
152 u_int offset;
153 u_int32_t val;
154 {
155 if (sc->sc_c.features & SF_CHIP_RAM) {
156 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
157 offset * 4, val);
158 } else {
159 sc->sc_c.sc_script[offset] = htole32(val);
160 }
161 }
162
163 void
siop_attach(sc)164 siop_attach(sc)
165 struct siop_softc *sc;
166 {
167 if (siop_common_attach(&sc->sc_c) != 0)
168 return;
169
170 TAILQ_INIT(&sc->free_list);
171 TAILQ_INIT(&sc->ready_list);
172 TAILQ_INIT(&sc->urgent_list);
173 TAILQ_INIT(&sc->cmds);
174 TAILQ_INIT(&sc->lunsw_list);
175 sc->sc_currschedslot = 0;
176 sc->sc_c.sc_link.adapter = &siop_adapter;
177 sc->sc_c.sc_link.device = &siop_dev;
178 sc->sc_c.sc_link.openings = SIOP_NTAG;
179
180 /* Start with one page worth of commands */
181 siop_morecbd(sc);
182
183 #ifdef SIOP_DEBUG
184 printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",
185 sc->sc_c.sc_dev.dv_xname, (int)sizeof(siop_script),
186 (u_int32_t)sc->sc_c.sc_scriptaddr, sc->sc_c.sc_script);
187 #endif
188
189 /* Do a bus reset, so that devices fall back to narrow/async */
190 siop_resetbus(&sc->sc_c);
191 /*
192 * siop_reset() will reset the chip, thus clearing pending interrupts
193 */
194 siop_reset(sc);
195 #ifdef DUMP_SCRIPT
196 siop_dump_script(sc);
197 #endif
198
199 config_found((struct device*)sc, &sc->sc_c.sc_link, scsiprint);
200 }
201
202 void
siop_reset(sc)203 siop_reset(sc)
204 struct siop_softc *sc;
205 {
206 int i, j;
207 struct siop_lunsw *lunsw;
208
209 siop_common_reset(&sc->sc_c);
210
211 /* copy and patch the script */
212 if (sc->sc_c.features & SF_CHIP_RAM) {
213 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh, 0,
214 siop_script, sizeof(siop_script) / sizeof(siop_script[0]));
215 for (j = 0; j <
216 (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
217 j++) {
218 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
219 E_abs_msgin_Used[j] * 4,
220 sc->sc_c.sc_scriptaddr + Ent_msgin_space);
221 }
222 if (sc->sc_c.features & SF_CHIP_LED0) {
223 bus_space_write_region_4(sc->sc_c.sc_ramt,
224 sc->sc_c.sc_ramh,
225 Ent_led_on1, siop_led_on,
226 sizeof(siop_led_on) / sizeof(siop_led_on[0]));
227 bus_space_write_region_4(sc->sc_c.sc_ramt,
228 sc->sc_c.sc_ramh,
229 Ent_led_on2, siop_led_on,
230 sizeof(siop_led_on) / sizeof(siop_led_on[0]));
231 bus_space_write_region_4(sc->sc_c.sc_ramt,
232 sc->sc_c.sc_ramh,
233 Ent_led_off, siop_led_off,
234 sizeof(siop_led_off) / sizeof(siop_led_off[0]));
235 }
236 } else {
237 for (j = 0;
238 j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) {
239 sc->sc_c.sc_script[j] = htole32(siop_script[j]);
240 }
241 for (j = 0; j <
242 (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));
243 j++) {
244 sc->sc_c.sc_script[E_abs_msgin_Used[j]] =
245 htole32(sc->sc_c.sc_scriptaddr + Ent_msgin_space);
246 }
247 if (sc->sc_c.features & SF_CHIP_LED0) {
248 for (j = 0; j < (sizeof(siop_led_on) /
249 sizeof(siop_led_on[0])); j++)
250 sc->sc_c.sc_script[
251 Ent_led_on1 / sizeof(siop_led_on[0]) + j
252 ] = htole32(siop_led_on[j]);
253 for (j = 0; j < (sizeof(siop_led_on) /
254 sizeof(siop_led_on[0])); j++)
255 sc->sc_c.sc_script[
256 Ent_led_on2 / sizeof(siop_led_on[0]) + j
257 ] = htole32(siop_led_on[j]);
258 for (j = 0; j < (sizeof(siop_led_off) /
259 sizeof(siop_led_off[0])); j++)
260 sc->sc_c.sc_script[
261 Ent_led_off / sizeof(siop_led_off[0]) + j
262 ] = htole32(siop_led_off[j]);
263 }
264 }
265 sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]);
266 sc->script_free_hi = sc->sc_c.ram_size / 4;
267 sc->sc_ntargets = 0;
268
269 /* free used and unused lun switches */
270 while((lunsw = TAILQ_FIRST(&sc->lunsw_list)) != NULL) {
271 #ifdef SIOP_DEBUG
272 printf("%s: free lunsw at offset %d\n",
273 sc->sc_c.sc_dev.dv_xname, lunsw->lunsw_off);
274 #endif
275 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
276 free(lunsw, M_DEVBUF);
277 }
278 TAILQ_INIT(&sc->lunsw_list);
279 /* restore reselect switch */
280 for (i = 0; i < sc->sc_c.sc_link.adapter_buswidth; i++) {
281 struct siop_target *target;
282 if (sc->sc_c.targets[i] == NULL)
283 continue;
284 #ifdef SIOP_DEBUG
285 printf("%s: restore sw for target %d\n",
286 sc->sc_c.sc_dev.dv_xname, i);
287 #endif
288 target = (struct siop_target *)sc->sc_c.targets[i];
289 free(target->lunsw, M_DEVBUF);
290 target->lunsw = siop_get_lunsw(sc);
291 if (target->lunsw == NULL) {
292 printf("%s: can't alloc lunsw for target %d\n",
293 sc->sc_c.sc_dev.dv_xname, i);
294 break;
295 }
296 siop_add_reselsw(sc, i);
297 }
298
299 /* start script */
300 if ((sc->sc_c.features & SF_CHIP_RAM) == 0) {
301 bus_dmamap_sync(sc->sc_c.sc_dmat, sc->sc_c.sc_scriptdma, 0,
302 PAGE_SIZE, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
303 }
304 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP,
305 sc->sc_c.sc_scriptaddr + Ent_reselect);
306 }
307
308 #if 0
309 #define CALL_SCRIPT(ent) do {\
310 printf ("start script DSA 0x%lx DSP 0x%lx\n", \
311 siop_cmd->cmd_c.dsa, \
312 sc->sc_c.sc_scriptaddr + ent); \
313 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
314 } while (0)
315 #else
316 #define CALL_SCRIPT(ent) do {\
317 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSP, sc->sc_c.sc_scriptaddr + ent); \
318 } while (0)
319 #endif
320
321 int
siop_intr(v)322 siop_intr(v)
323 void *v;
324 {
325 struct siop_softc *sc = v;
326 struct siop_target *siop_target;
327 struct siop_cmd *siop_cmd;
328 struct siop_lun *siop_lun;
329 struct scsi_xfer *xs;
330 int istat, sist, sstat1, dstat;
331 u_int32_t irqcode;
332 int need_reset = 0;
333 int offset, target, lun, tag;
334 bus_addr_t dsa;
335 struct siop_cbd *cbdp;
336 int freetarget = 0;
337 int restart = 0;
338
339 istat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_ISTAT);
340 if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)
341 return 0;
342 INCSTAT(siop_stat_intr);
343 if (istat & ISTAT_INTF) {
344 printf("INTRF\n");
345 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
346 SIOP_ISTAT, ISTAT_INTF);
347 }
348 if ((istat &(ISTAT_DIP | ISTAT_SIP | ISTAT_ABRT)) ==
349 (ISTAT_DIP | ISTAT_ABRT)) {
350 /* clear abort */
351 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
352 SIOP_ISTAT, 0);
353 }
354 /* use DSA to find the current siop_cmd */
355 dsa = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA);
356 for (cbdp = TAILQ_FIRST(&sc->cmds); cbdp != NULL;
357 cbdp = TAILQ_NEXT(cbdp, next)) {
358 if (dsa >= cbdp->xferdma->dm_segs[0].ds_addr &&
359 dsa < cbdp->xferdma->dm_segs[0].ds_addr + PAGE_SIZE) {
360 dsa -= cbdp->xferdma->dm_segs[0].ds_addr;
361 siop_cmd = &cbdp->cmds[dsa / sizeof(struct siop_xfer)];
362 siop_table_sync(siop_cmd,
363 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
364 break;
365 }
366 }
367 if (cbdp == NULL) {
368 siop_cmd = NULL;
369 }
370 if (siop_cmd) {
371 xs = siop_cmd->cmd_c.xs;
372 siop_target = (struct siop_target *)siop_cmd->cmd_c.siop_target;
373 target = siop_cmd->cmd_c.xs->sc_link->target;
374 lun = siop_cmd->cmd_c.xs->sc_link->lun;
375 tag = siop_cmd->cmd_c.tag;
376 siop_lun = siop_target->siop_lun[lun];
377 #ifdef DIAGNOSTIC
378 if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
379 siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
380 printf("siop_cmd (lun %d) for DSA 0x%x "
381 "not active (%d)\n", lun, (u_int)dsa,
382 siop_cmd->cmd_c.status);
383 xs = NULL;
384 siop_target = NULL;
385 target = -1;
386 lun = -1;
387 tag = -1;
388 siop_lun = NULL;
389 siop_cmd = NULL;
390 } else if (siop_lun->siop_tag[tag].active != siop_cmd) {
391 printf("siop_cmd (lun %d tag %d) not in siop_lun "
392 "active (%p != %p)\n", lun, tag, siop_cmd,
393 siop_lun->siop_tag[tag].active);
394 }
395 #endif
396 } else {
397 xs = NULL;
398 siop_target = NULL;
399 target = -1;
400 lun = -1;
401 tag = -1;
402 siop_lun = NULL;
403 }
404 if (istat & ISTAT_DIP) {
405 dstat = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
406 SIOP_DSTAT);
407 if (dstat & DSTAT_ABRT) {
408 /* was probably generated by a bus reset IOCTL */
409 if ((dstat & DSTAT_DFE) == 0)
410 siop_clearfifo(&sc->sc_c);
411 goto reset;
412 }
413 if (dstat & DSTAT_SSI) {
414 printf("single step dsp 0x%08x dsa 0x08%x\n",
415 (int)(bus_space_read_4(sc->sc_c.sc_rt,
416 sc->sc_c.sc_rh, SIOP_DSP) -
417 sc->sc_c.sc_scriptaddr),
418 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
419 SIOP_DSA));
420 if ((dstat & ~(DSTAT_DFE | DSTAT_SSI)) == 0 &&
421 (istat & ISTAT_SIP) == 0) {
422 bus_space_write_1(sc->sc_c.sc_rt,
423 sc->sc_c.sc_rh, SIOP_DCNTL,
424 bus_space_read_1(sc->sc_c.sc_rt,
425 sc->sc_c.sc_rh, SIOP_DCNTL) | DCNTL_STD);
426 }
427 return 1;
428 }
429
430 if (dstat & ~(DSTAT_SIR | DSTAT_DFE | DSTAT_SSI)) {
431 printf("%s: DMA IRQ:", sc->sc_c.sc_dev.dv_xname);
432 if (dstat & DSTAT_IID)
433 printf(" illegal instruction");
434 if (dstat & DSTAT_BF)
435 printf(" bus fault");
436 if (dstat & DSTAT_MDPE)
437 printf(" parity");
438 if (dstat & DSTAT_DFE)
439 printf(" dma fifo empty");
440 else
441 siop_clearfifo(&sc->sc_c);
442 printf(", DSP=0x%x DSA=0x%x: ",
443 (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
444 SIOP_DSP) - sc->sc_c.sc_scriptaddr),
445 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA));
446 if (siop_cmd)
447 printf("last msg_in=0x%x status=0x%x\n",
448 siop_cmd->cmd_tables->msg_in[0],
449 letoh32(siop_cmd->cmd_tables->status));
450 else
451 printf("current DSA invalid\n");
452 need_reset = 1;
453 }
454 }
455 if (istat & ISTAT_SIP) {
456 if (istat & ISTAT_DIP)
457 delay(10);
458 /*
459 * Can't read sist0 & sist1 independently, or we have to
460 * insert delay
461 */
462 sist = bus_space_read_2(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
463 SIOP_SIST0);
464 sstat1 = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
465 SIOP_SSTAT1);
466 #ifdef SIOP_DEBUG_INTR
467 printf("scsi interrupt, sist=0x%x sstat1=0x%x "
468 "DSA=0x%x DSP=0x%lx\n", sist, sstat1,
469 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
470 (u_long)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
471 SIOP_DSP) -
472 sc->sc_c.sc_scriptaddr));
473 #endif
474 if (sist & SIST0_RST) {
475 siop_handle_reset(sc);
476 siop_start(sc);
477 /* no table to flush here */
478 return 1;
479 }
480 if (sist & SIST0_SGE) {
481 if (siop_cmd)
482 sc_print_addr(xs->sc_link);
483 else
484 printf("%s:", sc->sc_c.sc_dev.dv_xname);
485 printf("scsi gross error\n");
486 goto reset;
487 }
488 if ((sist & SIST0_MA) && need_reset == 0) {
489 if (siop_cmd) {
490 int scratcha0;
491 /* XXX Why read DSTAT again? */
492 dstat = bus_space_read_1(sc->sc_c.sc_rt,
493 sc->sc_c.sc_rh, SIOP_DSTAT);
494 /*
495 * first restore DSA, in case we were in a S/G
496 * operation.
497 */
498 bus_space_write_4(sc->sc_c.sc_rt,
499 sc->sc_c.sc_rh,
500 SIOP_DSA, siop_cmd->cmd_c.dsa);
501 scratcha0 = bus_space_read_1(sc->sc_c.sc_rt,
502 sc->sc_c.sc_rh, SIOP_SCRATCHA);
503 switch (sstat1 & SSTAT1_PHASE_MASK) {
504 case SSTAT1_PHASE_STATUS:
505 /*
506 * previous phase may be aborted for any reason
507 * ( for example, the target has less data to
508 * transfer than requested). Just go to status
509 * and the command should terminate.
510 */
511 INCSTAT(siop_stat_intr_shortxfer);
512 if ((dstat & DSTAT_DFE) == 0)
513 siop_clearfifo(&sc->sc_c);
514 /* no table to flush here */
515 CALL_SCRIPT(Ent_status);
516 return 1;
517 case SSTAT1_PHASE_MSGIN:
518 /*
519 * target may be ready to disconnect
520 * Save data pointers just in case.
521 */
522 INCSTAT(siop_stat_intr_xferdisc);
523 if (scratcha0 & A_flag_data)
524 siop_sdp(&siop_cmd->cmd_c);
525 else if ((dstat & DSTAT_DFE) == 0)
526 siop_clearfifo(&sc->sc_c);
527 bus_space_write_1(sc->sc_c.sc_rt,
528 sc->sc_c.sc_rh, SIOP_SCRATCHA,
529 scratcha0 & ~A_flag_data);
530 siop_table_sync(siop_cmd,
531 BUS_DMASYNC_PREREAD |
532 BUS_DMASYNC_PREWRITE);
533 CALL_SCRIPT(Ent_msgin);
534 return 1;
535 }
536 printf("%s: unexpected phase mismatch %d\n",
537 sc->sc_c.sc_dev.dv_xname,
538 sstat1 & SSTAT1_PHASE_MASK);
539 } else {
540 printf("%s: phase mismatch without command\n",
541 sc->sc_c.sc_dev.dv_xname);
542 }
543 need_reset = 1;
544 }
545 if (sist & SIST0_PAR) {
546 /* parity error, reset */
547 if (siop_cmd)
548 sc_print_addr(xs->sc_link);
549 else
550 printf("%s:", sc->sc_c.sc_dev.dv_xname);
551 printf("parity error\n");
552 goto reset;
553 }
554 if ((sist & (SIST1_STO << 8)) && need_reset == 0) {
555 /* selection time out, assume there's no device here */
556 if (siop_cmd) {
557 siop_cmd->cmd_c.status = CMDST_DONE;
558 xs->error = XS_SELTIMEOUT;
559 freetarget = 1;
560 goto end;
561 } else {
562 printf("%s: selection timeout without "
563 "command\n", sc->sc_c.sc_dev.dv_xname);
564 need_reset = 1;
565 }
566 }
567 if (sist & SIST0_UDC) {
568 /*
569 * unexpected disconnect. Usually the target signals
570 * a fatal condition this way. Attempt to get sense.
571 */
572 if (siop_cmd) {
573 siop_cmd->cmd_tables->status =
574 htole32(SCSI_CHECK);
575 goto end;
576 }
577 printf("%s: unexpected disconnect without "
578 "command\n", sc->sc_c.sc_dev.dv_xname);
579 goto reset;
580 }
581 if (sist & (SIST1_SBMC << 8)) {
582 /* SCSI bus mode change */
583 if (siop_modechange(&sc->sc_c) == 0 || need_reset == 1)
584 goto reset;
585 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
586 /*
587 * we have a script interrupt, it will
588 * restart the script.
589 */
590 goto scintr;
591 }
592 /*
593 * else we have to restart it ourselve, at the
594 * interrupted instruction.
595 */
596 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
597 SIOP_DSP,
598 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
599 SIOP_DSP) - 8);
600 return 1;
601 }
602 /* Else it's an unhandled exception (for now). */
603 printf("%s: unhandled scsi interrupt, sist=0x%x sstat1=0x%x "
604 "DSA=0x%x DSP=0x%x\n", sc->sc_c.sc_dev.dv_xname,
605 sist, sstat1,
606 bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh, SIOP_DSA),
607 (int)(bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
608 SIOP_DSP) - sc->sc_c.sc_scriptaddr));
609 if (siop_cmd) {
610 siop_cmd->cmd_c.status = CMDST_DONE;
611 xs->error = XS_SELTIMEOUT;
612 goto end;
613 }
614 need_reset = 1;
615 }
616 if (need_reset) {
617 reset:
618 /* fatal error, reset the bus */
619 siop_resetbus(&sc->sc_c);
620 /* no table to flush here */
621 return 1;
622 }
623
624 scintr:
625 if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
626 irqcode = bus_space_read_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
627 SIOP_DSPS);
628 #ifdef SIOP_DEBUG_INTR
629 printf("script interrupt 0x%x\n", irqcode);
630 #endif
631 /*
632 * no command, or an inactive command is only valid for a
633 * reselect interrupt
634 */
635 if ((irqcode & 0x80) == 0) {
636 if (siop_cmd == NULL) {
637 printf(
638 "%s: script interrupt (0x%x) with invalid DSA !!!\n",
639 sc->sc_c.sc_dev.dv_xname, irqcode);
640 goto reset;
641 }
642 if (siop_cmd->cmd_c.status != CMDST_ACTIVE &&
643 siop_cmd->cmd_c.status != CMDST_SENSE_ACTIVE) {
644 printf("%s: command with invalid status "
645 "(IRQ code 0x%x current status %d) !\n",
646 sc->sc_c.sc_dev.dv_xname,
647 irqcode, siop_cmd->cmd_c.status);
648 xs = NULL;
649 }
650 }
651 switch(irqcode) {
652 case A_int_err:
653 printf("error, DSP=0x%x\n",
654 (int)(bus_space_read_4(sc->sc_c.sc_rt,
655 sc->sc_c.sc_rh, SIOP_DSP) - sc->sc_c.sc_scriptaddr));
656 if (xs) {
657 xs->error = XS_SELTIMEOUT;
658 goto end;
659 } else {
660 goto reset;
661 }
662 case A_int_reseltarg:
663 printf("%s: reselect with invalid target\n",
664 sc->sc_c.sc_dev.dv_xname);
665 goto reset;
666 case A_int_resellun:
667 INCSTAT(siop_stat_intr_lunresel);
668 target = bus_space_read_1(sc->sc_c.sc_rt,
669 sc->sc_c.sc_rh, SIOP_SCRATCHA) & 0xf;
670 lun = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
671 SIOP_SCRATCHA + 1);
672 tag = bus_space_read_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
673 SIOP_SCRATCHA + 2);
674 siop_target =
675 (struct siop_target *)sc->sc_c.targets[target];
676 if (siop_target == NULL) {
677 printf("%s: reselect with invalid target %d\n",
678 sc->sc_c.sc_dev.dv_xname, target);
679 goto reset;
680 }
681 siop_lun = siop_target->siop_lun[lun];
682 if (siop_lun == NULL) {
683 printf("%s: target %d reselect with invalid "
684 "lun %d\n", sc->sc_c.sc_dev.dv_xname,
685 target, lun);
686 goto reset;
687 }
688 if (siop_lun->siop_tag[tag].active == NULL) {
689 printf("%s: target %d lun %d tag %d reselect "
690 "without command\n",
691 sc->sc_c.sc_dev.dv_xname,
692 target, lun, tag);
693 goto reset;
694 }
695 siop_cmd = siop_lun->siop_tag[tag].active;
696 bus_space_write_4(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
697 SIOP_DSP, siop_cmd->cmd_c.dsa +
698 sizeof(struct siop_common_xfer) +
699 Ent_ldsa_reload_dsa);
700 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
701 return 1;
702 case A_int_reseltag:
703 printf("%s: reselect with invalid tag\n",
704 sc->sc_c.sc_dev.dv_xname);
705 goto reset;
706 case A_int_msgin:
707 {
708 int msgin = bus_space_read_1(sc->sc_c.sc_rt,
709 sc->sc_c.sc_rh, SIOP_SFBR);
710 if (msgin == MSG_MESSAGE_REJECT) {
711 int msg, extmsg;
712 if (siop_cmd->cmd_tables->msg_out[0] & 0x80) {
713 /*
714 * message was part of a identify +
715 * something else. Identify shouldn't
716 * have been rejected.
717 */
718 msg =
719 siop_cmd->cmd_tables->msg_out[1];
720 extmsg =
721 siop_cmd->cmd_tables->msg_out[3];
722 } else {
723 msg = siop_cmd->cmd_tables->msg_out[0];
724 extmsg =
725 siop_cmd->cmd_tables->msg_out[2];
726 }
727 if (msg == MSG_MESSAGE_REJECT) {
728 /* MSG_REJECT for a MSG_REJECT !*/
729 if (xs)
730 sc_print_addr(xs->sc_link);
731 else
732 printf("%s: ",
733 sc->sc_c.sc_dev.dv_xname);
734 printf("our reject message was "
735 "rejected\n");
736 goto reset;
737 }
738 if (msg == MSG_EXTENDED &&
739 extmsg == MSG_EXT_WDTR) {
740 /* WDTR rejected, initiate sync */
741 if ((siop_target->target_c.flags &
742 TARF_SYNC) == 0) {
743 siop_target->target_c.status =
744 TARST_OK;
745 siop_update_xfer_mode(&sc->sc_c,
746 target);
747 /* no table to flush here */
748 CALL_SCRIPT(Ent_msgin_ack);
749 return 1;
750 }
751 siop_target->target_c.status =
752 TARST_SYNC_NEG;
753 siop_sdtr_msg(&siop_cmd->cmd_c, 0,
754 sc->sc_c.st_minsync,
755 sc->sc_c.maxoff);
756 siop_table_sync(siop_cmd,
757 BUS_DMASYNC_PREREAD |
758 BUS_DMASYNC_PREWRITE);
759 CALL_SCRIPT(Ent_send_msgout);
760 return 1;
761 } else if (msg == MSG_EXTENDED &&
762 extmsg == MSG_EXT_SDTR) {
763 /* sync rejected */
764 siop_target->target_c.offset = 0;
765 siop_target->target_c.period = 0;
766 siop_target->target_c.status = TARST_OK;
767 siop_update_xfer_mode(&sc->sc_c,
768 target);
769 /* no table to flush here */
770 CALL_SCRIPT(Ent_msgin_ack);
771 return 1;
772 } else if (msg == MSG_EXTENDED &&
773 extmsg == MSG_EXT_PPR) {
774 /* PPR negotiation rejected */
775 siop_target->target_c.offset = 0;
776 siop_target->target_c.period = 0;
777 siop_target->target_c.status = TARST_ASYNC;
778 siop_target->target_c.flags &= ~(TARF_DT | TARF_ISDT);
779 CALL_SCRIPT(Ent_msgin_ack);
780 return 1;
781 } else if (msg == MSG_SIMPLE_Q_TAG ||
782 msg == MSG_HEAD_OF_Q_TAG ||
783 msg == MSG_ORDERED_Q_TAG) {
784 if (siop_handle_qtag_reject(
785 siop_cmd) == -1)
786 goto reset;
787 CALL_SCRIPT(Ent_msgin_ack);
788 return 1;
789 }
790 if (xs)
791 sc_print_addr(xs->sc_link);
792 else
793 printf("%s: ",
794 sc->sc_c.sc_dev.dv_xname);
795 if (msg == MSG_EXTENDED) {
796 printf("scsi message reject, extended "
797 "message sent was 0x%x\n", extmsg);
798 } else {
799 printf("scsi message reject, message "
800 "sent was 0x%x\n", msg);
801 }
802 /* no table to flush here */
803 CALL_SCRIPT(Ent_msgin_ack);
804 return 1;
805 }
806 if (xs)
807 sc_print_addr(xs->sc_link);
808 else
809 printf("%s: ", sc->sc_c.sc_dev.dv_xname);
810 printf("unhandled message 0x%x\n",
811 siop_cmd->cmd_tables->msg_in[0]);
812 siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
813 siop_cmd->cmd_tables->t_msgout.count= htole32(1);
814 siop_table_sync(siop_cmd,
815 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
816 CALL_SCRIPT(Ent_send_msgout);
817 return 1;
818 }
819 case A_int_extmsgin:
820 #ifdef SIOP_DEBUG_INTR
821 printf("extended message: msg 0x%x len %d\n",
822 siop_cmd->cmd_tables->msg_in[2],
823 siop_cmd->cmd_tables->msg_in[1]);
824 #endif
825 if (siop_cmd->cmd_tables->msg_in[1] >
826 sizeof(siop_cmd->cmd_tables->msg_in) - 2)
827 printf("%s: extended message too big (%d)\n",
828 sc->sc_c.sc_dev.dv_xname,
829 siop_cmd->cmd_tables->msg_in[1]);
830 siop_cmd->cmd_tables->t_extmsgdata.count =
831 htole32(siop_cmd->cmd_tables->msg_in[1] - 1);
832 siop_table_sync(siop_cmd,
833 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
834 CALL_SCRIPT(Ent_get_extmsgdata);
835 return 1;
836 case A_int_extmsgdata:
837 #ifdef SIOP_DEBUG_INTR
838 {
839 int i;
840 printf("extended message: 0x%x, data:",
841 siop_cmd->cmd_tables->msg_in[2]);
842 for (i = 3; i < 2 + siop_cmd->cmd_tables->msg_in[1];
843 i++)
844 printf(" 0x%x",
845 siop_cmd->cmd_tables->msg_in[i]);
846 printf("\n");
847 }
848 #endif
849 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_WDTR) {
850 switch (siop_wdtr_neg(&siop_cmd->cmd_c)) {
851 case SIOP_NEG_MSGOUT:
852 siop_update_scntl3(sc,
853 siop_cmd->cmd_c.siop_target);
854 siop_table_sync(siop_cmd,
855 BUS_DMASYNC_PREREAD |
856 BUS_DMASYNC_PREWRITE);
857 CALL_SCRIPT(Ent_send_msgout);
858 return(1);
859 case SIOP_NEG_ACK:
860 siop_update_scntl3(sc,
861 siop_cmd->cmd_c.siop_target);
862 CALL_SCRIPT(Ent_msgin_ack);
863 return(1);
864 default:
865 panic("invalid retval from "
866 "siop_wdtr_neg()");
867 }
868 return(1);
869 }
870 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_SDTR) {
871 switch (siop_sdtr_neg(&siop_cmd->cmd_c)) {
872 case SIOP_NEG_MSGOUT:
873 siop_update_scntl3(sc,
874 siop_cmd->cmd_c.siop_target);
875 siop_table_sync(siop_cmd,
876 BUS_DMASYNC_PREREAD |
877 BUS_DMASYNC_PREWRITE);
878 CALL_SCRIPT(Ent_send_msgout);
879 return(1);
880 case SIOP_NEG_ACK:
881 siop_update_scntl3(sc,
882 siop_cmd->cmd_c.siop_target);
883 CALL_SCRIPT(Ent_msgin_ack);
884 return(1);
885 default:
886 panic("invalid retval from "
887 "siop_sdtr_neg()");
888 }
889 return(1);
890 }
891 if (siop_cmd->cmd_tables->msg_in[2] == MSG_EXT_PPR) {
892 switch (siop_ppr_neg(&siop_cmd->cmd_c)) {
893 case SIOP_NEG_MSGOUT:
894 siop_update_scntl3(sc,
895 siop_cmd->cmd_c.siop_target);
896 siop_table_sync(siop_cmd,
897 BUS_DMASYNC_PREREAD |
898 BUS_DMASYNC_PREWRITE);
899 CALL_SCRIPT(Ent_send_msgout);
900 return(1);
901 case SIOP_NEG_ACK:
902 siop_update_scntl3(sc,
903 siop_cmd->cmd_c.siop_target);
904 CALL_SCRIPT(Ent_msgin_ack);
905 return(1);
906 default:
907 panic("invalid retval from "
908 "siop_wdtr_neg()");
909 }
910 return(1);
911 }
912 /* send a message reject */
913 siop_cmd->cmd_tables->msg_out[0] = MSG_MESSAGE_REJECT;
914 siop_cmd->cmd_tables->t_msgout.count = htole32(1);
915 siop_table_sync(siop_cmd,
916 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
917 CALL_SCRIPT(Ent_send_msgout);
918 return 1;
919 case A_int_disc:
920 INCSTAT(siop_stat_intr_sdp);
921 offset = bus_space_read_1(sc->sc_c.sc_rt,
922 sc->sc_c.sc_rh, SIOP_SCRATCHA + 1);
923 #ifdef SIOP_DEBUG_DR
924 printf("disconnect offset %d\n", offset);
925 #endif
926 if (offset > SIOP_NSG) {
927 printf("%s: bad offset for disconnect (%d)\n",
928 sc->sc_c.sc_dev.dv_xname, offset);
929 goto reset;
930 }
931 /*
932 * offset == SIOP_NSG may be a valid condition if
933 * we get a sdp when the xfer is done.
934 * Don't call bcopy in this case.
935 */
936 if (offset < SIOP_NSG) {
937 bcopy(&siop_cmd->cmd_tables->data[offset],
938 &siop_cmd->cmd_tables->data[0],
939 (SIOP_NSG - offset) * sizeof(scr_table_t));
940 siop_table_sync(siop_cmd,
941 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
942 }
943 /* check if we can put some command in scheduler */
944 siop_start(sc);
945 CALL_SCRIPT(Ent_script_sched);
946 return 1;
947 case A_int_resfail:
948 printf("reselect failed\n");
949 /* check if we can put some command in scheduler */
950 siop_start(sc);
951 CALL_SCRIPT(Ent_script_sched);
952 return 1;
953 case A_int_done:
954 if (xs == NULL) {
955 printf("%s: done without command, DSA=0x%lx\n",
956 sc->sc_c.sc_dev.dv_xname,
957 (u_long)siop_cmd->cmd_c.dsa);
958 siop_cmd->cmd_c.status = CMDST_FREE;
959 siop_start(sc);
960 CALL_SCRIPT(Ent_script_sched);
961 return 1;
962 }
963 #ifdef SIOP_DEBUG_INTR
964 printf("done, DSA=0x%lx target id 0x%x last msg "
965 "in=0x%x status=0x%x\n", (u_long)siop_cmd->cmd_c.dsa,
966 letoh32(siop_cmd->cmd_tables->id),
967 siop_cmd->cmd_tables->msg_in[0],
968 letoh32(siop_cmd->cmd_tables->status));
969 #endif
970 INCSTAT(siop_stat_intr_done);
971 if (siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
972 siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
973 else
974 siop_cmd->cmd_c.status = CMDST_DONE;
975 goto end;
976 default:
977 printf("unknown irqcode %x\n", irqcode);
978 if (xs) {
979 xs->error = XS_SELTIMEOUT;
980 goto end;
981 }
982 goto reset;
983 }
984 return 1;
985 }
986 /* We can get here if ISTAT_DIP and DSTAT_DFE are the only bits set. */
987 /* But that *SHOULDN'T* happen. It does on powerpc (at least). */
988 printf("%s: siop_intr() - we should not be here!\n"
989 " istat = 0x%x, dstat = 0x%x, sist = 0x%x, sstat1 = 0x%x\n"
990 " need_reset = %x, irqcode = %x, siop_cmd %s\n",
991 sc->sc_c.sc_dev.dv_xname,
992 istat, dstat, sist, sstat1, need_reset, irqcode,
993 (siop_cmd == NULL) ? "== NULL" : "!= NULL");
994 goto reset; /* Where we should have gone in the first place! */
995 end:
996 /*
997 * restart the script now if command completed properly
998 * Otherwise wait for siop_scsicmd_end(), we may need to cleanup the
999 * queue
1000 */
1001 xs->status = letoh32(siop_cmd->cmd_tables->status);
1002 if (xs->status == SCSI_OK)
1003 CALL_SCRIPT(Ent_script_sched);
1004 else
1005 restart = 1;
1006 siop_lun->siop_tag[tag].active = NULL;
1007 siop_scsicmd_end(siop_cmd);
1008 if (freetarget && siop_target->target_c.status == TARST_PROBING)
1009 siop_del_dev(sc, target, lun);
1010 siop_start(sc);
1011 if (restart)
1012 CALL_SCRIPT(Ent_script_sched);
1013 return 1;
1014 }
1015
1016 void
siop_scsicmd_end(siop_cmd)1017 siop_scsicmd_end(siop_cmd)
1018 struct siop_cmd *siop_cmd;
1019 {
1020 struct scsi_xfer *xs = siop_cmd->cmd_c.xs;
1021 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1022 struct siop_lun *siop_lun =
1023 ((struct siop_target*)sc->sc_c.targets[xs->sc_link->target])->siop_lun[xs->sc_link->lun];
1024
1025 /*
1026 * If the command is re-queued (SENSE, QUEUE_FULL) it
1027 * must get a new timeout, so delete existing timeout now.
1028 */
1029 timeout_del(&siop_cmd->cmd_c.xs->stimeout);
1030
1031 switch(xs->status) {
1032 case SCSI_OK:
1033 xs->error = (siop_cmd->cmd_c.status == CMDST_DONE) ?
1034 XS_NOERROR : XS_SENSE;
1035 break;
1036 case SCSI_BUSY:
1037 xs->error = XS_BUSY;
1038 break;
1039 case SCSI_CHECK:
1040 if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
1041 /* request sense on a request sense ? */
1042 printf("request sense failed\n");
1043 xs->error = XS_DRIVER_STUFFUP;
1044 } else {
1045 siop_cmd->cmd_c.status = CMDST_SENSE;
1046 }
1047 break;
1048 case SCSI_QUEUE_FULL:
1049 /*
1050 * Device didn't queue the command. We have to retry
1051 * it. We insert it into the urgent list, hoping to
1052 * preserve order. But unfortunately, commands already
1053 * in the scheduler may be accepted before this one.
1054 * Also remember the condition, to avoid starting new
1055 * commands for this device before one is done.
1056 */
1057 INCSTAT(siop_stat_intr_qfull);
1058 #ifdef SIOP_DEBUG
1059 printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_c.sc_dev.dv_xname,
1060 xs->sc_link->target,
1061 xs->sc_link->lun, siop_cmd->cmd_c.tag);
1062 #endif
1063 siop_lun->lun_flags |= SIOP_LUNF_FULL;
1064 siop_cmd->cmd_c.status = CMDST_READY;
1065 siop_setuptables(&siop_cmd->cmd_c);
1066 siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1067 TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next);
1068 return;
1069 case SCSI_SIOP_NOCHECK:
1070 /*
1071 * don't check status, xs->error is already valid
1072 */
1073 break;
1074 case SCSI_SIOP_NOSTATUS:
1075 /*
1076 * the status byte was not updated, cmd was
1077 * aborted
1078 */
1079 xs->error = XS_SELTIMEOUT;
1080 break;
1081 default:
1082 xs->error = XS_DRIVER_STUFFUP;
1083 }
1084 if (siop_cmd->cmd_c.status != CMDST_SENSE_DONE &&
1085 xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1086 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data, 0,
1087 siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1088 (xs->flags & SCSI_DATA_IN) ?
1089 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1090 bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
1091 }
1092 if (siop_cmd->cmd_c.status == CMDST_SENSE) {
1093 /* issue a request sense for this target */
1094 struct scsi_sense *cmd = (struct scsi_sense *)&siop_cmd->cmd_c.siop_tables->xscmd;
1095 int error;
1096 bzero(cmd, sizeof(*cmd));
1097 siop_cmd->cmd_c.siop_tables->cmd.count =
1098 htole32(sizeof(struct scsi_sense));
1099 cmd->opcode = REQUEST_SENSE;
1100 cmd->byte2 = xs->sc_link->lun << 5;
1101 cmd->unused[0] = cmd->unused[1] = 0;
1102 cmd->length = sizeof(struct scsi_sense_data);
1103 cmd->control = 0;
1104 siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
1105 error = bus_dmamap_load(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1106 &xs->sense, sizeof(struct scsi_sense_data),
1107 NULL, BUS_DMA_NOWAIT);
1108 if (error) {
1109 printf("%s: unable to load data DMA map "
1110 "(for SENSE): %d\n",
1111 sc->sc_c.sc_dev.dv_xname, error);
1112 xs->error = XS_DRIVER_STUFFUP;
1113 goto out;
1114 }
1115 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1116 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1117 BUS_DMASYNC_PREREAD);
1118
1119 siop_setuptables(&siop_cmd->cmd_c);
1120 siop_table_sync(siop_cmd, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1121 /* arrange for the cmd to be handled now */
1122 TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next);
1123 return;
1124 } else if (siop_cmd->cmd_c.status == CMDST_SENSE_DONE) {
1125 bus_dmamap_sync(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data,
1126 0, siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1127 BUS_DMASYNC_POSTREAD);
1128 bus_dmamap_unload(sc->sc_c.sc_dmat, siop_cmd->cmd_c.dmamap_data);
1129 }
1130 out:
1131 siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
1132 xs->flags |= ITSDONE;
1133 siop_cmd->cmd_c.status = CMDST_FREE;
1134 TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
1135 xs->resid = 0;
1136 scsi_done(xs);
1137 }
1138
1139 /*
1140 * handle a rejected queue tag message: the command will run untagged,
1141 * has to adjust the reselect script.
1142 */
1143 int
siop_handle_qtag_reject(siop_cmd)1144 siop_handle_qtag_reject(siop_cmd)
1145 struct siop_cmd *siop_cmd;
1146 {
1147 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1148 int target = siop_cmd->cmd_c.xs->sc_link->target;
1149 int lun = siop_cmd->cmd_c.xs->sc_link->lun;
1150 int tag = siop_cmd->cmd_tables->msg_out[2];
1151 struct siop_lun *siop_lun =
1152 ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
1153
1154 #ifdef SIOP_DEBUG
1155 printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
1156 sc->sc_c.sc_dev.dv_xname, target, lun, tag, siop_cmd->cmd_c.tag,
1157 siop_cmd->cmd_c.status);
1158 #endif
1159
1160 if (siop_lun->siop_tag[0].active != NULL) {
1161 printf("%s: untagged command already running for target %d "
1162 "lun %d (status %d)\n", sc->sc_c.sc_dev.dv_xname,
1163 target, lun, siop_lun->siop_tag[0].active->cmd_c.status);
1164 return -1;
1165 }
1166 /* clear tag slot */
1167 siop_lun->siop_tag[tag].active = NULL;
1168 /* add command to non-tagged slot */
1169 siop_lun->siop_tag[0].active = siop_cmd;
1170 siop_cmd->cmd_c.tag = 0;
1171 /* adjust reselect script if there is one */
1172 if (siop_lun->siop_tag[0].reseloff > 0) {
1173 siop_script_write(sc,
1174 siop_lun->siop_tag[0].reseloff + 1,
1175 siop_cmd->cmd_c.dsa + sizeof(struct siop_common_xfer) +
1176 Ent_ldsa_reload_dsa);
1177 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
1178 }
1179 return 0;
1180 }
1181
1182 /*
1183 * handle a bus reset: reset chip, unqueue all active commands, free all
1184 * target struct and report lossage to upper layer.
1185 * As the upper layer may requeue immediatly we have to first store
1186 * all active commands in a temporary queue.
1187 */
1188 void
siop_handle_reset(sc)1189 siop_handle_reset(sc)
1190 struct siop_softc *sc;
1191 {
1192 struct cmd_list reset_list;
1193 struct siop_cmd *siop_cmd, *next_siop_cmd;
1194 struct siop_lun *siop_lun;
1195 int target, lun, tag;
1196 /*
1197 * scsi bus reset. reset the chip and restart
1198 * the queue. Need to clean up all active commands
1199 */
1200 printf("%s: scsi bus reset\n", sc->sc_c.sc_dev.dv_xname);
1201 /* stop, reset and restart the chip */
1202 siop_reset(sc);
1203 TAILQ_INIT(&reset_list);
1204 /*
1205 * Process all commands: first commands being executed
1206 */
1207 for (target = 0; target < sc->sc_c.sc_link.adapter_buswidth;
1208 target++) {
1209 if (sc->sc_c.targets[target] == NULL)
1210 continue;
1211 for (lun = 0; lun < 8; lun++) {
1212 struct siop_target *siop_target =
1213 (struct siop_target *)sc->sc_c.targets[target];
1214 siop_lun = siop_target->siop_lun[lun];
1215 if (siop_lun == NULL)
1216 continue;
1217 siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
1218 for (tag = 0; tag <
1219 ((sc->sc_c.targets[target]->flags & TARF_TAG) ?
1220 SIOP_NTAG : 1);
1221 tag++) {
1222 siop_cmd = siop_lun->siop_tag[tag].active;
1223 if (siop_cmd == NULL)
1224 continue;
1225 siop_lun->siop_tag[tag].active = NULL;
1226 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1227 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1228 printf("cmd %p (tag %d) added to reset list\n",
1229 siop_cmd, tag);
1230 }
1231 }
1232 if (sc->sc_c.targets[target]->status != TARST_PROBING) {
1233 sc->sc_c.targets[target]->status = TARST_ASYNC;
1234 sc->sc_c.targets[target]->flags &= ~TARF_ISWIDE;
1235 sc->sc_c.targets[target]->period =
1236 sc->sc_c.targets[target]->offset = 0;
1237 siop_update_xfer_mode(&sc->sc_c, target);
1238 }
1239 }
1240 /* Next commands from the urgent list */
1241 for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;
1242 siop_cmd = next_siop_cmd) {
1243 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1244 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1245 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1246 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1247 printf("cmd %p added to reset list from urgent list\n",
1248 siop_cmd);
1249 }
1250 /* Then commands waiting in the input list. */
1251 for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL;
1252 siop_cmd = next_siop_cmd) {
1253 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1254 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1255 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1256 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1257 printf("cmd %p added to reset list from ready list\n",
1258 siop_cmd);
1259 }
1260
1261 for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;
1262 siop_cmd = next_siop_cmd) {
1263 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1264 siop_cmd->cmd_c.flags &= ~CMDFL_TAG;
1265 siop_cmd->cmd_c.xs->error =
1266 (siop_cmd->cmd_c.flags & CMDFL_TIMEOUT)
1267 ? XS_TIMEOUT : XS_RESET;
1268 siop_cmd->cmd_c.xs->status = SCSI_SIOP_NOCHECK;
1269 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1270 printf("cmd %p (status %d) reset",
1271 siop_cmd, siop_cmd->cmd_c.status);
1272 if (siop_cmd->cmd_c.status == CMDST_SENSE ||
1273 siop_cmd->cmd_c.status == CMDST_SENSE_ACTIVE)
1274 siop_cmd->cmd_c.status = CMDST_SENSE_DONE;
1275 else
1276 siop_cmd->cmd_c.status = CMDST_DONE;
1277 printf(" with status %d, xs->error %d\n",
1278 siop_cmd->cmd_c.status, siop_cmd->cmd_c.xs->error);
1279 TAILQ_REMOVE(&reset_list, siop_cmd, next);
1280 siop_scsicmd_end(siop_cmd);
1281 }
1282 }
1283
1284 int
siop_scsicmd(xs)1285 siop_scsicmd(xs)
1286 struct scsi_xfer *xs;
1287 {
1288 struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc;
1289 struct siop_cmd *siop_cmd;
1290 struct siop_target *siop_target;
1291 int s, error, i, j;
1292 const int target = xs->sc_link->target;
1293 const int lun = xs->sc_link->lun;
1294
1295 s = splbio();
1296 #ifdef SIOP_DEBUG_SCHED
1297 printf("starting cmd for %d:%d\n", target, lun);
1298 #endif
1299 siop_cmd = TAILQ_FIRST(&sc->free_list);
1300 if (siop_cmd == NULL) {
1301 xs->error = XS_DRIVER_STUFFUP;
1302 splx(s);
1303 return(TRY_AGAIN_LATER);
1304 }
1305 TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
1306
1307 /* Always reset xs->stimeout, lest we timeout_del() with trash */
1308 timeout_set(&xs->stimeout, siop_timeout, siop_cmd);
1309
1310 #ifdef DIAGNOSTIC
1311 if (siop_cmd->cmd_c.status != CMDST_FREE)
1312 panic("siop_scsicmd: new cmd not free");
1313 #endif
1314 siop_target = (struct siop_target*)sc->sc_c.targets[target];
1315 if (siop_target == NULL) {
1316 #ifdef SIOP_DEBUG
1317 printf("%s: alloc siop_target for target %d\n",
1318 sc->sc_c.sc_dev.dv_xname, target);
1319 #endif
1320 sc->sc_c.targets[target] =
1321 malloc(sizeof(struct siop_target),
1322 M_DEVBUF, M_NOWAIT);
1323 if (sc->sc_c.targets[target] == NULL) {
1324 printf("%s: can't malloc memory for "
1325 "target %d\n", sc->sc_c.sc_dev.dv_xname,
1326 target);
1327 xs->error = XS_DRIVER_STUFFUP;
1328 splx(s);
1329 return(TRY_AGAIN_LATER);
1330 }
1331 bzero(sc->sc_c.targets[target], sizeof(struct siop_target));
1332 siop_target =
1333 (struct siop_target*)sc->sc_c.targets[target];
1334 siop_target->target_c.status = TARST_PROBING;
1335 siop_target->target_c.flags = 0;
1336 siop_target->target_c.id =
1337 sc->sc_c.clock_div << 24; /* scntl3 */
1338 siop_target->target_c.id |= target << 16; /* id */
1339 /* siop_target->target_c.id |= 0x0 << 8; scxfer is 0 */
1340
1341 /* get a lun switch script */
1342 siop_target->lunsw = siop_get_lunsw(sc);
1343 if (siop_target->lunsw == NULL) {
1344 printf("%s: can't alloc lunsw for target %d\n",
1345 sc->sc_c.sc_dev.dv_xname, target);
1346 xs->error = XS_DRIVER_STUFFUP;
1347 splx(s);
1348 return(TRY_AGAIN_LATER);
1349 }
1350 for (i=0; i < 8; i++)
1351 siop_target->siop_lun[i] = NULL;
1352 siop_add_reselsw(sc, target);
1353 }
1354 if (siop_target->siop_lun[lun] == NULL) {
1355 siop_target->siop_lun[lun] =
1356 malloc(sizeof(struct siop_lun), M_DEVBUF,
1357 M_NOWAIT);
1358 if (siop_target->siop_lun[lun] == NULL) {
1359 printf("%s: can't alloc siop_lun for "
1360 "target %d lun %d\n",
1361 sc->sc_c.sc_dev.dv_xname, target, lun);
1362 xs->error = XS_DRIVER_STUFFUP;
1363 splx(s);
1364 return(TRY_AGAIN_LATER);
1365 }
1366 bzero(siop_target->siop_lun[lun], sizeof(struct siop_lun));
1367 }
1368 siop_cmd->cmd_c.siop_target = sc->sc_c.targets[target];
1369 siop_cmd->cmd_c.xs = xs;
1370 siop_cmd->cmd_c.flags = 0;
1371 siop_cmd->cmd_c.status = CMDST_READY;
1372
1373 bzero(&siop_cmd->cmd_c.siop_tables->xscmd,
1374 sizeof(siop_cmd->cmd_c.siop_tables->xscmd));
1375 bcopy(xs->cmd, &siop_cmd->cmd_c.siop_tables->xscmd, xs->cmdlen);
1376 siop_cmd->cmd_c.siop_tables->cmd.count = htole32(xs->cmdlen);
1377
1378 /* load the DMA maps */
1379 if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
1380 error = bus_dmamap_load(sc->sc_c.sc_dmat,
1381 siop_cmd->cmd_c.dmamap_data, xs->data, xs->datalen,
1382 NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
1383 ((xs->flags & SCSI_DATA_IN) ?
1384 BUS_DMA_READ : BUS_DMA_WRITE));
1385 if (error) {
1386 printf("%s: unable to load data DMA map: %d\n",
1387 sc->sc_c.sc_dev.dv_xname, error);
1388 xs->error = XS_DRIVER_STUFFUP;
1389 splx(s);
1390 return(TRY_AGAIN_LATER);
1391 }
1392 bus_dmamap_sync(sc->sc_c.sc_dmat,
1393 siop_cmd->cmd_c.dmamap_data, 0,
1394 siop_cmd->cmd_c.dmamap_data->dm_mapsize,
1395 (xs->flags & SCSI_DATA_IN) ?
1396 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1397 }
1398
1399 siop_setuptables(&siop_cmd->cmd_c);
1400 siop_table_sync(siop_cmd,
1401 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1402
1403 TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);
1404
1405 siop_start(sc);
1406 if ((xs->flags & SCSI_POLL) == 0) {
1407 splx(s);
1408 return (SUCCESSFULLY_QUEUED);
1409 }
1410
1411 /* Poll for command completion. */
1412 for(i = xs->timeout; i > 0; i--) {
1413 siop_intr(sc);
1414 if ((xs->flags & ITSDONE) == 0) {
1415 delay(1000);
1416 continue;
1417 }
1418 if (xs->cmd->opcode == INQUIRY && xs->error == XS_NOERROR) {
1419 struct scsi_inquiry_data *inqbuf =
1420 (struct scsi_inquiry_data *)xs->data;
1421 if ((inqbuf->device & SID_QUAL) == SID_QUAL_BAD_LU)
1422 break;
1423 /*
1424 * Allocate cbd's to hold maximum openings worth of
1425 * commands. Do this now because doing it dynamically in
1426 * siop_startcmd may cause calls to bus_dma* functions
1427 * in interrupt context.
1428 */
1429 for (j = 0; j < SIOP_NTAG; j += SIOP_NCMDPB)
1430 siop_morecbd(sc);
1431 if (sc->sc_c.targets[target]->status == TARST_PROBING)
1432 sc->sc_c.targets[target]->status = TARST_ASYNC;
1433
1434 /*
1435 * Set TARF_DT here because if it is turned off during
1436 * PPR, it must STAY off!
1437 */
1438 if ((lun == 0) && (sc->sc_c.features & SF_BUS_ULTRA3))
1439 sc->sc_c.targets[target]->flags |= TARF_DT;
1440 /*
1441 * Can't do lun 0 here, because flags are not set yet.
1442 * But have to do other lun's here because they never go
1443 * through TARST_ASYNC.
1444 */
1445 if (lun > 0)
1446 siop_add_dev(sc, target, lun);
1447 }
1448 break;
1449 }
1450 if (i == 0) {
1451 siop_timeout(siop_cmd);
1452 while ((xs->flags & ITSDONE) == 0)
1453 siop_intr(sc);
1454 }
1455
1456 splx(s);
1457 return (COMPLETE);
1458 }
1459
1460 void
siop_start(sc)1461 siop_start(sc)
1462 struct siop_softc *sc;
1463 {
1464 struct siop_cmd *siop_cmd, *next_siop_cmd;
1465 struct siop_lun *siop_lun;
1466 struct siop_xfer *siop_xfer;
1467 u_int32_t dsa;
1468 int timeout;
1469 int target, lun, tag, slot;
1470 int newcmd = 0;
1471 int doingready = 0;
1472
1473 /*
1474 * first make sure to read valid data
1475 */
1476 siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1477
1478 /*
1479 * The queue management here is a bit tricky: the script always looks
1480 * at the slot from first to last, so if we always use the first
1481 * free slot commands can stay at the tail of the queue ~forever.
1482 * The algorithm used here is to restart from the head when we know
1483 * that the queue is empty, and only add commands after the last one.
1484 * When we're at the end of the queue wait for the script to clear it.
1485 * The best thing to do here would be to implement a circular queue,
1486 * but using only 53c720 features this can be "interesting".
1487 * A mid-way solution could be to implement 2 queues and swap orders.
1488 */
1489 slot = sc->sc_currschedslot;
1490 /*
1491 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is
1492 * free. As this is the last used slot, all previous slots are free,
1493 * we can restart from 1.
1494 * slot 0 is reserved for request sense commands.
1495 */
1496 if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) ==
1497 0x80000000) {
1498 slot = sc->sc_currschedslot = 1;
1499 } else {
1500 slot++;
1501 }
1502 /* first handle commands from the urgent list */
1503 siop_cmd = TAILQ_FIRST(&sc->urgent_list);
1504 again:
1505 for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) {
1506 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1507 #ifdef DIAGNOSTIC
1508 if (siop_cmd->cmd_c.status != CMDST_READY &&
1509 siop_cmd->cmd_c.status != CMDST_SENSE)
1510 panic("siop: non-ready cmd in ready list");
1511 #endif
1512 target = siop_cmd->cmd_c.xs->sc_link->target;
1513 lun = siop_cmd->cmd_c.xs->sc_link->lun;
1514 siop_lun =
1515 ((struct siop_target*)sc->sc_c.targets[target])->siop_lun[lun];
1516 /* if non-tagged command active, wait */
1517 if (siop_lun->siop_tag[0].active != NULL)
1518 continue;
1519 /*
1520 * if we're in a queue full condition don't start a new
1521 * command, unless it's a request sense
1522 */
1523 if ((siop_lun->lun_flags & SIOP_LUNF_FULL) &&
1524 siop_cmd->cmd_c.status == CMDST_READY)
1525 continue;
1526 /* find a free tag if needed */
1527 if (siop_cmd->cmd_c.flags & CMDFL_TAG) {
1528 for (tag = 1; tag < SIOP_NTAG; tag++) {
1529 if (siop_lun->siop_tag[tag].active == NULL)
1530 break;
1531 }
1532 if (tag == SIOP_NTAG) /* no free tag */
1533 continue;
1534 } else {
1535 tag = 0;
1536 }
1537 siop_cmd->cmd_c.tag = tag;
1538 /*
1539 * find a free scheduler slot and load it. If it's a request
1540 * sense we need to use slot 0.
1541 */
1542 if (siop_cmd->cmd_c.status != CMDST_SENSE) {
1543 for (; slot < SIOP_NSLOTS; slot++) {
1544 /*
1545 * If cmd if 0x80000000 the slot is free
1546 */
1547 if (siop_script_read(sc,
1548 (Ent_script_sched_slot0 / 4) + slot * 2) ==
1549 0x80000000)
1550 break;
1551 }
1552 /* no more free slots, no need to continue */
1553 if (slot == SIOP_NSLOTS) {
1554 goto end;
1555 }
1556 } else {
1557 slot = 0;
1558 if (siop_script_read(sc, Ent_script_sched_slot0 / 4)
1559 != 0x80000000)
1560 goto end;
1561 }
1562
1563 #ifdef SIOP_DEBUG_SCHED
1564 printf("using slot %d for DSA 0x%lx\n", slot,
1565 (u_long)siop_cmd->cmd_c.dsa);
1566 #endif
1567 /* Ok, we can add the tag message */
1568 if (tag > 0) {
1569 #ifdef DIAGNOSTIC
1570 int msgcount =
1571 letoh32(siop_cmd->cmd_tables->t_msgout.count);
1572 if (msgcount != 1)
1573 printf("%s:%d:%d: tag %d with msgcount %d\n",
1574 sc->sc_c.sc_dev.dv_xname, target, lun, tag,
1575 msgcount);
1576 #endif
1577 if (siop_cmd->cmd_c.xs->bp != NULL &&
1578 (siop_cmd->cmd_c.xs->bp->b_flags & B_ASYNC))
1579 siop_cmd->cmd_tables->msg_out[1] =
1580 MSG_SIMPLE_Q_TAG;
1581 else
1582 siop_cmd->cmd_tables->msg_out[1] =
1583 MSG_ORDERED_Q_TAG;
1584 siop_cmd->cmd_tables->msg_out[2] = tag;
1585 siop_cmd->cmd_tables->t_msgout.count = htole32(3);
1586 }
1587 /* note that we started a new command */
1588 newcmd = 1;
1589 /* mark command as active */
1590 if (siop_cmd->cmd_c.status == CMDST_READY) {
1591 siop_cmd->cmd_c.status = CMDST_ACTIVE;
1592 } else if (siop_cmd->cmd_c.status == CMDST_SENSE) {
1593 siop_cmd->cmd_c.status = CMDST_SENSE_ACTIVE;
1594 } else
1595 panic("siop_start: bad status");
1596 if (doingready)
1597 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1598 else
1599 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1600 siop_lun->siop_tag[tag].active = siop_cmd;
1601 /* patch scripts with DSA addr */
1602 dsa = siop_cmd->cmd_c.dsa;
1603 /* first reselect switch, if we have an entry */
1604 if (siop_lun->siop_tag[tag].reseloff > 0)
1605 siop_script_write(sc,
1606 siop_lun->siop_tag[tag].reseloff + 1,
1607 dsa + sizeof(struct siop_common_xfer) +
1608 Ent_ldsa_reload_dsa);
1609 /* CMD script: MOVE MEMORY addr */
1610 siop_xfer = (struct siop_xfer*)siop_cmd->cmd_tables;
1611 siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
1612 htole32(sc->sc_c.sc_scriptaddr + Ent_script_sched_slot0 + slot * 8);
1613 siop_table_sync(siop_cmd, BUS_DMASYNC_PREWRITE);
1614 /* scheduler slot: JUMP ldsa_select */
1615 siop_script_write(sc,
1616 (Ent_script_sched_slot0 / 4) + slot * 2 + 1,
1617 dsa + sizeof(struct siop_common_xfer) + Ent_ldsa_select);
1618 /* handle timeout */
1619 if (siop_cmd->cmd_c.status == CMDST_ACTIVE) {
1620 if ((siop_cmd->cmd_c.xs->flags & SCSI_POLL) == 0) {
1621 /* start expire timer */
1622 timeout = (u_int64_t) siop_cmd->cmd_c.xs->timeout *
1623 (u_int64_t)hz / 1000;
1624 if (timeout == 0)
1625 timeout = 1;
1626 timeout_add(&siop_cmd->cmd_c.xs->stimeout, timeout);
1627 }
1628 }
1629 /*
1630 * Change JUMP cmd so that this slot will be handled
1631 */
1632 siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,
1633 0x80080000);
1634 /* if we're using the request sense slot, stop here */
1635 if (slot == 0)
1636 goto end;
1637 sc->sc_currschedslot = slot;
1638 slot++;
1639 }
1640 if (doingready == 0) {
1641 /* now process ready list */
1642 doingready = 1;
1643 siop_cmd = TAILQ_FIRST(&sc->ready_list);
1644 goto again;
1645 }
1646
1647 end:
1648 /* if nothing changed no need to flush cache and wakeup script */
1649 if (newcmd == 0)
1650 return;
1651 /* make sure SCRIPT processor will read valid data */
1652 siop_script_sync(sc,BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1653 /* Signal script it has some work to do */
1654 bus_space_write_1(sc->sc_c.sc_rt, sc->sc_c.sc_rh,
1655 SIOP_ISTAT, ISTAT_SIGP);
1656 /* and wait for IRQ */
1657 return;
1658 }
1659
1660 void
siop_timeout(v)1661 siop_timeout(v)
1662 void *v;
1663 {
1664 struct siop_cmd *siop_cmd = v;
1665 struct siop_softc *sc = (struct siop_softc *)siop_cmd->cmd_c.siop_sc;
1666 int s;
1667
1668 /* deactivate callout */
1669 timeout_del(&siop_cmd->cmd_c.xs->stimeout);
1670
1671 sc_print_addr(siop_cmd->cmd_c.xs->sc_link);
1672 printf("timeout on SCSI command 0x%x\n",
1673 siop_cmd->cmd_c.xs->cmd->opcode);
1674
1675 s = splbio();
1676 /* reset the scsi bus */
1677 siop_resetbus(&sc->sc_c);
1678 siop_cmd->cmd_c.flags |= CMDFL_TIMEOUT;
1679 siop_handle_reset(sc);
1680 splx(s);
1681
1682 return;
1683 }
1684
1685 void
siop_dump_script(sc)1686 siop_dump_script(sc)
1687 struct siop_softc *sc;
1688 {
1689 int i;
1690 for (i = 0; i < PAGE_SIZE / 4; i += 2) {
1691 printf("0x%04x: 0x%08x 0x%08x", i * 4,
1692 letoh32(sc->sc_c.sc_script[i]),
1693 letoh32(sc->sc_c.sc_script[i+1]));
1694 if ((letoh32(sc->sc_c.sc_script[i]) & 0xe0000000) ==
1695 0xc0000000) {
1696 i++;
1697 printf(" 0x%08x", letoh32(sc->sc_c.sc_script[i+1]));
1698 }
1699 printf("\n");
1700 }
1701 }
1702
1703 void
siop_morecbd(sc)1704 siop_morecbd(sc)
1705 struct siop_softc *sc;
1706 {
1707 int error, i, j, s;
1708 bus_dma_segment_t seg;
1709 int rseg;
1710 struct siop_cbd *newcbd;
1711 struct siop_xfer *xfer;
1712 bus_addr_t dsa;
1713 u_int32_t *scr;
1714
1715 /* allocate a new list head */
1716 newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT);
1717 if (newcbd == NULL) {
1718 printf("%s: can't allocate memory for command descriptors "
1719 "head\n", sc->sc_c.sc_dev.dv_xname);
1720 return;
1721 }
1722 bzero(newcbd, sizeof(struct siop_cbd));
1723
1724 /* allocate cmd list */
1725 newcbd->cmds = malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB,
1726 M_DEVBUF, M_NOWAIT);
1727 if (newcbd->cmds == NULL) {
1728 printf("%s: can't allocate memory for command descriptors\n",
1729 sc->sc_c.sc_dev.dv_xname);
1730 goto bad3;
1731 }
1732 bzero(newcbd->cmds, sizeof(struct siop_cmd) * SIOP_NCMDPB);
1733 error = bus_dmamem_alloc(sc->sc_c.sc_dmat, PAGE_SIZE, PAGE_SIZE, 0, &seg,
1734 1, &rseg, BUS_DMA_NOWAIT);
1735 if (error) {
1736 printf("%s: unable to allocate cbd DMA memory, error = %d\n",
1737 sc->sc_c.sc_dev.dv_xname, error);
1738 goto bad2;
1739 }
1740 error = bus_dmamem_map(sc->sc_c.sc_dmat, &seg, rseg, PAGE_SIZE,
1741 (caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1742 if (error) {
1743 printf("%s: unable to map cbd DMA memory, error = %d\n",
1744 sc->sc_c.sc_dev.dv_xname, error);
1745 goto bad2;
1746 }
1747 error = bus_dmamap_create(sc->sc_c.sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
1748 BUS_DMA_NOWAIT, &newcbd->xferdma);
1749 if (error) {
1750 printf("%s: unable to create cbd DMA map, error = %d\n",
1751 sc->sc_c.sc_dev.dv_xname, error);
1752 goto bad1;
1753 }
1754 error = bus_dmamap_load(sc->sc_c.sc_dmat, newcbd->xferdma, newcbd->xfers,
1755 PAGE_SIZE, NULL, BUS_DMA_NOWAIT);
1756 if (error) {
1757 printf("%s: unable to load cbd DMA map, error = %d\n",
1758 sc->sc_c.sc_dev.dv_xname, error);
1759 goto bad0;
1760 }
1761 #ifdef SIOP_DEBUG
1762 printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_c.sc_dev.dv_xname,
1763 (unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
1764 #endif
1765 for (i = 0; i < SIOP_NCMDPB; i++) {
1766 error = bus_dmamap_create(sc->sc_c.sc_dmat, MAXPHYS, SIOP_NSG,
1767 MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1768 &newcbd->cmds[i].cmd_c.dmamap_data);
1769 if (error) {
1770 printf("%s: unable to create data DMA map for cbd: "
1771 "error %d\n",
1772 sc->sc_c.sc_dev.dv_xname, error);
1773 goto bad0;
1774 }
1775 }
1776
1777 /* Use two loops since bailing out above releases allocated memory */
1778 for (i = 0; i < SIOP_NCMDPB; i++) {
1779 newcbd->cmds[i].cmd_c.siop_sc = &sc->sc_c;
1780 newcbd->cmds[i].siop_cbdp = newcbd;
1781 xfer = &newcbd->xfers[i];
1782 newcbd->cmds[i].cmd_tables = (struct siop_common_xfer *)xfer;
1783 bzero(newcbd->cmds[i].cmd_tables, sizeof(struct siop_xfer));
1784 dsa = newcbd->xferdma->dm_segs[0].ds_addr +
1785 i * sizeof(struct siop_xfer);
1786 newcbd->cmds[i].cmd_c.dsa = dsa;
1787 newcbd->cmds[i].cmd_c.status = CMDST_FREE;
1788 xfer->siop_tables.t_msgout.count= htole32(1);
1789 xfer->siop_tables.t_msgout.addr = htole32(dsa);
1790 xfer->siop_tables.t_msgin.count= htole32(1);
1791 xfer->siop_tables.t_msgin.addr = htole32(dsa +
1792 offsetof(struct siop_common_xfer, msg_in));
1793 xfer->siop_tables.t_extmsgin.count= htole32(2);
1794 xfer->siop_tables.t_extmsgin.addr = htole32(dsa +
1795 offsetof(struct siop_common_xfer, msg_in) + 1);
1796 xfer->siop_tables.t_extmsgdata.addr = htole32(dsa +
1797 offsetof(struct siop_common_xfer, msg_in) + 3);
1798 xfer->siop_tables.t_status.count= htole32(1);
1799 xfer->siop_tables.t_status.addr = htole32(dsa +
1800 offsetof(struct siop_common_xfer, status));
1801 xfer->siop_tables.cmd.count= htole32(0);
1802 xfer->siop_tables.cmd.addr = htole32(dsa +
1803 offsetof(struct siop_common_xfer, xscmd));
1804 /* The select/reselect script */
1805 scr = &xfer->resel[0];
1806 for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++)
1807 scr[j] = htole32(load_dsa[j]);
1808 /*
1809 * 0x78000000 is a 'move data8 to reg'. data8 is the second
1810 * octet, reg offset is the third.
1811 */
1812 scr[Ent_rdsa0 / 4] =
1813 htole32(0x78100000 | ((dsa & 0x000000ff) << 8));
1814 scr[Ent_rdsa1 / 4] =
1815 htole32(0x78110000 | ( dsa & 0x0000ff00 ));
1816 scr[Ent_rdsa2 / 4] =
1817 htole32(0x78120000 | ((dsa & 0x00ff0000) >> 8));
1818 scr[Ent_rdsa3 / 4] =
1819 htole32(0x78130000 | ((dsa & 0xff000000) >> 16));
1820 scr[E_ldsa_abs_reselected_Used[0]] =
1821 htole32(sc->sc_c.sc_scriptaddr + Ent_reselected);
1822 scr[E_ldsa_abs_reselect_Used[0]] =
1823 htole32(sc->sc_c.sc_scriptaddr + Ent_reselect);
1824 scr[E_ldsa_abs_selected_Used[0]] =
1825 htole32(sc->sc_c.sc_scriptaddr + Ent_selected);
1826 scr[E_ldsa_abs_data_Used[0]] =
1827 htole32(dsa + sizeof(struct siop_common_xfer) +
1828 Ent_ldsa_data);
1829 /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
1830 scr[Ent_ldsa_data / 4] = htole32(0x80000000);
1831 s = splbio();
1832 TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
1833 splx(s);
1834 #ifdef SIOP_DEBUG
1835 printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
1836 letoh32(newcbd->cmds[i].cmd_tables->t_msgin.addr),
1837 letoh32(newcbd->cmds[i].cmd_tables->t_msgout.addr),
1838 letoh32(newcbd->cmds[i].cmd_tables->t_status.addr));
1839 #endif
1840 }
1841 s = splbio();
1842 TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
1843 splx(s);
1844 return;
1845 bad0:
1846 bus_dmamap_unload(sc->sc_c.sc_dmat, newcbd->xferdma);
1847 bus_dmamap_destroy(sc->sc_c.sc_dmat, newcbd->xferdma);
1848 bad1:
1849 bus_dmamem_free(sc->sc_c.sc_dmat, &seg, rseg);
1850 bad2:
1851 free(newcbd->cmds, M_DEVBUF);
1852 bad3:
1853 free(newcbd, M_DEVBUF);
1854 return;
1855 }
1856
1857 struct siop_lunsw *
siop_get_lunsw(sc)1858 siop_get_lunsw(sc)
1859 struct siop_softc *sc;
1860 {
1861 struct siop_lunsw *lunsw;
1862 int i;
1863
1864 if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >=
1865 sc->script_free_hi)
1866 return NULL;
1867 lunsw = TAILQ_FIRST(&sc->lunsw_list);
1868 if (lunsw != NULL) {
1869 #ifdef SIOP_DEBUG
1870 printf("siop_get_lunsw got lunsw at offset %d\n",
1871 lunsw->lunsw_off);
1872 #endif
1873 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
1874 return lunsw;
1875 }
1876 lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT);
1877 if (lunsw == NULL)
1878 return NULL;
1879 bzero(lunsw, sizeof(struct siop_lunsw));
1880 #ifdef SIOP_DEBUG
1881 printf("allocating lunsw at offset %d\n", sc->script_free_lo);
1882 #endif
1883 if (sc->sc_c.features & SF_CHIP_RAM) {
1884 bus_space_write_region_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
1885 sc->script_free_lo * 4, lun_switch,
1886 sizeof(lun_switch) / sizeof(lun_switch[0]));
1887 bus_space_write_4(sc->sc_c.sc_ramt, sc->sc_c.sc_ramh,
1888 (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4,
1889 sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
1890 } else {
1891 for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]);
1892 i++)
1893 sc->sc_c.sc_script[sc->script_free_lo + i] =
1894 htole32(lun_switch[i]);
1895 sc->sc_c.sc_script[
1896 sc->script_free_lo + E_abs_lunsw_return_Used[0]] =
1897 htole32(sc->sc_c.sc_scriptaddr + Ent_lunsw_return);
1898 }
1899 lunsw->lunsw_off = sc->script_free_lo;
1900 lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]);
1901 sc->script_free_lo += lunsw->lunsw_size;
1902 siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1903 return lunsw;
1904 }
1905
1906 void
siop_add_reselsw(sc,target)1907 siop_add_reselsw(sc, target)
1908 struct siop_softc *sc;
1909 int target;
1910 {
1911 int i,j;
1912 struct siop_target *siop_target;
1913 struct siop_lun *siop_lun;
1914
1915 siop_target = (struct siop_target *)sc->sc_c.targets[target];
1916 /*
1917 * add an entry to resel switch
1918 */
1919 siop_script_sync(sc, BUS_DMASYNC_POSTWRITE);
1920 for (i = 0; i < 15; i++) {
1921 siop_target->reseloff = Ent_resel_targ0 / 4 + i * 2;
1922 if ((siop_script_read(sc, siop_target->reseloff) & 0xff)
1923 == 0xff) { /* it's free */
1924 #ifdef SIOP_DEBUG
1925 printf("siop: target %d slot %d offset %d\n",
1926 target, i, siop_target->reseloff);
1927 #endif
1928 /* JUMP abs_foo, IF target | 0x80; */
1929 siop_script_write(sc, siop_target->reseloff,
1930 0x800c0080 | target);
1931 siop_script_write(sc, siop_target->reseloff + 1,
1932 sc->sc_c.sc_scriptaddr +
1933 siop_target->lunsw->lunsw_off * 4 +
1934 Ent_lun_switch_entry);
1935 break;
1936 }
1937 }
1938 if (i == 15) /* no free slot, shouldn't happen */
1939 panic("siop: resel switch full");
1940
1941 sc->sc_ntargets++;
1942 for (i = 0; i < 8; i++) {
1943 siop_lun = siop_target->siop_lun[i];
1944 if (siop_lun == NULL)
1945 continue;
1946 if (siop_lun->reseloff > 0) {
1947 siop_lun->reseloff = 0;
1948 for (j = 0; j < SIOP_NTAG; j++)
1949 siop_lun->siop_tag[j].reseloff = 0;
1950 siop_add_dev(sc, target, i);
1951 }
1952 }
1953 siop_update_scntl3(sc, sc->sc_c.targets[target]);
1954 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
1955 }
1956
1957 void
siop_update_scntl3(sc,_siop_target)1958 siop_update_scntl3(sc, _siop_target)
1959 struct siop_softc *sc;
1960 struct siop_common_target *_siop_target;
1961 {
1962 struct siop_target *siop_target = (struct siop_target *)_siop_target;
1963 /* MOVE target->id >> 24 TO SCNTL3 */
1964 siop_script_write(sc,
1965 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4),
1966 0x78030000 | ((siop_target->target_c.id >> 16) & 0x0000ff00));
1967 /* MOVE target->id >> 8 TO SXFER */
1968 siop_script_write(sc,
1969 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2,
1970 0x78050000 | (siop_target->target_c.id & 0x0000ff00));
1971 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
1972 }
1973
1974 void
siop_add_dev(sc,target,lun)1975 siop_add_dev(sc, target, lun)
1976 struct siop_softc *sc;
1977 int target;
1978 int lun;
1979 {
1980 struct siop_lunsw *lunsw;
1981 struct siop_target *siop_target =
1982 (struct siop_target *)sc->sc_c.targets[target];
1983 struct siop_lun *siop_lun = siop_target->siop_lun[lun];
1984 int i, ntargets;
1985
1986 if (siop_lun->reseloff > 0)
1987 return;
1988 lunsw = siop_target->lunsw;
1989 if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) {
1990 /*
1991 * can't extend this slot. Probably not worth trying to deal
1992 * with this case
1993 */
1994 #ifdef SIOP_DEBUG
1995 printf("%s:%d:%d: can't allocate a lun sw slot\n",
1996 sc->sc_c.sc_dev.dv_xname, target, lun);
1997 #endif
1998 return;
1999 }
2000 /* count how many free targets we still have to probe */
2001 ntargets = (sc->sc_c.sc_link.adapter_buswidth - 1) - 1 - sc->sc_ntargets;
2002
2003 /*
2004 * we need 8 bytes for the lun sw additional entry, and
2005 * eventually sizeof(tag_switch) for the tag switch entry.
2006 * Keep enough free space for the free targets that could be
2007 * probed later.
2008 */
2009 if (sc->script_free_lo + 2 +
2010 (ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >=
2011 ((siop_target->target_c.flags & TARF_TAG) ?
2012 sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) :
2013 sc->script_free_hi)) {
2014 /*
2015 * not enough space, probably not worth dealing with it.
2016 * We can hold 13 tagged-queuing capable devices in the 4k RAM.
2017 */
2018 #ifdef SIOP_DEBUG
2019 printf("%s:%d:%d: not enough memory for a lun sw slot\n",
2020 sc->sc_c.sc_dev.dv_xname, target, lun);
2021 #endif
2022 return;
2023 }
2024 #ifdef SIOP_DEBUG
2025 printf("%s:%d:%d: allocate lun sw entry\n",
2026 sc->sc_c.sc_dev.dv_xname, target, lun);
2027 #endif
2028 /* INT int_resellun */
2029 siop_script_write(sc, sc->script_free_lo, 0x98080000);
2030 siop_script_write(sc, sc->script_free_lo + 1, A_int_resellun);
2031 /* Now the slot entry: JUMP abs_foo, IF lun */
2032 siop_script_write(sc, sc->script_free_lo - 2,
2033 0x800c0000 | lun);
2034 siop_script_write(sc, sc->script_free_lo - 1, 0);
2035 siop_lun->reseloff = sc->script_free_lo - 2;
2036 lunsw->lunsw_size += 2;
2037 sc->script_free_lo += 2;
2038 if (siop_target->target_c.flags & TARF_TAG) {
2039 /* we need a tag switch */
2040 sc->script_free_hi -=
2041 sizeof(tag_switch) / sizeof(tag_switch[0]);
2042 if (sc->sc_c.features & SF_CHIP_RAM) {
2043 bus_space_write_region_4(sc->sc_c.sc_ramt,
2044 sc->sc_c.sc_ramh,
2045 sc->script_free_hi * 4, tag_switch,
2046 sizeof(tag_switch) / sizeof(tag_switch[0]));
2047 } else {
2048 for(i = 0;
2049 i < sizeof(tag_switch) / sizeof(tag_switch[0]);
2050 i++) {
2051 sc->sc_c.sc_script[sc->script_free_hi + i] =
2052 htole32(tag_switch[i]);
2053 }
2054 }
2055 siop_script_write(sc,
2056 siop_lun->reseloff + 1,
2057 sc->sc_c.sc_scriptaddr + sc->script_free_hi * 4 +
2058 Ent_tag_switch_entry);
2059
2060 for (i = 0; i < SIOP_NTAG; i++) {
2061 siop_lun->siop_tag[i].reseloff =
2062 sc->script_free_hi + (Ent_resel_tag0 / 4) + i * 2;
2063 }
2064 } else {
2065 /* non-tag case; just work with the lun switch */
2066 siop_lun->siop_tag[0].reseloff =
2067 siop_target->siop_lun[lun]->reseloff;
2068 }
2069 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2070 }
2071
2072 void
siop_del_dev(sc,target,lun)2073 siop_del_dev(sc, target, lun)
2074 struct siop_softc *sc;
2075 int target;
2076 int lun;
2077 {
2078 int i;
2079 struct siop_target *siop_target;
2080 #ifdef SIOP_DEBUG
2081 printf("%s:%d:%d: free lun sw entry\n",
2082 sc->sc_c.sc_dev.dv_xname, target, lun);
2083 #endif
2084 if (sc->sc_c.targets[target] == NULL)
2085 return;
2086 siop_target = (struct siop_target *)sc->sc_c.targets[target];
2087 free(siop_target->siop_lun[lun], M_DEVBUF);
2088 siop_target->siop_lun[lun] = NULL;
2089 /* XXX compact sw entry too ? */
2090 /* check if we can free the whole target */
2091 for (i = 0; i < 8; i++) {
2092 if (siop_target->siop_lun[i] != NULL)
2093 return;
2094 }
2095 #ifdef SIOP_DEBUG
2096 printf("%s: free siop_target for target %d lun %d lunsw offset %d\n",
2097 sc->sc_c.sc_dev.dv_xname, target, lun,
2098 siop_target->lunsw->lunsw_off);
2099 #endif
2100 /*
2101 * nothing here, free the target struct and resel
2102 * switch entry
2103 */
2104 siop_script_write(sc, siop_target->reseloff, 0x800c00ff);
2105 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
2106 TAILQ_INSERT_TAIL(&sc->lunsw_list, siop_target->lunsw, next);
2107 free(sc->sc_c.targets[target], M_DEVBUF);
2108 sc->sc_c.targets[target] = NULL;
2109 sc->sc_ntargets--;
2110 }
2111
2112 #ifdef SIOP_STATS
2113 void
siop_printstats()2114 siop_printstats()
2115 {
2116 printf("siop_stat_intr %d\n", siop_stat_intr);
2117 printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
2118 printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
2119 printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
2120 printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
2121 printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel);
2122 printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull);
2123 }
2124 #endif
2125