xref: /openbsd-src/sys/arch/macppc/dev/dbdma.c (revision 58d5cf8a7dc00f4d357918db94831564cfaa56aa)
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