xref: /openbsd/sys/arch/amd64/amd64/bus_space.c (revision e12dfaa1)
1*e12dfaa1Skettenis /*	$OpenBSD: bus_space.c,v 1.27 2022/06/29 07:44:10 kettenis Exp $	*/
2f5df1827Smickey /*	$NetBSD: bus_space.c,v 1.2 2003/03/14 18:47:53 christos Exp $	*/
3f5df1827Smickey 
4f5df1827Smickey /*-
5f5df1827Smickey  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
6f5df1827Smickey  * All rights reserved.
7f5df1827Smickey  *
8f5df1827Smickey  * This code is derived from software contributed to The NetBSD Foundation
9f5df1827Smickey  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
10f5df1827Smickey  * Simulation Facility, NASA Ames Research Center.
11f5df1827Smickey  *
12f5df1827Smickey  * Redistribution and use in source and binary forms, with or without
13f5df1827Smickey  * modification, are permitted provided that the following conditions
14f5df1827Smickey  * are met:
15f5df1827Smickey  * 1. Redistributions of source code must retain the above copyright
16f5df1827Smickey  *    notice, this list of conditions and the following disclaimer.
17f5df1827Smickey  * 2. Redistributions in binary form must reproduce the above copyright
18f5df1827Smickey  *    notice, this list of conditions and the following disclaimer in the
19f5df1827Smickey  *    documentation and/or other materials provided with the distribution.
20f5df1827Smickey  *
21f5df1827Smickey  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22f5df1827Smickey  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23f5df1827Smickey  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24f5df1827Smickey  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25f5df1827Smickey  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26f5df1827Smickey  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27f5df1827Smickey  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28f5df1827Smickey  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29f5df1827Smickey  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30f5df1827Smickey  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31f5df1827Smickey  * POSSIBILITY OF SUCH DAMAGE.
32f5df1827Smickey  */
33f5df1827Smickey 
34f5df1827Smickey #include <sys/param.h>
35f5df1827Smickey #include <sys/systm.h>
36f5df1827Smickey #include <sys/malloc.h>
37f5df1827Smickey #include <sys/extent.h>
38f5df1827Smickey 
39f5df1827Smickey #include <uvm/uvm_extern.h>
40f5df1827Smickey 
41f5df1827Smickey #include <machine/bus.h>
42f5df1827Smickey 
43f5df1827Smickey #include <dev/isa/isareg.h>
44f5df1827Smickey #include <machine/isa_machdep.h>
45f5df1827Smickey 
46*e12dfaa1Skettenis extern int pmap_initialized;
47*e12dfaa1Skettenis 
48f5df1827Smickey /*
49f5df1827Smickey  * Extent maps to manage I/O and memory space.  Allocate
5048cd2e59Smikeb  * storage for 16 regions in each, initially.  Later, ioport_malloc_safe
51f5df1827Smickey  * will indicate that it's safe to use malloc() to dynamically allocate
52f5df1827Smickey  * region descriptors.
53f5df1827Smickey  *
54f5df1827Smickey  * N.B. At least two regions are _always_ allocated from the iomem
55f5df1827Smickey  * extent map; (0 -> ISA hole) and (end of ISA hole -> end of RAM).
56f5df1827Smickey  *
57f5df1827Smickey  * The extent maps are not static!  Machine-dependent ISA and EISA
58f5df1827Smickey  * routines need access to them for bus address space allocation.
59f5df1827Smickey  */
6048cd2e59Smikeb static	long ioport_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
6148cd2e59Smikeb static	long iomem_ex_storage[EXTENT_FIXED_STORAGE_SIZE(16) / sizeof(long)];
62f5df1827Smickey struct	extent *ioport_ex;
63f5df1827Smickey struct	extent *iomem_ex;
64f5df1827Smickey static	int ioport_malloc_safe;
65f5df1827Smickey 
66f5df1827Smickey int	x86_mem_add_mapping(bus_addr_t, bus_size_t,
67f5df1827Smickey 	    int, bus_space_handle_t *);
68f5df1827Smickey 
6993c7b57cSdlg u_int8_t	x86_bus_space_io_read_1(bus_space_handle_t, bus_size_t);
7093c7b57cSdlg u_int16_t	x86_bus_space_io_read_2(bus_space_handle_t, bus_size_t);
7193c7b57cSdlg u_int32_t	x86_bus_space_io_read_4(bus_space_handle_t, bus_size_t);
7293c7b57cSdlg u_int64_t	x86_bus_space_io_read_8(bus_space_handle_t, bus_size_t);
7393c7b57cSdlg 
7493c7b57cSdlg void		x86_bus_space_io_read_multi_1(bus_space_handle_t, bus_size_t,
7593c7b57cSdlg 		    u_int8_t *, bus_size_t);
7693c7b57cSdlg void		x86_bus_space_io_read_multi_2(bus_space_handle_t, bus_size_t,
7793c7b57cSdlg 		    u_int16_t *, bus_size_t);
7893c7b57cSdlg void		x86_bus_space_io_read_multi_4(bus_space_handle_t, bus_size_t,
7993c7b57cSdlg 		    u_int32_t *, bus_size_t);
8093c7b57cSdlg void		x86_bus_space_io_read_multi_8(bus_space_handle_t, bus_size_t,
8193c7b57cSdlg 		    u_int64_t *, bus_size_t);
8293c7b57cSdlg 
8393c7b57cSdlg void		x86_bus_space_io_read_region_1(bus_space_handle_t, bus_size_t,
8493c7b57cSdlg 		    u_int8_t *, bus_size_t);
8593c7b57cSdlg void		x86_bus_space_io_read_region_2(bus_space_handle_t, bus_size_t,
8693c7b57cSdlg 		    u_int16_t *, bus_size_t);
8793c7b57cSdlg void		x86_bus_space_io_read_region_4(bus_space_handle_t, bus_size_t,
8893c7b57cSdlg 		    u_int32_t *, bus_size_t);
8993c7b57cSdlg void		x86_bus_space_io_read_region_8(bus_space_handle_t, bus_size_t,
9093c7b57cSdlg 		    u_int64_t *, bus_size_t);
9193c7b57cSdlg 
9293c7b57cSdlg void		x86_bus_space_io_write_1(bus_space_handle_t, bus_size_t,
9393c7b57cSdlg 		    u_int8_t);
9493c7b57cSdlg void		x86_bus_space_io_write_2(bus_space_handle_t, bus_size_t,
9593c7b57cSdlg 		    u_int16_t);
9693c7b57cSdlg void		x86_bus_space_io_write_4(bus_space_handle_t, bus_size_t,
9793c7b57cSdlg 		    u_int32_t);
9893c7b57cSdlg void		x86_bus_space_io_write_8(bus_space_handle_t, bus_size_t,
9993c7b57cSdlg 		    u_int64_t);
10093c7b57cSdlg 
10193c7b57cSdlg void		x86_bus_space_io_write_multi_1(bus_space_handle_t,
10293c7b57cSdlg 		    bus_size_t, const u_int8_t *, bus_size_t);
10393c7b57cSdlg void		x86_bus_space_io_write_multi_2(bus_space_handle_t,
10493c7b57cSdlg 		    bus_size_t, const u_int16_t *, bus_size_t);
10593c7b57cSdlg void		x86_bus_space_io_write_multi_4(bus_space_handle_t,
10693c7b57cSdlg 		    bus_size_t, const u_int32_t *, bus_size_t);
10793c7b57cSdlg void		x86_bus_space_io_write_multi_8(bus_space_handle_t,
10893c7b57cSdlg 		    bus_size_t, const u_int64_t *, bus_size_t);
10993c7b57cSdlg 
11093c7b57cSdlg void		x86_bus_space_io_write_region_1(bus_space_handle_t,
11193c7b57cSdlg 		    bus_size_t, const u_int8_t *, bus_size_t);
11293c7b57cSdlg void		x86_bus_space_io_write_region_2(bus_space_handle_t,
11393c7b57cSdlg 		    bus_size_t, const u_int16_t *, bus_size_t);
11493c7b57cSdlg void		x86_bus_space_io_write_region_4(bus_space_handle_t,
11593c7b57cSdlg 		    bus_size_t, const u_int32_t *, bus_size_t);
11693c7b57cSdlg void		x86_bus_space_io_write_region_8(bus_space_handle_t,
11793c7b57cSdlg 		    bus_size_t, const u_int64_t *, bus_size_t);
11893c7b57cSdlg 
11993c7b57cSdlg void		x86_bus_space_io_set_multi_1(bus_space_handle_t, bus_size_t,
12093c7b57cSdlg 		    u_int8_t, size_t);
12193c7b57cSdlg void		x86_bus_space_io_set_multi_2(bus_space_handle_t, bus_size_t,
12293c7b57cSdlg 		    u_int16_t, size_t);
12393c7b57cSdlg void		x86_bus_space_io_set_multi_4(bus_space_handle_t, bus_size_t,
12493c7b57cSdlg 		    u_int32_t, size_t);
12593c7b57cSdlg void		x86_bus_space_io_set_multi_8(bus_space_handle_t, bus_size_t,
12693c7b57cSdlg 		    u_int64_t, size_t);
12793c7b57cSdlg 
12893c7b57cSdlg void		x86_bus_space_io_set_region_1(bus_space_handle_t, bus_size_t,
12993c7b57cSdlg 		    u_int8_t, size_t);
13093c7b57cSdlg void		x86_bus_space_io_set_region_2(bus_space_handle_t, bus_size_t,
13193c7b57cSdlg 		    u_int16_t, size_t);
13293c7b57cSdlg void		x86_bus_space_io_set_region_4(bus_space_handle_t, bus_size_t,
13393c7b57cSdlg 		    u_int32_t, size_t);
13493c7b57cSdlg void		x86_bus_space_io_set_region_8(bus_space_handle_t, bus_size_t,
13593c7b57cSdlg 		    u_int64_t, size_t);
13693c7b57cSdlg 
13793c7b57cSdlg void		x86_bus_space_io_copy_1(bus_space_handle_t, bus_size_t,
13893c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
13993c7b57cSdlg void		x86_bus_space_io_copy_2(bus_space_handle_t, bus_size_t,
14093c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
14193c7b57cSdlg void		x86_bus_space_io_copy_4(bus_space_handle_t, bus_size_t,
14293c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
14393c7b57cSdlg void		x86_bus_space_io_copy_8(bus_space_handle_t, bus_size_t,
14493c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
14593c7b57cSdlg 
14693c7b57cSdlg void *		x86_bus_space_io_vaddr(bus_space_handle_t);
14793c7b57cSdlg paddr_t		x86_bus_space_io_mmap(bus_addr_t, off_t, int, int);
14893c7b57cSdlg 
14993c7b57cSdlg const struct x86_bus_space_ops x86_bus_space_io_ops = {
15093c7b57cSdlg 	x86_bus_space_io_read_1,
15193c7b57cSdlg 	x86_bus_space_io_read_2,
15293c7b57cSdlg 	x86_bus_space_io_read_4,
15393c7b57cSdlg 	x86_bus_space_io_read_8,
15493c7b57cSdlg 	x86_bus_space_io_read_multi_1,
15593c7b57cSdlg 	x86_bus_space_io_read_multi_2,
15693c7b57cSdlg 	x86_bus_space_io_read_multi_4,
15793c7b57cSdlg 	x86_bus_space_io_read_multi_8,
15893c7b57cSdlg 	x86_bus_space_io_read_region_1,
15993c7b57cSdlg 	x86_bus_space_io_read_region_2,
16093c7b57cSdlg 	x86_bus_space_io_read_region_4,
16193c7b57cSdlg 	x86_bus_space_io_read_region_8,
16293c7b57cSdlg 	x86_bus_space_io_write_1,
16393c7b57cSdlg 	x86_bus_space_io_write_2,
16493c7b57cSdlg 	x86_bus_space_io_write_4,
16593c7b57cSdlg 	x86_bus_space_io_write_8,
16693c7b57cSdlg 	x86_bus_space_io_write_multi_1,
16793c7b57cSdlg 	x86_bus_space_io_write_multi_2,
16893c7b57cSdlg 	x86_bus_space_io_write_multi_4,
16993c7b57cSdlg 	x86_bus_space_io_write_multi_8,
17093c7b57cSdlg 	x86_bus_space_io_write_region_1,
17193c7b57cSdlg 	x86_bus_space_io_write_region_2,
17293c7b57cSdlg 	x86_bus_space_io_write_region_4,
17393c7b57cSdlg 	x86_bus_space_io_write_region_8,
17493c7b57cSdlg 	x86_bus_space_io_set_multi_1,
17593c7b57cSdlg 	x86_bus_space_io_set_multi_2,
17693c7b57cSdlg 	x86_bus_space_io_set_multi_4,
17793c7b57cSdlg 	x86_bus_space_io_set_multi_8,
17893c7b57cSdlg 	x86_bus_space_io_set_region_1,
17993c7b57cSdlg 	x86_bus_space_io_set_region_2,
18093c7b57cSdlg 	x86_bus_space_io_set_region_4,
18193c7b57cSdlg 	x86_bus_space_io_set_region_8,
18293c7b57cSdlg 	x86_bus_space_io_copy_1,
18393c7b57cSdlg 	x86_bus_space_io_copy_2,
18493c7b57cSdlg 	x86_bus_space_io_copy_4,
18593c7b57cSdlg 	x86_bus_space_io_copy_8,
18693c7b57cSdlg 	x86_bus_space_io_vaddr,
18793c7b57cSdlg 	x86_bus_space_io_mmap
18893c7b57cSdlg };
18993c7b57cSdlg 
19093c7b57cSdlg u_int8_t	x86_bus_space_mem_read_1(bus_space_handle_t, bus_size_t);
19193c7b57cSdlg u_int16_t	x86_bus_space_mem_read_2(bus_space_handle_t, bus_size_t);
19293c7b57cSdlg u_int32_t	x86_bus_space_mem_read_4(bus_space_handle_t, bus_size_t);
19393c7b57cSdlg u_int64_t	x86_bus_space_mem_read_8(bus_space_handle_t, bus_size_t);
19493c7b57cSdlg 
19593c7b57cSdlg void		x86_bus_space_mem_read_multi_1(bus_space_handle_t, bus_size_t,
19693c7b57cSdlg 		    u_int8_t *, bus_size_t);
19793c7b57cSdlg void		x86_bus_space_mem_read_multi_2(bus_space_handle_t, bus_size_t,
19893c7b57cSdlg 		    u_int16_t *, bus_size_t);
19993c7b57cSdlg void		x86_bus_space_mem_read_multi_4(bus_space_handle_t, bus_size_t,
20093c7b57cSdlg 		    u_int32_t *, bus_size_t);
20193c7b57cSdlg void		x86_bus_space_mem_read_multi_8(bus_space_handle_t, bus_size_t,
20293c7b57cSdlg 		    u_int64_t *, bus_size_t);
20393c7b57cSdlg 
20493c7b57cSdlg void		x86_bus_space_mem_read_region_1(bus_space_handle_t, bus_size_t,
20593c7b57cSdlg 		    u_int8_t *, bus_size_t);
20693c7b57cSdlg void		x86_bus_space_mem_read_region_2(bus_space_handle_t, bus_size_t,
20793c7b57cSdlg 		    u_int16_t *, bus_size_t);
20893c7b57cSdlg void		x86_bus_space_mem_read_region_4(bus_space_handle_t, bus_size_t,
20993c7b57cSdlg 		    u_int32_t *, bus_size_t);
21093c7b57cSdlg void		x86_bus_space_mem_read_region_8(bus_space_handle_t, bus_size_t,
21193c7b57cSdlg 		    u_int64_t *, bus_size_t);
21293c7b57cSdlg 
21393c7b57cSdlg void		x86_bus_space_mem_write_1(bus_space_handle_t, bus_size_t,
21493c7b57cSdlg 		    u_int8_t);
21593c7b57cSdlg void		x86_bus_space_mem_write_2(bus_space_handle_t, bus_size_t,
21693c7b57cSdlg 		    u_int16_t);
21793c7b57cSdlg void		x86_bus_space_mem_write_4(bus_space_handle_t, bus_size_t,
21893c7b57cSdlg 		    u_int32_t);
21993c7b57cSdlg void		x86_bus_space_mem_write_8(bus_space_handle_t, bus_size_t,
22093c7b57cSdlg 		    u_int64_t);
22193c7b57cSdlg 
22293c7b57cSdlg void		x86_bus_space_mem_write_multi_1(bus_space_handle_t,
22393c7b57cSdlg 		    bus_size_t, const u_int8_t *, bus_size_t);
22493c7b57cSdlg void		x86_bus_space_mem_write_multi_2(bus_space_handle_t,
22593c7b57cSdlg 		    bus_size_t, const u_int16_t *, bus_size_t);
22693c7b57cSdlg void		x86_bus_space_mem_write_multi_4(bus_space_handle_t,
22793c7b57cSdlg 		    bus_size_t, const u_int32_t *, bus_size_t);
22893c7b57cSdlg void		x86_bus_space_mem_write_multi_8(bus_space_handle_t,
22993c7b57cSdlg 		    bus_size_t, const u_int64_t *, bus_size_t);
23093c7b57cSdlg 
23193c7b57cSdlg void		x86_bus_space_mem_write_region_1(bus_space_handle_t,
23293c7b57cSdlg 		    bus_size_t, const u_int8_t *, bus_size_t);
23393c7b57cSdlg void		x86_bus_space_mem_write_region_2(bus_space_handle_t,
23493c7b57cSdlg 		    bus_size_t, const u_int16_t *, bus_size_t);
23593c7b57cSdlg void		x86_bus_space_mem_write_region_4(bus_space_handle_t,
23693c7b57cSdlg 		    bus_size_t, const u_int32_t *, bus_size_t);
23793c7b57cSdlg void		x86_bus_space_mem_write_region_8(bus_space_handle_t,
23893c7b57cSdlg 		    bus_size_t, const u_int64_t *, bus_size_t);
23993c7b57cSdlg 
24093c7b57cSdlg void		x86_bus_space_mem_set_multi_1(bus_space_handle_t, bus_size_t,
24193c7b57cSdlg 		    u_int8_t, size_t);
24293c7b57cSdlg void		x86_bus_space_mem_set_multi_2(bus_space_handle_t, bus_size_t,
24393c7b57cSdlg 		    u_int16_t, size_t);
24493c7b57cSdlg void		x86_bus_space_mem_set_multi_4(bus_space_handle_t, bus_size_t,
24593c7b57cSdlg 		    u_int32_t, size_t);
24693c7b57cSdlg void		x86_bus_space_mem_set_multi_8(bus_space_handle_t, bus_size_t,
24793c7b57cSdlg 		    u_int64_t, size_t);
24893c7b57cSdlg 
24993c7b57cSdlg void		x86_bus_space_mem_set_region_1(bus_space_handle_t, bus_size_t,
25093c7b57cSdlg 		    u_int8_t, size_t);
25193c7b57cSdlg void		x86_bus_space_mem_set_region_2(bus_space_handle_t, bus_size_t,
25293c7b57cSdlg 		    u_int16_t, size_t);
25393c7b57cSdlg void		x86_bus_space_mem_set_region_4(bus_space_handle_t, bus_size_t,
25493c7b57cSdlg 		    u_int32_t, size_t);
25593c7b57cSdlg void		x86_bus_space_mem_set_region_8(bus_space_handle_t, bus_size_t,
25693c7b57cSdlg 		    u_int64_t, size_t);
25793c7b57cSdlg 
25893c7b57cSdlg void		x86_bus_space_mem_copy_1(bus_space_handle_t, bus_size_t,
25993c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
26093c7b57cSdlg void		x86_bus_space_mem_copy_2(bus_space_handle_t, bus_size_t,
26193c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
26293c7b57cSdlg void		x86_bus_space_mem_copy_4(bus_space_handle_t, bus_size_t,
26393c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
26493c7b57cSdlg void		x86_bus_space_mem_copy_8(bus_space_handle_t, bus_size_t,
26593c7b57cSdlg 		    bus_space_handle_t, bus_size_t, size_t);
26693c7b57cSdlg 
26793c7b57cSdlg void *		x86_bus_space_mem_vaddr(bus_space_handle_t);
26893c7b57cSdlg 
26993c7b57cSdlg paddr_t		x86_bus_space_mem_mmap(bus_addr_t, off_t, int, int);
27093c7b57cSdlg 
27193c7b57cSdlg const struct x86_bus_space_ops x86_bus_space_mem_ops = {
27293c7b57cSdlg 	x86_bus_space_mem_read_1,
27393c7b57cSdlg 	x86_bus_space_mem_read_2,
27493c7b57cSdlg 	x86_bus_space_mem_read_4,
27593c7b57cSdlg 	x86_bus_space_mem_read_8,
27693c7b57cSdlg 	x86_bus_space_mem_read_multi_1,
27793c7b57cSdlg 	x86_bus_space_mem_read_multi_2,
27893c7b57cSdlg 	x86_bus_space_mem_read_multi_4,
27993c7b57cSdlg 	x86_bus_space_mem_read_multi_8,
28093c7b57cSdlg 	x86_bus_space_mem_read_region_1,
28193c7b57cSdlg 	x86_bus_space_mem_read_region_2,
28293c7b57cSdlg 	x86_bus_space_mem_read_region_4,
28393c7b57cSdlg 	x86_bus_space_mem_read_region_8,
28493c7b57cSdlg 	x86_bus_space_mem_write_1,
28593c7b57cSdlg 	x86_bus_space_mem_write_2,
28693c7b57cSdlg 	x86_bus_space_mem_write_4,
28793c7b57cSdlg 	x86_bus_space_mem_write_8,
28893c7b57cSdlg 	x86_bus_space_mem_write_multi_1,
28993c7b57cSdlg 	x86_bus_space_mem_write_multi_2,
29093c7b57cSdlg 	x86_bus_space_mem_write_multi_4,
29193c7b57cSdlg 	x86_bus_space_mem_write_multi_8,
29293c7b57cSdlg 	x86_bus_space_mem_write_region_1,
29393c7b57cSdlg 	x86_bus_space_mem_write_region_2,
29493c7b57cSdlg 	x86_bus_space_mem_write_region_4,
29593c7b57cSdlg 	x86_bus_space_mem_write_region_8,
29693c7b57cSdlg 	x86_bus_space_mem_set_multi_1,
29793c7b57cSdlg 	x86_bus_space_mem_set_multi_2,
29893c7b57cSdlg 	x86_bus_space_mem_set_multi_4,
29993c7b57cSdlg 	x86_bus_space_mem_set_multi_8,
30093c7b57cSdlg 	x86_bus_space_mem_set_region_1,
30193c7b57cSdlg 	x86_bus_space_mem_set_region_2,
30293c7b57cSdlg 	x86_bus_space_mem_set_region_4,
30393c7b57cSdlg 	x86_bus_space_mem_set_region_8,
30493c7b57cSdlg 	x86_bus_space_mem_copy_1,
30593c7b57cSdlg 	x86_bus_space_mem_copy_2,
30693c7b57cSdlg 	x86_bus_space_mem_copy_4,
30793c7b57cSdlg 	x86_bus_space_mem_copy_8,
30893c7b57cSdlg 	x86_bus_space_mem_vaddr,
30993c7b57cSdlg 	x86_bus_space_mem_mmap
31093c7b57cSdlg };
31193c7b57cSdlg 
312f5df1827Smickey void
3132bb6026aSjsg x86_bus_space_init(void)
314f5df1827Smickey {
315f5df1827Smickey 	/*
316f5df1827Smickey 	 * Initialize the I/O port and I/O mem extent maps.
317f5df1827Smickey 	 * Note: we don't have to check the return value since
318f5df1827Smickey 	 * creation of a fixed extent map will never fail (since
319f5df1827Smickey 	 * descriptor storage has already been allocated).
320f5df1827Smickey 	 *
321f5df1827Smickey 	 * N.B. The iomem extent manages _all_ physical addresses
322f5df1827Smickey 	 * on the machine.  When the amount of RAM is found, the two
323f5df1827Smickey 	 * extents of RAM are allocated from the map (0 -> ISA hole
324f5df1827Smickey 	 * and end of ISA hole -> end of RAM).
325f5df1827Smickey 	 */
326f5df1827Smickey 	ioport_ex = extent_create("ioport", 0x0, 0xffff, M_DEVBUF,
327f5df1827Smickey 	    (caddr_t)ioport_ex_storage, sizeof(ioport_ex_storage),
328f5df1827Smickey 	    EX_NOCOALESCE|EX_NOWAIT);
329ddf0857aSkettenis 	iomem_ex = extent_create("iomem", 0x0, 0xffffffffffff, M_DEVBUF,
330f5df1827Smickey 	    (caddr_t)iomem_ex_storage, sizeof(iomem_ex_storage),
331f5df1827Smickey 	    EX_NOCOALESCE|EX_NOWAIT);
332f5df1827Smickey }
333f5df1827Smickey 
334f5df1827Smickey void
3352bb6026aSjsg x86_bus_space_mallocok(void)
336f5df1827Smickey {
337f5df1827Smickey 	ioport_malloc_safe = 1;
338f5df1827Smickey }
339f5df1827Smickey 
340f5df1827Smickey int
34199afcea1Sderaadt bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
3422bb6026aSjsg     bus_space_handle_t *bshp)
343f5df1827Smickey {
344f5df1827Smickey 	int error;
345f5df1827Smickey 	struct extent *ex;
346f5df1827Smickey 
347f5df1827Smickey 	/*
348f5df1827Smickey 	 * Pick the appropriate extent map.
349f5df1827Smickey 	 */
350f5df1827Smickey 	if (t == X86_BUS_SPACE_IO) {
351f5df1827Smickey 		ex = ioport_ex;
352515b194eSmarco 		if (flags & BUS_SPACE_MAP_LINEAR)
353515b194eSmarco 			return (EINVAL);
354f5df1827Smickey 	} else if (t == X86_BUS_SPACE_MEM)
355f5df1827Smickey 		ex = iomem_ex;
356f5df1827Smickey 	else
35799afcea1Sderaadt 		panic("bus_space_map: bad bus space tag");
358f5df1827Smickey 
359f5df1827Smickey 	/*
360f5df1827Smickey 	 * Before we go any further, let's make sure that this
361f5df1827Smickey 	 * region is available.
362f5df1827Smickey 	 */
363f5df1827Smickey 	error = extent_alloc_region(ex, bpa, size,
364f5df1827Smickey 	    EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0));
365f5df1827Smickey 	if (error)
366f5df1827Smickey 		return (error);
367f5df1827Smickey 
368f5df1827Smickey 	/*
369f5df1827Smickey 	 * For I/O space, that's all she wrote.
370f5df1827Smickey 	 */
371f5df1827Smickey 	if (t == X86_BUS_SPACE_IO) {
372f5df1827Smickey 		*bshp = bpa;
373f5df1827Smickey 		return (0);
374f5df1827Smickey 	}
375f5df1827Smickey 
376f5df1827Smickey 	if (bpa >= IOM_BEGIN && (bpa + size) <= IOM_END) {
377f5df1827Smickey 		*bshp = (bus_space_handle_t)ISA_HOLE_VADDR(bpa);
378f5df1827Smickey 		return(0);
379f5df1827Smickey 	}
380f5df1827Smickey 
381*e12dfaa1Skettenis 	if (!pmap_initialized && bpa < 0x100000000) {
382*e12dfaa1Skettenis 		*bshp = (bus_space_handle_t)PMAP_DIRECT_MAP(bpa);
383*e12dfaa1Skettenis 		return(0);
384*e12dfaa1Skettenis 	}
385*e12dfaa1Skettenis 
386f5df1827Smickey 	/*
387f5df1827Smickey 	 * For memory space, map the bus physical address to
388f5df1827Smickey 	 * a kernel virtual address.
389f5df1827Smickey 	 */
3905bac233bSoga 	error = x86_mem_add_mapping(bpa, size, flags, bshp);
391f5df1827Smickey 	if (error) {
392f5df1827Smickey 		if (extent_free(ex, bpa, size, EX_NOWAIT |
393f5df1827Smickey 		    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
39499afcea1Sderaadt 			printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
395f5df1827Smickey 			    bpa, size);
39699afcea1Sderaadt 			printf("bus_space_map: can't free region\n");
397f5df1827Smickey 		}
398f5df1827Smickey 	}
399f5df1827Smickey 
400f5df1827Smickey 	return (error);
401f5df1827Smickey }
402f5df1827Smickey 
403f5df1827Smickey int
40499afcea1Sderaadt _bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
4052bb6026aSjsg     bus_space_handle_t *bshp)
406f5df1827Smickey {
407f5df1827Smickey 
408f5df1827Smickey 	/*
409f5df1827Smickey 	 * For I/O space, just fill in the handle.
410f5df1827Smickey 	 */
411f5df1827Smickey 	if (t == X86_BUS_SPACE_IO) {
412f5df1827Smickey 		*bshp = bpa;
413f5df1827Smickey 		return (0);
414f5df1827Smickey 	}
415f5df1827Smickey 
416f5df1827Smickey 	/*
417f5df1827Smickey 	 * For memory space, map the bus physical address to
418f5df1827Smickey 	 * a kernel virtual address.
419f5df1827Smickey 	 */
4205bac233bSoga 	return (x86_mem_add_mapping(bpa, size, flags, bshp));
421f5df1827Smickey }
422f5df1827Smickey 
423f5df1827Smickey int
42499afcea1Sderaadt bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
4252bb6026aSjsg     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
4262bb6026aSjsg     bus_addr_t *bpap, bus_space_handle_t *bshp)
427f5df1827Smickey {
428f5df1827Smickey 	struct extent *ex;
429f5df1827Smickey 	u_long bpa;
430f5df1827Smickey 	int error;
431f5df1827Smickey 
432f5df1827Smickey 	/*
433f5df1827Smickey 	 * Pick the appropriate extent map.
434f5df1827Smickey 	 */
435f5df1827Smickey 	if (t == X86_BUS_SPACE_IO) {
436f5df1827Smickey 		ex = ioport_ex;
437f5df1827Smickey 	} else if (t == X86_BUS_SPACE_MEM)
438f5df1827Smickey 		ex = iomem_ex;
439f5df1827Smickey 	else
44099afcea1Sderaadt 		panic("bus_space_alloc: bad bus space tag");
441f5df1827Smickey 
442f5df1827Smickey 	/*
443f5df1827Smickey 	 * Sanity check the allocation against the extent's boundaries.
444f5df1827Smickey 	 */
445f5df1827Smickey 	if (rstart < ex->ex_start || rend > ex->ex_end)
44699afcea1Sderaadt 		panic("bus_space_alloc: bad region start/end");
447f5df1827Smickey 
448f5df1827Smickey 	/*
449f5df1827Smickey 	 * Do the requested allocation.
450f5df1827Smickey 	 */
451f5df1827Smickey 	error = extent_alloc_subregion(ex, rstart, rend, size, alignment,
452f5df1827Smickey 	    0, boundary,
453f5df1827Smickey 	    EX_FAST | EX_NOWAIT | (ioport_malloc_safe ?  EX_MALLOCOK : 0),
454f5df1827Smickey 	    &bpa);
455f5df1827Smickey 
456f5df1827Smickey 	if (error)
457f5df1827Smickey 		return (error);
458f5df1827Smickey 
459f5df1827Smickey 	/*
460f5df1827Smickey 	 * For I/O space, that's all she wrote.
461f5df1827Smickey 	 */
462f5df1827Smickey 	if (t == X86_BUS_SPACE_IO) {
463f5df1827Smickey 		*bshp = *bpap = bpa;
464f5df1827Smickey 		return (0);
465f5df1827Smickey 	}
466f5df1827Smickey 
467f5df1827Smickey 	/*
468f5df1827Smickey 	 * For memory space, map the bus physical address to
469f5df1827Smickey 	 * a kernel virtual address.
470f5df1827Smickey 	 */
4715bac233bSoga 	error = x86_mem_add_mapping(bpa, size, flags, bshp);
472f5df1827Smickey 	if (error) {
473f5df1827Smickey 		if (extent_free(iomem_ex, bpa, size, EX_NOWAIT |
474f5df1827Smickey 		    (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
47599afcea1Sderaadt 			printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
476f5df1827Smickey 			    bpa, size);
47799afcea1Sderaadt 			printf("bus_space_alloc: can't free region\n");
478f5df1827Smickey 		}
479f5df1827Smickey 	}
480f5df1827Smickey 
481f5df1827Smickey 	*bpap = bpa;
482f5df1827Smickey 
483f5df1827Smickey 	return (error);
484f5df1827Smickey }
485f5df1827Smickey 
486f5df1827Smickey int
4875bac233bSoga x86_mem_add_mapping(bus_addr_t bpa, bus_size_t size, int flags,
4882bb6026aSjsg     bus_space_handle_t *bshp)
489f5df1827Smickey {
49007dfb2ccSoga 	paddr_t pa, endpa;
491de00544fSoga 	vaddr_t va;
4925bac233bSoga 	bus_size_t map_size;
49307dfb2ccSoga 	int pmap_flags = PMAP_NOCACHE;
4945bac233bSoga 
4955bac233bSoga 	pa = trunc_page(bpa);
4965bac233bSoga 	endpa = round_page(bpa + size);
4975bac233bSoga 
4985bac233bSoga #ifdef DIAGNOSTIC
4995bac233bSoga 	if (endpa <= pa && endpa != 0)
5005bac233bSoga 		panic("bus_mem_add_mapping: overflow");
5015bac233bSoga #endif
5025bac233bSoga 
5035bac233bSoga 	map_size = endpa - pa;
5045bac233bSoga 
50537d9e641Skettenis 	va = (vaddr_t)km_alloc(map_size, &kv_any, &kp_none, &kd_nowait);
5065bac233bSoga 	if (va == 0)
5075bac233bSoga 		return (ENOMEM);
5085bac233bSoga 
5095bac233bSoga 	*bshp = (bus_space_handle_t)(va + (bpa & PGOFSET));
5105bac233bSoga 
51107dfb2ccSoga 	if (flags & BUS_SPACE_MAP_CACHEABLE)
51207dfb2ccSoga 		pmap_flags = 0;
51307dfb2ccSoga 	else if (flags & BUS_SPACE_MAP_PREFETCHABLE)
51407dfb2ccSoga 		pmap_flags = PMAP_WC;
51507dfb2ccSoga 
5165bac233bSoga 	for (; map_size > 0;
517de00544fSoga 	    pa += PAGE_SIZE, va += PAGE_SIZE, map_size -= PAGE_SIZE)
5181e8cdc2eSderaadt 		pmap_kenter_pa(va, pa | pmap_flags, PROT_READ | PROT_WRITE);
5195bac233bSoga 	pmap_update(pmap_kernel());
5205bac233bSoga 
521f5df1827Smickey 	return 0;
522f5df1827Smickey }
523f5df1827Smickey 
524f5df1827Smickey /*
52599afcea1Sderaadt  * void _bus_space_unmap(bus_space_tag bst, bus_space_handle bsh,
526f5df1827Smickey  *                        bus_size_t size, bus_addr_t *adrp)
527f5df1827Smickey  *
528f5df1827Smickey  *   This function unmaps memory- or io-space mapped by the function
52999afcea1Sderaadt  *   _bus_space_map().  This function works nearly as same as
53099afcea1Sderaadt  *   bus_space_unmap(), but this function does not ask kernel
531f5df1827Smickey  *   built-in extents and returns physical address of the bus space,
532f5df1827Smickey  *   for the convenience of the extra extent manager.
533f5df1827Smickey  */
534f5df1827Smickey void
53599afcea1Sderaadt _bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size,
5362bb6026aSjsg     bus_addr_t *adrp)
537f5df1827Smickey {
5385bac233bSoga 	u_long va, endva;
539f5df1827Smickey 	bus_addr_t bpa;
540f5df1827Smickey 
541f5df1827Smickey 	/*
5425bac233bSoga 	 * Find the correct bus physical address.
543f5df1827Smickey 	 */
544f5df1827Smickey 	if (t == X86_BUS_SPACE_IO) {
545f5df1827Smickey 		bpa = bsh;
546f5df1827Smickey 	} else if (t == X86_BUS_SPACE_MEM) {
547f5df1827Smickey 		bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
5485bac233bSoga 		if (IOM_BEGIN <= bpa && bpa <= IOM_END)
5495bac233bSoga 			goto ok;
550f5df1827Smickey 
5515bac233bSoga 		va = trunc_page(bsh);
5525bac233bSoga 		endva = round_page(bsh + size);
5535bac233bSoga 
5545bac233bSoga #ifdef DIAGNOSTIC
5555bac233bSoga 		if (endva <= va)
5565bac233bSoga 			panic("_bus_space_unmap: overflow");
5575bac233bSoga #endif
5585bac233bSoga 
5595bac233bSoga 		(void) pmap_extract(pmap_kernel(), va, &bpa);
5605bac233bSoga 		bpa += (bsh & PGOFSET);
5615bac233bSoga 
5625bac233bSoga 		pmap_kremove(va, endva - va);
5635bac233bSoga 		pmap_update(pmap_kernel());
5645bac233bSoga 
5655bac233bSoga 		/*
5665bac233bSoga 		 * Free the kernel virtual mapping.
5675bac233bSoga 		 */
56837d9e641Skettenis 		km_free((void *)va, endva - va, &kv_any, &kp_none);
5695bac233bSoga 	} else
5705bac233bSoga 		panic("bus_space_unmap: bad bus space tag");
5715bac233bSoga 
5725bac233bSoga ok:
5735bac233bSoga 	if (adrp != NULL)
574f5df1827Smickey 		*adrp = bpa;
575f5df1827Smickey }
576f5df1827Smickey 
577f5df1827Smickey void
57899afcea1Sderaadt bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
579f5df1827Smickey {
580f5df1827Smickey 	struct extent *ex;
5815bac233bSoga 	u_long va, endva;
582f5df1827Smickey 	bus_addr_t bpa;
583f5df1827Smickey 
584f5df1827Smickey 	/*
585f5df1827Smickey 	 * Find the correct extent and bus physical address.
586f5df1827Smickey 	 */
587f5df1827Smickey 	if (t == X86_BUS_SPACE_IO) {
588f5df1827Smickey 		ex = ioport_ex;
589f5df1827Smickey 		bpa = bsh;
590f5df1827Smickey 	} else if (t == X86_BUS_SPACE_MEM) {
591f5df1827Smickey 		ex = iomem_ex;
592f5df1827Smickey 		bpa = (bus_addr_t)ISA_PHYSADDR(bsh);
5935bac233bSoga 		if (IOM_BEGIN <= bpa && bpa <= IOM_END)
594f5df1827Smickey 			goto ok;
595f5df1827Smickey 
596*e12dfaa1Skettenis 		if (bsh >= PMAP_DIRECT_BASE && bsh < PMAP_DIRECT_END) {
597*e12dfaa1Skettenis 			bpa = PMAP_DIRECT_UNMAP(bsh);
598*e12dfaa1Skettenis 			goto ok;
599*e12dfaa1Skettenis 		}
600*e12dfaa1Skettenis 
6015bac233bSoga 		va = trunc_page(bsh);
6025bac233bSoga 		endva = round_page(bsh + size);
6035bac233bSoga 
6045bac233bSoga #ifdef DIAGNOSTIC
6055bac233bSoga 		if (endva <= va)
6065bac233bSoga 			panic("bus_space_unmap: overflow");
6075bac233bSoga #endif
6085bac233bSoga 
6095bac233bSoga 		(void)pmap_extract(pmap_kernel(), va, &bpa);
6105bac233bSoga 		bpa += (bsh & PGOFSET);
6115bac233bSoga 
6125bac233bSoga 		pmap_kremove(va, endva - va);
6135bac233bSoga 		pmap_update(pmap_kernel());
6145bac233bSoga 
6155bac233bSoga 		/*
6165bac233bSoga 		 * Free the kernel virtual mapping.
6175bac233bSoga 		 */
61837d9e641Skettenis 		km_free((void *)va, endva - va, &kv_any, &kp_none);
619f5df1827Smickey 	} else
62099afcea1Sderaadt 		panic("bus_space_unmap: bad bus space tag");
621f5df1827Smickey 
622f5df1827Smickey ok:
623f5df1827Smickey 	if (extent_free(ex, bpa, size,
624f5df1827Smickey 	    EX_NOWAIT | (ioport_malloc_safe ? EX_MALLOCOK : 0))) {
62599afcea1Sderaadt 		printf("bus_space_unmap: %s 0x%lx, size 0x%lx\n",
626f5df1827Smickey 		    (t == X86_BUS_SPACE_IO) ? "port" : "pa", bpa, size);
62799afcea1Sderaadt 		printf("bus_space_unmap: can't free region\n");
628f5df1827Smickey 	}
629f5df1827Smickey }
630f5df1827Smickey 
631f5df1827Smickey void
63299afcea1Sderaadt bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
633f5df1827Smickey {
634f5df1827Smickey 
63599afcea1Sderaadt 	/* bus_space_unmap() does all that we need to do. */
63699afcea1Sderaadt 	bus_space_unmap(t, bsh, size);
637f5df1827Smickey }
638f5df1827Smickey 
639f5df1827Smickey int
64099afcea1Sderaadt bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
6412bb6026aSjsg     bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp)
642f5df1827Smickey {
643f5df1827Smickey 
644f5df1827Smickey 	*nbshp = bsh + offset;
645f5df1827Smickey 	return (0);
646f5df1827Smickey }
647f5df1827Smickey 
648ebbaad44Soga u_int8_t
64993c7b57cSdlg x86_bus_space_io_read_1(bus_space_handle_t h, bus_size_t o)
650ebbaad44Soga {
65193c7b57cSdlg 	return (inb(h + o));
652ebbaad44Soga }
653ebbaad44Soga 
654ebbaad44Soga u_int16_t
65593c7b57cSdlg x86_bus_space_io_read_2(bus_space_handle_t h, bus_size_t o)
656ebbaad44Soga {
65793c7b57cSdlg 	return (inw(h + o));
658ebbaad44Soga }
659ebbaad44Soga 
660ebbaad44Soga u_int32_t
66193c7b57cSdlg x86_bus_space_io_read_4(bus_space_handle_t h, bus_size_t o)
662ebbaad44Soga {
66393c7b57cSdlg 	return (inl(h + o));
664ebbaad44Soga }
665ebbaad44Soga 
6669f2791f2Sdlg u_int64_t
66793c7b57cSdlg x86_bus_space_io_read_8(bus_space_handle_t h, bus_size_t o)
6689f2791f2Sdlg {
66993c7b57cSdlg 	panic("bus_space_read_8: invalid bus space tag");
6709f2791f2Sdlg }
6719f2791f2Sdlg 
672ebbaad44Soga void
67393c7b57cSdlg x86_bus_space_io_read_multi_1(bus_space_handle_t h, bus_size_t o,
674ebbaad44Soga     u_int8_t *ptr, bus_size_t cnt)
675ebbaad44Soga {
676ebbaad44Soga 	insb(h + o, ptr, cnt);
677ebbaad44Soga }
678ebbaad44Soga 
679ebbaad44Soga void
68093c7b57cSdlg x86_bus_space_io_read_multi_2(bus_space_handle_t h, bus_size_t o,
681ebbaad44Soga     u_int16_t *ptr, bus_size_t cnt)
682ebbaad44Soga {
683ebbaad44Soga 	insw(h + o, ptr, cnt);
684ebbaad44Soga }
685ebbaad44Soga 
686ebbaad44Soga void
68793c7b57cSdlg x86_bus_space_io_read_multi_4(bus_space_handle_t h, bus_size_t o,
688ebbaad44Soga     u_int32_t *ptr, bus_size_t cnt)
689ebbaad44Soga {
690ebbaad44Soga 	insl(h + o, ptr, cnt);
691ebbaad44Soga }
692ebbaad44Soga 
693ebbaad44Soga void
69493c7b57cSdlg x86_bus_space_io_read_multi_8(bus_space_handle_t h, bus_size_t o,
6959f2791f2Sdlg     u_int64_t *ptr, bus_size_t cnt)
6969f2791f2Sdlg {
69793c7b57cSdlg 	panic("bus_space_multi_8: invalid bus space tag");
6989f2791f2Sdlg }
6999f2791f2Sdlg 
7009f2791f2Sdlg void
70193c7b57cSdlg x86_bus_space_io_read_region_1(bus_space_handle_t h,
702ebbaad44Soga     bus_size_t o, u_int8_t *ptr, bus_size_t cnt)
703ebbaad44Soga {
704ebbaad44Soga 	int dummy1;
705ebbaad44Soga 	void *dummy2;
706ebbaad44Soga 	int dummy3;
707ebbaad44Soga 	int __x;
708d5e88557Sjsg 	u_int32_t port = h + o;
709e39f036fSguenther 	__asm volatile(
710ebbaad44Soga 	"1:	inb %w1,%%al				;"
711ebbaad44Soga 	"	stosb					;"
712ebbaad44Soga 	"	incl %1					;"
713ebbaad44Soga 	"	loop 1b"				:
714ebbaad44Soga 	    "=&a" (__x), "=d" (dummy1), "=D" (dummy2),
715ebbaad44Soga 	    "=c" (dummy3)				:
716d5e88557Sjsg 	    "1" (port), "2" (ptr), "3" (cnt)	:
717ebbaad44Soga 	    "memory");
718ebbaad44Soga }
719ebbaad44Soga 
720ebbaad44Soga void
72193c7b57cSdlg x86_bus_space_io_read_region_2(bus_space_handle_t h,
722ebbaad44Soga     bus_size_t o, u_int16_t *ptr, bus_size_t cnt)
723ebbaad44Soga {
724ebbaad44Soga 	int dummy1;
725ebbaad44Soga 	void *dummy2;
726ebbaad44Soga 	int dummy3;
727ebbaad44Soga 	int __x;
728d5e88557Sjsg 	u_int32_t port = h + o;
729e39f036fSguenther 	__asm volatile(
730ebbaad44Soga 	"1:	inw %w1,%%ax				;"
731ebbaad44Soga 	"	stosw					;"
732ebbaad44Soga 	"	addl $2,%1				;"
733ebbaad44Soga 	"	loop 1b"				:
734ebbaad44Soga 	    "=&a" (__x), "=d" (dummy1), "=D" (dummy2),
735ebbaad44Soga 	    "=c" (dummy3)				:
736d5e88557Sjsg 	    "1" ((port)), "2" ((ptr)), "3" ((cnt))	:
737ebbaad44Soga 	    "memory");
738ebbaad44Soga }
739ebbaad44Soga 
740ebbaad44Soga void
74193c7b57cSdlg x86_bus_space_io_read_region_4(bus_space_handle_t h,
742ebbaad44Soga     bus_size_t o, u_int32_t *ptr, bus_size_t cnt)
743ebbaad44Soga {
744ebbaad44Soga 	int dummy1;
745ebbaad44Soga 	void *dummy2;
746ebbaad44Soga 	int dummy3;
747ebbaad44Soga 	int __x;
748d5e88557Sjsg 	u_int32_t port = h + o;
749e39f036fSguenther 	__asm volatile(
750ebbaad44Soga 	"1:	inl %w1,%%eax				;"
751ebbaad44Soga 	"	stosl					;"
752ebbaad44Soga 	"	addl $4,%1				;"
753ebbaad44Soga 	"	loop 1b"				:
754ebbaad44Soga 	    "=&a" (__x), "=d" (dummy1), "=D" (dummy2),
755ebbaad44Soga 	    "=c" (dummy3)				:
756d5e88557Sjsg 	    "1" (port), "2" (ptr), "3" (cnt)	:
757ebbaad44Soga 	    "memory");
758ebbaad44Soga }
7599f2791f2Sdlg 
7609f2791f2Sdlg void
76193c7b57cSdlg x86_bus_space_io_read_region_8(bus_space_handle_t h,
7629f2791f2Sdlg     bus_size_t o, u_int64_t *ptr, bus_size_t cnt)
7639f2791f2Sdlg {
76493c7b57cSdlg 	panic("bus_space_read_region_8: invalid bus space tag");
7659f2791f2Sdlg }
7669f2791f2Sdlg 
767ebbaad44Soga void
76893c7b57cSdlg x86_bus_space_io_write_1(bus_space_handle_t h, bus_size_t o, u_int8_t v)
769ebbaad44Soga {
770ebbaad44Soga 	outb(h + o, v);
771ebbaad44Soga }
772ebbaad44Soga 
773ebbaad44Soga void
77493c7b57cSdlg x86_bus_space_io_write_2(bus_space_handle_t h, bus_size_t o, u_int16_t v)
775ebbaad44Soga {
776ebbaad44Soga 	outw(h + o, v);
777ebbaad44Soga }
778ebbaad44Soga 
779ebbaad44Soga void
78093c7b57cSdlg x86_bus_space_io_write_4(bus_space_handle_t h, bus_size_t o, u_int32_t v)
781ebbaad44Soga {
782ebbaad44Soga 	outl(h + o, v);
783ebbaad44Soga }
784ebbaad44Soga 
785ebbaad44Soga void
78693c7b57cSdlg x86_bus_space_io_write_8(bus_space_handle_t h, bus_size_t o, u_int64_t v)
7879f2791f2Sdlg {
78893c7b57cSdlg 	panic("bus_space_write_8: invalid bus space tag");
7899f2791f2Sdlg }
7909f2791f2Sdlg 
7919f2791f2Sdlg void
79293c7b57cSdlg x86_bus_space_io_write_multi_1(bus_space_handle_t h,
793ebbaad44Soga     bus_size_t o, const u_int8_t *ptr, bus_size_t cnt)
794ebbaad44Soga {
795ebbaad44Soga 	outsb(h + o, ptr, cnt);
796ebbaad44Soga }
797ebbaad44Soga 
798ebbaad44Soga void
79993c7b57cSdlg x86_bus_space_io_write_multi_2(bus_space_handle_t h,
800ebbaad44Soga     bus_size_t o, const u_int16_t *ptr, bus_size_t cnt)
801ebbaad44Soga {
802ebbaad44Soga 	outsw(h + o, ptr, cnt);
803ebbaad44Soga }
804ebbaad44Soga 
805ebbaad44Soga void
80693c7b57cSdlg x86_bus_space_io_write_multi_4(bus_space_handle_t h,
807ebbaad44Soga     bus_size_t o, const u_int32_t *ptr, bus_size_t cnt)
808ebbaad44Soga {
809ebbaad44Soga 	outsl(h + o, ptr, cnt);
810ebbaad44Soga }
811ebbaad44Soga 
812ebbaad44Soga void
81393c7b57cSdlg x86_bus_space_io_write_multi_8(bus_space_handle_t h,
8149f2791f2Sdlg     bus_size_t o, const u_int64_t *ptr, bus_size_t cnt)
8159f2791f2Sdlg {
81693c7b57cSdlg 	panic("bus_space_write_multi_8: invalid bus space tag");
8179f2791f2Sdlg }
8189f2791f2Sdlg 
8199f2791f2Sdlg void
82093c7b57cSdlg x86_bus_space_io_write_region_1(bus_space_handle_t h,
821ebbaad44Soga     bus_size_t o, const u_int8_t *ptr, bus_size_t cnt)
822ebbaad44Soga {
823ebbaad44Soga 	int dummy1;
824ebbaad44Soga 	void *dummy2;
825ebbaad44Soga 	int dummy3;
826ebbaad44Soga 	int __x;
827d5e88557Sjsg 	u_int32_t port = h + o;
828e39f036fSguenther 	__asm volatile(
829ebbaad44Soga 	"1:	lodsb					;"
830ebbaad44Soga 	"	outb %%al,%w1				;"
831ebbaad44Soga 	"	incl %1					;"
832ebbaad44Soga 	"	loop 1b"				:
833ebbaad44Soga 	    "=&a" (__x), "=d" (dummy1), "=S" (dummy2),
834ebbaad44Soga 	    "=c" (dummy3)				:
835d5e88557Sjsg 	    "1" (port), "2" (ptr), "3" (cnt)	:
836ebbaad44Soga 	    "memory");
837ebbaad44Soga }
838ebbaad44Soga 
839ebbaad44Soga void
84093c7b57cSdlg x86_bus_space_io_write_region_2(bus_space_handle_t h,
841ebbaad44Soga     bus_size_t o, const u_int16_t *ptr, bus_size_t cnt)
842ebbaad44Soga {
843ebbaad44Soga 	int dummy1;
844ebbaad44Soga 	void *dummy2;
845ebbaad44Soga 	int dummy3;
846ebbaad44Soga 	int __x;
847d5e88557Sjsg 	u_int32_t port = h + o;
848e39f036fSguenther 	__asm volatile(
849ebbaad44Soga 	"1:	lodsw					;"
850ebbaad44Soga 	"	outw %%ax,%w1				;"
851ebbaad44Soga 	"	addl $2,%1				;"
852ebbaad44Soga 	"	loop 1b"				:
853ebbaad44Soga 	    "=&a" (__x), "=d" (dummy1), "=S" (dummy2),
854ebbaad44Soga 	    "=c" (dummy3)				:
855d5e88557Sjsg 	    "1" (port), "2" (ptr), "3" (cnt)	:
856ebbaad44Soga 	    "memory");
857ebbaad44Soga }
858ebbaad44Soga 
859ebbaad44Soga void
86093c7b57cSdlg x86_bus_space_io_write_region_4(bus_space_handle_t h,
861ebbaad44Soga     bus_size_t o, const u_int32_t *ptr, bus_size_t cnt)
862ebbaad44Soga {
863ebbaad44Soga 	int dummy1;
864ebbaad44Soga 	void *dummy2;
865ebbaad44Soga 	int dummy3;
866ebbaad44Soga 	int __x;
867d5e88557Sjsg 	u_int32_t port = h + o;
868e39f036fSguenther 	__asm volatile(
869ebbaad44Soga 	"1:	lodsl					;"
870ebbaad44Soga 	"	outl %%eax,%w1				;"
871ebbaad44Soga 	"	addl $4,%1				;"
872ebbaad44Soga 	"	loop 1b"				:
873ebbaad44Soga 	    "=&a" (__x), "=d" (dummy1), "=S" (dummy2),
874ebbaad44Soga 	    "=c" (dummy3)				:
875d5e88557Sjsg 	    "1" (port), "2" (ptr), "3" (cnt)	:
876ebbaad44Soga 	    "memory");
87793c7b57cSdlg }
87893c7b57cSdlg 
87993c7b57cSdlg void
88093c7b57cSdlg x86_bus_space_io_write_region_8(bus_space_handle_t h,
88193c7b57cSdlg     bus_size_t o, const u_int64_t *ptr, bus_size_t cnt)
88293c7b57cSdlg {
88393c7b57cSdlg 	panic("bus_space_write_region_8: invalid bus space tag");
88493c7b57cSdlg }
88593c7b57cSdlg 
88693c7b57cSdlg void
88793c7b57cSdlg x86_bus_space_io_set_multi_1(bus_space_handle_t h, bus_size_t o,
88893c7b57cSdlg     u_int8_t v, size_t c)
88993c7b57cSdlg {
89093c7b57cSdlg 	bus_addr_t addr = h + o;
89193c7b57cSdlg 
89293c7b57cSdlg 	while (c--)
89393c7b57cSdlg 		outb(addr, v);
89493c7b57cSdlg }
89593c7b57cSdlg 
89693c7b57cSdlg void
89793c7b57cSdlg x86_bus_space_io_set_multi_2(bus_space_handle_t h, bus_size_t o,
89893c7b57cSdlg     u_int16_t v, size_t c)
89993c7b57cSdlg {
90093c7b57cSdlg 	bus_addr_t addr = h + o;
90193c7b57cSdlg 
90293c7b57cSdlg 	while (c--)
90393c7b57cSdlg 		outw(addr, v);
90493c7b57cSdlg }
90593c7b57cSdlg 
90693c7b57cSdlg void
90793c7b57cSdlg x86_bus_space_io_set_multi_4(bus_space_handle_t h, bus_size_t o,
90893c7b57cSdlg     u_int32_t v, size_t c)
90993c7b57cSdlg {
91093c7b57cSdlg 	bus_addr_t addr = h + o;
91193c7b57cSdlg 
91293c7b57cSdlg 	while (c--)
91393c7b57cSdlg 		outl(addr, v);
91493c7b57cSdlg }
91593c7b57cSdlg 
91693c7b57cSdlg void
91793c7b57cSdlg x86_bus_space_io_set_multi_8(bus_space_handle_t h, bus_size_t o,
91893c7b57cSdlg     u_int64_t v, size_t c)
91993c7b57cSdlg {
92093c7b57cSdlg 	panic("bus_space_set_multi_8: invalid bus space tag");
92193c7b57cSdlg }
92293c7b57cSdlg 
92393c7b57cSdlg void
92493c7b57cSdlg x86_bus_space_io_set_region_1(bus_space_handle_t h, bus_size_t o,
92593c7b57cSdlg     u_int8_t v, size_t c)
92693c7b57cSdlg {
92793c7b57cSdlg 	bus_addr_t addr = h + o;
92893c7b57cSdlg 
92993c7b57cSdlg 	for (; c != 0; c--, addr++)
93093c7b57cSdlg 		outb(addr, v);
93193c7b57cSdlg }
93293c7b57cSdlg 
93393c7b57cSdlg void
93493c7b57cSdlg x86_bus_space_io_set_region_2(bus_space_handle_t h, bus_size_t o,
93593c7b57cSdlg     u_int16_t v, size_t c)
93693c7b57cSdlg {
93793c7b57cSdlg 	bus_addr_t addr = h + o;
93893c7b57cSdlg 
93993c7b57cSdlg 	for (; c != 0; c--, addr += sizeof(v))
94093c7b57cSdlg 		outw(addr, v);
94193c7b57cSdlg }
94293c7b57cSdlg 
94393c7b57cSdlg void
94493c7b57cSdlg x86_bus_space_io_set_region_4(bus_space_handle_t h, bus_size_t o,
94593c7b57cSdlg     u_int32_t v, size_t c)
94693c7b57cSdlg {
94793c7b57cSdlg 	bus_addr_t addr = h + o;
94893c7b57cSdlg 
94993c7b57cSdlg 	for (; c != 0; c--, addr += sizeof(v))
95093c7b57cSdlg 		outl(addr, v);
95193c7b57cSdlg }
95293c7b57cSdlg 
95393c7b57cSdlg void
95493c7b57cSdlg x86_bus_space_io_set_region_8(bus_space_handle_t h, bus_size_t o,
95593c7b57cSdlg     u_int64_t v, size_t c)
95693c7b57cSdlg {
95793c7b57cSdlg 	panic("bus_space_set_region_8: invalid bus space tag");
95893c7b57cSdlg }
95993c7b57cSdlg 
96093c7b57cSdlg void
96193c7b57cSdlg x86_bus_space_io_copy_1(bus_space_handle_t h1, bus_size_t o1,
96293c7b57cSdlg     bus_space_handle_t h2, bus_size_t o2, size_t c)
96393c7b57cSdlg {
96493c7b57cSdlg 	bus_addr_t addr1 = h1 + o1;
96593c7b57cSdlg 	bus_addr_t addr2 = h2 + o2;
96693c7b57cSdlg 
96793c7b57cSdlg 	if (addr1 >= addr2) {
96893c7b57cSdlg 		/* src after dest: copy forward */
96993c7b57cSdlg 		for (; c != 0; c--, addr1++, addr2++)
97093c7b57cSdlg 			outb(addr2, inb(addr1));
971ebbaad44Soga 	} else {
97293c7b57cSdlg 		/* dest after src: copy backwards */
97393c7b57cSdlg 		for (addr1 += (c - 1), addr2 += (c - 1);
97493c7b57cSdlg 		    c != 0; c--, addr1--, addr2--)
97593c7b57cSdlg 			outb(addr2, inb(addr1));
97693c7b57cSdlg 	}
97793c7b57cSdlg }
97893c7b57cSdlg 
97993c7b57cSdlg void
98093c7b57cSdlg x86_bus_space_io_copy_2(bus_space_handle_t h1, bus_size_t o1,
98193c7b57cSdlg     bus_space_handle_t h2, bus_size_t o2, size_t c)
98293c7b57cSdlg {
98393c7b57cSdlg 	bus_addr_t addr1 = h1 + o1;
98493c7b57cSdlg 	bus_addr_t addr2 = h2 + o2;
98593c7b57cSdlg 
98693c7b57cSdlg 	if (addr1 >= addr2) {
98793c7b57cSdlg 		/* src after dest: copy forward */
98893c7b57cSdlg 		for (; c != 0; c--, addr1 += 2, addr2 += 2)
98993c7b57cSdlg 			outw(addr2, inw(addr1));
99093c7b57cSdlg 	} else {
99193c7b57cSdlg 		/* dest after src: copy backwards */
99293c7b57cSdlg 		for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1);
99393c7b57cSdlg 		    c != 0; c--, addr1 -= 2, addr2 -= 2)
99493c7b57cSdlg 			outw(addr2, inw(addr1));
99593c7b57cSdlg 	}
99693c7b57cSdlg }
99793c7b57cSdlg 
99893c7b57cSdlg void
99993c7b57cSdlg x86_bus_space_io_copy_4(bus_space_handle_t h1, bus_size_t o1,
100093c7b57cSdlg     bus_space_handle_t h2, bus_size_t o2, size_t c)
100193c7b57cSdlg {
100293c7b57cSdlg 	bus_addr_t addr1 = h1 + o1;
100393c7b57cSdlg 	bus_addr_t addr2 = h2 + o2;
100493c7b57cSdlg 
100593c7b57cSdlg 	if (addr1 >= addr2) {
100693c7b57cSdlg 		/* src after dest: copy forward */
100793c7b57cSdlg 		for (; c != 0; c--, addr1 += 4, addr2 += 4)
100893c7b57cSdlg 			outl(addr2, inl(addr1));
100993c7b57cSdlg 	} else {
101093c7b57cSdlg 		/* dest after src: copy backwards */
101193c7b57cSdlg 		for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1);
101293c7b57cSdlg 		    c != 0; c--, addr1 -= 4, addr2 -= 4)
101393c7b57cSdlg 			outl(addr2, inl(addr1));
101493c7b57cSdlg 	}
101593c7b57cSdlg }
101693c7b57cSdlg 
101793c7b57cSdlg void
101893c7b57cSdlg x86_bus_space_io_copy_8(bus_space_handle_t h1, bus_size_t o1,
101993c7b57cSdlg     bus_space_handle_t h2, bus_size_t o2, size_t c)
102093c7b57cSdlg {
102193c7b57cSdlg 	panic("bus_space_set_region_8: invalid bus space tag");
102293c7b57cSdlg }
102393c7b57cSdlg 
102493c7b57cSdlg void *
102593c7b57cSdlg x86_bus_space_io_vaddr(bus_space_handle_t h)
102693c7b57cSdlg {
102793c7b57cSdlg 	return (NULL);
102893c7b57cSdlg }
102993c7b57cSdlg 
103093c7b57cSdlg paddr_t
103193c7b57cSdlg x86_bus_space_io_mmap(bus_addr_t addr, off_t off, int prot, int flags)
103293c7b57cSdlg {
103393c7b57cSdlg 	/* Can't mmap I/O space. */
103493c7b57cSdlg 	return (-1);
103593c7b57cSdlg }
103693c7b57cSdlg 
103793c7b57cSdlg void
103893c7b57cSdlg x86_bus_space_mem_write_1(bus_space_handle_t h, bus_size_t o, u_int8_t v)
103993c7b57cSdlg {
104093c7b57cSdlg 	*(volatile u_int8_t *)(h + o) = v;
104193c7b57cSdlg }
104293c7b57cSdlg 
104393c7b57cSdlg void
104493c7b57cSdlg x86_bus_space_mem_write_2(bus_space_handle_t h, bus_size_t o, u_int16_t v)
104593c7b57cSdlg {
104693c7b57cSdlg 	*(volatile u_int16_t *)(h + o) = v;
104793c7b57cSdlg }
104893c7b57cSdlg 
104993c7b57cSdlg u_int8_t
105093c7b57cSdlg x86_bus_space_mem_read_1(bus_space_handle_t h, bus_size_t o)
105193c7b57cSdlg {
105293c7b57cSdlg 	return (*(volatile u_int8_t *)(h + o));
105393c7b57cSdlg }
105493c7b57cSdlg 
105593c7b57cSdlg u_int16_t
105693c7b57cSdlg x86_bus_space_mem_read_2(bus_space_handle_t h, bus_size_t o)
105793c7b57cSdlg {
105893c7b57cSdlg 	return (*(volatile u_int16_t *)(h + o));
105993c7b57cSdlg }
106093c7b57cSdlg 
106193c7b57cSdlg u_int32_t
106293c7b57cSdlg x86_bus_space_mem_read_4(bus_space_handle_t h, bus_size_t o)
106393c7b57cSdlg {
106493c7b57cSdlg 	return (*(volatile u_int32_t *)(h + o));
106593c7b57cSdlg }
106693c7b57cSdlg 
106793c7b57cSdlg u_int64_t
106893c7b57cSdlg x86_bus_space_mem_read_8(bus_space_handle_t h, bus_size_t o)
106993c7b57cSdlg {
107093c7b57cSdlg 	return (*(volatile u_int64_t *)(h + o));
107193c7b57cSdlg }
107293c7b57cSdlg 
107393c7b57cSdlg void
107493c7b57cSdlg x86_bus_space_mem_read_multi_1(bus_space_handle_t h, bus_size_t o,
107593c7b57cSdlg     u_int8_t *ptr, bus_size_t cnt)
107693c7b57cSdlg {
107793c7b57cSdlg 	void *dummy1;
107893c7b57cSdlg 	int dummy2;
107993c7b57cSdlg 	void *dummy3;
108093c7b57cSdlg 	int __x;
1081e39f036fSguenther 	__asm volatile(
108293c7b57cSdlg 	"1:	movb (%2),%%al				;"
108393c7b57cSdlg 	"	stosb					;"
108493c7b57cSdlg 	"	loop 1b"				:
108593c7b57cSdlg 	    "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
108693c7b57cSdlg 	    "0" ((ptr)), "1" ((cnt)), "2" (h + o)       :
108793c7b57cSdlg 	    "memory");
108893c7b57cSdlg }
108993c7b57cSdlg 
109093c7b57cSdlg void
109193c7b57cSdlg x86_bus_space_mem_read_multi_2(bus_space_handle_t h, bus_size_t o,
109293c7b57cSdlg     u_int16_t *ptr, bus_size_t cnt)
109393c7b57cSdlg {
109493c7b57cSdlg 	void *dummy1;
109593c7b57cSdlg 	int dummy2;
109693c7b57cSdlg 	void *dummy3;
109793c7b57cSdlg 	int __x;
1098e39f036fSguenther 	__asm volatile(
109993c7b57cSdlg 	"1:	movw (%2),%%ax				;"
110093c7b57cSdlg 	"	stosw					;"
110193c7b57cSdlg 	"	loop 1b"				:
110293c7b57cSdlg 	    "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
110393c7b57cSdlg 	    "0" ((ptr)), "1" ((cnt)), "2" (h + o)       :
110493c7b57cSdlg 	    "memory");
110593c7b57cSdlg }
110693c7b57cSdlg 
110793c7b57cSdlg void
110893c7b57cSdlg x86_bus_space_mem_read_multi_4(bus_space_handle_t h, bus_size_t o,
110993c7b57cSdlg     u_int32_t *ptr, bus_size_t cnt)
111093c7b57cSdlg {
111193c7b57cSdlg 	void *dummy1;
111293c7b57cSdlg 	int dummy2;
111393c7b57cSdlg 	void *dummy3;
111493c7b57cSdlg 	int __x;
1115e39f036fSguenther 	__asm volatile(
111693c7b57cSdlg 	"1:	movl (%2),%%eax				;"
111793c7b57cSdlg 	"	stosl					;"
111893c7b57cSdlg 	"	loop 1b"				:
111993c7b57cSdlg 	    "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
112093c7b57cSdlg 	    "0" ((ptr)), "1" ((cnt)), "2" (h + o)       :
112193c7b57cSdlg 	    "memory");
112293c7b57cSdlg }
112393c7b57cSdlg 
112493c7b57cSdlg void
112593c7b57cSdlg x86_bus_space_mem_read_multi_8(bus_space_handle_t h, bus_size_t o,
112693c7b57cSdlg     u_int64_t *ptr, bus_size_t cnt)
112793c7b57cSdlg {
112893c7b57cSdlg 	void *dummy1;
112993c7b57cSdlg 	int dummy2;
113093c7b57cSdlg 	void *dummy3;
113193c7b57cSdlg 	int __x;
1132e39f036fSguenther 	__asm volatile(
113393c7b57cSdlg 	"1:	movq (%2),%%rax				;"
113493c7b57cSdlg 	"	stosq					;"
113593c7b57cSdlg 	"	loop 1b"				:
113693c7b57cSdlg 	    "=D" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
113793c7b57cSdlg 	    "0" ((ptr)), "1" ((cnt)), "2" (h + o)       :
113893c7b57cSdlg 	    "memory");
113993c7b57cSdlg }
114093c7b57cSdlg 
114193c7b57cSdlg void
114293c7b57cSdlg x86_bus_space_mem_read_region_1(bus_space_handle_t h,
114393c7b57cSdlg     bus_size_t o, u_int8_t *ptr, bus_size_t cnt)
114493c7b57cSdlg {
114593c7b57cSdlg 	int dummy1;
114693c7b57cSdlg 	void *dummy2;
114793c7b57cSdlg 	int dummy3;
1148e39f036fSguenther 	__asm volatile(
114993c7b57cSdlg 	"	repne					;"
115093c7b57cSdlg 	"	movsb"					:
115193c7b57cSdlg 	    "=S" (dummy1), "=D" (dummy2), "=c" (dummy3)	:
115293c7b57cSdlg 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
115393c7b57cSdlg 	    "memory");
115493c7b57cSdlg }
115593c7b57cSdlg 
115693c7b57cSdlg void
115793c7b57cSdlg x86_bus_space_mem_read_region_2(bus_space_handle_t h,
115893c7b57cSdlg     bus_size_t o, u_int16_t *ptr, bus_size_t cnt)
115993c7b57cSdlg {
116093c7b57cSdlg 	int dummy1;
116193c7b57cSdlg 	void *dummy2;
116293c7b57cSdlg 	int dummy3;
1163e39f036fSguenther 	__asm volatile(
116493c7b57cSdlg 	"	repne					;"
116593c7b57cSdlg 	"	movsw"					:
116693c7b57cSdlg 	    "=S" (dummy1), "=D" (dummy2), "=c" (dummy3)	:
116793c7b57cSdlg 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
116893c7b57cSdlg 	    "memory");
116993c7b57cSdlg }
117093c7b57cSdlg 
117193c7b57cSdlg void
117293c7b57cSdlg x86_bus_space_mem_read_region_4(bus_space_handle_t h,
117393c7b57cSdlg     bus_size_t o, u_int32_t *ptr, bus_size_t cnt)
117493c7b57cSdlg {
117593c7b57cSdlg 	int dummy1;
117693c7b57cSdlg 	void *dummy2;
117793c7b57cSdlg 	int dummy3;
1178e39f036fSguenther 	__asm volatile(
117993c7b57cSdlg 	"	repne					;"
118093c7b57cSdlg 	"	movsl"					:
118193c7b57cSdlg 	    "=S" (dummy1), "=D" (dummy2), "=c" (dummy3)	:
118293c7b57cSdlg 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
118393c7b57cSdlg 	    "memory");
118493c7b57cSdlg }
118593c7b57cSdlg 
118693c7b57cSdlg void
118793c7b57cSdlg x86_bus_space_mem_read_region_8(bus_space_handle_t h,
118893c7b57cSdlg     bus_size_t o, u_int64_t *ptr, bus_size_t cnt)
118993c7b57cSdlg {
119093c7b57cSdlg 	int dummy1;
119193c7b57cSdlg 	void *dummy2;
119293c7b57cSdlg 	int dummy3;
1193e39f036fSguenther 	__asm volatile(
119493c7b57cSdlg 	"	repne					;"
119593c7b57cSdlg 	"	movsq"					:
119693c7b57cSdlg 	    "=S" (dummy1), "=D" (dummy2), "=c" (dummy3)	:
119793c7b57cSdlg 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
119893c7b57cSdlg 	    "memory");
119993c7b57cSdlg }
120093c7b57cSdlg 
120193c7b57cSdlg void
120293c7b57cSdlg x86_bus_space_mem_write_4(bus_space_handle_t h, bus_size_t o, u_int32_t v)
120393c7b57cSdlg {
120493c7b57cSdlg 	*(volatile u_int32_t *)(h + o) = v;
120593c7b57cSdlg }
120693c7b57cSdlg 
120793c7b57cSdlg void
120893c7b57cSdlg x86_bus_space_mem_write_8(bus_space_handle_t h, bus_size_t o, u_int64_t v)
120993c7b57cSdlg {
121093c7b57cSdlg 	*(volatile u_int64_t *)(h + o) = v;
121193c7b57cSdlg }
121293c7b57cSdlg 
121393c7b57cSdlg void
121493c7b57cSdlg x86_bus_space_mem_write_multi_1(bus_space_handle_t h,
121593c7b57cSdlg     bus_size_t o, const u_int8_t *ptr, bus_size_t cnt)
121693c7b57cSdlg {
121793c7b57cSdlg 	void *dummy1;
121893c7b57cSdlg 	int dummy2;
121993c7b57cSdlg 	void *dummy3;
122093c7b57cSdlg 	int __x;
1221e39f036fSguenther 	__asm volatile(
122293c7b57cSdlg 	"1:	lodsb					;"
122393c7b57cSdlg 	"	movb %%al,(%2)				;"
122493c7b57cSdlg 	"	loop 1b"				:
122593c7b57cSdlg 	    "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
122693c7b57cSdlg 	    "0" (ptr), "1" (cnt), "2" (h + o));
122793c7b57cSdlg }
122893c7b57cSdlg 
122993c7b57cSdlg void
123093c7b57cSdlg x86_bus_space_mem_write_multi_2(bus_space_handle_t h,
123193c7b57cSdlg     bus_size_t o, const u_int16_t *ptr, bus_size_t cnt)
123293c7b57cSdlg {
123393c7b57cSdlg 	void *dummy1;
123493c7b57cSdlg 	int dummy2;
123593c7b57cSdlg 	void *dummy3;
123693c7b57cSdlg 	int __x;
1237e39f036fSguenther 	__asm volatile(
123893c7b57cSdlg 	"1:	lodsw					;"
123993c7b57cSdlg 	"	movw %%ax,(%2)				;"
124093c7b57cSdlg 	"	loop 1b"				:
124193c7b57cSdlg 	    "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
124293c7b57cSdlg 	    "0" (ptr), "1" (cnt), "2" (h + o));
124393c7b57cSdlg }
124493c7b57cSdlg 
124593c7b57cSdlg void
124693c7b57cSdlg x86_bus_space_mem_write_multi_4(bus_space_handle_t h,
124793c7b57cSdlg     bus_size_t o, const u_int32_t *ptr, bus_size_t cnt)
124893c7b57cSdlg {
124993c7b57cSdlg 	void *dummy1;
125093c7b57cSdlg 	int dummy2;
125193c7b57cSdlg 	void *dummy3;
125293c7b57cSdlg 	int __x;
1253e39f036fSguenther 	__asm volatile(
125493c7b57cSdlg 	"1:	lodsl					;"
125593c7b57cSdlg 	"	movl %%eax,(%2)				;"
125693c7b57cSdlg 	"	loop 1b"				:
125793c7b57cSdlg 	    "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
125893c7b57cSdlg 	    "0" (ptr), "1" (cnt), "2" (h + o));
125993c7b57cSdlg }
126093c7b57cSdlg 
126193c7b57cSdlg void
126293c7b57cSdlg x86_bus_space_mem_write_multi_8(bus_space_handle_t h,
126393c7b57cSdlg     bus_size_t o, const u_int64_t *ptr, bus_size_t cnt)
126493c7b57cSdlg {
126593c7b57cSdlg 	void *dummy1;
126693c7b57cSdlg 	int dummy2;
126793c7b57cSdlg 	void *dummy3;
126893c7b57cSdlg 	int __x;
1269e39f036fSguenther 	__asm volatile(
127093c7b57cSdlg 	"1:	lodsq					;"
127193c7b57cSdlg 	"	movq %%rax,(%2)				;"
127293c7b57cSdlg 	"	loop 1b"				:
127393c7b57cSdlg 	    "=S" (dummy1), "=c" (dummy2), "=r" (dummy3), "=&a" (__x) :
127493c7b57cSdlg 	    "0" (ptr), "1" (cnt), "2" (h + o));
127593c7b57cSdlg }
127693c7b57cSdlg 
127793c7b57cSdlg void
127893c7b57cSdlg x86_bus_space_mem_write_region_1(bus_space_handle_t h,
127993c7b57cSdlg     bus_size_t o, const u_int8_t *ptr, bus_size_t cnt)
128093c7b57cSdlg {
128193c7b57cSdlg 	int dummy1;
128293c7b57cSdlg 	void *dummy2;
128393c7b57cSdlg 	int dummy3;
1284e39f036fSguenther 	__asm volatile(
128593c7b57cSdlg 	"	repne					;"
128693c7b57cSdlg 	"	movsb"					:
128793c7b57cSdlg 	    "=D" (dummy1), "=S" (dummy2), "=c" (dummy3)	:
128893c7b57cSdlg 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
128993c7b57cSdlg 	    "memory");
129093c7b57cSdlg }
129193c7b57cSdlg 
129293c7b57cSdlg void
129393c7b57cSdlg x86_bus_space_mem_write_region_2(bus_space_handle_t h,
129493c7b57cSdlg     bus_size_t o, const u_int16_t *ptr, bus_size_t cnt)
129593c7b57cSdlg {
129693c7b57cSdlg 	int dummy1;
129793c7b57cSdlg 	void *dummy2;
129893c7b57cSdlg 	int dummy3;
1299e39f036fSguenther 	__asm volatile(
130093c7b57cSdlg 	"	repne					;"
130193c7b57cSdlg 	"	movsw"					:
130293c7b57cSdlg 	    "=D" (dummy1), "=S" (dummy2), "=c" (dummy3)	:
130393c7b57cSdlg 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
130493c7b57cSdlg 	    "memory");
130593c7b57cSdlg }
130693c7b57cSdlg 
130793c7b57cSdlg void
130893c7b57cSdlg x86_bus_space_mem_write_region_4(bus_space_handle_t h,
130993c7b57cSdlg     bus_size_t o, const u_int32_t *ptr, bus_size_t cnt)
131093c7b57cSdlg {
1311ebbaad44Soga 	int dummy1;
1312ebbaad44Soga 	void *dummy2;
1313ebbaad44Soga 	int dummy3;
1314e39f036fSguenther 	__asm volatile(
1315ebbaad44Soga 	"	repne					;"
1316ebbaad44Soga 	"	movsl"					:
1317ebbaad44Soga 	    "=D" (dummy1), "=S" (dummy2), "=c" (dummy3)	:
1318ebbaad44Soga 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
1319ebbaad44Soga 	    "memory");
1320ebbaad44Soga }
1321ebbaad44Soga 
1322ebbaad44Soga void
132393c7b57cSdlg x86_bus_space_mem_write_region_8(bus_space_handle_t h,
13249f2791f2Sdlg     bus_size_t o, const u_int64_t *ptr, bus_size_t cnt)
13259f2791f2Sdlg {
13269f2791f2Sdlg 	int dummy1;
13279f2791f2Sdlg 	void *dummy2;
13289f2791f2Sdlg 	int dummy3;
1329e39f036fSguenther 	__asm volatile(
13309f2791f2Sdlg 	"	repne					;"
13319f2791f2Sdlg 	"	movsq"					:
13329f2791f2Sdlg 	    "=D" (dummy1), "=S" (dummy2), "=c" (dummy3)	:
13339f2791f2Sdlg 	    "0" (h + o), "1" (ptr), "2" (cnt)	:
13349f2791f2Sdlg 	    "memory");
13359f2791f2Sdlg }
13369f2791f2Sdlg 
13379f2791f2Sdlg void
133893c7b57cSdlg x86_bus_space_mem_set_multi_1(bus_space_handle_t h, bus_size_t o,
1339ebbaad44Soga     u_int8_t v, size_t c)
1340ebbaad44Soga {
1341ebbaad44Soga 	bus_addr_t addr = h + o;
1342ebbaad44Soga 
1343ebbaad44Soga 	while (c--)
1344ebbaad44Soga 		*(volatile u_int8_t *)(addr) = v;
1345ebbaad44Soga }
1346ebbaad44Soga 
1347ebbaad44Soga void
134893c7b57cSdlg x86_bus_space_mem_set_multi_2(bus_space_handle_t h, bus_size_t o,
1349ebbaad44Soga     u_int16_t v, size_t c)
1350ebbaad44Soga {
1351ebbaad44Soga 	bus_addr_t addr = h + o;
1352ebbaad44Soga 
1353ebbaad44Soga 	while (c--)
1354ebbaad44Soga 		*(volatile u_int16_t *)(addr) = v;
1355ebbaad44Soga }
1356ebbaad44Soga 
1357ebbaad44Soga void
135893c7b57cSdlg x86_bus_space_mem_set_multi_4(bus_space_handle_t h, bus_size_t o,
1359ebbaad44Soga     u_int32_t v, size_t c)
1360ebbaad44Soga {
1361ebbaad44Soga 	bus_addr_t addr = h + o;
1362ebbaad44Soga 
1363ebbaad44Soga 	while (c--)
1364ebbaad44Soga 		*(volatile u_int32_t *)(addr) = v;
1365ebbaad44Soga }
1366ebbaad44Soga 
1367ebbaad44Soga void
136893c7b57cSdlg x86_bus_space_mem_set_multi_8(bus_space_handle_t h, bus_size_t o,
13699f2791f2Sdlg     u_int64_t v, size_t c)
13709f2791f2Sdlg {
13719f2791f2Sdlg 	bus_addr_t addr = h + o;
13729f2791f2Sdlg 
13739f2791f2Sdlg 	while (c--)
13749f2791f2Sdlg 		*(volatile u_int64_t *)(addr) = v;
13759f2791f2Sdlg }
13769f2791f2Sdlg 
13779f2791f2Sdlg void
137893c7b57cSdlg x86_bus_space_mem_set_region_1(bus_space_handle_t h, bus_size_t o,
1379ebbaad44Soga     u_int8_t v, size_t c)
1380ebbaad44Soga {
1381ebbaad44Soga 	bus_addr_t addr = h + o;
1382ebbaad44Soga 
1383ebbaad44Soga 	for (; c != 0; c--, addr++)
1384ebbaad44Soga 		*(volatile u_int8_t *)(addr) = v;
1385ebbaad44Soga }
1386ebbaad44Soga 
1387ebbaad44Soga void
138893c7b57cSdlg x86_bus_space_mem_set_region_2(bus_space_handle_t h, bus_size_t o,
1389ebbaad44Soga     u_int16_t v, size_t c)
1390ebbaad44Soga {
1391ebbaad44Soga 	bus_addr_t addr = h + o;
1392ebbaad44Soga 
139393c7b57cSdlg 	for (; c != 0; c--, addr += sizeof(v))
1394ebbaad44Soga 		*(volatile u_int16_t *)(addr) = v;
1395ebbaad44Soga }
1396ebbaad44Soga 
1397ebbaad44Soga void
139893c7b57cSdlg x86_bus_space_mem_set_region_4(bus_space_handle_t h, bus_size_t o,
1399ebbaad44Soga     u_int32_t v, size_t c)
1400ebbaad44Soga {
1401ebbaad44Soga 	bus_addr_t addr = h + o;
1402ebbaad44Soga 
140393c7b57cSdlg 	for (; c != 0; c--, addr += sizeof(v))
1404ebbaad44Soga 		*(volatile u_int32_t *)(addr) = v;
1405ebbaad44Soga }
1406ebbaad44Soga 
1407ebbaad44Soga void
140893c7b57cSdlg x86_bus_space_mem_set_region_8(bus_space_handle_t h, bus_size_t o,
14099f2791f2Sdlg     u_int64_t v, size_t c)
14109f2791f2Sdlg {
14119f2791f2Sdlg 	bus_addr_t addr = h + o;
14129f2791f2Sdlg 
14139f2791f2Sdlg 	for (; c != 0; c--, addr += sizeof(v))
14149f2791f2Sdlg 		*(volatile u_int64_t *)(addr) = v;
14159f2791f2Sdlg }
14169f2791f2Sdlg 
14179f2791f2Sdlg void
141893c7b57cSdlg x86_bus_space_mem_copy_1( bus_space_handle_t h1, bus_size_t o1,
1419ebbaad44Soga     bus_space_handle_t h2, bus_size_t o2, size_t c)
1420ebbaad44Soga {
1421ebbaad44Soga 	bus_addr_t addr1 = h1 + o1;
1422ebbaad44Soga 	bus_addr_t addr2 = h2 + o2;
1423ebbaad44Soga 
1424ebbaad44Soga 	if (addr1 >= addr2) {
1425ebbaad44Soga 		/* src after dest: copy forward */
1426ebbaad44Soga 		for (; c != 0; c--, addr1++, addr2++)
1427ebbaad44Soga 			*(volatile u_int8_t *)(addr2) =
1428ebbaad44Soga 			    *(volatile u_int8_t *)(addr1);
1429ebbaad44Soga 	} else {
1430ebbaad44Soga 		/* dest after src: copy backwards */
1431ebbaad44Soga 		for (addr1 += (c - 1), addr2 += (c - 1);
1432ebbaad44Soga 		    c != 0; c--, addr1--, addr2--)
1433ebbaad44Soga 			*(volatile u_int8_t *)(addr2) =
1434ebbaad44Soga 			    *(volatile u_int8_t *)(addr1);
1435ebbaad44Soga 	}
1436ebbaad44Soga }
1437ebbaad44Soga 
1438ebbaad44Soga void
143993c7b57cSdlg x86_bus_space_mem_copy_2(bus_space_handle_t h1, bus_size_t o1,
1440ebbaad44Soga     bus_space_handle_t h2, bus_size_t o2, size_t c)
1441ebbaad44Soga {
1442ebbaad44Soga 	bus_addr_t addr1 = h1 + o1;
1443ebbaad44Soga 	bus_addr_t addr2 = h2 + o2;
1444ebbaad44Soga 
1445ebbaad44Soga 	if (addr1 >= addr2) {
1446ebbaad44Soga 		/* src after dest: copy forward */
1447ebbaad44Soga 		for (; c != 0; c--, addr1 += 2, addr2 += 2)
1448ebbaad44Soga 			*(volatile u_int16_t *)(addr2) =
1449ebbaad44Soga 			    *(volatile u_int16_t *)(addr1);
1450ebbaad44Soga 	} else {
1451ebbaad44Soga 		/* dest after src: copy backwards */
1452ebbaad44Soga 		for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1);
1453ebbaad44Soga 		    c != 0; c--, addr1 -= 2, addr2 -= 2)
1454ebbaad44Soga 			*(volatile u_int16_t *)(addr2) =
1455ebbaad44Soga 			    *(volatile u_int16_t *)(addr1);
1456ebbaad44Soga 	}
1457ebbaad44Soga }
1458ebbaad44Soga 
1459ebbaad44Soga void
146093c7b57cSdlg x86_bus_space_mem_copy_4(bus_space_handle_t h1, bus_size_t o1,
1461ebbaad44Soga     bus_space_handle_t h2, bus_size_t o2, size_t c)
1462ebbaad44Soga {
1463ebbaad44Soga 	bus_addr_t addr1 = h1 + o1;
1464ebbaad44Soga 	bus_addr_t addr2 = h2 + o2;
1465ebbaad44Soga 
1466ebbaad44Soga 	if (addr1 >= addr2) {
1467ebbaad44Soga 		/* src after dest: copy forward */
1468ebbaad44Soga 		for (; c != 0; c--, addr1 += 4, addr2 += 4)
1469ebbaad44Soga 			*(volatile u_int32_t *)(addr2) =
1470ebbaad44Soga 			    *(volatile u_int32_t *)(addr1);
1471ebbaad44Soga 	} else {
1472ebbaad44Soga 		/* dest after src: copy backwards */
1473ebbaad44Soga 		for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1);
1474ebbaad44Soga 		    c != 0; c--, addr1 -= 4, addr2 -= 4)
1475ebbaad44Soga 			*(volatile u_int32_t *)(addr2) =
1476ebbaad44Soga 			    *(volatile u_int32_t *)(addr1);
1477ebbaad44Soga 	}
1478ebbaad44Soga }
1479ebbaad44Soga 
1480ebbaad44Soga void
148193c7b57cSdlg x86_bus_space_mem_copy_8(bus_space_handle_t h1, bus_size_t o1,
14829f2791f2Sdlg     bus_space_handle_t h2, bus_size_t o2, size_t c)
14839f2791f2Sdlg {
14849f2791f2Sdlg 	bus_addr_t addr1 = h1 + o1;
14859f2791f2Sdlg 	bus_addr_t addr2 = h2 + o2;
14869f2791f2Sdlg 
14879f2791f2Sdlg 	if (addr1 >= addr2) {
14889f2791f2Sdlg 		/* src after dest: copy forward */
14899f2791f2Sdlg 		for (; c != 0; c--, addr1 += 8, addr2 += 8)
14909f2791f2Sdlg 			*(volatile u_int64_t *)(addr2) =
14919f2791f2Sdlg 			    *(volatile u_int64_t *)(addr1);
14929f2791f2Sdlg 	} else {
14939f2791f2Sdlg 		/* dest after src: copy backwards */
14949f2791f2Sdlg 		for (addr1 += 8 * (c - 1), addr2 += 8 * (c - 1);
14959f2791f2Sdlg 		    c != 0; c--, addr1 -= 8, addr2 -= 8)
14969f2791f2Sdlg 			*(volatile u_int64_t *)(addr2) =
14979f2791f2Sdlg 			    *(volatile u_int64_t *)(addr1);
14989f2791f2Sdlg 	}
14999f2791f2Sdlg }
15009f2791f2Sdlg 
150193c7b57cSdlg void *
150293c7b57cSdlg x86_bus_space_mem_vaddr(bus_space_handle_t h)
1503ebbaad44Soga {
150493c7b57cSdlg 	return ((void *)h);
1505ebbaad44Soga }
1506ebbaad44Soga 
150793c7b57cSdlg paddr_t
150893c7b57cSdlg x86_bus_space_mem_mmap(bus_addr_t addr, off_t off, int prot, int flags)
150993c7b57cSdlg {
151093c7b57cSdlg 	/*
151193c7b57cSdlg 	 * "addr" is the base address of the device we're mapping.
151293c7b57cSdlg 	 * "off" is the offset into that device.
151393c7b57cSdlg 	 *
151493c7b57cSdlg 	 * Note we are called for each "page" in the device that
151593c7b57cSdlg 	 * the upper layers want to map.
151693c7b57cSdlg 	 */
151793c7b57cSdlg 	return (addr + off);
151893c7b57cSdlg }
1519