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