xref: /openbsd/sys/arch/hppa/hppa/mainbus.c (revision 688f69f0)
1 /*	$OpenBSD: mainbus.c,v 1.91 2024/02/07 20:32:54 miod Exp $	*/
2 
3 /*
4  * Copyright (c) 1998-2004 Michael Shalayeff
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "lcd.h"
30 #include "power.h"
31 
32 #undef BTLBDEBUG
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/device.h>
38 #include <sys/reboot.h>
39 #include <sys/extent.h>
40 #include <sys/mbuf.h>
41 
42 #include <uvm/uvm_extern.h>
43 
44 #include <machine/bus.h>
45 #include <machine/pdc.h>
46 #include <machine/iomod.h>
47 #include <machine/autoconf.h>
48 
49 #include <hppa/dev/cpudevs.h>
50 
51 struct mainbus_softc {
52 	struct  device sc_dv;
53 
54 	hppa_hpa_t sc_hpa;
55 };
56 
57 int	mbmatch(struct device *, void *, void *);
58 void	mbattach(struct device *, struct device *, void *);
59 
60 const struct cfattach mainbus_ca = {
61 	sizeof(struct mainbus_softc), mbmatch, mbattach
62 };
63 
64 struct cfdriver mainbus_cd = {
65 	NULL, "mainbus", DV_DULL
66 };
67 
68 struct pdc_hpa pdc_hpa PDC_ALIGNMENT;
69 struct pdc_power_info pdc_power_info PDC_ALIGNMENT;
70 struct pdc_chassis_info pdc_chassis_info PDC_ALIGNMENT;
71 struct pdc_chassis_lcd pdc_chassis_lcd PDC_ALIGNMENT;
72 
73 /* from machdep.c */
74 extern struct extent *hppa_ex;
75 extern struct pdc_btlb pdc_btlb;
76 
77 int		 mbus_add_mapping(bus_addr_t bpa, bus_size_t size, int flags,
78 		    bus_space_handle_t *bshp);
79 int		 mbus_map(void *v, bus_addr_t bpa, bus_size_t size,
80 		    int flags, bus_space_handle_t *bshp);
81 void		 mbus_unmap(void *v, bus_space_handle_t bsh, bus_size_t size);
82 int		 mbus_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
83 		    bus_size_t size, bus_size_t align, bus_size_t boundary,
84 		    int flags, bus_addr_t *addrp, bus_space_handle_t *bshp);
85 void		 mbus_free(void *v, bus_space_handle_t h, bus_size_t size);
86 int		 mbus_subregion(void *v, bus_space_handle_t bsh,
87 		    bus_size_t offset, bus_size_t size,
88 		    bus_space_handle_t *nbshp);
89 void		 mbus_barrier(void *v, bus_space_handle_t h, bus_size_t o,
90 		    bus_size_t l, int op);
91 void		*mbus_vaddr(void *v, bus_space_handle_t h);
92 u_int8_t	 mbus_r1(void *v, bus_space_handle_t h, bus_size_t o);
93 u_int16_t	 mbus_r2(void *v, bus_space_handle_t h, bus_size_t o);
94 u_int32_t	 mbus_r4(void *v, bus_space_handle_t h, bus_size_t o);
95 u_int64_t	 mbus_r8(void *v, bus_space_handle_t h, bus_size_t o);
96 void		 mbus_w1(void *v, bus_space_handle_t h, bus_size_t o,
97 		    u_int8_t vv);
98 void		 mbus_w2(void *v, bus_space_handle_t h, bus_size_t o,
99 		    u_int16_t vv);
100 void		 mbus_w4(void *v, bus_space_handle_t h, bus_size_t o,
101 		    u_int32_t vv);
102 void		 mbus_w8(void *v, bus_space_handle_t h, bus_size_t o,
103 		    u_int64_t vv);
104 void		 mbus_rm_1(void *v, bus_space_handle_t h, bus_size_t o,
105 		    u_int8_t *a, bus_size_t c);
106 void		 mbus_rm_2(void *v, bus_space_handle_t h, bus_size_t o,
107 		    u_int16_t *a, bus_size_t c);
108 void		 mbus_rm_4(void *v, bus_space_handle_t h, bus_size_t o,
109 		    u_int32_t *a, bus_size_t c);
110 void		 mbus_rm_8(void *v, bus_space_handle_t h, bus_size_t o,
111 		    u_int64_t *a, bus_size_t c);
112 void		 mbus_wm_1(void *v, bus_space_handle_t h, bus_size_t o,
113 		    const u_int8_t *a, bus_size_t c);
114 void		 mbus_wm_2(void *v, bus_space_handle_t h, bus_size_t o,
115 		    const u_int16_t *a, bus_size_t c);
116 void		 mbus_wm_4(void *v, bus_space_handle_t h, bus_size_t o,
117 		    const u_int32_t *a, bus_size_t c);
118 void		 mbus_wm_8(void *v, bus_space_handle_t h, bus_size_t o,
119 		    const u_int64_t *a, bus_size_t c);
120 void		 mbus_sm_1(void *v, bus_space_handle_t h, bus_size_t o,
121 		    u_int8_t vv, bus_size_t c);
122 void		 mbus_sm_2(void *v, bus_space_handle_t h, bus_size_t o,
123 		    u_int16_t vv, bus_size_t c);
124 void		 mbus_sm_4(void *v, bus_space_handle_t h, bus_size_t o,
125 		    u_int32_t vv, bus_size_t c);
126 void		 mbus_sm_8(void *v, bus_space_handle_t h, bus_size_t o,
127 		    u_int64_t vv, bus_size_t c);
128 
129 void		 mbus_rr_1(void *v, bus_space_handle_t h, bus_size_t o,
130 		    u_int8_t *a, bus_size_t c);
131 void		 mbus_rr_2(void *v, bus_space_handle_t h, bus_size_t o,
132 		    u_int16_t *a, bus_size_t c);
133 void		 mbus_rr_4(void *v, bus_space_handle_t h, bus_size_t o,
134 		    u_int32_t *a, bus_size_t c);
135 void		 mbus_rr_8(void *v, bus_space_handle_t h, bus_size_t o,
136 		    u_int64_t *a, bus_size_t c);
137 void		 mbus_wr_1(void *v, bus_space_handle_t h, bus_size_t o,
138 		    const u_int8_t *a, bus_size_t c);
139 void		 mbus_wr_2(void *v, bus_space_handle_t h, bus_size_t o,
140 		    const u_int16_t *a, bus_size_t c);
141 void		 mbus_wr_4(void *v, bus_space_handle_t h, bus_size_t o,
142 		    const u_int32_t *a, bus_size_t c);
143 void		 mbus_wr_8(void *v, bus_space_handle_t h, bus_size_t o,
144 		    const u_int64_t *a, bus_size_t c);
145 void		 mbus_sr_1(void *v, bus_space_handle_t h, bus_size_t o,
146 		    u_int8_t vv, bus_size_t c);
147 void		 mbus_sr_2(void *v, bus_space_handle_t h, bus_size_t o,
148 		    u_int16_t vv, bus_size_t c);
149 void		 mbus_sr_4(void *v, bus_space_handle_t h, bus_size_t o,
150 		    u_int32_t vv, bus_size_t c);
151 void		 mbus_sr_8(void *v, bus_space_handle_t h, bus_size_t o,
152 		    u_int64_t vv, bus_size_t c);
153 void		 mbus_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
154 		    bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
155 void		 mbus_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
156 		    bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
157 void		 mbus_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
158 		    bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
159 void		 mbus_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
160 		    bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
161 
162 int
mbus_add_mapping(bus_addr_t bpa,bus_size_t size,int flags,bus_space_handle_t * bshp)163 mbus_add_mapping(bus_addr_t bpa, bus_size_t size, int flags,
164     bus_space_handle_t *bshp)
165 {
166 	static u_int32_t bmm[0x4000/32];
167 	int bank, off, flex;
168 	vaddr_t pa, spa, epa;
169 	vsize_t len;
170 
171 #ifdef BTLBDEBUG
172 	printf("bus_mem_add_mapping(%lx,%lx,%scachable,%p)\n",
173 	    bpa, size, flags? "" : "non", bshp);
174 #endif
175 
176 	if ((bank = vm_physseg_find(atop(bpa), &off)) >= 0)
177 		panic("mbus_add_mapping: mapping real memory @0x%lx", bpa);
178 
179 #ifdef DEBUG
180 	if (flags & BUS_SPACE_MAP_CACHEABLE) {
181 		printf("WARNING: mapping I/O space cacheable\n");
182 		flags &= ~BUS_SPACE_MAP_CACHEABLE;
183 	}
184 #endif
185 
186 	/*
187 	 * Mappings are established in HPPA_FLEX_SIZE units,
188 	 * either with BTLB, or regular mappings of the whole area.
189 	 */
190 	pa = bpa;
191 	while (size != 0) {
192 		flex = HPPA_FLEX(pa);
193 		spa = pa & HPPA_FLEX_MASK;
194 		epa = spa + HPPA_FLEX_SIZE; /* may wrap to 0... */
195 
196 		size -= min(size, HPPA_FLEX_SIZE - (pa - spa));
197 
198 		/* do need a new mapping? */
199 		if (!(bmm[flex / 32] & (1U << (flex % 32)))) {
200 #ifdef BTLBDEBUG
201 			printf("bus_mem_add_mapping: adding flex=%x "
202 			    "%lx-%lx, ", flex, spa, epa - 1);
203 #endif
204 			while (spa != epa) {
205 				len = epa - spa;
206 
207 				/*
208 				 * Try to map with a BTLB first (might map
209 				 * much more than what we are requesting
210 				 * for, and cross HPPA_FLEX boundaries).
211 				 *
212 				 * Note that this code assumes that
213 				 * BTLB size are a power of two, so if
214 				 * the size is larger than HPPA_FLEX_SIZE
215 				 * it will span an integral number of
216 				 * HPPA_FLEX_SIZE slots.
217 				 */
218 				if (len > pdc_btlb.max_size << PGSHIFT)
219 					len = pdc_btlb.max_size << PGSHIFT;
220 
221 				if (btlb_insert(HPPA_SID_KERNEL, spa, spa, &len,
222 				    pmap_sid2pid(HPPA_SID_KERNEL) |
223 				    pmap_prot(pmap_kernel(), PROT_READ | PROT_WRITE))
224 				    >= 0) {
225 					pa = spa + len;	/* may wrap to 0... */
226 #ifdef BTLBDEBUG
227 					printf("--- %x/%lx, %lx-%lx ",
228 					    flex, HPPA_FLEX(pa - 1),
229 					    spa, pa - 1);
230 #endif
231 					/* register all ranges */
232 					for (; flex <= HPPA_FLEX(pa - 1);
233 					    flex++) {
234 #ifdef BTLBDEBUG
235 						printf("mask %x ", flex);
236 #endif
237 						bmm[flex / 32] |=
238 						    (1U << (flex % 32));
239 					}
240 					if (len > epa - spa)
241 						spa = epa;
242 					else
243 						spa = pa;
244 				} else {
245 #ifdef BTLBDEBUG
246 					printf("kenter 0x%lx-0x%lx", spa, epa);
247 #endif
248 					for (; spa != epa; spa += PAGE_SIZE)
249 						pmap_kenter_pa(spa, spa,
250 						    PROT_READ | PROT_WRITE);
251 				}
252 #ifdef BTLBDEBUG
253 				printf("\n");
254 #endif
255 			}
256 		}
257 #ifdef BTLBDEBUG
258 		else {
259 			printf("+++ already b-mapped flex=%x, mask=%x\n",
260 			    flex, bmm[flex / 32]);
261 		}
262 #endif
263 
264 		pa = epa;
265 	}
266 
267 	*bshp = bpa;
268 	return (0);
269 }
270 
271 int
mbus_map(void * v,bus_addr_t bpa,bus_size_t size,int flags,bus_space_handle_t * bshp)272 mbus_map(void *v, bus_addr_t bpa, bus_size_t size,
273     int flags, bus_space_handle_t *bshp)
274 {
275 	int error;
276 
277 	if ((error = extent_alloc_region(hppa_ex, bpa, size, EX_NOWAIT)))
278 		return (error);
279 
280 	if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
281 		if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
282 			printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
283 				bpa, size);
284 			printf("bus_space_map: can't free region\n");
285 		}
286 	}
287 
288 	return error;
289 }
290 
291 void
mbus_unmap(void * v,bus_space_handle_t bsh,bus_size_t size)292 mbus_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
293 {
294 	u_long sva, eva;
295 
296 	sva = trunc_page(bsh);
297 	eva = round_page(bsh + size);
298 
299 #ifdef DIAGNOSTIC
300 	if (eva <= sva)
301 		panic("bus_space_unmap: overflow");
302 #endif
303 
304 	if (pmap_extract(pmap_kernel(), bsh, NULL))
305 		pmap_kremove(sva, eva - sva);
306 	else
307 		;	/* XXX assuming equ b-mapping been done */
308 
309 	if (extent_free(hppa_ex, bsh, size, EX_NOWAIT)) {
310 		printf("bus_space_unmap: ps 0x%lx, size 0x%lx\n",
311 		    bsh, size);
312 		printf("bus_space_unmap: can't free region\n");
313 	}
314 }
315 
316 int
mbus_alloc(void * v,bus_addr_t rstart,bus_addr_t rend,bus_size_t size,bus_size_t align,bus_size_t boundary,int flags,bus_addr_t * addrp,bus_space_handle_t * bshp)317 mbus_alloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
318     bus_size_t align, bus_size_t boundary, int flags,
319     bus_addr_t *addrp, bus_space_handle_t *bshp)
320 {
321 	u_long bpa;
322 	int error;
323 
324 	if (rstart < hppa_ex->ex_start || rend > hppa_ex->ex_end)
325 		panic("bus_space_alloc: bad region start/end");
326 
327 	if ((error = extent_alloc_subregion(hppa_ex, rstart, rend, size,
328 	    align, 0, boundary, EX_NOWAIT, &bpa)))
329 		return (error);
330 
331 	if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
332 		if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
333 			printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
334 				bpa, size);
335 			printf("bus_space_alloc: can't free region\n");
336 		}
337 	}
338 
339 	*addrp = bpa;
340 	return (error);
341 }
342 
343 void
mbus_free(void * v,bus_space_handle_t h,bus_size_t size)344 mbus_free(void *v, bus_space_handle_t h, bus_size_t size)
345 {
346 	/* bus_space_unmap() does all that we need to do. */
347 	mbus_unmap(v, h, size);
348 }
349 
350 int
mbus_subregion(void * v,bus_space_handle_t bsh,bus_size_t offset,bus_size_t size,bus_space_handle_t * nbshp)351 mbus_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset,
352     bus_size_t size, bus_space_handle_t *nbshp)
353 {
354 	*nbshp = bsh + offset;
355 	return (0);
356 }
357 
358 void
mbus_barrier(void * v,bus_space_handle_t h,bus_size_t o,bus_size_t l,int op)359 mbus_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
360 {
361 	sync_caches();
362 }
363 
364 void *
mbus_vaddr(void * v,bus_space_handle_t h)365 mbus_vaddr(void *v, bus_space_handle_t h)
366 {
367 	return ((void *)h);
368 }
369 
370 u_int8_t
mbus_r1(void * v,bus_space_handle_t h,bus_size_t o)371 mbus_r1(void *v, bus_space_handle_t h, bus_size_t o)
372 {
373 	return *((volatile u_int8_t *)(h + o));
374 }
375 
376 u_int16_t
mbus_r2(void * v,bus_space_handle_t h,bus_size_t o)377 mbus_r2(void *v, bus_space_handle_t h, bus_size_t o)
378 {
379 	return *((volatile u_int16_t *)(h + o));
380 }
381 
382 u_int32_t
mbus_r4(void * v,bus_space_handle_t h,bus_size_t o)383 mbus_r4(void *v, bus_space_handle_t h, bus_size_t o)
384 {
385 	return *((volatile u_int32_t *)(h + o));
386 }
387 
388 u_int64_t
mbus_r8(void * v,bus_space_handle_t h,bus_size_t o)389 mbus_r8(void *v, bus_space_handle_t h, bus_size_t o)
390 {
391 	return *((volatile u_int64_t *)(h + o));
392 }
393 
394 void
mbus_w1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t vv)395 mbus_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv)
396 {
397 	*((volatile u_int8_t *)(h + o)) = vv;
398 }
399 
400 void
mbus_w2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t vv)401 mbus_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv)
402 {
403 	*((volatile u_int16_t *)(h + o)) = vv;
404 }
405 
406 void
mbus_w4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t vv)407 mbus_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv)
408 {
409 	*((volatile u_int32_t *)(h + o)) = vv;
410 }
411 
412 void
mbus_w8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t vv)413 mbus_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv)
414 {
415 	*((volatile u_int64_t *)(h + o)) = vv;
416 }
417 
418 
419 void
mbus_rm_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t * a,bus_size_t c)420 mbus_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
421 {
422 	h += o;
423 	while (c--)
424 		*(a++) = *(volatile u_int8_t *)h;
425 }
426 
427 void
mbus_rm_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t * a,bus_size_t c)428 mbus_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
429 {
430 	h += o;
431 	while (c--)
432 		*(a++) = *(volatile u_int16_t *)h;
433 }
434 
435 void
mbus_rm_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t * a,bus_size_t c)436 mbus_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
437 {
438 	h += o;
439 	while (c--)
440 		*(a++) = *(volatile u_int32_t *)h;
441 }
442 
443 void
mbus_rm_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t * a,bus_size_t c)444 mbus_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
445 {
446 	h += o;
447 	while (c--)
448 		*(a++) = *(volatile u_int64_t *)h;
449 }
450 
451 void
mbus_wm_1(void * v,bus_space_handle_t h,bus_size_t o,const u_int8_t * a,bus_size_t c)452 mbus_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
453 {
454 	h += o;
455 	while (c--)
456 		*(volatile u_int8_t *)h = *(a++);
457 }
458 
459 void
mbus_wm_2(void * v,bus_space_handle_t h,bus_size_t o,const u_int16_t * a,bus_size_t c)460 mbus_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
461 {
462 	h += o;
463 	while (c--)
464 		*(volatile u_int16_t *)h = *(a++);
465 }
466 
467 void
mbus_wm_4(void * v,bus_space_handle_t h,bus_size_t o,const u_int32_t * a,bus_size_t c)468 mbus_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
469 {
470 	h += o;
471 	while (c--)
472 		*(volatile u_int32_t *)h = *(a++);
473 }
474 
475 void
mbus_wm_8(void * v,bus_space_handle_t h,bus_size_t o,const u_int64_t * a,bus_size_t c)476 mbus_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
477 {
478 	h += o;
479 	while (c--)
480 		*(volatile u_int64_t *)h = *(a++);
481 }
482 
483 void
mbus_sm_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t vv,bus_size_t c)484 mbus_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
485 {
486 	h += o;
487 	while (c--)
488 		*(volatile u_int8_t *)h = vv;
489 }
490 
491 void
mbus_sm_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t vv,bus_size_t c)492 mbus_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
493 {
494 	h += o;
495 	while (c--)
496 		*(volatile u_int16_t *)h = vv;
497 }
498 
499 void
mbus_sm_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t vv,bus_size_t c)500 mbus_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
501 {
502 	h += o;
503 	while (c--)
504 		*(volatile u_int32_t *)h = vv;
505 }
506 
507 void
mbus_sm_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t vv,bus_size_t c)508 mbus_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
509 {
510 	h += o;
511 	while (c--)
512 		*(volatile u_int64_t *)h = vv;
513 }
514 
515 void
mbus_rr_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t * a,bus_size_t c)516 mbus_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
517 {
518 	volatile u_int8_t *p = (u_int8_t *)(h + o);
519 
520 	while (c--)
521 		*a++ = *p++;
522 }
523 
524 void
mbus_rr_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t * a,bus_size_t c)525 mbus_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
526 {
527 	volatile u_int16_t *p = (u_int16_t *)(h + o);
528 
529 	while (c--)
530 		*a++ = *p++;
531 }
532 
533 void
mbus_rr_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t * a,bus_size_t c)534 mbus_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
535 {
536 	volatile u_int32_t *p = (u_int32_t *)(h + o);
537 
538 	while (c--)
539 		*a++ = *p++;
540 }
541 
542 void
mbus_rr_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t * a,bus_size_t c)543 mbus_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
544 {
545 	volatile u_int64_t *p = (u_int64_t *)(h + o);
546 
547 	while (c--)
548 		*a++ = *p++;
549 }
550 
551 void
mbus_wr_1(void * v,bus_space_handle_t h,bus_size_t o,const u_int8_t * a,bus_size_t c)552 mbus_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
553 {
554 	volatile u_int8_t *p = (u_int8_t *)(h + o);
555 
556 	while (c--)
557 		*p++ = *a++;
558 }
559 
560 void
mbus_wr_2(void * v,bus_space_handle_t h,bus_size_t o,const u_int16_t * a,bus_size_t c)561 mbus_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
562 {
563 	volatile u_int16_t *p = (u_int16_t *)(h + o);
564 
565 	while (c--)
566 		*p++ = *a++;
567 }
568 
569 void
mbus_wr_4(void * v,bus_space_handle_t h,bus_size_t o,const u_int32_t * a,bus_size_t c)570 mbus_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
571 {
572 	volatile u_int32_t *p = (u_int32_t *)(h + o);
573 
574 	while (c--)
575 		*p++ = *a++;
576 }
577 
578 void
mbus_wr_8(void * v,bus_space_handle_t h,bus_size_t o,const u_int64_t * a,bus_size_t c)579 mbus_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
580 {
581 	volatile u_int64_t *p = (u_int64_t *)(h + o);
582 
583 	while (c--)
584 		*p++ = *a++;
585 }
586 
587 void
mbus_sr_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t vv,bus_size_t c)588 mbus_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
589 {
590 	volatile u_int8_t *p = (u_int8_t *)(h + o);
591 
592 	while (c--)
593 		*p++ = vv;
594 }
595 
596 void
mbus_sr_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t vv,bus_size_t c)597 mbus_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
598 {
599 	volatile u_int16_t *p = (u_int16_t *)(h + o);
600 
601 	while (c--)
602 		*p++ = vv;
603 }
604 
605 void
mbus_sr_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t vv,bus_size_t c)606 mbus_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
607 {
608 	volatile u_int32_t *p = (u_int32_t *)(h + o);
609 
610 	while (c--)
611 		*p++ = vv;
612 }
613 
614 void
mbus_sr_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t vv,bus_size_t c)615 mbus_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
616 {
617 	volatile u_int64_t *p = (u_int64_t *)(h + o);
618 
619 	while (c--)
620 		*p++ = vv;
621 }
622 
623 void
mbus_cp_1(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)624 mbus_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
625 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
626 {
627 	volatile u_int8_t *p1 = (u_int8_t *)(h1 + o1);
628 	volatile u_int8_t *p2 = (u_int8_t *)(h2 + o2);
629 
630 	while (c--)
631 		*p1++ = *p2++;
632 }
633 
634 void
mbus_cp_2(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)635 mbus_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
636 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
637 {
638 	volatile u_int16_t *p1 = (u_int16_t *)(h1 + o1);
639 	volatile u_int16_t *p2 = (u_int16_t *)(h2 + o2);
640 
641 	while (c--)
642 		*p1++ = *p2++;
643 }
644 
645 void
mbus_cp_4(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)646 mbus_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
647 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
648 {
649 	volatile u_int32_t *p1 = (u_int32_t *)(h1 + o1);
650 	volatile u_int32_t *p2 = (u_int32_t *)(h2 + o2);
651 
652 	while (c--)
653 		*p1++ = *p2++;
654 }
655 
656 void
mbus_cp_8(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)657 mbus_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
658 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
659 {
660 	volatile u_int64_t *p1 = (u_int64_t *)(h1 + o1);
661 	volatile u_int64_t *p2 = (u_int64_t *)(h2 + o2);
662 
663 	while (c--)
664 		*p1++ = *p2++;
665 }
666 
667 
668 /* ugly typecast macro */
669 #define	crr(n)	((void (*)(void *, bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t))(n))
670 #define	cwr(n)	((void (*)(void *, bus_space_handle_t, bus_size_t, const u_int8_t *, bus_size_t))(n))
671 
672 const struct hppa_bus_space_tag hppa_bustag = {
673 	NULL,
674 
675 	mbus_map, mbus_unmap, mbus_subregion, mbus_alloc, mbus_free,
676 	mbus_barrier, mbus_vaddr,
677 	mbus_r1,    mbus_r2,   mbus_r4,   mbus_r8,
678 	mbus_w1,    mbus_w2,   mbus_w4,   mbus_w8,
679 	mbus_rm_1,  mbus_rm_2, mbus_rm_4, mbus_rm_8,
680 	mbus_wm_1,  mbus_wm_2, mbus_wm_4, mbus_wm_8,
681 	mbus_sm_1,  mbus_sm_2, mbus_sm_4, mbus_sm_8,
682 	/* *_raw_* are the same as non-raw for native busses */
683 	            crr(mbus_rm_1), crr(mbus_rm_1), crr(mbus_rm_1),
684 	            cwr(mbus_wm_1), cwr(mbus_wm_1), cwr(mbus_wm_1),
685 	mbus_rr_1,  mbus_rr_2, mbus_rr_4, mbus_rr_8,
686 	mbus_wr_1,  mbus_wr_2, mbus_wr_4, mbus_wr_8,
687 	/* *_raw_* are the same as non-raw for native busses */
688 	            crr(mbus_rr_1), crr(mbus_rr_1), crr(mbus_rr_1),
689 	            cwr(mbus_wr_1), cwr(mbus_wr_1), cwr(mbus_wr_1),
690 	mbus_sr_1,  mbus_sr_2, mbus_sr_4, mbus_sr_8,
691 	mbus_cp_1,  mbus_cp_2, mbus_cp_4, mbus_cp_8
692 };
693 
694 int		 mbus_dmamap_create(void *v, bus_size_t size, int nsegments,
695 		   bus_size_t maxsegsz, bus_size_t boundary, int flags,
696 		   bus_dmamap_t *dmamp);
697 void		 mbus_dmamap_unload(void *v, bus_dmamap_t map);
698 void		 mbus_dmamap_destroy(void *v, bus_dmamap_t map);
699 int		 _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map,
700 		    void *buf, bus_size_t buflen, struct proc *p, int flags,
701 		    paddr_t *lastaddrp, int *segp, int first);
702 int		 mbus_dmamap_load(void *v, bus_dmamap_t map, void *addr,
703 		    bus_size_t size, struct proc *p, int flags);
704 int		 mbus_dmamap_load_mbuf(void *v, bus_dmamap_t map,
705 		    struct mbuf *m0, int flags);
706 int		 mbus_dmamap_load_uio(void *v, bus_dmamap_t map,
707 		    struct uio *uio, int flags);
708 int		 mbus_dmamap_load_raw(void *v, bus_dmamap_t map,
709 		    bus_dma_segment_t *segs, int nsegs, bus_size_t size,
710 		    int flags);
711 void		 mbus_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
712 		    bus_size_t len, int ops);
713 int		 mbus_dmamem_alloc(void *v, bus_size_t size,
714 		    bus_size_t alignment, bus_size_t boundary,
715 		    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
716 void		 mbus_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs);
717 int		 mbus_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs,
718 		    size_t size, caddr_t *kvap, int flags);
719 void		 mbus_dmamem_unmap(void *v, caddr_t kva, size_t size);
720 paddr_t		 mbus_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs,
721 		    off_t off, int prot, int flags);
722 
723 int
mbus_dmamap_create(void * v,bus_size_t size,int nsegments,bus_size_t maxsegsz,bus_size_t boundary,int flags,bus_dmamap_t * dmamp)724 mbus_dmamap_create(void *v, bus_size_t size, int nsegments,
725 		   bus_size_t maxsegsz, bus_size_t boundary, int flags,
726 		   bus_dmamap_t *dmamp)
727 {
728 	struct hppa_bus_dmamap *map;
729 	size_t mapsize;
730 
731 	mapsize = sizeof(struct hppa_bus_dmamap) +
732 	    (sizeof(bus_dma_segment_t) * (nsegments - 1));
733 	map = malloc(mapsize, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ?
734 	    (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO));
735 	if (!map)
736 		return (ENOMEM);
737 
738 	map->_dm_size = size;
739 	map->_dm_segcnt = nsegments;
740 	map->_dm_maxsegsz = maxsegsz;
741 	map->_dm_boundary = boundary;
742 	map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
743 	map->dm_mapsize = 0;
744 	map->dm_nsegs = 0;
745 
746 	*dmamp = map;
747 	return (0);
748 }
749 
750 void
mbus_dmamap_unload(void * v,bus_dmamap_t map)751 mbus_dmamap_unload(void *v, bus_dmamap_t map)
752 {
753 	map->dm_mapsize = 0;
754 	map->dm_nsegs = 0;
755 }
756 
757 void
mbus_dmamap_destroy(void * v,bus_dmamap_t map)758 mbus_dmamap_destroy(void *v, bus_dmamap_t map)
759 {
760 	if (map->dm_mapsize != 0)
761 		mbus_dmamap_unload(v, map);
762 
763 	free(map, M_DEVBUF, 0);
764 }
765 
766 /*
767  * Utility function to load a linear buffer.  lastaddrp holds state
768  * between invocations (for multiple-buffer loads).  segp contains
769  * the starting segment on entrance, and the ending segment on exit.
770  * first indicates if this is the first invocation of this function.
771  */
772 int
_bus_dmamap_load_buffer(bus_dma_tag_t t,bus_dmamap_t map,void * buf,bus_size_t buflen,struct proc * p,int flags,paddr_t * lastaddrp,int * segp,int first)773 _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
774     bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp,
775     int *segp, int first)
776 {
777 	bus_size_t sgsize;
778 	bus_addr_t curaddr, lastaddr, baddr, bmask;
779 	vaddr_t vaddr = (vaddr_t)buf;
780 	int seg;
781 	pmap_t pmap;
782 
783 	pmap = p? p->p_vmspace->vm_map.pmap : pmap_kernel();
784 	lastaddr = *lastaddrp;
785 	bmask  = ~(map->_dm_boundary - 1);
786 
787 	for (seg = *segp; buflen > 0 ; ) {
788 		/*
789 		 * Get the physical address for this segment.
790 		 */
791 		pmap_extract(pmap, vaddr, (paddr_t *)&curaddr);
792 
793 		/*
794 		 * Compute the segment size, and adjust counts.
795 		 */
796 		sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
797 		if (buflen < sgsize)
798 			sgsize = buflen;
799 
800 		/*
801 		 * Make sure we don't cross any boundaries.
802 		 */
803 		if (map->_dm_boundary > 0) {
804 			baddr = (curaddr + map->_dm_boundary) & bmask;
805 			if (sgsize > (baddr - curaddr))
806 				sgsize = (baddr - curaddr);
807 		}
808 
809 		/*
810 		 * Insert chunk into a segment, coalescing with
811 		 * previous segment if possible.
812 		 */
813 		if (first) {
814 			map->dm_segs[seg].ds_addr = curaddr;
815 			map->dm_segs[seg].ds_len = sgsize;
816 			map->dm_segs[seg]._ds_va = vaddr;
817 			first = 0;
818 		} else {
819 			if (curaddr == lastaddr &&
820 			    (map->dm_segs[seg].ds_len + sgsize) <=
821 			     map->_dm_maxsegsz &&
822 			    (map->_dm_boundary == 0 ||
823 			     (map->dm_segs[seg].ds_addr & bmask) ==
824 			     (curaddr & bmask)))
825 				map->dm_segs[seg].ds_len += sgsize;
826 			else {
827 				if (++seg >= map->_dm_segcnt)
828 					break;
829 				map->dm_segs[seg].ds_addr = curaddr;
830 				map->dm_segs[seg].ds_len = sgsize;
831 				map->dm_segs[seg]._ds_va = vaddr;
832 			}
833 		}
834 
835 		lastaddr = curaddr + sgsize;
836 		vaddr += sgsize;
837 		buflen -= sgsize;
838 	}
839 
840 	*segp = seg;
841 	*lastaddrp = lastaddr;
842 
843 	/*
844 	 * Did we fit?
845 	 */
846 	if (buflen != 0)
847 		return (EFBIG);		/* XXX better return value here? */
848 	return (0);
849 }
850 
851 int
mbus_dmamap_load(void * v,bus_dmamap_t map,void * addr,bus_size_t size,struct proc * p,int flags)852 mbus_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
853 		 struct proc *p, int flags)
854 {
855 	paddr_t lastaddr;
856 	int seg, error;
857 
858 	/*
859 	 * Make sure that on error condition we return "no valid mappings".
860 	 */
861 	map->dm_nsegs = 0;
862 	map->dm_mapsize = 0;
863 
864 	if (size > map->_dm_size)
865 		return (EINVAL);
866 
867 	seg = 0;
868 	lastaddr = 0;
869 	error = _bus_dmamap_load_buffer(NULL, map, addr, size, p, flags,
870 	    &lastaddr, &seg, 1);
871 	if (error == 0) {
872 		map->dm_mapsize = size;
873 		map->dm_nsegs = seg + 1;
874 	}
875 
876 	return (0);
877 }
878 
879 int
mbus_dmamap_load_mbuf(void * v,bus_dmamap_t map,struct mbuf * m0,int flags)880 mbus_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m0, int flags)
881 {
882 	paddr_t lastaddr;
883 	int seg, error, first;
884 	struct mbuf *m;
885 
886 	map->dm_mapsize = 0;
887 	map->dm_nsegs = 0;
888 
889 #ifdef DIAGNOSTIC
890 	if ((m0->m_flags & M_PKTHDR) == 0)
891 		panic("_bus_dmamap_load_mbuf: no packet header");
892 #endif
893 
894 	if (m0->m_pkthdr.len > map->_dm_size)
895 		return (EINVAL);
896 
897 	first = 1;
898 	seg = 0;
899 	error = 0;
900 	lastaddr = 0;
901 	for (m = m0; m != NULL && error == 0; m = m->m_next) {
902 		if (m->m_len == 0)
903 			continue;
904 		error = _bus_dmamap_load_buffer(NULL, map, m->m_data, m->m_len,
905 		    NULL, flags, &lastaddr, &seg, first);
906 		first = 0;
907 	}
908 	if (error == 0) {
909 		map->dm_mapsize = m0->m_pkthdr.len;
910 		map->dm_nsegs = seg + 1;
911 	}
912 
913 	return (error);
914 }
915 
916 int
mbus_dmamap_load_uio(void * v,bus_dmamap_t map,struct uio * uio,int flags)917 mbus_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
918 {
919 	paddr_t lastaddr;
920 	int seg, i, error, first;
921 	bus_size_t minlen, resid;
922 	struct proc *p = NULL;
923 	struct iovec *iov;
924 	caddr_t addr;
925 
926 	/*
927 	 * Make sure that on error condition we return "no valid mappings".
928 	 */
929 	map->dm_mapsize = 0;
930 	map->dm_nsegs = 0;
931 
932 	resid = uio->uio_resid;
933 	iov = uio->uio_iov;
934 
935 	if (resid > map->_dm_size)
936 		return (EINVAL);
937 
938 	if (uio->uio_segflg == UIO_USERSPACE) {
939 		p = uio->uio_procp;
940 #ifdef DIAGNOSTIC
941 		if (p == NULL)
942 			panic("_bus_dmamap_load_uio: USERSPACE but no proc");
943 #endif
944 	}
945 
946 	first = 1;
947 	seg = 0;
948 	error = 0;
949 	lastaddr = 0;
950 	for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
951 		/*
952 		 * Now at the first iovec to load.  Load each iovec
953 		 * until we have exhausted the residual count.
954 		 */
955 		minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
956 		addr = (caddr_t)iov[i].iov_base;
957 
958 		error = _bus_dmamap_load_buffer(NULL, map, addr, minlen,
959 		    p, flags, &lastaddr, &seg, first);
960 		first = 0;
961 
962 		resid -= minlen;
963 	}
964 	if (error == 0) {
965 		map->dm_mapsize = uio->uio_resid;
966 		map->dm_nsegs = seg + 1;
967 	}
968 	return (error);
969 }
970 
971 int
mbus_dmamap_load_raw(void * v,bus_dmamap_t map,bus_dma_segment_t * segs,int nsegs,bus_size_t size,int flags)972 mbus_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
973     int nsegs, bus_size_t size, int flags)
974 {
975 	if (nsegs > map->_dm_segcnt || size > map->_dm_size)
976 		return (EINVAL);
977 
978 	/*
979 	 * Make sure we don't cross any boundaries.
980 	 */
981 	if (map->_dm_boundary) {
982 		bus_addr_t bmask = ~(map->_dm_boundary - 1);
983 		int i;
984 
985 		for (i = 0; i < nsegs; i++) {
986 			if (segs[i].ds_len > map->_dm_maxsegsz)
987 				return (EINVAL);
988 			if ((segs[i].ds_addr & bmask) !=
989 			    ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask))
990 				return (EINVAL);
991 		}
992 	}
993 
994 	bcopy(segs, map->dm_segs, nsegs * sizeof(*segs));
995 	map->dm_nsegs = nsegs;
996 	map->dm_mapsize = size;
997 	return (0);
998 }
999 
1000 void
mbus_dmamap_sync(void * v,bus_dmamap_t map,bus_addr_t off,bus_size_t len,int ops)1001 mbus_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, bus_size_t len,
1002     int ops)
1003 {
1004 	bus_dma_segment_t *ps = map->dm_segs,
1005 	    *es = &map->dm_segs[map->dm_nsegs];
1006 
1007 	if (off >= map->_dm_size)
1008 		return;
1009 
1010 	if ((off + len) > map->_dm_size)
1011 		len = map->_dm_size - off;
1012 
1013 	for (; len && ps < es; ps++)
1014 		if (off > ps->ds_len)
1015 			off -= ps->ds_len;
1016 		else {
1017 			bus_size_t l = ps->ds_len - off;
1018 			if (l > len)
1019 				l = len;
1020 			fdcache(HPPA_SID_KERNEL, ps->_ds_va + off, l);
1021 			len -= l;
1022 			off = 0;
1023 		}
1024 
1025 	/* for either operation sync the shit away */
1026 	__asm volatile ("sync\n\tsyncdma\n\tsync\n\t"
1027 	    "nop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop");
1028 }
1029 
1030 int
mbus_dmamem_alloc(void * v,bus_size_t size,bus_size_t alignment,bus_size_t boundary,bus_dma_segment_t * segs,int nsegs,int * rsegs,int flags)1031 mbus_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
1032 		  bus_size_t boundary, bus_dma_segment_t *segs, int nsegs,
1033 		  int *rsegs, int flags)
1034 {
1035 	struct pglist pglist;
1036 	struct vm_page *pg;
1037 	int plaflag;
1038 
1039 	size = round_page(size);
1040 
1041 	plaflag = flags & BUS_DMA_NOWAIT ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK;
1042 	if (flags & BUS_DMA_ZERO)
1043 		plaflag |= UVM_PLA_ZERO;
1044 
1045 	TAILQ_INIT(&pglist);
1046 	if (uvm_pglistalloc(size, 0, -1, alignment, boundary,
1047 	    &pglist, 1, plaflag))
1048 		return (ENOMEM);
1049 
1050 	pg = TAILQ_FIRST(&pglist);
1051 	segs[0]._ds_va = segs[0].ds_addr = VM_PAGE_TO_PHYS(pg);
1052 	segs[0].ds_len = size;
1053 	*rsegs = 1;
1054 
1055 	for(; pg; pg = TAILQ_NEXT(pg, pageq))
1056 		/* XXX for now */
1057 		pmap_changebit(pg, PTE_PROT(TLB_UNCACHABLE), 0);
1058 	pmap_update(pmap_kernel());
1059 
1060 	return (0);
1061 }
1062 
1063 void
mbus_dmamem_free(void * v,bus_dma_segment_t * segs,int nsegs)1064 mbus_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
1065 {
1066 	struct pglist pglist;
1067 	paddr_t pa, epa;
1068 
1069 	TAILQ_INIT(&pglist);
1070 	for(; nsegs--; segs++)
1071 		for (pa = segs->ds_addr, epa = pa + segs->ds_len;
1072 		     pa < epa; pa += PAGE_SIZE) {
1073 			struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
1074 			if (!pg)
1075 				panic("mbus_dmamem_free: no page for pa");
1076 			TAILQ_INSERT_TAIL(&pglist, pg, pageq);
1077 			pdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
1078 			pdtlb(HPPA_SID_KERNEL, pa);
1079 			pitlb(HPPA_SID_KERNEL, pa);
1080 		}
1081 	uvm_pglistfree(&pglist);
1082 }
1083 
1084 int
mbus_dmamem_map(void * v,bus_dma_segment_t * segs,int nsegs,size_t size,caddr_t * kvap,int flags)1085 mbus_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
1086 		caddr_t *kvap, int flags)
1087 {
1088 	*kvap = (caddr_t)segs[0].ds_addr;
1089 	return 0;
1090 }
1091 
1092 void
mbus_dmamem_unmap(void * v,caddr_t kva,size_t size)1093 mbus_dmamem_unmap(void *v, caddr_t kva, size_t size)
1094 {
1095 }
1096 
1097 paddr_t
mbus_dmamem_mmap(void * v,bus_dma_segment_t * segs,int nsegs,off_t off,int prot,int flags)1098 mbus_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
1099 		 int prot, int flags)
1100 {
1101 	panic("_dmamem_mmap: not implemented");
1102 }
1103 
1104 const struct hppa_bus_dma_tag hppa_dmatag = {
1105 	NULL,
1106 	mbus_dmamap_create, mbus_dmamap_destroy,
1107 	mbus_dmamap_load, mbus_dmamap_load_mbuf,
1108 	mbus_dmamap_load_uio, mbus_dmamap_load_raw,
1109 	mbus_dmamap_unload, mbus_dmamap_sync,
1110 
1111 	mbus_dmamem_alloc, mbus_dmamem_free, mbus_dmamem_map,
1112 	mbus_dmamem_unmap, mbus_dmamem_mmap
1113 };
1114 
1115 int
mbmatch(parent,cfdata,aux)1116 mbmatch(parent, cfdata, aux)
1117 	struct device *parent;
1118 	void *cfdata;
1119 	void *aux;
1120 {
1121 	struct cfdata *cf = cfdata;
1122 
1123 	/* there will be only one */
1124 	if (cf->cf_unit)
1125 		return 0;
1126 
1127 	return 1;
1128 }
1129 
1130 void
mbattach(parent,self,aux)1131 mbattach(parent, self, aux)
1132 	struct device *parent;
1133 	struct device *self;
1134 	void *aux;
1135 {
1136 	struct mainbus_softc *sc = (struct mainbus_softc *)self;
1137 	struct confargs nca;
1138 	bus_space_handle_t ioh;
1139 
1140 	/* fetch the "default" cpu hpa */
1141 	if (pdc_call((iodcio_t)pdc, 0, PDC_HPA, PDC_HPA_DFLT, &pdc_hpa) < 0)
1142 		panic("mbattach: PDC_HPA failed");
1143 
1144 	printf(" [flex %x]\n", pdc_hpa.hpa & HPPA_FLEX_MASK);
1145 
1146 	/* map all the way till the end of the memory */
1147 	if (bus_space_map(&hppa_bustag, pdc_hpa.hpa,
1148 	    (~0LU - pdc_hpa.hpa + 1), 0, &ioh))
1149 		panic("mbattach: cannot map mainbus IO space");
1150 
1151 	/*
1152 	 * Local-Broadcast the HPA to all modules on this bus
1153 	 */
1154 	((struct iomod *)HPPA_LBCAST)->io_flex =
1155 	    (pdc_hpa.hpa & HPPA_FLEX_MASK) | DMA_ENABLE;
1156 
1157 	sc->sc_hpa = pdc_hpa.hpa;
1158 
1159 	/* PDC first */
1160 	bzero(&nca, sizeof(nca));
1161 	nca.ca_name = "pdc";
1162 	nca.ca_iot = &hppa_bustag;
1163 	nca.ca_dmatag = &hppa_dmatag;
1164 	config_found(self, &nca, mbprint);
1165 
1166 #if NPOWER > 0
1167 	/* get some power */
1168 	bzero(&nca, sizeof(nca));
1169 	nca.ca_name = "power";
1170 	nca.ca_irq = -1;
1171 	if (!pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER,
1172 	    PDC_SOFT_POWER_INFO, &pdc_power_info, 0)) {
1173 		nca.ca_iot = &hppa_bustag;
1174 		nca.ca_hpa = pdc_power_info.addr;
1175 		nca.ca_hpamask = HPPA_IOBEGIN;
1176 	}
1177 	config_found(self, &nca, mbprint);
1178 #endif
1179 
1180 #if NLCD > 0
1181 	if (!pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_INFO,
1182 	    &pdc_chassis_info, &pdc_chassis_lcd, sizeof(pdc_chassis_lcd)) &&
1183 	    pdc_chassis_lcd.enabled) {
1184 		bzero(&nca, sizeof(nca));
1185 		nca.ca_name = "lcd";
1186 		nca.ca_irq = -1;
1187 		nca.ca_iot = &hppa_bustag;
1188 		nca.ca_hpa = pdc_chassis_lcd.cmd_addr;
1189 		nca.ca_hpamask = HPPA_IOBEGIN;
1190 		nca.ca_pdc_iodc_read = (void *)&pdc_chassis_lcd;
1191 
1192 		config_found(self, &nca, mbprint);
1193 	}
1194 #endif
1195 
1196 	bzero(&nca, sizeof(nca));
1197 	nca.ca_hpa = 0;
1198 	nca.ca_irq = -1;
1199 	nca.ca_hpamask = HPPA_IOBEGIN;
1200 	nca.ca_iot = &hppa_bustag;
1201 	nca.ca_dmatag = &hppa_dmatag;
1202 	nca.ca_dp.dp_bc[0] = nca.ca_dp.dp_bc[1] = nca.ca_dp.dp_bc[2] =
1203 	nca.ca_dp.dp_bc[3] = nca.ca_dp.dp_bc[4] = nca.ca_dp.dp_bc[5] = -1;
1204 	nca.ca_dp.dp_mod = -1;
1205 	switch (cpu_hvers) {
1206 	case HPPA_BOARD_HP809:
1207 	case HPPA_BOARD_HP819:
1208 	case HPPA_BOARD_HP829:
1209 	case HPPA_BOARD_HP839:
1210 	case HPPA_BOARD_HP849:
1211 	case HPPA_BOARD_HP859:
1212 	case HPPA_BOARD_HP869:
1213 #if 0
1214 	case HPPA_BOARD_HP770_J200:
1215 	case HPPA_BOARD_HP770_J210:
1216 	case HPPA_BOARD_HP770_J210XC:
1217 	case HPPA_BOARD_HP780_J282:
1218 	case HPPA_BOARD_HP782_J2240:
1219 #endif
1220 	case HPPA_BOARD_HP780_C160:
1221 	case HPPA_BOARD_HP780_C180P:
1222 	case HPPA_BOARD_HP780_C180XP:
1223 	case HPPA_BOARD_HP780_C200:
1224 	case HPPA_BOARD_HP780_C230:
1225 	case HPPA_BOARD_HP780_C240:
1226 	case HPPA_BOARD_HP785_C360:
1227 		/* Attach CPUs first, then everything else... */
1228 		ncpusfound = 0;
1229 		pdc_scanbus(self, &nca, MAXMODBUS, HPPA_FPA, 1);
1230 		pdc_scanbus(self, &nca, MAXMODBUS, HPPA_FPA, 0);
1231 	break;
1232 	default:
1233 		/* Attach CPUs first, then everything else... */
1234 		ncpusfound = 0;
1235 		pdc_scanbus(self, &nca, MAXMODBUS, 0, 1);
1236 		pdc_scanbus(self, &nca, MAXMODBUS, 0, 0);
1237 	}
1238 }
1239 
1240 /*
1241  * Retrieve CPU #N HPA value
1242  */
1243 hppa_hpa_t
cpu_gethpa(n)1244 cpu_gethpa(n)
1245 	int n;
1246 {
1247 	struct mainbus_softc *sc;
1248 
1249 	sc = mainbus_cd.cd_devs[0];
1250 
1251 	return sc->sc_hpa;
1252 }
1253 
1254 int
mbprint(aux,pnp)1255 mbprint(aux, pnp)
1256 	void *aux;
1257 	const char *pnp;
1258 {
1259 	struct confargs *ca = aux;
1260 
1261 	if (pnp)
1262 		printf("\"%s\" at %s (type %x sv %x mod %x hv %x)",
1263 		    ca->ca_name, pnp,
1264 		    ca->ca_type.iodc_type, ca->ca_type.iodc_sv_model,
1265 		    ca->ca_type.iodc_model, ca->ca_type.iodc_revision);
1266 	if (ca->ca_hpa) {
1267 		if (~ca->ca_hpamask)
1268 			printf(" offset %lx", ca->ca_hpa & ~ca->ca_hpamask);
1269 		if (!pnp && ca->ca_irq >= 0)
1270 			printf(" irq %d", ca->ca_irq);
1271 	}
1272 
1273 	return (UNCONF);
1274 }
1275 
1276 int
mbsubmatch(parent,match,aux)1277 mbsubmatch(parent, match, aux)
1278 	struct device *parent;
1279 	void *match, *aux;
1280 {
1281 	struct cfdata *cf = match;
1282 	struct confargs *ca = aux;
1283 	int ret;
1284 
1285 	if (autoconf_verbose)
1286 		printf(">> hpa %lx off %lx cf_off %lx\n",
1287 		    ca->ca_hpa, ca->ca_hpa & ~ca->ca_hpamask, cf->hppacf_off);
1288 
1289 	if (ca->ca_hpa && ~ca->ca_hpamask && cf->hppacf_off != -1 &&
1290 	    ((ca->ca_hpa & ~ca->ca_hpamask) != cf->hppacf_off))
1291 		return (0);
1292 
1293 	if ((ret = (*cf->cf_attach->ca_match)(parent, match, aux)))
1294 		ca->ca_irq = cf->hppacf_irq;
1295 
1296 	return ret;
1297 }
1298 
1299