1*58d5cf8aSderaadt /* $OpenBSD: dbdma.c,v 1.11 2015/09/08 08:29:35 deraadt Exp $ */
2d9a5f17fSdrahn /* $NetBSD: dbdma.c,v 1.2 1998/08/21 16:13:28 tsubai Exp $ */
3d9a5f17fSdrahn
4d9a5f17fSdrahn /*
5d9a5f17fSdrahn * Copyright 1991-1998 by Open Software Foundation, Inc.
6d9a5f17fSdrahn * All Rights Reserved
7d9a5f17fSdrahn *
8d9a5f17fSdrahn * Permission to use, copy, modify, and distribute this software and
9d9a5f17fSdrahn * its documentation for any purpose and without fee is hereby granted,
10d9a5f17fSdrahn * provided that the above copyright notice appears in all copies and
11d9a5f17fSdrahn * that both the copyright notice and this permission notice appear in
12d9a5f17fSdrahn * supporting documentation.
13d9a5f17fSdrahn *
14d9a5f17fSdrahn * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
15d9a5f17fSdrahn * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
16d9a5f17fSdrahn * FOR A PARTICULAR PURPOSE.
17d9a5f17fSdrahn *
18d9a5f17fSdrahn * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
19d9a5f17fSdrahn * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20d9a5f17fSdrahn * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
21d9a5f17fSdrahn * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
22d9a5f17fSdrahn * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23d9a5f17fSdrahn *
24d9a5f17fSdrahn */
25d9a5f17fSdrahn
26d9a5f17fSdrahn #include <sys/param.h>
27d9a5f17fSdrahn #include <sys/malloc.h>
28d9a5f17fSdrahn #include <sys/systm.h>
29d9a5f17fSdrahn
30489e49f9Smiod #include <uvm/uvm_extern.h>
31d9a5f17fSdrahn
32e6d856e8Smickey #include <machine/bus.h>
3378a7e9fcSdrahn #include <macppc/dev/dbdma.h>
34d9a5f17fSdrahn
35d9a5f17fSdrahn dbdma_command_t *dbdma_alloc_commands = NULL;
36d9a5f17fSdrahn
37d9a5f17fSdrahn void
dbdma_start(dbdma_regmap_t * dmap,dbdma_t dt)38093da1aaSdrahn dbdma_start(dbdma_regmap_t *dmap, dbdma_t dt)
39d9a5f17fSdrahn {
40e6d856e8Smickey u_int32_t addr = dt->d_paddr;
41d9a5f17fSdrahn
42d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_intselect, DBDMA_CLEAR_CNTRL((0xffff)));
43e6d856e8Smickey DBDMA_ST4_ENDIAN(&dmap->d_control, DBDMA_CLEAR_CNTRL((
446a1aaa0fSderaadt DBDMA_CNTRL_ACTIVE |
456a1aaa0fSderaadt DBDMA_CNTRL_DEAD |
466a1aaa0fSderaadt DBDMA_CNTRL_WAKE |
476a1aaa0fSderaadt DBDMA_CNTRL_FLUSH |
486a1aaa0fSderaadt DBDMA_CNTRL_PAUSE |
496a1aaa0fSderaadt DBDMA_CNTRL_RUN)));
50d9a5f17fSdrahn
51e6d856e8Smickey /* XXX time-bind it? */
52d9a5f17fSdrahn do {
53d9a5f17fSdrahn delay(10);
54d9a5f17fSdrahn } while (DBDMA_LD4_ENDIAN(&dmap->d_status) & DBDMA_CNTRL_ACTIVE);
55d9a5f17fSdrahn
56d9a5f17fSdrahn
57d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_cmdptrhi, 0); /* 64-bit not yet */
58d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_cmdptrlo, addr);
59d9a5f17fSdrahn
60d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_control,
61d9a5f17fSdrahn DBDMA_SET_CNTRL(DBDMA_CNTRL_RUN|DBDMA_CNTRL_WAKE)|
62d9a5f17fSdrahn DBDMA_CLEAR_CNTRL(DBDMA_CNTRL_PAUSE|DBDMA_CNTRL_DEAD) );
63d9a5f17fSdrahn }
64d9a5f17fSdrahn
65d9a5f17fSdrahn void
dbdma_stop(dbdma_regmap_t * dmap)66093da1aaSdrahn dbdma_stop(dbdma_regmap_t *dmap)
67d9a5f17fSdrahn {
68d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_control, DBDMA_CLEAR_CNTRL(DBDMA_CNTRL_RUN) |
69d9a5f17fSdrahn DBDMA_SET_CNTRL(DBDMA_CNTRL_FLUSH));
70d9a5f17fSdrahn
71d9a5f17fSdrahn while (DBDMA_LD4_ENDIAN(&dmap->d_status) &
726a1aaa0fSderaadt (DBDMA_CNTRL_ACTIVE|DBDMA_CNTRL_FLUSH));
73d9a5f17fSdrahn }
74d9a5f17fSdrahn
75d9a5f17fSdrahn void
dbdma_flush(dbdma_regmap_t * dmap)76093da1aaSdrahn dbdma_flush(dbdma_regmap_t *dmap)
77d9a5f17fSdrahn {
78d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_control, DBDMA_SET_CNTRL(DBDMA_CNTRL_FLUSH));
79d9a5f17fSdrahn
80e6d856e8Smickey /* XXX time-bind it? */
816a1aaa0fSderaadt while (DBDMA_LD4_ENDIAN(&dmap->d_status) & (DBDMA_CNTRL_FLUSH));
82d9a5f17fSdrahn }
83d9a5f17fSdrahn
84d9a5f17fSdrahn void
dbdma_reset(dbdma_regmap_t * dmap)85093da1aaSdrahn dbdma_reset(dbdma_regmap_t *dmap)
86d9a5f17fSdrahn {
87d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_control,
88d9a5f17fSdrahn DBDMA_CLEAR_CNTRL( (DBDMA_CNTRL_ACTIVE |
896a1aaa0fSderaadt DBDMA_CNTRL_DEAD |
906a1aaa0fSderaadt DBDMA_CNTRL_WAKE |
916a1aaa0fSderaadt DBDMA_CNTRL_FLUSH |
926a1aaa0fSderaadt DBDMA_CNTRL_PAUSE |
93d9a5f17fSdrahn DBDMA_CNTRL_RUN )));
94d9a5f17fSdrahn
95e6d856e8Smickey /* XXX time-bind it? */
966a1aaa0fSderaadt while (DBDMA_LD4_ENDIAN(&dmap->d_status) & DBDMA_CNTRL_RUN);
97d9a5f17fSdrahn }
98d9a5f17fSdrahn
99d9a5f17fSdrahn void
dbdma_continue(dbdma_regmap_t * dmap)100093da1aaSdrahn dbdma_continue(dbdma_regmap_t *dmap)
101d9a5f17fSdrahn {
102d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_control,
103d9a5f17fSdrahn DBDMA_SET_CNTRL(DBDMA_CNTRL_RUN | DBDMA_CNTRL_WAKE) |
104d9a5f17fSdrahn DBDMA_CLEAR_CNTRL(DBDMA_CNTRL_PAUSE | DBDMA_CNTRL_DEAD));
105d9a5f17fSdrahn }
106d9a5f17fSdrahn
107d9a5f17fSdrahn void
dbdma_pause(dbdma_regmap_t * dmap)108093da1aaSdrahn dbdma_pause(dbdma_regmap_t *dmap)
109d9a5f17fSdrahn {
110d9a5f17fSdrahn DBDMA_ST4_ENDIAN(&dmap->d_control,DBDMA_SET_CNTRL(DBDMA_CNTRL_PAUSE));
111d9a5f17fSdrahn
112e6d856e8Smickey /* XXX time-bind it? */
1136a1aaa0fSderaadt while (DBDMA_LD4_ENDIAN(&dmap->d_status) & DBDMA_CNTRL_ACTIVE);
114d9a5f17fSdrahn }
115d9a5f17fSdrahn
116e6d856e8Smickey dbdma_t
dbdma_alloc(bus_dma_tag_t dmat,int size)117093da1aaSdrahn dbdma_alloc(bus_dma_tag_t dmat, int size)
118d9a5f17fSdrahn {
119e6d856e8Smickey dbdma_t dt;
120fe1b9aebSmiod int error;
121d9a5f17fSdrahn
122bc9397c2Skrw dt = malloc(sizeof *dt, M_DEVBUF, M_NOWAIT | M_ZERO);
123e6d856e8Smickey if (!dt)
124e6d856e8Smickey return (dt);
125d9a5f17fSdrahn
126e6d856e8Smickey dt->d_size = size *= sizeof(dbdma_command_t);
127fe1b9aebSmiod dt->d_dmat = dmat;
128e6d856e8Smickey if ((error = bus_dmamem_alloc(dmat, size, NBPG, 0, dt->d_segs,
129fe1b9aebSmiod 1, &dt->d_nsegs, BUS_DMA_NOWAIT)) != 0) {
130e6d856e8Smickey printf("dbdma: unable to allocate dma, error = %d\n", error);
131fe1b9aebSmiod } else if ((error = bus_dmamem_map(dmat, dt->d_segs, dt->d_nsegs, size,
132e6d856e8Smickey (caddr_t *)&dt->d_addr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
133e6d856e8Smickey printf("dbdma: unable to map dma, error = %d\n", error);
134e6d856e8Smickey } else if ((error = bus_dmamap_create(dmat, dt->d_size, 1,
135e6d856e8Smickey dt->d_size, 0, BUS_DMA_NOWAIT, &dt->d_map)) != 0) {
136e6d856e8Smickey printf("dbdma: unable to create dma map, error = %d\n", error);
137e6d856e8Smickey } else if ((error = bus_dmamap_load_raw(dmat, dt->d_map,
138fe1b9aebSmiod dt->d_segs, dt->d_nsegs, size, BUS_DMA_NOWAIT)) != 0) {
139e6d856e8Smickey printf("dbdma: unable to load dma map, error = %d\n", error);
140e6d856e8Smickey } else
141e6d856e8Smickey return dt;
142e6d856e8Smickey
143fe1b9aebSmiod dbdma_free(dt);
144e6d856e8Smickey return (NULL);
145d9a5f17fSdrahn }
146fe1b9aebSmiod
147fe1b9aebSmiod void
dbdma_free(dbdma_t dt)148fe1b9aebSmiod dbdma_free(dbdma_t dt)
149fe1b9aebSmiod {
150fe1b9aebSmiod if (dt->d_map)
151fe1b9aebSmiod bus_dmamap_destroy(dt->d_dmat, dt->d_map);
152fe1b9aebSmiod if (dt->d_addr)
153fe1b9aebSmiod bus_dmamem_unmap(dt->d_dmat, (caddr_t)dt->d_addr, dt->d_size);
154fe1b9aebSmiod if (dt->d_nsegs)
155fe1b9aebSmiod bus_dmamem_free(dt->d_dmat, dt->d_segs, dt->d_nsegs);
156*58d5cf8aSderaadt free(dt, M_DEVBUF, sizeof *dt);
157fe1b9aebSmiod }
158