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