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