apbus.c revision 1.3 1 /* $NetBSD: apbus.c,v 1.3 2000/10/12 03:11:38 onoe Exp $ */
2
3 /*-
4 * Copyright (C) 1999 SHIMIZU Ryo. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/malloc.h>
32 #include <sys/device.h>
33
34 #include <machine/adrsmap.h>
35 #include <machine/autoconf.h>
36 #define _NEWSMIPS_BUS_DMA_PRIVATE
37 #include <machine/bus.h>
38 #include <newsmips/apbus/apbusvar.h>
39
40 static int apbusmatch __P((struct device *, struct cfdata *, void *));
41 static void apbusattach __P((struct device *, struct device *, void *));
42 static int apbusprint __P((void *, const char *));
43 /* static void *aptokseg0 __P((void *)); */
44
45 #define MAXAPDEVNUM 32
46
47 struct apbus_softc {
48 struct device apbs_dev;
49 };
50
51 struct cfattach ap_ca = {
52 sizeof(struct apbus_softc), apbusmatch, apbusattach
53 };
54
55 #define APBUS_DEVNAMELEN 16
56
57 struct ap_intrhand {
58 struct ap_intrhand *ai_next;
59 int ai_mask;
60 int ai_priority;
61 int (*ai_func) __P((void*)); /* function */
62 void *ai_aux; /* softc */
63 char ai_name[APBUS_DEVNAMELEN];
64 int ai_ctlno;
65 };
66
67 #define NLEVEL 2
68
69 static struct ap_intrhand *apintr[NLEVEL];
70
71 static int
72 apbusmatch(parent, cfdata, aux)
73 struct device *parent;
74 struct cfdata *cfdata;
75 void *aux;
76 {
77 struct confargs *ca = aux;
78
79 if (strcmp(ca->ca_name, "ap") != 0)
80 return 0;
81
82 return 1;
83 }
84
85
86 static void
87 apbusattach(parent, self, aux)
88 struct device *parent;
89 struct device *self;
90 void *aux;
91 {
92 struct apbus_attach_args child;
93 struct apbus_dev *apdev;
94 struct apbus_ctl *apctl;
95
96 *(volatile u_int *)(NEWS5000_APBUS_INTST) = 0xffffffff;
97 *(volatile u_int *)(NEWS5000_APBUS_INTMSK) = 0xffffffff;
98 *(volatile u_int *)(NEWS5000_APBUS_CTRL) = 0x00000004;
99 *(volatile u_int *)(NEWS5000_APBUS_DMA) = 0xffffffff;
100
101 printf("\n");
102
103 /*
104 * get first ap-device
105 */
106 apdev = apbus_lookupdev(NULL);
107
108 /*
109 * trace device chain
110 */
111 while (apdev) {
112 apctl = apdev->apbd_ctl;
113
114 /*
115 * probe physical device only
116 * (no pseudo device)
117 */
118 if (apctl && apctl->apbc_hwbase) {
119 /*
120 * ... and, all units
121 */
122 while (apctl) {
123 /* make apbus_attach_args for devices */
124 child.apa_name = apdev->apbd_name;
125 child.apa_ctlnum = apctl->apbc_ctlno;
126 child.apa_slotno = apctl->apbc_sl;
127 child.apa_hwbase = apctl->apbc_hwbase;
128
129 config_found(self, &child, apbusprint);
130
131 apctl = apctl->apbc_link;
132 }
133 }
134
135 apdev = apdev->apbd_link;
136 }
137 }
138
139 int
140 apbusprint(aux, pnp)
141 void *aux;
142 const char *pnp;
143 {
144 struct apbus_attach_args *a = aux;
145
146 if (pnp)
147 printf("%s at %s slot%d addr 0x%lx",
148 a->apa_name, pnp, a->apa_slotno, a->apa_hwbase);
149
150 return UNCONF;
151 }
152
153 #if 0
154 void *
155 aptokseg0(va)
156 void *va;
157 {
158 vaddr_t addr = (vaddr_t)va;
159
160 if (addr >= 0xfff00000) {
161 addr -= 0xfff00000;
162 addr += physmem << PGSHIFT;
163 addr += 0x80000000;
164 va = (void *)addr;
165 }
166 return va;
167 }
168 #endif
169
170 void
171 apbus_wbflush()
172 {
173 volatile int *wbflush = (int *)NEWS5000_WBFLUSH;
174
175 (void)*wbflush;
176 }
177
178 /*
179 * called by hardware interrupt routine
180 */
181 int
182 apbus_intr_call(level, stat)
183 int level;
184 int stat;
185 {
186 int nintr = 0;
187 struct ap_intrhand *ai;
188
189 for (ai = apintr[level]; ai != NULL; ai = ai->ai_next) {
190 if (ai->ai_mask & stat) {
191 nintr += (*ai->ai_func)(ai->ai_aux);
192 }
193 }
194 return nintr;
195 }
196
197 /*
198 * register device interrupt routine
199 */
200 void *
201 apbus_intr_establish(level, mask, priority, func, aux, name, ctlno)
202 int level;
203 int mask;
204 int priority;
205 int (*func) __P((void *));
206 void *aux;
207 char *name;
208 int ctlno;
209 {
210 struct ap_intrhand *ai, **aip;
211 volatile unsigned int *inten0 = (volatile unsigned int *)NEWS5000_INTEN0;
212 volatile unsigned int *inten1 = (volatile unsigned int *)NEWS5000_INTEN1;
213
214 ai = malloc(sizeof(*ai), M_DEVBUF, M_NOWAIT);
215 if (ai == NULL)
216 panic("apbus_intr_establish: can't malloc handler info");
217 ai->ai_mask = mask;
218 ai->ai_priority = priority;
219 ai->ai_func = func;
220 ai->ai_aux = aux;
221 strncpy(ai->ai_name, name, APBUS_DEVNAMELEN-1);
222 ai->ai_ctlno = ctlno;
223
224 for (aip = &apintr[level]; *aip != NULL; aip = &(*aip)->ai_next) {
225 if ((*aip)->ai_priority < priority)
226 break;
227 }
228 ai->ai_next = *aip;
229 *aip = ai;
230 switch (level) {
231 case 0:
232 *inten0 |= mask;
233 break;
234 case 1:
235 *inten1 |= mask;
236 break;
237 }
238
239 return (void *)ai;
240 }
241
242 void
243 apbus_dmamap_sync(t, map, offset, len, ops)
244 bus_dma_tag_t t;
245 bus_dmamap_t map;
246 bus_addr_t offset;
247 bus_size_t len;
248 int ops;
249 {
250
251 /*
252 * Flush DMA cache by issueing IO read for the AProm of specified slot.
253 */
254 bus_space_read_4(t->_slotbaset, t->_slotbaseh, 0);
255
256 _bus_dmamap_sync(t, map, offset, len, ops);
257 }
258
259 struct newsmips_bus_dma_tag apbus_dma_tag = {
260 _bus_dmamap_create,
261 _bus_dmamap_destroy,
262 _bus_dmamap_load,
263 _bus_dmamap_load_mbuf,
264 _bus_dmamap_load_uio,
265 _bus_dmamap_load_raw,
266 _bus_dmamap_unload,
267 apbus_dmamap_sync,
268 _bus_dmamem_alloc,
269 _bus_dmamem_free,
270 _bus_dmamem_map,
271 _bus_dmamem_unmap,
272 _bus_dmamem_mmap,
273 };
274
275 struct newsmips_bus_dma_tag *
276 apbus_dmatag_init(apa)
277 struct apbus_attach_args *apa;
278 {
279 struct newsmips_bus_dma_tag *dmat;
280
281 dmat = malloc(sizeof(*dmat), M_DEVBUF, M_NOWAIT);
282 if (dmat != NULL) {
283 memcpy(dmat, &apbus_dma_tag, sizeof(*dmat));
284 dmat->_slotno = apa->apa_slotno;
285 dmat->_slotbaset = 0;
286 dmat->_slotbaseh = apa->apa_hwbase;
287 }
288 return dmat;
289 }
290