source: drsdaq/VME/struck/sis1100/V2.02/dev/pci/sis1100_read_dma_netbsd.c@ 23

Last change on this file since 23 was 22, checked in by ogrimm, 16 years ago
First commit of drsdaq program
File size: 6.6 KB
Line 
1/* $ZEL: sis1100_read_dma_netbsd.c,v 1.3 2004/05/27 23:10:31 wuestner Exp $ */
2
3/*
4 * Copyright (c) 2001-2004
5 * Matthias Drochner, Peter Wuestner. 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 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include "sis1100_sc.h"
30
31ssize_t
32_sis1100_read_dma(
33 struct sis1100_softc* sc,
34 struct sis1100_fdata* fd,
35 u_int32_t addr, /* VME or SDRAM address */
36 int32_t am, /* address modifier, not used if <0 */
37 int size, /* datasize must be 4 for DMA but is not checked*/
38 int space, /* remote space (1,2: VME; 6: SDRAM) */
39 int fifo_mode,
40 size_t count, /* words to be transferred */
41 /* count==0 is illegal */
42 size_t* count_read, /* words transferred */
43 u_int8_t* data, /* destination (user virtual address) */
44 int* prot_error, /* protocol error */
45 int* eot /* end of transport indicator */
46 )
47{
48 int res, i, aborted=0, s;
49 u_int32_t head;
50 struct plx9054_dmadesc *dd;
51 u_int32_t nextptr;
52
53 count*=size;
54 if (count>MAX_DMA_LEN) count=MAX_DMA_LEN;
55
56 res = uvm_vslock(fd->p, data, count, VM_PROT_READ|VM_PROT_WRITE);
57 if (res) {
58 pINFO(sc, "uvm_vslock failed");
59 return res;
60 }
61
62 res=bus_dmamap_load(sc->sc_dma.dmat, sc->sc_dma.userdma,
63 data, count, fd->p, BUS_DMA_NOWAIT);
64 if (res) {
65 uvm_vsunlock(fd->p, data, count);
66 pINFO(sc, "bus_dmamap_load failed");
67 return res;
68 }
69 dd = sc->sc_dma.descs;
70 nextptr = 0x0000000a;
71 for (i = sc->sc_dma.userdma->dm_nsegs - 1; i >= 0; i--) {
72 dd[i].pcistart = sc->sc_dma.userdma->dm_segs[i].ds_addr;
73 dd[i].size = sc->sc_dma.userdma->dm_segs[i].ds_len;
74 dd[i].localstart = 0;
75 dd[i].next = nextptr;
76 nextptr = (sc->sc_dma.descdma->dm_segs[0].ds_addr +
77 i * sizeof(struct plx9054_dmadesc)) | 9;
78 }
79
80/* prepare PLX */
81 plxwritereg(sc, DMACSR0_DMACSR1, 1<<3); /* clear irq */
82 plxwritereg(sc, DMAMODE0, 0x43|(1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<11)|
83 (1<<12)|(1<<14)|(1<<17));
84 plxwritereg(sc, DMADPR0, nextptr);
85
86
87/* prepare add on logic */
88 /* 4 Byte, local space 2, BT, EOT, start with t_adl */
89 head=0x0080A002|((0x00f00000<<size)&0x0f000000)|(space&0x3f)<<16;
90 if (am>=0) {
91 head|=0x800;
92 sis1100writereg(sc, t_am, am);
93 }
94 if (fifo_mode) head|=0x4000;
95 sis1100writereg(sc, t_hdr, head);
96 /*wmb();*/
97 sis1100writereg(sc, t_dal, count);
98
99 sis1100writereg(sc, d0_bc, 0);
100 sis1100writereg(sc, d0_bc_buf, 0);
101 sis1100writereg(sc, d0_bc_blen, 0);
102
103 sis1100writereg(sc, p_balance, 0);
104
105/* enable irq */
106 sc->got_irqs=0;
107 sis1100_enable_irq(sc, plxirq_dma0, irq_synch_chg|irq_prot_l_err);
108
109/* enable dma */
110 plxwritereg(sc, DMACSR0_DMACSR1, 3);
111
112/* start transfer and wait for dma*/
113 s = splbio();
114 sis1100writereg(sc, t_adl, addr);
115
116 {
117 int nochmal=0;
118 do {
119 res=0;
120 nochmal=0;
121 while (!(res||(sc->got_irqs&(got_dma0|got_sync|got_l_err)))) {
122 res = tsleep(&sc->local_wait, PCATCH, "plxdma_r_1", 10*hz);
123 }
124 if (res==ERESTART) {
125 res=0;
126 nochmal=1;
127 pINFO(sc, "DMA read restart");
128 }
129 } while (nochmal);
130 }
131 sis1100_disable_irq(sc, plxirq_dma0, irq_prot_l_err);
132 splx(s);
133 if (sc->got_irqs&(got_dma0|got_l_err)) { /* transfer complete or error */
134 *count_read=sis1100readreg(sc, d0_bc)/size;
135 if (!(sc->got_irqs&got_dma0)) {
136 u_int32_t val;
137 val=plxreadreg(sc, DMACSR0_DMACSR1);
138 pINFO(sc, "read_dma/abort: DMACSR0=0x%x\n", val);
139 if (!(val&0x10)) { /* DMA not stopped yet; abort it */
140 sis1100writereg(sc, sr, sr_abort_dma);
141 do {
142 val=plxreadreg(sc, DMACSR0_DMACSR1);
143 } while (!(val&0x10));
144 }
145 }
146 } else /*(res||(sc->got_irqs&(got_sync)))*/ { /* fatal */
147 u_int32_t val;
148 *count_read=sis1100readreg(sc, d0_bc);
149 aborted=0x300;
150 if (res) {
151 if (res==EWOULDBLOCK)
152 pINFO(sc, "read_dma: timed out");
153 else if (res==EINTR)
154 pINFO(sc, "read_dma(1): interrupted; res=%d", res);
155 else if (res==ERESTART)
156 pINFO(sc, "read_dma(1): interrupted; restart");
157 else
158 pINFO(sc, "read_dma(1): res=%d", res);
159 aborted|=1;
160 }
161 if (sc->got_irqs&got_sync) {
162 pINFO(sc, "read_dma: synchronisation lost");
163 aborted|=2;
164 }
165 val=plxreadreg(sc, DMACSR0_DMACSR1);
166 if (!(val&0x10)) { /* DMA not stopped yet; abort it */
167 sis1100writereg(sc, sr, sr_abort_dma);
168 do {
169 val=plxreadreg(sc, DMACSR0_DMACSR1);
170 } while (!(val&0x10));
171 }
172 }
173
174 plxwritereg(sc, DMACSR0_DMACSR1, 0);
175
176 uvm_vsunlock(fd->p, data, count);
177
178 *prot_error=sis1100readreg(sc, prot_error);
179 *eot=!!(sis1100readreg(sc, sr)&0x200);
180
181 if (aborted) {
182 /*dump_glink_status(sc, "after abort", 1);*/
183 pINFO(sc, "prot_error=0x%x; aborted=0x%x, count_read=%d\n",
184 *prot_error, aborted, *count_read);
185 }
186 if (aborted) *prot_error=aborted;
187 if ((*prot_error!=0) && ((*prot_error&0x200)!=0x200)) {
188 pINFO(sc, "read_dma: prot_error=0x%x", *prot_error);
189 res=EIO;
190 }
191
192 return res;
193}
Note: See TracBrowser for help on using the repository browser.