xref: /haiku/src/add-ons/kernel/drivers/bus/pcmcia/ds.c (revision 400ba068e0971623161ea2f939fd5ede8e5af25c)
1 /*
2  * Copyright 2005, Jérôme DUVAL. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <Drivers.h>
7 #include <OS.h>
8 #include <bus_manager.h>
9 #include <malloc.h>
10 #include <module.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <sys/ioccom.h>
14 #include <sys/ioctl.h>
15 
16 #define __KERNEL__
17 #include <pcmcia/cs_types.h>
18 #include <pcmcia/cs.h>
19 #include <pcmcia/cistpl.h>
20 #include <pcmcia/ds.h>
21 
22 #define copy_from_user memcpy
23 #define copy_to_user memcpy
24 #define CardServices gPcmciaCs->_CardServices
25 #define get_handle gPcmciaDs->get_handle
26 
27 const char sockname[] = "bus/pcmcia/sock/%ld";
28 static char ** devices;
29 uint32 devices_count = 0;
30 
31 int32 api_version = B_CUR_DRIVER_API_VERSION;
32 
33 cs_client_module_info *gPcmciaCs;
34 ds_module_info *gPcmciaDs;
35 
36 static status_t
ds_open(const char * name,uint32 flags,void ** _cookie)37 ds_open(const char *name, uint32 flags, void **_cookie)
38 {
39 	int32 socket = -1;
40 	int32 i;
41 	*_cookie = NULL;
42 
43 	for (i=0; i<devices_count; i++) {
44 		if (strcmp(name, devices[i]) == 0) {
45 			socket = i;
46 			break;
47 		}
48 	}
49 
50 	if (socket < 0) {
51 		return B_BAD_VALUE;
52 	}
53 
54 	if (get_handle(socket, (client_handle_t *)_cookie) != B_OK) {
55 		return ENODEV;
56 	}
57 
58 	return B_OK;
59 }
60 
61 
62 static status_t
ds_close(void * cookie)63 ds_close(void *cookie)
64 {
65 	return B_OK;
66 }
67 
68 
69 static status_t
ds_free(void * cookie)70 ds_free(void *cookie)
71 {
72 	return B_OK;
73 }
74 
75 
76 static status_t
ds_read(void * cookie,off_t position,void * data,size_t * numBytes)77 ds_read(void *cookie, off_t position, void *data, size_t *numBytes)
78 {
79 	return B_ERROR;
80 }
81 
82 
83 static status_t
ds_write(void * cookie,off_t position,const void * data,size_t * numBytes)84 ds_write(void *cookie, off_t position, const void *data, size_t *numBytes)
85 {
86 	return B_ERROR;
87 }
88 
89 
90 /*====================================================================*/
91 
92 static status_t
ds_ioctl(void * cookie,uint32 cmd,void * arg,size_t len)93 ds_ioctl(void *cookie, uint32 cmd, void *arg, size_t len)
94 {
95 	/*socket_info_t *s = (socket_info_t *) cookie;
96     u_int size = IOCPARM_LEN(cmd);
97     status_t ret, err;
98     ds_ioctl_arg_t buf;
99 
100     if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
101 
102 	err = ret = 0;
103 
104     if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);
105 
106     switch (cmd) {
107     case DS_ADJUST_RESOURCE_INFO:
108 	ret = CardServices(AdjustResourceInfo, s->handle, &buf.adjust);
109 	break;
110     case DS_GET_CARD_SERVICES_INFO:
111 	ret = CardServices(GetCardServicesInfo, &buf.servinfo);
112 	break;
113     case DS_GET_CONFIGURATION_INFO:
114 	ret = CardServices(GetConfigurationInfo, s->handle, &buf.config);
115 	break;
116     case DS_GET_FIRST_TUPLE:
117 	ret = CardServices(GetFirstTuple, s->handle, &buf.tuple);
118 	break;
119     case DS_GET_NEXT_TUPLE:
120 	ret = CardServices(GetNextTuple, s->handle, &buf.tuple);
121 	break;
122     case DS_GET_TUPLE_DATA:
123 	buf.tuple.TupleData = buf.tuple_parse.data;
124 	buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
125 	ret = CardServices(GetTupleData, s->handle, &buf.tuple);
126 	break;
127     case DS_PARSE_TUPLE:
128 	buf.tuple.TupleData = buf.tuple_parse.data;
129 	ret = CardServices(ParseTuple, s->handle, &buf.tuple,
130 			   &buf.tuple_parse.parse);
131 	break;
132     case DS_RESET_CARD:
133 	ret = CardServices(ResetCard, s->handle, NULL);
134 	break;
135     case DS_GET_STATUS:
136 	ret = CardServices(GetStatus, s->handle, &buf.status);
137 	break;
138     case DS_VALIDATE_CIS:
139 	ret = CardServices(ValidateCIS, s->handle, &buf.cisinfo);
140 	break;
141     case DS_SUSPEND_CARD:
142 	ret = CardServices(SuspendCard, s->handle, NULL);
143 	break;
144     case DS_RESUME_CARD:
145 	ret = CardServices(ResumeCard, s->handle, NULL);
146 	break;
147     case DS_EJECT_CARD:
148 	ret = CardServices(EjectCard, s->handle, NULL);
149 	break;
150     case DS_INSERT_CARD:
151 	ret = CardServices(InsertCard, s->handle, NULL);
152 	break;
153     case DS_ACCESS_CONFIGURATION_REGISTER:
154 	if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
155 	    return -EPERM;
156 	ret = CardServices(AccessConfigurationRegister, s->handle,
157 			   &buf.conf_reg);
158 	break;
159     case DS_GET_FIRST_REGION:
160         ret = CardServices(GetFirstRegion, s->handle, &buf.region);
161 	break;
162     case DS_GET_NEXT_REGION:
163 	ret = CardServices(GetNextRegion, s->handle, &buf.region);
164 	break;
165     case DS_GET_FIRST_WINDOW:
166 	buf.win_info.handle = (window_handle_t)s->handle;
167 	ret = CardServices(GetFirstWindow, &buf.win_info.handle,
168 			   &buf.win_info.window);
169 	break;
170     case DS_GET_NEXT_WINDOW:
171 	ret = CardServices(GetNextWindow, &buf.win_info.handle,
172 			   &buf.win_info.window);
173 	break;
174     case DS_GET_MEM_PAGE:
175 	ret = CardServices(GetMemPage, buf.win_info.handle,
176 			   &buf.win_info.map);
177 	break;
178     case DS_REPLACE_CIS:
179 	ret = CardServices(ReplaceCIS, s->handle, &buf.cisdump);
180 	break;
181 	*/
182 	client_handle_t h = (client_handle_t) cookie;
183     u_int size = IOCPARM_LEN(cmd);
184     status_t ret, err;
185     ds_ioctl_arg_t buf;
186 
187     if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
188 
189 	err = ret = 0;
190 
191     if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size);
192 
193     switch (cmd) {
194     case DS_ADJUST_RESOURCE_INFO:
195 	ret = CardServices(AdjustResourceInfo, h, &buf.adjust);
196 	break;
197     case DS_GET_CARD_SERVICES_INFO:
198 	ret = CardServices(GetCardServicesInfo, &buf.servinfo);
199 	break;
200     case DS_GET_CONFIGURATION_INFO:
201 	ret = CardServices(GetConfigurationInfo, h, &buf.config);
202 	break;
203     case DS_GET_FIRST_TUPLE:
204 	ret = CardServices(GetFirstTuple, h, &buf.tuple);
205 	break;
206     case DS_GET_NEXT_TUPLE:
207 	ret = CardServices(GetNextTuple, h, &buf.tuple);
208 	break;
209     case DS_GET_TUPLE_DATA:
210 	buf.tuple.TupleData = buf.tuple_parse.data;
211 	buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data);
212 	ret = CardServices(GetTupleData, h, &buf.tuple);
213 	break;
214     case DS_PARSE_TUPLE:
215 	buf.tuple.TupleData = buf.tuple_parse.data;
216 	ret = CardServices(ParseTuple, h, &buf.tuple,
217 			   &buf.tuple_parse.parse);
218 	break;
219     case DS_RESET_CARD:
220 	ret = CardServices(ResetCard, h, NULL);
221 	break;
222     case DS_GET_STATUS:
223 	ret = CardServices(GetStatus, h, &buf.status);
224 	break;
225     case DS_VALIDATE_CIS:
226 	ret = CardServices(ValidateCIS, h, &buf.cisinfo);
227 	break;
228     case DS_SUSPEND_CARD:
229 	ret = CardServices(SuspendCard, h, NULL);
230 	break;
231     case DS_RESUME_CARD:
232 	ret = CardServices(ResumeCard, h, NULL);
233 	break;
234     case DS_EJECT_CARD:
235 	ret = CardServices(EjectCard, h, NULL);
236 	break;
237     case DS_INSERT_CARD:
238 	ret = CardServices(InsertCard, h, NULL);
239 	break;
240 /*    case DS_ACCESS_CONFIGURATION_REGISTER:
241 	if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
242 	    return -EPERM;
243 	ret = CardServices(AccessConfigurationRegister, h,
244 			   &buf.conf_reg);
245 	break;
246     case DS_GET_FIRST_REGION:
247         ret = CardServices(GetFirstRegion, h, &buf.region);
248 	break;
249     case DS_GET_NEXT_REGION:
250 	ret = CardServices(GetNextRegion, h, &buf.region);
251 	break;
252     case DS_GET_FIRST_WINDOW:
253 	buf.win_info.handle = (window_handle_t)h;
254 	ret = CardServices(GetFirstWindow, &buf.win_info.handle,
255 			   &buf.win_info.window);
256 	break;
257     case DS_GET_NEXT_WINDOW:
258 	ret = CardServices(GetNextWindow, &buf.win_info.handle,
259 			   &buf.win_info.window);
260 	break;
261     case DS_GET_MEM_PAGE:
262 	ret = CardServices(GetMemPage, buf.win_info.handle,
263 			   &buf.win_info.map);
264 	break;*/
265     case DS_REPLACE_CIS:
266 	ret = CardServices(ReplaceCIS, h, &buf.cisdump);
267 	break;
268 
269 /*    case DS_BIND_REQUEST:
270 	if (!capable(CAP_SYS_ADMIN)) return -EPERM;
271 	err = bind_request(i, &buf.bind_info);
272 	break;
273     case DS_GET_DEVICE_INFO:
274 	err = get_device_info(i, &buf.bind_info, 1);
275 	break;
276     case DS_GET_NEXT_DEVICE:
277 	err = get_device_info(i, &buf.bind_info, 0);
278 	break;
279     case DS_UNBIND_REQUEST:
280 	err = unbind_request(i, &buf.bind_info);
281 	break;
282     case DS_BIND_MTD:
283 	if (!capable(CAP_SYS_ADMIN)) return -EPERM;
284 	err = bind_mtd(i, &buf.mtd_info);
285 	break;*/
286     default:
287     err = -EINVAL;
288     }
289 
290     if ((err == 0) && (ret != CS_SUCCESS)) {
291 	switch (ret) {
292 	case CS_BAD_SOCKET: case CS_NO_CARD:
293 	    err = ENODEV; break;
294 	case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ:
295 	case CS_BAD_TUPLE:
296 		err = EINVAL; break;
297 	case CS_IN_USE:
298 	    err = EBUSY; break;
299 	case CS_OUT_OF_RESOURCE:
300 	    err = ENOSPC; break;
301 	case CS_NO_MORE_ITEMS:
302 	    err = ENODATA; break;
303 	case CS_UNSUPPORTED_FUNCTION:
304 	    err = ENOSYS; break;
305 	default:
306 	    err = EIO; break;
307 	}
308     }
309 
310     if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size);
311 
312     return err;
313 } /* ds_ioctl */
314 
315 
316 status_t
init_hardware()317 init_hardware()
318 {
319 	return B_OK;
320 }
321 
322 
323 const char **
publish_devices(void)324 publish_devices(void)
325 {
326 	return (const char **)devices;
327 }
328 
329 
330 static device_hooks hooks = {
331 	&ds_open,
332 	&ds_close,
333 	&ds_free,
334 	&ds_ioctl,
335 	&ds_read,
336 	&ds_write,
337 	NULL,
338 	NULL,
339 	NULL,
340 	NULL
341 };
342 
343 device_hooks *
find_device(const char * name)344 find_device(const char *name)
345 {
346 	return &hooks;
347 }
348 
349 
350 status_t
init_driver()351 init_driver()
352 {
353 	status_t err;
354 	client_handle_t handle;
355 	uint32 i;
356 
357 #if DEBUG && !defined(__HAIKU__)
358 	load_driver_symbols("ds");
359 #endif
360 
361 	if ((err = get_module(CS_CLIENT_MODULE_NAME, (module_info **)&gPcmciaCs))!=B_OK)
362 		return err;
363 	if ((err = get_module(DS_MODULE_NAME, (module_info **)&gPcmciaDs))!=B_OK) {
364 		put_module(CS_CLIENT_MODULE_NAME);
365 		return err;
366 	}
367 
368 	devices_count = 0;
369 	while (get_handle(devices_count, &handle)==B_OK) {
370 		devices_count++;
371 	}
372 
373 	if (devices_count <= 0) {
374 		put_module(CS_CLIENT_MODULE_NAME);
375 		put_module(DS_MODULE_NAME);
376 		return ENODEV;
377 	}
378 
379 	devices = malloc(sizeof(char *) * (devices_count+1));
380 	if (!devices) {
381 		put_module(CS_CLIENT_MODULE_NAME);
382 		put_module(DS_MODULE_NAME);
383 		return ENOMEM;
384 	}
385 	for (i=0; i<devices_count; i++) {
386 		devices[i] = strdup(sockname);
387 		sprintf(devices[i], sockname, i);
388 	}
389 	devices[devices_count] = NULL;
390 
391 	return B_OK;
392 }
393 
394 
395 void
uninit_driver()396 uninit_driver()
397 {
398 	int32 i = 0;
399 	for (i=0; i<devices_count; i++) {
400 		free (devices[i]);
401 	}
402 	free(devices);
403 	devices = NULL;
404 
405 	put_module(DS_MODULE_NAME);
406 	put_module(CS_CLIENT_MODULE_NAME);
407 }
408 
409