Initial import from FreeBSD RELENG_4:
[dragonfly.git] / lib / libio / swiz.c
1 /*-
2  * Copyright (c) 1998 Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/lib/libio/swiz.c,v 1.3.2.1 2000/12/11 01:03:20 obrien Exp $
27  */
28
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/swiz.h>
36 #include <machine/sysarch.h>
37 #include <stdlib.h>
38 #include "io.h"
39
40 #define mb()    __asm__ __volatile__("mb"  : : : "memory")
41 #define wmb()   __asm__ __volatile__("wmb" : : : "memory")
42
43 static int              mem_fd;         /* file descriptor to /dev/mem */
44 static void            *swiz_ports;     /* mapped io ports */
45 static u_int64_t        swiz_io_base;   /* physical address of ports */
46 static u_int64_t        swiz_mem_base;  /* physical address of sparse mem */
47 static u_int64_t        swiz_dense_base; /* physical address of dense mem */
48 static u_int64_t        swiz_hae_mask;  /* mask address bits for hae */
49 static u_int32_t        swiz_hae;       /* cache of current hae */
50
51 static void
52 swiz_init()
53 {
54
55     size_t len = sizeof(u_int64_t);
56     int error;
57
58     mem_fd = open(_PATH_MEM, O_RDWR);
59     if (mem_fd < 0)
60         err(1, _PATH_MEM);
61     swiz_ports = mmap(0, 1L<<32, PROT_READ, MAP_ANON, -1, 0);
62
63     if ((error = sysctlbyname("hw.chipset.ports", &swiz_io_base, &len,
64                               0, 0)) < 0)
65             err(1, "hw.chipset.ports");
66     if ((error = sysctlbyname("hw.chipset.memory", &swiz_mem_base, &len,
67                               0, 0)) < 0)
68             err(1, "hw.chipset.memory");
69     if ((error = sysctlbyname("hw.chipset.dense", &swiz_dense_base, &len,
70                               0, 0)) < 0)
71             err(1, "hw.chipset.memory");
72     if ((error = sysctlbyname("hw.chipset.hae_mask", &swiz_hae_mask, &len,
73                               0, 0)) < 0)
74             err(1, "hw.chipset.memory");
75
76 }
77
78 static int
79 swiz_ioperm(u_int32_t from, u_int32_t num, int on)
80 {
81     u_int64_t start, end;
82     void *addr;
83
84     if (!swiz_ports)
85         swiz_init();
86
87     if (!on)
88         return -1;              /* XXX can't unmap yet */
89
90     start = trunc_page(from << 5);
91     end = round_page((from + num) << 5);
92     addr = swiz_ports + start;
93     munmap(addr, end - start);
94     mmap(addr, end - start, PROT_READ|PROT_WRITE, MAP_SHARED,
95          mem_fd, swiz_io_base + start);
96     return 0;
97 }
98
99 static u_int8_t
100 swiz_inb(u_int32_t port)
101 {
102     mb();
103     return SPARSE_READ_BYTE(swiz_ports, port);
104 }
105
106 static u_int16_t
107 swiz_inw(u_int32_t port)
108 {
109     mb();
110     return SPARSE_READ_WORD(swiz_ports, port);
111 }
112
113 static u_int32_t
114 swiz_inl(u_int32_t port)
115 {
116     mb();
117     return SPARSE_READ_LONG(swiz_ports, port);
118 }
119
120 static void
121 swiz_outb(u_int32_t port, u_int8_t val)
122 {
123     SPARSE_WRITE_BYTE(swiz_ports, port, val);
124     wmb();
125 }
126
127 static void
128 swiz_outw(u_int32_t port, u_int16_t val)
129 {
130     SPARSE_WRITE_WORD(swiz_ports, port, val);
131     wmb();
132 }
133
134 static void
135 swiz_outl(u_int32_t port, u_int32_t val)
136 {
137     SPARSE_WRITE_LONG(swiz_ports, port, val);
138     wmb();
139 }
140
141 struct swiz_mem_handle {
142     u_int32_t   phys;           /* address in PCI address-space */
143     void        *virt;          /* address in user address-space */
144     u_int32_t   size;           /* size of mapped region */
145 };
146
147 static void *
148 swiz_map_memory(u_int32_t address, u_int32_t size)
149 {
150     struct swiz_mem_handle *h;
151     h = malloc(sizeof(struct swiz_mem_handle));
152     if (!h) return 0;
153     h->phys = address;
154     h->virt = mmap(0, size << 5, PROT_READ|PROT_WRITE, MAP_SHARED,
155                    mem_fd,
156                    swiz_mem_base + ((address & ~swiz_hae_mask) << 5));
157     if ((long) h->virt == -1) {
158         free(h);
159         return 0;
160     }
161     h->size = size << 5;
162     return h;
163 }
164
165 static void
166 swiz_unmap_memory(void *handle, u_int32_t size)
167 {
168     struct swiz_mem_handle *h = handle;
169     munmap(h->virt, h->size);
170     free(h);
171 }
172
173 static void
174 swiz_sethae(vm_offset_t phys)
175 {
176     u_int32_t hae = phys & swiz_hae_mask;
177     if (hae != swiz_hae) {
178         alpha_sethae(hae);
179         swiz_hae = hae;
180     }
181 }
182
183 static u_int8_t
184 swiz_readb(void *handle, u_int32_t offset)
185 {
186     struct swiz_mem_handle *h = handle;
187     swiz_sethae(h->phys + offset);
188     return SPARSE_READ_BYTE(h->virt, offset);
189 }
190
191 static u_int16_t
192 swiz_readw(void *handle, u_int32_t offset)
193 {
194     struct swiz_mem_handle *h = handle;
195     swiz_sethae(h->phys + offset);
196     return SPARSE_READ_WORD(h->virt, offset);
197 }
198
199 static u_int32_t
200 swiz_readl(void *handle, u_int32_t offset)
201 {
202     struct swiz_mem_handle *h = handle;
203     swiz_sethae(h->phys + offset);
204     return SPARSE_READ_LONG(h->virt, offset);
205 }
206
207 static void
208 swiz_writeb(void *handle, u_int32_t offset, u_int8_t val)
209 {
210     struct swiz_mem_handle *h = handle;
211     swiz_sethae(h->phys + offset);
212     SPARSE_WRITE_BYTE(h->virt, offset, val);
213 }
214
215 static void
216 swiz_writew(void *handle, u_int32_t offset, u_int16_t val)
217 {
218     struct swiz_mem_handle *h = handle;
219     swiz_sethae(h->phys + offset);
220     SPARSE_WRITE_WORD(h->virt, offset, val);
221 }
222
223 static void
224 swiz_writel(void *handle, u_int32_t offset, u_int32_t val)
225 {
226     struct swiz_mem_handle *h = handle;
227     swiz_sethae(h->phys + offset);
228     SPARSE_WRITE_LONG(h->virt, offset, val);
229 }
230
231 struct io_ops swiz_io_ops = {
232     swiz_ioperm,
233     swiz_inb,
234     swiz_inw,
235     swiz_inl,
236     swiz_outb,
237     swiz_outw,
238     swiz_outl,
239     swiz_map_memory,
240     swiz_unmap_memory,
241     swiz_readb,
242     swiz_readw,
243     swiz_readl,
244     swiz_writeb,
245     swiz_writew,
246     swiz_writel,
247 };