14f9f2ee2SJérôme Duval /* 24f9f2ee2SJérôme Duval * Copyright 2005, Jérôme DUVAL. All rights reserved. 34f9f2ee2SJérôme Duval * Distributed under the terms of the MIT License. 44f9f2ee2SJérôme Duval */ 54f9f2ee2SJérôme Duval 64f9f2ee2SJérôme Duval #include <Drivers.h> 74f9f2ee2SJérôme Duval #include <OS.h> 84f9f2ee2SJérôme Duval #include <bus_manager.h> 94f9f2ee2SJérôme Duval #include <malloc.h> 10*cb57453fSJérôme Duval #include <module.h> 114f9f2ee2SJérôme Duval #include <stdio.h> 12*cb57453fSJérôme Duval #include <string.h> 13*cb57453fSJérôme Duval #include <sys/ioccom.h> 14*cb57453fSJérôme Duval #include <sys/ioctl.h> 154f9f2ee2SJérôme Duval 164f9f2ee2SJérôme Duval #define __KERNEL__ 174f9f2ee2SJérôme Duval #include <pcmcia/cs_types.h> 184f9f2ee2SJérôme Duval #include <pcmcia/cs.h> 194f9f2ee2SJérôme Duval #include <pcmcia/cistpl.h> 204f9f2ee2SJérôme Duval #include <pcmcia/ds.h> 214f9f2ee2SJérôme Duval 224f9f2ee2SJérôme Duval #define copy_from_user memcpy 234f9f2ee2SJérôme Duval #define copy_to_user memcpy 244f9f2ee2SJérôme Duval #define CardServices gPcmciaCs->_CardServices 254f9f2ee2SJérôme Duval 264f9f2ee2SJérôme Duval const char sockname[] = "bus/pcmcia/sock/%d"; 274f9f2ee2SJérôme Duval static char ** devices; 284f9f2ee2SJérôme Duval uint32 devices_count = 0; 294f9f2ee2SJérôme Duval 304f9f2ee2SJérôme Duval int32 api_version = B_CUR_DRIVER_API_VERSION; 314f9f2ee2SJérôme Duval 324f9f2ee2SJérôme Duval cs_client_module_info *gPcmciaCs; 334f9f2ee2SJérôme Duval ds_module_info *gPcmciaDs; 344f9f2ee2SJérôme Duval 354f9f2ee2SJérôme Duval static status_t 364f9f2ee2SJérôme Duval ds_open(const char *name, uint32 flags, void **_cookie) 374f9f2ee2SJérôme Duval { 384f9f2ee2SJérôme Duval int32 socket = -1; 394f9f2ee2SJérôme Duval int32 i; 404f9f2ee2SJérôme Duval *_cookie = NULL; 414f9f2ee2SJérôme Duval 424f9f2ee2SJérôme Duval for (i=0; i<devices_count; i++) { 434f9f2ee2SJérôme Duval if (strcmp(name, devices[i]) == 0) { 444f9f2ee2SJérôme Duval socket = i; 454f9f2ee2SJérôme Duval break; 464f9f2ee2SJérôme Duval } 474f9f2ee2SJérôme Duval } 484f9f2ee2SJérôme Duval 494f9f2ee2SJérôme Duval if (socket < 0) { 504f9f2ee2SJérôme Duval return B_BAD_VALUE; 514f9f2ee2SJérôme Duval } 524f9f2ee2SJérôme Duval 534f9f2ee2SJérôme Duval if (gPcmciaDs->get_handle(socket, (client_handle_t *)_cookie) != B_OK) { 544f9f2ee2SJérôme Duval return ENODEV; 554f9f2ee2SJérôme Duval } 564f9f2ee2SJérôme Duval 574f9f2ee2SJérôme Duval return B_OK; 584f9f2ee2SJérôme Duval } 594f9f2ee2SJérôme Duval 604f9f2ee2SJérôme Duval 614f9f2ee2SJérôme Duval static status_t 624f9f2ee2SJérôme Duval ds_close(void *cookie) 634f9f2ee2SJérôme Duval { 644f9f2ee2SJérôme Duval return B_OK; 654f9f2ee2SJérôme Duval } 664f9f2ee2SJérôme Duval 674f9f2ee2SJérôme Duval 684f9f2ee2SJérôme Duval static status_t 694f9f2ee2SJérôme Duval ds_free(void *cookie) 704f9f2ee2SJérôme Duval { 714f9f2ee2SJérôme Duval return B_OK; 724f9f2ee2SJérôme Duval } 734f9f2ee2SJérôme Duval 744f9f2ee2SJérôme Duval 754f9f2ee2SJérôme Duval static status_t 764f9f2ee2SJérôme Duval ds_read(void *cookie, off_t position, void *data, size_t *numBytes) 774f9f2ee2SJérôme Duval { 784f9f2ee2SJérôme Duval return B_ERROR; 794f9f2ee2SJérôme Duval } 804f9f2ee2SJérôme Duval 814f9f2ee2SJérôme Duval 824f9f2ee2SJérôme Duval static status_t 834f9f2ee2SJérôme Duval ds_write(void *cookie, off_t position, const void *data, size_t *numBytes) 844f9f2ee2SJérôme Duval { 854f9f2ee2SJérôme Duval return B_ERROR; 864f9f2ee2SJérôme Duval } 874f9f2ee2SJérôme Duval 884f9f2ee2SJérôme Duval 894f9f2ee2SJérôme Duval /*====================================================================*/ 904f9f2ee2SJérôme Duval 914f9f2ee2SJérôme Duval static status_t 924f9f2ee2SJérôme Duval ds_ioctl(void *cookie, uint32 cmd, void *arg, size_t len) 934f9f2ee2SJérôme Duval { 944f9f2ee2SJérôme Duval /*socket_info_t *s = (socket_info_t *) cookie; 954f9f2ee2SJérôme Duval u_int size = IOCPARM_LEN(cmd); 964f9f2ee2SJérôme Duval status_t ret, err; 974f9f2ee2SJérôme Duval ds_ioctl_arg_t buf; 984f9f2ee2SJérôme Duval 994f9f2ee2SJérôme Duval if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; 1004f9f2ee2SJérôme Duval 1014f9f2ee2SJérôme Duval err = ret = 0; 1024f9f2ee2SJérôme Duval 1034f9f2ee2SJérôme Duval if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size); 1044f9f2ee2SJérôme Duval 1054f9f2ee2SJérôme Duval switch (cmd) { 1064f9f2ee2SJérôme Duval case DS_ADJUST_RESOURCE_INFO: 1074f9f2ee2SJérôme Duval ret = CardServices(AdjustResourceInfo, s->handle, &buf.adjust); 1084f9f2ee2SJérôme Duval break; 1094f9f2ee2SJérôme Duval case DS_GET_CARD_SERVICES_INFO: 1104f9f2ee2SJérôme Duval ret = CardServices(GetCardServicesInfo, &buf.servinfo); 1114f9f2ee2SJérôme Duval break; 1124f9f2ee2SJérôme Duval case DS_GET_CONFIGURATION_INFO: 1134f9f2ee2SJérôme Duval ret = CardServices(GetConfigurationInfo, s->handle, &buf.config); 1144f9f2ee2SJérôme Duval break; 1154f9f2ee2SJérôme Duval case DS_GET_FIRST_TUPLE: 1164f9f2ee2SJérôme Duval ret = CardServices(GetFirstTuple, s->handle, &buf.tuple); 1174f9f2ee2SJérôme Duval break; 1184f9f2ee2SJérôme Duval case DS_GET_NEXT_TUPLE: 1194f9f2ee2SJérôme Duval ret = CardServices(GetNextTuple, s->handle, &buf.tuple); 1204f9f2ee2SJérôme Duval break; 1214f9f2ee2SJérôme Duval case DS_GET_TUPLE_DATA: 1224f9f2ee2SJérôme Duval buf.tuple.TupleData = buf.tuple_parse.data; 1234f9f2ee2SJérôme Duval buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data); 1244f9f2ee2SJérôme Duval ret = CardServices(GetTupleData, s->handle, &buf.tuple); 1254f9f2ee2SJérôme Duval break; 1264f9f2ee2SJérôme Duval case DS_PARSE_TUPLE: 1274f9f2ee2SJérôme Duval buf.tuple.TupleData = buf.tuple_parse.data; 1284f9f2ee2SJérôme Duval ret = CardServices(ParseTuple, s->handle, &buf.tuple, 1294f9f2ee2SJérôme Duval &buf.tuple_parse.parse); 1304f9f2ee2SJérôme Duval break; 1314f9f2ee2SJérôme Duval case DS_RESET_CARD: 1324f9f2ee2SJérôme Duval ret = CardServices(ResetCard, s->handle, NULL); 1334f9f2ee2SJérôme Duval break; 1344f9f2ee2SJérôme Duval case DS_GET_STATUS: 1354f9f2ee2SJérôme Duval ret = CardServices(GetStatus, s->handle, &buf.status); 1364f9f2ee2SJérôme Duval break; 1374f9f2ee2SJérôme Duval case DS_VALIDATE_CIS: 1384f9f2ee2SJérôme Duval ret = CardServices(ValidateCIS, s->handle, &buf.cisinfo); 1394f9f2ee2SJérôme Duval break; 1404f9f2ee2SJérôme Duval case DS_SUSPEND_CARD: 1414f9f2ee2SJérôme Duval ret = CardServices(SuspendCard, s->handle, NULL); 1424f9f2ee2SJérôme Duval break; 1434f9f2ee2SJérôme Duval case DS_RESUME_CARD: 1444f9f2ee2SJérôme Duval ret = CardServices(ResumeCard, s->handle, NULL); 1454f9f2ee2SJérôme Duval break; 1464f9f2ee2SJérôme Duval case DS_EJECT_CARD: 1474f9f2ee2SJérôme Duval ret = CardServices(EjectCard, s->handle, NULL); 1484f9f2ee2SJérôme Duval break; 1494f9f2ee2SJérôme Duval case DS_INSERT_CARD: 1504f9f2ee2SJérôme Duval ret = CardServices(InsertCard, s->handle, NULL); 1514f9f2ee2SJérôme Duval break; 1524f9f2ee2SJérôme Duval case DS_ACCESS_CONFIGURATION_REGISTER: 1534f9f2ee2SJérôme Duval if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) 1544f9f2ee2SJérôme Duval return -EPERM; 1554f9f2ee2SJérôme Duval ret = CardServices(AccessConfigurationRegister, s->handle, 1564f9f2ee2SJérôme Duval &buf.conf_reg); 1574f9f2ee2SJérôme Duval break; 1584f9f2ee2SJérôme Duval case DS_GET_FIRST_REGION: 1594f9f2ee2SJérôme Duval ret = CardServices(GetFirstRegion, s->handle, &buf.region); 1604f9f2ee2SJérôme Duval break; 1614f9f2ee2SJérôme Duval case DS_GET_NEXT_REGION: 1624f9f2ee2SJérôme Duval ret = CardServices(GetNextRegion, s->handle, &buf.region); 1634f9f2ee2SJérôme Duval break; 1644f9f2ee2SJérôme Duval case DS_GET_FIRST_WINDOW: 1654f9f2ee2SJérôme Duval buf.win_info.handle = (window_handle_t)s->handle; 1664f9f2ee2SJérôme Duval ret = CardServices(GetFirstWindow, &buf.win_info.handle, 1674f9f2ee2SJérôme Duval &buf.win_info.window); 1684f9f2ee2SJérôme Duval break; 1694f9f2ee2SJérôme Duval case DS_GET_NEXT_WINDOW: 1704f9f2ee2SJérôme Duval ret = CardServices(GetNextWindow, &buf.win_info.handle, 1714f9f2ee2SJérôme Duval &buf.win_info.window); 1724f9f2ee2SJérôme Duval break; 1734f9f2ee2SJérôme Duval case DS_GET_MEM_PAGE: 1744f9f2ee2SJérôme Duval ret = CardServices(GetMemPage, buf.win_info.handle, 1754f9f2ee2SJérôme Duval &buf.win_info.map); 1764f9f2ee2SJérôme Duval break; 1774f9f2ee2SJérôme Duval case DS_REPLACE_CIS: 1784f9f2ee2SJérôme Duval ret = CardServices(ReplaceCIS, s->handle, &buf.cisdump); 1794f9f2ee2SJérôme Duval break; 1804f9f2ee2SJérôme Duval */ 1814f9f2ee2SJérôme Duval client_handle_t h = (client_handle_t) cookie; 1824f9f2ee2SJérôme Duval u_int size = IOCPARM_LEN(cmd); 1834f9f2ee2SJérôme Duval status_t ret, err; 1844f9f2ee2SJérôme Duval ds_ioctl_arg_t buf; 1854f9f2ee2SJérôme Duval 1864f9f2ee2SJérôme Duval if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; 1874f9f2ee2SJérôme Duval 1884f9f2ee2SJérôme Duval err = ret = 0; 1894f9f2ee2SJérôme Duval 1904f9f2ee2SJérôme Duval if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size); 1914f9f2ee2SJérôme Duval 1924f9f2ee2SJérôme Duval switch (cmd) { 1934f9f2ee2SJérôme Duval case DS_ADJUST_RESOURCE_INFO: 1944f9f2ee2SJérôme Duval ret = CardServices(AdjustResourceInfo, h, &buf.adjust); 1954f9f2ee2SJérôme Duval break; 1964f9f2ee2SJérôme Duval case DS_GET_CARD_SERVICES_INFO: 1974f9f2ee2SJérôme Duval ret = CardServices(GetCardServicesInfo, &buf.servinfo); 1984f9f2ee2SJérôme Duval break; 1994f9f2ee2SJérôme Duval case DS_GET_CONFIGURATION_INFO: 2004f9f2ee2SJérôme Duval ret = CardServices(GetConfigurationInfo, h, &buf.config); 2014f9f2ee2SJérôme Duval break; 2024f9f2ee2SJérôme Duval case DS_GET_FIRST_TUPLE: 2034f9f2ee2SJérôme Duval ret = CardServices(GetFirstTuple, h, &buf.tuple); 2044f9f2ee2SJérôme Duval break; 2054f9f2ee2SJérôme Duval case DS_GET_NEXT_TUPLE: 2064f9f2ee2SJérôme Duval ret = CardServices(GetNextTuple, h, &buf.tuple); 2074f9f2ee2SJérôme Duval break; 2084f9f2ee2SJérôme Duval case DS_GET_TUPLE_DATA: 2094f9f2ee2SJérôme Duval buf.tuple.TupleData = buf.tuple_parse.data; 2104f9f2ee2SJérôme Duval buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data); 2114f9f2ee2SJérôme Duval ret = CardServices(GetTupleData, h, &buf.tuple); 2124f9f2ee2SJérôme Duval break; 2134f9f2ee2SJérôme Duval case DS_PARSE_TUPLE: 2144f9f2ee2SJérôme Duval buf.tuple.TupleData = buf.tuple_parse.data; 2154f9f2ee2SJérôme Duval ret = CardServices(ParseTuple, h, &buf.tuple, 2164f9f2ee2SJérôme Duval &buf.tuple_parse.parse); 2174f9f2ee2SJérôme Duval break; 2184f9f2ee2SJérôme Duval case DS_RESET_CARD: 2194f9f2ee2SJérôme Duval ret = CardServices(ResetCard, h, NULL); 2204f9f2ee2SJérôme Duval break; 2214f9f2ee2SJérôme Duval case DS_GET_STATUS: 2224f9f2ee2SJérôme Duval ret = CardServices(GetStatus, h, &buf.status); 2234f9f2ee2SJérôme Duval break; 2244f9f2ee2SJérôme Duval case DS_VALIDATE_CIS: 2254f9f2ee2SJérôme Duval ret = CardServices(ValidateCIS, h, &buf.cisinfo); 2264f9f2ee2SJérôme Duval break; 2274f9f2ee2SJérôme Duval case DS_SUSPEND_CARD: 2284f9f2ee2SJérôme Duval ret = CardServices(SuspendCard, h, NULL); 2294f9f2ee2SJérôme Duval break; 2304f9f2ee2SJérôme Duval case DS_RESUME_CARD: 2314f9f2ee2SJérôme Duval ret = CardServices(ResumeCard, h, NULL); 2324f9f2ee2SJérôme Duval break; 2334f9f2ee2SJérôme Duval case DS_EJECT_CARD: 2344f9f2ee2SJérôme Duval ret = CardServices(EjectCard, h, NULL); 2354f9f2ee2SJérôme Duval break; 2364f9f2ee2SJérôme Duval case DS_INSERT_CARD: 2374f9f2ee2SJérôme Duval ret = CardServices(InsertCard, h, NULL); 2384f9f2ee2SJérôme Duval break; 2394f9f2ee2SJérôme Duval /* case DS_ACCESS_CONFIGURATION_REGISTER: 2404f9f2ee2SJérôme Duval if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) 2414f9f2ee2SJérôme Duval return -EPERM; 2424f9f2ee2SJérôme Duval ret = CardServices(AccessConfigurationRegister, h, 2434f9f2ee2SJérôme Duval &buf.conf_reg); 2444f9f2ee2SJérôme Duval break; 2454f9f2ee2SJérôme Duval case DS_GET_FIRST_REGION: 2464f9f2ee2SJérôme Duval ret = CardServices(GetFirstRegion, h, &buf.region); 2474f9f2ee2SJérôme Duval break; 2484f9f2ee2SJérôme Duval case DS_GET_NEXT_REGION: 2494f9f2ee2SJérôme Duval ret = CardServices(GetNextRegion, h, &buf.region); 2504f9f2ee2SJérôme Duval break; 2514f9f2ee2SJérôme Duval case DS_GET_FIRST_WINDOW: 2524f9f2ee2SJérôme Duval buf.win_info.handle = (window_handle_t)h; 2534f9f2ee2SJérôme Duval ret = CardServices(GetFirstWindow, &buf.win_info.handle, 2544f9f2ee2SJérôme Duval &buf.win_info.window); 2554f9f2ee2SJérôme Duval break; 2564f9f2ee2SJérôme Duval case DS_GET_NEXT_WINDOW: 2574f9f2ee2SJérôme Duval ret = CardServices(GetNextWindow, &buf.win_info.handle, 2584f9f2ee2SJérôme Duval &buf.win_info.window); 2594f9f2ee2SJérôme Duval break; 2604f9f2ee2SJérôme Duval case DS_GET_MEM_PAGE: 2614f9f2ee2SJérôme Duval ret = CardServices(GetMemPage, buf.win_info.handle, 2624f9f2ee2SJérôme Duval &buf.win_info.map); 2634f9f2ee2SJérôme Duval break;*/ 2644f9f2ee2SJérôme Duval case DS_REPLACE_CIS: 2654f9f2ee2SJérôme Duval ret = CardServices(ReplaceCIS, h, &buf.cisdump); 2664f9f2ee2SJérôme Duval break; 2674f9f2ee2SJérôme Duval 2684f9f2ee2SJérôme Duval /* case DS_BIND_REQUEST: 2694f9f2ee2SJérôme Duval if (!capable(CAP_SYS_ADMIN)) return -EPERM; 2704f9f2ee2SJérôme Duval err = bind_request(i, &buf.bind_info); 2714f9f2ee2SJérôme Duval break; 2724f9f2ee2SJérôme Duval case DS_GET_DEVICE_INFO: 2734f9f2ee2SJérôme Duval err = get_device_info(i, &buf.bind_info, 1); 2744f9f2ee2SJérôme Duval break; 2754f9f2ee2SJérôme Duval case DS_GET_NEXT_DEVICE: 2764f9f2ee2SJérôme Duval err = get_device_info(i, &buf.bind_info, 0); 2774f9f2ee2SJérôme Duval break; 2784f9f2ee2SJérôme Duval case DS_UNBIND_REQUEST: 2794f9f2ee2SJérôme Duval err = unbind_request(i, &buf.bind_info); 2804f9f2ee2SJérôme Duval break; 2814f9f2ee2SJérôme Duval case DS_BIND_MTD: 2824f9f2ee2SJérôme Duval if (!capable(CAP_SYS_ADMIN)) return -EPERM; 2834f9f2ee2SJérôme Duval err = bind_mtd(i, &buf.mtd_info); 2844f9f2ee2SJérôme Duval break;*/ 2854f9f2ee2SJérôme Duval default: 2864f9f2ee2SJérôme Duval err = -EINVAL; 2874f9f2ee2SJérôme Duval } 2884f9f2ee2SJérôme Duval 2894f9f2ee2SJérôme Duval if ((err == 0) && (ret != CS_SUCCESS)) { 2904f9f2ee2SJérôme Duval switch (ret) { 2914f9f2ee2SJérôme Duval case CS_BAD_SOCKET: case CS_NO_CARD: 2924f9f2ee2SJérôme Duval err = ENODEV; break; 2934f9f2ee2SJérôme Duval case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ: 2944f9f2ee2SJérôme Duval case CS_BAD_TUPLE: 2954f9f2ee2SJérôme Duval err = EINVAL; break; 2964f9f2ee2SJérôme Duval case CS_IN_USE: 2974f9f2ee2SJérôme Duval err = EBUSY; break; 2984f9f2ee2SJérôme Duval case CS_OUT_OF_RESOURCE: 2994f9f2ee2SJérôme Duval err = ENOSPC; break; 3004f9f2ee2SJérôme Duval case CS_NO_MORE_ITEMS: 3014f9f2ee2SJérôme Duval err = ENODATA; break; 3024f9f2ee2SJérôme Duval case CS_UNSUPPORTED_FUNCTION: 3034f9f2ee2SJérôme Duval err = ENOSYS; break; 3044f9f2ee2SJérôme Duval default: 3054f9f2ee2SJérôme Duval err = EIO; break; 3064f9f2ee2SJérôme Duval } 3074f9f2ee2SJérôme Duval } 3084f9f2ee2SJérôme Duval 3094f9f2ee2SJérôme Duval if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size); 3104f9f2ee2SJérôme Duval 3114f9f2ee2SJérôme Duval return err; 3124f9f2ee2SJérôme Duval } /* ds_ioctl */ 3134f9f2ee2SJérôme Duval 3144f9f2ee2SJérôme Duval 3154f9f2ee2SJérôme Duval status_t 3164f9f2ee2SJérôme Duval init_hardware() 3174f9f2ee2SJérôme Duval { 3184f9f2ee2SJérôme Duval return B_OK; 3194f9f2ee2SJérôme Duval } 3204f9f2ee2SJérôme Duval 3214f9f2ee2SJérôme Duval 3224f9f2ee2SJérôme Duval const char ** 3234f9f2ee2SJérôme Duval publish_devices(void) 3244f9f2ee2SJérôme Duval { 3254f9f2ee2SJérôme Duval return (const char **)devices; 3264f9f2ee2SJérôme Duval } 3274f9f2ee2SJérôme Duval 3284f9f2ee2SJérôme Duval 3294f9f2ee2SJérôme Duval static device_hooks hooks = { 3304f9f2ee2SJérôme Duval &ds_open, 3314f9f2ee2SJérôme Duval &ds_close, 3324f9f2ee2SJérôme Duval &ds_free, 3334f9f2ee2SJérôme Duval &ds_ioctl, 3344f9f2ee2SJérôme Duval &ds_read, 3354f9f2ee2SJérôme Duval &ds_write, 3364f9f2ee2SJérôme Duval NULL, 3374f9f2ee2SJérôme Duval NULL, 3384f9f2ee2SJérôme Duval NULL, 3394f9f2ee2SJérôme Duval NULL 3404f9f2ee2SJérôme Duval }; 3414f9f2ee2SJérôme Duval 3424f9f2ee2SJérôme Duval device_hooks * 3434f9f2ee2SJérôme Duval find_device(const char *name) 3444f9f2ee2SJérôme Duval { 3454f9f2ee2SJérôme Duval return &hooks; 3464f9f2ee2SJérôme Duval } 3474f9f2ee2SJérôme Duval 3484f9f2ee2SJérôme Duval 3494f9f2ee2SJérôme Duval status_t 3504f9f2ee2SJérôme Duval init_driver() 3514f9f2ee2SJérôme Duval { 3524f9f2ee2SJérôme Duval status_t err; 3534f9f2ee2SJérôme Duval client_handle_t handle; 3544f9f2ee2SJérôme Duval uint32 i; 3554f9f2ee2SJérôme Duval 3564f9f2ee2SJérôme Duval #if DEBUG 3574f9f2ee2SJérôme Duval load_driver_symbols("ds"); 3584f9f2ee2SJérôme Duval #endif 3594f9f2ee2SJérôme Duval 3604f9f2ee2SJérôme Duval if ((err = get_module(CS_CLIENT_MODULE_NAME, (module_info **)&gPcmciaCs))!=B_OK) 3614f9f2ee2SJérôme Duval return err; 3624f9f2ee2SJérôme Duval if ((err = get_module(DS_MODULE_NAME, (module_info **)&gPcmciaDs))!=B_OK) { 3634f9f2ee2SJérôme Duval put_module(CS_CLIENT_MODULE_NAME); 3644f9f2ee2SJérôme Duval return err; 3654f9f2ee2SJérôme Duval } 3664f9f2ee2SJérôme Duval 3674f9f2ee2SJérôme Duval devices_count = 0; 3684f9f2ee2SJérôme Duval while (gPcmciaDs->get_handle(devices_count, &handle)==B_OK) { 3694f9f2ee2SJérôme Duval devices_count++; 3704f9f2ee2SJérôme Duval } 3714f9f2ee2SJérôme Duval 3724f9f2ee2SJérôme Duval if (devices_count <= 0) 3734f9f2ee2SJérôme Duval return ENODEV; 3744f9f2ee2SJérôme Duval 3754f9f2ee2SJérôme Duval devices = malloc(sizeof(char *) * (devices_count+1)); 3764f9f2ee2SJérôme Duval for (i=0; i<devices_count; i++) { 3774f9f2ee2SJérôme Duval devices[i] = strdup(sockname); 3784f9f2ee2SJérôme Duval sprintf(devices[i], sockname, i); 3794f9f2ee2SJérôme Duval } 3804f9f2ee2SJérôme Duval devices[devices_count] = NULL; 3814f9f2ee2SJérôme Duval 3824f9f2ee2SJérôme Duval return B_OK; 3834f9f2ee2SJérôme Duval } 3844f9f2ee2SJérôme Duval 3854f9f2ee2SJérôme Duval 3864f9f2ee2SJérôme Duval void 3874f9f2ee2SJérôme Duval uninit_driver() 3884f9f2ee2SJérôme Duval { 3894f9f2ee2SJérôme Duval int32 i = 0; 3904f9f2ee2SJérôme Duval for (i=0; i<devices_count; i++) { 3914f9f2ee2SJérôme Duval free (devices[i]); 3924f9f2ee2SJérôme Duval } 3934f9f2ee2SJérôme Duval 3944f9f2ee2SJérôme Duval put_module(DS_MODULE_NAME); 3954f9f2ee2SJérôme Duval put_module(CS_CLIENT_MODULE_NAME); 3964f9f2ee2SJérôme Duval } 397