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