mesh.c revision 1.12.6.3 1 1.12.6.3 nathanw /* $NetBSD: mesh.c,v 1.12.6.3 2002/10/18 02:38:35 nathanw Exp $ */
2 1.12.6.2 nathanw
3 1.12.6.2 nathanw /*-
4 1.12.6.2 nathanw * Copyright (c) 2000 Tsubai Masanari.
5 1.12.6.2 nathanw * Copyright (c) 1999 Internet Research Institute, Inc.
6 1.12.6.2 nathanw * All rights reserved.
7 1.12.6.2 nathanw *
8 1.12.6.2 nathanw * Redistribution and use in source and binary forms, with or without
9 1.12.6.2 nathanw * modification, are permitted provided that the following conditions
10 1.12.6.2 nathanw * are met:
11 1.12.6.2 nathanw * 1. Redistributions of source code must retain the above copyright
12 1.12.6.2 nathanw * notice, this list of conditions and the following disclaimer.
13 1.12.6.2 nathanw * 2. Redistributions in binary form must reproduce the above copyright
14 1.12.6.2 nathanw * notice, this list of conditions and the following disclaimer in the
15 1.12.6.2 nathanw * documentation and/or other materials provided with the distribution.
16 1.12.6.2 nathanw * 3. All advertising materials mentioning features or use of this software
17 1.12.6.2 nathanw * must display the following acknowledgement:
18 1.12.6.2 nathanw * This product includes software developed by
19 1.12.6.2 nathanw * Internet Research Institute, Inc.
20 1.12.6.2 nathanw * 4. The name of the author may not be used to endorse or promote products
21 1.12.6.2 nathanw * derived from this software without specific prior written permission.
22 1.12.6.2 nathanw *
23 1.12.6.2 nathanw * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 1.12.6.2 nathanw * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 1.12.6.2 nathanw * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 1.12.6.2 nathanw * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 1.12.6.2 nathanw * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 1.12.6.2 nathanw * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 1.12.6.2 nathanw * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 1.12.6.2 nathanw * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 1.12.6.2 nathanw * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 1.12.6.2 nathanw * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 1.12.6.2 nathanw */
34 1.12.6.2 nathanw
35 1.12.6.2 nathanw #include <sys/param.h>
36 1.12.6.2 nathanw #include <sys/buf.h>
37 1.12.6.2 nathanw #include <sys/device.h>
38 1.12.6.2 nathanw #include <sys/errno.h>
39 1.12.6.2 nathanw #include <sys/kernel.h>
40 1.12.6.2 nathanw #include <sys/malloc.h>
41 1.12.6.2 nathanw #include <sys/queue.h>
42 1.12.6.2 nathanw #include <sys/systm.h>
43 1.12.6.2 nathanw
44 1.12.6.2 nathanw #include <uvm/uvm_extern.h>
45 1.12.6.2 nathanw
46 1.12.6.2 nathanw #include <dev/scsipi/scsi_all.h>
47 1.12.6.2 nathanw #include <dev/scsipi/scsipi_all.h>
48 1.12.6.2 nathanw #include <dev/scsipi/scsiconf.h>
49 1.12.6.2 nathanw #include <dev/scsipi/scsi_message.h>
50 1.12.6.2 nathanw
51 1.12.6.2 nathanw #include <dev/ofw/openfirm.h>
52 1.12.6.2 nathanw
53 1.12.6.2 nathanw #include <machine/autoconf.h>
54 1.12.6.2 nathanw #include <machine/cpu.h>
55 1.12.6.2 nathanw #include <machine/pio.h>
56 1.12.6.2 nathanw
57 1.12.6.2 nathanw #include <macppc/dev/dbdma.h>
58 1.12.6.2 nathanw #include <macppc/dev/meshreg.h>
59 1.12.6.2 nathanw
60 1.12.6.2 nathanw #ifdef MESH_DEBUG
61 1.12.6.2 nathanw # define DPRINTF printf
62 1.12.6.2 nathanw #else
63 1.12.6.2 nathanw # define DPRINTF while (0) printf
64 1.12.6.2 nathanw #endif
65 1.12.6.2 nathanw
66 1.12.6.2 nathanw #define T_SYNCMODE 0x01 /* target uses sync mode */
67 1.12.6.2 nathanw #define T_SYNCNEGO 0x02 /* sync negotiation done */
68 1.12.6.2 nathanw
69 1.12.6.2 nathanw struct mesh_tinfo {
70 1.12.6.2 nathanw int flags;
71 1.12.6.2 nathanw int period;
72 1.12.6.2 nathanw int offset;
73 1.12.6.2 nathanw };
74 1.12.6.2 nathanw
75 1.12.6.2 nathanw /* scb flags */
76 1.12.6.2 nathanw #define MESH_POLL 0x01
77 1.12.6.2 nathanw #define MESH_CHECK 0x02
78 1.12.6.2 nathanw #define MESH_READ 0x80
79 1.12.6.2 nathanw
80 1.12.6.2 nathanw struct mesh_scb {
81 1.12.6.2 nathanw TAILQ_ENTRY(mesh_scb) chain;
82 1.12.6.2 nathanw int flags;
83 1.12.6.2 nathanw struct scsipi_xfer *xs;
84 1.12.6.2 nathanw struct scsi_generic cmd;
85 1.12.6.2 nathanw int cmdlen;
86 1.12.6.2 nathanw int target; /* target SCSI ID */
87 1.12.6.2 nathanw int resid;
88 1.12.6.2 nathanw vaddr_t daddr;
89 1.12.6.2 nathanw vsize_t dlen;
90 1.12.6.2 nathanw int status;
91 1.12.6.2 nathanw };
92 1.12.6.2 nathanw
93 1.12.6.2 nathanw /* sc_flags value */
94 1.12.6.2 nathanw #define MESH_DMA_ACTIVE 0x01
95 1.12.6.2 nathanw
96 1.12.6.2 nathanw struct mesh_softc {
97 1.12.6.2 nathanw struct device sc_dev; /* us as a device */
98 1.12.6.2 nathanw struct scsipi_channel sc_channel;
99 1.12.6.2 nathanw struct scsipi_adapter sc_adapter;
100 1.12.6.2 nathanw
101 1.12.6.2 nathanw u_char *sc_reg; /* MESH base address */
102 1.12.6.2 nathanw dbdma_regmap_t *sc_dmareg; /* DMA register address */
103 1.12.6.2 nathanw dbdma_command_t *sc_dmacmd; /* DMA command area */
104 1.12.6.2 nathanw
105 1.12.6.2 nathanw int sc_flags;
106 1.12.6.2 nathanw int sc_cfflags; /* copy of config flags */
107 1.12.6.2 nathanw int sc_meshid; /* MESH version */
108 1.12.6.2 nathanw int sc_minsync; /* minimum sync period */
109 1.12.6.2 nathanw int sc_irq;
110 1.12.6.2 nathanw int sc_freq; /* SCSI bus frequency in MHz */
111 1.12.6.2 nathanw int sc_id; /* our SCSI ID */
112 1.12.6.2 nathanw struct mesh_tinfo sc_tinfo[8]; /* target information */
113 1.12.6.2 nathanw
114 1.12.6.2 nathanw int sc_nextstate;
115 1.12.6.2 nathanw int sc_prevphase;
116 1.12.6.2 nathanw struct mesh_scb *sc_nexus; /* current command */
117 1.12.6.2 nathanw
118 1.12.6.2 nathanw int sc_msgout;
119 1.12.6.2 nathanw int sc_imsglen;
120 1.12.6.2 nathanw u_char sc_imsg[16];
121 1.12.6.2 nathanw u_char sc_omsg[16];
122 1.12.6.2 nathanw
123 1.12.6.2 nathanw TAILQ_HEAD(, mesh_scb) free_scb;
124 1.12.6.2 nathanw TAILQ_HEAD(, mesh_scb) ready_scb;
125 1.12.6.2 nathanw struct mesh_scb sc_scb[16];
126 1.12.6.2 nathanw };
127 1.12.6.2 nathanw
128 1.12.6.2 nathanw /* mesh_msgout() values */
129 1.12.6.2 nathanw #define SEND_REJECT 1
130 1.12.6.2 nathanw #define SEND_IDENTIFY 2
131 1.12.6.2 nathanw #define SEND_SDTR 4
132 1.12.6.2 nathanw
133 1.12.6.2 nathanw static __inline int mesh_read_reg __P((struct mesh_softc *, int));
134 1.12.6.2 nathanw static __inline void mesh_set_reg __P((struct mesh_softc *, int, int));
135 1.12.6.2 nathanw
136 1.12.6.2 nathanw int mesh_match __P((struct device *, struct cfdata *, void *));
137 1.12.6.2 nathanw void mesh_attach __P((struct device *, struct device *, void *));
138 1.12.6.2 nathanw void mesh_shutdownhook __P((void *));
139 1.12.6.2 nathanw int mesh_intr __P((void *));
140 1.12.6.2 nathanw void mesh_error __P((struct mesh_softc *, struct mesh_scb *, int, int));
141 1.12.6.2 nathanw void mesh_select __P((struct mesh_softc *, struct mesh_scb *));
142 1.12.6.2 nathanw void mesh_identify __P((struct mesh_softc *, struct mesh_scb *));
143 1.12.6.2 nathanw void mesh_command __P((struct mesh_softc *, struct mesh_scb *));
144 1.12.6.2 nathanw void mesh_dma_setup __P((struct mesh_softc *, struct mesh_scb *));
145 1.12.6.2 nathanw void mesh_dataio __P((struct mesh_softc *, struct mesh_scb *));
146 1.12.6.2 nathanw void mesh_status __P((struct mesh_softc *, struct mesh_scb *));
147 1.12.6.2 nathanw void mesh_msgin __P((struct mesh_softc *, struct mesh_scb *));
148 1.12.6.2 nathanw void mesh_msgout __P((struct mesh_softc *, int));
149 1.12.6.2 nathanw void mesh_bus_reset __P((struct mesh_softc *));
150 1.12.6.2 nathanw void mesh_reset __P((struct mesh_softc *));
151 1.12.6.2 nathanw int mesh_stp __P((struct mesh_softc *, int));
152 1.12.6.2 nathanw void mesh_setsync __P((struct mesh_softc *, struct mesh_tinfo *));
153 1.12.6.2 nathanw struct mesh_scb *mesh_get_scb __P((struct mesh_softc *));
154 1.12.6.2 nathanw void mesh_free_scb __P((struct mesh_softc *, struct mesh_scb *));
155 1.12.6.2 nathanw void mesh_scsi_request __P((struct scsipi_channel *,
156 1.12.6.2 nathanw scsipi_adapter_req_t, void *));
157 1.12.6.2 nathanw void mesh_sched __P((struct mesh_softc *));
158 1.12.6.2 nathanw int mesh_poll __P((struct mesh_softc *, struct scsipi_xfer *));
159 1.12.6.2 nathanw void mesh_done __P((struct mesh_softc *, struct mesh_scb *));
160 1.12.6.2 nathanw void mesh_timeout __P((void *));
161 1.12.6.2 nathanw void mesh_minphys __P((struct buf *));
162 1.12.6.2 nathanw
163 1.12.6.2 nathanw
164 1.12.6.2 nathanw #define MESH_DATAOUT 0
165 1.12.6.2 nathanw #define MESH_DATAIN MESH_STATUS0_IO
166 1.12.6.2 nathanw #define MESH_COMMAND MESH_STATUS0_CD
167 1.12.6.2 nathanw #define MESH_STATUS (MESH_STATUS0_CD | MESH_STATUS0_IO)
168 1.12.6.2 nathanw #define MESH_MSGOUT (MESH_STATUS0_MSG | MESH_STATUS0_CD)
169 1.12.6.2 nathanw #define MESH_MSGIN (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
170 1.12.6.2 nathanw
171 1.12.6.2 nathanw #define MESH_SELECTING 8
172 1.12.6.2 nathanw #define MESH_IDENTIFY 9
173 1.12.6.2 nathanw #define MESH_COMPLETE 10
174 1.12.6.2 nathanw #define MESH_BUSFREE 11
175 1.12.6.2 nathanw #define MESH_UNKNOWN -1
176 1.12.6.2 nathanw
177 1.12.6.2 nathanw #define MESH_PHASE_MASK (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
178 1.12.6.2 nathanw
179 1.12.6.3 nathanw CFATTACH_DECL(mesh, sizeof(struct mesh_softc),
180 1.12.6.3 nathanw mesh_match, mesh_attach, NULL, NULL);
181 1.12.6.2 nathanw
182 1.12.6.2 nathanw int
183 1.12.6.2 nathanw mesh_match(parent, cf, aux)
184 1.12.6.2 nathanw struct device *parent;
185 1.12.6.2 nathanw struct cfdata *cf;
186 1.12.6.2 nathanw void *aux;
187 1.12.6.2 nathanw {
188 1.12.6.2 nathanw struct confargs *ca = aux;
189 1.12.6.2 nathanw char compat[32];
190 1.12.6.2 nathanw
191 1.12.6.2 nathanw if (strcmp(ca->ca_name, "mesh") == 0)
192 1.12.6.2 nathanw return 1;
193 1.12.6.2 nathanw
194 1.12.6.2 nathanw memset(compat, 0, sizeof(compat));
195 1.12.6.2 nathanw OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
196 1.12.6.2 nathanw if (strcmp(compat, "chrp,mesh0") == 0)
197 1.12.6.2 nathanw return 1;
198 1.12.6.2 nathanw
199 1.12.6.2 nathanw return 0;
200 1.12.6.2 nathanw }
201 1.12.6.2 nathanw
202 1.12.6.2 nathanw void
203 1.12.6.2 nathanw mesh_attach(parent, self, aux)
204 1.12.6.2 nathanw struct device *parent, *self;
205 1.12.6.2 nathanw void *aux;
206 1.12.6.2 nathanw {
207 1.12.6.2 nathanw struct mesh_softc *sc = (void *)self;
208 1.12.6.2 nathanw struct confargs *ca = aux;
209 1.12.6.2 nathanw int i;
210 1.12.6.2 nathanw u_int *reg;
211 1.12.6.2 nathanw
212 1.12.6.2 nathanw reg = ca->ca_reg;
213 1.12.6.2 nathanw reg[0] += ca->ca_baseaddr;
214 1.12.6.2 nathanw reg[2] += ca->ca_baseaddr;
215 1.12.6.2 nathanw sc->sc_reg = mapiodev(reg[0], reg[1]);
216 1.12.6.2 nathanw sc->sc_irq = ca->ca_intr[0];
217 1.12.6.2 nathanw sc->sc_dmareg = mapiodev(reg[2], reg[3]);
218 1.12.6.2 nathanw
219 1.12.6.2 nathanw sc->sc_cfflags = self->dv_cfdata->cf_flags;
220 1.12.6.2 nathanw sc->sc_meshid = mesh_read_reg(sc, MESH_MESH_ID) & 0x1f;
221 1.12.6.2 nathanw #if 0
222 1.12.6.2 nathanw if (sc->sc_meshid != (MESH_SIGNATURE & 0x1f) {
223 1.12.6.2 nathanw printf(": unknown MESH ID (0x%x)\n", sc->sc_meshid);
224 1.12.6.2 nathanw return;
225 1.12.6.2 nathanw }
226 1.12.6.2 nathanw #endif
227 1.12.6.2 nathanw if (OF_getprop(ca->ca_node, "clock-frequency", &sc->sc_freq, 4) != 4) {
228 1.12.6.2 nathanw printf(": cannot get clock-frequency\n");
229 1.12.6.2 nathanw return;
230 1.12.6.2 nathanw }
231 1.12.6.2 nathanw sc->sc_freq /= 1000000; /* in MHz */
232 1.12.6.2 nathanw sc->sc_minsync = 25; /* maximum sync rate = 10MB/sec */
233 1.12.6.2 nathanw sc->sc_id = 7;
234 1.12.6.2 nathanw
235 1.12.6.2 nathanw TAILQ_INIT(&sc->free_scb);
236 1.12.6.2 nathanw TAILQ_INIT(&sc->ready_scb);
237 1.12.6.2 nathanw for (i = 0; i < sizeof(sc->sc_scb)/sizeof(sc->sc_scb[0]); i++)
238 1.12.6.2 nathanw TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain);
239 1.12.6.2 nathanw
240 1.12.6.2 nathanw sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20);
241 1.12.6.2 nathanw
242 1.12.6.2 nathanw mesh_reset(sc);
243 1.12.6.2 nathanw mesh_bus_reset(sc);
244 1.12.6.2 nathanw
245 1.12.6.2 nathanw printf(" irq %d: %dMHz, SCSI ID %d\n",
246 1.12.6.2 nathanw sc->sc_irq, sc->sc_freq, sc->sc_id);
247 1.12.6.2 nathanw
248 1.12.6.2 nathanw sc->sc_adapter.adapt_dev = &sc->sc_dev;
249 1.12.6.2 nathanw sc->sc_adapter.adapt_nchannels = 1;
250 1.12.6.2 nathanw sc->sc_adapter.adapt_openings = 7;
251 1.12.6.2 nathanw sc->sc_adapter.adapt_max_periph = 1;
252 1.12.6.2 nathanw sc->sc_adapter.adapt_ioctl = NULL;
253 1.12.6.2 nathanw sc->sc_adapter.adapt_minphys = mesh_minphys;
254 1.12.6.2 nathanw sc->sc_adapter.adapt_request = mesh_scsi_request;
255 1.12.6.2 nathanw
256 1.12.6.2 nathanw sc->sc_channel.chan_adapter = &sc->sc_adapter;
257 1.12.6.2 nathanw sc->sc_channel.chan_bustype = &scsi_bustype;
258 1.12.6.2 nathanw sc->sc_channel.chan_channel = 0;
259 1.12.6.2 nathanw sc->sc_channel.chan_ntargets = 8;
260 1.12.6.2 nathanw sc->sc_channel.chan_nluns = 8;
261 1.12.6.2 nathanw sc->sc_channel.chan_id = sc->sc_id;
262 1.12.6.2 nathanw
263 1.12.6.2 nathanw config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
264 1.12.6.2 nathanw
265 1.12.6.2 nathanw intr_establish(sc->sc_irq, IST_LEVEL, IPL_BIO, mesh_intr, sc);
266 1.12.6.2 nathanw
267 1.12.6.2 nathanw /* Reset SCSI bus when halt. */
268 1.12.6.2 nathanw shutdownhook_establish(mesh_shutdownhook, sc);
269 1.12.6.2 nathanw }
270 1.12.6.2 nathanw
271 1.12.6.2 nathanw #define MESH_SET_XFER(sc, count) do { \
272 1.12.6.2 nathanw mesh_set_reg(sc, MESH_XFER_COUNT0, count); \
273 1.12.6.2 nathanw mesh_set_reg(sc, MESH_XFER_COUNT1, count >> 8); \
274 1.12.6.2 nathanw } while (0)
275 1.12.6.2 nathanw
276 1.12.6.2 nathanw #define MESH_GET_XFER(sc) ((mesh_read_reg(sc, MESH_XFER_COUNT1) << 8) | \
277 1.12.6.2 nathanw mesh_read_reg(sc, MESH_XFER_COUNT0))
278 1.12.6.2 nathanw
279 1.12.6.2 nathanw int
280 1.12.6.2 nathanw mesh_read_reg(sc, reg)
281 1.12.6.2 nathanw struct mesh_softc *sc;
282 1.12.6.2 nathanw int reg;
283 1.12.6.2 nathanw {
284 1.12.6.2 nathanw return in8(sc->sc_reg + reg);
285 1.12.6.2 nathanw }
286 1.12.6.2 nathanw
287 1.12.6.2 nathanw void
288 1.12.6.2 nathanw mesh_set_reg(sc, reg, val)
289 1.12.6.2 nathanw struct mesh_softc *sc;
290 1.12.6.2 nathanw int reg, val;
291 1.12.6.2 nathanw {
292 1.12.6.2 nathanw out8(sc->sc_reg + reg, val);
293 1.12.6.2 nathanw }
294 1.12.6.2 nathanw
295 1.12.6.2 nathanw void
296 1.12.6.2 nathanw mesh_shutdownhook(arg)
297 1.12.6.2 nathanw void *arg;
298 1.12.6.2 nathanw {
299 1.12.6.2 nathanw struct mesh_softc *sc = arg;
300 1.12.6.2 nathanw
301 1.12.6.2 nathanw /* Set to async mode. */
302 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
303 1.12.6.2 nathanw }
304 1.12.6.2 nathanw
305 1.12.6.2 nathanw #ifdef MESH_DEBUG
306 1.12.6.2 nathanw static char scsi_phase[][8] = {
307 1.12.6.2 nathanw "DATAOUT",
308 1.12.6.2 nathanw "DATAIN",
309 1.12.6.2 nathanw "COMMAND",
310 1.12.6.2 nathanw "STATUS",
311 1.12.6.2 nathanw "",
312 1.12.6.2 nathanw "",
313 1.12.6.2 nathanw "MSGOUT",
314 1.12.6.2 nathanw "MSGIN"
315 1.12.6.2 nathanw };
316 1.12.6.2 nathanw #endif
317 1.12.6.2 nathanw
318 1.12.6.2 nathanw int
319 1.12.6.2 nathanw mesh_intr(arg)
320 1.12.6.2 nathanw void *arg;
321 1.12.6.2 nathanw {
322 1.12.6.2 nathanw struct mesh_softc *sc = arg;
323 1.12.6.2 nathanw struct mesh_scb *scb;
324 1.12.6.2 nathanw int fifocnt;
325 1.12.6.2 nathanw u_char intr, exception, error, status0, status1;
326 1.12.6.2 nathanw
327 1.12.6.2 nathanw intr = mesh_read_reg(sc, MESH_INTERRUPT);
328 1.12.6.2 nathanw if (intr == 0) {
329 1.12.6.2 nathanw DPRINTF("%s: stray interrupt\n", sc->sc_dev.dv_xname);
330 1.12.6.2 nathanw return 0;
331 1.12.6.2 nathanw }
332 1.12.6.2 nathanw
333 1.12.6.2 nathanw exception = mesh_read_reg(sc, MESH_EXCEPTION);
334 1.12.6.2 nathanw error = mesh_read_reg(sc, MESH_ERROR);
335 1.12.6.2 nathanw status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
336 1.12.6.2 nathanw status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
337 1.12.6.2 nathanw
338 1.12.6.2 nathanw /* clear interrupt */
339 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTERRUPT, intr);
340 1.12.6.2 nathanw
341 1.12.6.2 nathanw #ifdef MESH_DEBUG
342 1.12.6.2 nathanw {
343 1.12.6.2 nathanw char buf1[64], buf2[64];
344 1.12.6.2 nathanw
345 1.12.6.2 nathanw bitmask_snprintf(status0, MESH_STATUS0_BITMASK, buf1, sizeof buf1);
346 1.12.6.2 nathanw bitmask_snprintf(exception, MESH_EXC_BITMASK, buf2, sizeof buf2);
347 1.12.6.2 nathanw printf("mesh_intr status0 = 0x%s (%s), exc = 0x%s\n",
348 1.12.6.2 nathanw buf1, scsi_phase[status0 & 7], buf2);
349 1.12.6.2 nathanw }
350 1.12.6.2 nathanw #endif
351 1.12.6.2 nathanw
352 1.12.6.2 nathanw scb = sc->sc_nexus;
353 1.12.6.2 nathanw if (scb == NULL) {
354 1.12.6.2 nathanw DPRINTF("%s: NULL nexus\n", sc->sc_dev.dv_xname);
355 1.12.6.2 nathanw return 1;
356 1.12.6.2 nathanw }
357 1.12.6.2 nathanw
358 1.12.6.2 nathanw if (sc->sc_flags & MESH_DMA_ACTIVE) {
359 1.12.6.2 nathanw dbdma_stop(sc->sc_dmareg);
360 1.12.6.2 nathanw
361 1.12.6.2 nathanw sc->sc_flags &= ~MESH_DMA_ACTIVE;
362 1.12.6.2 nathanw scb->resid = MESH_GET_XFER(sc);
363 1.12.6.2 nathanw
364 1.12.6.2 nathanw fifocnt = mesh_read_reg(sc, MESH_FIFO_COUNT);
365 1.12.6.2 nathanw if (fifocnt != 0 && (scb->flags & MESH_READ)) {
366 1.12.6.2 nathanw char *cp = (char *)scb->daddr + scb->dlen - fifocnt;
367 1.12.6.2 nathanw
368 1.12.6.2 nathanw DPRINTF("fifocnt = %d, resid = %d\n", fifocnt,
369 1.12.6.2 nathanw scb->resid);
370 1.12.6.2 nathanw while (fifocnt > 0) {
371 1.12.6.2 nathanw *cp++ = mesh_read_reg(sc, MESH_FIFO);
372 1.12.6.2 nathanw fifocnt--;
373 1.12.6.2 nathanw }
374 1.12.6.2 nathanw } else
375 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
376 1.12.6.2 nathanw }
377 1.12.6.2 nathanw
378 1.12.6.2 nathanw if (intr & MESH_INTR_ERROR) {
379 1.12.6.2 nathanw mesh_error(sc, scb, error, 0);
380 1.12.6.2 nathanw return 1;
381 1.12.6.2 nathanw }
382 1.12.6.2 nathanw
383 1.12.6.2 nathanw if (intr & MESH_INTR_EXCEPTION) {
384 1.12.6.2 nathanw /* selection timeout */
385 1.12.6.2 nathanw if (exception & MESH_EXC_SELTO) {
386 1.12.6.2 nathanw mesh_error(sc, scb, 0, exception);
387 1.12.6.2 nathanw return 1;
388 1.12.6.2 nathanw }
389 1.12.6.2 nathanw
390 1.12.6.2 nathanw /* phase mismatch */
391 1.12.6.2 nathanw if (exception & MESH_EXC_PHASEMM) {
392 1.12.6.2 nathanw DPRINTF("%s: PHASE MISMATCH; nextstate = %d -> ",
393 1.12.6.2 nathanw sc->sc_dev.dv_xname, sc->sc_nextstate);
394 1.12.6.2 nathanw sc->sc_nextstate = status0 & MESH_PHASE_MASK;
395 1.12.6.2 nathanw
396 1.12.6.2 nathanw DPRINTF("%d, resid = %d\n",
397 1.12.6.2 nathanw sc->sc_nextstate, scb->resid);
398 1.12.6.2 nathanw }
399 1.12.6.2 nathanw }
400 1.12.6.2 nathanw
401 1.12.6.2 nathanw if (sc->sc_nextstate == MESH_UNKNOWN)
402 1.12.6.2 nathanw sc->sc_nextstate = status0 & MESH_PHASE_MASK;
403 1.12.6.2 nathanw
404 1.12.6.2 nathanw switch (sc->sc_nextstate) {
405 1.12.6.2 nathanw
406 1.12.6.2 nathanw case MESH_IDENTIFY:
407 1.12.6.2 nathanw mesh_identify(sc, scb);
408 1.12.6.2 nathanw break;
409 1.12.6.2 nathanw case MESH_COMMAND:
410 1.12.6.2 nathanw mesh_command(sc, scb);
411 1.12.6.2 nathanw break;
412 1.12.6.2 nathanw case MESH_DATAIN:
413 1.12.6.2 nathanw case MESH_DATAOUT:
414 1.12.6.2 nathanw mesh_dataio(sc, scb);
415 1.12.6.2 nathanw break;
416 1.12.6.2 nathanw case MESH_STATUS:
417 1.12.6.2 nathanw mesh_status(sc, scb);
418 1.12.6.2 nathanw break;
419 1.12.6.2 nathanw case MESH_MSGIN:
420 1.12.6.2 nathanw mesh_msgin(sc, scb);
421 1.12.6.2 nathanw break;
422 1.12.6.2 nathanw case MESH_COMPLETE:
423 1.12.6.2 nathanw mesh_done(sc, scb);
424 1.12.6.2 nathanw break;
425 1.12.6.2 nathanw
426 1.12.6.2 nathanw default:
427 1.12.6.2 nathanw printf("%s: unknown state (%d)\n", sc->sc_dev.dv_xname,
428 1.12.6.2 nathanw sc->sc_nextstate);
429 1.12.6.2 nathanw scb->xs->error = XS_DRIVER_STUFFUP;
430 1.12.6.2 nathanw mesh_done(sc, scb);
431 1.12.6.2 nathanw }
432 1.12.6.2 nathanw
433 1.12.6.2 nathanw return 1;
434 1.12.6.2 nathanw }
435 1.12.6.2 nathanw
436 1.12.6.2 nathanw void
437 1.12.6.2 nathanw mesh_error(sc, scb, error, exception)
438 1.12.6.2 nathanw struct mesh_softc *sc;
439 1.12.6.2 nathanw struct mesh_scb *scb;
440 1.12.6.2 nathanw int error, exception;
441 1.12.6.2 nathanw {
442 1.12.6.2 nathanw if (error & MESH_ERR_SCSI_RESET) {
443 1.12.6.2 nathanw printf("%s: SCSI RESET\n", sc->sc_dev.dv_xname);
444 1.12.6.2 nathanw
445 1.12.6.2 nathanw /* Wait until the RST signal is deasserted. */
446 1.12.6.2 nathanw while (mesh_read_reg(sc, MESH_BUS_STATUS1) & MESH_STATUS1_RST);
447 1.12.6.2 nathanw mesh_reset(sc);
448 1.12.6.2 nathanw return;
449 1.12.6.2 nathanw }
450 1.12.6.2 nathanw
451 1.12.6.2 nathanw if (error & MESH_ERR_PARITY_ERR0) {
452 1.12.6.2 nathanw printf("%s: parity error\n", sc->sc_dev.dv_xname);
453 1.12.6.2 nathanw scb->xs->error = XS_DRIVER_STUFFUP;
454 1.12.6.2 nathanw }
455 1.12.6.2 nathanw
456 1.12.6.2 nathanw if (error & MESH_ERR_DISCONNECT) {
457 1.12.6.2 nathanw printf("%s: unexpected disconnect\n", sc->sc_dev.dv_xname);
458 1.12.6.2 nathanw if (sc->sc_nextstate != MESH_COMPLETE)
459 1.12.6.2 nathanw scb->xs->error = XS_DRIVER_STUFFUP;
460 1.12.6.2 nathanw }
461 1.12.6.2 nathanw
462 1.12.6.2 nathanw if (exception & MESH_EXC_SELTO) {
463 1.12.6.2 nathanw /* XXX should reset bus here? */
464 1.12.6.2 nathanw scb->xs->error = XS_SELTIMEOUT;
465 1.12.6.2 nathanw }
466 1.12.6.2 nathanw
467 1.12.6.2 nathanw mesh_done(sc, scb);
468 1.12.6.2 nathanw }
469 1.12.6.2 nathanw
470 1.12.6.2 nathanw void
471 1.12.6.2 nathanw mesh_select(sc, scb)
472 1.12.6.2 nathanw struct mesh_softc *sc;
473 1.12.6.2 nathanw struct mesh_scb *scb;
474 1.12.6.2 nathanw {
475 1.12.6.2 nathanw struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
476 1.12.6.2 nathanw int timeout;
477 1.12.6.2 nathanw
478 1.12.6.2 nathanw DPRINTF("mesh_select\n");
479 1.12.6.2 nathanw
480 1.12.6.2 nathanw mesh_setsync(sc, ti);
481 1.12.6.2 nathanw MESH_SET_XFER(sc, 0);
482 1.12.6.2 nathanw
483 1.12.6.2 nathanw /* arbitration */
484 1.12.6.2 nathanw
485 1.12.6.2 nathanw /*
486 1.12.6.2 nathanw * MESH mistakenly asserts TARGET ID bit along with its own ID bit
487 1.12.6.2 nathanw * in arbitration phase (like selection). So we should load
488 1.12.6.2 nathanw * initiator ID to DestID register temporarily.
489 1.12.6.2 nathanw */
490 1.12.6.2 nathanw mesh_set_reg(sc, MESH_DEST_ID, sc->sc_id);
491 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTR_MASK, 0); /* disable intr. */
492 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ARBITRATE);
493 1.12.6.2 nathanw
494 1.12.6.2 nathanw while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
495 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTERRUPT, 1);
496 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTR_MASK, 7);
497 1.12.6.2 nathanw
498 1.12.6.2 nathanw /* selection */
499 1.12.6.2 nathanw mesh_set_reg(sc, MESH_DEST_ID, scb->target);
500 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_SELECT | MESH_SEQ_ATN);
501 1.12.6.2 nathanw
502 1.12.6.2 nathanw sc->sc_prevphase = MESH_SELECTING;
503 1.12.6.2 nathanw sc->sc_nextstate = MESH_IDENTIFY;
504 1.12.6.2 nathanw
505 1.12.6.2 nathanw timeout = mstohz(scb->xs->timeout);
506 1.12.6.2 nathanw if (timeout == 0)
507 1.12.6.2 nathanw timeout = 1;
508 1.12.6.2 nathanw
509 1.12.6.2 nathanw callout_reset(&scb->xs->xs_callout, timeout, mesh_timeout, scb);
510 1.12.6.2 nathanw }
511 1.12.6.2 nathanw
512 1.12.6.2 nathanw void
513 1.12.6.2 nathanw mesh_identify(sc, scb)
514 1.12.6.2 nathanw struct mesh_softc *sc;
515 1.12.6.2 nathanw struct mesh_scb *scb;
516 1.12.6.2 nathanw {
517 1.12.6.2 nathanw struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
518 1.12.6.2 nathanw
519 1.12.6.2 nathanw DPRINTF("mesh_identify\n");
520 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
521 1.12.6.2 nathanw
522 1.12.6.2 nathanw if ((ti->flags & T_SYNCNEGO) == 0) {
523 1.12.6.2 nathanw ti->period = sc->sc_minsync;
524 1.12.6.2 nathanw ti->offset = 15;
525 1.12.6.2 nathanw mesh_msgout(sc, SEND_IDENTIFY | SEND_SDTR);
526 1.12.6.2 nathanw sc->sc_nextstate = MESH_MSGIN;
527 1.12.6.2 nathanw } else {
528 1.12.6.2 nathanw mesh_msgout(sc, SEND_IDENTIFY);
529 1.12.6.2 nathanw sc->sc_nextstate = MESH_COMMAND;
530 1.12.6.2 nathanw }
531 1.12.6.2 nathanw }
532 1.12.6.2 nathanw
533 1.12.6.2 nathanw void
534 1.12.6.2 nathanw mesh_command(sc, scb)
535 1.12.6.2 nathanw struct mesh_softc *sc;
536 1.12.6.2 nathanw struct mesh_scb *scb;
537 1.12.6.2 nathanw {
538 1.12.6.2 nathanw int i;
539 1.12.6.2 nathanw char *cmdp;
540 1.12.6.2 nathanw
541 1.12.6.2 nathanw #ifdef MESH_DEBUG
542 1.12.6.2 nathanw printf("mesh_command cdb = %02x", scb->cmd.opcode);
543 1.12.6.2 nathanw for (i = 0; i < 5; i++)
544 1.12.6.2 nathanw printf(" %02x", scb->cmd.bytes[i]);
545 1.12.6.2 nathanw printf("\n");
546 1.12.6.2 nathanw #endif
547 1.12.6.2 nathanw
548 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
549 1.12.6.2 nathanw
550 1.12.6.2 nathanw MESH_SET_XFER(sc, scb->cmdlen);
551 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_COMMAND);
552 1.12.6.2 nathanw
553 1.12.6.2 nathanw cmdp = (char *)&scb->cmd;
554 1.12.6.2 nathanw for (i = 0; i < scb->cmdlen; i++)
555 1.12.6.2 nathanw mesh_set_reg(sc, MESH_FIFO, *cmdp++);
556 1.12.6.2 nathanw
557 1.12.6.2 nathanw if (scb->resid == 0)
558 1.12.6.2 nathanw sc->sc_nextstate = MESH_STATUS; /* no data xfer */
559 1.12.6.2 nathanw else
560 1.12.6.2 nathanw sc->sc_nextstate = MESH_DATAIN;
561 1.12.6.2 nathanw }
562 1.12.6.2 nathanw
563 1.12.6.2 nathanw void
564 1.12.6.2 nathanw mesh_dma_setup(sc, scb)
565 1.12.6.2 nathanw struct mesh_softc *sc;
566 1.12.6.2 nathanw struct mesh_scb *scb;
567 1.12.6.2 nathanw {
568 1.12.6.2 nathanw int datain = scb->flags & MESH_READ;
569 1.12.6.2 nathanw dbdma_command_t *cmdp;
570 1.12.6.2 nathanw u_int cmd;
571 1.12.6.2 nathanw vaddr_t va;
572 1.12.6.2 nathanw int count, offset;
573 1.12.6.2 nathanw
574 1.12.6.2 nathanw cmdp = sc->sc_dmacmd;
575 1.12.6.2 nathanw cmd = datain ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE;
576 1.12.6.2 nathanw
577 1.12.6.2 nathanw count = scb->dlen;
578 1.12.6.2 nathanw
579 1.12.6.2 nathanw if (count / NBPG > 32)
580 1.12.6.2 nathanw panic("mesh: transfer size >= 128k");
581 1.12.6.2 nathanw
582 1.12.6.2 nathanw va = scb->daddr;
583 1.12.6.2 nathanw offset = va & PGOFSET;
584 1.12.6.2 nathanw
585 1.12.6.2 nathanw /* if va is not page-aligned, setup the first page */
586 1.12.6.2 nathanw if (offset != 0) {
587 1.12.6.2 nathanw int rest = NBPG - offset; /* the rest in the page */
588 1.12.6.2 nathanw
589 1.12.6.2 nathanw if (count > rest) { /* if continues to next page */
590 1.12.6.2 nathanw DBDMA_BUILD(cmdp, cmd, 0, rest, vtophys(va),
591 1.12.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER,
592 1.12.6.2 nathanw DBDMA_BRANCH_NEVER);
593 1.12.6.2 nathanw count -= rest;
594 1.12.6.2 nathanw va += rest;
595 1.12.6.2 nathanw cmdp++;
596 1.12.6.2 nathanw }
597 1.12.6.2 nathanw }
598 1.12.6.2 nathanw
599 1.12.6.2 nathanw /* now va is page-aligned */
600 1.12.6.2 nathanw while (count > NBPG) {
601 1.12.6.2 nathanw DBDMA_BUILD(cmdp, cmd, 0, NBPG, vtophys(va),
602 1.12.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
603 1.12.6.2 nathanw count -= NBPG;
604 1.12.6.2 nathanw va += NBPG;
605 1.12.6.2 nathanw cmdp++;
606 1.12.6.2 nathanw }
607 1.12.6.2 nathanw
608 1.12.6.2 nathanw /* the last page (count <= NBPG here) */
609 1.12.6.2 nathanw cmd = datain ? DBDMA_CMD_IN_LAST : DBDMA_CMD_OUT_LAST;
610 1.12.6.2 nathanw DBDMA_BUILD(cmdp, cmd , 0, count, vtophys(va),
611 1.12.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
612 1.12.6.2 nathanw cmdp++;
613 1.12.6.2 nathanw
614 1.12.6.2 nathanw DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
615 1.12.6.2 nathanw DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
616 1.12.6.2 nathanw }
617 1.12.6.2 nathanw
618 1.12.6.2 nathanw void
619 1.12.6.2 nathanw mesh_dataio(sc, scb)
620 1.12.6.2 nathanw struct mesh_softc *sc;
621 1.12.6.2 nathanw struct mesh_scb *scb;
622 1.12.6.2 nathanw {
623 1.12.6.2 nathanw DPRINTF("mesh_dataio len = %ld (%s)\n", scb->dlen,
624 1.12.6.2 nathanw scb->flags & MESH_READ ? "read" : "write");
625 1.12.6.2 nathanw
626 1.12.6.2 nathanw mesh_dma_setup(sc, scb);
627 1.12.6.2 nathanw
628 1.12.6.2 nathanw if (scb->dlen == 65536)
629 1.12.6.2 nathanw MESH_SET_XFER(sc, 0); /* TC = 0 means 64KB transfer */
630 1.12.6.2 nathanw else
631 1.12.6.2 nathanw MESH_SET_XFER(sc, scb->dlen);
632 1.12.6.2 nathanw
633 1.12.6.2 nathanw if (scb->flags & MESH_READ)
634 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAIN | MESH_SEQ_DMA);
635 1.12.6.2 nathanw else
636 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAOUT | MESH_SEQ_DMA);
637 1.12.6.2 nathanw dbdma_start(sc->sc_dmareg, sc->sc_dmacmd);
638 1.12.6.2 nathanw sc->sc_flags |= MESH_DMA_ACTIVE;
639 1.12.6.2 nathanw sc->sc_nextstate = MESH_STATUS;
640 1.12.6.2 nathanw }
641 1.12.6.2 nathanw
642 1.12.6.2 nathanw void
643 1.12.6.2 nathanw mesh_status(sc, scb)
644 1.12.6.2 nathanw struct mesh_softc *sc;
645 1.12.6.2 nathanw struct mesh_scb *scb;
646 1.12.6.2 nathanw {
647 1.12.6.2 nathanw if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
648 1.12.6.2 nathanw DPRINTF("mesh_status(0)\n");
649 1.12.6.2 nathanw MESH_SET_XFER(sc, 1);
650 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_STATUS);
651 1.12.6.2 nathanw sc->sc_nextstate = MESH_STATUS;
652 1.12.6.2 nathanw return;
653 1.12.6.2 nathanw }
654 1.12.6.2 nathanw
655 1.12.6.2 nathanw scb->status = mesh_read_reg(sc, MESH_FIFO);
656 1.12.6.2 nathanw DPRINTF("mesh_status(1): status = 0x%x\n", scb->status);
657 1.12.6.2 nathanw if (mesh_read_reg(sc, MESH_FIFO_COUNT) != 0)
658 1.12.6.2 nathanw DPRINTF("FIFO_COUNT=%d\n", mesh_read_reg(sc, MESH_FIFO_COUNT));
659 1.12.6.2 nathanw
660 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
661 1.12.6.2 nathanw MESH_SET_XFER(sc, 1);
662 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
663 1.12.6.2 nathanw
664 1.12.6.2 nathanw sc->sc_nextstate = MESH_MSGIN;
665 1.12.6.2 nathanw }
666 1.12.6.2 nathanw
667 1.12.6.2 nathanw void
668 1.12.6.2 nathanw mesh_msgin(sc, scb)
669 1.12.6.2 nathanw struct mesh_softc *sc;
670 1.12.6.2 nathanw struct mesh_scb *scb;
671 1.12.6.2 nathanw {
672 1.12.6.2 nathanw DPRINTF("mesh_msgin\n");
673 1.12.6.2 nathanw
674 1.12.6.2 nathanw if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
675 1.12.6.2 nathanw MESH_SET_XFER(sc, 1);
676 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
677 1.12.6.2 nathanw sc->sc_imsglen = 0;
678 1.12.6.2 nathanw sc->sc_nextstate = MESH_MSGIN;
679 1.12.6.2 nathanw return;
680 1.12.6.2 nathanw }
681 1.12.6.2 nathanw
682 1.12.6.2 nathanw sc->sc_imsg[sc->sc_imsglen++] = mesh_read_reg(sc, MESH_FIFO);
683 1.12.6.2 nathanw
684 1.12.6.2 nathanw if (sc->sc_imsglen == 1 && MSG_IS1BYTE(sc->sc_imsg[0]))
685 1.12.6.2 nathanw goto gotit;
686 1.12.6.2 nathanw if (sc->sc_imsglen == 2 && MSG_IS2BYTE(sc->sc_imsg[0]))
687 1.12.6.2 nathanw goto gotit;
688 1.12.6.2 nathanw if (sc->sc_imsglen >= 3 && MSG_ISEXTENDED(sc->sc_imsg[0]) &&
689 1.12.6.2 nathanw sc->sc_imsglen == sc->sc_imsg[1] + 2)
690 1.12.6.2 nathanw goto gotit;
691 1.12.6.2 nathanw
692 1.12.6.2 nathanw sc->sc_nextstate = MESH_MSGIN;
693 1.12.6.2 nathanw MESH_SET_XFER(sc, 1);
694 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
695 1.12.6.2 nathanw return;
696 1.12.6.2 nathanw
697 1.12.6.2 nathanw gotit:
698 1.12.6.2 nathanw #ifdef MESH_DEBUG
699 1.12.6.2 nathanw printf("msgin:");
700 1.12.6.2 nathanw for (i = 0; i < sc->sc_imsglen; i++)
701 1.12.6.2 nathanw printf(" 0x%02x", sc->sc_imsg[i]);
702 1.12.6.2 nathanw printf("\n");
703 1.12.6.2 nathanw #endif
704 1.12.6.2 nathanw
705 1.12.6.2 nathanw switch (sc->sc_imsg[0]) {
706 1.12.6.2 nathanw case MSG_CMDCOMPLETE:
707 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
708 1.12.6.2 nathanw sc->sc_nextstate = MESH_COMPLETE;
709 1.12.6.2 nathanw sc->sc_imsglen = 0;
710 1.12.6.2 nathanw return;
711 1.12.6.2 nathanw
712 1.12.6.2 nathanw case MSG_MESSAGE_REJECT:
713 1.12.6.2 nathanw if (sc->sc_msgout & SEND_SDTR) {
714 1.12.6.2 nathanw printf("SDTR rejected\n");
715 1.12.6.2 nathanw printf("using async mode\n");
716 1.12.6.2 nathanw sc->sc_tinfo[scb->target].period = 0;
717 1.12.6.2 nathanw sc->sc_tinfo[scb->target].offset = 0;
718 1.12.6.2 nathanw mesh_setsync(sc, &sc->sc_tinfo[scb->target]);
719 1.12.6.2 nathanw break;
720 1.12.6.2 nathanw }
721 1.12.6.2 nathanw break;
722 1.12.6.2 nathanw
723 1.12.6.2 nathanw case MSG_NOOP:
724 1.12.6.2 nathanw break;
725 1.12.6.2 nathanw
726 1.12.6.2 nathanw case MSG_EXTENDED:
727 1.12.6.2 nathanw goto extended_msg;
728 1.12.6.2 nathanw
729 1.12.6.2 nathanw default:
730 1.12.6.2 nathanw scsipi_printaddr(scb->xs->xs_periph);
731 1.12.6.2 nathanw printf("unrecognized MESSAGE(0x%02x); sending REJECT\n",
732 1.12.6.2 nathanw sc->sc_imsg[0]);
733 1.12.6.2 nathanw
734 1.12.6.2 nathanw reject:
735 1.12.6.2 nathanw mesh_msgout(sc, SEND_REJECT);
736 1.12.6.2 nathanw return;
737 1.12.6.2 nathanw }
738 1.12.6.2 nathanw goto done;
739 1.12.6.2 nathanw
740 1.12.6.2 nathanw extended_msg:
741 1.12.6.2 nathanw /* process an extended message */
742 1.12.6.2 nathanw switch (sc->sc_imsg[2]) {
743 1.12.6.2 nathanw case MSG_EXT_SDTR:
744 1.12.6.2 nathanw {
745 1.12.6.2 nathanw struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
746 1.12.6.2 nathanw int period = sc->sc_imsg[3];
747 1.12.6.2 nathanw int offset = sc->sc_imsg[4];
748 1.12.6.2 nathanw int r = 250 / period;
749 1.12.6.2 nathanw int s = (100*250) / period - 100 * r;
750 1.12.6.2 nathanw
751 1.12.6.2 nathanw if (period < sc->sc_minsync) {
752 1.12.6.2 nathanw ti->period = sc->sc_minsync;
753 1.12.6.2 nathanw ti->offset = 15;
754 1.12.6.2 nathanw mesh_msgout(sc, SEND_SDTR);
755 1.12.6.2 nathanw return;
756 1.12.6.2 nathanw }
757 1.12.6.2 nathanw scsipi_printaddr(scb->xs->xs_periph);
758 1.12.6.2 nathanw /* XXX if (offset != 0) ... */
759 1.12.6.2 nathanw printf("max sync rate %d.%02dMb/s\n", r, s);
760 1.12.6.2 nathanw ti->period = period;
761 1.12.6.2 nathanw ti->offset = offset;
762 1.12.6.2 nathanw ti->flags |= T_SYNCNEGO;
763 1.12.6.2 nathanw ti->flags |= T_SYNCMODE;
764 1.12.6.2 nathanw mesh_setsync(sc, ti);
765 1.12.6.2 nathanw goto done;
766 1.12.6.2 nathanw }
767 1.12.6.2 nathanw default:
768 1.12.6.2 nathanw printf("%s target %d: rejecting extended message 0x%x\n",
769 1.12.6.2 nathanw sc->sc_dev.dv_xname, scb->target, sc->sc_imsg[0]);
770 1.12.6.2 nathanw goto reject;
771 1.12.6.2 nathanw }
772 1.12.6.2 nathanw
773 1.12.6.2 nathanw done:
774 1.12.6.2 nathanw sc->sc_imsglen = 0;
775 1.12.6.2 nathanw sc->sc_nextstate = MESH_UNKNOWN;
776 1.12.6.2 nathanw
777 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); /* XXX really? */
778 1.12.6.2 nathanw }
779 1.12.6.2 nathanw
780 1.12.6.2 nathanw void
781 1.12.6.2 nathanw mesh_msgout(sc, msg)
782 1.12.6.2 nathanw struct mesh_softc *sc;
783 1.12.6.2 nathanw int msg;
784 1.12.6.2 nathanw {
785 1.12.6.2 nathanw struct mesh_scb *scb = sc->sc_nexus;
786 1.12.6.2 nathanw struct mesh_tinfo *ti;
787 1.12.6.2 nathanw int lun, len, i;
788 1.12.6.2 nathanw
789 1.12.6.2 nathanw DPRINTF("mesh_msgout: sending");
790 1.12.6.2 nathanw
791 1.12.6.2 nathanw sc->sc_msgout = msg;
792 1.12.6.2 nathanw len = 0;
793 1.12.6.2 nathanw
794 1.12.6.2 nathanw if (msg & SEND_REJECT) {
795 1.12.6.2 nathanw DPRINTF(" REJECT");
796 1.12.6.2 nathanw sc->sc_omsg[len++] = MSG_MESSAGE_REJECT;
797 1.12.6.2 nathanw }
798 1.12.6.2 nathanw if (msg & SEND_IDENTIFY) {
799 1.12.6.2 nathanw DPRINTF(" IDENTIFY");
800 1.12.6.2 nathanw lun = scb->xs->xs_periph->periph_lun;
801 1.12.6.2 nathanw sc->sc_omsg[len++] = MSG_IDENTIFY(lun, 0);
802 1.12.6.2 nathanw }
803 1.12.6.2 nathanw if (msg & SEND_SDTR) {
804 1.12.6.2 nathanw DPRINTF(" SDTR");
805 1.12.6.2 nathanw ti = &sc->sc_tinfo[scb->target];
806 1.12.6.2 nathanw sc->sc_omsg[len++] = MSG_EXTENDED;
807 1.12.6.2 nathanw sc->sc_omsg[len++] = 3;
808 1.12.6.2 nathanw sc->sc_omsg[len++] = MSG_EXT_SDTR;
809 1.12.6.2 nathanw sc->sc_omsg[len++] = ti->period;
810 1.12.6.2 nathanw sc->sc_omsg[len++] = ti->offset;
811 1.12.6.2 nathanw }
812 1.12.6.2 nathanw DPRINTF("\n");
813 1.12.6.2 nathanw
814 1.12.6.2 nathanw MESH_SET_XFER(sc, len);
815 1.12.6.2 nathanw if (len == 1) {
816 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT);
817 1.12.6.2 nathanw mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[0]);
818 1.12.6.2 nathanw } else {
819 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT | MESH_SEQ_ATN);
820 1.12.6.2 nathanw
821 1.12.6.2 nathanw for (i = 0; i < len - 1; i++)
822 1.12.6.2 nathanw mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
823 1.12.6.2 nathanw
824 1.12.6.2 nathanw /* Wait for the FIFO empty... */
825 1.12.6.2 nathanw while (mesh_read_reg(sc, MESH_FIFO_COUNT) > 0);
826 1.12.6.2 nathanw
827 1.12.6.2 nathanw /* ...then write the last byte. */
828 1.12.6.2 nathanw mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
829 1.12.6.2 nathanw }
830 1.12.6.2 nathanw sc->sc_nextstate = MESH_UNKNOWN;
831 1.12.6.2 nathanw }
832 1.12.6.2 nathanw
833 1.12.6.2 nathanw void
834 1.12.6.2 nathanw mesh_bus_reset(sc)
835 1.12.6.2 nathanw struct mesh_softc *sc;
836 1.12.6.2 nathanw {
837 1.12.6.2 nathanw DPRINTF("mesh_bus_reset\n");
838 1.12.6.2 nathanw
839 1.12.6.2 nathanw /* Disable interrupts. */
840 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTR_MASK, 0);
841 1.12.6.2 nathanw
842 1.12.6.2 nathanw /* Assert RST line. */
843 1.12.6.2 nathanw mesh_set_reg(sc, MESH_BUS_STATUS1, MESH_STATUS1_RST);
844 1.12.6.2 nathanw delay(50);
845 1.12.6.2 nathanw mesh_set_reg(sc, MESH_BUS_STATUS1, 0);
846 1.12.6.2 nathanw
847 1.12.6.2 nathanw mesh_reset(sc);
848 1.12.6.2 nathanw }
849 1.12.6.2 nathanw
850 1.12.6.2 nathanw void
851 1.12.6.2 nathanw mesh_reset(sc)
852 1.12.6.2 nathanw struct mesh_softc *sc;
853 1.12.6.2 nathanw {
854 1.12.6.2 nathanw int i;
855 1.12.6.2 nathanw
856 1.12.6.2 nathanw DPRINTF("mesh_reset\n");
857 1.12.6.2 nathanw
858 1.12.6.2 nathanw /* Reset DMA first. */
859 1.12.6.2 nathanw dbdma_reset(sc->sc_dmareg);
860 1.12.6.2 nathanw
861 1.12.6.2 nathanw /* Disable interrupts. */
862 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTR_MASK, 0);
863 1.12.6.2 nathanw
864 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_RESET_MESH);
865 1.12.6.2 nathanw delay(1);
866 1.12.6.2 nathanw
867 1.12.6.2 nathanw /* Wait for reset done. */
868 1.12.6.2 nathanw while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
869 1.12.6.2 nathanw
870 1.12.6.2 nathanw /* Clear interrupts */
871 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTERRUPT, 0x7);
872 1.12.6.2 nathanw
873 1.12.6.2 nathanw /* Set SCSI ID */
874 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SOURCE_ID, sc->sc_id);
875 1.12.6.2 nathanw
876 1.12.6.2 nathanw /* Set to async mode by default. */
877 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
878 1.12.6.2 nathanw
879 1.12.6.2 nathanw /* Set selection timeout to 250ms. */
880 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEL_TIMEOUT, 250 * sc->sc_freq / 500);
881 1.12.6.2 nathanw
882 1.12.6.2 nathanw /* Enable parity check. */
883 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ENABLE_PARITY);
884 1.12.6.2 nathanw
885 1.12.6.2 nathanw /* Enable all interrupts. */
886 1.12.6.2 nathanw mesh_set_reg(sc, MESH_INTR_MASK, 0x7);
887 1.12.6.2 nathanw
888 1.12.6.2 nathanw for (i = 0; i < 7; i++) {
889 1.12.6.2 nathanw struct mesh_tinfo *ti = &sc->sc_tinfo[i];
890 1.12.6.2 nathanw
891 1.12.6.2 nathanw ti->flags = 0;
892 1.12.6.2 nathanw ti->period = ti->offset = 0;
893 1.12.6.2 nathanw if (sc->sc_cfflags & (0x100 << i))
894 1.12.6.2 nathanw ti->flags |= T_SYNCNEGO;
895 1.12.6.2 nathanw }
896 1.12.6.2 nathanw sc->sc_nexus = NULL;
897 1.12.6.2 nathanw }
898 1.12.6.2 nathanw
899 1.12.6.2 nathanw int
900 1.12.6.2 nathanw mesh_stp(sc, v)
901 1.12.6.2 nathanw struct mesh_softc *sc;
902 1.12.6.2 nathanw int v;
903 1.12.6.2 nathanw {
904 1.12.6.2 nathanw /*
905 1.12.6.2 nathanw * stp(v) = 5 * clock_period (v == 0)
906 1.12.6.2 nathanw * = (v + 2) * 2 clock_period (v > 0)
907 1.12.6.2 nathanw */
908 1.12.6.2 nathanw
909 1.12.6.2 nathanw if (v == 0)
910 1.12.6.2 nathanw return 5 * 250 / sc->sc_freq;
911 1.12.6.2 nathanw else
912 1.12.6.2 nathanw return (v + 2) * 2 * 250 / sc->sc_freq;
913 1.12.6.2 nathanw }
914 1.12.6.2 nathanw
915 1.12.6.2 nathanw void
916 1.12.6.2 nathanw mesh_setsync(sc, ti)
917 1.12.6.2 nathanw struct mesh_softc *sc;
918 1.12.6.2 nathanw struct mesh_tinfo *ti;
919 1.12.6.2 nathanw {
920 1.12.6.2 nathanw int period = ti->period;
921 1.12.6.2 nathanw int offset = ti->offset;
922 1.12.6.2 nathanw int v;
923 1.12.6.2 nathanw
924 1.12.6.2 nathanw if ((ti->flags & T_SYNCMODE) == 0)
925 1.12.6.2 nathanw offset = 0;
926 1.12.6.2 nathanw
927 1.12.6.2 nathanw if (offset == 0) { /* async mode */
928 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
929 1.12.6.2 nathanw return;
930 1.12.6.2 nathanw }
931 1.12.6.2 nathanw
932 1.12.6.2 nathanw v = period * sc->sc_freq / 250 / 2 - 2;
933 1.12.6.2 nathanw if (v < 0)
934 1.12.6.2 nathanw v = 0;
935 1.12.6.2 nathanw if (mesh_stp(sc, v) < period)
936 1.12.6.2 nathanw v++;
937 1.12.6.2 nathanw if (v > 15)
938 1.12.6.2 nathanw v = 15;
939 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v);
940 1.12.6.2 nathanw }
941 1.12.6.2 nathanw
942 1.12.6.2 nathanw struct mesh_scb *
943 1.12.6.2 nathanw mesh_get_scb(sc)
944 1.12.6.2 nathanw struct mesh_softc *sc;
945 1.12.6.2 nathanw {
946 1.12.6.2 nathanw struct mesh_scb *scb;
947 1.12.6.2 nathanw int s;
948 1.12.6.2 nathanw
949 1.12.6.2 nathanw s = splbio();
950 1.12.6.2 nathanw if ((scb = sc->free_scb.tqh_first) != NULL)
951 1.12.6.2 nathanw TAILQ_REMOVE(&sc->free_scb, scb, chain);
952 1.12.6.2 nathanw splx(s);
953 1.12.6.2 nathanw
954 1.12.6.2 nathanw return scb;
955 1.12.6.2 nathanw }
956 1.12.6.2 nathanw
957 1.12.6.2 nathanw void
958 1.12.6.2 nathanw mesh_free_scb(sc, scb)
959 1.12.6.2 nathanw struct mesh_softc *sc;
960 1.12.6.2 nathanw struct mesh_scb *scb;
961 1.12.6.2 nathanw {
962 1.12.6.2 nathanw int s;
963 1.12.6.2 nathanw
964 1.12.6.2 nathanw s = splbio();
965 1.12.6.2 nathanw TAILQ_INSERT_HEAD(&sc->free_scb, scb, chain);
966 1.12.6.2 nathanw splx(s);
967 1.12.6.2 nathanw }
968 1.12.6.2 nathanw
969 1.12.6.2 nathanw void
970 1.12.6.2 nathanw mesh_scsi_request(chan, req, arg)
971 1.12.6.2 nathanw struct scsipi_channel *chan;
972 1.12.6.2 nathanw scsipi_adapter_req_t req;
973 1.12.6.2 nathanw void *arg;
974 1.12.6.2 nathanw {
975 1.12.6.2 nathanw struct scsipi_xfer *xs;
976 1.12.6.2 nathanw struct scsipi_periph *periph;
977 1.12.6.2 nathanw struct mesh_softc *sc = (void *)chan->chan_adapter->adapt_dev;
978 1.12.6.2 nathanw struct mesh_scb *scb;
979 1.12.6.2 nathanw u_int flags;
980 1.12.6.2 nathanw int s;
981 1.12.6.2 nathanw
982 1.12.6.2 nathanw switch (req) {
983 1.12.6.2 nathanw case ADAPTER_REQ_RUN_XFER:
984 1.12.6.2 nathanw xs = arg;
985 1.12.6.2 nathanw periph = xs->xs_periph;
986 1.12.6.2 nathanw flags = xs->xs_control;
987 1.12.6.2 nathanw
988 1.12.6.2 nathanw
989 1.12.6.2 nathanw if ((scb = mesh_get_scb(sc)) == NULL) {
990 1.12.6.2 nathanw xs->error = XS_RESOURCE_SHORTAGE;
991 1.12.6.2 nathanw scsipi_done(xs);
992 1.12.6.2 nathanw return;
993 1.12.6.2 nathanw }
994 1.12.6.2 nathanw scb->xs = xs;
995 1.12.6.2 nathanw scb->flags = 0;
996 1.12.6.2 nathanw scb->status = 0;
997 1.12.6.2 nathanw scb->daddr = (vaddr_t)xs->data;
998 1.12.6.2 nathanw scb->dlen = xs->datalen;
999 1.12.6.2 nathanw scb->resid = xs->datalen;
1000 1.12.6.2 nathanw memcpy(&scb->cmd, xs->cmd, xs->cmdlen);
1001 1.12.6.2 nathanw scb->cmdlen = xs->cmdlen;
1002 1.12.6.2 nathanw scb->target = periph->periph_target;
1003 1.12.6.2 nathanw sc->sc_imsglen = 0; /* XXX ? */
1004 1.12.6.2 nathanw
1005 1.12.6.2 nathanw #ifdef MESH_DEBUG
1006 1.12.6.2 nathanw {
1007 1.12.6.2 nathanw int i;
1008 1.12.6.2 nathanw printf("mesh_scsi_cmd: target = %d, cdb = %02x",
1009 1.12.6.2 nathanw scb->target, scb->cmd.opcode);
1010 1.12.6.2 nathanw for (i = 0; i < 5; i++)
1011 1.12.6.2 nathanw printf(" %02x", scb->cmd.bytes[i]);
1012 1.12.6.2 nathanw printf("\n");
1013 1.12.6.2 nathanw }
1014 1.12.6.2 nathanw #endif
1015 1.12.6.2 nathanw
1016 1.12.6.2 nathanw if (flags & XS_CTL_POLL)
1017 1.12.6.2 nathanw scb->flags |= MESH_POLL;
1018 1.12.6.2 nathanw #if 0
1019 1.12.6.2 nathanw if (flags & XS_CTL_DATA_OUT)
1020 1.12.6.2 nathanw scb->flags &= ~MESH_READ;
1021 1.12.6.2 nathanw #endif
1022 1.12.6.2 nathanw if (flags & XS_CTL_DATA_IN)
1023 1.12.6.2 nathanw scb->flags |= MESH_READ;
1024 1.12.6.2 nathanw
1025 1.12.6.2 nathanw s = splbio();
1026 1.12.6.2 nathanw
1027 1.12.6.2 nathanw TAILQ_INSERT_TAIL(&sc->ready_scb, scb, chain);
1028 1.12.6.2 nathanw
1029 1.12.6.2 nathanw if (sc->sc_nexus == NULL) /* IDLE */
1030 1.12.6.2 nathanw mesh_sched(sc);
1031 1.12.6.2 nathanw
1032 1.12.6.2 nathanw splx(s);
1033 1.12.6.2 nathanw
1034 1.12.6.2 nathanw if ((flags & XS_CTL_POLL) == 0)
1035 1.12.6.2 nathanw return;
1036 1.12.6.2 nathanw
1037 1.12.6.2 nathanw if (mesh_poll(sc, xs)) {
1038 1.12.6.2 nathanw printf("%s: timeout\n", sc->sc_dev.dv_xname);
1039 1.12.6.2 nathanw if (mesh_poll(sc, xs))
1040 1.12.6.2 nathanw printf("%s: timeout again\n", sc->sc_dev.dv_xname);
1041 1.12.6.2 nathanw }
1042 1.12.6.2 nathanw return;
1043 1.12.6.2 nathanw
1044 1.12.6.2 nathanw case ADAPTER_REQ_GROW_RESOURCES:
1045 1.12.6.2 nathanw /* XXX Not supported. */
1046 1.12.6.2 nathanw return;
1047 1.12.6.2 nathanw
1048 1.12.6.2 nathanw case ADAPTER_REQ_SET_XFER_MODE:
1049 1.12.6.2 nathanw /* XXX Not supported. */
1050 1.12.6.2 nathanw return;
1051 1.12.6.2 nathanw }
1052 1.12.6.2 nathanw
1053 1.12.6.2 nathanw }
1054 1.12.6.2 nathanw
1055 1.12.6.2 nathanw void
1056 1.12.6.2 nathanw mesh_sched(sc)
1057 1.12.6.2 nathanw struct mesh_softc *sc;
1058 1.12.6.2 nathanw {
1059 1.12.6.2 nathanw struct scsipi_xfer *xs;
1060 1.12.6.2 nathanw struct mesh_scb *scb;
1061 1.12.6.2 nathanw
1062 1.12.6.2 nathanw scb = sc->ready_scb.tqh_first;
1063 1.12.6.2 nathanw start:
1064 1.12.6.2 nathanw if (scb == NULL)
1065 1.12.6.2 nathanw return;
1066 1.12.6.2 nathanw
1067 1.12.6.2 nathanw xs = scb->xs;
1068 1.12.6.2 nathanw
1069 1.12.6.2 nathanw if (sc->sc_nexus == NULL) {
1070 1.12.6.2 nathanw TAILQ_REMOVE(&sc->ready_scb, scb, chain);
1071 1.12.6.2 nathanw sc->sc_nexus = scb;
1072 1.12.6.2 nathanw mesh_select(sc, scb);
1073 1.12.6.2 nathanw return;
1074 1.12.6.2 nathanw }
1075 1.12.6.2 nathanw
1076 1.12.6.2 nathanw scb = scb->chain.tqe_next;
1077 1.12.6.2 nathanw goto start;
1078 1.12.6.2 nathanw }
1079 1.12.6.2 nathanw
1080 1.12.6.2 nathanw int
1081 1.12.6.2 nathanw mesh_poll(sc, xs)
1082 1.12.6.2 nathanw struct mesh_softc *sc;
1083 1.12.6.2 nathanw struct scsipi_xfer *xs;
1084 1.12.6.2 nathanw {
1085 1.12.6.2 nathanw int count = xs->timeout;
1086 1.12.6.2 nathanw
1087 1.12.6.2 nathanw while (count) {
1088 1.12.6.2 nathanw if (mesh_read_reg(sc, MESH_INTERRUPT))
1089 1.12.6.2 nathanw mesh_intr(sc);
1090 1.12.6.2 nathanw
1091 1.12.6.2 nathanw if (xs->xs_status & XS_STS_DONE)
1092 1.12.6.2 nathanw return 0;
1093 1.12.6.2 nathanw delay(1000);
1094 1.12.6.2 nathanw count--;
1095 1.12.6.2 nathanw };
1096 1.12.6.2 nathanw return 1;
1097 1.12.6.2 nathanw }
1098 1.12.6.2 nathanw
1099 1.12.6.2 nathanw void
1100 1.12.6.2 nathanw mesh_done(sc, scb)
1101 1.12.6.2 nathanw struct mesh_softc *sc;
1102 1.12.6.2 nathanw struct mesh_scb *scb;
1103 1.12.6.2 nathanw {
1104 1.12.6.2 nathanw struct scsipi_xfer *xs = scb->xs;
1105 1.12.6.2 nathanw
1106 1.12.6.2 nathanw DPRINTF("mesh_done\n");
1107 1.12.6.2 nathanw
1108 1.12.6.2 nathanw sc->sc_nextstate = MESH_BUSFREE;
1109 1.12.6.2 nathanw sc->sc_nexus = NULL;
1110 1.12.6.2 nathanw
1111 1.12.6.2 nathanw callout_stop(&scb->xs->xs_callout);
1112 1.12.6.2 nathanw
1113 1.12.6.2 nathanw if (scb->status == SCSI_BUSY) {
1114 1.12.6.2 nathanw xs->error = XS_BUSY;
1115 1.12.6.2 nathanw printf("Target busy\n");
1116 1.12.6.2 nathanw }
1117 1.12.6.2 nathanw
1118 1.12.6.2 nathanw xs->xs_status = scb->status;
1119 1.12.6.2 nathanw xs->resid = scb->resid;
1120 1.12.6.2 nathanw if (scb->status == SCSI_CHECK) {
1121 1.12.6.2 nathanw xs->error = XS_BUSY;
1122 1.12.6.2 nathanw }
1123 1.12.6.2 nathanw
1124 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
1125 1.12.6.2 nathanw
1126 1.12.6.2 nathanw if ((xs->xs_control & XS_CTL_POLL) == 0)
1127 1.12.6.2 nathanw mesh_sched(sc);
1128 1.12.6.2 nathanw
1129 1.12.6.2 nathanw scsipi_done(xs);
1130 1.12.6.2 nathanw mesh_free_scb(sc, scb);
1131 1.12.6.2 nathanw }
1132 1.12.6.2 nathanw
1133 1.12.6.2 nathanw void
1134 1.12.6.2 nathanw mesh_timeout(arg)
1135 1.12.6.2 nathanw void *arg;
1136 1.12.6.2 nathanw {
1137 1.12.6.2 nathanw struct mesh_scb *scb = arg;
1138 1.12.6.2 nathanw struct mesh_softc *sc =
1139 1.12.6.2 nathanw (void *)scb->xs->xs_periph->periph_channel->chan_adapter->adapt_dev;
1140 1.12.6.2 nathanw int s;
1141 1.12.6.2 nathanw int status0, status1;
1142 1.12.6.2 nathanw int intr, error, exception;
1143 1.12.6.2 nathanw
1144 1.12.6.2 nathanw printf("%s: timeout state %d\n", sc->sc_dev.dv_xname, sc->sc_nextstate);
1145 1.12.6.2 nathanw
1146 1.12.6.2 nathanw intr = mesh_read_reg(sc, MESH_INTERRUPT);
1147 1.12.6.2 nathanw exception = mesh_read_reg(sc, MESH_EXCEPTION);
1148 1.12.6.2 nathanw error = mesh_read_reg(sc, MESH_ERROR);
1149 1.12.6.2 nathanw status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
1150 1.12.6.2 nathanw status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
1151 1.12.6.2 nathanw
1152 1.12.6.2 nathanw s = splbio();
1153 1.12.6.2 nathanw if (sc->sc_flags & MESH_DMA_ACTIVE) {
1154 1.12.6.2 nathanw printf("mesh: resetting dma\n");
1155 1.12.6.2 nathanw dbdma_reset(sc->sc_dmareg);
1156 1.12.6.2 nathanw }
1157 1.12.6.2 nathanw scb->xs->error = XS_TIMEOUT;
1158 1.12.6.2 nathanw
1159 1.12.6.2 nathanw mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
1160 1.12.6.2 nathanw sc->sc_nextstate = MESH_COMPLETE;
1161 1.12.6.2 nathanw
1162 1.12.6.2 nathanw splx(s);
1163 1.12.6.2 nathanw }
1164 1.12.6.2 nathanw
1165 1.12.6.2 nathanw void
1166 1.12.6.2 nathanw mesh_minphys(bp)
1167 1.12.6.2 nathanw struct buf *bp;
1168 1.12.6.2 nathanw {
1169 1.12.6.2 nathanw if (bp->b_bcount > 64*1024)
1170 1.12.6.2 nathanw bp->b_bcount = 64*1024;
1171 1.12.6.2 nathanw
1172 1.12.6.2 nathanw minphys(bp);
1173 1.12.6.2 nathanw }
1174