1/* $NetBSD: au_wired_space.c,v 1.11 2021/01/04 17:35:12 thorpej Exp $ */
2
3/*-
4 * Copyright (c) 2006 Itronix Inc.
5 * All rights reserved.
6 *
7 * Written by Garrett D'Amore for Itronix Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. The name of Itronix Inc. may not be used to endorse
18 *    or promote products derived from this software without specific
19 *    prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33/*
34 * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
35 * All rights reserved.
36 *
37 * This code is derived from software contributed to The NetBSD Foundation
38 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
39 * Simulation Facility, NASA Ames Research Center.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 *    notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 *    notice, this list of conditions and the following disclaimer in the
48 *    documentation and/or other materials provided with the distribution.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
61 */
62
63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: au_wired_space.c,v 1.11 2021/01/04 17:35:12 thorpej Exp $");
65
66/*
67 * This provides mappings for the upper I/O regions used on some
68 * Alchemy parts, e.g. PCI and PCMCIA spaces.  These spaces can be
69 * accessed using wired TLB entries.
70 */
71
72#include <sys/param.h>
73#include <sys/systm.h>
74#include <sys/extent.h>
75#include <sys/kmem.h>
76#include <sys/endian.h>
77
78#include <sys/bus.h>
79#include <mips/locore.h>
80#include <machine/wired_map.h>
81#include <mips/alchemy/include/au_wired_space.h>
82
83#ifndef	AU_WIRED_EXTENT_SZ
84#define	AU_WIRED_EXTENT_SZ	EXTENT_FIXED_STORAGE_SIZE(10)
85#endif
86
87typedef struct au_wired_cookie {
88	const char	*c_name;
89	bus_addr_t	c_start;
90	bus_size_t	c_size;
91	paddr_t		c_pbase;
92	int		c_flags;
93	int		c_swswap;
94	bool		c_hwswap;
95	struct extent	*c_extent;
96	long		c_exstore[AU_WIRED_EXTENT_SZ/sizeof (long)];
97} au_wired_cookie_t;
98
99int au_wired_map(void *, bus_addr_t, bus_size_t, int,
100    bus_space_handle_t *, int);
101void au_wired_unmap(void *, bus_space_handle_t, bus_size_t, int);
102void *au_wired_vaddr(void *, bus_space_handle_t);
103int au_wired_subregion(void *, bus_space_handle_t, bus_size_t, bus_size_t,
104    bus_space_handle_t *);
105paddr_t au_wired_mmap(void *, bus_addr_t, off_t, int, int);
106int au_wired_alloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,
107    bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
108void au_wired_free(void *, bus_space_handle_t, bus_size_t);
109void au_wired_barrier(void *, bus_space_handle_t, bus_size_t, bus_size_t, int);
110uint8_t au_wired_r_1(void *, bus_space_handle_t, bus_size_t);
111uint16_t au_wired_r_2(void *, bus_space_handle_t, bus_size_t);
112uint32_t au_wired_r_4(void *, bus_space_handle_t, bus_size_t);
113uint64_t au_wired_r_8(void *, bus_space_handle_t, bus_size_t);
114void au_wired_rm_1(void *, bus_space_handle_t, bus_size_t, uint8_t *,
115    bus_size_t);
116void au_wired_rm_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
117    bus_size_t);
118void au_wired_rm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
119    bus_size_t);
120void au_wired_rm_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
121    bus_size_t);
122void au_wired_rr_1(void *, bus_space_handle_t, bus_size_t, uint8_t *,
123    bus_size_t);
124void au_wired_rr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
125    bus_size_t);
126void au_wired_rr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
127    bus_size_t);
128void au_wired_rr_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
129    bus_size_t);
130void au_wired_w_1(void *, bus_space_handle_t, bus_size_t, uint8_t);
131void au_wired_w_2(void *, bus_space_handle_t, bus_size_t, uint16_t);
132void au_wired_w_4(void *, bus_space_handle_t, bus_size_t, uint32_t);
133void au_wired_w_8(void *, bus_space_handle_t, bus_size_t, uint64_t);
134void au_wired_wm_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *,
135    bus_size_t);
136void au_wired_wm_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
137    bus_size_t);
138void au_wired_wm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
139    bus_size_t);
140void au_wired_wm_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
141    bus_size_t);
142void au_wired_wr_1(void *, bus_space_handle_t, bus_size_t, const uint8_t *,
143    bus_size_t);
144void au_wired_wr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
145    bus_size_t);
146void au_wired_wr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
147    bus_size_t);
148void au_wired_wr_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
149    bus_size_t);
150void au_wired_sm_1(void *, bus_space_handle_t, bus_size_t, uint8_t,
151    bus_size_t);
152void au_wired_sm_2(void *, bus_space_handle_t, bus_size_t, uint16_t,
153    bus_size_t);
154void au_wired_sm_4(void *, bus_space_handle_t, bus_size_t, uint32_t,
155    bus_size_t);
156void au_wired_sm_8(void *, bus_space_handle_t, bus_size_t, uint64_t,
157    bus_size_t);
158void au_wired_sr_1(void *, bus_space_handle_t, bus_size_t, uint8_t,
159    bus_size_t);
160void au_wired_sr_2(void *, bus_space_handle_t, bus_size_t, uint16_t,
161    bus_size_t);
162void au_wired_sr_4(void *, bus_space_handle_t, bus_size_t, uint32_t,
163    bus_size_t);
164void au_wired_sr_8(void *, bus_space_handle_t, bus_size_t, uint64_t,
165    bus_size_t);
166void au_wired_c_1(void *, bus_space_handle_t, bus_size_t,
167    bus_space_handle_t, bus_size_t, bus_size_t);
168void au_wired_c_2(void *, bus_space_handle_t, bus_size_t,
169    bus_space_handle_t, bus_size_t, bus_size_t);
170void au_wired_c_4(void *, bus_space_handle_t, bus_size_t,
171    bus_space_handle_t, bus_size_t, bus_size_t);
172void au_wired_c_8(void *, bus_space_handle_t, bus_size_t,
173    bus_space_handle_t, bus_size_t, bus_size_t);
174uint16_t au_wired_rs_2(void *, bus_space_handle_t, bus_size_t);
175uint32_t au_wired_rs_4(void *, bus_space_handle_t, bus_size_t);
176uint64_t au_wired_rs_8(void *, bus_space_handle_t, bus_size_t);
177void au_wired_ws_2(void *, bus_space_handle_t, bus_size_t, uint16_t);
178void au_wired_ws_4(void *, bus_space_handle_t, bus_size_t, uint32_t);
179void au_wired_ws_8(void *, bus_space_handle_t, bus_size_t, uint64_t);
180void au_wired_rms_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
181    bus_size_t);
182void au_wired_rms_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
183    bus_size_t);
184void au_wired_rms_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
185    bus_size_t);
186void au_wired_rrs_2(void *, bus_space_handle_t, bus_size_t, uint16_t *,
187    bus_size_t);
188void au_wired_rrs_4(void *, bus_space_handle_t, bus_size_t, uint32_t *,
189    bus_size_t);
190void au_wired_rrs_8(void *, bus_space_handle_t, bus_size_t, uint64_t *,
191    bus_size_t);
192void au_wired_wms_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
193    bus_size_t);
194void au_wired_wms_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
195    bus_size_t);
196void au_wired_wms_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
197    bus_size_t);
198void au_wired_wrs_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *,
199    bus_size_t);
200void au_wired_wrs_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *,
201    bus_size_t);
202void au_wired_wrs_8(void *, bus_space_handle_t, bus_size_t, const uint64_t *,
203    bus_size_t);
204
205int
206au_wired_map(void *cookie, bus_addr_t addr, bus_size_t size,
207    int flags, bus_space_handle_t *bshp, int acct)
208{
209	int			err;
210	au_wired_cookie_t	*c = (au_wired_cookie_t *)cookie;
211	paddr_t			pa;
212
213	/* make sure we can map this bus address */
214	if (addr < c->c_start ||
215	    addr + size > c->c_start + c->c_size)
216		return EINVAL;
217
218	pa = c->c_pbase + (addr - c->c_start);
219
220	if (!mips3_wired_enter_region(addr, pa, size))
221		return ENOMEM;
222
223	/*
224	 * bus addresses are taken from virtual address space.
225	 */
226	if (acct && c->c_extent != NULL) {
227		err = extent_alloc_region(c->c_extent, addr, size, EX_NOWAIT);
228		if (err)
229			return err;
230	}
231
232	*bshp = addr;
233
234	return 0;
235}
236
237void
238au_wired_unmap(void *cookie, bus_space_handle_t bsh, bus_size_t size, int acct)
239{
240	au_wired_cookie_t	*c = (au_wired_cookie_t *)cookie;
241
242	if (acct != 0 && c->c_extent != NULL) {
243		extent_free(c->c_extent, (vaddr_t)bsh, size, EX_NOWAIT);
244	}
245}
246
247int
248au_wired_subregion(void *cookie, bus_space_handle_t bsh,
249    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
250{
251
252	*nbshp = bsh + offset;
253	return 0;
254}
255
256void *
257au_wired_vaddr(void *cookie, bus_space_handle_t bsh)
258{
259
260	return ((void *)bsh);
261}
262
263paddr_t
264au_wired_mmap(void *cookie, bus_addr_t addr, off_t off, int prot, int flags)
265{
266	au_wired_cookie_t	*c = (au_wired_cookie_t *)cookie;
267
268	/* I/O spaces should not be directly mmap'ed */
269	if (c->c_flags & AU_WIRED_SPACE_IO)
270		return -1;
271
272	if (addr < c->c_start || (addr + off) >= (c->c_start + c->c_size))
273		return -1;
274
275	return mips_btop(c->c_pbase + (addr - c->c_start) + off);
276}
277
278int
279au_wired_alloc(void *cookie, bus_addr_t start, bus_addr_t end,
280    bus_size_t size, bus_size_t align, bus_size_t boundary, int flags,
281    bus_addr_t *addrp, bus_space_handle_t *bshp)
282{
283	au_wired_cookie_t	*c = (au_wired_cookie_t *)cookie;
284	vaddr_t addr;
285	int err;
286	paddr_t pa;
287
288	if (c->c_extent == NULL)
289		panic("au_wired_alloc: extent map %s not avail", c->c_name);
290
291	if (start < c->c_start || ((start + size) > (c->c_start + c->c_size)))
292		return EINVAL;
293
294	err = extent_alloc_subregion(c->c_extent, start, end, size,
295	    align, boundary, EX_FAST | EX_NOWAIT, &addr);
296	if (err)
297		return err;
298
299	pa = c->c_pbase + (addr - c->c_start);
300
301	if (!mips3_wired_enter_region(addr, pa, size))
302		return ENOMEM;
303
304	*bshp = addr;
305	*addrp = addr;
306	return 0;
307}
308
309void
310au_wired_free(void *cookie, bus_space_handle_t bsh, bus_size_t size)
311{
312
313	/* unmap takes care of it all */
314	au_wired_unmap(cookie, bsh, size, 1);
315}
316
317inline void
318au_wired_barrier(void *cookie, bus_space_handle_t bsh, bus_size_t o,
319    bus_size_t l, int f)
320{
321
322	if (f & BUS_SPACE_BARRIER_WRITE)
323		wbflush();
324}
325
326inline uint8_t
327au_wired_r_1(void *v, bus_space_handle_t h, bus_size_t o)
328{
329
330	return (*(volatile uint8_t *)(h + o));
331}
332
333inline uint16_t
334au_wired_r_2(void *v, bus_space_handle_t h, bus_size_t o)
335{
336	uint16_t		val = (*(volatile uint16_t *)(h + o));
337	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
338
339	return (c->c_swswap ? bswap16(val) : val);
340}
341
342inline uint32_t
343au_wired_r_4(void *v, bus_space_handle_t h, bus_size_t o)
344{
345	uint32_t		val = (*(volatile uint32_t *)(h + o));
346	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
347
348	return (c->c_swswap ? bswap32(val) : val);
349}
350
351inline uint64_t
352au_wired_r_8(void *v, bus_space_handle_t h, bus_size_t o)
353{
354	uint64_t		val = (*(volatile uint64_t *)(h + o));
355	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
356
357	return (c->c_swswap ? bswap64(val) : val);
358}
359
360inline void
361au_wired_w_1(void *v, bus_space_handle_t h, bus_size_t o, uint8_t val)
362{
363
364	*(volatile uint8_t *)(h + o) = val;
365}
366
367inline void
368au_wired_w_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t val)
369{
370	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
371
372	*(volatile uint16_t *)(h + o) = c->c_swswap ? bswap16(val) : val;
373}
374
375inline void
376au_wired_w_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t val)
377{
378	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
379
380	*(volatile uint32_t *)(h + o) = c->c_swswap ? bswap32(val) : val;
381}
382
383inline void
384au_wired_w_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t val)
385{
386	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
387
388	*(volatile uint64_t *)(h + o) = c->c_swswap ? bswap64(val) : val;
389}
390
391inline uint16_t
392au_wired_rs_2(void *v, bus_space_handle_t h, bus_size_t o)
393{
394	uint16_t		val = (*(volatile uint16_t *)(h + o));
395	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
396
397	return (c->c_hwswap ? bswap16(val) : val);
398}
399
400inline uint32_t
401au_wired_rs_4(void *v, bus_space_handle_t h, bus_size_t o)
402{
403	uint32_t		val = (*(volatile uint32_t *)(h + o));
404	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
405
406	return (c->c_hwswap ? bswap32(val) : val);
407}
408
409inline uint64_t
410au_wired_rs_8(void *v, bus_space_handle_t h, bus_size_t o)
411{
412	uint64_t		val = (*(volatile uint64_t *)(h + o));
413	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
414
415	return (c->c_hwswap ? bswap64(val) : val);
416}
417
418inline void
419au_wired_ws_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t val)
420{
421	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
422
423	*(volatile uint16_t *)(h + o) = c->c_hwswap ? bswap16(val) : val;
424}
425
426inline void
427au_wired_ws_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t val)
428{
429	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
430
431	*(volatile uint32_t *)(h + o) = c->c_hwswap ? bswap32(val) : val;
432}
433
434inline void
435au_wired_ws_8(void *v, bus_space_handle_t h, bus_size_t o, uint64_t val)
436{
437	au_wired_cookie_t	*c = (au_wired_cookie_t *)v;
438
439	*(volatile uint64_t *)(h + o) = c->c_hwswap ? bswap64(val) : val;
440}
441
442#define	AU_WIRED_RM(TYPE,BYTES)						\
443void									\
444__CONCAT(au_wired_rm_,BYTES)(void *v,					\
445    bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt)	\
446{									\
447									\
448	while (cnt-- > 0)						\
449		*dst ++ = __CONCAT(au_wired_r_,BYTES)(v, h, o);		\
450}
451AU_WIRED_RM(uint8_t,1)
452AU_WIRED_RM(uint16_t,2)
453AU_WIRED_RM(uint32_t,4)
454AU_WIRED_RM(uint64_t,8)
455
456#define	AU_WIRED_RMS(TYPE,BYTES)					\
457void									\
458__CONCAT(au_wired_rms_,BYTES)(void *v,					\
459    bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt)	\
460{									\
461									\
462	while (cnt-- > 0) {						\
463		wbflush();						\
464		*dst++ = __CONCAT(au_wired_rs_,BYTES)(v, h, o);		\
465	}								\
466}
467AU_WIRED_RMS(uint16_t,2)
468AU_WIRED_RMS(uint32_t,4)
469AU_WIRED_RMS(uint64_t,8)
470
471#define AU_WIRED_RR(TYPE,BYTES)						\
472void									\
473__CONCAT(au_wired_rr_,BYTES)(void *v,					\
474    bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt)	\
475{									\
476									\
477	while (cnt-- > 0) {						\
478		*dst++ = __CONCAT(au_wired_r_,BYTES)(v, h, o);		\
479		o += BYTES;						\
480	}								\
481}
482AU_WIRED_RR(uint8_t,1)
483AU_WIRED_RR(uint16_t,2)
484AU_WIRED_RR(uint32_t,4)
485AU_WIRED_RR(uint64_t,8)
486
487#define AU_WIRED_RRS(TYPE,BYTES)					\
488void									\
489__CONCAT(au_wired_rrs_,BYTES)(void *v,					\
490    bus_space_handle_t h, bus_size_t o, TYPE *dst, bus_size_t cnt)	\
491{									\
492									\
493	while (cnt-- > 0) {						\
494		*dst++ = __CONCAT(au_wired_rs_,BYTES)(v, h, o);		\
495		o += BYTES;						\
496	}								\
497}
498AU_WIRED_RRS(uint16_t,2)
499AU_WIRED_RRS(uint32_t,4)
500AU_WIRED_RRS(uint64_t,8)
501
502#define	AU_WIRED_WM(TYPE,BYTES)						\
503void									\
504__CONCAT(au_wired_wm_,BYTES)(void *v,					\
505    bus_space_handle_t h, bus_size_t o, const TYPE *src,		\
506    bus_size_t cnt)							\
507{									\
508									\
509	while (cnt-- > 0) {						\
510		__CONCAT(au_wired_w_,BYTES)(v, h, o, *src++);		\
511		wbflush();						\
512	}								\
513}
514AU_WIRED_WM(uint8_t,1)
515AU_WIRED_WM(uint16_t,2)
516AU_WIRED_WM(uint32_t,4)
517AU_WIRED_WM(uint64_t,8)
518
519#define	AU_WIRED_WMS(TYPE,BYTES)					\
520void									\
521__CONCAT(au_wired_wms_,BYTES)(void *v,					\
522    bus_space_handle_t h, bus_size_t o, const TYPE *src,		\
523    bus_size_t cnt)							\
524{									\
525									\
526	while (cnt-- > 0) {						\
527		__CONCAT(au_wired_ws_,BYTES)(v, h, o, *src++);		\
528		wbflush();						\
529	}								\
530}
531AU_WIRED_WMS(uint16_t,2)
532AU_WIRED_WMS(uint32_t,4)
533AU_WIRED_WMS(uint64_t,8)
534
535#define	AU_WIRED_WR(TYPE,BYTES)						\
536void									\
537__CONCAT(au_wired_wr_,BYTES)(void *v,					\
538    bus_space_handle_t h, bus_size_t o, const TYPE *src,		\
539    bus_size_t cnt)							\
540{									\
541									\
542	while (cnt-- > 0) {						\
543		__CONCAT(au_wired_w_,BYTES)(v, h, o, *src++);		\
544		o += BYTES;						\
545	}								\
546}
547AU_WIRED_WR(uint8_t,1)
548AU_WIRED_WR(uint16_t,2)
549AU_WIRED_WR(uint32_t,4)
550AU_WIRED_WR(uint64_t,8)
551
552#define	AU_WIRED_WRS(TYPE,BYTES)					\
553void									\
554__CONCAT(au_wired_wrs_,BYTES)(void *v,					\
555    bus_space_handle_t h, bus_size_t o, const TYPE *src,		\
556    bus_size_t cnt)							\
557{									\
558									\
559	while (cnt-- > 0) {						\
560		__CONCAT(au_wired_ws_,BYTES)(v, h, o, *src++);		\
561		o += BYTES;						\
562	}								\
563}
564AU_WIRED_WRS(uint16_t,2)
565AU_WIRED_WRS(uint32_t,4)
566AU_WIRED_WRS(uint64_t,8)
567
568#define	AU_WIRED_SM(TYPE,BYTES)						\
569void									\
570__CONCAT(au_wired_sm_,BYTES)(void *v,					\
571    bus_space_handle_t h, bus_size_t o, TYPE val,			\
572    bus_size_t cnt)							\
573{									\
574									\
575	while (cnt-- > 0) {						\
576		__CONCAT(au_wired_w_,BYTES)(v, h, o, val);		\
577		wbflush();						\
578	}								\
579}
580AU_WIRED_SM(uint8_t,1)
581AU_WIRED_SM(uint16_t,2)
582AU_WIRED_SM(uint32_t,4)
583AU_WIRED_SM(uint64_t,8)
584
585#define	AU_WIRED_SR(TYPE,BYTES)						\
586void									\
587__CONCAT(au_wired_sr_,BYTES)(void *v,					\
588    bus_space_handle_t h, bus_size_t o, TYPE val,			\
589    bus_size_t cnt)							\
590{									\
591									\
592	while (cnt-- > 0) {						\
593		__CONCAT(au_wired_w_,BYTES)(v, h, o, val);		\
594		o += BYTES;						\
595	}								\
596}
597AU_WIRED_SR(uint8_t,1)
598AU_WIRED_SR(uint16_t,2)
599AU_WIRED_SR(uint32_t,4)
600AU_WIRED_SR(uint64_t,8)
601
602
603#define	AU_WIRED_C(TYPE,BYTES)						\
604void									\
605__CONCAT(au_wired_c_,BYTES)(void *v,					\
606    bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2,	\
607    bus_space_handle_t o2, bus_size_t cnt)				\
608{									\
609	volatile TYPE *src, *dst;					\
610	src = (volatile TYPE *)(h1 + o1);				\
611	dst = (volatile TYPE *)(h2 + o2);				\
612									\
613	if (src >= dst) {						\
614		while (cnt-- > 0)					\
615			*dst++ = *src++;				\
616	} else {							\
617		src += cnt - 1;						\
618		dst += cnt - 1;						\
619		while (cnt-- > 0)					\
620			*dst-- = *src--;				\
621	}								\
622}
623AU_WIRED_C(uint8_t,1)
624AU_WIRED_C(uint16_t,2)
625AU_WIRED_C(uint32_t,4)
626AU_WIRED_C(uint64_t,8)
627
628
629void
630au_wired_space_init(bus_space_tag_t bst, const char *name,
631    paddr_t paddr, bus_addr_t start, bus_size_t size, int flags)
632{
633	au_wired_cookie_t	*c;
634
635	c = kmem_zalloc(sizeof (struct au_wired_cookie), KM_SLEEP);
636	c->c_pbase = paddr;
637	c->c_name = name;
638	c->c_start = start;
639	c->c_size = size;
640
641	/* allocate extent manager */
642	c->c_extent = extent_create(name, start, start + size,
643	    (void *)c->c_exstore, sizeof (c->c_exstore), EX_NOWAIT);
644	if (c->c_extent == NULL)
645		panic("au_wired_space_init: %s: cannot create extent", name);
646
647#if	_BYTE_ORDER == _BIG_ENDIAN
648	if (flags & AU_WIRED_SPACE_LITTLE_ENDIAN) {
649		if (flags & AU_WIRED_SPACE_SWAP_HW)
650			c->c_hwswap = 1;
651		else
652			c->c_swswap = 1;
653	}
654
655#elif	_BYTE_ORDER == _LITTLE_ENDIAN
656	if (flags & AU_WIRED_SPACE_BIG_ENDIAN) {
657		if (flags & AU_WIRED_SPACE_SWAP_HW)
658			c->c_hwswap = 1;
659		else
660			c->c_swswap = 1;
661	}
662#endif
663
664	bst->bs_cookie = c;
665	bst->bs_map = au_wired_map;
666	bst->bs_unmap = au_wired_unmap;
667	bst->bs_subregion = au_wired_subregion;
668	bst->bs_translate = NULL;	/* we don't use these */
669	bst->bs_get_window = NULL;	/* we don't use these */
670	bst->bs_alloc = au_wired_alloc;
671	bst->bs_free = au_wired_free;
672	bst->bs_vaddr = au_wired_vaddr;
673	bst->bs_mmap = au_wired_mmap;
674	bst->bs_barrier = au_wired_barrier;
675	bst->bs_r_1 = au_wired_r_1;
676	bst->bs_w_1 = au_wired_w_1;
677	bst->bs_r_2 = au_wired_r_2;
678	bst->bs_r_4 = au_wired_r_4;
679	bst->bs_r_8 = au_wired_r_8;
680	bst->bs_w_2 = au_wired_w_2;
681	bst->bs_w_4 = au_wired_w_4;
682	bst->bs_w_8 = au_wired_w_8;
683	bst->bs_rm_1 = au_wired_rm_1;
684	bst->bs_rm_2 = au_wired_rm_2;
685	bst->bs_rm_4 = au_wired_rm_4;
686	bst->bs_rm_8 = au_wired_rm_8;
687	bst->bs_rr_1 = au_wired_rr_1;
688	bst->bs_rr_2 = au_wired_rr_2;
689	bst->bs_rr_4 = au_wired_rr_4;
690	bst->bs_rr_8 = au_wired_rr_8;
691	bst->bs_wm_1 = au_wired_wm_1;
692	bst->bs_wm_2 = au_wired_wm_2;
693	bst->bs_wm_4 = au_wired_wm_4;
694	bst->bs_wm_8 = au_wired_wm_8;
695	bst->bs_wr_1 = au_wired_wr_1;
696	bst->bs_wr_2 = au_wired_wr_2;
697	bst->bs_wr_4 = au_wired_wr_4;
698	bst->bs_wr_8 = au_wired_wr_8;
699	bst->bs_sm_1 = au_wired_sm_1;
700	bst->bs_sm_2 = au_wired_sm_2;
701	bst->bs_sm_4 = au_wired_sm_4;
702	bst->bs_sm_8 = au_wired_sm_8;
703	bst->bs_sr_1 = au_wired_sr_1;
704	bst->bs_sr_2 = au_wired_sr_2;
705	bst->bs_sr_4 = au_wired_sr_4;
706	bst->bs_sr_8 = au_wired_sr_8;
707	bst->bs_c_1 = au_wired_c_1;
708	bst->bs_c_2 = au_wired_c_2;
709	bst->bs_c_4 = au_wired_c_4;
710	bst->bs_c_8 = au_wired_c_8;
711
712	bst->bs_rs_1 = au_wired_r_1;
713	bst->bs_rs_2 = au_wired_rs_2;
714	bst->bs_rs_4 = au_wired_rs_4;
715	bst->bs_rs_8 = au_wired_rs_8;
716	bst->bs_rms_1 = au_wired_rm_1;
717	bst->bs_rms_2 = au_wired_rms_2;
718	bst->bs_rms_4 = au_wired_rms_4;
719	bst->bs_rms_8 = au_wired_rms_8;
720	bst->bs_rrs_1 = au_wired_rr_1;
721	bst->bs_rrs_2 = au_wired_rrs_2;
722	bst->bs_rrs_4 = au_wired_rrs_4;
723	bst->bs_rrs_8 = au_wired_rrs_8;
724	bst->bs_ws_1 = au_wired_w_1;
725	bst->bs_ws_2 = au_wired_ws_2;
726	bst->bs_ws_4 = au_wired_ws_4;
727	bst->bs_ws_8 = au_wired_ws_8;
728	bst->bs_wms_1 = au_wired_wm_1;
729	bst->bs_wms_2 = au_wired_wms_2;
730	bst->bs_wms_4 = au_wired_wms_4;
731	bst->bs_wms_8 = au_wired_wms_8;
732	bst->bs_wrs_1 = au_wired_wr_1;
733	bst->bs_wrs_2 = au_wired_wrs_2;
734	bst->bs_wrs_4 = au_wired_wrs_4;
735	bst->bs_wrs_8 = au_wired_wrs_8;
736}
737