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