1 /* $NetBSD: bus_space_alignstride_chipdep.c,v 1.2 2002/03/23 14:20:41 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 #include <sys/extent.h>
85 
86 #define	__C(A,B)	__CONCAT(A,B)
87 #define	__S(S)		__STRING(S)
88 
89 #ifdef CHIP_IO
90 #define	__BS(A)		__C(__C(CHIP,_bus_io_),A)
91 #endif
92 #ifdef CHIP_MEM
93 #define	__BS(A)		__C(__C(CHIP,_bus_mem_),A)
94 #endif
95 
96 /* mapping/unmapping */
97 int		__BS(map)(void *, bus_addr_t, bus_size_t, int,
98 		    bus_space_handle_t *, int);
99 void		__BS(unmap)(void *, bus_space_handle_t, bus_size_t, int);
100 int		__BS(subregion)(void *, bus_space_handle_t, bus_size_t,
101 		    bus_size_t, bus_space_handle_t *);
102 
103 int		__BS(translate)(void *, bus_addr_t, bus_size_t, int,
104 		    struct mips_bus_space_translation *);
105 int		__BS(get_window)(void *, int,
106 		    struct mips_bus_space_translation *);
107 
108 /* allocation/deallocation */
109 int		__BS(alloc)(void *, bus_addr_t, bus_addr_t, bus_size_t,
110 		    bus_size_t, bus_addr_t, int, bus_addr_t *,
111 		    bus_space_handle_t *);
112 void		__BS(free)(void *, bus_space_handle_t, bus_size_t);
113 
114 /* get kernel virtual address */
115 void *		__BS(vaddr)(void *, bus_space_handle_t);
116 
117 /* mmap for user */
118 paddr_t		__BS(mmap)(void *, bus_addr_t, off_t, int, int);
119 
120 /* barrier */
121 inline void	__BS(barrier)(void *, bus_space_handle_t, bus_size_t,
122 		    bus_size_t, int);
123 
124 /* read (single) */
125 inline uint8_t	__BS(read_1)(void *, bus_space_handle_t, bus_size_t);
126 inline uint16_t	__BS(read_2)(void *, bus_space_handle_t, bus_size_t);
127 inline uint32_t	__BS(read_4)(void *, bus_space_handle_t, bus_size_t);
128 inline uint64_t	__BS(read_8)(void *, bus_space_handle_t, bus_size_t);
129 
130 /* read multiple */
131 void		__BS(read_multi_1)(void *, bus_space_handle_t, bus_size_t,
132 		    uint8_t *, bus_size_t);
133 void		__BS(read_multi_2)(void *, bus_space_handle_t, bus_size_t,
134 		    uint16_t *, bus_size_t);
135 void		__BS(read_multi_4)(void *, bus_space_handle_t, bus_size_t,
136 		    uint32_t *, bus_size_t);
137 void		__BS(read_multi_8)(void *, bus_space_handle_t, bus_size_t,
138 		    uint64_t *, bus_size_t);
139 
140 /* read region */
141 void		__BS(read_region_1)(void *, bus_space_handle_t, bus_size_t,
142 		    uint8_t *, bus_size_t);
143 void		__BS(read_region_2)(void *, bus_space_handle_t, bus_size_t,
144 		    uint16_t *, bus_size_t);
145 void		__BS(read_region_4)(void *, bus_space_handle_t, bus_size_t,
146 		    uint32_t *, bus_size_t);
147 void		__BS(read_region_8)(void *, bus_space_handle_t, bus_size_t,
148 		    uint64_t *, bus_size_t);
149 
150 /* write (single) */
151 inline void	__BS(write_1)(void *, bus_space_handle_t, bus_size_t, uint8_t);
152 inline void	__BS(write_2)(void *, bus_space_handle_t, bus_size_t, uint16_t);
153 inline void	__BS(write_4)(void *, bus_space_handle_t, bus_size_t, uint32_t);
154 inline void	__BS(write_8)(void *, bus_space_handle_t, bus_size_t, uint64_t);
155 
156 /* write multiple */
157 void		__BS(write_multi_1)(void *, bus_space_handle_t, bus_size_t,
158 		    const uint8_t *, bus_size_t);
159 void		__BS(write_multi_2)(void *, bus_space_handle_t, bus_size_t,
160 		    const uint16_t *, bus_size_t);
161 void		__BS(write_multi_4)(void *, bus_space_handle_t, bus_size_t,
162 		    const uint32_t *, bus_size_t);
163 void		__BS(write_multi_8)(void *, bus_space_handle_t, bus_size_t,
164 		    const uint64_t *, bus_size_t);
165 
166 /* write region */
167 void		__BS(write_region_1)(void *, bus_space_handle_t, bus_size_t,
168 		    const uint8_t *, bus_size_t);
169 void		__BS(write_region_2)(void *, bus_space_handle_t, bus_size_t,
170 		    const uint16_t *, bus_size_t);
171 void		__BS(write_region_4)(void *, bus_space_handle_t, bus_size_t,
172 		    const uint32_t *, bus_size_t);
173 void		__BS(write_region_8)(void *, bus_space_handle_t, bus_size_t,
174 		    const uint64_t *, bus_size_t);
175 
176 /* set multiple */
177 void		__BS(set_multi_1)(void *, bus_space_handle_t, bus_size_t,
178 		    uint8_t, bus_size_t);
179 void		__BS(set_multi_2)(void *, bus_space_handle_t, bus_size_t,
180 		    uint16_t, bus_size_t);
181 void		__BS(set_multi_4)(void *, bus_space_handle_t, bus_size_t,
182 		    uint32_t, bus_size_t);
183 void		__BS(set_multi_8)(void *, bus_space_handle_t, bus_size_t,
184 		    uint64_t, bus_size_t);
185 
186 /* set region */
187 void		__BS(set_region_1)(void *, bus_space_handle_t, bus_size_t,
188 		    uint8_t, bus_size_t);
189 void		__BS(set_region_2)(void *, bus_space_handle_t, bus_size_t,
190 		    uint16_t, bus_size_t);
191 void		__BS(set_region_4)(void *, bus_space_handle_t, bus_size_t,
192 		    uint32_t, bus_size_t);
193 void		__BS(set_region_8)(void *, bus_space_handle_t, bus_size_t,
194 		    uint64_t, bus_size_t);
195 
196 /* copy */
197 void		__BS(copy_region_1)(void *, bus_space_handle_t, bus_size_t,
198 		    bus_space_handle_t, bus_size_t, bus_size_t);
199 void		__BS(copy_region_2)(void *, bus_space_handle_t, bus_size_t,
200 		    bus_space_handle_t, bus_size_t, bus_size_t);
201 void		__BS(copy_region_4)(void *, bus_space_handle_t, bus_size_t,
202 		    bus_space_handle_t, bus_size_t, bus_size_t);
203 void		__BS(copy_region_8)(void *, bus_space_handle_t, bus_size_t,
204 		    bus_space_handle_t, bus_size_t, bus_size_t);
205 
206 #ifdef CHIP_EXTENT
207 #ifndef	CHIP_EX_STORE
208 static long
209     __BS(ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
210 #define	CHIP_EX_STORE(v)	(__BS(ex_storage))
211 #define	CHIP_EX_STORE_SIZE(v)	(sizeof __BS(ex_storage))
212 #endif
213 #endif /* CHIP_EXTENT */
214 
215 #ifndef CHIP_ALIGN_STRIDE
216 #define	CHIP_ALIGN_STRIDE	0
217 #endif
218 
219 void
220 __BS(init)(bus_space_tag_t t, void *v)
221 {
222 #ifdef CHIP_EXTENT
223 	struct extent *ex;
224 #endif
225 
226 	/*
227 	 * Initialize the bus space tag.
228 	 */
229 
230 	/* cookie */
231 	t->bs_cookie =		v;
232 
233 	/* mapping/unmapping */
234 	t->bs_map =		__BS(map);
235 	t->bs_unmap =		__BS(unmap);
236 	t->bs_subregion =	__BS(subregion);
237 
238 	t->bs_translate =	__BS(translate);
239 	t->bs_get_window =	__BS(get_window);
240 
241 	/* allocation/deallocation */
242 	t->bs_alloc =		__BS(alloc);
243 	t->bs_free =		__BS(free);
244 
245 	/* get kernel virtual address */
246 	t->bs_vaddr =		__BS(vaddr);
247 
248 	/* mmap for user */
249 	t->bs_mmap =		__BS(mmap);
250 
251 	/* barrier */
252 	t->bs_barrier =		__BS(barrier);
253 
254 	/* read (single) */
255 	t->bs_r_1 =		__BS(read_1);
256 	t->bs_r_2 =		__BS(read_2);
257 	t->bs_r_4 =		__BS(read_4);
258 	t->bs_r_8 =		__BS(read_8);
259 
260 	/* read multiple */
261 	t->bs_rm_1 =		__BS(read_multi_1);
262 	t->bs_rm_2 =		__BS(read_multi_2);
263 	t->bs_rm_4 =		__BS(read_multi_4);
264 	t->bs_rm_8 =		__BS(read_multi_8);
265 
266 	/* read region */
267 	t->bs_rr_1 =		__BS(read_region_1);
268 	t->bs_rr_2 =		__BS(read_region_2);
269 	t->bs_rr_4 =		__BS(read_region_4);
270 	t->bs_rr_8 =		__BS(read_region_8);
271 
272 	/* write (single) */
273 	t->bs_w_1 =		__BS(write_1);
274 	t->bs_w_2 =		__BS(write_2);
275 	t->bs_w_4 =		__BS(write_4);
276 	t->bs_w_8 =		__BS(write_8);
277 
278 	/* write multiple */
279 	t->bs_wm_1 =		__BS(write_multi_1);
280 	t->bs_wm_2 =		__BS(write_multi_2);
281 	t->bs_wm_4 =		__BS(write_multi_4);
282 	t->bs_wm_8 =		__BS(write_multi_8);
283 
284 	/* write region */
285 	t->bs_wr_1 =		__BS(write_region_1);
286 	t->bs_wr_2 =		__BS(write_region_2);
287 	t->bs_wr_4 =		__BS(write_region_4);
288 	t->bs_wr_8 =		__BS(write_region_8);
289 
290 	/* set multiple */
291 	t->bs_sm_1 =		__BS(set_multi_1);
292 	t->bs_sm_2 =		__BS(set_multi_2);
293 	t->bs_sm_4 =		__BS(set_multi_4);
294 	t->bs_sm_8 =		__BS(set_multi_8);
295 
296 	/* set region */
297 	t->bs_sr_1 =		__BS(set_region_1);
298 	t->bs_sr_2 =		__BS(set_region_2);
299 	t->bs_sr_4 =		__BS(set_region_4);
300 	t->bs_sr_8 =		__BS(set_region_8);
301 
302 	/* copy */
303 	t->bs_c_1 =		__BS(copy_region_1);
304 	t->bs_c_2 =		__BS(copy_region_2);
305 	t->bs_c_4 =		__BS(copy_region_4);
306 	t->bs_c_8 =		__BS(copy_region_8);
307 
308 #ifdef CHIP_EXTENT
309 	/* XXX WE WANT EXTENT_NOCOALESCE, BUT WE CAN'T USE IT. XXX */
310 	ex = extent_create(__S(__BS(bus)), 0x0UL, 0xffffffffUL, M_DEVBUF,
311 	    (caddr_t)CHIP_EX_STORE(v), CHIP_EX_STORE_SIZE(v), EX_NOWAIT);
312 	extent_alloc_region(ex, 0, 0xffffffffUL, EX_NOWAIT);
313 
314 #ifdef CHIP_W1_BUS_START
315 	/*
316 	 * The window may be disabled.  We notice this by seeing
317 	 * -1 as the bus base address.
318 	 */
319 	if (CHIP_W1_BUS_START(v) == (bus_addr_t) -1) {
320 #ifdef EXTENT_DEBUG
321 		printf("xxx: this space is disabled\n");
322 #endif
323 		return;
324 	}
325 
326 #ifdef EXTENT_DEBUG
327 	printf("xxx: freeing from 0x%lx to 0x%lx\n", CHIP_W1_BUS_START(v),
328 	    CHIP_W1_BUS_END(v));
329 #endif
330 	extent_free(ex, CHIP_W1_BUS_START(v),
331 	    CHIP_W1_BUS_END(v) - CHIP_W1_BUS_START(v) + 1, EX_NOWAIT);
332 #endif
333 #ifdef CHIP_W2_BUS_START
334 	if (CHIP_W2_BUS_START(v) != CHIP_W1_BUS_START(v)) {
335 #ifdef EXTENT_DEBUG
336 		printf("xxx: freeing from 0x%lx to 0x%lx\n",
337 		    CHIP_W2_BUS_START(v), CHIP_W2_BUS_END(v));
338 #endif
339 		extent_free(ex, CHIP_W2_BUS_START(v),
340 		    CHIP_W2_BUS_END(v) - CHIP_W2_BUS_START(v) + 1, EX_NOWAIT);
341 	} else {
342 #ifdef EXTENT_DEBUG
343 		printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
344 		    CHIP_W2_BUS_START(v), CHIP_W2_BUS_END(v));
345 #endif
346 	}
347 #endif
348 #ifdef CHIP_W3_BUS_START
349 	if (CHIP_W3_BUS_START(v) != CHIP_W1_BUS_START(v) &&
350 	    CHIP_W3_BUS_START(v) != CHIP_W2_BUS_START(v)) {
351 #ifdef EXTENT_DEBUG
352 		printf("xxx: freeing from 0x%lx to 0x%lx\n",
353 		    CHIP_W3_BUS_START(v), CHIP_W3_BUS_END(v));
354 #endif
355 		extent_free(ex, CHIP_W3_BUS_START(v),
356 		    CHIP_W3_BUS_END(v) - CHIP_W3_BUS_START(v) + 1, EX_NOWAIT);
357 	} else {
358 #ifdef EXTENT_DEBUG
359 		printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
360 		    CHIP_W2_BUS_START(v), CHIP_W2_BUS_END(v));
361 #endif
362 	}
363 #endif
364 
365 #ifdef EXTENT_DEBUG
366 	extent_print(ex);
367 #endif
368 	CHIP_EXTENT(v) = ex;
369 #endif /* CHIP_EXTENT */
370 }
371 
372 int
373 __BS(translate)(void *v, bus_addr_t addr, bus_size_t len, int flags,
374     struct mips_bus_space_translation *mbst)
375 {
376 	bus_addr_t end = addr + (len - 1);
377 #if CHIP_ALIGN_STRIDE != 0
378 	int linear = flags & BUS_SPACE_MAP_LINEAR;
379 
380 	/*
381 	 * Can't map xxx space linearly.
382 	 */
383 	if (linear)
384 		return (EOPNOTSUPP);
385 #endif
386 
387 #ifdef CHIP_W1_BUS_START
388 	if (addr >= CHIP_W1_BUS_START(v) && end <= CHIP_W1_BUS_END(v))
389 		return (__BS(get_window)(v, 0, mbst));
390 #endif
391 
392 #ifdef CHIP_W2_BUS_START
393 	if (addr >= CHIP_W2_BUS_START(v) && end <= CHIP_W2_BUS_END(v))
394 		return (__BS(get_window)(v, 1, mbst));
395 #endif
396 
397 #ifdef CHIP_W3_BUS_START
398 	if (addr >= CHIP_W3_BUS_START(v) && end <= CHIP_W3_BUS_END(v))
399 		return (__BS(get_window)(v, 2, mbst));
400 #endif
401 
402 #ifdef EXTENT_DEBUG
403 	printf("\n");
404 #ifdef CHIP_W1_BUS_START
405 	printf("%s: window[1]=0x%lx-0x%lx\n",
406 	    __S(__BS(map)), CHIP_W1_BUS_START(v),
407 	    CHIP_W1_BUS_END(v));
408 #endif
409 #ifdef CHIP_W2_BUS_START
410 	printf("%s: window[2]=0x%lx-0x%lx\n",
411 	    __S(__BS(map)), CHIP_W2_BUS_START(v),
412 	    CHIP_W2_BUS_END(v));
413 #endif
414 #ifdef CHIP_W3_BUS_START
415 	printf("%s: window[3]=0x%lx-0x%lx\n",
416 	    __S(__BS(map)), CHIP_W3_BUS_START(v),
417 	    CHIP_W3_BUS_END(v));
418 #endif
419 #endif /* EXTENT_DEBUG */
420 	/* No translation. */
421 	return (EINVAL);
422 }
423 
424 int
425 __BS(get_window)(void *v, int window, struct mips_bus_space_translation *mbst)
426 {
427 
428 	switch (window) {
429 #ifdef CHIP_W1_BUS_START
430 	case 0:
431 		mbst->mbst_bus_start = CHIP_W1_BUS_START(v);
432 		mbst->mbst_bus_end = CHIP_W1_BUS_END(v);
433 		mbst->mbst_sys_start = CHIP_W1_SYS_START(v);
434 		mbst->mbst_sys_end = CHIP_W1_SYS_END(v);
435 		mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
436 		mbst->mbst_flags = 0;
437 		break;
438 #endif
439 
440 #ifdef CHIP_W2_BUS_START
441 	case 1:
442 		mbst->mbst_bus_start = CHIP_W2_BUS_START(v);
443 		mbst->mbst_bus_end = CHIP_W2_BUS_END(v);
444 		mbst->mbst_sys_start = CHIP_W2_SYS_START(v);
445 		mbst->mbst_sys_end = CHIP_W2_SYS_END(v);
446 		mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
447 		mbst->mbst_flags = 0;
448 		break;
449 #endif
450 
451 #ifdef CHIP_W3_BUS_START
452 	case 2:
453 		mbst->mbst_bus_start = CHIP_W3_BUS_START(v);
454 		mbst->mbst_bus_end = CHIP_W3_BUS_END(v);
455 		mbst->mbst_sys_start = CHIP_W3_SYS_START(v);
456 		mbst->mbst_sys_end = CHIP_W3_SYS_END(v);
457 		mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
458 		mbst->mbst_flags = 0;
459 		break;
460 #endif
461 
462 	default:
463 		panic(__S(__BS(get_window)) ": invalid window %d",
464 		    window);
465 	}
466 
467 	return (0);
468 }
469 
470 int
471 __BS(map)(void *v, bus_addr_t addr, bus_size_t size, int flags,
472     bus_space_handle_t *hp, int acct)
473 {
474 	struct mips_bus_space_translation mbst;
475 	int error;
476 
477 	/*
478 	 * Get the translation for this address.
479 	 */
480 	error = __BS(translate)(v, addr, size, flags, &mbst);
481 	if (error)
482 		return (error);
483 
484 #ifdef CHIP_EXTENT
485 	if (acct == 0)
486 		goto mapit;
487 
488 #ifdef EXTENT_DEBUG
489 	printf("xxx: allocating 0x%lx to 0x%lx\n", addr, addr + size - 1);
490 #endif
491         error = extent_alloc_region(CHIP_EXTENT(v), addr, size,
492             EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
493 	if (error) {
494 #ifdef EXTENT_DEBUG
495 		printf("xxx: allocation failed (%d)\n", error);
496 		extent_print(CHIP_EXTENT(v));
497 #endif
498 		return (error);
499 	}
500 
501  mapit:
502 #endif /* CHIP_EXTENT */
503 	if (flags & BUS_SPACE_MAP_CACHEABLE)
504 		*hp = MIPS_PHYS_TO_KSEG0(mbst.mbst_sys_start +
505 		    (addr - mbst.mbst_bus_start));
506 	else
507 		*hp = MIPS_PHYS_TO_KSEG1(mbst.mbst_sys_start +
508 		    (addr - mbst.mbst_bus_start));
509 
510 	return (0);
511 }
512 
513 void
514 __BS(unmap)(void *v, bus_space_handle_t h, bus_size_t size, int acct)
515 {
516 #ifdef CHIP_EXTENT
517 	bus_addr_t addr;
518 	int error;
519 
520 	if (acct == 0)
521 		return;
522 
523 #ifdef EXTENT_DEBUG
524 	printf("xxx: freeing handle 0x%lx for 0x%lx\n", h, size);
525 #endif
526 
527 	if (h >= MIPS_KSEG0_START && h < MIPS_KSEG1_START)
528 		h = MIPS_KSEG0_TO_PHYS(h);
529 	else
530 		h = MIPS_KSEG1_TO_PHYS(h);
531 
532 #ifdef CHIP_W1_BUS_START
533 	if (h >= CHIP_W1_SYS_START(v) && h <= CHIP_W1_SYS_END(v)) {
534 		addr = CHIP_W1_BUS_START(v) + (h - CHIP_W1_SYS_START(v));
535 	} else
536 #endif
537 #ifdef CHIP_W2_BUS_START
538 	if (h >= CHIP_W2_SYS_START(v) && h <= CHIP_W2_SYS_END(v)) {
539 		addr = CHIP_W2_BUS_START(v) + (h - CHIP_W2_SYS_START(v));
540 	} else
541 #endif
542 #ifdef CHIP_W3_BUS_START
543 	if (h >= CHIP_W3_SYS_START(v) && h <= CHIP_W3_SYS_END(v)) {
544 		addr = CHIP_W3_BUS_START(v) + (h - CHIP_W3_SYS_START(v));
545 	} else
546 #endif
547 	{
548 		printf("\n");
549 #ifdef CHIP_W1_BUS_START
550 		printf("%s: sys window[1]=0x%lx-0x%lx\n",
551 		    __S(__BS(map)), CHIP_W1_SYS_START(v),
552 		    CHIP_W1_SYS_END(v));
553 #endif
554 #ifdef CHIP_W2_BUS_START
555 		printf("%s: sys window[2]=0x%lx-0x%lx\n",
556 		    __S(__BS(map)), CHIP_W2_SYS_START(v),
557 		    CHIP_W2_SYS_END(v));
558 #endif
559 #ifdef CHIP_W3_BUS_START
560 		printf("%s: sys window[3]=0x%lx-0x%lx\n",
561 		    __S(__BS(map)), CHIP_W3_SYS_START(v),
562 		    CHIP_W3_SYS_END(v));
563 #endif
564 		panic("%s: don't know how to unmap %lx", __S(__BS(unmap)), h);
565 	}
566 
567 #ifdef EXTENT_DEBUG
568 	printf("xxx: freeing 0x%lx to 0x%lx\n", addr, addr + size - 1);
569 #endif
570         error = extent_free(CHIP_EXTENT(v), addr, size,
571             EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
572 	if (error) {
573 		printf("%s: WARNING: could not unmap 0x%lx-0x%lx (error %d)\n",
574 		    __S(__BS(unmap)), addr, addr + size - 1,
575 		    error);
576 #ifdef EXTENT_DEBUG
577 		extent_print(CHIP_EXTENT(v));
578 #endif
579 	}
580 #endif /* CHIP_EXTENT */
581 }
582 
583 int
584 __BS(subregion)(void *v, bus_space_handle_t h, bus_size_t offset,
585     bus_size_t size, bus_space_handle_t *nh)
586 {
587 
588 	*nh = h + (offset << CHIP_ALIGN_STRIDE);
589 	return (0);
590 }
591 
592 int
593 __BS(alloc)(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
594     bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
595     bus_space_handle_t *bshp)
596 {
597 #ifdef CHIP_EXTENT
598 	struct mips_bus_space_translation mbst;
599 	bus_addr_t addr;
600 	int error;
601 #if CHIP_ALIGN_STRIDE != 0
602 	int linear = flags & BUS_SPACE_MAP_LINEAR;
603 
604 	/*
605 	 * Can't map xxx space linearly.
606 	 */
607 	if (linear)
608 		return (EOPNOTSUPP);
609 #endif
610 
611 	/*
612 	 * Do the requested allocation.
613 	 */
614 #ifdef EXTENT_DEBUG
615 	printf("xxx: allocating from 0x%lx to 0x%lx\n", rstart, rend);
616 #endif
617 	error = extent_alloc_subregion(CHIP_EXTENT(v), rstart, rend, size,
618 	    align, boundary,
619 	    EX_FAST | EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0),
620 	    &addr);
621 	if (error) {
622 #ifdef EXTENT_DEBUG
623 		printf("xxx: allocation failed (%d)\n", error);
624 		extent_print(CHIP_EXTENT(v));
625 #endif
626 		return (error);
627 	}
628 
629 #ifdef EXTENT_DEBUG
630 	printf("xxx: allocated 0x%lx to 0x%lx\n", addr, addr + size - 1);
631 #endif
632 
633 	error = __BS(translate)(v, addr, size, flags, &mbst);
634 	if (error) {
635 		(void) extent_free(CHIP_EXTENT(v), addr, size,
636 		    EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
637 		return (error);
638 	}
639 
640 	*addrp = addr;
641 	if (flags & BUS_SPACE_MAP_CACHEABLE)
642 		*bshp = MIPS_PHYS_TO_KSEG0(mbst.mbst_sys_start +
643 		    (addr - mbst.mbst_bus_start));
644 	else
645 		*bshp = MIPS_PHYS_TO_KSEG1(mbst.mbst_sys_start +
646 		    (addr - mbst.mbst_bus_start));
647 
648 	return (0);
649 #else /* ! CHIP_EXTENT */
650 	return (EOPNOTSUPP);
651 #endif /* CHIP_EXTENT */
652 }
653 
654 void
655 __BS(free)(void *v, bus_space_handle_t bsh, bus_size_t size)
656 {
657 
658 	/* Unmap does all we need to do. */
659 	__BS(unmap)(v, bsh, size, 1);
660 }
661 
662 void *
663 __BS(vaddr)(void *v, bus_space_handle_t bsh)
664 {
665 
666 #if CHIP_ALIGN_STRIDE != 0
667 	/* Linear mappings not possible. */
668 	return (NULL);
669 #else
670 	return ((void *)bsh);
671 #endif
672 }
673 
674 paddr_t
675 __BS(mmap)(void *v, bus_addr_t addr, off_t off, int prot, int flags)
676 {
677 #ifdef CHIP_IO
678 
679 	/* Not supported for I/O space. */
680 	return (-1);
681 #elif defined(CHIP_MEM)
682 	struct mips_bus_space_translation mbst;
683 	int error;
684 
685 	/*
686 	 * Get the translation for this address.
687 	 */
688 	error = __BS(translate)(v, addr, off + PAGE_SIZE, flags,
689 	    &mbst);
690 	if (error)
691 		return (-1);
692 
693 	return (mips_btop(mbst.mbst_sys_start +
694 	    (addr - mbst.mbst_bus_start) + off));
695 #else
696 # error must define one of CHIP_IO or CHIP_MEM
697 #endif
698 }
699 
700 inline void
701 __BS(barrier)(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int f)
702 {
703 
704 	/* XXX XXX XXX */
705 	if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
706 		wbflush();
707 }
708 
709 inline uint8_t
710 __BS(read_1)(void *v, bus_space_handle_t h, bus_size_t off)
711 {
712 	uint8_t *ptr = (void *)(h + (off << CHIP_ALIGN_STRIDE));
713 
714 	return (*ptr);
715 }
716 
717 inline uint16_t
718 __BS(read_2)(void *v, bus_space_handle_t h, bus_size_t off)
719 {
720 #if CHIP_ALIGN_STRIDE >= 1
721 	uint16_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 1)));
722 #else
723 	uint16_t *ptr = (void *)(h + off);
724 #endif
725 
726 	return (*ptr);
727 }
728 
729 inline uint32_t
730 __BS(read_4)(void *v, bus_space_handle_t h, bus_size_t off)
731 {
732 #if CHIP_ALIGN_STRIDE >= 2
733 	uint32_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 2)));
734 #else
735 	uint32_t *ptr = (void *)(h + off);
736 #endif
737 
738 	return (*ptr);
739 }
740 
741 inline uint64_t
742 __BS(read_8)(void *v, bus_space_handle_t h, bus_size_t off)
743 {
744 
745 	/* XXX XXX XXX */
746 	panic("%s not implemented", __S(__BS(read_8)));
747 }
748 
749 #define CHIP_read_multi_N(BYTES,TYPE)					\
750 void									\
751 __C(__BS(read_multi_),BYTES)(void *v, bus_space_handle_t h,		\
752     bus_size_t o, TYPE *a, bus_size_t c)				\
753 {									\
754 									\
755 	while (c-- > 0) {						\
756 		__BS(barrier)(v, h, o, sizeof *a,			\
757 		    BUS_SPACE_BARRIER_READ);				\
758 		*a++ = __C(__BS(read_),BYTES)(v, h, o);			\
759 	}								\
760 }
761 CHIP_read_multi_N(1,uint8_t)
762 CHIP_read_multi_N(2,uint16_t)
763 CHIP_read_multi_N(4,uint32_t)
764 CHIP_read_multi_N(8,uint64_t)
765 
766 #define CHIP_read_region_N(BYTES,TYPE)					\
767 void									\
768 __C(__BS(read_region_),BYTES)(void *v, bus_space_handle_t h,		\
769     bus_size_t o, TYPE *a, bus_size_t c)				\
770 {									\
771 									\
772 	while (c-- > 0) {						\
773 		*a++ = __C(__BS(read_),BYTES)(v, h, o);			\
774 		o += sizeof *a;						\
775 	}								\
776 }
777 CHIP_read_region_N(1,uint8_t)
778 CHIP_read_region_N(2,uint16_t)
779 CHIP_read_region_N(4,uint32_t)
780 CHIP_read_region_N(8,uint64_t)
781 
782 inline void
783 __BS(write_1)(void *v, bus_space_handle_t h, bus_size_t off, uint8_t val)
784 {
785 	uint8_t *ptr = (void *)(h + (off << CHIP_ALIGN_STRIDE));
786 
787 	*ptr = val;
788 }
789 
790 inline void
791 __BS(write_2)(void *v, bus_space_handle_t h, bus_size_t off, uint16_t val)
792 {
793 #if CHIP_ALIGN_STRIDE >= 1
794 	uint16_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 1)));
795 #else
796 	uint16_t *ptr = (void *)(h + off);
797 #endif
798 
799 	*ptr = val;
800 }
801 
802 inline void
803 __BS(write_4)(void *v, bus_space_handle_t h, bus_size_t off, uint32_t val)
804 {
805 #if CHIP_ALIGN_STRIDE >= 2
806 	uint32_t *ptr = (void *)(h + (off << (CHIP_ALIGN_STRIDE - 2)));
807 #else
808 	uint32_t *ptr = (void *)(h + off);
809 #endif
810 
811 	*ptr = val;
812 }
813 
814 inline void
815 __BS(write_8)(void *v, bus_space_handle_t h, bus_size_t off, uint64_t val)
816 {
817 
818 	/* XXX XXX XXX */
819 	panic("%s not implemented", __S(__BS(write_8)));
820 }
821 
822 #define CHIP_write_multi_N(BYTES,TYPE)					\
823 void									\
824 __C(__BS(write_multi_),BYTES)(void *v, bus_space_handle_t h,		\
825     bus_size_t o, const TYPE *a, bus_size_t c)				\
826 {									\
827 									\
828 	while (c-- > 0) {						\
829 		__C(__BS(write_),BYTES)(v, h, o, *a++);			\
830 		__BS(barrier)(v, h, o, sizeof *a,			\
831 		    BUS_SPACE_BARRIER_WRITE);				\
832 	}								\
833 }
834 CHIP_write_multi_N(1,uint8_t)
835 CHIP_write_multi_N(2,uint16_t)
836 CHIP_write_multi_N(4,uint32_t)
837 CHIP_write_multi_N(8,uint64_t)
838 
839 #define CHIP_write_region_N(BYTES,TYPE)					\
840 void									\
841 __C(__BS(write_region_),BYTES)(void *v, bus_space_handle_t h,		\
842     bus_size_t o, const TYPE *a, bus_size_t c)				\
843 {									\
844 									\
845 	while (c-- > 0) {						\
846 		__C(__BS(write_),BYTES)(v, h, o, *a++);			\
847 		o += sizeof *a;						\
848 	}								\
849 }
850 CHIP_write_region_N(1,uint8_t)
851 CHIP_write_region_N(2,uint16_t)
852 CHIP_write_region_N(4,uint32_t)
853 CHIP_write_region_N(8,uint64_t)
854 
855 #define CHIP_set_multi_N(BYTES,TYPE)					\
856 void									\
857 __C(__BS(set_multi_),BYTES)(void *v, bus_space_handle_t h,		\
858     bus_size_t o, TYPE val, bus_size_t c)				\
859 {									\
860 									\
861 	while (c-- > 0) {						\
862 		__C(__BS(write_),BYTES)(v, h, o, val);			\
863 		__BS(barrier)(v, h, o, sizeof val,			\
864 		    BUS_SPACE_BARRIER_WRITE);				\
865 	}								\
866 }
867 CHIP_set_multi_N(1,uint8_t)
868 CHIP_set_multi_N(2,uint16_t)
869 CHIP_set_multi_N(4,uint32_t)
870 CHIP_set_multi_N(8,uint64_t)
871 
872 #define CHIP_set_region_N(BYTES,TYPE)					\
873 void									\
874 __C(__BS(set_region_),BYTES)(void *v, bus_space_handle_t h,		\
875     bus_size_t o, TYPE val, bus_size_t c)				\
876 {									\
877 									\
878 	while (c-- > 0) {						\
879 		__C(__BS(write_),BYTES)(v, h, o, val);			\
880 		o += sizeof val;					\
881 	}								\
882 }
883 CHIP_set_region_N(1,uint8_t)
884 CHIP_set_region_N(2,uint16_t)
885 CHIP_set_region_N(4,uint32_t)
886 CHIP_set_region_N(8,uint64_t)
887 
888 #define	CHIP_copy_region_N(BYTES)					\
889 void									\
890 __C(__BS(copy_region_),BYTES)(void *v, bus_space_handle_t h1,		\
891     bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)	\
892 {									\
893 	bus_size_t o;							\
894 									\
895 	if ((h1 + o1) >= (h2 + o2)) {					\
896 		/* src after dest: copy forward */			\
897 		for (o = 0; c != 0; c--, o += BYTES)			\
898 			__C(__BS(write_),BYTES)(v, h2, o2 + o,		\
899 			    __C(__BS(read_),BYTES)(v, h1, o1 + o));	\
900 	} else {							\
901 		/* dest after src: copy backwards */			\
902 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
903 			__C(__BS(write_),BYTES)(v, h2, o2 + o,		\
904 			    __C(__BS(read_),BYTES)(v, h1, o1 + o));	\
905 	}								\
906 }
907 CHIP_copy_region_N(1)
908 CHIP_copy_region_N(2)
909 CHIP_copy_region_N(4)
910 CHIP_copy_region_N(8)
911