1 /* $OpenBSD: bwx.c,v 1.6 2012/12/20 21:05:07 naddy Exp $ */ 2 /*- 3 * Copyright (c) 1998 Doug Rabson 4 * 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 AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE 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 21 * OR 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 #define vm_page_size (sysconf(_SC_PAGESIZE)) /* XXX */ 29 #include <sys/param.h> 30 #include <sys/mman.h> 31 #include <sys/fcntl.h> 32 #include <sys/sysctl.h> 33 #include <err.h> 34 #include <paths.h> 35 #include <machine/bwx.h> 36 #include <machine/cpu.h> 37 #include <machine/sysarch.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 41 #include "io.h" 42 43 #define PATH_APERTURE "/dev/xf86" 44 45 #define mb() __asm__ __volatile__("mb" : : : "memory") 46 #define wmb() __asm__ __volatile__("wmb" : : : "memory") 47 48 static int mem_fd = -1; /* file descriptor to /dev/mem */ 49 static void *bwx_int1_ports = MAP_FAILED; /* mapped int1 io ports */ 50 static void *bwx_int2_ports = MAP_FAILED; /* mapped int2 io ports */ 51 static void *bwx_int4_ports = MAP_FAILED; /* mapped int4 io ports */ 52 static u_int64_t bwx_io_base; /* physical address of ports */ 53 static u_int64_t bwx_mem_base; /* physical address of bwx mem */ 54 55 static void 56 bwx_open_mem(void) 57 { 58 59 if (mem_fd != -1) 60 return; 61 mem_fd = open(_PATH_MEM, O_RDWR); 62 if (mem_fd < 0) 63 mem_fd = open(PATH_APERTURE, O_RDWR); 64 if (mem_fd < 0) 65 err(1, "Failed to open both %s and %s", _PATH_MEM, 66 PATH_APERTURE); 67 } 68 69 static void 70 bwx_close_mem(void) 71 { 72 73 if (mem_fd != -1) { 74 close(mem_fd); 75 mem_fd = -1; 76 } 77 } 78 79 static void 80 bwx_init(void) 81 { 82 size_t len = sizeof(u_int64_t); 83 int error; 84 int mib[3]; 85 86 mib[0] = CTL_MACHDEP; 87 mib[1] = CPU_CHIPSET; 88 mib[2] = CPU_CHIPSET_PORTS; 89 if ((error = sysctl(mib, 3, &bwx_io_base, &len, NULL, 0)) < 0) 90 err(1, "machdep.chipset.ports_base"); 91 mib[2] = CPU_CHIPSET_MEM; 92 if ((error = sysctl(mib, 3, &bwx_mem_base, &len, 0, 0)) < 0) 93 err(1, "machdep.chipset.memory"); 94 } 95 96 static int 97 bwx_ioperm(u_int32_t from, u_int32_t num, int on) 98 { 99 u_int32_t start, end; 100 101 if (bwx_int1_ports == MAP_FAILED) 102 bwx_init(); 103 104 if (!on) 105 return -1; /* XXX can't unmap yet */ 106 107 if (bwx_int1_ports != MAP_FAILED) 108 return 0; 109 110 bwx_open_mem(); 111 start = trunc_page(from); 112 end = round_page(from + num); 113 if ((bwx_int1_ports = mmap(0, end-start, PROT_READ|PROT_WRITE, 114 MAP_SHARED, mem_fd, bwx_io_base + BWX_EV56_INT1 + start)) == 115 MAP_FAILED) 116 err(1, "mmap int1"); 117 if ((bwx_int2_ports = mmap(0, end-start, PROT_READ|PROT_WRITE, 118 MAP_SHARED, mem_fd, bwx_io_base + BWX_EV56_INT2 + start)) == 119 MAP_FAILED) 120 err(1, "mmap int2"); 121 if ((bwx_int4_ports = mmap(0, end-start, PROT_READ|PROT_WRITE, 122 MAP_SHARED, mem_fd, bwx_io_base + BWX_EV56_INT4 + start)) == 123 MAP_FAILED) 124 err(1, "mmap int4"); 125 bwx_close_mem(); 126 return 0; 127 } 128 129 static u_int8_t 130 bwx_inb(u_int32_t port) 131 { 132 mb(); 133 return alpha_ldbu(bwx_int1_ports + port); 134 } 135 136 static u_int16_t 137 bwx_inw(u_int32_t port) 138 { 139 mb(); 140 return alpha_ldwu(bwx_int2_ports + port); 141 } 142 143 static u_int32_t 144 bwx_inl(u_int32_t port) 145 { 146 mb(); 147 return alpha_ldlu(bwx_int4_ports + port); 148 } 149 150 static void 151 bwx_outb(u_int32_t port, u_int8_t val) 152 { 153 alpha_stb(bwx_int1_ports + port, val); 154 mb(); 155 wmb(); 156 } 157 158 static void 159 bwx_outw(u_int32_t port, u_int16_t val) 160 { 161 alpha_stw(bwx_int2_ports + port, val); 162 mb(); 163 wmb(); 164 } 165 166 static void 167 bwx_outl(u_int32_t port, u_int32_t val) 168 { 169 alpha_stl(bwx_int4_ports + port, val); 170 mb(); 171 wmb(); 172 } 173 174 struct bwx_mem_handle { 175 void *virt1; /* int1 address in user address-space */ 176 void *virt2; /* int2 address in user address-space */ 177 void *virt4; /* int4 address in user address-space */ 178 }; 179 180 static void * 181 bwx_map_memory(u_int32_t address, u_int32_t size) 182 { 183 struct bwx_mem_handle *h; 184 size_t sz = (size_t)size << 5; 185 186 h = malloc(sizeof(struct bwx_mem_handle)); 187 if (h == NULL) return NULL; 188 bwx_open_mem(); 189 h->virt1 = mmap(0, sz, PROT_READ|PROT_WRITE, MAP_SHARED, 190 mem_fd, bwx_mem_base + BWX_EV56_INT1 + address); 191 if (h->virt1 == MAP_FAILED) { 192 bwx_close_mem(); 193 free(h); 194 return NULL; 195 } 196 h->virt2 = mmap(0, sz, PROT_READ|PROT_WRITE, MAP_SHARED, 197 mem_fd, bwx_mem_base + BWX_EV56_INT2 + address); 198 if (h->virt2 == MAP_FAILED) { 199 munmap(h->virt1, sz); 200 bwx_close_mem(); 201 free(h); 202 return NULL; 203 } 204 h->virt4 = mmap(0, sz, PROT_READ|PROT_WRITE, MAP_SHARED, 205 mem_fd, bwx_mem_base + BWX_EV56_INT4 + address); 206 if (h->virt4 == MAP_FAILED) { 207 munmap(h->virt1, sz); 208 munmap(h->virt2, sz); 209 bwx_close_mem(); 210 free(h); 211 return NULL; 212 } 213 bwx_close_mem(); 214 return h; 215 } 216 217 static void 218 bwx_unmap_memory(void *handle, u_int32_t size) 219 { 220 struct bwx_mem_handle *h = handle; 221 size_t sz = (size_t)size << 5; 222 223 munmap(h->virt1, sz); 224 munmap(h->virt2, sz); 225 munmap(h->virt4, sz); 226 free(h); 227 } 228 229 static u_int8_t 230 bwx_readb(void *handle, u_int32_t offset) 231 { 232 struct bwx_mem_handle *h = handle; 233 234 return alpha_ldbu(h->virt1 + offset); 235 } 236 237 static u_int16_t 238 bwx_readw(void *handle, u_int32_t offset) 239 { 240 struct bwx_mem_handle *h = handle; 241 242 return alpha_ldwu(h->virt2 + offset); 243 } 244 245 static u_int32_t 246 bwx_readl(void *handle, u_int32_t offset) 247 { 248 struct bwx_mem_handle *h = handle; 249 250 return alpha_ldlu(h->virt4 + offset); 251 } 252 253 static void 254 bwx_writeb(void *handle, u_int32_t offset, u_int8_t val) 255 { 256 struct bwx_mem_handle *h = handle; 257 258 alpha_stb(h->virt1 + offset, val); 259 } 260 261 static void 262 bwx_writew(void *handle, u_int32_t offset, u_int16_t val) 263 { 264 struct bwx_mem_handle *h = handle; 265 266 alpha_stw(h->virt2 + offset, val); 267 } 268 269 static void 270 bwx_writel(void *handle, u_int32_t offset, u_int32_t val) 271 { 272 struct bwx_mem_handle *h = handle; 273 274 alpha_stl(h->virt4 + offset, val); 275 } 276 277 struct io_ops bwx_io_ops = { 278 bwx_ioperm, 279 bwx_inb, 280 bwx_inw, 281 bwx_inl, 282 bwx_outb, 283 bwx_outw, 284 bwx_outl, 285 bwx_map_memory, 286 bwx_unmap_memory, 287 bwx_readb, 288 bwx_readw, 289 bwx_readl, 290 bwx_writeb, 291 bwx_writew, 292 bwx_writel, 293 }; 294