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:
Jérôme Duval 2005-12-14 22:50:05 +00:00
parent 42a631e9fa
commit 4f9f2ee29d
6 changed files with 468 additions and 0 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 ;

View File

@ -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
;

View File

@ -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);
}