io.h revision 300594
1/*-
2 * Copyright (c) 2010 Isilon Systems, Inc.
3 * Copyright (c) 2010 iX Systems, Inc.
4 * Copyright (c) 2010 Panasas, Inc.
5 * Copyright (c) 2013-2015 Mellanox Technologies, Ltd.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice unmodified, this list of conditions, and the following
13 *    disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/compat/linuxkpi/common/include/linux/io.h 300594 2016-05-24 09:23:04Z kevlo $
30 */
31#ifndef	_LINUX_IO_H_
32#define	_LINUX_IO_H_
33
34#include <machine/vm.h>
35#include <sys/endian.h>
36#include <sys/types.h>
37
38#include <linux/compiler.h>
39
40static inline uint32_t
41__raw_readl(const volatile void *addr)
42{
43	return *(const volatile uint32_t *)addr;
44}
45
46static inline void
47__raw_writel(uint32_t b, volatile void *addr)
48{
49	*(volatile uint32_t *)addr = b;
50}
51
52static inline uint64_t
53__raw_readq(const volatile void *addr)
54{
55	return *(const volatile uint64_t *)addr;
56}
57
58static inline void
59__raw_writeq(uint64_t b, volatile void *addr)
60{
61	*(volatile uint64_t *)addr = b;
62}
63
64/*
65 * XXX This is all x86 specific.  It should be bus space access.
66 */
67#define	mmiowb()	barrier()
68
69#undef writel
70static inline void
71writel(uint32_t b, void *addr)
72{
73        *(volatile uint32_t *)addr = b;
74}
75
76#undef writeq
77static inline void
78writeq(uint64_t b, void *addr)
79{
80        *(volatile uint64_t *)addr = b;
81}
82
83#undef writeb
84static inline void
85writeb(uint8_t b, void *addr)
86{
87        *(volatile uint8_t *)addr = b;
88}
89
90#undef writew
91static inline void
92writew(uint16_t b, void *addr)
93{
94        *(volatile uint16_t *)addr = b;
95}
96
97#undef ioread8
98static inline uint8_t
99ioread8(const volatile void *addr)
100{
101	return *(const volatile uint8_t *)addr;
102}
103
104#undef ioread16
105static inline uint16_t
106ioread16(const volatile void *addr)
107{
108	return *(const volatile uint16_t *)addr;
109}
110
111#undef ioread32
112static inline uint32_t
113ioread32(const volatile void *addr)
114{
115	return *(const volatile uint32_t *)addr;
116}
117
118#undef ioread32be
119static inline uint32_t
120ioread32be(const volatile void *addr)
121{
122	return be32toh(*(const volatile uint32_t *)addr);
123}
124
125#undef iowrite8
126static inline void
127iowrite8(uint8_t v, volatile void *addr)
128{
129	*(volatile uint8_t *)addr = v;
130}
131
132#undef iowrite16
133static inline void
134iowrite16(uint16_t v, volatile void *addr)
135{
136	*(volatile uint16_t *)addr = v;
137}
138
139#undef iowrite32
140static inline void
141iowrite32(uint32_t v, volatile void *addr)
142{
143	*(volatile uint32_t *)addr = v;
144}
145
146#undef iowrite32be
147static inline void
148iowrite32be(uint32_t v, volatile void *addr)
149{
150	*(volatile uint32_t *)addr = htobe32(v);
151}
152
153#undef readb
154static inline uint8_t
155readb(const volatile void *addr)
156{
157	return *(const volatile uint8_t *)addr;
158}
159
160#undef readw
161static inline uint16_t
162readw(const volatile void *addr)
163{
164	return *(const volatile uint16_t *)addr;
165}
166
167#undef readl
168static inline uint32_t
169readl(const volatile void *addr)
170{
171	return *(const volatile uint32_t *)addr;
172}
173
174#if defined(__i386__) || defined(__amd64__)
175static inline void
176_outb(u_char data, u_int port)
177{
178	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
179}
180#endif
181
182#if defined(__i386__) || defined(__amd64__)
183void *_ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr);
184#else
185#define	_ioremap_attr(...) NULL
186#endif
187
188#define	ioremap_nocache(addr, size)					\
189    _ioremap_attr((addr), (size), VM_MEMATTR_UNCACHEABLE)
190#define	ioremap_wc(addr, size)						\
191    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_COMBINING)
192#define	ioremap_wb(addr, size)						\
193    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_BACK)
194#define	ioremap_wt(addr, size)						\
195    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_THROUGH)
196#define	ioremap(addr, size)						\
197    _ioremap_attr((addr), (size), VM_MEMATTR_UNCACHEABLE)
198void iounmap(void *addr);
199
200#define	memset_io(a, b, c)	memset((a), (b), (c))
201#define	memcpy_fromio(a, b, c)	memcpy((a), (b), (c))
202#define	memcpy_toio(a, b, c)	memcpy((a), (b), (c))
203
204static inline void
205__iowrite32_copy(void *to, void *from, size_t count)
206{
207	uint32_t *src;
208	uint32_t *dst;
209	int i;
210
211	for (i = 0, src = from, dst = to; i < count; i++, src++, dst++)
212		__raw_writel(*src, dst);
213}
214
215static inline void
216__iowrite64_copy(void *to, void *from, size_t count)
217{
218#ifdef __LP64__
219	uint64_t *src;
220	uint64_t *dst;
221	int i;
222
223	for (i = 0, src = from, dst = to; i < count; i++, src++, dst++)
224		__raw_writeq(*src, dst);
225#else
226	__iowrite32_copy(to, from, count * 2);
227#endif
228}
229
230enum {
231	MEMREMAP_WB = 1 << 0,
232	MEMREMAP_WT = 1 << 1,
233	MEMREMAP_WC = 1 << 2,
234};
235
236static inline void *
237memremap(resource_size_t offset, size_t size, unsigned long flags)
238{
239	void *addr = NULL;
240
241	if ((flags & MEMREMAP_WB) &&
242	    (addr = ioremap_wb(offset, size)) != NULL)
243		goto done;
244	if ((flags & MEMREMAP_WT) &&
245	    (addr = ioremap_wt(offset, size)) != NULL)
246		goto done;
247	if ((flags & MEMREMAP_WC) &&
248	    (addr = ioremap_wc(offset, size)) != NULL)
249		goto done;
250done:
251	return (addr);
252}
253
254static inline void
255memunmap(void *addr)
256{
257	/* XXX May need to check if this is RAM */
258	iounmap(addr);
259}
260
261#endif	/* _LINUX_IO_H_ */
262