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