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