xref: /netbsd-src/sys/arch/sgimips/hpc/hpcdma.c (revision 27578b9aac214cc7796ead81dcc5427e79d5f2a0)
1 /*	$NetBSD: hpcdma.c,v 1.1 2001/08/19 03:16:21 wdk Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 Wayne Knowles
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Wayne Knowles
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/device.h>
42 #include <sys/buf.h>
43 
44 #include <machine/bus.h>
45 
46 #include <sgimips/hpc/hpcvar.h>
47 #include <sgimips/hpc/hpcreg.h>
48 #include <sgimips/hpc/hpcdma.h>
49 
50 /*
51  * Allocate DMA Chain descriptor list
52  *
53  * XXX:  Need to place in device tree
54  */
55 void
56 hpcdma_init(haa, sc, ndesc)
57 	struct hpc_attach_args *haa;
58 	struct hpc_dma_softc *sc;
59 	int	ndesc;
60 {
61 	bus_dma_segment_t seg;
62 	struct hpc_dma_desc *hdd;
63 	int rseg, allocsz;
64 
65 	sc->sc_bst = haa->ha_iot;
66 	sc->sc_bsh = haa->ha_ioh;
67 	sc->sc_dmat = haa->ha_dmat;
68 	sc->sc_ndesc = ndesc;
69 	sc->sc_flags = 0;
70 
71 	/* Alloc 1 additional descriptor - needed for DMA bug fix */
72 	allocsz = sizeof(struct hpc_dma_desc) * (ndesc + 1);
73 	KASSERT(allocsz <= NBPG);
74 
75 	if (bus_dmamap_create(sc->sc_dmat, NBPG, 1 /*seg*/,
76 			      NBPG, 0, BUS_DMA_WAITOK,
77 			      &sc->sc_dmamap) != 0) {
78 		printf(": failed to create dmamap\n");
79 		return;
80 	}
81 
82 	/*
83 	 * Allocate a block of memory for dma chaining pointers
84 	 */
85 	if (bus_dmamem_alloc(sc->sc_dmat, allocsz, 0, 0,
86 			     &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
87 		printf(": can't allocate sglist\n");
88 		return;
89 	}
90 	/* Map pages into kernel memory */
91 	if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, allocsz,
92 			   (caddr_t *)&hdd, BUS_DMA_NOWAIT)) {
93 		printf(": can't map sglist\n");
94 		bus_dmamem_free(sc->sc_dmat, &seg, rseg);
95 		return;
96 	}
97 
98 	if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, hdd,
99 			    allocsz, NULL, BUS_DMA_NOWAIT)) {
100 		printf(": can't load sglist\n");
101 		return;
102 	}
103 
104 	sc->sc_desc_kva = hdd;
105 	sc->sc_desc_pa = (void *) sc->sc_dmamap->dm_segs[0].ds_addr;
106 }
107 
108 
109 void
110 hpcdma_sglist_create(sc, dmamap)
111 	struct hpc_dma_softc *sc;
112 	bus_dmamap_t   dmamap;
113 {
114 	struct hpc_dma_desc *hva, *hpa;
115 	bus_dma_segment_t   *segp;
116 	int i;
117 
118 	KASSERT(dmamap->dm_nsegs <= sc->sc_ndesc);
119 
120 	hva  = sc->sc_desc_kva;
121 	hpa  = sc->sc_desc_pa;
122 	segp = dmamap->dm_segs;
123 
124 #ifdef DMA_DEBUG
125 	printf("DMA_SGLIST<");
126 #endif
127 	for (i = dmamap->dm_nsegs; i; i--) {
128 #ifdef DMA_DEBUG
129 		printf("%p:%ld, ", (void *)segp->ds_addr, segp->ds_len);
130 #endif
131 		hva->hdd_bufptr = segp->ds_addr;
132 		hva->hdd_ctl    = segp->ds_len;
133 		hva->hdd_descptr = (u_int32_t) ++hpa;
134 		++hva; ++segp;
135 	}
136 	/* Work around HPC3 DMA bug */
137 	hva->hdd_bufptr  = 0;
138 	hva->hdd_ctl     = HDD_CTL_EOCHAIN;
139 	hva->hdd_descptr = 0;
140 	hva++;
141 #ifdef DMA_DEBUG
142 	printf(">\n");
143 #endif
144 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap,
145 	    0, sc->sc_dmamap->dm_mapsize,
146 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
147 
148 	/* Load DMA Descriptor list */
149 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, HPC_SCSI0_NDBP,
150 			    (u_int32_t)sc->sc_desc_pa);
151 }
152 
153 void
154 hpcdma_cntl(sc, mode)
155 	struct hpc_dma_softc *sc;
156 	u_int32_t	mode;
157 {
158 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, HPC_SCSI0_CTL, mode);
159 }
160 
161 void
162 hpcdma_flush(sc)
163 	struct hpc_dma_softc *sc;
164 {
165 	u_int32_t	mode;
166 
167 	mode = bus_space_read_4(sc->sc_bst, sc->sc_bsh, HPC_SCSI0_CTL);
168 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, HPC_SCSI0_CTL,
169 	    			mode | HPC_DMACTL_FLUSH);
170 
171 	/* Wait for Active bit to drop */
172 	while (bus_space_read_4(sc->sc_bst, sc->sc_bsh, HPC_SCSI0_CTL) &
173 	    HPC_DMACTL_ACTIVE) {
174 		bus_space_barrier(sc->sc_bst, sc->sc_bsh, HPC_SCSI0_CTL, 4,
175 		    BUS_SPACE_BARRIER_READ);
176 	}
177 }
178