Commit 7fbcee09 authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Linus Torvalds

[PATCH] pcmcia: register drivers with bus

Register all pcmcia drivers with the pcmcia bus within the old
register_pccard_driver() function. Alternatively, a new
registration function "pcmcia_register_driver()" (and its
counterpart,  "pcmcia_unregister_driver()") can be used.
parent 9a0c1982
......@@ -77,16 +77,8 @@ static const char *version =
/*====================================================================*/
typedef struct driver_info_t {
dev_info_t dev_info;
int use_count, status;
dev_link_t *(*attach)(void);
void (*detach)(dev_link_t *);
struct driver_info_t *next;
} driver_info_t;
typedef struct socket_bind_t {
driver_info_t *driver;
struct pcmcia_driver *driver;
u_char function;
dev_link_t *instance;
struct socket_bind_t *next;
......@@ -125,7 +117,7 @@ typedef struct socket_info_t {
static dev_info_t dev_info = "Driver Services";
/* Linked list of all registered device drivers */
static driver_info_t *root_driver = NULL;
static struct pcmcia_driver *root_driver = NULL;
static int sockets = 0, major_dev = -1;
static socket_info_t *socket_table = NULL;
......@@ -151,27 +143,67 @@ static void cs_error(client_handle_t handle, int func, int ret)
======================================================================*/
/**
* pcmcia_register_driver - register a PCMCIA driver with the bus core
*
* Registers a PCMCIA driver with the PCMCIA bus core.
*/
int pcmcia_register_driver(struct pcmcia_driver *driver)
{
if (!driver)
return -EINVAL;
driver->use_count = 0;
driver->status = init_status;
driver->drv.bus = &pcmcia_bus_type;
driver->next = root_driver;
root_driver = driver;
return driver_register(&driver->drv);
}
EXPORT_SYMBOL(pcmcia_register_driver);
/**
* pcmcia_unregister_driver - unregister a PCMCIA driver with the bus core
*/
void pcmcia_unregister_driver(struct pcmcia_driver *driver)
{
socket_bind_t *b;
int i;
if (driver->use_count > 0) {
/* Blank out any left-over device instances */
driver->attach = NULL; driver->detach = NULL;
for (i = 0; i < sockets; i++)
for (b = socket_table[i].bind; b; b = b->next)
if (b->driver == driver)
b->instance = NULL;
}
driver_unregister(&driver->drv);
}
EXPORT_SYMBOL(pcmcia_unregister_driver);
int register_pccard_driver(dev_info_t *dev_info,
dev_link_t *(*attach)(void),
void (*detach)(dev_link_t *))
{
driver_info_t *driver;
struct pcmcia_driver *driver;
socket_bind_t *b;
int i;
DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
for (driver = root_driver; driver; driver = driver->next)
if (strncmp((char *)dev_info, (char *)driver->dev_info,
if (strncmp((char *)dev_info, (char *)driver->drv.name,
DEV_NAME_LEN) == 0)
break;
if (!driver) {
driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
if (!driver) return -ENOMEM;
strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
driver->use_count = 0;
driver->status = init_status;
driver->next = root_driver;
root_driver = driver;
memset(driver, 0, sizeof(struct pcmcia_driver));
driver->drv.name = (char *)dev_info;
pcmcia_register_driver(driver);
}
driver->attach = attach;
......@@ -185,7 +217,7 @@ int register_pccard_driver(dev_info_t *dev_info,
b->instance = driver->attach();
if (b->instance == NULL)
printk(KERN_NOTICE "ds: unable to create instance "
"of '%s'!\n", driver->dev_info);
"of '%s'!\n", driver->drv.name);
}
return 0;
......@@ -195,29 +227,18 @@ int register_pccard_driver(dev_info_t *dev_info,
int unregister_pccard_driver(dev_info_t *dev_info)
{
driver_info_t *target, **d = &root_driver;
socket_bind_t *b;
int i;
struct pcmcia_driver **d = &root_driver;
DEBUG(0, "ds: unregister_pccard_driver('%s')\n",
(char *)dev_info);
while ((*d) && (strncmp((*d)->dev_info, (char *)dev_info,
while ((*d) && (strncmp((*d)->drv.name, (char *)dev_info,
DEV_NAME_LEN) != 0))
d = &(*d)->next;
if (*d == NULL)
return -ENODEV;
target = *d;
if (target->use_count == 0) {
*d = target->next;
kfree(target);
} else {
/* Blank out any left-over device instances */
target->attach = NULL; target->detach = NULL;
for (i = 0; i < sockets; i++)
for (b = socket_table[i].bind; b; b = b->next)
if (b->driver == target) b->instance = NULL;
}
pcmcia_unregister_driver(*d);
kfree(*d);
return 0;
} /* unregister_pccard_driver */
......@@ -227,10 +248,10 @@ int unregister_pccard_driver(dev_info_t *dev_info)
static int proc_read_drivers(char *buf, char **start, off_t pos,
int count, int *eof, void *data)
{
driver_info_t *d;
struct pcmcia_driver *d;
char *p = buf;
for (d = root_driver; d; d = d->next)
p += sprintf(p, "%-24.24s %d %d\n", d->dev_info,
p += sprintf(p, "%-24.24s %d %d\n", d->drv.name,
d->status, d->use_count);
return (p - buf);
}
......@@ -376,7 +397,7 @@ static int bind_mtd(int i, mtd_info_t *mtd_info)
static int bind_request(int i, bind_info_t *bind_info)
{
struct driver_info_t *driver;
struct pcmcia_driver *driver;
socket_bind_t *b;
bind_req_t bind_req;
socket_info_t *s = &socket_table[i];
......@@ -385,17 +406,15 @@ static int bind_request(int i, bind_info_t *bind_info)
DEBUG(2, "bind_request(%d, '%s')\n", i,
(char *)bind_info->dev_info);
for (driver = root_driver; driver; driver = driver->next)
if (strcmp((char *)driver->dev_info,
if (strcmp((char *)driver->drv.name,
(char *)bind_info->dev_info) == 0)
break;
if (driver == NULL) {
driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
if (!driver) return -ENOMEM;
strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN);
driver->use_count = 0;
driver->next = root_driver;
driver->attach = NULL; driver->detach = NULL;
root_driver = driver;
memset(driver, 0, sizeof(struct pcmcia_driver));
driver->drv.name = bind_info->dev_info;
pcmcia_register_driver(driver);
}
for (b = s->bind; b; b = b->next)
......@@ -409,7 +428,7 @@ static int bind_request(int i, bind_info_t *bind_info)
bind_req.Socket = i;
bind_req.Function = bind_info->function;
bind_req.dev_info = &driver->dev_info;
bind_req.dev_info = (dev_info_t *) driver->drv.name;
ret = pcmcia_bind_device(&bind_req);
if (ret != CS_SUCCESS) {
cs_error(NULL, BindDevice, ret);
......@@ -490,7 +509,7 @@ static int get_device_info(int i, bind_info_t *bind_info, int first)
#endif
for (b = s->bind; b; b = b->next)
if ((strcmp((char *)b->driver->dev_info,
if ((strcmp((char *)b->driver->drv.name,
(char *)bind_info->dev_info) == 0) &&
(b->function == bind_info->function))
break;
......@@ -524,7 +543,7 @@ static int unbind_request(int i, bind_info_t *bind_info)
DEBUG(2, "unbind_request(%d, '%s')\n", i,
(char *)bind_info->dev_info);
for (b = &s->bind; *b; b = &(*b)->next)
if ((strcmp((char *)(*b)->driver->dev_info,
if ((strcmp((char *)(*b)->driver->drv.name,
(char *)bind_info->dev_info) == 0) &&
((*b)->function == bind_info->function))
break;
......@@ -538,10 +557,11 @@ static int unbind_request(int i, bind_info_t *bind_info)
c->driver->detach(c->instance);
} else {
if (c->driver->use_count == 0) {
driver_info_t **d;
struct pcmcia_driver **d;
for (d = &root_driver; *d; d = &((*d)->next))
if (c->driver == *d) break;
*d = (*d)->next;
pcmcia_unregister_driver(c->driver);
kfree(c->driver);
}
}
......
......@@ -146,6 +146,18 @@ int unregister_pccard_driver(dev_info_t *dev_info);
extern struct bus_type pcmcia_bus_type;
struct pcmcia_driver {
int use_count, status;
dev_link_t *(*attach)(void);
void (*detach)(dev_link_t *);
struct module *owner;
struct device_driver drv;
struct pcmcia_driver *next;
};
int pcmcia_register_driver(struct pcmcia_driver *driver);
void pcmcia_unregister_driver(struct pcmcia_driver *driver);
#endif /* __KERNEL__ */
#endif /* _LINUX_DS_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment