xref: /haiku/src/add-ons/kernel/drivers/misc/poke.cpp (revision f290b766707b386d72e2eaadd35cc3d999405077)
1 /*
2  * Copyright 2005, Oscar Lesta. All rights reserved.
3  * Copyright 2018, Haiku, Inc. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include <Drivers.h>
9 #include <KernelExport.h>
10 #include <ISA.h>
11 #include <PCI.h>
12 
13 #include "poke.h"
14 
15 
16 static status_t poke_open(const char*, uint32, void**);
17 static status_t poke_close(void*);
18 static status_t poke_free(void*);
19 static status_t poke_control(void*, uint32, void*, size_t);
20 static status_t poke_read(void*, off_t, void*, size_t*);
21 static status_t poke_write(void*, off_t, const void*, size_t*);
22 
23 
24 static const char* poke_name[] = {
25     "misc/" POKE_DEVICE_NAME,
26     NULL
27 };
28 
29 
30 device_hooks poke_hooks = {
31 	poke_open,
32 	poke_close,
33 	poke_free,
34 	poke_control,
35 	poke_read,
36 	poke_write,
37 };
38 
39 int32 api_version = B_CUR_DRIVER_API_VERSION;
40 
41 isa_module_info* isa;
42 pci_module_info* pci;
43 
44 static int32 open_count;
45 
46 
47 status_t
48 init_hardware(void)
49 {
50 	return B_OK;
51 }
52 
53 
54 status_t
55 init_driver(void)
56 {
57 	open_count = 0;
58 
59 	if (get_module(B_ISA_MODULE_NAME, (module_info**)&isa) < B_OK)
60 		return ENOSYS;
61 
62 	if (get_module(B_PCI_MODULE_NAME, (module_info**)&pci) < B_OK) {
63 		put_module(B_ISA_MODULE_NAME);
64 		return ENOSYS;
65 	}
66 
67 	return B_OK;
68 }
69 
70 
71 void
72 uninit_driver(void)
73 {
74 	put_module(B_ISA_MODULE_NAME);
75 	put_module(B_PCI_MODULE_NAME);
76 }
77 
78 
79 const char**
80 publish_devices(void)
81 {
82 	return poke_name;
83 }
84 
85 
86 device_hooks*
87 find_device(const char* name)
88 {
89 	return &poke_hooks;
90 }
91 
92 
93 //	#pragma mark -
94 
95 
96 status_t
97 poke_open(const char* name, uint32 flags, void** cookie)
98 {
99 	*cookie = NULL;
100 
101 	if (getuid() != 0 && geteuid() != 0)
102 		return EPERM;
103 
104 	if (atomic_add(&open_count, 1) != 0) {
105 		atomic_add(&open_count, -1);
106 		return B_BUSY;
107 	}
108 
109 	return B_OK;
110 }
111 
112 
113 status_t
114 poke_close(void* cookie)
115 {
116 	return B_OK;
117 }
118 
119 
120 status_t
121 poke_free(void* cookie)
122 {
123 	atomic_add(&open_count, -1);
124 	return B_OK;
125 }
126 
127 
128 status_t
129 poke_control(void* cookie, uint32 op, void* arg, size_t length)
130 {
131 	switch (op) {
132 		case POKE_PORT_READ:
133 		{
134 			status_t result = B_OK;
135 			port_io_args ioctl;
136 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
137 				return B_BAD_ADDRESS;
138 			if (ioctl.signature != POKE_SIGNATURE)
139 				return B_BAD_VALUE;
140 
141 			switch (ioctl.size) {
142 				case 1:
143 					ioctl.value = isa->read_io_8(ioctl.port);
144 				break;
145 				case 2:
146 					ioctl.value = isa->read_io_16(ioctl.port);
147 				break;
148 				case 4:
149 					ioctl.value = isa->read_io_32(ioctl.port);
150 				break;
151 				default:
152 					result = B_BAD_VALUE;
153 			}
154 
155 			if (user_memcpy(arg, &ioctl, sizeof(port_io_args)) != B_OK)
156 				return B_BAD_ADDRESS;
157 			return result;
158 		}
159 
160 		case POKE_PORT_WRITE:
161 		{
162 			status_t result = B_OK;
163 			port_io_args ioctl;
164 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
165 				return B_BAD_ADDRESS;
166 			if (ioctl.signature != POKE_SIGNATURE)
167 				return B_BAD_VALUE;
168 
169 			switch (ioctl.size) {
170 				case 1:
171 					isa->write_io_8(ioctl.port, ioctl.value);
172 					break;
173 				case 2:
174 					isa->write_io_16(ioctl.port, ioctl.value);
175 					break;
176 				case 4:
177 					isa->write_io_32(ioctl.port, ioctl.value);
178 					break;
179 				default:
180 					result = B_BAD_VALUE;
181 			}
182 
183 			return result;
184 		}
185 
186 		case POKE_PORT_INDEXED_READ:
187 		{
188 			port_io_args ioctl;
189 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
190 				return B_BAD_ADDRESS;
191 			if (ioctl.signature != POKE_SIGNATURE)
192 				return B_BAD_VALUE;
193 
194 			isa->write_io_8(ioctl.port, ioctl.size);
195 			ioctl.value = isa->read_io_8(ioctl.port + 1);
196 
197 			if (user_memcpy(arg, &ioctl, sizeof(port_io_args)) != B_OK)
198 				return B_BAD_ADDRESS;
199 			return B_OK;
200 		}
201 
202 		case POKE_PORT_INDEXED_WRITE:
203 		{
204 			port_io_args ioctl;
205 			if (user_memcpy(&ioctl, arg, sizeof(port_io_args)) != B_OK)
206 				return B_BAD_ADDRESS;
207 			if (ioctl.signature != POKE_SIGNATURE)
208 				return B_BAD_VALUE;
209 
210 			isa->write_io_8(ioctl.port, ioctl.size);
211 			isa->write_io_8(ioctl.port + 1, ioctl.value);
212 			return B_OK;
213 		}
214 
215 		case POKE_PCI_READ_CONFIG:
216 		{
217 			pci_io_args ioctl;
218 			if (user_memcpy(&ioctl, arg, sizeof(pci_io_args)) != B_OK)
219 				return B_BAD_ADDRESS;
220 			if (ioctl.signature != POKE_SIGNATURE)
221 				return B_BAD_VALUE;
222 
223 			ioctl.value = pci->read_pci_config(ioctl.bus, ioctl.device,
224 				ioctl.function, ioctl.offset, ioctl.size);
225 			if (user_memcpy(arg, &ioctl, sizeof(pci_io_args)) != B_OK)
226 				return B_BAD_ADDRESS;
227 			return B_OK;
228 		}
229 
230 		case POKE_PCI_WRITE_CONFIG:
231 		{
232 			pci_io_args ioctl;
233 			if (user_memcpy(&ioctl, arg, sizeof(pci_io_args)) != B_OK)
234 				return B_BAD_ADDRESS;
235 			if (ioctl.signature != POKE_SIGNATURE)
236 				return B_BAD_VALUE;
237 
238 			pci->write_pci_config(ioctl.bus, ioctl.device, ioctl.function,
239 				ioctl.offset, ioctl.size, ioctl.value);
240 			return B_OK;
241 		}
242 
243 		case POKE_GET_NTH_PCI_INFO:
244 		{
245 			pci_info_args ioctl;
246 			if (user_memcpy(&ioctl, arg, sizeof(pci_info_args)) != B_OK)
247 				return B_BAD_ADDRESS;
248 			if (ioctl.signature != POKE_SIGNATURE)
249 				return B_BAD_VALUE;
250 
251 			pci_info info;
252 			ioctl.status = pci->get_nth_pci_info(ioctl.index, &info);
253 
254 			if (user_memcpy(ioctl.info, &info, sizeof(pci_info)) != B_OK)
255 				return B_BAD_ADDRESS;
256 			if (user_memcpy(arg, &ioctl, sizeof(pci_info_args)) != B_OK)
257 				return B_BAD_ADDRESS;
258 			return B_OK;
259 		}
260 
261 		case POKE_GET_PHYSICAL_ADDRESS:
262 		{
263 			mem_map_args ioctl;
264 			if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK)
265 				return B_BAD_ADDRESS;
266 			physical_entry table;
267 			status_t result;
268 
269 			if (ioctl.signature != POKE_SIGNATURE)
270 				return B_BAD_VALUE;
271 
272 			result = get_memory_map(ioctl.address, ioctl.size, &table, 1);
273 			ioctl.physical_address = (void*)(addr_t)table.address;
274 				// TODO: mem_map_args::physical_address should be phys_addr_t!
275 			ioctl.size = table.size;
276 			if (user_memcpy(arg, &ioctl, sizeof(mem_map_args)) != B_OK)
277 				return B_BAD_ADDRESS;
278 			return result;
279 		}
280 
281 		case POKE_MAP_MEMORY:
282 		{
283 			mem_map_args ioctl;
284 			if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK)
285 				return B_BAD_ADDRESS;
286 			if (ioctl.signature != POKE_SIGNATURE)
287 				return B_BAD_VALUE;
288 
289 			char name[B_OS_NAME_LENGTH];
290 			if (user_strlcpy(name, ioctl.name, B_OS_NAME_LENGTH) != B_OK)
291 				return B_BAD_ADDRESS;
292 
293 			ioctl.area = map_physical_memory(name,
294 				(addr_t)ioctl.physical_address, ioctl.size, ioctl.flags,
295 				ioctl.protection, (void**)&ioctl.address);
296 
297 			if (user_memcpy(arg, &ioctl, sizeof(mem_map_args)) != B_OK)
298 				return B_BAD_ADDRESS;
299 			return ioctl.area;
300 		}
301 
302 		case POKE_UNMAP_MEMORY:
303 		{
304 			mem_map_args ioctl;
305 			if (user_memcpy(&ioctl, arg, sizeof(mem_map_args)) != B_OK)
306 				return B_BAD_ADDRESS;
307 			if (ioctl.signature != POKE_SIGNATURE)
308 				return B_BAD_VALUE;
309 
310 			return delete_area(ioctl.area);
311 		}
312 	}
313 
314 	return B_BAD_VALUE;
315 }
316 
317 
318 status_t
319 poke_read(void* cookie, off_t position, void* buffer, size_t* numBytes)
320 {
321 	*numBytes = 0;
322 	return B_NOT_ALLOWED;
323 }
324 
325 
326 status_t
327 poke_write(void* cookie, off_t position, const void* buffer, size_t* numBytes)
328 {
329 	*numBytes = 0;
330 	return B_NOT_ALLOWED;
331 }
332