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