1 /* $FreeBSD: src/sys/i386/isa/bs/bshw_dma.c,v 1.6.6.1 2000/10/21 07:44:26 nyan Exp $ */
2 /* $DragonFly: src/sys/dev/disk/i386/bs/Attic/bshw_dma.c,v 1.4 2004/02/13 01:04:14 joerg Exp $ */
3 /* $NecBSD: bshw_dma.c,v 1.3 1997/07/26 06:03:16 honda Exp $ */
6 * [NetBSD for NEC PC98 series]
7 * Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 * Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
37 /*********************************************************
39 *********************************************************/
40 static void bshw_dmastart (struct bs_softc *);
41 static void bshw_dmadone (struct bs_softc *);
43 /**********************************************
44 * UPPER INTERFACE FUNCS (all funcs exported)
45 **********************************************/
47 bshw_dmaabort(bsc, ti)
54 bshw_set_count(bsc, 0);
59 struct targ_info *tmpti;
61 for (i = 0; i < NTARGETS; i++)
62 if ((tmpti = bsc->sc_ti[i]) != NULL)
63 tmpti->ti_scsp.seglen = 0;
66 ti->ti_scsp.seglen = 0;
71 bs_dma_xfer(ti, direction)
75 vm_offset_t va, endva, phys, nphys;
76 struct bs_softc *bsc = ti->ti_bsc;
77 struct sc_p *sp = &bsc->sc_p;
79 bsc->sc_dmadir = direction;
80 bshw_set_dma_trans(bsc, ti->ti_cfgflags);
84 phys = vtophys((vm_offset_t) sp->data);
88 sp->segaddr = ti->bounce_phys;
90 sp->seglen = sp->datalen;
91 if (sp->seglen > ti->bounce_size)
92 sp->seglen = ti->bounce_size;
94 sp->bufp = ti->bounce_addr;
95 if (bsc->sc_dmadir != BSHW_READ)
96 bcopy(sp->data, sp->bufp, sp->seglen);
98 bs_bounce_used[ti->ti_id]++;
99 #endif /* BS_STATICS */
104 sp->segaddr = (u_int8_t *) phys;
106 endva = (vm_offset_t)round_page((unsigned long)(sp->data + sp->datalen));
107 for (va = (vm_offset_t) sp->data; ; phys = nphys)
109 if ((va += BSHW_NBPG) >= endva)
111 sp->seglen = sp->datalen;
116 if (phys + BSHW_NBPG != nphys || nphys >= RAM_END)
119 (u_int8_t *) trunc_page(va) - sp->data;
129 bshw_set_count(bsc, sp->seglen);
134 struct targ_info *ti;
136 struct bs_softc *bsc = ti->ti_bsc;
137 struct sc_p *sp = &bsc->sc_p;
138 u_int count, transbytes;
141 if (ti->ti_phase == DATAPHASE)
143 count = bshw_get_count(bsc);
144 if (count < (u_int) sp->seglen)
146 transbytes = sp->seglen - count;
149 if (bsc->sc_dmadir == BSHW_READ)
150 bcopy(sp->bufp, sp->data, transbytes);
151 sp->bufp += transbytes;
154 sp->segaddr += transbytes;
155 sp->data += transbytes;
156 sp->datalen -= transbytes;
159 else if (count == (u_int) sp->seglen)
164 bs_printf(ti, "xfer_end", "strange count");
165 printf("port data %x seglen %x\n", count, sp->seglen);
168 bs_printf(ti, "xfer_end", "extra dma interrupt");
170 ti->ti_error |= BSDMAABNORMAL;
171 sp->seglen = ti->ti_scsp.seglen = 0; /* XXX */
174 /**********************************************
176 **********************************************/
177 static u_int8_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
179 /* common dma settings */
181 #define DMA1_SMSK (0x15)
183 #define DMA1_MODE (0x17)
185 #define DMA1_FFC (0x19)
187 #define DMA37SM_SET 0x04
189 #define DMA1_CHN(c) (0x01 + ((c) << 2))
193 struct bs_softc *bsc;
195 int chan = bsc->sc_dmachan;
197 u_int8_t *phys = bsc->sc_p.segaddr;
198 u_int nbytes = bsc->sc_p.seglen;
201 * Program one of DMA channels 0..3. These are
202 * byte mode channels.
204 /* set dma channel mode, and reset address ff */
205 #if defined(__DragonFly__) || defined(__FreeBSD__)
206 if (need_pre_dma_flush)
208 #else /* NetBSD/pc98 */
209 if (bsc->sc_dmadir & BSHW_READ)
210 cpu_cf_preRead(curcpu);
212 cpu_cf_preWrite(curcpu);
215 if (bsc->sc_dmadir & BSHW_READ)
216 outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_WRITE | chan);
218 outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_READ | chan);
221 /* send start address */
222 waport = DMA1_CHN(chan);
223 outb(waport, (u_int) phys);
224 outb(waport, ((u_int) phys) >> 8);
225 outb(dmapageport[chan], ((u_int) phys) >> 16);
228 outb(waport + 2, --nbytes);
229 outb(waport + 2, nbytes >> 8);
231 /* vendor unique hook */
232 if (bsc->sc_hw->dma_start)
233 (*bsc->sc_hw->dma_start)(bsc);
235 outb(DMA1_SMSK, chan);
236 BUS_IOW(cmd_port, CMDP_DMES);
238 bsc->sc_flags |= BSDMASTART;
243 struct bs_softc *bsc;
246 outb(DMA1_SMSK, (bsc->sc_dmachan | DMA37SM_SET));
247 BUS_IOW(cmd_port, CMDP_DMER);
249 /* vendor unique hook */
250 if (bsc->sc_hw->dma_stop)
251 (*bsc->sc_hw->dma_stop)(bsc);
253 #if defined(__DragonFly__) || defined(__FreeBSD__)
254 if (need_post_dma_flush)
257 if (bsc->sc_dmadir & BSHW_READ)
258 cpu_cf_postRead(curcpu);
260 cpu_cf_postWrite(curcpu);
263 bsc->sc_flags &= (~BSDMASTART);
266 /**********************************************
267 * VENDOR UNIQUE DMA FUNCS
268 **********************************************/
270 bshw_dma_init_texa(bsc)
271 struct bs_softc *bsc;
275 if ((regval = read_wd33c93(bsc, 0x37)) & 0x08)
278 write_wd33c93(bsc, 0x37, regval | 0x08);
279 regval = read_wd33c93(bsc, 0x3f);
280 write_wd33c93(bsc, 0x3f, regval | 0x08);
285 bshw_dma_init_sc98(bsc)
286 struct bs_softc *bsc;
289 if (read_wd33c93(bsc, 0x37) & 0x08)
292 /* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
293 write_wd33c93(bsc, 0x37, 0x1a);
294 write_wd33c93(bsc, 0x3f, 0x1a);
296 /* only valid for IO */
297 write_wd33c93(bsc, 0x40, 0xf4);
298 write_wd33c93(bsc, 0x41, 0x9);
299 write_wd33c93(bsc, 0x43, 0xff);
300 write_wd33c93(bsc, 0x46, 0x4e);
302 write_wd33c93(bsc, 0x48, 0xf4);
303 write_wd33c93(bsc, 0x49, 0x9);
304 write_wd33c93(bsc, 0x4b, 0xff);
305 write_wd33c93(bsc, 0x4e, 0x4e);
311 bshw_dma_start_sc98(bsc)
312 struct bs_softc *bsc;
315 write_wd33c93(bsc, 0x73, 0x32);
316 write_wd33c93(bsc, 0x74, 0x23);
320 bshw_dma_stop_sc98(bsc)
321 struct bs_softc *bsc;
324 write_wd33c93(bsc, 0x73, 0x43);
325 write_wd33c93(bsc, 0x74, 0x34);
329 bshw_dma_start_elecom(bsc)
330 struct bs_softc *bsc;
332 u_int8_t tmp = read_wd33c93(bsc, 0x4c);
334 write_wd33c93(bsc, 0x32, tmp & 0xdf);
338 bshw_dma_stop_elecom(bsc)
339 struct bs_softc *bsc;
341 u_int8_t tmp = read_wd33c93(bsc, 0x4c);
343 write_wd33c93(bsc, 0x32, tmp | 0x20);