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