siop.c revision 1.37.2.2 1 /* $NetBSD: siop.c,v 1.37.2.2 2000/11/20 11:40:54 bouyer 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 return 1;
698 case A_int_reseltag:
699 printf("%s: reselect with invalid tag\n",
700 sc->sc_dev.dv_xname);
701 goto reset;
702 case A_int_msgin:
703 {
704 int msgin = bus_space_read_1(sc->sc_rt, sc->sc_rh,
705 SIOP_SFBR);
706 if (msgin == MSG_MESSAGE_REJECT) {
707 int msg, extmsg;
708 if (siop_cmd->siop_tables.msg_out[0] & 0x80) {
709 /*
710 * message was part of a identify +
711 * something else. Identify shoudl't
712 * have been rejected.
713 */
714 msg = siop_cmd->siop_tables.msg_out[1];
715 extmsg =
716 siop_cmd->siop_tables.msg_out[3];
717 } else {
718 msg = siop_cmd->siop_tables.msg_out[0];
719 extmsg =
720 siop_cmd->siop_tables.msg_out[2];
721 }
722 if (msg == MSG_MESSAGE_REJECT) {
723 /* MSG_REJECT for a MSG_REJECT !*/
724 if (xs)
725 scsi_print_addr(xs->sc_link);
726 else
727 printf("%s: ",
728 sc->sc_dev.dv_xname);
729 printf("our reject message was "
730 "rejected\n");
731 goto reset;
732 }
733 if (msg == MSG_EXTENDED &&
734 extmsg == MSG_EXT_WDTR) {
735 /* WDTR rejected, initiate sync */
736 printf("%s: target %d using 8bit "
737 "transfers\n", sc->sc_dev.dv_xname,
738 target);
739 if ((siop_target->flags & TARF_SYNC)
740 == 0) {
741 siop_target->status = TARST_OK;
742 /* no table to flush here */
743 CALL_SCRIPT(Ent_msgin_ack);
744 return 1;
745 }
746 siop_target->status = TARST_SYNC_NEG;
747 siop_sdtr_msg(siop_cmd, 0,
748 sc->minsync, sc->maxoff);
749 siop_table_sync(siop_cmd,
750 BUS_DMASYNC_PREREAD |
751 BUS_DMASYNC_PREWRITE);
752 CALL_SCRIPT(Ent_send_msgout);
753 return 1;
754 } else if (msg == MSG_EXTENDED &&
755 extmsg == MSG_EXT_SDTR) {
756 /* sync rejected */
757 printf("%s: target %d asynchronous\n",
758 sc->sc_dev.dv_xname,
759 target);
760 siop_target->status = TARST_OK;
761 /* no table to flush here */
762 CALL_SCRIPT(Ent_msgin_ack);
763 return 1;
764 } else if (msg == MSG_SIMPLE_Q_TAG ||
765 msg == MSG_HEAD_OF_Q_TAG ||
766 msg == MSG_ORDERED_Q_TAG) {
767 if (siop_handle_qtag_reject(
768 siop_cmd) == -1)
769 goto reset;
770 CALL_SCRIPT(Ent_msgin_ack);
771 return 1;
772 }
773 if (xs)
774 scsi_print_addr(xs->sc_link);
775 else
776 printf("%s: ", sc->sc_dev.dv_xname);
777 if (msg == MSG_EXTENDED) {
778 printf("scsi message reject, extended "
779 "message sent was 0x%x\n", extmsg);
780 } else {
781 printf("scsi message reject, message "
782 "sent was 0x%x\n", msg);
783 }
784 /* no table to flush here */
785 CALL_SCRIPT(Ent_msgin_ack);
786 return 1;
787 }
788 if (xs)
789 scsi_print_addr(xs->sc_link);
790 else
791 printf("%s: ", sc->sc_dev.dv_xname);
792 printf("unhandled message 0x%x\n",
793 siop_cmd->siop_tables.msg_in[0]);
794 siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;
795 siop_cmd->siop_tables.t_msgout.count= htole32(1);
796 siop_table_sync(siop_cmd,
797 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
798 CALL_SCRIPT(Ent_send_msgout);
799 return 1;
800 }
801 case A_int_extmsgin:
802 #ifdef SIOP_DEBUG_INTR
803 printf("extended message: msg 0x%x len %d\n",
804 siop_cmd->siop_tables.msg_in[2],
805 siop_cmd->siop_tables.msg_in[1]);
806 #endif
807 if (siop_cmd->siop_tables.msg_in[1] > 6)
808 printf("%s: extended message too big (%d)\n",
809 sc->sc_dev.dv_xname,
810 siop_cmd->siop_tables.msg_in[1]);
811 siop_cmd->siop_tables.t_extmsgdata.count =
812 htole32(siop_cmd->siop_tables.msg_in[1] - 1);
813 siop_table_sync(siop_cmd,
814 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
815 CALL_SCRIPT(Ent_get_extmsgdata);
816 return 1;
817 case A_int_extmsgdata:
818 #ifdef SIOP_DEBUG_INTR
819 {
820 int i;
821 printf("extended message: 0x%x, data:",
822 siop_cmd->siop_tables.msg_in[2]);
823 for (i = 3; i < 2 + siop_cmd->siop_tables.msg_in[1];
824 i++)
825 printf(" 0x%x",
826 siop_cmd->siop_tables.msg_in[i]);
827 printf("\n");
828 }
829 #endif
830 if (siop_cmd->siop_tables.msg_in[2] == MSG_EXT_WDTR) {
831 switch (siop_wdtr_neg(siop_cmd)) {
832 case SIOP_NEG_MSGOUT:
833 siop_update_scntl3(sc,
834 siop_cmd->siop_target);
835 siop_table_sync(siop_cmd,
836 BUS_DMASYNC_PREREAD |
837 BUS_DMASYNC_PREWRITE);
838 CALL_SCRIPT(Ent_send_msgout);
839 return(1);
840 case SIOP_NEG_ACK:
841 siop_update_scntl3(sc,
842 siop_cmd->siop_target);
843 CALL_SCRIPT(Ent_msgin_ack);
844 return(1);
845 default:
846 panic("invalid retval from "
847 "siop_wdtr_neg()");
848 }
849 return(1);
850 }
851 if (siop_cmd->siop_tables.msg_in[2] == MSG_EXT_SDTR) {
852 switch (siop_sdtr_neg(siop_cmd)) {
853 case SIOP_NEG_MSGOUT:
854 siop_update_scntl3(sc,
855 siop_cmd->siop_target);
856 siop_table_sync(siop_cmd,
857 BUS_DMASYNC_PREREAD |
858 BUS_DMASYNC_PREWRITE);
859 CALL_SCRIPT(Ent_send_msgout);
860 return(1);
861 case SIOP_NEG_ACK:
862 siop_update_scntl3(sc,
863 siop_cmd->siop_target);
864 CALL_SCRIPT(Ent_msgin_ack);
865 return(1);
866 default:
867 panic("invalid retval from "
868 "siop_wdtr_neg()");
869 }
870 return(1);
871 }
872 /* send a message reject */
873 siop_cmd->siop_tables.msg_out[0] = MSG_MESSAGE_REJECT;
874 siop_cmd->siop_tables.t_msgout.count = htole32(1);
875 siop_table_sync(siop_cmd,
876 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
877 CALL_SCRIPT(Ent_send_msgout);
878 return 1;
879 case A_int_disc:
880 INCSTAT(siop_stat_intr_sdp);
881 offset = bus_space_read_1(sc->sc_rt, sc->sc_rh,
882 SIOP_SCRATCHA + 1);
883 #ifdef SIOP_DEBUG_DR
884 printf("disconnect offset %d\n", offset);
885 #endif
886 if (offset > SIOP_NSG) {
887 printf("%s: bad offset for disconnect (%d)\n",
888 sc->sc_dev.dv_xname, offset);
889 goto reset;
890 }
891 /*
892 * offset == SIOP_NSG may be a valid condition if
893 * we get a sdp when the xfer is done.
894 * Don't call memmove in this case.
895 */
896 if (offset < SIOP_NSG) {
897 memmove(&siop_cmd->siop_tables.data[0],
898 &siop_cmd->siop_tables.data[offset],
899 (SIOP_NSG - offset) * sizeof(scr_table_t));
900 siop_table_sync(siop_cmd,
901 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
902 }
903 CALL_SCRIPT(Ent_script_sched);
904 /* check if we can put some command in scheduler */
905 siop_start(sc);
906 return 1;
907 case A_int_resfail:
908 printf("reselect failed\n");
909 CALL_SCRIPT(Ent_script_sched);
910 return 1;
911 case A_int_done:
912 if (xs == NULL) {
913 printf("%s: done without command, DSA=0x%lx\n",
914 sc->sc_dev.dv_xname, (u_long)siop_cmd->dsa);
915 siop_cmd->status = CMDST_FREE;
916 siop_start(sc);
917 CALL_SCRIPT(Ent_script_sched);
918 return 1;
919 }
920 #ifdef SIOP_DEBUG_INTR
921 printf("done, DSA=0x%lx target id 0x%x last msg "
922 "in=0x%x status=0x%x\n", (u_long)siop_cmd->dsa,
923 le32toh(siop_cmd->siop_tables.id),
924 siop_cmd->siop_tables.msg_in[0],
925 le32toh(siop_cmd->siop_tables.status));
926 #endif
927 INCSTAT(siop_stat_intr_done);
928 if (siop_cmd->status == CMDST_SENSE_ACTIVE)
929 siop_cmd->status = CMDST_SENSE_DONE;
930 else
931 siop_cmd->status = CMDST_DONE;
932 goto end;
933 default:
934 printf("unknown irqcode %x\n", irqcode);
935 if (xs) {
936 xs->error = XS_SELTIMEOUT;
937 goto end;
938 }
939 goto reset;
940 }
941 return 1;
942 }
943 /* We just should't get there */
944 panic("siop_intr: I shouldn't be there !");
945 return 1;
946 end:
947 CALL_SCRIPT(Ent_script_sched);
948 siop_scsicmd_end(siop_cmd);
949 siop_lun->siop_tag[tag].active = NULL;
950 if (siop_cmd->status == CMDST_FREE) {
951 TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
952 siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
953 if (freetarget && siop_target->status == TARST_PROBING)
954 siop_del_dev(sc, target, lun);
955 }
956 siop_start(sc);
957 return 1;
958 }
959
960 void
961 siop_scsicmd_end(siop_cmd)
962 struct siop_cmd *siop_cmd;
963 {
964 struct scsipi_xfer *xs = siop_cmd->xs;
965 struct siop_softc *sc = siop_cmd->siop_sc;
966
967 switch(le32toh(siop_cmd->siop_tables.status)) {
968 case SCSI_OK:
969 xs->error = (siop_cmd->status == CMDST_DONE) ?
970 XS_NOERROR : XS_SENSE;
971 break;
972 case SCSI_BUSY:
973 xs->error = XS_BUSY;
974 break;
975 case SCSI_CHECK:
976 if (siop_cmd->status == CMDST_SENSE_DONE) {
977 /* request sense on a request sense ? */
978 printf("request sense failed\n");
979 xs->error = XS_DRIVER_STUFFUP;
980 } else {
981 siop_cmd->status = CMDST_SENSE;
982 }
983 break;
984 case SCSI_QUEUE_FULL:
985 {
986 struct siop_lun *siop_lun = siop_cmd->siop_target->siop_lun[
987 xs->sc_link->scsipi_scsi.lun];
988 /*
989 * device didn't queue the command. We have to
990 * retry it.
991 * We insert it in the urgent list, hoping to preserve order.
992 * But unfortunably, commands already in the scheduler may
993 * be accepted before this one.
994 * Also remember the condition, to avoid starting new commands
995 * for this device before one is done.
996 */
997 INCSTAT(siop_stat_intr_qfull);
998 #ifdef SIOP_DEBUG
999 printf("%s:%d:%d: queue full (tag %d)\n", sc->sc_dev.dv_xname,
1000 xs->sc_link->scsipi_scsi.target,
1001 xs->sc_link->scsipi_scsi.lun, siop_cmd->tag);
1002 #endif
1003 callout_stop(&xs->xs_callout);
1004 siop_lun->lun_flags |= SIOP_LUNF_FULL;
1005 siop_cmd->status = CMDST_READY;
1006 siop_setuptables(siop_cmd);
1007 TAILQ_INSERT_TAIL(&sc->urgent_list, siop_cmd, next);
1008 return;
1009 }
1010 case SCSI_SIOP_NOCHECK:
1011 /*
1012 * don't check status, xs->error is already valid
1013 */
1014 break;
1015 case SCSI_SIOP_NOSTATUS:
1016 /*
1017 * the status byte was not updated, cmd was
1018 * aborted
1019 */
1020 xs->error = XS_SELTIMEOUT;
1021 break;
1022 default:
1023 xs->error = XS_DRIVER_STUFFUP;
1024 }
1025 if (siop_cmd->status != CMDST_SENSE_DONE &&
1026 xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
1027 bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1028 siop_cmd->dmamap_data->dm_mapsize,
1029 (xs->xs_control & XS_CTL_DATA_IN) ?
1030 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1031 bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);
1032 }
1033 bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
1034 if (siop_cmd->status == CMDST_SENSE) {
1035 /* issue a request sense for this target */
1036 int error;
1037 siop_cmd->rs_cmd.opcode = REQUEST_SENSE;
1038 siop_cmd->rs_cmd.byte2 = xs->sc_link->scsipi_scsi.lun << 5;
1039 siop_cmd->rs_cmd.unused[0] = siop_cmd->rs_cmd.unused[1] = 0;
1040 siop_cmd->rs_cmd.length = sizeof(struct scsipi_sense_data);
1041 siop_cmd->rs_cmd.control = 0;
1042 siop_cmd->flags &= ~CMDFL_TAG;
1043 error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
1044 &siop_cmd->rs_cmd, sizeof(struct scsipi_sense),
1045 NULL, BUS_DMA_NOWAIT);
1046 if (error) {
1047 printf("%s: unable to load cmd DMA map: %d",
1048 sc->sc_dev.dv_xname, error);
1049 xs->error = XS_DRIVER_STUFFUP;
1050 goto out;
1051 }
1052 error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,
1053 &xs->sense.scsi_sense, sizeof(struct scsipi_sense_data),
1054 NULL, BUS_DMA_NOWAIT);
1055 if (error) {
1056 printf("%s: unable to load sense DMA map: %d",
1057 sc->sc_dev.dv_xname, error);
1058 xs->error = XS_DRIVER_STUFFUP;
1059 bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
1060 goto out;
1061 }
1062 bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1063 siop_cmd->dmamap_data->dm_mapsize, BUS_DMASYNC_PREREAD);
1064 bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd, 0,
1065 siop_cmd->dmamap_cmd->dm_mapsize, BUS_DMASYNC_PREWRITE);
1066
1067 siop_setuptables(siop_cmd);
1068 /* arrange for the cmd to be handled now */
1069 TAILQ_INSERT_HEAD(&sc->urgent_list, siop_cmd, next);
1070 return;
1071 } else if (siop_cmd->status == CMDST_SENSE_DONE) {
1072 bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1073 siop_cmd->dmamap_data->dm_mapsize, BUS_DMASYNC_POSTREAD);
1074 bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_data);
1075 }
1076 out:
1077 callout_stop(&siop_cmd->xs->xs_callout);
1078 siop_cmd->status = CMDST_FREE;
1079 xs->xs_status |= XS_STS_DONE;
1080 xs->resid = 0;
1081 if ((xs->xs_control & XS_CTL_POLL) == 0)
1082 scsipi_done (xs);
1083 }
1084
1085 /*
1086 * handle a rejected queue tag message: the command will run untagged,
1087 * has to adjust the reselect script.
1088 */
1089 int
1090 siop_handle_qtag_reject(siop_cmd)
1091 struct siop_cmd *siop_cmd;
1092 {
1093 struct siop_softc *sc = siop_cmd->siop_sc;
1094 int target = siop_cmd->xs->sc_link->scsipi_scsi.target;
1095 int lun = siop_cmd->xs->sc_link->scsipi_scsi.lun;
1096 int tag = siop_cmd->siop_tables.msg_out[2];
1097 struct siop_lun *siop_lun = sc->targets[target]->siop_lun[lun];
1098
1099 #ifdef SIOP_DEBUG
1100 printf("%s:%d:%d: tag message %d (%d) rejected (status %d)\n",
1101 sc->sc_dev.dv_xname, target, lun, tag, siop_cmd->tag,
1102 siop_cmd->status);
1103 #endif
1104
1105 if (siop_lun->siop_tag[0].active != NULL) {
1106 printf("%s: untagged command already running for target %d "
1107 "lun %d (status %d)\n", sc->sc_dev.dv_xname, target, lun,
1108 siop_lun->siop_tag[0].active->status);
1109 return -1;
1110 }
1111 /* clear tag slot */
1112 siop_lun->siop_tag[tag].active = NULL;
1113 /* add command to non-tagged slot */
1114 siop_lun->siop_tag[0].active = siop_cmd;
1115 siop_cmd->tag = 0;
1116 /* adjust reselect script if there is one */
1117 if (siop_lun->siop_tag[0].reseloff > 0) {
1118 siop_script_write(sc,
1119 siop_lun->siop_tag[0].reseloff + 1,
1120 siop_cmd->dsa + sizeof(struct siop_xfer_common) +
1121 Ent_ldsa_reload_dsa);
1122 }
1123 return 0;
1124 }
1125
1126 /*
1127 * handle a bus reset: reset chip, unqueue all active commands, free all
1128 * target struct and report loosage to upper layer.
1129 * As the upper layer may requeue immediatly we have to first store
1130 * all active commands in a temporary queue.
1131 */
1132 void
1133 siop_handle_reset(sc)
1134 struct siop_softc *sc;
1135 {
1136 struct cmd_list reset_list;
1137 struct siop_cmd *siop_cmd, *next_siop_cmd;
1138 struct siop_lun *siop_lun;
1139 int target, lun, tag;
1140 /*
1141 * scsi bus reset. reset the chip and restart
1142 * the queue. Need to clean up all active commands
1143 */
1144 printf("%s: scsi bus reset\n", sc->sc_dev.dv_xname);
1145 /* stop, reset and restart the chip */
1146 siop_reset(sc);
1147 TAILQ_INIT(&reset_list);
1148 /*
1149 * Process all commands: first commmands being executed
1150 */
1151 for (target = 0; target <= sc->sc_link.scsipi_scsi.max_target;
1152 target++) {
1153 if (sc->targets[target] == NULL)
1154 continue;
1155 for (lun = 0; lun < 8; lun++) {
1156 siop_lun = sc->targets[target]->siop_lun[lun];
1157 if (siop_lun == NULL)
1158 continue;
1159 siop_lun->lun_flags &= ~SIOP_LUNF_FULL;
1160 for (tag = 0; tag <
1161 ((sc->targets[target]->flags & TARF_TAG) ?
1162 SIOP_NTAG : 1);
1163 tag++) {
1164 siop_cmd = siop_lun->siop_tag[tag].active;
1165 if (siop_cmd == NULL)
1166 continue;
1167 printf("cmd %p (target %d:%d) in reset list\n",
1168 siop_cmd, target, lun);
1169 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1170 siop_lun->siop_tag[tag].active = NULL;
1171 }
1172 }
1173 sc->targets[target]->status = TARST_ASYNC;
1174 sc->targets[target]->flags &= ~TARF_ISWIDE;
1175 }
1176 /* Next commands from the urgent list */
1177 for (siop_cmd = TAILQ_FIRST(&sc->urgent_list); siop_cmd != NULL;
1178 siop_cmd = next_siop_cmd) {
1179 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1180 siop_cmd->flags &= ~CMDFL_TAG;
1181 printf("cmd %p (target %d:%d) in reset list (wait)\n",
1182 siop_cmd, siop_cmd->xs->sc_link->scsipi_scsi.target,
1183 siop_cmd->xs->sc_link->scsipi_scsi.lun);
1184 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1185 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1186 }
1187 /* Then command waiting in the input list */
1188 for (siop_cmd = TAILQ_FIRST(&sc->ready_list); siop_cmd != NULL;
1189 siop_cmd = next_siop_cmd) {
1190 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1191 siop_cmd->flags &= ~CMDFL_TAG;
1192 printf("cmd %p (target %d:%d) in reset list (wait)\n",
1193 siop_cmd, siop_cmd->xs->sc_link->scsipi_scsi.target,
1194 siop_cmd->xs->sc_link->scsipi_scsi.lun);
1195 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1196 TAILQ_INSERT_TAIL(&reset_list, siop_cmd, next);
1197 }
1198
1199 for (siop_cmd = TAILQ_FIRST(&reset_list); siop_cmd != NULL;
1200 siop_cmd = next_siop_cmd) {
1201 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1202 siop_cmd->xs->error = (siop_cmd->flags & CMDFL_TIMEOUT) ?
1203 XS_TIMEOUT : XS_RESET;
1204 siop_cmd->siop_tables.status = htole32(SCSI_SIOP_NOCHECK);
1205 printf("cmd %p (status %d) about to be processed\n", siop_cmd,
1206 siop_cmd->status);
1207 if (siop_cmd->status == CMDST_SENSE ||
1208 siop_cmd->status == CMDST_SENSE_ACTIVE)
1209 siop_cmd->status = CMDST_SENSE_DONE;
1210 else
1211 siop_cmd->status = CMDST_DONE;
1212 TAILQ_REMOVE(&reset_list, siop_cmd, next);
1213 siop_scsicmd_end(siop_cmd);
1214 TAILQ_INSERT_TAIL(&sc->free_list, siop_cmd, next);
1215 }
1216 }
1217
1218 int
1219 siop_scsicmd(xs)
1220 struct scsipi_xfer *xs;
1221 {
1222 struct siop_softc *sc = (struct siop_softc *)xs->sc_link->adapter_softc;
1223 struct siop_cmd *siop_cmd;
1224 int s, error, i;
1225 const int target = xs->sc_link->scsipi_scsi.target;
1226 const int lun = xs->sc_link->scsipi_scsi.lun;
1227
1228 s = splbio();
1229 #ifdef SIOP_DEBUG_SCHED
1230 printf("starting cmd for %d:%d\n", target, lun);
1231 #endif
1232 siop_cmd = TAILQ_FIRST(&sc->free_list);
1233 if (siop_cmd) {
1234 TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
1235 } else {
1236 if (siop_morecbd(sc) == 0) {
1237 siop_cmd = TAILQ_FIRST(&sc->free_list);
1238 #ifdef DIAGNOSTIC
1239 if (siop_cmd == NULL)
1240 panic("siop_morecbd succeed and does nothing");
1241 #endif
1242 TAILQ_REMOVE(&sc->free_list, siop_cmd, next);
1243 }
1244 }
1245 if (siop_cmd == NULL) {
1246 xs->error = XS_DRIVER_STUFFUP;
1247 splx(s);
1248 return(TRY_AGAIN_LATER);
1249 }
1250 #ifdef DIAGNOSTIC
1251 if (siop_cmd->status != CMDST_FREE)
1252 panic("siop_scsicmd: new cmd not free");
1253 #endif
1254 if (sc->targets[target] == NULL) {
1255 #ifdef SIOP_DEBUG
1256 printf("%s: alloc siop_target for target %d\n",
1257 sc->sc_dev.dv_xname, target);
1258 #endif
1259 sc->targets[target] =
1260 malloc(sizeof(struct siop_target), M_DEVBUF, M_NOWAIT);
1261 if (sc->targets[target] == NULL) {
1262 printf("%s: can't malloc memory for target %d\n",
1263 sc->sc_dev.dv_xname, target);
1264 xs->error = XS_DRIVER_STUFFUP;
1265 splx(s);
1266 return(TRY_AGAIN_LATER);
1267 }
1268 sc->targets[target]->status = TARST_PROBING;
1269 sc->targets[target]->flags = 0;
1270 sc->targets[target]->id = sc->clock_div << 24; /* scntl3 */
1271 sc->targets[target]->id |= target << 16; /* id */
1272 /* sc->targets[target]->id |= 0x0 << 8; scxfer is 0 */
1273
1274 /* get a lun switch script */
1275 sc->targets[target]->lunsw = siop_get_lunsw(sc);
1276 if (sc->targets[target]->lunsw == NULL) {
1277 printf("%s: can't alloc lunsw for target %d\n",
1278 sc->sc_dev.dv_xname, target);
1279 xs->error = XS_DRIVER_STUFFUP;
1280 splx(s);
1281 return(TRY_AGAIN_LATER);
1282 }
1283 for (i=0; i < 8; i++)
1284 sc->targets[target]->siop_lun[i] = NULL;
1285 siop_add_reselsw(sc, target);
1286 }
1287 if (sc->targets[target]->siop_lun[lun] == NULL) {
1288 sc->targets[target]->siop_lun[lun] =
1289 malloc(sizeof(struct siop_lun), M_DEVBUF, M_NOWAIT);
1290 if (sc->targets[target]->siop_lun[lun] == NULL) {
1291 printf("%s: can't alloc siop_lun for target %d "
1292 "lun %d\n", sc->sc_dev.dv_xname, target, lun);
1293 xs->error = XS_DRIVER_STUFFUP;
1294 splx(s);
1295 return(TRY_AGAIN_LATER);
1296 }
1297 memset(sc->targets[target]->siop_lun[lun], 0,
1298 sizeof(struct siop_lun));
1299 }
1300 siop_cmd->siop_target = sc->targets[target];
1301 siop_cmd->xs = xs;
1302 siop_cmd->flags = 0;
1303 siop_cmd->status = CMDST_READY;
1304
1305 /* load the DMA maps */
1306 error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_cmd,
1307 xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT);
1308 if (error) {
1309 printf("%s: unable to load cmd DMA map: %d",
1310 sc->sc_dev.dv_xname, error);
1311 xs->error = XS_DRIVER_STUFFUP;
1312 splx(s);
1313 return(TRY_AGAIN_LATER);
1314 }
1315 if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
1316 error = bus_dmamap_load(sc->sc_dmat, siop_cmd->dmamap_data,
1317 xs->data, xs->datalen, NULL, BUS_DMA_NOWAIT);
1318 if (error) {
1319 printf("%s: unable to load cmd DMA map: %d",
1320 sc->sc_dev.dv_xname, error);
1321 xs->error = XS_DRIVER_STUFFUP;
1322 bus_dmamap_unload(sc->sc_dmat, siop_cmd->dmamap_cmd);
1323 splx(s);
1324 return(TRY_AGAIN_LATER);
1325 }
1326 bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_data, 0,
1327 siop_cmd->dmamap_data->dm_mapsize,
1328 (xs->xs_control & XS_CTL_DATA_IN) ?
1329 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
1330 }
1331 bus_dmamap_sync(sc->sc_dmat, siop_cmd->dmamap_cmd, 0,
1332 siop_cmd->dmamap_cmd->dm_mapsize, BUS_DMASYNC_PREWRITE);
1333
1334 siop_setuptables(siop_cmd);
1335
1336 TAILQ_INSERT_TAIL(&sc->ready_list, siop_cmd, next);
1337 siop_start(sc);
1338 if (xs->xs_control & XS_CTL_POLL) {
1339 /* poll for command completion */
1340 while ((xs->xs_status & XS_STS_DONE) == 0) {
1341 delay(1000);
1342 siop_intr(sc);
1343 }
1344 splx(s);
1345 return (COMPLETE);
1346 }
1347 splx(s);
1348 return (SUCCESSFULLY_QUEUED);
1349 }
1350
1351 void
1352 siop_start(sc)
1353 struct siop_softc *sc;
1354 {
1355 struct siop_cmd *siop_cmd, *next_siop_cmd;
1356 struct siop_lun *siop_lun;
1357 u_int32_t dsa;
1358 int timeout;
1359 int target, lun, tag, slot;
1360 int newcmd = 0;
1361 int doingready = 0;
1362
1363 /*
1364 * first make sure to read valid data
1365 */
1366 siop_script_sync(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1367
1368 /*
1369 * The queue management here is a bit tricky: the script always looks
1370 * at the slot from first to last, so if we always use the first
1371 * free slot commands can stay at the tail of the queue ~forever.
1372 * The algorithm used here is to restart from the head when we know
1373 * that the queue is empty, and only add commands after the last one.
1374 * When we're at the end of the queue wait for the script to clear it.
1375 * The best thing to do here would be to implement a circular queue,
1376 * but using only 53c720 features this can be "interesting".
1377 * A mid-way solution could be to implement 2 queues and swap orders.
1378 */
1379 slot = sc->sc_currschedslot;
1380 /*
1381 * If the instruction is 0x80000000 (JUMP foo, IF FALSE) the slot is
1382 * free. As this is the last used slot, all previous slots are free,
1383 * we can restart from 0.
1384 */
1385 if (siop_script_read(sc, (Ent_script_sched_slot0 / 4) + slot * 2) ==
1386 0x80000000) {
1387 slot = sc->sc_currschedslot = 0;
1388 } else {
1389 slot++;
1390 }
1391 /* first handle commands from the urgent list */
1392 siop_cmd = TAILQ_FIRST(&sc->urgent_list);
1393 again:
1394 for (; siop_cmd != NULL; siop_cmd = next_siop_cmd) {
1395 next_siop_cmd = TAILQ_NEXT(siop_cmd, next);
1396 #ifdef DIAGNOSTIC
1397 if (siop_cmd->status != CMDST_READY &&
1398 siop_cmd->status != CMDST_SENSE)
1399 panic("siop: non-ready cmd in ready list");
1400 #endif
1401 target = siop_cmd->xs->sc_link->scsipi_scsi.target;
1402 lun = siop_cmd->xs->sc_link->scsipi_scsi.lun;
1403 siop_lun = sc->targets[target]->siop_lun[lun];
1404 /* if non-tagged command active, wait */
1405 if (siop_lun->siop_tag[0].active != NULL)
1406 continue;
1407 /*
1408 * if we're in a queue full condition don't start a new
1409 * command, unless it's a request sense
1410 */
1411 if ((siop_lun->lun_flags & SIOP_LUNF_FULL) &&
1412 siop_cmd->status == CMDST_READY)
1413 continue;
1414 /* find a free tag if needed */
1415 if (siop_cmd->flags & CMDFL_TAG) {
1416 for (tag = 1; tag < SIOP_NTAG; tag++) {
1417 if (siop_lun->siop_tag[tag].active == NULL)
1418 break;
1419 }
1420 if (tag == SIOP_NTAG) /* no free tag */
1421 continue;
1422 } else {
1423 tag = 0;
1424 }
1425 siop_cmd->tag = tag;
1426 /* find a free scheduler slot and load it */
1427 for (; slot < SIOP_NSLOTS; slot++) {
1428 /*
1429 * If cmd if 0x80000000 the slot is free
1430 */
1431 if (siop_script_read(sc,
1432 (Ent_script_sched_slot0 / 4) + slot * 2) ==
1433 0x80000000)
1434 break;
1435 }
1436 /* no more free slot, no need to continue */
1437 if (slot == SIOP_NSLOTS) {
1438 goto end;
1439 }
1440 #ifdef SIOP_DEBUG_SCHED
1441 printf("using slot %d for DSA 0x%lx\n", slot,
1442 (u_long)siop_cmd->dsa);
1443 #endif
1444 /* Ok, we can add the tag message */
1445 if (tag > 0) {
1446 #ifdef DIAGNOSTIC
1447 int msgcount =
1448 le32toh(siop_cmd->siop_tables.t_msgout.count);
1449 if (msgcount != 1)
1450 printf("%s:%d:%d: tag %d with msgcount %d\n",
1451 sc->sc_dev.dv_xname, target, lun, tag,
1452 msgcount);
1453 #endif
1454 if (siop_cmd->xs->bp != NULL &&
1455 (siop_cmd->xs->bp->b_flags & B_ASYNC))
1456 siop_cmd->siop_tables.msg_out[1] =
1457 MSG_SIMPLE_Q_TAG;
1458 else
1459 siop_cmd->siop_tables.msg_out[1] =
1460 MSG_ORDERED_Q_TAG;
1461 siop_cmd->siop_tables.msg_out[2] = tag;
1462 siop_cmd->siop_tables.t_msgout.count = htole32(3);
1463 }
1464 /* note that we started a new command */
1465 newcmd = 1;
1466 /* mark command as active */
1467 if (siop_cmd->status == CMDST_READY) {
1468 siop_cmd->status = CMDST_ACTIVE;
1469 } else if (siop_cmd->status == CMDST_SENSE) {
1470 siop_cmd->status = CMDST_SENSE_ACTIVE;
1471 } else
1472 panic("siop_start: bad status");
1473 if (doingready)
1474 TAILQ_REMOVE(&sc->ready_list, siop_cmd, next);
1475 else
1476 TAILQ_REMOVE(&sc->urgent_list, siop_cmd, next);
1477 siop_lun->siop_tag[tag].active = siop_cmd;
1478 /* patch scripts with DSA addr */
1479 dsa = siop_cmd->dsa;
1480 /* first reselect switch, if we have an entry */
1481 if (siop_lun->siop_tag[tag].reseloff > 0)
1482 siop_script_write(sc,
1483 siop_lun->siop_tag[tag].reseloff + 1,
1484 dsa + sizeof(struct siop_xfer_common) +
1485 Ent_ldsa_reload_dsa);
1486 /* CMD script: MOVE MEMORY addr */
1487 siop_cmd->siop_xfer->resel[E_ldsa_abs_slot_Used[0]] =
1488 htole32(sc->sc_scriptaddr + Ent_script_sched_slot0 +
1489 slot * 8);
1490 /* scheduler slot: JUMP ldsa_select */
1491 siop_script_write(sc,
1492 (Ent_script_sched_slot0 / 4) + slot * 2 + 1,
1493 dsa + sizeof(struct siop_xfer_common) + Ent_ldsa_select);
1494 /* handle timeout */
1495 if (siop_cmd->status == CMDST_ACTIVE) {
1496 if ((siop_cmd->xs->xs_control &
1497 XS_CTL_POLL) == 0) {
1498 /* start exire timer */
1499 timeout = (u_int64_t) siop_cmd->xs->timeout *
1500 (u_int64_t)hz / 1000;
1501 if (timeout == 0)
1502 timeout = 1;
1503 callout_reset( &siop_cmd->xs->xs_callout,
1504 timeout, siop_timeout, siop_cmd);
1505 }
1506 }
1507 /*
1508 * Change JUMP cmd so that this slot will be handled
1509 */
1510 siop_script_write(sc, (Ent_script_sched_slot0 / 4) + slot * 2,
1511 0x80080000);
1512 sc->sc_currschedslot = slot;
1513 slot++;
1514 }
1515 if (doingready == 0) {
1516 /* now process ready list */
1517 doingready = 1;
1518 siop_cmd = TAILQ_FIRST(&sc->ready_list);
1519 goto again;
1520 }
1521
1522 end:
1523 /* if nothing changed no need to flush cache and wakeup script */
1524 if (newcmd == 0)
1525 return;
1526 /* make sure SCRIPT processor will read valid data */
1527 siop_script_sync(sc,BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1528 /* Signal script it has some work to do */
1529 bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_SIGP);
1530 /* and wait for IRQ */
1531 return;
1532 }
1533
1534 void
1535 siop_timeout(v)
1536 void *v;
1537 {
1538 struct siop_cmd *siop_cmd = v;
1539 struct siop_softc *sc = siop_cmd->siop_sc;
1540 int s;
1541
1542 scsi_print_addr(siop_cmd->xs->sc_link);
1543 printf("command timeout\n");
1544
1545 s = splbio();
1546 /* reset the scsi bus */
1547 siop_resetbus(sc);
1548
1549 /* deactivate callout */
1550 callout_stop(&siop_cmd->xs->xs_callout);
1551 /* mark command as being timed out; siop_intr will handle it */
1552 /*
1553 * mark command has being timed out and just return;
1554 * the bus reset will generate an interrupt,
1555 * it will be handled in siop_intr()
1556 */
1557 siop_cmd->flags |= CMDFL_TIMEOUT;
1558 splx(s);
1559 return;
1560
1561 }
1562
1563 void
1564 siop_dump_script(sc)
1565 struct siop_softc *sc;
1566 {
1567 int i;
1568 for (i = 0; i < NBPG / 4; i += 2) {
1569 printf("0x%04x: 0x%08x 0x%08x", i * 4,
1570 le32toh(sc->sc_script[i]), le32toh(sc->sc_script[i+1]));
1571 if ((le32toh(sc->sc_script[i]) & 0xe0000000) == 0xc0000000) {
1572 i++;
1573 printf(" 0x%08x", le32toh(sc->sc_script[i+1]));
1574 }
1575 printf("\n");
1576 }
1577 }
1578
1579 int
1580 siop_morecbd(sc)
1581 struct siop_softc *sc;
1582 {
1583 int error, i, j;
1584 bus_dma_segment_t seg;
1585 int rseg;
1586 struct siop_cbd *newcbd;
1587 bus_addr_t dsa;
1588 u_int32_t *scr;
1589
1590 /* allocate a new list head */
1591 newcbd = malloc(sizeof(struct siop_cbd), M_DEVBUF, M_NOWAIT);
1592 if (newcbd == NULL) {
1593 printf("%s: can't allocate memory for command descriptors "
1594 "head\n", sc->sc_dev.dv_xname);
1595 return ENOMEM;
1596 }
1597 memset(newcbd, 0, sizeof(struct siop_cbd));
1598
1599 /* allocate cmd list */
1600 newcbd->cmds =
1601 malloc(sizeof(struct siop_cmd) * SIOP_NCMDPB, M_DEVBUF, M_NOWAIT);
1602 if (newcbd->cmds == NULL) {
1603 printf("%s: can't allocate memory for command descriptors\n",
1604 sc->sc_dev.dv_xname);
1605 error = ENOMEM;
1606 goto bad3;
1607 }
1608 memset(newcbd->cmds, 0, sizeof(struct siop_cmd) * SIOP_NCMDPB);
1609 error = bus_dmamem_alloc(sc->sc_dmat, NBPG, NBPG, 0, &seg, 1, &rseg,
1610 BUS_DMA_NOWAIT);
1611 if (error) {
1612 printf("%s: unable to allocate cbd DMA memory, error = %d\n",
1613 sc->sc_dev.dv_xname, error);
1614 goto bad2;
1615 }
1616 error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, NBPG,
1617 (caddr_t *)&newcbd->xfers, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
1618 if (error) {
1619 printf("%s: unable to map cbd DMA memory, error = %d\n",
1620 sc->sc_dev.dv_xname, error);
1621 goto bad2;
1622 }
1623 error = bus_dmamap_create(sc->sc_dmat, NBPG, 1, NBPG, 0,
1624 BUS_DMA_NOWAIT, &newcbd->xferdma);
1625 if (error) {
1626 printf("%s: unable to create cbd DMA map, error = %d\n",
1627 sc->sc_dev.dv_xname, error);
1628 goto bad1;
1629 }
1630 error = bus_dmamap_load(sc->sc_dmat, newcbd->xferdma, newcbd->xfers,
1631 NBPG, NULL, BUS_DMA_NOWAIT);
1632 if (error) {
1633 printf("%s: unable to load cbd DMA map, error = %d\n",
1634 sc->sc_dev.dv_xname, error);
1635 goto bad0;
1636 }
1637 #ifdef DEBUG
1638 printf("%s: alloc newcdb at PHY addr 0x%lx\n", sc->sc_dev.dv_xname,
1639 (unsigned long)newcbd->xferdma->dm_segs[0].ds_addr);
1640 #endif
1641
1642 for (i = 0; i < SIOP_NCMDPB; i++) {
1643 error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, SIOP_NSG,
1644 MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1645 &newcbd->cmds[i].dmamap_data);
1646 if (error) {
1647 printf("%s: unable to create data DMA map for cbd: "
1648 "error %d\n",
1649 sc->sc_dev.dv_xname, error);
1650 goto bad0;
1651 }
1652 error = bus_dmamap_create(sc->sc_dmat,
1653 sizeof(struct scsipi_generic), 1,
1654 sizeof(struct scsipi_generic), 0,
1655 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
1656 &newcbd->cmds[i].dmamap_cmd);
1657 if (error) {
1658 printf("%s: unable to create cmd DMA map for cbd %d\n",
1659 sc->sc_dev.dv_xname, error);
1660 goto bad0;
1661 }
1662 newcbd->cmds[i].siop_sc = sc;
1663 newcbd->cmds[i].siop_cbdp = newcbd;
1664 newcbd->cmds[i].siop_xfer = &newcbd->xfers[i];
1665 memset(newcbd->cmds[i].siop_xfer, 0,
1666 sizeof(struct siop_xfer));
1667 newcbd->cmds[i].dsa = newcbd->xferdma->dm_segs[0].ds_addr +
1668 i * sizeof(struct siop_xfer);
1669 dsa = newcbd->cmds[i].dsa;
1670 newcbd->cmds[i].status = CMDST_FREE;
1671 newcbd->cmds[i].siop_tables.t_msgout.count= htole32(1);
1672 newcbd->cmds[i].siop_tables.t_msgout.addr = htole32(dsa);
1673 newcbd->cmds[i].siop_tables.t_msgin.count= htole32(1);
1674 newcbd->cmds[i].siop_tables.t_msgin.addr = htole32(dsa + 8);
1675 newcbd->cmds[i].siop_tables.t_extmsgin.count= htole32(2);
1676 newcbd->cmds[i].siop_tables.t_extmsgin.addr = htole32(dsa + 9);
1677 newcbd->cmds[i].siop_tables.t_extmsgdata.addr =
1678 htole32(dsa + 11);
1679 newcbd->cmds[i].siop_tables.t_status.count= htole32(1);
1680 newcbd->cmds[i].siop_tables.t_status.addr = htole32(dsa + 16);
1681
1682 /* The select/reselect script */
1683 scr = &newcbd->cmds[i].siop_xfer->resel[0];
1684 for (j = 0; j < sizeof(load_dsa) / sizeof(load_dsa[0]); j++)
1685 scr[j] = htole32(load_dsa[j]);
1686 /*
1687 * 0x78000000 is a 'move data8 to reg'. data8 is the second
1688 * octet, reg offset is the third.
1689 */
1690 scr[Ent_rdsa0 / 4] =
1691 htole32(0x78100000 | ((dsa & 0x000000ff) << 8));
1692 scr[Ent_rdsa1 / 4] =
1693 htole32(0x78110000 | ( dsa & 0x0000ff00 ));
1694 scr[Ent_rdsa2 / 4] =
1695 htole32(0x78120000 | ((dsa & 0x00ff0000) >> 8));
1696 scr[Ent_rdsa3 / 4] =
1697 htole32(0x78130000 | ((dsa & 0xff000000) >> 16));
1698 scr[E_ldsa_abs_reselected_Used[0]] =
1699 htole32(sc->sc_scriptaddr + Ent_reselected);
1700 scr[E_ldsa_abs_reselect_Used[0]] =
1701 htole32(sc->sc_scriptaddr + Ent_reselect);
1702 scr[E_ldsa_abs_selected_Used[0]] =
1703 htole32(sc->sc_scriptaddr + Ent_selected);
1704 scr[E_ldsa_abs_data_Used[0]] =
1705 htole32(dsa + sizeof(struct siop_xfer_common) +
1706 Ent_ldsa_data);
1707 /* JUMP foo, IF FALSE - used by MOVE MEMORY to clear the slot */
1708 scr[Ent_ldsa_data / 4] = htole32(0x80000000);
1709 TAILQ_INSERT_TAIL(&sc->free_list, &newcbd->cmds[i], next);
1710 #ifdef SIOP_DEBUG
1711 printf("tables[%d]: in=0x%x out=0x%x status=0x%x\n", i,
1712 le32toh(newcbd->cmds[i].siop_tables.t_msgin.addr),
1713 le32toh(newcbd->cmds[i].siop_tables.t_msgout.addr),
1714 le32toh(newcbd->cmds[i].siop_tables.t_status.addr));
1715 #endif
1716 }
1717 TAILQ_INSERT_TAIL(&sc->cmds, newcbd, next);
1718 return 0;
1719 bad0:
1720 bus_dmamap_destroy(sc->sc_dmat, newcbd->xferdma);
1721 bad1:
1722 bus_dmamem_free(sc->sc_dmat, &seg, rseg);
1723 bad2:
1724 free(newcbd->cmds, M_DEVBUF);
1725 bad3:
1726 free(newcbd, M_DEVBUF);
1727 return error;
1728 }
1729
1730 struct siop_lunsw *
1731 siop_get_lunsw(sc)
1732 struct siop_softc *sc;
1733 {
1734 struct siop_lunsw *lunsw;
1735 int i;
1736
1737 if (sc->script_free_lo + (sizeof(lun_switch) / sizeof(lun_switch[0])) >=
1738 sc->script_free_hi)
1739 return NULL;
1740 lunsw = TAILQ_FIRST(&sc->lunsw_list);
1741 if (lunsw != NULL) {
1742 #ifdef SIOP_DEBUG
1743 printf("siop_get_lunsw got lunsw at offset %d\n",
1744 lunsw->lunsw_off);
1745 #endif
1746 TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);
1747 return lunsw;
1748 }
1749 lunsw = malloc(sizeof(struct siop_lunsw), M_DEVBUF, M_NOWAIT);
1750 if (lunsw == NULL)
1751 return NULL;
1752 memset(lunsw, 0, sizeof(struct siop_lunsw));
1753 #ifdef SIOP_DEBUG
1754 printf("allocating lunsw at offset %d\n", sc->script_free_lo);
1755 #endif
1756 if (sc->features & SF_CHIP_RAM) {
1757 bus_space_write_region_4(sc->sc_ramt, sc->sc_ramh,
1758 sc->script_free_lo * 4, lun_switch,
1759 sizeof(lun_switch) / sizeof(lun_switch[0]));
1760 bus_space_write_4(sc->sc_ramt, sc->sc_ramh,
1761 (sc->script_free_lo + E_abs_lunsw_return_Used[0]) * 4,
1762 sc->sc_scriptaddr + Ent_lunsw_return);
1763 } else {
1764 for (i = 0; i < sizeof(lun_switch) / sizeof(lun_switch[0]);
1765 i++)
1766 sc->sc_script[sc->script_free_lo + i] =
1767 htole32(lun_switch[i]);
1768 sc->sc_script[sc->script_free_lo + E_abs_lunsw_return_Used[0]] =
1769 htole32(sc->sc_scriptaddr + Ent_lunsw_return);
1770 }
1771 lunsw->lunsw_off = sc->script_free_lo;
1772 lunsw->lunsw_size = sizeof(lun_switch) / sizeof(lun_switch[0]);
1773 sc->script_free_lo += lunsw->lunsw_size;
1774 if (sc->script_free_lo > 1024)
1775 printf("%s: script_free_lo (%d) > 1024\n", sc->sc_dev.dv_xname,
1776 sc->script_free_lo);
1777 siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1778 return lunsw;
1779 }
1780
1781 void
1782 siop_add_reselsw(sc, target)
1783 struct siop_softc *sc;
1784 int target;
1785 {
1786 int i;
1787 struct siop_lun *siop_lun;
1788 /*
1789 * add an entry to resel switch
1790 */
1791 siop_script_sync(sc, BUS_DMASYNC_POSTWRITE);
1792 for (i = 0; i < 15; i++) {
1793 sc->targets[target]->reseloff = Ent_resel_targ0 / 4 + i * 2;
1794 if ((siop_script_read(sc, sc->targets[target]->reseloff) & 0xff)
1795 == 0xff) { /* it's free */
1796 #ifdef SIOP_DEBUG
1797 printf("siop: target %d slot %d offset %d\n",
1798 target, i, sc->targets[target]->reseloff);
1799 #endif
1800 /* JUMP abs_foo, IF target | 0x80; */
1801 siop_script_write(sc, sc->targets[target]->reseloff,
1802 0x800c0080 | target);
1803 siop_script_write(sc, sc->targets[target]->reseloff + 1,
1804 sc->sc_scriptaddr +
1805 sc->targets[target]->lunsw->lunsw_off * 4 +
1806 Ent_lun_switch_entry);
1807 break;
1808 }
1809 }
1810 if (i == 15) /* no free slot, shouldn't happen */
1811 panic("siop: resel switch full");
1812
1813 sc->sc_ntargets++;
1814 for (i = 0; i < 8; i++) {
1815 siop_lun = sc->targets[target]->siop_lun[i];
1816 if (siop_lun == NULL)
1817 continue;
1818 if (siop_lun->reseloff > 0) {
1819 siop_lun->reseloff = 0;
1820 siop_add_dev(sc, target, i);
1821 }
1822 }
1823 siop_update_scntl3(sc, sc->targets[target]);
1824 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
1825 }
1826
1827 void
1828 siop_update_scntl3(sc, siop_target)
1829 struct siop_softc *sc;
1830 struct siop_target *siop_target;
1831 {
1832 /* MOVE target->id >> 24 TO SCNTL3 */
1833 siop_script_write(sc,
1834 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4),
1835 0x78030000 | ((siop_target->id >> 16) & 0x0000ff00));
1836 /* MOVE target->id >> 8 TO SXFER */
1837 siop_script_write(sc,
1838 siop_target->lunsw->lunsw_off + (Ent_restore_scntl3 / 4) + 2,
1839 0x78050000 | (siop_target->id & 0x0000ff00));
1840 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
1841 }
1842
1843 void
1844 siop_add_dev(sc, target, lun)
1845 struct siop_softc *sc;
1846 int target;
1847 int lun;
1848 {
1849 struct siop_lunsw *lunsw;
1850 struct siop_lun *siop_lun = sc->targets[target]->siop_lun[lun];
1851 int i, ntargets;
1852
1853 if (siop_lun->reseloff > 0)
1854 return;
1855 lunsw = sc->targets[target]->lunsw;
1856 if ((lunsw->lunsw_off + lunsw->lunsw_size) < sc->script_free_lo) {
1857 /*
1858 * can't extend this slot. Probably not worth trying to deal
1859 * with this case
1860 */
1861 #ifdef DEBUG
1862 printf("%s:%d:%d: can't allocate a lun sw slot\n",
1863 sc->sc_dev.dv_xname, target, lun);
1864 #endif
1865 return;
1866 }
1867 /* count how many free targets we still have to probe */
1868 ntargets = sc->sc_link.scsipi_scsi.max_target - 1 - sc->sc_ntargets;
1869
1870 /*
1871 * we need 8 bytes for the lun sw additionnal entry, and
1872 * eventually sizeof(tag_switch) for the tag switch entry.
1873 * Keep enouth free space for the free targets that could be
1874 * probed later.
1875 */
1876 if (sc->script_free_lo + 2 +
1877 (ntargets * sizeof(lun_switch) / sizeof(lun_switch[0])) >=
1878 ((sc->targets[target]->flags & TARF_TAG) ?
1879 sc->script_free_hi - (sizeof(tag_switch) / sizeof(tag_switch[0])) :
1880 sc->script_free_hi)) {
1881 /*
1882 * not enouth space, probably not worth dealing with it.
1883 * We can hold 13 tagged-queuing capable devices in the 4k RAM.
1884 */
1885 #ifdef DEBUG
1886 printf("%s:%d:%d: not enouth memory for a lun sw slot\n",
1887 sc->sc_dev.dv_xname, target, lun);
1888 #endif
1889 return;
1890 }
1891 #ifdef SIOP_DEBUG
1892 printf("%s:%d:%d: allocate lun sw entry\n",
1893 sc->sc_dev.dv_xname, target, lun);
1894 #endif
1895 /* INT int_resellun */
1896 siop_script_write(sc, sc->script_free_lo, 0x98080000);
1897 siop_script_write(sc, sc->script_free_lo + 1, A_int_resellun);
1898 /* Now the slot entry: JUMP abs_foo, IF lun */
1899 siop_script_write(sc, sc->script_free_lo - 2,
1900 0x800c0000 | lun);
1901 siop_script_write(sc, sc->script_free_lo - 1, 0);
1902 siop_lun->reseloff = sc->script_free_lo - 2;
1903 lunsw->lunsw_size += 2;
1904 sc->script_free_lo += 2;
1905 if (sc->targets[target]->flags & TARF_TAG) {
1906 /* we need a tag switch */
1907 sc->script_free_hi -=
1908 sizeof(tag_switch) / sizeof(tag_switch[0]);
1909 if (sc->features & SF_CHIP_RAM) {
1910 bus_space_write_region_4(sc->sc_ramt, sc->sc_ramh,
1911 sc->script_free_hi * 4, tag_switch,
1912 sizeof(tag_switch) / sizeof(tag_switch[0]));
1913 } else {
1914 for(i = 0;
1915 i < sizeof(tag_switch) / sizeof(tag_switch[0]);
1916 i++) {
1917 sc->sc_script[sc->script_free_hi + i] =
1918 htole32(tag_switch[i]);
1919 }
1920 }
1921 siop_script_write(sc,
1922 siop_lun->reseloff + 1,
1923 sc->sc_scriptaddr + sc->script_free_hi * 4 +
1924 Ent_tag_switch_entry);
1925
1926 for (i = 0; i < SIOP_NTAG; i++) {
1927 siop_lun->siop_tag[i].reseloff =
1928 sc->script_free_hi + (Ent_resel_tag0 / 4) + i * 2;
1929 }
1930 } else {
1931 /* non-tag case; just work with the lun switch */
1932 siop_lun->siop_tag[0].reseloff =
1933 sc->targets[target]->siop_lun[lun]->reseloff;
1934 }
1935 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
1936 }
1937
1938 void
1939 siop_del_dev(sc, target, lun)
1940 struct siop_softc *sc;
1941 int target;
1942 int lun;
1943 {
1944 int i;
1945 #ifdef SIOP_DEBUG
1946 printf("%s:%d:%d: free lun sw entry\n",
1947 sc->sc_dev.dv_xname, target, lun);
1948 #endif
1949 if (sc->targets[target] == NULL)
1950 return;
1951 free(sc->targets[target]->siop_lun[lun], M_DEVBUF);
1952 sc->targets[target]->siop_lun[lun] = NULL;
1953 /* XXX compact sw entry too ? */
1954 /* check if we can free the whole target */
1955 for (i = 0; i < 8; i++) {
1956 if (sc->targets[target]->siop_lun[i] != NULL)
1957 return;
1958 }
1959 #ifdef SIOP_DEBUG
1960 printf("%s: free siop_target for target %d lun %d lunsw offset %d\n",
1961 sc->sc_dev.dv_xname, target, lun,
1962 sc->targets[target]->lunsw->lunsw_off);
1963 #endif
1964 /*
1965 * nothing here, free the target struct and resel
1966 * switch entry
1967 */
1968 siop_script_write(sc, sc->targets[target]->reseloff, 0x800c00ff);
1969 siop_script_sync(sc, BUS_DMASYNC_PREWRITE);
1970 TAILQ_INSERT_TAIL(&sc->lunsw_list, sc->targets[target]->lunsw, next);
1971 free(sc->targets[target], M_DEVBUF);
1972 sc->targets[target] = NULL;
1973 sc->sc_ntargets--;
1974 }
1975
1976 #ifdef SIOP_STATS
1977 void
1978 siop_printstats()
1979 {
1980 printf("siop_stat_intr %d\n", siop_stat_intr);
1981 printf("siop_stat_intr_shortxfer %d\n", siop_stat_intr_shortxfer);
1982 printf("siop_stat_intr_xferdisc %d\n", siop_stat_intr_xferdisc);
1983 printf("siop_stat_intr_sdp %d\n", siop_stat_intr_sdp);
1984 printf("siop_stat_intr_done %d\n", siop_stat_intr_done);
1985 printf("siop_stat_intr_lunresel %d\n", siop_stat_intr_lunresel);
1986 printf("siop_stat_intr_qfull %d\n", siop_stat_intr_qfull);
1987 }
1988 #endif
1989