blob: acefdf7ceab769b11392fd856a6af8ff9ccfbf89 [file] [log] [blame]
Patrick Georgi1e916e02011-01-28 07:54:11 +00001#include <assert.h>
2#include "cmos_lowlevel.h"
3
4#if defined(__FreeBSD__)
5#include <sys/types.h>
6#include <machine/cpufunc.h>
7#define OUTB(x, y) do { u_int tmp = (y); outb(tmp, (x)); } while (0)
8#define OUTW(x, y) do { u_int tmp = (y); outw(tmp, (x)); } while (0)
9#define OUTL(x, y) do { u_int tmp = (y); outl(tmp, (x)); } while (0)
10#define INB(x) __extension__ ({ u_int tmp = (x); inb(tmp); })
11#define INW(x) __extension__ ({ u_int tmp = (x); inw(tmp); })
12#define INL(x) __extension__ ({ u_int tmp = (x); inl(tmp); })
13#else
14#if defined(__GLIBC__)
15#include <sys/io.h>
16#endif
17#if (defined(__MACH__) && defined(__APPLE__))
Stefan Reinauercff573d2011-03-18 22:08:39 +000018#include <DirectHW/DirectHW.h>
Patrick Georgi1e916e02011-01-28 07:54:11 +000019#endif
jakllschb0c94a12011-02-08 16:07:49 +000020#if defined(__NetBSD__)
Stefan Reinauer5ff7c132011-10-31 12:56:45 -070021#if defined(__i386__) || defined(__x86_64__)
jakllschb0c94a12011-02-08 16:07:49 +000022#include <machine/sysarch.h>
23
24static inline void outb(uint8_t value, uint16_t port)
25{
26 asm volatile ("outb %b0,%w1": :"a" (value), "Nd" (port));
27}
28
29static inline uint8_t inb(uint16_t port)
30{
31 uint8_t value;
32 asm volatile ("inb %w1,%0":"=a" (value):"Nd" (port));
33 return value;
34}
35
36static inline void outw(uint16_t value, uint16_t port)
37{
38 asm volatile ("outw %w0,%w1": :"a" (value), "Nd" (port));
39}
40
41static inline uint16_t inw(uint16_t port)
42{
43 uint16_t value;
44 asm volatile ("inw %w1,%0":"=a" (value):"Nd" (port));
45 return value;
46}
47
48static inline void outl(uint32_t value, uint16_t port)
49{
50 asm volatile ("outl %0,%w1": :"a" (value), "Nd" (port));
51}
52
53static inline uint32_t inl(uint16_t port)
54{
55 uint32_t value;
56 asm volatile ("inl %1,%0":"=a" (value):"Nd" (port));
57 return value;
58}
59#endif
60#ifdef __x86_64__
61#define iopl x86_64_iopl
62#endif
63#ifdef __i386__
64#define iopl i386_iopl
65#endif
66#endif
Patrick Georgi1e916e02011-01-28 07:54:11 +000067#define OUTB outb
68#define OUTW outw
69#define OUTL outl
70#define INB inb
71#define INW inw
72#define INL inl
73#endif
74
75static void cmos_hal_init(void* data);
76static unsigned char cmos_hal_read(unsigned addr);
77static void cmos_hal_write(unsigned addr, unsigned char value);
78static void cmos_set_iopl(int level);
79
80/* no need to initialize anything */
81static void cmos_hal_init(__attribute__((unused)) void *data)
82{
83}
84
85static unsigned char cmos_hal_read(unsigned index)
86{
87 unsigned short port_0, port_1;
88
89 assert(!verify_cmos_byte_index(index));
90
91 if (index < 128) {
92 port_0 = 0x70;
93 port_1 = 0x71;
94 } else {
95 port_0 = 0x72;
96 port_1 = 0x73;
97 }
98
99 OUTB(index, port_0);
100 return INB(port_1);
101}
102
103static void cmos_hal_write(unsigned index, unsigned char value)
104{
105 unsigned short port_0, port_1;
106
107 assert(!verify_cmos_byte_index(index));
108
109 if (index < 128) {
110 port_0 = 0x70;
111 port_1 = 0x71;
112 } else {
113 port_0 = 0x72;
114 port_1 = 0x73;
115 }
116
117 OUTB(index, port_0);
118 OUTB(value, port_1);
119}
120
121
122/****************************************************************************
123 * cmos_set_iopl
124 *
125 * Set the I/O privilege level of the executing process. Root privileges are
126 * required for performing this action. A sufficient I/O privilege level
127 * allows the process to access x86 I/O address space and to disable/reenable
128 * interrupts while executing in user space. Messing with the I/O privilege
129 * level is therefore somewhat dangerous.
130 ****************************************************************************/
131static void cmos_set_iopl(int level)
132{
133#if defined(__FreeBSD__)
134 static int io_fd = -1;
135#endif
136
137 assert((level >= 0) && (level <= 3));
138
139#if defined(__FreeBSD__)
140 if (level == 0) {
141 if (io_fd != -1) {
142 close(io_fd);
143 io_fd = -1;
144 }
145 } else {
146 if (io_fd == -1) {
147 io_fd = open("/dev/io", O_RDWR);
148 if (io_fd < 0) {
149 perror("/dev/io");
150 exit(1);
151 }
152 }
153 }
154#else
155 if (iopl(level)) {
156 fprintf(stderr, "%s: iopl() system call failed. "
157 "You must be root to do this.\n", prog_name);
158 exit(1);
159 }
160#endif
161}
162
163cmos_access_t cmos_hal = {
164 .init = cmos_hal_init,
165 .read = cmos_hal_read,
166 .write = cmos_hal_write,
167 .set_iopl = cmos_set_iopl,
168};