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