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