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