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