Annotation of sys/arch/mvme88k/dev/vs.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: vs.c,v 1.64 2006/12/01 19:36:09 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2004, Miodrag Vallat.
5: * Copyright (c) 1999 Steve Murphree, Jr.
6: * Copyright (c) 1990 The Regents of the University of California.
7: * All rights reserved.
8: *
9: * This code is derived from software contributed to Berkeley by
10: * Van Jacobson of Lawrence Berkeley Laboratory.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: /*
38: * MVME328S SCSI adaptor driver
39: */
40:
41: /* This card lives in D16 space */
42: #define __BUS_SPACE_RESTRICT_D16__
43:
44: #include <sys/param.h>
45: #include <sys/systm.h>
46: #include <sys/device.h>
47: #include <sys/disklabel.h>
48: #include <sys/dkstat.h>
49: #include <sys/buf.h>
50: #include <sys/malloc.h>
51:
52: #include <uvm/uvm_extern.h>
53:
54: #include <scsi/scsi_all.h>
55: #include <scsi/scsiconf.h>
56:
57: #include <machine/autoconf.h>
58: #include <machine/cmmu.h>
59: #include <machine/cpu.h>
60:
61: #include <mvme88k/dev/vsreg.h>
62: #include <mvme88k/dev/vsvar.h>
63: #include <mvme88k/dev/vme.h>
64:
65: int vsmatch(struct device *, void *, void *);
66: void vsattach(struct device *, struct device *, void *);
67: int vs_scsicmd(struct scsi_xfer *);
68:
69: struct scsi_adapter vs_scsiswitch = {
70: vs_scsicmd,
71: minphys,
72: 0, /* no lun support */
73: 0, /* no lun support */
74: };
75:
76: struct scsi_device vs_scsidev = {
77: NULL, /* use default error handler */
78: NULL, /* do not have a start function */
79: NULL, /* have no async handler */
80: NULL, /* Use default done routine */
81: };
82:
83: struct cfattach vs_ca = {
84: sizeof(struct vs_softc), vsmatch, vsattach,
85: };
86:
87: struct cfdriver vs_cd = {
88: NULL, "vs", DV_DULL,
89: };
90:
91: int do_vspoll(struct vs_softc *, struct scsi_xfer *, int);
92: void thaw_queue(struct vs_softc *, int);
93: void thaw_all_queues(struct vs_softc *);
94: M328_SG vs_alloc_scatter_gather(void);
95: M328_SG vs_build_memory_structure(struct vs_softc *, struct scsi_xfer *,
96: bus_addr_t);
97: void vs_chksense(struct scsi_xfer *);
98: void vs_dealloc_scatter_gather(M328_SG);
99: int vs_eintr(void *);
100: bus_addr_t vs_getcqe(struct vs_softc *);
101: bus_addr_t vs_getiopb(struct vs_softc *);
102: int vs_initialize(struct vs_softc *);
103: int vs_intr(struct vs_softc *);
104: void vs_link_sg_element(sg_list_element_t *, vaddr_t, int);
105: void vs_link_sg_list(sg_list_element_t *, vaddr_t, int);
106: int vs_nintr(void *);
107: int vs_poll(struct vs_softc *, struct vs_cb *);
108: void vs_print_addr(struct vs_softc *, struct scsi_xfer *);
109: struct vs_cb *vs_find_queue(struct scsi_link *, struct vs_softc *);
110: void vs_reset(struct vs_softc *, int);
111: void vs_resync(struct vs_softc *);
112: void vs_scsidone(struct vs_softc *, struct vs_cb *);
113:
114: static __inline__ void vs_free(struct vs_cb *);
115: static __inline__ void vs_clear_return_info(struct vs_softc *);
116: static __inline__ paddr_t kvtop(vaddr_t);
117:
118: int
119: vsmatch(struct device *device, void *cf, void *args)
120: {
121: struct confargs *ca = args;
122: bus_space_tag_t iot = ca->ca_iot;
123: bus_space_handle_t ioh;
124: int rc;
125:
126: if (bus_space_map(iot, ca->ca_paddr, S_SHORTIO, 0, &ioh) != 0)
127: return 0;
128: rc = badaddr((vaddr_t)bus_space_vaddr(iot, ioh), 1);
129: bus_space_unmap(iot, ioh, S_SHORTIO);
130:
131: return rc == 0;
132: }
133:
134: void
135: vsattach(struct device *parent, struct device *self, void *args)
136: {
137: struct vs_softc *sc = (struct vs_softc *)self;
138: struct confargs *ca = args;
139: struct scsi_link *sc_link;
140: struct scsibus_attach_args saa;
141: int evec, bus;
142: int tmp;
143:
144: /* get the next available vector for the error interrupt */
145: evec = vme_findvec(ca->ca_vec);
146:
147: if (ca->ca_vec < 0 || evec < 0) {
148: printf(": no more interrupts!\n");
149: return;
150: }
151: if (ca->ca_ipl < 0)
152: ca->ca_ipl = IPL_BIO;
153:
154: printf(" vec 0x%x: ", evec);
155:
156: sc->sc_paddr = ca->ca_paddr;
157: sc->sc_iot = ca->ca_iot;
158: if (bus_space_map(sc->sc_iot, sc->sc_paddr, S_SHORTIO, 0,
159: &sc->sc_ioh) != 0) {
160: printf("can't map registers!\n");
161: return;
162: }
163:
164: sc->sc_ipl = ca->ca_ipl;
165: sc->sc_nvec = ca->ca_vec;
166: sc->sc_evec = evec;
167:
168: if (vs_initialize(sc))
169: return;
170:
171: sc->sc_ih_n.ih_fn = vs_nintr;
172: sc->sc_ih_n.ih_arg = sc;
173: sc->sc_ih_n.ih_wantframe = 0;
174: sc->sc_ih_n.ih_ipl = ca->ca_ipl;
175:
176: sc->sc_ih_e.ih_fn = vs_eintr;
177: sc->sc_ih_e.ih_arg = sc;
178: sc->sc_ih_e.ih_wantframe = 0;
179: sc->sc_ih_e.ih_ipl = ca->ca_ipl;
180:
181: vmeintr_establish(sc->sc_nvec, &sc->sc_ih_n, self->dv_xname);
182: snprintf(sc->sc_intrname_e, sizeof sc->sc_intrname_e,
183: "%s_err", self->dv_xname);
184: vmeintr_establish(sc->sc_evec, &sc->sc_ih_e, sc->sc_intrname_e);
185:
186: printf("SCSI ID");
187:
188: for (bus = 0; bus < 2; bus++) {
189: if (sc->sc_id[bus] < 0)
190: continue;
191:
192: sc_link = &sc->sc_link[bus];
193: sc_link->adapter = &vs_scsiswitch;
194: sc_link->adapter_buswidth = 8;
195: sc_link->adapter_softc = sc;
196: sc_link->adapter_target = sc->sc_id[bus];
197: sc_link->device = &vs_scsidev;
198: #if 0
199: sc_link->luns = 1;
200: #endif
201: sc_link->openings = NUM_IOPB / 8;
202: if (bus != 0)
203: sc_link->flags = SDEV_2NDBUS;
204:
205: printf("%c%d", bus == 0 ? ' ' : '/', sc->sc_id[bus]);
206: }
207:
208: printf("\n");
209:
210: /*
211: * Attach all scsi units on us, watching for boot device
212: * (see device_register).
213: */
214: tmp = bootpart;
215: if (sc->sc_paddr != bootaddr)
216: bootpart = -1; /* invalid flag to device_register */
217:
218: for (bus = 0; bus < 2; bus++) {
219: if (sc->sc_id[bus] < 0)
220: continue;
221:
222: bzero(&saa, sizeof(saa));
223: saa.saa_sc_link = &sc->sc_link[bus];
224:
225: bootbus = bus;
226: config_found(self, &saa, scsiprint);
227: }
228:
229: bootpart = tmp; /* restore old values */
230: bootbus = 0;
231: }
232:
233: void
234: vs_print_addr(struct vs_softc *sc, struct scsi_xfer *xs)
235: {
236: if (xs == NULL)
237: printf("%s: ", sc->sc_dev.dv_xname);
238: else {
239: sc_print_addr(xs->sc_link);
240:
241: /* print bus number too if appropriate */
242: if (sc->sc_id[1] >= 0)
243: printf("(bus %d) ",
244: !!(xs->sc_link->flags & SDEV_2NDBUS));
245: }
246: }
247:
248: int
249: do_vspoll(struct vs_softc *sc, struct scsi_xfer *xs, int canreset)
250: {
251: int to;
252: int crsw, bus;
253:
254: if (xs != NULL) {
255: bus = !!(xs->sc_link->flags & SDEV_2NDBUS);
256: to = xs->timeout;
257: if (to == 0)
258: to = 2000;
259: } else {
260: bus = -1;
261: to = 2000;
262: }
263:
264: while (((crsw = CRSW) & (M_CRSW_CRBV | M_CRSW_CC)) == 0) {
265: if (to-- <= 0) {
266: vs_print_addr(sc, xs);
267: printf("command timeout, crsw 0x%x\n", crsw);
268:
269: if (canreset) {
270: vs_reset(sc, bus);
271: vs_resync(sc);
272: }
273: return 1;
274: }
275: delay(1000);
276: }
277: return 0;
278: }
279:
280: int
281: vs_poll(struct vs_softc *sc, struct vs_cb *cb)
282: {
283: struct scsi_xfer *xs;
284: int s;
285: int rc;
286:
287: xs = cb->cb_xs;
288: rc = do_vspoll(sc, xs, 1);
289:
290: s = splbio();
291: if (rc != 0) {
292: xs->error = XS_SELTIMEOUT;
293: xs->status = -1;
294: xs->flags |= ITSDONE;
295: #if 0
296: scsi_done(xs);
297: #endif
298: vs_free(cb);
299: } else
300: vs_scsidone(sc, cb);
301: splx(s);
302:
303: if (CRSW & M_CRSW_ER)
304: CRB_CLR_ER;
305: CRB_CLR_DONE;
306:
307: vs_clear_return_info(sc);
308: return (COMPLETE);
309: }
310:
311: void
312: thaw_queue(struct vs_softc *sc, int target)
313: {
314: THAW(target);
315:
316: /* loop until thawed */
317: while (THAW_REG & M_THAW_TWQE)
318: ;
319: }
320:
321: void
322: thaw_all_queues(struct vs_softc *sc)
323: {
324: int i;
325:
326: for (i = 1; i < NUM_WQ; i++)
327: thaw_queue(sc, i);
328: }
329:
330: void
331: vs_scsidone(struct vs_softc *sc, struct vs_cb *cb)
332: {
333: struct scsi_xfer *xs = cb->cb_xs;
334: u_int32_t len;
335: int error;
336:
337: len = vs_read(4, sh_RET_IOPB + IOPB_LENGTH);
338: xs->resid = xs->datalen - len;
339:
340: error = vs_read(2, sh_RET_IOPB + IOPB_STATUS);
341: if ((error & 0xff) == SCSI_SELECTION_TO) {
342: xs->error = XS_SELTIMEOUT;
343: xs->status = -1;
344: } else
345: xs->status = error >> 8;
346:
347: while (xs->status == SCSI_CHECK) {
348: vs_chksense(xs);
349: }
350:
351: xs->flags |= ITSDONE;
352: thaw_queue(sc, cb->cb_q);
353:
354: scsi_done(xs);
355:
356: vs_free(cb);
357: }
358:
359: int
360: vs_scsicmd(struct scsi_xfer *xs)
361: {
362: struct scsi_link *slp = xs->sc_link;
363: struct vs_softc *sc = slp->adapter_softc;
364: int flags, option;
365: unsigned int iopb_len;
366: bus_addr_t cqep, iopb;
367: struct vs_cb *cb;
368: u_int queue;
369: int s;
370:
371: flags = xs->flags;
372: if (flags & SCSI_POLL) {
373: cb = &sc->sc_cb[0];
374: cqep = sh_MCE;
375: iopb = sh_MCE_IOPB;
376:
377: #ifdef VS_DEBUG
378: if (mce_read(2, CQE_QECR) & M_QECR_GO)
379: printf("%s: master command queue busy\n",
380: sc->sc_dev.dv_xname);
381: #endif
382: /* Wait until we can use the command queue entry. */
383: while (mce_read(2, CQE_QECR) & M_QECR_GO)
384: ;
385: #ifdef VS_DEBUG
386: if (cb->cb_xs != NULL) {
387: printf("%s: master command not idle\n",
388: sc->sc_dev.dv_xname);
389: return (TRY_AGAIN_LATER);
390: }
391: #endif
392: s = splbio();
393: } else {
394: s = splbio();
395: cb = vs_find_queue(slp, sc);
396: if (cb == NULL) {
397: splx(s);
398: #ifdef VS_DEBUG
399: printf("%s: no free queues\n", sc->sc_dev.dv_xname);
400: #endif
401: return (TRY_AGAIN_LATER);
402: }
403: cqep = vs_getcqe(sc);
404: if (cqep == 0) {
405: splx(s);
406: return (TRY_AGAIN_LATER);
407: }
408: iopb = vs_getiopb(sc);
409: }
410:
411: queue = cb->cb_q;
412:
413: vs_bzero(iopb, IOPB_LONG_SIZE);
414:
415: /*
416: * We should only provide the iopb len if the controller is not
417: * able to compute it from the SCSI command group.
418: * Note that it has no knowledge of group 2.
419: */
420: switch ((xs->cmd->opcode) >> 5) {
421: case 0:
422: case 1:
423: case 5:
424: iopb_len = 0;
425: break;
426: default:
427: iopb_len = IOPB_SHORT_SIZE + xs->cmdlen;
428: break;
429: }
430:
431: bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, iopb + IOPB_SCSI_DATA,
432: (u_int8_t *)xs->cmd, xs->cmdlen);
433:
434: vs_write(2, iopb + IOPB_CMD, IOPB_PASSTHROUGH);
435: vs_write(2, iopb + IOPB_UNIT,
436: IOPB_UNIT_VALUE(!!(slp->flags & SDEV_2NDBUS), slp->target, slp->lun));
437: vs_write(1, iopb + IOPB_NVCT, sc->sc_nvec);
438: vs_write(1, iopb + IOPB_EVCT, sc->sc_evec);
439:
440: /*
441: * Since the 88k doesn't support cache snooping, we have
442: * to flush the cache for a write and flush with inval for
443: * a read, prior to starting the IO.
444: */
445: dma_cachectl(pmap_kernel(), (vaddr_t)xs->data, xs->datalen,
446: flags & SCSI_DATA_IN ? DMA_CACHE_SYNC_INVAL : DMA_CACHE_SYNC);
447:
448: option = 0;
449: if (flags & SCSI_DATA_OUT)
450: option |= M_OPT_DIR;
451:
452: if (flags & SCSI_POLL) {
453: vs_write(2, iopb + IOPB_OPTION, option);
454: vs_write(2, iopb + IOPB_LEVEL, 0);
455: } else {
456: vs_write(2, iopb + IOPB_OPTION, option | M_OPT_IE);
457: vs_write(2, iopb + IOPB_LEVEL, sc->sc_ipl);
458: }
459: vs_write(2, iopb + IOPB_ADDR, ADDR_MOD);
460:
461: vs_write(2, cqep + CQE_IOPB_ADDR, iopb);
462: vs_write(1, cqep + CQE_IOPB_LENGTH, iopb_len);
463: vs_write(1, cqep + CQE_WORK_QUEUE, queue);
464:
465: cb->cb_xs = xs;
466: splx(s);
467:
468: if (xs->datalen != 0)
469: cb->cb_sg = vs_build_memory_structure(sc, xs, iopb);
470: else
471: cb->cb_sg = NULL;
472:
473: vs_write(4, cqep + CQE_CTAG, (u_int32_t)cb);
474:
475: if (crb_read(2, CRB_CRSW) & M_CRSW_AQ)
476: vs_write(2, cqep + CQE_QECR, M_QECR_AA | M_QECR_GO);
477: else
478: vs_write(2, cqep + CQE_QECR, M_QECR_GO);
479:
480: if (flags & SCSI_POLL) {
481: /* poll for the command to complete */
482: return vs_poll(sc, cb);
483: }
484:
485: return (SUCCESSFULLY_QUEUED);
486: }
487:
488: void
489: vs_chksense(struct scsi_xfer *xs)
490: {
491: int s;
492: struct scsi_link *slp = xs->sc_link;
493: struct vs_softc *sc = slp->adapter_softc;
494: struct scsi_sense *ss;
495:
496: /* ack and clear the error */
497: if (CRSW & M_CRSW_ER)
498: CRB_CLR_ER;
499: CRB_CLR_DONE;
500: xs->status = 0;
501:
502: /* Wait until we can use the command queue entry. */
503: while (mce_read(2, CQE_QECR) & M_QECR_GO)
504: ;
505:
506: vs_bzero(sh_MCE_IOPB, IOPB_LONG_SIZE);
507: /* This is a command, so point to it */
508: ss = (void *)(bus_space_vaddr(sc->sc_iot, sc->sc_ioh) +
509: sh_MCE_IOPB + IOPB_SCSI_DATA);
510: ss->opcode = REQUEST_SENSE;
511: ss->byte2 = slp->lun << 5;
512: ss->length = sizeof(struct scsi_sense_data);
513:
514: mce_iopb_write(2, IOPB_CMD, IOPB_PASSTHROUGH);
515: mce_iopb_write(2, IOPB_OPTION, 0);
516: mce_iopb_write(1, IOPB_NVCT, sc->sc_nvec);
517: mce_iopb_write(1, IOPB_EVCT, sc->sc_evec);
518: mce_iopb_write(2, IOPB_LEVEL, 0 /* sc->sc_ipl */);
519: mce_iopb_write(2, IOPB_ADDR, ADDR_MOD);
520: mce_iopb_write(4, IOPB_BUFF, kvtop((vaddr_t)&xs->sense));
521: mce_iopb_write(4, IOPB_LENGTH, sizeof(struct scsi_sense_data));
522: mce_iopb_write(2, IOPB_UNIT,
523: IOPB_UNIT_VALUE(!!(slp->flags & SDEV_2NDBUS), slp->target, slp->lun));
524:
525: vs_bzero(sh_MCE, CQE_SIZE);
526: mce_write(2, CQE_IOPB_ADDR, sh_MCE_IOPB);
527: mce_write(1, CQE_IOPB_LENGTH, 0);
528: mce_write(1, CQE_WORK_QUEUE, 0);
529: mce_write(2, CQE_QECR, M_QECR_GO);
530:
531: /* poll for the command to complete */
532: s = splbio();
533: do_vspoll(sc, xs, 1);
534: xs->status = vs_read(2, sh_RET_IOPB + IOPB_STATUS) >> 8;
535: splx(s);
536: }
537:
538: bus_addr_t
539: vs_getcqe(struct vs_softc *sc)
540: {
541: bus_addr_t cqep;
542: int qhdp;
543:
544: qhdp = mcsb_read(2, MCSB_QHDP);
545: cqep = sh_CQE(qhdp);
546:
547: if (vs_read(2, cqep + CQE_QECR) & M_QECR_GO) {
548: /* should never happen */
549: return 0;
550: }
551:
552: if (++qhdp == NUM_CQE)
553: qhdp = 0;
554: mcsb_write(2, MCSB_QHDP, qhdp);
555:
556: vs_bzero(cqep, CQE_SIZE);
557: return cqep;
558: }
559:
560: bus_addr_t
561: vs_getiopb(struct vs_softc *sc)
562: {
563: bus_addr_t iopb;
564: int qhdp;
565:
566: /*
567: * Since we are always invoked after vs_getcqe(), qhdp has already
568: * been incremented...
569: */
570: qhdp = mcsb_read(2, MCSB_QHDP);
571: if (--qhdp < 0)
572: qhdp = NUM_CQE - 1;
573:
574: iopb = sh_IOPB(qhdp);
575: return iopb;
576: }
577:
578: int
579: vs_initialize(struct vs_softc *sc)
580: {
581: int i, msr, dbid;
582:
583: for (i = 0; i < NUM_WQ; i++)
584: sc->sc_cb[i].cb_q = i;
585:
586: /*
587: * Reset the board, and wait for it to get ready.
588: * The reset signal is applied for 70 usec, and the board status
589: * is not tested until 100 usec after the reset signal has been
590: * cleared, per the manual (MVME328/D1) pages 4-6 and 4-9.
591: */
592:
593: mcsb_write(2, MCSB_MCR, M_MCR_RES | M_MCR_SFEN);
594: delay(70);
595: mcsb_write(2, MCSB_MCR, M_MCR_SFEN);
596:
597: delay(100);
598: i = 0;
599: for (;;) {
600: msr = mcsb_read(2, MCSB_MSR);
601: if ((msr & (M_MSR_BOK | M_MSR_CNA)) == M_MSR_BOK)
602: break;
603: if (++i > 5000) {
604: printf("board reset failed, status %x\n", msr);
605: return 1;
606: }
607: delay(1000);
608: }
609:
610: /* initialize channels id */
611: sc->sc_id[0] = csb_read(1, CSB_PID);
612: sc->sc_id[1] = -1;
613: switch (dbid = csb_read(1, CSB_DBID)) {
614: case DBID_SCSI2:
615: case DBID_SCSI:
616: #if 0
617: printf("daughter board, ");
618: #endif
619: sc->sc_id[1] = csb_read(1, CSB_SID);
620: break;
621: case DBID_PRINTER:
622: printf("printer port, ");
623: break;
624: case DBID_NONE:
625: break;
626: default:
627: printf("unknown daughterboard id %x, ", dbid);
628: break;
629: }
630:
631: CRB_CLR_DONE;
632: mcsb_write(2, MCSB_QHDP, 0);
633:
634: vs_bzero(sh_CIB, CIB_SIZE);
635: cib_write(2, CIB_NCQE, NUM_CQE);
636: cib_write(2, CIB_BURST, 0);
637: cib_write(2, CIB_NVECT, (sc->sc_ipl << 8) | sc->sc_nvec);
638: cib_write(2, CIB_EVECT, (sc->sc_ipl << 8) | sc->sc_evec);
639: cib_write(2, CIB_PID, 0x08); /* XXX default */
640: cib_write(2, CIB_SID, 0x08);
641: cib_write(2, CIB_CRBO, sh_CRB);
642: cib_write(4, CIB_SELECT, SELECTION_TIMEOUT);
643: cib_write(4, CIB_WQTIMO, 4);
644: cib_write(4, CIB_VMETIMO, 0 /* VME_BUS_TIMEOUT */);
645: cib_write(2, CIB_ERR_FLGS, M_ERRFLGS_RIN | M_ERRFLGS_RSE);
646: cib_write(2, CIB_SBRIV, (sc->sc_ipl << 8) | sc->sc_evec);
647: cib_write(1, CIB_SOF0, 0x15);
648: cib_write(1, CIB_SRATE0, 100 / 4);
649: cib_write(1, CIB_SOF1, 0);
650: cib_write(1, CIB_SRATE1, 0);
651:
652: vs_bzero(sh_MCE_IOPB, IOPB_LONG_SIZE);
653: mce_iopb_write(2, IOPB_CMD, CNTR_INIT);
654: mce_iopb_write(2, IOPB_OPTION, 0);
655: mce_iopb_write(1, IOPB_NVCT, sc->sc_nvec);
656: mce_iopb_write(1, IOPB_EVCT, sc->sc_evec);
657: mce_iopb_write(2, IOPB_LEVEL, 0 /* sc->sc_ipl */);
658: mce_iopb_write(2, IOPB_ADDR, SHIO_MOD);
659: mce_iopb_write(4, IOPB_BUFF, sh_CIB);
660: mce_iopb_write(4, IOPB_LENGTH, CIB_SIZE);
661:
662: vs_bzero(sh_MCE, CQE_SIZE);
663: mce_write(2, CQE_IOPB_ADDR, sh_MCE_IOPB);
664: mce_write(1, CQE_IOPB_LENGTH, 0);
665: mce_write(1, CQE_WORK_QUEUE, 0);
666: mce_write(2, CQE_QECR, M_QECR_GO);
667:
668: /* poll for the command to complete */
669: do_vspoll(sc, NULL, 1);
670:
671: /* initialize work queues */
672: for (i = 1; i < NUM_WQ; i++) {
673: /* Wait until we can use the command queue entry. */
674: while (mce_read(2, CQE_QECR) & M_QECR_GO)
675: ;
676:
677: vs_bzero(sh_MCE_IOPB, IOPB_LONG_SIZE);
678: mce_iopb_write(2, WQCF_CMD, CNTR_INIT_WORKQ);
679: mce_iopb_write(2, WQCF_OPTION, 0);
680: mce_iopb_write(1, WQCF_NVCT, sc->sc_nvec);
681: mce_iopb_write(1, WQCF_EVCT, sc->sc_evec);
682: mce_iopb_write(2, WQCF_ILVL, 0 /* sc->sc_ipl */);
683: mce_iopb_write(2, WQCF_WORKQ, i);
684: mce_iopb_write(2, WQCF_WOPT, M_WOPT_FE | M_WOPT_IWQ);
685: mce_iopb_write(2, WQCF_SLOTS, JAGUAR_MAX_Q_SIZ);
686: mce_iopb_write(4, WQCF_CMDTO, 4); /* 1 second */
687:
688: vs_bzero(sh_MCE, CQE_SIZE);
689: mce_write(2, CQE_IOPB_ADDR, sh_MCE_IOPB);
690: mce_write(1, CQE_IOPB_LENGTH, 0);
691: mce_write(1, CQE_WORK_QUEUE, 0);
692: mce_write(2, CQE_QECR, M_QECR_GO);
693:
694: /* poll for the command to complete */
695: do_vspoll(sc, NULL, 1);
696: if (CRSW & M_CRSW_ER) {
697: printf("work queue %d initialization error 0x%x\n",
698: i, vs_read(2, sh_RET_IOPB + IOPB_STATUS));
699: return 1;
700: }
701: CRB_CLR_DONE;
702: }
703:
704: /* start queue mode */
705: mcsb_write(2, MCSB_MCR, mcsb_read(2, MCSB_MCR) | M_MCR_SQM);
706:
707: /* reset all SCSI buses */
708: vs_reset(sc, -1);
709: /* sync all devices */
710: vs_resync(sc);
711:
712: return 0;
713: }
714:
715: void
716: vs_resync(struct vs_softc *sc)
717: {
718: int bus, target;
719:
720: for (bus = 0; bus < 2; bus++) {
721: if (sc->sc_id[bus] < 0)
722: break;
723:
724: for (target = 0; target < 8; target++) {
725: if (target == sc->sc_id[bus])
726: continue;
727:
728: /* Wait until we can use the command queue entry. */
729: while (mce_read(2, CQE_QECR) & M_QECR_GO)
730: ;
731:
732: vs_bzero(sh_MCE_IOPB, IOPB_SHORT_SIZE);
733: mce_iopb_write(2, DRCF_CMD, CNTR_DEV_REINIT);
734: mce_iopb_write(2, DRCF_OPTION, 0); /* prefer polling */
735: mce_iopb_write(1, DRCF_NVCT, sc->sc_nvec);
736: mce_iopb_write(1, DRCF_EVCT, sc->sc_evec);
737: mce_iopb_write(2, DRCF_ILVL, 0);
738: mce_iopb_write(2, DRCF_UNIT,
739: IOPB_UNIT_VALUE(bus, target, 0));
740:
741: vs_bzero(sh_MCE, CQE_SIZE);
742: mce_write(2, CQE_IOPB_ADDR, sh_MCE_IOPB);
743: mce_write(1, CQE_IOPB_LENGTH, 0);
744: mce_write(1, CQE_WORK_QUEUE, 0);
745: mce_write(2, CQE_QECR, M_QECR_GO);
746:
747: /* poll for the command to complete */
748: do_vspoll(sc, NULL, 0);
749: if (CRSW & M_CRSW_ER)
750: CRB_CLR_ER;
751: CRB_CLR_DONE;
752: }
753: }
754: }
755:
756: void
757: vs_reset(struct vs_softc *sc, int bus)
758: {
759: int b, s;
760:
761: s = splbio();
762:
763: for (b = 0; b < 2; b++) {
764: if (bus >= 0 && b != bus)
765: continue;
766:
767: /* Wait until we can use the command queue entry. */
768: while (mce_read(2, CQE_QECR) & M_QECR_GO)
769: ;
770:
771: vs_bzero(sh_MCE_IOPB, IOPB_SHORT_SIZE);
772: mce_iopb_write(2, SRCF_CMD, IOPB_RESET);
773: mce_iopb_write(2, SRCF_OPTION, 0); /* prefer polling */
774: mce_iopb_write(1, SRCF_NVCT, sc->sc_nvec);
775: mce_iopb_write(1, SRCF_EVCT, sc->sc_evec);
776: mce_iopb_write(2, SRCF_ILVL, 0);
777: mce_iopb_write(2, SRCF_BUSID, b << 15);
778:
779: vs_bzero(sh_MCE, CQE_SIZE);
780: mce_write(2, CQE_IOPB_ADDR, sh_MCE_IOPB);
781: mce_write(1, CQE_IOPB_LENGTH, 0);
782: mce_write(1, CQE_WORK_QUEUE, 0);
783: mce_write(2, CQE_QECR, M_QECR_GO);
784:
785: /* poll for the command to complete */
786: for (;;) {
787: do_vspoll(sc, NULL, 0);
788: /* ack & clear scsi error condition cause by reset */
789: if (CRSW & M_CRSW_ER) {
790: CRB_CLR_DONE;
791: vs_write(2, sh_RET_IOPB + IOPB_STATUS, 0);
792: break;
793: }
794: CRB_CLR_DONE;
795: }
796: }
797:
798: thaw_all_queues(sc);
799:
800: splx(s);
801: }
802:
803: /* free a cb; invoked at splbio */
804: static __inline__ void
805: vs_free(struct vs_cb *cb)
806: {
807: if (cb->cb_sg != NULL) {
808: vs_dealloc_scatter_gather(cb->cb_sg);
809: cb->cb_sg = NULL;
810: }
811: cb->cb_xs = NULL;
812: }
813:
814: /* normal interrupt routine */
815: int
816: vs_nintr(void *vsc)
817: {
818: struct vs_softc *sc = (struct vs_softc *)vsc;
819: struct vs_cb *cb;
820: int s;
821:
822: if ((CRSW & CONTROLLER_ERROR) == CONTROLLER_ERROR)
823: return vs_eintr(sc);
824:
825: /* Got a valid interrupt on this device */
826: s = splbio();
827: cb = (struct vs_cb *)crb_read(4, CRB_CTAG);
828:
829: /*
830: * If this is a controller error, there won't be a cb
831: * pointer in the CTAG field. Bad things happen if you try
832: * to point to address 0. But then, we should have caught
833: * the controller error above.
834: */
835: if (cb != NULL)
836: vs_scsidone(sc, cb);
837:
838: /* ack the interrupt */
839: if (CRSW & M_CRSW_ER)
840: CRB_CLR_ER;
841: CRB_CLR_DONE;
842:
843: vs_clear_return_info(sc);
844: splx(s);
845:
846: return 1;
847: }
848:
849: /* error interrupts */
850: int
851: vs_eintr(void *vsc)
852: {
853: struct vs_softc *sc = (struct vs_softc *)vsc;
854: struct vs_cb *cb;
855: struct scsi_xfer *xs;
856: int crsw, ecode;
857: int s;
858:
859: /* Got a valid interrupt on this device */
860: s = splbio();
861:
862: crsw = vs_read(2, sh_CEVSB + CEVSB_CRSW);
863: ecode = vs_read(1, sh_CEVSB + CEVSB_ERROR);
864: cb = (struct vs_cb *)crb_read(4, CRB_CTAG);
865: xs = cb != NULL ? cb->cb_xs : NULL;
866:
867: vs_print_addr(sc, xs);
868:
869: if (crsw & M_CRSW_RST) {
870: printf("bus reset\n");
871: } else {
872: switch (ecode) {
873: case CEVSB_ERR_TYPE:
874: printf("IOPB type error\n");
875: break;
876: case CEVSB_ERR_TO:
877: printf("timeout\n");
878: break;
879: case CEVSB_ERR_TR:
880: printf("reconnect error\n");
881: break;
882: case CEVSB_ERR_OF:
883: printf("overflow\n");
884: break;
885: case CEVSB_ERR_BD:
886: printf("bad direction\n");
887: break;
888: case CEVSB_ERR_NR:
889: printf("non-recoverable error\n");
890: break;
891: case CEVSB_ERR_PANIC:
892: printf("board panic\n");
893: break;
894: default:
895: printf("unexpected error %x\n", ecode);
896: break;
897: }
898: }
899:
900: if (xs != NULL) {
901: xs->error = XS_SELTIMEOUT;
902: xs->status = -1;
903: xs->flags |= ITSDONE;
904: scsi_done(xs);
905: }
906:
907: if (CRSW & M_CRSW_ER)
908: CRB_CLR_ER;
909: CRB_CLR_DONE;
910:
911: thaw_all_queues(sc);
912: vs_clear_return_info(sc);
913: splx(s);
914:
915: return 1;
916: }
917:
918: static void
919: vs_clear_return_info(struct vs_softc *sc)
920: {
921: vs_bzero(sh_RET_IOPB, CRB_SIZE + IOPB_LONG_SIZE);
922: }
923:
924: /*
925: * Choose the first available work queue (invoked at splbio).
926: * We used a simple round-robin mechanism which is faster than rescanning
927: * from the beginning if we have more than one target on the bus.
928: */
929: struct vs_cb *
930: vs_find_queue(struct scsi_link *sl, struct vs_softc *sc)
931: {
932: struct vs_cb *cb;
933: static u_int last = 0;
934: u_int q;
935:
936: q = last;
937: for (;;) {
938: if (++q == NUM_WQ)
939: q = 1;
940: if (q == last)
941: break;
942:
943: if ((cb = &sc->sc_cb[q])->cb_xs == NULL) {
944: last = q;
945: return (cb);
946: }
947: }
948:
949: return (NULL);
950: }
951:
952: /*
953: * Useful functions for scatter/gather list
954: */
955:
956: M328_SG
957: vs_alloc_scatter_gather(void)
958: {
959: M328_SG sg;
960:
961: MALLOC(sg, M328_SG, sizeof(struct m328_sg), M_DEVBUF, M_WAITOK);
962: bzero(sg, sizeof(struct m328_sg));
963:
964: return (sg);
965: }
966:
967: void
968: vs_dealloc_scatter_gather(M328_SG sg)
969: {
970: int i;
971:
972: if (sg->level > 0) {
973: for (i = 0; sg->down[i] && i < MAX_SG_ELEMENTS; i++) {
974: vs_dealloc_scatter_gather(sg->down[i]);
975: }
976: }
977: FREE(sg, M_DEVBUF);
978: }
979:
980: void
981: vs_link_sg_element(sg_list_element_t *element, vaddr_t phys_add, int len)
982: {
983: element->count.bytes = len;
984: element->addrlo = phys_add;
985: element->addrhi = phys_add >> 16;
986: element->link = 0; /* FALSE */
987: element->transfer_type = NORMAL_TYPE;
988: element->memory_type = LONG_TRANSFER;
989: element->address_modifier = ADRM_EXT_S_D;
990: }
991:
992: void
993: vs_link_sg_list(sg_list_element_t *list, vaddr_t phys_add, int elements)
994: {
995: list->count.scatter.gather = elements;
996: list->addrlo = phys_add;
997: list->addrhi = phys_add >> 16;
998: list->link = 1; /* TRUE */
999: list->transfer_type = NORMAL_TYPE;
1000: list->memory_type = LONG_TRANSFER;
1001: list->address_modifier = ADRM_EXT_S_D;
1002: }
1003:
1004: M328_SG
1005: vs_build_memory_structure(struct vs_softc *sc, struct scsi_xfer *xs,
1006: bus_addr_t iopb)
1007: {
1008: M328_SG sg;
1009: vaddr_t starting_point_virt, starting_point_phys, point_virt,
1010: point1_phys, point2_phys, virt;
1011: unsigned int len;
1012: int level;
1013:
1014: sg = NULL; /* Hopefully we need no scatter/gather list */
1015:
1016: /*
1017: * We have the following things:
1018: * virt va of the virtual memory block
1019: * len length of the virtual memory block
1020: * starting_point_virt va of the physical memory block
1021: * starting_point_phys pa of the physical memory block
1022: * point_virt va of the virtual memory
1023: * we are checking at the moment
1024: * point1_phys pa of the physical memory
1025: * we are checking at the moment
1026: * point2_phys pa of another physical memory
1027: * we are checking at the moment
1028: */
1029:
1030: level = 0;
1031: virt = starting_point_virt = (vaddr_t)xs->data;
1032: point1_phys = starting_point_phys = kvtop((vaddr_t)xs->data);
1033: len = xs->datalen;
1034:
1035: /*
1036: * Check if we need scatter/gather
1037: */
1038: if (trunc_page(virt + len - 1) != trunc_page(virt)) {
1039: for (point_virt = round_page(starting_point_virt + 1);
1040: /* if we do already scatter/gather we have to stay in the loop and jump */
1041: point_virt < virt + len || sg != NULL;
1042: point_virt += PAGE_SIZE) { /* out later */
1043:
1044: point2_phys = kvtop(point_virt);
1045:
1046: if ((point2_phys != trunc_page(point1_phys) + PAGE_SIZE) || /* physical memory is not contiguous */
1047: (point_virt - starting_point_virt >= MAX_SG_BLOCK_SIZE && sg)) { /* we only can access (1<<16)-1 bytes in scatter/gather_mode */
1048: if (point_virt - starting_point_virt >= MAX_SG_BLOCK_SIZE) { /* We were walking too far for one scatter/gather block ... */
1049: point_virt = trunc_page(starting_point_virt+MAX_SG_BLOCK_SIZE-1); /* So go back to the beginning of the last matching page */
1050: /* and generate the physical address of
1051: * this location for the next time. */
1052: point2_phys = kvtop(point_virt);
1053: }
1054:
1055: if (sg == NULL)
1056: sg = vs_alloc_scatter_gather();
1057:
1058: #if 1 /* broken firmware */
1059: if (sg->elements >= MAX_SG_ELEMENTS) {
1060: vs_dealloc_scatter_gather(sg);
1061: printf("%s: scatter/gather list too large\n",
1062: sc->sc_dev.dv_xname);
1063: return (NULL);
1064: }
1065: #else /* if the firmware will ever get fixed */
1066: while (sg->elements >= MAX_SG_ELEMENTS) {
1067: if (!sg->up) { /* If the list full in this layer ? */
1068: sg->up = vs_alloc_scatter_gather();
1069: sg->up->level = sg->level+1;
1070: sg->up->down[0] = sg;
1071: sg->up->elements = 1;
1072: }
1073: /* link this full list also in physical memory */
1074: vs_link_sg_list(&(sg->up->list[sg->up->elements-1]),
1075: kvtop((vaddr_t)sg->list),
1076: sg->elements);
1077: sg = sg->up; /* Climb up */
1078: }
1079: while (sg->level) { /* As long as we are not a the base level */
1080: int i;
1081:
1082: i = sg->elements;
1083: /* We need a new element */
1084: sg->down[i] = vs_alloc_scatter_gather();
1085: sg->down[i]->level = sg->level - 1;
1086: sg->down[i]->up = sg;
1087: sg->elements++;
1088: sg = sg->down[i]; /* Climb down */
1089: }
1090: #endif /* 1 */
1091: if (point_virt < virt + len) {
1092: /* linking element */
1093: vs_link_sg_element(&(sg->list[sg->elements]),
1094: starting_point_phys,
1095: point_virt - starting_point_virt);
1096: sg->elements++;
1097: } else {
1098: /* linking last element */
1099: vs_link_sg_element(&(sg->list[sg->elements]),
1100: starting_point_phys,
1101: virt + len - starting_point_virt);
1102: sg->elements++;
1103: break; /* We have now collected all blocks */
1104: }
1105: starting_point_virt = point_virt;
1106: starting_point_phys = point2_phys;
1107: }
1108: point1_phys = point2_phys;
1109: }
1110: }
1111:
1112: /*
1113: * Climb up along the right side of the tree until we reach the top.
1114: */
1115:
1116: if (sg != NULL) {
1117: while (sg->up) {
1118: /* link this list also in physical memory */
1119: vs_link_sg_list(&(sg->up->list[sg->up->elements-1]),
1120: kvtop((vaddr_t)sg->list),
1121: sg->elements);
1122: sg = sg->up; /* Climb up */
1123: }
1124:
1125: vs_write(2, iopb + IOPB_OPTION,
1126: vs_read(2, iopb + IOPB_OPTION) | M_OPT_SG);
1127: vs_write(2, iopb + IOPB_ADDR,
1128: vs_read(2, iopb + IOPB_ADDR) | M_ADR_SG_LINK);
1129: vs_write(4, iopb + IOPB_BUFF, kvtop((vaddr_t)sg->list));
1130: vs_write(4, iopb + IOPB_LENGTH, sg->elements);
1131: vs_write(4, iopb + IOPB_SGTTL, len);
1132: } else {
1133: /* no scatter/gather necessary */
1134: vs_write(4, iopb + IOPB_BUFF, starting_point_phys);
1135: vs_write(4, iopb + IOPB_LENGTH, len);
1136: }
1137: return sg;
1138: }
1139:
1140: static paddr_t
1141: kvtop(vaddr_t va)
1142: {
1143: paddr_t pa;
1144:
1145: pmap_extract(pmap_kernel(), va, &pa);
1146: /* XXX check for failure */
1147: return pa;
1148: }
CVSweb