xref: /openbsd/lib/libarch/alpha/bwx.c (revision 7b36286a)
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