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