Home | History | Annotate | Line # | Download | only in libpci
rumpdev_bus_space.c revision 1.8
      1 /*	$NetBSD: rumpdev_bus_space.c,v 1.8 2016/07/07 06:55:43 msaitoh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2013 Antti Kantee.  All Rights Reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25  * SUCH DAMAGE.
     26  */
     27 
     28 #include <sys/cdefs.h>
     29 #include <sys/atomic.h>
     30 
     31 #include <sys/param.h>
     32 
     33 #include <dev/pci/pcivar.h>
     34 
     35 #include "pci_user.h"
     36 
     37 #if defined(RUMPCOMP_USERFEATURE_PCI_IOSPACE) \
     38     && (defined(__i386__) || defined(__x86_64__))
     39 #define IOSPACE_SUPPORTED
     40 #endif
     41 
     42 int
     43 bus_space_map(bus_space_tag_t bst, bus_addr_t address, bus_size_t size,
     44 	int flags, bus_space_handle_t *handlep)
     45 {
     46 	int rv;
     47 
     48 	/*
     49 	 * I/O space we just "let it bli" in case someone wants to
     50 	 * map it (e.g. on Xen)
     51  	 *
     52 	 * Memory space needs to be mapped into our guest, so we
     53 	 * make a hypercall to request it.
     54 	 */
     55 	if (bst == 0) {
     56 #ifdef IOSPACE_SUPPORTED
     57 		*handlep = address;
     58 		rv = 0;
     59 #else
     60 		rv = ENOTSUP;
     61 #endif
     62 	} else {
     63 		*handlep = (bus_space_handle_t)rumpcomp_pci_map(address, size);
     64 		rv = *handlep ? 0 : EINVAL;
     65 	}
     66 
     67 	return rv;
     68 }
     69 
     70 uint8_t
     71 bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh,
     72 	bus_size_t offset)
     73 {
     74 	uint8_t rv;
     75 
     76 	if (bst == 0) {
     77 #ifdef IOSPACE_SUPPORTED
     78 		unsigned short addr = bsh + offset;
     79 		__asm__ __volatile__("inb %1, %0" : "=a"(rv) : "d"(addr));
     80 #else
     81 		panic("IO space not supported");
     82 #endif
     83 	} else {
     84 		rv = *(volatile uint8_t *)(bsh + offset);
     85 	}
     86 
     87 	return rv;
     88 }
     89 
     90 uint16_t
     91 bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh,
     92 	bus_size_t offset)
     93 {
     94 	uint16_t rv;
     95 
     96 	if (bst == 0) {
     97 #ifdef IOSPACE_SUPPORTED
     98 		unsigned short addr = bsh + offset;
     99 		__asm__ __volatile__("in %1, %0" : "=a"(rv) : "d"(addr));
    100 #else
    101 		panic("IO space not supported");
    102 #endif
    103 	} else {
    104 		rv = *(volatile uint16_t *)(bsh + offset);
    105 	}
    106 
    107 	return rv;
    108 }
    109 
    110 uint32_t
    111 bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh,
    112 	bus_size_t offset)
    113 {
    114 	uint32_t rv;
    115 
    116 	if (bst == 0) {
    117 #ifdef IOSPACE_SUPPORTED
    118 		unsigned short addr = bsh + offset;
    119 		__asm__ __volatile__("inl %1, %0" : "=a"(rv) : "d"(addr));
    120 #else
    121 		panic("IO space not supported");
    122 #endif
    123 	} else {
    124 		rv = *(volatile uint32_t *)(bsh + offset);
    125 	}
    126 
    127 	return rv;
    128 }
    129 
    130 void
    131 bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
    132 	bus_size_t offset, uint8_t *datap, bus_size_t count)
    133 {
    134 
    135 	while (count--) {
    136 		*datap++ = bus_space_read_1(bst, bsh, offset);
    137 		bus_space_barrier(bst, bsh, offset, 1, BUS_SPACE_BARRIER_READ);
    138 	}
    139 }
    140 
    141 void
    142 bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
    143 	bus_size_t offset, uint16_t *datap, bus_size_t count)
    144 {
    145 
    146 	while (count--) {
    147 		*datap++ = bus_space_read_2(bst, bsh, offset);
    148 		bus_space_barrier(bst, bsh, offset, 2, BUS_SPACE_BARRIER_READ);
    149 	}
    150 }
    151 
    152 void
    153 bus_space_read_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
    154 	bus_size_t offset, uint32_t *datap, bus_size_t count)
    155 {
    156 
    157 	while (count--) {
    158 		*datap++ = bus_space_read_4(bst, bsh, offset);
    159 		bus_space_barrier(bst, bsh, offset, 4, BUS_SPACE_BARRIER_READ);
    160 	}
    161 }
    162 
    163 void
    164 bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh,
    165 	bus_size_t offset, uint8_t v)
    166 {
    167 
    168 	if (bst == 0) {
    169 #ifdef IOSPACE_SUPPORTED
    170 		unsigned short addr = bsh + offset;
    171 		__asm__ __volatile__("outb %0, %1" :: "a"(v), "d"(addr));
    172 #else
    173 		panic("IO space not supported");
    174 #endif
    175 	} else {
    176 		*(volatile uint8_t *)(bsh + offset) = v;
    177 	}
    178 }
    179 
    180 void
    181 bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh,
    182 	bus_size_t offset, uint16_t v)
    183 {
    184 
    185 	if (bst == 0) {
    186 #ifdef IOSPACE_SUPPORTED
    187 		unsigned short addr = bsh + offset;
    188 		__asm__ __volatile__("out %0, %1" :: "a"(v), "d"(addr));
    189 #else
    190 		panic("IO space not supported");
    191 #endif
    192 	} else {
    193 		*(volatile uint16_t *)(bsh + offset) = v;
    194 	}
    195 }
    196 
    197 void
    198 bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh,
    199 	bus_size_t offset, uint32_t v)
    200 {
    201 
    202 	if (bst == 0) {
    203 #ifdef IOSPACE_SUPPORTED
    204 		unsigned short addr = bsh + offset;
    205 		__asm__ __volatile__("outl %0, %1" :: "a"(v), "d"(addr));
    206 #else
    207 		panic("IO space not supported");
    208 #endif
    209 	} else {
    210 		*(volatile uint32_t *)(bsh + offset) = v;
    211 	}
    212 }
    213 
    214 void
    215 bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
    216 	bus_size_t offset, const uint8_t *datap, bus_size_t count)
    217 {
    218 
    219 	while (count--) {
    220 		const uint8_t value = *datap++;
    221 
    222 		bus_space_write_1(bst, bsh, offset, value);
    223 		bus_space_barrier(bst, bsh, offset, 1, BUS_SPACE_BARRIER_WRITE);
    224 	}
    225 }
    226 
    227 void
    228 bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
    229 	bus_size_t offset, const uint16_t *datap, bus_size_t count)
    230 {
    231 
    232 	while (count--) {
    233 		const uint16_t value = *datap++;
    234 
    235 		bus_space_write_2(bst, bsh, offset, value);
    236 		bus_space_barrier(bst, bsh, offset, 2, BUS_SPACE_BARRIER_WRITE);
    237 	}
    238 }
    239 
    240 void
    241 bus_space_write_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
    242 	bus_size_t offset, const uint32_t *datap, bus_size_t count)
    243 {
    244 
    245 	while (count--) {
    246 		const uint32_t value = *datap++;
    247 
    248 		bus_space_write_4(bst, bsh, offset, value);
    249 		bus_space_barrier(bst, bsh, offset, 4, BUS_SPACE_BARRIER_WRITE);
    250 	}
    251 }
    252 
    253 paddr_t
    254 bus_space_mmap(bus_space_tag_t bst, bus_addr_t addr, off_t off,
    255 	int prot, int flags)
    256 {
    257 
    258 	panic("%s: unimplemented", __func__);
    259 }
    260 
    261 int
    262 bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh,
    263 	bus_size_t offset, bus_size_t size, bus_space_handle_t *nhandlep)
    264 {
    265 
    266 	*nhandlep = bsh + offset;
    267 	return 0;
    268 }
    269 
    270 void
    271 bus_space_unmap(bus_space_tag_t bst, bus_space_handle_t bsh,
    272 	bus_size_t size)
    273 {
    274 
    275 	if (bst == 0)
    276 		return;
    277 
    278 	panic("%s: unimplemented", __func__);
    279 }
    280 
    281 void
    282 bus_space_barrier(bus_space_tag_t bst, bus_space_handle_t bsh,
    283 	bus_size_t offset, bus_size_t len, int flags)
    284 {
    285 
    286 	/* weelll ... */
    287 	membar_sync();
    288 }
    289