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