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