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