mesh.c revision 1.1 1 /* $NetBSD: mesh.c,v 1.1 1999/02/19 13:06:03 tsubai Exp $ */
2
3 /*-
4 * Copyright (C) 1999 Internet Research Institute, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by
18 * Internet Research Institute, Inc.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <sys/param.h>
35 #include <sys/buf.h>
36 #include <sys/device.h>
37 #include <sys/errno.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/queue.h>
41 #include <sys/systm.h>
42
43 #include <vm/vm.h>
44
45 #include <dev/scsipi/scsi_all.h>
46 #include <dev/scsipi/scsipi_all.h>
47 #include <dev/scsipi/scsiconf.h>
48 #include <dev/scsipi/scsi_message.h>
49
50 #include <dev/ofw/openfirm.h>
51
52 #include <machine/autoconf.h>
53 #include <machine/cpu.h>
54 #include <machine/pio.h>
55
56 #include <macppc/dev/dbdma.h>
57 #include <macppc/dev/meshreg.h>
58
59 #define T_SYNCMODE 0x01 /* target uses sync mode */
60 #define T_SYNCNEGO 0x02 /* sync negotiation done */
61
62 struct mesh_tinfo {
63 int flags;
64 int period;
65 int offset;
66 };
67
68 /* scb flags */
69 #define MESH_POLL 0x01
70 #define MESH_CHECK 0x02
71 #define MESH_SENSE 0x04
72 #define MESH_READ 0x80
73
74 struct mesh_scb {
75 TAILQ_ENTRY(mesh_scb) chain;
76 int flags;
77 struct scsipi_xfer *xs;
78 struct scsi_generic cmd;
79 int cmdlen;
80 int target; /* target SCSI ID */
81 int resid;
82 vaddr_t daddr;
83 vsize_t dlen;
84 int status;
85 };
86
87 /* sc_flags value */
88 #define MESH_DMA_ACTIVE 0x01
89
90 struct mesh_softc {
91 struct device sc_dev; /* us as a device */
92 struct scsipi_link sc_link;
93 struct scsipi_adapter sc_adapter;
94
95 u_char *sc_reg; /* MESH base address */
96 dbdma_regmap_t *sc_dmareg; /* DMA register address */
97 dbdma_command_t *sc_dmacmd; /* DMA command area */
98
99 int sc_flags;
100 int sc_cfflags; /* copy of config flags */
101 int sc_meshid; /* MESH version */
102 int sc_minsync; /* minimum sync period */
103 int sc_irq;
104 int sc_freq; /* SCSI bus frequency in MHz */
105 int sc_id; /* our SCSI ID */
106 struct mesh_tinfo sc_tinfo[8]; /* target information */
107
108 int sc_nextstate;
109 int sc_prevphase;
110 struct mesh_scb *sc_nexus; /* current command */
111
112 int sc_msgout;
113 int sc_imsglen;
114 int sc_omsglen;
115 u_char sc_imsg[16];
116 u_char sc_omsg[16];
117
118 TAILQ_HEAD(, mesh_scb) free_scb;
119 TAILQ_HEAD(, mesh_scb) ready_scb;
120 struct mesh_scb sc_scb[16];
121 };
122
123 /* mesh_msgout() values */
124 #define SEND_REJECT 1
125 #define SEND_IDENTIFY 2
126 #define SEND_SDTR 4
127
128 static __inline int mesh_read_reg __P((struct mesh_softc *, int));
129 static __inline void mesh_set_reg __P((struct mesh_softc *, int, int));
130
131 int mesh_match __P((struct device *, struct cfdata *, void *));
132 void mesh_attach __P((struct device *, struct device *, void *));
133 void mesh_shutdownhook __P((void *));
134 int mesh_intr __P((void *));
135 void mesh_error __P((struct mesh_softc *, struct mesh_scb *, int, int));
136 void mesh_select __P((struct mesh_softc *, struct mesh_scb *));
137 void mesh_identify __P((struct mesh_softc *, struct mesh_scb *));
138 void mesh_command __P((struct mesh_softc *, struct mesh_scb *));
139 void mesh_dma_setup __P((struct mesh_softc *, struct mesh_scb *));
140 void mesh_dataio __P((struct mesh_softc *, struct mesh_scb *));
141 void mesh_status __P((struct mesh_softc *, struct mesh_scb *));
142 void mesh_msgin __P((struct mesh_softc *, struct mesh_scb *));
143 void mesh_msgout __P((struct mesh_softc *, int));
144 void mesh_bus_reset __P((struct mesh_softc *));
145 void mesh_reset __P((struct mesh_softc *));
146 int mesh_stp __P((struct mesh_softc *, int));
147 void mesh_setsync __P((struct mesh_softc *, struct mesh_tinfo *));
148 struct mesh_scb *mesh_get_scb __P((struct mesh_softc *));
149 void mesh_free_scb __P((struct mesh_softc *, struct mesh_scb *));
150 int mesh_scsi_cmd __P((struct scsipi_xfer *));
151 void mesh_sched __P((struct mesh_softc *));
152 int mesh_poll __P((struct mesh_softc *, struct scsipi_xfer *));
153 void mesh_done __P((struct mesh_softc *, struct mesh_scb *));
154 void mesh_timeout __P((void *));
155 void mesh_sense __P((struct mesh_softc *, struct mesh_scb *));
156 void mesh_minphys __P((struct buf *));
157
158
159 #define MESH_DATAOUT 0
160 #define MESH_DATAIN MESH_STATUS0_IO
161 #define MESH_COMMAND MESH_STATUS0_CD
162 #define MESH_STATUS (MESH_STATUS0_CD | MESH_STATUS0_IO)
163 #define MESH_MSGOUT (MESH_STATUS0_MSG | MESH_STATUS0_CD)
164 #define MESH_MSGIN (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
165
166 #define MESH_SELECTING 8
167 #define MESH_IDENTIFY 9
168 #define MESH_COMPLETE 10
169 #define MESH_BUSFREE 11
170 #define MESH_UNKNOWN -1
171
172 #define MESH_PHASE_MASK (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
173
174 struct cfattach mesh_ca = {
175 sizeof(struct mesh_softc), mesh_match, mesh_attach
176 };
177
178 struct scsipi_device mesh_dev = {
179 NULL, /* Use default error handler */
180 NULL, /* have a queue, served by this */
181 NULL, /* have no async handler */
182 NULL, /* Use default 'done' routine */
183 };
184
185 int
186 mesh_match(parent, cf, aux)
187 struct device *parent;
188 struct cfdata *cf;
189 void *aux;
190 {
191 struct confargs *ca = aux;
192
193 if (strcmp(ca->ca_name, "mesh") != 0)
194 return 0;
195
196 return 1;
197 }
198
199 void
200 mesh_attach(parent, self, aux)
201 struct device *parent, *self;
202 void *aux;
203 {
204 struct mesh_softc *sc = (void *)self;
205 struct confargs *ca = aux;
206 int i;
207 u_int *reg;
208
209 reg = ca->ca_reg;
210 reg[0] += ca->ca_baseaddr;
211 reg[2] += ca->ca_baseaddr;
212 sc->sc_reg = mapiodev(reg[0], reg[1]);
213 sc->sc_irq = ca->ca_intr[0];
214 sc->sc_dmareg = mapiodev(reg[2], reg[3]);
215
216 sc->sc_cfflags = self->dv_cfdata->cf_flags;
217 sc->sc_meshid = mesh_read_reg(sc, MESH_MESH_ID) & 0x1f;
218 #if 0
219 if (sc->sc_meshid != (MESH_SIGNATURE & 0x1f) {
220 printf(": unknown MESH ID (0x%x)\n", sc->sc_meshid);
221 return;
222 }
223 #endif
224 if (OF_getprop(ca->ca_node, "clock-frequency", &sc->sc_freq, 4) != 4) {
225 printf(": cannot get clock-frequency\n");
226 return;
227 }
228 sc->sc_freq /= 1000000; /* in MHz */
229 sc->sc_minsync = 25; /* maximum sync rate = 10MB/sec */
230 sc->sc_id = 7;
231
232 TAILQ_INIT(&sc->free_scb);
233 TAILQ_INIT(&sc->ready_scb);
234 for (i = 0; i < sizeof(sc->sc_scb)/sizeof(sc->sc_scb[0]); i++)
235 TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain);
236
237 sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20);
238
239 mesh_reset(sc);
240 mesh_bus_reset(sc);
241
242 printf(" irq %d: %dMHz, SCSI ID %d\n",
243 sc->sc_irq, sc->sc_freq, sc->sc_id);
244
245 sc->sc_adapter.scsipi_cmd = mesh_scsi_cmd;
246 sc->sc_adapter.scsipi_minphys = mesh_minphys;
247
248 sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
249 sc->sc_link.adapter_softc = sc;
250 sc->sc_link.scsipi_scsi.adapter_target = sc->sc_id;
251 sc->sc_link.adapter = &sc->sc_adapter;
252 sc->sc_link.device = &mesh_dev;
253 sc->sc_link.openings = 2;
254 sc->sc_link.scsipi_scsi.max_target = 7;
255 sc->sc_link.scsipi_scsi.max_lun = 7;
256 sc->sc_link.type = BUS_SCSI;
257
258 config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
259
260 intr_establish(sc->sc_irq, IST_LEVEL, IPL_BIO, mesh_intr, sc);
261
262 /* Reset SCSI bus when halt. */
263 shutdownhook_establish(mesh_shutdownhook, sc);
264 }
265
266 #define MESH_SET_XFER(sc, count) do { \
267 mesh_set_reg(sc, MESH_XFER_COUNT0, count); \
268 mesh_set_reg(sc, MESH_XFER_COUNT1, count >> 8); \
269 } while (0)
270
271 #define MESH_GET_XFER(sc) ((mesh_read_reg(sc, MESH_XFER_COUNT1) << 8) | \
272 mesh_read_reg(sc, MESH_XFER_COUNT0))
273
274 int
275 mesh_read_reg(sc, reg)
276 struct mesh_softc *sc;
277 int reg;
278 {
279 return in8(sc->sc_reg + reg);
280 }
281
282 void
283 mesh_set_reg(sc, reg, val)
284 struct mesh_softc *sc;
285 int reg, val;
286 {
287 out8(sc->sc_reg + reg, val);
288 }
289
290 void
291 mesh_shutdownhook(arg)
292 void *arg;
293 {
294 struct mesh_softc *sc = arg;
295
296 /* Set to async mode. */
297 mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
298 }
299
300 int
301 mesh_intr(arg)
302 void *arg;
303 {
304 struct mesh_softc *sc = arg;
305 struct mesh_scb *scb;
306 u_char intr, exception, error, status0, status1;
307 int i;
308
309 intr = mesh_read_reg(sc, MESH_INTERRUPT);
310
311 #ifdef MESH_DEBUG
312 if (intr == 0) {
313 printf("mesh: stray interrupt\n");
314 return 0;
315 }
316 #endif
317
318 exception = mesh_read_reg(sc, MESH_EXCEPTION);
319 error = mesh_read_reg(sc, MESH_ERROR);
320 status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
321 status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
322
323 /* clear interrupt */
324 mesh_set_reg(sc, MESH_INTERRUPT, intr);
325
326 scb = sc->sc_nexus;
327 if (scb == NULL) {
328 #ifdef MESH_DEBUG
329 printf("mesh: NULL nexus\n");
330 #endif
331 return 1;
332 }
333
334 if (sc->sc_flags & MESH_DMA_ACTIVE) {
335 dbdma_stop(sc->sc_dmareg);
336
337 sc->sc_flags &= ~MESH_DMA_ACTIVE;
338 scb->resid = MESH_GET_XFER(sc);
339
340 if (mesh_read_reg(sc, MESH_FIFO_COUNT) != 0)
341 panic("mesh: FIFO != 0"); /* XXX */
342 }
343
344 if (intr & MESH_INTR_ERROR) {
345 mesh_error(sc, scb, error, 0);
346 return 1;
347 }
348
349 if (intr & MESH_INTR_EXCEPTION) {
350 /* selection timeout */
351 if (exception & MESH_EXC_SELTO) {
352 mesh_error(sc, scb, 0, exception);
353 return 1;
354 }
355
356 /* phase mismatch */
357 if (exception & MESH_EXC_PHASEMM) {
358 sc->sc_nextstate = status0 & MESH_PHASE_MASK;
359 #if 0
360 printf("mesh: PHASE MISMATCH cdb =");
361 printf(" %02x", scb->cmd.opcode);
362 for (i = 0; i < 5; i++) {
363 printf(" %02x", scb->cmd.bytes[i]);
364 }
365 printf("\n");
366 #endif
367 }
368 }
369
370 if (sc->sc_nextstate == MESH_UNKNOWN)
371 sc->sc_nextstate = status0 & MESH_PHASE_MASK;
372
373 switch (sc->sc_nextstate) {
374
375 case MESH_IDENTIFY:
376 mesh_identify(sc, scb);
377 break;
378 case MESH_COMMAND:
379 mesh_command(sc, scb);
380 break;
381 case MESH_DATAIN:
382 case MESH_DATAOUT:
383 mesh_dataio(sc, scb);
384 break;
385 case MESH_STATUS:
386 mesh_status(sc, scb);
387 break;
388 case MESH_MSGIN:
389 mesh_msgin(sc, scb);
390 break;
391 case MESH_COMPLETE:
392 mesh_done(sc, scb);
393 break;
394
395 default:
396 panic("mesh: unknown state (0x%x)", sc->sc_nextstate);
397 }
398
399 return 1;
400 }
401
402 void
403 mesh_error(sc, scb, error, exception)
404 struct mesh_softc *sc;
405 struct mesh_scb *scb;
406 int error, exception;
407 {
408 if (error & MESH_ERR_SCSI_RESET) {
409 printf("mesh: SCSI RESET\n");
410
411 /* Wait until the RST signal is deasserted. */
412 while (mesh_read_reg(sc, MESH_BUS_STATUS1) & MESH_STATUS1_RST);
413 mesh_reset(sc);
414 return;
415 }
416
417 if (error & MESH_ERR_PARITY_ERR0) {
418 printf("mesh: parity error\n");
419 scb->xs->error = XS_DRIVER_STUFFUP;
420 }
421
422 if (error & MESH_ERR_DISCONNECT) {
423 printf("mesh: unexpected disconnect\n");
424 if (sc->sc_nextstate != MESH_COMPLETE)
425 scb->xs->error = XS_DRIVER_STUFFUP;
426 }
427
428 if (exception & MESH_EXC_SELTO) {
429 /* XXX should reset bus here? */
430 scb->xs->error = XS_DRIVER_STUFFUP;
431 }
432
433 mesh_done(sc, scb);
434 }
435
436 void
437 mesh_select(sc, scb)
438 struct mesh_softc *sc;
439 struct mesh_scb *scb;
440 {
441 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
442
443 mesh_setsync(sc, ti);
444 MESH_SET_XFER(sc, 0);
445
446 /* arbitration */
447
448 /*
449 * MESH mistakenly asserts TARGET ID bit along with its own ID bit
450 * in arbitration phase (like selection). So we should load
451 * initiator ID to DestID register temporarily.
452 */
453 mesh_set_reg(sc, MESH_DEST_ID, sc->sc_id);
454 mesh_set_reg(sc, MESH_INTR_MASK, 0); /* disable intr. */
455 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ARBITRATE);
456
457 while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
458 mesh_set_reg(sc, MESH_INTERRUPT, 1);
459 mesh_set_reg(sc, MESH_INTR_MASK, 7);
460
461 /* selection */
462 mesh_set_reg(sc, MESH_DEST_ID, scb->target);
463 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_SELECT | MESH_SEQ_ATN);
464
465 sc->sc_prevphase = MESH_SELECTING;
466 sc->sc_nextstate = MESH_IDENTIFY;
467
468 timeout(mesh_timeout, scb, 10*hz);
469 }
470
471 void
472 mesh_identify(sc, scb)
473 struct mesh_softc *sc;
474 struct mesh_scb *scb;
475 {
476 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
477 mesh_msgout(sc, SEND_IDENTIFY);
478
479 sc->sc_nextstate = MESH_COMMAND;
480 }
481
482 void
483 mesh_command(sc, scb)
484 struct mesh_softc *sc;
485 struct mesh_scb *scb;
486 {
487 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
488 int i;
489 char *cmdp;
490
491 if ((ti->flags & T_SYNCNEGO) == 0) {
492 ti->period = sc->sc_minsync;
493 ti->offset = 15;
494 mesh_msgout(sc, SEND_SDTR);
495 sc->sc_prevphase = MESH_COMMAND;
496 sc->sc_nextstate = MESH_MSGIN;
497 return;
498 }
499
500 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
501
502 MESH_SET_XFER(sc, scb->cmdlen);
503 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_COMMAND);
504
505 cmdp = (char *)&scb->cmd;
506 for (i = 0; i < scb->cmdlen; i++)
507 mesh_set_reg(sc, MESH_FIFO, *cmdp++);
508
509 if (scb->resid == 0)
510 sc->sc_nextstate = MESH_STATUS; /* no data xfer */
511 else
512 sc->sc_nextstate = MESH_DATAIN;
513 }
514
515 void
516 mesh_dma_setup(sc, scb)
517 struct mesh_softc *sc;
518 struct mesh_scb *scb;
519 {
520 struct scsipi_xfer *xs = scb->xs;
521 int datain = scb->flags & MESH_READ;
522 dbdma_command_t *cmdp;
523 u_int cmd;
524 vaddr_t va;
525 int count, offset;
526
527 cmdp = sc->sc_dmacmd;
528 cmd = datain ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE;
529
530 count = scb->dlen;
531
532 if (count / NBPG > 32)
533 panic("mesh: transfer size >= 128k");
534
535 va = scb->daddr;
536 offset = va & PGOFSET;
537
538 /* if va is not page-aligned, setup the first page */
539 if (offset != 0) {
540 int rest = NBPG - offset; /* the rest in the page */
541
542 if (count > rest) { /* if continues to next page */
543 DBDMA_BUILD(cmdp, cmd, 0, rest, vtophys(va),
544 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER,
545 DBDMA_BRANCH_NEVER);
546 count -= rest;
547 va += rest;
548 cmdp++;
549 }
550 }
551
552 /* now va is page-aligned */
553 while (count > NBPG) {
554 DBDMA_BUILD(cmdp, cmd, 0, NBPG, vtophys(va),
555 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
556 count -= NBPG;
557 va += NBPG;
558 cmdp++;
559 }
560
561 /* the last page (count <= NBPG here) */
562 cmd = datain ? DBDMA_CMD_IN_LAST : DBDMA_CMD_OUT_LAST;
563 DBDMA_BUILD(cmdp, cmd , 0, count, vtophys(va),
564 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
565 cmdp++;
566
567 DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
568 DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
569 }
570
571 void
572 mesh_dataio(sc, scb)
573 struct mesh_softc *sc;
574 struct mesh_scb *scb;
575 {
576 mesh_dma_setup(sc, scb);
577
578 if (scb->dlen == 65536)
579 MESH_SET_XFER(sc, 0); /* TC = 0 means 64KB transfer */
580 else
581 MESH_SET_XFER(sc, scb->dlen);
582
583 if (scb->flags & MESH_READ)
584 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAIN | MESH_SEQ_DMA);
585 else
586 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAOUT | MESH_SEQ_DMA);
587 dbdma_start(sc->sc_dmareg, sc->sc_dmacmd);
588 sc->sc_flags |= MESH_DMA_ACTIVE;
589 sc->sc_nextstate = MESH_STATUS;
590 }
591
592 void
593 mesh_status(sc, scb)
594 struct mesh_softc *sc;
595 struct mesh_scb *scb;
596 {
597 if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
598 MESH_SET_XFER(sc, 1);
599 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_STATUS);
600 sc->sc_nextstate = MESH_STATUS;
601 return;
602 }
603
604 scb->status = mesh_read_reg(sc, MESH_FIFO);
605
606 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
607 MESH_SET_XFER(sc, 1);
608 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
609
610 sc->sc_nextstate = MESH_MSGIN;
611 }
612
613 #define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80)
614 #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
615 #define ISEXTMSG(m) ((m) == 1)
616
617 void
618 mesh_msgin(sc, scb)
619 struct mesh_softc *sc;
620 struct mesh_scb *scb;
621 {
622 int i;
623
624 if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) { /* XXX cheat */
625 MESH_SET_XFER(sc, 1);
626 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
627 sc->sc_imsglen = 0;
628 sc->sc_nextstate = MESH_MSGIN;
629 return;
630 }
631
632 sc->sc_imsg[sc->sc_imsglen++] = mesh_read_reg(sc, MESH_FIFO);
633
634 if (sc->sc_imsglen == 1 && IS1BYTEMSG(sc->sc_imsg[0]))
635 goto gotit;
636 if (sc->sc_imsglen == 2 && IS2BYTEMSG(sc->sc_imsg[0]))
637 goto gotit;
638 if (sc->sc_imsglen >= 3 && ISEXTMSG(sc->sc_imsg[0]) &&
639 sc->sc_imsglen == sc->sc_imsg[1] + 2)
640 goto gotit;
641
642 sc->sc_nextstate = MESH_MSGIN;
643 MESH_SET_XFER(sc, 1);
644 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
645 return;
646
647 gotit:
648 #ifdef DEBUG
649 printf("msgin:");
650 for (i = 0; i < sc->sc_imsglen; i++)
651 printf(" 0x%02x", sc->sc_imsg[i]);
652 printf("\n");
653 #endif
654
655 switch (sc->sc_imsg[0]) {
656 case MSG_CMDCOMPLETE:
657 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
658 sc->sc_nextstate = MESH_COMPLETE;
659 sc->sc_imsglen = 0;
660 return;
661
662 case MSG_MESSAGE_REJECT:
663 switch (sc->sc_msgout) {
664 case SEND_SDTR:
665 printf("SDTR rejected\n");
666 printf("using async mode\n");
667 sc->sc_tinfo[scb->target].period = 0;
668 sc->sc_tinfo[scb->target].offset = 0;
669 mesh_setsync(sc, &sc->sc_tinfo[scb->target]);
670 break;
671 }
672 break;
673
674 case MSG_NOOP:
675 break;
676
677 case MSG_EXTENDED:
678 goto extended_msg;
679
680 default:
681 scsi_print_addr(scb->xs->sc_link);
682 printf("unrecognized MESSAGE(0x%02x); sending REJECT\n",
683 sc->sc_imsg[0]);
684
685 reject:
686 mesh_msgout(sc, SEND_REJECT);
687 return;
688 }
689 goto done;
690
691 extended_msg:
692 /* process an extended message */
693 switch (sc->sc_imsg[2]) {
694 case MSG_EXT_SDTR:
695 {
696 struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
697 int period = sc->sc_imsg[3];
698 int offset = sc->sc_imsg[4];
699 int r = 250 / period;
700 int s = (100*250) / period - 100 * r;
701
702 if (period < sc->sc_minsync) {
703 ti->period = sc->sc_minsync;
704 ti->offset = 15;
705 mesh_msgout(sc, SEND_SDTR);
706 return;
707 }
708 scsi_print_addr(scb->xs->sc_link);
709 /* XXX if (offset != 0) ... */
710 printf("max sync rate %d.%02dMb/s\n", r, s);
711 ti->period = period;
712 ti->offset = offset;
713 ti->flags |= T_SYNCNEGO;
714 ti->flags |= T_SYNCMODE;
715 mesh_setsync(sc, ti);
716 goto done;
717 }
718 default:
719 printf("%s target %d: rejecting extended message 0x%x\n",
720 sc->sc_dev.dv_xname, scb->target, sc->sc_imsg[0]);
721 goto reject;
722 }
723
724 done:
725 sc->sc_imsglen = 0;
726 sc->sc_nextstate = MESH_UNKNOWN;
727
728 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); /* XXX really? */
729 }
730
731 void
732 mesh_msgout(sc, msg)
733 struct mesh_softc *sc;
734 int msg;
735 {
736 struct mesh_scb *scb = sc->sc_nexus;
737 struct mesh_tinfo *ti;
738 int lun, i;
739
740 switch (msg) {
741 case SEND_REJECT:
742 sc->sc_omsglen = 1;
743 sc->sc_omsg[0] = MSG_MESSAGE_REJECT;
744 break;
745 case SEND_IDENTIFY:
746 lun = scb->xs->sc_link->scsipi_scsi.lun;
747 sc->sc_omsglen = 1;
748 sc->sc_omsg[0] = MSG_IDENTIFY(lun, 0);
749 break;
750 case SEND_SDTR:
751 ti = &sc->sc_tinfo[scb->target];
752 sc->sc_omsglen = 5;
753 sc->sc_omsg[0] = MSG_EXTENDED;
754 sc->sc_omsg[1] = 3;
755 sc->sc_omsg[2] = MSG_EXT_SDTR;
756 sc->sc_omsg[3] = ti->period;
757 sc->sc_omsg[4] = ti->offset;
758 break;
759 }
760 sc->sc_msgout = msg;
761
762 MESH_SET_XFER(sc, sc->sc_omsglen);
763 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT | MESH_SEQ_ATN);
764
765 for (i = 0; i < sc->sc_omsglen; i++)
766 mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
767
768 sc->sc_nextstate = MESH_UNKNOWN;
769 }
770
771 void
772 mesh_bus_reset(sc)
773 struct mesh_softc *sc;
774 {
775 /* Disable interrupts. */
776 mesh_set_reg(sc, MESH_INTR_MASK, 0);
777
778 /* Assert RST line. */
779 mesh_set_reg(sc, MESH_BUS_STATUS1, MESH_STATUS1_RST);
780 delay(50);
781 mesh_set_reg(sc, MESH_BUS_STATUS1, 0);
782
783 mesh_reset(sc);
784 }
785
786 void
787 mesh_reset(sc)
788 struct mesh_softc *sc;
789 {
790 int i;
791
792 /* Reset DMA first. */
793 dbdma_reset(sc->sc_dmareg);
794
795 /* Disable interrupts. */
796 mesh_set_reg(sc, MESH_INTR_MASK, 0);
797
798 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_RESET_MESH);
799 delay(1);
800
801 /* Wait for reset done. */
802 while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
803
804 /* Clear interrupts */
805 mesh_set_reg(sc, MESH_INTERRUPT, 0x7);
806
807 /* Set SCSI ID */
808 mesh_set_reg(sc, MESH_SOURCE_ID, sc->sc_id);
809
810 /* Set to async mode by default. */
811 mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
812
813 /* Set selection timeout to 250ms. */
814 mesh_set_reg(sc, MESH_SEL_TIMEOUT, 250 * sc->sc_freq / 500);
815
816 /* Enable parity check. */
817 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ENABLE_PARITY);
818
819 /* Enable all interrupts. */
820 mesh_set_reg(sc, MESH_INTR_MASK, 0x7);
821
822 for (i = 0; i < 7; i++) {
823 struct mesh_tinfo *ti = &sc->sc_tinfo[i];
824
825 ti->flags = 0;
826 ti->period = ti->offset = 0;
827 if (sc->sc_cfflags & (1 << i)) {
828 ti->flags |= T_SYNCNEGO;
829 }
830 }
831 sc->sc_nexus = NULL;
832 }
833
834 int
835 mesh_stp(sc, v)
836 struct mesh_softc *sc;
837 int v;
838 {
839 /*
840 * stp(v) = 5 * clock_period (v == 0)
841 * = (v + 2) * 2 clock_period (v > 0)
842 */
843
844 if (v == 0)
845 return 5 * 250 / sc->sc_freq;
846 else
847 return (v + 2) * 2 * 250 / sc->sc_freq;
848 }
849
850 void
851 mesh_setsync(sc, ti)
852 struct mesh_softc *sc;
853 struct mesh_tinfo *ti;
854 {
855 int period = ti->period;
856 int offset = ti->offset;
857 int v;
858
859 if ((ti->flags & T_SYNCMODE) == 0)
860 offset = 0;
861
862 if (offset == 0) { /* async mode */
863 mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
864 return;
865 }
866
867 v = period * sc->sc_freq / 250 / 2 - 2;
868 if (v < 0)
869 v = 0;
870 if (mesh_stp(sc, v) < period)
871 v++;
872 if (v > 15)
873 v = 15;
874 mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v);
875 }
876
877 struct mesh_scb *
878 mesh_get_scb(sc)
879 struct mesh_softc *sc;
880 {
881 struct mesh_scb *scb;
882 int s;
883
884 s = splbio();
885 while ((scb = sc->free_scb.tqh_first) == NULL)
886 tsleep(&sc->free_scb, PRIBIO, "meshscb", 0);
887 TAILQ_REMOVE(&sc->free_scb, scb, chain);
888 splx(s);
889
890 return scb;
891 }
892
893 void
894 mesh_free_scb(sc, scb)
895 struct mesh_softc *sc;
896 struct mesh_scb *scb;
897 {
898 int s;
899
900 s = splbio();
901 TAILQ_INSERT_HEAD(&sc->free_scb, scb, chain);
902 if (scb->chain.tqe_next == NULL)
903 wakeup(&sc->free_scb);
904 splx(s);
905 }
906
907 int
908 mesh_scsi_cmd(xs)
909 struct scsipi_xfer *xs;
910 {
911 struct scsipi_link *sc_link = xs->sc_link;
912 struct mesh_softc *sc = sc_link->adapter_softc;
913 struct mesh_scb *scb;
914 u_int flags;
915 int s;
916
917 flags = xs->flags;
918
919 scb = mesh_get_scb(sc);
920 scb->xs = xs;
921 scb->flags = 0;
922 scb->status = 0;
923 scb->daddr = (vaddr_t)xs->data;
924 scb->dlen = xs->datalen;
925 scb->resid = xs->datalen;
926 bcopy(xs->cmd, &scb->cmd, xs->cmdlen);
927 scb->cmdlen = xs->cmdlen;
928
929 scb->target = sc_link->scsipi_scsi.target;
930 sc->sc_imsglen = 0; /* XXX ? */
931
932 if (flags & SCSI_POLL)
933 scb->flags |= MESH_POLL;
934 #if 0
935 if (flags & SCSI_DATA_OUT)
936 scb->flags &= ~MESH_READ;
937 #endif
938 if (flags & SCSI_DATA_IN)
939 scb->flags |= MESH_READ;
940
941 s = splbio();
942
943 TAILQ_INSERT_TAIL(&sc->ready_scb, scb, chain);
944
945 if (sc->sc_nexus == NULL) /* IDLE */
946 mesh_sched(sc);
947
948 splx(s);
949
950 if ((flags & SCSI_POLL) == 0)
951 return SUCCESSFULLY_QUEUED;
952
953 if (mesh_poll(sc, xs)) {
954 printf("mesh: timeout\n");
955 if (mesh_poll(sc, xs))
956 printf("mesh: timeout again\n");
957 }
958 return COMPLETE;
959 }
960
961 void
962 mesh_sched(sc)
963 struct mesh_softc *sc;
964 {
965 struct scsipi_xfer *xs;
966 struct scsipi_link *sc_link;
967 struct mesh_scb *scb;
968
969 scb = sc->ready_scb.tqh_first;
970 start:
971 if (scb == NULL)
972 return;
973
974 xs = scb->xs;
975 sc_link = xs->sc_link;
976
977 if (sc->sc_nexus == NULL) {
978 TAILQ_REMOVE(&sc->ready_scb, scb, chain);
979 sc->sc_nexus = scb;
980 mesh_select(sc, scb);
981 return;
982 }
983
984 scb = scb->chain.tqe_next;
985 goto start;
986 }
987
988 int
989 mesh_poll(sc, xs)
990 struct mesh_softc *sc;
991 struct scsipi_xfer *xs;
992 {
993 int count = xs->timeout;
994
995 while (count) {
996 if (mesh_read_reg(sc, MESH_INTERRUPT))
997 mesh_intr(sc);
998
999 if (xs->flags & ITSDONE)
1000 return 0;
1001 DELAY(1000);
1002 count--;
1003 };
1004 return 1;
1005 }
1006
1007 void
1008 mesh_done(sc, scb)
1009 struct mesh_softc *sc;
1010 struct mesh_scb *scb;
1011 {
1012 struct scsipi_xfer *xs = scb->xs;
1013
1014 #ifdef MESH_SHOWSTATE
1015 printf("mesh_done\n");
1016 #endif
1017
1018 sc->sc_nextstate = MESH_BUSFREE;
1019 sc->sc_nexus = NULL;
1020
1021 untimeout(mesh_timeout, scb);
1022
1023 if (scb->status == SCSI_BUSY) {
1024 xs->error = XS_BUSY;
1025 printf("Target busy\n");
1026 }
1027
1028 if (scb->status == SCSI_CHECK) {
1029 if (scb->flags & MESH_SENSE)
1030 panic("SCSI_CHECK && MESH_SENSE?");
1031 xs->resid = scb->resid;
1032 mesh_sense(sc, scb);
1033 return;
1034 }
1035
1036 if (xs->error == XS_NOERROR) {
1037 xs->status = scb->status;
1038 if (scb->flags & MESH_SENSE)
1039 xs->error = XS_SENSE;
1040 else
1041 xs->resid = scb->resid;
1042 }
1043
1044 xs->flags |= ITSDONE;
1045
1046 mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
1047
1048 if ((xs->flags & SCSI_POLL) == 0)
1049 mesh_sched(sc);
1050
1051 scsipi_done(xs);
1052 mesh_free_scb(sc, scb);
1053 }
1054
1055 void
1056 mesh_timeout(arg)
1057 void *arg;
1058 {
1059 struct mesh_scb *scb = arg;
1060 struct mesh_softc *sc = scb->xs->sc_link->adapter_softc;
1061 int s;
1062 int status0, status1;
1063 int intr, error, exception;
1064
1065 printf("mesh: timeout state=%x\n", sc->sc_nextstate);
1066
1067 intr = mesh_read_reg(sc, MESH_INTERRUPT);
1068 exception = mesh_read_reg(sc, MESH_EXCEPTION);
1069 error = mesh_read_reg(sc, MESH_ERROR);
1070 status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
1071 status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
1072
1073 #if 0
1074 printf("intr 0x%02x, except 0x%02x, err 0x%02x\n", intr, exception, error);
1075 printf("current phase:"); mesh_showsignal(sc, status0, status1);
1076 #endif
1077
1078 s = splbio();
1079 if (sc->sc_flags & MESH_DMA_ACTIVE) {
1080 printf("mesh: resetting dma\n");
1081 dbdma_reset(sc->sc_dmareg);
1082 }
1083 scb->xs->error = XS_TIMEOUT;
1084
1085 mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
1086 sc->sc_nextstate = MESH_COMPLETE;
1087
1088 splx(s);
1089 }
1090
1091 void
1092 mesh_sense(sc, scb)
1093 struct mesh_softc *sc;
1094 struct mesh_scb *scb;
1095 {
1096 struct scsipi_xfer *xs = scb->xs;
1097 struct scsipi_link *sc_link = xs->sc_link;
1098 struct scsipi_sense *ss = (void *)&scb->cmd;
1099
1100 bzero(ss, sizeof(*ss));
1101 ss->opcode = REQUEST_SENSE;
1102 ss->byte2 = sc_link->scsipi_scsi.lun << 5;
1103 ss->length = sizeof(struct scsipi_sense_data);
1104 scb->cmdlen = sizeof(*ss);
1105 scb->daddr = (vaddr_t)&xs->sense.scsi_sense;
1106 scb->dlen = sizeof(struct scsipi_sense_data);
1107 scb->resid = scb->dlen;
1108 bzero((void *)scb->daddr, scb->dlen);
1109
1110 scb->flags |= MESH_SENSE | MESH_READ;
1111
1112 TAILQ_INSERT_HEAD(&sc->ready_scb, scb, chain);
1113 if (sc->sc_nexus == NULL)
1114 mesh_sched(sc);
1115 }
1116
1117 void
1118 mesh_minphys(bp)
1119 struct buf *bp;
1120 {
1121 if (bp->b_bcount > 64*1024)
1122 bp->b_bcount = 64*1024;
1123
1124 minphys(bp);
1125 }
1126