1 /* $FreeBSD: releng/5.1/sys/i386/isa/bs/bshw_dma.c 92765 2002-03-20 07:51:46Z alfred $ */
2 /* $NecBSD: bshw_dma.c,v 1.3 1997/07/26 06:03:16 honda Exp $ */
3 /* $NetBSD$ */
4 /*
5 * [NetBSD for NEC PC98 series]
6 * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
34 */
35
36 /*********************************************************
37 * static declare.
38 *********************************************************/
39 static void bshw_dmastart(struct bs_softc *);
40 static void bshw_dmadone(struct bs_softc *);
41
42 /**********************************************
43 * UPPER INTERFACE FUNCS (all funcs exported)
44 **********************************************/
45 void
46 bshw_dmaabort(bsc, ti)
47 struct bs_softc *bsc;
48 struct targ_info *ti;
49 {
50
51 bshw_dmadone(bsc);
52 bsc->sc_p.seglen = 0;
53 bshw_set_count(bsc, 0);
54
55 if (ti == NULL)
56 {
57 int i;
58 struct targ_info *tmpti;
59
60 for (i = 0; i < NTARGETS; i++)
61 if ((tmpti = bsc->sc_ti[i]) != NULL)
62 tmpti->ti_scsp.seglen = 0;
63 }
64 else
65 ti->ti_scsp.seglen = 0;
66 }
67
68 /* DMA TRANSFER */
69 void
70 bs_dma_xfer(ti, direction)
71 struct targ_info *ti;
72 u_int direction;
73 {
74 vm_offset_t va, endva, phys, nphys;
75 struct bs_softc *bsc = ti->ti_bsc;
76 struct sc_p *sp = &bsc->sc_p;
77
78 bsc->sc_dmadir = direction;
79 bshw_set_dma_trans(bsc, ti->ti_cfgflags);
80
81 if (sp->seglen == 0)
82 {
83 phys = vtophys((vm_offset_t) sp->data);
84 if (phys >= RAM_END)
85 {
86 /* setup segaddr */
87 sp->segaddr = ti->bounce_phys;
88 /* setup seglen */
89 sp->seglen = sp->datalen;
90 if (sp->seglen > ti->bounce_size)
91 sp->seglen = ti->bounce_size;
92 /* setup bufp */
93 sp->bufp = ti->bounce_addr;
94 if (bsc->sc_dmadir != BSHW_READ)
95 bcopy(sp->data, sp->bufp, sp->seglen);
96 #ifdef BS_STATICS
97 bs_bounce_used[ti->ti_id]++;
98 #endif /* BS_STATICS */
99 }
100 else
101 {
102 /* setup segaddr */
103 sp->segaddr = (u_int8_t *) phys;
104 /* setup seglen */
105 endva = (vm_offset_t)round_page((unsigned long)(sp->data + sp->datalen));
106 for (va = (vm_offset_t) sp->data; ; phys = nphys)
107 {
108 if ((va += BSHW_NBPG) >= endva)
109 {
110 sp->seglen = sp->datalen;
111 break;
112 }
113
114 nphys = vtophys(va);
115 if (phys + BSHW_NBPG != nphys || nphys >= RAM_END)
116 {
117 sp->seglen =
118 (u_int8_t *) trunc_page(va) - sp->data;
119 break;
120 }
121 }
122 /* setup bufp */
123 sp->bufp = NULL;
124 }
125 }
126
127 bshw_dmastart(bsc);
128 bshw_set_count(bsc, sp->seglen);
129 }
130
131 void
132 bs_dma_xfer_end(ti)
133 struct targ_info *ti;
134 {
135 struct bs_softc *bsc = ti->ti_bsc;
136 struct sc_p *sp = &bsc->sc_p;
137 u_int count, transbytes;
138
139 bshw_dmadone(bsc);
140 if (ti->ti_phase == DATAPHASE)
141 {
142 count = bshw_get_count(bsc);
143 if (count < (u_int) sp->seglen)
144 {
145 transbytes = sp->seglen - count;
146 if (sp->bufp)
147 {
148 if (bsc->sc_dmadir == BSHW_READ)
149 bcopy(sp->bufp, sp->data, transbytes);
150 sp->bufp += transbytes;
151 }
152 sp->seglen = count;
153 sp->segaddr += transbytes;
154 sp->data += transbytes;
155 sp->datalen -= transbytes;
156 return;
157 }
158 else if (count == (u_int) sp->seglen)
159 {
160 return;
161 }
162
163 bs_printf(ti, "xfer_end", "strange count");
164 printf("port data %x seglen %x\n", count, sp->seglen);
165 }
166 else
167 bs_printf(ti, "xfer_end", "extra dma interrupt");
168
169 ti->ti_error |= BSDMAABNORMAL;
170 sp->seglen = ti->ti_scsp.seglen = 0; /* XXX */
171 }
172
173 /**********************************************
174 * GENERIC DMA FUNCS
175 **********************************************/
176 static u_int8_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
177
178 /* common dma settings */
179 #undef DMA1_SMSK
180 #define DMA1_SMSK (0x15)
181 #undef DMA1_MODE
182 #define DMA1_MODE (0x17)
183 #undef DMA1_FFC
184 #define DMA1_FFC (0x19)
185 #undef DMA37SM_SET
186 #define DMA37SM_SET 0x04
187 #undef DMA1_CHN
188 #define DMA1_CHN(c) (0x01 + ((c) << 2))
189
190 static void
191 bshw_dmastart(bsc)
192 struct bs_softc *bsc;
193 {
194 int chan = bsc->sc_dmachan;
195 int waport;
196 u_int8_t *phys = bsc->sc_p.segaddr;
197 u_int nbytes = bsc->sc_p.seglen;
198
199 /*
200 * Program one of DMA channels 0..3. These are
201 * byte mode channels.
202 */
203 /* set dma channel mode, and reset address ff */
204 #ifdef __FreeBSD__
205 if (need_pre_dma_flush)
206 wbinvd();
207 #else /* NetBSD/pc98 */
208 if (bsc->sc_dmadir & BSHW_READ)
209 cpu_cf_preRead(curcpu);
210 else
211 cpu_cf_preWrite(curcpu);
212 #endif
213
214 if (bsc->sc_dmadir & BSHW_READ)
215 outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_WRITE | chan);
216 else
217 outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_READ | chan);
218 outb(DMA1_FFC, 0);
219
220 /* send start address */
221 waport = DMA1_CHN(chan);
222 outb(waport, (u_int) phys);
223 outb(waport, ((u_int) phys) >> 8);
224 outb(dmapageport[chan], ((u_int) phys) >> 16);
225
226 /* send count */
227 outb(waport + 2, --nbytes);
228 outb(waport + 2, nbytes >> 8);
229
230 /* vendor unique hook */
231 if (bsc->sc_hw->dma_start)
232 (*bsc->sc_hw->dma_start)(bsc);
233
234 outb(DMA1_SMSK, chan);
235 BUS_IOW(cmd_port, CMDP_DMES);
236
237 bsc->sc_flags |= BSDMASTART;
238 }
239
240 static void
241 bshw_dmadone(bsc)
242 struct bs_softc *bsc;
243 {
244
245 outb(DMA1_SMSK, (bsc->sc_dmachan | DMA37SM_SET));
246 BUS_IOW(cmd_port, CMDP_DMER);
247
248 /* vendor unique hook */
249 if (bsc->sc_hw->dma_stop)
250 (*bsc->sc_hw->dma_stop)(bsc);
251
252 #ifdef __FreeBSD__
253 if (need_post_dma_flush)
254 invd();
255 #else
256 if (bsc->sc_dmadir & BSHW_READ)
257 cpu_cf_postRead(curcpu);
258 else
259 cpu_cf_postWrite(curcpu);
260 #endif
261
262 bsc->sc_flags &= (~BSDMASTART);
263 }
264
265 /**********************************************
266 * VENDOR UNIQUE DMA FUNCS
267 **********************************************/
268 static int
269 bshw_dma_init_texa(bsc)
270 struct bs_softc *bsc;
271 {
272 u_int8_t regval;
273
274 if ((regval = read_wd33c93(bsc, 0x37)) & 0x08)
275 return 0;
276
277 write_wd33c93(bsc, 0x37, regval | 0x08);
278 regval = read_wd33c93(bsc, 0x3f);
279 write_wd33c93(bsc, 0x3f, regval | 0x08);
280 return 1;
281 }
282
283 static int
284 bshw_dma_init_sc98(bsc)
285 struct bs_softc *bsc;
286 {
287
288 if (read_wd33c93(bsc, 0x37) & 0x08)
289 return 0;
290
291 /* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
292 write_wd33c93(bsc, 0x37, 0x1a);
293 write_wd33c93(bsc, 0x3f, 0x1a);
294 #if 0
295 /* only valid for IO */
296 write_wd33c93(bsc, 0x40, 0xf4);
297 write_wd33c93(bsc, 0x41, 0x9);
298 write_wd33c93(bsc, 0x43, 0xff);
299 write_wd33c93(bsc, 0x46, 0x4e);
300
301 write_wd33c93(bsc, 0x48, 0xf4);
302 write_wd33c93(bsc, 0x49, 0x9);
303 write_wd33c93(bsc, 0x4b, 0xff);
304 write_wd33c93(bsc, 0x4e, 0x4e);
305 #endif
306 return 1;
307 }
308
309 static void
310 bshw_dma_start_sc98(bsc)
311 struct bs_softc *bsc;
312 {
313
314 write_wd33c93(bsc, 0x73, 0x32);
315 write_wd33c93(bsc, 0x74, 0x23);
316 }
317
318 static void
319 bshw_dma_stop_sc98(bsc)
320 struct bs_softc *bsc;
321 {
322
323 write_wd33c93(bsc, 0x73, 0x43);
324 write_wd33c93(bsc, 0x74, 0x34);
325 }
326
327 static void
328 bshw_dma_start_elecom(bsc)
329 struct bs_softc *bsc;
330 {
331 u_int8_t tmp = read_wd33c93(bsc, 0x4c);
332
333 write_wd33c93(bsc, 0x32, tmp & 0xdf);
334 }
335
336 static void
337 bshw_dma_stop_elecom(bsc)
338 struct bs_softc *bsc;
339 {
340 u_int8_t tmp = read_wd33c93(bsc, 0x4c);
341
342 write_wd33c93(bsc, 0x32, tmp | 0x20);
343 }
Cache object: d0621e2ab0003d064fd18c4f063db71e
|