siop2.c revision 1.16.4.2 1 1.16.4.2 nathanw /* $NetBSD: siop2.c,v 1.16.4.2 2002/02/28 04:07:00 nathanw Exp $ */
2 1.16.4.2 nathanw
3 1.16.4.2 nathanw /*
4 1.16.4.2 nathanw * Copyright (c) 1994,1998 Michael L. Hitch
5 1.16.4.2 nathanw * Copyright (c) 1990 The Regents of the University of California.
6 1.16.4.2 nathanw * All rights reserved.
7 1.16.4.2 nathanw *
8 1.16.4.2 nathanw * This code is derived from software contributed to Berkeley by
9 1.16.4.2 nathanw * Van Jacobson of Lawrence Berkeley Laboratory.
10 1.16.4.2 nathanw *
11 1.16.4.2 nathanw * Redistribution and use in source and binary forms, with or without
12 1.16.4.2 nathanw * modification, are permitted provided that the following conditions
13 1.16.4.2 nathanw * are met:
14 1.16.4.2 nathanw * 1. Redistributions of source code must retain the above copyright
15 1.16.4.2 nathanw * notice, this list of conditions and the following disclaimer.
16 1.16.4.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
17 1.16.4.2 nathanw * notice, this list of conditions and the following disclaimer in the
18 1.16.4.2 nathanw * documentation and/or other materials provided with the distribution.
19 1.16.4.2 nathanw * 3. All advertising materials mentioning features or use of this software
20 1.16.4.2 nathanw * must display the following acknowledgement:
21 1.16.4.2 nathanw * This product includes software developed by the University of
22 1.16.4.2 nathanw * California, Berkeley and its contributors.
23 1.16.4.2 nathanw * 4. Neither the name of the University nor the names of its contributors
24 1.16.4.2 nathanw * may be used to endorse or promote products derived from this software
25 1.16.4.2 nathanw * without specific prior written permission.
26 1.16.4.2 nathanw *
27 1.16.4.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 1.16.4.2 nathanw * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 1.16.4.2 nathanw * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 1.16.4.2 nathanw * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 1.16.4.2 nathanw * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 1.16.4.2 nathanw * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 1.16.4.2 nathanw * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 1.16.4.2 nathanw * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 1.16.4.2 nathanw * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 1.16.4.2 nathanw * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 1.16.4.2 nathanw * SUCH DAMAGE.
38 1.16.4.2 nathanw *
39 1.16.4.2 nathanw * @(#)siop.c 7.5 (Berkeley) 5/4/91
40 1.16.4.2 nathanw */
41 1.16.4.2 nathanw
42 1.16.4.2 nathanw /*
43 1.16.4.2 nathanw * AMIGA 53C720/770 scsi adaptor driver
44 1.16.4.2 nathanw */
45 1.16.4.2 nathanw
46 1.16.4.2 nathanw #include "opt_ddb.h"
47 1.16.4.2 nathanw
48 1.16.4.2 nathanw #include <sys/cdefs.h>
49 1.16.4.2 nathanw __KERNEL_RCSID(0, "$NetBSD: siop2.c,v 1.16.4.2 2002/02/28 04:07:00 nathanw Exp $");
50 1.16.4.2 nathanw
51 1.16.4.2 nathanw #include <sys/param.h>
52 1.16.4.2 nathanw #include <sys/systm.h>
53 1.16.4.2 nathanw #include <sys/device.h>
54 1.16.4.2 nathanw #include <sys/disklabel.h>
55 1.16.4.2 nathanw #include <sys/dkstat.h>
56 1.16.4.2 nathanw #include <sys/buf.h>
57 1.16.4.2 nathanw #include <sys/malloc.h>
58 1.16.4.2 nathanw #include <dev/scsipi/scsi_all.h>
59 1.16.4.2 nathanw #include <dev/scsipi/scsipi_all.h>
60 1.16.4.2 nathanw #include <dev/scsipi/scsiconf.h>
61 1.16.4.2 nathanw #include <machine/cpu.h>
62 1.16.4.2 nathanw #ifdef __m68k__
63 1.16.4.2 nathanw #include <m68k/include/cacheops.h>
64 1.16.4.2 nathanw #endif
65 1.16.4.2 nathanw #include <amiga/amiga/custom.h>
66 1.16.4.2 nathanw #include <amiga/amiga/isr.h>
67 1.16.4.2 nathanw
68 1.16.4.2 nathanw #define ARCH_720
69 1.16.4.2 nathanw
70 1.16.4.2 nathanw #include <amiga/dev/siopreg.h>
71 1.16.4.2 nathanw #include <amiga/dev/siopvar.h>
72 1.16.4.2 nathanw
73 1.16.4.2 nathanw /*
74 1.16.4.2 nathanw * SCSI delays
75 1.16.4.2 nathanw * In u-seconds, primarily for state changes on the SPC.
76 1.16.4.2 nathanw */
77 1.16.4.2 nathanw #define SCSI_CMD_WAIT 500000 /* wait per step of 'immediate' cmds */
78 1.16.4.2 nathanw #define SCSI_DATA_WAIT 500000 /* wait per data in/out step */
79 1.16.4.2 nathanw #define SCSI_INIT_WAIT 500000 /* wait per step (both) during init */
80 1.16.4.2 nathanw
81 1.16.4.2 nathanw void siopng_select(struct siop_softc *);
82 1.16.4.2 nathanw void siopngabort(struct siop_softc *, siop_regmap_p, char *);
83 1.16.4.2 nathanw void siopngerror(struct siop_softc *, siop_regmap_p, u_char);
84 1.16.4.2 nathanw int siopng_checkintr(struct siop_softc *, u_char, u_char, u_short, int *);
85 1.16.4.2 nathanw void siopngreset(struct siop_softc *);
86 1.16.4.2 nathanw void siopngsetdelay(int);
87 1.16.4.2 nathanw void siopng_scsidone(struct siop_acb *, int);
88 1.16.4.2 nathanw void siopng_sched(struct siop_softc *);
89 1.16.4.2 nathanw void siopng_poll(struct siop_softc *, struct siop_acb *);
90 1.16.4.2 nathanw void siopngintr(struct siop_softc *);
91 1.16.4.2 nathanw void scsi_period_to_siopng(struct siop_softc *, int);
92 1.16.4.2 nathanw void siopng_start(struct siop_softc *, int, int, u_char *, int, u_char *, int);
93 1.16.4.2 nathanw void siopng_dump_acb(struct siop_acb *);
94 1.16.4.2 nathanw
95 1.16.4.2 nathanw /* 53C720/770 script */
96 1.16.4.2 nathanw
97 1.16.4.2 nathanw #include <amiga/dev/siop2_script.out>
98 1.16.4.2 nathanw
99 1.16.4.2 nathanw /* default to not inhibit sync negotiation on any drive */
100 1.16.4.2 nathanw u_char siopng_inhibit_sync[16] = {
101 1.16.4.2 nathanw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
102 1.16.4.2 nathanw }; /* initialize, so patchable */
103 1.16.4.2 nathanw
104 1.16.4.2 nathanw u_char siopng_inhibit_wide[16] = {
105 1.16.4.2 nathanw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106 1.16.4.2 nathanw }; /* initialize, so patchable */
107 1.16.4.2 nathanw
108 1.16.4.2 nathanw u_char siopng_allow_disc[16] = {
109 1.16.4.2 nathanw 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
110 1.16.4.2 nathanw };
111 1.16.4.2 nathanw
112 1.16.4.2 nathanw int siopng_no_dma = 0;
113 1.16.4.2 nathanw
114 1.16.4.2 nathanw int siopng_reset_delay = 250; /* delay after reset, in milleseconds */
115 1.16.4.2 nathanw
116 1.16.4.2 nathanw int siopng_cmd_wait = SCSI_CMD_WAIT;
117 1.16.4.2 nathanw int siopng_data_wait = SCSI_DATA_WAIT;
118 1.16.4.2 nathanw int siopng_init_wait = SCSI_INIT_WAIT;
119 1.16.4.2 nathanw
120 1.16.4.2 nathanw #define DEBUG_SYNC
121 1.16.4.2 nathanw
122 1.16.4.2 nathanw #ifdef DEBUG
123 1.16.4.2 nathanw /*
124 1.16.4.2 nathanw * 0x01 - full debug
125 1.16.4.2 nathanw * 0x02 - DMA chaining
126 1.16.4.2 nathanw * 0x04 - siopngintr
127 1.16.4.2 nathanw * 0x08 - phase mismatch
128 1.16.4.2 nathanw * 0x10 - <not used>
129 1.16.4.2 nathanw * 0x20 - panic on unhandled exceptions
130 1.16.4.2 nathanw * 0x100 - disconnect/reselect
131 1.16.4.2 nathanw */
132 1.16.4.2 nathanw int siopng_debug = 0;
133 1.16.4.2 nathanw int siopngsync_debug = 0;
134 1.16.4.2 nathanw int siopngdma_hits = 0;
135 1.16.4.2 nathanw int siopngdma_misses = 0;
136 1.16.4.2 nathanw int siopngchain_ints = 0;
137 1.16.4.2 nathanw int siopngstarts = 0;
138 1.16.4.2 nathanw int siopngints = 0;
139 1.16.4.2 nathanw int siopngphmm = 0;
140 1.16.4.2 nathanw #define SIOP_TRACE_SIZE 128
141 1.16.4.2 nathanw #define SIOP_TRACE(a,b,c,d) \
142 1.16.4.2 nathanw siopng_trbuf[siopng_trix] = (a); \
143 1.16.4.2 nathanw siopng_trbuf[siopng_trix+1] = (b); \
144 1.16.4.2 nathanw siopng_trbuf[siopng_trix+2] = (c); \
145 1.16.4.2 nathanw siopng_trbuf[siopng_trix+3] = (d); \
146 1.16.4.2 nathanw siopng_trix = (siopng_trix + 4) & (SIOP_TRACE_SIZE - 1);
147 1.16.4.2 nathanw u_char siopng_trbuf[SIOP_TRACE_SIZE];
148 1.16.4.2 nathanw int siopng_trix;
149 1.16.4.2 nathanw void siopng_dump(struct siop_softc *);
150 1.16.4.2 nathanw void siopng_dump_trace(void);
151 1.16.4.2 nathanw #else
152 1.16.4.2 nathanw #define SIOP_TRACE(a,b,c,d)
153 1.16.4.2 nathanw #endif
154 1.16.4.2 nathanw
155 1.16.4.2 nathanw
156 1.16.4.2 nathanw static char *siopng_chips[] = {
157 1.16.4.2 nathanw "720", "720SE", "770", "0x3",
158 1.16.4.2 nathanw "810A", "0x5", "0x6", "0x7",
159 1.16.4.2 nathanw "0x8", "0x9", "0xA", "0xB",
160 1.16.4.2 nathanw "0xC", "0xD", "0xE", "0xF",
161 1.16.4.2 nathanw };
162 1.16.4.2 nathanw
163 1.16.4.2 nathanw /*
164 1.16.4.2 nathanw * default minphys routine for siopng based controllers
165 1.16.4.2 nathanw */
166 1.16.4.2 nathanw void
167 1.16.4.2 nathanw siopng_minphys(struct buf *bp)
168 1.16.4.2 nathanw {
169 1.16.4.2 nathanw
170 1.16.4.2 nathanw /*
171 1.16.4.2 nathanw * No max transfer at this level.
172 1.16.4.2 nathanw */
173 1.16.4.2 nathanw minphys(bp);
174 1.16.4.2 nathanw }
175 1.16.4.2 nathanw
176 1.16.4.2 nathanw /*
177 1.16.4.2 nathanw * used by specific siopng controller
178 1.16.4.2 nathanw *
179 1.16.4.2 nathanw */
180 1.16.4.2 nathanw void
181 1.16.4.2 nathanw siopng_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
182 1.16.4.2 nathanw void *arg)
183 1.16.4.2 nathanw {
184 1.16.4.2 nathanw struct scsipi_xfer *xs;
185 1.16.4.2 nathanw struct scsipi_periph *periph;
186 1.16.4.2 nathanw struct siop_acb *acb;
187 1.16.4.2 nathanw struct siop_softc *sc = (void *)chan->chan_adapter->adapt_dev;
188 1.16.4.2 nathanw int flags, s;
189 1.16.4.2 nathanw
190 1.16.4.2 nathanw switch (req) {
191 1.16.4.2 nathanw case ADAPTER_REQ_RUN_XFER:
192 1.16.4.2 nathanw xs = arg;
193 1.16.4.2 nathanw periph = xs->xs_periph;
194 1.16.4.2 nathanw flags = xs->xs_control;
195 1.16.4.2 nathanw
196 1.16.4.2 nathanw /* XXXX ?? */
197 1.16.4.2 nathanw if (flags & XS_CTL_DATA_UIO)
198 1.16.4.2 nathanw panic("siopng: scsi data uio requested");
199 1.16.4.2 nathanw
200 1.16.4.2 nathanw /* XXXX ?? */
201 1.16.4.2 nathanw if (sc->sc_nexus && flags & XS_CTL_POLL)
202 1.16.4.2 nathanw /* panic("siopng_scsicmd: busy");*/
203 1.16.4.2 nathanw printf("siopng_scsicmd: busy\n");
204 1.16.4.2 nathanw
205 1.16.4.2 nathanw s = splbio();
206 1.16.4.2 nathanw acb = sc->free_list.tqh_first;
207 1.16.4.2 nathanw if (acb) {
208 1.16.4.2 nathanw TAILQ_REMOVE(&sc->free_list, acb, chain);
209 1.16.4.2 nathanw }
210 1.16.4.2 nathanw splx(s);
211 1.16.4.2 nathanw
212 1.16.4.2 nathanw #ifdef DIAGNOSTIC
213 1.16.4.2 nathanw /*
214 1.16.4.2 nathanw * This should never happen as we track the resources
215 1.16.4.2 nathanw * in the mid-layer.
216 1.16.4.2 nathanw */
217 1.16.4.2 nathanw if (acb == NULL) {
218 1.16.4.2 nathanw scsipi_printaddr(periph);
219 1.16.4.2 nathanw printf("unable to allocate acb\n");
220 1.16.4.2 nathanw panic("siopng_scsipi_request");
221 1.16.4.2 nathanw }
222 1.16.4.2 nathanw #endif
223 1.16.4.2 nathanw acb->flags = ACB_ACTIVE;
224 1.16.4.2 nathanw acb->xs = xs;
225 1.16.4.2 nathanw bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
226 1.16.4.2 nathanw acb->clen = xs->cmdlen;
227 1.16.4.2 nathanw acb->daddr = xs->data;
228 1.16.4.2 nathanw acb->dleft = xs->datalen;
229 1.16.4.2 nathanw
230 1.16.4.2 nathanw s = splbio();
231 1.16.4.2 nathanw TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
232 1.16.4.2 nathanw
233 1.16.4.2 nathanw if (sc->sc_nexus == NULL)
234 1.16.4.2 nathanw siopng_sched(sc);
235 1.16.4.2 nathanw
236 1.16.4.2 nathanw splx(s);
237 1.16.4.2 nathanw
238 1.16.4.2 nathanw if (flags & XS_CTL_POLL || siopng_no_dma)
239 1.16.4.2 nathanw siopng_poll(sc, acb);
240 1.16.4.2 nathanw return;
241 1.16.4.2 nathanw
242 1.16.4.2 nathanw case ADAPTER_REQ_GROW_RESOURCES:
243 1.16.4.2 nathanw return;
244 1.16.4.2 nathanw
245 1.16.4.2 nathanw case ADAPTER_REQ_SET_XFER_MODE:
246 1.16.4.2 nathanw return;
247 1.16.4.2 nathanw }
248 1.16.4.2 nathanw }
249 1.16.4.2 nathanw
250 1.16.4.2 nathanw void
251 1.16.4.2 nathanw siopng_poll(struct siop_softc *sc, struct siop_acb *acb)
252 1.16.4.2 nathanw {
253 1.16.4.2 nathanw siop_regmap_p rp = sc->sc_siopp;
254 1.16.4.2 nathanw struct scsipi_xfer *xs = acb->xs;
255 1.16.4.2 nathanw int i;
256 1.16.4.2 nathanw int status;
257 1.16.4.2 nathanw u_char istat;
258 1.16.4.2 nathanw u_char dstat;
259 1.16.4.2 nathanw u_short sist;
260 1.16.4.2 nathanw int s;
261 1.16.4.2 nathanw int to;
262 1.16.4.2 nathanw
263 1.16.4.2 nathanw s = splbio();
264 1.16.4.2 nathanw to = xs->timeout / 1000;
265 1.16.4.2 nathanw if (sc->nexus_list.tqh_first)
266 1.16.4.2 nathanw printf("%s: siopng_poll called with disconnected device\n",
267 1.16.4.2 nathanw sc->sc_dev.dv_xname);
268 1.16.4.2 nathanw for (;;) {
269 1.16.4.2 nathanw /* use cmd_wait values? */
270 1.16.4.2 nathanw i = 50000;
271 1.16.4.2 nathanw /* XXX spl0(); */
272 1.16.4.2 nathanw while (((istat = rp->siop_istat) &
273 1.16.4.2 nathanw (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) {
274 1.16.4.2 nathanw if (--i <= 0) {
275 1.16.4.2 nathanw #ifdef DEBUG
276 1.16.4.2 nathanw printf ("waiting: tgt %d cmd %02x sbcl %02x istat %02x sbdl %04x\n dsp %lx (+%lx) dcmd %lx ds %p timeout %d\n",
277 1.16.4.2 nathanw xs->xs_periph->periph_target, acb->cmd.opcode,
278 1.16.4.2 nathanw rp->siop_sbcl, istat, rp->siop_sbdl, rp->siop_dsp,
279 1.16.4.2 nathanw rp->siop_dsp - sc->sc_scriptspa,
280 1.16.4.2 nathanw *((long *)&rp->siop_dcmd), &acb->ds, acb->xs->timeout);
281 1.16.4.2 nathanw #endif
282 1.16.4.2 nathanw i = 50000;
283 1.16.4.2 nathanw --to;
284 1.16.4.2 nathanw if (to <= 0) {
285 1.16.4.2 nathanw siopngreset(sc);
286 1.16.4.2 nathanw return;
287 1.16.4.2 nathanw }
288 1.16.4.2 nathanw }
289 1.16.4.2 nathanw delay(20);
290 1.16.4.2 nathanw }
291 1.16.4.2 nathanw sist = rp->siop_sist;
292 1.16.4.2 nathanw dstat = rp->siop_dstat;
293 1.16.4.2 nathanw if (siopng_checkintr(sc, istat, dstat, sist, &status)) {
294 1.16.4.2 nathanw if (acb != sc->sc_nexus)
295 1.16.4.2 nathanw printf("%s: siopng_poll disconnected device completed\n",
296 1.16.4.2 nathanw sc->sc_dev.dv_xname);
297 1.16.4.2 nathanw else if ((sc->sc_flags & SIOP_INTDEFER) == 0) {
298 1.16.4.2 nathanw sc->sc_flags &= ~SIOP_INTSOFF;
299 1.16.4.2 nathanw rp->siop_sien = sc->sc_sien;
300 1.16.4.2 nathanw rp->siop_dien = sc->sc_dien;
301 1.16.4.2 nathanw }
302 1.16.4.2 nathanw siopng_scsidone(sc->sc_nexus, status);
303 1.16.4.2 nathanw }
304 1.16.4.2 nathanw if (xs->xs_status & XS_STS_DONE)
305 1.16.4.2 nathanw break;
306 1.16.4.2 nathanw }
307 1.16.4.2 nathanw splx(s);
308 1.16.4.2 nathanw }
309 1.16.4.2 nathanw
310 1.16.4.2 nathanw /*
311 1.16.4.2 nathanw * start next command that's ready
312 1.16.4.2 nathanw */
313 1.16.4.2 nathanw void
314 1.16.4.2 nathanw siopng_sched(struct siop_softc *sc)
315 1.16.4.2 nathanw {
316 1.16.4.2 nathanw struct scsipi_periph *periph;
317 1.16.4.2 nathanw struct siop_acb *acb;
318 1.16.4.2 nathanw int i;
319 1.16.4.2 nathanw
320 1.16.4.2 nathanw #ifdef DEBUG
321 1.16.4.2 nathanw if (sc->sc_nexus) {
322 1.16.4.2 nathanw printf("%s: siopng_sched- nexus %p/%d ready %p/%d\n",
323 1.16.4.2 nathanw sc->sc_dev.dv_xname, sc->sc_nexus,
324 1.16.4.2 nathanw sc->sc_nexus->xs->xs_periph->periph_target,
325 1.16.4.2 nathanw sc->ready_list.tqh_first,
326 1.16.4.2 nathanw sc->ready_list.tqh_first->xs->xs_periph->periph_target);
327 1.16.4.2 nathanw return;
328 1.16.4.2 nathanw }
329 1.16.4.2 nathanw #endif
330 1.16.4.2 nathanw for (acb = sc->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) {
331 1.16.4.2 nathanw periph = acb->xs->xs_periph;
332 1.16.4.2 nathanw i = periph->periph_target;
333 1.16.4.2 nathanw if(!(sc->sc_tinfo[i].lubusy & (1 << periph->periph_lun))) {
334 1.16.4.2 nathanw struct siop_tinfo *ti = &sc->sc_tinfo[i];
335 1.16.4.2 nathanw
336 1.16.4.2 nathanw TAILQ_REMOVE(&sc->ready_list, acb, chain);
337 1.16.4.2 nathanw sc->sc_nexus = acb;
338 1.16.4.2 nathanw periph = acb->xs->xs_periph;
339 1.16.4.2 nathanw ti = &sc->sc_tinfo[periph->periph_target];
340 1.16.4.2 nathanw ti->lubusy |= (1 << periph->periph_lun);
341 1.16.4.2 nathanw break;
342 1.16.4.2 nathanw }
343 1.16.4.2 nathanw }
344 1.16.4.2 nathanw
345 1.16.4.2 nathanw if (acb == NULL) {
346 1.16.4.2 nathanw #ifdef DEBUGXXX
347 1.16.4.2 nathanw printf("%s: siopng_sched didn't find ready command\n",
348 1.16.4.2 nathanw sc->sc_dev.dv_xname);
349 1.16.4.2 nathanw #endif
350 1.16.4.2 nathanw return;
351 1.16.4.2 nathanw }
352 1.16.4.2 nathanw
353 1.16.4.2 nathanw if (acb->xs->xs_control & XS_CTL_RESET)
354 1.16.4.2 nathanw siopngreset(sc);
355 1.16.4.2 nathanw
356 1.16.4.2 nathanw #if 0
357 1.16.4.2 nathanw acb->cmd.bytes[0] |= periph->periph_lun << 5; /* XXXX */
358 1.16.4.2 nathanw #endif
359 1.16.4.2 nathanw ++sc->sc_active;
360 1.16.4.2 nathanw siopng_select(sc);
361 1.16.4.2 nathanw }
362 1.16.4.2 nathanw
363 1.16.4.2 nathanw void
364 1.16.4.2 nathanw siopng_scsidone(struct siop_acb *acb, int stat)
365 1.16.4.2 nathanw {
366 1.16.4.2 nathanw struct scsipi_xfer *xs;
367 1.16.4.2 nathanw struct scsipi_periph *periph;
368 1.16.4.2 nathanw struct siop_softc *sc;
369 1.16.4.2 nathanw int dosched = 0;
370 1.16.4.2 nathanw
371 1.16.4.2 nathanw if (acb == NULL || (xs = acb->xs) == NULL) {
372 1.16.4.2 nathanw #ifdef DIAGNOSTIC
373 1.16.4.2 nathanw printf("siopng_scsidone: NULL acb or scsipi_xfer\n");
374 1.16.4.2 nathanw #if defined(DEBUG) && defined(DDB)
375 1.16.4.2 nathanw Debugger();
376 1.16.4.2 nathanw #endif
377 1.16.4.2 nathanw #endif
378 1.16.4.2 nathanw return;
379 1.16.4.2 nathanw }
380 1.16.4.2 nathanw periph = xs->xs_periph;
381 1.16.4.2 nathanw sc = (void *)periph->periph_channel->chan_adapter->adapt_dev;
382 1.16.4.2 nathanw
383 1.16.4.2 nathanw xs->status = stat;
384 1.16.4.2 nathanw xs->resid = 0; /* XXXX */
385 1.16.4.2 nathanw
386 1.16.4.2 nathanw if (xs->error == XS_NOERROR) {
387 1.16.4.2 nathanw if (stat == SCSI_CHECK || stat == SCSI_BUSY)
388 1.16.4.2 nathanw xs->error = XS_BUSY;
389 1.16.4.2 nathanw }
390 1.16.4.2 nathanw
391 1.16.4.2 nathanw /*
392 1.16.4.2 nathanw * Remove the ACB from whatever queue it's on. We have to do a bit of
393 1.16.4.2 nathanw * a hack to figure out which queue it's on. Note that it is *not*
394 1.16.4.2 nathanw * necessary to cdr down the ready queue, but we must cdr down the
395 1.16.4.2 nathanw * nexus queue and see if it's there, so we can mark the unit as no
396 1.16.4.2 nathanw * longer busy. This code is sickening, but it works.
397 1.16.4.2 nathanw */
398 1.16.4.2 nathanw if (acb == sc->sc_nexus) {
399 1.16.4.2 nathanw sc->sc_nexus = NULL;
400 1.16.4.2 nathanw sc->sc_tinfo[periph->periph_target].lubusy &=
401 1.16.4.2 nathanw ~(1<<periph->periph_lun);
402 1.16.4.2 nathanw if (sc->ready_list.tqh_first)
403 1.16.4.2 nathanw dosched = 1; /* start next command */
404 1.16.4.2 nathanw --sc->sc_active;
405 1.16.4.2 nathanw SIOP_TRACE('d','a',stat,0)
406 1.16.4.2 nathanw } else if (sc->ready_list.tqh_last == &acb->chain.tqe_next) {
407 1.16.4.2 nathanw TAILQ_REMOVE(&sc->ready_list, acb, chain);
408 1.16.4.2 nathanw SIOP_TRACE('d','r',stat,0)
409 1.16.4.2 nathanw } else {
410 1.16.4.2 nathanw register struct siop_acb *acb2;
411 1.16.4.2 nathanw for (acb2 = sc->nexus_list.tqh_first; acb2;
412 1.16.4.2 nathanw acb2 = acb2->chain.tqe_next)
413 1.16.4.2 nathanw if (acb2 == acb) {
414 1.16.4.2 nathanw TAILQ_REMOVE(&sc->nexus_list, acb, chain);
415 1.16.4.2 nathanw sc->sc_tinfo[periph->periph_target].lubusy
416 1.16.4.2 nathanw &= ~(1<<periph->periph_lun);
417 1.16.4.2 nathanw --sc->sc_active;
418 1.16.4.2 nathanw break;
419 1.16.4.2 nathanw }
420 1.16.4.2 nathanw if (acb2)
421 1.16.4.2 nathanw ;
422 1.16.4.2 nathanw else if (acb->chain.tqe_next) {
423 1.16.4.2 nathanw TAILQ_REMOVE(&sc->ready_list, acb, chain);
424 1.16.4.2 nathanw --sc->sc_active;
425 1.16.4.2 nathanw } else {
426 1.16.4.2 nathanw printf("%s: can't find matching acb\n",
427 1.16.4.2 nathanw sc->sc_dev.dv_xname);
428 1.16.4.2 nathanw #ifdef DDB
429 1.16.4.2 nathanw /* Debugger(); */
430 1.16.4.2 nathanw #endif
431 1.16.4.2 nathanw }
432 1.16.4.2 nathanw SIOP_TRACE('d','n',stat,0);
433 1.16.4.2 nathanw }
434 1.16.4.2 nathanw /* Put it on the free list. */
435 1.16.4.2 nathanw acb->flags = ACB_FREE;
436 1.16.4.2 nathanw TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
437 1.16.4.2 nathanw
438 1.16.4.2 nathanw sc->sc_tinfo[periph->periph_target].cmds++;
439 1.16.4.2 nathanw
440 1.16.4.2 nathanw scsipi_done(xs);
441 1.16.4.2 nathanw
442 1.16.4.2 nathanw if (dosched && sc->sc_nexus == NULL)
443 1.16.4.2 nathanw siopng_sched(sc);
444 1.16.4.2 nathanw }
445 1.16.4.2 nathanw
446 1.16.4.2 nathanw void
447 1.16.4.2 nathanw siopngabort(register struct siop_softc *sc, siop_regmap_p rp, char *where)
448 1.16.4.2 nathanw {
449 1.16.4.2 nathanw #ifdef fix_this
450 1.16.4.2 nathanw int i;
451 1.16.4.2 nathanw #endif
452 1.16.4.2 nathanw
453 1.16.4.2 nathanw printf ("%s: abort %s: dstat %02x, istat %02x sist %04x sien %04x sbcl %02x\n",
454 1.16.4.2 nathanw sc->sc_dev.dv_xname,
455 1.16.4.2 nathanw where, rp->siop_dstat, rp->siop_istat, rp->siop_sist,
456 1.16.4.2 nathanw rp->siop_sien, rp->siop_sbcl);
457 1.16.4.2 nathanw siopng_dump_registers(sc);
458 1.16.4.2 nathanw
459 1.16.4.2 nathanw if (sc->sc_active > 0) {
460 1.16.4.2 nathanw #ifdef TODO
461 1.16.4.2 nathanw SET_SBIC_cmd (rp, SBIC_CMD_ABORT);
462 1.16.4.2 nathanw WAIT_CIP (rp);
463 1.16.4.2 nathanw
464 1.16.4.2 nathanw GET_SBIC_asr (rp, asr);
465 1.16.4.2 nathanw if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI))
466 1.16.4.2 nathanw {
467 1.16.4.2 nathanw /* ok, get more drastic.. */
468 1.16.4.2 nathanw
469 1.16.4.2 nathanw SET_SBIC_cmd (rp, SBIC_CMD_RESET);
470 1.16.4.2 nathanw delay(25);
471 1.16.4.2 nathanw SBIC_WAIT(rp, SBIC_ASR_INT, 0);
472 1.16.4.2 nathanw GET_SBIC_csr (rp, csr); /* clears interrupt also */
473 1.16.4.2 nathanw
474 1.16.4.2 nathanw return;
475 1.16.4.2 nathanw }
476 1.16.4.2 nathanw
477 1.16.4.2 nathanw do
478 1.16.4.2 nathanw {
479 1.16.4.2 nathanw SBIC_WAIT (rp, SBIC_ASR_INT, 0);
480 1.16.4.2 nathanw GET_SBIC_csr (rp, csr);
481 1.16.4.2 nathanw }
482 1.16.4.2 nathanw while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
483 1.16.4.2 nathanw && (csr != SBIC_CSR_CMD_INVALID));
484 1.16.4.2 nathanw #endif
485 1.16.4.2 nathanw
486 1.16.4.2 nathanw /* lets just hope it worked.. */
487 1.16.4.2 nathanw #ifdef fix_this
488 1.16.4.2 nathanw for (i = 0; i < 2; ++i) {
489 1.16.4.2 nathanw if (sc->sc_iob[i].sc_xs && &sc->sc_iob[i] !=
490 1.16.4.2 nathanw sc->sc_cur) {
491 1.16.4.2 nathanw printf ("siopngabort: cleanup!\n");
492 1.16.4.2 nathanw sc->sc_iob[i].sc_xs = NULL;
493 1.16.4.2 nathanw }
494 1.16.4.2 nathanw }
495 1.16.4.2 nathanw #endif /* fix_this */
496 1.16.4.2 nathanw /* sc->sc_active = 0; */
497 1.16.4.2 nathanw }
498 1.16.4.2 nathanw }
499 1.16.4.2 nathanw
500 1.16.4.2 nathanw void
501 1.16.4.2 nathanw siopnginitialize(struct siop_softc *sc)
502 1.16.4.2 nathanw {
503 1.16.4.2 nathanw int i;
504 1.16.4.2 nathanw u_int inhibit_sync;
505 1.16.4.2 nathanw extern u_long scsi_nosync;
506 1.16.4.2 nathanw extern int shift_nosync;
507 1.16.4.2 nathanw
508 1.16.4.2 nathanw /*
509 1.16.4.2 nathanw * Need to check that scripts is on a long word boundary
510 1.16.4.2 nathanw * Also should verify that dev doesn't span non-contiguous
511 1.16.4.2 nathanw * physical pages.
512 1.16.4.2 nathanw */
513 1.16.4.2 nathanw sc->sc_scriptspa = kvtop((caddr_t)siopng_scripts);
514 1.16.4.2 nathanw
515 1.16.4.2 nathanw /*
516 1.16.4.2 nathanw * malloc sc_acb to ensure that DS is on a long word boundary.
517 1.16.4.2 nathanw */
518 1.16.4.2 nathanw
519 1.16.4.2 nathanw MALLOC(sc->sc_acb, struct siop_acb *,
520 1.16.4.2 nathanw sizeof(struct siop_acb) * SIOP_NACB, M_DEVBUF, M_NOWAIT);
521 1.16.4.2 nathanw if (sc->sc_acb == NULL)
522 1.16.4.2 nathanw panic("siopnginitialize: ACB malloc failed!");
523 1.16.4.2 nathanw
524 1.16.4.2 nathanw sc->sc_tcp[1] = 1000 / sc->sc_clock_freq;
525 1.16.4.2 nathanw sc->sc_tcp[2] = 1500 / sc->sc_clock_freq;
526 1.16.4.2 nathanw sc->sc_tcp[3] = 2000 / sc->sc_clock_freq;
527 1.16.4.2 nathanw sc->sc_minsync = sc->sc_tcp[1]; /* in 4ns units */
528 1.16.4.2 nathanw if (sc->sc_minsync < 25)
529 1.16.4.2 nathanw sc->sc_minsync = 25;
530 1.16.4.2 nathanw sc->sc_minsync >>= 1; /* Using clock doubler, allow Ultra */
531 1.16.4.2 nathanw if (sc->sc_clock_freq <= 25) {
532 1.16.4.2 nathanw sc->sc_dcntl |= 0x80; /* SCLK/1 */
533 1.16.4.2 nathanw sc->sc_tcp[0] = sc->sc_tcp[1];
534 1.16.4.2 nathanw } else if (sc->sc_clock_freq <= 37) {
535 1.16.4.2 nathanw sc->sc_dcntl |= 0x40; /* SCLK/1.5 */
536 1.16.4.2 nathanw sc->sc_tcp[0] = sc->sc_tcp[2];
537 1.16.4.2 nathanw } else if (sc->sc_clock_freq <= 50) {
538 1.16.4.2 nathanw sc->sc_dcntl |= 0x00; /* SCLK/2 */
539 1.16.4.2 nathanw sc->sc_tcp[0] = sc->sc_tcp[3];
540 1.16.4.2 nathanw } else {
541 1.16.4.2 nathanw sc->sc_dcntl |= 0xc0; /* SCLK/3 */
542 1.16.4.2 nathanw sc->sc_tcp[0] = 3000 / sc->sc_clock_freq;
543 1.16.4.2 nathanw }
544 1.16.4.2 nathanw
545 1.16.4.2 nathanw if (scsi_nosync) {
546 1.16.4.2 nathanw inhibit_sync = (scsi_nosync >> shift_nosync) & 0xffff;
547 1.16.4.2 nathanw shift_nosync += 16; /* XXX maxtarget */
548 1.16.4.2 nathanw #ifdef DEBUG
549 1.16.4.2 nathanw if (inhibit_sync)
550 1.16.4.2 nathanw printf("%s: Inhibiting synchronous transfer %02x\n",
551 1.16.4.2 nathanw sc->sc_dev.dv_xname, inhibit_sync);
552 1.16.4.2 nathanw #endif
553 1.16.4.2 nathanw for (i = 0; i < 16; ++i) /* XXX maxtarget */
554 1.16.4.2 nathanw if (inhibit_sync & (1 << i))
555 1.16.4.2 nathanw siopng_inhibit_sync[i] = 1;
556 1.16.4.2 nathanw }
557 1.16.4.2 nathanw
558 1.16.4.2 nathanw siopngreset (sc);
559 1.16.4.2 nathanw }
560 1.16.4.2 nathanw
561 1.16.4.2 nathanw void
562 1.16.4.2 nathanw siopngreset(struct siop_softc *sc)
563 1.16.4.2 nathanw {
564 1.16.4.2 nathanw siop_regmap_p rp;
565 1.16.4.2 nathanw u_int i, s;
566 1.16.4.2 nathanw u_short dummy;
567 1.16.4.2 nathanw struct siop_acb *acb;
568 1.16.4.2 nathanw
569 1.16.4.2 nathanw rp = sc->sc_siopp;
570 1.16.4.2 nathanw
571 1.16.4.2 nathanw if (sc->sc_flags & SIOP_ALIVE)
572 1.16.4.2 nathanw siopngabort(sc, rp, "reset");
573 1.16.4.2 nathanw
574 1.16.4.2 nathanw printf("%s: ", sc->sc_dev.dv_xname); /* XXXX */
575 1.16.4.2 nathanw
576 1.16.4.2 nathanw s = splbio();
577 1.16.4.2 nathanw
578 1.16.4.2 nathanw /*
579 1.16.4.2 nathanw * Reset the chip
580 1.16.4.2 nathanw * XXX - is this really needed?
581 1.16.4.2 nathanw */
582 1.16.4.2 nathanw rp->siop_istat |= SIOP_ISTAT_ABRT; /* abort current script */
583 1.16.4.2 nathanw rp->siop_istat |= SIOP_ISTAT_RST; /* reset chip */
584 1.16.4.2 nathanw rp->siop_istat &= ~SIOP_ISTAT_RST;
585 1.16.4.2 nathanw /*
586 1.16.4.2 nathanw * Reset SCSI bus (do we really want this?)
587 1.16.4.2 nathanw */
588 1.16.4.2 nathanw rp->siop_sien = 0;
589 1.16.4.2 nathanw rp->siop_scntl1 |= SIOP_SCNTL1_RST;
590 1.16.4.2 nathanw delay(1);
591 1.16.4.2 nathanw rp->siop_scntl1 &= ~SIOP_SCNTL1_RST;
592 1.16.4.2 nathanw
593 1.16.4.2 nathanw /*
594 1.16.4.2 nathanw * Set up various chip parameters
595 1.16.4.2 nathanw */
596 1.16.4.2 nathanw rp->siop_stest1 |= SIOP_STEST1_DBLEN; /* SCLK doubler enable */
597 1.16.4.2 nathanw delay(20);
598 1.16.4.2 nathanw rp->siop_stest3 |= SIOP_STEST3_HSC; /* Halt SCSI clock */
599 1.16.4.2 nathanw rp->siop_scntl3 = 0x15; /* SCF/CCF*/
600 1.16.4.2 nathanw rp->siop_stest1 |= SIOP_STEST1_DBLSEL; /* SCLK doubler select */
601 1.16.4.2 nathanw rp->siop_stest3 &= ~SIOP_STEST3_HSC; /* Clear Halt SCSI clock */
602 1.16.4.2 nathanw rp->siop_scntl0 = SIOP_ARB_FULL | /*SIOP_SCNTL0_EPC |*/ SIOP_SCNTL0_EPG;
603 1.16.4.2 nathanw rp->siop_dcntl = sc->sc_dcntl;
604 1.16.4.2 nathanw rp->siop_dmode = 0xc0; /* XXX burst length */
605 1.16.4.2 nathanw rp->siop_sien = 0x00; /* don't enable interrupts yet */
606 1.16.4.2 nathanw rp->siop_dien = 0x00; /* don't enable interrupts yet */
607 1.16.4.2 nathanw rp->siop_scid = sc->sc_channel.chan_id |
608 1.16.4.2 nathanw SIOP_SCID_RRE | SIOP_SCID_SRE;
609 1.16.4.2 nathanw rp->siop_respid = 1 << sc->sc_channel.chan_id;
610 1.16.4.2 nathanw rp->siop_dwt = 0x00;
611 1.16.4.2 nathanw rp->siop_stime0 = 0x0c; /* XXXXX check */
612 1.16.4.2 nathanw
613 1.16.4.2 nathanw /* will need to re-negotiate sync xfers */
614 1.16.4.2 nathanw bzero(&sc->sc_sync, sizeof (sc->sc_sync));
615 1.16.4.2 nathanw
616 1.16.4.2 nathanw i = rp->siop_istat;
617 1.16.4.2 nathanw if (i & SIOP_ISTAT_SIP)
618 1.16.4.2 nathanw dummy = rp->siop_sist;
619 1.16.4.2 nathanw if (i & SIOP_ISTAT_DIP)
620 1.16.4.2 nathanw dummy = rp->siop_dstat;
621 1.16.4.2 nathanw
622 1.16.4.2 nathanw splx (s);
623 1.16.4.2 nathanw
624 1.16.4.2 nathanw delay (siopng_reset_delay * 1000);
625 1.16.4.2 nathanw
626 1.16.4.2 nathanw /*
627 1.16.4.2 nathanw * is lower half unterminated?
628 1.16.4.2 nathanw */
629 1.16.4.2 nathanw if ((rp->siop_sbdl & 0x00ff) == 0x00ff) {
630 1.16.4.2 nathanw printf(" no SCSI termination, host adapter deactivated.\n");
631 1.16.4.2 nathanw sc->sc_channel.chan_ntargets = 0; /* XXX */
632 1.16.4.2 nathanw sc->sc_flags &= ~(SIOP_ALIVE|SIOP_INTDEFER|SIOP_INTSOFF);
633 1.16.4.2 nathanw /* disable SCSI and DMA interrupts */
634 1.16.4.2 nathanw sc->sc_sien = 0;
635 1.16.4.2 nathanw sc->sc_dien = 0;
636 1.16.4.2 nathanw rp->siop_sien = sc->sc_sien;
637 1.16.4.2 nathanw rp->siop_dien = sc->sc_dien;
638 1.16.4.2 nathanw
639 1.16.4.2 nathanw return;
640 1.16.4.2 nathanw }
641 1.16.4.2 nathanw
642 1.16.4.2 nathanw /*
643 1.16.4.2 nathanw * Check if upper half of SCSI bus is unterminated, and disallow
644 1.16.4.2 nathanw * disconnections if it appears to be unterminated.
645 1.16.4.2 nathanw */
646 1.16.4.2 nathanw if ((rp->siop_sbdl & 0xff00) == 0xff00) {
647 1.16.4.2 nathanw printf(" NO WIDE TERM");
648 1.16.4.2 nathanw /* XXX need to restrict maximum target ID as well? */
649 1.16.4.2 nathanw sc->sc_channel.chan_ntargets = 8;
650 1.16.4.2 nathanw for (i = 0; i < 16; ++i) {
651 1.16.4.2 nathanw siopng_allow_disc[i] = 0;
652 1.16.4.2 nathanw siopng_inhibit_wide[i] |= 0x80;
653 1.16.4.2 nathanw }
654 1.16.4.2 nathanw }
655 1.16.4.2 nathanw
656 1.16.4.2 nathanw printf("siopng type %s id %d reset V%d\n",
657 1.16.4.2 nathanw siopng_chips[rp->siop_macntl>>4],
658 1.16.4.2 nathanw sc->sc_channel.chan_ntargets,
659 1.16.4.2 nathanw rp->siop_ctest3 >> 4);
660 1.16.4.2 nathanw
661 1.16.4.2 nathanw if ((sc->sc_flags & SIOP_ALIVE) == 0) {
662 1.16.4.2 nathanw TAILQ_INIT(&sc->ready_list);
663 1.16.4.2 nathanw TAILQ_INIT(&sc->nexus_list);
664 1.16.4.2 nathanw TAILQ_INIT(&sc->free_list);
665 1.16.4.2 nathanw sc->sc_nexus = NULL;
666 1.16.4.2 nathanw acb = sc->sc_acb;
667 1.16.4.2 nathanw bzero(acb, sizeof(struct siop_acb) * SIOP_NACB);
668 1.16.4.2 nathanw for (i = 0; i < SIOP_NACB; i++) {
669 1.16.4.2 nathanw TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
670 1.16.4.2 nathanw acb++;
671 1.16.4.2 nathanw }
672 1.16.4.2 nathanw bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
673 1.16.4.2 nathanw } else {
674 1.16.4.2 nathanw if (sc->sc_nexus != NULL) {
675 1.16.4.2 nathanw sc->sc_nexus->xs->error = XS_RESET;
676 1.16.4.2 nathanw siopng_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]);
677 1.16.4.2 nathanw }
678 1.16.4.2 nathanw while ((acb = sc->nexus_list.tqh_first) > 0) {
679 1.16.4.2 nathanw acb->xs->error = XS_RESET;
680 1.16.4.2 nathanw siopng_scsidone(acb, acb->stat[0]);
681 1.16.4.2 nathanw }
682 1.16.4.2 nathanw }
683 1.16.4.2 nathanw
684 1.16.4.2 nathanw sc->sc_flags |= SIOP_ALIVE;
685 1.16.4.2 nathanw sc->sc_flags &= ~(SIOP_INTDEFER|SIOP_INTSOFF);
686 1.16.4.2 nathanw /* enable SCSI and DMA interrupts */
687 1.16.4.2 nathanw sc->sc_sien = SIOP_SIEN_MA | SIOP_SIEN_STO | /*SIOP_SIEN_GEN |*/
688 1.16.4.2 nathanw /*SIOP_SIEN_SEL |*/ SIOP_SIEN_SGE | SIOP_SIEN_UDC |
689 1.16.4.2 nathanw SIOP_SIEN_RST | SIOP_SIEN_PAR;
690 1.16.4.2 nathanw sc->sc_dien = SIOP_DIEN_BF | SIOP_DIEN_ABRT | SIOP_DIEN_SIR |
691 1.16.4.2 nathanw /*SIOP_DIEN_WTD |*/ SIOP_DIEN_IID;
692 1.16.4.2 nathanw rp->siop_sien = sc->sc_sien;
693 1.16.4.2 nathanw rp->siop_dien = sc->sc_dien;
694 1.16.4.2 nathanw /*siopng_dump_registers(sc);*/
695 1.16.4.2 nathanw }
696 1.16.4.2 nathanw
697 1.16.4.2 nathanw /*
698 1.16.4.2 nathanw * Setup Data Storage for 53C720/770 and start SCRIPTS processing
699 1.16.4.2 nathanw */
700 1.16.4.2 nathanw
701 1.16.4.2 nathanw void
702 1.16.4.2 nathanw siopng_start(struct siop_softc *sc, int target, int lun, u_char *cbuf,
703 1.16.4.2 nathanw int clen, u_char *buf, int len)
704 1.16.4.2 nathanw {
705 1.16.4.2 nathanw siop_regmap_p rp = sc->sc_siopp;
706 1.16.4.2 nathanw int nchain;
707 1.16.4.2 nathanw int count, tcount;
708 1.16.4.2 nathanw char *addr, *dmaend;
709 1.16.4.2 nathanw struct siop_acb *acb = sc->sc_nexus;
710 1.16.4.2 nathanw #ifdef DEBUG
711 1.16.4.2 nathanw int i;
712 1.16.4.2 nathanw #endif
713 1.16.4.2 nathanw
714 1.16.4.2 nathanw #ifdef DEBUG
715 1.16.4.2 nathanw if (siopng_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) {
716 1.16.4.2 nathanw printf ("ACK! siopng was busy: rp %p script %p dsa %p active %ld\n",
717 1.16.4.2 nathanw rp, &siopng_scripts, &acb->ds, sc->sc_active);
718 1.16.4.2 nathanw printf ("istat %02x sfbr %02x respid %02x sien %04x dien %02x\n",
719 1.16.4.2 nathanw rp->siop_istat, rp->siop_sfbr, rp->siop_respid,
720 1.16.4.2 nathanw rp->siop_sien, rp->siop_dien);
721 1.16.4.2 nathanw #ifdef DDB
722 1.16.4.2 nathanw /*Debugger();*/
723 1.16.4.2 nathanw #endif
724 1.16.4.2 nathanw }
725 1.16.4.2 nathanw #endif
726 1.16.4.2 nathanw acb->msgout[0] = MSG_IDENTIFY | lun;
727 1.16.4.2 nathanw if (siopng_allow_disc[target] & 2 ||
728 1.16.4.2 nathanw (siopng_allow_disc[target] && len == 0))
729 1.16.4.2 nathanw acb->msgout[0] = MSG_IDENTIFY_DR | lun;
730 1.16.4.2 nathanw acb->status = 0;
731 1.16.4.2 nathanw acb->stat[0] = -1;
732 1.16.4.2 nathanw acb->msg[0] = -1;
733 1.16.4.2 nathanw acb->ds.scsi_addr = (target << 16) | (sc->sc_sync[target].sxfer << 8) |
734 1.16.4.2 nathanw (sc->sc_sync[target].scntl3 << 24);
735 1.16.4.2 nathanw acb->ds.idlen = 1;
736 1.16.4.2 nathanw acb->ds.idbuf = (char *) kvtop(&acb->msgout[0]);
737 1.16.4.2 nathanw acb->ds.cmdlen = clen;
738 1.16.4.2 nathanw acb->ds.cmdbuf = (char *) kvtop(cbuf);
739 1.16.4.2 nathanw acb->ds.stslen = 1;
740 1.16.4.2 nathanw acb->ds.stsbuf = (char *) kvtop(&acb->stat[0]);
741 1.16.4.2 nathanw acb->ds.msglen = 1;
742 1.16.4.2 nathanw acb->ds.msgbuf = (char *) kvtop(&acb->msg[0]);
743 1.16.4.2 nathanw acb->msg[1] = -1;
744 1.16.4.2 nathanw acb->ds.msginlen = 1;
745 1.16.4.2 nathanw acb->ds.extmsglen = 1;
746 1.16.4.2 nathanw acb->ds.synmsglen = 3;
747 1.16.4.2 nathanw acb->ds.msginbuf = acb->ds.msgbuf + 1;
748 1.16.4.2 nathanw acb->ds.extmsgbuf = acb->ds.msginbuf + 1;
749 1.16.4.2 nathanw acb->ds.synmsgbuf = acb->ds.extmsgbuf + 1;
750 1.16.4.2 nathanw bzero(&acb->ds.chain, sizeof (acb->ds.chain));
751 1.16.4.2 nathanw
752 1.16.4.2 nathanw if (sc->sc_sync[target].state == NEG_WIDE) {
753 1.16.4.2 nathanw if (siopng_inhibit_wide[target]) {
754 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_SYNC;
755 1.16.4.2 nathanw sc->sc_sync[target].scntl3 &= ~SIOP_SCNTL3_EWS;
756 1.16.4.2 nathanw #ifdef DEBUG
757 1.16.4.2 nathanw if (siopngsync_debug)
758 1.16.4.2 nathanw printf ("Forcing target %d narrow\n", target);
759 1.16.4.2 nathanw #endif
760 1.16.4.2 nathanw }
761 1.16.4.2 nathanw else {
762 1.16.4.2 nathanw sc->sc_sync[target].scntl3 = 0x15 | /* XXX */
763 1.16.4.2 nathanw (sc->sc_sync[target].scntl3 & 0x88); /* XXX */
764 1.16.4.2 nathanw acb->msg[2] = -1;
765 1.16.4.2 nathanw acb->msgout[1] = MSG_EXT_MESSAGE;
766 1.16.4.2 nathanw acb->msgout[2] = 2;
767 1.16.4.2 nathanw acb->msgout[3] = MSG_WIDE_REQ;
768 1.16.4.2 nathanw acb->msgout[4] = 1;
769 1.16.4.2 nathanw acb->ds.idlen = 5;
770 1.16.4.2 nathanw acb->ds.synmsglen = 2;
771 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_WAITW;
772 1.16.4.2 nathanw #ifdef DEBUG
773 1.16.4.2 nathanw if (siopngsync_debug)
774 1.16.4.2 nathanw printf("Sending wide request to target %d\n", target);
775 1.16.4.2 nathanw #endif
776 1.16.4.2 nathanw }
777 1.16.4.2 nathanw }
778 1.16.4.2 nathanw if (sc->sc_sync[target].state == NEG_SYNC) {
779 1.16.4.2 nathanw if (siopng_inhibit_sync[target]) {
780 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_DONE;
781 1.16.4.2 nathanw sc->sc_sync[target].scntl3 = 5 | /* XXX */
782 1.16.4.2 nathanw (sc->sc_sync[target].scntl3 & 0x88); /* XXX */
783 1.16.4.2 nathanw sc->sc_sync[target].sxfer = 0;
784 1.16.4.2 nathanw #ifdef DEBUG
785 1.16.4.2 nathanw if (siopngsync_debug)
786 1.16.4.2 nathanw printf ("Forcing target %d asynchronous\n", target);
787 1.16.4.2 nathanw #endif
788 1.16.4.2 nathanw }
789 1.16.4.2 nathanw else {
790 1.16.4.2 nathanw sc->sc_sync[target].scntl3 = 0x15 | /* XXX */
791 1.16.4.2 nathanw (sc->sc_sync[target].scntl3 & 0x88); /* XXX */
792 1.16.4.2 nathanw acb->msg[2] = -1;
793 1.16.4.2 nathanw acb->msgout[1] = MSG_EXT_MESSAGE;
794 1.16.4.2 nathanw acb->msgout[2] = 3;
795 1.16.4.2 nathanw acb->msgout[3] = MSG_SYNC_REQ;
796 1.16.4.2 nathanw #ifdef MAXTOR_SYNC_KLUDGE
797 1.16.4.2 nathanw acb->msgout[4] = 50 / 4; /* ask for ridiculous period */
798 1.16.4.2 nathanw #else
799 1.16.4.2 nathanw acb->msgout[4] = sc->sc_minsync;
800 1.16.4.2 nathanw #endif
801 1.16.4.2 nathanw acb->msgout[5] = SIOP_MAX_OFFSET;
802 1.16.4.2 nathanw acb->ds.idlen = 6;
803 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_WAITS;
804 1.16.4.2 nathanw #ifdef DEBUG
805 1.16.4.2 nathanw if (siopngsync_debug)
806 1.16.4.2 nathanw printf ("Sending sync request to target %d\n", target);
807 1.16.4.2 nathanw #endif
808 1.16.4.2 nathanw }
809 1.16.4.2 nathanw }
810 1.16.4.2 nathanw
811 1.16.4.2 nathanw /*
812 1.16.4.2 nathanw * Build physical DMA addresses for scatter/gather I/O
813 1.16.4.2 nathanw */
814 1.16.4.2 nathanw acb->iob_buf = buf;
815 1.16.4.2 nathanw acb->iob_len = len;
816 1.16.4.2 nathanw acb->iob_curbuf = acb->iob_curlen = 0;
817 1.16.4.2 nathanw nchain = 0;
818 1.16.4.2 nathanw count = len;
819 1.16.4.2 nathanw addr = buf;
820 1.16.4.2 nathanw dmaend = NULL;
821 1.16.4.2 nathanw while (count > 0) {
822 1.16.4.2 nathanw acb->ds.chain[nchain].databuf = (char *) kvtop (addr);
823 1.16.4.2 nathanw if (count < (tcount = NBPG - ((int) addr & PGOFSET)))
824 1.16.4.2 nathanw tcount = count;
825 1.16.4.2 nathanw
826 1.16.4.2 nathanw #if DEBUG_ONLY_IF_DESPERATE
827 1.16.4.2 nathanw printf("chain[%d]: count %d tcount %d vaddr %p paddr %p\n",
828 1.16.4.2 nathanw nchain, count, tcount, addr,
829 1.16.4.2 nathanw acb->ds.chain[nchain].databuf);
830 1.16.4.2 nathanw #endif
831 1.16.4.2 nathanw acb->ds.chain[nchain].datalen = tcount;
832 1.16.4.2 nathanw addr += tcount;
833 1.16.4.2 nathanw count -= tcount;
834 1.16.4.2 nathanw if (acb->ds.chain[nchain].databuf == dmaend) {
835 1.16.4.2 nathanw dmaend += acb->ds.chain[nchain].datalen;
836 1.16.4.2 nathanw acb->ds.chain[nchain].datalen = 0;
837 1.16.4.2 nathanw acb->ds.chain[--nchain].datalen += tcount;
838 1.16.4.2 nathanw #ifdef DEBUG
839 1.16.4.2 nathanw ++siopngdma_hits;
840 1.16.4.2 nathanw #endif
841 1.16.4.2 nathanw }
842 1.16.4.2 nathanw else {
843 1.16.4.2 nathanw dmaend = acb->ds.chain[nchain].databuf +
844 1.16.4.2 nathanw acb->ds.chain[nchain].datalen;
845 1.16.4.2 nathanw acb->ds.chain[nchain].datalen = tcount;
846 1.16.4.2 nathanw #ifdef DEBUG
847 1.16.4.2 nathanw if (nchain) /* Don't count miss on first one */
848 1.16.4.2 nathanw ++siopngdma_misses;
849 1.16.4.2 nathanw #endif
850 1.16.4.2 nathanw }
851 1.16.4.2 nathanw ++nchain;
852 1.16.4.2 nathanw }
853 1.16.4.2 nathanw #ifdef DEBUG
854 1.16.4.2 nathanw if (nchain != 1 && len != 0 && siopng_debug & 3) {
855 1.16.4.2 nathanw printf ("DMA chaining set: %d\n", nchain);
856 1.16.4.2 nathanw for (i = 0; i < nchain; ++i) {
857 1.16.4.2 nathanw printf (" [%d] %8p %lx\n", i, acb->ds.chain[i].databuf,
858 1.16.4.2 nathanw acb->ds.chain[i].datalen);
859 1.16.4.2 nathanw }
860 1.16.4.2 nathanw }
861 1.16.4.2 nathanw #endif
862 1.16.4.2 nathanw
863 1.16.4.2 nathanw /* push data cache for all data the 53c720/770 needs to access */
864 1.16.4.2 nathanw dma_cachectl ((caddr_t)acb, sizeof (struct siop_acb));
865 1.16.4.2 nathanw dma_cachectl (cbuf, clen);
866 1.16.4.2 nathanw if (buf != NULL && len != 0)
867 1.16.4.2 nathanw dma_cachectl (buf, len);
868 1.16.4.2 nathanw #ifdef DEBUG
869 1.16.4.2 nathanw if (siopng_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) {
870 1.16.4.2 nathanw printf ("ACK! siopng was busy at start: rp %p script %p dsa %p active %ld\n",
871 1.16.4.2 nathanw rp, &siopng_scripts, &acb->ds, sc->sc_active);
872 1.16.4.2 nathanw #ifdef DDB
873 1.16.4.2 nathanw /*Debugger();*/
874 1.16.4.2 nathanw #endif
875 1.16.4.2 nathanw }
876 1.16.4.2 nathanw #endif
877 1.16.4.2 nathanw if (sc->nexus_list.tqh_first == NULL) {
878 1.16.4.2 nathanw if (rp->siop_istat & SIOP_ISTAT_CON)
879 1.16.4.2 nathanw printf("%s: siopng_select while connected?\n",
880 1.16.4.2 nathanw sc->sc_dev.dv_xname);
881 1.16.4.2 nathanw rp->siop_temp = 0;
882 1.16.4.2 nathanw #ifndef FIXME
883 1.16.4.2 nathanw rp->siop_scntl3 = sc->sc_sync[target].scntl3;
884 1.16.4.2 nathanw #endif
885 1.16.4.2 nathanw rp->siop_dsa = kvtop((caddr_t)&acb->ds);
886 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa;
887 1.16.4.2 nathanw SIOP_TRACE('s',1,0,0)
888 1.16.4.2 nathanw } else {
889 1.16.4.2 nathanw if ((rp->siop_istat & SIOP_ISTAT_CON) == 0) {
890 1.16.4.2 nathanw rp->siop_istat = SIOP_ISTAT_SIGP;
891 1.16.4.2 nathanw SIOP_TRACE('s',2,0,0);
892 1.16.4.2 nathanw }
893 1.16.4.2 nathanw else {
894 1.16.4.2 nathanw SIOP_TRACE('s',3,rp->siop_istat,0);
895 1.16.4.2 nathanw }
896 1.16.4.2 nathanw }
897 1.16.4.2 nathanw #ifdef DEBUG
898 1.16.4.2 nathanw ++siopngstarts;
899 1.16.4.2 nathanw #endif
900 1.16.4.2 nathanw }
901 1.16.4.2 nathanw
902 1.16.4.2 nathanw /*
903 1.16.4.2 nathanw * Process a DMA or SCSI interrupt from the 53C720/770 SIOP
904 1.16.4.2 nathanw */
905 1.16.4.2 nathanw
906 1.16.4.2 nathanw int
907 1.16.4.2 nathanw siopng_checkintr(struct siop_softc *sc, u_char istat, u_char dstat,
908 1.16.4.2 nathanw u_short sist, int *status)
909 1.16.4.2 nathanw {
910 1.16.4.2 nathanw siop_regmap_p rp = sc->sc_siopp;
911 1.16.4.2 nathanw struct siop_acb *acb = sc->sc_nexus;
912 1.16.4.2 nathanw int target = 0;
913 1.16.4.2 nathanw int dfifo, dbc, sstat0, sstat1, sstat2;
914 1.16.4.2 nathanw
915 1.16.4.2 nathanw dfifo = rp->siop_dfifo;
916 1.16.4.2 nathanw dbc = rp->siop_dbc0;
917 1.16.4.2 nathanw sstat0 = rp->siop_sstat0;
918 1.16.4.2 nathanw sstat1 = rp->siop_sstat1;
919 1.16.4.2 nathanw sstat2 = rp->siop_sstat2;
920 1.16.4.2 nathanw rp->siop_ctest3 |= SIOP_CTEST8_CLF;
921 1.16.4.2 nathanw while ((rp->siop_ctest1 & SIOP_CTEST1_FMT) != SIOP_CTEST1_FMT)
922 1.16.4.2 nathanw ;
923 1.16.4.2 nathanw rp->siop_ctest3 &= ~SIOP_CTEST8_CLF;
924 1.16.4.2 nathanw #ifdef DEBUG
925 1.16.4.2 nathanw ++siopngints;
926 1.16.4.2 nathanw #if 0
927 1.16.4.2 nathanw if (siopng_debug & 0x100) {
928 1.16.4.2 nathanw DCIAS(&acb->stat[0]); /* XXX */
929 1.16.4.2 nathanw printf ("siopngchkintr: istat %x dstat %x sist %x dsps %x sbcl %x sts %x msg %x\n",
930 1.16.4.2 nathanw istat, dstat, sist, rp->siop_dsps, rp->siop_sbcl, acb->stat[0], acb->msg[0]);
931 1.16.4.2 nathanw printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
932 1.16.4.2 nathanw acb->msg[0], acb->msg[1], acb->msg[2],
933 1.16.4.2 nathanw acb->msg[3], acb->msg[4], acb->msg[5]);
934 1.16.4.2 nathanw }
935 1.16.4.2 nathanw #endif
936 1.16.4.2 nathanw if (rp->siop_dsp && (rp->siop_dsp < sc->sc_scriptspa ||
937 1.16.4.2 nathanw rp->siop_dsp >= sc->sc_scriptspa + sizeof(siopng_scripts))) {
938 1.16.4.2 nathanw printf ("%s: dsp not within script dsp %lx scripts %lx:%lx",
939 1.16.4.2 nathanw sc->sc_dev.dv_xname, rp->siop_dsp, sc->sc_scriptspa,
940 1.16.4.2 nathanw sc->sc_scriptspa + sizeof(siopng_scripts));
941 1.16.4.2 nathanw printf(" istat %x dstat %x sist %x\n",
942 1.16.4.2 nathanw istat, dstat, sist);
943 1.16.4.2 nathanw #ifdef DDB
944 1.16.4.2 nathanw Debugger();
945 1.16.4.2 nathanw #endif
946 1.16.4.2 nathanw }
947 1.16.4.2 nathanw #endif
948 1.16.4.2 nathanw SIOP_TRACE('i',dstat,istat,(istat&SIOP_ISTAT_DIP)?rp->siop_dsps&0xff:sist);
949 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff00) {
950 1.16.4.2 nathanw /* Normal completion status, or check condition */
951 1.16.4.2 nathanw #ifdef DEBUG
952 1.16.4.2 nathanw if (rp->siop_dsa != kvtop((caddr_t)&acb->ds)) {
953 1.16.4.2 nathanw printf ("siopng: invalid dsa: %lx %x\n", rp->siop_dsa,
954 1.16.4.2 nathanw kvtop((caddr_t)&acb->ds));
955 1.16.4.2 nathanw panic("*** siopng DSA invalid ***");
956 1.16.4.2 nathanw }
957 1.16.4.2 nathanw #endif
958 1.16.4.2 nathanw target = acb->xs->xs_periph->periph_target;
959 1.16.4.2 nathanw if (sc->sc_sync[target].state == NEG_WAITW) {
960 1.16.4.2 nathanw if (acb->msg[1] == 0xff)
961 1.16.4.2 nathanw printf ("%s: target %d ignored wide request\n",
962 1.16.4.2 nathanw sc->sc_dev.dv_xname, target);
963 1.16.4.2 nathanw else if (acb->msg[1] == MSG_REJECT)
964 1.16.4.2 nathanw printf ("%s: target %d rejected wide request\n",
965 1.16.4.2 nathanw sc->sc_dev.dv_xname, target);
966 1.16.4.2 nathanw else {
967 1.16.4.2 nathanw printf("%s: target %d (wide) %02x %02x %02x %02x\n",
968 1.16.4.2 nathanw sc->sc_dev.dv_xname, target, acb->msg[1],
969 1.16.4.2 nathanw acb->msg[2], acb->msg[3], acb->msg[4]);
970 1.16.4.2 nathanw if (acb->msg[1] == MSG_EXT_MESSAGE &&
971 1.16.4.2 nathanw acb->msg[2] == 2 &&
972 1.16.4.2 nathanw acb->msg[3] == MSG_WIDE_REQ)
973 1.16.4.2 nathanw sc->sc_sync[target].scntl3 = acb->msg[4] ?
974 1.16.4.2 nathanw sc->sc_sync[target].scntl3 | SIOP_SCNTL3_EWS :
975 1.16.4.2 nathanw sc->sc_sync[target].scntl3 & ~SIOP_SCNTL3_EWS;
976 1.16.4.2 nathanw }
977 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_SYNC;
978 1.16.4.2 nathanw }
979 1.16.4.2 nathanw if (sc->sc_sync[target].state == NEG_WAITS) {
980 1.16.4.2 nathanw if (acb->msg[1] == 0xff)
981 1.16.4.2 nathanw printf ("%s: target %d ignored sync request\n",
982 1.16.4.2 nathanw sc->sc_dev.dv_xname, target);
983 1.16.4.2 nathanw else if (acb->msg[1] == MSG_REJECT)
984 1.16.4.2 nathanw printf ("%s: target %d rejected sync request\n",
985 1.16.4.2 nathanw sc->sc_dev.dv_xname, target);
986 1.16.4.2 nathanw else
987 1.16.4.2 nathanw /* XXX - need to set sync transfer parameters */
988 1.16.4.2 nathanw printf("%s: target %d (sync) %02x %02x %02x\n",
989 1.16.4.2 nathanw sc->sc_dev.dv_xname, target, acb->msg[1],
990 1.16.4.2 nathanw acb->msg[2], acb->msg[3]);
991 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_DONE;
992 1.16.4.2 nathanw }
993 1.16.4.2 nathanw dma_cachectl(&acb->stat[0], 1);
994 1.16.4.2 nathanw *status = acb->stat[0];
995 1.16.4.2 nathanw #ifdef DEBUG
996 1.16.4.2 nathanw if (rp->siop_sbcl & SIOP_BSY) {
997 1.16.4.2 nathanw /*printf ("ACK! siop was busy at end: rp %x script %x dsa %x\n",
998 1.16.4.2 nathanw rp, &siopng_scripts, &acb->ds);*/
999 1.16.4.2 nathanw #ifdef DDB
1000 1.16.4.2 nathanw /*Debugger();*/
1001 1.16.4.2 nathanw #endif
1002 1.16.4.2 nathanw }
1003 1.16.4.2 nathanw if (acb->msg[0] != 0x00)
1004 1.16.4.2 nathanw printf("%s: message was not COMMAND COMPLETE: %x\n",
1005 1.16.4.2 nathanw sc->sc_dev.dv_xname, acb->msg[0]);
1006 1.16.4.2 nathanw #endif
1007 1.16.4.2 nathanw if (sc->nexus_list.tqh_first)
1008 1.16.4.2 nathanw rp->siop_dcntl |= SIOP_DCNTL_STD;
1009 1.16.4.2 nathanw return 1;
1010 1.16.4.2 nathanw }
1011 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0b) {
1012 1.16.4.2 nathanw target = acb->xs->xs_periph->periph_target;
1013 1.16.4.2 nathanw if (acb->msg[1] == MSG_EXT_MESSAGE && acb->msg[2] == 2 &&
1014 1.16.4.2 nathanw acb->msg[3] == MSG_WIDE_REQ) {
1015 1.16.4.2 nathanw #ifdef DEBUG
1016 1.16.4.2 nathanw if (siopngsync_debug)
1017 1.16.4.2 nathanw printf ("wide msg in: %02x %02x %02x %02x %02x %02x\n",
1018 1.16.4.2 nathanw acb->msg[0], acb->msg[1], acb->msg[2],
1019 1.16.4.2 nathanw acb->msg[3], acb->msg[4], acb->msg[5]);
1020 1.16.4.2 nathanw #endif
1021 1.16.4.2 nathanw sc->sc_sync[target].scntl3 &= ~(SIOP_SCNTL3_EWS);
1022 1.16.4.2 nathanw if (acb->msg[2] == 2 &&
1023 1.16.4.2 nathanw acb->msg[3] == MSG_WIDE_REQ &&
1024 1.16.4.2 nathanw acb->msg[4] != 0) {
1025 1.16.4.2 nathanw sc->sc_sync[target].scntl3 |= SIOP_SCNTL3_EWS;
1026 1.16.4.2 nathanw printf ("%s: target %d now wide %d\n",
1027 1.16.4.2 nathanw sc->sc_dev.dv_xname, target,
1028 1.16.4.2 nathanw acb->msg[4]);
1029 1.16.4.2 nathanw }
1030 1.16.4.2 nathanw rp->siop_scntl3 = sc->sc_sync[target].scntl3;
1031 1.16.4.2 nathanw if (sc->sc_sync[target].state == NEG_WAITW) {
1032 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_SYNC;
1033 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_clear_ack;
1034 1.16.4.2 nathanw return(0);
1035 1.16.4.2 nathanw }
1036 1.16.4.2 nathanw rp->siop_dcntl |= SIOP_DCNTL_STD;
1037 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_SYNC;
1038 1.16.4.2 nathanw return (0);
1039 1.16.4.2 nathanw }
1040 1.16.4.2 nathanw if (acb->msg[1] == MSG_EXT_MESSAGE && acb->msg[2] == 3 &&
1041 1.16.4.2 nathanw acb->msg[3] == MSG_SYNC_REQ) {
1042 1.16.4.2 nathanw #ifdef DEBUG
1043 1.16.4.2 nathanw if (siopngsync_debug)
1044 1.16.4.2 nathanw printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
1045 1.16.4.2 nathanw acb->msg[0], acb->msg[1], acb->msg[2],
1046 1.16.4.2 nathanw acb->msg[3], acb->msg[4], acb->msg[5]);
1047 1.16.4.2 nathanw #endif
1048 1.16.4.2 nathanw sc->sc_sync[target].sxfer = 0;
1049 1.16.4.2 nathanw sc->sc_sync[target].scntl3 = 5 | /* XXX */
1050 1.16.4.2 nathanw (sc->sc_sync[target].scntl3 & 0x88); /* XXX */
1051 1.16.4.2 nathanw if (acb->msg[2] == 3 &&
1052 1.16.4.2 nathanw acb->msg[3] == MSG_SYNC_REQ &&
1053 1.16.4.2 nathanw acb->msg[5] != 0) {
1054 1.16.4.2 nathanw #ifdef MAXTOR_KLUDGE
1055 1.16.4.2 nathanw /*
1056 1.16.4.2 nathanw * Kludge for my Maxtor XT8580S
1057 1.16.4.2 nathanw * It accepts whatever we request, even
1058 1.16.4.2 nathanw * though it won't work. So we ask for
1059 1.16.4.2 nathanw * a short period than we can handle. If
1060 1.16.4.2 nathanw * the device says it can do it, use 208ns.
1061 1.16.4.2 nathanw * If the device says it can do less than
1062 1.16.4.2 nathanw * 100ns, then we limit it to 100ns.
1063 1.16.4.2 nathanw */
1064 1.16.4.2 nathanw if (acb->msg[4] && acb->msg[4] < 100 / 4) {
1065 1.16.4.2 nathanw #ifdef DEBUG
1066 1.16.4.2 nathanw printf ("%d: target %d wanted %dns period\n",
1067 1.16.4.2 nathanw sc->sc_dev.dv_xname, target,
1068 1.16.4.2 nathanw acb->msg[4] * 4);
1069 1.16.4.2 nathanw #endif
1070 1.16.4.2 nathanw if (acb->msg[4] == 50 / 4)
1071 1.16.4.2 nathanw acb->msg[4] = 208 / 4;
1072 1.16.4.2 nathanw else
1073 1.16.4.2 nathanw acb->msg[4] = 100 / 4;
1074 1.16.4.2 nathanw }
1075 1.16.4.2 nathanw #endif /* MAXTOR_KLUDGE */
1076 1.16.4.2 nathanw printf ("%s: target %d now synchronous, period=%dns, offset=%d\n",
1077 1.16.4.2 nathanw sc->sc_dev.dv_xname, target,
1078 1.16.4.2 nathanw (acb->msg[4] == 12) ? 50 : acb->msg[4] * 4,
1079 1.16.4.2 nathanw acb->msg[5]);
1080 1.16.4.2 nathanw scsi_period_to_siopng (sc, target);
1081 1.16.4.2 nathanw }
1082 1.16.4.2 nathanw rp->siop_sxfer = sc->sc_sync[target].sxfer;
1083 1.16.4.2 nathanw rp->siop_scntl3 = sc->sc_sync[target].scntl3;
1084 1.16.4.2 nathanw if (sc->sc_sync[target].state == NEG_WAITS) {
1085 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_DONE;
1086 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_clear_ack;
1087 1.16.4.2 nathanw return(0);
1088 1.16.4.2 nathanw }
1089 1.16.4.2 nathanw rp->siop_dcntl |= SIOP_DCNTL_STD;
1090 1.16.4.2 nathanw sc->sc_sync[target].state = NEG_DONE;
1091 1.16.4.2 nathanw return (0);
1092 1.16.4.2 nathanw }
1093 1.16.4.2 nathanw /* XXX - not SDTR message */
1094 1.16.4.2 nathanw }
1095 1.16.4.2 nathanw if (sist & SIOP_SIST_MA) { /* Phase mismatch */
1096 1.16.4.2 nathanw #ifdef DEBUG
1097 1.16.4.2 nathanw ++siopngphmm;
1098 1.16.4.2 nathanw if (acb == NULL)
1099 1.16.4.2 nathanw printf("%s: Phase mismatch with no active command?\n",
1100 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1101 1.16.4.2 nathanw #endif
1102 1.16.4.2 nathanw if (acb->iob_len) {
1103 1.16.4.2 nathanw int adjust;
1104 1.16.4.2 nathanw adjust = ((dfifo - (dbc & 0x7f)) & 0x7f);
1105 1.16.4.2 nathanw if (sstat0 & SIOP_SSTAT0_OLF) /* sstat0 SODL lsb */
1106 1.16.4.2 nathanw ++adjust;
1107 1.16.4.2 nathanw if (sstat0 & SIOP_SSTAT0_ORF) /* sstat0 SODR lsb */
1108 1.16.4.2 nathanw ++adjust;
1109 1.16.4.2 nathanw if (sstat2 & SIOP_SSTAT2_OLF1) /* sstat2 SODL msb */
1110 1.16.4.2 nathanw ++adjust;
1111 1.16.4.2 nathanw if (sstat2 & SIOP_SSTAT2_ORF1) /* sstat2 SODR msb */
1112 1.16.4.2 nathanw ++adjust;
1113 1.16.4.2 nathanw acb->iob_curlen = *((long *)&rp->siop_dcmd) & 0xffffff;
1114 1.16.4.2 nathanw acb->iob_curlen += adjust;
1115 1.16.4.2 nathanw acb->iob_curbuf = *((long *)&rp->siop_dnad) - adjust;
1116 1.16.4.2 nathanw #ifdef DEBUG
1117 1.16.4.2 nathanw if (siopng_debug & 0x100) {
1118 1.16.4.2 nathanw int i;
1119 1.16.4.2 nathanw printf ("Phase mismatch: curbuf %lx curlen %lx dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %p\n",
1120 1.16.4.2 nathanw acb->iob_curbuf, acb->iob_curlen, dfifo,
1121 1.16.4.2 nathanw dbc, sstat1, adjust, rp->siop_sbcl, siopngstarts, acb);
1122 1.16.4.2 nathanw if (acb->ds.chain[1].datalen) {
1123 1.16.4.2 nathanw for (i = 0; acb->ds.chain[i].datalen; ++i)
1124 1.16.4.2 nathanw printf("chain[%d] addr %p len %lx\n",
1125 1.16.4.2 nathanw i, acb->ds.chain[i].databuf,
1126 1.16.4.2 nathanw acb->ds.chain[i].datalen);
1127 1.16.4.2 nathanw }
1128 1.16.4.2 nathanw }
1129 1.16.4.2 nathanw #endif
1130 1.16.4.2 nathanw dma_cachectl ((caddr_t)acb, sizeof(*acb));
1131 1.16.4.2 nathanw }
1132 1.16.4.2 nathanw #ifdef DEBUG
1133 1.16.4.2 nathanw SIOP_TRACE('m',rp->siop_sbcl,(rp->siop_dsp>>8),rp->siop_dsp);
1134 1.16.4.2 nathanw if (siopng_debug & 9)
1135 1.16.4.2 nathanw printf ("Phase mismatch: %x dsp +%lx dcmd %lx\n",
1136 1.16.4.2 nathanw rp->siop_sbcl,
1137 1.16.4.2 nathanw rp->siop_dsp - sc->sc_scriptspa,
1138 1.16.4.2 nathanw *((long *)&rp->siop_dcmd));
1139 1.16.4.2 nathanw #endif
1140 1.16.4.2 nathanw if ((rp->siop_sbcl & SIOP_REQ) == 0) {
1141 1.16.4.2 nathanw printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n",
1142 1.16.4.2 nathanw rp->siop_sbcl, rp->siop_dsp);
1143 1.16.4.2 nathanw #if defined(DEBUG) && defined(DDB)
1144 1.16.4.2 nathanw Debugger();
1145 1.16.4.2 nathanw #endif
1146 1.16.4.2 nathanw }
1147 1.16.4.2 nathanw switch (rp->siop_sbcl & 7) {
1148 1.16.4.2 nathanw case 0: /* data out */
1149 1.16.4.2 nathanw case 1: /* data in */
1150 1.16.4.2 nathanw case 2: /* status */
1151 1.16.4.2 nathanw case 3: /* command */
1152 1.16.4.2 nathanw case 6: /* message in */
1153 1.16.4.2 nathanw case 7: /* message out */
1154 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_switch;
1155 1.16.4.2 nathanw break;
1156 1.16.4.2 nathanw default:
1157 1.16.4.2 nathanw goto bad_phase;
1158 1.16.4.2 nathanw }
1159 1.16.4.2 nathanw return 0;
1160 1.16.4.2 nathanw }
1161 1.16.4.2 nathanw if (sist & SIOP_SIST_STO) { /* Select timed out */
1162 1.16.4.2 nathanw #ifdef DEBUG
1163 1.16.4.2 nathanw if (acb == NULL)
1164 1.16.4.2 nathanw printf("%s: Select timeout with no active command?\n",
1165 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1166 1.16.4.2 nathanw if (rp->siop_sbcl & SIOP_BSY) {
1167 1.16.4.2 nathanw printf ("ACK! siop was busy at timeout: rp %p script %p dsa %p\n",
1168 1.16.4.2 nathanw rp, &siopng_scripts, &acb->ds);
1169 1.16.4.2 nathanw printf(" sbcl %x sdid %x istat %x dstat %x sist %x\n",
1170 1.16.4.2 nathanw rp->siop_sbcl, rp->siop_sdid, istat, dstat, sist);
1171 1.16.4.2 nathanw if (!(rp->siop_sbcl & SIOP_BSY)) {
1172 1.16.4.2 nathanw printf ("Yikes, it's not busy now!\n");
1173 1.16.4.2 nathanw #if 0
1174 1.16.4.2 nathanw *status = -1;
1175 1.16.4.2 nathanw if (sc->nexus_list.tqh_first)
1176 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
1177 1.16.4.2 nathanw return 1;
1178 1.16.4.2 nathanw #endif
1179 1.16.4.2 nathanw }
1180 1.16.4.2 nathanw /* rp->siop_dcntl |= SIOP_DCNTL_STD;*/
1181 1.16.4.2 nathanw return (0);
1182 1.16.4.2 nathanw #ifdef DDB
1183 1.16.4.2 nathanw Debugger();
1184 1.16.4.2 nathanw #endif
1185 1.16.4.2 nathanw }
1186 1.16.4.2 nathanw #endif
1187 1.16.4.2 nathanw *status = -1;
1188 1.16.4.2 nathanw acb->xs->error = XS_SELTIMEOUT;
1189 1.16.4.2 nathanw if (sc->nexus_list.tqh_first)
1190 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
1191 1.16.4.2 nathanw return 1;
1192 1.16.4.2 nathanw }
1193 1.16.4.2 nathanw if (acb)
1194 1.16.4.2 nathanw target = acb->xs->xs_periph->periph_target;
1195 1.16.4.2 nathanw else
1196 1.16.4.2 nathanw target = 7;
1197 1.16.4.2 nathanw if (sist & SIOP_SIST_UDC) {
1198 1.16.4.2 nathanw #ifdef DEBUG
1199 1.16.4.2 nathanw if (acb == NULL)
1200 1.16.4.2 nathanw printf("%s: Unexpected disconnect with no active command?\n",
1201 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1202 1.16.4.2 nathanw printf ("%s: target %d disconnected unexpectedly\n",
1203 1.16.4.2 nathanw sc->sc_dev.dv_xname, target);
1204 1.16.4.2 nathanw siopng_dump_registers(sc);
1205 1.16.4.2 nathanw siopng_dump(sc);
1206 1.16.4.2 nathanw #endif
1207 1.16.4.2 nathanw #if 0
1208 1.16.4.2 nathanw siopngabort (sc, rp, "siopngchkintr");
1209 1.16.4.2 nathanw #endif
1210 1.16.4.2 nathanw *status = STS_BUSY;
1211 1.16.4.2 nathanw if (sc->nexus_list.tqh_first)
1212 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
1213 1.16.4.2 nathanw return (acb != NULL);
1214 1.16.4.2 nathanw }
1215 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR && (rp->siop_dsps == 0xff01 ||
1216 1.16.4.2 nathanw rp->siop_dsps == 0xff02)) {
1217 1.16.4.2 nathanw #ifdef DEBUG
1218 1.16.4.2 nathanw if (siopng_debug & 0x100)
1219 1.16.4.2 nathanw printf ("%s: ID %02x disconnected TEMP %lx (+%lx) curbuf %lx curlen %lx buf %p len %lx dfifo %x dbc %x sstat1 %x starts %d acb %p\n",
1220 1.16.4.2 nathanw sc->sc_dev.dv_xname, 1 << target, rp->siop_temp,
1221 1.16.4.2 nathanw rp->siop_temp ? rp->siop_temp - sc->sc_scriptspa : 0,
1222 1.16.4.2 nathanw acb->iob_curbuf, acb->iob_curlen,
1223 1.16.4.2 nathanw acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, siopngstarts, acb);
1224 1.16.4.2 nathanw #endif
1225 1.16.4.2 nathanw if (acb == NULL) {
1226 1.16.4.2 nathanw printf("%s: Disconnect with no active command?\n",
1227 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1228 1.16.4.2 nathanw return (0);
1229 1.16.4.2 nathanw }
1230 1.16.4.2 nathanw /*
1231 1.16.4.2 nathanw * XXXX need to update iob_curbuf/iob_curlen to reflect
1232 1.16.4.2 nathanw * current data transferred. If device disconnected in
1233 1.16.4.2 nathanw * the middle of a DMA block, they should already be set
1234 1.16.4.2 nathanw * by the phase change interrupt. If the disconnect
1235 1.16.4.2 nathanw * occurs on a DMA block boundary, we have to figure out
1236 1.16.4.2 nathanw * which DMA block it was.
1237 1.16.4.2 nathanw */
1238 1.16.4.2 nathanw if (acb->iob_len && rp->siop_temp) {
1239 1.16.4.2 nathanw int n = rp->siop_temp - sc->sc_scriptspa;
1240 1.16.4.2 nathanw
1241 1.16.4.2 nathanw if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen)
1242 1.16.4.2 nathanw printf("%s: iob_curbuf/len already set? n %x iob %lx/%lx chain[0] %p/%lx\n",
1243 1.16.4.2 nathanw sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen,
1244 1.16.4.2 nathanw acb->ds.chain[0].databuf, acb->ds.chain[0].datalen);
1245 1.16.4.2 nathanw if (n < Ent_datain)
1246 1.16.4.2 nathanw n = (n - Ent_dataout) / 16;
1247 1.16.4.2 nathanw else
1248 1.16.4.2 nathanw n = (n - Ent_datain) / 16;
1249 1.16.4.2 nathanw if (n <= 0 && n > DMAMAXIO)
1250 1.16.4.2 nathanw printf("TEMP invalid %d\n", n);
1251 1.16.4.2 nathanw else {
1252 1.16.4.2 nathanw acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf;
1253 1.16.4.2 nathanw acb->iob_curlen = acb->ds.chain[n].datalen;
1254 1.16.4.2 nathanw }
1255 1.16.4.2 nathanw #ifdef DEBUG
1256 1.16.4.2 nathanw if (siopng_debug & 0x100) {
1257 1.16.4.2 nathanw printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n);
1258 1.16.4.2 nathanw printf(" curbuf %lx curlen %lx\n", acb->iob_curbuf,
1259 1.16.4.2 nathanw acb->iob_curlen);
1260 1.16.4.2 nathanw }
1261 1.16.4.2 nathanw #endif
1262 1.16.4.2 nathanw }
1263 1.16.4.2 nathanw /*
1264 1.16.4.2 nathanw * If data transfer was interrupted by disconnect, iob_curbuf
1265 1.16.4.2 nathanw * and iob_curlen should reflect the point of interruption.
1266 1.16.4.2 nathanw * Adjust the DMA chain so that the data transfer begins
1267 1.16.4.2 nathanw * at the appropriate place upon reselection.
1268 1.16.4.2 nathanw * XXX This should only be done on save data pointer message?
1269 1.16.4.2 nathanw */
1270 1.16.4.2 nathanw if (acb->iob_curlen) {
1271 1.16.4.2 nathanw int i, j;
1272 1.16.4.2 nathanw
1273 1.16.4.2 nathanw #ifdef DEBUG
1274 1.16.4.2 nathanw if (siopng_debug & 0x100)
1275 1.16.4.2 nathanw printf ("%s: adjusting DMA chain\n",
1276 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1277 1.16.4.2 nathanw if (rp->siop_dsps == 0xff02)
1278 1.16.4.2 nathanw printf ("%s: ID %02x disconnected without Save Data Pointers\n",
1279 1.16.4.2 nathanw sc->sc_dev.dv_xname, 1 << target);
1280 1.16.4.2 nathanw #endif
1281 1.16.4.2 nathanw for (i = 0; i < DMAMAXIO; ++i) {
1282 1.16.4.2 nathanw if (acb->ds.chain[i].datalen == 0)
1283 1.16.4.2 nathanw break;
1284 1.16.4.2 nathanw if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf &&
1285 1.16.4.2 nathanw acb->iob_curbuf < (long)(acb->ds.chain[i].databuf +
1286 1.16.4.2 nathanw acb->ds.chain[i].datalen))
1287 1.16.4.2 nathanw break;
1288 1.16.4.2 nathanw }
1289 1.16.4.2 nathanw if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0) {
1290 1.16.4.2 nathanw printf("couldn't find saved data pointer: ");
1291 1.16.4.2 nathanw printf("curbuf %lx curlen %lx i %d\n",
1292 1.16.4.2 nathanw acb->iob_curbuf, acb->iob_curlen, i);
1293 1.16.4.2 nathanw #ifdef DDB
1294 1.16.4.2 nathanw Debugger();
1295 1.16.4.2 nathanw #endif
1296 1.16.4.2 nathanw }
1297 1.16.4.2 nathanw #ifdef DEBUG
1298 1.16.4.2 nathanw if (siopng_debug & 0x100)
1299 1.16.4.2 nathanw printf(" chain[0]: %p/%lx -> %lx/%lx\n",
1300 1.16.4.2 nathanw acb->ds.chain[0].databuf,
1301 1.16.4.2 nathanw acb->ds.chain[0].datalen,
1302 1.16.4.2 nathanw acb->iob_curbuf,
1303 1.16.4.2 nathanw acb->iob_curlen);
1304 1.16.4.2 nathanw #endif
1305 1.16.4.2 nathanw acb->ds.chain[0].databuf = (char *)acb->iob_curbuf;
1306 1.16.4.2 nathanw acb->ds.chain[0].datalen = acb->iob_curlen;
1307 1.16.4.2 nathanw for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) {
1308 1.16.4.2 nathanw #ifdef DEBUG
1309 1.16.4.2 nathanw if (siopng_debug & 0x100)
1310 1.16.4.2 nathanw printf(" chain[%d]: %p/%lx -> %p/%lx\n", j,
1311 1.16.4.2 nathanw acb->ds.chain[j].databuf,
1312 1.16.4.2 nathanw acb->ds.chain[j].datalen,
1313 1.16.4.2 nathanw acb->ds.chain[i].databuf,
1314 1.16.4.2 nathanw acb->ds.chain[i].datalen);
1315 1.16.4.2 nathanw #endif
1316 1.16.4.2 nathanw acb->ds.chain[j].databuf = acb->ds.chain[i].databuf;
1317 1.16.4.2 nathanw acb->ds.chain[j].datalen = acb->ds.chain[i].datalen;
1318 1.16.4.2 nathanw }
1319 1.16.4.2 nathanw if (j < DMAMAXIO)
1320 1.16.4.2 nathanw acb->ds.chain[j].datalen = 0;
1321 1.16.4.2 nathanw DCIAS(kvtop((caddr_t)&acb->ds.chain));
1322 1.16.4.2 nathanw }
1323 1.16.4.2 nathanw ++sc->sc_tinfo[target].dconns;
1324 1.16.4.2 nathanw /*
1325 1.16.4.2 nathanw * add nexus to waiting list
1326 1.16.4.2 nathanw * clear nexus
1327 1.16.4.2 nathanw * try to start another command for another target/lun
1328 1.16.4.2 nathanw */
1329 1.16.4.2 nathanw acb->status = sc->sc_flags & SIOP_INTSOFF;
1330 1.16.4.2 nathanw TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
1331 1.16.4.2 nathanw sc->sc_nexus = NULL; /* no current device */
1332 1.16.4.2 nathanw /* start script to wait for reselect */
1333 1.16.4.2 nathanw if (sc->sc_nexus == NULL)
1334 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
1335 1.16.4.2 nathanw /* XXXX start another command ? */
1336 1.16.4.2 nathanw if (sc->ready_list.tqh_first)
1337 1.16.4.2 nathanw siopng_sched(sc);
1338 1.16.4.2 nathanw #if 0
1339 1.16.4.2 nathanw else
1340 1.16.4.2 nathanw rp->siop_dcntl |= SIOP_DCNTL_STD;
1341 1.16.4.2 nathanw #endif
1342 1.16.4.2 nathanw return (0);
1343 1.16.4.2 nathanw }
1344 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff03) {
1345 1.16.4.2 nathanw int reselid = rp->siop_scratcha & 0x7f;
1346 1.16.4.2 nathanw int reselun = rp->siop_sfbr & 0x07;
1347 1.16.4.2 nathanw
1348 1.16.4.2 nathanw sc->sc_sstat1 = rp->siop_sbcl; /* XXXX save current SBCL */
1349 1.16.4.2 nathanw #ifdef DEBUG
1350 1.16.4.2 nathanw if (siopng_debug & 0x100)
1351 1.16.4.2 nathanw printf ("%s: target ID %02x reselected dsps %lx\n",
1352 1.16.4.2 nathanw sc->sc_dev.dv_xname, reselid,
1353 1.16.4.2 nathanw rp->siop_dsps);
1354 1.16.4.2 nathanw if ((rp->siop_sfbr & 0x80) == 0)
1355 1.16.4.2 nathanw printf("%s: Reselect message in was not identify: %x\n",
1356 1.16.4.2 nathanw sc->sc_dev.dv_xname, rp->siop_sfbr);
1357 1.16.4.2 nathanw #endif
1358 1.16.4.2 nathanw if (sc->sc_nexus) {
1359 1.16.4.2 nathanw #ifdef DEBUG
1360 1.16.4.2 nathanw if (siopng_debug & 0x100)
1361 1.16.4.2 nathanw printf ("%s: reselect ID %02x w/active\n",
1362 1.16.4.2 nathanw sc->sc_dev.dv_xname, reselid);
1363 1.16.4.2 nathanw #endif
1364 1.16.4.2 nathanw TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain);
1365 1.16.4.2 nathanw sc->sc_tinfo[sc->sc_nexus->xs->xs_periph->periph_target].lubusy
1366 1.16.4.2 nathanw &= ~(1 << sc->sc_nexus->xs->xs_periph->periph_lun);
1367 1.16.4.2 nathanw --sc->sc_active;
1368 1.16.4.2 nathanw }
1369 1.16.4.2 nathanw /*
1370 1.16.4.2 nathanw * locate acb of reselecting device
1371 1.16.4.2 nathanw * set sc->sc_nexus to acb
1372 1.16.4.2 nathanw */
1373 1.16.4.2 nathanw for (acb = sc->nexus_list.tqh_first; acb;
1374 1.16.4.2 nathanw acb = acb->chain.tqe_next) {
1375 1.16.4.2 nathanw if (reselid != ((acb->ds.scsi_addr >> 16) & 0xff) ||
1376 1.16.4.2 nathanw reselun != (acb->msgout[0] & 0x07))
1377 1.16.4.2 nathanw continue;
1378 1.16.4.2 nathanw TAILQ_REMOVE(&sc->nexus_list, acb, chain);
1379 1.16.4.2 nathanw sc->sc_nexus = acb;
1380 1.16.4.2 nathanw sc->sc_flags |= acb->status;
1381 1.16.4.2 nathanw acb->status = 0;
1382 1.16.4.2 nathanw DCIAS(kvtop(&acb->stat[0]));
1383 1.16.4.2 nathanw rp->siop_dsa = kvtop((caddr_t)&acb->ds);
1384 1.16.4.2 nathanw rp->siop_sxfer =
1385 1.16.4.2 nathanw sc->sc_sync[acb->xs->xs_periph->periph_target].sxfer;
1386 1.16.4.2 nathanw #ifndef FIXME
1387 1.16.4.2 nathanw rp->siop_scntl3 =
1388 1.16.4.2 nathanw sc->sc_sync[acb->xs->xs_periph->periph_target].scntl3;
1389 1.16.4.2 nathanw #endif
1390 1.16.4.2 nathanw break;
1391 1.16.4.2 nathanw }
1392 1.16.4.2 nathanw if (acb == NULL) {
1393 1.16.4.2 nathanw printf("%s: target ID %02x reselect nexus_list %p\n",
1394 1.16.4.2 nathanw sc->sc_dev.dv_xname, reselid,
1395 1.16.4.2 nathanw sc->nexus_list.tqh_first);
1396 1.16.4.2 nathanw panic("unable to find reselecting device");
1397 1.16.4.2 nathanw }
1398 1.16.4.2 nathanw dma_cachectl ((caddr_t)acb, sizeof(*acb));
1399 1.16.4.2 nathanw rp->siop_temp = 0;
1400 1.16.4.2 nathanw rp->siop_dcntl |= SIOP_DCNTL_STD;
1401 1.16.4.2 nathanw return (0);
1402 1.16.4.2 nathanw }
1403 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff04) {
1404 1.16.4.2 nathanw #ifdef DEBUG
1405 1.16.4.2 nathanw u_short ctest2 = rp->siop_ctest2;
1406 1.16.4.2 nathanw
1407 1.16.4.2 nathanw /* reselect was interrupted (by Sig_P or select) */
1408 1.16.4.2 nathanw if (siopng_debug & 0x100 ||
1409 1.16.4.2 nathanw (ctest2 & SIOP_CTEST2_SIGP) == 0)
1410 1.16.4.2 nathanw printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x sfbr %x istat %x/%x\n",
1411 1.16.4.2 nathanw sc->sc_dev.dv_xname, rp->siop_scntl1,
1412 1.16.4.2 nathanw ctest2, rp->siop_sfbr, istat, rp->siop_istat);
1413 1.16.4.2 nathanw #endif
1414 1.16.4.2 nathanw /* XXX assumes it was not select */
1415 1.16.4.2 nathanw if (sc->sc_nexus == NULL) {
1416 1.16.4.2 nathanw #ifdef DEBUG
1417 1.16.4.2 nathanw printf("%s: reselect interrupted, sc_nexus == NULL\n",
1418 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1419 1.16.4.2 nathanw #if 0
1420 1.16.4.2 nathanw siopng_dump(sc);
1421 1.16.4.2 nathanw #ifdef DDB
1422 1.16.4.2 nathanw Debugger();
1423 1.16.4.2 nathanw #endif
1424 1.16.4.2 nathanw #endif
1425 1.16.4.2 nathanw #endif
1426 1.16.4.2 nathanw rp->siop_dcntl |= SIOP_DCNTL_STD;
1427 1.16.4.2 nathanw return(0);
1428 1.16.4.2 nathanw }
1429 1.16.4.2 nathanw target = sc->sc_nexus->xs->xs_periph->periph_target;
1430 1.16.4.2 nathanw rp->siop_temp = 0;
1431 1.16.4.2 nathanw rp->siop_dsa = kvtop((caddr_t)&sc->sc_nexus->ds);
1432 1.16.4.2 nathanw rp->siop_sxfer = sc->sc_sync[target].sxfer;
1433 1.16.4.2 nathanw #ifndef FIXME
1434 1.16.4.2 nathanw rp->siop_scntl3 = sc->sc_sync[target].scntl3;
1435 1.16.4.2 nathanw #endif
1436 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa;
1437 1.16.4.2 nathanw return (0);
1438 1.16.4.2 nathanw }
1439 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff06) {
1440 1.16.4.2 nathanw if (acb == NULL)
1441 1.16.4.2 nathanw printf("%s: Bad message-in with no active command?\n",
1442 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1443 1.16.4.2 nathanw /* Unrecognized message in byte */
1444 1.16.4.2 nathanw dma_cachectl (&acb->msg[1],1);
1445 1.16.4.2 nathanw printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n",
1446 1.16.4.2 nathanw sc->sc_dev.dv_xname, rp->siop_sfbr, acb->msg[1], rp->siop_sbcl);
1447 1.16.4.2 nathanw /* what should be done here? */
1448 1.16.4.2 nathanw DCIAS(kvtop(&acb->msg[1]));
1449 1.16.4.2 nathanw rp->siop_dsp = sc->sc_scriptspa + Ent_switch;
1450 1.16.4.2 nathanw return (0);
1451 1.16.4.2 nathanw }
1452 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0a) {
1453 1.16.4.2 nathanw /* Status phase wasn't followed by message in phase? */
1454 1.16.4.2 nathanw printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n",
1455 1.16.4.2 nathanw sc->sc_dev.dv_xname, rp->siop_sbcl, rp->siop_sbdl);
1456 1.16.4.2 nathanw if (rp->siop_sbcl == 0xa7) {
1457 1.16.4.2 nathanw /* It is now, just continue the script? */
1458 1.16.4.2 nathanw rp->siop_dcntl |= SIOP_DCNTL_STD;
1459 1.16.4.2 nathanw return (0);
1460 1.16.4.2 nathanw }
1461 1.16.4.2 nathanw }
1462 1.16.4.2 nathanw if (sist == 0 && dstat & SIOP_DSTAT_SIR) {
1463 1.16.4.2 nathanw dma_cachectl (&acb->stat[0], 1);
1464 1.16.4.2 nathanw dma_cachectl (&acb->msg[0], 1);
1465 1.16.4.2 nathanw printf ("SIOP interrupt: %lx sts %x msg %x %x sbcl %x\n",
1466 1.16.4.2 nathanw rp->siop_dsps, acb->stat[0], acb->msg[0], acb->msg[1],
1467 1.16.4.2 nathanw rp->siop_sbcl);
1468 1.16.4.2 nathanw siopngreset (sc);
1469 1.16.4.2 nathanw *status = -1;
1470 1.16.4.2 nathanw return 0; /* siopngreset has cleaned up */
1471 1.16.4.2 nathanw }
1472 1.16.4.2 nathanw if (sist & SIOP_SIST_SGE)
1473 1.16.4.2 nathanw printf ("SIOP: SCSI Gross Error\n");
1474 1.16.4.2 nathanw if (sist & SIOP_SIST_PAR)
1475 1.16.4.2 nathanw printf ("SIOP: Parity Error\n");
1476 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_IID)
1477 1.16.4.2 nathanw printf ("SIOP: Invalid instruction detected\n");
1478 1.16.4.2 nathanw bad_phase:
1479 1.16.4.2 nathanw /*
1480 1.16.4.2 nathanw * temporary panic for unhandled conditions
1481 1.16.4.2 nathanw * displays various things about the 53C720/770 status and registers
1482 1.16.4.2 nathanw * then panics.
1483 1.16.4.2 nathanw * XXXX need to clean this up to print out the info, reset, and continue
1484 1.16.4.2 nathanw */
1485 1.16.4.2 nathanw printf ("siopngchkintr: target %x ds %p\n", target, &acb->ds);
1486 1.16.4.2 nathanw printf ("scripts %lx ds %x rp %x dsp %lx dcmd %lx\n", sc->sc_scriptspa,
1487 1.16.4.2 nathanw kvtop((caddr_t)&acb->ds), kvtop((caddr_t)rp), rp->siop_dsp,
1488 1.16.4.2 nathanw *((long *)&rp->siop_dcmd));
1489 1.16.4.2 nathanw printf ("siopngchkintr: istat %x dstat %x sist %x dsps %lx dsa %lx sbcl %x sts %x msg %x %x sfbr %x\n",
1490 1.16.4.2 nathanw istat, dstat, sist, rp->siop_dsps, rp->siop_dsa,
1491 1.16.4.2 nathanw rp->siop_sbcl, acb->stat[0], acb->msg[0], acb->msg[1], rp->siop_sfbr);
1492 1.16.4.2 nathanw #ifdef DEBUG
1493 1.16.4.2 nathanw if (siopng_debug & 0x20)
1494 1.16.4.2 nathanw panic("siopngchkintr: **** temp ****");
1495 1.16.4.2 nathanw #endif
1496 1.16.4.2 nathanw #ifdef DDB
1497 1.16.4.2 nathanw Debugger ();
1498 1.16.4.2 nathanw #endif
1499 1.16.4.2 nathanw siopngreset (sc); /* hard reset */
1500 1.16.4.2 nathanw *status = -1;
1501 1.16.4.2 nathanw return 0; /* siopngreset cleaned up */
1502 1.16.4.2 nathanw }
1503 1.16.4.2 nathanw
1504 1.16.4.2 nathanw void
1505 1.16.4.2 nathanw siopng_select(struct siop_softc *sc)
1506 1.16.4.2 nathanw {
1507 1.16.4.2 nathanw siop_regmap_p rp;
1508 1.16.4.2 nathanw struct siop_acb *acb = sc->sc_nexus;
1509 1.16.4.2 nathanw
1510 1.16.4.2 nathanw #ifdef DEBUG
1511 1.16.4.2 nathanw if (siopng_debug & 1)
1512 1.16.4.2 nathanw printf ("%s: select ", sc->sc_dev.dv_xname);
1513 1.16.4.2 nathanw #endif
1514 1.16.4.2 nathanw
1515 1.16.4.2 nathanw rp = sc->sc_siopp;
1516 1.16.4.2 nathanw if (acb->xs->xs_control & XS_CTL_POLL || siopng_no_dma) {
1517 1.16.4.2 nathanw sc->sc_flags |= SIOP_INTSOFF;
1518 1.16.4.2 nathanw sc->sc_flags &= ~SIOP_INTDEFER;
1519 1.16.4.2 nathanw if ((rp->siop_istat & 0x08) == 0) {
1520 1.16.4.2 nathanw rp->siop_sien = 0;
1521 1.16.4.2 nathanw rp->siop_dien = 0;
1522 1.16.4.2 nathanw }
1523 1.16.4.2 nathanw #if 0
1524 1.16.4.2 nathanw } else if ((sc->sc_flags & SIOP_INTDEFER) == 0) {
1525 1.16.4.2 nathanw sc->sc_flags &= ~SIOP_INTSOFF;
1526 1.16.4.2 nathanw if ((rp->siop_istat & 0x08) == 0) {
1527 1.16.4.2 nathanw rp->siop_sien = sc->sc_sien;
1528 1.16.4.2 nathanw rp->siop_dien = sc->sc_dien;
1529 1.16.4.2 nathanw }
1530 1.16.4.2 nathanw #endif
1531 1.16.4.2 nathanw }
1532 1.16.4.2 nathanw #ifdef DEBUG
1533 1.16.4.2 nathanw if (siopng_debug & 1)
1534 1.16.4.2 nathanw printf ("siopng_select: target %x cmd %02x ds %p\n",
1535 1.16.4.2 nathanw acb->xs->xs_periph->periph_target, acb->cmd.opcode,
1536 1.16.4.2 nathanw &sc->sc_nexus->ds);
1537 1.16.4.2 nathanw #endif
1538 1.16.4.2 nathanw
1539 1.16.4.2 nathanw siopng_start(sc, acb->xs->xs_periph->periph_target,
1540 1.16.4.2 nathanw acb->xs->xs_periph->periph_lun,
1541 1.16.4.2 nathanw (u_char *)&acb->cmd, acb->clen, acb->daddr, acb->dleft);
1542 1.16.4.2 nathanw
1543 1.16.4.2 nathanw return;
1544 1.16.4.2 nathanw }
1545 1.16.4.2 nathanw
1546 1.16.4.2 nathanw /*
1547 1.16.4.2 nathanw * 53C720/770 interrupt handler
1548 1.16.4.2 nathanw */
1549 1.16.4.2 nathanw
1550 1.16.4.2 nathanw void
1551 1.16.4.2 nathanw siopngintr(register struct siop_softc *sc)
1552 1.16.4.2 nathanw {
1553 1.16.4.2 nathanw siop_regmap_p rp;
1554 1.16.4.2 nathanw u_char istat, dstat;
1555 1.16.4.2 nathanw u_short sist;
1556 1.16.4.2 nathanw int status;
1557 1.16.4.2 nathanw int s = splbio();
1558 1.16.4.2 nathanw
1559 1.16.4.2 nathanw istat = sc->sc_istat;
1560 1.16.4.2 nathanw if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) {
1561 1.16.4.2 nathanw splx(s);
1562 1.16.4.2 nathanw return;
1563 1.16.4.2 nathanw }
1564 1.16.4.2 nathanw
1565 1.16.4.2 nathanw /* Got a valid interrupt on this device */
1566 1.16.4.2 nathanw rp = sc->sc_siopp;
1567 1.16.4.2 nathanw dstat = sc->sc_dstat;
1568 1.16.4.2 nathanw sist = sc->sc_sist;
1569 1.16.4.2 nathanw if (dstat & SIOP_DSTAT_SIR)
1570 1.16.4.2 nathanw sc->sc_intcode = rp->siop_dsps;
1571 1.16.4.2 nathanw sc->sc_istat = 0;
1572 1.16.4.2 nathanw #ifdef DEBUG
1573 1.16.4.2 nathanw if (siopng_debug & 1)
1574 1.16.4.2 nathanw printf ("%s: intr istat %x dstat %x sist %x\n",
1575 1.16.4.2 nathanw sc->sc_dev.dv_xname, istat, dstat, sist);
1576 1.16.4.2 nathanw if (!sc->sc_active) {
1577 1.16.4.2 nathanw printf ("%s: spurious interrupt? istat %x dstat %x sist %x nexus %p status %x\n",
1578 1.16.4.2 nathanw sc->sc_dev.dv_xname, istat, dstat, sist,
1579 1.16.4.2 nathanw sc->sc_nexus, sc->sc_nexus ? sc->sc_nexus->stat[0] : 0);
1580 1.16.4.2 nathanw }
1581 1.16.4.2 nathanw #endif
1582 1.16.4.2 nathanw
1583 1.16.4.2 nathanw #ifdef DEBUG
1584 1.16.4.2 nathanw if (siopng_debug & 5) {
1585 1.16.4.2 nathanw DCIAS(kvtop(&sc->sc_nexus->stat[0]));
1586 1.16.4.2 nathanw printf ("%s: intr istat %x dstat %x sist %x dsps %lx sbcl %x sts %x msg %x\n",
1587 1.16.4.2 nathanw sc->sc_dev.dv_xname, istat, dstat, sist,
1588 1.16.4.2 nathanw rp->siop_dsps, rp->siop_sbcl,
1589 1.16.4.2 nathanw sc->sc_nexus->stat[0], sc->sc_nexus->msg[0]);
1590 1.16.4.2 nathanw }
1591 1.16.4.2 nathanw #endif
1592 1.16.4.2 nathanw if (sc->sc_flags & SIOP_INTDEFER) {
1593 1.16.4.2 nathanw sc->sc_flags &= ~(SIOP_INTDEFER | SIOP_INTSOFF);
1594 1.16.4.2 nathanw rp->siop_sien = sc->sc_sien;
1595 1.16.4.2 nathanw rp->siop_dien = sc->sc_dien;
1596 1.16.4.2 nathanw }
1597 1.16.4.2 nathanw if (siopng_checkintr (sc, istat, dstat, sist, &status)) {
1598 1.16.4.2 nathanw #if 1
1599 1.16.4.2 nathanw if (status == 0xff)
1600 1.16.4.2 nathanw printf ("siopngintr: status == 0xff\n");
1601 1.16.4.2 nathanw #endif
1602 1.16.4.2 nathanw if ((sc->sc_flags & (SIOP_INTSOFF | SIOP_INTDEFER)) != SIOP_INTSOFF) {
1603 1.16.4.2 nathanw #if 0
1604 1.16.4.2 nathanw if (rp->siop_sbcl & SIOP_BSY) {
1605 1.16.4.2 nathanw printf ("%s: SCSI bus busy at completion",
1606 1.16.4.2 nathanw sc->sc_dev.dv_xname);
1607 1.16.4.2 nathanw printf(" targ %d sbcl %02x sfbr %x respid %02x dsp +%x\n",
1608 1.16.4.2 nathanw sc->sc_nexus->xs->xs_periph->periph_target,
1609 1.16.4.2 nathanw rp->siop_sbcl, rp->siop_sfbr, rp->siop_respid,
1610 1.16.4.2 nathanw rp->siop_dsp - sc->sc_scriptspa);
1611 1.16.4.2 nathanw }
1612 1.16.4.2 nathanw #endif
1613 1.16.4.2 nathanw siopng_scsidone(sc->sc_nexus, sc->sc_nexus ?
1614 1.16.4.2 nathanw sc->sc_nexus->stat[0] : -1);
1615 1.16.4.2 nathanw }
1616 1.16.4.2 nathanw }
1617 1.16.4.2 nathanw splx(s);
1618 1.16.4.2 nathanw }
1619 1.16.4.2 nathanw
1620 1.16.4.2 nathanw /*
1621 1.16.4.2 nathanw * This is based on the Progressive Peripherals 33Mhz Zeus driver and will
1622 1.16.4.2 nathanw * not be correct for other 53c710 boards.
1623 1.16.4.2 nathanw *
1624 1.16.4.2 nathanw */
1625 1.16.4.2 nathanw void
1626 1.16.4.2 nathanw scsi_period_to_siopng(struct siop_softc *sc, int target)
1627 1.16.4.2 nathanw {
1628 1.16.4.2 nathanw int period, offset, sxfer, scntl3 = 0;
1629 1.16.4.2 nathanw
1630 1.16.4.2 nathanw period = sc->sc_nexus->msg[4];
1631 1.16.4.2 nathanw offset = sc->sc_nexus->msg[5];
1632 1.16.4.2 nathanw #ifdef FIXME
1633 1.16.4.2 nathanw for (scntl3 = 1; scntl3 < 4; ++scntl3) {
1634 1.16.4.2 nathanw sxfer = (period * 4 - 1) / sc->sc_tcp[scntl3] - 3;
1635 1.16.4.2 nathanw if (sxfer >= 0 && sxfer <= 7)
1636 1.16.4.2 nathanw break;
1637 1.16.4.2 nathanw }
1638 1.16.4.2 nathanw if (scntl3 > 3) {
1639 1.16.4.2 nathanw printf("siopng sync: unable to compute sync params for period %dns\n",
1640 1.16.4.2 nathanw period * 4);
1641 1.16.4.2 nathanw /*
1642 1.16.4.2 nathanw * XXX need to pick a value we can do and renegotiate
1643 1.16.4.2 nathanw */
1644 1.16.4.2 nathanw sxfer = scntl3 = 0;
1645 1.16.4.2 nathanw } else {
1646 1.16.4.2 nathanw sxfer = (sxfer << 4) | ((offset <= SIOP_MAX_OFFSET) ?
1647 1.16.4.2 nathanw offset : SIOP_MAX_OFFSET);
1648 1.16.4.2 nathanw #ifdef DEBUG_SYNC
1649 1.16.4.2 nathanw printf("siopng sync: params for period %dns: sxfer %x scntl3 %x",
1650 1.16.4.2 nathanw period * 4, sxfer, scntl3);
1651 1.16.4.2 nathanw printf(" actual period %dns\n",
1652 1.16.4.2 nathanw sc->sc_tcp[scntl3] * ((sxfer >> 4) + 4));
1653 1.16.4.2 nathanw #endif /* DEBUG_SYNC */
1654 1.16.4.2 nathanw }
1655 1.16.4.2 nathanw #else /* FIXME */
1656 1.16.4.2 nathanw sxfer = offset <= SIOP_MAX_OFFSET ? offset : SIOP_MAX_OFFSET;
1657 1.16.4.2 nathanw sxfer |= 0x20; /* XXX XFERP: 5 */
1658 1.16.4.2 nathanw #ifndef FIXME
1659 1.16.4.2 nathanw if (period <= (50 / 4)) /* XXX */
1660 1.16.4.2 nathanw scntl3 = 0x95; /* Ultra, SCF: /1, CCF: /4 */
1661 1.16.4.2 nathanw else if (period <= (100 / 4))
1662 1.16.4.2 nathanw scntl3 = 0x35; /* SCF: /2, CCF: /4 */
1663 1.16.4.2 nathanw else if (period <= (200 / 4))
1664 1.16.4.2 nathanw scntl3 = 0x55; /* SCF: /4, CCF: /4 */
1665 1.16.4.2 nathanw else
1666 1.16.4.2 nathanw scntl3 = 0xff; /* XXX ??? */
1667 1.16.4.2 nathanw #else
1668 1.16.4.2 nathanw scntl3 = 5;
1669 1.16.4.2 nathanw #endif
1670 1.16.4.2 nathanw #endif
1671 1.16.4.2 nathanw sc->sc_sync[target].sxfer = sxfer;
1672 1.16.4.2 nathanw sc->sc_sync[target].scntl3 = scntl3 |
1673 1.16.4.2 nathanw (sc->sc_sync[target].scntl3 & SIOP_SCNTL3_EWS);
1674 1.16.4.2 nathanw #ifdef DEBUG_SYNC
1675 1.16.4.2 nathanw printf ("siopng sync: siop_sxfr %02x, siop_scntl3 %02x\n", sxfer, scntl3);
1676 1.16.4.2 nathanw #endif
1677 1.16.4.2 nathanw }
1678 1.16.4.2 nathanw
1679 1.16.4.2 nathanw void
1680 1.16.4.2 nathanw siopng_dump_registers(struct siop_softc *sc)
1681 1.16.4.2 nathanw {
1682 1.16.4.2 nathanw siop_regmap_p rp = sc->sc_siopp;
1683 1.16.4.2 nathanw
1684 1.16.4.2 nathanw printf(" scntl0 %02x scntl1 %02x scntl2 %02x scntl3 %02x\n",
1685 1.16.4.2 nathanw rp->siop_scntl0, rp->siop_scntl1, rp->siop_scntl2, rp->siop_scntl3);
1686 1.16.4.2 nathanw printf(" scid %02x sxfer %02x sdid %02x gpreg %02x\n",
1687 1.16.4.2 nathanw rp->siop_scid, rp->siop_sxfer, rp->siop_sdid, rp->siop_gpreg);
1688 1.16.4.2 nathanw printf(" sfbr %02x socl %02x ssid %02x sbcl %02x\n",
1689 1.16.4.2 nathanw rp->siop_sfbr, rp->siop_socl, rp->siop_ssid, rp->siop_sbcl);
1690 1.16.4.2 nathanw printf(" dstat %02x sstat0 %02x sstat1 %02x sstat2 %02x\n",
1691 1.16.4.2 nathanw rp->siop_dstat, rp->siop_sstat0, rp->siop_sstat1, rp->siop_sstat2);
1692 1.16.4.2 nathanw printf(" ctest0 %02x ctest1 %02x ctest2 %02x ctest3 %02x\n",
1693 1.16.4.2 nathanw rp->siop_ctest0, rp->siop_ctest1, rp->siop_ctest2, rp->siop_ctest3);
1694 1.16.4.2 nathanw printf(" dfifo %02x ctest4 %02x ctest5 %02x ctest6 %02x\n",
1695 1.16.4.2 nathanw 0, rp->siop_ctest4, rp->siop_ctest5, rp->siop_ctest6);
1696 1.16.4.2 nathanw printf(" dcmd %02x dbc2 %02x dbc1 %02x dbc0 %02x\n",
1697 1.16.4.2 nathanw rp->siop_dcmd, rp->siop_dbc2, rp->siop_dbc1, rp->siop_dbc0);
1698 1.16.4.2 nathanw printf(" dmode %02x dien %02x dwt %02x dcntl %02x\n",
1699 1.16.4.2 nathanw rp->siop_dmode, rp->siop_dien, rp->siop_dwt, rp->siop_dcntl);
1700 1.16.4.2 nathanw printf(" stest0 %02x stest1 %02x stest2 %02x stest3 %02x\n",
1701 1.16.4.2 nathanw rp->siop_stest0, rp->siop_stest1, rp->siop_stest2, rp->siop_stest3);
1702 1.16.4.2 nathanw printf(" istat %02x sien %04x sist %04x respid %04x\n",
1703 1.16.4.2 nathanw rp->siop_istat, rp->siop_sien, rp->siop_sist, rp->siop_respid);
1704 1.16.4.2 nathanw printf(" sidl %04x sodl %04x sbdl %04x\n",
1705 1.16.4.2 nathanw rp->siop_sidl, rp->siop_sodl, rp->siop_sbdl);
1706 1.16.4.2 nathanw printf(" dsps %08lx dsp %08lx (+%lx)\n",
1707 1.16.4.2 nathanw rp->siop_dsps, rp->siop_dsp, rp->siop_dsp > sc->sc_scriptspa ?
1708 1.16.4.2 nathanw rp->siop_dsp - sc->sc_scriptspa : 0);
1709 1.16.4.2 nathanw printf(" dsa %08lx temp %08lx dnad %08lx\n",
1710 1.16.4.2 nathanw rp->siop_dsa, rp->siop_temp, rp->siop_dnad);
1711 1.16.4.2 nathanw printf(" scratcha %08lx scratchb %08lx adder %08lx\n",
1712 1.16.4.2 nathanw rp->siop_scratcha, rp->siop_scratchb, rp->siop_adder);
1713 1.16.4.2 nathanw }
1714 1.16.4.2 nathanw
1715 1.16.4.2 nathanw #ifdef DEBUG
1716 1.16.4.2 nathanw
1717 1.16.4.2 nathanw #if SIOP_TRACE_SIZE
1718 1.16.4.2 nathanw void
1719 1.16.4.2 nathanw siopng_dump_trace(void)
1720 1.16.4.2 nathanw {
1721 1.16.4.2 nathanw int i;
1722 1.16.4.2 nathanw
1723 1.16.4.2 nathanw printf("siopng trace: next index %d\n", siopng_trix);
1724 1.16.4.2 nathanw i = siopng_trix;
1725 1.16.4.2 nathanw do {
1726 1.16.4.2 nathanw printf("%3d: '%c' %02x %02x %02x\n", i, siopng_trbuf[i],
1727 1.16.4.2 nathanw siopng_trbuf[i + 1], siopng_trbuf[i + 2], siopng_trbuf[i + 3]);
1728 1.16.4.2 nathanw i = (i + 4) & (SIOP_TRACE_SIZE - 1);
1729 1.16.4.2 nathanw } while (i != siopng_trix);
1730 1.16.4.2 nathanw }
1731 1.16.4.2 nathanw #endif
1732 1.16.4.2 nathanw
1733 1.16.4.2 nathanw void
1734 1.16.4.2 nathanw siopng_dump_acb(struct siop_acb *acb)
1735 1.16.4.2 nathanw {
1736 1.16.4.2 nathanw u_char *b = (u_char *) &acb->cmd;
1737 1.16.4.2 nathanw int i;
1738 1.16.4.2 nathanw
1739 1.16.4.2 nathanw printf("acb@%p ", acb);
1740 1.16.4.2 nathanw if (acb->xs == NULL) {
1741 1.16.4.2 nathanw printf("<unused>\n");
1742 1.16.4.2 nathanw return;
1743 1.16.4.2 nathanw }
1744 1.16.4.2 nathanw printf("(%d:%d) flags %2x clen %2d cmd ",
1745 1.16.4.2 nathanw acb->xs->xs_periph->periph_target,
1746 1.16.4.2 nathanw acb->xs->xs_periph->periph_lun, acb->flags, acb->clen);
1747 1.16.4.2 nathanw for (i = acb->clen; i; --i)
1748 1.16.4.2 nathanw printf(" %02x", *b++);
1749 1.16.4.2 nathanw printf("\n");
1750 1.16.4.2 nathanw printf(" xs: %p data %p:%04x ", acb->xs, acb->xs->data,
1751 1.16.4.2 nathanw acb->xs->datalen);
1752 1.16.4.2 nathanw printf("va %p:%lx ", acb->iob_buf, acb->iob_len);
1753 1.16.4.2 nathanw printf("cur %lx:%lx\n", acb->iob_curbuf, acb->iob_curlen);
1754 1.16.4.2 nathanw }
1755 1.16.4.2 nathanw
1756 1.16.4.2 nathanw void
1757 1.16.4.2 nathanw siopng_dump(struct siop_softc *sc)
1758 1.16.4.2 nathanw {
1759 1.16.4.2 nathanw struct siop_acb *acb;
1760 1.16.4.2 nathanw siop_regmap_p rp = sc->sc_siopp;
1761 1.16.4.2 nathanw int s;
1762 1.16.4.2 nathanw int i;
1763 1.16.4.2 nathanw
1764 1.16.4.2 nathanw s = splbio();
1765 1.16.4.2 nathanw #if SIOP_TRACE_SIZE
1766 1.16.4.2 nathanw siopng_dump_trace();
1767 1.16.4.2 nathanw #endif
1768 1.16.4.2 nathanw printf("%s@%p regs %p istat %x\n",
1769 1.16.4.2 nathanw sc->sc_dev.dv_xname, sc, rp, rp->siop_istat);
1770 1.16.4.2 nathanw if ((acb = sc->free_list.tqh_first) > 0) {
1771 1.16.4.2 nathanw printf("Free list:\n");
1772 1.16.4.2 nathanw while (acb) {
1773 1.16.4.2 nathanw siopng_dump_acb(acb);
1774 1.16.4.2 nathanw acb = acb->chain.tqe_next;
1775 1.16.4.2 nathanw }
1776 1.16.4.2 nathanw }
1777 1.16.4.2 nathanw if ((acb = sc->ready_list.tqh_first) > 0) {
1778 1.16.4.2 nathanw printf("Ready list:\n");
1779 1.16.4.2 nathanw while (acb) {
1780 1.16.4.2 nathanw siopng_dump_acb(acb);
1781 1.16.4.2 nathanw acb = acb->chain.tqe_next;
1782 1.16.4.2 nathanw }
1783 1.16.4.2 nathanw }
1784 1.16.4.2 nathanw if ((acb = sc->nexus_list.tqh_first) > 0) {
1785 1.16.4.2 nathanw printf("Nexus list:\n");
1786 1.16.4.2 nathanw while (acb) {
1787 1.16.4.2 nathanw siopng_dump_acb(acb);
1788 1.16.4.2 nathanw acb = acb->chain.tqe_next;
1789 1.16.4.2 nathanw }
1790 1.16.4.2 nathanw }
1791 1.16.4.2 nathanw if (sc->sc_nexus) {
1792 1.16.4.2 nathanw printf("Nexus:\n");
1793 1.16.4.2 nathanw siopng_dump_acb(sc->sc_nexus);
1794 1.16.4.2 nathanw }
1795 1.16.4.2 nathanw for (i = 0; i < 8; ++i) {
1796 1.16.4.2 nathanw if (sc->sc_tinfo[i].cmds > 2) {
1797 1.16.4.2 nathanw printf("tgt %d: cmds %d disc %d lubusy %x\n",
1798 1.16.4.2 nathanw i, sc->sc_tinfo[i].cmds,
1799 1.16.4.2 nathanw sc->sc_tinfo[i].dconns,
1800 1.16.4.2 nathanw sc->sc_tinfo[i].lubusy);
1801 1.16.4.2 nathanw }
1802 1.16.4.2 nathanw }
1803 1.16.4.2 nathanw splx(s);
1804 1.16.4.2 nathanw }
1805 1.16.4.2 nathanw #endif
1806