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