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