1/*	$NetBSD: bus.h,v 1.19 2019/09/23 16:17:58 skrll Exp $	*/
2
3/*-
4 * Copyright (c) 1996, 1997, 1998, 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 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
35 * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 *    must display the following acknowledgement:
47 *      This product includes software developed by Christopher G. Demetriou
48 *	for the NetBSD Project.
49 * 4. The name of the author may not be used to endorse or promote products
50 *    derived from this software without specific prior written permission
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62 */
63
64#ifndef _SUN68K_BUS_H_
65#define _SUN68K_BUS_H_
66
67#define	SUN68K_BUS_SPACE	0
68
69/*
70 * Bus address and size types
71 */
72typedef	u_long	bus_space_handle_t;
73typedef u_long	bus_type_t;
74typedef u_long	bus_addr_t;
75typedef u_long	bus_size_t;
76
77#define PRIxBSH		"lx"
78#define PRIxBUSADDR	"lx"
79#define PRIxBUSSIZE	"lx"
80#define PRIuBUSSIZE	"lu"
81
82#define	BUS_ADDR_PADDR(x)	((x) & 0xffffffff)
83
84/*
85 * Access methods for bus resources and address space.
86 */
87typedef struct sun68k_bus_space_tag	*bus_space_tag_t;
88
89struct sun68k_bus_space_tag {
90	void		*cookie;
91	bus_space_tag_t	parent;
92
93	int	(*sun68k_bus_map)(
94				bus_space_tag_t,
95				bus_type_t,
96				bus_addr_t,
97				bus_size_t,
98				int,			/*flags*/
99				vaddr_t,		/*preferred vaddr*/
100				bus_space_handle_t *);
101
102	int	(*sun68k_bus_unmap)(
103				bus_space_tag_t,
104				bus_space_handle_t,
105				bus_size_t);
106
107	int	(*sun68k_bus_subregion)(
108				bus_space_tag_t,
109				bus_space_handle_t,
110				bus_size_t,		/*offset*/
111				bus_size_t,		/*size*/
112				bus_space_handle_t *);
113
114	void	(*sun68k_bus_barrier)(
115				bus_space_tag_t,
116				bus_space_handle_t,
117				bus_size_t,		/*offset*/
118				bus_size_t,		/*size*/
119				int);			/*flags*/
120
121	paddr_t	(*sun68k_bus_mmap)(
122				bus_space_tag_t,
123				bus_type_t,		/**/
124				bus_addr_t,		/**/
125				off_t,			/*offset*/
126				int,			/*prot*/
127				int);			/*flags*/
128
129	void	*(*sun68k_intr_establish)(
130				bus_space_tag_t,
131				int,			/*bus-specific intr*/
132				int,			/*device class level,
133							  see machine/intr.h*/
134				int,			/*flags*/
135				int (*)(void *),	/*handler*/
136				void *);		/*handler arg*/
137
138	int	(*sun68k_bus_peek)(
139				bus_space_tag_t,
140				bus_space_handle_t,
141				bus_size_t,		/*offset*/
142				size_t,			/*probe size*/
143				void *);		/*result ptr*/
144
145	int	(*sun68k_bus_poke)(
146				bus_space_tag_t,
147				bus_space_handle_t,
148				bus_size_t,		/*offset*/
149				size_t,			/*probe size*/
150				uint32_t);		/*value*/
151};
152
153#if 0
154/*
155 * The following macro could be used to generate the bus_space*() functions
156 * but it uses a gcc extension and is ANSI-only.
157#define PROTO_bus_space_xxx		(bus_space_tag_t t, ...)
158#define RETURNTYPE_bus_space_xxx	void *
159#define BUSFUN(name, returntype, t, args...)			\
160	__inline RETURNTYPE_##name				\
161	bus_##name PROTO_##name					\
162	{							\
163		while (t->sun68k_##name == NULL)			\
164			t = t->parent;				\
165		return (*(t)->sun68k_##name)(t, args);		\
166	}
167 */
168#endif
169
170/*
171 * Bus space function prototypes.
172 */
173static int	bus_space_map(
174				bus_space_tag_t,
175				bus_addr_t,
176				bus_size_t,
177				int,			/*flags*/
178				bus_space_handle_t *);
179static int	bus_space_map2(
180				bus_space_tag_t,
181				bus_type_t,
182				bus_addr_t,
183				bus_size_t,
184				int,			/*flags*/
185				vaddr_t,		/*preferred vaddr*/
186				bus_space_handle_t *);
187static int	bus_space_unmap(
188				bus_space_tag_t,
189				bus_space_handle_t,
190				bus_size_t);
191static int	bus_space_subregion(
192				bus_space_tag_t,
193				bus_space_handle_t,
194				bus_size_t,
195				bus_size_t,
196				bus_space_handle_t *);
197static void	bus_space_barrier(
198				bus_space_tag_t,
199				bus_space_handle_t,
200				bus_size_t,
201				bus_size_t,
202				int);
203static paddr_t	bus_space_mmap(
204				bus_space_tag_t,
205				bus_addr_t,		/**/
206				off_t,			/*offset*/
207				int,			/*prot*/
208				int);			/*flags*/
209static paddr_t	bus_space_mmap2(
210				bus_space_tag_t,
211				bus_type_t,
212				bus_addr_t,		/**/
213				off_t,			/*offset*/
214				int,			/*prot*/
215				int);			/*flags*/
216static void	*bus_intr_establish(
217				bus_space_tag_t,
218				int,			/*bus-specific intr*/
219				int,			/*device class level,
220							  see machine/intr.h*/
221				int,			/*flags*/
222				int (*)(void *),	/*handler*/
223				void *);		/*handler arg*/
224static int	_bus_space_peek(
225				bus_space_tag_t,
226				bus_space_handle_t,
227				bus_size_t,		/*offset*/
228				size_t,			/*probe size*/
229				void *);		/*result ptr*/
230static int	_bus_space_poke(
231				bus_space_tag_t,
232				bus_space_handle_t,
233				bus_size_t,		/*offset*/
234				size_t,			/*probe size*/
235				uint32_t);		/*value*/
236
237/* This macro finds the first "upstream" implementation of method `f' */
238#define _BS_CALL(t,f)			\
239	while (t->f == NULL)		\
240		t = t->parent;		\
241	return (*(t)->f)
242
243static __inline int
244bus_space_map(bus_space_tag_t t, bus_addr_t a, bus_size_t s, int f,
245    bus_space_handle_t *hp)
246{
247	_BS_CALL(t, sun68k_bus_map)((t), 0, (a), (s), (f), 0, (hp));
248}
249
250static __inline int
251bus_space_map2(bus_space_tag_t t, bus_type_t bt, bus_addr_t a, bus_size_t s,
252    int f, vaddr_t v, bus_space_handle_t *hp)
253{
254	_BS_CALL(t, sun68k_bus_map)(t, bt, a, s, f, v, hp);
255}
256
257static __inline int
258bus_space_unmap(bus_space_tag_t t, bus_space_handle_t h, bus_size_t s)
259{
260	_BS_CALL(t, sun68k_bus_unmap)(t, h, s);
261}
262
263static __inline int
264bus_space_subregion(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
265    bus_size_t s, bus_space_handle_t *hp)
266{
267	_BS_CALL(t, sun68k_bus_subregion)(t, h, o, s, hp);
268}
269
270static __inline paddr_t
271bus_space_mmap(bus_space_tag_t t, bus_addr_t a, off_t o, int p, int f)
272{
273	_BS_CALL(t, sun68k_bus_mmap)(t, 0, a, o, p, f);
274}
275
276static __inline paddr_t
277bus_space_mmap2(bus_space_tag_t	t, bus_type_t bt, bus_addr_t a, off_t o, int p,
278    int f)
279{
280	_BS_CALL(t, sun68k_bus_mmap)(t, bt, a, o, p, f);
281}
282
283static __inline void *
284bus_intr_establish(bus_space_tag_t t, int p, int l, int f, int (*h)(void *),
285    void *a)
286{
287	_BS_CALL(t, sun68k_intr_establish)(t, p, l, f, h, a);
288}
289
290static __inline void
291bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
292    bus_size_t s, int f)
293{
294	_BS_CALL(t, sun68k_bus_barrier)(t, h, o, s, f);
295}
296
297static __inline int
298_bus_space_peek(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, size_t s,
299    void *vp)
300{
301	_BS_CALL(t, sun68k_bus_peek)(t, h, o, s, vp);
302}
303
304static __inline int
305_bus_space_poke(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o, size_t s,
306    uint32_t v)
307{
308	_BS_CALL(t, sun68k_bus_poke)(t, h, o, s, v);
309}
310
311#if 0
312int	bus_space_alloc(bus_space_tag_t, bus_addr_t, bus_addr_t, bus_size_t,
313	    bus_size_t, bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
314void	bus_space_free(bus_space_tag_t, bus_space_handle_t, bus_size_t);
315#endif
316
317/*
318 *	void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
319 *
320 * Get the kernel virtual address for the mapped bus space.
321 * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
322 *  (XXX not enforced)
323 */
324#define bus_space_vaddr(t, h)	((void)(t), (void *)(h))
325
326/* flags for bus space map functions */
327#define BUS_SPACE_MAP_CACHEABLE	0x0001
328#define BUS_SPACE_MAP_LINEAR	0x0002
329#define BUS_SPACE_MAP_PREFETCHABLE	0x0004
330#define BUS_SPACE_MAP_BUS1	0x0100	/* placeholders for bus functions... */
331#define BUS_SPACE_MAP_BUS2	0x0200
332#define BUS_SPACE_MAP_BUS3	0x0400
333#define BUS_SPACE_MAP_BUS4	0x0800
334
335/* Internal flag: try to find and use a PROM maping for the device. */
336#define	_SUN68K_BUS_MAP_USE_PROM		BUS_SPACE_MAP_BUS1
337
338/* flags for intr_establish() */
339#define BUS_INTR_ESTABLISH_FASTTRAP	1
340#define BUS_INTR_ESTABLISH_SOFTINTR	2
341
342/* flags for bus_space_barrier() */
343#define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
344#define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
345
346/*
347 *	int bus_space_peek_N(bus_space_tag_t tag,
348 *	    bus_space_handle_t bsh, bus_size_t offset, u_intN_t *valuep);
349 *
350 * Cautiously read 1, 2, 4 or 8 byte quantity from bus space described
351 * by tag/handle/offset.
352 * If no hardware responds to the read access, the function returns a
353 * non-zero value. Otherwise the value read is placed in `valuep'.
354 */
355
356#define	bus_space_peek_1(t, h, o, vp)					\
357    _bus_space_peek(t, h, o, sizeof(uint8_t), (void *)vp)
358
359#define	bus_space_peek_2(t, h, o, vp)					\
360    _bus_space_peek(t, h, o, sizeof(uint16_t), (void *)vp)
361
362#define	bus_space_peek_4(t, h, o, vp)					\
363    _bus_space_peek(t, h, o, sizeof(uint32_t), (void *)vp)
364
365/*
366 *	int bus_space_poke_N(bus_space_tag_t tag,
367 *	    bus_space_handle_t bsh, bus_size_t offset, uintN_t value);
368 *
369 * Cautiously write 1, 2, 4 or 8 byte quantity to bus space described
370 * by tag/handle/offset.
371 * If no hardware responds to the write access, the function returns a
372 * non-zero value.
373 */
374
375#define	bus_space_poke_1(t, h, o, v)					\
376    _bus_space_poke(t, h, o, sizeof(uint8_t), v)
377
378#define	bus_space_poke_2(t, h, o, v)					\
379    _bus_space_poke(t, h, o, sizeof(uint16_t), v)
380
381#define	bus_space_poke_4(t, h, o, v)					\
382    _bus_space_poke(t, h, o, sizeof(uint32_t), v)
383
384/*
385 *	uintN_t bus_space_read_N(bus_space_tag_t tag,
386 *	    bus_space_handle_t bsh, bus_size_t offset);
387 *
388 * Read a 1, 2, 4, or 8 byte quantity from bus space
389 * described by tag/handle/offset.
390 */
391
392#define	bus_space_read_1(t, h, o)					\
393	    ((void)t, *(volatile uint8_t *)((h) + (o)))
394
395#define	bus_space_read_2(t, h, o)					\
396	    ((void)t, *(volatile uint16_t *)((h) + (o)))
397
398#define	bus_space_read_4(t, h, o)					\
399	    ((void)t, *(volatile uint32_t *)((h) + (o)))
400
401#define	bus_space_read_8(t, h, o)					\
402	    ((void)t, *(volatile uint64_t *)((h) + (o)))
403
404
405/*
406 *	void bus_space_write_N(bus_space_tag_t tag,
407 *	    bus_space_handle_t bsh, bus_size_t offset,
408 *	    uintN_t value);
409 *
410 * Write the 1, 2, 4, or 8 byte value `value' to bus space
411 * described by tag/handle/offset.
412 */
413
414#define	bus_space_write_1(t, h, o, v)	do {				\
415	((void)t, (void)(*(volatile uint8_t *)((h) + (o)) = (v)));	\
416} while (0)
417
418#define	bus_space_write_2(t, h, o, v)	do {				\
419	((void)t, (void)(*(volatile uint16_t *)((h) + (o)) = (v)));	\
420} while (0)
421
422#define	bus_space_write_4(t, h, o, v)	do {				\
423	((void)t, (void)(*(volatile uint32_t *)((h) + (o)) = (v)));	\
424} while (0)
425
426#define	bus_space_write_8(t, h, o, v)	do {				\
427	((void)t, (void)(*(volatile uint64_t *)((h) + (o)) = (v)));	\
428} while (0)
429
430
431/*
432 *	void bus_space_read_multi_N(bus_space_tag_t tag,
433 *	    bus_space_handle_t bsh, bus_size_t offset,
434 *	    uintN_t *addr, bus_size_t count);
435 *
436 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
437 * described by tag/handle/offset and copy into buffer provided.
438 */
439
440static __inline void
441bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
442    uint8_t *a, bus_size_t c)
443{
444	volatile uint8_t *p;
445
446	p = (volatile uint8_t *)(h + o);
447	while (c-- > 0)
448		*a++ = *p;
449}
450
451static __inline void
452bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
453    uint16_t *a, bus_size_t c)
454{
455	volatile uint16_t *p;
456
457	p = (volatile uint16_t *)(h + o);
458	while (c-- > 0)
459		*a++ = *p;
460}
461
462static __inline void
463bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
464    uint32_t *a, bus_size_t c)
465{
466	volatile uint32_t *p;
467
468	p = (volatile uint32_t *)(h + o);
469	while (c-- > 0)
470		*a++ = *p;
471}
472
473static __inline void
474bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
475    uint64_t *a, bus_size_t c)
476{
477	volatile uint64_t *p;
478
479	p = (volatile uint64_t *)(h + o);
480	while (c-- > 0)
481		*a++ = *p;
482}
483
484
485/*
486 *	void bus_space_write_multi_N(bus_space_tag_t tag,
487 *	    bus_space_handle_t bsh, bus_size_t offset,
488 *	    const u_intN_t *addr, bus_size_t count);
489 *
490 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
491 * provided to bus space described by tag/handle/offset.
492 */
493
494static __inline void
495bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
496    const uint8_t *a, bus_size_t c)
497{
498	volatile uint8_t *p;
499
500	p = (volatile uint8_t *)(h + o);
501	while (c-- > 0)
502		*p = *a++;
503}
504
505static __inline void
506bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
507    const uint16_t *a, bus_size_t c)
508{
509	volatile uint16_t *p;
510
511	p = (volatile uint16_t *)(h + o);
512	while (c-- > 0)
513		*p = *a++;
514}
515
516static __inline void
517bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
518    const uint32_t *a, bus_size_t c)
519{
520	volatile uint32_t *p;
521
522	p = (volatile uint32_t *)(h + o);
523	while (c-- > 0)
524		*p = *a++;
525}
526
527static __inline void
528bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
529    const uint64_t *a, bus_size_t c)
530{
531	volatile uint64_t *p;
532
533	p = (volatile uint64_t *)(h + o);
534	while (c-- > 0)
535		*p = *a++;
536}
537
538/*
539 *	void bus_space_set_multi_N(bus_space_tag_t tag,
540 *	    bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
541 *	    bus_size_t count);
542 *
543 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
544 * by tag/handle/offset `count' times.
545 */
546
547static __inline void
548bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
549    const uint8_t v, bus_size_t c)
550{
551	volatile uint8_t *p;
552
553	p = (volatile uint8_t *)(h + o);
554	while (c-- > 0)
555		*p = v;
556}
557
558static __inline void
559bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
560    const uint16_t v, bus_size_t c)
561{
562	volatile uint16_t *p;
563
564	p = (volatile uint16_t *)(h + o);
565	while (c-- > 0)
566		*p = v;
567}
568
569static __inline void
570bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
571    const uint32_t v, bus_size_t c)
572{
573	volatile uint32_t *p;
574
575	p = (volatile uint32_t *)(h + o);
576	while (c-- > 0)
577		*p = v;
578}
579
580static __inline void
581bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
582    const uint64_t v, bus_size_t c)
583{
584	volatile uint64_t *p;
585
586	p = (volatile uint64_t *)(h + o);
587	while (c-- > 0)
588		*p = v;
589}
590
591
592/*
593 *	void bus_space_read_region_N(bus_space_tag_t tag,
594 *	    bus_space_handle_t bsh, bus_size_t off,
595 *	    uintN_t *addr, bus_size_t count);
596 *
597 */
598
599static __inline void
600bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
601    uint8_t *a, bus_size_t c)
602{
603	volatile uint8_t *p;
604
605	p = (volatile uint8_t *)(h + o);
606	while (c-- > 0)
607		*a++ = *p++;
608}
609static __inline void
610bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
611    uint16_t *a, bus_size_t c)
612{
613	volatile uint16_t *p;
614
615	p = (volatile uint16_t *)(h + o);
616	while (c-- > 0)
617		*a++ = *p++;
618}
619static __inline void
620bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
621    uint32_t *a, bus_size_t c)
622{
623	volatile uint32_t *p;
624
625	p = (volatile uint32_t *)(h + o);
626	while (c-- > 0)
627		*a++ = *p++;
628}
629static __inline void
630bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
631    uint64_t *a, bus_size_t c)
632{
633	volatile uint64_t *p;
634
635	p = (volatile uint64_t *)(h + o);
636	while (c-- > 0)
637		*a++ = *p++;
638}
639
640/*
641 *	void bus_space_write_region_N(bus_space_tag_t tag,
642 *	    bus_space_handle_t bsh, bus_size_t off,
643 *	    uintN_t *addr, bus_size_t count);
644 *
645 */
646
647static __inline void
648bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
649    const uint8_t *a, bus_size_t c)
650{
651	volatile uint8_t *p;
652
653	p = (volatile uint8_t *)(h + o);
654	while (c-- > 0)
655		*p++ = *a++;
656}
657
658static __inline void
659bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
660    const uint16_t *a, bus_size_t c)
661{
662	volatile uint16_t *p;
663
664	p = (volatile uint16_t *)(h + o);
665	while (c-- > 0)
666		*p++ = *a++;
667}
668
669static __inline void
670bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
671    const uint32_t *a, bus_size_t c)
672{
673	volatile uint32_t *p;
674
675	p = (volatile uint32_t *)(h + o);
676	while (c-- > 0)
677		*p++ = *a++;
678}
679
680static __inline void
681bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
682    const uint64_t *a, bus_size_t c)
683{
684	volatile uint64_t *p;
685
686	p = (volatile uint64_t *)(h + o);
687	while (c-- > 0)
688		*p++ = *a++;
689}
690
691
692/*
693 *	void bus_space_set_region_N(bus_space_tag_t tag,
694 *	    bus_space_handle_t bsh, bus_size_t off,
695 *	    uintN_t *addr, bus_size_t count);
696 *
697 */
698
699static __inline void
700bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
701    const uint8_t v, bus_size_t c)
702{
703	volatile uint8_t *p;
704
705	p = (volatile uint8_t *)(h + o);
706	while (c-- > 0)
707		*p++ = v;
708}
709
710static __inline void
711bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
712    const uint16_t v, bus_size_t c)
713{
714	volatile uint16_t *p;
715
716	p = (volatile uint16_t *)(h + o);
717	while (c-- > 0)
718		*p++ = v;
719}
720
721static __inline void
722bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
723    const uint32_t v, bus_size_t c)
724{
725	volatile uint32_t *p;
726
727	p = (volatile uint32_t *)(h + o);
728	while (c-- > 0)
729		*p++ = v;
730}
731
732static __inline void
733bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
734    const uint64_t v, bus_size_t c)
735{
736	volatile uint64_t *p;
737
738	p = (volatile uint64_t *)(h + o);
739	while (c-- > 0)
740		*p++ = v;
741}
742
743
744/*
745 *	void bus_space_copy_region_N(bus_space_tag_t tag,
746 *	    bus_space_handle_t bsh1, bus_size_t off1,
747 *	    bus_space_handle_t bsh2, bus_size_t off2,
748 *	    bus_size_t count);
749 *
750 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
751 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
752 */
753
754static __inline void
755bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
756    bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
757{
758	volatile uint8_t *srcp, *dstp;
759	bus_size_t offset;
760
761	srcp = (volatile uint8_t *)(h1 + o1);
762	dstp = (volatile uint8_t *)(h2 + o2);
763	if (srcp >= dstp) {
764		/* src after dest; copy forward */
765		for (offset = 0; c > 0; c--, offset++)
766			dstp[offset] = srcp[offset];
767	} else {
768		/* dst after src; copy backward */
769		for (offset = c; c > 0; c--, offset--)
770			dstp[offset] = srcp[offset];
771	}
772}
773
774static __inline void
775bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
776    bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
777{
778	volatile uint16_t *srcp, *dstp;
779	bus_size_t offset;
780
781	srcp = (volatile uint16_t *)(h1 + o1);
782	dstp = (volatile uint16_t *)(h2 + o2);
783	if (srcp >= dstp) {
784		/* src after dest; copy forward */
785		for (offset = 0; c > 0; c--, offset++)
786			dstp[offset] = srcp[offset];
787	} else {
788		/* dst after src; copy backward */
789		for (offset = c; c > 0; c--, offset--)
790			dstp[offset] = srcp[offset];
791	}
792}
793
794static __inline void
795bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
796    bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
797{
798	volatile uint32_t *srcp, *dstp;
799	bus_size_t offset;
800
801	srcp = (volatile uint32_t *)(h1 + o1);
802	dstp = (volatile uint32_t *)(h2 + o2);
803	if (srcp >= dstp) {
804		/* src after dest; copy forward */
805		for (offset = 0; c > 0; c--, offset++)
806			dstp[offset] = srcp[offset];
807	} else {
808		/* dst after src; copy backward */
809		for (offset = c; c > 0; c--, offset--)
810			dstp[offset] = srcp[offset];
811	}
812}
813
814static __inline void
815bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1, bus_size_t o1,
816    bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
817{
818	volatile uint64_t *srcp, *dstp;
819	bus_size_t offset;
820
821	srcp = (volatile uint64_t *)(h1 + o1);
822	dstp = (volatile uint64_t *)(h2 + o2);
823	if (srcp >= dstp) {
824		/* src after dest; copy forward */
825		for (offset = 0; c > 0; c--, offset++)
826			dstp[offset] = srcp[offset];
827	} else {
828		/* dst after src; copy backward */
829		for (offset = c; c > 0; c--, offset--)
830			dstp[offset] = srcp[offset];
831	}
832}
833
834/*
835 *	void bus_space_copyin(bus_space_tag_t tag,
836 *	    bus_space_handle_t bsh, bus_size_t off,
837 *	    void *addr, bus_size_t count);
838 *
839 * Copy `count' bytes from bus space starting at tag/bsh/off
840 * to kernel memory at addr using the most optimized transfer
841 * possible for the bus.
842 */
843
844#define	bus_space_copyin(t, h, o, a, c)					\
845	    ((void)t, w16copy((uint8_t *)((h) + (o)), (a), (c)))
846
847/*
848 *	void bus_space_copyout(bus_space_tag_t tag,
849 *	    bus_space_handle_t bsh, bus_size_t off,
850 *	    const void *addr, bus_size_t count);
851 *
852 * Copy `count' bytes to bus space starting at tag/bsh/off
853 * from kernel memory at addr using the most optimized transfer
854 * possible for the bus.
855 */
856
857#define	bus_space_copyout(t, h, o, a, c)				\
858	    ((void)t, w16copy((a), (uint8_t *)((h) + (o)), (c)))
859
860#define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
861
862int find_prom_map(paddr_t, bus_type_t, int, vaddr_t *);
863
864/*--------------------------------*/
865
866/*
867 * Flags used in various bus DMA methods.
868 */
869#define	BUS_DMA_WAITOK		0x000	/* safe to sleep (pseudo-flag) */
870#define	BUS_DMA_NOWAIT		0x001	/* not safe to sleep */
871#define	BUS_DMA_ALLOCNOW	0x002	/* perform resource allocation now */
872#define	BUS_DMA_COHERENT	0x004	/* hint: map memory DMA coherent */
873#define	BUS_DMA_BUS1		0x010	/* placeholders for bus functions... */
874#define	BUS_DMA_BUS2		0x020
875#define	BUS_DMA_BUS3		0x040
876#define	BUS_DMA_BUS4		0x080
877#define	BUS_DMA_READ		0x100	/* mapping is device -> memory only */
878#define	BUS_DMA_WRITE		0x200	/* mapping is memory -> device only */
879#define	BUS_DMA_NOCACHE		0x400	/* hint: map non-cached memory */
880
881/* For devices that have a 24-bit address space */
882#define BUS_DMA_24BIT		BUS_DMA_BUS1
883
884/* Internal flag: current DVMA address is equal to the KVA buffer address */
885#define _BUS_DMA_DIRECTMAP	BUS_DMA_BUS2
886
887/*
888 * Internal flag: current DVMA address has been double-mapped by hand
889 * to the KVA buffer address (without the pmap's help).
890 */
891#define	_BUS_DMA_NOPMAP		BUS_DMA_BUS3
892
893/* Forwards needed by prototypes below. */
894struct mbuf;
895struct uio;
896
897/*
898 * Operations performed by bus_dmamap_sync().
899 */
900#define	BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
901#define	BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
902#define	BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
903#define	BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
904
905typedef struct sun68k_bus_dma_tag	*bus_dma_tag_t;
906typedef struct sun68k_bus_dmamap	*bus_dmamap_t;
907
908#define BUS_DMA_TAG_VALID(t)    ((t) != NULL)
909
910/*
911 *	bus_dma_segment_t
912 *
913 *	Describes a single contiguous DMA transaction.  Values
914 *	are suitable for programming into DMA registers.
915 */
916struct sun68k_bus_dma_segment {
917	bus_addr_t	ds_addr;	/* DVMA address */
918	bus_size_t	ds_len;		/* length of transfer */
919	bus_size_t	_ds_sgsize;	/* size of allocated DVMA segment */
920	void		*_ds_mlist;	/* page list when dmamem_alloc'ed */
921	vaddr_t		_ds_va;		/* VA when dmamem_map'ed */
922};
923typedef struct sun68k_bus_dma_segment	bus_dma_segment_t;
924
925
926/*
927 *	bus_dma_tag_t
928 *
929 *	A machine-dependent opaque type describing the implementation of
930 *	DMA for a given bus.
931 */
932struct sun68k_bus_dma_tag {
933	void	*_cookie;		/* cookie used in the guts */
934
935	/*
936	 * DMA mapping methods.
937	 */
938	int	(*_dmamap_create)(bus_dma_tag_t, bus_size_t, int, bus_size_t,
939		    bus_size_t, int, bus_dmamap_t *);
940	void	(*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
941	int	(*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
942		    struct proc *, int);
943	int	(*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t, struct mbuf *,
944		    int);
945	int	(*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t, struct uio *,
946		    int);
947	int	(*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
948		    bus_dma_segment_t *, int, bus_size_t, int);
949	void	(*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
950	void	(*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
951		    bus_size_t, int);
952
953	/*
954	 * DMA memory utility functions.
955	 */
956	int	(*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
957		    bus_size_t, bus_dma_segment_t *, int, int *, int);
958	void	(*_dmamem_free)(bus_dma_tag_t, bus_dma_segment_t *, int);
959	int	(*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *, int, size_t,
960		    void **, int);
961	void	(*_dmamem_unmap)(bus_dma_tag_t, void *, size_t);
962	paddr_t	(*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *, int, off_t,
963		    int, int);
964};
965
966#define	bus_dmamap_create(t, s, n, m, b, f, p)			\
967	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
968#define	bus_dmamap_destroy(t, p)				\
969	(*(t)->_dmamap_destroy)((t), (p))
970#define	bus_dmamap_load(t, m, b, s, p, f)			\
971	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
972#define	bus_dmamap_load_mbuf(t, m, b, f)			\
973	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
974#define	bus_dmamap_load_uio(t, m, u, f)				\
975	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
976#define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
977	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
978#define	bus_dmamap_unload(t, p)					\
979	(*(t)->_dmamap_unload)((t), (p))
980#define	bus_dmamap_sync(t, p, o, l, ops)			\
981	(void)((t)->_dmamap_sync ?				\
982	    (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
983
984#define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
985	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
986#define	bus_dmamem_free(t, sg, n)				\
987	(*(t)->_dmamem_free)((t), (sg), (n))
988#define	bus_dmamem_map(t, sg, n, s, k, f)			\
989	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
990#define	bus_dmamem_unmap(t, k, s)				\
991	(*(t)->_dmamem_unmap)((t), (k), (s))
992#define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
993	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
994
995#define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP
996#define bus_dmatag_destroy(t)
997
998/*
999 *	bus_dmamap_t
1000 *
1001 *	Describes a DMA mapping.
1002 */
1003struct sun68k_bus_dmamap {
1004	/*
1005	 * PRIVATE MEMBERS: not for use by machine-independent code.
1006	 */
1007	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
1008	int		_dm_segcnt;	/* number of segs this map can map */
1009	bus_size_t	_dm_maxmaxsegsz; /* fixed largest possible segment */
1010	bus_size_t	_dm_boundary;	/* don't cross this */
1011	int		_dm_flags;	/* misc. flags */
1012
1013	void		*_dm_cookie;	/* cookie for bus-specific functions */
1014
1015	u_long		_dm_align;	/* DVMA alignment; must be a
1016					   multiple of the page size */
1017	u_long		_dm_ex_start;	/* constraints on DVMA map */
1018	u_long		_dm_ex_end;	/* allocations; used by the VME bus
1019					   driver and by the IOMMU driver
1020					   when mapping 24-bit devices */
1021
1022	/*
1023	 * PUBLIC MEMBERS: these are used by machine-independent code.
1024	 */
1025	bus_size_t	dm_maxsegsz;	/* largest possible segment */
1026	bus_size_t	dm_mapsize;	/* size of the mapping */
1027	int		dm_nsegs;	/* # valid segments in mapping */
1028	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
1029};
1030
1031#ifdef _SUN68K_BUS_DMA_PRIVATE
1032int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
1033	    bus_size_t, int, bus_dmamap_t *);
1034void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
1035int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *, int);
1036int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
1037int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *,
1038	    int, bus_size_t, int);
1039int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
1040	    struct proc *, int);
1041void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
1042void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t, bus_size_t,
1043	    int);
1044
1045int	_bus_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t,
1046	    bus_dma_segment_t *, int, int *, int);
1047void	_bus_dmamem_free(bus_dma_tag_t, bus_dma_segment_t *, int);
1048int	_bus_dmamem_map(bus_dma_tag_t, bus_dma_segment_t *, int, size_t,
1049	    void **, int);
1050void	_bus_dmamem_unmap(bus_dma_tag_t, void *, size_t);
1051paddr_t	_bus_dmamem_mmap(bus_dma_tag_t, bus_dma_segment_t *, int, off_t, int,
1052	    int);
1053
1054int	_bus_dmamem_alloc_range(bus_dma_tag_t, bus_size_t, bus_size_t,
1055	    bus_size_t, bus_dma_segment_t *, int, int *, int, vaddr_t, vaddr_t);
1056
1057vaddr_t	_bus_dma_valloc_skewed(size_t, u_long, u_long, u_long);
1058#endif /* _SUN68K_BUS_DMA_PRIVATE */
1059
1060#endif /* _SUN68K_BUS_H_ */
1061