From 4f9f2ee29da9e68b02891f78d4a8fafa28eb88da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Wed, 14 Dec 2005 22:50:05 +0000 Subject: [PATCH] added a pcmcia bus raw driver compatible with R5 git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15540 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/drivers/pcmcia/cs.h | 24 ++ headers/os/drivers/pcmcia/driver_ops.h | 9 + headers/os/drivers/pcmcia/ds.h | 22 + src/add-ons/kernel/drivers/bus/Jamfile | 1 + src/add-ons/kernel/drivers/bus/pcmcia/Jamfile | 17 + src/add-ons/kernel/drivers/bus/pcmcia/ds.c | 395 ++++++++++++++++++ 6 files changed, 468 insertions(+) create mode 100644 src/add-ons/kernel/drivers/bus/pcmcia/Jamfile create mode 100644 src/add-ons/kernel/drivers/bus/pcmcia/ds.c diff --git a/headers/os/drivers/pcmcia/cs.h b/headers/os/drivers/pcmcia/cs.h index 8e202c6788..66b4c4acec 100644 --- a/headers/os/drivers/pcmcia/cs.h +++ b/headers/os/drivers/pcmcia/cs.h @@ -436,6 +436,30 @@ extern int CardServices(int func, void *a1, void *a2, void *a3); extern int CardServices(int func, ...); #endif +#ifdef __BEOS__ +#define SS_MODULE_NAME(s) ("busses/pcmcia/" s "/v1") +#define MTD_MODULE_NAME(s) ("busses/pcmcia/" s "/v1") +#define CS_CLIENT_MODULE_NAME "bus_managers/pcmcia_cs/client/v1" +typedef struct cs_client_module_info { + bus_manager_info binfo; + int (*_CardServices)(int, ...); + int (*_MTDHelperEntry)(int, ...); + // void (*_add_timer)(struct timer_list *); + // void (*_del_timer)(struct timer_list *); +} cs_client_module_info; +#define CS_SOCKET_MODULE_NAME "bus_managers/pcmcia_cs/socket/v1" +typedef struct cs_socket_module_info { + bus_manager_info binfo; + int (*_register_ss_entry)(int, ss_entry_t); + void (*_unregister_ss_entry)(ss_entry_t); + // void (*_add_timer)(struct timer_list *); + // void (*_del_timer)(struct timer_list *); + int (*register_resource)(int, u_long, u_long); + int (*release_resource)(int, u_long, u_long); + int (*check_resource)(int, u_long, u_long); +} cs_socket_module_info; +#endif + #endif /* __KERNEL__ */ #endif /* _LINUX_CS_H */ diff --git a/headers/os/drivers/pcmcia/driver_ops.h b/headers/os/drivers/pcmcia/driver_ops.h index 9903e5bf54..b6c7d69c54 100644 --- a/headers/os/drivers/pcmcia/driver_ops.h +++ b/headers/os/drivers/pcmcia/driver_ops.h @@ -68,6 +68,15 @@ typedef struct driver_operations { int register_driver(struct driver_operations *ops); void unregister_driver(struct driver_operations *ops); +#ifdef __BEOS__ +#define CB_ENABLER_MODULE_NAME "bus_managers/cb_enabler/v1" +typedef struct cb_enabler_module_info { + bus_manager_info binfo; + int (*register_driver)(struct driver_operations *ops); + void (*unregister_driver)(struct driver_operations *ops); +} cb_enabler_module_info; +#endif /* __BEOS__ */ + #endif /* __KERNEL__ */ #endif /* _LINUX_DRIVER_OPS_H */ diff --git a/headers/os/drivers/pcmcia/ds.h b/headers/os/drivers/pcmcia/ds.h index 9d72d62dda..853960b65d 100644 --- a/headers/os/drivers/pcmcia/ds.h +++ b/headers/os/drivers/pcmcia/ds.h @@ -79,11 +79,19 @@ typedef union ds_ioctl_arg_t { #ifndef __HAIKU__ #undef _IOC +#undef IOCPARM_LEN #undef _IOR #undef _IOW #undef _IOWR +#undef IOC_IN +#undef IOC_OUT +#undef IOC_INOUT +#define IOC_IN 1 +#define IOC_OUT 2 +#define IOC_INOUT (IOC_IN|IOC_OUT) #define _IOC(inout, group, num, len) \ (inout | ((len & IOCPARM_MASK)<<2) | ((group) << 24) | (num<<16)) +#define IOCPARM_LEN(x) (((x) >> 2) & IOCPARM_MASK) #define _IOR(g,n,t) _IOC(2, (g), (n), sizeof(t)) #define _IOW(g,n,t) _IOC(1 , (g), (n), sizeof(t)) #define _IOWR(g,n,t) _IOC(3, (g), (n), sizeof(t)) @@ -122,8 +130,10 @@ typedef union ds_ioctl_arg_t { typedef struct dev_link_t { dev_node_t *dev; u_int state, open; +#ifndef __BEOS__ wait_queue_head_t pending; struct timer_list release; +#endif client_handle_t handle; io_req_t io; irq_req_t irq; @@ -155,6 +165,18 @@ int unregister_pccard_driver(dev_info_t *dev_info); #define register_pcmcia_driver register_pccard_driver #define unregister_pcmcia_driver unregister_pccard_driver +#ifdef __BEOS__ +#define DS_MODULE_NAME "bus_managers/pcmcia_ds/v2" +typedef struct ds_module_info { + bus_manager_info binfo; + int (*_register_pccard_driver)(dev_info_t *, + dev_link_t *(*)(void), + void (*)(dev_link_t *)); + int (*_unregister_pccard_driver)(dev_info_t *); + int (*get_handle)(int socket, client_handle_t *handle); +} ds_module_info; +#endif /* __BEOS__ */ + #endif /* __KERNEL__ */ #endif /* _LINUX_DS_H */ diff --git a/src/add-ons/kernel/drivers/bus/Jamfile b/src/add-ons/kernel/drivers/bus/Jamfile index 56fa565589..dae876c50f 100644 --- a/src/add-ons/kernel/drivers/bus/Jamfile +++ b/src/add-ons/kernel/drivers/bus/Jamfile @@ -1,3 +1,4 @@ SubDir HAIKU_TOP src add-ons kernel drivers bus ; SubInclude HAIKU_TOP src add-ons kernel drivers bus scsi ; +SubInclude HAIKU_TOP src add-ons kernel drivers bus pcmcia ; diff --git a/src/add-ons/kernel/drivers/bus/pcmcia/Jamfile b/src/add-ons/kernel/drivers/bus/pcmcia/Jamfile new file mode 100644 index 0000000000..7d27aee8f2 --- /dev/null +++ b/src/add-ons/kernel/drivers/bus/pcmcia/Jamfile @@ -0,0 +1,17 @@ +SubDir HAIKU_TOP src add-ons kernel drivers bus pcmcia ; + +SetSubDirSupportedPlatformsBeOSCompatible ; + +if $(TARGET_PLATFORM) != haiku { + UseHeaders [ FStandardOSHeaders ] : true ; + # Needed for and maybe other stuff. + UseHeaders [ FDirName $(HAIKU_TOP) headers os drivers ] : true ; + # We need the public pcmcia headers also when not compiling for Haiku. + UseHeaders [ FDirName $(HAIKU_TOP) headers posix ] : true ; + # We need the public posix headers also when not compiling for Haiku. +} + +KernelAddon ds : kernel drivers bus pcmcia : + ds.c + ; + diff --git a/src/add-ons/kernel/drivers/bus/pcmcia/ds.c b/src/add-ons/kernel/drivers/bus/pcmcia/ds.c new file mode 100644 index 0000000000..b38b435fc7 --- /dev/null +++ b/src/add-ons/kernel/drivers/bus/pcmcia/ds.c @@ -0,0 +1,395 @@ +/* + * 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 + +#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