Commit d7906de1 authored by Linus Torvalds's avatar Linus Torvalds
parents fbd91ac2 725a6abf
This file details changes in 2.6 which affect PCMCIA card driver authors: This file details changes in 2.6 which affect PCMCIA card driver authors:
* Unify detach and REMOVAL event code, as well as attach and INSERTION
code (as of 2.6.16)
void (*remove) (struct pcmcia_device *dev);
int (*probe) (struct pcmcia_device *dev);
* Move suspend, resume and reset out of event handler (as of 2.6.16)
int (*suspend) (struct pcmcia_device *dev);
int (*resume) (struct pcmcia_device *dev);
should be initialized in struct pcmcia_driver, and handle
(SUSPEND == RESET_PHYSICAL) and (RESUME == CARD_RESET) events
* event handler initialization in struct pcmcia_driver (as of 2.6.13) * event handler initialization in struct pcmcia_driver (as of 2.6.13)
The event handler is notified of all events, and must be initialized The event handler is notified of all events, and must be initialized
as the event() callback in the driver's struct pcmcia_driver. as the event() callback in the driver's struct pcmcia_driver.
......
...@@ -62,6 +62,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state) ...@@ -62,6 +62,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
up(&dpm_sem); up(&dpm_sem);
return error; return error;
} }
EXPORT_SYMBOL(dpm_runtime_suspend);
#if 0 #if 0
......
...@@ -87,14 +87,8 @@ typedef struct bluecard_info_t { ...@@ -87,14 +87,8 @@ typedef struct bluecard_info_t {
static void bluecard_config(dev_link_t *link); static void bluecard_config(dev_link_t *link);
static void bluecard_release(dev_link_t *link); static void bluecard_release(dev_link_t *link);
static int bluecard_event(event_t event, int priority, event_callback_args_t *args);
static dev_info_t dev_info = "bluecard_cs"; static void bluecard_detach(struct pcmcia_device *p_dev);
static dev_link_t *bluecard_attach(void);
static void bluecard_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
/* Default baud rate: 57600, 115200, 230400 or 460800 */ /* Default baud rate: 57600, 115200, 230400 or 460800 */
...@@ -862,17 +856,15 @@ static int bluecard_close(bluecard_info_t *info) ...@@ -862,17 +856,15 @@ static int bluecard_close(bluecard_info_t *info)
return 0; return 0;
} }
static dev_link_t *bluecard_attach(void) static int bluecard_attach(struct pcmcia_device *p_dev)
{ {
bluecard_info_t *info; bluecard_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
/* Create new info device */ /* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return -ENOMEM;
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
...@@ -889,50 +881,24 @@ static dev_link_t *bluecard_attach(void) ...@@ -889,50 +881,24 @@ static dev_link_t *bluecard_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
bluecard_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
bluecard_config(link);
return 0;
} }
static void bluecard_detach(dev_link_t *link) static void bluecard_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
bluecard_info_t *info = link->priv; bluecard_info_t *info = link->priv;
dev_link_t **linkp;
int ret;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
bluecard_release(link); bluecard_release(link);
if (link->handle) {
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
}
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(info); kfree(info);
} }
...@@ -1045,39 +1011,24 @@ static void bluecard_release(dev_link_t *link) ...@@ -1045,39 +1011,24 @@ static void bluecard_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int bluecard_suspend(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
static int bluecard_event(event_t event, int priority, event_callback_args_t *args) return 0;
}
static int bluecard_resume(struct pcmcia_device *dev)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
bluecard_info_t *info = link->priv;
switch (event) { link->state &= ~DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (DEV_OK(link))
link->state &= ~DEV_PRESENT; pcmcia_request_configuration(link->handle, &link->conf);
if (link->state & DEV_CONFIG) {
bluecard_close(info);
bluecard_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
bluecard_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (DEV_OK(link))
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0; return 0;
} }
...@@ -1095,10 +1046,11 @@ static struct pcmcia_driver bluecard_driver = { ...@@ -1095,10 +1046,11 @@ static struct pcmcia_driver bluecard_driver = {
.drv = { .drv = {
.name = "bluecard_cs", .name = "bluecard_cs",
}, },
.attach = bluecard_attach, .probe = bluecard_attach,
.event = bluecard_event, .remove = bluecard_detach,
.detach = bluecard_detach,
.id_table = bluecard_ids, .id_table = bluecard_ids,
.suspend = bluecard_suspend,
.resume = bluecard_resume,
}; };
static int __init init_bluecard_cs(void) static int __init init_bluecard_cs(void)
...@@ -1110,7 +1062,6 @@ static int __init init_bluecard_cs(void) ...@@ -1110,7 +1062,6 @@ static int __init init_bluecard_cs(void)
static void __exit exit_bluecard_cs(void) static void __exit exit_bluecard_cs(void)
{ {
pcmcia_unregister_driver(&bluecard_driver); pcmcia_unregister_driver(&bluecard_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_bluecard_cs); module_init(init_bluecard_cs);
......
...@@ -90,14 +90,8 @@ typedef struct bt3c_info_t { ...@@ -90,14 +90,8 @@ typedef struct bt3c_info_t {
static void bt3c_config(dev_link_t *link); static void bt3c_config(dev_link_t *link);
static void bt3c_release(dev_link_t *link); static void bt3c_release(dev_link_t *link);
static int bt3c_event(event_t event, int priority, event_callback_args_t *args);
static dev_info_t dev_info = "bt3c_cs"; static void bt3c_detach(struct pcmcia_device *p_dev);
static dev_link_t *bt3c_attach(void);
static void bt3c_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
/* Transmit states */ /* Transmit states */
...@@ -663,17 +657,15 @@ static int bt3c_close(bt3c_info_t *info) ...@@ -663,17 +657,15 @@ static int bt3c_close(bt3c_info_t *info)
return 0; return 0;
} }
static dev_link_t *bt3c_attach(void) static int bt3c_attach(struct pcmcia_device *p_dev)
{ {
bt3c_info_t *info; bt3c_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
/* Create new info device */ /* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return -ENOMEM;
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
...@@ -690,50 +682,24 @@ static dev_link_t *bt3c_attach(void) ...@@ -690,50 +682,24 @@ static dev_link_t *bt3c_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
bt3c_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
bt3c_config(link);
return 0;
} }
static void bt3c_detach(dev_link_t *link) static void bt3c_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
bt3c_info_t *info = link->priv; bt3c_info_t *info = link->priv;
dev_link_t **linkp;
int ret;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
bt3c_release(link); bt3c_release(link);
if (link->handle) {
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
}
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(info); kfree(info);
} }
...@@ -891,43 +857,29 @@ static void bt3c_release(dev_link_t *link) ...@@ -891,43 +857,29 @@ static void bt3c_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int bt3c_suspend(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
static int bt3c_event(event_t event, int priority, event_callback_args_t *args) link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0;
}
static int bt3c_resume(struct pcmcia_device *dev)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
bt3c_info_t *info = link->priv;
switch (event) { link->state &= ~DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (DEV_OK(link))
link->state &= ~DEV_PRESENT; pcmcia_request_configuration(link->handle, &link->conf);
if (link->state & DEV_CONFIG) {
bt3c_close(info);
bt3c_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
bt3c_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (DEV_OK(link))
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0; return 0;
} }
static struct pcmcia_device_id bt3c_ids[] = { static struct pcmcia_device_id bt3c_ids[] = {
PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02), PCMCIA_DEVICE_PROD_ID13("3COM", "Bluetooth PC Card", 0xefce0a31, 0xd4ce9b02),
PCMCIA_DEVICE_NULL PCMCIA_DEVICE_NULL
...@@ -939,10 +891,11 @@ static struct pcmcia_driver bt3c_driver = { ...@@ -939,10 +891,11 @@ static struct pcmcia_driver bt3c_driver = {
.drv = { .drv = {
.name = "bt3c_cs", .name = "bt3c_cs",
}, },
.attach = bt3c_attach, .probe = bt3c_attach,
.event = bt3c_event, .remove = bt3c_detach,
.detach = bt3c_detach,
.id_table = bt3c_ids, .id_table = bt3c_ids,
.suspend = bt3c_suspend,
.resume = bt3c_resume,
}; };
static int __init init_bt3c_cs(void) static int __init init_bt3c_cs(void)
...@@ -954,7 +907,6 @@ static int __init init_bt3c_cs(void) ...@@ -954,7 +907,6 @@ static int __init init_bt3c_cs(void)
static void __exit exit_bt3c_cs(void) static void __exit exit_bt3c_cs(void)
{ {
pcmcia_unregister_driver(&bt3c_driver); pcmcia_unregister_driver(&bt3c_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_bt3c_cs); module_init(init_bt3c_cs);
......
...@@ -86,14 +86,8 @@ typedef struct btuart_info_t { ...@@ -86,14 +86,8 @@ typedef struct btuart_info_t {
static void btuart_config(dev_link_t *link); static void btuart_config(dev_link_t *link);
static void btuart_release(dev_link_t *link); static void btuart_release(dev_link_t *link);
static int btuart_event(event_t event, int priority, event_callback_args_t *args);
static dev_info_t dev_info = "btuart_cs"; static void btuart_detach(struct pcmcia_device *p_dev);
static dev_link_t *btuart_attach(void);
static void btuart_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
/* Maximum baud rate */ /* Maximum baud rate */
...@@ -582,17 +576,15 @@ static int btuart_close(btuart_info_t *info) ...@@ -582,17 +576,15 @@ static int btuart_close(btuart_info_t *info)
return 0; return 0;
} }
static dev_link_t *btuart_attach(void) static int btuart_attach(struct pcmcia_device *p_dev)
{ {
btuart_info_t *info; btuart_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
/* Create new info device */ /* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return -ENOMEM;
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
...@@ -609,50 +601,24 @@ static dev_link_t *btuart_attach(void) ...@@ -609,50 +601,24 @@ static dev_link_t *btuart_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
btuart_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
btuart_config(link);
return 0;
} }
static void btuart_detach(dev_link_t *link) static void btuart_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
btuart_info_t *info = link->priv; btuart_info_t *info = link->priv;
dev_link_t **linkp;
int ret;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
btuart_release(link); btuart_release(link);
if (link->handle) {
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
}
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(info); kfree(info);
} }
...@@ -811,43 +777,29 @@ static void btuart_release(dev_link_t *link) ...@@ -811,43 +777,29 @@ static void btuart_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int btuart_suspend(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
static int btuart_event(event_t event, int priority, event_callback_args_t *args) link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0;
}
static int btuart_resume(struct pcmcia_device *dev)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
btuart_info_t *info = link->priv;
switch (event) { link->state &= ~DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (DEV_OK(link))
link->state &= ~DEV_PRESENT; pcmcia_request_configuration(link->handle, &link->conf);
if (link->state & DEV_CONFIG) {
btuart_close(info);
btuart_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
btuart_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (DEV_OK(link))
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0; return 0;
} }
static struct pcmcia_device_id btuart_ids[] = { static struct pcmcia_device_id btuart_ids[] = {
/* don't use this driver. Use serial_cs + hci_uart instead */ /* don't use this driver. Use serial_cs + hci_uart instead */
PCMCIA_DEVICE_NULL PCMCIA_DEVICE_NULL
...@@ -859,10 +811,11 @@ static struct pcmcia_driver btuart_driver = { ...@@ -859,10 +811,11 @@ static struct pcmcia_driver btuart_driver = {
.drv = { .drv = {
.name = "btuart_cs", .name = "btuart_cs",
}, },
.attach = btuart_attach, .probe = btuart_attach,
.event = btuart_event, .remove = btuart_detach,
.detach = btuart_detach,
.id_table = btuart_ids, .id_table = btuart_ids,
.suspend = btuart_suspend,
.resume = btuart_resume,
}; };
static int __init init_btuart_cs(void) static int __init init_btuart_cs(void)
...@@ -874,7 +827,6 @@ static int __init init_btuart_cs(void) ...@@ -874,7 +827,6 @@ static int __init init_btuart_cs(void)
static void __exit exit_btuart_cs(void) static void __exit exit_btuart_cs(void)
{ {
pcmcia_unregister_driver(&btuart_driver); pcmcia_unregister_driver(&btuart_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_btuart_cs); module_init(init_btuart_cs);
......
...@@ -89,14 +89,8 @@ typedef struct dtl1_info_t { ...@@ -89,14 +89,8 @@ typedef struct dtl1_info_t {
static void dtl1_config(dev_link_t *link); static void dtl1_config(dev_link_t *link);
static void dtl1_release(dev_link_t *link); static void dtl1_release(dev_link_t *link);
static int dtl1_event(event_t event, int priority, event_callback_args_t *args);
static dev_info_t dev_info = "dtl1_cs"; static void dtl1_detach(struct pcmcia_device *p_dev);
static dev_link_t *dtl1_attach(void);
static void dtl1_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
/* Transmit states */ /* Transmit states */
...@@ -561,17 +555,15 @@ static int dtl1_close(dtl1_info_t *info) ...@@ -561,17 +555,15 @@ static int dtl1_close(dtl1_info_t *info)
return 0; return 0;
} }
static dev_link_t *dtl1_attach(void) static int dtl1_attach(struct pcmcia_device *p_dev)
{ {
dtl1_info_t *info; dtl1_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
/* Create new info device */ /* Create new info device */
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return -ENOMEM;
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
...@@ -588,50 +580,24 @@ static dev_link_t *dtl1_attach(void) ...@@ -588,50 +580,24 @@ static dev_link_t *dtl1_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
dtl1_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
dtl1_config(link);
return 0;
} }
static void dtl1_detach(dev_link_t *link) static void dtl1_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
dtl1_info_t *info = link->priv; dtl1_info_t *info = link->priv;
dev_link_t **linkp;
int ret;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
dtl1_release(link); dtl1_release(link);
if (link->handle) {
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
}
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(info); kfree(info);
} }
...@@ -763,46 +729,33 @@ static void dtl1_release(dev_link_t *link) ...@@ -763,46 +729,33 @@ static void dtl1_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int dtl1_suspend(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
static int dtl1_event(event_t event, int priority, event_callback_args_t *args) link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0;
}
static int dtl1_resume(struct pcmcia_device *dev)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
dtl1_info_t *info = link->priv;
switch (event) { link->state &= ~DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (DEV_OK(link))
link->state &= ~DEV_PRESENT; pcmcia_request_configuration(link->handle, &link->conf);
if (link->state & DEV_CONFIG) {
dtl1_close(info);
dtl1_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
dtl1_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (DEV_OK(link))
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0; return 0;
} }
static struct pcmcia_device_id dtl1_ids[] = { static struct pcmcia_device_id dtl1_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d),
PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863),
PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3),
PCMCIA_DEVICE_NULL PCMCIA_DEVICE_NULL
}; };
MODULE_DEVICE_TABLE(pcmcia, dtl1_ids); MODULE_DEVICE_TABLE(pcmcia, dtl1_ids);
...@@ -812,10 +765,11 @@ static struct pcmcia_driver dtl1_driver = { ...@@ -812,10 +765,11 @@ static struct pcmcia_driver dtl1_driver = {
.drv = { .drv = {
.name = "dtl1_cs", .name = "dtl1_cs",
}, },
.attach = dtl1_attach, .probe = dtl1_attach,
.event = dtl1_event, .remove = dtl1_detach,
.detach = dtl1_detach,
.id_table = dtl1_ids, .id_table = dtl1_ids,
.suspend = dtl1_suspend,
.resume = dtl1_resume,
}; };
static int __init init_dtl1_cs(void) static int __init init_dtl1_cs(void)
...@@ -827,7 +781,6 @@ static int __init init_dtl1_cs(void) ...@@ -827,7 +781,6 @@ static int __init init_dtl1_cs(void)
static void __exit exit_dtl1_cs(void) static void __exit exit_dtl1_cs(void)
{ {
pcmcia_unregister_driver(&dtl1_driver); pcmcia_unregister_driver(&dtl1_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_dtl1_cs); module_init(init_dtl1_cs);
......
...@@ -66,7 +66,6 @@ static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte"; ...@@ -66,7 +66,6 @@ static char *version = "cm4000_cs.c v2.4.0gm5 - All bugs added by Harald Welte";
#define T_100MSEC msecs_to_jiffies(100) #define T_100MSEC msecs_to_jiffies(100)
#define T_500MSEC msecs_to_jiffies(500) #define T_500MSEC msecs_to_jiffies(500)
static void cm4000_detach(dev_link_t *link);
static void cm4000_release(dev_link_t *link); static void cm4000_release(dev_link_t *link);
static int major; /* major number we get from the kernel */ static int major; /* major number we get from the kernel */
...@@ -156,7 +155,6 @@ struct cm4000_dev { ...@@ -156,7 +155,6 @@ struct cm4000_dev {
/*sbuf*/ 512*sizeof(char) - \ /*sbuf*/ 512*sizeof(char) - \
/*queue*/ 4*sizeof(wait_queue_head_t)) /*queue*/ 4*sizeof(wait_queue_head_t))
static dev_info_t dev_info = MODULE_NAME;
static dev_link_t *dev_table[CM4000_MAX_DEV]; static dev_link_t *dev_table[CM4000_MAX_DEV];
/* This table doesn't use spaces after the comma between fields and thus /* This table doesn't use spaces after the comma between fields and thus
...@@ -1864,68 +1862,36 @@ static void cm4000_config(dev_link_t * link, int devno) ...@@ -1864,68 +1862,36 @@ static void cm4000_config(dev_link_t * link, int devno)
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
} }
static int cm4000_event(event_t event, int priority, static int cm4000_suspend(struct pcmcia_device *p_dev)
event_callback_args_t *args)
{ {
dev_link_t *link; dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev; struct cm4000_dev *dev;
int devno;
link = args->client_data;
dev = link->priv; dev = link->priv;
DEBUGP(3, dev, "-> cm4000_event\n"); link->state |= DEV_SUSPEND;
for (devno = 0; devno < CM4000_MAX_DEV; devno++) if (link->state & DEV_CONFIG)
if (dev_table[devno] == link) pcmcia_release_configuration(link->handle);
break; stop_monitor(dev);
if (devno == CM4000_MAX_DEV) return 0;
return CS_BAD_ADAPTER; }
switch (event) { static int cm4000_resume(struct pcmcia_device *p_dev)
case CS_EVENT_CARD_INSERTION: {
DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n"); dev_link_t *link = dev_to_instance(p_dev);
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; struct cm4000_dev *dev;
cm4000_config(link, devno);
break; dev = link->priv;
case CS_EVENT_CARD_REMOVAL:
DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); link->state &= ~DEV_SUSPEND;
link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG)
stop_monitor(dev); pcmcia_request_configuration(link->handle, &link->conf);
break;
case CS_EVENT_PM_SUSPEND: if (link->open)
DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " start_monitor(dev);
"(fall-through to CS_EVENT_RESET_PHYSICAL)\n");
link->state |= DEV_SUSPEND; return 0;
/* fall-through */
case CS_EVENT_RESET_PHYSICAL:
DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG) {
DEBUGP(5, dev, "ReleaseConfiguration\n");
pcmcia_release_configuration(link->handle);
}
stop_monitor(dev);
break;
case CS_EVENT_PM_RESUME:
DEBUGP(5, dev, "CS_EVENT_PM_RESUME "
"(fall-through to CS_EVENT_CARD_RESET)\n");
link->state &= ~DEV_SUSPEND;
/* fall-through */
case CS_EVENT_CARD_RESET:
DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n");
if ((link->state & DEV_CONFIG)) {
DEBUGP(5, dev, "RequestConfiguration\n");
pcmcia_request_configuration(link->handle, &link->conf);
}
if (link->open)
start_monitor(dev);
break;
default:
DEBUGP(5, dev, "unknown event %.2x\n", event);
break;
}
DEBUGP(3, dev, "<- cm4000_event\n");
return CS_SUCCESS;
} }
static void cm4000_release(dev_link_t *link) static void cm4000_release(dev_link_t *link)
...@@ -1935,11 +1901,10 @@ static void cm4000_release(dev_link_t *link) ...@@ -1935,11 +1901,10 @@ static void cm4000_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io); pcmcia_release_io(link->handle, &link->io);
} }
static dev_link_t *cm4000_attach(void) static int cm4000_attach(struct pcmcia_device *p_dev)
{ {
struct cm4000_dev *dev; struct cm4000_dev *dev;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int i; int i;
for (i = 0; i < CM4000_MAX_DEV; i++) for (i = 0; i < CM4000_MAX_DEV; i++)
...@@ -1948,76 +1913,55 @@ static dev_link_t *cm4000_attach(void) ...@@ -1948,76 +1913,55 @@ static dev_link_t *cm4000_attach(void)
if (i == CM4000_MAX_DEV) { if (i == CM4000_MAX_DEV) {
printk(KERN_NOTICE MODULE_NAME ": all devices in use\n"); printk(KERN_NOTICE MODULE_NAME ": all devices in use\n");
return NULL; return -ENODEV;
} }
/* create a new cm4000_cs device */ /* create a new cm4000_cs device */
dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL); dev = kzalloc(sizeof(struct cm4000_dev), GFP_KERNEL);
if (dev == NULL) if (dev == NULL)
return NULL; return -ENOMEM;
link = &dev->link; link = &dev->link;
link->priv = dev; link->priv = dev;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link; dev_table[i] = link;
/* register with card services */
client_reg.dev_info = &dev_info;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
i = pcmcia_register_client(&link->handle, &client_reg);
if (i) {
cs_error(link->handle, RegisterClient, i);
cm4000_detach(link);
return NULL;
}
init_waitqueue_head(&dev->devq); init_waitqueue_head(&dev->devq);
init_waitqueue_head(&dev->ioq); init_waitqueue_head(&dev->ioq);
init_waitqueue_head(&dev->atrq); init_waitqueue_head(&dev->atrq);
init_waitqueue_head(&dev->readq); init_waitqueue_head(&dev->readq);
return link; link->handle = p_dev;
} p_dev->instance = link;
static void cm4000_detach_by_devno(int devno, dev_link_t * link)
{
struct cm4000_dev *dev = link->priv;
DEBUGP(3, dev, "-> detach_by_devno(devno=%d)\n", devno);
if (link->state & DEV_CONFIG) {
DEBUGP(5, dev, "device still configured (try to release it)\n");
cm4000_release(link);
}
if (link->handle) { link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
pcmcia_deregister_client(link->handle); cm4000_config(link, i);
}
dev_table[devno] = NULL; return 0;
kfree(dev);
return;
} }
static void cm4000_detach(dev_link_t * link) static void cm4000_detach(struct pcmcia_device *p_dev)
{ {
int i; dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev = link->priv;
int devno;
/* find device */ /* find device */
for (i = 0; i < CM4000_MAX_DEV; i++) for (devno = 0; devno < CM4000_MAX_DEV; devno++)
if (dev_table[i] == link) if (dev_table[devno] == link)
break; break;
if (devno == CM4000_MAX_DEV)
if (i == CM4000_MAX_DEV)
return; return;
cm4000_detach_by_devno(i, link); link->state &= ~DEV_PRESENT;
stop_monitor(dev);
if (link->state & DEV_CONFIG)
cm4000_release(link);
dev_table[devno] = NULL;
kfree(dev);
return; return;
} }
...@@ -2042,9 +1986,10 @@ static struct pcmcia_driver cm4000_driver = { ...@@ -2042,9 +1986,10 @@ static struct pcmcia_driver cm4000_driver = {
.drv = { .drv = {
.name = "cm4000_cs", .name = "cm4000_cs",
}, },
.attach = cm4000_attach, .probe = cm4000_attach,
.detach = cm4000_detach, .remove = cm4000_detach,
.event = cm4000_event, .suspend = cm4000_suspend,
.resume = cm4000_resume,
.id_table = cm4000_ids, .id_table = cm4000_ids,
}; };
...@@ -2064,13 +2009,8 @@ static int __init cmm_init(void) ...@@ -2064,13 +2009,8 @@ static int __init cmm_init(void)
static void __exit cmm_exit(void) static void __exit cmm_exit(void)
{ {
int i;
printk(KERN_INFO MODULE_NAME ": unloading\n"); printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&cm4000_driver); pcmcia_unregister_driver(&cm4000_driver);
for (i = 0; i < CM4000_MAX_DEV; i++)
if (dev_table[i])
cm4000_detach_by_devno(i, dev_table[i]);
unregister_chrdev(major, DEVICE_NAME); unregister_chrdev(major, DEVICE_NAME);
}; };
......
...@@ -65,7 +65,6 @@ static char *version = ...@@ -65,7 +65,6 @@ static char *version =
#define POLL_PERIOD msecs_to_jiffies(10) #define POLL_PERIOD msecs_to_jiffies(10)
static void reader_release(dev_link_t *link); static void reader_release(dev_link_t *link);
static void reader_detach(dev_link_t *link);
static int major; static int major;
...@@ -86,7 +85,6 @@ struct reader_dev { ...@@ -86,7 +85,6 @@ struct reader_dev {
struct timer_list poll_timer; struct timer_list poll_timer;
}; };
static dev_info_t dev_info = MODULE_NAME;
static dev_link_t *dev_table[CM_MAX_DEV]; static dev_link_t *dev_table[CM_MAX_DEV];
#ifndef PCMCIA_DEBUG #ifndef PCMCIA_DEBUG
...@@ -629,65 +627,26 @@ static void reader_config(dev_link_t *link, int devno) ...@@ -629,65 +627,26 @@ static void reader_config(dev_link_t *link, int devno)
link->state &= ~DEV_CONFIG_PENDING; link->state &= ~DEV_CONFIG_PENDING;
} }
static int reader_event(event_t event, int priority, static int reader_suspend(struct pcmcia_device *p_dev)
event_callback_args_t *args)
{ {
dev_link_t *link; dev_link_t *link = dev_to_instance(p_dev);
struct reader_dev *dev;
int devno;
link = args->client_data; link->state |= DEV_SUSPEND;
dev = link->priv; if (link->state & DEV_CONFIG)
DEBUGP(3, dev, "-> reader_event\n"); pcmcia_release_configuration(link->handle);
for (devno = 0; devno < CM_MAX_DEV; devno++) {
if (dev_table[devno] == link)
break;
}
if (devno == CM_MAX_DEV)
return CS_BAD_ADAPTER;
switch (event) { return 0;
case CS_EVENT_CARD_INSERTION: }
DEBUGP(5, dev, "CS_EVENT_CARD_INSERTION\n");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; static int reader_resume(struct pcmcia_device *p_dev)
reader_config(link, devno); {
break; dev_link_t *link = dev_to_instance(p_dev);
case CS_EVENT_CARD_REMOVAL:
DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n"); link->state &= ~DEV_SUSPEND;
link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG)
break; pcmcia_request_configuration(link->handle, &link->conf);
case CS_EVENT_PM_SUSPEND:
DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND " return 0;
"(fall-through to CS_EVENT_RESET_PHYSICAL)\n");
link->state |= DEV_SUSPEND;
case CS_EVENT_RESET_PHYSICAL:
DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG) {
DEBUGP(5, dev, "ReleaseConfiguration\n");
pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_PM_RESUME:
DEBUGP(5, dev, "CS_EVENT_PM_RESUME "
"(fall-through to CS_EVENT_CARD_RESET)\n");
link->state &= ~DEV_SUSPEND;
case CS_EVENT_CARD_RESET:
DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n");
if ((link->state & DEV_CONFIG)) {
DEBUGP(5, dev, "RequestConfiguration\n");
pcmcia_request_configuration(link->handle,
&link->conf);
}
break;
default:
DEBUGP(5, dev, "reader_event: unknown event %.2x\n",
event);
break;
}
DEBUGP(3, dev, "<- reader_event\n");
return CS_SUCCESS;
} }
static void reader_release(dev_link_t *link) static void reader_release(dev_link_t *link)
...@@ -697,11 +656,10 @@ static void reader_release(dev_link_t *link) ...@@ -697,11 +656,10 @@ static void reader_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io); pcmcia_release_io(link->handle, &link->io);
} }
static dev_link_t *reader_attach(void) static int reader_attach(struct pcmcia_device *p_dev)
{ {
struct reader_dev *dev; struct reader_dev *dev;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int i; int i;
for (i = 0; i < CM_MAX_DEV; i++) { for (i = 0; i < CM_MAX_DEV; i++) {
...@@ -710,11 +668,11 @@ static dev_link_t *reader_attach(void) ...@@ -710,11 +668,11 @@ static dev_link_t *reader_attach(void)
} }
if (i == CM_MAX_DEV) if (i == CM_MAX_DEV)
return NULL; return -ENODEV;
dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL); dev = kzalloc(sizeof(struct reader_dev), GFP_KERNEL);
if (dev == NULL) if (dev == NULL)
return NULL; return -ENOMEM;
dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT; dev->timeout = CCID_DRIVER_MINIMUM_TIMEOUT;
dev->buffer_status = 0; dev->buffer_status = 0;
...@@ -725,20 +683,6 @@ static dev_link_t *reader_attach(void) ...@@ -725,20 +683,6 @@ static dev_link_t *reader_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link; dev_table[i] = link;
client_reg.dev_info = &dev_info;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask=
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
i = pcmcia_register_client(&link->handle, &client_reg);
if (i) {
cs_error(link->handle, RegisterClient, i);
reader_detach(link);
return NULL;
}
init_waitqueue_head(&dev->devq); init_waitqueue_head(&dev->devq);
init_waitqueue_head(&dev->poll_wait); init_waitqueue_head(&dev->poll_wait);
init_waitqueue_head(&dev->read_wait); init_waitqueue_head(&dev->read_wait);
...@@ -746,39 +690,37 @@ static dev_link_t *reader_attach(void) ...@@ -746,39 +690,37 @@ static dev_link_t *reader_attach(void)
init_timer(&dev->poll_timer); init_timer(&dev->poll_timer);
dev->poll_timer.function = &cm4040_do_poll; dev->poll_timer.function = &cm4040_do_poll;
return link; link->handle = p_dev;
} p_dev->instance = link;
static void reader_detach_by_devno(int devno, dev_link_t *link)
{
struct reader_dev *dev = link->priv;
if (link->state & DEV_CONFIG) { link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
DEBUGP(5, dev, "device still configured (try to release it)\n"); reader_config(link, i);
reader_release(link);
}
pcmcia_deregister_client(link->handle); return 0;
dev_table[devno] = NULL;
DEBUGP(5, dev, "freeing dev=%p\n", dev);
cm4040_stop_poll(dev);
kfree(dev);
return;
} }
static void reader_detach(dev_link_t *link) static void reader_detach(struct pcmcia_device *p_dev)
{ {
int i; dev_link_t *link = dev_to_instance(p_dev);
struct reader_dev *dev = link->priv;
int devno;
/* find device */ /* find device */
for (i = 0; i < CM_MAX_DEV; i++) { for (devno = 0; devno < CM_MAX_DEV; devno++) {
if (dev_table[i] == link) if (dev_table[devno] == link)
break; break;
} }
if (i == CM_MAX_DEV) if (devno == CM_MAX_DEV)
return; return;
reader_detach_by_devno(i, link); link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
reader_release(link);
dev_table[devno] = NULL;
kfree(dev);
return; return;
} }
...@@ -804,9 +746,10 @@ static struct pcmcia_driver reader_driver = { ...@@ -804,9 +746,10 @@ static struct pcmcia_driver reader_driver = {
.drv = { .drv = {
.name = "cm4040_cs", .name = "cm4040_cs",
}, },
.attach = reader_attach, .probe = reader_attach,
.detach = reader_detach, .remove = reader_detach,
.event = reader_event, .suspend = reader_suspend,
.resume = reader_resume,
.id_table = cm4040_ids, .id_table = cm4040_ids,
}; };
...@@ -825,14 +768,8 @@ static int __init cm4040_init(void) ...@@ -825,14 +768,8 @@ static int __init cm4040_init(void)
static void __exit cm4040_exit(void) static void __exit cm4040_exit(void)
{ {
int i;
printk(KERN_INFO MODULE_NAME ": unloading\n"); printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&reader_driver); pcmcia_unregister_driver(&reader_driver);
for (i = 0; i < CM_MAX_DEV; i++) {
if (dev_table[i])
reader_detach_by_devno(i, dev_table[i]);
}
unregister_chrdev(major, DEVICE_NAME); unregister_chrdev(major, DEVICE_NAME);
} }
......
...@@ -486,13 +486,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout); ...@@ -486,13 +486,7 @@ static void mgslpc_wait_until_sent(struct tty_struct *tty, int timeout);
static void mgslpc_config(dev_link_t *link); static void mgslpc_config(dev_link_t *link);
static void mgslpc_release(u_long arg); static void mgslpc_release(u_long arg);
static int mgslpc_event(event_t event, int priority, static void mgslpc_detach(struct pcmcia_device *p_dev);
event_callback_args_t *args);
static dev_link_t *mgslpc_attach(void);
static void mgslpc_detach(dev_link_t *);
static dev_info_t dev_info = "synclink_cs";
static dev_link_t *dev_list = NULL;
/* /*
* 1st function defined in .text section. Calling this function in * 1st function defined in .text section. Calling this function in
...@@ -539,12 +533,10 @@ static void ldisc_receive_buf(struct tty_struct *tty, ...@@ -539,12 +533,10 @@ static void ldisc_receive_buf(struct tty_struct *tty,
} }
} }
static dev_link_t *mgslpc_attach(void) static int mgslpc_attach(struct pcmcia_device *p_dev)
{ {
MGSLPC_INFO *info; MGSLPC_INFO *info;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_attach\n"); printk("mgslpc_attach\n");
...@@ -552,7 +544,7 @@ static dev_link_t *mgslpc_attach(void) ...@@ -552,7 +544,7 @@ static dev_link_t *mgslpc_attach(void)
info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL); info = (MGSLPC_INFO *)kmalloc(sizeof(MGSLPC_INFO), GFP_KERNEL);
if (!info) { if (!info) {
printk("Error can't allocate device instance data\n"); printk("Error can't allocate device instance data\n");
return NULL; return -ENOMEM;
} }
memset(info, 0, sizeof(MGSLPC_INFO)); memset(info, 0, sizeof(MGSLPC_INFO));
...@@ -587,24 +579,15 @@ static dev_link_t *mgslpc_attach(void) ...@@ -587,24 +579,15 @@ static dev_link_t *mgslpc_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
if (ret != CS_SUCCESS) { mgslpc_config(link);
cs_error(link->handle, RegisterClient, ret);
mgslpc_detach(link);
return NULL;
}
mgslpc_add_device(info); mgslpc_add_device(info);
return link; return 0;
} }
/* Card has been inserted. /* Card has been inserted.
...@@ -736,85 +719,50 @@ static void mgslpc_release(u_long arg) ...@@ -736,85 +719,50 @@ static void mgslpc_release(u_long arg)
pcmcia_release_io(link->handle, &link->io); pcmcia_release_io(link->handle, &link->io);
if (link->irq.AssignedIRQ) if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq); pcmcia_release_irq(link->handle, &link->irq);
if (link->state & DEV_STALE_LINK)
mgslpc_detach(link);
} }
static void mgslpc_detach(dev_link_t *link) static void mgslpc_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
if (debug_level >= DEBUG_LEVEL_INFO) if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_detach(0x%p)\n", link); printk("mgslpc_detach(0x%p)\n", link);
/* find device */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
/* device is configured/active, mark it so when ((MGSLPC_INFO *)link->priv)->stop = 1;
* release() is called a proper detach() occurs. mgslpc_release((u_long)link);
*/
if (debug_level >= DEBUG_LEVEL_INFO)
printk(KERN_DEBUG "synclinkpc: detach postponed, '%s' "
"still locked\n", link->dev->dev_name);
link->state |= DEV_STALE_LINK;
return;
} }
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, and free it */
*linkp = link->next;
mgslpc_remove_device((MGSLPC_INFO *)link->priv); mgslpc_remove_device((MGSLPC_INFO *)link->priv);
} }
static int mgslpc_event(event_t event, int priority, static int mgslpc_suspend(struct pcmcia_device *dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
MGSLPC_INFO *info = link->priv; MGSLPC_INFO *info = link->priv;
if (debug_level >= DEBUG_LEVEL_INFO) link->state |= DEV_SUSPEND;
printk("mgslpc_event(0x%06x)\n", event); info->stop = 1;
if (link->state & DEV_CONFIG)
switch (event) { pcmcia_release_configuration(link->handle);
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT; return 0;
if (link->state & DEV_CONFIG) {
((MGSLPC_INFO *)link->priv)->stop = 1;
mgslpc_release((u_long)link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
mgslpc_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
/* Mark the device as stopped, to block IO until later */
info->stop = 1;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
info->stop = 0;
break;
}
return 0;
} }
static int mgslpc_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
MGSLPC_INFO *info = link->priv;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
info->stop = 0;
return 0;
}
static inline int mgslpc_paranoia_check(MGSLPC_INFO *info, static inline int mgslpc_paranoia_check(MGSLPC_INFO *info,
char *name, const char *routine) char *name, const char *routine)
{ {
...@@ -3091,10 +3039,11 @@ static struct pcmcia_driver mgslpc_driver = { ...@@ -3091,10 +3039,11 @@ static struct pcmcia_driver mgslpc_driver = {
.drv = { .drv = {
.name = "synclink_cs", .name = "synclink_cs",
}, },
.attach = mgslpc_attach, .probe = mgslpc_attach,
.event = mgslpc_event, .remove = mgslpc_detach,
.detach = mgslpc_detach,
.id_table = mgslpc_ids, .id_table = mgslpc_ids,
.suspend = mgslpc_suspend,
.resume = mgslpc_resume,
}; };
static struct tty_operations mgslpc_ops = { static struct tty_operations mgslpc_ops = {
...@@ -3138,7 +3087,6 @@ static void synclink_cs_cleanup(void) ...@@ -3138,7 +3087,6 @@ static void synclink_cs_cleanup(void)
} }
pcmcia_unregister_driver(&mgslpc_driver); pcmcia_unregister_driver(&mgslpc_driver);
BUG_ON(dev_list != NULL);
} }
static int __init synclink_cs_init(void) static int __init synclink_cs_init(void)
......
...@@ -88,15 +88,12 @@ typedef struct ide_info_t { ...@@ -88,15 +88,12 @@ typedef struct ide_info_t {
} ide_info_t; } ide_info_t;
static void ide_release(dev_link_t *); static void ide_release(dev_link_t *);
static int ide_event(event_t event, int priority, static void ide_config(dev_link_t *);
event_callback_args_t *args);
static void ide_detach(struct pcmcia_device *p_dev);
static dev_info_t dev_info = "ide-cs";
static dev_link_t *ide_attach(void);
static void ide_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
/*====================================================================== /*======================================================================
...@@ -106,18 +103,17 @@ static dev_link_t *dev_list = NULL; ...@@ -106,18 +103,17 @@ static dev_link_t *dev_list = NULL;
======================================================================*/ ======================================================================*/
static dev_link_t *ide_attach(void) static int ide_attach(struct pcmcia_device *p_dev)
{ {
ide_info_t *info; ide_info_t *info;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
DEBUG(0, "ide_attach()\n"); DEBUG(0, "ide_attach()\n");
/* Create new ide device */ /* Create new ide device */
info = kzalloc(sizeof(*info), GFP_KERNEL); info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) return NULL; if (!info)
return -ENOMEM;
link = &info->link; link->priv = info; link = &info->link; link->priv = info;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
...@@ -128,21 +124,14 @@ static dev_link_t *ide_attach(void) ...@@ -128,21 +124,14 @@ static dev_link_t *ide_attach(void)
link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; ide_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg); return 0;
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
ide_detach(link);
return NULL;
}
return link;
} /* ide_attach */ } /* ide_attach */
/*====================================================================== /*======================================================================
...@@ -154,32 +143,16 @@ static dev_link_t *ide_attach(void) ...@@ -154,32 +143,16 @@ static dev_link_t *ide_attach(void)
======================================================================*/ ======================================================================*/
static void ide_detach(dev_link_t *link) static void ide_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
int ret;
DEBUG(0, "ide_detach(0x%p)\n", link); DEBUG(0, "ide_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
ide_release(link); ide_release(link);
if (link->handle) {
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
}
/* Unlink, free device structure */
*linkp = link->next;
kfree(link->priv); kfree(link->priv);
} /* ide_detach */ } /* ide_detach */
static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
...@@ -406,6 +379,28 @@ void ide_release(dev_link_t *link) ...@@ -406,6 +379,28 @@ void ide_release(dev_link_t *link)
} /* ide_release */ } /* ide_release */
static int ide_suspend(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0;
}
static int ide_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
link->state &= ~DEV_SUSPEND;
if (DEV_OK(link))
pcmcia_request_configuration(link->handle, &link->conf);
return 0;
}
/*====================================================================== /*======================================================================
The card status event handler. Mostly, this schedules other The card status event handler. Mostly, this schedules other
...@@ -415,48 +410,15 @@ void ide_release(dev_link_t *link) ...@@ -415,48 +410,15 @@ void ide_release(dev_link_t *link)
======================================================================*/ ======================================================================*/
int ide_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
DEBUG(1, "ide_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
ide_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
ide_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (DEV_OK(link))
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0;
} /* ide_event */
static struct pcmcia_device_id ide_ids[] = { static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_FUNC_ID(4), PCMCIA_DEVICE_FUNC_ID(4),
PCMCIA_DEVICE_MANF_CARD(0x0007, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704), PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401), PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),
PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */ PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000), /* Toshiba */
PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d), PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */ PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000), /* Samsung */
PCMCIA_DEVICE_MANF_CARD(0x0319, 0x0000), /* Hitachi */
PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x2080, 0x0001),
PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */ PCMCIA_DEVICE_MANF_CARD(0x4e01, 0x0200), /* Lexar */
PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0), PCMCIA_DEVICE_PROD_ID123("Caravelle", "PSC-IDE ", "PSC000", 0x8c36137c, 0xd0693ab8, 0x2768a9f0),
...@@ -471,6 +433,8 @@ static struct pcmcia_device_id ide_ids[] = { ...@@ -471,6 +433,8 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591), PCMCIA_DEVICE_PROD_ID12("EXP ", "CD-ROM", 0x0a5c52fd, 0x66536591),
PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("EXP ", "PnPIDE", 0x0a5c52fd, 0x0c694728),
PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e), PCMCIA_DEVICE_PROD_ID12("FREECOM", "PCCARD-IDE", 0x5714cbf7, 0x48e0ab8e),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "FLASH", 0xf4f43949, 0x9eb86aae),
PCMCIA_DEVICE_PROD_ID12("HITACHI", "microdrive", 0xf4f43949, 0xa6d76178),
PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b),
PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149),
...@@ -494,10 +458,11 @@ static struct pcmcia_driver ide_cs_driver = { ...@@ -494,10 +458,11 @@ static struct pcmcia_driver ide_cs_driver = {
.drv = { .drv = {
.name = "ide-cs", .name = "ide-cs",
}, },
.attach = ide_attach, .probe = ide_attach,
.event = ide_event, .remove = ide_detach,
.detach = ide_detach,
.id_table = ide_ids, .id_table = ide_ids,
.suspend = ide_suspend,
.resume = ide_resume,
}; };
static int __init init_ide_cs(void) static int __init init_ide_cs(void)
...@@ -508,7 +473,6 @@ static int __init init_ide_cs(void) ...@@ -508,7 +473,6 @@ static int __init init_ide_cs(void)
static void __exit exit_ide_cs(void) static void __exit exit_ide_cs(void)
{ {
pcmcia_unregister_driver(&ide_cs_driver); pcmcia_unregister_driver(&ide_cs_driver);
BUG_ON(dev_list != NULL);
} }
late_initcall(init_ide_cs); late_initcall(init_ide_cs);
......
...@@ -53,8 +53,6 @@ MODULE_LICENSE("GPL"); ...@@ -53,8 +53,6 @@ MODULE_LICENSE("GPL");
static void avmcs_config(dev_link_t *link); static void avmcs_config(dev_link_t *link);
static void avmcs_release(dev_link_t *link); static void avmcs_release(dev_link_t *link);
static int avmcs_event(event_t event, int priority,
event_callback_args_t *args);
/* /*
The attach() and detach() entry points are used to create and destroy The attach() and detach() entry points are used to create and destroy
...@@ -62,16 +60,7 @@ static int avmcs_event(event_t event, int priority, ...@@ -62,16 +60,7 @@ static int avmcs_event(event_t event, int priority,
needed to manage one actual PCMCIA card. needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *avmcs_attach(void); static void avmcs_detach(struct pcmcia_device *p_dev);
static void avmcs_detach(dev_link_t *);
/*
The dev_info variable is the "key" that is used to match up this
device driver with appropriate cards, through the card configuration
database.
*/
static dev_info_t dev_info = "avm_cs";
/* /*
A linked list of "instances" of the skeleton device. Each actual A linked list of "instances" of the skeleton device. Each actual
...@@ -83,15 +72,7 @@ static dev_info_t dev_info = "avm_cs"; ...@@ -83,15 +72,7 @@ static dev_info_t dev_info = "avm_cs";
device numbers are used to derive the corresponding array index. device numbers are used to derive the corresponding array index.
*/ */
static dev_link_t *dev_list = NULL;
/* /*
A dev_link_t structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
'priv' pointer in a dev_link_t structure can be used to point to
a device-specific private data structure, like this.
A driver needs to provide a dev_node_t structure for each device A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be example, ethernet cards, modems). In other cases, there may be
...@@ -118,13 +99,11 @@ typedef struct local_info_t { ...@@ -118,13 +99,11 @@ typedef struct local_info_t {
======================================================================*/ ======================================================================*/
static dev_link_t *avmcs_attach(void) static int avmcs_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
local_info_t *local; local_info_t *local;
int ret;
/* Initialize the dev_link_t structure */ /* Initialize the dev_link_t structure */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) if (!link)
...@@ -155,25 +134,19 @@ static dev_link_t *avmcs_attach(void) ...@@ -155,25 +134,19 @@ static dev_link_t *avmcs_attach(void)
goto err_kfree; goto err_kfree;
memset(local, 0, sizeof(local_info_t)); memset(local, 0, sizeof(local_info_t));
link->priv = local; link->priv = local;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; avmcs_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg); return 0;
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
avmcs_detach(link);
goto err;
}
return link;
err_kfree: err_kfree:
kfree(link); kfree(link);
err: err:
return NULL; return -EINVAL;
} /* avmcs_attach */ } /* avmcs_attach */
/*====================================================================== /*======================================================================
...@@ -185,33 +158,13 @@ static dev_link_t *avmcs_attach(void) ...@@ -185,33 +158,13 @@ static dev_link_t *avmcs_attach(void)
======================================================================*/ ======================================================================*/
static void avmcs_detach(dev_link_t *link) static void avmcs_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
/* if (link->state & DEV_CONFIG)
If the device is currently configured and active, we won't avmcs_release(link);
actually delete it yet. Instead, it is marked so that when
the release() function is called, that will trigger a proper
detach().
*/
if (link->state & DEV_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free pieces */
*linkp = link->next;
kfree(link->priv); kfree(link->priv);
kfree(link); kfree(link);
} /* avmcs_detach */ } /* avmcs_detach */
...@@ -424,12 +377,30 @@ static void avmcs_release(dev_link_t *link) ...@@ -424,12 +377,30 @@ static void avmcs_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io); pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq); pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK)
avmcs_detach(link);
} /* avmcs_release */ } /* avmcs_release */
static int avmcs_suspend(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0;
}
static int avmcs_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
return 0;
}
/*====================================================================== /*======================================================================
The card status event handler. Mostly, this schedules other The card status event handler. Mostly, this schedules other
...@@ -444,38 +415,6 @@ static void avmcs_release(dev_link_t *link) ...@@ -444,38 +415,6 @@ static void avmcs_release(dev_link_t *link)
======================================================================*/ ======================================================================*/
static int avmcs_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
avmcs_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
avmcs_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0;
} /* avmcs_event */
static struct pcmcia_device_id avmcs_ids[] = { static struct pcmcia_device_id avmcs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335), PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN-Controller B1", 0x95d42008, 0x845dc335),
...@@ -490,10 +429,11 @@ static struct pcmcia_driver avmcs_driver = { ...@@ -490,10 +429,11 @@ static struct pcmcia_driver avmcs_driver = {
.drv = { .drv = {
.name = "avm_cs", .name = "avm_cs",
}, },
.attach = avmcs_attach, .probe = avmcs_attach,
.event = avmcs_event, .remove = avmcs_detach,
.detach = avmcs_detach,
.id_table = avmcs_ids, .id_table = avmcs_ids,
.suspend= avmcs_suspend,
.resume = avmcs_resume,
}; };
static int __init avmcs_init(void) static int __init avmcs_init(void)
...@@ -504,7 +444,6 @@ static int __init avmcs_init(void) ...@@ -504,7 +444,6 @@ static int __init avmcs_init(void)
static void __exit avmcs_exit(void) static void __exit avmcs_exit(void)
{ {
pcmcia_unregister_driver(&avmcs_driver); pcmcia_unregister_driver(&avmcs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(avmcs_init); module_init(avmcs_init);
......
...@@ -69,8 +69,6 @@ module_param(isdnprot, int, 0); ...@@ -69,8 +69,6 @@ module_param(isdnprot, int, 0);
static void avma1cs_config(dev_link_t *link); static void avma1cs_config(dev_link_t *link);
static void avma1cs_release(dev_link_t *link); static void avma1cs_release(dev_link_t *link);
static int avma1cs_event(event_t event, int priority,
event_callback_args_t *args);
/* /*
The attach() and detach() entry points are used to create and destroy The attach() and detach() entry points are used to create and destroy
...@@ -78,16 +76,8 @@ static int avma1cs_event(event_t event, int priority, ...@@ -78,16 +76,8 @@ static int avma1cs_event(event_t event, int priority,
needed to manage one actual PCMCIA card. needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *avma1cs_attach(void); static void avma1cs_detach(struct pcmcia_device *p_dev);
static void avma1cs_detach(dev_link_t *);
/*
The dev_info variable is the "key" that is used to match up this
device driver with appropriate cards, through the card configuration
database.
*/
static dev_info_t dev_info = "avma1_cs";
/* /*
A linked list of "instances" of the skeleton device. Each actual A linked list of "instances" of the skeleton device. Each actual
...@@ -99,15 +89,7 @@ static dev_info_t dev_info = "avma1_cs"; ...@@ -99,15 +89,7 @@ static dev_info_t dev_info = "avma1_cs";
device numbers are used to derive the corresponding array index. device numbers are used to derive the corresponding array index.
*/ */
static dev_link_t *dev_list = NULL;
/* /*
A dev_link_t structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
'priv' pointer in a dev_link_t structure can be used to point to
a device-specific private data structure, like this.
A driver needs to provide a dev_node_t structure for each device A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be example, ethernet cards, modems). In other cases, there may be
...@@ -134,26 +116,24 @@ typedef struct local_info_t { ...@@ -134,26 +116,24 @@ typedef struct local_info_t {
======================================================================*/ ======================================================================*/
static dev_link_t *avma1cs_attach(void) static int avma1cs_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
local_info_t *local; local_info_t *local;
int ret;
DEBUG(0, "avma1cs_attach()\n"); DEBUG(0, "avma1cs_attach()\n");
/* Initialize the dev_link_t structure */ /* Initialize the dev_link_t structure */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) if (!link)
return NULL; return -ENOMEM;
memset(link, 0, sizeof(struct dev_link_t)); memset(link, 0, sizeof(struct dev_link_t));
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL); local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) { if (!local) {
kfree(link); kfree(link);
return NULL; return -ENOMEM;
} }
memset(local, 0, sizeof(local_info_t)); memset(local, 0, sizeof(local_info_t));
link->priv = local; link->priv = local;
...@@ -178,20 +158,13 @@ static dev_link_t *avma1cs_attach(void) ...@@ -178,20 +158,13 @@ static dev_link_t *avma1cs_attach(void)
link->conf.ConfigIndex = 1; link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION; link->conf.Present = PRESENT_OPTION;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
avma1cs_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
avma1cs_config(link);
return 0;
} /* avma1cs_attach */ } /* avma1cs_attach */
/*====================================================================== /*======================================================================
...@@ -203,42 +176,17 @@ static dev_link_t *avma1cs_attach(void) ...@@ -203,42 +176,17 @@ static dev_link_t *avma1cs_attach(void)
======================================================================*/ ======================================================================*/
static void avma1cs_detach(dev_link_t *link) static void avma1cs_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "avma1cs_detach(0x%p)\n", link); DEBUG(0, "avma1cs_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
/* if (link->state & DEV_CONFIG)
If the device is currently configured and active, we won't avma1cs_release(link);
actually delete it yet. Instead, it is marked so that when
the release() function is called, that will trigger a proper
detach().
*/
if (link->state & DEV_CONFIG) {
#ifdef PCMCIA_DEBUG
printk(KERN_DEBUG "avma1_cs: detach postponed, '%s' "
"still locked\n", link->dev->dev_name);
#endif
link->state |= DEV_STALE_LINK;
return;
}
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free pieces */
*linkp = link->next;
kfree(link->priv); kfree(link->priv);
kfree(link); kfree(link);
} /* avma1cs_detach */ } /* avma1cs_detach */
/*====================================================================== /*======================================================================
...@@ -440,58 +388,30 @@ static void avma1cs_release(dev_link_t *link) ...@@ -440,58 +388,30 @@ static void avma1cs_release(dev_link_t *link)
pcmcia_release_io(link->handle, &link->io); pcmcia_release_io(link->handle, &link->io);
pcmcia_release_irq(link->handle, &link->irq); pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK)
avma1cs_detach(link);
} /* avma1cs_release */ } /* avma1cs_release */
/*====================================================================== static int avma1cs_suspend(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
The card status event handler. Mostly, this schedules other link->state |= DEV_SUSPEND;
stuff to run after an event is received. A CARD_REMOVAL event if (link->state & DEV_CONFIG)
also sets some flags to discourage the net drivers from trying pcmcia_release_configuration(link->handle);
to talk to the card any more.
When a CARD_REMOVAL event is received, we immediately set a flag return 0;
to block future accesses to this device. All the functions that }
actually access the device should check this flag to make sure
the card is still present.
======================================================================*/
static int avma1cs_event(event_t event, int priority, static int avma1cs_resume(struct pcmcia_device *dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
DEBUG(1, "avma1cs_event(0x%06x)\n", event); link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG)
switch (event) {
case CS_EVENT_CARD_REMOVAL:
if (link->state & DEV_CONFIG)
avma1cs_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
avma1cs_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
break;
} return 0;
return 0; }
} /* avma1cs_event */
static struct pcmcia_device_id avma1cs_ids[] = { static struct pcmcia_device_id avma1cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb), PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
...@@ -505,10 +425,11 @@ static struct pcmcia_driver avma1cs_driver = { ...@@ -505,10 +425,11 @@ static struct pcmcia_driver avma1cs_driver = {
.drv = { .drv = {
.name = "avma1_cs", .name = "avma1_cs",
}, },
.attach = avma1cs_attach, .probe = avma1cs_attach,
.event = avma1cs_event, .remove = avma1cs_detach,
.detach = avma1cs_detach,
.id_table = avma1cs_ids, .id_table = avma1cs_ids,
.suspend = avma1cs_suspend,
.resume = avma1cs_resume,
}; };
/*====================================================================*/ /*====================================================================*/
...@@ -521,7 +442,6 @@ static int __init init_avma1_cs(void) ...@@ -521,7 +442,6 @@ static int __init init_avma1_cs(void)
static void __exit exit_avma1_cs(void) static void __exit exit_avma1_cs(void)
{ {
pcmcia_unregister_driver(&avma1cs_driver); pcmcia_unregister_driver(&avma1cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_avma1_cs); module_init(init_avma1_cs);
......
...@@ -96,8 +96,6 @@ module_param(protocol, int, 0); ...@@ -96,8 +96,6 @@ module_param(protocol, int, 0);
static void elsa_cs_config(dev_link_t *link); static void elsa_cs_config(dev_link_t *link);
static void elsa_cs_release(dev_link_t *link); static void elsa_cs_release(dev_link_t *link);
static int elsa_cs_event(event_t event, int priority,
event_callback_args_t *args);
/* /*
The attach() and detach() entry points are used to create and destroy The attach() and detach() entry points are used to create and destroy
...@@ -105,39 +103,9 @@ static int elsa_cs_event(event_t event, int priority, ...@@ -105,39 +103,9 @@ static int elsa_cs_event(event_t event, int priority,
needed to manage one actual PCMCIA card. needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *elsa_cs_attach(void); static void elsa_cs_detach(struct pcmcia_device *p_dev);
static void elsa_cs_detach(dev_link_t *);
/* /*
The dev_info variable is the "key" that is used to match up this
device driver with appropriate cards, through the card configuration
database.
*/
static dev_info_t dev_info = "elsa_cs";
/*
A linked list of "instances" of the elsa_cs device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
memory card driver uses an array of dev_link_t pointers, where minor
device numbers are used to derive the corresponding array index.
*/
static dev_link_t *dev_list = NULL;
/*
A dev_link_t structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
'priv' pointer in a dev_link_t structure can be used to point to
a device-specific private data structure, like this.
To simplify the data structure handling, we actually include the
dev_link_t structure in the device's private data structure.
A driver needs to provide a dev_node_t structure for each device A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be example, ethernet cards, modems). In other cases, there may be
...@@ -171,18 +139,16 @@ typedef struct local_info_t { ...@@ -171,18 +139,16 @@ typedef struct local_info_t {
======================================================================*/ ======================================================================*/
static dev_link_t *elsa_cs_attach(void) static int elsa_cs_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
local_info_t *local; local_info_t *local;
int ret;
DEBUG(0, "elsa_cs_attach()\n"); DEBUG(0, "elsa_cs_attach()\n");
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL); local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return NULL; if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t)); memset(local, 0, sizeof(local_info_t));
local->cardnr = -1; local->cardnr = -1;
link = &local->link; link->priv = local; link = &local->link; link->priv = local;
...@@ -207,20 +173,13 @@ static dev_link_t *elsa_cs_attach(void) ...@@ -207,20 +173,13 @@ static dev_link_t *elsa_cs_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
elsa_cs_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
elsa_cs_config(link);
return 0;
} /* elsa_cs_attach */ } /* elsa_cs_attach */
/*====================================================================== /*======================================================================
...@@ -232,32 +191,18 @@ static dev_link_t *elsa_cs_attach(void) ...@@ -232,32 +191,18 @@ static dev_link_t *elsa_cs_attach(void)
======================================================================*/ ======================================================================*/
static void elsa_cs_detach(dev_link_t *link) static void elsa_cs_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
local_info_t *info = link->priv; local_info_t *info = link->priv;
int ret;
DEBUG(0, "elsa_cs_detach(0x%p)\n", link); DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
/* Locate device structure */ if (link->state & DEV_CONFIG) {
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) info->busy = 1;
if (*linkp == link) break; elsa_cs_release(link);
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG)
elsa_cs_release(link);
/* Break the link with Card Services */
if (link->handle) {
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
} }
/* Unlink device structure and free it */
*linkp = link->next;
kfree(info); kfree(info);
} /* elsa_cs_detach */ } /* elsa_cs_detach */
...@@ -447,60 +392,31 @@ static void elsa_cs_release(dev_link_t *link) ...@@ -447,60 +392,31 @@ static void elsa_cs_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} /* elsa_cs_release */ } /* elsa_cs_release */
/*====================================================================== static int elsa_suspend(struct pcmcia_device *p_dev)
{
The card status event handler. Mostly, this schedules other dev_link_t *link = dev_to_instance(p_dev);
stuff to run after an event is received. A CARD_REMOVAL event local_info_t *dev = link->priv;
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
When a CARD_REMOVAL event is received, we immediately set a flag link->state |= DEV_SUSPEND;
to block future accesses to this device. All the functions that dev->busy = 1;
actually access the device should check this flag to make sure if (link->state & DEV_CONFIG)
the card is still present. pcmcia_release_configuration(link->handle);
======================================================================*/ return 0;
}
static int elsa_cs_event(event_t event, int priority, static int elsa_resume(struct pcmcia_device *p_dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv; local_info_t *dev = link->priv;
DEBUG(1, "elsa_cs_event(%d)\n", event);
switch (event) { link->state &= ~DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG)
link->state &= ~DEV_PRESENT; pcmcia_request_configuration(link->handle, &link->conf);
if (link->state & DEV_CONFIG) {
((local_info_t*)link->priv)->busy = 1;
elsa_cs_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
elsa_cs_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
/* Mark the device as stopped, to block IO until later */
dev->busy = 1;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0; dev->busy = 0;
break;
} return 0;
return 0; }
} /* elsa_cs_event */
static struct pcmcia_device_id elsa_ids[] = { static struct pcmcia_device_id elsa_ids[] = {
PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257), PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257),
...@@ -514,10 +430,11 @@ static struct pcmcia_driver elsa_cs_driver = { ...@@ -514,10 +430,11 @@ static struct pcmcia_driver elsa_cs_driver = {
.drv = { .drv = {
.name = "elsa_cs", .name = "elsa_cs",
}, },
.attach = elsa_cs_attach, .probe = elsa_cs_attach,
.event = elsa_cs_event, .remove = elsa_cs_detach,
.detach = elsa_cs_detach,
.id_table = elsa_ids, .id_table = elsa_ids,
.suspend = elsa_suspend,
.resume = elsa_resume,
}; };
static int __init init_elsa_cs(void) static int __init init_elsa_cs(void)
...@@ -528,7 +445,6 @@ static int __init init_elsa_cs(void) ...@@ -528,7 +445,6 @@ static int __init init_elsa_cs(void)
static void __exit exit_elsa_cs(void) static void __exit exit_elsa_cs(void)
{ {
pcmcia_unregister_driver(&elsa_cs_driver); pcmcia_unregister_driver(&elsa_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_elsa_cs); module_init(init_elsa_cs);
......
...@@ -97,8 +97,6 @@ module_param(protocol, int, 0); ...@@ -97,8 +97,6 @@ module_param(protocol, int, 0);
static void sedlbauer_config(dev_link_t *link); static void sedlbauer_config(dev_link_t *link);
static void sedlbauer_release(dev_link_t *link); static void sedlbauer_release(dev_link_t *link);
static int sedlbauer_event(event_t event, int priority,
event_callback_args_t *args);
/* /*
The attach() and detach() entry points are used to create and destroy The attach() and detach() entry points are used to create and destroy
...@@ -106,8 +104,7 @@ static int sedlbauer_event(event_t event, int priority, ...@@ -106,8 +104,7 @@ static int sedlbauer_event(event_t event, int priority,
needed to manage one actual PCMCIA card. needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *sedlbauer_attach(void); static void sedlbauer_detach(struct pcmcia_device *p_dev);
static void sedlbauer_detach(dev_link_t *);
/* /*
You'll also need to prototype all the functions that will actually You'll also need to prototype all the functions that will actually
...@@ -117,35 +114,6 @@ static void sedlbauer_detach(dev_link_t *); ...@@ -117,35 +114,6 @@ static void sedlbauer_detach(dev_link_t *);
*/ */
/* /*
The dev_info variable is the "key" that is used to match up this
device driver with appropriate cards, through the card configuration
database.
*/
static dev_info_t dev_info = "sedlbauer_cs";
/*
A linked list of "instances" of the sedlbauer device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
memory card driver uses an array of dev_link_t pointers, where minor
device numbers are used to derive the corresponding array index.
*/
static dev_link_t *dev_list = NULL;
/*
A dev_link_t structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
'priv' pointer in a dev_link_t structure can be used to point to
a device-specific private data structure, like this.
To simplify the data structure handling, we actually include the
dev_link_t structure in the device's private data structure.
A driver needs to provide a dev_node_t structure for each device A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be example, ethernet cards, modems). In other cases, there may be
...@@ -180,18 +148,16 @@ typedef struct local_info_t { ...@@ -180,18 +148,16 @@ typedef struct local_info_t {
======================================================================*/ ======================================================================*/
static dev_link_t *sedlbauer_attach(void) static int sedlbauer_attach(struct pcmcia_device *p_dev)
{ {
local_info_t *local; local_info_t *local;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
DEBUG(0, "sedlbauer_attach()\n"); DEBUG(0, "sedlbauer_attach()\n");
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL); local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return NULL; if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t)); memset(local, 0, sizeof(local_info_t));
local->cardnr = -1; local->cardnr = -1;
link = &local->link; link->priv = local; link = &local->link; link->priv = local;
...@@ -221,20 +187,13 @@ static dev_link_t *sedlbauer_attach(void) ...@@ -221,20 +187,13 @@ static dev_link_t *sedlbauer_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; sedlbauer_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
sedlbauer_detach(link);
return NULL;
}
return link; return 0;
} /* sedlbauer_attach */ } /* sedlbauer_attach */
/*====================================================================== /*======================================================================
...@@ -246,39 +205,17 @@ static dev_link_t *sedlbauer_attach(void) ...@@ -246,39 +205,17 @@ static dev_link_t *sedlbauer_attach(void)
======================================================================*/ ======================================================================*/
static void sedlbauer_detach(dev_link_t *link) static void sedlbauer_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "sedlbauer_detach(0x%p)\n", link); DEBUG(0, "sedlbauer_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
/*
If the device is currently configured and active, we won't
actually delete it yet. Instead, it is marked so that when
the release() function is called, that will trigger a proper
detach().
*/
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
#ifdef PCMCIA_DEBUG ((local_info_t *)link->priv)->stop = 1;
printk(KERN_DEBUG "sedlbauer_cs: detach postponed, '%s' " sedlbauer_release(link);
"still locked\n", link->dev->dev_name);
#endif
link->state |= DEV_STALE_LINK;
return;
} }
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, and free it */
*linkp = link->next;
/* This points to the parent local_info_t struct */ /* This points to the parent local_info_t struct */
kfree(link->priv); kfree(link->priv);
} /* sedlbauer_detach */ } /* sedlbauer_detach */
...@@ -547,68 +484,34 @@ static void sedlbauer_release(dev_link_t *link) ...@@ -547,68 +484,34 @@ static void sedlbauer_release(dev_link_t *link)
if (link->irq.AssignedIRQ) if (link->irq.AssignedIRQ)
pcmcia_release_irq(link->handle, &link->irq); pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK)
sedlbauer_detach(link);
} /* sedlbauer_release */ } /* sedlbauer_release */
/*====================================================================== static int sedlbauer_suspend(struct pcmcia_device *p_dev)
The card status event handler. Mostly, this schedules other
stuff to run after an event is received.
When a CARD_REMOVAL event is received, we immediately set a
private flag to block future accesses to this device. All the
functions that actually access the device should check this flag
to make sure the card is still present.
======================================================================*/
static int sedlbauer_event(event_t event, int priority,
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv; local_info_t *dev = link->priv;
DEBUG(1, "sedlbauer_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
((local_info_t *)link->priv)->stop = 1;
sedlbauer_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
sedlbauer_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND; link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
/* Mark the device as stopped, to block IO until later */
dev->stop = 1; dev->stop = 1;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME: return 0;
}
static int sedlbauer_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
dev->stop = 0; dev->stop = 0;
/*
In a normal driver, additional code may go here to restore return 0;
the device state and restart IO. }
*/
break;
}
return 0;
} /* sedlbauer_event */
static struct pcmcia_device_id sedlbauer_ids[] = { static struct pcmcia_device_id sedlbauer_ids[] = {
PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a), PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
...@@ -627,10 +530,11 @@ static struct pcmcia_driver sedlbauer_driver = { ...@@ -627,10 +530,11 @@ static struct pcmcia_driver sedlbauer_driver = {
.drv = { .drv = {
.name = "sedlbauer_cs", .name = "sedlbauer_cs",
}, },
.attach = sedlbauer_attach, .probe = sedlbauer_attach,
.event = sedlbauer_event, .remove = sedlbauer_detach,
.detach = sedlbauer_detach,
.id_table = sedlbauer_ids, .id_table = sedlbauer_ids,
.suspend = sedlbauer_suspend,
.resume = sedlbauer_resume,
}; };
static int __init init_sedlbauer_cs(void) static int __init init_sedlbauer_cs(void)
...@@ -641,7 +545,6 @@ static int __init init_sedlbauer_cs(void) ...@@ -641,7 +545,6 @@ static int __init init_sedlbauer_cs(void)
static void __exit exit_sedlbauer_cs(void) static void __exit exit_sedlbauer_cs(void)
{ {
pcmcia_unregister_driver(&sedlbauer_driver); pcmcia_unregister_driver(&sedlbauer_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_sedlbauer_cs); module_init(init_sedlbauer_cs);
......
...@@ -77,8 +77,6 @@ module_param(protocol, int, 0); ...@@ -77,8 +77,6 @@ module_param(protocol, int, 0);
static void teles_cs_config(dev_link_t *link); static void teles_cs_config(dev_link_t *link);
static void teles_cs_release(dev_link_t *link); static void teles_cs_release(dev_link_t *link);
static int teles_cs_event(event_t event, int priority,
event_callback_args_t *args);
/* /*
The attach() and detach() entry points are used to create and destroy The attach() and detach() entry points are used to create and destroy
...@@ -86,16 +84,7 @@ static int teles_cs_event(event_t event, int priority, ...@@ -86,16 +84,7 @@ static int teles_cs_event(event_t event, int priority,
needed to manage one actual PCMCIA card. needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *teles_attach(void); static void teles_detach(struct pcmcia_device *p_dev);
static void teles_detach(dev_link_t *);
/*
The dev_info variable is the "key" that is used to match up this
device driver with appropriate cards, through the card configuration
database.
*/
static dev_info_t dev_info = "teles_cs";
/* /*
A linked list of "instances" of the teles_cs device. Each actual A linked list of "instances" of the teles_cs device. Each actual
...@@ -107,18 +96,7 @@ static dev_info_t dev_info = "teles_cs"; ...@@ -107,18 +96,7 @@ static dev_info_t dev_info = "teles_cs";
device numbers are used to derive the corresponding array index. device numbers are used to derive the corresponding array index.
*/ */
static dev_link_t *dev_list = NULL;
/* /*
A dev_link_t structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
'priv' pointer in a dev_link_t structure can be used to point to
a device-specific private data structure, like this.
To simplify the data structure handling, we actually include the
dev_link_t structure in the device's private data structure.
A driver needs to provide a dev_node_t structure for each device A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be example, ethernet cards, modems). In other cases, there may be
...@@ -152,18 +130,16 @@ typedef struct local_info_t { ...@@ -152,18 +130,16 @@ typedef struct local_info_t {
======================================================================*/ ======================================================================*/
static dev_link_t *teles_attach(void) static int teles_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
local_info_t *local; local_info_t *local;
int ret;
DEBUG(0, "teles_attach()\n"); DEBUG(0, "teles_attach()\n");
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL); local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) return NULL; if (!local) return -ENOMEM;
memset(local, 0, sizeof(local_info_t)); memset(local, 0, sizeof(local_info_t));
local->cardnr = -1; local->cardnr = -1;
link = &local->link; link->priv = local; link = &local->link; link->priv = local;
...@@ -188,20 +164,13 @@ static dev_link_t *teles_attach(void) ...@@ -188,20 +164,13 @@ static dev_link_t *teles_attach(void)
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; teles_cs_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
teles_detach(link);
return NULL;
}
return link; return 0;
} /* teles_attach */ } /* teles_attach */
/*====================================================================== /*======================================================================
...@@ -213,32 +182,18 @@ static dev_link_t *teles_attach(void) ...@@ -213,32 +182,18 @@ static dev_link_t *teles_attach(void)
======================================================================*/ ======================================================================*/
static void teles_detach(dev_link_t *link) static void teles_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
local_info_t *info = link->priv; local_info_t *info = link->priv;
int ret;
DEBUG(0, "teles_detach(0x%p)\n", link); DEBUG(0, "teles_detach(0x%p)\n", link);
/* Locate device structure */ if (link->state & DEV_CONFIG) {
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) info->busy = 1;
if (*linkp == link) break; teles_cs_release(link);
if (*linkp == NULL)
return;
if (link->state & DEV_CONFIG)
teles_cs_release(link);
/* Break the link with Card Services */
if (link->handle) {
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
} }
/* Unlink device structure and free it */
*linkp = link->next;
kfree(info); kfree(info);
} /* teles_detach */ } /* teles_detach */
...@@ -428,60 +383,32 @@ static void teles_cs_release(dev_link_t *link) ...@@ -428,60 +383,32 @@ static void teles_cs_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} /* teles_cs_release */ } /* teles_cs_release */
/*====================================================================== static int teles_suspend(struct pcmcia_device *p_dev)
{
The card status event handler. Mostly, this schedules other dev_link_t *link = dev_to_instance(p_dev);
stuff to run after an event is received. A CARD_REMOVAL event local_info_t *dev = link->priv;
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
When a CARD_REMOVAL event is received, we immediately set a flag link->state |= DEV_SUSPEND;
to block future accesses to this device. All the functions that dev->busy = 1;
actually access the device should check this flag to make sure if (link->state & DEV_CONFIG)
the card is still present. pcmcia_release_configuration(link->handle);
======================================================================*/ return 0;
}
static int teles_cs_event(event_t event, int priority, static int teles_resume(struct pcmcia_device *p_dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv; local_info_t *dev = link->priv;
DEBUG(1, "teles_cs_event(%d)\n", event);
switch (event) { link->state &= ~DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG)
link->state &= ~DEV_PRESENT; pcmcia_request_configuration(link->handle, &link->conf);
if (link->state & DEV_CONFIG) {
((local_info_t*)link->priv)->busy = 1;
teles_cs_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
teles_cs_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
/* Mark the device as stopped, to block IO until later */
dev->busy = 1;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
dev->busy = 0; dev->busy = 0;
break;
} return 0;
return 0; }
} /* teles_cs_event */
static struct pcmcia_device_id teles_ids[] = { static struct pcmcia_device_id teles_ids[] = {
PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119), PCMCIA_DEVICE_PROD_ID12("TELES", "S0/PC", 0x67b50eae, 0xe9e70119),
...@@ -494,10 +421,11 @@ static struct pcmcia_driver teles_cs_driver = { ...@@ -494,10 +421,11 @@ static struct pcmcia_driver teles_cs_driver = {
.drv = { .drv = {
.name = "teles_cs", .name = "teles_cs",
}, },
.attach = teles_attach, .probe = teles_attach,
.event = teles_cs_event, .remove = teles_detach,
.detach = teles_detach,
.id_table = teles_ids, .id_table = teles_ids,
.suspend = teles_suspend,
.resume = teles_resume,
}; };
static int __init init_teles_cs(void) static int __init init_teles_cs(void)
...@@ -508,7 +436,6 @@ static int __init init_teles_cs(void) ...@@ -508,7 +436,6 @@ static int __init init_teles_cs(void)
static void __exit exit_teles_cs(void) static void __exit exit_teles_cs(void)
{ {
pcmcia_unregister_driver(&teles_cs_driver); pcmcia_unregister_driver(&teles_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_teles_cs); module_init(init_teles_cs);
......
...@@ -66,9 +66,6 @@ struct pcmciamtd_dev { ...@@ -66,9 +66,6 @@ struct pcmciamtd_dev {
}; };
static dev_info_t dev_info = "pcmciamtd";
static dev_link_t *dev_list;
/* Module parameters */ /* Module parameters */
/* 2 = do 16-bit transfers, 1 = do 8-bit transfers */ /* 2 = do 16-bit transfers, 1 = do 8-bit transfers */
...@@ -691,55 +688,21 @@ static void pcmciamtd_config(dev_link_t *link) ...@@ -691,55 +688,21 @@ static void pcmciamtd_config(dev_link_t *link)
} }
/* The card status event handler. Mostly, this schedules other static int pcmciamtd_suspend(struct pcmcia_device *dev)
* stuff to run after an event is received. A CARD_REMOVAL event {
* also sets some flags to discourage the driver from trying DEBUG(2, "EVENT_PM_RESUME");
* to talk to the card any more.
*/ /* get_lock(link); */
return 0;
}
static int pcmciamtd_event(event_t event, int priority, static int pcmciamtd_resume(struct pcmcia_device *dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; DEBUG(2, "EVENT_PM_SUSPEND");
DEBUG(1, "event=0x%06x", event); /* free_lock(link); */
switch (event) {
case CS_EVENT_CARD_REMOVAL:
DEBUG(2, "EVENT_CARD_REMOVAL");
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
struct pcmciamtd_dev *dev = link->priv;
if(dev->mtd_info) {
del_mtd_device(dev->mtd_info);
info("mtd%d: Removed", dev->mtd_info->index);
}
pcmciamtd_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
DEBUG(2, "EVENT_CARD_INSERTION");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
pcmciamtd_config(link);
break;
case CS_EVENT_PM_SUSPEND:
DEBUG(2, "EVENT_PM_SUSPEND");
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
DEBUG(2, "EVENT_RESET_PHYSICAL");
/* get_lock(link); */
break;
case CS_EVENT_PM_RESUME:
DEBUG(2, "EVENT_PM_RESUME");
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
DEBUG(2, "EVENT_CARD_RESET");
/* free_lock(link); */
break;
default:
DEBUG(2, "Unknown event %d", event);
}
return 0; return 0;
} }
...@@ -750,23 +713,21 @@ static int pcmciamtd_event(event_t event, int priority, ...@@ -750,23 +713,21 @@ static int pcmciamtd_event(event_t event, int priority,
* when the device is released. * when the device is released.
*/ */
static void pcmciamtd_detach(dev_link_t *link) static void pcmciamtd_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
DEBUG(3, "link=0x%p", link); DEBUG(3, "link=0x%p", link);
if(link->state & DEV_CONFIG) { if(link->state & DEV_CONFIG) {
pcmciamtd_release(link); struct pcmciamtd_dev *dev = link->priv;
} if(dev->mtd_info) {
del_mtd_device(dev->mtd_info);
info("mtd%d: Removed", dev->mtd_info->index);
}
if (link->handle) { pcmciamtd_release(link);
int ret;
DEBUG(2, "Deregistering with card services");
ret = pcmcia_deregister_client(link->handle);
if (ret != CS_SUCCESS)
cs_error(link->handle, DeregisterClient, ret);
} }
link->state |= DEV_STALE_LINK;
} }
...@@ -775,16 +736,14 @@ static void pcmciamtd_detach(dev_link_t *link) ...@@ -775,16 +736,14 @@ static void pcmciamtd_detach(dev_link_t *link)
* with Card Services. * with Card Services.
*/ */
static dev_link_t *pcmciamtd_attach(void) static int pcmciamtd_attach(struct pcmcia_device *p_dev)
{ {
struct pcmciamtd_dev *dev; struct pcmciamtd_dev *dev;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
/* Create new memory card device */ /* Create new memory card device */
dev = kmalloc(sizeof(*dev), GFP_KERNEL); dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) return NULL; if (!dev) return -ENOMEM;
DEBUG(1, "dev=0x%p", dev); DEBUG(1, "dev=0x%p", dev);
memset(dev, 0, sizeof(*dev)); memset(dev, 0, sizeof(*dev));
...@@ -794,22 +753,14 @@ static dev_link_t *pcmciamtd_attach(void) ...@@ -794,22 +753,14 @@ static dev_link_t *pcmciamtd_attach(void)
link->conf.Attributes = 0; link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY; link->conf.IntType = INT_MEMORY;
link->next = dev_list; link->next = NULL;
dev_list = link; link->handle = p_dev;
p_dev->instance = link;
/* Register with Card Services */
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; pcmciamtd_config(link);
client_reg.event_callback_args.client_data = link;
DEBUG(2, "Calling RegisterClient"); return 0;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
pcmciamtd_detach(link);
return NULL;
}
DEBUG(2, "link = %p", link);
return link;
} }
static struct pcmcia_device_id pcmciamtd_ids[] = { static struct pcmcia_device_id pcmciamtd_ids[] = {
...@@ -843,11 +794,12 @@ static struct pcmcia_driver pcmciamtd_driver = { ...@@ -843,11 +794,12 @@ static struct pcmcia_driver pcmciamtd_driver = {
.drv = { .drv = {
.name = "pcmciamtd" .name = "pcmciamtd"
}, },
.attach = pcmciamtd_attach, .probe = pcmciamtd_attach,
.event = pcmciamtd_event, .remove = pcmciamtd_detach,
.detach = pcmciamtd_detach,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id_table = pcmciamtd_ids, .id_table = pcmciamtd_ids,
.suspend = pcmciamtd_suspend,
.resume = pcmciamtd_resume,
}; };
...@@ -875,7 +827,6 @@ static void __exit exit_pcmciamtd(void) ...@@ -875,7 +827,6 @@ static void __exit exit_pcmciamtd(void)
{ {
DEBUG(1, DRIVER_DESC " unloading"); DEBUG(1, DRIVER_DESC " unloading");
pcmcia_unregister_driver(&pcmciamtd_driver); pcmcia_unregister_driver(&pcmciamtd_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_pcmciamtd); module_init(init_pcmciamtd);
......
...@@ -227,8 +227,6 @@ static char mii_preamble_required = 0; ...@@ -227,8 +227,6 @@ static char mii_preamble_required = 0;
static void tc574_config(dev_link_t *link); static void tc574_config(dev_link_t *link);
static void tc574_release(dev_link_t *link); static void tc574_release(dev_link_t *link);
static int tc574_event(event_t event, int priority,
event_callback_args_t *args);
static void mdio_sync(kio_addr_t ioaddr, int bits); static void mdio_sync(kio_addr_t ioaddr, int bits);
static int mdio_read(kio_addr_t ioaddr, int phy_id, int location); static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
...@@ -250,12 +248,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); ...@@ -250,12 +248,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static struct ethtool_ops netdev_ethtool_ops; static struct ethtool_ops netdev_ethtool_ops;
static void set_rx_mode(struct net_device *dev); static void set_rx_mode(struct net_device *dev);
static dev_info_t dev_info = "3c574_cs"; static void tc574_detach(struct pcmcia_device *p_dev);
static dev_link_t *tc574_attach(void);
static void tc574_detach(dev_link_t *);
static dev_link_t *dev_list;
/* /*
tc574_attach() creates an "instance" of the driver, allocating tc574_attach() creates an "instance" of the driver, allocating
...@@ -263,20 +256,18 @@ static dev_link_t *dev_list; ...@@ -263,20 +256,18 @@ static dev_link_t *dev_list;
with Card Services. with Card Services.
*/ */
static dev_link_t *tc574_attach(void) static int tc574_attach(struct pcmcia_device *p_dev)
{ {
struct el3_private *lp; struct el3_private *lp;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
int ret;
DEBUG(0, "3c574_attach()\n"); DEBUG(0, "3c574_attach()\n");
/* Create the PC card device object. */ /* Create the PC card device object. */
dev = alloc_etherdev(sizeof(struct el3_private)); dev = alloc_etherdev(sizeof(struct el3_private));
if (!dev) if (!dev)
return NULL; return -ENOMEM;
lp = netdev_priv(dev); lp = netdev_priv(dev);
link = &lp->link; link = &lp->link;
link->priv = dev; link->priv = dev;
...@@ -307,20 +298,13 @@ static dev_link_t *tc574_attach(void) ...@@ -307,20 +298,13 @@ static dev_link_t *tc574_attach(void)
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
#endif #endif
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
tc574_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
tc574_config(link);
return 0;
} /* tc574_attach */ } /* tc574_attach */
/* /*
...@@ -332,30 +316,19 @@ static dev_link_t *tc574_attach(void) ...@@ -332,30 +316,19 @@ static dev_link_t *tc574_attach(void)
*/ */
static void tc574_detach(dev_link_t *link) static void tc574_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "3c574_detach(0x%p)\n", link); DEBUG(0, "3c574_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
tc574_release(link); tc574_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
} /* tc574_detach */ } /* tc574_detach */
...@@ -547,56 +520,37 @@ static void tc574_release(dev_link_t *link) ...@@ -547,56 +520,37 @@ static void tc574_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/* static int tc574_suspend(struct pcmcia_device *p_dev)
The card status event handler. Mostly, this schedules other
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
*/
static int tc574_event(event_t event, int priority,
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
DEBUG(1, "3c574_event(0x%06x)\n", event); link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
switch (event) { if (link->open)
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
netif_device_detach(dev); netif_device_detach(dev);
break; pcmcia_release_configuration(link->handle);
case CS_EVENT_CARD_INSERTION: }
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
tc574_config(link); return 0;
break; }
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND; static int tc574_resume(struct pcmcia_device *p_dev)
/* Fall through... */ {
case CS_EVENT_RESET_PHYSICAL: dev_link_t *link = dev_to_instance(p_dev);
if (link->state & DEV_CONFIG) { struct net_device *dev = link->priv;
if (link->open)
netif_device_detach(dev); link->state &= ~DEV_SUSPEND;
pcmcia_release_configuration(link->handle); if (link->state & DEV_CONFIG) {
} pcmcia_request_configuration(link->handle, &link->conf);
break; if (link->open) {
case CS_EVENT_PM_RESUME: tc574_reset(dev);
link->state &= ~DEV_SUSPEND; netif_device_attach(dev);
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
tc574_reset(dev);
netif_device_attach(dev);
}
} }
break;
} }
return 0; return 0;
} /* tc574_event */ }
static void dump_status(struct net_device *dev) static void dump_status(struct net_device *dev)
{ {
...@@ -1292,10 +1246,11 @@ static struct pcmcia_driver tc574_driver = { ...@@ -1292,10 +1246,11 @@ static struct pcmcia_driver tc574_driver = {
.drv = { .drv = {
.name = "3c574_cs", .name = "3c574_cs",
}, },
.attach = tc574_attach, .probe = tc574_attach,
.event = tc574_event, .remove = tc574_detach,
.detach = tc574_detach,
.id_table = tc574_ids, .id_table = tc574_ids,
.suspend = tc574_suspend,
.resume = tc574_resume,
}; };
static int __init init_tc574(void) static int __init init_tc574(void)
...@@ -1306,7 +1261,6 @@ static int __init init_tc574(void) ...@@ -1306,7 +1261,6 @@ static int __init init_tc574(void)
static void __exit exit_tc574(void) static void __exit exit_tc574(void)
{ {
pcmcia_unregister_driver(&tc574_driver); pcmcia_unregister_driver(&tc574_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_tc574); module_init(init_tc574);
......
...@@ -143,8 +143,6 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; ...@@ -143,8 +143,6 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
static void tc589_config(dev_link_t *link); static void tc589_config(dev_link_t *link);
static void tc589_release(dev_link_t *link); static void tc589_release(dev_link_t *link);
static int tc589_event(event_t event, int priority,
event_callback_args_t *args);
static u16 read_eeprom(kio_addr_t ioaddr, int index); static u16 read_eeprom(kio_addr_t ioaddr, int index);
static void tc589_reset(struct net_device *dev); static void tc589_reset(struct net_device *dev);
...@@ -161,12 +159,7 @@ static void el3_tx_timeout(struct net_device *dev); ...@@ -161,12 +159,7 @@ static void el3_tx_timeout(struct net_device *dev);
static void set_multicast_list(struct net_device *dev); static void set_multicast_list(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops; static struct ethtool_ops netdev_ethtool_ops;
static dev_info_t dev_info = "3c589_cs"; static void tc589_detach(struct pcmcia_device *p_dev);
static dev_link_t *tc589_attach(void);
static void tc589_detach(dev_link_t *);
static dev_link_t *dev_list;
/*====================================================================== /*======================================================================
...@@ -176,20 +169,18 @@ static dev_link_t *dev_list; ...@@ -176,20 +169,18 @@ static dev_link_t *dev_list;
======================================================================*/ ======================================================================*/
static dev_link_t *tc589_attach(void) static int tc589_attach(struct pcmcia_device *p_dev)
{ {
struct el3_private *lp; struct el3_private *lp;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
int ret;
DEBUG(0, "3c589_attach()\n"); DEBUG(0, "3c589_attach()\n");
/* Create new ethernet device */ /* Create new ethernet device */
dev = alloc_etherdev(sizeof(struct el3_private)); dev = alloc_etherdev(sizeof(struct el3_private));
if (!dev) if (!dev)
return NULL; return -ENOMEM;
lp = netdev_priv(dev); lp = netdev_priv(dev);
link = &lp->link; link = &lp->link;
link->priv = dev; link->priv = dev;
...@@ -206,7 +197,7 @@ static dev_link_t *tc589_attach(void) ...@@ -206,7 +197,7 @@ static dev_link_t *tc589_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1; link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION; link->conf.Present = PRESENT_OPTION;
/* The EL3-specific entries in the device structure. */ /* The EL3-specific entries in the device structure. */
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
dev->hard_start_xmit = &el3_start_xmit; dev->hard_start_xmit = &el3_start_xmit;
...@@ -221,20 +212,13 @@ static dev_link_t *tc589_attach(void) ...@@ -221,20 +212,13 @@ static dev_link_t *tc589_attach(void)
#endif #endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; tc589_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg); return 0;
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
tc589_detach(link);
return NULL;
}
return link;
} /* tc589_attach */ } /* tc589_attach */
/*====================================================================== /*======================================================================
...@@ -246,30 +230,19 @@ static dev_link_t *tc589_attach(void) ...@@ -246,30 +230,19 @@ static dev_link_t *tc589_attach(void)
======================================================================*/ ======================================================================*/
static void tc589_detach(dev_link_t *link) static void tc589_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "3c589_detach(0x%p)\n", link); DEBUG(0, "3c589_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
tc589_release(link); tc589_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
} /* tc589_detach */ } /* tc589_detach */
...@@ -421,58 +394,37 @@ static void tc589_release(dev_link_t *link) ...@@ -421,58 +394,37 @@ static void tc589_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*====================================================================== static int tc589_suspend(struct pcmcia_device *p_dev)
The card status event handler. Mostly, this schedules other
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
======================================================================*/
static int tc589_event(event_t event, int priority,
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
DEBUG(1, "3c589_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
netif_device_detach(dev);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
tc589_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND; link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
if (link->open) if (link->open)
netif_device_detach(dev); netif_device_detach(dev);
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
} }
break;
case CS_EVENT_PM_RESUME: return 0;
}
static int tc589_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) { if (link->open) {
tc589_reset(dev); tc589_reset(dev);
netif_device_attach(dev); netif_device_attach(dev);
} }
} }
break;
} return 0;
return 0; }
} /* tc589_event */
/*====================================================================*/ /*====================================================================*/
...@@ -1067,10 +1019,11 @@ static struct pcmcia_driver tc589_driver = { ...@@ -1067,10 +1019,11 @@ static struct pcmcia_driver tc589_driver = {
.drv = { .drv = {
.name = "3c589_cs", .name = "3c589_cs",
}, },
.attach = tc589_attach, .probe = tc589_attach,
.event = tc589_event, .remove = tc589_detach,
.detach = tc589_detach,
.id_table = tc589_ids, .id_table = tc589_ids,
.suspend = tc589_suspend,
.resume = tc589_resume,
}; };
static int __init init_tc589(void) static int __init init_tc589(void)
...@@ -1081,7 +1034,6 @@ static int __init init_tc589(void) ...@@ -1081,7 +1034,6 @@ static int __init init_tc589(void)
static void __exit exit_tc589(void) static void __exit exit_tc589(void)
{ {
pcmcia_unregister_driver(&tc589_driver); pcmcia_unregister_driver(&tc589_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_tc589); module_init(init_tc589);
......
...@@ -87,8 +87,6 @@ static char *version = ...@@ -87,8 +87,6 @@ static char *version =
static void axnet_config(dev_link_t *link); static void axnet_config(dev_link_t *link);
static void axnet_release(dev_link_t *link); static void axnet_release(dev_link_t *link);
static int axnet_event(event_t event, int priority,
event_callback_args_t *args);
static int axnet_open(struct net_device *dev); static int axnet_open(struct net_device *dev);
static int axnet_close(struct net_device *dev); static int axnet_close(struct net_device *dev);
static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
...@@ -107,11 +105,7 @@ static void block_input(struct net_device *dev, int count, ...@@ -107,11 +105,7 @@ static void block_input(struct net_device *dev, int count,
static void block_output(struct net_device *dev, int count, static void block_output(struct net_device *dev, int count,
const u_char *buf, const int start_page); const u_char *buf, const int start_page);
static dev_link_t *axnet_attach(void); static void axnet_detach(struct pcmcia_device *p_dev);
static void axnet_detach(dev_link_t *);
static dev_info_t dev_info = "axnet_cs";
static dev_link_t *dev_list;
static void axdev_setup(struct net_device *dev); static void axdev_setup(struct net_device *dev);
static void AX88190_init(struct net_device *dev, int startp); static void AX88190_init(struct net_device *dev, int startp);
...@@ -147,13 +141,11 @@ static inline axnet_dev_t *PRIV(struct net_device *dev) ...@@ -147,13 +141,11 @@ static inline axnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/ ======================================================================*/
static dev_link_t *axnet_attach(void) static int axnet_attach(struct pcmcia_device *p_dev)
{ {
axnet_dev_t *info; axnet_dev_t *info;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
client_reg_t client_reg;
int ret;
DEBUG(0, "axnet_attach()\n"); DEBUG(0, "axnet_attach()\n");
...@@ -161,7 +153,7 @@ static dev_link_t *axnet_attach(void) ...@@ -161,7 +153,7 @@ static dev_link_t *axnet_attach(void)
"eth%d", axdev_setup); "eth%d", axdev_setup);
if (!dev) if (!dev)
return NULL; return -ENOMEM;
info = PRIV(dev); info = PRIV(dev);
link = &info->link; link = &info->link;
...@@ -176,20 +168,13 @@ static dev_link_t *axnet_attach(void) ...@@ -176,20 +168,13 @@ static dev_link_t *axnet_attach(void)
dev->do_ioctl = &axnet_ioctl; dev->do_ioctl = &axnet_ioctl;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
axnet_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
axnet_config(link);
return 0;
} /* axnet_attach */ } /* axnet_attach */
/*====================================================================== /*======================================================================
...@@ -201,30 +186,19 @@ static dev_link_t *axnet_attach(void) ...@@ -201,30 +186,19 @@ static dev_link_t *axnet_attach(void)
======================================================================*/ ======================================================================*/
static void axnet_detach(dev_link_t *link) static void axnet_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "axnet_detach(0x%p)\n", link); DEBUG(0, "axnet_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
axnet_release(link); axnet_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
} /* axnet_detach */ } /* axnet_detach */
...@@ -490,59 +464,39 @@ static void axnet_release(dev_link_t *link) ...@@ -490,59 +464,39 @@ static void axnet_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*====================================================================== static int axnet_suspend(struct pcmcia_device *p_dev)
The card status event handler. Mostly, this schedules other
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
======================================================================*/
static int axnet_event(event_t event, int priority,
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
DEBUG(2, "axnet_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
netif_device_detach(dev);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
axnet_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND; link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
if (link->open) if (link->open)
netif_device_detach(dev); netif_device_detach(dev);
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
} }
break;
case CS_EVENT_PM_RESUME: return 0;
}
static int axnet_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) { if (link->open) {
axnet_reset_8390(dev); axnet_reset_8390(dev);
AX88190_init(dev, 1); AX88190_init(dev, 1);
netif_device_attach(dev); netif_device_attach(dev);
} }
} }
break;
} return 0;
return 0; }
} /* axnet_event */
/*====================================================================== /*======================================================================
...@@ -616,7 +570,7 @@ static int axnet_open(struct net_device *dev) ...@@ -616,7 +570,7 @@ static int axnet_open(struct net_device *dev)
link->open++; link->open++;
request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, dev_info, dev); request_irq(dev->irq, ei_irq_wrapper, SA_SHIRQ, "axnet_cs", dev);
info->link_status = 0x00; info->link_status = 0x00;
init_timer(&info->watchdog); init_timer(&info->watchdog);
...@@ -877,10 +831,11 @@ static struct pcmcia_driver axnet_cs_driver = { ...@@ -877,10 +831,11 @@ static struct pcmcia_driver axnet_cs_driver = {
.drv = { .drv = {
.name = "axnet_cs", .name = "axnet_cs",
}, },
.attach = axnet_attach, .probe = axnet_attach,
.event = axnet_event, .remove = axnet_detach,
.detach = axnet_detach,
.id_table = axnet_ids, .id_table = axnet_ids,
.suspend = axnet_suspend,
.resume = axnet_resume,
}; };
static int __init init_axnet_cs(void) static int __init init_axnet_cs(void)
...@@ -891,7 +846,6 @@ static int __init init_axnet_cs(void) ...@@ -891,7 +846,6 @@ static int __init init_axnet_cs(void)
static void __exit exit_axnet_cs(void) static void __exit exit_axnet_cs(void)
{ {
pcmcia_unregister_driver(&axnet_cs_driver); pcmcia_unregister_driver(&axnet_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_axnet_cs); module_init(init_axnet_cs);
......
...@@ -120,15 +120,8 @@ MODULE_LICENSE("GPL"); ...@@ -120,15 +120,8 @@ MODULE_LICENSE("GPL");
static void com20020_config(dev_link_t *link); static void com20020_config(dev_link_t *link);
static void com20020_release(dev_link_t *link); static void com20020_release(dev_link_t *link);
static int com20020_event(event_t event, int priority,
event_callback_args_t *args);
static dev_info_t dev_info = "com20020_cs"; static void com20020_detach(struct pcmcia_device *p_dev);
static dev_link_t *com20020_attach(void);
static void com20020_detach(dev_link_t *);
static dev_link_t *dev_list;
/*====================================================================*/ /*====================================================================*/
...@@ -145,21 +138,19 @@ typedef struct com20020_dev_t { ...@@ -145,21 +138,19 @@ typedef struct com20020_dev_t {
======================================================================*/ ======================================================================*/
static dev_link_t *com20020_attach(void) static int com20020_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
com20020_dev_t *info; com20020_dev_t *info;
struct net_device *dev; struct net_device *dev;
int ret;
struct arcnet_local *lp; struct arcnet_local *lp;
DEBUG(0, "com20020_attach()\n"); DEBUG(0, "com20020_attach()\n");
/* Create new network device */ /* Create new network device */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) if (!link)
return NULL; return -ENOMEM;
info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); info = kmalloc(sizeof(struct com20020_dev_t), GFP_KERNEL);
if (!info) if (!info)
...@@ -191,30 +182,19 @@ static dev_link_t *com20020_attach(void) ...@@ -191,30 +182,19 @@ static dev_link_t *com20020_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.Present = PRESENT_OPTION; link->conf.Present = PRESENT_OPTION;
link->irq.Instance = info->dev = dev; link->irq.Instance = info->dev = dev;
link->priv = info; link->priv = info;
/* Register with Card Services */ link->state |= DEV_PRESENT;
link->next = dev_list; com20020_config(link);
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
com20020_detach(link);
return NULL;
}
return link; return 0;
fail_alloc_dev: fail_alloc_dev:
kfree(info); kfree(info);
fail_alloc_info: fail_alloc_info:
kfree(link); kfree(link);
return NULL; return -ENOMEM;
} /* com20020_attach */ } /* com20020_attach */
/*====================================================================== /*======================================================================
...@@ -226,29 +206,21 @@ static dev_link_t *com20020_attach(void) ...@@ -226,29 +206,21 @@ static dev_link_t *com20020_attach(void)
======================================================================*/ ======================================================================*/
static void com20020_detach(dev_link_t *link) static void com20020_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct com20020_dev_t *info = link->priv; struct com20020_dev_t *info = link->priv;
dev_link_t **linkp; struct net_device *dev = info->dev;
struct net_device *dev;
DEBUG(1,"detach...\n"); DEBUG(1,"detach...\n");
DEBUG(0, "com20020_detach(0x%p)\n", link); DEBUG(0, "com20020_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
dev = info->dev;
if (link->dev) { if (link->dev) {
DEBUG(1,"unregister...\n"); DEBUG(1,"unregister...\n");
unregister_netdev(dev); unregister_netdev(dev);
/* /*
* this is necessary because we register our IRQ separately * this is necessary because we register our IRQ separately
* from card services. * from card services.
...@@ -260,12 +232,8 @@ static void com20020_detach(dev_link_t *link) ...@@ -260,12 +232,8 @@ static void com20020_detach(dev_link_t *link)
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
com20020_release(link); com20020_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */ /* Unlink device structure, free bits */
DEBUG(1,"unlinking...\n"); DEBUG(1,"unlinking...\n");
*linkp = link->next;
if (link->priv) if (link->priv)
{ {
dev = info->dev; dev = info->dev;
...@@ -421,61 +389,41 @@ static void com20020_release(dev_link_t *link) ...@@ -421,61 +389,41 @@ static void com20020_release(dev_link_t *link)
link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
} }
/*====================================================================== static int com20020_suspend(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev;
The card status event handler. Mostly, this schedules other link->state |= DEV_SUSPEND;
stuff to run after an event is received. A CARD_REMOVAL event if (link->state & DEV_CONFIG) {
also sets some flags to discourage the net drivers from trying if (link->open) {
to talk to the card any more. netif_device_detach(dev);
}
pcmcia_release_configuration(link->handle);
}
======================================================================*/ return 0;
}
static int com20020_event(event_t event, int priority, static int com20020_resume(struct pcmcia_device *p_dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
com20020_dev_t *info = link->priv; com20020_dev_t *info = link->priv;
struct net_device *dev = info->dev; struct net_device *dev = info->dev;
DEBUG(1, "com20020_event(0x%06x)\n", event); link->state &= ~DEV_SUSPEND;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
netif_device_detach(dev);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT;
com20020_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
if (link->open) {
netif_device_detach(dev);
}
pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) { if (link->open) {
int ioaddr = dev->base_addr; int ioaddr = dev->base_addr;
struct arcnet_local *lp = dev->priv; struct arcnet_local *lp = dev->priv;
ARCRESET; ARCRESET;
} }
} }
break;
} return 0;
return 0; }
} /* com20020_event */
static struct pcmcia_device_id com20020_ids[] = { static struct pcmcia_device_id com20020_ids[] = {
PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
...@@ -488,10 +436,11 @@ static struct pcmcia_driver com20020_cs_driver = { ...@@ -488,10 +436,11 @@ static struct pcmcia_driver com20020_cs_driver = {
.drv = { .drv = {
.name = "com20020_cs", .name = "com20020_cs",
}, },
.attach = com20020_attach, .probe = com20020_attach,
.event = com20020_event, .remove = com20020_detach,
.detach = com20020_detach,
.id_table = com20020_ids, .id_table = com20020_ids,
.suspend = com20020_suspend,
.resume = com20020_resume,
}; };
static int __init init_com20020_cs(void) static int __init init_com20020_cs(void)
...@@ -502,7 +451,6 @@ static int __init init_com20020_cs(void) ...@@ -502,7 +451,6 @@ static int __init init_com20020_cs(void)
static void __exit exit_com20020_cs(void) static void __exit exit_com20020_cs(void)
{ {
pcmcia_unregister_driver(&com20020_cs_driver); pcmcia_unregister_driver(&com20020_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_com20020_cs); module_init(init_com20020_cs);
......
...@@ -88,10 +88,7 @@ static void fmvj18x_config(dev_link_t *link); ...@@ -88,10 +88,7 @@ static void fmvj18x_config(dev_link_t *link);
static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id); static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
static int fmvj18x_setup_mfc(dev_link_t *link); static int fmvj18x_setup_mfc(dev_link_t *link);
static void fmvj18x_release(dev_link_t *link); static void fmvj18x_release(dev_link_t *link);
static int fmvj18x_event(event_t event, int priority, static void fmvj18x_detach(struct pcmcia_device *p_dev);
event_callback_args_t *args);
static dev_link_t *fmvj18x_attach(void);
static void fmvj18x_detach(dev_link_t *);
/* /*
LAN controller(MBH86960A) specific routines LAN controller(MBH86960A) specific routines
...@@ -108,9 +105,6 @@ static void set_rx_mode(struct net_device *dev); ...@@ -108,9 +105,6 @@ static void set_rx_mode(struct net_device *dev);
static void fjn_tx_timeout(struct net_device *dev); static void fjn_tx_timeout(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops; static struct ethtool_ops netdev_ethtool_ops;
static dev_info_t dev_info = "fmvj18x_cs";
static dev_link_t *dev_list;
/* /*
card type card type
*/ */
...@@ -234,20 +228,18 @@ typedef struct local_info_t { ...@@ -234,20 +228,18 @@ typedef struct local_info_t {
#define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */
#define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */
static dev_link_t *fmvj18x_attach(void) static int fmvj18x_attach(struct pcmcia_device *p_dev)
{ {
local_info_t *lp; local_info_t *lp;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
client_reg_t client_reg;
int ret;
DEBUG(0, "fmvj18x_attach()\n"); DEBUG(0, "fmvj18x_attach()\n");
/* Make up a FMVJ18x specific data structure */ /* Make up a FMVJ18x specific data structure */
dev = alloc_etherdev(sizeof(local_info_t)); dev = alloc_etherdev(sizeof(local_info_t));
if (!dev) if (!dev)
return NULL; return -ENOMEM;
lp = netdev_priv(dev); lp = netdev_priv(dev);
link = &lp->link; link = &lp->link;
link->priv = dev; link->priv = dev;
...@@ -262,7 +254,7 @@ static dev_link_t *fmvj18x_attach(void) ...@@ -262,7 +254,7 @@ static dev_link_t *fmvj18x_attach(void)
link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = &fjn_interrupt; link->irq.Handler = &fjn_interrupt;
link->irq.Instance = dev; link->irq.Instance = dev;
/* General socket configuration */ /* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50; link->conf.Vcc = 50;
...@@ -281,37 +273,24 @@ static dev_link_t *fmvj18x_attach(void) ...@@ -281,37 +273,24 @@ static dev_link_t *fmvj18x_attach(void)
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
#endif #endif
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
fmvj18x_detach(link);
return NULL;
}
return link; link->handle = p_dev;
p_dev->instance = link;
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
fmvj18x_config(link);
return 0;
} /* fmvj18x_attach */ } /* fmvj18x_attach */
/*====================================================================*/ /*====================================================================*/
static void fmvj18x_detach(dev_link_t *link) static void fmvj18x_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "fmvj18x_detach(0x%p)\n", link); DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
...@@ -319,12 +298,6 @@ static void fmvj18x_detach(dev_link_t *link) ...@@ -319,12 +298,6 @@ static void fmvj18x_detach(dev_link_t *link)
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
fmvj18x_release(link); fmvj18x_release(link);
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free pieces */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
} /* fmvj18x_detach */ } /* fmvj18x_detach */
...@@ -713,51 +686,40 @@ static void fmvj18x_release(dev_link_t *link) ...@@ -713,51 +686,40 @@ static void fmvj18x_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*====================================================================*/ static int fmvj18x_suspend(struct pcmcia_device *p_dev)
static int fmvj18x_event(event_t event, int priority,
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
netif_device_detach(dev);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
fmvj18x_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND; link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
if (link->open) if (link->open)
netif_device_detach(dev); netif_device_detach(dev);
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
} }
break;
case CS_EVENT_PM_RESUME:
return 0;
}
static int fmvj18x_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) { if (link->open) {
fjn_reset(dev); fjn_reset(dev);
netif_device_attach(dev); netif_device_attach(dev);
} }
} }
break;
} return 0;
return 0; }
} /* fmvj18x_event */
/*====================================================================*/
static struct pcmcia_device_id fmvj18x_ids[] = { static struct pcmcia_device_id fmvj18x_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
...@@ -789,10 +751,11 @@ static struct pcmcia_driver fmvj18x_cs_driver = { ...@@ -789,10 +751,11 @@ static struct pcmcia_driver fmvj18x_cs_driver = {
.drv = { .drv = {
.name = "fmvj18x_cs", .name = "fmvj18x_cs",
}, },
.attach = fmvj18x_attach, .probe = fmvj18x_attach,
.event = fmvj18x_event, .remove = fmvj18x_detach,
.detach = fmvj18x_detach,
.id_table = fmvj18x_ids, .id_table = fmvj18x_ids,
.suspend = fmvj18x_suspend,
.resume = fmvj18x_resume,
}; };
static int __init init_fmvj18x_cs(void) static int __init init_fmvj18x_cs(void)
...@@ -803,7 +766,6 @@ static int __init init_fmvj18x_cs(void) ...@@ -803,7 +766,6 @@ static int __init init_fmvj18x_cs(void)
static void __exit exit_fmvj18x_cs(void) static void __exit exit_fmvj18x_cs(void)
{ {
pcmcia_unregister_driver(&fmvj18x_cs_driver); pcmcia_unregister_driver(&fmvj18x_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_fmvj18x_cs); module_init(init_fmvj18x_cs);
......
...@@ -108,15 +108,7 @@ MODULE_LICENSE("GPL"); ...@@ -108,15 +108,7 @@ MODULE_LICENSE("GPL");
static void ibmtr_config(dev_link_t *link); static void ibmtr_config(dev_link_t *link);
static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
static void ibmtr_release(dev_link_t *link); static void ibmtr_release(dev_link_t *link);
static int ibmtr_event(event_t event, int priority, static void ibmtr_detach(struct pcmcia_device *p_dev);
event_callback_args_t *args);
static dev_info_t dev_info = "ibmtr_cs";
static dev_link_t *ibmtr_attach(void);
static void ibmtr_detach(dev_link_t *);
static dev_link_t *dev_list;
/*====================================================================*/ /*====================================================================*/
...@@ -146,25 +138,23 @@ static struct ethtool_ops netdev_ethtool_ops = { ...@@ -146,25 +138,23 @@ static struct ethtool_ops netdev_ethtool_ops = {
======================================================================*/ ======================================================================*/
static dev_link_t *ibmtr_attach(void) static int ibmtr_attach(struct pcmcia_device *p_dev)
{ {
ibmtr_dev_t *info; ibmtr_dev_t *info;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
client_reg_t client_reg;
int ret;
DEBUG(0, "ibmtr_attach()\n"); DEBUG(0, "ibmtr_attach()\n");
/* Create new token-ring device */ /* Create new token-ring device */
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) return NULL; if (!info) return -ENOMEM;
memset(info,0,sizeof(*info)); memset(info,0,sizeof(*info));
dev = alloc_trdev(sizeof(struct tok_info)); dev = alloc_trdev(sizeof(struct tok_info));
if (!dev) { if (!dev) {
kfree(info); kfree(info);
return NULL; return -ENOMEM;
} }
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
...@@ -185,25 +175,13 @@ static dev_link_t *ibmtr_attach(void) ...@@ -185,25 +175,13 @@ static dev_link_t *ibmtr_attach(void)
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
goto out_detach;
}
out: link->state |= DEV_PRESENT;
return link; ibmtr_config(link);
out_detach: return 0;
ibmtr_detach(link);
link = NULL;
goto out;
} /* ibmtr_attach */ } /* ibmtr_attach */
/*====================================================================== /*======================================================================
...@@ -215,22 +193,14 @@ static dev_link_t *ibmtr_attach(void) ...@@ -215,22 +193,14 @@ static dev_link_t *ibmtr_attach(void)
======================================================================*/ ======================================================================*/
static void ibmtr_detach(dev_link_t *link) static void ibmtr_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct ibmtr_dev_t *info = link->priv; struct ibmtr_dev_t *info = link->priv;
dev_link_t **linkp; struct net_device *dev = info->dev;
struct net_device *dev;
DEBUG(0, "ibmtr_detach(0x%p)\n", link); DEBUG(0, "ibmtr_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
dev = info->dev;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
...@@ -241,13 +211,8 @@ static void ibmtr_detach(dev_link_t *link) ...@@ -241,13 +211,8 @@ static void ibmtr_detach(dev_link_t *link)
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
ibmtr_release(link); ibmtr_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
kfree(info); kfree(info);
} /* ibmtr_detach */ } /* ibmtr_detach */
/*====================================================================== /*======================================================================
...@@ -401,63 +366,40 @@ static void ibmtr_release(dev_link_t *link) ...@@ -401,63 +366,40 @@ static void ibmtr_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*====================================================================== static int ibmtr_suspend(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
The card status event handler. Mostly, this schedules other link->state |= DEV_SUSPEND;
stuff to run after an event is received. A CARD_REMOVAL event if (link->state & DEV_CONFIG) {
also sets some flags to discourage the net drivers from trying if (link->open)
to talk to the card any more. netif_device_detach(dev);
pcmcia_release_configuration(link->handle);
}
======================================================================*/ return 0;
}
static int ibmtr_event(event_t event, int priority, static int ibmtr_resume(struct pcmcia_device *p_dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
ibmtr_dev_t *info = link->priv; ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev; struct net_device *dev = info->dev;
DEBUG(1, "ibmtr_event(0x%06x)\n", event); link->state &= ~DEV_SUSPEND;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
/* set flag to bypass normal interrupt code */
struct tok_info *priv = netdev_priv(dev);
priv->sram_phys |= 1;
netif_device_detach(dev);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT;
ibmtr_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
if (link->open) pcmcia_request_configuration(link->handle, &link->conf);
netif_device_detach(dev); if (link->open) {
pcmcia_release_configuration(link->handle); ibmtr_probe(dev); /* really? */
netif_device_attach(dev);
}
} }
break;
case CS_EVENT_PM_RESUME: return 0;
link->state &= ~DEV_SUSPEND; }
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
ibmtr_probe(dev); /* really? */
netif_device_attach(dev);
}
}
break;
}
return 0;
} /* ibmtr_event */
/*====================================================================*/ /*====================================================================*/
...@@ -514,10 +456,11 @@ static struct pcmcia_driver ibmtr_cs_driver = { ...@@ -514,10 +456,11 @@ static struct pcmcia_driver ibmtr_cs_driver = {
.drv = { .drv = {
.name = "ibmtr_cs", .name = "ibmtr_cs",
}, },
.attach = ibmtr_attach, .probe = ibmtr_attach,
.event = ibmtr_event, .remove = ibmtr_detach,
.detach = ibmtr_detach,
.id_table = ibmtr_ids, .id_table = ibmtr_ids,
.suspend = ibmtr_suspend,
.resume = ibmtr_resume,
}; };
static int __init init_ibmtr_cs(void) static int __init init_ibmtr_cs(void)
...@@ -528,7 +471,6 @@ static int __init init_ibmtr_cs(void) ...@@ -528,7 +471,6 @@ static int __init init_ibmtr_cs(void)
static void __exit exit_ibmtr_cs(void) static void __exit exit_ibmtr_cs(void)
{ {
pcmcia_unregister_driver(&ibmtr_cs_driver); pcmcia_unregister_driver(&ibmtr_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_ibmtr_cs); module_init(init_ibmtr_cs);
......
...@@ -388,9 +388,6 @@ static char *version = ...@@ -388,9 +388,6 @@ static char *version =
DRV_NAME " " DRV_VERSION " (Roger C. Pao)"; DRV_NAME " " DRV_VERSION " (Roger C. Pao)";
#endif #endif
static dev_info_t dev_info="nmclan_cs";
static dev_link_t *dev_list;
static char *if_names[]={ static char *if_names[]={
"Auto", "10baseT", "BNC", "Auto", "10baseT", "BNC",
}; };
...@@ -422,8 +419,6 @@ Function Prototypes ...@@ -422,8 +419,6 @@ Function Prototypes
static void nmclan_config(dev_link_t *link); static void nmclan_config(dev_link_t *link);
static void nmclan_release(dev_link_t *link); static void nmclan_release(dev_link_t *link);
static int nmclan_event(event_t event, int priority,
event_callback_args_t *args);
static void nmclan_reset(struct net_device *dev); static void nmclan_reset(struct net_device *dev);
static int mace_config(struct net_device *dev, struct ifmap *map); static int mace_config(struct net_device *dev, struct ifmap *map);
...@@ -439,8 +434,7 @@ static void set_multicast_list(struct net_device *dev); ...@@ -439,8 +434,7 @@ static void set_multicast_list(struct net_device *dev);
static struct ethtool_ops netdev_ethtool_ops; static struct ethtool_ops netdev_ethtool_ops;
static dev_link_t *nmclan_attach(void); static void nmclan_detach(struct pcmcia_device *p_dev);
static void nmclan_detach(dev_link_t *);
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
nmclan_attach nmclan_attach
...@@ -449,13 +443,11 @@ nmclan_attach ...@@ -449,13 +443,11 @@ nmclan_attach
Services. Services.
---------------------------------------------------------------------------- */ ---------------------------------------------------------------------------- */
static dev_link_t *nmclan_attach(void) static int nmclan_attach(struct pcmcia_device *p_dev)
{ {
mace_private *lp; mace_private *lp;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
client_reg_t client_reg;
int ret;
DEBUG(0, "nmclan_attach()\n"); DEBUG(0, "nmclan_attach()\n");
DEBUG(1, "%s\n", rcsid); DEBUG(1, "%s\n", rcsid);
...@@ -463,7 +455,7 @@ static dev_link_t *nmclan_attach(void) ...@@ -463,7 +455,7 @@ static dev_link_t *nmclan_attach(void)
/* Create new ethernet device */ /* Create new ethernet device */
dev = alloc_etherdev(sizeof(mace_private)); dev = alloc_etherdev(sizeof(mace_private));
if (!dev) if (!dev)
return NULL; return -ENOMEM;
lp = netdev_priv(dev); lp = netdev_priv(dev);
link = &lp->link; link = &lp->link;
link->priv = dev; link->priv = dev;
...@@ -497,20 +489,13 @@ static dev_link_t *nmclan_attach(void) ...@@ -497,20 +489,13 @@ static dev_link_t *nmclan_attach(void)
dev->watchdog_timeo = TX_TIMEOUT; dev->watchdog_timeo = TX_TIMEOUT;
#endif #endif
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; nmclan_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
nmclan_detach(link);
return NULL;
}
return link; return 0;
} /* nmclan_attach */ } /* nmclan_attach */
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
...@@ -521,30 +506,19 @@ nmclan_detach ...@@ -521,30 +506,19 @@ nmclan_detach
when the device is released. when the device is released.
---------------------------------------------------------------------------- */ ---------------------------------------------------------------------------- */
static void nmclan_detach(dev_link_t *link) static void nmclan_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "nmclan_detach(0x%p)\n", link); DEBUG(0, "nmclan_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
nmclan_release(link); nmclan_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
} /* nmclan_detach */ } /* nmclan_detach */
...@@ -801,59 +775,39 @@ static void nmclan_release(dev_link_t *link) ...@@ -801,59 +775,39 @@ static void nmclan_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/* ---------------------------------------------------------------------------- static int nmclan_suspend(struct pcmcia_device *p_dev)
nmclan_event
The card status event handler. Mostly, this schedules other
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
---------------------------------------------------------------------------- */
static int nmclan_event(event_t event, int priority,
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
pcmcia_release_configuration(link->handle);
}
DEBUG(1, "nmclan_event(0x%06x)\n", event);
switch (event) { return 0;
case CS_EVENT_CARD_REMOVAL: }
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) static int nmclan_resume(struct pcmcia_device *p_dev)
netif_device_detach(dev); {
break; dev_link_t *link = dev_to_instance(p_dev);
case CS_EVENT_CARD_INSERTION: struct net_device *dev = link->priv;
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
nmclan_config(link); link->state &= ~DEV_SUSPEND;
break; if (link->state & DEV_CONFIG) {
case CS_EVENT_PM_SUSPEND: pcmcia_request_configuration(link->handle, &link->conf);
link->state |= DEV_SUSPEND; if (link->open) {
/* Fall through... */ nmclan_reset(dev);
case CS_EVENT_RESET_PHYSICAL: netif_device_attach(dev);
if (link->state & DEV_CONFIG) { }
if (link->open)
netif_device_detach(dev);
pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
nmclan_reset(dev);
netif_device_attach(dev);
} }
}
break; return 0;
case CS_EVENT_RESET_REQUEST: }
return 1;
break;
}
return 0;
} /* nmclan_event */
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
nmclan_reset nmclan_reset
...@@ -1681,10 +1635,11 @@ static struct pcmcia_driver nmclan_cs_driver = { ...@@ -1681,10 +1635,11 @@ static struct pcmcia_driver nmclan_cs_driver = {
.drv = { .drv = {
.name = "nmclan_cs", .name = "nmclan_cs",
}, },
.attach = nmclan_attach, .probe = nmclan_attach,
.event = nmclan_event, .remove = nmclan_detach,
.detach = nmclan_detach,
.id_table = nmclan_ids, .id_table = nmclan_ids,
.suspend = nmclan_suspend,
.resume = nmclan_resume,
}; };
static int __init init_nmclan_cs(void) static int __init init_nmclan_cs(void)
...@@ -1695,7 +1650,6 @@ static int __init init_nmclan_cs(void) ...@@ -1695,7 +1650,6 @@ static int __init init_nmclan_cs(void)
static void __exit exit_nmclan_cs(void) static void __exit exit_nmclan_cs(void)
{ {
pcmcia_unregister_driver(&nmclan_cs_driver); pcmcia_unregister_driver(&nmclan_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_nmclan_cs); module_init(init_nmclan_cs);
......
...@@ -105,8 +105,6 @@ module_param_array(hw_addr, int, NULL, 0); ...@@ -105,8 +105,6 @@ module_param_array(hw_addr, int, NULL, 0);
static void mii_phy_probe(struct net_device *dev); static void mii_phy_probe(struct net_device *dev);
static void pcnet_config(dev_link_t *link); static void pcnet_config(dev_link_t *link);
static void pcnet_release(dev_link_t *link); static void pcnet_release(dev_link_t *link);
static int pcnet_event(event_t event, int priority,
event_callback_args_t *args);
static int pcnet_open(struct net_device *dev); static int pcnet_open(struct net_device *dev);
static int pcnet_close(struct net_device *dev); static int pcnet_close(struct net_device *dev);
static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
...@@ -120,11 +118,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg, ...@@ -120,11 +118,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
static int setup_dma_config(dev_link_t *link, int start_pg, static int setup_dma_config(dev_link_t *link, int start_pg,
int stop_pg); int stop_pg);
static dev_link_t *pcnet_attach(void); static void pcnet_detach(struct pcmcia_device *p_dev);
static void pcnet_detach(dev_link_t *);
static dev_info_t dev_info = "pcnet_cs"; static dev_info_t dev_info = "pcnet_cs";
static dev_link_t *dev_list;
/*====================================================================*/ /*====================================================================*/
...@@ -244,19 +240,17 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev) ...@@ -244,19 +240,17 @@ static inline pcnet_dev_t *PRIV(struct net_device *dev)
======================================================================*/ ======================================================================*/
static dev_link_t *pcnet_attach(void) static int pcnet_probe(struct pcmcia_device *p_dev)
{ {
pcnet_dev_t *info; pcnet_dev_t *info;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
client_reg_t client_reg;
int ret;
DEBUG(0, "pcnet_attach()\n"); DEBUG(0, "pcnet_attach()\n");
/* Create new ethernet device */ /* Create new ethernet device */
dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
if (!dev) return NULL; if (!dev) return -ENOMEM;
info = PRIV(dev); info = PRIV(dev);
link = &info->link; link = &info->link;
link->priv = dev; link->priv = dev;
...@@ -271,20 +265,13 @@ static dev_link_t *pcnet_attach(void) ...@@ -271,20 +265,13 @@ static dev_link_t *pcnet_attach(void)
dev->stop = &pcnet_close; dev->stop = &pcnet_close;
dev->set_config = &set_config; dev->set_config = &set_config;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
pcnet_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
pcnet_config(link);
return 0;
} /* pcnet_attach */ } /* pcnet_attach */
/*====================================================================== /*======================================================================
...@@ -296,31 +283,20 @@ static dev_link_t *pcnet_attach(void) ...@@ -296,31 +283,20 @@ static dev_link_t *pcnet_attach(void)
======================================================================*/ ======================================================================*/
static void pcnet_detach(dev_link_t *link) static void pcnet_detach(struct pcmcia_device *p_dev)
{ {
struct net_device *dev = link->priv; dev_link_t *link = dev_to_instance(p_dev);
dev_link_t **linkp; struct net_device *dev = link->priv;
DEBUG(0, "pcnet_detach(0x%p)\n", link);
/* Locate device structure */ DEBUG(0, "pcnet_detach(0x%p)\n", link);
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
pcnet_release(link); pcnet_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */ free_netdev(dev);
*linkp = link->next;
free_netdev(dev);
} /* pcnet_detach */ } /* pcnet_detach */
/*====================================================================== /*======================================================================
...@@ -780,50 +756,39 @@ static void pcnet_release(dev_link_t *link) ...@@ -780,50 +756,39 @@ static void pcnet_release(dev_link_t *link)
======================================================================*/ ======================================================================*/
static int pcnet_event(event_t event, int priority, static int pcnet_suspend(struct pcmcia_device *p_dev)
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
DEBUG(2, "pcnet_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
netif_device_detach(dev);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
pcnet_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND; link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
if (link->open) if (link->open)
netif_device_detach(dev); netif_device_detach(dev);
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
} }
break;
case CS_EVENT_PM_RESUME: return 0;
}
static int pcnet_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) { if (link->open) {
pcnet_reset_8390(dev); pcnet_reset_8390(dev);
NS8390_init(dev, 1); NS8390_init(dev, 1);
netif_device_attach(dev); netif_device_attach(dev);
} }
} }
break;
} return 0;
return 0; }
} /* pcnet_event */
/*====================================================================== /*======================================================================
...@@ -1844,11 +1809,12 @@ static struct pcmcia_driver pcnet_driver = { ...@@ -1844,11 +1809,12 @@ static struct pcmcia_driver pcnet_driver = {
.drv = { .drv = {
.name = "pcnet_cs", .name = "pcnet_cs",
}, },
.attach = pcnet_attach, .probe = pcnet_probe,
.event = pcnet_event, .remove = pcnet_detach,
.detach = pcnet_detach,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.id_table = pcnet_ids, .id_table = pcnet_ids,
.suspend = pcnet_suspend,
.resume = pcnet_resume,
}; };
static int __init init_pcnet_cs(void) static int __init init_pcnet_cs(void)
...@@ -1860,7 +1826,6 @@ static void __exit exit_pcnet_cs(void) ...@@ -1860,7 +1826,6 @@ static void __exit exit_pcnet_cs(void)
{ {
DEBUG(0, "pcnet_cs: unloading\n"); DEBUG(0, "pcnet_cs: unloading\n");
pcmcia_unregister_driver(&pcnet_driver); pcmcia_unregister_driver(&pcnet_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_pcnet_cs); module_init(init_pcnet_cs);
......
...@@ -102,10 +102,6 @@ static const char *version = ...@@ -102,10 +102,6 @@ static const char *version =
currently have room for another Tx packet. */ currently have room for another Tx packet. */
#define MEMORY_WAIT_TIME 8 #define MEMORY_WAIT_TIME 8
static dev_info_t dev_info = "smc91c92_cs";
static dev_link_t *dev_list;
struct smc_private { struct smc_private {
dev_link_t link; dev_link_t link;
spinlock_t lock; spinlock_t lock;
...@@ -281,12 +277,9 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, ...@@ -281,12 +277,9 @@ enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002,
/*====================================================================*/ /*====================================================================*/
static dev_link_t *smc91c92_attach(void); static void smc91c92_detach(struct pcmcia_device *p_dev);
static void smc91c92_detach(dev_link_t *);
static void smc91c92_config(dev_link_t *link); static void smc91c92_config(dev_link_t *link);
static void smc91c92_release(dev_link_t *link); static void smc91c92_release(dev_link_t *link);
static int smc91c92_event(event_t event, int priority,
event_callback_args_t *args);
static int smc_open(struct net_device *dev); static int smc_open(struct net_device *dev);
static int smc_close(struct net_device *dev); static int smc_close(struct net_device *dev);
...@@ -315,20 +308,18 @@ static struct ethtool_ops ethtool_ops; ...@@ -315,20 +308,18 @@ static struct ethtool_ops ethtool_ops;
======================================================================*/ ======================================================================*/
static dev_link_t *smc91c92_attach(void) static int smc91c92_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
struct smc_private *smc; struct smc_private *smc;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
int ret;
DEBUG(0, "smc91c92_attach()\n"); DEBUG(0, "smc91c92_attach()\n");
/* Create new ethernet device */ /* Create new ethernet device */
dev = alloc_etherdev(sizeof(struct smc_private)); dev = alloc_etherdev(sizeof(struct smc_private));
if (!dev) if (!dev)
return NULL; return -ENOMEM;
smc = netdev_priv(dev); smc = netdev_priv(dev);
link = &smc->link; link = &smc->link;
link->priv = dev; link->priv = dev;
...@@ -366,20 +357,13 @@ static dev_link_t *smc91c92_attach(void) ...@@ -366,20 +357,13 @@ static dev_link_t *smc91c92_attach(void)
smc->mii_if.phy_id_mask = 0x1f; smc->mii_if.phy_id_mask = 0x1f;
smc->mii_if.reg_num_mask = 0x1f; smc->mii_if.reg_num_mask = 0x1f;
/* Register with Card Services */ link->handle = p_dev;
link->next = dev_list; p_dev->instance = link;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; smc91c92_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
smc91c92_detach(link);
return NULL;
}
return link; return 0;
} /* smc91c92_attach */ } /* smc91c92_attach */
/*====================================================================== /*======================================================================
...@@ -391,30 +375,19 @@ static dev_link_t *smc91c92_attach(void) ...@@ -391,30 +375,19 @@ static dev_link_t *smc91c92_attach(void)
======================================================================*/ ======================================================================*/
static void smc91c92_detach(dev_link_t *link) static void smc91c92_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "smc91c92_detach(0x%p)\n", link); DEBUG(0, "smc91c92_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
smc91c92_release(link); smc91c92_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
} /* smc91c92_detach */ } /* smc91c92_detach */
...@@ -895,6 +868,62 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) ...@@ -895,6 +868,62 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
return rc; return rc;
} }
static int smc91c92_suspend(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
pcmcia_release_configuration(link->handle);
}
return 0;
}
static int smc91c92_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
int i;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
if ((smc->manfid == MANFID_MEGAHERTZ) &&
(smc->cardid == PRODID_MEGAHERTZ_EM3288))
mhz_3288_power(link);
pcmcia_request_configuration(link->handle, &link->conf);
if (smc->manfid == MANFID_MOTOROLA)
mot_config(link);
if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN)) {
/* Power up the card and enable interrupts */
set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
}
if (((smc->manfid == MANFID_OSITECH) &&
(smc->cardid == PRODID_OSITECH_SEVEN)) ||
((smc->manfid == MANFID_PSION) &&
(smc->cardid == PRODID_PSION_NET100))) {
/* Download the Seven of Diamonds firmware */
for (i = 0; i < sizeof(__Xilinx7OD); i++) {
outb(__Xilinx7OD[i], link->io.BasePort1+2);
udelay(50);
}
}
if (link->open) {
smc_reset(dev);
netif_device_attach(dev);
}
}
return 0;
}
/*====================================================================== /*======================================================================
This verifies that the chip is some SMC91cXX variant, and returns This verifies that the chip is some SMC91cXX variant, and returns
...@@ -935,14 +964,12 @@ static int check_sig(dev_link_t *link) ...@@ -935,14 +964,12 @@ static int check_sig(dev_link_t *link)
} }
if (width) { if (width) {
event_callback_args_t args;
printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n"); printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");
args.client_data = link; smc91c92_suspend(link->handle);
smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args);
pcmcia_release_io(link->handle, &link->io); pcmcia_release_io(link->handle, &link->io);
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
pcmcia_request_io(link->handle, &link->io); pcmcia_request_io(link->handle, &link->io);
smc91c92_event(CS_EVENT_CARD_RESET, 0, &args); smc91c92_resume(link->handle);
return check_sig(link); return check_sig(link);
} }
return -ENODEV; return -ENODEV;
...@@ -1170,82 +1197,6 @@ static void smc91c92_release(dev_link_t *link) ...@@ -1170,82 +1197,6 @@ static void smc91c92_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*======================================================================
The card status event handler. Mostly, this schedules other
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
======================================================================*/
static int smc91c92_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
int i;
DEBUG(1, "smc91c92_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
netif_device_detach(dev);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
smc91c92_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
if ((smc->manfid == MANFID_MEGAHERTZ) &&
(smc->cardid == PRODID_MEGAHERTZ_EM3288))
mhz_3288_power(link);
pcmcia_request_configuration(link->handle, &link->conf);
if (smc->manfid == MANFID_MOTOROLA)
mot_config(link);
if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN)) {
/* Power up the card and enable interrupts */
set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);
set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);
}
if (((smc->manfid == MANFID_OSITECH) &&
(smc->cardid == PRODID_OSITECH_SEVEN)) ||
((smc->manfid == MANFID_PSION) &&
(smc->cardid == PRODID_PSION_NET100))) {
/* Download the Seven of Diamonds firmware */
for (i = 0; i < sizeof(__Xilinx7OD); i++) {
outb(__Xilinx7OD[i], link->io.BasePort1+2);
udelay(50);
}
}
if (link->open) {
smc_reset(dev);
netif_device_attach(dev);
}
}
break;
}
return 0;
} /* smc91c92_event */
/*====================================================================== /*======================================================================
MII interface support for SMC91cXX based cards MII interface support for SMC91cXX based cards
...@@ -2360,10 +2311,11 @@ static struct pcmcia_driver smc91c92_cs_driver = { ...@@ -2360,10 +2311,11 @@ static struct pcmcia_driver smc91c92_cs_driver = {
.drv = { .drv = {
.name = "smc91c92_cs", .name = "smc91c92_cs",
}, },
.attach = smc91c92_attach, .probe = smc91c92_attach,
.event = smc91c92_event, .remove = smc91c92_detach,
.detach = smc91c92_detach,
.id_table = smc91c92_ids, .id_table = smc91c92_ids,
.suspend = smc91c92_suspend,
.resume = smc91c92_resume,
}; };
static int __init init_smc91c92_cs(void) static int __init init_smc91c92_cs(void)
...@@ -2374,7 +2326,6 @@ static int __init init_smc91c92_cs(void) ...@@ -2374,7 +2326,6 @@ static int __init init_smc91c92_cs(void)
static void __exit exit_smc91c92_cs(void) static void __exit exit_smc91c92_cs(void)
{ {
pcmcia_unregister_driver(&smc91c92_cs_driver); pcmcia_unregister_driver(&smc91c92_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_smc91c92_cs); module_init(init_smc91c92_cs);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -754,20 +754,11 @@ static void ...@@ -754,20 +754,11 @@ static void
static int static int
wavelan_open(struct net_device *), /* Open the device */ wavelan_open(struct net_device *), /* Open the device */
wavelan_close(struct net_device *); /* Close the device */ wavelan_close(struct net_device *); /* Close the device */
static dev_link_t *
wavelan_attach(void); /* Create a new device */
static void static void
wavelan_detach(dev_link_t *); /* Destroy a removed device */ wavelan_detach(struct pcmcia_device *p_dev); /* Destroy a removed device */
static int
wavelan_event(event_t, /* Manage pcmcia events */
int,
event_callback_args_t *);
/**************************** VARIABLES ****************************/ /**************************** VARIABLES ****************************/
static dev_info_t dev_info = "wavelan_cs";
static dev_link_t *dev_list = NULL; /* Linked list of devices */
/* /*
* Parameters that can be set with 'insmod' * Parameters that can be set with 'insmod'
* The exact syntax is 'insmod wavelan_cs.o <var>=<value>' * The exact syntax is 'insmod wavelan_cs.o <var>=<value>'
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -241,23 +241,6 @@ au1x00_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status) ...@@ -241,23 +241,6 @@ au1x00_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
return 0; return 0;
} }
/* au1x00_pcmcia_get_socket()
* Implements the get_socket() operation for the in-kernel PCMCIA
* service (formerly SS_GetSocket in Card Services). Not a very
* exciting routine.
*
* Returns: 0
*/
static int
au1x00_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct au1000_pcmcia_socket *skt = to_au1000_socket(sock);
debug("for sock %u\n", skt->nr);
*state = skt->cs_state;
return 0;
}
/* au1x00_pcmcia_set_socket() /* au1x00_pcmcia_set_socket()
* Implements the set_socket() operation for the in-kernel PCMCIA * Implements the set_socket() operation for the in-kernel PCMCIA
* service (formerly SS_SetSocket in Card Services). We more or * service (formerly SS_SetSocket in Card Services). We more or
...@@ -352,7 +335,6 @@ static struct pccard_operations au1x00_pcmcia_operations = { ...@@ -352,7 +335,6 @@ static struct pccard_operations au1x00_pcmcia_operations = {
.init = au1x00_pcmcia_sock_init, .init = au1x00_pcmcia_sock_init,
.suspend = au1x00_pcmcia_suspend, .suspend = au1x00_pcmcia_suspend,
.get_status = au1x00_pcmcia_get_status, .get_status = au1x00_pcmcia_get_status,
.get_socket = au1x00_pcmcia_get_socket,
.set_socket = au1x00_pcmcia_set_socket, .set_socket = au1x00_pcmcia_set_socket,
.set_io_map = au1x00_pcmcia_set_io_map, .set_io_map = au1x00_pcmcia_set_io_map,
.set_mem_map = au1x00_pcmcia_set_mem_map, .set_mem_map = au1x00_pcmcia_set_mem_map,
...@@ -372,13 +354,12 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, ...@@ -372,13 +354,12 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops,
struct skt_dev_info *sinfo; struct skt_dev_info *sinfo;
int ret, i; int ret, i;
sinfo = kmalloc(sizeof(struct skt_dev_info), GFP_KERNEL); sinfo = kzalloc(sizeof(struct skt_dev_info), GFP_KERNEL);
if (!sinfo) { if (!sinfo) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
memset(sinfo, 0, sizeof(struct skt_dev_info));
sinfo->nskt = nr; sinfo->nskt = nr;
/* /*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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