Annotation of sys/arch/mac68k/dev/sbc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: sbc.c,v 1.16 2006/12/13 21:12:56 miod Exp $ */
2: /* $NetBSD: sbc.c,v 1.24 1997/04/18 17:38:08 scottr Exp $ */
3:
4: /*
5: * Copyright (C) 1996 Scott Reynolds. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Scott Reynolds for
18: * the NetBSD Project.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * This file contains only the machine-dependent parts of the mac68k
36: * NCR 5380 SCSI driver. (Autoconfig stuff and PDMA functions.)
37: * The machine-independent parts are in ncr5380sbc.c
38: *
39: * Supported hardware includes:
40: * Macintosh II family 5380-based controller
41: *
42: * Credits, history:
43: *
44: * Scott Reynolds wrote this module, based on work by Allen Briggs
45: * (mac68k), Gordon W. Ross and David Jones (sun3), and Leo Weppelman
46: * (atari). Thanks to Allen for supplying crucial interpretation of the
47: * NetBSD/mac68k 1.1 'ncrscsi' driver. Also, Allen, Gordon, and Jason
48: * Thorpe all helped to refine this code, and were considerable sources
49: * of moral support.
50: */
51:
52: #include <sys/types.h>
53: #include <sys/param.h>
54: #include <sys/systm.h>
55: #include <sys/kernel.h>
56: #include <sys/errno.h>
57: #include <sys/device.h>
58: #include <sys/buf.h>
59: #include <sys/proc.h>
60: #include <sys/user.h>
61:
62: #include <scsi/scsi_all.h>
63: #include <scsi/scsi_debug.h>
64: #include <scsi/scsiconf.h>
65:
66: #include <dev/ic/ncr5380reg.h>
67: #include <dev/ic/ncr5380var.h>
68:
69: #include <machine/cpu.h>
70: #include <machine/viareg.h>
71:
72: #include "sbcreg.h"
73: #include "sbcvar.h"
74:
75: int sbc_debug = 0 /* | SBC_DB_INTR | SBC_DB_DMA */;
76: int sbc_link_flags = 0 /* | SDEV_DB2 */;
77: int sbc_options = 0 /* | SBC_PDMA */;
78:
79: static void sbc_minphys(struct buf *bp);
80:
81: struct scsi_adapter sbc_ops = {
82: ncr5380_scsi_cmd, /* scsi_cmd() */
83: sbc_minphys, /* scsi_minphys() */
84: NULL, /* open_target_lu() */
85: NULL, /* close_target_lu() */
86: };
87:
88: /* This is copied from julian's bt driver */
89: /* "so we have a default dev struct for our link struct." */
90: struct scsi_device sbc_dev = {
91: NULL, /* Use default error handler. */
92: NULL, /* Use default start handler. */
93: NULL, /* Use default async handler. */
94: NULL, /* Use default "done" routine. */
95: };
96:
97: struct cfdriver sbc_cd = {
98: NULL, "sbc", DV_DULL
99: };
100:
101: static int sbc_ready(struct ncr5380_softc *);
102: static void sbc_wait_not_req(struct ncr5380_softc *);
103:
104: static void
105: sbc_minphys(struct buf *bp)
106: {
107: if (bp->b_bcount > MAX_DMA_LEN)
108: bp->b_bcount = MAX_DMA_LEN;
109: return (minphys(bp));
110: }
111:
112:
113: /***
114: * General support for Mac-specific SCSI logic.
115: ***/
116:
117: int
118: sbc_irq_intr(p)
119: void *p;
120: {
121: struct ncr5380_softc *ncr_sc = p;
122: int claimed = 0;
123:
124: /* How we ever arrive here without IRQ set is a mystery... */
125: if (*ncr_sc->sci_csr & SCI_CSR_INT) {
126: #ifdef SBC_DEBUG
127: if (sbc_debug & SBC_DB_INTR)
128: decode_5380_intr(ncr_sc);
129: #endif
130: claimed = ncr5380_intr(ncr_sc);
131: if (!claimed) {
132: if (((*ncr_sc->sci_csr & ~SCI_CSR_PHASE_MATCH) == SCI_CSR_INT)
133: && ((*ncr_sc->sci_bus_csr & ~SCI_BUS_RST) == 0))
134: SCI_CLR_INTR(ncr_sc); /* RST interrupt */
135: #ifdef SBC_DEBUG
136: else {
137: printf("%s: spurious intr\n",
138: ncr_sc->sc_dev.dv_xname);
139: SBC_BREAK;
140: }
141: #endif
142: }
143: }
144:
145: return (claimed);
146: }
147:
148: #ifdef SBC_DEBUG
149: void
150: decode_5380_intr(ncr_sc)
151: struct ncr5380_softc *ncr_sc;
152: {
153: u_char csr = *ncr_sc->sci_csr;
154: u_char bus_csr = *ncr_sc->sci_bus_csr;
155:
156: if (((csr & ~(SCI_CSR_PHASE_MATCH | SCI_CSR_ATN)) == SCI_CSR_INT) &&
157: ((bus_csr & ~(SCI_BUS_MSG | SCI_BUS_CD | SCI_BUS_IO | SCI_BUS_DBP)) == SCI_BUS_SEL)) {
158: if (csr & SCI_BUS_IO)
159: printf("%s: reselect\n", ncr_sc->sc_dev.dv_xname);
160: else
161: printf("%s: select\n", ncr_sc->sc_dev.dv_xname);
162: } else if (((csr & ~SCI_CSR_ACK) == (SCI_CSR_DONE | SCI_CSR_INT)) &&
163: ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_SEL)) == SCI_BUS_BSY))
164: printf("%s: dma eop\n", ncr_sc->sc_dev.dv_xname);
165: else if (((csr & ~SCI_CSR_PHASE_MATCH) == SCI_CSR_INT) &&
166: ((bus_csr & ~SCI_BUS_RST) == 0))
167: printf("%s: bus reset\n", ncr_sc->sc_dev.dv_xname);
168: else if (((csr & ~(SCI_CSR_DREQ | SCI_CSR_ATN | SCI_CSR_ACK)) == (SCI_CSR_PERR | SCI_CSR_INT | SCI_CSR_PHASE_MATCH)) &&
169: ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_SEL)) == SCI_BUS_BSY))
170: printf("%s: parity error\n", ncr_sc->sc_dev.dv_xname);
171: else if (((csr & ~SCI_CSR_ATN) == SCI_CSR_INT) &&
172: ((bus_csr & (SCI_BUS_RST | SCI_BUS_BSY | SCI_BUS_REQ | SCI_BUS_SEL)) == (SCI_BUS_BSY | SCI_BUS_REQ)))
173: printf("%s: phase mismatch\n", ncr_sc->sc_dev.dv_xname);
174: else if (((csr & ~SCI_CSR_PHASE_MATCH) == (SCI_CSR_INT | SCI_CSR_DISC)) &&
175: (bus_csr == 0))
176: printf("%s: disconnect\n", ncr_sc->sc_dev.dv_xname);
177: else
178: printf("%s: unknown intr: csr=%x, bus_csr=%x\n",
179: ncr_sc->sc_dev.dv_xname, csr, bus_csr);
180: }
181: #endif
182:
183:
184: /***
185: * The following code implements polled PDMA.
186: ***/
187:
188: #define TIMEOUT 5000000 /* x 2 usec = 10 sec */
189:
190: static __inline__ int
191: sbc_ready(sc)
192: struct ncr5380_softc *sc;
193: {
194: int i = TIMEOUT;
195:
196: for (;;) {
197: if ((*sc->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH)) ==
198: (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
199: return 1;
200: if (((*sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0) ||
201: (SCI_BUSY(sc) == 0))
202: return 0;
203: if (--i < 0)
204: break;
205: delay(2);
206: }
207:
208: printf("%s: ready timeout\n", sc->sc_dev.dv_xname);
209: return 0;
210: }
211:
212: static __inline__ void
213: sbc_wait_not_req(sc)
214: struct ncr5380_softc *sc;
215: {
216: int i = TIMEOUT;
217:
218: for (;;) {
219: if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0 ||
220: (*sc->sci_csr & SCI_CSR_PHASE_MATCH) == 0 ||
221: SCI_BUSY(sc) == 0) {
222: return;
223: }
224: if (--i < 0)
225: break;
226: delay(2);
227: }
228: printf("%s: pdma not_req timeout\n", sc->sc_dev.dv_xname);
229: }
230:
231: int
232: sbc_pdma_in(ncr_sc, phase, datalen, data)
233: struct ncr5380_softc *ncr_sc;
234: int phase, datalen;
235: u_char *data;
236: {
237: struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
238: volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
239: volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
240: int resid, s;
241:
242: s = splbio();
243: *ncr_sc->sci_mode |= SCI_MODE_DMA;
244: *ncr_sc->sci_irecv = 0;
245:
246: #define R4 *((u_int32_t *)data)++ = *long_data++
247: #define R1 *data++ = *byte_data++
248: for (resid = datalen; resid >= 128; resid -= 128) {
249: if (sbc_ready(ncr_sc) == 0)
250: goto interrupt;
251: R4; R4; R4; R4; R4; R4; R4; R4;
252: R4; R4; R4; R4; R4; R4; R4; R4;
253: R4; R4; R4; R4; R4; R4; R4; R4;
254: R4; R4; R4; R4; R4; R4; R4; R4;
255:
256: long_data = (u_int32_t *)sc->sc_drq_addr;
257: byte_data = (u_int8_t *)sc->sc_nodrq_addr;
258: }
259: while (resid) {
260: if (sbc_ready(ncr_sc) == 0)
261: goto interrupt;
262: R1;
263: resid--;
264: }
265: #undef R4
266: #undef R1
267:
268: sbc_wait_not_req(ncr_sc);
269: interrupt:
270: SCI_CLR_INTR(ncr_sc);
271: *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
272: splx(s);
273: return datalen - resid;
274: }
275:
276: int
277: sbc_pdma_out(ncr_sc, phase, datalen, data)
278: struct ncr5380_softc *ncr_sc;
279: int phase, datalen;
280: u_char *data;
281: {
282: struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
283: volatile u_int32_t *long_data = (u_int32_t *)sc->sc_drq_addr;
284: volatile u_int8_t *byte_data = (u_int8_t *)sc->sc_nodrq_addr;
285: int i, s, resid;
286: u_char icmd;
287:
288: if (datalen < 64)
289: return ncr5380_pio_out(ncr_sc, phase, datalen, data);
290:
291: s = splbio();
292: icmd = *(ncr_sc->sci_icmd) & SCI_ICMD_RMASK;
293: *ncr_sc->sci_icmd = icmd | SCI_ICMD_DATA;
294: *ncr_sc->sci_mode |= SCI_MODE_DMA;
295: *ncr_sc->sci_dma_send = 0;
296:
297: resid = datalen;
298: if (sbc_ready(ncr_sc) == 0)
299: goto interrupt;
300:
301: #define W1 *byte_data++ = *data++
302: #define W4 *long_data++ = *((u_int32_t *)data)++
303: while (resid >= 64) {
304: if (sbc_ready(ncr_sc) == 0)
305: goto interrupt;
306: W1;
307: resid--;
308: if (sbc_ready(ncr_sc) == 0)
309: goto interrupt;
310: W1;
311: resid--;
312: if (sbc_ready(ncr_sc) == 0)
313: goto interrupt;
314: W1;
315: resid--;
316: if (sbc_ready(ncr_sc) == 0)
317: goto interrupt;
318: W1;
319: resid--;
320: if (sbc_ready(ncr_sc) == 0)
321: goto interrupt;
322: W4; W4; W4; W4;
323: W4; W4; W4; W4;
324: W4; W4; W4; W4;
325: W4; W4; W4;
326: resid -= 60;
327:
328: long_data = (u_int32_t *)sc->sc_drq_addr;
329: byte_data = (u_int8_t *)sc->sc_nodrq_addr;
330: }
331: for (; resid; resid--) {
332: if (sbc_ready(ncr_sc) == 0)
333: goto interrupt;
334: W1;
335: }
336: #undef W1
337: #undef W4
338:
339: for (i = TIMEOUT; i > 0; i--) {
340: if ((*ncr_sc->sci_csr & (SCI_CSR_DREQ|SCI_CSR_PHASE_MATCH))
341: != SCI_CSR_DREQ)
342: break;
343: }
344: if (i != 0)
345: *byte_data = 0;
346: else
347: printf("%s: timeout waiting for final SCI_DSR_DREQ.\n",
348: ncr_sc->sc_dev.dv_xname);
349:
350: sbc_wait_not_req(ncr_sc);
351: interrupt:
352: SCI_CLR_INTR(ncr_sc);
353: *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
354: *ncr_sc->sci_icmd = icmd;
355: splx(s);
356: return (datalen - resid);
357: }
358:
359:
360: /***
361: * The following code implements interrupt-driven PDMA.
362: ***/
363:
364: /*
365: * This is the meat of the PDMA transfer.
366: * When we get here, we shove data as fast as the mac can take it.
367: * We depend on several things:
368: * * All macs after the Mac Plus that have a 5380 chip should have a general
369: * logic IC that handshakes data for blind transfers.
370: * * If the SCSI controller finishes sending/receiving data before we do,
371: * the same general logic IC will generate a /BERR for us in short order.
372: * * The fault address for said /BERR minus the base address for the
373: * transfer will be the amount of data that was actually written.
374: *
375: * We use the nofault flag and the setjmp/longjmp in locore.s so we can
376: * detect and handle the bus error for early termination of a command.
377: * This is usually caused by a disconnecting target.
378: */
379: int
380: sbc_drq_intr(p)
381: void *p;
382: {
383: extern int *nofault, m68k_fault_addr;
384: struct sbc_softc *sc = (struct sbc_softc *)p;
385: struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)p;
386: struct sci_req *sr = ncr_sc->sc_current;
387: struct sbc_pdma_handle *dh = sr->sr_dma_hand;
388: label_t faultbuf;
389: volatile u_int32_t *long_drq;
390: u_int32_t *long_data;
391: volatile u_int8_t *drq;
392: u_int8_t *data;
393: int count, dcount, resid;
394: #ifdef SBC_WRITE_HACK
395: u_int8_t tmp;
396: #endif
397:
398: /*
399: * If we're not ready to xfer data, or have no more, just return.
400: */
401: if ((*ncr_sc->sci_csr & SCI_CSR_DREQ) == 0 || dh->dh_len == 0)
402: return (0);
403:
404: #ifdef SBC_DEBUG
405: if (sbc_debug & SBC_DB_INTR)
406: printf("%s: drq intr, dh_len=0x%x, dh_flags=0x%x\n",
407: ncr_sc->sc_dev.dv_xname, dh->dh_len, dh->dh_flags);
408: #endif
409:
410: /*
411: * Setup for a possible bus error caused by SCSI controller
412: * switching out of DATA-IN/OUT before we're done with the
413: * current transfer.
414: */
415: nofault = (int *) &faultbuf;
416:
417: if (setjmp((label_t *)nofault)) {
418: nofault = (int *) 0;
419: if ((dh->dh_flags & SBC_DH_DONE) == 0) {
420: count = (( (u_long)m68k_fault_addr
421: - (u_long)sc->sc_drq_addr));
422:
423: if ((count < 0) || (count > dh->dh_len)) {
424: printf("%s: complete=0x%x (pending 0x%x)\n",
425: ncr_sc->sc_dev.dv_xname, count, dh->dh_len);
426: panic("something is wrong");
427: }
428:
429: dh->dh_addr += count;
430: dh->dh_len -= count;
431: } else
432: count = 0;
433:
434: #ifdef SBC_DEBUG
435: if (sbc_debug & SBC_DB_INTR)
436: printf("%s: drq /berr, complete=0x%x (pending 0x%x)\n",
437: ncr_sc->sc_dev.dv_xname, count, dh->dh_len);
438: #endif
439: m68k_fault_addr = 0;
440:
441: return (1);
442: }
443:
444: if (dh->dh_flags & SBC_DH_OUT) { /* Data Out */
445: #if notyet /* XXX */
446: /*
447: * Get the source address aligned.
448: */
449: resid =
450: count = min(dh->dh_len, 4 - (((int)dh->dh_addr) & 0x3));
451: if (count && count < 4) {
452: drq = (volatile u_int8_t *)sc->sc_drq_addr;
453: data = (u_int8_t *)dh->dh_addr;
454:
455: #define W1 *drq++ = *data++
456: while (count) {
457: W1; count--;
458: }
459: #undef W1
460: dh->dh_addr += resid;
461: dh->dh_len -= resid;
462: }
463:
464: /*
465: * Start the transfer.
466: */
467: while (dh->dh_len) {
468: dcount = count = min(dh->dh_len, MAX_DMA_LEN);
469: long_drq = (volatile u_int32_t *)sc->sc_drq_addr;
470: long_data = (u_int32_t *)dh->dh_addr;
471:
472: #define W4 *long_drq++ = *long_data++
473: while (count >= 64) {
474: W4; W4; W4; W4; W4; W4; W4; W4;
475: W4; W4; W4; W4; W4; W4; W4; W4; /* 64 */
476: count -= 64;
477: }
478: while (count >= 4) {
479: W4; count -= 4;
480: }
481: #undef W4
482: data = (u_int8_t *)long_data;
483: drq = (u_int8_t *)long_drq;
484: #else /* notyet */
485: /*
486: * Start the transfer.
487: */
488: while (dh->dh_len) {
489: dcount = count = min(dh->dh_len, MAX_DMA_LEN);
490: drq = (volatile u_int8_t *)sc->sc_drq_addr;
491: data = (u_int8_t *)dh->dh_addr;
492: #endif /* notyet */
493:
494: #define W1 *drq++ = *data++
495: while (count) {
496: W1; count--;
497: }
498: #undef W1
499: dh->dh_len -= dcount;
500: dh->dh_addr += dcount;
501: }
502: dh->dh_flags |= SBC_DH_DONE;
503:
504: #ifdef SBC_WRITE_HACK
505: /*
506: * XXX -- Read a byte from the SBC to trigger a /BERR.
507: * This seems to be necessary for us to notice that
508: * the target has disconnected. Ick. 06 jun 1996 (sr)
509: */
510: if (dcount >= MAX_DMA_LEN) {
511: #if 0
512: while ((*ncr_sc->sci_csr & SCI_CSR_ACK) == 0)
513: ;
514: #endif
515: drq = (volatile u_int8_t *)sc->sc_drq_addr;
516: }
517: tmp = *drq;
518: #endif
519: } else { /* Data In */
520: /*
521: * Get the dest address aligned.
522: */
523: resid =
524: count = min(dh->dh_len, 4 - (((int)dh->dh_addr) & 0x3));
525: if (count && count < 4) {
526: data = (u_int8_t *)dh->dh_addr;
527: drq = (volatile u_int8_t *)sc->sc_drq_addr;
528:
529: #define R1 *data++ = *drq++
530: while (count) {
531: R1; count--;
532: }
533: #undef R1
534: dh->dh_addr += resid;
535: dh->dh_len -= resid;
536: }
537:
538: /*
539: * Start the transfer.
540: */
541: while (dh->dh_len) {
542: dcount = count = min(dh->dh_len, MAX_DMA_LEN);
543: long_data = (u_int32_t *)dh->dh_addr;
544: long_drq = (volatile u_int32_t *)sc->sc_drq_addr;
545:
546: #define R4 *long_data++ = *long_drq++
547: while (count >= 64) {
548: R4; R4; R4; R4; R4; R4; R4; R4;
549: R4; R4; R4; R4; R4; R4; R4; R4; /* 64 */
550: count -= 64;
551: }
552: while (count >= 4) {
553: R4; count -= 4;
554: }
555: #undef R4
556: data = (u_int8_t *)long_data;
557: drq = (volatile u_int8_t *)long_drq;
558:
559: #define R1 *data++ = *drq++
560: while (count) {
561: R1; count--;
562: }
563: #undef R1
564: dh->dh_len -= dcount;
565: dh->dh_addr += dcount;
566: }
567: dh->dh_flags |= SBC_DH_DONE;
568: }
569:
570: /*
571: * OK. No bus error occurred above. Clear the nofault flag
572: * so we no longer short-circuit bus errors.
573: */
574: nofault = (int *) 0;
575:
576: #ifdef SBC_DEBUG
577: if (sbc_debug & (SBC_DB_REG | SBC_DB_INTR))
578: printf("%s: drq intr complete: csr=0x%x, bus_csr=0x%x\n",
579: ncr_sc->sc_dev.dv_xname, *ncr_sc->sci_csr,
580: *ncr_sc->sci_bus_csr);
581: #endif
582:
583: return (1);
584: }
585:
586: void
587: sbc_dma_alloc(ncr_sc)
588: struct ncr5380_softc *ncr_sc;
589: {
590: struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
591: struct sci_req *sr = ncr_sc->sc_current;
592: struct scsi_xfer *xs = sr->sr_xs;
593: struct sbc_pdma_handle *dh;
594: int i, xlen;
595:
596: #ifdef DIAGNOSTIC
597: if (sr->sr_dma_hand != NULL)
598: panic("sbc_dma_alloc: already have PDMA handle");
599: #endif
600:
601: /* Polled transfers shouldn't allocate a PDMA handle. */
602: if (sr->sr_flags & SR_IMMED)
603: return;
604:
605: xlen = ncr_sc->sc_datalen;
606:
607: /* Make sure our caller checked sc_min_dma_len. */
608: if (xlen < MIN_DMA_LEN)
609: panic("sbc_dma_alloc: len=0x%x", xlen);
610:
611: /*
612: * Find free PDMA handle. Guaranteed to find one since we
613: * have as many PDMA handles as the driver has processes.
614: * (instances?)
615: */
616: for (i = 0; i < SCI_OPENINGS; i++) {
617: if ((sc->sc_pdma[i].dh_flags & SBC_DH_BUSY) == 0)
618: goto found;
619: }
620: panic("sbc: no free PDMA handles");
621: found:
622: dh = &sc->sc_pdma[i];
623: dh->dh_flags = SBC_DH_BUSY;
624: dh->dh_addr = ncr_sc->sc_dataptr;
625: dh->dh_len = xlen;
626:
627: /* Copy the 'write' flag for convenience. */
628: if (xs->flags & SCSI_DATA_OUT)
629: dh->dh_flags |= SBC_DH_OUT;
630:
631: sr->sr_dma_hand = dh;
632: }
633:
634: void
635: sbc_dma_free(ncr_sc)
636: struct ncr5380_softc *ncr_sc;
637: {
638: struct sci_req *sr = ncr_sc->sc_current;
639: struct sbc_pdma_handle *dh = sr->sr_dma_hand;
640:
641: #ifdef DIAGNOSTIC
642: if (sr->sr_dma_hand == NULL)
643: panic("sbc_dma_free: no DMA handle");
644: #endif
645:
646: if (ncr_sc->sc_state & NCR_DOINGDMA)
647: panic("sbc_dma_free: free while in progress");
648:
649: if (dh->dh_flags & SBC_DH_BUSY) {
650: dh->dh_flags = 0;
651: dh->dh_addr = NULL;
652: dh->dh_len = 0;
653: }
654: sr->sr_dma_hand = NULL;
655: }
656:
657: void
658: sbc_dma_poll(ncr_sc)
659: struct ncr5380_softc *ncr_sc;
660: {
661: struct sci_req *sr = ncr_sc->sc_current;
662:
663: /*
664: * We shouldn't arrive here; if SR_IMMED is set, then
665: * dma_alloc() should have refused to allocate a handle
666: * for the transfer. This forces the polled PDMA code
667: * to handle the request...
668: */
669: #ifdef SBC_DEBUG
670: if (sbc_debug & SBC_DB_DMA)
671: printf("%s: lost DRQ interrupt?\n", ncr_sc->sc_dev.dv_xname);
672: #endif
673: sr->sr_flags |= SR_OVERDUE;
674: }
675:
676: void
677: sbc_dma_setup(ncr_sc)
678: struct ncr5380_softc *ncr_sc;
679: {
680: /* Not needed; we don't have real DMA */
681: }
682:
683: void
684: sbc_dma_start(ncr_sc)
685: struct ncr5380_softc *ncr_sc;
686: {
687: struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
688: struct sci_req *sr = ncr_sc->sc_current;
689: struct sbc_pdma_handle *dh = sr->sr_dma_hand;
690:
691: /*
692: * Match bus phase, clear pending interrupts, set DMA mode, and
693: * assert data bus (for writing only), then start the transfer.
694: */
695: if (dh->dh_flags & SBC_DH_OUT) {
696: *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
697: SCI_CLR_INTR(ncr_sc);
698: if (sc->sc_clrintr)
699: (*sc->sc_clrintr)(ncr_sc);
700: *ncr_sc->sci_mode |= SCI_MODE_DMA;
701: *ncr_sc->sci_icmd = SCI_ICMD_DATA;
702: *ncr_sc->sci_dma_send = 0;
703: } else {
704: *ncr_sc->sci_tcmd = PHASE_DATA_IN;
705: SCI_CLR_INTR(ncr_sc);
706: if (sc->sc_clrintr)
707: (*sc->sc_clrintr)(ncr_sc);
708: *ncr_sc->sci_mode |= SCI_MODE_DMA;
709: *ncr_sc->sci_icmd = 0;
710: *ncr_sc->sci_irecv = 0;
711: }
712: ncr_sc->sc_state |= NCR_DOINGDMA;
713:
714: #ifdef SBC_DEBUG
715: if (sbc_debug & SBC_DB_DMA)
716: printf("%s: PDMA started, va=%p, len=0x%x\n",
717: ncr_sc->sc_dev.dv_xname, dh->dh_addr, dh->dh_len);
718: #endif
719: }
720:
721: void
722: sbc_dma_stop(ncr_sc)
723: struct ncr5380_softc *ncr_sc;
724: {
725: struct sbc_softc *sc = (struct sbc_softc *)ncr_sc;
726: struct sci_req *sr = ncr_sc->sc_current;
727: struct sbc_pdma_handle *dh = sr->sr_dma_hand;
728: int ntrans;
729:
730: if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
731: #ifdef SBC_DEBUG
732: if (sbc_debug & SBC_DB_DMA)
733: printf("%s: dma_stop: DMA not running\n",
734: ncr_sc->sc_dev.dv_xname);
735: #endif
736: return;
737: }
738: ncr_sc->sc_state &= ~NCR_DOINGDMA;
739:
740: if ((ncr_sc->sc_state & NCR_ABORTING) == 0) {
741: ntrans = ncr_sc->sc_datalen - dh->dh_len;
742:
743: #ifdef SBC_DEBUG
744: if (sbc_debug & SBC_DB_DMA)
745: printf("%s: dma_stop: ntrans=0x%x\n",
746: ncr_sc->sc_dev.dv_xname, ntrans);
747: #endif
748:
749: if (ntrans > ncr_sc->sc_datalen)
750: panic("sbc_dma_stop: excess transfer");
751:
752: /* Adjust data pointer */
753: ncr_sc->sc_dataptr += ntrans;
754: ncr_sc->sc_datalen -= ntrans;
755:
756: /* Clear any pending interrupts. */
757: SCI_CLR_INTR(ncr_sc);
758: if (sc->sc_clrintr)
759: (*sc->sc_clrintr)(ncr_sc);
760: }
761:
762: /* Put SBIC back into PIO mode. */
763: *ncr_sc->sci_mode &= ~SCI_MODE_DMA;
764: *ncr_sc->sci_icmd = 0;
765:
766: #ifdef SBC_DEBUG
767: if (sbc_debug & SBC_DB_REG)
768: printf("%s: dma_stop: csr=0x%x, bus_csr=0x%x\n",
769: ncr_sc->sc_dev.dv_xname, *ncr_sc->sci_csr,
770: *ncr_sc->sci_bus_csr);
771: #endif
772: }
CVSweb