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