Home | History | Annotate | Line # | Download | only in pci
      1 /* $NetBSD: pci_swiz_bus_io_chipdep.c,v 1.45 2023/12/06 01:46:34 thorpej Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 /*
     34  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
     35  * All rights reserved.
     36  *
     37  * Author: Chris G. Demetriou
     38  *
     39  * Permission to use, copy, modify and distribute this software and
     40  * its documentation is hereby granted, provided that both the copyright
     41  * notice and this permission notice appear in all copies of the
     42  * software, derivative works or modified versions, and any portions
     43  * thereof, and that both notices appear in supporting documentation.
     44  *
     45  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     46  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     47  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     48  *
     49  * Carnegie Mellon requests users of this software to return to
     50  *
     51  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     52  *  School of Computer Science
     53  *  Carnegie Mellon University
     54  *  Pittsburgh PA 15213-3890
     55  *
     56  * any improvements or extensions that they make and grant Carnegie the
     57  * rights to redistribute these changes.
     58  */
     59 
     60 /*
     61  * Common PCI Chipset "bus I/O" functions, for chipsets which have to
     62  * deal with only a single PCI interface chip in a machine.
     63  *
     64  * uses:
     65  *	CHIP		name of the 'chip' it's being compiled for.
     66  *	CHIP_IO_BASE	Sparse I/O space base to use.
     67  *	CHIP_IO_ARENA_STORE
     68  *			If defined, device-provided static storage area
     69  *			for the I/O space arena.  If this is defined,
     70  *			CHIP_IO_BTAG_STORE and CHIP_IO_BTAG_COUNT must
     71  *			also be defined.  If this is not defined, a
     72  *			static area will be declared.
     73  *	CHIP_IO_BTAG_STORE
     74  *			Device-provided static storage area for the
     75  *			I/O space arena's boundary tags.  Ignored
     76  *			unless CHIP_IO_ARENA_STORE is defined.
     77  *	CHIP_IO_BTAG_COUNT
     78  *			The number of device-provided static I/O
     79  *			space boundary tags.  Ignored unless
     80  *			CHIP_IO_ARENA_STORE is defined.
     81  */
     82 
     83 #include <sys/cdefs.h>
     84 __KERNEL_RCSID(1, "$NetBSD: pci_swiz_bus_io_chipdep.c,v 1.45 2023/12/06 01:46:34 thorpej Exp $");
     85 
     86 #include <sys/vmem_impl.h>
     87 
     88 #define	__C(A,B)	__CONCAT(A,B)
     89 #define	__S(S)		__STRING(S)
     90 
     91 /* mapping/unmapping */
     92 static int	__C(CHIP,_io_map)(void *, bus_addr_t, bus_size_t, int,
     93 		    bus_space_handle_t *, int);
     94 static void	__C(CHIP,_io_unmap)(void *, bus_space_handle_t,
     95 		    bus_size_t, int);
     96 static int	__C(CHIP,_io_subregion)(void *, bus_space_handle_t,
     97 		    bus_size_t, bus_size_t, bus_space_handle_t *);
     98 
     99 static int	__C(CHIP,_io_translate)(void *, bus_addr_t, bus_size_t,
    100 		    int, struct alpha_bus_space_translation *);
    101 static int	__C(CHIP,_io_get_window)(void *, int,
    102 		    struct alpha_bus_space_translation *);
    103 
    104 /* allocation/deallocation */
    105 static int	__C(CHIP,_io_alloc)(void *, bus_addr_t, bus_addr_t,
    106 		    bus_size_t, bus_size_t, bus_addr_t, int, bus_addr_t *,
    107 	            bus_space_handle_t *);
    108 static void	__C(CHIP,_io_free)(void *, bus_space_handle_t,
    109 		    bus_size_t);
    110 
    111 /* get kernel virtual address */
    112 static void *	__C(CHIP,_io_vaddr)(void *, bus_space_handle_t);
    113 
    114 /* mmap for user */
    115 static paddr_t	__C(CHIP,_io_mmap)(void *, bus_addr_t, off_t, int, int);
    116 
    117 /* barrier */
    118 static inline void __C(CHIP,_io_barrier)(void *, bus_space_handle_t,
    119 		    bus_size_t, bus_size_t, int);
    120 
    121 /* read (single) */
    122 static inline uint8_t __C(CHIP,_io_read_1)(void *, bus_space_handle_t,
    123 		    bus_size_t);
    124 static inline uint16_t __C(CHIP,_io_read_2)(void *, bus_space_handle_t,
    125 		    bus_size_t);
    126 static inline uint32_t __C(CHIP,_io_read_4)(void *, bus_space_handle_t,
    127 		    bus_size_t);
    128 static inline uint64_t __C(CHIP,_io_read_8)(void *, bus_space_handle_t,
    129 		    bus_size_t);
    130 
    131 /* read multiple */
    132 static void	__C(CHIP,_io_read_multi_1)(void *, bus_space_handle_t,
    133 		    bus_size_t, uint8_t *, bus_size_t);
    134 static void	__C(CHIP,_io_read_multi_2)(void *, bus_space_handle_t,
    135 		    bus_size_t, uint16_t *, bus_size_t);
    136 static void	__C(CHIP,_io_read_multi_4)(void *, bus_space_handle_t,
    137 		    bus_size_t, uint32_t *, bus_size_t);
    138 static void	__C(CHIP,_io_read_multi_8)(void *, bus_space_handle_t,
    139 		    bus_size_t, uint64_t *, bus_size_t);
    140 
    141 /* read region */
    142 static void	__C(CHIP,_io_read_region_1)(void *, bus_space_handle_t,
    143 		    bus_size_t, uint8_t *, bus_size_t);
    144 static void	__C(CHIP,_io_read_region_2)(void *, bus_space_handle_t,
    145 		    bus_size_t, uint16_t *, bus_size_t);
    146 static void	__C(CHIP,_io_read_region_4)(void *, bus_space_handle_t,
    147 		    bus_size_t, uint32_t *, bus_size_t);
    148 static void	__C(CHIP,_io_read_region_8)(void *, bus_space_handle_t,
    149 		    bus_size_t, uint64_t *, bus_size_t);
    150 
    151 /* write (single) */
    152 static inline void __C(CHIP,_io_write_1)(void *, bus_space_handle_t,
    153 		    bus_size_t, uint8_t);
    154 static inline void __C(CHIP,_io_write_2)(void *, bus_space_handle_t,
    155 		    bus_size_t, uint16_t);
    156 static inline void __C(CHIP,_io_write_4)(void *, bus_space_handle_t,
    157 		    bus_size_t, uint32_t);
    158 static inline void __C(CHIP,_io_write_8)(void *, bus_space_handle_t,
    159 		    bus_size_t, uint64_t);
    160 
    161 /* write multiple */
    162 static void	__C(CHIP,_io_write_multi_1)(void *, bus_space_handle_t,
    163 		    bus_size_t, const uint8_t *, bus_size_t);
    164 static void	__C(CHIP,_io_write_multi_2)(void *, bus_space_handle_t,
    165 		    bus_size_t, const uint16_t *, bus_size_t);
    166 static void	__C(CHIP,_io_write_multi_4)(void *, bus_space_handle_t,
    167 		    bus_size_t, const uint32_t *, bus_size_t);
    168 static void	__C(CHIP,_io_write_multi_8)(void *, bus_space_handle_t,
    169 		    bus_size_t, const uint64_t *, bus_size_t);
    170 
    171 /* write region */
    172 static void	__C(CHIP,_io_write_region_1)(void *, bus_space_handle_t,
    173 		    bus_size_t, const uint8_t *, bus_size_t);
    174 static void	__C(CHIP,_io_write_region_2)(void *, bus_space_handle_t,
    175 		    bus_size_t, const uint16_t *, bus_size_t);
    176 static void	__C(CHIP,_io_write_region_4)(void *, bus_space_handle_t,
    177 		    bus_size_t, const uint32_t *, bus_size_t);
    178 static void	__C(CHIP,_io_write_region_8)(void *, bus_space_handle_t,
    179 		    bus_size_t, const uint64_t *, bus_size_t);
    180 
    181 /* set multiple */
    182 static void	__C(CHIP,_io_set_multi_1)(void *, bus_space_handle_t,
    183 		    bus_size_t, uint8_t, bus_size_t);
    184 static void	__C(CHIP,_io_set_multi_2)(void *, bus_space_handle_t,
    185 		    bus_size_t, uint16_t, bus_size_t);
    186 static void	__C(CHIP,_io_set_multi_4)(void *, bus_space_handle_t,
    187 		    bus_size_t, uint32_t, bus_size_t);
    188 static void	__C(CHIP,_io_set_multi_8)(void *, bus_space_handle_t,
    189 		    bus_size_t, uint64_t, bus_size_t);
    190 
    191 /* set region */
    192 static void	__C(CHIP,_io_set_region_1)(void *, bus_space_handle_t,
    193 		    bus_size_t, uint8_t, bus_size_t);
    194 static void	__C(CHIP,_io_set_region_2)(void *, bus_space_handle_t,
    195 		    bus_size_t, uint16_t, bus_size_t);
    196 static void	__C(CHIP,_io_set_region_4)(void *, bus_space_handle_t,
    197 		    bus_size_t, uint32_t, bus_size_t);
    198 static void	__C(CHIP,_io_set_region_8)(void *, bus_space_handle_t,
    199 		    bus_size_t, uint64_t, bus_size_t);
    200 
    201 /* copy */
    202 static void	__C(CHIP,_io_copy_region_1)(void *, bus_space_handle_t,
    203 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
    204 static void	__C(CHIP,_io_copy_region_2)(void *, bus_space_handle_t,
    205 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
    206 static void	__C(CHIP,_io_copy_region_4)(void *, bus_space_handle_t,
    207 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
    208 static void	__C(CHIP,_io_copy_region_8)(void *, bus_space_handle_t,
    209 		    bus_size_t, bus_space_handle_t, bus_size_t, bus_size_t);
    210 
    211 #ifndef CHIP_IO_ARENA_STORE
    212 
    213 #ifdef CHIP_IO_W1_BUS_START
    214 #define	CHIP_IO_W1_BUS_SPAN	1
    215 #else
    216 #define	CHIP_IO_W1_BUS_SPAN	0
    217 #endif /* CHIP_IO_W1_BUS_START */
    218 
    219 #ifdef CHIP_IO_W2_BUS_START
    220 #define	CHIP_IO_W2_BUS_SPAN	1
    221 #else
    222 #define	CHIP_IO_W2_BUS_SPAN	0
    223 #endif /* CHIP_IO_W2_BUS_START */
    224 
    225 #define	CHIP_IO_SPAN_COUNT	(CHIP_IO_W1_BUS_SPAN + CHIP_IO_W2_BUS_SPAN)
    226 
    227 #define	CHIP_IO_BTAG_COUNT(v)	VMEM_EST_BTCOUNT(CHIP_IO_SPAN_COUNT, 8)
    228 #define	CHIP_IO_BTAG_STORE(v)	__C(CHIP,_io_btag_store)
    229 #define	CHIP_IO_ARENA_STORE(v)	(&(__C(CHIP,_io_arena_store)))
    230 
    231 static struct vmem __C(CHIP,_io_arena_store);
    232 static struct vmem_btag __C(CHIP,_io_btag_store)[CHIP_IO_BTAG_COUNT(xxx)];
    233 
    234 #endif /* CHIP_IO_ARENA_STORE */
    235 
    236 #ifndef CHIP_ADDR_SHIFT
    237 #define	CHIP_ADDR_SHIFT		5
    238 #endif
    239 
    240 #ifndef CHIP_SIZE_SHIFT
    241 #define	CHIP_SIZE_SHIFT		3
    242 #endif
    243 
    244 void
    245 __C(CHIP,_bus_io_init)(bus_space_tag_t t, void *v)
    246 {
    247 	vmem_t *vm;
    248 	int error __diagused;
    249 
    250 	/*
    251 	 * Initialize the bus space tag.
    252 	 */
    253 
    254 	/* cookie */
    255 	t->abs_cookie =		v;
    256 
    257 	/* mapping/unmapping */
    258 	t->abs_map =		__C(CHIP,_io_map);
    259 	t->abs_unmap =		__C(CHIP,_io_unmap);
    260 	t->abs_subregion =	__C(CHIP,_io_subregion);
    261 
    262 	t->abs_translate =	__C(CHIP,_io_translate);
    263 	t->abs_get_window =	__C(CHIP,_io_get_window);
    264 
    265 	/* allocation/deallocation */
    266 	t->abs_alloc =		__C(CHIP,_io_alloc);
    267 	t->abs_free = 		__C(CHIP,_io_free);
    268 
    269 	/* get kernel virtual address */
    270 	t->abs_vaddr =		__C(CHIP,_io_vaddr);
    271 
    272 	/* mmap for user */
    273 	t->abs_mmap =		__C(CHIP,_io_mmap);
    274 
    275 	/* barrier */
    276 	t->abs_barrier =	__C(CHIP,_io_barrier);
    277 
    278 	/* read (single) */
    279 	t->abs_r_1 =		__C(CHIP,_io_read_1);
    280 	t->abs_r_2 =		__C(CHIP,_io_read_2);
    281 	t->abs_r_4 =		__C(CHIP,_io_read_4);
    282 	t->abs_r_8 =		__C(CHIP,_io_read_8);
    283 
    284 	/* read multiple */
    285 	t->abs_rm_1 =		__C(CHIP,_io_read_multi_1);
    286 	t->abs_rm_2 =		__C(CHIP,_io_read_multi_2);
    287 	t->abs_rm_4 =		__C(CHIP,_io_read_multi_4);
    288 	t->abs_rm_8 =		__C(CHIP,_io_read_multi_8);
    289 
    290 	/* read region */
    291 	t->abs_rr_1 =		__C(CHIP,_io_read_region_1);
    292 	t->abs_rr_2 =		__C(CHIP,_io_read_region_2);
    293 	t->abs_rr_4 =		__C(CHIP,_io_read_region_4);
    294 	t->abs_rr_8 =		__C(CHIP,_io_read_region_8);
    295 
    296 	/* write (single) */
    297 	t->abs_w_1 =		__C(CHIP,_io_write_1);
    298 	t->abs_w_2 =		__C(CHIP,_io_write_2);
    299 	t->abs_w_4 =		__C(CHIP,_io_write_4);
    300 	t->abs_w_8 =		__C(CHIP,_io_write_8);
    301 
    302 	/* write multiple */
    303 	t->abs_wm_1 =		__C(CHIP,_io_write_multi_1);
    304 	t->abs_wm_2 =		__C(CHIP,_io_write_multi_2);
    305 	t->abs_wm_4 =		__C(CHIP,_io_write_multi_4);
    306 	t->abs_wm_8 =		__C(CHIP,_io_write_multi_8);
    307 
    308 	/* write region */
    309 	t->abs_wr_1 =		__C(CHIP,_io_write_region_1);
    310 	t->abs_wr_2 =		__C(CHIP,_io_write_region_2);
    311 	t->abs_wr_4 =		__C(CHIP,_io_write_region_4);
    312 	t->abs_wr_8 =		__C(CHIP,_io_write_region_8);
    313 
    314 	/* set multiple */
    315 	t->abs_sm_1 =		__C(CHIP,_io_set_multi_1);
    316 	t->abs_sm_2 =		__C(CHIP,_io_set_multi_2);
    317 	t->abs_sm_4 =		__C(CHIP,_io_set_multi_4);
    318 	t->abs_sm_8 =		__C(CHIP,_io_set_multi_8);
    319 
    320 	/* set region */
    321 	t->abs_sr_1 =		__C(CHIP,_io_set_region_1);
    322 	t->abs_sr_2 =		__C(CHIP,_io_set_region_2);
    323 	t->abs_sr_4 =		__C(CHIP,_io_set_region_4);
    324 	t->abs_sr_8 =		__C(CHIP,_io_set_region_8);
    325 
    326 	/* copy */
    327 	t->abs_c_1 =		__C(CHIP,_io_copy_region_1);
    328 	t->abs_c_2 =		__C(CHIP,_io_copy_region_2);
    329 	t->abs_c_4 =		__C(CHIP,_io_copy_region_4);
    330 	t->abs_c_8 =		__C(CHIP,_io_copy_region_8);
    331 
    332 	vm = vmem_init(CHIP_IO_ARENA_STORE(v),
    333 		       __S(__C(CHIP,_bus_io)),		/* name */
    334 		       0,				/* addr */
    335 		       0,				/* size */
    336 		       1,				/* quantum */
    337 		       NULL,				/* importfn */
    338 		       NULL,				/* releasefn */
    339 		       NULL,				/* source */
    340 		       0,				/* qcache_max */
    341 		       VM_NOSLEEP | VM_PRIVTAGS,
    342 		       IPL_NONE);
    343 	KASSERT(vm != NULL);
    344 
    345 	vmem_add_bts(vm, CHIP_IO_BTAG_STORE(v), CHIP_IO_BTAG_COUNT(v));
    346 
    347 #ifdef CHIP_IO_W1_BUS_START
    348 #ifdef EXTENT_DEBUG
    349 	printf("io: adding span 0x%lx to 0x%lx\n", CHIP_IO_W1_BUS_START(v),
    350 	    CHIP_IO_W1_BUS_END(v));
    351 #endif
    352 	error = vmem_add(vm, CHIP_IO_W1_BUS_START(v),
    353 	    CHIP_IO_W1_BUS_END(v) - CHIP_IO_W1_BUS_START(v) + 1, VM_NOSLEEP);
    354 	KASSERT(error == 0);
    355 #endif /* CHIP_IO_W1_BUS_START */
    356 
    357 #ifdef CHIP_IO_W2_BUS_START
    358 #ifdef EXTENT_DEBUG
    359 	printf("io: adding span 0x%lx to 0x%lx\n", CHIP_IO_W2_BUS_START(v),
    360 	    CHIP_IO_W2_BUS_END(v));
    361 #endif
    362 	error = vmem_add(vm, CHIP_IO_W2_BUS_START(v),
    363 	    CHIP_IO_W2_BUS_END(v) - CHIP_IO_W2_BUS_START(v) + 1, VM_NOSLEEP);
    364 #endif /* CHIP_IO_W2_BUS_START */
    365 
    366 #ifdef EXTENT_DEBUG
    367 	/* vmem_print(vm);			XXX */
    368 #endif
    369 	CHIP_IO_ARENA(v) = vm;
    370 }
    371 
    372 static int
    373 __C(CHIP,_io_translate)(void *v, bus_addr_t ioaddr, bus_size_t iolen,
    374     int flags, struct alpha_bus_space_translation *abst)
    375 {
    376 	bus_addr_t ioend = ioaddr + (iolen - 1);
    377 	int linear = flags & BUS_SPACE_MAP_LINEAR;
    378 
    379 	/*
    380 	 * Can't map i/o space linearly.
    381 	 */
    382 	if (linear)
    383 		return (EOPNOTSUPP);
    384 
    385 #ifdef CHIP_IO_W1_BUS_START
    386 	if (ioaddr >= CHIP_IO_W1_BUS_START(v) &&
    387 	    ioend <= CHIP_IO_W1_BUS_END(v))
    388 		return (__C(CHIP,_io_get_window)(v, 0, abst));
    389 #endif
    390 
    391 #ifdef CHIP_IO_W2_BUS_START
    392 	if (ioaddr >= CHIP_IO_W2_BUS_START(v) &&
    393 	    ioend <= CHIP_IO_W2_BUS_END(v))
    394 		return (__C(CHIP,_io_get_window)(v, 1, abst));
    395 #endif
    396 
    397 #ifdef EXTENT_DEBUG
    398 	printf("\n");
    399 #ifdef CHIP_IO_W1_BUS_START
    400 	printf("%s: window[1]=0x%lx-0x%lx\n",
    401 	    __S(__C(CHIP,_io_map)), CHIP_IO_W1_BUS_START(v),
    402 	    CHIP_IO_W1_BUS_END(v));
    403 #endif
    404 #ifdef CHIP_IO_W2_BUS_START
    405 	printf("%s: window[2]=0x%lx-0x%lx\n",
    406 	    __S(__C(CHIP,_io_map)), CHIP_IO_W2_BUS_START(v),
    407 	    CHIP_IO_W2_BUS_END(v));
    408 #endif
    409 #endif /* EXTENT_DEBUG */
    410 	/* No translation. */
    411 	return (EINVAL);
    412 }
    413 
    414 static int
    415 __C(CHIP,_io_get_window)(void *v, int window,
    416     struct alpha_bus_space_translation *abst)
    417 {
    418 
    419 	switch (window) {
    420 #ifdef CHIP_IO_W1_BUS_START
    421 	case 0:
    422 		abst->abst_bus_start = CHIP_IO_W1_BUS_START(v);
    423 		abst->abst_bus_end = CHIP_IO_W1_BUS_END(v);
    424 		abst->abst_sys_start = CHIP_IO_W1_SYS_START(v);
    425 		abst->abst_sys_end = CHIP_IO_W1_SYS_END(v);
    426 		abst->abst_addr_shift = CHIP_ADDR_SHIFT;
    427 		abst->abst_size_shift = CHIP_SIZE_SHIFT;
    428 		abst->abst_flags = 0;
    429 		break;
    430 #endif
    431 
    432 #ifdef CHIP_IO_W2_BUS_START
    433 	case 1:
    434 		abst->abst_bus_start = CHIP_IO_W2_BUS_START(v);
    435 		abst->abst_bus_end = CHIP_IO_W2_BUS_END(v);
    436 		abst->abst_sys_start = CHIP_IO_W2_SYS_START(v);
    437 		abst->abst_sys_end = CHIP_IO_W2_SYS_END(v);
    438 		abst->abst_addr_shift = CHIP_ADDR_SHIFT;
    439 		abst->abst_size_shift = CHIP_SIZE_SHIFT;
    440 		abst->abst_flags = 0;
    441 		break;
    442 #endif
    443 
    444 	default:
    445 		panic(__S(__C(CHIP,_io_get_window)) ": invalid window %d",
    446 		    window);
    447 	}
    448 
    449 	return (0);
    450 }
    451 
    452 static int
    453 __C(CHIP,_io_map)(void *v, bus_addr_t ioaddr, bus_size_t iosize,
    454     int flags, bus_space_handle_t *iohp, int acct)
    455 {
    456 	struct alpha_bus_space_translation abst;
    457 	int error;
    458 
    459 	/*
    460 	 * Get the translation for this address.
    461 	 */
    462 	error = __C(CHIP,_io_translate)(v, ioaddr, iosize, flags, &abst);
    463 	if (error)
    464 		return (error);
    465 
    466 	if (acct == 0)
    467 		goto mapit;
    468 
    469 #ifdef EXTENT_DEBUG
    470 	printf("io: allocating 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
    471 #endif
    472 	error = vmem_xalloc_addr(CHIP_IO_ARENA(v), ioaddr, iosize, VM_NOSLEEP);
    473 	if (error) {
    474 #ifdef EXTENT_DEBUG
    475 		printf("io: allocation failed (%d)\n", error);
    476 		/* vmem_print(CHIP_IO_ARENA(v));	XXX */
    477 #endif
    478 		return (error);
    479 	}
    480 
    481  mapit:
    482 	*iohp = (ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start) >>
    483 	    CHIP_ADDR_SHIFT) + (ioaddr - abst.abst_bus_start);
    484 
    485 	return (0);
    486 }
    487 
    488 static void
    489 __C(CHIP,_io_unmap)(void *v, bus_space_handle_t ioh,
    490     bus_size_t iosize, int acct)
    491 {
    492 	bus_addr_t ioaddr;
    493 
    494 	if (acct == 0)
    495 		return;
    496 
    497 #ifdef EXTENT_DEBUG
    498 	printf("io: freeing handle 0x%lx for 0x%lx\n", ioh, iosize);
    499 #endif
    500 
    501 	ioh = ALPHA_K0SEG_TO_PHYS(ioh << CHIP_ADDR_SHIFT) >> CHIP_ADDR_SHIFT;
    502 
    503 #ifdef CHIP_IO_W1_BUS_START
    504 	if ((ioh << CHIP_ADDR_SHIFT) >= CHIP_IO_W1_SYS_START(v) &&
    505 	    (ioh << CHIP_ADDR_SHIFT) <= CHIP_IO_W1_SYS_END(v)) {
    506 		ioaddr = CHIP_IO_W1_BUS_START(v) +
    507 		    (ioh - (CHIP_IO_W1_SYS_START(v) >> CHIP_ADDR_SHIFT));
    508 	} else
    509 #endif
    510 #ifdef CHIP_IO_W2_BUS_START
    511 	if ((ioh << CHIP_ADDR_SHIFT) >= CHIP_IO_W2_SYS_START(v) &&
    512 	    (ioh << CHIP_ADDR_SHIFT) <= CHIP_IO_W2_SYS_END(v)) {
    513 		ioaddr = CHIP_IO_W2_BUS_START(v) +
    514 		    (ioh - (CHIP_IO_W2_SYS_START(v) >> CHIP_ADDR_SHIFT));
    515 	} else
    516 #endif
    517 	{
    518 		printf("\n");
    519 #ifdef CHIP_IO_W1_BUS_START
    520 		printf("%s: sys window[1]=0x%lx-0x%lx\n",
    521 		    __S(__C(CHIP,_io_map)), CHIP_IO_W1_SYS_START(v),
    522 		    CHIP_IO_W1_SYS_END(v));
    523 #endif
    524 #ifdef CHIP_IO_W2_BUS_START
    525 		printf("%s: sys window[2]=0x%lx-0x%lx\n",
    526 		    __S(__C(CHIP,_io_map)), CHIP_IO_W2_SYS_START(v),
    527 		    CHIP_IO_W2_SYS_END(v));
    528 #endif
    529 		panic("%s: don't know how to unmap %lx",
    530 		    __S(__C(CHIP,_io_unmap)), (ioh << CHIP_ADDR_SHIFT));
    531 	}
    532 
    533 #ifdef EXTENT_DEBUG
    534 	printf("io: freeing 0x%lx to 0x%lx\n", ioaddr, ioaddr + iosize - 1);
    535 #endif
    536 	vmem_xfree(CHIP_IO_ARENA(v), ioaddr, iosize);
    537 }
    538 
    539 static int
    540 __C(CHIP,_io_subregion)(void *v, bus_space_handle_t ioh,
    541     bus_size_t offset, bus_size_t size, bus_space_handle_t *nioh)
    542 {
    543 
    544 	*nioh = ioh + offset;
    545 	return (0);
    546 }
    547 
    548 static int
    549 __C(CHIP,_io_alloc)(void *v, bus_addr_t rstart, bus_addr_t rend,
    550     bus_size_t size, bus_size_t align, bus_size_t boundary, int flags,
    551     bus_addr_t *addrp, bus_space_handle_t *bshp)
    552 {
    553 	struct alpha_bus_space_translation abst;
    554 	int linear = flags & BUS_SPACE_MAP_LINEAR;
    555 	vmem_addr_t ioaddr;
    556 	int error;
    557 
    558 	/*
    559 	 * Can't map i/o space linearly.
    560 	 */
    561 	if (linear)
    562 		return (EOPNOTSUPP);
    563 
    564 	/*
    565 	 * Do the requested allocation.
    566 	 */
    567 #ifdef EXTENT_DEBUG
    568 	printf("io: allocating from 0x%lx to 0x%lx\n", rstart, rend);
    569 #endif
    570 	error = vmem_xalloc(CHIP_IO_ARENA(v), size,
    571 			    align,		/* align */
    572 			    0,			/* phase */
    573 			    boundary,		/* nocross */
    574 			    rstart,		/* minaddr */
    575 			    rend,		/* maxaddr */
    576 			    VM_BESTFIT | VM_NOSLEEP,
    577 			    &ioaddr);
    578 	if (error) {
    579 #ifdef EXTENT_DEBUG
    580 		printf("io: allocation failed (%d)\n", error);
    581 		extent_print(CHIP_IO_EXTENT(v));
    582 #endif
    583 		return (error);
    584 	}
    585 
    586 #ifdef EXTENT_DEBUG
    587 	printf("io: allocated 0x%lx to 0x%lx\n", ioaddr, ioaddr + size - 1);
    588 #endif
    589 
    590 	error = __C(CHIP,_io_translate)(v, ioaddr, size, flags, &abst);
    591 	if (error) {
    592 		vmem_xfree(CHIP_IO_ARENA(v), ioaddr, size);
    593 		return (error);
    594 	}
    595 
    596 	*addrp = ioaddr;
    597 	*bshp = (ALPHA_PHYS_TO_K0SEG(abst.abst_sys_start) >>
    598 	    CHIP_ADDR_SHIFT) + (ioaddr - abst.abst_bus_start);
    599 
    600 	return (0);
    601 }
    602 
    603 static void
    604 __C(CHIP,_io_free)(void *v, bus_space_handle_t bsh, bus_size_t size)
    605 {
    606 
    607 	/* Unmap does all we need to do. */
    608 	__C(CHIP,_io_unmap)(v, bsh, size, 1);
    609 }
    610 
    611 static void *
    612 __C(CHIP,_io_vaddr)(void *v, bus_space_handle_t bsh)
    613 {
    614 	/*
    615 	 * _io_translate() catches BUS_SPACE_MAP_LINEAR,
    616 	 * so we shouldn't get here
    617 	 */
    618 	panic("_io_vaddr");
    619 }
    620 
    621 static paddr_t
    622 __C(CHIP,_io_mmap)(void *v, bus_addr_t addr, off_t off, int prot, int flags)
    623 {
    624 
    625 	/* Not supported for I/O space. */
    626 	return (-1);
    627 }
    628 
    629 static inline void
    630 __C(CHIP,_io_barrier)(void *v, bus_space_handle_t h,
    631     bus_size_t o, bus_size_t l, int f)
    632 {
    633 
    634 	if ((f & BUS_SPACE_BARRIER_READ) != 0)
    635 		alpha_mb();
    636 	else if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
    637 		alpha_wmb();
    638 }
    639 
    640 static inline uint8_t
    641 __C(CHIP,_io_read_1)(void *v, bus_space_handle_t ioh, bus_size_t off)
    642 {
    643 	register bus_space_handle_t tmpioh;
    644 	register uint32_t *port, val;
    645 	register uint8_t rval;
    646 	register int offset;
    647 
    648 	alpha_mb();
    649 
    650 	tmpioh = ioh + off;
    651 	offset = tmpioh & 3;
    652 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
    653 	    (0 << CHIP_SIZE_SHIFT));
    654 	val = *port;
    655 	rval = ((val) >> (8 * offset)) & 0xff;
    656 
    657 	return rval;
    658 }
    659 
    660 static inline uint16_t
    661 __C(CHIP,_io_read_2)(void *v, bus_space_handle_t ioh, bus_size_t off)
    662 {
    663 	register bus_space_handle_t tmpioh;
    664 	register uint32_t *port, val;
    665 	register uint16_t rval;
    666 	register int offset;
    667 
    668 	alpha_mb();
    669 
    670 	tmpioh = ioh + off;
    671 	offset = tmpioh & 3;
    672 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
    673 	    (1 << CHIP_SIZE_SHIFT));
    674 	val = *port;
    675 	rval = ((val) >> (8 * offset)) & 0xffff;
    676 
    677 	return rval;
    678 }
    679 
    680 static inline uint32_t
    681 __C(CHIP,_io_read_4)(void *v, bus_space_handle_t ioh, bus_size_t off)
    682 {
    683 	register bus_space_handle_t tmpioh;
    684 	register uint32_t *port, val;
    685 	register uint32_t rval;
    686 
    687 	alpha_mb();
    688 
    689 	tmpioh = ioh + off;
    690 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
    691 	    (3 << CHIP_SIZE_SHIFT));
    692 	val = *port;
    693 #if 0
    694 	int offset = tmpioh & 3;
    695 	rval = ((val) >> (8 * offset)) & 0xffffffff;
    696 #else
    697 	rval = val;
    698 #endif
    699 
    700 	return rval;
    701 }
    702 
    703 static inline uint64_t
    704 __C(CHIP,_io_read_8)(void *v, bus_space_handle_t ioh, bus_size_t off)
    705 {
    706 
    707 	/* XXX XXX XXX */
    708 	panic("%s not implemented", __S(__C(CHIP,_io_read_8)));
    709 }
    710 
    711 #define CHIP_io_read_multi_N(BYTES,TYPE)				\
    712 static void								\
    713 __C(__C(CHIP,_io_read_multi_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE *a, bus_size_t c)			\
    714 {									\
    715 									\
    716 	while (c-- > 0) {						\
    717 		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
    718 		    BUS_SPACE_BARRIER_READ);				\
    719 		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
    720 	}								\
    721 }
    722 CHIP_io_read_multi_N(1,uint8_t)
    723 CHIP_io_read_multi_N(2,uint16_t)
    724 CHIP_io_read_multi_N(4,uint32_t)
    725 CHIP_io_read_multi_N(8,uint64_t)
    726 
    727 #define CHIP_io_read_region_N(BYTES,TYPE)				\
    728 static void								\
    729 __C(__C(CHIP,_io_read_region_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE *a, bus_size_t c)			\
    730 {									\
    731 									\
    732 	while (c-- > 0) {						\
    733 		*a++ = __C(__C(CHIP,_io_read_),BYTES)(v, h, o);		\
    734 		o += sizeof *a;						\
    735 	}								\
    736 }
    737 CHIP_io_read_region_N(1,uint8_t)
    738 CHIP_io_read_region_N(2,uint16_t)
    739 CHIP_io_read_region_N(4,uint32_t)
    740 CHIP_io_read_region_N(8,uint64_t)
    741 
    742 static inline void
    743 __C(CHIP,_io_write_1)(void *v, bus_space_handle_t ioh,
    744     bus_size_t off, uint8_t val)
    745 {
    746 	register bus_space_handle_t tmpioh;
    747 	register uint32_t *port, nval;
    748 	register int offset;
    749 
    750 	tmpioh = ioh + off;
    751 	offset = tmpioh & 3;
    752 	nval = val << (8 * offset);
    753 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
    754 	    (0 << CHIP_SIZE_SHIFT));
    755 	*port = nval;
    756 	alpha_mb();
    757 }
    758 
    759 static inline void
    760 __C(CHIP,_io_write_2)(void *v, bus_space_handle_t ioh,
    761     bus_size_t off, uint16_t val)
    762 {
    763 	register bus_space_handle_t tmpioh;
    764 	register uint32_t *port, nval;
    765 	register int offset;
    766 
    767 	tmpioh = ioh + off;
    768 	offset = tmpioh & 3;
    769 	nval = val << (8 * offset);
    770 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
    771 	    (1 << CHIP_SIZE_SHIFT));
    772 	*port = nval;
    773 	alpha_mb();
    774 }
    775 
    776 static inline void
    777 __C(CHIP,_io_write_4)(void *v, bus_space_handle_t ioh,
    778     bus_size_t off, uint32_t val)
    779 {
    780 	register bus_space_handle_t tmpioh;
    781 	register uint32_t *port, nval;
    782 
    783 	tmpioh = ioh + off;
    784 #if 0
    785 	register int offset;
    786 	offset = tmpioh & 3;
    787 #endif
    788 	nval = val /*<< (8 * offset)*/;
    789 	port = (uint32_t *)((tmpioh << CHIP_ADDR_SHIFT) |
    790 	    (3 << CHIP_SIZE_SHIFT));
    791 	*port = nval;
    792 	alpha_mb();
    793 }
    794 
    795 static inline void
    796 __C(CHIP,_io_write_8)(void *v, bus_space_handle_t ioh,
    797     bus_size_t off, uint64_t val)
    798 {
    799 
    800 	/* XXX XXX XXX */
    801 	panic("%s not implemented", __S(__C(CHIP,_io_write_8)));
    802 	alpha_mb();
    803 }
    804 
    805 #define CHIP_io_write_multi_N(BYTES,TYPE)				\
    806 static void								\
    807 __C(__C(CHIP,_io_write_multi_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, const TYPE *a, bus_size_t c)			\
    808 {									\
    809 									\
    810 	while (c-- > 0) {						\
    811 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
    812 		__C(CHIP,_io_barrier)(v, h, o, sizeof *a,		\
    813 		    BUS_SPACE_BARRIER_WRITE);				\
    814 	}								\
    815 }
    816 CHIP_io_write_multi_N(1,uint8_t)
    817 CHIP_io_write_multi_N(2,uint16_t)
    818 CHIP_io_write_multi_N(4,uint32_t)
    819 CHIP_io_write_multi_N(8,uint64_t)
    820 
    821 #define CHIP_io_write_region_N(BYTES,TYPE)				\
    822 static void								\
    823 __C(__C(CHIP,_io_write_region_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, const TYPE *a, bus_size_t c)			\
    824 {									\
    825 									\
    826 	while (c-- > 0) {						\
    827 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, *a++);		\
    828 		o += sizeof *a;						\
    829 	}								\
    830 }
    831 CHIP_io_write_region_N(1,uint8_t)
    832 CHIP_io_write_region_N(2,uint16_t)
    833 CHIP_io_write_region_N(4,uint32_t)
    834 CHIP_io_write_region_N(8,uint64_t)
    835 
    836 #define CHIP_io_set_multi_N(BYTES,TYPE)					\
    837 static void								\
    838 __C(__C(CHIP,_io_set_multi_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE val, bus_size_t c)			\
    839 {									\
    840 									\
    841 	while (c-- > 0) {						\
    842 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
    843 		__C(CHIP,_io_barrier)(v, h, o, sizeof val,		\
    844 		    BUS_SPACE_BARRIER_WRITE);				\
    845 	}								\
    846 }
    847 CHIP_io_set_multi_N(1,uint8_t)
    848 CHIP_io_set_multi_N(2,uint16_t)
    849 CHIP_io_set_multi_N(4,uint32_t)
    850 CHIP_io_set_multi_N(8,uint64_t)
    851 
    852 #define CHIP_io_set_region_N(BYTES,TYPE)				\
    853 static void								\
    854 __C(__C(CHIP,_io_set_region_),BYTES)(void *v, bus_space_handle_t h, bus_size_t o, TYPE val, bus_size_t c)			\
    855 {									\
    856 									\
    857 	while (c-- > 0) {						\
    858 		__C(__C(CHIP,_io_write_),BYTES)(v, h, o, val);		\
    859 		o += sizeof val;					\
    860 	}								\
    861 }
    862 CHIP_io_set_region_N(1,uint8_t)
    863 CHIP_io_set_region_N(2,uint16_t)
    864 CHIP_io_set_region_N(4,uint32_t)
    865 CHIP_io_set_region_N(8,uint64_t)
    866 
    867 #define	CHIP_io_copy_region_N(BYTES)					\
    868 static void								\
    869 __C(__C(CHIP,_io_copy_region_),BYTES)(void *v, bus_space_handle_t h1, bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)		\
    870 {									\
    871 	bus_size_t o;							\
    872 									\
    873 	if ((h1 + o1) >= (h2 + o2)) {					\
    874 		/* src after dest: copy forward */			\
    875 		for (o = 0; c != 0; c--, o += BYTES)			\
    876 			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
    877 			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
    878 	} else {							\
    879 		/* dest after src: copy backwards */			\
    880 		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
    881 			__C(__C(CHIP,_io_write_),BYTES)(v, h2, o2 + o,	\
    882 			    __C(__C(CHIP,_io_read_),BYTES)(v, h1, o1 + o)); \
    883 	}								\
    884 }
    885 CHIP_io_copy_region_N(1)
    886 CHIP_io_copy_region_N(2)
    887 CHIP_io_copy_region_N(4)
    888 CHIP_io_copy_region_N(8)
    889