1 /* $NetBSD: bus_space_alignstride_chipdep.c,v 1.4 2002/08/19 12:03:48 simonb Exp $ */
2 
3 /*-
4  * Copyright (c) 1998, 2000, 2001 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
42  * All rights reserved.
43  *
44  * Author: Chris G. Demetriou
45  *
46  * Permission to use, copy, modify and distribute this software and
47  * its documentation is hereby granted, provided that both the copyright
48  * notice and this permission notice appear in all copies of the
49  * software, derivative works or modified versions, and any portions
50  * thereof, and that both notices appear in supporting documentation.
51  *
52  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
53  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
54  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
55  *
56  * Carnegie Mellon requests users of this software to return to
57  *
58  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
59  *  School of Computer Science
60  *  Carnegie Mellon University
61  *  Pittsburgh PA 15213-3890
62  *
63  * any improvements or extensions that they make and grant Carnegie the
64  * rights to redistribute these changes.
65  */
66 
67 /*
68  * Common Chipset "bus I/O" functions.
69  *
70  * uses:
71  *	CHIP		name of the 'chip' it's being compiled for.
72  *	CHIP_BASE	memory or I/O space base to use.
73  *	CHIP_EX_STORE
74  *			If defined, device-provided static storage area
75  *			for the memory or I/O space extent.  If this is
76  *			defined, CHIP_EX_STORE_SIZE must also be defined.
77  *			If this is not defined, a static area will be
78  *			declared.
79  *	CHIP_EX_STORE_SIZE
80  *			Size of the device-provided static storage area
81  *			for the memory or I/O memory space extent.
82  */
83 
84 #ifdef CHIP_EXTENT
85 #include <sys/extent.h>
86 #endif
87 #include <sys/malloc.h>
88 
89 #include <machine/locore.h>
90 
91 #include <uvm/uvm_extern.h>
92 
93 #define	__C(A,B)	__CONCAT(A,B)
94 #define	__S(S)		__STRING(S)
95 
96 #ifdef CHIP_IO
97 #define	__BS(A)		__C(__C(CHIP,_bus_io_),A)
98 #endif
99 #ifdef CHIP_MEM
100 #define	__BS(A)		__C(__C(CHIP,_bus_mem_),A)
101 #endif
102 
103 /* mapping/unmapping */
104 int		__BS(map)(void *, bus_addr_t, bus_size_t, int,
105 		    bus_space_handle_t *, int);
106 void		__BS(unmap)(void *, bus_space_handle_t, bus_size_t, int);
107 int		__BS(subregion)(void *, bus_space_handle_t, bus_size_t,
108 		    bus_size_t, bus_space_handle_t *);
109 
110 int		__BS(translate)(void *, bus_addr_t, bus_size_t, int,
111 		    struct mips_bus_space_translation *);
112 int		__BS(get_window)(void *, int,
113 		    struct mips_bus_space_translation *);
114 
115 /* allocation/deallocation */
116 int		__BS(alloc)(void *, bus_addr_t, bus_addr_t, bus_size_t,
117 		    bus_size_t, bus_addr_t, int, bus_addr_t *,
118 		    bus_space_handle_t *);
119 void		__BS(free)(void *, bus_space_handle_t, bus_size_t);
120 
121 /* get kernel virtual address */
122 void *		__BS(vaddr)(void *, bus_space_handle_t);
123 
124 /* mmap for user */
125 paddr_t		__BS(mmap)(void *, bus_addr_t, off_t, int, int);
126 
127 /* barrier */
128 inline void	__BS(barrier)(void *, bus_space_handle_t, bus_size_t,
129 		    bus_size_t, int);
130 
131 /* read (single) */
132 inline uint8_t	__BS(read_1)(void *, bus_space_handle_t, bus_size_t);
133 inline uint16_t	__BS(read_2)(void *, bus_space_handle_t, bus_size_t);
134 inline uint32_t	__BS(read_4)(void *, bus_space_handle_t, bus_size_t);
135 inline uint64_t	__BS(read_8)(void *, bus_space_handle_t, bus_size_t);
136 
137 /* read multiple */
138 void		__BS(read_multi_1)(void *, bus_space_handle_t, bus_size_t,
139 		    uint8_t *, bus_size_t);
140 void		__BS(read_multi_2)(void *, bus_space_handle_t, bus_size_t,
141 		    uint16_t *, bus_size_t);
142 void		__BS(read_multi_4)(void *, bus_space_handle_t, bus_size_t,
143 		    uint32_t *, bus_size_t);
144 void		__BS(read_multi_8)(void *, bus_space_handle_t, bus_size_t,
145 		    uint64_t *, bus_size_t);
146 
147 /* read region */
148 void		__BS(read_region_1)(void *, bus_space_handle_t, bus_size_t,
149 		    uint8_t *, bus_size_t);
150 void		__BS(read_region_2)(void *, bus_space_handle_t, bus_size_t,
151 		    uint16_t *, bus_size_t);
152 void		__BS(read_region_4)(void *, bus_space_handle_t, bus_size_t,
153 		    uint32_t *, bus_size_t);
154 void		__BS(read_region_8)(void *, bus_space_handle_t, bus_size_t,
155 		    uint64_t *, bus_size_t);
156 
157 /* write (single) */
158 inline void	__BS(write_1)(void *, bus_space_handle_t, bus_size_t, uint8_t);
159 inline void	__BS(write_2)(void *, bus_space_handle_t, bus_size_t, uint16_t);
160 inline void	__BS(write_4)(void *, bus_space_handle_t, bus_size_t, uint32_t);
161 inline void	__BS(write_8)(void *, bus_space_handle_t, bus_size_t, uint64_t);
162 
163 /* write multiple */
164 void		__BS(write_multi_1)(void *, bus_space_handle_t, bus_size_t,
165 		    const uint8_t *, bus_size_t);
166 void		__BS(write_multi_2)(void *, bus_space_handle_t, bus_size_t,
167 		    const uint16_t *, bus_size_t);
168 void		__BS(write_multi_4)(void *, bus_space_handle_t, bus_size_t,
169 		    const uint32_t *, bus_size_t);
170 void		__BS(write_multi_8)(void *, bus_space_handle_t, bus_size_t,
171 		    const uint64_t *, bus_size_t);
172 
173 /* write region */
174 void		__BS(write_region_1)(void *, bus_space_handle_t, bus_size_t,
175 		    const uint8_t *, bus_size_t);
176 void		__BS(write_region_2)(void *, bus_space_handle_t, bus_size_t,
177 		    const uint16_t *, bus_size_t);
178 void		__BS(write_region_4)(void *, bus_space_handle_t, bus_size_t,
179 		    const uint32_t *, bus_size_t);
180 void		__BS(write_region_8)(void *, bus_space_handle_t, bus_size_t,
181 		    const uint64_t *, bus_size_t);
182 
183 /* set multiple */
184 void		__BS(set_multi_1)(void *, bus_space_handle_t, bus_size_t,
185 		    uint8_t, bus_size_t);
186 void		__BS(set_multi_2)(void *, bus_space_handle_t, bus_size_t,
187 		    uint16_t, bus_size_t);
188 void		__BS(set_multi_4)(void *, bus_space_handle_t, bus_size_t,
189 		    uint32_t, bus_size_t);
190 void		__BS(set_multi_8)(void *, bus_space_handle_t, bus_size_t,
191 		    uint64_t, bus_size_t);
192 
193 /* set region */
194 void		__BS(set_region_1)(void *, bus_space_handle_t, bus_size_t,
195 		    uint8_t, bus_size_t);
196 void		__BS(set_region_2)(void *, bus_space_handle_t, bus_size_t,
197 		    uint16_t, bus_size_t);
198 void		__BS(set_region_4)(void *, bus_space_handle_t, bus_size_t,
199 		    uint32_t, bus_size_t);
200 void		__BS(set_region_8)(void *, bus_space_handle_t, bus_size_t,
201 		    uint64_t, bus_size_t);
202 
203 /* copy */
204 void		__BS(copy_region_1)(void *, bus_space_handle_t, bus_size_t,
205 		    bus_space_handle_t, bus_size_t, bus_size_t);
206 void		__BS(copy_region_2)(void *, bus_space_handle_t, bus_size_t,
207 		    bus_space_handle_t, bus_size_t, bus_size_t);
208 void		__BS(copy_region_4)(void *, bus_space_handle_t, bus_size_t,
209 		    bus_space_handle_t, bus_size_t, bus_size_t);
210 void		__BS(copy_region_8)(void *, bus_space_handle_t, bus_size_t,
211 		    bus_space_handle_t, bus_size_t, bus_size_t);
212 
213 #ifdef CHIP_EXTENT
214 #ifndef	CHIP_EX_STORE
215 static long
216     __BS(ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
217 #define	CHIP_EX_STORE(v)	(__BS(ex_storage))
218 #define	CHIP_EX_STORE_SIZE(v)	(sizeof __BS(ex_storage))
219 #endif
220 #endif /* CHIP_EXTENT */
221 
222 #ifndef CHIP_ALIGN_STRIDE
223 #define	CHIP_ALIGN_STRIDE	0
224 #endif
225 
226 void
227 __BS(init)(bus_space_tag_t t, void *v)
228 {
229 #ifdef CHIP_EXTENT
230 	struct extent *ex;
231 #endif
232 
233 	/*
234 	 * Initialize the bus space tag.
235 	 */
236 
237 	/* cookie */
238 	t->bs_cookie =		v;
239 
240 	/* mapping/unmapping */
241 	t->bs_map =		__BS(map);
242 	t->bs_unmap =		__BS(unmap);
243 	t->bs_subregion =	__BS(subregion);
244 
245 	t->bs_translate =	__BS(translate);
246 	t->bs_get_window =	__BS(get_window);
247 
248 	/* allocation/deallocation */
249 	t->bs_alloc =		__BS(alloc);
250 	t->bs_free =		__BS(free);
251 
252 	/* get kernel virtual address */
253 	t->bs_vaddr =		__BS(vaddr);
254 
255 	/* mmap for user */
256 	t->bs_mmap =		__BS(mmap);
257 
258 	/* barrier */
259 	t->bs_barrier =		__BS(barrier);
260 
261 	/* read (single) */
262 	t->bs_r_1 =		__BS(read_1);
263 	t->bs_r_2 =		__BS(read_2);
264 	t->bs_r_4 =		__BS(read_4);
265 	t->bs_r_8 =		__BS(read_8);
266 
267 	/* read multiple */
268 	t->bs_rm_1 =		__BS(read_multi_1);
269 	t->bs_rm_2 =		__BS(read_multi_2);
270 	t->bs_rm_4 =		__BS(read_multi_4);
271 	t->bs_rm_8 =		__BS(read_multi_8);
272 
273 	/* read region */
274 	t->bs_rr_1 =		__BS(read_region_1);
275 	t->bs_rr_2 =		__BS(read_region_2);
276 	t->bs_rr_4 =		__BS(read_region_4);
277 	t->bs_rr_8 =		__BS(read_region_8);
278 
279 	/* write (single) */
280 	t->bs_w_1 =		__BS(write_1);
281 	t->bs_w_2 =		__BS(write_2);
282 	t->bs_w_4 =		__BS(write_4);
283 	t->bs_w_8 =		__BS(write_8);
284 
285 	/* write multiple */
286 	t->bs_wm_1 =		__BS(write_multi_1);
287 	t->bs_wm_2 =		__BS(write_multi_2);
288 	t->bs_wm_4 =		__BS(write_multi_4);
289 	t->bs_wm_8 =		__BS(write_multi_8);
290 
291 	/* write region */
292 	t->bs_wr_1 =		__BS(write_region_1);
293 	t->bs_wr_2 =		__BS(write_region_2);
294 	t->bs_wr_4 =		__BS(write_region_4);
295 	t->bs_wr_8 =		__BS(write_region_8);
296 
297 	/* set multiple */
298 	t->bs_sm_1 =		__BS(set_multi_1);
299 	t->bs_sm_2 =		__BS(set_multi_2);
300 	t->bs_sm_4 =		__BS(set_multi_4);
301 	t->bs_sm_8 =		__BS(set_multi_8);
302 
303 	/* set region */
304 	t->bs_sr_1 =		__BS(set_region_1);
305 	t->bs_sr_2 =		__BS(set_region_2);
306 	t->bs_sr_4 =		__BS(set_region_4);
307 	t->bs_sr_8 =		__BS(set_region_8);
308 
309 	/* copy */
310 	t->bs_c_1 =		__BS(copy_region_1);
311 	t->bs_c_2 =		__BS(copy_region_2);
312 	t->bs_c_4 =		__BS(copy_region_4);
313 	t->bs_c_8 =		__BS(copy_region_8);
314 
315 #ifdef CHIP_EXTENT
316 	/* XXX WE WANT EXTENT_NOCOALESCE, BUT WE CAN'T USE IT. XXX */
317 	ex = extent_create(__S(__BS(bus)), 0x0UL, 0xffffffffUL, M_DEVBUF,
318 	    (caddr_t)CHIP_EX_STORE(v), CHIP_EX_STORE_SIZE(v), EX_NOWAIT);
319 	extent_alloc_region(ex, 0, 0xffffffffUL, EX_NOWAIT);
320 
321 #ifdef CHIP_W1_BUS_START
322 	/*
323 	 * The window may be disabled.  We notice this by seeing
324 	 * -1 as the bus base address.
325 	 */
326 	if (CHIP_W1_BUS_START(v) == (bus_addr_t) -1) {
327 #ifdef EXTENT_DEBUG
328 		printf("xxx: this space is disabled\n");
329 #endif
330 		return;
331 	}
332 
333 #ifdef EXTENT_DEBUG
334 	printf("xxx: freeing from 0x%x to 0x%x\n", CHIP_W1_BUS_START(v),
335 	    CHIP_W1_BUS_END(v));
336 #endif
337 	extent_free(ex, CHIP_W1_BUS_START(v),
338 	    CHIP_W1_BUS_END(v) - CHIP_W1_BUS_START(v) + 1, EX_NOWAIT);
339 #endif
340 #ifdef CHIP_W2_BUS_START
341 	if (CHIP_W2_BUS_START(v) != CHIP_W1_BUS_START(v)) {
342 #ifdef EXTENT_DEBUG
343 		printf("xxx: freeing from 0x%lx to 0x%lx\n",
344 		    (u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
345 #endif
346 		extent_free(ex, CHIP_W2_BUS_START(v),
347 		    CHIP_W2_BUS_END(v) - CHIP_W2_BUS_START(v) + 1, EX_NOWAIT);
348 	} else {
349 #ifdef EXTENT_DEBUG
350 		printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
351 		    (u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
352 #endif
353 	}
354 #endif
355 #ifdef CHIP_W3_BUS_START
356 	if (CHIP_W3_BUS_START(v) != CHIP_W1_BUS_START(v) &&
357 	    CHIP_W3_BUS_START(v) != CHIP_W2_BUS_START(v)) {
358 #ifdef EXTENT_DEBUG
359 		printf("xxx: freeing from 0x%lx to 0x%lx\n",
360 		    (u_long)CHIP_W3_BUS_START(v), (u_long)CHIP_W3_BUS_END(v));
361 #endif
362 		extent_free(ex, CHIP_W3_BUS_START(v),
363 		    CHIP_W3_BUS_END(v) - CHIP_W3_BUS_START(v) + 1, EX_NOWAIT);
364 	} else {
365 #ifdef EXTENT_DEBUG
366 		printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
367 		    (u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
368 #endif
369 	}
370 #endif
371 
372 #ifdef EXTENT_DEBUG
373 	extent_print(ex);
374 #endif
375 	CHIP_EXTENT(v) = ex;
376 #endif /* CHIP_EXTENT */
377 }
378 
379 int
380 __BS(translate)(void *v, bus_addr_t addr, bus_size_t len, int flags,
381     struct mips_bus_space_translation *mbst)
382 {
383 	bus_addr_t end = addr + (len - 1);
384 #if CHIP_ALIGN_STRIDE != 0
385 	int linear = flags & BUS_SPACE_MAP_LINEAR;
386 
387 	/*
388 	 * Can't map xxx space linearly.
389 	 */
390 	if (linear)
391 		return (EOPNOTSUPP);
392 #endif
393 
394 #ifdef CHIP_W1_BUS_START
395 	if (addr >= CHIP_W1_BUS_START(v) && end <= CHIP_W1_BUS_END(v))
396 		return (__BS(get_window)(v, 0, mbst));
397 #endif
398 
399 #ifdef CHIP_W2_BUS_START
400 	if (addr >= CHIP_W2_BUS_START(v) && end <= CHIP_W2_BUS_END(v))
401 		return (__BS(get_window)(v, 1, mbst));
402 #endif
403 
404 #ifdef CHIP_W3_BUS_START
405 	if (addr >= CHIP_W3_BUS_START(v) && end <= CHIP_W3_BUS_END(v))
406 		return (__BS(get_window)(v, 2, mbst));
407 #endif
408 
409 #ifdef EXTENT_DEBUG
410 	printf("\n");
411 #ifdef CHIP_W1_BUS_START
412 	printf("%s: window[1]=0x%lx-0x%lx\n", __S(__BS(map)),
413 	    (u_long)CHIP_W1_BUS_START(v), (u_long)CHIP_W1_BUS_END(v));
414 #endif
415 #ifdef CHIP_W2_BUS_START
416 	printf("%s: window[2]=0x%lx-0x%lx\n", __S(__BS(map)),
417 	    (u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
418 #endif
419 #ifdef CHIP_W3_BUS_START
420 	printf("%s: window[3]=0x%lx-0x%lx\n", __S(__BS(map)),
421 	    (u_long)CHIP_W3_BUS_START(v), (u_long)CHIP_W3_BUS_END(v));
422 #endif
423 #endif /* EXTENT_DEBUG */
424 	/* No translation. */
425 	return (EINVAL);
426 }
427 
428 int
429 __BS(get_window)(void *v, int window, struct mips_bus_space_translation *mbst)
430 {
431 
432 	switch (window) {
433 #ifdef CHIP_W1_BUS_START
434 	case 0:
435 		mbst->mbst_bus_start = CHIP_W1_BUS_START(v);
436 		mbst->mbst_bus_end = CHIP_W1_BUS_END(v);
437 		mbst->mbst_sys_start = CHIP_W1_SYS_START(v);
438 		mbst->mbst_sys_end = CHIP_W1_SYS_END(v);
439 		mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
440 		mbst->mbst_flags = 0;
441 		break;
442 #endif
443 
444 #ifdef CHIP_W2_BUS_START
445 	case 1:
446 		mbst->mbst_bus_start = CHIP_W2_BUS_START(v);
447 		mbst->mbst_bus_end = CHIP_W2_BUS_END(v);
448 		mbst->mbst_sys_start = CHIP_W2_SYS_START(v);
449 		mbst->mbst_sys_end = CHIP_W2_SYS_END(v);
450 		mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
451 		mbst->mbst_flags = 0;
452 		break;
453 #endif
454 
455 #ifdef CHIP_W3_BUS_START
456 	case 2:
457 		mbst->mbst_bus_start = CHIP_W3_BUS_START(v);
458 		mbst->mbst_bus_end = CHIP_W3_BUS_END(v);
459 		mbst->mbst_sys_start = CHIP_W3_SYS_START(v);
460 		mbst->mbst_sys_end = CHIP_W3_SYS_END(v);
461 		mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
462 		mbst->mbst_flags = 0;
463 		break;
464 #endif
465 
466 	default:
467 		panic(__S(__BS(get_window)) ": invalid window %d",
468 		    window);
469 	}
470 
471 	return (0);
472 }
473 
474 int
475 __BS(map)(void *v, bus_addr_t addr, bus_size_t size, int flags,
476     bus_space_handle_t *hp, int acct)
477 {
478 	struct mips_bus_space_translation mbst;
479 	int error;
480 
481 	/*
482 	 * Get the translation for this address.
483 	 */
484 	error = __BS(translate)(v, addr, size, flags, &mbst);
485 	if (error)
486 		return (error);
487 
488 #ifdef CHIP_EXTENT
489 	if (acct == 0)
490 		goto mapit;
491 
492 #ifdef EXTENT_DEBUG
493 	printf("xxx: allocating 0x%lx to 0x%lx\n", addr, addr + size - 1);
494 #endif
495         error = extent_alloc_region(CHIP_EXTENT(v), addr, size,
496             EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
497 	if (error) {
498 #ifdef EXTENT_DEBUG
499 		printf("xxx: allocation failed (%d)\n", error);
500 		extent_print(CHIP_EXTENT(v));
501 #endif
502 		return (error);
503 	}
504 
505  mapit:
506 #endif /* CHIP_EXTENT */
507 	if (flags & BUS_SPACE_MAP_CACHEABLE)
508 		*hp = MIPS_PHYS_TO_KSEG0(mbst.mbst_sys_start +
509 		    (addr - mbst.mbst_bus_start));
510 	else
511 		*hp = MIPS_PHYS_TO_KSEG1(mbst.mbst_sys_start +
512 		    (addr - mbst.mbst_bus_start));
513 
514 	return (0);
515 }
516 
517 void
518 __BS(unmap)(void *v, bus_space_handle_t h, bus_size_t size, int acct)
519 {
520 #ifdef CHIP_EXTENT
521 	bus_addr_t addr;
522 	int error;
523 
524 	if (acct == 0)
525 		return;
526 
527 #ifdef EXTENT_DEBUG
528 	printf("xxx: freeing handle 0x%lx for 0x%lx\n", h, size);
529 #endif
530 
531 	if (h >= MIPS_KSEG0_START && h < MIPS_KSEG1_START)
532 		h = MIPS_KSEG0_TO_PHYS(h);
533 	else
534 		h = MIPS_KSEG1_TO_PHYS(h);
535 
536 #ifdef CHIP_W1_BUS_START
537 	if (h >= CHIP_W1_SYS_START(v) && h <= CHIP_W1_SYS_END(v)) {
538 		addr = CHIP_W1_BUS_START(v) + (h - CHIP_W1_SYS_START(v));
539 	} else
540 #endif
541 #ifdef CHIP_W2_BUS_START
542 	if (h >= CHIP_W2_SYS_START(v) && h <= CHIP_W2_SYS_END(v)) {
543 		addr = CHIP_W2_BUS_START(v) + (h - CHIP_W2_SYS_START(v));
544 	} else
545 #endif
546 #ifdef CHIP_W3_BUS_START
547 	if (h >= CHIP_W3_SYS_START(v) && h <= CHIP_W3_SYS_END(v)) {
548 		addr = CHIP_W3_BUS_START(v) + (h - CHIP_W3_SYS_START(v));
549 	} else
550 #endif
551 	{
552 		printf("\n");
553 #ifdef CHIP_W1_BUS_START
554 		printf("%s: sys window[1]=0x%lx-0x%lx\n",
555 		    __S(__BS(map)), (u_long)CHIP_W1_SYS_START(v),
556 		    (u_long)CHIP_W1_SYS_END(v));
557 #endif
558 #ifdef CHIP_W2_BUS_START
559 		printf("%s: sys window[2]=0x%lx-0x%lx\n",
560 		    __S(__BS(map)), (u_long)CHIP_W2_SYS_START(v),
561 		    (u_long)CHIP_W2_SYS_END(v));
562 #endif
563 #ifdef CHIP_W3_BUS_START
564 		printf("%s: sys window[3]=0x%lx-0x%lx\n",
565 		    __S(__BS(map)), (u_long)CHIP_W3_SYS_START(v),
566 		    (u_long)CHIP_W3_SYS_END(v));
567 #endif
568 		panic("%s: don't know how to unmap %lx", __S(__BS(unmap)), h);
569 	}
570 
571 #ifdef EXTENT_DEBUG
572 	printf("xxx: freeing 0x%lx to 0x%lx\n", addr, addr + size - 1);
573 #endif
574         error = extent_free(CHIP_EXTENT(v), addr, size,
575             EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
576 	if (error) {
577 		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
578 		    __S(__BS(unmap)), addr, addr + size - 1,
579 		    error);
580 #ifdef EXTENT_DEBUG
581 		extent_print(CHIP_EXTENT(v));
582 #endif
583 	}
584 #endif /* CHIP_EXTENT */
585 }
586 
587 int
588 __BS(subregion)(void *v, bus_space_handle_t h, bus_size_t offset,
589     bus_size_t size, bus_space_handle_t *nh)
590 {
591 
592 	*nh = h + (offset << CHIP_ALIGN_STRIDE);
593 	return (0);
594 }
595 
596 int
597 __BS(alloc)(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
598     bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
599     bus_space_handle_t *bshp)
600 {
601 #ifdef CHIP_EXTENT
602 	struct mips_bus_space_translation mbst;
603 	bus_addr_t addr;
604 	int error;
605 #if CHIP_ALIGN_STRIDE != 0
606 	int linear = flags & BUS_SPACE_MAP_LINEAR;
607 
608 	/*
609 	 * Can't map xxx space linearly.
610 	 */
611 	if (linear)
612 		return (EOPNOTSUPP);
613 #endif
614 
615 	/*
616 	 * Do the requested allocation.
617 	 */
618 #ifdef EXTENT_DEBUG
619 	printf("xxx: allocating from 0x%lx to 0x%lx\n", rstart, rend);
620 #endif
621 	error = extent_alloc_subregion(CHIP_EXTENT(v), rstart, rend, size,
622 	    align, boundary,
623 	    EX_FAST | EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0),
624 	    &addr);
625 	if (error) {
626 #ifdef EXTENT_DEBUG
627 		printf("xxx: allocation failed (%d)\n", error);
628 		extent_print(CHIP_EXTENT(v));
629 #endif
630 		return (error);
631 	}
632 
633 #ifdef EXTENT_DEBUG
634 	printf("xxx: allocated 0x%lx to 0x%lx\n", addr, addr + size - 1);
635 #endif
636 
637 	error = __BS(translate)(v, addr, size, flags, &mbst);
638 	if (error) {
639 		(void) extent_free(CHIP_EXTENT(v), addr, size,
640 		    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
641 		return (error);
642 	}
643 
644 	*addrp = addr;
645 	if (flags & BUS_SPACE_MAP_CACHEABLE)
646 		*bshp = MIPS_PHYS_TO_KSEG0(mbst.mbst_sys_start +
647 		    (addr - mbst.mbst_bus_start));
648 	else
649 		*bshp = MIPS_PHYS_TO_KSEG1(mbst.mbst_sys_start +
650 		    (addr - mbst.mbst_bus_start));
651 
652 	return (0);
653 #else /* ! CHIP_EXTENT */
654 	return (EOPNOTSUPP);
655 #endif /* CHIP_EXTENT */
656 }
657 
658 void
659 __BS(free)(void *v, bus_space_handle_t bsh, bus_size_t size)
660 {
661 
662 	/* Unmap does all we need to do. */
663 	__BS(unmap)(v, bsh, size, 1);
664 }
665 
666 void *
667 __BS(vaddr)(void *v, bus_space_handle_t bsh)
668 {
669 
670 #if CHIP_ALIGN_STRIDE != 0
671 	/* Linear mappings not possible. */
672 	return (NULL);
673 #else
674 	return ((void *)bsh);
675 #endif
676 }
677 
678 paddr_t
679 __BS(mmap)(void *v, bus_addr_t addr, off_t off, int prot, int flags)
680 {
681 #ifdef CHIP_IO
682 
683 	/* Not supported for I/O space. */
684 	return (-1);
685 #elif defined(CHIP_MEM)
686 	struct mips_bus_space_translation mbst;
687 	int error;
688 
689 	/*
690 	 * Get the translation for this address.
691 	 */
692 	error = __BS(translate)(v, addr, off + PAGE_SIZE, flags,
693 	    &mbst);
694 	if (error)
695 		return (-1);
696 
697 	return (mips_btop(mbst.mbst_sys_start +
698 	    (addr - mbst.mbst_bus_start) + off));
699 #else
700 # error must define one of CHIP_IO or CHIP_MEM
701 #endif
702 }
703 
704 inline void
705 __BS(barrier)(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int f)
706 {
707 
708 	/* XXX XXX XXX */
709 	if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
710 		wbflush();
711 }
712 
713 inline uint8_t
714 __BS(read_1)(void *v, bus_space_handle_t h, bus_size_t off)
715 {
716 #ifdef CHIP_ACCESSTYPE
717 	CHIP_ACCESSTYPE *ptr = (void *)(h + (off << CHIP_ALIGN_STRIDE));
718 	CHIP_ACCESSTYPE rval;
719 
720 	rval = *ptr;
721 	return (rval & 0xff);		/* XXX BigEndian safe? */
722 #else	/* !CHIP_ACCESSTYPE */
723 	uint8_t *ptr = (void *)(h + (off << CHIP_ALIGN_STRIDE));
724 
725 	return (*ptr);
726 #endif	/* !CHIP_ACCESSTYPE */
727 }
728 
729 inline uint16_t
730 __BS(read_2)(void *v, bus_space_handle_t h, bus_size_t off)
731 {
732 #ifdef CHIP_ACCESSTYPE
733 #if CHIP_ALIGN_STRIDE >= 1
734 	CHIP_ACCESSTYPE *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 1)));
735 #else
736 	CHIP_ACCESSTYPE *ptr = (void *)(h + off);
737 #endif
738 	CHIP_ACCESSTYPE rval;
739 
740 	rval = *ptr;
741 	return (rval & 0xffff);		/* XXX BigEndian safe? */
742 #else	/* !CHIP_ACCESSTYPE */
743 #if CHIP_ALIGN_STRIDE >= 1
744 	uint16_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 1)));
745 #else
746 	uint16_t *ptr = (void *)(h + off);
747 #endif
748 
749 	return (*ptr);
750 #endif	/* !CHIP_ACCESSTYPE */
751 }
752 
753 inline uint32_t
754 __BS(read_4)(void *v, bus_space_handle_t h, bus_size_t off)
755 {
756 	/* XXX XXX XXX should use CHIP_ACCESSTYPE if it's > 32bits */
757 #if CHIP_ALIGN_STRIDE >= 2
758 	uint32_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 2)));
759 #else
760 	uint32_t *ptr = (void *)(h + off);
761 #endif
762 
763 	return (*ptr);
764 }
765 
766 inline uint64_t
767 __BS(read_8)(void *v, bus_space_handle_t h, bus_size_t off)
768 {
769 
770 	/* XXX XXX XXX */
771 	panic("%s not implemented", __S(__BS(read_8)));
772 }
773 
774 #define CHIP_read_multi_N(BYTES,TYPE)					\
775 void									\
776 __C(__BS(read_multi_),BYTES)(void *v, bus_space_handle_t h,		\
777     bus_size_t o, TYPE *a, bus_size_t c)				\
778 {									\
779 									\
780 	while (c-- > 0) {						\
781 		__BS(barrier)(v, h, o, sizeof *a,			\
782 		    BUS_SPACE_BARRIER_READ);				\
783 		*a++ = __C(__BS(read_),BYTES)(v, h, o);			\
784 	}								\
785 }
786 CHIP_read_multi_N(1,uint8_t)
787 CHIP_read_multi_N(2,uint16_t)
788 CHIP_read_multi_N(4,uint32_t)
789 CHIP_read_multi_N(8,uint64_t)
790 
791 #define CHIP_read_region_N(BYTES,TYPE)					\
792 void									\
793 __C(__BS(read_region_),BYTES)(void *v, bus_space_handle_t h,		\
794     bus_size_t o, TYPE *a, bus_size_t c)				\
795 {									\
796 									\
797 	while (c-- > 0) {						\
798 		*a++ = __C(__BS(read_),BYTES)(v, h, o);			\
799 		o += sizeof *a;						\
800 	}								\
801 }
802 CHIP_read_region_N(1,uint8_t)
803 CHIP_read_region_N(2,uint16_t)
804 CHIP_read_region_N(4,uint32_t)
805 CHIP_read_region_N(8,uint64_t)
806 
807 inline void
808 __BS(write_1)(void *v, bus_space_handle_t h, bus_size_t off, uint8_t val)
809 {
810 #ifdef CHIP_ACCESSTYPE
811 	CHIP_ACCESSTYPE *ptr = (void *)(h + (off << CHIP_ALIGN_STRIDE));
812 	CHIP_ACCESSTYPE wval;
813 
814 	wval = val & 0xff;		/* XXX BigEndian safe? */
815 	*ptr = wval;
816 #else	/* !CHIP_ACCESSTYPE */
817 	uint8_t *ptr = (void *)(h + (off << CHIP_ALIGN_STRIDE));
818 
819 	*ptr = val;
820 #endif	/* !CHIP_ACCESSTYPE */
821 }
822 
823 inline void
824 __BS(write_2)(void *v, bus_space_handle_t h, bus_size_t off, uint16_t val)
825 {
826 #ifdef CHIP_ACCESSTYPE
827 #if CHIP_ALIGN_STRIDE >= 1
828 	CHIP_ACCESSTYPE *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 1)));
829 #else
830 	CHIP_ACCESSTYPE *ptr = (void *)(h + off);
831 #endif
832 	CHIP_ACCESSTYPE wval;
833 
834 	wval = val & 0xffff;		/* XXX BigEndian safe? */
835 	*ptr = wval;
836 #else	/* !CHIP_ACCESSTYPE */
837 #if CHIP_ALIGN_STRIDE >= 1
838 	uint16_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 1)));
839 #else
840 	uint16_t *ptr = (void *)(h + off);
841 #endif
842 
843 	*ptr = val;
844 #endif	/* !CHIP_ACCESSTYPE */
845 }
846 
847 inline void
848 __BS(write_4)(void *v, bus_space_handle_t h, bus_size_t off, uint32_t val)
849 {
850 	/* XXX XXX XXX should use CHIP_ACCESSTYPE if it's > 32bits */
851 #if CHIP_ALIGN_STRIDE >= 2
852 	uint32_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 2)));
853 #else
854 	uint32_t *ptr = (void *)(h + off);
855 #endif
856 
857 	*ptr = val;
858 }
859 
860 inline void
861 __BS(write_8)(void *v, bus_space_handle_t h, bus_size_t off, uint64_t val)
862 {
863 
864 	/* XXX XXX XXX */
865 	panic("%s not implemented", __S(__BS(write_8)));
866 }
867 
868 #define CHIP_write_multi_N(BYTES,TYPE)					\
869 void									\
870 __C(__BS(write_multi_),BYTES)(void *v, bus_space_handle_t h,		\
871     bus_size_t o, const TYPE *a, bus_size_t c)				\
872 {									\
873 									\
874 	while (c-- > 0) {						\
875 		__C(__BS(write_),BYTES)(v, h, o, *a++);			\
876 		__BS(barrier)(v, h, o, sizeof *a,			\
877 		    BUS_SPACE_BARRIER_WRITE);				\
878 	}								\
879 }
880 CHIP_write_multi_N(1,uint8_t)
881 CHIP_write_multi_N(2,uint16_t)
882 CHIP_write_multi_N(4,uint32_t)
883 CHIP_write_multi_N(8,uint64_t)
884 
885 #define CHIP_write_region_N(BYTES,TYPE)					\
886 void									\
887 __C(__BS(write_region_),BYTES)(void *v, bus_space_handle_t h,		\
888     bus_size_t o, const TYPE *a, bus_size_t c)				\
889 {									\
890 									\
891 	while (c-- > 0) {						\
892 		__C(__BS(write_),BYTES)(v, h, o, *a++);			\
893 		o += sizeof *a;						\
894 	}								\
895 }
896 CHIP_write_region_N(1,uint8_t)
897 CHIP_write_region_N(2,uint16_t)
898 CHIP_write_region_N(4,uint32_t)
899 CHIP_write_region_N(8,uint64_t)
900 
901 #define CHIP_set_multi_N(BYTES,TYPE)					\
902 void									\
903 __C(__BS(set_multi_),BYTES)(void *v, bus_space_handle_t h,		\
904     bus_size_t o, TYPE val, bus_size_t c)				\
905 {									\
906 									\
907 	while (c-- > 0) {						\
908 		__C(__BS(write_),BYTES)(v, h, o, val);			\
909 		__BS(barrier)(v, h, o, sizeof val,			\
910 		    BUS_SPACE_BARRIER_WRITE);				\
911 	}								\
912 }
913 CHIP_set_multi_N(1,uint8_t)
914 CHIP_set_multi_N(2,uint16_t)
915 CHIP_set_multi_N(4,uint32_t)
916 CHIP_set_multi_N(8,uint64_t)
917 
918 #define CHIP_set_region_N(BYTES,TYPE)					\
919 void									\
920 __C(__BS(set_region_),BYTES)(void *v, bus_space_handle_t h,		\
921     bus_size_t o, TYPE val, bus_size_t c)				\
922 {									\
923 									\
924 	while (c-- > 0) {						\
925 		__C(__BS(write_),BYTES)(v, h, o, val);			\
926 		o += sizeof val;					\
927 	}								\
928 }
929 CHIP_set_region_N(1,uint8_t)
930 CHIP_set_region_N(2,uint16_t)
931 CHIP_set_region_N(4,uint32_t)
932 CHIP_set_region_N(8,uint64_t)
933 
934 #define	CHIP_copy_region_N(BYTES)					\
935 void									\
936 __C(__BS(copy_region_),BYTES)(void *v, bus_space_handle_t h1,		\
937     bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)	\
938 {									\
939 	bus_size_t o;							\
940 									\
941 	if ((h1 + o1) >= (h2 + o2)) {					\
942 		/* src after dest: copy forward */			\
943 		for (o = 0; c != 0; c--, o += BYTES)			\
944 			__C(__BS(write_),BYTES)(v, h2, o2 + o,		\
945 			    __C(__BS(read_),BYTES)(v, h1, o1 + o));	\
946 	} else {							\
947 		/* dest after src: copy backwards */			\
948 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
949 			__C(__BS(write_),BYTES)(v, h2, o2 + o,		\
950 			    __C(__BS(read_),BYTES)(v, h1, o1 + o));	\
951 	}								\
952 }
953 CHIP_copy_region_N(1)
954 CHIP_copy_region_N(2)
955 CHIP_copy_region_N(4)
956 CHIP_copy_region_N(8)
957