Annotation of sys/arch/sparc/dev/si.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: si.c,v 1.27 2007/07/01 19:05:37 miod Exp $ */
2: /* $NetBSD: si.c,v 1.38 1997/08/27 11:24:20 bouyer Exp $ */
3:
4: /*-
5: * Copyright (c) 1996 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Adam Glass, David Jones, Gordon W. Ross, and Jason R. Thorpe.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
31: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * This file contains only the machine-dependent parts of the
42: * Sun4 SCSI driver. (Autoconfig stuff and DMA functions.)
43: * The machine-independent parts are in ncr5380sbc.c
44: *
45: * Supported hardware includes:
46: * Sun "SCSI Weird" on OBIO (sw: Sun 4/100-series)
47: * Sun SCSI-3 on VME (si: Sun 4/200-series, others)
48: *
49: * The VME variant has a bit to enable or disable the DMA engine,
50: * but that bit also gates the interrupt line from the NCR5380!
51: * Therefore, in order to get any interrupt from the 5380, (i.e.
52: * for reselect) one must clear the DMA engine transfer count and
53: * then enable DMA. This has the further complication that you
54: * CAN NOT touch the NCR5380 while the DMA enable bit is set, so
55: * we have to turn DMA back off before we even look at the 5380.
56: *
57: * What wonderfully whacky hardware this is!
58: *
59: * David Jones wrote the initial version of this module for NetBSD/sun3,
60: * which included support for the VME adapter only. (no reselection).
61: *
62: * Gordon Ross added support for the Sun 3 OBIO adapter, and re-worked
63: * both the VME and OBIO code to support disconnect/reselect.
64: * (Required figuring out the hardware "features" noted above.)
65: *
66: * The autoconfiguration boilerplate came from Adam Glass.
67: *
68: * Jason R. Thorpe ported the autoconfiguration and VME portions to
69: * NetBSD/sparc, and added initial support for the 4/100 "SCSI Weird",
70: * a wacky OBIO variant of the VME SCSI-3. Many thanks to Chuck Cranor
71: * for lots of helpful tips and suggestions. Thanks also to Paul Kranenburg
72: * and Chris Torek for bits of insight needed along the way. Thanks to
73: * David Gilbert and Andrew Gillham who risked filesystem life-and-limb
74: * for the sake of testing. Andrew Gillham helped work out the bugs
75: * in the 4/100 DMA code.
76: */
77:
78: /*
79: * NOTE: support for the 4/100 "SCSI Weird" is not complete! DMA
80: * works, but interrupts (and, thus, reselection) don't. I don't know
81: * why, and I don't have a machine to test this on further.
82: *
83: * DMA, DMA completion interrupts, and reselection work fine on my
84: * 4/260 with modern SCSI-II disks attached. I've had reports of
85: * reselection failing on Sun Shoebox-type configurations where
86: * there are multiple non-SCSI devices behind Emulex or Adaptec
87: * bridges. These devices pre-date the SCSI-I spec, and might not
88: * bahve the way the 5380 code expects. For this reason, only
89: * DMA is enabled by default in this driver.
90: *
91: * Jason R. Thorpe <thorpej@NetBSD.ORG>
92: * December 8, 1995
93: */
94:
95: #include <sys/types.h>
96: #include <sys/param.h>
97: #include <sys/systm.h>
98: #include <sys/kernel.h>
99: #include <sys/malloc.h>
100: #include <sys/errno.h>
101: #include <sys/device.h>
102: #include <sys/buf.h>
103: #include <sys/proc.h>
104: #include <sys/user.h>
105:
106: #include <scsi/scsi_all.h>
107: #include <scsi/scsi_debug.h>
108: #include <scsi/scsiconf.h>
109:
110: #include <machine/autoconf.h>
111: #include <machine/cpu.h>
112: #include <machine/pmap.h>
113:
114: #include <sparc/sparc/vaddrs.h>
115: #include <sparc/sparc/cpuvar.h>
116:
117: #define COUNT_SW_LEFTOVERS XXX /* See sw DMA completion code */
118:
119: #include <dev/ic/ncr5380reg.h>
120: #include <dev/ic/ncr5380var.h>
121:
122: #include <sparc/dev/sireg.h>
123:
124: /*
125: * Transfers smaller than this are done using PIO
126: * (on assumption they're not worth DMA overhead)
127: */
128: #define MIN_DMA_LEN 128
129:
130: /*
131: * Transfers lager than 65535 bytes need to be split-up.
132: * (Some of the FIFO logic has only 16 bits counters.)
133: * Make the size an integer multiple of the page size
134: * to avoid buf/cluster remap problems. (paranoid?)
135: */
136: #define MAX_DMA_LEN 0xE000
137:
138: #ifdef DEBUG
139: int si_debug = 0;
140: static int si_link_flags = 0 /* | SDEV_DB2 */ ;
141: #endif
142:
143: /*
144: * This structure is used to keep track of mapped DMA requests.
145: */
146: struct si_dma_handle {
147: int dh_flags;
148: #define SIDH_BUSY 0x01 /* This DH is in use */
149: #define SIDH_OUT 0x02 /* DMA does data out (write) */
150: u_char * dh_addr; /* KVA of start of buffer */
151: int dh_maplen; /* Original data length */
152: long dh_dvma; /* VA of buffer in DVMA space */
153: long dh_startingpa; /* PA of buffer; for "sw" */
154: };
155:
156: /*
157: * The first structure member has to be the ncr5380_softc
158: * so we can just cast to go back and fourth between them.
159: */
160: struct si_softc {
161: struct ncr5380_softc ncr_sc;
162: volatile struct si_regs *sc_regs;
163: struct intrhand sc_ih;
164: int sc_adapter_type;
165: int sc_adapter_iv_am; /* int. vec + address modifier */
166: struct si_dma_handle *sc_dma;
167: int sc_xlen; /* length of current DMA segment. */
168: int sc_options; /* options for this instance. */
169: };
170:
171: /*
172: * Options. By default, configuration files enable DMA and disable
173: * DMA completion interrupts and reselect. You may enable additional features
174: * the `flags' directive in your kernel's configuration file.
175: *
176: * On the "sw", interrupts (and thus) reselection don't work, so they're
177: * disabled. DMA is still a little dangerous, too.
178: */
179: #define SI_ENABLE_DMA 0x01 /* Use DMA (maybe polled) */
180: #define SI_DMA_INTR 0x02 /* DMA completion interrupts */
181: #define SI_DO_RESELECT 0x04 /* Allow disconnect/reselect */
182: #define SI_OPTIONS_MASK (SI_ENABLE_DMA|SI_DMA_INTR|SI_DO_RESELECT)
183: #define SW_OPTIONS_MASK (SI_ENABLE_DMA)
184: #define SI_OPTIONS_BITS "\10\3RESELECT\2DMA_INTR\1DMA"
185:
186: /* How long to wait for DMA before declaring an error. */
187: int si_dma_intr_timo = 500; /* ticks (sec. X 100) */
188:
189: static int si_match(struct device *, void *, void *);
190: static void si_attach(struct device *, struct device *, void *);
191: static int si_intr(void *);
192: static void si_reset_adapter(struct ncr5380_softc *);
193: static void si_minphys(struct buf *);
194:
195: void si_dma_alloc(struct ncr5380_softc *);
196: void si_dma_free(struct ncr5380_softc *);
197: void si_dma_poll(struct ncr5380_softc *);
198:
199: void si_vme_dma_setup(struct ncr5380_softc *);
200: void si_vme_dma_start(struct ncr5380_softc *);
201: void si_vme_dma_stop(struct ncr5380_softc *);
202:
203: void si_vme_intr_on(struct ncr5380_softc *);
204: void si_vme_intr_off(struct ncr5380_softc *);
205:
206: void si_obio_dma_setup(struct ncr5380_softc *);
207: void si_obio_dma_start(struct ncr5380_softc *);
208: void si_obio_dma_stop(struct ncr5380_softc *);
209:
210: void si_obio_intr_on(struct ncr5380_softc *);
211: void si_obio_intr_off(struct ncr5380_softc *);
212:
213: static struct scsi_adapter si_ops = {
214: ncr5380_scsi_cmd, /* scsi_cmd() */
215: si_minphys, /* scsi_minphys() */
216: NULL, /* open_target_lu() */
217: NULL, /* close_target_lu() */
218: };
219:
220: /* This is copied from julian's bt driver */
221: /* "so we have a default dev struct for our link struct." */
222: static struct scsi_device si_dev = {
223: NULL, /* Use default error handler. */
224: NULL, /* Use default start handler. */
225: NULL, /* Use default async handler. */
226: NULL, /* Use default "done" routine. */
227: };
228:
229:
230: /* The Sun SCSI-3 VME controller. */
231: struct cfattach si_ca = {
232: sizeof(struct si_softc), si_match, si_attach
233: };
234:
235: struct cfdriver si_cd = {
236: NULL, "si", DV_DULL
237: };
238:
239: /* The Sun "SCSI Weird" 4/100 obio controller. */
240: struct cfattach sw_ca = {
241: sizeof(struct si_softc), si_match, si_attach
242: };
243:
244: struct cfdriver sw_cd = {
245: NULL, "sw", DV_DULL
246: };
247:
248: static int
249: si_match(parent, vcf, aux)
250: struct device *parent;
251: void *vcf, *aux;
252: {
253: struct cfdata *cf = vcf;
254: struct confargs *ca = aux;
255: struct romaux *ra = &ca->ca_ra;
256:
257: /* Are we looking for the right thing? */
258: if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
259: return (0);
260:
261: /* Nothing but a Sun 4 is going to have these devices. */
262: if (!CPU_ISSUN4)
263: return (0);
264:
265: /*
266: * Default interrupt priority always is 3. At least, that's
267: * what my board seems to be at. --thorpej
268: */
269: if (ra->ra_intr[0].int_pri == -1)
270: ra->ra_intr[0].int_pri = 3;
271:
272: /* Figure out the bus type and look for the appropriate adapter. */
273: switch (ca->ca_bustype) {
274: case BUS_VME16:
275: /* AFAIK, the `si' can only exist on the vmes. */
276: if (strcmp(ra->ra_name, "si") ||
277: cpuinfo.cpu_type == CPUTYP_4_100)
278: return (0);
279: break;
280:
281: case BUS_OBIO:
282: /* AFAIK, an `sw' can only exist on the obio. */
283: if (strcmp(ra->ra_name, "sw") ||
284: cpuinfo.cpu_type != CPUTYP_4_100)
285: return (0);
286: break;
287:
288: default:
289: /* Don't know what we ended up with ... */
290: return (0);
291: }
292:
293: /* Make sure there is something there... */
294: if (probeget(ra->ra_vaddr + 1, 1) == -1)
295: return (0);
296:
297: /*
298: * If this is a VME SCSI board, we have to determine whether
299: * it is an "sc" (Sun2) or "si" (Sun3) SCSI board. This can
300: * be determined using the fact that the "sc" board occupies
301: * 4K bytes in VME space but the "si" board occupies 2K bytes.
302: */
303: if (strcmp(cf->cf_driver->cd_name, "si") == 0)
304: if (probeget(ra->ra_vaddr + 0x801, 1) != -1)
305: return(0);
306:
307: return (1);
308: }
309:
310: static void
311: si_attach(parent, self, args)
312: struct device *parent, *self;
313: void *args;
314: {
315: struct si_softc *sc = (struct si_softc *) self;
316: struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc;
317: struct scsibus_attach_args saa;
318: volatile struct si_regs *regs;
319: struct confargs *ca = args;
320: struct romaux *ra = &ca->ca_ra;
321: struct bootpath *bp;
322: int i;
323:
324: /*
325: * Pull in the options flags. Allow the user to completely
326: * override the default values.
327: */
328: sc->sc_options = ncr_sc->sc_dev.dv_cfdata->cf_flags &
329: (ca->ca_bustype == BUS_OBIO ? SW_OPTIONS_MASK : SI_OPTIONS_MASK);
330:
331: /* Map the controller registers. */
332: regs = (struct si_regs *)
333: mapiodev(ra->ra_reg, 0, sizeof(struct si_regs));
334:
335: /*
336: * Fill in the prototype scsi_link.
337: */
338: ncr_sc->sc_link.adapter_softc = sc;
339: ncr_sc->sc_link.adapter_target = 7;
340: ncr_sc->sc_link.adapter = &si_ops;
341: ncr_sc->sc_link.device = &si_dev;
342: ncr_sc->sc_link.openings = 4;
343:
344: /*
345: * Initialize fields used by the MI code
346: */
347: ncr_sc->sci_r0 = ®s->sci.sci_r0;
348: ncr_sc->sci_r1 = ®s->sci.sci_r1;
349: ncr_sc->sci_r2 = ®s->sci.sci_r2;
350: ncr_sc->sci_r3 = ®s->sci.sci_r3;
351: ncr_sc->sci_r4 = ®s->sci.sci_r4;
352: ncr_sc->sci_r5 = ®s->sci.sci_r5;
353: ncr_sc->sci_r6 = ®s->sci.sci_r6;
354: ncr_sc->sci_r7 = ®s->sci.sci_r7;
355:
356: /*
357: * MD function pointers used by the MI code.
358: */
359: ncr_sc->sc_pio_out = ncr5380_pio_out;
360: ncr_sc->sc_pio_in = ncr5380_pio_in;
361: if (sc->sc_options & SI_ENABLE_DMA) {
362: ncr_sc->sc_dma_alloc = si_dma_alloc;
363: ncr_sc->sc_dma_free = si_dma_free;
364: ncr_sc->sc_dma_poll = si_dma_poll;
365: }
366:
367: switch (ca->ca_bustype) {
368: case BUS_VME16:
369: if (sc->sc_options & SI_ENABLE_DMA) {
370: ncr_sc->sc_dma_setup = si_vme_dma_setup;
371: ncr_sc->sc_dma_start = si_vme_dma_start;
372: ncr_sc->sc_dma_stop = si_vme_dma_stop;
373: if (sc->sc_options & SI_DO_RESELECT) {
374: /*
375: * Need to enable interrupts (and DMA!)
376: * on this H/W for reselect to work.
377: */
378: ncr_sc->sc_intr_on = si_vme_intr_on;
379: ncr_sc->sc_intr_off = si_vme_intr_off;
380: }
381: }
382: break;
383:
384: case BUS_OBIO:
385: if (sc->sc_options & SI_ENABLE_DMA) {
386: ncr_sc->sc_dma_setup = si_obio_dma_setup;
387: ncr_sc->sc_dma_start = si_obio_dma_start;
388: ncr_sc->sc_dma_stop = si_obio_dma_stop;
389: }
390: ncr_sc->sc_intr_on = si_obio_intr_on;
391: ncr_sc->sc_intr_off = si_obio_intr_off;
392: break;
393:
394: default:
395: panic("si_attach: impossible bus type 0x%x", ca->ca_bustype);
396: /* NOTREACHED */
397: }
398:
399: ncr_sc->sc_flags = 0;
400: if ((sc->sc_options & SI_DO_RESELECT) == 0)
401: ncr_sc->sc_flags |= NCR5380_PERMIT_RESELECT;
402: if ((sc->sc_options & (SI_ENABLE_DMA | SI_DMA_INTR)) !=
403: (SI_ENABLE_DMA | SI_DMA_INTR))
404: ncr_sc->sc_flags |= NCR5380_FORCE_POLLING;
405: ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
406:
407: /*
408: * Initialize fields used only here in the MD code.
409: */
410: sc->sc_regs = regs;
411: sc->sc_adapter_type = ca->ca_bustype;
412: /* sc_adapter_iv_am = (was set above) */
413:
414: /*
415: * Allocate DMA handles.
416: */
417: i = SCI_OPENINGS * sizeof(struct si_dma_handle);
418: sc->sc_dma = (struct si_dma_handle *)malloc(i, M_DEVBUF, M_NOWAIT);
419: if (sc->sc_dma == NULL)
420: panic("si: dma handle malloc failed");
421: for (i = 0; i < SCI_OPENINGS; i++)
422: sc->sc_dma[i].dh_flags = 0;
423:
424: sc->sc_regs = regs;
425: sc->sc_adapter_type = ca->ca_bustype;
426:
427: /* Establish the interrupt. */
428: sc->sc_ih.ih_fun = si_intr;
429: sc->sc_ih.ih_arg = sc;
430:
431: switch (ca->ca_bustype) {
432: case BUS_OBIO:
433: /*
434: * This will be an "sw" controller.
435: */
436: intr_establish(ra->ra_intr[0].int_pri, &sc->sc_ih, IPL_BIO,
437: self->dv_xname);
438: break;
439:
440: case BUS_VME16:
441: /*
442: * This will be an "si" controller.
443: */
444: vmeintr_establish(ra->ra_intr[0].int_vec,
445: ra->ra_intr[0].int_pri, &sc->sc_ih, IPL_BIO,
446: self->dv_xname);
447: sc->sc_adapter_iv_am =
448: VME_SUPV_DATA_24 | (ra->ra_intr[0].int_vec & 0xFF);
449: break;
450:
451: default:
452: /* Impossible case handled above. */
453: break;
454: }
455: printf(" pri %d\n", ra->ra_intr[0].int_pri);
456: #ifdef DEBUG
457: if (sc->sc_options) {
458: printf("%s: options=%b\n", ncr_sc->sc_dev.dv_xname,
459: sc->sc_options, SI_OPTIONS_BITS);
460: }
461: if (si_debug)
462: printf("si: Set TheSoftC=%p TheRegs=%p\n", sc, regs);
463: ncr_sc->sc_link.flags |= si_link_flags;
464: #endif
465:
466: /*
467: * Initialize si board itself.
468: */
469: si_reset_adapter(ncr_sc);
470: ncr5380_init(ncr_sc);
471: ncr5380_reset_scsibus(ncr_sc);
472: DELAY(2000000);
473:
474: /*
475: * If the boot path is "sw" or "si" at the moment and it's me, then
476: * walk out pointer to the sub-device, ready for the config
477: * below.
478: */
479: bp = ra->ra_bp;
480: if (bp != NULL && strcmp(bp->name, ra->ra_name) == 0 &&
481: bp->val[0] == -1 && bp->val[1] == ncr_sc->sc_dev.dv_unit)
482: bootpath_store(1, bp + 1);
483:
484: bzero(&saa, sizeof(saa));
485: saa.saa_sc_link = &(ncr_sc->sc_link);
486:
487: /* Configure sub-devices */
488: config_found(self, &saa, scsiprint);
489:
490: bootpath_store(1, NULL);
491: }
492:
493: static void
494: si_minphys(struct buf *bp)
495: {
496: if (bp->b_bcount > MAX_DMA_LEN) {
497: #ifdef DEBUG
498: if (si_debug) {
499: printf("si_minphys len = 0x%x.\n", MAX_DMA_LEN);
500: #ifdef DDB
501: Debugger();
502: #endif
503: }
504: #endif
505: bp->b_bcount = MAX_DMA_LEN;
506: }
507: return (minphys(bp));
508: }
509:
510: #define CSR_WANT (SI_CSR_SBC_IP | SI_CSR_DMA_IP | \
511: SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR )
512:
513: static int
514: si_intr(void *arg)
515: {
516: struct si_softc *sc = arg;
517: volatile struct si_regs *si = sc->sc_regs;
518: int dma_error, claimed;
519: u_short csr;
520:
521: claimed = 0;
522: dma_error = 0;
523:
524: /* SBC interrupt? DMA interrupt? */
525: if (sc->sc_adapter_type == BUS_OBIO)
526: csr = si->sw_csr;
527: else
528: csr = si->si_csr;
529: NCR_TRACE("si_intr: csr=0x%x\n", csr);
530:
531: if (csr & SI_CSR_DMA_CONFLICT) {
532: dma_error |= SI_CSR_DMA_CONFLICT;
533: printf("si_intr: DMA conflict\n");
534: }
535: if (csr & SI_CSR_DMA_BUS_ERR) {
536: dma_error |= SI_CSR_DMA_BUS_ERR;
537: printf("si_intr: DMA bus error\n");
538: }
539: if (dma_error) {
540: if (sc->ncr_sc.sc_state & NCR_DOINGDMA)
541: sc->ncr_sc.sc_state |= NCR_ABORTING;
542: /* Make sure we will call the main isr. */
543: csr |= SI_CSR_DMA_IP;
544: }
545:
546: if (csr & (SI_CSR_SBC_IP | SI_CSR_DMA_IP)) {
547: claimed = ncr5380_intr(&sc->ncr_sc);
548: #ifdef DEBUG
549: if (!claimed) {
550: printf("si_intr: spurious from SBC\n");
551: #ifdef DDB
552: if (si_debug & 4) {
553: Debugger(); /* XXX */
554: }
555: #endif
556: }
557: #endif
558: }
559:
560: return (claimed);
561: }
562:
563:
564: static void
565: si_reset_adapter(struct ncr5380_softc *ncr_sc)
566: {
567: struct si_softc *sc = (struct si_softc *)ncr_sc;
568: volatile struct si_regs *si = sc->sc_regs;
569:
570: #ifdef DEBUG
571: if (si_debug) {
572: printf("si_reset_adapter\n");
573: }
574: #endif
575:
576: /*
577: * The SCSI3 controller has an 8K FIFO to buffer data between the
578: * 5380 and the DMA. Make sure it starts out empty.
579: *
580: * The reset bits in the CSR are active low.
581: */
582: switch(sc->sc_adapter_type) {
583: case BUS_VME16:
584: si->si_csr = 0;
585: delay(10);
586: si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES | SI_CSR_INTR_EN;
587: delay(10);
588: si->fifo_count = 0;
589: si->dma_addrh = 0;
590: si->dma_addrl = 0;
591: si->dma_counth = 0;
592: si->dma_countl = 0;
593: si->si_iv_am = sc->sc_adapter_iv_am;
594: si->fifo_cnt_hi = 0;
595: break;
596:
597: case BUS_OBIO:
598: si->sw_csr = 0;
599: delay(10);
600: si->sw_csr = SI_CSR_SCSI_RES;
601: si->dma_addr = 0;
602: si->dma_count = 0;
603: delay(10);
604: si->sw_csr |= SI_CSR_INTR_EN;
605: break;
606: }
607:
608: SCI_CLR_INTR(ncr_sc);
609: }
610:
611:
612: /*****************************************************************
613: * Common functions for DMA
614: ****************************************************************/
615:
616: /*
617: * Allocate a DMA handle and put it in sc->sc_dma. Prepare
618: * for DMA transfer. On the Sun4, this means mapping the buffer
619: * into DVMA space.
620: */
621: void
622: si_dma_alloc(ncr_sc)
623: struct ncr5380_softc *ncr_sc;
624: {
625: struct si_softc *sc = (struct si_softc *)ncr_sc;
626: struct sci_req *sr = ncr_sc->sc_current;
627: struct scsi_xfer *xs = sr->sr_xs;
628: struct si_dma_handle *dh;
629: int i, xlen;
630: u_long addr;
631:
632: #ifdef DIAGNOSTIC
633: if (sr->sr_dma_hand != NULL)
634: panic("si_dma_alloc: already have DMA handle");
635: #endif
636:
637: #if 1 /* XXX - Temporary */
638: /* XXX - In case we think DMA is completely broken... */
639: if ((sc->sc_options & SI_ENABLE_DMA) == 0)
640: return;
641: #endif
642:
643: addr = (u_long) ncr_sc->sc_dataptr;
644: xlen = ncr_sc->sc_datalen;
645:
646: /* If the DMA start addr is misaligned then do PIO */
647: if ((addr & 1) || (xlen & 1)) {
648: #ifdef DEBUG
649: printf("si_dma_alloc: misaligned.\n");
650: #endif
651: return;
652: }
653:
654: /* Make sure our caller checked sc_min_dma_len. */
655: if (xlen < MIN_DMA_LEN)
656: panic("si_dma_alloc: xlen=0x%x", xlen);
657:
658: /* Find free DMA handle. Guaranteed to find one since we have
659: as many DMA handles as the driver has processes. */
660: for (i = 0; i < SCI_OPENINGS; i++) {
661: if ((sc->sc_dma[i].dh_flags & SIDH_BUSY) == 0)
662: goto found;
663: }
664: panic("si: no free DMA handles.");
665: found:
666:
667: dh = &sc->sc_dma[i];
668: dh->dh_flags = SIDH_BUSY;
669: dh->dh_addr = (u_char *) addr;
670: dh->dh_maplen = xlen;
671: dh->dh_dvma = 0;
672:
673: /* Copy the "write" flag for convenience. */
674: if (xs->flags & SCSI_DATA_OUT)
675: dh->dh_flags |= SIDH_OUT;
676:
677: /*
678: * Double-map the buffer into DVMA space. If we can't re-map
679: * the buffer, we print a warning and fall back to PIO mode.
680: *
681: * NOTE: it is not safe to sleep here!
682: */
683: dh->dh_dvma = (long)kdvma_mapin((caddr_t)addr, xlen, 0);
684: if (dh->dh_dvma == 0) {
685: /* Can't remap segment */
686: printf("si_dma_alloc: can't remap %p/0x%x, doing PIO\n",
687: dh->dh_addr, dh->dh_maplen);
688: dh->dh_flags = 0;
689: return;
690: }
691:
692: /* success */
693: sr->sr_dma_hand = dh;
694:
695: return;
696: }
697:
698:
699: void
700: si_dma_free(ncr_sc)
701: struct ncr5380_softc *ncr_sc;
702: {
703: struct sci_req *sr = ncr_sc->sc_current;
704: struct si_dma_handle *dh = sr->sr_dma_hand;
705:
706: #ifdef DIAGNOSTIC
707: if (dh == NULL)
708: panic("si_dma_free: no DMA handle");
709: #endif
710:
711: if (ncr_sc->sc_state & NCR_DOINGDMA)
712: panic("si_dma_free: free while in progress");
713:
714: if (dh->dh_flags & SIDH_BUSY) {
715: /* XXX - Should separate allocation and mapping. */
716:
717: /* Give back the DVMA space. */
718: dvma_mapout((vaddr_t)dh->dh_dvma, (vaddr_t)dh->dh_addr,
719: dh->dh_maplen);
720:
721: dh->dh_dvma = 0;
722: dh->dh_flags = 0;
723: }
724: sr->sr_dma_hand = NULL;
725: }
726:
727:
728: /*
729: * Poll (spin-wait) for DMA completion.
730: * Called right after xx_dma_start(), and
731: * xx_dma_stop() will be called next.
732: * Same for either VME or OBIO.
733: */
734: void
735: si_dma_poll(ncr_sc)
736: struct ncr5380_softc *ncr_sc;
737: {
738: struct si_softc *sc = (struct si_softc *)ncr_sc;
739: struct sci_req *sr = ncr_sc->sc_current;
740: volatile struct si_regs *si = sc->sc_regs;
741: int tmo, csr_mask, csr;
742:
743: /* Make sure DMA started successfully. */
744: if (ncr_sc->sc_state & NCR_ABORTING)
745: return;
746:
747: csr_mask = SI_CSR_SBC_IP | SI_CSR_DMA_IP |
748: SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR;
749:
750: tmo = 50000; /* X100 = 5 sec. */
751: for (;;) {
752: if (sc->sc_adapter_type == BUS_OBIO)
753: csr = si->sw_csr;
754: else
755: csr = si->si_csr;
756: if (csr & csr_mask)
757: break;
758: if (--tmo <= 0) {
759: printf("%s: DMA timeout (while polling)\n",
760: ncr_sc->sc_dev.dv_xname);
761: /* Indicate timeout as MI code would. */
762: sr->sr_flags |= SR_OVERDUE;
763: break;
764: }
765: delay(100);
766: }
767:
768: #ifdef DEBUG
769: if (si_debug) {
770: printf("si_dma_poll: done, csr=0x%x\n", csr);
771: }
772: #endif
773: }
774:
775:
776: /*****************************************************************
777: * VME functions for DMA
778: ****************************************************************/
779:
780:
781: /*
782: * This is called when the bus is going idle,
783: * so we want to enable the SBC interrupts.
784: * That is controlled by the DMA enable!
785: * Who would have guessed!
786: * What a NASTY trick!
787: */
788: void
789: si_vme_intr_on(ncr_sc)
790: struct ncr5380_softc *ncr_sc;
791: {
792: struct si_softc *sc = (struct si_softc *)ncr_sc;
793: volatile struct si_regs *si = sc->sc_regs;
794:
795: si_vme_dma_setup(ncr_sc);
796: si->si_csr |= SI_CSR_DMA_EN;
797: }
798:
799: /*
800: * This is called when the bus is idle and we are
801: * about to start playing with the SBC chip.
802: */
803: void
804: si_vme_intr_off(ncr_sc)
805: struct ncr5380_softc *ncr_sc;
806: {
807: struct si_softc *sc = (struct si_softc *)ncr_sc;
808: volatile struct si_regs *si = sc->sc_regs;
809:
810: si->si_csr &= ~SI_CSR_DMA_EN;
811: }
812:
813: /*
814: * This function is called during the COMMAND or MSG_IN phase
815: * that precedes a DATA_IN or DATA_OUT phase, in case we need
816: * to setup the DMA engine before the bus enters a DATA phase.
817: *
818: * XXX: The VME adapter appears to suppress SBC interrupts
819: * when the FIFO is not empty or the FIFO count is non-zero!
820: *
821: * On the VME version we just clear the DMA count and address
822: * here (to make sure it stays idle) and do the real setup
823: * later, in dma_start.
824: */
825: void
826: si_vme_dma_setup(ncr_sc)
827: struct ncr5380_softc *ncr_sc;
828: {
829: struct si_softc *sc = (struct si_softc *)ncr_sc;
830: volatile struct si_regs *si = sc->sc_regs;
831:
832: /* Reset the FIFO */
833: si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
834: si->si_csr |= SI_CSR_FIFO_RES;
835:
836: /* Set direction (assume recv here) */
837: si->si_csr &= ~SI_CSR_SEND;
838: /* Assume worst alignment */
839: si->si_csr |= SI_CSR_BPCON;
840:
841: si->dma_addrh = 0;
842: si->dma_addrl = 0;
843:
844: si->dma_counth = 0;
845: si->dma_countl = 0;
846:
847: /* Clear FIFO counter. (also hits dma_count) */
848: si->fifo_cnt_hi = 0;
849: si->fifo_count = 0;
850: }
851:
852:
853: void
854: si_vme_dma_start(ncr_sc)
855: struct ncr5380_softc *ncr_sc;
856: {
857: struct si_softc *sc = (struct si_softc *)ncr_sc;
858: struct sci_req *sr = ncr_sc->sc_current;
859: struct si_dma_handle *dh = sr->sr_dma_hand;
860: volatile struct si_regs *si = sc->sc_regs;
861: u_long data_pa;
862: int xlen;
863:
864: /*
865: * Get the DVMA mapping for this segment.
866: * XXX - Should separate allocation and mapin.
867: */
868: data_pa = (u_long)(dh->dh_dvma - DVMA_BASE);
869: if (data_pa & 1)
870: panic("si_dma_start: bad pa=0x%lx", data_pa);
871: xlen = ncr_sc->sc_datalen;
872: xlen &= ~1;
873: sc->sc_xlen = xlen; /* XXX: or less... */
874:
875: #ifdef DEBUG
876: if (si_debug & 2) {
877: printf("si_dma_start: dh=%p, pa=0x%lx, xlen=%d\n",
878: dh, data_pa, xlen);
879: }
880: #endif
881:
882: /*
883: * Set up the DMA controller.
884: * Note that (dh->dh_len < sc_datalen)
885: */
886: si->si_csr &= ~SI_CSR_FIFO_RES; /* active low */
887: si->si_csr |= SI_CSR_FIFO_RES;
888:
889: /* Set direction (send/recv) */
890: if (dh->dh_flags & SIDH_OUT) {
891: si->si_csr |= SI_CSR_SEND;
892: } else {
893: si->si_csr &= ~SI_CSR_SEND;
894: }
895:
896: if (data_pa & 2) {
897: si->si_csr |= SI_CSR_BPCON;
898: } else {
899: si->si_csr &= ~SI_CSR_BPCON;
900: }
901:
902: si->dma_addrh = (u_short)(data_pa >> 16);
903: si->dma_addrl = (u_short)(data_pa & 0xFFFF);
904:
905: si->dma_counth = (u_short)(xlen >> 16);
906: si->dma_countl = (u_short)(xlen & 0xFFFF);
907:
908: #if 1
909: /* Set it anyway, even though dma_count hits it? */
910: si->fifo_cnt_hi = (u_short)(xlen >> 16);
911: si->fifo_count = (u_short)(xlen & 0xFFFF);
912: #endif
913:
914: #ifdef DEBUG
915: if (si->fifo_count != xlen) {
916: printf("si_dma_start: Fifo_count=0x%x, xlen=0x%x\n",
917: si->fifo_count, xlen);
918: #ifdef DDB
919: Debugger();
920: #endif
921: }
922: #endif
923:
924: /*
925: * Acknowledge the phase change. (After DMA setup!)
926: * Put the SBIC into DMA mode, and start the transfer.
927: */
928: if (dh->dh_flags & SIDH_OUT) {
929: *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
930: SCI_CLR_INTR(ncr_sc);
931: *ncr_sc->sci_icmd = SCI_ICMD_DATA;
932: *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
933: *ncr_sc->sci_dma_send = 0; /* start it */
934: } else {
935: *ncr_sc->sci_tcmd = PHASE_DATA_IN;
936: SCI_CLR_INTR(ncr_sc);
937: *ncr_sc->sci_icmd = 0;
938: *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
939: *ncr_sc->sci_irecv = 0; /* start it */
940: }
941:
942: /* Let'er rip! */
943: si->si_csr |= SI_CSR_DMA_EN;
944:
945: ncr_sc->sc_state |= NCR_DOINGDMA;
946:
947: #ifdef DEBUG
948: if (si_debug & 2) {
949: printf("si_dma_start: started, flags=0x%x\n",
950: ncr_sc->sc_state);
951: }
952: #endif
953: }
954:
955:
956: void
957: si_vme_dma_stop(ncr_sc)
958: struct ncr5380_softc *ncr_sc;
959: {
960: struct si_softc *sc = (struct si_softc *)ncr_sc;
961: struct sci_req *sr = ncr_sc->sc_current;
962: struct si_dma_handle *dh = sr->sr_dma_hand;
963: volatile struct si_regs *si = sc->sc_regs;
964: int resid, ntrans;
965:
966: if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
967: #ifdef DEBUG
968: printf("si_dma_stop: dma not running\n");
969: #endif
970: return;
971: }
972: ncr_sc->sc_state &= ~NCR_DOINGDMA;
973:
974: /* First, halt the DMA engine. */
975: si->si_csr &= ~SI_CSR_DMA_EN; /* VME only */
976:
977: if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
978: printf("si: DMA error, csr=0x%x, reset\n", si->si_csr);
979: sr->sr_xs->error = XS_DRIVER_STUFFUP;
980: ncr_sc->sc_state |= NCR_ABORTING;
981: si_reset_adapter(ncr_sc);
982: }
983:
984: /* Note that timeout may have set the error flag. */
985: if (ncr_sc->sc_state & NCR_ABORTING)
986: goto out;
987:
988: /*
989: * Now try to figure out how much actually transferred
990: *
991: * The fifo_count does not reflect how many bytes were
992: * actually transferred for VME.
993: *
994: * SCSI-3 VME interface is a little funny on writes:
995: * if we have a disconnect, the dma has overshot by
996: * one byte and the resid needs to be incremented.
997: * Only happens for partial transfers.
998: * (Thanks to Matt Jacob)
999: */
1000:
1001: resid = si->fifo_count & 0xFFFF;
1002: if (dh->dh_flags & SIDH_OUT)
1003: if ((resid > 0) && (resid < sc->sc_xlen))
1004: resid++;
1005: ntrans = sc->sc_xlen - resid;
1006:
1007: #ifdef DEBUG
1008: if (si_debug & 2) {
1009: printf("si_dma_stop: resid=0x%x ntrans=0x%x\n",
1010: resid, ntrans);
1011: }
1012: #endif
1013: if (ntrans < MIN_DMA_LEN) {
1014: printf("si: fifo count: 0x%x\n", resid);
1015: ncr_sc->sc_state |= NCR_ABORTING;
1016: goto out;
1017: }
1018: if (ntrans > ncr_sc->sc_datalen)
1019: panic("si_dma_stop: excess transfer");
1020:
1021: /* Adjust data pointer */
1022: ncr_sc->sc_dataptr += ntrans;
1023: ncr_sc->sc_datalen -= ntrans;
1024:
1025: #ifdef DEBUG
1026: if (si_debug & 2) {
1027: printf("si_dma_stop: ntrans=0x%x\n", ntrans);
1028: }
1029: #endif
1030:
1031: /*
1032: * After a read, we may need to clean-up
1033: * "Left-over bytes" (yuck!)
1034: */
1035: if (((dh->dh_flags & SIDH_OUT) == 0) &&
1036: ((si->si_csr & SI_CSR_LOB) != 0))
1037: {
1038: char *cp = ncr_sc->sc_dataptr;
1039: #ifdef DEBUG
1040: printf("si: Got Left-over bytes!\n");
1041: #endif
1042: if (si->si_csr & SI_CSR_BPCON) {
1043: /* have SI_CSR_BPCON */
1044: cp[-1] = (si->si_bprl & 0xff00) >> 8;
1045: } else {
1046: switch (si->si_csr & SI_CSR_LOB) {
1047: case SI_CSR_LOB_THREE:
1048: cp[-3] = (si->si_bprh & 0xff00) >> 8;
1049: cp[-2] = (si->si_bprh & 0x00ff);
1050: cp[-1] = (si->si_bprl & 0xff00) >> 8;
1051: break;
1052: case SI_CSR_LOB_TWO:
1053: cp[-2] = (si->si_bprh & 0xff00) >> 8;
1054: cp[-1] = (si->si_bprh & 0x00ff);
1055: break;
1056: case SI_CSR_LOB_ONE:
1057: cp[-1] = (si->si_bprh & 0xff00) >> 8;
1058: break;
1059: }
1060: }
1061: }
1062:
1063: out:
1064: si->dma_addrh = 0;
1065: si->dma_addrl = 0;
1066:
1067: si->dma_counth = 0;
1068: si->dma_countl = 0;
1069:
1070: si->fifo_cnt_hi = 0;
1071: si->fifo_count = 0;
1072:
1073: /* Put SBIC back in PIO mode. */
1074: *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
1075: *ncr_sc->sci_icmd = 0;
1076: }
1077:
1078:
1079: /*****************************************************************
1080: * OBIO functions for DMA
1081: ****************************************************************/
1082:
1083:
1084: /*
1085: * This is called when the bus is going idle,
1086: * so we want to enable the SBC interrupts.
1087: * That is controlled by the DMA enable!
1088: * Who would have guessed!
1089: * What a NASTY trick!
1090: *
1091: * XXX THIS MIGHT NOT WORK RIGHT!
1092: */
1093: void
1094: si_obio_intr_on(ncr_sc)
1095: struct ncr5380_softc *ncr_sc;
1096: {
1097: struct si_softc *sc = (struct si_softc *)ncr_sc;
1098: volatile struct si_regs *si = sc->sc_regs;
1099:
1100: si_obio_dma_setup(ncr_sc);
1101: si->sw_csr |= SI_CSR_DMA_EN;
1102: }
1103:
1104: /*
1105: * This is called when the bus is idle and we are
1106: * about to start playing with the SBC chip.
1107: *
1108: * XXX THIS MIGHT NOT WORK RIGHT!
1109: */
1110: void
1111: si_obio_intr_off(ncr_sc)
1112: struct ncr5380_softc *ncr_sc;
1113: {
1114: struct si_softc *sc = (struct si_softc *)ncr_sc;
1115: volatile struct si_regs *si = sc->sc_regs;
1116:
1117: si->sw_csr &= ~SI_CSR_DMA_EN;
1118: }
1119:
1120:
1121: /*
1122: * This function is called during the COMMAND or MSG_IN phase
1123: * that precedes a DATA_IN or DATA_OUT phase, in case we need
1124: * to setup the DMA engine before the bus enters a DATA phase.
1125: *
1126: * On the OBIO version we just clear the DMA count and address
1127: * here (to make sure it stays idle) and do the real setup
1128: * later, in dma_start.
1129: */
1130: void
1131: si_obio_dma_setup(ncr_sc)
1132: struct ncr5380_softc *ncr_sc;
1133: {
1134: struct si_softc *sc = (struct si_softc *)ncr_sc;
1135: volatile struct si_regs *si = sc->sc_regs;
1136:
1137: /* No FIFO to reset on "sw". */
1138:
1139: /* Set direction (assume recv here) */
1140: si->sw_csr &= ~SI_CSR_SEND;
1141:
1142: si->dma_addr = 0;
1143: si->dma_count = 0;
1144: }
1145:
1146:
1147: void
1148: si_obio_dma_start(ncr_sc)
1149: struct ncr5380_softc *ncr_sc;
1150: {
1151: struct si_softc *sc = (struct si_softc *)ncr_sc;
1152: struct sci_req *sr = ncr_sc->sc_current;
1153: struct si_dma_handle *dh = sr->sr_dma_hand;
1154: volatile struct si_regs *si = sc->sc_regs;
1155: u_long data_pa;
1156: int xlen, adj, adjlen;
1157:
1158: /*
1159: * Get the DVMA mapping for this segment.
1160: * XXX - Should separate allocation and mapin.
1161: */
1162: data_pa = (u_long)(dh->dh_dvma - DVMA_BASE);
1163: if (data_pa & 1)
1164: panic("si_dma_start: bad pa=0x%lx", data_pa);
1165: xlen = ncr_sc->sc_datalen;
1166: xlen &= ~1;
1167: sc->sc_xlen = xlen; /* XXX: or less... */
1168:
1169: #ifdef DEBUG
1170: if (si_debug & 2) {
1171: printf("si_dma_start: dh=%p, pa=0x%lx, xlen=%d\n",
1172: dh, data_pa, xlen);
1173: }
1174: #endif
1175:
1176: /*
1177: * Set up the DMA controller.
1178: * Note that (dh->dh_len < sc_datalen)
1179: */
1180:
1181: /* Set direction (send/recv) */
1182: if (dh->dh_flags & SIDH_OUT) {
1183: si->sw_csr |= SI_CSR_SEND;
1184: } else {
1185: si->sw_csr &= ~SI_CSR_SEND;
1186: }
1187:
1188: /*
1189: * The "sw" needs longword aligned transfers. We
1190: * detect a shortword aligned transfer here, and adjust the
1191: * DMA transfer by 2 bytes. These two bytes are read/written
1192: * in PIO mode just before the DMA is started.
1193: */
1194: adj = 0;
1195: if (data_pa & 2) {
1196: adj = 2;
1197: #ifdef DEBUG
1198: if (si_debug & 2)
1199: printf("si_dma_start: adjusted up %d bytes\n", adj);
1200: #endif
1201: }
1202:
1203: /* We have to frob the address on the "sw". */
1204: dh->dh_startingpa = (data_pa | 0xF00000);
1205: si->dma_addr = (int)(dh->dh_startingpa + adj);
1206: si->dma_count = (xlen - adj);
1207:
1208: /*
1209: * Acknowledge the phase change. (After DMA setup!)
1210: * Put the SBIC into DMA mode, and start the transfer.
1211: */
1212: if (dh->dh_flags & SIDH_OUT) {
1213: *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
1214: if (adj) {
1215: adjlen = ncr5380_pio_out(ncr_sc, PHASE_DATA_OUT,
1216: adj, dh->dh_addr);
1217: if (adjlen != adj)
1218: printf("%s: bad outgoing adj, %d != %d\n",
1219: ncr_sc->sc_dev.dv_xname, adjlen, adj);
1220: }
1221: SCI_CLR_INTR(ncr_sc);
1222: *ncr_sc->sci_icmd = SCI_ICMD_DATA;
1223: *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
1224: *ncr_sc->sci_dma_send = 0; /* start it */
1225: } else {
1226: *ncr_sc->sci_tcmd = PHASE_DATA_IN;
1227: if (adj) {
1228: adjlen = ncr5380_pio_in(ncr_sc, PHASE_DATA_IN,
1229: adj, dh->dh_addr);
1230: if (adjlen != adj)
1231: printf("%s: bad incoming adj, %d != %d\n",
1232: ncr_sc->sc_dev.dv_xname, adjlen, adj);
1233: }
1234: SCI_CLR_INTR(ncr_sc);
1235: *ncr_sc->sci_icmd = 0;
1236: *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
1237: *ncr_sc->sci_irecv = 0; /* start it */
1238: }
1239:
1240: /* Let'er rip! */
1241: si->sw_csr |= SI_CSR_DMA_EN;
1242:
1243: ncr_sc->sc_state |= NCR_DOINGDMA;
1244:
1245: #ifdef DEBUG
1246: if (si_debug & 2) {
1247: printf("si_dma_start: started, flags=0x%x\n",
1248: ncr_sc->sc_state);
1249: }
1250: #endif
1251: }
1252:
1253:
1254: #if (defined(DEBUG) || defined(DIAGNOSTIC)) && !defined(COUNT_SW_LEFTOVERS)
1255: #define COUNT_SW_LEFTOVERS
1256: #endif
1257: #ifdef COUNT_SW_LEFTOVERS
1258: /*
1259: * Let's find out how often these occur. Read these with DDB from time
1260: * to time.
1261: */
1262: int sw_3_leftover = 0;
1263: int sw_2_leftover = 0;
1264: int sw_1_leftover = 0;
1265: int sw_0_leftover = 0;
1266: #endif
1267:
1268: void
1269: si_obio_dma_stop(ncr_sc)
1270: struct ncr5380_softc *ncr_sc;
1271: {
1272: struct si_softc *sc = (struct si_softc *)ncr_sc;
1273: struct sci_req *sr = ncr_sc->sc_current;
1274: struct si_dma_handle *dh = sr->sr_dma_hand;
1275: volatile struct si_regs *si = sc->sc_regs;
1276: int ntrans = 0, Dma_addr;
1277:
1278: if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
1279: #ifdef DEBUG
1280: printf("si_dma_stop: dma not running\n");
1281: #endif
1282: return;
1283: }
1284: ncr_sc->sc_state &= ~NCR_DOINGDMA;
1285:
1286: /* First, halt the DMA engine. */
1287: si->sw_csr &= ~SI_CSR_DMA_EN;
1288:
1289: /*
1290: * XXX HARDWARE BUG!
1291: * Apparently, some early 4/100 SCSI controllers had a hardware
1292: * bug that caused the controller to do illegal memory access.
1293: * We see this as SI_CSR_DMA_BUS_ERR (makes sense). To work around
1294: * this, we simply need to clean up after ourselves ... there will
1295: * be as many as 3 bytes left over. Since we clean up "left-over"
1296: * bytes on every read anyway, we just continue to chug along
1297: * if SI_CSR_DMA_BUS_ERR is asserted. (This was probably worked
1298: * around in hardware later with the "left-over byte" indicator
1299: * in the VME controller.)
1300: */
1301: #if 0
1302: if (si->sw_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
1303: #else
1304: if (si->sw_csr & (SI_CSR_DMA_CONFLICT)) {
1305: #endif
1306: printf("sw: DMA error, csr=0x%x, reset\n", si->sw_csr);
1307: sr->sr_xs->error = XS_DRIVER_STUFFUP;
1308: ncr_sc->sc_state |= NCR_ABORTING;
1309: si_reset_adapter(ncr_sc);
1310: }
1311:
1312: /* Note that timeout may have set the error flag. */
1313: if (ncr_sc->sc_state & NCR_ABORTING)
1314: goto out;
1315:
1316: /*
1317: * Now try to figure out how much actually transferred
1318: *
1319: * The "sw" doesn't have a FIFO or a bcr, so we've stored
1320: * the starting PA of the transfer in the DMA handle,
1321: * and subtract it from the ending PA left in the dma_addr
1322: * register.
1323: */
1324: Dma_addr = si->dma_addr;
1325: ntrans = (Dma_addr - dh->dh_startingpa);
1326:
1327: #ifdef DEBUG
1328: if (si_debug & 2) {
1329: printf("si_dma_stop: ntrans=0x%x\n", ntrans);
1330: }
1331: #endif
1332:
1333: if (ntrans < MIN_DMA_LEN) {
1334: printf("sw: short transfer\n");
1335: ncr_sc->sc_state |= NCR_ABORTING;
1336: goto out;
1337: }
1338:
1339: if (ntrans > ncr_sc->sc_datalen)
1340: panic("si_dma_stop: excess transfer");
1341:
1342: /* Adjust data pointer */
1343: ncr_sc->sc_dataptr += ntrans;
1344: ncr_sc->sc_datalen -= ntrans;
1345:
1346: /*
1347: * After a read, we may need to clean-up
1348: * "Left-over bytes" (yuck!) The "sw" doesn't
1349: * have a "left-over" indicator, so we have to so
1350: * this no matter what. Ick.
1351: */
1352: if ((dh->dh_flags & SIDH_OUT) == 0) {
1353: char *cp = ncr_sc->sc_dataptr;
1354:
1355: switch (Dma_addr & 3) {
1356: case 3:
1357: cp[0] = (si->sw_bpr & 0xff000000) >> 24;
1358: cp[1] = (si->sw_bpr & 0x00ff0000) >> 16;
1359: cp[2] = (si->sw_bpr & 0x0000ff00) >> 8;
1360: #ifdef COUNT_SW_LEFTOVERS
1361: ++sw_3_leftover;
1362: #endif
1363: break;
1364:
1365: case 2:
1366: cp[0] = (si->sw_bpr & 0xff000000) >> 24;
1367: cp[1] = (si->sw_bpr & 0x00ff0000) >> 16;
1368: #ifdef COUNT_SW_LEFTOVERS
1369: ++sw_2_leftover;
1370: #endif
1371: break;
1372:
1373: case 1:
1374: cp[0] = (si->sw_bpr & 0xff000000) >> 24;
1375: #ifdef COUNT_SW_LEFTOVERS
1376: ++sw_1_leftover;
1377: #endif
1378: break;
1379:
1380: #ifdef COUNT_SW_LEFTOVERS
1381: default:
1382: ++sw_0_leftover;
1383: break;
1384: #endif
1385: }
1386: }
1387:
1388: out:
1389: si->dma_addr = 0;
1390: si->dma_count = 0;
1391:
1392: /* Put SBIC back in PIO mode. */
1393: *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
1394: *ncr_sc->sci_icmd = 0;
1395:
1396: #ifdef DEBUG
1397: if (si_debug & 2) {
1398: printf("si_dma_stop: ntrans=0x%x\n", ntrans);
1399: }
1400: #endif
1401: }
CVSweb