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