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