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
This commit is contained in:
parent
42a631e9fa
commit
4f9f2ee29d
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
SubDir HAIKU_TOP src add-ons kernel drivers bus pcmcia ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
if $(TARGET_PLATFORM) != haiku {
|
||||
UseHeaders [ FStandardOSHeaders ] : true ;
|
||||
# Needed for <support/Errors.h> 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
|
||||
;
|
||||
|
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
* Copyright 2005, Jérôme DUVAL. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <Drivers.h>
|
||||
#include <OS.h>
|
||||
#include <bus_manager.h>
|
||||
#include <module.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <malloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define __KERNEL__
|
||||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/cistpl.h>
|
||||
#include <pcmcia/ds.h>
|
||||
|
||||
#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; i<devices_count; i++) {
|
||||
if (strcmp(name, devices[i]) == 0) {
|
||||
socket = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (socket < 0) {
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
if (gPcmciaDs->get_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<devices_count; i++) {
|
||||
devices[i] = strdup(sockname);
|
||||
sprintf(devices[i], sockname, i);
|
||||
}
|
||||
devices[devices_count] = NULL;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
uninit_driver()
|
||||
{
|
||||
int32 i = 0;
|
||||
for (i=0; i<devices_count; i++) {
|
||||
free (devices[i]);
|
||||
}
|
||||
|
||||
put_module(DS_MODULE_NAME);
|
||||
put_module(CS_CLIENT_MODULE_NAME);
|
||||
}
|
Loading…
Reference in New Issue