bus.h revision 32517
132517Sgibbs/*	$NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $	*/
232517Sgibbs
332517Sgibbs/*-
432517Sgibbs * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
532517Sgibbs * All rights reserved.
632517Sgibbs *
732517Sgibbs * This code is derived from software contributed to The NetBSD Foundation
832517Sgibbs * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
932517Sgibbs * NASA Ames Research Center.
1032517Sgibbs *
1132517Sgibbs * Redistribution and use in source and binary forms, with or without
1232517Sgibbs * modification, are permitted provided that the following conditions
1332517Sgibbs * are met:
1432517Sgibbs * 1. Redistributions of source code must retain the above copyright
1532517Sgibbs *    notice, this list of conditions and the following disclaimer.
1632517Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
1732517Sgibbs *    notice, this list of conditions and the following disclaimer in the
1832517Sgibbs *    documentation and/or other materials provided with the distribution.
1932517Sgibbs * 3. All advertising materials mentioning features or use of this software
2032517Sgibbs *    must display the following acknowledgement:
2132517Sgibbs *	This product includes software developed by the NetBSD
2232517Sgibbs *	Foundation, Inc. and its contributors.
2332517Sgibbs * 4. Neither the name of The NetBSD Foundation nor the names of its
2432517Sgibbs *    contributors may be used to endorse or promote products derived
2532517Sgibbs *    from this software without specific prior written permission.
2632517Sgibbs *
2732517Sgibbs * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2832517Sgibbs * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2932517Sgibbs * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
3032517Sgibbs * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
3132517Sgibbs * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3232517Sgibbs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3332517Sgibbs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3432517Sgibbs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3532517Sgibbs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3632517Sgibbs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3732517Sgibbs * POSSIBILITY OF SUCH DAMAGE.
3832517Sgibbs */
3932517Sgibbs
4032517Sgibbs/*
4132517Sgibbs * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
4232517Sgibbs * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
4332517Sgibbs *
4432517Sgibbs * Redistribution and use in source and binary forms, with or without
4532517Sgibbs * modification, are permitted provided that the following conditions
4632517Sgibbs * are met:
4732517Sgibbs * 1. Redistributions of source code must retain the above copyright
4832517Sgibbs *    notice, this list of conditions and the following disclaimer.
4932517Sgibbs * 2. Redistributions in binary form must reproduce the above copyright
5032517Sgibbs *    notice, this list of conditions and the following disclaimer in the
5132517Sgibbs *    documentation and/or other materials provided with the distribution.
5232517Sgibbs * 3. All advertising materials mentioning features or use of this software
5332517Sgibbs *    must display the following acknowledgement:
5432517Sgibbs *      This product includes software developed by Christopher G. Demetriou
5532517Sgibbs *	for the NetBSD Project.
5632517Sgibbs * 4. The name of the author may not be used to endorse or promote products
5732517Sgibbs *    derived from this software without specific prior written permission
5832517Sgibbs *
5932517Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
6032517Sgibbs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
6132517Sgibbs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
6232517Sgibbs * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
6332517Sgibbs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
6432517Sgibbs * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6532517Sgibbs * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6632517Sgibbs * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6732517Sgibbs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
6832517Sgibbs * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6932517Sgibbs */
7032517Sgibbs/* $Id$ */
7132517Sgibbs
7232517Sgibbs#ifndef _I386_BUS_H_
7332517Sgibbs#define _I386_BUS_H_
7432517Sgibbs
7532517Sgibbs#include <machine/cpufunc.h>
7632517Sgibbs
7732517Sgibbs/*
7832517Sgibbs * Values for the i386 bus space tag, not to be used directly by MI code.
7932517Sgibbs */
8032517Sgibbs#define	I386_BUS_SPACE_IO	0	/* space is i/o space */
8132517Sgibbs#define I386_BUS_SPACE_MEM	1	/* space is mem space */
8232517Sgibbs
8332517Sgibbs/*
8432517Sgibbs * Bus address and size types
8532517Sgibbs */
8632517Sgibbstypedef u_long bus_addr_t;
8732517Sgibbstypedef u_long bus_size_t;
8832517Sgibbs
8932517Sgibbs#define BUS_SPACE_MAXSIZE_24BIT	0xFFFFFF
9032517Sgibbs#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
9132517Sgibbs#define BUS_SPACE_MAXSIZE	(64 * 1024) /* Maximum supported size */
9232517Sgibbs#define BUS_SPACE_MAXADDR_24BIT	0xFFFFFF
9332517Sgibbs#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
9432517Sgibbs#define BUS_SPACE_MAXADDR	0xFFFFFFFF
9532517Sgibbs
9632517Sgibbs/*
9732517Sgibbs * Access methods for bus resources and address space.
9832517Sgibbs */
9932517Sgibbstypedef	int bus_space_tag_t;
10032517Sgibbstypedef	u_long bus_space_handle_t;
10132517Sgibbs
10232517Sgibbs/*
10332517Sgibbs * Map a region of device bus space into CPU virtual address space.
10432517Sgibbs */
10532517Sgibbs
10632517Sgibbs#define	BUS_SPACE_MAP_CACHEABLE		0x01
10732517Sgibbs#define	BUS_SPACE_MAP_LINEAR		0x02
10832517Sgibbs
10932517Sgibbsint	bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
11032517Sgibbs		      int flags, bus_space_handle_t *bshp);
11132517Sgibbs
11232517Sgibbs/*
11332517Sgibbs * Unmap a region of device bus space.
11432517Sgibbs */
11532517Sgibbs
11632517Sgibbsvoid	bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
11732517Sgibbs			bus_size_t size);
11832517Sgibbs
11932517Sgibbs/*
12032517Sgibbs * Get a new handle for a subregion of an already-mapped area of bus space.
12132517Sgibbs */
12232517Sgibbs
12332517Sgibbsint	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
12432517Sgibbs			    bus_size_t offset, bus_size_t size,
12532517Sgibbs			    bus_space_handle_t *nbshp);
12632517Sgibbs
12732517Sgibbs/*
12832517Sgibbs * Allocate a region of memory that is accessible to devices in bus space.
12932517Sgibbs */
13032517Sgibbs
13132517Sgibbsint	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
13232517Sgibbs			bus_addr_t rend, bus_size_t size, bus_size_t align,
13332517Sgibbs			bus_size_t boundary, int flags, bus_addr_t *addrp,
13432517Sgibbs			bus_space_handle_t *bshp);
13532517Sgibbs
13632517Sgibbs/*
13732517Sgibbs * Free a region of bus space accessible memory.
13832517Sgibbs */
13932517Sgibbs
14032517Sgibbsvoid	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
14132517Sgibbs		       bus_size_t size);
14232517Sgibbs
14332517Sgibbs#if defined(_I386_BUS_PIO_H_) || defined(_I386_BUS_MEMIO_H_)
14432517Sgibbs
14532517Sgibbs/*
14632517Sgibbs * Read a 1, 2, 4, or 8 byte quantity from bus space
14732517Sgibbs * described by tag/handle/offset.
14832517Sgibbs */
14932517Sgibbsstatic __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
15032517Sgibbs					  bus_space_handle_t handle,
15132517Sgibbs					  bus_size_t offset);
15232517Sgibbs
15332517Sgibbsstatic __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
15432517Sgibbs					   bus_space_handle_t handle,
15532517Sgibbs					   bus_size_t offset);
15632517Sgibbs
15732517Sgibbsstatic __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
15832517Sgibbs					   bus_space_handle_t handle,
15932517Sgibbs					   bus_size_t offset);
16032517Sgibbs
16132517Sgibbsstatic __inline u_int8_t
16232517Sgibbsbus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
16332517Sgibbs		 bus_size_t offset)
16432517Sgibbs{
16532517Sgibbs#if defined (_I386_BUS_PIO_H_)
16632517Sgibbs#if defined (_I386_BUS_MEMIO_H_)
16732517Sgibbs	if (tag == I386_BUS_SPACE_IO)
16832517Sgibbs#endif
16932517Sgibbs		return (inb(handle + offset));
17032517Sgibbs#endif
17132517Sgibbs#if defined (_I386_BUS_MEMIO_H_)
17232517Sgibbs	return (*(volatile u_int8_t *)(handle + offset));
17332517Sgibbs#endif
17432517Sgibbs}
17532517Sgibbs
17632517Sgibbsstatic __inline u_int16_t
17732517Sgibbsbus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
17832517Sgibbs		 bus_size_t offset)
17932517Sgibbs{
18032517Sgibbs#if defined(_I386_BUS_PIO_H_)
18132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
18232517Sgibbs	if (tag == I386_BUS_SPACE_IO)
18332517Sgibbs#endif
18432517Sgibbs		return (inw(handle + offset));
18532517Sgibbs#endif
18632517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
18732517Sgibbs	return (*(volatile u_int16_t *)(handle + offset));
18832517Sgibbs#endif
18932517Sgibbs}
19032517Sgibbs
19132517Sgibbsstatic __inline u_int32_t
19232517Sgibbsbus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
19332517Sgibbs		 bus_size_t offset)
19432517Sgibbs{
19532517Sgibbs#if defined(_I386_BUS_PIO_H_)
19632517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
19732517Sgibbs	if (tag == I386_BUS_SPACE_IO)
19832517Sgibbs#endif
19932517Sgibbs		return (inl(handle + offset));
20032517Sgibbs#endif
20132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
20232517Sgibbs	return (*(volatile u_int32_t *)(handle + offset));
20332517Sgibbs#endif
20432517Sgibbs}
20532517Sgibbs
20632517Sgibbs#if 0	/* Cause a link error for bus_space_read_8 */
20732517Sgibbs#define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
20832517Sgibbs#endif
20932517Sgibbs
21032517Sgibbs/*
21132517Sgibbs * Read `count' 1, 2, 4, or 8 byte quantities from bus space
21232517Sgibbs * described by tag/handle/offset and copy into buffer provided.
21332517Sgibbs */
21432517Sgibbsstatic __inline void bus_space_read_multi_1(bus_space_tag_t tag,
21532517Sgibbs					    bus_space_handle_t bsh,
21632517Sgibbs					    bus_size_t offset, u_int8_t *addr,
21732517Sgibbs					    size_t count);
21832517Sgibbs
21932517Sgibbsstatic __inline void bus_space_read_multi_2(bus_space_tag_t tag,
22032517Sgibbs					    bus_space_handle_t bsh,
22132517Sgibbs					    bus_size_t offset, u_int16_t *addr,
22232517Sgibbs					    size_t count);
22332517Sgibbs
22432517Sgibbsstatic __inline void bus_space_read_multi_4(bus_space_tag_t tag,
22532517Sgibbs					    bus_space_handle_t bsh,
22632517Sgibbs					    bus_size_t offset, u_int32_t *addr,
22732517Sgibbs					    size_t count);
22832517Sgibbs
22932517Sgibbsstatic __inline void
23032517Sgibbsbus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
23132517Sgibbs		       bus_size_t offset, u_int8_t *addr, size_t count)
23232517Sgibbs{
23332517Sgibbs#if defined(_I386_BUS_PIO_H_)
23432517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
23532517Sgibbs	if (tag == I386_BUS_SPACE_IO)
23632517Sgibbs#endif
23732517Sgibbs		insb(bsh + offset, addr, count);
23832517Sgibbs#endif
23932517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
24032517Sgibbs#if defined(_I386_BUS_PIO_H_)
24132517Sgibbs	else
24232517Sgibbs#endif
24332517Sgibbs	{
24432517Sgibbs		int __x __asm__("%eax");
24532517Sgibbs		__asm __volatile("
24632517Sgibbs			cld					;
24732517Sgibbs		1:	movb (%1),%%al				;
24832517Sgibbs			stosb					;
24932517Sgibbs			loop 1b"				:
25032517Sgibbs		    "=&a" (__x)					:
25132517Sgibbs		    "r" (bsh + offset), "D" (addr), "c" (count)	:
25232517Sgibbs		    "%edi", "%ecx", "memory");
25332517Sgibbs	}
25432517Sgibbs#endif
25532517Sgibbs}
25632517Sgibbs
25732517Sgibbsstatic __inline void
25832517Sgibbsbus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
25932517Sgibbs		       bus_size_t offset, u_int16_t *addr, size_t count)
26032517Sgibbs{
26132517Sgibbs#if defined(_I386_BUS_PIO_H_)
26232517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
26332517Sgibbs	if (tag == I386_BUS_SPACE_IO)
26432517Sgibbs#endif
26532517Sgibbs		insw(bsh + offset, addr, count);
26632517Sgibbs#endif
26732517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
26832517Sgibbs#if defined(_I386_BUS_PIO_H_)
26932517Sgibbs	else
27032517Sgibbs#endif
27132517Sgibbs	{
27232517Sgibbs		int __x __asm__("%eax");
27332517Sgibbs		__asm __volatile("
27432517Sgibbs			cld					;
27532517Sgibbs		1:	movw (%1),%%ax				;
27632517Sgibbs			stosw					;
27732517Sgibbs			loop 1b"				:
27832517Sgibbs		    "=&a" (__x)					:
27932517Sgibbs		    "r" (bsh + offset), "D" (addr), "c" (count)	:
28032517Sgibbs		    "%edi", "%ecx", "memory");
28132517Sgibbs	}
28232517Sgibbs#endif
28332517Sgibbs}
28432517Sgibbs
28532517Sgibbsstatic __inline void
28632517Sgibbsbus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
28732517Sgibbs		       bus_size_t offset, u_int32_t *addr, size_t count)
28832517Sgibbs{
28932517Sgibbs#if defined(_I386_BUS_PIO_H_)
29032517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
29132517Sgibbs	if (tag == I386_BUS_SPACE_IO)
29232517Sgibbs#endif
29332517Sgibbs		insl(bsh + offset, addr, count);
29432517Sgibbs#endif
29532517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
29632517Sgibbs#if defined(_I386_BUS_PIO_H_)
29732517Sgibbs	else
29832517Sgibbs#endif
29932517Sgibbs	{
30032517Sgibbs		int __x __asm__("%eax");
30132517Sgibbs		__asm __volatile("
30232517Sgibbs			cld					;
30332517Sgibbs		1:	movl (%1),%%eax				;
30432517Sgibbs			stosl					;
30532517Sgibbs			loop 1b"				:
30632517Sgibbs		    "=&a" (__x)					:
30732517Sgibbs		    "r" (bsh + offset), "D" (addr), "c" (count)	:
30832517Sgibbs		    "%edi", "%ecx", "memory");
30932517Sgibbs	}
31032517Sgibbs#endif
31132517Sgibbs}
31232517Sgibbs
31332517Sgibbs#if 0	/* Cause a link error for bus_space_read_multi_8 */
31432517Sgibbs#define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
31532517Sgibbs#endif
31632517Sgibbs
31732517Sgibbs/*
31832517Sgibbs * Read `count' 1, 2, 4, or 8 byte quantities from bus space
31932517Sgibbs * described by tag/handle and starting at `offset' and copy into
32032517Sgibbs * buffer provided.
32132517Sgibbs */
32232517Sgibbsstatic __inline void bus_space_read_region_1(bus_space_tag_t tag,
32332517Sgibbs					     bus_space_handle_t bsh,
32432517Sgibbs					     bus_size_t offset, u_int8_t *addr,
32532517Sgibbs					     size_t count);
32632517Sgibbs
32732517Sgibbsstatic __inline void bus_space_read_region_2(bus_space_tag_t tag,
32832517Sgibbs					     bus_space_handle_t bsh,
32932517Sgibbs					     bus_size_t offset, u_int16_t *addr,
33032517Sgibbs					     size_t count);
33132517Sgibbs
33232517Sgibbsstatic __inline void bus_space_read_region_4(bus_space_tag_t tag,
33332517Sgibbs					     bus_space_handle_t bsh,
33432517Sgibbs					     bus_size_t offset, u_int32_t *addr,
33532517Sgibbs					     size_t count);
33632517Sgibbs
33732517Sgibbs
33832517Sgibbsstatic __inline void
33932517Sgibbsbus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
34032517Sgibbs			bus_size_t offset, u_int8_t *addr, size_t count)
34132517Sgibbs{
34232517Sgibbs#if defined(_I386_BUS_PIO_H_)
34332517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
34432517Sgibbs	if (tag == I386_BUS_SPACE_IO)
34532517Sgibbs#endif
34632517Sgibbs	{
34732517Sgibbs		int __x __asm__("%eax");
34832517Sgibbs		__asm __volatile("
34932517Sgibbs			cld					;
35032517Sgibbs		1:	inb %w1,%%al				;
35132517Sgibbs			stosb					;
35232517Sgibbs			incl %1					;
35332517Sgibbs			loop 1b"				:
35432517Sgibbs		    "=&a" (__x)					:
35532517Sgibbs		    "d" (bsh + offset), "D" (addr), "c" (count)	:
35632517Sgibbs		    "%edx", "%edi", "%ecx", "memory");
35732517Sgibbs	}
35832517Sgibbs#endif
35932517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
36032517Sgibbs#if defined(_I386_BUS_PIO_H_)
36132517Sgibbs	else
36232517Sgibbs#endif
36332517Sgibbs	{
36432517Sgibbs		__asm __volatile("
36532517Sgibbs			cld					;
36632517Sgibbs			repne					;
36732517Sgibbs			movsb"					:
36832517Sgibbs								:
36932517Sgibbs		    "S" (bsh + offset), "D" (addr), "c" (count)	:
37032517Sgibbs		    "%esi", "%edi", "%ecx", "memory");
37132517Sgibbs	}
37232517Sgibbs#endif
37332517Sgibbs}
37432517Sgibbs
37532517Sgibbsstatic __inline void
37632517Sgibbsbus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
37732517Sgibbs			bus_size_t offset, u_int16_t *addr, size_t count)
37832517Sgibbs{
37932517Sgibbs#if defined(_I386_BUS_PIO_H_)
38032517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
38132517Sgibbs	if (tag == I386_BUS_SPACE_IO)
38232517Sgibbs#endif
38332517Sgibbs	{
38432517Sgibbs		int __x __asm__("%eax");
38532517Sgibbs		__asm __volatile("
38632517Sgibbs			cld					;
38732517Sgibbs		1:	inw %w1,%%ax				;
38832517Sgibbs			stosw					;
38932517Sgibbs			addl $2,%1				;
39032517Sgibbs			loop 1b"				:
39132517Sgibbs		    "=&a" (__x)					:
39232517Sgibbs		    "d" (bsh + offset), "D" (addr), "c" (count)	:
39332517Sgibbs		    "%edx", "%edi", "%ecx", "memory");
39432517Sgibbs	}
39532517Sgibbs#endif
39632517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
39732517Sgibbs#if defined(_I386_BUS_PIO_H_)
39832517Sgibbs	else
39932517Sgibbs#endif
40032517Sgibbs	{
40132517Sgibbs		__asm __volatile("
40232517Sgibbs			cld					;
40332517Sgibbs			repne					;
40432517Sgibbs			movsw"					:
40532517Sgibbs								:
40632517Sgibbs		    "S" (bsh + offset), "D" (addr), "c" (count)	:
40732517Sgibbs		    "%esi", "%edi", "%ecx", "memory");
40832517Sgibbs	}
40932517Sgibbs#endif
41032517Sgibbs}
41132517Sgibbs
41232517Sgibbsstatic __inline void
41332517Sgibbsbus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
41432517Sgibbs			bus_size_t offset, u_int32_t *addr, size_t count)
41532517Sgibbs{
41632517Sgibbs#if defined(_I386_BUS_PIO_H_)
41732517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
41832517Sgibbs	if (tag == I386_BUS_SPACE_IO)
41932517Sgibbs#endif
42032517Sgibbs	{
42132517Sgibbs		int __x __asm__("%eax");
42232517Sgibbs		__asm __volatile("
42332517Sgibbs			cld					;
42432517Sgibbs		1:	inl %w1,%%eax				;
42532517Sgibbs			stosl					;
42632517Sgibbs			addl $4,%1				;
42732517Sgibbs			loop 1b"				:
42832517Sgibbs		    "=&a" (__x)					:
42932517Sgibbs		    "d" (bsh + offset), "D" (addr), "c" (count)	:
43032517Sgibbs		    "%edx", "%edi", "%ecx", "memory");
43132517Sgibbs	}
43232517Sgibbs#endif
43332517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
43432517Sgibbs#if defined(_I386_BUS_PIO_H_)
43532517Sgibbs	else
43632517Sgibbs#endif
43732517Sgibbs	{
43832517Sgibbs		__asm __volatile("
43932517Sgibbs			cld					;
44032517Sgibbs			repne					;
44132517Sgibbs			movsl"					:
44232517Sgibbs								:
44332517Sgibbs		    "S" (bsh + offset), "D" (addr), "c" (count)	:
44432517Sgibbs		    "%esi", "%edi", "%ecx", "memory");
44532517Sgibbs	}
44632517Sgibbs#endif
44732517Sgibbs}
44832517Sgibbs
44932517Sgibbs#if 0	/* Cause a link error for bus_space_read_region_8 */
45032517Sgibbs#define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
45132517Sgibbs#endif
45232517Sgibbs
45332517Sgibbs/*
45432517Sgibbs * Write the 1, 2, 4, or 8 byte value `value' to bus space
45532517Sgibbs * described by tag/handle/offset.
45632517Sgibbs */
45732517Sgibbs
45832517Sgibbsstatic __inline void bus_space_write_1(bus_space_tag_t tag,
45932517Sgibbs				       bus_space_handle_t bsh,
46032517Sgibbs				       bus_size_t offset, u_int8_t value);
46132517Sgibbs
46232517Sgibbsstatic __inline void bus_space_write_2(bus_space_tag_t tag,
46332517Sgibbs				       bus_space_handle_t bsh,
46432517Sgibbs				       bus_size_t offset, u_int16_t value);
46532517Sgibbs
46632517Sgibbsstatic __inline void bus_space_write_4(bus_space_tag_t tag,
46732517Sgibbs				       bus_space_handle_t bsh,
46832517Sgibbs				       bus_size_t offset, u_int32_t value);
46932517Sgibbs
47032517Sgibbsstatic __inline void
47132517Sgibbsbus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
47232517Sgibbs		       bus_size_t offset, u_int8_t value)
47332517Sgibbs{
47432517Sgibbs#if defined(_I386_BUS_PIO_H_)
47532517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
47632517Sgibbs	if (tag == I386_BUS_SPACE_IO)
47732517Sgibbs#endif
47832517Sgibbs		outb(bsh + offset, value);
47932517Sgibbs#endif
48032517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
48132517Sgibbs#if defined(_I386_BUS_PIO_H_)
48232517Sgibbs	else
48332517Sgibbs#endif
48432517Sgibbs		*(volatile u_int8_t *)(bsh + offset) = value;
48532517Sgibbs#endif
48632517Sgibbs}
48732517Sgibbs
48832517Sgibbsstatic __inline void
48932517Sgibbsbus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
49032517Sgibbs		       bus_size_t offset, u_int16_t value)
49132517Sgibbs{
49232517Sgibbs#if defined(_I386_BUS_PIO_H_)
49332517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
49432517Sgibbs	if (tag == I386_BUS_SPACE_IO)
49532517Sgibbs#endif
49632517Sgibbs		outw(bsh + offset, value);
49732517Sgibbs#endif
49832517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
49932517Sgibbs#if defined(_I386_BUS_PIO_H_)
50032517Sgibbs	else
50132517Sgibbs#endif
50232517Sgibbs		*(volatile u_int16_t *)(bsh + offset) = value;
50332517Sgibbs#endif
50432517Sgibbs}
50532517Sgibbs
50632517Sgibbsstatic __inline void
50732517Sgibbsbus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
50832517Sgibbs		       bus_size_t offset, u_int32_t value)
50932517Sgibbs{
51032517Sgibbs#if defined(_I386_BUS_PIO_H_)
51132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
51232517Sgibbs	if (tag == I386_BUS_SPACE_IO)
51332517Sgibbs#endif
51432517Sgibbs		outl(bsh + offset, value);
51532517Sgibbs#endif
51632517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
51732517Sgibbs#if defined(_I386_BUS_PIO_H_)
51832517Sgibbs	else
51932517Sgibbs#endif
52032517Sgibbs		*(volatile u_int32_t *)(bsh + offset) = value;
52132517Sgibbs#endif
52232517Sgibbs}
52332517Sgibbs
52432517Sgibbs#if 0	/* Cause a link error for bus_space_write_8 */
52532517Sgibbs#define	bus_space_write_8	!!! bus_space_write_8 not implemented !!!
52632517Sgibbs#endif
52732517Sgibbs
52832517Sgibbs/*
52932517Sgibbs * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
53032517Sgibbs * provided to bus space described by tag/handle/offset.
53132517Sgibbs */
53232517Sgibbs
53332517Sgibbsstatic __inline void bus_space_write_multi_1(bus_space_tag_t tag,
53432517Sgibbs					     bus_space_handle_t bsh,
53532517Sgibbs					     bus_size_t offset,
53632517Sgibbs					     const u_int8_t *addr,
53732517Sgibbs					     size_t count);
53832517Sgibbsstatic __inline void bus_space_write_multi_2(bus_space_tag_t tag,
53932517Sgibbs					     bus_space_handle_t bsh,
54032517Sgibbs					     bus_size_t offset,
54132517Sgibbs					     const u_int16_t *addr,
54232517Sgibbs					     size_t count);
54332517Sgibbs
54432517Sgibbsstatic __inline void bus_space_write_multi_4(bus_space_tag_t tag,
54532517Sgibbs					     bus_space_handle_t bsh,
54632517Sgibbs					     bus_size_t offset,
54732517Sgibbs					     const u_int32_t *addr,
54832517Sgibbs					     size_t count);
54932517Sgibbs
55032517Sgibbsstatic __inline void
55132517Sgibbsbus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
55232517Sgibbs			bus_size_t offset, const u_int8_t *addr, size_t count)
55332517Sgibbs{
55432517Sgibbs#if defined(_I386_BUS_PIO_H_)
55532517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
55632517Sgibbs	if (tag == I386_BUS_SPACE_IO)
55732517Sgibbs#endif
55832517Sgibbs		outsb(bsh + offset, addr, count);
55932517Sgibbs#endif
56032517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
56132517Sgibbs#if defined(_I386_BUS_PIO_H_)
56232517Sgibbs	else
56332517Sgibbs#endif
56432517Sgibbs	{
56532517Sgibbs		int __x __asm__("%eax");
56632517Sgibbs		__asm __volatile("
56732517Sgibbs			cld					;
56832517Sgibbs		1:	lodsb					;
56932517Sgibbs			movb %%al,(%1)				;
57032517Sgibbs			loop 1b"				:
57132517Sgibbs		    "=&a" (__x)					:
57232517Sgibbs		    "r" (bsh + offset), "S" (addr), "c" (count)	:
57332517Sgibbs		    "%esi", "%ecx");
57432517Sgibbs	}
57532517Sgibbs#endif
57632517Sgibbs}
57732517Sgibbs
57832517Sgibbsstatic __inline void
57932517Sgibbsbus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
58032517Sgibbs			bus_size_t offset, const u_int16_t *addr, size_t count)
58132517Sgibbs{
58232517Sgibbs#if defined(_I386_BUS_PIO_H_)
58332517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
58432517Sgibbs	if (tag == I386_BUS_SPACE_IO)
58532517Sgibbs#endif
58632517Sgibbs		outsw(bsh + offset, addr, count);
58732517Sgibbs#endif
58832517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
58932517Sgibbs#if defined(_I386_BUS_PIO_H_)
59032517Sgibbs	else
59132517Sgibbs#endif
59232517Sgibbs	{
59332517Sgibbs		int __x __asm__("%eax");
59432517Sgibbs		__asm __volatile("
59532517Sgibbs			cld					;
59632517Sgibbs		1:	lodsw					;
59732517Sgibbs			movw %%ax,(%1)				;
59832517Sgibbs			loop 1b"				:
59932517Sgibbs		    "=&a" (__x)					:
60032517Sgibbs		    "r" (bsh + offset), "S" (addr), "c" (count)	:
60132517Sgibbs		    "%esi", "%ecx");
60232517Sgibbs	}
60332517Sgibbs#endif
60432517Sgibbs}
60532517Sgibbs
60632517Sgibbsstatic __inline void
60732517Sgibbsbus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
60832517Sgibbs			bus_size_t offset, const u_int32_t *addr, size_t count)
60932517Sgibbs{
61032517Sgibbs#if defined(_I386_BUS_PIO_H_)
61132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
61232517Sgibbs	if (tag == I386_BUS_SPACE_IO)
61332517Sgibbs#endif
61432517Sgibbs		outsl(bsh + offset, addr, count);
61532517Sgibbs#endif
61632517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
61732517Sgibbs#if defined(_I386_BUS_PIO_H_)
61832517Sgibbs	else
61932517Sgibbs#endif
62032517Sgibbs	{
62132517Sgibbs		int __x __asm__("%eax");
62232517Sgibbs		__asm __volatile("
62332517Sgibbs			cld					;
62432517Sgibbs		1:	lodsl					;
62532517Sgibbs			movl %%eax,(%1)				;
62632517Sgibbs			loop 1b"				:
62732517Sgibbs		    "=&a" (__x)					:
62832517Sgibbs		    "r" (bsh + offset), "S" (addr), "c" (count)	:
62932517Sgibbs		    "%esi", "%ecx");
63032517Sgibbs	}
63132517Sgibbs#endif
63232517Sgibbs}
63332517Sgibbs
63432517Sgibbs#if 0	/* Cause a link error for bus_space_write_multi_8 */
63532517Sgibbs#define	bus_space_write_multi_8(t, h, o, a, c)				\
63632517Sgibbs			!!! bus_space_write_multi_8 unimplemented !!!
63732517Sgibbs#endif
63832517Sgibbs
63932517Sgibbs/*
64032517Sgibbs * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
64132517Sgibbs * to bus space described by tag/handle starting at `offset'.
64232517Sgibbs */
64332517Sgibbs
64432517Sgibbsstatic __inline void bus_space_write_region_1(bus_space_tag_t tag,
64532517Sgibbs					      bus_space_handle_t bsh,
64632517Sgibbs					      bus_size_t offset,
64732517Sgibbs					      const u_int8_t *addr,
64832517Sgibbs					      size_t count);
64932517Sgibbsstatic __inline void bus_space_write_region_2(bus_space_tag_t tag,
65032517Sgibbs					      bus_space_handle_t bsh,
65132517Sgibbs					      bus_size_t offset,
65232517Sgibbs					      const u_int16_t *addr,
65332517Sgibbs					      size_t count);
65432517Sgibbsstatic __inline void bus_space_write_region_4(bus_space_tag_t tag,
65532517Sgibbs					      bus_space_handle_t bsh,
65632517Sgibbs					      bus_size_t offset,
65732517Sgibbs					      const u_int32_t *addr,
65832517Sgibbs					      size_t count);
65932517Sgibbs
66032517Sgibbsstatic __inline void
66132517Sgibbsbus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
66232517Sgibbs			 bus_size_t offset, const u_int8_t *addr, size_t count)
66332517Sgibbs{
66432517Sgibbs#if defined(_I386_BUS_PIO_H_)
66532517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
66632517Sgibbs	if (tag == I386_BUS_SPACE_IO)
66732517Sgibbs#endif
66832517Sgibbs	{
66932517Sgibbs		int __x __asm__("%eax");
67032517Sgibbs		__asm __volatile("
67132517Sgibbs			cld					;
67232517Sgibbs		1:	lodsb					;
67332517Sgibbs			outb %%al,%w1				;
67432517Sgibbs			incl %1					;
67532517Sgibbs			loop 1b"				:
67632517Sgibbs		    "=&a" (__x)					:
67732517Sgibbs		    "d" (bsh + offset), "S" (addr), "c" (count)	:
67832517Sgibbs		    "%edx", "%esi", "%ecx", "memory");
67932517Sgibbs	}
68032517Sgibbs#endif
68132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
68232517Sgibbs#if defined(_I386_BUS_PIO_H_)
68332517Sgibbs	else
68432517Sgibbs#endif
68532517Sgibbs	{
68632517Sgibbs		__asm __volatile("
68732517Sgibbs			cld					;
68832517Sgibbs			repne					;
68932517Sgibbs			movsb"					:
69032517Sgibbs								:
69132517Sgibbs		    "D" (bsh + offset), "S" (addr), "c" (count)	:
69232517Sgibbs		    "%edi", "%esi", "%ecx", "memory");
69332517Sgibbs	}
69432517Sgibbs#endif
69532517Sgibbs}
69632517Sgibbs
69732517Sgibbsstatic __inline void
69832517Sgibbsbus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
69932517Sgibbs			 bus_size_t offset, const u_int16_t *addr, size_t count)
70032517Sgibbs{
70132517Sgibbs#if defined(_I386_BUS_PIO_H_)
70232517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
70332517Sgibbs	if (tag == I386_BUS_SPACE_IO)
70432517Sgibbs#endif
70532517Sgibbs	{
70632517Sgibbs		int __x __asm__("%eax");
70732517Sgibbs		__asm __volatile("
70832517Sgibbs			cld					;
70932517Sgibbs		1:	lodsw					;
71032517Sgibbs			outw %%ax,%w1				;
71132517Sgibbs			addl $2,%1				;
71232517Sgibbs			loop 1b"				:
71332517Sgibbs		    "=&a" (__x)					:
71432517Sgibbs		    "d" (bsh + offset), "S" (addr), "c" (count)	:
71532517Sgibbs		    "%edx", "%esi", "%ecx", "memory");
71632517Sgibbs	}
71732517Sgibbs#endif
71832517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
71932517Sgibbs#if defined(_I386_BUS_PIO_H_)
72032517Sgibbs	else
72132517Sgibbs#endif
72232517Sgibbs	{
72332517Sgibbs		__asm __volatile("
72432517Sgibbs			cld					;
72532517Sgibbs			repne					;
72632517Sgibbs			movsw"					:
72732517Sgibbs								:
72832517Sgibbs		    "D" (bsh + offset), "S" (addr), "c" (count)	:
72932517Sgibbs		    "%edi", "%esi", "%ecx", "memory");
73032517Sgibbs	}
73132517Sgibbs#endif
73232517Sgibbs}
73332517Sgibbs
73432517Sgibbsstatic __inline void
73532517Sgibbsbus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
73632517Sgibbs			 bus_size_t offset, const u_int32_t *addr, size_t count)
73732517Sgibbs{
73832517Sgibbs#if defined(_I386_BUS_PIO_H_)
73932517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
74032517Sgibbs	if (tag == I386_BUS_SPACE_IO)
74132517Sgibbs#endif
74232517Sgibbs	{
74332517Sgibbs		int __x __asm__("%eax");
74432517Sgibbs		__asm __volatile("
74532517Sgibbs			cld					;
74632517Sgibbs		1:	lodsl					;
74732517Sgibbs			outl %%eax,%w1				;
74832517Sgibbs			addl $4,%1				;
74932517Sgibbs			loop 1b"				:
75032517Sgibbs		    "=&a" (__x)					:
75132517Sgibbs		    "d" (bsh + offset), "S" (addr), "c" (count)	:
75232517Sgibbs		    "%edx", "%esi", "%ecx", "memory");
75332517Sgibbs	}
75432517Sgibbs#endif
75532517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
75632517Sgibbs#if defined(_I386_BUS_PIO_H_)
75732517Sgibbs	else
75832517Sgibbs#endif
75932517Sgibbs	{
76032517Sgibbs		__asm __volatile("
76132517Sgibbs			cld					;
76232517Sgibbs			repne					;
76332517Sgibbs			movsl"					:
76432517Sgibbs								:
76532517Sgibbs		    "D" (bsh + offset), "S" (addr), "c" (count)	:
76632517Sgibbs		    "%edi", "%esi", "%ecx", "memory");
76732517Sgibbs	}
76832517Sgibbs#endif
76932517Sgibbs}
77032517Sgibbs
77132517Sgibbs#if 0	/* Cause a link error for bus_space_write_region_8 */
77232517Sgibbs#define	bus_space_write_region_8					\
77332517Sgibbs			!!! bus_space_write_region_8 unimplemented !!!
77432517Sgibbs#endif
77532517Sgibbs
77632517Sgibbs/*
77732517Sgibbs * Write the 1, 2, 4, or 8 byte value `val' to bus space described
77832517Sgibbs * by tag/handle/offset `count' times.
77932517Sgibbs */
78032517Sgibbs
78132517Sgibbsstatic __inline void bus_space_set_multi_1(bus_space_tag_t tag,
78232517Sgibbs					   bus_space_handle_t bsh,
78332517Sgibbs					   bus_size_t offset,
78432517Sgibbs					   u_int8_t value, size_t count);
78532517Sgibbsstatic __inline void bus_space_set_multi_2(bus_space_tag_t tag,
78632517Sgibbs					   bus_space_handle_t bsh,
78732517Sgibbs					   bus_size_t offset,
78832517Sgibbs					   u_int16_t value, size_t count);
78932517Sgibbsstatic __inline void bus_space_set_multi_4(bus_space_tag_t tag,
79032517Sgibbs					   bus_space_handle_t bsh,
79132517Sgibbs					   bus_size_t offset,
79232517Sgibbs					   u_int32_t value, size_t count);
79332517Sgibbs
79432517Sgibbsstatic __inline void
79532517Sgibbsbus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
79632517Sgibbs		      bus_size_t offset, u_int8_t value, size_t count)
79732517Sgibbs{
79832517Sgibbs	bus_addr_t addr = bsh + offset;
79932517Sgibbs
80032517Sgibbs#if defined(_I386_BUS_PIO_H_)
80132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
80232517Sgibbs	if (tag == I386_BUS_SPACE_IO)
80332517Sgibbs#endif
80432517Sgibbs		while (count--)
80532517Sgibbs			outb(addr, value);
80632517Sgibbs#endif
80732517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
80832517Sgibbs#if defined(_I386_BUS_PIO_H_)
80932517Sgibbs	else
81032517Sgibbs#endif
81132517Sgibbs		while (count--)
81232517Sgibbs			*(volatile u_int8_t *)(addr) = value;
81332517Sgibbs#endif
81432517Sgibbs}
81532517Sgibbs
81632517Sgibbsstatic __inline void
81732517Sgibbsbus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
81832517Sgibbs		     bus_size_t offset, u_int16_t value, size_t count)
81932517Sgibbs{
82032517Sgibbs	bus_addr_t addr = bsh + offset;
82132517Sgibbs
82232517Sgibbs#if defined(_I386_BUS_PIO_H_)
82332517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
82432517Sgibbs	if (tag == I386_BUS_SPACE_IO)
82532517Sgibbs#endif
82632517Sgibbs		while (count--)
82732517Sgibbs			outw(addr, value);
82832517Sgibbs#endif
82932517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
83032517Sgibbs#if defined(_I386_BUS_PIO_H_)
83132517Sgibbs	else
83232517Sgibbs#endif
83332517Sgibbs		while (count--)
83432517Sgibbs			*(volatile u_int16_t *)(addr) = value;
83532517Sgibbs#endif
83632517Sgibbs}
83732517Sgibbs
83832517Sgibbsstatic __inline void
83932517Sgibbsbus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
84032517Sgibbs		      bus_size_t offset, u_int32_t value, size_t count)
84132517Sgibbs{
84232517Sgibbs	bus_addr_t addr = bsh + offset;
84332517Sgibbs
84432517Sgibbs#if defined(_I386_BUS_PIO_H_)
84532517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
84632517Sgibbs	if (tag == I386_BUS_SPACE_IO)
84732517Sgibbs#endif
84832517Sgibbs		while (count--)
84932517Sgibbs			outl(addr, value);
85032517Sgibbs#endif
85132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
85232517Sgibbs#if defined(_I386_BUS_PIO_H_)
85332517Sgibbs	else
85432517Sgibbs#endif
85532517Sgibbs		while (count--)
85632517Sgibbs			*(volatile u_int32_t *)(addr) = value;
85732517Sgibbs#endif
85832517Sgibbs}
85932517Sgibbs
86032517Sgibbs#if 0	/* Cause a link error for bus_space_set_multi_8 */
86132517Sgibbs#define	bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
86232517Sgibbs#endif
86332517Sgibbs
86432517Sgibbs/*
86532517Sgibbs * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
86632517Sgibbs * by tag/handle starting at `offset'.
86732517Sgibbs */
86832517Sgibbs
86932517Sgibbsstatic __inline void bus_space_set_region_1(bus_space_tag_t tag,
87032517Sgibbs					    bus_space_handle_t bsh,
87132517Sgibbs					    bus_size_t offset, u_int8_t value,
87232517Sgibbs					    size_t count);
87332517Sgibbsstatic __inline void bus_space_set_region_2(bus_space_tag_t tag,
87432517Sgibbs					    bus_space_handle_t bsh,
87532517Sgibbs					    bus_size_t offset, u_int16_t value,
87632517Sgibbs					    size_t count);
87732517Sgibbsstatic __inline void bus_space_set_region_4(bus_space_tag_t tag,
87832517Sgibbs					    bus_space_handle_t bsh,
87932517Sgibbs					    bus_size_t offset, u_int32_t value,
88032517Sgibbs					    size_t count);
88132517Sgibbs
88232517Sgibbsstatic __inline void
88332517Sgibbsbus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
88432517Sgibbs		       bus_size_t offset, u_int8_t value, size_t count)
88532517Sgibbs{
88632517Sgibbs	bus_addr_t addr = bsh + offset;
88732517Sgibbs
88832517Sgibbs#if defined(_I386_BUS_PIO_H_)
88932517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
89032517Sgibbs	if (tag == I386_BUS_SPACE_IO)
89132517Sgibbs#endif
89232517Sgibbs		for (; count != 0; count--, addr++)
89332517Sgibbs			outb(addr, value);
89432517Sgibbs#endif
89532517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
89632517Sgibbs#if defined(_I386_BUS_PIO_H_)
89732517Sgibbs	else
89832517Sgibbs#endif
89932517Sgibbs		for (; count != 0; count--, addr++)
90032517Sgibbs			*(volatile u_int8_t *)(addr) = value;
90132517Sgibbs#endif
90232517Sgibbs}
90332517Sgibbs
90432517Sgibbsstatic __inline void
90532517Sgibbsbus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
90632517Sgibbs		       bus_size_t offset, u_int16_t value, size_t count)
90732517Sgibbs{
90832517Sgibbs	bus_addr_t addr = bsh + offset;
90932517Sgibbs
91032517Sgibbs#if defined(_I386_BUS_PIO_H_)
91132517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
91232517Sgibbs	if (tag == I386_BUS_SPACE_IO)
91332517Sgibbs#endif
91432517Sgibbs		for (; count != 0; count--, addr += 2)
91532517Sgibbs			outw(addr, value);
91632517Sgibbs#endif
91732517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
91832517Sgibbs#if defined(_I386_BUS_PIO_H_)
91932517Sgibbs	else
92032517Sgibbs#endif
92132517Sgibbs		for (; count != 0; count--, addr += 2)
92232517Sgibbs			*(volatile u_int16_t *)(addr) = value;
92332517Sgibbs#endif
92432517Sgibbs}
92532517Sgibbs
92632517Sgibbsstatic __inline void
92732517Sgibbsbus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
92832517Sgibbs		       bus_size_t offset, u_int32_t value, size_t count)
92932517Sgibbs{
93032517Sgibbs	bus_addr_t addr = bsh + offset;
93132517Sgibbs
93232517Sgibbs#if defined(_I386_BUS_PIO_H_)
93332517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
93432517Sgibbs	if (tag == I386_BUS_SPACE_IO)
93532517Sgibbs#endif
93632517Sgibbs		for (; count != 0; count--, addr += 4)
93732517Sgibbs			outl(addr, value);
93832517Sgibbs#endif
93932517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
94032517Sgibbs#if defined(_I386_BUS_PIO_H_)
94132517Sgibbs	else
94232517Sgibbs#endif
94332517Sgibbs		for (; count != 0; count--, addr += 4)
94432517Sgibbs			*(volatile u_int32_t *)(addr) = value;
94532517Sgibbs#endif
94632517Sgibbs}
94732517Sgibbs
94832517Sgibbs#if 0	/* Cause a link error for bus_space_set_region_8 */
94932517Sgibbs#define	bus_space_set_region_8	!!! bus_space_set_region_8 unimplemented !!!
95032517Sgibbs#endif
95132517Sgibbs
95232517Sgibbs/*
95332517Sgibbs * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
95432517Sgibbs * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
95532517Sgibbs */
95632517Sgibbs
95732517Sgibbsstatic __inline void bus_space_copy_region_1(bus_space_tag_t tag,
95832517Sgibbs					     bus_space_handle_t bsh1,
95932517Sgibbs					     bus_size_t off1,
96032517Sgibbs					     bus_space_handle_t bsh2,
96132517Sgibbs					     bus_size_t off2, size_t count);
96232517Sgibbs
96332517Sgibbsstatic __inline void bus_space_copy_region_2(bus_space_tag_t tag,
96432517Sgibbs					     bus_space_handle_t bsh1,
96532517Sgibbs					     bus_size_t off1,
96632517Sgibbs					     bus_space_handle_t bsh2,
96732517Sgibbs					     bus_size_t off2, size_t count);
96832517Sgibbs
96932517Sgibbsstatic __inline void bus_space_copy_region_4(bus_space_tag_t tag,
97032517Sgibbs					     bus_space_handle_t bsh1,
97132517Sgibbs					     bus_size_t off1,
97232517Sgibbs					     bus_space_handle_t bsh2,
97332517Sgibbs					     bus_size_t off2, size_t count);
97432517Sgibbs
97532517Sgibbsstatic __inline void
97632517Sgibbsbus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
97732517Sgibbs			bus_size_t off1, bus_space_handle_t bsh2,
97832517Sgibbs			bus_size_t off2, size_t count)
97932517Sgibbs{
98032517Sgibbs	bus_addr_t addr1 = bsh1 + off1;
98132517Sgibbs	bus_addr_t addr2 = bsh2 + off2;
98232517Sgibbs
98332517Sgibbs#if defined(_I386_BUS_PIO_H_)
98432517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
98532517Sgibbs	if (tag == I386_BUS_SPACE_IO)
98632517Sgibbs#endif
98732517Sgibbs	{
98832517Sgibbs		if (addr1 >= addr2) {
98932517Sgibbs			/* src after dest: copy forward */
99032517Sgibbs			for (; count != 0; count--, addr1++, addr2++)
99132517Sgibbs				outb(addr2, inb(addr1));
99232517Sgibbs		} else {
99332517Sgibbs			/* dest after src: copy backwards */
99432517Sgibbs			for (addr1 += (count - 1), addr2 += (count - 1);
99532517Sgibbs			    count != 0; count--, addr1--, addr2--)
99632517Sgibbs				outb(addr2, inb(addr1));
99732517Sgibbs		}
99832517Sgibbs	}
99932517Sgibbs#endif
100032517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
100132517Sgibbs#if defined(_I386_BUS_PIO_H_)
100232517Sgibbs	else
100332517Sgibbs#endif
100432517Sgibbs	{
100532517Sgibbs		if (addr1 >= addr2) {
100632517Sgibbs			/* src after dest: copy forward */
100732517Sgibbs			for (; count != 0; count--, addr1++, addr2++)
100832517Sgibbs				*(volatile u_int8_t *)(addr2) =
100932517Sgibbs				    *(volatile u_int8_t *)(addr1);
101032517Sgibbs		} else {
101132517Sgibbs			/* dest after src: copy backwards */
101232517Sgibbs			for (addr1 += (count - 1), addr2 += (count - 1);
101332517Sgibbs			    count != 0; count--, addr1--, addr2--)
101432517Sgibbs				*(volatile u_int8_t *)(addr2) =
101532517Sgibbs				    *(volatile u_int8_t *)(addr1);
101632517Sgibbs		}
101732517Sgibbs	}
101832517Sgibbs#endif
101932517Sgibbs}
102032517Sgibbs
102132517Sgibbsstatic __inline void
102232517Sgibbsbus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
102332517Sgibbs			bus_size_t off1, bus_space_handle_t bsh2,
102432517Sgibbs			bus_size_t off2, size_t count)
102532517Sgibbs{
102632517Sgibbs	bus_addr_t addr1 = bsh1 + off1;
102732517Sgibbs	bus_addr_t addr2 = bsh2 + off2;
102832517Sgibbs
102932517Sgibbs#if defined(_I386_BUS_PIO_H_)
103032517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
103132517Sgibbs	if (tag == I386_BUS_SPACE_IO)
103232517Sgibbs#endif
103332517Sgibbs	{
103432517Sgibbs		if (addr1 >= addr2) {
103532517Sgibbs			/* src after dest: copy forward */
103632517Sgibbs			for (; count != 0; count--, addr1 += 2, addr2 += 2)
103732517Sgibbs				outw(addr2, inw(addr1));
103832517Sgibbs		} else {
103932517Sgibbs			/* dest after src: copy backwards */
104032517Sgibbs			for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
104132517Sgibbs			    count != 0; count--, addr1 -= 2, addr2 -= 2)
104232517Sgibbs				outw(addr2, inw(addr1));
104332517Sgibbs		}
104432517Sgibbs	}
104532517Sgibbs#endif
104632517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
104732517Sgibbs#if defined(_I386_BUS_PIO_H_)
104832517Sgibbs	else
104932517Sgibbs#endif
105032517Sgibbs	{
105132517Sgibbs		if (addr1 >= addr2) {
105232517Sgibbs			/* src after dest: copy forward */
105332517Sgibbs			for (; count != 0; count--, addr1 += 2, addr2 += 2)
105432517Sgibbs				*(volatile u_int16_t *)(addr2) =
105532517Sgibbs				    *(volatile u_int16_t *)(addr1);
105632517Sgibbs		} else {
105732517Sgibbs			/* dest after src: copy backwards */
105832517Sgibbs			for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
105932517Sgibbs			    count != 0; count--, addr1 -= 2, addr2 -= 2)
106032517Sgibbs				*(volatile u_int16_t *)(addr2) =
106132517Sgibbs				    *(volatile u_int16_t *)(addr1);
106232517Sgibbs		}
106332517Sgibbs	}
106432517Sgibbs#endif
106532517Sgibbs}
106632517Sgibbs
106732517Sgibbsstatic __inline void
106832517Sgibbsbus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
106932517Sgibbs			bus_size_t off1, bus_space_handle_t bsh2,
107032517Sgibbs			bus_size_t off2, size_t count)
107132517Sgibbs{
107232517Sgibbs	bus_addr_t addr1 = bsh1 + off1;
107332517Sgibbs	bus_addr_t addr2 = bsh2 + off2;
107432517Sgibbs
107532517Sgibbs#if defined(_I386_BUS_PIO_H_)
107632517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
107732517Sgibbs	if (tag == I386_BUS_SPACE_IO)
107832517Sgibbs#endif
107932517Sgibbs	{
108032517Sgibbs		if (addr1 >= addr2) {
108132517Sgibbs			/* src after dest: copy forward */
108232517Sgibbs			for (; count != 0; count--, addr1 += 4, addr2 += 4)
108332517Sgibbs				outl(addr2, inl(addr1));
108432517Sgibbs		} else {
108532517Sgibbs			/* dest after src: copy backwards */
108632517Sgibbs			for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
108732517Sgibbs			    count != 0; count--, addr1 -= 4, addr2 -= 4)
108832517Sgibbs				outl(addr2, inl(addr1));
108932517Sgibbs		}
109032517Sgibbs	}
109132517Sgibbs#endif
109232517Sgibbs#if defined(_I386_BUS_MEMIO_H_)
109332517Sgibbs#if defined(_I386_BUS_PIO_H_)
109432517Sgibbs	else
109532517Sgibbs#endif
109632517Sgibbs	{
109732517Sgibbs		if (addr1 >= addr2) {
109832517Sgibbs			/* src after dest: copy forward */
109932517Sgibbs			for (; count != 0; count--, addr1 += 4, addr2 += 4)
110032517Sgibbs				*(volatile u_int32_t *)(addr2) =
110132517Sgibbs				    *(volatile u_int32_t *)(addr1);
110232517Sgibbs		} else {
110332517Sgibbs			/* dest after src: copy backwards */
110432517Sgibbs			for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
110532517Sgibbs			    count != 0; count--, addr1 -= 4, addr2 -= 4)
110632517Sgibbs				*(volatile u_int32_t *)(addr2) =
110732517Sgibbs				    *(volatile u_int32_t *)(addr1);
110832517Sgibbs		}
110932517Sgibbs	}
111032517Sgibbs#endif
111132517Sgibbs}
111232517Sgibbs
111332517Sgibbs#endif /* defined(_I386_BUS_PIO_H_) || defined(_I386_MEM_IO_H_) */
111432517Sgibbs
111532517Sgibbs#if 0	/* Cause a link error for bus_space_copy_8 */
111632517Sgibbs#define	bus_space_copy_region_8	!!! bus_space_copy_region_8 unimplemented !!!
111732517Sgibbs#endif
111832517Sgibbs
111932517Sgibbs/*
112032517Sgibbs * Bus read/write barrier methods.
112132517Sgibbs *
112232517Sgibbs *	void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
112332517Sgibbs *			       bus_size_t offset, bus_size_t len, int flags);
112432517Sgibbs *
112532517Sgibbs * Note: the i386 does not currently require barriers, but we must
112632517Sgibbs * provide the flags to MI code.
112732517Sgibbs */
112832517Sgibbs#define	bus_space_barrier(t, h, o, l, f)	\
112932517Sgibbs	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
113032517Sgibbs#define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
113132517Sgibbs#define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
113232517Sgibbs
113332517Sgibbs/*
113432517Sgibbs * Flags used in various bus DMA methods.
113532517Sgibbs */
113632517Sgibbs#define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
113732517Sgibbs#define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
113832517Sgibbs#define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
113932517Sgibbs#define	BUS_DMAMEM_NOSYNC	0x04	/* map memory to not require sync */
114032517Sgibbs#define	BUS_DMA_BUS1		0x10	/* placeholders for bus functions... */
114132517Sgibbs#define	BUS_DMA_BUS2		0x20
114232517Sgibbs#define	BUS_DMA_BUS3		0x40
114332517Sgibbs#define	BUS_DMA_BUS4		0x80
114432517Sgibbs
114532517Sgibbs/* Forwards needed by prototypes below. */
114632517Sgibbsstruct mbuf;
114732517Sgibbsstruct uio;
114832517Sgibbs
114932517Sgibbs/*
115032517Sgibbs *	bus_dmasync_op_t
115132517Sgibbs *
115232517Sgibbs *	Operations performed by bus_dmamap_sync().
115332517Sgibbs */
115432517Sgibbstypedef enum {
115532517Sgibbs	BUS_DMASYNC_PREREAD,
115632517Sgibbs	BUS_DMASYNC_POSTREAD,
115732517Sgibbs	BUS_DMASYNC_PREWRITE,
115832517Sgibbs	BUS_DMASYNC_POSTWRITE,
115932517Sgibbs} bus_dmasync_op_t;
116032517Sgibbs
116132517Sgibbs/*
116232517Sgibbs *	bus_dma_tag_t
116332517Sgibbs *
116432517Sgibbs *	A machine-dependent opaque type describing the characteristics
116532517Sgibbs *	of how to perform DMA mappings.  This structure encapsultes
116632517Sgibbs *	information concerning address and alignment restrictions, number
116732517Sgibbs *	of S/G	segments, amount of data per S/G segment, etc.
116832517Sgibbs */
116932517Sgibbstypedef struct bus_dma_tag	*bus_dma_tag_t;
117032517Sgibbs
117132517Sgibbs/*
117232517Sgibbs *	bus_dmamap_t
117332517Sgibbs *
117432517Sgibbs *	DMA mapping instance information.
117532517Sgibbs */
117632517Sgibbstypedef struct bus_dmamap	*bus_dmamap_t;
117732517Sgibbs
117832517Sgibbs/*
117932517Sgibbs *	bus_dma_segment_t
118032517Sgibbs *
118132517Sgibbs *	Describes a single contiguous DMA transaction.  Values
118232517Sgibbs *	are suitable for programming into DMA registers.
118332517Sgibbs */
118432517Sgibbstypedef struct bus_dma_segment {
118532517Sgibbs	bus_addr_t	ds_addr;	/* DMA address */
118632517Sgibbs	bus_size_t	ds_len;		/* length of transfer */
118732517Sgibbs} bus_dma_segment_t;
118832517Sgibbs
118932517Sgibbs/*
119032517Sgibbs * A function that returns 1 if the address cannot be accessed by
119132517Sgibbs * a device and 0 if it can be.
119232517Sgibbs */
119332517Sgibbstypedef int bus_dma_filter_t(void *, bus_addr_t);
119432517Sgibbs
119532517Sgibbs/*
119632517Sgibbs * Allocate a device specific dma_tag encapsulating the constraints of
119732517Sgibbs * the parent tag in addition to other restrictions specified:
119832517Sgibbs *
119932517Sgibbs *	boundary:	Boundary that segments cannot cross.
120032517Sgibbs *	lowaddr:	Low restricted address that cannot appear in a mapping.
120132517Sgibbs *	highaddr:	High restricted address that cannot appear in a mapping.
120232517Sgibbs *	filtfunc:	An optional function to further test if an address
120332517Sgibbs *			within the range of lowaddr and highaddr cannot appear
120432517Sgibbs *			in a mapping.
120532517Sgibbs *	filtfuncarg:	An argument that will be passed to filtfunc in addition
120632517Sgibbs *			to the address to test.
120732517Sgibbs *	flags:		Bus DMA flags.
120832517Sgibbs *	dmat:		A pointer to set to a valid dma tag should the return
120932517Sgibbs *			value of this function indicate success.
121032517Sgibbs */
121132517Sgibbsint bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t boundary,
121232517Sgibbs		       bus_addr_t lowaddr, bus_addr_t highaddr,
121332517Sgibbs		       bus_dma_filter_t *filtfunc, void *filtfuncarg,
121432517Sgibbs		       bus_size_t maxsize, int nsegments, bus_size_t maxsegsz,
121532517Sgibbs		       int flags, bus_dma_tag_t *dmat);
121632517Sgibbs
121732517Sgibbsint bus_dma_tag_destroy(bus_dma_tag_t dmat);
121832517Sgibbs
121932517Sgibbs/*
122032517Sgibbs * Allocate a handle for mapping from kva/uva/physical
122132517Sgibbs * address space into bus device space.
122232517Sgibbs *
122332517Sgibbs *	maxsize:	Maximum mapping size supported by this handle.
122432517Sgibbs *	nsegments:	Number of discontinuities allowed in the map.
122532517Sgibbs *	maxsegsz:	Maximum size of a segment in the map.
122632517Sgibbs */
122732517Sgibbsint bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
122832517Sgibbs
122932517Sgibbs/*
123032517Sgibbs * Destroy  a handle for mapping from kva/uva/physical
123132517Sgibbs * address space into bus device space.
123232517Sgibbs */
123332517Sgibbsint bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map);
123432517Sgibbs
123532517Sgibbs/*
123632517Sgibbs * A function that processes a successfully loaded dma map or an error
123732517Sgibbs * from a delayed load map.
123832517Sgibbs */
123932517Sgibbstypedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
124032517Sgibbs
124132517Sgibbs/*
124232517Sgibbs * Map the buffer buf into bus space using the dmamap map.
124332517Sgibbs */
124432517Sgibbsint bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
124532517Sgibbs		    bus_size_t buflen, bus_dmamap_callback_t *callback,
124632517Sgibbs		    void *callback_arg, int flags);
124732517Sgibbs
124832517Sgibbs/*
124932517Sgibbs * Perform a syncronization operation on the given map.
125032517Sgibbs */
125132517Sgibbsvoid _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
125232517Sgibbs#define bus_dmamap_sync(dmat, dmamap, op) 		\
125332517Sgibbs	if ((dmamap) != NULL)				\
125432517Sgibbs		_bus_dmamap_sync(dmat, dmamap, op)
125532517Sgibbs
125632517Sgibbs/*
125732517Sgibbs * Release the mapping held by map.
125832517Sgibbs */
125932517Sgibbsvoid _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
126032517Sgibbs#define bus_dmamap_unload(dmat, dmamap) 		\
126132517Sgibbs	if ((dmamap) != NULL)				\
126232517Sgibbs		_bus_dmamap_unload(dmat, dmamap)
126332517Sgibbs
126432517Sgibbs#endif /* _I386_BUS_H_ */
1265