mesh.c revision 1.19 1 /* $NetBSD: mesh.c,v 1.19 2003/07/15 02:43:29 lukem 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.19 2003/07/15 02:43:29 lukem 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 scsi_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 __P((struct mesh_softc *, int));
137 static __inline void mesh_set_reg __P((struct mesh_softc *, int, int));
138
139 int mesh_match __P((struct device *, struct cfdata *, void *));
140 void mesh_attach __P((struct device *, struct device *, void *));
141 void mesh_shutdownhook __P((void *));
142 int mesh_intr __P((void *));
143 void mesh_error __P((struct mesh_softc *, struct mesh_scb *, int, int));
144 void mesh_select __P((struct mesh_softc *, struct mesh_scb *));
145 void mesh_identify __P((struct mesh_softc *, struct mesh_scb *));
146 void mesh_command __P((struct mesh_softc *, struct mesh_scb *));
147 void mesh_dma_setup __P((struct mesh_softc *, struct mesh_scb *));
148 void mesh_dataio __P((struct mesh_softc *, struct mesh_scb *));
149 void mesh_status __P((struct mesh_softc *, struct mesh_scb *));
150 void mesh_msgin __P((struct mesh_softc *, struct mesh_scb *));
151 void mesh_msgout __P((struct mesh_softc *, int));
152 void mesh_bus_reset __P((struct mesh_softc *));
153 void mesh_reset __P((struct mesh_softc *));
154 int mesh_stp __P((struct mesh_softc *, int));
155 void mesh_setsync __P((struct mesh_softc *, struct mesh_tinfo *));
156 struct mesh_scb *mesh_get_scb __P((struct mesh_softc *));
157 void mesh_free_scb __P((struct mesh_softc *, struct mesh_scb *));
158 void mesh_scsi_request __P((struct scsipi_channel *,
159 scsipi_adapter_req_t, void *));
160 void mesh_sched __P((struct mesh_softc *));
161 int mesh_poll __P((struct mesh_softc *, struct scsipi_xfer *));
162 void mesh_done __P((struct mesh_softc *, struct mesh_scb *));
163 void mesh_timeout __P((void *));
164 void mesh_minphys __P((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 = self->dv_cfdata->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_LEVEL, 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 }
307
308 #ifdef MESH_DEBUG
309 static char scsi_phase[][8] = {
310 "DATAOUT",
311 "DATAIN",
312 "COMMAND",
313 "STATUS",
314 "",
315 "",
316 "MSGOUT",
317 "MSGIN"
318 };
319 #endif
320
321 int
322 mesh_intr(arg)
323 void *arg;
324 {
325 struct mesh_softc *sc = arg;
326 struct mesh_scb *scb;
327 int fifocnt;
328 u_char intr, exception, error, status0, status1;
329
330 intr = mesh_read_reg(sc, MESH_INTERRUPT);
331 if (intr == 0) {
332 DPRINTF("%s: stray interrupt\n", sc->sc_dev.dv_xname);
333 return 0;
334 }
335
336 exception = mesh_read_reg(sc, MESH_EXCEPTION);
337 error = mesh_read_reg(sc, MESH_ERROR);
338 status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
339 status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
340
341 /* clear interrupt */
342 mesh_set_reg(sc, MESH_INTERRUPT, intr);
343
344 #ifdef MESH_DEBUG
345 {
346 char buf1[64], buf2[64];
347
348 bitmask_snprintf(status0, MESH_STATUS0_BITMASK, buf1, sizeof buf1);
349 bitmask_snprintf(exception, MESH_EXC_BITMASK, buf2, sizeof buf2);
350 printf("mesh_intr status0 = 0x%s (%s), exc = 0x%s\n",
351 buf1, scsi_phase[status0 & 7], buf2);
352 }
353 #endif
354
355 scb = sc->sc_nexus;
356 if (scb == NULL) {
357 DPRINTF("%s: NULL nexus\n", sc->sc_dev.dv_xname);
358 return 1;
359 }
360
361 if (sc->sc_flags & MESH_DMA_ACTIVE) {
362 dbdma_stop(sc->sc_dmareg);
363
364 sc->sc_flags &= ~MESH_DMA_ACTIVE;
365 scb->resid = MESH_GET_XFER(sc);
366
367 fifocnt = mesh_read_reg(sc, MESH_FIFO_COUNT);
368 if (fifocnt != 0 && (scb->flags & MESH_READ)) {
369 char *cp = (char *)scb->daddr + scb->dlen - fifocnt;
370
371 DPRINTF("fifocnt = %d, resid = %d\n", fifocnt,
372 scb->resid);
373 while (fifocnt > 0) {
374 *cp++ = mesh_read_reg(sc, MESH_FIFO);
375 fifocnt--;
376 }
377 } else
378 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
379 }
380
381 if (intr & MESH_INTR_ERROR) {
382 mesh_error(sc, scb, error, 0);
383 return 1;
384 }
385
386 if (intr & MESH_INTR_EXCEPTION) {
387 /* selection timeout */
388 if (exception & MESH_EXC_SELTO) {
389 mesh_error(sc, scb, 0, exception);
390 return 1;
391 }
392
393 /* phase mismatch */
394 if (exception & MESH_EXC_PHASEMM) {
395 DPRINTF("%s: PHASE MISMATCH; nextstate = %d -> ",
396 sc->sc_dev.dv_xname, sc->sc_nextstate);
397 sc->sc_nextstate = status0 & MESH_PHASE_MASK;
398
399 DPRINTF("%d, resid = %d\n",
400 sc->sc_nextstate, scb->resid);
401 }
402 }
403
404 if (sc->sc_nextstate == MESH_UNKNOWN)
405 sc->sc_nextstate = status0 & MESH_PHASE_MASK;
406
407 switch (sc->sc_nextstate) {
408
409 case MESH_IDENTIFY:
410 mesh_identify(sc, scb);
411 break;
412 case MESH_COMMAND:
413 mesh_command(sc, scb);
414 break;
415 case MESH_DATAIN:
416 case MESH_DATAOUT:
417 mesh_dataio(sc, scb);
418 break;
419 case MESH_STATUS:
420 mesh_status(sc, scb);
421 break;
422 case MESH_MSGIN:
423 mesh_msgin(sc, scb);
424 break;
425 case MESH_COMPLETE:
426 mesh_done(sc, scb);
427 break;
428
429 default:
430 printf("%s: unknown state (%d)\n", sc->sc_dev.dv_xname,
431 sc->sc_nextstate);
432 scb->xs->error = XS_DRIVER_STUFFUP;
433 mesh_done(sc, scb);
434 }
435
436 return 1;
437 }
438
439 void
440 mesh_error(sc, scb, error, exception)
441 struct mesh_softc *sc;
442 struct mesh_scb *scb;
443 int error, exception;
444 {
445 if (error & MESH_ERR_SCSI_RESET) {
446 printf("%s: SCSI RESET\n", sc->sc_dev.dv_xname);
447
448 /* Wait until the RST signal is deasserted. */
449 while (mesh_read_reg(sc, MESH_BUS_STATUS1) & MESH_STATUS1_RST);
450 mesh_reset(sc);
451 return;
452 }
453
454 if (error & MESH_ERR_PARITY_ERR0) {
455 printf("%s: parity error\n", sc->sc_dev.dv_xname);
456 scb->xs->error = XS_DRIVER_STUFFUP;
457 }
458
459 if (error & MESH_ERR_DISCONNECT) {
460 printf("%s: unexpected disconnect\n", sc->sc_dev.dv_xname);
461 if (sc->sc_nextstate != MESH_COMPLETE)
462 scb->xs->error = XS_DRIVER_STUFFUP;
463 }
464
465 if (exception & MESH_EXC_SELTO) {
466 /* XXX should reset bus here? */
467 scb->xs->error = XS_SELTIMEOUT;
468 }
469
470 mesh_done(sc, scb);
471 }
472
473 void
474 mesh_select(sc, scb)
475 struct mesh_softc *sc;
476 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(sc, scb)
517 struct mesh_softc *sc;
518 struct mesh_scb *scb;
519 {
520 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
521
522 DPRINTF("mesh_identify\n");
523 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
524
525 if ((ti->flags & T_SYNCNEGO) == 0) {
526 ti->period = sc->sc_minsync;
527 ti->offset = 15;
528 mesh_msgout(sc, SEND_IDENTIFY | SEND_SDTR);
529 sc->sc_nextstate = MESH_MSGIN;
530 } else {
531 mesh_msgout(sc, SEND_IDENTIFY);
532 sc->sc_nextstate = MESH_COMMAND;
533 }
534 }
535
536 void
537 mesh_command(sc, scb)
538 struct mesh_softc *sc;
539 struct mesh_scb *scb;
540 {
541 int i;
542 char *cmdp;
543
544 #ifdef MESH_DEBUG
545 printf("mesh_command cdb = %02x", scb->cmd.opcode);
546 for (i = 0; i < 5; i++)
547 printf(" %02x", scb->cmd.bytes[i]);
548 printf("\n");
549 #endif
550
551 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
552
553 MESH_SET_XFER(sc, scb->cmdlen);
554 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_COMMAND);
555
556 cmdp = (char *)&scb->cmd;
557 for (i = 0; i < scb->cmdlen; i++)
558 mesh_set_reg(sc, MESH_FIFO, *cmdp++);
559
560 if (scb->resid == 0)
561 sc->sc_nextstate = MESH_STATUS; /* no data xfer */
562 else
563 sc->sc_nextstate = MESH_DATAIN;
564 }
565
566 void
567 mesh_dma_setup(sc, scb)
568 struct mesh_softc *sc;
569 struct mesh_scb *scb;
570 {
571 int datain = scb->flags & MESH_READ;
572 dbdma_command_t *cmdp;
573 u_int cmd;
574 vaddr_t va;
575 int count, offset;
576
577 cmdp = sc->sc_dmacmd;
578 cmd = datain ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE;
579
580 count = scb->dlen;
581
582 if (count / PAGE_SIZE > 32)
583 panic("mesh: transfer size >= 128k");
584
585 va = scb->daddr;
586 offset = va & PGOFSET;
587
588 /* if va is not page-aligned, setup the first page */
589 if (offset != 0) {
590 int rest = PAGE_SIZE - offset; /* the rest in the page */
591
592 if (count > rest) { /* if continues to next page */
593 DBDMA_BUILD(cmdp, cmd, 0, rest, vtophys(va),
594 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER,
595 DBDMA_BRANCH_NEVER);
596 count -= rest;
597 va += rest;
598 cmdp++;
599 }
600 }
601
602 /* now va is page-aligned */
603 while (count > PAGE_SIZE) {
604 DBDMA_BUILD(cmdp, cmd, 0, PAGE_SIZE, vtophys(va),
605 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
606 count -= PAGE_SIZE;
607 va += PAGE_SIZE;
608 cmdp++;
609 }
610
611 /* the last page (count <= PAGE_SIZE here) */
612 cmd = datain ? DBDMA_CMD_IN_LAST : DBDMA_CMD_OUT_LAST;
613 DBDMA_BUILD(cmdp, cmd , 0, count, vtophys(va),
614 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
615 cmdp++;
616
617 DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
618 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
619 }
620
621 void
622 mesh_dataio(sc, scb)
623 struct mesh_softc *sc;
624 struct mesh_scb *scb;
625 {
626 DPRINTF("mesh_dataio len = %ld (%s)\n", scb->dlen,
627 scb->flags & MESH_READ ? "read" : "write");
628
629 mesh_dma_setup(sc, scb);
630
631 if (scb->dlen == 65536)
632 MESH_SET_XFER(sc, 0); /* TC = 0 means 64KB transfer */
633 else
634 MESH_SET_XFER(sc, scb->dlen);
635
636 if (scb->flags & MESH_READ)
637 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAIN | MESH_SEQ_DMA);
638 else
639 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAOUT | MESH_SEQ_DMA);
640 dbdma_start(sc->sc_dmareg, sc->sc_dmacmd);
641 sc->sc_flags |= MESH_DMA_ACTIVE;
642 sc->sc_nextstate = MESH_STATUS;
643 }
644
645 void
646 mesh_status(sc, scb)
647 struct mesh_softc *sc;
648 struct mesh_scb *scb;
649 {
650 if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
651 DPRINTF("mesh_status(0)\n");
652 MESH_SET_XFER(sc, 1);
653 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_STATUS);
654 sc->sc_nextstate = MESH_STATUS;
655 return;
656 }
657
658 scb->status = mesh_read_reg(sc, MESH_FIFO);
659 DPRINTF("mesh_status(1): status = 0x%x\n", scb->status);
660 if (mesh_read_reg(sc, MESH_FIFO_COUNT) != 0)
661 DPRINTF("FIFO_COUNT=%d\n", mesh_read_reg(sc, MESH_FIFO_COUNT));
662
663 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
664 MESH_SET_XFER(sc, 1);
665 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
666
667 sc->sc_nextstate = MESH_MSGIN;
668 }
669
670 void
671 mesh_msgin(sc, scb)
672 struct mesh_softc *sc;
673 struct mesh_scb *scb;
674 {
675 DPRINTF("mesh_msgin\n");
676
677 if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
678 MESH_SET_XFER(sc, 1);
679 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
680 sc->sc_imsglen = 0;
681 sc->sc_nextstate = MESH_MSGIN;
682 return;
683 }
684
685 sc->sc_imsg[sc->sc_imsglen++] = mesh_read_reg(sc, MESH_FIFO);
686
687 if (sc->sc_imsglen == 1 && MSG_IS1BYTE(sc->sc_imsg[0]))
688 goto gotit;
689 if (sc->sc_imsglen == 2 && MSG_IS2BYTE(sc->sc_imsg[0]))
690 goto gotit;
691 if (sc->sc_imsglen >= 3 && MSG_ISEXTENDED(sc->sc_imsg[0]) &&
692 sc->sc_imsglen == sc->sc_imsg[1] + 2)
693 goto gotit;
694
695 sc->sc_nextstate = MESH_MSGIN;
696 MESH_SET_XFER(sc, 1);
697 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
698 return;
699
700 gotit:
701 #ifdef MESH_DEBUG
702 printf("msgin:");
703 for (i = 0; i < sc->sc_imsglen; i++)
704 printf(" 0x%02x", sc->sc_imsg[i]);
705 printf("\n");
706 #endif
707
708 switch (sc->sc_imsg[0]) {
709 case MSG_CMDCOMPLETE:
710 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
711 sc->sc_nextstate = MESH_COMPLETE;
712 sc->sc_imsglen = 0;
713 return;
714
715 case MSG_MESSAGE_REJECT:
716 if (sc->sc_msgout & SEND_SDTR) {
717 printf("SDTR rejected\n");
718 printf("using async mode\n");
719 sc->sc_tinfo[scb->target].period = 0;
720 sc->sc_tinfo[scb->target].offset = 0;
721 mesh_setsync(sc, &sc->sc_tinfo[scb->target]);
722 break;
723 }
724 break;
725
726 case MSG_NOOP:
727 break;
728
729 case MSG_EXTENDED:
730 goto extended_msg;
731
732 default:
733 scsipi_printaddr(scb->xs->xs_periph);
734 printf("unrecognized MESSAGE(0x%02x); sending REJECT\n",
735 sc->sc_imsg[0]);
736
737 reject:
738 mesh_msgout(sc, SEND_REJECT);
739 return;
740 }
741 goto done;
742
743 extended_msg:
744 /* process an extended message */
745 switch (sc->sc_imsg[2]) {
746 case MSG_EXT_SDTR:
747 {
748 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
749 int period = sc->sc_imsg[3];
750 int offset = sc->sc_imsg[4];
751 int r = 250 / period;
752 int s = (100*250) / period - 100 * r;
753
754 if (period < sc->sc_minsync) {
755 ti->period = sc->sc_minsync;
756 ti->offset = 15;
757 mesh_msgout(sc, SEND_SDTR);
758 return;
759 }
760 scsipi_printaddr(scb->xs->xs_periph);
761 /* XXX if (offset != 0) ... */
762 printf("max sync rate %d.%02dMb/s\n", r, s);
763 ti->period = period;
764 ti->offset = offset;
765 ti->flags |= T_SYNCNEGO;
766 ti->flags |= T_SYNCMODE;
767 mesh_setsync(sc, ti);
768 goto done;
769 }
770 default:
771 printf("%s target %d: rejecting extended message 0x%x\n",
772 sc->sc_dev.dv_xname, scb->target, sc->sc_imsg[0]);
773 goto reject;
774 }
775
776 done:
777 sc->sc_imsglen = 0;
778 sc->sc_nextstate = MESH_UNKNOWN;
779
780 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); /* XXX really? */
781 }
782
783 void
784 mesh_msgout(sc, msg)
785 struct mesh_softc *sc;
786 int msg;
787 {
788 struct mesh_scb *scb = sc->sc_nexus;
789 struct mesh_tinfo *ti;
790 int lun, len, i;
791
792 DPRINTF("mesh_msgout: sending");
793
794 sc->sc_msgout = msg;
795 len = 0;
796
797 if (msg & SEND_REJECT) {
798 DPRINTF(" REJECT");
799 sc->sc_omsg[len++] = MSG_MESSAGE_REJECT;
800 }
801 if (msg & SEND_IDENTIFY) {
802 DPRINTF(" IDENTIFY");
803 lun = scb->xs->xs_periph->periph_lun;
804 sc->sc_omsg[len++] = MSG_IDENTIFY(lun, 0);
805 }
806 if (msg & SEND_SDTR) {
807 DPRINTF(" SDTR");
808 ti = &sc->sc_tinfo[scb->target];
809 sc->sc_omsg[len++] = MSG_EXTENDED;
810 sc->sc_omsg[len++] = 3;
811 sc->sc_omsg[len++] = MSG_EXT_SDTR;
812 sc->sc_omsg[len++] = ti->period;
813 sc->sc_omsg[len++] = ti->offset;
814 }
815 DPRINTF("\n");
816
817 MESH_SET_XFER(sc, len);
818 if (len == 1) {
819 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT);
820 mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[0]);
821 } else {
822 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT | MESH_SEQ_ATN);
823
824 for (i = 0; i < len - 1; i++)
825 mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
826
827 /* Wait for the FIFO empty... */
828 while (mesh_read_reg(sc, MESH_FIFO_COUNT) > 0);
829
830 /* ...then write the last byte. */
831 mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
832 }
833 sc->sc_nextstate = MESH_UNKNOWN;
834 }
835
836 void
837 mesh_bus_reset(sc)
838 struct mesh_softc *sc;
839 {
840 DPRINTF("mesh_bus_reset\n");
841
842 /* Disable interrupts. */
843 mesh_set_reg(sc, MESH_INTR_MASK, 0);
844
845 /* Assert RST line. */
846 mesh_set_reg(sc, MESH_BUS_STATUS1, MESH_STATUS1_RST);
847 delay(50);
848 mesh_set_reg(sc, MESH_BUS_STATUS1, 0);
849
850 mesh_reset(sc);
851 }
852
853 void
854 mesh_reset(sc)
855 struct mesh_softc *sc;
856 {
857 int i;
858
859 DPRINTF("mesh_reset\n");
860
861 /* Reset DMA first. */
862 dbdma_reset(sc->sc_dmareg);
863
864 /* Disable interrupts. */
865 mesh_set_reg(sc, MESH_INTR_MASK, 0);
866
867 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_RESET_MESH);
868 delay(1);
869
870 /* Wait for reset done. */
871 while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
872
873 /* Clear interrupts */
874 mesh_set_reg(sc, MESH_INTERRUPT, 0x7);
875
876 /* Set SCSI ID */
877 mesh_set_reg(sc, MESH_SOURCE_ID, sc->sc_id);
878
879 /* Set to async mode by default. */
880 mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
881
882 /* Set selection timeout to 250ms. */
883 mesh_set_reg(sc, MESH_SEL_TIMEOUT, 250 * sc->sc_freq / 500);
884
885 /* Enable parity check. */
886 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ENABLE_PARITY);
887
888 /* Enable all interrupts. */
889 mesh_set_reg(sc, MESH_INTR_MASK, 0x7);
890
891 for (i = 0; i < 7; i++) {
892 struct mesh_tinfo *ti = &sc->sc_tinfo[i];
893
894 ti->flags = 0;
895 ti->period = ti->offset = 0;
896 if (sc->sc_cfflags & (0x100 << i))
897 ti->flags |= T_SYNCNEGO;
898 }
899 sc->sc_nexus = NULL;
900 }
901
902 int
903 mesh_stp(sc, v)
904 struct mesh_softc *sc;
905 int v;
906 {
907 /*
908 * stp(v) = 5 * clock_period (v == 0)
909 * = (v + 2) * 2 clock_period (v > 0)
910 */
911
912 if (v == 0)
913 return 5 * 250 / sc->sc_freq;
914 else
915 return (v + 2) * 2 * 250 / sc->sc_freq;
916 }
917
918 void
919 mesh_setsync(sc, ti)
920 struct mesh_softc *sc;
921 struct mesh_tinfo *ti;
922 {
923 int period = ti->period;
924 int offset = ti->offset;
925 int v;
926
927 if ((ti->flags & T_SYNCMODE) == 0)
928 offset = 0;
929
930 if (offset == 0) { /* async mode */
931 mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
932 return;
933 }
934
935 v = period * sc->sc_freq / 250 / 2 - 2;
936 if (v < 0)
937 v = 0;
938 if (mesh_stp(sc, v) < period)
939 v++;
940 if (v > 15)
941 v = 15;
942 mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v);
943 }
944
945 struct mesh_scb *
946 mesh_get_scb(sc)
947 struct mesh_softc *sc;
948 {
949 struct mesh_scb *scb;
950 int s;
951
952 s = splbio();
953 if ((scb = sc->free_scb.tqh_first) != NULL)
954 TAILQ_REMOVE(&sc->free_scb, scb, chain);
955 splx(s);
956
957 return scb;
958 }
959
960 void
961 mesh_free_scb(sc, scb)
962 struct mesh_softc *sc;
963 struct mesh_scb *scb;
964 {
965 int s;
966
967 s = splbio();
968 TAILQ_INSERT_HEAD(&sc->free_scb, scb, chain);
969 splx(s);
970 }
971
972 void
973 mesh_scsi_request(chan, req, arg)
974 struct scsipi_channel *chan;
975 scsipi_adapter_req_t req;
976 void *arg;
977 {
978 struct scsipi_xfer *xs;
979 struct scsipi_periph *periph;
980 struct mesh_softc *sc = (void *)chan->chan_adapter->adapt_dev;
981 struct mesh_scb *scb;
982 u_int flags;
983 int s;
984
985 switch (req) {
986 case ADAPTER_REQ_RUN_XFER:
987 xs = arg;
988 periph = xs->xs_periph;
989 flags = xs->xs_control;
990
991
992 if ((scb = mesh_get_scb(sc)) == NULL) {
993 xs->error = XS_RESOURCE_SHORTAGE;
994 scsipi_done(xs);
995 return;
996 }
997 scb->xs = xs;
998 scb->flags = 0;
999 scb->status = 0;
1000 scb->daddr = (vaddr_t)xs->data;
1001 scb->dlen = xs->datalen;
1002 scb->resid = xs->datalen;
1003 memcpy(&scb->cmd, xs->cmd, xs->cmdlen);
1004 scb->cmdlen = xs->cmdlen;
1005 scb->target = periph->periph_target;
1006 sc->sc_imsglen = 0; /* XXX ? */
1007
1008 #ifdef MESH_DEBUG
1009 {
1010 int i;
1011 printf("mesh_scsi_cmd: target = %d, cdb = %02x",
1012 scb->target, scb->cmd.opcode);
1013 for (i = 0; i < 5; i++)
1014 printf(" %02x", scb->cmd.bytes[i]);
1015 printf("\n");
1016 }
1017 #endif
1018
1019 if (flags & XS_CTL_POLL)
1020 scb->flags |= MESH_POLL;
1021 #if 0
1022 if (flags & XS_CTL_DATA_OUT)
1023 scb->flags &= ~MESH_READ;
1024 #endif
1025 if (flags & XS_CTL_DATA_IN)
1026 scb->flags |= MESH_READ;
1027
1028 s = splbio();
1029
1030 TAILQ_INSERT_TAIL(&sc->ready_scb, scb, chain);
1031
1032 if (sc->sc_nexus == NULL) /* IDLE */
1033 mesh_sched(sc);
1034
1035 splx(s);
1036
1037 if ((flags & XS_CTL_POLL) == 0)
1038 return;
1039
1040 if (mesh_poll(sc, xs)) {
1041 printf("%s: timeout\n", sc->sc_dev.dv_xname);
1042 if (mesh_poll(sc, xs))
1043 printf("%s: timeout again\n", sc->sc_dev.dv_xname);
1044 }
1045 return;
1046
1047 case ADAPTER_REQ_GROW_RESOURCES:
1048 /* XXX Not supported. */
1049 return;
1050
1051 case ADAPTER_REQ_SET_XFER_MODE:
1052 /* XXX Not supported. */
1053 return;
1054 }
1055
1056 }
1057
1058 void
1059 mesh_sched(sc)
1060 struct mesh_softc *sc;
1061 {
1062 struct scsipi_xfer *xs;
1063 struct mesh_scb *scb;
1064
1065 scb = sc->ready_scb.tqh_first;
1066 start:
1067 if (scb == NULL)
1068 return;
1069
1070 xs = scb->xs;
1071
1072 if (sc->sc_nexus == NULL) {
1073 TAILQ_REMOVE(&sc->ready_scb, scb, chain);
1074 sc->sc_nexus = scb;
1075 mesh_select(sc, scb);
1076 return;
1077 }
1078
1079 scb = scb->chain.tqe_next;
1080 goto start;
1081 }
1082
1083 int
1084 mesh_poll(sc, xs)
1085 struct mesh_softc *sc;
1086 struct scsipi_xfer *xs;
1087 {
1088 int count = xs->timeout;
1089
1090 while (count) {
1091 if (mesh_read_reg(sc, MESH_INTERRUPT))
1092 mesh_intr(sc);
1093
1094 if (xs->xs_status & XS_STS_DONE)
1095 return 0;
1096 delay(1000);
1097 count--;
1098 };
1099 return 1;
1100 }
1101
1102 void
1103 mesh_done(sc, scb)
1104 struct mesh_softc *sc;
1105 struct mesh_scb *scb;
1106 {
1107 struct scsipi_xfer *xs = scb->xs;
1108
1109 DPRINTF("mesh_done\n");
1110
1111 sc->sc_nextstate = MESH_BUSFREE;
1112 sc->sc_nexus = NULL;
1113
1114 callout_stop(&scb->xs->xs_callout);
1115
1116 if (scb->status == SCSI_BUSY) {
1117 xs->error = XS_BUSY;
1118 printf("Target busy\n");
1119 }
1120
1121 xs->xs_status = scb->status;
1122 xs->resid = scb->resid;
1123 if (scb->status == SCSI_CHECK) {
1124 xs->error = XS_BUSY;
1125 }
1126
1127 mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
1128
1129 if ((xs->xs_control & XS_CTL_POLL) == 0)
1130 mesh_sched(sc);
1131
1132 scsipi_done(xs);
1133 mesh_free_scb(sc, scb);
1134 }
1135
1136 void
1137 mesh_timeout(arg)
1138 void *arg;
1139 {
1140 struct mesh_scb *scb = arg;
1141 struct mesh_softc *sc =
1142 (void *)scb->xs->xs_periph->periph_channel->chan_adapter->adapt_dev;
1143 int s;
1144 int status0, status1;
1145 int intr, error, exception;
1146
1147 printf("%s: timeout state %d\n", sc->sc_dev.dv_xname, sc->sc_nextstate);
1148
1149 intr = mesh_read_reg(sc, MESH_INTERRUPT);
1150 exception = mesh_read_reg(sc, MESH_EXCEPTION);
1151 error = mesh_read_reg(sc, MESH_ERROR);
1152 status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
1153 status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
1154
1155 s = splbio();
1156 if (sc->sc_flags & MESH_DMA_ACTIVE) {
1157 printf("mesh: resetting DMA\n");
1158 dbdma_reset(sc->sc_dmareg);
1159 }
1160 scb->xs->error = XS_TIMEOUT;
1161
1162 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
1163 sc->sc_nextstate = MESH_COMPLETE;
1164
1165 splx(s);
1166 }
1167
1168 void
1169 mesh_minphys(bp)
1170 struct buf *bp;
1171 {
1172 if (bp->b_bcount > 64*1024)
1173 bp->b_bcount = 64*1024;
1174
1175 minphys(bp);
1176 }
1177