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