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 = ...@@ -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 { typedef struct socket_bind_t {
driver_info_t *driver; struct pcmcia_driver *driver;
u_char function; u_char function;
dev_link_t *instance; dev_link_t *instance;
struct socket_bind_t *next; struct socket_bind_t *next;
...@@ -125,7 +117,7 @@ typedef struct socket_info_t { ...@@ -125,7 +117,7 @@ typedef struct socket_info_t {
static dev_info_t dev_info = "Driver Services"; static dev_info_t dev_info = "Driver Services";
/* Linked list of all registered device drivers */ /* 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 int sockets = 0, major_dev = -1;
static socket_info_t *socket_table = NULL; static socket_info_t *socket_table = NULL;
...@@ -151,27 +143,67 @@ static void cs_error(client_handle_t handle, int func, int ret) ...@@ -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, int register_pccard_driver(dev_info_t *dev_info,
dev_link_t *(*attach)(void), dev_link_t *(*attach)(void),
void (*detach)(dev_link_t *)) void (*detach)(dev_link_t *))
{ {
driver_info_t *driver; struct pcmcia_driver *driver;
socket_bind_t *b; socket_bind_t *b;
int i; int i;
DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info); DEBUG(0, "ds: register_pccard_driver('%s')\n", (char *)dev_info);
for (driver = root_driver; driver; driver = driver->next) 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) DEV_NAME_LEN) == 0)
break; break;
if (!driver) { if (!driver) {
driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL); driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
if (!driver) return -ENOMEM; if (!driver) return -ENOMEM;
strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN); memset(driver, 0, sizeof(struct pcmcia_driver));
driver->use_count = 0; driver->drv.name = (char *)dev_info;
driver->status = init_status; pcmcia_register_driver(driver);
driver->next = root_driver;
root_driver = driver;
} }
driver->attach = attach; driver->attach = attach;
...@@ -185,7 +217,7 @@ int register_pccard_driver(dev_info_t *dev_info, ...@@ -185,7 +217,7 @@ int register_pccard_driver(dev_info_t *dev_info,
b->instance = driver->attach(); b->instance = driver->attach();
if (b->instance == NULL) if (b->instance == NULL)
printk(KERN_NOTICE "ds: unable to create instance " printk(KERN_NOTICE "ds: unable to create instance "
"of '%s'!\n", driver->dev_info); "of '%s'!\n", driver->drv.name);
} }
return 0; return 0;
...@@ -195,29 +227,18 @@ int register_pccard_driver(dev_info_t *dev_info, ...@@ -195,29 +227,18 @@ int register_pccard_driver(dev_info_t *dev_info,
int unregister_pccard_driver(dev_info_t *dev_info) int unregister_pccard_driver(dev_info_t *dev_info)
{ {
driver_info_t *target, **d = &root_driver; struct pcmcia_driver **d = &root_driver;
socket_bind_t *b;
int i;
DEBUG(0, "ds: unregister_pccard_driver('%s')\n", DEBUG(0, "ds: unregister_pccard_driver('%s')\n",
(char *)dev_info); (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)) DEV_NAME_LEN) != 0))
d = &(*d)->next; d = &(*d)->next;
if (*d == NULL) if (*d == NULL)
return -ENODEV; return -ENODEV;
target = *d; pcmcia_unregister_driver(*d);
if (target->use_count == 0) { kfree(*d);
*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;
}
return 0; return 0;
} /* unregister_pccard_driver */ } /* unregister_pccard_driver */
...@@ -227,10 +248,10 @@ int unregister_pccard_driver(dev_info_t *dev_info) ...@@ -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, static int proc_read_drivers(char *buf, char **start, off_t pos,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
driver_info_t *d; struct pcmcia_driver *d;
char *p = buf; char *p = buf;
for (d = root_driver; d; d = d->next) 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); d->status, d->use_count);
return (p - buf); return (p - buf);
} }
...@@ -376,7 +397,7 @@ static int bind_mtd(int i, mtd_info_t *mtd_info) ...@@ -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) static int bind_request(int i, bind_info_t *bind_info)
{ {
struct driver_info_t *driver; struct pcmcia_driver *driver;
socket_bind_t *b; socket_bind_t *b;
bind_req_t bind_req; bind_req_t bind_req;
socket_info_t *s = &socket_table[i]; socket_info_t *s = &socket_table[i];
...@@ -385,17 +406,15 @@ static int bind_request(int i, bind_info_t *bind_info) ...@@ -385,17 +406,15 @@ static int bind_request(int i, bind_info_t *bind_info)
DEBUG(2, "bind_request(%d, '%s')\n", i, DEBUG(2, "bind_request(%d, '%s')\n", i,
(char *)bind_info->dev_info); (char *)bind_info->dev_info);
for (driver = root_driver; driver; driver = driver->next) 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) (char *)bind_info->dev_info) == 0)
break; break;
if (driver == NULL) { if (driver == NULL) {
driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL); driver = kmalloc(sizeof(struct pcmcia_driver), GFP_KERNEL);
if (!driver) return -ENOMEM; if (!driver) return -ENOMEM;
strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN); memset(driver, 0, sizeof(struct pcmcia_driver));
driver->use_count = 0; driver->drv.name = bind_info->dev_info;
driver->next = root_driver; pcmcia_register_driver(driver);
driver->attach = NULL; driver->detach = NULL;
root_driver = driver;
} }
for (b = s->bind; b; b = b->next) for (b = s->bind; b; b = b->next)
...@@ -409,7 +428,7 @@ static int bind_request(int i, bind_info_t *bind_info) ...@@ -409,7 +428,7 @@ static int bind_request(int i, bind_info_t *bind_info)
bind_req.Socket = i; bind_req.Socket = i;
bind_req.Function = bind_info->function; 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); ret = pcmcia_bind_device(&bind_req);
if (ret != CS_SUCCESS) { if (ret != CS_SUCCESS) {
cs_error(NULL, BindDevice, ret); cs_error(NULL, BindDevice, ret);
...@@ -490,7 +509,7 @@ static int get_device_info(int i, bind_info_t *bind_info, int first) ...@@ -490,7 +509,7 @@ static int get_device_info(int i, bind_info_t *bind_info, int first)
#endif #endif
for (b = s->bind; b; b = b->next) 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) && (char *)bind_info->dev_info) == 0) &&
(b->function == bind_info->function)) (b->function == bind_info->function))
break; break;
...@@ -524,7 +543,7 @@ static int unbind_request(int i, bind_info_t *bind_info) ...@@ -524,7 +543,7 @@ static int unbind_request(int i, bind_info_t *bind_info)
DEBUG(2, "unbind_request(%d, '%s')\n", i, DEBUG(2, "unbind_request(%d, '%s')\n", i,
(char *)bind_info->dev_info); (char *)bind_info->dev_info);
for (b = &s->bind; *b; b = &(*b)->next) 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) && (char *)bind_info->dev_info) == 0) &&
((*b)->function == bind_info->function)) ((*b)->function == bind_info->function))
break; break;
...@@ -538,10 +557,11 @@ static int unbind_request(int i, bind_info_t *bind_info) ...@@ -538,10 +557,11 @@ static int unbind_request(int i, bind_info_t *bind_info)
c->driver->detach(c->instance); c->driver->detach(c->instance);
} else { } else {
if (c->driver->use_count == 0) { if (c->driver->use_count == 0) {
driver_info_t **d; struct pcmcia_driver **d;
for (d = &root_driver; *d; d = &((*d)->next)) for (d = &root_driver; *d; d = &((*d)->next))
if (c->driver == *d) break; if (c->driver == *d) break;
*d = (*d)->next; *d = (*d)->next;
pcmcia_unregister_driver(c->driver);
kfree(c->driver); kfree(c->driver);
} }
} }
......
...@@ -146,6 +146,18 @@ int unregister_pccard_driver(dev_info_t *dev_info); ...@@ -146,6 +146,18 @@ int unregister_pccard_driver(dev_info_t *dev_info);
extern struct bus_type pcmcia_bus_type; 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 /* __KERNEL__ */
#endif /* _LINUX_DS_H */ #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