/* * Copyright 2005, Jérôme DUVAL. All rights reserved. * Distributed under the terms of the MIT License. */ #include #include #include #include #include #include #include #include #include #define __KERNEL__ #include #include #include #include #define copy_from_user memcpy #define copy_to_user memcpy #define CardServices gPcmciaCs->_CardServices const char sockname[] = "bus/pcmcia/sock/%d"; static char ** devices; uint32 devices_count = 0; int32 api_version = B_CUR_DRIVER_API_VERSION; cs_client_module_info *gPcmciaCs; ds_module_info *gPcmciaDs; static status_t ds_open(const char *name, uint32 flags, void **_cookie) { int32 socket = -1; int32 i; *_cookie = NULL; for (i=0; iget_handle(socket, (client_handle_t *)_cookie) != B_OK) { return ENODEV; } return B_OK; } static status_t ds_close(void *cookie) { return B_OK; } static status_t ds_free(void *cookie) { return B_OK; } static status_t ds_read(void *cookie, off_t position, void *data, size_t *numBytes) { return B_ERROR; } static status_t ds_write(void *cookie, off_t position, const void *data, size_t *numBytes) { return B_ERROR; } /*====================================================================*/ static status_t ds_ioctl(void *cookie, uint32 cmd, void *arg, size_t len) { /*socket_info_t *s = (socket_info_t *) cookie; u_int size = IOCPARM_LEN(cmd); status_t ret, err; ds_ioctl_arg_t buf; if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; err = ret = 0; if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size); switch (cmd) { case DS_ADJUST_RESOURCE_INFO: ret = CardServices(AdjustResourceInfo, s->handle, &buf.adjust); break; case DS_GET_CARD_SERVICES_INFO: ret = CardServices(GetCardServicesInfo, &buf.servinfo); break; case DS_GET_CONFIGURATION_INFO: ret = CardServices(GetConfigurationInfo, s->handle, &buf.config); break; case DS_GET_FIRST_TUPLE: ret = CardServices(GetFirstTuple, s->handle, &buf.tuple); break; case DS_GET_NEXT_TUPLE: ret = CardServices(GetNextTuple, s->handle, &buf.tuple); break; case DS_GET_TUPLE_DATA: buf.tuple.TupleData = buf.tuple_parse.data; buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data); ret = CardServices(GetTupleData, s->handle, &buf.tuple); break; case DS_PARSE_TUPLE: buf.tuple.TupleData = buf.tuple_parse.data; ret = CardServices(ParseTuple, s->handle, &buf.tuple, &buf.tuple_parse.parse); break; case DS_RESET_CARD: ret = CardServices(ResetCard, s->handle, NULL); break; case DS_GET_STATUS: ret = CardServices(GetStatus, s->handle, &buf.status); break; case DS_VALIDATE_CIS: ret = CardServices(ValidateCIS, s->handle, &buf.cisinfo); break; case DS_SUSPEND_CARD: ret = CardServices(SuspendCard, s->handle, NULL); break; case DS_RESUME_CARD: ret = CardServices(ResumeCard, s->handle, NULL); break; case DS_EJECT_CARD: ret = CardServices(EjectCard, s->handle, NULL); break; case DS_INSERT_CARD: ret = CardServices(InsertCard, s->handle, NULL); break; case DS_ACCESS_CONFIGURATION_REGISTER: if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) return -EPERM; ret = CardServices(AccessConfigurationRegister, s->handle, &buf.conf_reg); break; case DS_GET_FIRST_REGION: ret = CardServices(GetFirstRegion, s->handle, &buf.region); break; case DS_GET_NEXT_REGION: ret = CardServices(GetNextRegion, s->handle, &buf.region); break; case DS_GET_FIRST_WINDOW: buf.win_info.handle = (window_handle_t)s->handle; ret = CardServices(GetFirstWindow, &buf.win_info.handle, &buf.win_info.window); break; case DS_GET_NEXT_WINDOW: ret = CardServices(GetNextWindow, &buf.win_info.handle, &buf.win_info.window); break; case DS_GET_MEM_PAGE: ret = CardServices(GetMemPage, buf.win_info.handle, &buf.win_info.map); break; case DS_REPLACE_CIS: ret = CardServices(ReplaceCIS, s->handle, &buf.cisdump); break; */ client_handle_t h = (client_handle_t) cookie; u_int size = IOCPARM_LEN(cmd); status_t ret, err; ds_ioctl_arg_t buf; if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL; err = ret = 0; if (cmd & IOC_IN) copy_from_user((char *)&buf, (char *)arg, size); switch (cmd) { case DS_ADJUST_RESOURCE_INFO: ret = CardServices(AdjustResourceInfo, h, &buf.adjust); break; case DS_GET_CARD_SERVICES_INFO: ret = CardServices(GetCardServicesInfo, &buf.servinfo); break; case DS_GET_CONFIGURATION_INFO: ret = CardServices(GetConfigurationInfo, h, &buf.config); break; case DS_GET_FIRST_TUPLE: ret = CardServices(GetFirstTuple, h, &buf.tuple); break; case DS_GET_NEXT_TUPLE: ret = CardServices(GetNextTuple, h, &buf.tuple); break; case DS_GET_TUPLE_DATA: buf.tuple.TupleData = buf.tuple_parse.data; buf.tuple.TupleDataMax = sizeof(buf.tuple_parse.data); ret = CardServices(GetTupleData, h, &buf.tuple); break; case DS_PARSE_TUPLE: buf.tuple.TupleData = buf.tuple_parse.data; ret = CardServices(ParseTuple, h, &buf.tuple, &buf.tuple_parse.parse); break; case DS_RESET_CARD: ret = CardServices(ResetCard, h, NULL); break; case DS_GET_STATUS: ret = CardServices(GetStatus, h, &buf.status); break; case DS_VALIDATE_CIS: ret = CardServices(ValidateCIS, h, &buf.cisinfo); break; case DS_SUSPEND_CARD: ret = CardServices(SuspendCard, h, NULL); break; case DS_RESUME_CARD: ret = CardServices(ResumeCard, h, NULL); break; case DS_EJECT_CARD: ret = CardServices(EjectCard, h, NULL); break; case DS_INSERT_CARD: ret = CardServices(InsertCard, h, NULL); break; /* case DS_ACCESS_CONFIGURATION_REGISTER: if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN)) return -EPERM; ret = CardServices(AccessConfigurationRegister, h, &buf.conf_reg); break; case DS_GET_FIRST_REGION: ret = CardServices(GetFirstRegion, h, &buf.region); break; case DS_GET_NEXT_REGION: ret = CardServices(GetNextRegion, h, &buf.region); break; case DS_GET_FIRST_WINDOW: buf.win_info.handle = (window_handle_t)h; ret = CardServices(GetFirstWindow, &buf.win_info.handle, &buf.win_info.window); break; case DS_GET_NEXT_WINDOW: ret = CardServices(GetNextWindow, &buf.win_info.handle, &buf.win_info.window); break; case DS_GET_MEM_PAGE: ret = CardServices(GetMemPage, buf.win_info.handle, &buf.win_info.map); break;*/ case DS_REPLACE_CIS: ret = CardServices(ReplaceCIS, h, &buf.cisdump); break; /* case DS_BIND_REQUEST: if (!capable(CAP_SYS_ADMIN)) return -EPERM; err = bind_request(i, &buf.bind_info); break; case DS_GET_DEVICE_INFO: err = get_device_info(i, &buf.bind_info, 1); break; case DS_GET_NEXT_DEVICE: err = get_device_info(i, &buf.bind_info, 0); break; case DS_UNBIND_REQUEST: err = unbind_request(i, &buf.bind_info); break; case DS_BIND_MTD: if (!capable(CAP_SYS_ADMIN)) return -EPERM; err = bind_mtd(i, &buf.mtd_info); break;*/ default: err = -EINVAL; } if ((err == 0) && (ret != CS_SUCCESS)) { switch (ret) { case CS_BAD_SOCKET: case CS_NO_CARD: err = ENODEV; break; case CS_BAD_ARGS: case CS_BAD_ATTRIBUTE: case CS_BAD_IRQ: case CS_BAD_TUPLE: err = EINVAL; break; case CS_IN_USE: err = EBUSY; break; case CS_OUT_OF_RESOURCE: err = ENOSPC; break; case CS_NO_MORE_ITEMS: err = ENODATA; break; case CS_UNSUPPORTED_FUNCTION: err = ENOSYS; break; default: err = EIO; break; } } if (cmd & IOC_OUT) copy_to_user((char *)arg, (char *)&buf, size); return err; } /* ds_ioctl */ status_t init_hardware() { return B_OK; } const char ** publish_devices(void) { return (const char **)devices; } static device_hooks hooks = { &ds_open, &ds_close, &ds_free, &ds_ioctl, &ds_read, &ds_write, NULL, NULL, NULL, NULL }; device_hooks * find_device(const char *name) { return &hooks; } status_t init_driver() { status_t err; client_handle_t handle; uint32 i; #if DEBUG load_driver_symbols("ds"); #endif if ((err = get_module(CS_CLIENT_MODULE_NAME, (module_info **)&gPcmciaCs))!=B_OK) return err; if ((err = get_module(DS_MODULE_NAME, (module_info **)&gPcmciaDs))!=B_OK) { put_module(CS_CLIENT_MODULE_NAME); return err; } devices_count = 0; while (gPcmciaDs->get_handle(devices_count, &handle)==B_OK) { devices_count++; } if (devices_count <= 0) return ENODEV; devices = malloc(sizeof(char *) * (devices_count+1)); for (i=0; i