Merge git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6

This commit is contained in:
Linus Torvalds 2006-01-05 15:55:49 -08:00
commit d7906de1d7
76 changed files with 2592 additions and 5409 deletions

View File

@ -1,5 +1,16 @@
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.

View File

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

View File

@ -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)
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)
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) { bluecard_config(link);
cs_error(link->handle, RegisterClient, ret);
bluecard_detach(link);
return NULL;
}
return 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)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int bluecard_suspend(struct pcmcia_device *dev)
static int bluecard_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(dev);
bluecard_info_t *info = link->priv;
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG)
link->state &= ~DEV_PRESENT; pcmcia_release_configuration(link->handle);
if (link->state & DEV_CONFIG) {
bluecard_close(info); return 0;
bluecard_release(link); }
}
break; static int bluecard_resume(struct pcmcia_device *dev)
case CS_EVENT_CARD_INSERTION: {
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; dev_link_t *link = dev_to_instance(dev);
bluecard_config(link);
break; link->state &= ~DEV_SUSPEND;
case CS_EVENT_PM_SUSPEND: if (DEV_OK(link))
link->state |= DEV_SUSPEND; pcmcia_request_configuration(link->handle, &link->conf);
/* 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 = {
.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)
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);

View File

@ -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)
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)
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) { bt3c_config(link);
cs_error(link->handle, RegisterClient, ret);
bt3c_detach(link);
return NULL;
}
return 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)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int bt3c_suspend(struct pcmcia_device *dev)
static int bt3c_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(dev);
bt3c_info_t *info = link->priv;
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG)
link->state &= ~DEV_PRESENT; pcmcia_release_configuration(link->handle);
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 int bt3c_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;
}
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 = {
.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)
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);

View File

@ -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)
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)
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) { btuart_config(link);
cs_error(link->handle, RegisterClient, ret);
btuart_detach(link);
return NULL;
}
return 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)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int btuart_suspend(struct pcmcia_device *dev)
static int btuart_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(dev);
btuart_info_t *info = link->priv;
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG)
link->state &= ~DEV_PRESENT; pcmcia_release_configuration(link->handle);
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 int btuart_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;
}
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 = {
.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)
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);

View File

@ -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)
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)
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) { dtl1_config(link);
cs_error(link->handle, RegisterClient, ret);
dtl1_detach(link);
return NULL;
}
return 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)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int dtl1_suspend(struct pcmcia_device *dev)
static int dtl1_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(dev);
dtl1_info_t *info = link->priv;
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG)
link->state &= ~DEV_PRESENT; pcmcia_release_configuration(link->handle);
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 int dtl1_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;
}
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 = {
.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)
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);

View File

@ -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 {
/*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 @@ cs_release:
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)
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)
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;
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
cm4000_config(link, i);
return 0;
} }
static void cm4000_detach_by_devno(int devno, dev_link_t * link) static void cm4000_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct cm4000_dev *dev = link->priv; struct cm4000_dev *dev = link->priv;
int devno;
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) {
pcmcia_deregister_client(link->handle);
}
dev_table[devno] = NULL;
kfree(dev);
return;
}
static void cm4000_detach(dev_link_t * link)
{
int i;
/* 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 = {
.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)
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);
}; };

View File

@ -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 {
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 @@ cs_release:
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;
reader_config(link, devno);
break;
case CS_EVENT_CARD_REMOVAL:
DEBUGP(5, dev, "CS_EVENT_CARD_REMOVAL\n");
link->state &= ~DEV_PRESENT;
break;
case CS_EVENT_PM_SUSPEND:
DEBUGP(5, dev, "CS_EVENT_PM_SUSPEND "
"(fall-through to CS_EVENT_RESET_PHYSICAL)\n");
link->state |= DEV_SUSPEND;
case CS_EVENT_RESET_PHYSICAL: static int reader_resume(struct pcmcia_device *p_dev)
DEBUGP(5, dev, "CS_EVENT_RESET_PHYSICAL\n"); {
if (link->state & DEV_CONFIG) { dev_link_t *link = dev_to_instance(p_dev);
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: link->state &= ~DEV_SUSPEND;
DEBUGP(5, dev, "CS_EVENT_CARD_RESET\n"); if (link->state & DEV_CONFIG)
if ((link->state & DEV_CONFIG)) { pcmcia_request_configuration(link->handle, &link->conf);
DEBUGP(5, dev, "RequestConfiguration\n");
pcmcia_request_configuration(link->handle, return 0;
&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)
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)
} }
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)
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)
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;
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
reader_config(link, i);
return 0;
} }
static void reader_detach_by_devno(int devno, dev_link_t *link) static void reader_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct reader_dev *dev = link->priv; struct reader_dev *dev = link->priv;
int devno;
if (link->state & DEV_CONFIG) {
DEBUGP(5, dev, "device still configured (try to release it)\n");
reader_release(link);
}
pcmcia_deregister_client(link->handle);
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)
{
int i;
/* 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 = {
.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)
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);
} }

View File

@ -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,
} }
} }
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)
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)
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; mgslpc_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);
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)
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 = {
.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)
} }
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)

View File

@ -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;
======================================================================*/ ======================================================================*/
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)
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)
======================================================================*/ ======================================================================*/
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)
} /* 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)
======================================================================*/ ======================================================================*/
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[] = {
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 = {
.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)
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);

View File

@ -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,
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";
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 {
======================================================================*/ ======================================================================*/
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)
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)
======================================================================*/ ======================================================================*/
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 */ if (link->state & DEV_CONFIG)
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) avmcs_release(link);
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) {
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)
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)
======================================================================*/ ======================================================================*/
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 = {
.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)
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);

View File

@ -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,
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";
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 {
======================================================================*/ ======================================================================*/
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)
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)
======================================================================*/ ======================================================================*/
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)
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)
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.
When a CARD_REMOVAL event is received, we immediately set a 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 avma1cs_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(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); pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME: return 0;
link->state &= ~DEV_SUSPEND; }
/* Fall through... */
case CS_EVENT_CARD_RESET: static int avma1cs_resume(struct pcmcia_device *dev)
if (link->state & DEV_CONFIG) {
dev_link_t *link = dev_to_instance(dev);
link->state &= ~DEV_SUSPEND;
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 = {
.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)
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);

View File

@ -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,
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 {
======================================================================*/ ======================================================================*/
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)
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)
======================================================================*/ ======================================================================*/
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)
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
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.
When a CARD_REMOVAL event is received, we immediately set a 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 elsa_cs_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, "elsa_cs_event(%d)\n", event); link->state |= DEV_SUSPEND;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
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; dev->busy = 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;
link->state &= ~DEV_SUSPEND; }
/* Fall through... */
case CS_EVENT_CARD_RESET: static int elsa_resume(struct pcmcia_device *p_dev)
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
link->state &= ~DEV_SUSPEND;
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 = {
.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)
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);

View File

@ -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,
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 *);
*/ */
/* /*
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 {
======================================================================*/ ======================================================================*/
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)
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);
sedlbauer_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
sedlbauer_config(link);
return 0;
} /* sedlbauer_attach */ } /* sedlbauer_attach */
/*====================================================================== /*======================================================================
@ -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)
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 = {
.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)
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);

View File

@ -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,
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";
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 {
======================================================================*/ ======================================================================*/
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)
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);
teles_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
teles_cs_config(link);
return 0;
} /* teles_attach */ } /* teles_attach */
/*====================================================================== /*======================================================================
@ -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)
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
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.
When a CARD_REMOVAL event is received, we immediately set a 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 teles_cs_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, "teles_cs_event(%d)\n", event); link->state |= DEV_SUSPEND;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
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; dev->busy = 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;
link->state &= ~DEV_SUSPEND; }
/* Fall through... */
case CS_EVENT_CARD_RESET: static int teles_resume(struct pcmcia_device *p_dev)
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf); dev_link_t *link = dev_to_instance(p_dev);
local_info_t *dev = link->priv;
link->state &= ~DEV_SUSPEND;
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 = {
.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)
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);

View File

@ -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)
} }
/* 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
* to talk to the card any more.
*/
static int pcmciamtd_event(event_t event, int priority,
event_callback_args_t *args)
{ {
dev_link_t *link = args->client_data; DEBUG(2, "EVENT_PM_RESUME");
/* get_lock(link); */
return 0;
}
static int pcmciamtd_resume(struct pcmcia_device *dev)
{
DEBUG(2, "EVENT_PM_SUSPEND");
/* free_lock(link); */
DEBUG(1, "event=0x%06x", event);
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,
* 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) {
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); pcmciamtd_release(link);
} }
if (link->handle) {
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)
* 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)
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 */ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.dev_info = &dev_info; pcmciamtd_config(link);
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link; return 0;
DEBUG(2, "Calling RegisterClient");
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 = {
.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)
{ {
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);

View File

@ -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);
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;
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)
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)
*/ */
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)
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);
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) {
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 int tc574_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;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
tc574_reset(dev);
netif_device_attach(dev);
}
}
return 0;
}
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 = {
.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)
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);

View File

@ -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);
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;
======================================================================*/ ======================================================================*/
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)
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)
#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)
======================================================================*/ ======================================================================*/
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)
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 = {
.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)
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);

View File

@ -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,
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)
======================================================================*/ ======================================================================*/
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)
"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)
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)
======================================================================*/ ======================================================================*/
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)
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)
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 = {
.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)
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);

View File

@ -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 {
======================================================================*/ ======================================================================*/
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)
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 @@ fail_alloc_info:
======================================================================*/ ======================================================================*/
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)
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)
link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING);
} }
/*====================================================================== static int com20020_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 com20020_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);
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->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;
link->state &= ~DEV_SUSPEND; }
/* Fall through... */
case CS_EVENT_CARD_RESET: static int com20020_resume(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;
link->state &= ~DEV_SUSPEND;
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 = {
.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)
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);

View File

@ -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);
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 {
#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)
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)
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)
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)
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 = {
.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)
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);

View File

@ -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 = {
======================================================================*/ ======================================================================*/
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)
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 @@ out_detach:
======================================================================*/ ======================================================================*/
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)
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)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*====================================================================== static int ibmtr_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 ibmtr_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);
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;
if (link->state & DEV_CONFIG) {
if (link->open)
netif_device_detach(dev);
pcmcia_release_configuration(link->handle);
}
switch (event) { return 0;
case CS_EVENT_CARD_REMOVAL: }
link->state &= ~DEV_PRESENT;
static int ibmtr_resume(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;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
/* set flag to bypass normal interrupt code */ pcmcia_request_configuration(link->handle, &link->conf);
struct tok_info *priv = netdev_priv(dev); if (link->open) {
priv->sram_phys |= 1; ibmtr_probe(dev); /* really? */
netif_device_detach(dev); netif_device_attach(dev);
}
} }
break;
case CS_EVENT_CARD_INSERTION: return 0;
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->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) {
ibmtr_probe(dev); /* really? */
netif_device_attach(dev);
}
}
break;
}
return 0;
} /* ibmtr_event */
/*====================================================================*/ /*====================================================================*/
@ -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)
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);

View File

@ -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
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);
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
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)
/* 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)
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);
nmclan_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
nmclan_config(link);
return 0;
} /* nmclan_attach */ } /* nmclan_attach */
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
@ -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)
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;
DEBUG(1, "nmclan_event(0x%06x)\n", event); link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
switch (event) { if (link->open)
case CS_EVENT_CARD_REMOVAL: netif_device_detach(dev);
link->state &= ~DEV_PRESENT; pcmcia_release_configuration(link->handle);
if (link->state & DEV_CONFIG)
netif_device_detach(dev);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
nmclan_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) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
nmclan_reset(dev);
netif_device_attach(dev);
} }
}
break;
case CS_EVENT_RESET_REQUEST: return 0;
return 1; }
break;
} static int nmclan_resume(struct pcmcia_device *p_dev)
return 0; {
} /* nmclan_event */ dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
nmclan_reset(dev);
netif_device_attach(dev);
}
}
return 0;
}
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
nmclan_reset nmclan_reset
@ -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)
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);

View File

@ -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,
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)
======================================================================*/ ======================================================================*/
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)
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)
======================================================================*/ ======================================================================*/
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); DEBUG(0, "pcnet_detach(0x%p)\n", link);
/* Locate device structure */ if (link->dev)
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) unregister_netdev(dev);
if (*linkp == link) break;
if (*linkp == NULL)
return;
if (link->dev) if (link->state & DEV_CONFIG)
unregister_netdev(dev); pcnet_release(link);
if (link->state & DEV_CONFIG) free_netdev(dev);
pcnet_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
free_netdev(dev);
} /* pcnet_detach */ } /* pcnet_detach */
/*====================================================================== /*======================================================================
@ -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 = {
.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)
{ {
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);

View File

@ -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,
/*====================================================================*/ /*====================================================================*/
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;
======================================================================*/ ======================================================================*/
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)
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;
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);
smc91c92_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
smc91c92_config(link);
return 0;
} /* smc91c92_attach */ } /* smc91c92_attach */
/*====================================================================== /*======================================================================
@ -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 @@ free_cfg_mem:
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)
} }
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)
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 = {
.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)
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);

View File

@ -292,8 +292,6 @@ static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg,
static int has_ce2_string(dev_link_t * link); static int has_ce2_string(dev_link_t * link);
static void xirc2ps_config(dev_link_t * link); static void xirc2ps_config(dev_link_t * link);
static void xirc2ps_release(dev_link_t * link); static void xirc2ps_release(dev_link_t * link);
static int xirc2ps_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
@ -301,8 +299,7 @@ static int xirc2ps_event(event_t event, int priority,
* needed to manage one actual PCMCIA card. * needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *xirc2ps_attach(void); static void xirc2ps_detach(struct pcmcia_device *p_dev);
static void xirc2ps_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
@ -313,14 +310,6 @@ static void xirc2ps_detach(dev_link_t *);
static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs);
/*
* 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 = "xirc2ps_cs";
/**************** /****************
* A linked list of "instances" of the device. Each actual * A linked list of "instances" of the device. Each actual
* PCMCIA card corresponds to one device instance, and is described * PCMCIA card corresponds to one device instance, and is described
@ -331,15 +320,7 @@ static dev_info_t dev_info = "xirc2ps_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;
/**************** /****************
* 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
@ -571,21 +552,19 @@ mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len)
* card insertion event. * card insertion event.
*/ */
static dev_link_t * static int
xirc2ps_attach(void) xirc2ps_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
local_info_t *local; local_info_t *local;
int err;
DEBUG(0, "attach()\n"); DEBUG(0, "attach()\n");
/* Allocate the device structure */ /* Allocate the device structure */
dev = alloc_etherdev(sizeof(local_info_t)); dev = alloc_etherdev(sizeof(local_info_t));
if (!dev) if (!dev)
return NULL; return -ENOMEM;
local = netdev_priv(dev); local = netdev_priv(dev);
link = &local->link; link = &local->link;
link->priv = dev; link->priv = dev;
@ -614,19 +593,13 @@ xirc2ps_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;
if ((err = pcmcia_register_client(&link->handle, &client_reg))) {
cs_error(link->handle, RegisterClient, err);
xirc2ps_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
xirc2ps_config(link);
return 0;
} /* xirc2ps_attach */ } /* xirc2ps_attach */
/**************** /****************
@ -637,40 +610,19 @@ xirc2ps_attach(void)
*/ */
static void static void
xirc2ps_detach(dev_link_t * link) xirc2ps_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, "detach(0x%p)\n", link); DEBUG(0, "detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (!*linkp) {
DEBUG(0, "detach(0x%p): dev_link lost\n", link);
return;
}
if (link->dev) if (link->dev)
unregister_netdev(dev); unregister_netdev(dev);
/*
* 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)
xirc2ps_release(link); xirc2ps_release(link);
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free it */
*linkp = link->next;
free_netdev(dev); free_netdev(dev);
} /* xirc2ps_detach */ } /* xirc2ps_detach */
@ -1157,67 +1109,41 @@ xirc2ps_release(dev_link_t *link)
/*====================================================================*/ /*====================================================================*/
/****************
* 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.
*
* When a CARD_REMOVAL event is received, we immediately set a 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 static int xirc2ps_suspend(struct pcmcia_device *p_dev)
xirc2ps_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(0, "event(%d)\n", (int)event);
switch (event) {
case CS_EVENT_REGISTRATION_COMPLETE:
DEBUG(0, "registration complete\n");
break;
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;
xirc2ps_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);
do_powerdown(dev); do_powerdown(dev);
} }
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
} }
break;
case CS_EVENT_PM_RESUME: return 0;
}
static int xirc2ps_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) {
do_reset(dev,1); do_reset(dev,1);
netif_device_attach(dev); netif_device_attach(dev);
} }
} }
break;
} return 0;
return 0; }
} /* xirc2ps_event */
/*====================================================================*/ /*====================================================================*/
@ -2009,10 +1935,11 @@ static struct pcmcia_driver xirc2ps_cs_driver = {
.drv = { .drv = {
.name = "xirc2ps_cs", .name = "xirc2ps_cs",
}, },
.attach = xirc2ps_attach, .probe = xirc2ps_attach,
.event = xirc2ps_event, .remove = xirc2ps_detach,
.detach = xirc2ps_detach,
.id_table = xirc2ps_ids, .id_table = xirc2ps_ids,
.suspend = xirc2ps_suspend,
.resume = xirc2ps_resume,
}; };
static int __init static int __init
@ -2025,7 +1952,6 @@ static void __exit
exit_xirc2ps_cs(void) exit_xirc2ps_cs(void)
{ {
pcmcia_unregister_driver(&xirc2ps_cs_driver); pcmcia_unregister_driver(&xirc2ps_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_xirc2ps_cs); module_init(init_xirc2ps_cs);

View File

@ -82,8 +82,6 @@ MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
static void airo_config(dev_link_t *link); static void airo_config(dev_link_t *link);
static void airo_release(dev_link_t *link); static void airo_release(dev_link_t *link);
static int airo_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
@ -91,8 +89,7 @@ static int airo_event(event_t event, int priority,
needed to manage one actual PCMCIA card. needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *airo_attach(void); static void airo_detach(struct pcmcia_device *p_dev);
static void airo_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
@ -101,14 +98,6 @@ static void airo_detach(dev_link_t *);
less on other parts of the kernel. less on other parts of the kernel.
*/ */
/*
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 = "airo_cs";
/* /*
A linked list of "instances" of the aironet device. Each actual A linked list of "instances" of the aironet device. Each actual
PCMCIA card corresponds to one device instance, and is described PCMCIA card corresponds to one device instance, and is described
@ -119,15 +108,7 @@ static dev_info_t dev_info = "airo_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
@ -160,20 +141,18 @@ typedef struct local_info_t {
======================================================================*/ ======================================================================*/
static dev_link_t *airo_attach(void) static int airo_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, "airo_attach()\n"); DEBUG(0, "airo_attach()\n");
/* Initialize the dev_link_t structure */ /* Initialize the dev_link_t structure */
link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) { if (!link) {
printk(KERN_ERR "airo_cs: no memory for new device\n"); printk(KERN_ERR "airo_cs: no memory for new device\n");
return NULL; return -ENOMEM;
} }
/* Interrupt setup */ /* Interrupt setup */
@ -197,24 +176,17 @@ static dev_link_t *airo_attach(void)
if (!local) { if (!local) {
printk(KERN_ERR "airo_cs: no memory for new device\n"); printk(KERN_ERR "airo_cs: no memory for new device\n");
kfree (link); kfree (link);
return NULL; return -ENOMEM;
} }
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; airo_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);
airo_detach(link);
return NULL;
}
return link;
} /* airo_attach */ } /* airo_attach */
/*====================================================================== /*======================================================================
@ -226,37 +198,22 @@ static dev_link_t *airo_attach(void)
======================================================================*/ ======================================================================*/
static void airo_detach(dev_link_t *link) static void airo_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "airo_detach(0x%p)\n", link); DEBUG(0, "airo_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)
airo_release(link); airo_release(link);
if ( ((local_info_t*)link->priv)->eth_dev ) { if ( ((local_info_t*)link->priv)->eth_dev ) {
stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 ); stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
} }
((local_info_t*)link->priv)->eth_dev = NULL; ((local_info_t*)link->priv)->eth_dev = NULL;
/* 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);
} /* airo_detach */ } /* airo_detach */
/*====================================================================== /*======================================================================
@ -492,60 +449,34 @@ static void airo_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*====================================================================== static int airo_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 airo_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 *local = link->priv; local_info_t *local = link->priv;
DEBUG(1, "airo_event(0x%06x)\n", event); link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
switch (event) { netif_device_detach(local->eth_dev);
case CS_EVENT_CARD_REMOVAL: pcmcia_release_configuration(link->handle);
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(local->eth_dev);
airo_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
airo_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
netif_device_detach(local->eth_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);
reset_airo_card(local->eth_dev);
netif_device_attach(local->eth_dev);
}
break;
} }
return 0; return 0;
} /* airo_event */ }
static int airo_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
local_info_t *local = link->priv;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
reset_airo_card(local->eth_dev);
netif_device_attach(local->eth_dev);
}
return 0;
}
static struct pcmcia_device_id airo_ids[] = { static struct pcmcia_device_id airo_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a),
@ -561,10 +492,11 @@ static struct pcmcia_driver airo_driver = {
.drv = { .drv = {
.name = "airo_cs", .name = "airo_cs",
}, },
.attach = airo_attach, .probe = airo_attach,
.event = airo_event, .remove = airo_detach,
.detach = airo_detach,
.id_table = airo_ids, .id_table = airo_ids,
.suspend = airo_suspend,
.resume = airo_resume,
}; };
static int airo_cs_init(void) static int airo_cs_init(void)
@ -575,7 +507,6 @@ static int airo_cs_init(void)
static void airo_cs_cleanup(void) static void airo_cs_cleanup(void)
{ {
pcmcia_unregister_driver(&airo_driver); pcmcia_unregister_driver(&airo_driver);
BUG_ON(dev_list != NULL);
} }
/* /*

View File

@ -93,8 +93,6 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards");
static void atmel_config(dev_link_t *link); static void atmel_config(dev_link_t *link);
static void atmel_release(dev_link_t *link); static void atmel_release(dev_link_t *link);
static int atmel_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
@ -102,8 +100,7 @@ static int atmel_event(event_t event, int priority,
needed to manage one actual PCMCIA card. needed to manage one actual PCMCIA card.
*/ */
static dev_link_t *atmel_attach(void); static void atmel_detach(struct pcmcia_device *p_dev);
static void atmel_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
@ -112,14 +109,6 @@ static void atmel_detach(dev_link_t *);
less on other parts of the kernel. less on other parts of the kernel.
*/ */
/*
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 = "atmel_cs";
/* /*
A linked list of "instances" of the atmelnet device. Each actual A linked list of "instances" of the atmelnet device. Each actual
PCMCIA card corresponds to one device instance, and is described PCMCIA card corresponds to one device instance, and is described
@ -130,15 +119,7 @@ static dev_info_t dev_info = "atmel_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
@ -171,27 +152,25 @@ typedef struct local_info_t {
======================================================================*/ ======================================================================*/
static dev_link_t *atmel_attach(void) static int atmel_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, "atmel_attach()\n"); DEBUG(0, "atmel_attach()\n");
/* Initialize the dev_link_t structure */ /* Initialize the dev_link_t structure */
link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) { if (!link) {
printk(KERN_ERR "atmel_cs: no memory for new device\n"); printk(KERN_ERR "atmel_cs: no memory for new device\n");
return NULL; return -ENOMEM;
} }
/* Interrupt setup */ /* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.IRQInfo1 = IRQ_LEVEL_ID; link->irq.IRQInfo1 = IRQ_LEVEL_ID;
link->irq.Handler = NULL; link->irq.Handler = NULL;
/* /*
General socket configuration defaults can go here. In this General socket configuration defaults can go here. In this
client, we assume very little, and rely on the CIS for almost client, we assume very little, and rely on the CIS for almost
@ -202,30 +181,23 @@ static dev_link_t *atmel_attach(void)
link->conf.Attributes = 0; link->conf.Attributes = 0;
link->conf.Vcc = 50; link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
local = kzalloc(sizeof(local_info_t), GFP_KERNEL); local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) { if (!local) {
printk(KERN_ERR "atmel_cs: no memory for new device\n"); printk(KERN_ERR "atmel_cs: no memory for new device\n");
kfree (link); kfree (link);
return NULL; return -ENOMEM;
} }
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; atmel_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);
atmel_detach(link);
return NULL;
}
return link;
} /* atmel_attach */ } /* atmel_attach */
/*====================================================================== /*======================================================================
@ -237,27 +209,15 @@ static dev_link_t *atmel_attach(void)
======================================================================*/ ======================================================================*/
static void atmel_detach(dev_link_t *link) static void atmel_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "atmel_detach(0x%p)\n", link); DEBUG(0, "atmel_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)
atmel_release(link); atmel_release(link);
/* 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);
} }
@ -477,60 +437,34 @@ static void atmel_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/*====================================================================== static int atmel_suspend(struct pcmcia_device *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 atmel_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(dev);
local_info_t *local = link->priv; local_info_t *local = link->priv;
DEBUG(1, "atmel_event(0x%06x)\n", event); link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
switch (event) { netif_device_detach(local->eth_dev);
case CS_EVENT_CARD_REMOVAL: pcmcia_release_configuration(link->handle);
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(local->eth_dev);
atmel_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
atmel_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
netif_device_detach(local->eth_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);
atmel_open(local->eth_dev);
netif_device_attach(local->eth_dev);
}
break;
} }
return 0; return 0;
} /* atmel_event */ }
static int atmel_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
local_info_t *local = link->priv;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
atmel_open(local->eth_dev);
netif_device_attach(local->eth_dev);
}
return 0;
}
/*====================================================================*/ /*====================================================================*/
/* We use the driver_info field to store the correct firmware type for a card. */ /* We use the driver_info field to store the correct firmware type for a card. */
@ -581,10 +515,11 @@ static struct pcmcia_driver atmel_driver = {
.drv = { .drv = {
.name = "atmel_cs", .name = "atmel_cs",
}, },
.attach = atmel_attach, .probe = atmel_attach,
.event = atmel_event, .remove = atmel_detach,
.detach = atmel_detach,
.id_table = atmel_ids, .id_table = atmel_ids,
.suspend = atmel_suspend,
.resume = atmel_resume,
}; };
static int atmel_cs_init(void) static int atmel_cs_init(void)
@ -595,7 +530,6 @@ static int atmel_cs_init(void)
static void atmel_cs_cleanup(void) static void atmel_cs_cleanup(void)
{ {
pcmcia_unregister_driver(&atmel_driver); pcmcia_unregister_driver(&atmel_driver);
BUG_ON(dev_list != NULL);
} }
/* /*

View File

@ -25,7 +25,6 @@
static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)"; static char *version = PRISM2_VERSION " (Jouni Malinen <jkmaline@cc.hut.fi>)";
static dev_info_t dev_info = "hostap_cs"; static dev_info_t dev_info = "hostap_cs";
static dev_link_t *dev_list = NULL;
MODULE_AUTHOR("Jouni Malinen"); MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN "
@ -203,10 +202,9 @@ static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
static void prism2_detach(dev_link_t *link); static void prism2_detach(struct pcmcia_device *p_dev);
static void prism2_release(u_long arg); static void prism2_release(u_long arg);
static int prism2_event(event_t event, int priority, static int prism2_config(dev_link_t *link);
event_callback_args_t *args);
static int prism2_pccard_card_present(local_info_t *local) static int prism2_pccard_card_present(local_info_t *local)
@ -503,15 +501,13 @@ static struct prism2_helper_functions prism2_pccard_funcs =
/* allocate local data and register with CardServices /* allocate local data and register with CardServices
* initialize dev_link structure, but do not configure the card yet */ * initialize dev_link structure, but do not configure the card yet */
static dev_link_t *prism2_attach(void) static int prism2_attach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
link = kmalloc(sizeof(dev_link_t), GFP_KERNEL); link = kmalloc(sizeof(dev_link_t), GFP_KERNEL);
if (link == NULL) if (link == NULL)
return NULL; return -ENOMEM;
memset(link, 0, sizeof(dev_link_t)); memset(link, 0, sizeof(dev_link_t));
@ -519,50 +515,27 @@ static dev_link_t *prism2_attach(void)
link->conf.Vcc = 33; link->conf.Vcc = 33;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* register with CardServices */ 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; if (prism2_config(link))
client_reg.event_callback_args.client_data = link; PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) { return 0;
cs_error(link->handle, RegisterClient, ret);
prism2_detach(link);
return NULL;
}
return link;
} }
static void prism2_detach(dev_link_t *link) static void prism2_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
PDEBUG(DEBUG_FLOW, "prism2_detach\n"); PDEBUG(DEBUG_FLOW, "prism2_detach\n");
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp == NULL) {
printk(KERN_WARNING "%s: Attempt to detach non-existing "
"PCMCIA client\n", dev_info);
return;
}
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
prism2_release((u_long)link); prism2_release((u_long)link);
} }
if (link->handle) {
int res = pcmcia_deregister_client(link->handle);
if (res) {
printk("CardService(DeregisterClient) => %d\n", res);
cs_error(link->handle, DeregisterClient, res);
}
}
*linkp = link->next;
/* release net devices */ /* release net devices */
if (link->priv) { if (link->priv) {
struct hostap_cs_priv *hw_priv; struct hostap_cs_priv *hw_priv;
@ -846,83 +819,57 @@ static void prism2_release(u_long arg)
PDEBUG(DEBUG_FLOW, "release - done\n"); PDEBUG(DEBUG_FLOW, "release - done\n");
} }
static int hostap_cs_suspend(struct pcmcia_device *p_dev)
static int prism2_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 = (struct net_device *) link->priv; struct net_device *dev = (struct net_device *) link->priv;
int dev_open = 0; int dev_open = 0;
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
struct hostap_interface *iface = netdev_priv(dev); struct hostap_interface *iface = netdev_priv(dev);
if (iface && iface->local) if (iface && iface->local)
dev_open = iface->local->num_dev_open > 0; dev_open = iface->local->num_dev_open > 0;
} if (dev_open) {
switch (event) {
case CS_EVENT_CARD_INSERTION:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_INSERTION\n", dev_info);
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
if (prism2_config(link)) {
PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n");
}
break;
case CS_EVENT_CARD_REMOVAL:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_REMOVAL\n", dev_info);
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_stop_queue(dev); netif_stop_queue(dev);
netif_device_detach(dev); netif_device_detach(dev);
prism2_release((u_long) link);
} }
break; prism2_suspend(dev);
pcmcia_release_configuration(link->handle);
case CS_EVENT_PM_SUSPEND:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info);
link->state |= DEV_SUSPEND;
/* fall through */
case CS_EVENT_RESET_PHYSICAL:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_RESET_PHYSICAL\n", dev_info);
if (link->state & DEV_CONFIG) {
if (dev_open) {
netif_stop_queue(dev);
netif_device_detach(dev);
}
prism2_suspend(dev);
pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_PM_RESUME:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
link->state &= ~DEV_SUSPEND;
/* fall through */
case CS_EVENT_CARD_RESET:
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_CARD_RESET\n", dev_info);
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle,
&link->conf);
prism2_hw_shutdown(dev, 1);
prism2_hw_config(dev, dev_open ? 0 : 1);
if (dev_open) {
netif_device_attach(dev);
netif_start_queue(dev);
}
}
break;
default:
PDEBUG(DEBUG_EXTRA, "%s: prism2_event() - unknown event %d\n",
dev_info, event);
break;
} }
return 0; return 0;
} }
static int hostap_cs_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = (struct net_device *) link->priv;
int dev_open = 0;
PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info);
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
struct hostap_interface *iface = netdev_priv(dev);
if (iface && iface->local)
dev_open = iface->local->num_dev_open > 0;
pcmcia_request_configuration(link->handle, &link->conf);
prism2_hw_shutdown(dev, 1);
prism2_hw_config(dev, dev_open ? 0 : 1);
if (dev_open) {
netif_device_attach(dev);
netif_start_queue(dev);
}
}
return 0;
}
static struct pcmcia_device_id hostap_cs_ids[] = { static struct pcmcia_device_id hostap_cs_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100),
@ -982,11 +929,12 @@ static struct pcmcia_driver hostap_driver = {
.drv = { .drv = {
.name = "hostap_cs", .name = "hostap_cs",
}, },
.attach = prism2_attach, .probe = prism2_attach,
.detach = prism2_detach, .remove = prism2_detach,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.event = prism2_event,
.id_table = hostap_cs_ids, .id_table = hostap_cs_ids,
.suspend = hostap_cs_suspend,
.resume = hostap_cs_resume,
}; };
static int __init init_prism2_pccard(void) static int __init init_prism2_pccard(void)

View File

@ -166,8 +166,6 @@ static char *version =
#define DEBUG(n, args...) #define DEBUG(n, args...)
#endif #endif
static dev_info_t dev_info = "netwave_cs";
/*====================================================================*/ /*====================================================================*/
/* Parameters that can be set with 'insmod' */ /* Parameters that can be set with 'insmod' */
@ -195,12 +193,9 @@ module_param(mem_speed, int, 0);
/* PCMCIA (Card Services) related functions */ /* PCMCIA (Card Services) related functions */
static void netwave_release(dev_link_t *link); /* Card removal */ static void netwave_release(dev_link_t *link); /* Card removal */
static int netwave_event(event_t event, int priority,
event_callback_args_t *args);
static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card static void netwave_pcmcia_config(dev_link_t *arg); /* Runs after card
insertion */ insertion */
static dev_link_t *netwave_attach(void); /* Create instance */ static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */
static void netwave_detach(dev_link_t *); /* Destroy instance */
/* Hardware configuration */ /* Hardware configuration */
static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase); static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase);
@ -227,17 +222,6 @@ static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev); static void set_multicast_list(struct net_device *dev);
/*
A linked list of "instances" of the skeleton 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;
/* /*
A dev_link_t structure has fields for most things that are needed 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 to keep track of a socket, but there will usually be some device
@ -394,20 +378,18 @@ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
* configure the card at this point -- we wait until we receive a * configure the card at this point -- we wait until we receive a
* card insertion event. * card insertion event.
*/ */
static dev_link_t *netwave_attach(void) static int netwave_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
netwave_private *priv; netwave_private *priv;
int ret;
DEBUG(0, "netwave_attach()\n"); DEBUG(0, "netwave_attach()\n");
/* Initialize the dev_link_t structure */ /* Initialize the dev_link_t structure */
dev = alloc_etherdev(sizeof(netwave_private)); dev = alloc_etherdev(sizeof(netwave_private));
if (!dev) if (!dev)
return NULL; return -ENOMEM;
priv = netdev_priv(dev); priv = netdev_priv(dev);
link = &priv->link; link = &priv->link;
link->priv = dev; link->priv = dev;
@ -449,21 +431,14 @@ static dev_link_t *netwave_attach(void)
dev->open = &netwave_open; dev->open = &netwave_open;
dev->stop = &netwave_close; dev->stop = &netwave_close;
link->irq.Instance = dev; link->irq.Instance = dev;
/* 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);
netwave_detach(link);
return NULL;
}
return link; link->handle = p_dev;
p_dev->instance = link;
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
netwave_pcmcia_config( link);
return 0;
} /* netwave_attach */ } /* netwave_attach */
/* /*
@ -474,42 +449,20 @@ static dev_link_t *netwave_attach(void)
* structures are freed. Otherwise, the structures will be freed * structures are freed. Otherwise, the structures will be freed
* when the device is released. * when the device is released.
*/ */
static void netwave_detach(dev_link_t *link) static void netwave_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, "netwave_detach(0x%p)\n", link); DEBUG(0, "netwave_detach(0x%p)\n", link);
/*
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)
netwave_release(link);
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
{
DEBUG(1, "netwave_cs: detach fail, '%s' not in list\n",
link->dev->dev_name);
return;
}
/* Unlink device structure, free pieces */ if (link->state & DEV_CONFIG)
*linkp = link->next; netwave_release(link);
if (link->dev)
unregister_netdev(dev); if (link->dev)
free_netdev(dev); unregister_netdev(dev);
free_netdev(dev);
} /* netwave_detach */ } /* netwave_detach */
/* /*
@ -935,69 +888,38 @@ static void netwave_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/* static int netwave_suspend(struct pcmcia_device *p_dev)
* Function netwave_event (event, priority, args)
*
* 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.
*
* When a CARD_REMOVAL event is received, we immediately set a 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 netwave_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, "netwave_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_REGISTRATION_COMPLETE:
DEBUG(0, "netwave_cs: registration complete\n");
break;
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
netif_device_detach(dev);
netwave_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
netwave_pcmcia_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 netwave_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) {
netwave_reset(dev); netwave_reset(dev);
netif_device_attach(dev); netif_device_attach(dev);
} }
} }
break;
} return 0;
return 0; }
} /* netwave_event */
/* /*
* Function netwave_doreset (ioBase, ramBase) * Function netwave_doreset (ioBase, ramBase)
@ -1491,10 +1413,11 @@ static struct pcmcia_driver netwave_driver = {
.drv = { .drv = {
.name = "netwave_cs", .name = "netwave_cs",
}, },
.attach = netwave_attach, .probe = netwave_attach,
.event = netwave_event, .remove = netwave_detach,
.detach = netwave_detach,
.id_table = netwave_ids, .id_table = netwave_ids,
.suspend = netwave_suspend,
.resume = netwave_resume,
}; };
static int __init init_netwave_cs(void) static int __init init_netwave_cs(void)
@ -1505,7 +1428,6 @@ static int __init init_netwave_cs(void)
static void __exit exit_netwave_cs(void) static void __exit exit_netwave_cs(void)
{ {
pcmcia_unregister_driver(&netwave_driver); pcmcia_unregister_driver(&netwave_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_netwave_cs); module_init(init_netwave_cs);

View File

@ -42,17 +42,6 @@ static int ignore_cis_vcc; /* = 0 */
module_param(ignore_cis_vcc, int, 0); module_param(ignore_cis_vcc, int, 0);
MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
/********************************************************************/
/* Magic constants */
/********************************************************************/
/*
* 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 = DRIVER_NAME;
/********************************************************************/ /********************************************************************/
/* Data structures */ /* Data structures */
/********************************************************************/ /********************************************************************/
@ -69,19 +58,14 @@ struct orinoco_pccard {
unsigned long hard_reset_in_progress; unsigned long hard_reset_in_progress;
}; };
/*
* A linked list of "instances" of the device. Each actual PCMCIA
* card corresponds to one device instance, and is described by one
* dev_link_t structure (defined in ds.h).
*/
static dev_link_t *dev_list; /* = NULL */
/********************************************************************/ /********************************************************************/
/* Function prototypes */ /* Function prototypes */
/********************************************************************/ /********************************************************************/
static void orinoco_cs_config(dev_link_t *link);
static void orinoco_cs_release(dev_link_t *link); static void orinoco_cs_release(dev_link_t *link);
static void orinoco_cs_detach(dev_link_t *link); static void orinoco_cs_detach(struct pcmcia_device *p_dev);
/********************************************************************/ /********************************************************************/
/* Device methods */ /* Device methods */
@ -119,19 +103,17 @@ orinoco_cs_hard_reset(struct orinoco_private *priv)
* The dev_link structure is initialized, but we don't actually * The dev_link structure is initialized, but we don't actually
* configure the card at this point -- we wait until we receive a card * configure the card at this point -- we wait until we receive a card
* insertion event. */ * insertion event. */
static dev_link_t * static int
orinoco_cs_attach(void) orinoco_cs_attach(struct pcmcia_device *p_dev)
{ {
struct net_device *dev; struct net_device *dev;
struct orinoco_private *priv; struct orinoco_private *priv;
struct orinoco_pccard *card; struct orinoco_pccard *card;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
if (! dev) if (! dev)
return NULL; return -ENOMEM;
priv = netdev_priv(dev); priv = netdev_priv(dev);
card = priv->card; card = priv->card;
@ -154,22 +136,15 @@ orinoco_cs_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ /* Register with Card Services */
/* FIXME: need a lock? */ link->next = NULL;
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info; link->handle = p_dev;
client_reg.Version = 0x0210; /* FIXME: what does this mean? */ p_dev->instance = link;
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) { orinoco_cs_config(link);
cs_error(link->handle, RegisterClient, ret);
orinoco_cs_detach(link);
return NULL;
}
return link; return 0;
} /* orinoco_cs_attach */ } /* orinoco_cs_attach */
/* /*
@ -178,27 +153,14 @@ orinoco_cs_attach(void)
* are freed. Otherwise, the structures will be freed when the device * are freed. Otherwise, the structures will be freed when the device
* is released. * is released.
*/ */
static void orinoco_cs_detach(dev_link_t *link) static void orinoco_cs_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
BUG_ON(*linkp == NULL);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
orinoco_cs_release(link); orinoco_cs_release(link);
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, and free it */
*linkp = link->next;
DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
if (link->dev) { if (link->dev) {
DEBUG(0, PFX "About to unregister net device %p\n", DEBUG(0, PFX "About to unregister net device %p\n",
@ -465,106 +427,82 @@ orinoco_cs_release(dev_link_t *link)
ioport_unmap(priv->hw.iobase); ioport_unmap(priv->hw.iobase);
} /* orinoco_cs_release */ } /* orinoco_cs_release */
/* static int orinoco_cs_suspend(struct pcmcia_device *p_dev)
* The card status event handler. Mostly, this schedules other stuff
* to run after an event is received.
*/
static int
orinoco_cs_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;
struct orinoco_private *priv = netdev_priv(dev); struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card; struct orinoco_pccard *card = priv->card;
int err = 0; int err = 0;
unsigned long flags; unsigned long flags;
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG) {
link->state &= ~DEV_PRESENT; /* This is probably racy, but I can't think of
if (link->state & DEV_CONFIG) { a better way, short of rewriting the PCMCIA
unsigned long flags; layer to not suck :-( */
if (! test_bit(0, &card->hard_reset_in_progress)) {
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
err = __orinoco_down(dev);
if (err)
printk(KERN_WARNING "%s: Error %d downing interface\n",
dev->name, err);
netif_device_detach(dev); netif_device_detach(dev);
priv->hw_unavailable++; priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
} }
break;
case CS_EVENT_CARD_INSERTION: pcmcia_release_configuration(link->handle);
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
orinoco_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 */
if (link->state & DEV_CONFIG) {
/* This is probably racy, but I can't think of
a better way, short of rewriting the PCMCIA
layer to not suck :-( */
if (! test_bit(0, &card->hard_reset_in_progress)) {
spin_lock_irqsave(&priv->lock, flags);
err = __orinoco_down(dev);
if (err)
printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
dev->name,
event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
err);
netif_device_detach(dev);
priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags);
}
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) {
/* FIXME: should we double check that this is
* the same card as we had before */
pcmcia_request_configuration(link->handle, &link->conf);
if (! test_bit(0, &card->hard_reset_in_progress)) {
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
dev->name, err);
break;
}
spin_lock_irqsave(&priv->lock, flags);
netif_device_attach(dev);
priv->hw_unavailable--;
if (priv->open && ! priv->hw_unavailable) {
err = __orinoco_up(dev);
if (err)
printk(KERN_ERR "%s: Error %d restarting card\n",
dev->name, err);
}
spin_unlock_irqrestore(&priv->lock, flags);
}
}
break;
} }
return err; return 0;
} /* orinoco_cs_event */ }
static int orinoco_cs_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card;
int err = 0;
unsigned long flags;
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
/* FIXME: should we double check that this is
* the same card as we had before */
pcmcia_request_configuration(link->handle, &link->conf);
if (! test_bit(0, &card->hard_reset_in_progress)) {
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
dev->name, err);
return -EIO;
}
spin_lock_irqsave(&priv->lock, flags);
netif_device_attach(dev);
priv->hw_unavailable--;
if (priv->open && ! priv->hw_unavailable) {
err = __orinoco_up(dev);
if (err)
printk(KERN_ERR "%s: Error %d restarting card\n",
dev->name, err);
}
spin_unlock_irqrestore(&priv->lock, flags);
}
}
return 0;
}
/********************************************************************/ /********************************************************************/
/* Module initialization */ /* Module initialization */
@ -665,10 +603,11 @@ static struct pcmcia_driver orinoco_driver = {
.drv = { .drv = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
}, },
.attach = orinoco_cs_attach, .probe = orinoco_cs_attach,
.detach = orinoco_cs_detach, .remove = orinoco_cs_detach,
.event = orinoco_cs_event,
.id_table = orinoco_cs_ids, .id_table = orinoco_cs_ids,
.suspend = orinoco_cs_suspend,
.resume = orinoco_cs_resume,
}; };
static int __init static int __init
@ -683,7 +622,6 @@ static void __exit
exit_orinoco_cs(void) exit_orinoco_cs(void)
{ {
pcmcia_unregister_driver(&orinoco_driver); pcmcia_unregister_driver(&orinoco_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_orinoco_cs); module_init(init_orinoco_cs);

View File

@ -92,9 +92,7 @@ module_param(pc_debug, int, 0);
/** Prototypes based on PCMCIA skeleton driver *******************************/ /** Prototypes based on PCMCIA skeleton driver *******************************/
static void ray_config(dev_link_t *link); static void ray_config(dev_link_t *link);
static void ray_release(dev_link_t *link); static void ray_release(dev_link_t *link);
static int ray_event(event_t event, int priority, event_callback_args_t *args); static void ray_detach(struct pcmcia_device *p_dev);
static dev_link_t *ray_attach(void);
static void ray_detach(dev_link_t *);
/***** Prototypes indicated by device structure ******************************/ /***** Prototypes indicated by device structure ******************************/
static int ray_dev_close(struct net_device *dev); static int ray_dev_close(struct net_device *dev);
@ -192,12 +190,6 @@ static int bc;
static char *phy_addr = NULL; static char *phy_addr = NULL;
/* 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 = "ray_cs";
/* A linked list of "instances" of the ray device. Each actual /* A linked list of "instances" of the ray device. Each actual
PCMCIA card corresponds to one device instance, and is described PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h). by one dev_link_t structure (defined in ds.h).
@ -314,12 +306,10 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.
configure the card at this point -- we wait until we receive a configure the card at this point -- we wait until we receive a
card insertion event. card insertion event.
=============================================================================*/ =============================================================================*/
static dev_link_t *ray_attach(void) static int ray_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
ray_dev_t *local; ray_dev_t *local;
int ret;
struct net_device *dev; struct net_device *dev;
DEBUG(1, "ray_attach()\n"); DEBUG(1, "ray_attach()\n");
@ -328,7 +318,7 @@ static dev_link_t *ray_attach(void)
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;
/* Allocate space for private device-specific data */ /* Allocate space for private device-specific data */
dev = alloc_etherdev(sizeof(ray_dev_t)); dev = alloc_etherdev(sizeof(ray_dev_t));
@ -387,30 +377,19 @@ static dev_link_t *ray_attach(void)
dev->stop = &ray_dev_close; dev->stop = &ray_dev_close;
netif_stop_queue(dev); netif_stop_queue(dev);
/* 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;
DEBUG(2,"ray_cs ray_attach calling pcmcia_register_client(...)\n");
init_timer(&local->timer); init_timer(&local->timer);
ret = pcmcia_register_client(&link->handle, &client_reg); link->handle = p_dev;
if (ret != 0) { p_dev->instance = link;
printk("ray_cs ray_attach RegisterClient unhappy - detaching\n");
cs_error(link->handle, RegisterClient, ret); link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
ray_detach(link); ray_config(link);
return NULL;
} return 0;
DEBUG(2,"ray_cs ray_attach ending\n");
return link;
fail_alloc_dev: fail_alloc_dev:
kfree(link); kfree(link);
return NULL; return -ENOMEM;
} /* ray_attach */ } /* ray_attach */
/*============================================================================= /*=============================================================================
This deletes a driver "instance". The device is de-registered This deletes a driver "instance". The device is de-registered
@ -418,9 +397,12 @@ fail_alloc_dev:
structures are freed. Otherwise, the structures will be freed structures are freed. Otherwise, the structures will be freed
when the device is released. when the device is released.
=============================================================================*/ =============================================================================*/
static void ray_detach(dev_link_t *link) static void ray_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
dev_link_t **linkp; dev_link_t **linkp;
struct net_device *dev;
ray_dev_t *local;
DEBUG(1, "ray_detach(0x%p)\n", link); DEBUG(1, "ray_detach(0x%p)\n", link);
@ -430,22 +412,18 @@ static void ray_detach(dev_link_t *link)
if (*linkp == NULL) if (*linkp == NULL)
return; return;
/* If the device is currently configured and active, we won't dev = link->priv;
actually delete it yet. Instead, it is marked so that when
the release() function is called, that will trigger a proper if (link->state & DEV_CONFIG) {
detach(). ray_release(link);
*/
if (link->state & DEV_CONFIG) local = (ray_dev_t *)dev->priv;
ray_release(link); del_timer(&local->timer);
}
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free pieces */ /* Unlink device structure, free pieces */
*linkp = link->next; *linkp = link->next;
if (link->priv) { if (link->priv) {
struct net_device *dev = link->priv;
if (link->dev) unregister_netdev(dev); if (link->dev) unregister_netdev(dev);
free_netdev(dev); free_netdev(dev);
} }
@ -891,65 +869,40 @@ static void ray_release(dev_link_t *link)
DEBUG(2,"ray_release ending\n"); DEBUG(2,"ray_release ending\n");
} }
/*============================================================================= static int ray_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.
When a CARD_REMOVAL event is received, we immediately set a 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 ray_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;
ray_dev_t *local = (ray_dev_t *)dev->priv;
DEBUG(1, "ray_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
netif_device_detach(dev);
if (link->state & DEV_CONFIG) {
ray_release(link);
del_timer(&local->timer);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
ray_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); link->state |= DEV_SUSPEND;
}
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); if (link->open)
if (link->open) { netif_device_detach(dev);
ray_reset(dev);
netif_device_attach(dev); pcmcia_release_configuration(link->handle);
}
} }
break;
}
return 0; return 0;
DEBUG(2,"ray_event ending\n"); }
} /* ray_event */
static int ray_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;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
ray_reset(dev);
netif_device_attach(dev);
}
}
return 0;
}
/*===========================================================================*/ /*===========================================================================*/
int ray_dev_init(struct net_device *dev) int ray_dev_init(struct net_device *dev)
{ {
@ -2945,10 +2898,11 @@ static struct pcmcia_driver ray_driver = {
.drv = { .drv = {
.name = "ray_cs", .name = "ray_cs",
}, },
.attach = ray_attach, .probe = ray_attach,
.event = ray_event, .remove = ray_detach,
.detach = ray_detach,
.id_table = ray_ids, .id_table = ray_ids,
.suspend = ray_suspend,
.resume = ray_resume,
}; };
static int __init init_ray_cs(void) static int __init init_ray_cs(void)

View File

@ -56,17 +56,6 @@ static int ignore_cis_vcc; /* = 0 */
module_param(ignore_cis_vcc, int, 0); module_param(ignore_cis_vcc, int, 0);
MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
/********************************************************************/
/* Magic constants */
/********************************************************************/
/*
* 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 = DRIVER_NAME;
/********************************************************************/ /********************************************************************/
/* Data structures */ /* Data structures */
/********************************************************************/ /********************************************************************/
@ -78,19 +67,12 @@ struct orinoco_pccard {
dev_node_t node; dev_node_t node;
}; };
/*
* A linked list of "instances" of the device. Each actual PCMCIA
* card corresponds to one device instance, and is described by one
* dev_link_t structure (defined in ds.h).
*/
static dev_link_t *dev_list; /* = NULL */
/********************************************************************/ /********************************************************************/
/* Function prototypes */ /* Function prototypes */
/********************************************************************/ /********************************************************************/
static void spectrum_cs_config(dev_link_t *link);
static void spectrum_cs_release(dev_link_t *link); static void spectrum_cs_release(dev_link_t *link);
static void spectrum_cs_detach(dev_link_t *link);
/********************************************************************/ /********************************************************************/
/* Firmware downloader */ /* Firmware downloader */
@ -601,19 +583,17 @@ spectrum_cs_hard_reset(struct orinoco_private *priv)
* The dev_link structure is initialized, but we don't actually * The dev_link structure is initialized, but we don't actually
* configure the card at this point -- we wait until we receive a card * configure the card at this point -- we wait until we receive a card
* insertion event. */ * insertion event. */
static dev_link_t * static int
spectrum_cs_attach(void) spectrum_cs_attach(struct pcmcia_device *p_dev)
{ {
struct net_device *dev; struct net_device *dev;
struct orinoco_private *priv; struct orinoco_private *priv;
struct orinoco_pccard *card; struct orinoco_pccard *card;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset); dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);
if (! dev) if (! dev)
return NULL; return -ENOMEM;
priv = netdev_priv(dev); priv = netdev_priv(dev);
card = priv->card; card = priv->card;
@ -635,23 +615,13 @@ spectrum_cs_attach(void)
link->conf.Attributes = 0; link->conf.Attributes = 0;
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Register with Card Services */ link->handle = p_dev;
/* FIXME: need a lock? */ p_dev->instance = link;
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; /* FIXME: what does this mean? */ spectrum_cs_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);
spectrum_cs_detach(link);
return NULL;
}
return link;
} /* spectrum_cs_attach */ } /* spectrum_cs_attach */
/* /*
@ -660,27 +630,14 @@ spectrum_cs_attach(void)
* are freed. Otherwise, the structures will be freed when the device * are freed. Otherwise, the structures will be freed when the device
* is released. * is released.
*/ */
static void spectrum_cs_detach(dev_link_t *link) static void spectrum_cs_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
BUG_ON(*linkp == NULL);
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
spectrum_cs_release(link); spectrum_cs_release(link);
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, and free it */
*linkp = link->next;
DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev); DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);
if (link->dev) { if (link->dev) {
DEBUG(0, PFX "About to unregister net device %p\n", DEBUG(0, PFX "About to unregister net device %p\n",
@ -948,82 +905,56 @@ spectrum_cs_release(dev_link_t *link)
ioport_unmap(priv->hw.iobase); ioport_unmap(priv->hw.iobase);
} /* spectrum_cs_release */ } /* spectrum_cs_release */
/*
* The card status event handler. Mostly, this schedules other stuff
* to run after an event is received.
*/
static int static int
spectrum_cs_event(event_t event, int priority, spectrum_cs_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;
struct orinoco_private *priv = netdev_priv(dev); struct orinoco_private *priv = netdev_priv(dev);
int err = 0;
unsigned long flags; unsigned long flags;
int err = 0;
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: /* Mark the device as stopped, to block IO until later */
link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) {
if (link->state & DEV_CONFIG) { spin_lock_irqsave(&priv->lock, flags);
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags); err = __orinoco_down(dev);
netif_device_detach(dev); if (err)
priv->hw_unavailable++; printk(KERN_WARNING "%s: Error %d downing interface\n",
spin_unlock_irqrestore(&priv->lock, flags); dev->name, err);
}
break;
case CS_EVENT_CARD_INSERTION: netif_device_detach(dev);
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; priv->hw_unavailable++;
spectrum_cs_config(link);
break;
case CS_EVENT_PM_SUSPEND: spin_unlock_irqrestore(&priv->lock, flags);
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
/* Mark the device as stopped, to block IO until later */
if (link->state & DEV_CONFIG) {
/* This is probably racy, but I can't think of
a better way, short of rewriting the PCMCIA
layer to not suck :-( */
spin_lock_irqsave(&priv->lock, flags);
err = __orinoco_down(dev); pcmcia_release_configuration(link->handle);
if (err)
printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
dev->name,
event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
err);
netif_device_detach(dev);
priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags);
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) {
/* FIXME: should we double check that this is
* the same card as we had before */
pcmcia_request_configuration(link->handle, &link->conf);
netif_device_attach(dev);
priv->hw_unavailable--;
schedule_work(&priv->reset_work);
}
break;
} }
return err; return 0;
} /* spectrum_cs_event */ }
static int
spectrum_cs_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
/* FIXME: should we double check that this is
* the same card as we had before */
pcmcia_request_configuration(link->handle, &link->conf);
netif_device_attach(dev);
priv->hw_unavailable--;
schedule_work(&priv->reset_work);
}
return 0;
}
/********************************************************************/ /********************************************************************/
/* Module initialization */ /* Module initialization */
@ -1048,9 +979,10 @@ static struct pcmcia_driver orinoco_driver = {
.drv = { .drv = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
}, },
.attach = spectrum_cs_attach, .probe = spectrum_cs_attach,
.detach = spectrum_cs_detach, .remove = spectrum_cs_detach,
.event = spectrum_cs_event, .suspend = spectrum_cs_suspend,
.resume = spectrum_cs_resume,
.id_table = spectrum_cs_ids, .id_table = spectrum_cs_ids,
}; };
@ -1066,7 +998,6 @@ static void __exit
exit_spectrum_cs(void) exit_spectrum_cs(void)
{ {
pcmcia_unregister_driver(&orinoco_driver); pcmcia_unregister_driver(&orinoco_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_spectrum_cs); module_init(init_spectrum_cs);

View File

@ -4594,14 +4594,12 @@ wavelan_close(struct net_device * dev)
* configure the card at this point -- we wait until we receive a * configure the card at this point -- we wait until we receive a
* card insertion event. * card insertion event.
*/ */
static dev_link_t * static int
wavelan_attach(void) wavelan_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg; /* Register with cardmgr */
dev_link_t * link; /* Info for cardmgr */ dev_link_t * link; /* Info for cardmgr */
struct net_device * dev; /* Interface generic data */ struct net_device * dev; /* Interface generic data */
net_local * lp; /* Interface specific data */ net_local * lp; /* Interface specific data */
int ret;
#ifdef DEBUG_CALLBACK_TRACE #ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_attach()\n"); printk(KERN_DEBUG "-> wavelan_attach()\n");
@ -4609,7 +4607,7 @@ wavelan_attach(void)
/* Initialize the dev_link_t structure */ /* Initialize the dev_link_t structure */
link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL); link = kzalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link) return NULL; if (!link) return -ENOMEM;
/* The io structure describes IO port mapping */ /* The io structure describes IO port mapping */
link->io.NumPorts1 = 8; link->io.NumPorts1 = 8;
@ -4627,14 +4625,13 @@ wavelan_attach(void)
link->conf.IntType = INT_MEMORY_AND_IO; link->conf.IntType = INT_MEMORY_AND_IO;
/* Chain drivers */ /* Chain drivers */
link->next = dev_list; link->next = NULL;
dev_list = link;
/* Allocate the generic data structure */ /* Allocate the generic data structure */
dev = alloc_etherdev(sizeof(net_local)); dev = alloc_etherdev(sizeof(net_local));
if (!dev) { if (!dev) {
kfree(link); kfree(link);
return NULL; return -ENOMEM;
} }
link->priv = link->irq.Instance = dev; link->priv = link->irq.Instance = dev;
@ -4679,28 +4676,21 @@ wavelan_attach(void)
/* Other specific data */ /* Other specific data */
dev->mtu = WAVELAN_MTU; dev->mtu = WAVELAN_MTU;
/* Register with Card Services */ link->handle = p_dev;
client_reg.dev_info = &dev_info; p_dev->instance = link;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
#ifdef DEBUG_CONFIG_INFO link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
printk(KERN_DEBUG "wavelan_attach(): almost done, calling pcmcia_register_client\n"); if(wv_pcmcia_config(link) &&
#endif wv_hw_config(dev))
wv_init_info(dev);
ret = pcmcia_register_client(&link->handle, &client_reg); else
if(ret != 0) dev->irq = 0;
{
cs_error(link->handle, RegisterClient, ret);
wavelan_detach(link);
return NULL;
}
#ifdef DEBUG_CALLBACK_TRACE #ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "<- wavelan_attach()\n"); printk(KERN_DEBUG "<- wavelan_attach()\n");
#endif #endif
return link; return 0;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
@ -4711,8 +4701,10 @@ wavelan_attach(void)
* is released. * is released.
*/ */
static void static void
wavelan_detach(dev_link_t * link) wavelan_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
#ifdef DEBUG_CALLBACK_TRACE #ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link);
#endif #endif
@ -4729,31 +4721,6 @@ wavelan_detach(dev_link_t * link)
wv_pcmcia_release(link); wv_pcmcia_release(link);
} }
/* Break the link with Card Services */
if(link->handle)
pcmcia_deregister_client(link->handle);
/* Remove the interface data from the linked list */
if(dev_list == link)
dev_list = link->next;
else
{
dev_link_t * prev = dev_list;
while((prev != (dev_link_t *) NULL) && (prev->next != link))
prev = prev->next;
if(prev == (dev_link_t *) NULL)
{
#ifdef DEBUG_CONFIG_ERRORS
printk(KERN_WARNING "wavelan_detach : Attempting to remove a nonexistent device.\n");
#endif
return;
}
prev->next = link->next;
}
/* Free pieces */ /* Free pieces */
if(link->priv) if(link->priv)
{ {
@ -4775,65 +4742,11 @@ wavelan_detach(dev_link_t * link)
#endif #endif
} }
/*------------------------------------------------------------------*/ static int wavelan_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
wavelan_event(event_t event, /* The event received */
int priority,
event_callback_args_t * args)
{ {
dev_link_t * link = (dev_link_t *) args->client_data; dev_link_t *link = dev_to_instance(p_dev);
struct net_device * dev = (struct net_device *) link->priv; struct net_device * dev = (struct net_device *) link->priv;
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "->wavelan_event(): %s\n",
((event == CS_EVENT_REGISTRATION_COMPLETE)?"registration complete" :
((event == CS_EVENT_CARD_REMOVAL) ? "card removal" :
((event == CS_EVENT_CARD_INSERTION) ? "card insertion" :
((event == CS_EVENT_PM_SUSPEND) ? "pm suspend" :
((event == CS_EVENT_RESET_PHYSICAL) ? "physical reset" :
((event == CS_EVENT_PM_RESUME) ? "pm resume" :
((event == CS_EVENT_CARD_RESET) ? "card reset" :
"unknown"))))))));
#endif
switch(event)
{
case CS_EVENT_REGISTRATION_COMPLETE:
#ifdef DEBUG_CONFIG_INFO
printk(KERN_DEBUG "wavelan_cs: registration complete\n");
#endif
break;
case CS_EVENT_CARD_REMOVAL:
/* Oups ! The card is no more there */
link->state &= ~DEV_PRESENT;
if(link->state & DEV_CONFIG)
{
/* Accept no more transmissions */
netif_device_detach(dev);
/* Release the card */
wv_pcmcia_release(link);
}
break;
case CS_EVENT_CARD_INSERTION:
/* Reset and configure the card */
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
if(wv_pcmcia_config(link) &&
wv_hw_config(dev))
wv_init_info(dev);
else
dev->irq = 0;
break;
case CS_EVENT_PM_SUSPEND:
/* NB: wavelan_close will be called, but too late, so we are /* NB: wavelan_close will be called, but too late, so we are
* obliged to close nicely the wavelan here. David, could you * obliged to close nicely the wavelan here. David, could you
* close the device before suspending them ? And, by the way, * close the device before suspending them ? And, by the way,
@ -4848,38 +4761,37 @@ wavelan_event(event_t event, /* The event received */
/* The card is now suspended */ /* The card is now suspended */
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;
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) /* If RESET -> True, If RESUME -> False ? */
{
wv_hw_reset(dev);
netif_device_attach(dev);
}
}
break;
}
#ifdef DEBUG_CALLBACK_TRACE
printk(KERN_DEBUG "<-wavelan_event()\n");
#endif
return 0;
} }
static int wavelan_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device * dev = (struct net_device *) link->priv;
link->state &= ~DEV_SUSPEND;
if(link->state & DEV_CONFIG)
{
pcmcia_request_configuration(link->handle, &link->conf);
if(link->open) /* If RESET -> True, If RESUME -> False ? */
{
wv_hw_reset(dev);
netif_device_attach(dev);
}
}
return 0;
}
static struct pcmcia_device_id wavelan_ids[] = { static struct pcmcia_device_id wavelan_ids[] = {
PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975),
PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06),
@ -4894,10 +4806,11 @@ static struct pcmcia_driver wavelan_driver = {
.drv = { .drv = {
.name = "wavelan_cs", .name = "wavelan_cs",
}, },
.attach = wavelan_attach, .probe = wavelan_attach,
.event = wavelan_event, .remove = wavelan_detach,
.detach = wavelan_detach,
.id_table = wavelan_ids, .id_table = wavelan_ids,
.suspend = wavelan_suspend,
.resume = wavelan_resume,
}; };
static int __init static int __init

View File

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

View File

@ -105,7 +105,6 @@ module_param(pc_debug, int, 0);
*/ */
static void wl3501_config(dev_link_t *link); static void wl3501_config(dev_link_t *link);
static void wl3501_release(dev_link_t *link); static void wl3501_release(dev_link_t *link);
static int wl3501_event(event_t event, int pri, event_callback_args_t *args);
/* /*
* The dev_info variable is the "key" that is used to match up this * The dev_info variable is the "key" that is used to match up this
@ -1498,9 +1497,11 @@ static struct ethtool_ops ops = {
* Services. If it has been released, all local data structures are freed. * Services. If it has been released, all local data structures are freed.
* Otherwise, the structures will be freed when the device is released. * Otherwise, the structures will be freed when the device is released.
*/ */
static void wl3501_detach(dev_link_t *link) static void wl3501_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
dev_link_t **linkp; dev_link_t **linkp;
struct net_device *dev = link->priv;
/* Locate device structure */ /* Locate device structure */
for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next) for (linkp = &wl3501_dev_list; *linkp; linkp = &(*linkp)->next)
@ -1514,16 +1515,12 @@ static void wl3501_detach(dev_link_t *link)
* function is called, that will trigger a proper detach(). */ * function is called, that will trigger a proper detach(). */
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
#ifdef PCMCIA_DEBUG while (link->open > 0)
printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' " wl3501_close(dev);
"still locked\n", link->dev->dev_name);
#endif
goto out;
}
/* Break the link with Card Services */ netif_device_detach(dev);
if (link->handle) wl3501_release(link);
pcmcia_deregister_client(link->handle); }
/* Unlink device structure, free pieces */ /* Unlink device structure, free pieces */
*linkp = link->next; *linkp = link->next;
@ -1956,18 +1953,16 @@ static const struct iw_handler_def wl3501_handler_def = {
* The dev_link structure is initialized, but we don't actually configure the * The dev_link structure is initialized, but we don't actually configure the
* card at this point -- we wait until we receive a card insertion event. * card at this point -- we wait until we receive a card insertion event.
*/ */
static dev_link_t *wl3501_attach(void) static int wl3501_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
struct net_device *dev; struct net_device *dev;
struct wl3501_card *this; struct wl3501_card *this;
int ret;
/* Initialize the dev_link_t structure */ /* Initialize the dev_link_t structure */
link = kzalloc(sizeof(*link), GFP_KERNEL); link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link) if (!link)
goto out; return -ENOMEM;
/* The io structure describes IO port mapping */ /* The io structure describes IO port mapping */
link->io.NumPorts1 = 16; link->io.NumPorts1 = 16;
@ -2003,24 +1998,17 @@ static dev_link_t *wl3501_attach(void)
netif_stop_queue(dev); netif_stop_queue(dev);
link->priv = link->irq.Instance = dev; link->priv = link->irq.Instance = dev;
/* Register with Card Services */ link->handle = p_dev;
link->next = wl3501_dev_list; p_dev->instance = link;
wl3501_dev_list = link;
client_reg.dev_info = &wl3501_dev_info; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.Version = 0x0210; wl3501_config(link);
client_reg.event_callback_args.client_data = link;
ret = pcmcia_register_client(&link->handle, &client_reg); return 0;
if (ret) {
cs_error(link->handle, RegisterClient, ret);
wl3501_detach(link);
link = NULL;
}
out:
return link;
out_link: out_link:
kfree(link); kfree(link);
link = NULL; link = NULL;
goto out; return -ENOMEM;
} }
#define CS_CHECK(fn, ret) \ #define CS_CHECK(fn, ret) \
@ -2173,67 +2161,41 @@ static void wl3501_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
/** static int wl3501_suspend(struct pcmcia_device *p_dev)
* wl3501_event - The card status event handler
* @event - event
* @pri - priority
* @args - arguments for this 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.
*
* When a CARD_REMOVAL event is received, we immediately set a 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 wl3501_event(event_t event, int pri, 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;
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT; wl3501_pwr_mgmt(dev->priv, WL3501_SUSPEND);
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
while (link->open > 0) if (link->open)
wl3501_close(dev);
netif_device_detach(dev); netif_device_detach(dev);
wl3501_release(link); pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
wl3501_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
wl3501_pwr_mgmt(dev->priv, WL3501_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;
wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
wl3501_reset(dev);
netif_device_attach(dev);
}
}
break;
} }
return 0; return 0;
} }
static int wl3501_resume(struct pcmcia_device *p_dev)
{
dev_link_t *link = dev_to_instance(p_dev);
struct net_device *dev = link->priv;
wl3501_pwr_mgmt(dev->priv, WL3501_RESUME);
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
if (link->open) {
wl3501_reset(dev);
netif_device_attach(dev);
}
}
return 0;
}
static struct pcmcia_device_id wl3501_ids[] = { static struct pcmcia_device_id wl3501_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001),
PCMCIA_DEVICE_NULL PCMCIA_DEVICE_NULL
@ -2245,10 +2207,11 @@ static struct pcmcia_driver wl3501_driver = {
.drv = { .drv = {
.name = "wl3501_cs", .name = "wl3501_cs",
}, },
.attach = wl3501_attach, .probe = wl3501_attach,
.event = wl3501_event, .remove = wl3501_detach,
.detach = wl3501_detach,
.id_table = wl3501_ids, .id_table = wl3501_ids,
.suspend = wl3501_suspend,
.resume = wl3501_resume,
}; };
static int __init wl3501_init_module(void) static int __init wl3501_init_module(void)

View File

@ -87,15 +87,9 @@ typedef struct parport_info_t {
struct parport *port; struct parport *port;
} parport_info_t; } parport_info_t;
static dev_link_t *parport_attach(void); static void parport_detach(struct pcmcia_device *p_dev);
static void parport_detach(dev_link_t *);
static void parport_config(dev_link_t *link); static void parport_config(dev_link_t *link);
static void parport_cs_release(dev_link_t *); static void parport_cs_release(dev_link_t *);
static int parport_event(event_t event, int priority,
event_callback_args_t *args);
static dev_info_t dev_info = "parport_cs";
static dev_link_t *dev_list = NULL;
/*====================================================================== /*======================================================================
@ -105,18 +99,16 @@ static dev_link_t *dev_list = NULL;
======================================================================*/ ======================================================================*/
static dev_link_t *parport_attach(void) static int parport_attach(struct pcmcia_device *p_dev)
{ {
parport_info_t *info; parport_info_t *info;
dev_link_t *link; dev_link_t *link;
client_reg_t client_reg;
int ret;
DEBUG(0, "parport_attach()\n"); DEBUG(0, "parport_attach()\n");
/* Create new parport device */ /* Create new parport 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));
link = &info->link; link->priv = info; link = &info->link; link->priv = info;
@ -127,21 +119,14 @@ static dev_link_t *parport_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; parport_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);
parport_detach(link);
return NULL;
}
return link;
} /* parport_attach */ } /* parport_attach */
/*====================================================================== /*======================================================================
@ -153,32 +138,16 @@ static dev_link_t *parport_attach(void)
======================================================================*/ ======================================================================*/
static void parport_detach(dev_link_t *link) static void parport_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
int ret;
DEBUG(0, "parport_detach(0x%p)\n", link); DEBUG(0, "parport_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)
parport_cs_release(link); parport_cs_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);
} /* parport_detach */ } /* parport_detach */
/*====================================================================== /*======================================================================
@ -325,47 +294,27 @@ void parport_cs_release(dev_link_t *link)
} /* parport_cs_release */ } /* parport_cs_release */
/*====================================================================== static int parport_suspend(struct pcmcia_device *dev)
The card status event handler. Mostly, this schedules other
stuff to run after an event is received.
======================================================================*/
int parport_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(dev);
DEBUG(1, "parport_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
parport_cs_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
parport_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)
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME: return 0;
}
static int parport_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (DEV_OK(link)) if (DEV_OK(link))
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
break;
} return 0;
return 0; }
} /* parport_event */
static struct pcmcia_device_id parport_ids[] = { static struct pcmcia_device_id parport_ids[] = {
PCMCIA_DEVICE_FUNC_ID(3), PCMCIA_DEVICE_FUNC_ID(3),
@ -379,11 +328,11 @@ static struct pcmcia_driver parport_cs_driver = {
.drv = { .drv = {
.name = "parport_cs", .name = "parport_cs",
}, },
.attach = parport_attach, .probe = parport_attach,
.event = parport_event, .remove = parport_detach,
.detach = parport_detach,
.id_table = parport_ids, .id_table = parport_ids,
.suspend = parport_suspend,
.resume = parport_resume,
}; };
static int __init init_parport_cs(void) static int __init init_parport_cs(void)
@ -394,7 +343,6 @@ static int __init init_parport_cs(void)
static void __exit exit_parport_cs(void) static void __exit exit_parport_cs(void)
{ {
pcmcia_unregister_driver(&parport_cs_driver); pcmcia_unregister_driver(&parport_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_parport_cs); module_init(init_parport_cs);

View File

@ -116,6 +116,31 @@ config YENTA
If unsure, say Y. If unsure, say Y.
config YENTA_O2
default y
bool "Special initialization for O2Micro bridges" if EMBEDDED
depends on YENTA
config YENTA_RICOH
default y
bool "Special initialization for Ricoh bridges" if EMBEDDED
depends on YENTA
config YENTA_TI
default y
bool "Special initialization for TI and EnE bridges" if EMBEDDED
depends on YENTA
config YENTA_ENE_TUNE
default y
bool "Auto-tune EnE bridges for CB cards" if EMBEDDED
depends on YENTA_TI && CARDBUS
config YENTA_TOSHIBA
default y
bool "Special initialization for Toshiba ToPIC bridges" if EMBEDDED
depends on YENTA
config PD6729 config PD6729
tristate "Cirrus PD6729 compatible bridge support" tristate "Cirrus PD6729 compatible bridge support"
depends on PCMCIA && PCI depends on PCMCIA && PCI
@ -157,7 +182,7 @@ config TCIC
config PCMCIA_M8XX config PCMCIA_M8XX
tristate "MPC8xx PCMCIA support" tristate "MPC8xx PCMCIA support"
depends on PCMCIA && PPC && 8xx depends on PCMCIA && PPC && 8xx
select PCCARD_NONSTATIC select PCCARD_IODYN
help help
Say Y here to include support for PowerPC 8xx series PCMCIA Say Y here to include support for PowerPC 8xx series PCMCIA
controller. controller.
@ -200,7 +225,7 @@ config PCMCIA_PXA2XX
config PCMCIA_PROBE config PCMCIA_PROBE
bool bool
default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC
config M32R_PCC config M32R_PCC
bool "M32R PCMCIA I/F" bool "M32R PCMCIA I/F"
@ -241,6 +266,9 @@ config OMAP_CF
config PCCARD_NONSTATIC config PCCARD_NONSTATIC
tristate tristate
config PCCARD_IODYN
bool
endif # PCCARD endif # PCCARD
endmenu endmenu

View File

@ -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 = {
.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,
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;
/* /*

View File

@ -60,9 +60,9 @@ static const u_int exponent[] = {
/* Parameters that can be set with 'insmod' */ /* Parameters that can be set with 'insmod' */
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) /* 16-bit CIS? */
static int cis_width;
INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */ module_param(cis_width, int, 0444);
void release_cis_mem(struct pcmcia_socket *s) void release_cis_mem(struct pcmcia_socket *s)
{ {
@ -463,7 +463,7 @@ static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
/* Get indirect link from the MFC tuple */ /* Get indirect link from the MFC tuple */
read_cis_cache(s, LINK_SPACE(tuple->Flags), read_cis_cache(s, LINK_SPACE(tuple->Flags),
tuple->LinkOffset, 5, link); tuple->LinkOffset, 5, link);
ofs = le32_to_cpu(*(u_int *)(link+1)); ofs = le32_to_cpu(*(__le32 *)(link+1));
SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR); SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
/* Move to the next indirect link */ /* Move to the next indirect link */
tuple->LinkOffset += 5; tuple->LinkOffset += 5;
@ -671,8 +671,8 @@ static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
if (tuple->TupleDataLen < 5) if (tuple->TupleDataLen < 5)
return CS_BAD_TUPLE; return CS_BAD_TUPLE;
p = (u_char *)tuple->TupleData; p = (u_char *)tuple->TupleData;
csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2; csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(__le16 *)p)-2;
csum->len = le16_to_cpu(*(u_short *)(p + 2)); csum->len = le16_to_cpu(*(__le16 *)(p + 2));
csum->sum = *(p+4); csum->sum = *(p+4);
return CS_SUCCESS; return CS_SUCCESS;
} }
@ -683,7 +683,7 @@ static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
{ {
if (tuple->TupleDataLen < 4) if (tuple->TupleDataLen < 4)
return CS_BAD_TUPLE; return CS_BAD_TUPLE;
link->addr = le32_to_cpu(*(u_int *)tuple->TupleData); link->addr = le32_to_cpu(*(__le32 *)tuple->TupleData);
return CS_SUCCESS; return CS_SUCCESS;
} }
@ -702,7 +702,7 @@ static int parse_longlink_mfc(tuple_t *tuple,
return CS_BAD_TUPLE; return CS_BAD_TUPLE;
for (i = 0; i < link->nfn; i++) { for (i = 0; i < link->nfn; i++) {
link->fn[i].space = *p; p++; link->fn[i].space = *p; p++;
link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4; link->fn[i].addr = le32_to_cpu(*(__le32 *)p); p += 4;
} }
return CS_SUCCESS; return CS_SUCCESS;
} }
@ -789,10 +789,10 @@ static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m) static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
{ {
u_short *p; __le16 *p;
if (tuple->TupleDataLen < 4) if (tuple->TupleDataLen < 4)
return CS_BAD_TUPLE; return CS_BAD_TUPLE;
p = (u_short *)tuple->TupleData; p = (__le16 *)tuple->TupleData;
m->manf = le16_to_cpu(p[0]); m->manf = le16_to_cpu(p[0]);
m->card = le16_to_cpu(p[1]); m->card = le16_to_cpu(p[1]);
return CS_SUCCESS; return CS_SUCCESS;
@ -1093,7 +1093,7 @@ static int parse_cftable_entry(tuple_t *tuple,
break; break;
case 0x20: case 0x20:
entry->mem.nwin = 1; entry->mem.nwin = 1;
entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8; entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
entry->mem.win[0].card_addr = 0; entry->mem.win[0].card_addr = 0;
entry->mem.win[0].host_addr = 0; entry->mem.win[0].host_addr = 0;
p += 2; p += 2;
@ -1101,9 +1101,9 @@ static int parse_cftable_entry(tuple_t *tuple,
break; break;
case 0x40: case 0x40:
entry->mem.nwin = 1; entry->mem.nwin = 1;
entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8; entry->mem.win[0].len = le16_to_cpu(*(__le16 *)p) << 8;
entry->mem.win[0].card_addr = entry->mem.win[0].card_addr =
le16_to_cpu(*(u_short *)(p+2)) << 8; le16_to_cpu(*(__le16 *)(p+2)) << 8;
entry->mem.win[0].host_addr = 0; entry->mem.win[0].host_addr = 0;
p += 4; p += 4;
if (p > q) return CS_BAD_TUPLE; if (p > q) return CS_BAD_TUPLE;
@ -1140,7 +1140,7 @@ static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
p = (u_char *)tuple->TupleData; p = (u_char *)tuple->TupleData;
bar->attr = *p; bar->attr = *p;
p += 2; p += 2;
bar->size = le32_to_cpu(*(u_int *)p); bar->size = le32_to_cpu(*(__le32 *)p);
return CS_SUCCESS; return CS_SUCCESS;
} }
@ -1153,7 +1153,7 @@ static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
return CS_BAD_TUPLE; return CS_BAD_TUPLE;
config->last_idx = *(++p); config->last_idx = *(++p);
p++; p++;
config->base = le32_to_cpu(*(u_int *)p); config->base = le32_to_cpu(*(__le32 *)p);
config->subtuples = tuple->TupleDataLen - 6; config->subtuples = tuple->TupleDataLen - 6;
return CS_SUCCESS; return CS_SUCCESS;
} }
@ -1269,7 +1269,7 @@ static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
v2->vers = p[0]; v2->vers = p[0];
v2->comply = p[1]; v2->comply = p[1];
v2->dindex = le16_to_cpu(*(u_short *)(p+2)); v2->dindex = le16_to_cpu(*(__le16 *)(p+2));
v2->vspec8 = p[6]; v2->vspec8 = p[6];
v2->vspec9 = p[7]; v2->vspec9 = p[7];
v2->nhdr = p[8]; v2->nhdr = p[8];
@ -1310,8 +1310,8 @@ static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
fmt->type = p[0]; fmt->type = p[0];
fmt->edc = p[1]; fmt->edc = p[1];
fmt->offset = le32_to_cpu(*(u_int *)(p+2)); fmt->offset = le32_to_cpu(*(__le32 *)(p+2));
fmt->length = le32_to_cpu(*(u_int *)(p+6)); fmt->length = le32_to_cpu(*(__le32 *)(p+6));
return CS_SUCCESS; return CS_SUCCESS;
} }

View File

@ -309,41 +309,6 @@ struct pcmcia_socket * pcmcia_get_socket_by_nr(unsigned int nr)
} }
EXPORT_SYMBOL(pcmcia_get_socket_by_nr); EXPORT_SYMBOL(pcmcia_get_socket_by_nr);
/**
* socket_setup() and shutdown_socket() are called by the main event
* handler when card insertion and removal events are received.
* socket_setup() turns on socket power and resets the socket, in two stages.
* shutdown_socket() unconfigures a socket and turns off socket power.
*/
static void shutdown_socket(struct pcmcia_socket *s)
{
cs_dbg(s, 1, "shutdown_socket\n");
/* Blank out the socket state */
s->socket = dead_socket;
s->ops->init(s);
s->ops->set_socket(s, &s->socket);
s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0;
destroy_cis_cache(s);
#ifdef CONFIG_CARDBUS
cb_free(s);
#endif
s->functions = 0;
kfree(s->config);
s->config = NULL;
{
int status;
s->ops->get_status(s, &status);
if (status & SS_POWERON) {
printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
}
}
} /* shutdown_socket */
/** /**
* The central event handler. Send_event() sends an event to the * The central event handler. Send_event() sends an event to the
* 16-bit subsystem, which then calls the relevant device drivers. * 16-bit subsystem, which then calls the relevant device drivers.
@ -383,17 +348,6 @@ static void socket_remove_drivers(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);
} }
static void socket_shutdown(struct pcmcia_socket *skt)
{
cs_dbg(skt, 4, "shutdown\n");
socket_remove_drivers(skt);
skt->state &= SOCKET_INUSE|SOCKET_PRESENT;
msleep(shutdown_delay * 10);
skt->state &= SOCKET_INUSE;
shutdown_socket(skt);
}
static int socket_reset(struct pcmcia_socket *skt) static int socket_reset(struct pcmcia_socket *skt)
{ {
int status, i; int status, i;
@ -424,6 +378,45 @@ static int socket_reset(struct pcmcia_socket *skt)
return CS_GENERAL_FAILURE; return CS_GENERAL_FAILURE;
} }
/**
* socket_setup() and socket_shutdown() are called by the main event handler
* when card insertion and removal events are received.
* socket_setup() turns on socket power and resets the socket, in two stages.
* socket_shutdown() unconfigures a socket and turns off socket power.
*/
static void socket_shutdown(struct pcmcia_socket *s)
{
int status;
cs_dbg(s, 4, "shutdown\n");
socket_remove_drivers(s);
s->state &= SOCKET_INUSE | SOCKET_PRESENT;
msleep(shutdown_delay * 10);
s->state &= SOCKET_INUSE;
/* Blank out the socket state */
s->socket = dead_socket;
s->ops->init(s);
s->ops->set_socket(s, &s->socket);
s->irq.AssignedIRQ = s->irq.Config = 0;
s->lock_count = 0;
destroy_cis_cache(s);
#ifdef CONFIG_CARDBUS
cb_free(s);
#endif
s->functions = 0;
kfree(s->config);
s->config = NULL;
s->ops->get_status(s, &status);
if (status & SS_POWERON) {
printk(KERN_ERR "PCMCIA: socket %p: *** DANGER *** unable to remove socket power\n", s);
}
cs_socket_put(s);
}
static int socket_setup(struct pcmcia_socket *skt, int initial_delay) static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
{ {
int status, i; int status, i;
@ -529,7 +522,6 @@ static int socket_insert(struct pcmcia_socket *skt)
send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);
} else { } else {
socket_shutdown(skt); socket_shutdown(skt);
cs_socket_put(skt);
} }
return ret; return ret;
@ -593,7 +585,6 @@ static int socket_resume(struct pcmcia_socket *skt)
} }
} else { } else {
socket_shutdown(skt); socket_shutdown(skt);
cs_socket_put(skt);
} }
skt->state &= ~SOCKET_SUSPEND; skt->state &= ~SOCKET_SUSPEND;
@ -605,7 +596,6 @@ static void socket_remove(struct pcmcia_socket *skt)
{ {
printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock); printk(KERN_NOTICE "pccard: card ejected from slot %d\n", skt->sock);
socket_shutdown(skt); socket_shutdown(skt);
cs_socket_put(skt);
} }
/* /*
@ -780,8 +770,13 @@ int pccard_reset_card(struct pcmcia_socket *skt)
ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
if (ret == 0) { if (ret == 0) {
send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
if (socket_reset(skt) == CS_SUCCESS) if (skt->callback)
skt->callback->suspend(skt);
if (socket_reset(skt) == CS_SUCCESS) {
send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
if (skt->callback)
skt->callback->resume(skt);
}
} }
ret = CS_SUCCESS; ret = CS_SUCCESS;
@ -812,6 +807,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
ret = CS_UNSUPPORTED_FUNCTION; ret = CS_UNSUPPORTED_FUNCTION;
break; break;
} }
if (skt->callback) {
ret = skt->callback->suspend(skt);
if (ret)
break;
}
ret = socket_suspend(skt); ret = socket_suspend(skt);
} while (0); } while (0);
up(&skt->skt_sem); up(&skt->skt_sem);
@ -838,6 +838,8 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
break; break;
} }
ret = socket_resume(skt); ret = socket_resume(skt);
if (!ret && skt->callback)
skt->callback->resume(skt);
} while (0); } while (0);
up(&skt->skt_sem); up(&skt->skt_sem);

View File

@ -117,7 +117,7 @@ int verify_cis_cache(struct pcmcia_socket *s);
int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse); int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse);
/* In rsrc_mgr */ /* In rsrc_mgr */
void pcmcia_validate_mem(struct pcmcia_socket *s); int pcmcia_validate_mem(struct pcmcia_socket *s);
struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align, struct resource *pcmcia_find_io_region(unsigned long base, int num, unsigned long align,
struct pcmcia_socket *s); struct pcmcia_socket *s);
int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start, int pcmcia_adjust_io_region(struct resource *res, unsigned long r_start,
@ -143,6 +143,8 @@ struct pcmcia_callback{
struct module *owner; struct module *owner;
int (*event) (struct pcmcia_socket *s, event_t event, int priority); int (*event) (struct pcmcia_socket *s, event_t event, int priority);
void (*requery) (struct pcmcia_socket *s); void (*requery) (struct pcmcia_socket *s);
int (*suspend) (struct pcmcia_socket *s);
int (*resume) (struct pcmcia_socket *s);
}; };
int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c); int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);

View File

@ -57,8 +57,6 @@ module_param_named(pc_debug, ds_pc_debug, int, 0644);
spinlock_t pcmcia_dev_list_lock; spinlock_t pcmcia_dev_list_lock;
static int unbind_request(struct pcmcia_socket *s);
/*====================================================================*/ /*====================================================================*/
/* code which was in cs.c before */ /* code which was in cs.c before */
@ -205,7 +203,7 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
unsigned int i; unsigned int i;
u32 hash; u32 hash;
if (!p_drv->attach || !p_drv->event || !p_drv->detach) if (!p_drv->probe || !p_drv->remove)
printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback " printk(KERN_DEBUG "pcmcia: %s lacks a requisite callback "
"function\n", p_drv->drv.name); "function\n", p_drv->drv.name);
@ -266,12 +264,10 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
if (fw->size >= CISTPL_MAX_CIS_SIZE) if (fw->size >= CISTPL_MAX_CIS_SIZE)
goto release; goto release;
cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL); cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
if (!cis) if (!cis)
goto release; goto release;
memset(cis, 0, sizeof(cisdump_t));
cis->Length = fw->size + 1; cis->Length = fw->size + 1;
memcpy(cis->Data, fw->data, fw->size); memcpy(cis->Data, fw->data, fw->size);
@ -363,6 +359,7 @@ static int pcmcia_device_probe(struct device * dev)
{ {
struct pcmcia_device *p_dev; struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv; struct pcmcia_driver *p_drv;
struct pcmcia_socket *s;
int ret = 0; int ret = 0;
dev = get_device(dev); dev = get_device(dev);
@ -371,25 +368,38 @@ static int pcmcia_device_probe(struct device * dev)
p_dev = to_pcmcia_dev(dev); p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver); p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
if (!try_module_get(p_drv->owner)) { if ((!p_drv->probe) || (!try_module_get(p_drv->owner))) {
ret = -EINVAL; ret = -EINVAL;
goto put_dev; goto put_dev;
} }
if (p_drv->attach) { p_dev->state &= ~CLIENT_UNBOUND;
p_dev->instance = p_drv->attach();
if ((!p_dev->instance) || (p_dev->state & CLIENT_UNBOUND)) { /* set up the device configuration, if it hasn't been done before */
printk(KERN_NOTICE "ds: unable to create instance " if (!s->functions) {
"of '%s'!\n", p_drv->drv.name); cistpl_longlink_mfc_t mfc;
ret = -EINVAL; if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC,
&mfc) == CS_SUCCESS)
s->functions = mfc.nfn;
else
s->functions = 1;
s->config = kzalloc(sizeof(config_t) * s->functions,
GFP_KERNEL);
if (!s->config) {
ret = -ENOMEM;
goto put_module;
} }
} }
ret = p_drv->probe(p_dev);
put_module:
if (ret) if (ret)
module_put(p_drv->owner); module_put(p_drv->owner);
put_dev: put_dev:
if ((ret) || !(p_drv->attach)) if (ret)
put_device(dev); put_device(dev);
return (ret); return (ret);
} }
@ -399,24 +409,66 @@ static int pcmcia_device_remove(struct device * dev)
{ {
struct pcmcia_device *p_dev; struct pcmcia_device *p_dev;
struct pcmcia_driver *p_drv; struct pcmcia_driver *p_drv;
int i;
/* detach the "instance" */ /* detach the "instance" */
p_dev = to_pcmcia_dev(dev); p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver); p_drv = to_pcmcia_drv(dev->driver);
if (!p_drv)
return 0;
if (p_drv) { if (p_drv->remove)
if ((p_drv->detach) && (p_dev->instance)) { p_drv->remove(p_dev);
p_drv->detach(p_dev->instance);
/* from pcmcia_probe_device */ /* check for proper unloading */
put_device(&p_dev->dev); if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
} printk(KERN_INFO "pcmcia: driver %s did not release config properly\n",
module_put(p_drv->owner); p_drv->drv.name);
}
for (i = 0; i < MAX_WIN; i++)
if (p_dev->state & CLIENT_WIN_REQ(i))
printk(KERN_INFO "pcmcia: driver %s did not release windows properly\n",
p_drv->drv.name);
/* references from pcmcia_probe_device */
p_dev->state = CLIENT_UNBOUND;
pcmcia_put_dev(p_dev);
module_put(p_drv->owner);
return 0; return 0;
} }
/*
* Removes a PCMCIA card from the device tree and socket list.
*/
static void pcmcia_card_remove(struct pcmcia_socket *s)
{
struct pcmcia_device *p_dev;
unsigned long flags;
ds_dbg(2, "unbind_request(%d)\n", s->sock);
s->device_count = 0;
for (;;) {
/* unregister all pcmcia_devices registered with this socket*/
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (list_empty(&s->devices_list)) {
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
return;
}
p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
list_del(&p_dev->socket_device_list);
p_dev->state |= CLIENT_STALE;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
device_unregister(&p_dev->dev);
}
return;
} /* unbind_request */
/* /*
* pcmcia_device_query -- determine information about a pcmcia device * pcmcia_device_query -- determine information about a pcmcia device
@ -517,10 +569,9 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
if (s->device_count == 2) if (s->device_count == 2)
goto err_put; goto err_put;
p_dev = kmalloc(sizeof(struct pcmcia_device), GFP_KERNEL); p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
if (!p_dev) if (!p_dev)
goto err_put; goto err_put;
memset(p_dev, 0, sizeof(struct pcmcia_device));
p_dev->socket = s; p_dev->socket = s;
p_dev->device_no = (s->device_count++); p_dev->device_no = (s->device_count++);
@ -583,7 +634,9 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
if (!(s->resource_setup_done)) if (!(s->resource_setup_done))
return -EAGAIN; /* try again, but later... */ return -EAGAIN; /* try again, but later... */
pcmcia_validate_mem(s); if (pcmcia_validate_mem(s))
return -EAGAIN; /* try again, but later... */
ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo); ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
if (ret || !cisinfo.Chains) { if (ret || !cisinfo.Chains) {
ds_dbg(0, "invalid CIS or invalid resources\n"); ds_dbg(0, "invalid CIS or invalid resources\n");
@ -918,6 +971,78 @@ static struct device_attribute pcmcia_dev_attrs[] = {
__ATTR_NULL, __ATTR_NULL,
}; };
/* PM support, also needed for reset */
static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv = NULL;
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
if (p_drv && p_drv->suspend)
return p_drv->suspend(p_dev);
return 0;
}
static int pcmcia_dev_resume(struct device * dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv = NULL;
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
if (p_drv && p_drv->resume)
return p_drv->resume(p_dev);
return 0;
}
static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
{
struct pcmcia_socket *skt = _data;
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
if (p_dev->socket != skt)
return 0;
return dpm_runtime_suspend(dev, PMSG_SUSPEND);
}
static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
{
struct pcmcia_socket *skt = _data;
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
if (p_dev->socket != skt)
return 0;
dpm_runtime_resume(dev);
return 0;
}
static int pcmcia_bus_resume(struct pcmcia_socket *skt)
{
bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
return 0;
}
static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
{
if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
pcmcia_bus_suspend_callback)) {
pcmcia_bus_resume(skt);
return -EIO;
}
return 0;
}
/*====================================================================== /*======================================================================
@ -925,49 +1050,6 @@ static struct device_attribute pcmcia_dev_attrs[] = {
======================================================================*/ ======================================================================*/
struct send_event_data {
struct pcmcia_socket *skt;
event_t event;
int priority;
};
static int send_event_callback(struct device *dev, void * _data)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
struct pcmcia_driver *p_drv;
struct send_event_data *data = _data;
/* we get called for all sockets, but may only pass the event
* for drivers _on the affected socket_ */
if (p_dev->socket != data->skt)
return 0;
p_drv = to_pcmcia_drv(p_dev->dev.driver);
if (!p_drv)
return 0;
if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE))
return 0;
if (p_drv->event)
return p_drv->event(data->event, data->priority,
&p_dev->event_callback_args);
return 0;
}
static int send_event(struct pcmcia_socket *s, event_t event, int priority)
{
struct send_event_data private;
private.skt = s;
private.event = event;
private.priority = priority;
return bus_for_each_dev(&pcmcia_bus_type, NULL, &private, send_event_callback);
} /* send_event */
/* Normally, the event is passed to individual drivers after /* Normally, the event is passed to individual drivers after
* informing userspace. Only for CS_EVENT_CARD_REMOVAL this * informing userspace. Only for CS_EVENT_CARD_REMOVAL this
* is inversed to maintain historic compatibility. * is inversed to maintain historic compatibility.
@ -976,20 +1058,17 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)
static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
{ {
struct pcmcia_socket *s = pcmcia_get_socket(skt); struct pcmcia_socket *s = pcmcia_get_socket(skt);
int ret = 0;
ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n", ds_dbg(1, "ds_event(0x%06x, %d, 0x%p)\n",
event, priority, skt); event, priority, skt);
switch (event) {
switch (event) {
case CS_EVENT_CARD_REMOVAL: case CS_EVENT_CARD_REMOVAL:
s->pcmcia_state.present = 0; s->pcmcia_state.present = 0;
send_event(skt, event, priority); pcmcia_card_remove(skt);
unbind_request(skt);
handle_event(skt, event); handle_event(skt, event);
break; break;
case CS_EVENT_CARD_INSERTION: case CS_EVENT_CARD_INSERTION:
s->pcmcia_state.present = 1; s->pcmcia_state.present = 1;
pcmcia_card_add(skt); pcmcia_card_add(skt);
@ -997,12 +1076,14 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
break; break;
case CS_EVENT_EJECTION_REQUEST: case CS_EVENT_EJECTION_REQUEST:
ret = send_event(skt, event, priority);
break; break;
case CS_EVENT_PM_SUSPEND:
case CS_EVENT_PM_RESUME:
case CS_EVENT_RESET_PHYSICAL:
case CS_EVENT_CARD_RESET:
default: default:
handle_event(skt, event); handle_event(skt, event);
send_event(skt, event, priority);
break; break;
} }
@ -1012,152 +1093,12 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
} /* ds_event */ } /* ds_event */
int pcmcia_register_client(struct pcmcia_device **handle, client_reg_t *req)
{
struct pcmcia_socket *s = NULL;
struct pcmcia_device *p_dev = NULL;
struct pcmcia_driver *p_drv = NULL;
/* Look for unbound client with matching dev_info */
down_read(&pcmcia_socket_list_rwsem);
list_for_each_entry(s, &pcmcia_socket_list, socket_list) {
unsigned long flags;
if (s->state & SOCKET_CARDBUS)
continue;
s = pcmcia_get_socket(s);
if (!s)
continue;
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
list_for_each_entry(p_dev, &s->devices_list, socket_device_list) {
p_dev = pcmcia_get_dev(p_dev);
if (!p_dev)
continue;
if (!(p_dev->state & CLIENT_UNBOUND) ||
(!p_dev->dev.driver)) {
pcmcia_put_dev(p_dev);
continue;
}
p_drv = to_pcmcia_drv(p_dev->dev.driver);
if (!strncmp(p_drv->drv.name, (char *)req->dev_info, DEV_NAME_LEN)) {
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
goto found;
}
pcmcia_put_dev(p_dev);
}
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
pcmcia_put_socket(s);
}
found:
up_read(&pcmcia_socket_list_rwsem);
if (!p_dev)
return -ENODEV;
pcmcia_put_socket(s); /* safe, as we already hold a reference from bind_device */
*handle = p_dev;
p_dev->state &= ~CLIENT_UNBOUND;
p_dev->event_callback_args = req->event_callback_args;
p_dev->event_callback_args.client_handle = p_dev;
if (!s->functions) {
cistpl_longlink_mfc_t mfc;
if (pccard_read_tuple(s, p_dev->func, CISTPL_LONGLINK_MFC, &mfc)
== CS_SUCCESS)
s->functions = mfc.nfn;
else
s->functions = 1;
s->config = kmalloc(sizeof(config_t) * s->functions,
GFP_KERNEL);
if (!s->config)
goto out_no_resource;
memset(s->config, 0, sizeof(config_t) * s->functions);
}
ds_dbg(1, "register_client(): client 0x%p, dev %s\n",
p_dev, p_dev->dev.bus_id);
if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) {
if (p_drv->event)
p_drv->event(CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW,
&p_dev->event_callback_args);
}
return CS_SUCCESS;
out_no_resource:
pcmcia_put_dev(p_dev);
return CS_OUT_OF_RESOURCE;
} /* register_client */
EXPORT_SYMBOL(pcmcia_register_client);
/* unbind _all_ devices attached to a given pcmcia_bus_socket. The
* drivers have been called with EVENT_CARD_REMOVAL before.
*/
static int unbind_request(struct pcmcia_socket *s)
{
struct pcmcia_device *p_dev;
unsigned long flags;
ds_dbg(2, "unbind_request(%d)\n", s->sock);
s->device_count = 0;
for (;;) {
/* unregister all pcmcia_devices registered with this socket*/
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (list_empty(&s->devices_list)) {
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
return 0;
}
p_dev = list_entry((&s->devices_list)->next, struct pcmcia_device, socket_device_list);
list_del(&p_dev->socket_device_list);
p_dev->state |= CLIENT_STALE;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
device_unregister(&p_dev->dev);
}
return 0;
} /* unbind_request */
int pcmcia_deregister_client(struct pcmcia_device *p_dev)
{
struct pcmcia_socket *s;
int i;
s = p_dev->socket;
ds_dbg(1, "deregister_client(%p)\n", p_dev);
if (p_dev->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED))
goto warn_out;
for (i = 0; i < MAX_WIN; i++)
if (p_dev->state & CLIENT_WIN_REQ(i))
goto warn_out;
if (p_dev->state & CLIENT_STALE) {
p_dev->state &= ~CLIENT_STALE;
pcmcia_put_dev(p_dev);
} else {
p_dev->state = CLIENT_UNBOUND;
}
return CS_SUCCESS;
warn_out:
printk(KERN_WARNING "ds: deregister_client was called too early.\n");
return CS_IN_USE;
} /* deregister_client */
EXPORT_SYMBOL(pcmcia_deregister_client);
static struct pcmcia_callback pcmcia_bus_callback = { static struct pcmcia_callback pcmcia_bus_callback = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.event = ds_event, .event = ds_event,
.requery = pcmcia_bus_rescan, .requery = pcmcia_bus_rescan,
.suspend = pcmcia_bus_suspend,
.resume = pcmcia_bus_resume,
}; };
static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev, static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
@ -1226,6 +1167,8 @@ struct bus_type pcmcia_bus_type = {
.uevent = pcmcia_bus_uevent, .uevent = pcmcia_bus_uevent,
.match = pcmcia_bus_match, .match = pcmcia_bus_match,
.dev_attrs = pcmcia_dev_attrs, .dev_attrs = pcmcia_dev_attrs,
.suspend = pcmcia_dev_suspend,
.resume = pcmcia_dev_resume,
}; };

View File

@ -417,18 +417,6 @@ static int hs_get_status(struct pcmcia_socket *s, u_int *value)
/*============================================================*/ /*============================================================*/
static int hs_get_socket(struct pcmcia_socket *s, socket_state_t *state)
{
hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
DPRINTK("hs_get_socket(%d)\n", sock);
*state = sp->state;
return 0;
}
/*============================================================*/
static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state) static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{ {
hs_socket_t *sp = container_of(s, struct hs_socket_t, socket); hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
@ -749,7 +737,6 @@ static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
static struct pccard_operations hs_operations = { static struct pccard_operations hs_operations = {
.init = hs_init, .init = hs_init,
.get_status = hs_get_status, .get_status = hs_get_status,
.get_socket = hs_get_socket,
.set_socket = hs_set_socket, .set_socket = hs_set_socket,
.set_io_map = hs_set_io_map, .set_io_map = hs_set_io_map,
.set_mem_map = hs_set_mem_map, .set_mem_map = hs_set_mem_map,

View File

@ -66,7 +66,6 @@ static struct pci_driver i82092aa_pci_drv = {
static struct pccard_operations i82092aa_operations = { static struct pccard_operations i82092aa_operations = {
.init = i82092aa_init, .init = i82092aa_init,
.get_status = i82092aa_get_status, .get_status = i82092aa_get_status,
.get_socket = i82092aa_get_socket,
.set_socket = i82092aa_set_socket, .set_socket = i82092aa_set_socket,
.set_io_map = i82092aa_set_io_map, .set_io_map = i82092aa_set_io_map,
.set_mem_map = i82092aa_set_mem_map, .set_mem_map = i82092aa_set_mem_map,
@ -482,78 +481,6 @@ static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value)
} }
static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state)
{
unsigned int sock = container_of(socket, struct socket_info, socket)->number;
unsigned char reg,vcc,vpp;
enter("i82092aa_get_socket");
state->flags = 0;
state->Vcc = 0;
state->Vpp = 0;
state->io_irq = 0;
state->csc_mask = 0;
/* First the power status of the socket */
reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */
if (reg & I365_PWR_AUTO)
state->flags |= SS_PWR_AUTO; /* Automatic Power Switch */
if (reg & I365_PWR_OUT)
state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */
state->Vcc = 50;
if (vpp == I365_VPP1_5V)
state->Vpp = 50;
if (vpp == I365_VPP1_12V)
state->Vpp = 120;
}
if ((reg & I365_VCC_3V)==I365_VCC_3V)
state->Vcc = 33;
/* Now the IO card, RESET flags and IO interrupt */
reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */
if ((reg & I365_PC_RESET)==0)
state->flags |= SS_RESET;
if (reg & I365_PC_IOCARD)
state->flags |= SS_IOCARD; /* This is an IO card */
/* Set the IRQ number */
if (sockets[sock].dev!=NULL)
state->io_irq = sockets[sock].dev->irq;
/* Card status change */
reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */
if (reg & I365_CSC_DETECT)
state->csc_mask |= SS_DETECT; /* Card detect is enabled */
if (state->flags & SS_IOCARD) {/* IO Cards behave different */
if (reg & I365_CSC_STSCHG)
state->csc_mask |= SS_STSCHG;
} else {
if (reg & I365_CSC_BVD1)
state->csc_mask |= SS_BATDEAD;
if (reg & I365_CSC_BVD2)
state->csc_mask |= SS_BATWARN;
if (reg & I365_CSC_READY)
state->csc_mask |= SS_READY;
}
leave("i82092aa_get_socket");
return 0;
}
static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state) static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state)
{ {
unsigned int sock = container_of(socket, struct socket_info, socket)->number; unsigned int sock = container_of(socket, struct socket_info, socket)->number;

View File

@ -29,7 +29,6 @@ static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs);
static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value); static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value);
static int i82092aa_get_socket(struct pcmcia_socket *socket, socket_state_t *state);
static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state); static int i82092aa_set_socket(struct pcmcia_socket *socket, socket_state_t *state);
static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io); static int i82092aa_set_io_map(struct pcmcia_socket *socket, struct pccard_io_map *io);
static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem); static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem);

View File

@ -940,78 +940,6 @@ static int i365_get_status(u_short sock, u_int *value)
/*====================================================================*/ /*====================================================================*/
static int i365_get_socket(u_short sock, socket_state_t *state)
{
struct i82365_socket *t = &socket[sock];
u_char reg, vcc, vpp;
reg = i365_get(sock, I365_POWER);
state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
state->Vcc = state->Vpp = 0;
if (t->flags & IS_CIRRUS) {
if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {
if (reg & I365_VCC_5V) state->Vcc = 33;
if (vpp == I365_VPP1_5V) state->Vpp = 33;
} else {
if (reg & I365_VCC_5V) state->Vcc = 50;
if (vpp == I365_VPP1_5V) state->Vpp = 50;
}
if (vpp == I365_VPP1_12V) state->Vpp = 120;
} else if (t->flags & IS_VG_PWR) {
if (i365_get(sock, VG469_VSELECT) & VG469_VSEL_VCC) {
if (reg & I365_VCC_5V) state->Vcc = 33;
if (vpp == I365_VPP1_5V) state->Vpp = 33;
} else {
if (reg & I365_VCC_5V) state->Vcc = 50;
if (vpp == I365_VPP1_5V) state->Vpp = 50;
}
if (vpp == I365_VPP1_12V) state->Vpp = 120;
} else if (t->flags & IS_DF_PWR) {
if (vcc == I365_VCC_3V) state->Vcc = 33;
if (vcc == I365_VCC_5V) state->Vcc = 50;
if (vpp == I365_VPP1_5V) state->Vpp = 50;
if (vpp == I365_VPP1_12V) state->Vpp = 120;
} else {
if (reg & I365_VCC_5V) {
state->Vcc = 50;
if (vpp == I365_VPP1_5V) state->Vpp = 50;
if (vpp == I365_VPP1_12V) state->Vpp = 120;
}
}
/* IO card, RESET flags, IO interrupt */
reg = i365_get(sock, I365_INTCTL);
state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
state->io_irq = reg & I365_IRQ_MASK;
/* speaker control */
if (t->flags & IS_CIRRUS) {
if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
state->flags |= SS_SPKR_ENA;
}
/* Card status change mask */
reg = i365_get(sock, I365_CSCINT);
state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
if (state->flags & SS_IOCARD)
state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
else {
state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
}
debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
return 0;
} /* i365_get_socket */
/*====================================================================*/
static int i365_set_socket(u_short sock, socket_state_t *state) static int i365_set_socket(u_short sock, socket_state_t *state)
{ {
struct i82365_socket *t = &socket[sock]; struct i82365_socket *t = &socket[sock];
@ -1265,16 +1193,6 @@ static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
LOCKED(i365_get_status(sock, value)); LOCKED(i365_get_status(sock, value));
} }
static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
{
unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(i365_get_socket(sock, state));
}
static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state) static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{ {
unsigned int sock = container_of(s, struct i82365_socket, socket)->number; unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
@ -1324,7 +1242,6 @@ static int pcic_init(struct pcmcia_socket *s)
static struct pccard_operations pcic_operations = { static struct pccard_operations pcic_operations = {
.init = pcic_init, .init = pcic_init,
.get_status = pcic_get_status, .get_status = pcic_get_status,
.get_socket = pcic_get_socket,
.set_socket = pcic_set_socket, .set_socket = pcic_set_socket,
.set_io_map = pcic_set_io_map, .set_io_map = pcic_set_io_map,
.set_mem_map = pcic_set_mem_map, .set_mem_map = pcic_set_mem_map,

View File

@ -480,25 +480,6 @@ static int _pcc_get_status(u_short sock, u_int *value)
/*====================================================================*/ /*====================================================================*/
static int _pcc_get_socket(u_short sock, socket_state_t *state)
{
// pcc_socket_t *t = &socket[sock];
state->flags = 0;
state->csc_mask = SS_DETECT;
state->csc_mask |= SS_READY;
state->io_irq = 0;
state->Vcc = 33; /* 3.3V fixed */
state->Vpp = 33;
debug(3, "m32r_cfc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
return 0;
} /* _get_socket */
/*====================================================================*/
static int _pcc_set_socket(u_short sock, socket_state_t *state) static int _pcc_set_socket(u_short sock, socket_state_t *state)
{ {
debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
@ -667,18 +648,6 @@ static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
LOCKED(_pcc_get_status(sock, value)); LOCKED(_pcc_get_status(sock, value));
} }
static int pcc_get_socket(struct pcmcia_socket *s, socket_state_t *state)
{
unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
if (socket[sock].flags & IS_ALIVE) {
debug(3, "m32r_cfc: pcc_get_socket: sock(%d) -EINVAL\n", sock);
return -EINVAL;
}
debug(3, "m32r_cfc: pcc_get_socket: sock(%d)\n", sock);
LOCKED(_pcc_get_socket(sock, state));
}
static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state) static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{ {
unsigned int sock = container_of(s, struct pcc_socket, socket)->number; unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
@ -724,7 +693,6 @@ static int pcc_init(struct pcmcia_socket *s)
static struct pccard_operations pcc_operations = { static struct pccard_operations pcc_operations = {
.init = pcc_init, .init = pcc_init,
.get_status = pcc_get_status, .get_status = pcc_get_status,
.get_socket = pcc_get_socket,
.set_socket = pcc_set_socket, .set_socket = pcc_set_socket,
.set_io_map = pcc_set_io_map, .set_io_map = pcc_set_io_map,
.set_mem_map = pcc_set_mem_map, .set_mem_map = pcc_set_mem_map,

View File

@ -429,16 +429,6 @@ static int _pcc_get_status(u_short sock, u_int *value)
/*====================================================================*/ /*====================================================================*/
static int _pcc_get_socket(u_short sock, socket_state_t *state)
{
debug(3, "m32r-pcc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
return 0;
} /* _get_socket */
/*====================================================================*/
static int _pcc_set_socket(u_short sock, socket_state_t *state) static int _pcc_set_socket(u_short sock, socket_state_t *state)
{ {
u_long reg = 0; u_long reg = 0;
@ -641,15 +631,6 @@ static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
LOCKED(_pcc_get_status(sock, value)); LOCKED(_pcc_get_status(sock, value));
} }
static int pcc_get_socket(struct pcmcia_socket *s, socket_state_t *state)
{
unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
if (socket[sock].flags & IS_ALIVE)
return -EINVAL;
LOCKED(_pcc_get_socket(sock, state));
}
static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state) static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{ {
unsigned int sock = container_of(s, struct pcc_socket, socket)->number; unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
@ -687,7 +668,6 @@ static int pcc_init(struct pcmcia_socket *s)
static struct pccard_operations pcc_operations = { static struct pccard_operations pcc_operations = {
.init = pcc_init, .init = pcc_init,
.get_status = pcc_get_status, .get_status = pcc_get_status,
.get_socket = pcc_get_socket,
.set_socket = pcc_set_socket, .set_socket = pcc_set_socket,
.set_io_map = pcc_set_io_map, .set_io_map = pcc_set_io_map,
.set_mem_map = pcc_set_mem_map, .set_mem_map = pcc_set_mem_map,

View File

@ -9,6 +9,9 @@
* <oliver.kurth@cyclades.de> * <oliver.kurth@cyclades.de>
* Further fixes, v2.6 kernel port * Further fixes, v2.6 kernel port
* <marcelo.tosatti@cyclades.com> * <marcelo.tosatti@cyclades.com>
*
* Some fixes, additions (C) 2005 Montavista Software, Inc.
* <vbordug@ru.mvista.com>
* *
* "The ExCA standard specifies that socket controllers should provide * "The ExCA standard specifies that socket controllers should provide
* two IO and five memory windows per socket, which can be independently * two IO and five memory windows per socket, which can be independently
@ -97,6 +100,11 @@ MODULE_LICENSE("Dual MPL/GPL");
#endif #endif
#endif #endif
#if defined(CONFIG_MPC885ADS)
#define CONFIG_PCMCIA_SLOT_A
#define PCMCIA_GLITCHY_CD
#endif
/* Cyclades ACS uses both slots */ /* Cyclades ACS uses both slots */
#ifdef CONFIG_PRxK #ifdef CONFIG_PRxK
#define CONFIG_PCMCIA_SLOT_A #define CONFIG_PCMCIA_SLOT_A
@ -374,10 +382,10 @@ static int voltage_set(int slot, int vcc, int vpp)
} }
/* first, turn off all power */ /* first, turn off all power */
out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK)); out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
/* enable new powersettings */ /* enable new powersettings */
out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | reg); out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | reg);
return 0; return 0;
} }
@ -386,12 +394,89 @@ static int voltage_set(int slot, int vcc, int vpp)
static void hardware_enable(int slot) static void hardware_enable(int slot)
{ {
out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) & ~BCSR1_PCCEN); out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) & ~BCSR1_PCCEN);
} }
static void hardware_disable(int slot) static void hardware_disable(int slot)
{ {
out_be32(&((u32 *)BCSR1), in_be32(&((u32 *)BCSR1)) | BCSR1_PCCEN); out_be32((u32 *)BCSR1, in_be32((u32 *)BCSR1) | BCSR1_PCCEN);
}
#endif
/* MPC885ADS Boards */
#if defined(CONFIG_MPC885ADS)
#define PCMCIA_BOARD_MSG "MPC885ADS"
static int voltage_set(int slot, int vcc, int vpp)
{
u32 reg = 0;
unsigned *bcsr_io;
bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
switch(vcc) {
case 0:
break;
case 33:
reg |= BCSR1_PCCVCC0;
break;
case 50:
reg |= BCSR1_PCCVCC1;
break;
default:
return 1;
}
switch(vpp) {
case 0:
break;
case 33:
case 50:
if(vcc == vpp)
reg |= BCSR1_PCCVPP1;
else
return 1;
break;
case 120:
if ((vcc == 33) || (vcc == 50))
reg |= BCSR1_PCCVPP0;
else
return 1;
default:
return 1;
}
/* first, turn off all power */
out_be32(bcsr_io, in_be32(bcsr_io) & ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK));
/* enable new powersettings */
out_be32(bcsr_io, in_be32(bcsr_io) | reg);
iounmap(bcsr_io);
return 0;
}
#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
static void hardware_enable(int slot)
{
unsigned *bcsr_io;
bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
out_be32(bcsr_io, in_be32(bcsr_io) & ~BCSR1_PCCEN);
iounmap(bcsr_io);
}
static void hardware_disable(int slot)
{
unsigned *bcsr_io;
bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
out_be32(bcsr_io, in_be32(bcsr_io) | BCSR1_PCCEN);
iounmap(bcsr_io);
} }
#endif #endif
@ -440,10 +525,10 @@ static int voltage_set(int slot, int vcc, int vpp)
} }
/* first, turn off all power */ /* first, turn off all power */
out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK)); out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) & ~(CSR2_VCC_MASK | CSR2_VPP_MASK));
/* enable new powersettings */ /* enable new powersettings */
out_8(&((u8 *)MBX_CSR2_ADDR), in_8(&((u8 *)MBX_CSR2_ADDR)) | reg); out_8((u8 *)MBX_CSR2_ADDR, in_8((u8 *)MBX_CSR2_ADDR) | reg);
return 0; return 0;
} }
@ -823,17 +908,6 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)
return 0; return 0;
} }
static int m8xx_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
int lsock = container_of(sock, struct socket_info, socket)->slot;
*state = socket[lsock].state; /* copy the whole structure */
dprintk("GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x\n", lsock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
return 0;
}
static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state) static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{ {
int lsock = container_of(sock, struct socket_info, socket)->slot; int lsock = container_of(sock, struct socket_info, socket)->slot;
@ -1023,8 +1097,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
if(io->flags & MAP_WRPROT) if(io->flags & MAP_WRPROT)
reg |= M8XX_PCMCIA_POR_WRPROT; reg |= M8XX_PCMCIA_POR_WRPROT;
/*if(io->flags & (MAP_16BIT | MAP_AUTOSZ))*/ if(io->flags & (MAP_16BIT | MAP_AUTOSZ))
if(io->flags & MAP_16BIT)
reg |= M8XX_PCMCIA_POR_16BIT; reg |= M8XX_PCMCIA_POR_16BIT;
if(io->flags & MAP_ACTIVE) if(io->flags & MAP_ACTIVE)
@ -1169,7 +1242,6 @@ static struct pccard_operations m8xx_services = {
.init = m8xx_sock_init, .init = m8xx_sock_init,
.suspend = m8xx_suspend, .suspend = m8xx_suspend,
.get_status = m8xx_get_status, .get_status = m8xx_get_status,
.get_socket = m8xx_get_socket,
.set_socket = m8xx_set_socket, .set_socket = m8xx_set_socket,
.set_io_map = m8xx_set_io_map, .set_io_map = m8xx_set_io_map,
.set_mem_map = m8xx_set_mem_map, .set_mem_map = m8xx_set_mem_map,
@ -1244,7 +1316,7 @@ static int __init m8xx_init(void)
socket[i].socket.io_offset = 0; socket[i].socket.io_offset = 0;
socket[i].socket.pci_irq = i ? 7 : 9; socket[i].socket.pci_irq = i ? 7 : 9;
socket[i].socket.ops = &m8xx_services; socket[i].socket.ops = &m8xx_services;
socket[i].socket.resource_ops = &pccard_nonstatic_ops; socket[i].socket.resource_ops = &pccard_iodyn_ops;
socket[i].socket.cb_dev = NULL; socket[i].socket.cb_dev = NULL;
socket[i].socket.dev.dev = &m8xx_device.dev; socket[i].socket.dev.dev = &m8xx_device.dev;
} }

View File

@ -304,75 +304,6 @@ static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
} }
static int pd6729_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct pd6729_socket *socket
= container_of(sock, struct pd6729_socket, socket);
unsigned char reg, vcc, vpp;
state->flags = 0;
state->Vcc = 0;
state->Vpp = 0;
state->io_irq = 0;
state->csc_mask = 0;
/* First the power status of the socket */
reg = indirect_read(socket, I365_POWER);
if (reg & I365_PWR_AUTO)
state->flags |= SS_PWR_AUTO; /* Automatic Power Switch */
if (reg & I365_PWR_OUT)
state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
if (reg & I365_VCC_5V) {
state->Vcc = (indirect_read(socket, PD67_MISC_CTL_1) &
PD67_MC1_VCC_3V) ? 33 : 50;
if (vpp == I365_VPP1_5V) {
if (state->Vcc == 50)
state->Vpp = 50;
else
state->Vpp = 33;
}
if (vpp == I365_VPP1_12V)
state->Vpp = 120;
}
/* Now the IO card, RESET flags and IO interrupt */
reg = indirect_read(socket, I365_INTCTL);
if ((reg & I365_PC_RESET) == 0)
state->flags |= SS_RESET;
if (reg & I365_PC_IOCARD)
state->flags |= SS_IOCARD; /* This is an IO card */
/* Set the IRQ number */
state->io_irq = socket->card_irq;
/* Card status change */
reg = indirect_read(socket, I365_CSCINT);
if (reg & I365_CSC_DETECT)
state->csc_mask |= SS_DETECT; /* Card detect is enabled */
if (state->flags & SS_IOCARD) {/* IO Cards behave different */
if (reg & I365_CSC_STSCHG)
state->csc_mask |= SS_STSCHG;
} else {
if (reg & I365_CSC_BVD1)
state->csc_mask |= SS_BATDEAD;
if (reg & I365_CSC_BVD2)
state->csc_mask |= SS_BATWARN;
if (reg & I365_CSC_READY)
state->csc_mask |= SS_READY;
}
return 0;
}
static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state) static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
{ {
struct pd6729_socket *socket struct pd6729_socket *socket
@ -640,7 +571,6 @@ static int pd6729_init(struct pcmcia_socket *sock)
static struct pccard_operations pd6729_operations = { static struct pccard_operations pd6729_operations = {
.init = pd6729_init, .init = pd6729_init,
.get_status = pd6729_get_status, .get_status = pd6729_get_status,
.get_socket = pd6729_get_socket,
.set_socket = pd6729_set_socket, .set_socket = pd6729_set_socket,
.set_io_map = pd6729_set_io_map, .set_io_map = pd6729_set_io_map,
.set_mem_map = pd6729_set_mem_map, .set_mem_map = pd6729_set_mem_map,
@ -704,13 +634,11 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
char configbyte; char configbyte;
struct pd6729_socket *socket; struct pd6729_socket *socket;
socket = kmalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS, socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
GFP_KERNEL); GFP_KERNEL);
if (!socket) if (!socket)
return -ENOMEM; return -ENOMEM;
memset(socket, 0, sizeof(struct pd6729_socket) * MAX_SOCKETS);
if ((ret = pci_enable_device(dev))) if ((ret = pci_enable_device(dev)))
goto err_out_free_mem; goto err_out_free_mem;

View File

@ -171,10 +171,9 @@ static int __init mst_pcmcia_init(void)
{ {
int ret; int ret;
mst_pcmcia_device = kmalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL); mst_pcmcia_device = kzalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL);
if (!mst_pcmcia_device) if (!mst_pcmcia_device)
return -ENOMEM; return -ENOMEM;
memset(mst_pcmcia_device, 0, sizeof(*mst_pcmcia_device));
mst_pcmcia_device->name = "pxa2xx-pcmcia"; mst_pcmcia_device->name = "pxa2xx-pcmcia";
mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;

View File

@ -264,11 +264,10 @@ static int __init sharpsl_pcmcia_init(void)
int ret; int ret;
sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs; sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs;
sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL); sharpsl_pcmcia_device = kzalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL);
if (!sharpsl_pcmcia_device) if (!sharpsl_pcmcia_device)
return -ENOMEM; return -ENOMEM;
memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device));
sharpsl_pcmcia_device->name = "pxa2xx-pcmcia"; sharpsl_pcmcia_device->name = "pxa2xx-pcmcia";
sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops;
sharpsl_pcmcia_device->dev.parent=platform_scoop_config->devs[0].dev; sharpsl_pcmcia_device->dev.parent=platform_scoop_config->devs[0].dev;

View File

@ -98,10 +98,12 @@ int pcmcia_adjust_resource_info(adjust_t *adj)
} }
EXPORT_SYMBOL(pcmcia_adjust_resource_info); EXPORT_SYMBOL(pcmcia_adjust_resource_info);
void pcmcia_validate_mem(struct pcmcia_socket *s) int pcmcia_validate_mem(struct pcmcia_socket *s)
{ {
if (s->resource_ops->validate_mem) if (s->resource_ops->validate_mem)
s->resource_ops->validate_mem(s); return s->resource_ops->validate_mem(s);
/* if there is no callback, we can assume that everything is OK */
return 0;
} }
EXPORT_SYMBOL(pcmcia_validate_mem); EXPORT_SYMBOL(pcmcia_validate_mem);
@ -164,3 +166,105 @@ struct pccard_resource_ops pccard_static_ops = {
.exit = NULL, .exit = NULL,
}; };
EXPORT_SYMBOL(pccard_static_ops); EXPORT_SYMBOL(pccard_static_ops);
#ifdef CONFIG_PCCARD_IODYN
static struct resource *
make_resource(unsigned long b, unsigned long n, int flags, char *name)
{
struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
if (res) {
res->name = name;
res->start = b;
res->end = b + n - 1;
res->flags = flags;
}
return res;
}
struct pcmcia_align_data {
unsigned long mask;
unsigned long offset;
};
static void pcmcia_align(void *align_data, struct resource *res,
unsigned long size, unsigned long align)
{
struct pcmcia_align_data *data = align_data;
unsigned long start;
start = (res->start & ~data->mask) + data->offset;
if (start < res->start)
start += data->mask + 1;
res->start = start;
#ifdef CONFIG_X86
if (res->flags & IORESOURCE_IO) {
if (start & 0x300) {
start = (start + 0x3ff) & ~0x3ff;
res->start = start;
}
}
#endif
#ifdef CONFIG_M68K
if (res->flags & IORESOURCE_IO) {
if ((res->start + size - 1) >= 1024)
res->start = res->end;
}
#endif
}
static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start,
unsigned long r_end, struct pcmcia_socket *s)
{
return adjust_resource(res, r_start, r_end - r_start + 1);
}
static struct resource *iodyn_find_io_region(unsigned long base, int num,
unsigned long align, struct pcmcia_socket *s)
{
struct resource *res = make_resource(0, num, IORESOURCE_IO,
s->dev.class_id);
struct pcmcia_align_data data;
unsigned long min = base;
int ret;
if (align == 0)
align = 0x10000;
data.mask = align - 1;
data.offset = base & data.mask;
#ifdef CONFIG_PCI
if (s->cb_dev) {
ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
min, 0, pcmcia_align, &data);
} else
#endif
ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
1, pcmcia_align, &data);
if (ret != 0) {
kfree(res);
res = NULL;
}
return res;
}
struct pccard_resource_ops pccard_iodyn_ops = {
.validate_mem = NULL,
.adjust_io_region = iodyn_adjust_io_region,
.find_io = iodyn_find_io_region,
.find_mem = NULL,
.adjust_resource = NULL,
.init = static_init,
.exit = NULL,
};
EXPORT_SYMBOL(pccard_iodyn_ops);
#endif /* CONFIG_PCCARD_IODYN */

View File

@ -75,10 +75,9 @@ static DECLARE_MUTEX(rsrc_sem);
static struct resource * static struct resource *
make_resource(unsigned long b, unsigned long n, int flags, char *name) make_resource(unsigned long b, unsigned long n, int flags, char *name)
{ {
struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
if (res) { if (res) {
memset(res, 0, sizeof(*res));
res->name = name; res->name = name;
res->start = b; res->start = b;
res->end = b + n - 1; res->end = b + n - 1;
@ -200,12 +199,11 @@ static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num
base, base+num-1); base, base+num-1);
/* First, what does a floating port look like? */ /* First, what does a floating port look like? */
b = kmalloc(256, GFP_KERNEL); b = kzalloc(256, GFP_KERNEL);
if (!b) { if (!b) {
printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes"); printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
return; return;
} }
memset(b, 0, 256);
for (i = base, most = 0; i < base+num; i += 8) { for (i = base, most = 0; i < base+num; i += 8) {
res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe"); res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
if (!res) if (!res)
@ -407,69 +405,79 @@ static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s) static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
{ {
struct socket_data *s_data = s->resource_data; struct socket_data *s_data = s->resource_data;
u_long ok; u_long ok;
if (m == &s_data->mem_db) if (m == &s_data->mem_db)
return 0; return 0;
ok = inv_probe(m->next, s); ok = inv_probe(m->next, s);
if (ok) { if (ok) {
if (m->base >= 0x100000) if (m->base >= 0x100000)
sub_interval(&s_data->mem_db, m->base, m->num); sub_interval(&s_data->mem_db, m->base, m->num);
return ok; return ok;
} }
if (m->base < 0x100000) if (m->base < 0x100000)
return 0; return 0;
return do_mem_probe(m->base, m->num, s); return do_mem_probe(m->base, m->num, s);
} }
static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{ {
struct resource_map *m, mm; struct resource_map *m, mm;
static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 }; static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
u_long b, i, ok = 0; unsigned long b, i, ok = 0;
struct socket_data *s_data = s->resource_data; struct socket_data *s_data = s->resource_data;
/* We do up to four passes through the list */ /* We do up to four passes through the list */
if (probe_mask & MEM_PROBE_HIGH) { if (probe_mask & MEM_PROBE_HIGH) {
if (inv_probe(s_data->mem_db.next, s) > 0) if (inv_probe(s_data->mem_db.next, s) > 0)
return; return 0;
printk(KERN_NOTICE "cs: warning: no high memory space " printk(KERN_NOTICE "cs: warning: no high memory space "
"available!\n"); "available!\n");
} return -ENODEV;
if ((probe_mask & MEM_PROBE_LOW) == 0)
return;
for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
mm = *m;
/* Only probe < 1 MB */
if (mm.base >= 0x100000) continue;
if ((mm.base | mm.num) & 0xffff) {
ok += do_mem_probe(mm.base, mm.num, s);
continue;
} }
/* Special probe for 64K-aligned block */
for (i = 0; i < 4; i++) { for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
b = order[i] << 12; mm = *m;
if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) { /* Only probe < 1 MB */
if (ok >= mem_limit) if (mm.base >= 0x100000)
sub_interval(&s_data->mem_db, b, 0x10000); continue;
else if ((mm.base | mm.num) & 0xffff) {
ok += do_mem_probe(b, 0x10000, s); ok += do_mem_probe(mm.base, mm.num, s);
} continue;
}
/* Special probe for 64K-aligned block */
for (i = 0; i < 4; i++) {
b = order[i] << 12;
if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
if (ok >= mem_limit)
sub_interval(&s_data->mem_db, b, 0x10000);
else
ok += do_mem_probe(b, 0x10000, s);
}
}
} }
}
if (ok > 0)
return 0;
return -ENODEV;
} }
#else /* CONFIG_PCMCIA_PROBE */ #else /* CONFIG_PCMCIA_PROBE */
static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask) static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{ {
struct resource_map *m, mm; struct resource_map *m, mm;
struct socket_data *s_data = s->resource_data; struct socket_data *s_data = s->resource_data;
unsigned long ok = 0;
for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) { for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
mm = *m; mm = *m;
do_mem_probe(mm.base, mm.num, s); ok += do_mem_probe(mm.base, mm.num, s);
} }
if (ok > 0)
return 0;
return -ENODEV;
} }
#endif /* CONFIG_PCMCIA_PROBE */ #endif /* CONFIG_PCMCIA_PROBE */
@ -478,27 +486,30 @@ static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
/* /*
* Locking note: Must be called with skt_sem held! * Locking note: Must be called with skt_sem held!
*/ */
static void pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s) static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
{ {
struct socket_data *s_data = s->resource_data; struct socket_data *s_data = s->resource_data;
if (probe_mem) { unsigned int probe_mask = MEM_PROBE_LOW;
unsigned int probe_mask; int ret = 0;
down(&rsrc_sem); if (!probe_mem)
return 0;
probe_mask = MEM_PROBE_LOW; down(&rsrc_sem);
if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
if (probe_mask & ~s_data->rsrc_mem_probe) { if (s->features & SS_CAP_PAGE_REGS)
probe_mask = MEM_PROBE_HIGH;
if (probe_mask & ~s_data->rsrc_mem_probe) {
if (s->state & SOCKET_PRESENT)
ret = validate_mem(s, probe_mask);
if (!ret)
s_data->rsrc_mem_probe |= probe_mask; s_data->rsrc_mem_probe |= probe_mask;
if (s->state & SOCKET_PRESENT)
validate_mem(s, probe_mask);
}
up(&rsrc_sem);
} }
up(&rsrc_sem);
return ret;
} }
struct pcmcia_align_data { struct pcmcia_align_data {
@ -837,10 +848,9 @@ static int nonstatic_init(struct pcmcia_socket *s)
{ {
struct socket_data *data; struct socket_data *data;
data = kmalloc(sizeof(struct socket_data), GFP_KERNEL); data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
memset(data, 0, sizeof(struct socket_data));
data->mem_db.next = &data->mem_db; data->mem_db.next = &data->mem_db;
data->io_db.next = &data->io_db; data->io_db.next = &data->io_db;

View File

@ -296,25 +296,6 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
} }
/*
* 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
soc_common_pcmcia_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
debug(skt, 2, "\n");
*state = skt->cs_state;
return 0;
}
/* /*
* 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
@ -528,7 +509,6 @@ static struct pccard_operations soc_common_pcmcia_operations = {
.init = soc_common_pcmcia_sock_init, .init = soc_common_pcmcia_sock_init,
.suspend = soc_common_pcmcia_suspend, .suspend = soc_common_pcmcia_suspend,
.get_status = soc_common_pcmcia_get_status, .get_status = soc_common_pcmcia_get_status,
.get_socket = soc_common_pcmcia_get_socket,
.set_socket = soc_common_pcmcia_set_socket, .set_socket = soc_common_pcmcia_set_socket,
.set_io_map = soc_common_pcmcia_set_io_map, .set_io_map = soc_common_pcmcia_set_io_map,
.set_mem_map = soc_common_pcmcia_set_mem_map, .set_mem_map = soc_common_pcmcia_set_mem_map,
@ -665,13 +645,12 @@ int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops
down(&soc_pcmcia_sockets_lock); down(&soc_pcmcia_sockets_lock);
sinfo = kmalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL);
if (!sinfo) { if (!sinfo) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
memset(sinfo, 0, SKT_DEV_INFO_SIZE(nr));
sinfo->nskt = nr; sinfo->nskt = nr;
/* /*

View File

@ -42,35 +42,28 @@
static ssize_t pccard_show_type(struct class_device *dev, char *buf) static ssize_t pccard_show_type(struct class_device *dev, char *buf)
{ {
int val;
struct pcmcia_socket *s = to_socket(dev); struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT)) if (!(s->state & SOCKET_PRESENT))
return -ENODEV; return -ENODEV;
s->ops->get_status(s, &val); if (s->state & SOCKET_CARDBUS)
if (val & SS_CARDBUS)
return sprintf(buf, "32-bit\n"); return sprintf(buf, "32-bit\n");
if (val & SS_DETECT) return sprintf(buf, "16-bit\n");
return sprintf(buf, "16-bit\n");
return sprintf(buf, "invalid\n");
} }
static CLASS_DEVICE_ATTR(card_type, 0400, pccard_show_type, NULL); static CLASS_DEVICE_ATTR(card_type, 0444, pccard_show_type, NULL);
static ssize_t pccard_show_voltage(struct class_device *dev, char *buf) static ssize_t pccard_show_voltage(struct class_device *dev, char *buf)
{ {
int val;
struct pcmcia_socket *s = to_socket(dev); struct pcmcia_socket *s = to_socket(dev);
if (!(s->state & SOCKET_PRESENT)) if (!(s->state & SOCKET_PRESENT))
return -ENODEV; return -ENODEV;
s->ops->get_status(s, &val); if (s->socket.Vcc)
if (val & SS_3VCARD) return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10,
return sprintf(buf, "3.3V\n"); s->socket.Vcc % 10);
if (val & SS_XVCARD) return sprintf(buf, "X.XV\n");
return sprintf(buf, "X.XV\n");
return sprintf(buf, "5.0V\n");
} }
static CLASS_DEVICE_ATTR(card_voltage, 0400, pccard_show_voltage, NULL); static CLASS_DEVICE_ATTR(card_voltage, 0444, pccard_show_voltage, NULL);
static ssize_t pccard_show_vpp(struct class_device *dev, char *buf) static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
{ {
@ -79,7 +72,7 @@ static ssize_t pccard_show_vpp(struct class_device *dev, char *buf)
return -ENODEV; return -ENODEV;
return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10); return sprintf(buf, "%d.%dV\n", s->socket.Vpp / 10, s->socket.Vpp % 10);
} }
static CLASS_DEVICE_ATTR(card_vpp, 0400, pccard_show_vpp, NULL); static CLASS_DEVICE_ATTR(card_vpp, 0444, pccard_show_vpp, NULL);
static ssize_t pccard_show_vcc(struct class_device *dev, char *buf) static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
{ {
@ -88,7 +81,7 @@ static ssize_t pccard_show_vcc(struct class_device *dev, char *buf)
return -ENODEV; return -ENODEV;
return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10); return sprintf(buf, "%d.%dV\n", s->socket.Vcc / 10, s->socket.Vcc % 10);
} }
static CLASS_DEVICE_ATTR(card_vcc, 0400, pccard_show_vcc, NULL); static CLASS_DEVICE_ATTR(card_vcc, 0444, pccard_show_vcc, NULL);
static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count) static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, size_t count)
@ -292,10 +285,9 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
if (!(s->state & SOCKET_PRESENT)) if (!(s->state & SOCKET_PRESENT))
return -ENODEV; return -ENODEV;
cis = kmalloc(sizeof(cisdump_t), GFP_KERNEL); cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
if (!cis) if (!cis)
return -ENOMEM; return -ENOMEM;
memset(cis, 0, sizeof(cisdump_t));
cis->Length = count + 1; cis->Length = count + 1;
memcpy(cis->Data, buf, count); memcpy(cis->Data, buf, count);

View File

@ -181,13 +181,6 @@ static void tcic_setl(u_char reg, u_int data)
outw(data >> 16, tcic_base+reg+2); outw(data >> 16, tcic_base+reg+2);
} }
static u_char tcic_aux_getb(u_short reg)
{
u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
tcic_setb(TCIC_MODE, mode);
return tcic_getb(TCIC_AUX);
}
static void tcic_aux_setb(u_short reg, u_char data) static void tcic_aux_setb(u_short reg, u_char data)
{ {
u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg; u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
@ -641,59 +634,6 @@ static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
debug(1, "GetStatus(%d) = %#2.2x\n", psock, *value); debug(1, "GetStatus(%d) = %#2.2x\n", psock, *value);
return 0; return 0;
} /* tcic_get_status */ } /* tcic_get_status */
/*====================================================================*/
static int tcic_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
u_char reg;
u_short scf1, scf2;
tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
| TCIC_ADDR_INDREG | TCIC_SCF1(psock));
scf1 = tcic_getw(TCIC_DATA);
state->flags = (scf1 & TCIC_SCF1_IOSTS) ? SS_IOCARD : 0;
state->flags |= (scf1 & TCIC_SCF1_DMA_MASK) ? SS_DMA_MODE : 0;
state->flags |= (scf1 & TCIC_SCF1_SPKR) ? SS_SPKR_ENA : 0;
if (tcic_getb(TCIC_SCTRL) & TCIC_SCTRL_ENA)
state->flags |= SS_OUTPUT_ENA;
state->io_irq = scf1 & TCIC_SCF1_IRQ_MASK;
if (state->io_irq == 1) state->io_irq = 11;
reg = tcic_getb(TCIC_PWR);
state->Vcc = state->Vpp = 0;
if (reg & TCIC_PWR_VCC(psock)) {
if (reg & TCIC_PWR_VPP(psock))
state->Vcc = 50;
else
state->Vcc = state->Vpp = 50;
} else {
if (reg & TCIC_PWR_VPP(psock)) {
state->Vcc = 50;
state->Vpp = 120;
}
}
reg = tcic_aux_getb(TCIC_AUX_ILOCK);
state->flags |= (reg & TCIC_ILOCK_CRESET) ? SS_RESET : 0;
/* Card status change interrupt mask */
tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
scf2 = tcic_getw(TCIC_DATA);
state->csc_mask = (scf2 & TCIC_SCF2_MCD) ? 0 : SS_DETECT;
if (state->flags & SS_IOCARD) {
state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_STSCHG;
} else {
state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT1) ? 0 : SS_BATDEAD;
state->csc_mask |= (scf2 & TCIC_SCF2_MLBAT2) ? 0 : SS_BATWARN;
state->csc_mask |= (scf2 & TCIC_SCF2_MRDY) ? 0 : SS_READY;
}
debug(1, "GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x\n", psock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
return 0;
} /* tcic_get_socket */
/*====================================================================*/ /*====================================================================*/
@ -874,7 +814,6 @@ static int tcic_init(struct pcmcia_socket *s)
static struct pccard_operations tcic_operations = { static struct pccard_operations tcic_operations = {
.init = tcic_init, .init = tcic_init,
.get_status = tcic_get_status, .get_status = tcic_get_status,
.get_socket = tcic_get_socket,
.set_socket = tcic_set_socket, .set_socket = tcic_set_socket,
.set_io_map = tcic_set_io_map, .set_io_map = tcic_set_io_map,
.set_mem_map = tcic_set_mem_map, .set_mem_map = tcic_set_mem_map,

View File

@ -873,7 +873,7 @@ static int ti1250_override(struct yenta_socket *socket)
* Some fixup code to make everybody happy (TM). * Some fixup code to make everybody happy (TM).
*/ */
#ifdef CONFIG_CARDBUS #ifdef CONFIG_YENTA_ENE_TUNE
/** /**
* set/clear various test bits: * set/clear various test bits:
* Defaults to clear the bit. * Defaults to clear the bit.
@ -937,7 +937,7 @@ static int ene_override(struct yenta_socket *socket)
} }
#else #else
# define ene_override ti1250_override # define ene_override ti1250_override
#endif #endif /* !CONFIG_YENTA_ENE_TUNE */
#endif /* _LINUX_TI113X_H */ #endif /* _LINUX_TI113X_H */

View File

@ -301,75 +301,6 @@ static int pccard_get_status(struct pcmcia_socket *sock, u_int *value)
return 0; return 0;
} }
static inline u_char get_Vcc_value(uint8_t voltage)
{
switch (voltage) {
case VCC_STATUS_3V:
return 33;
case VCC_STATUS_5V:
return 50;
default:
break;
}
return 0;
}
static inline u_char get_Vpp_value(uint8_t power, u_char Vcc)
{
if ((power & 0x03) == 0x01 || (power & 0x03) == 0x02)
return Vcc;
return 0;
}
static int pccard_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
unsigned int slot;
uint8_t power, voltage, control, cscint;
if (sock == NULL || sock->sock >= CARD_MAX_SLOTS || state == NULL)
return -EINVAL;
slot = sock->sock;
power = exca_read_byte(slot, I365_POWER);
voltage = exca_read_byte(slot, CARD_VOLTAGE_SELECT);
state->Vcc = get_Vcc_value(voltage);
state->Vpp = get_Vpp_value(power, state->Vcc);
state->flags = 0;
if (power & POWER_ENABLE)
state->flags |= SS_PWR_AUTO;
if (power & I365_PWR_OUT)
state->flags |= SS_OUTPUT_ENA;
control = exca_read_byte(slot, I365_INTCTL);
if (control & I365_PC_IOCARD)
state->flags |= SS_IOCARD;
if (!(control & I365_PC_RESET))
state->flags |= SS_RESET;
cscint = exca_read_byte(slot, I365_CSCINT);
state->csc_mask = 0;
if (state->flags & SS_IOCARD) {
if (cscint & I365_CSC_STSCHG)
state->flags |= SS_STSCHG;
} else {
if (cscint & I365_CSC_BVD1)
state->csc_mask |= SS_BATDEAD;
if (cscint & I365_CSC_BVD2)
state->csc_mask |= SS_BATWARN;
}
if (cscint & I365_CSC_READY)
state->csc_mask |= SS_READY;
if (cscint & I365_CSC_DETECT)
state->csc_mask |= SS_DETECT;
return 0;
}
static inline uint8_t set_Vcc_value(u_char Vcc) static inline uint8_t set_Vcc_value(u_char Vcc)
{ {
switch (Vcc) { switch (Vcc) {
@ -551,7 +482,6 @@ static int pccard_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
static struct pccard_operations vrc4171_pccard_operations = { static struct pccard_operations vrc4171_pccard_operations = {
.init = pccard_init, .init = pccard_init,
.get_status = pccard_get_status, .get_status = pccard_get_status,
.get_socket = pccard_get_socket,
.set_socket = pccard_set_socket, .set_socket = pccard_set_socket,
.set_io_map = pccard_set_io_map, .set_io_map = pccard_set_io_map,
.set_mem_map = pccard_set_mem_map, .set_mem_map = pccard_set_mem_map,

View File

@ -198,48 +198,6 @@ static int cardu_get_status(unsigned int sock, u_int *value)
return 0; return 0;
} }
static inline u_char get_Vcc_value(uint8_t val)
{
switch (val & VCC_MASK) {
case VCC_3V:
return 33;
case VCC_5V:
return 50;
}
return 0;
}
static inline u_char get_Vpp_value(uint8_t val)
{
switch (val & VPP_MASK) {
case VPP_12V:
return 120;
case VPP_VCC:
return get_Vcc_value(val);
}
return 0;
}
static int cardu_get_socket(unsigned int sock, socket_state_t *state)
{
vrc4173_socket_t *socket = &cardu_sockets[sock];
uint8_t val;
val = exca_readb(socket, PWR_CNT);
state->Vcc = get_Vcc_value(val);
state->Vpp = get_Vpp_value(val);
state->flags = 0;
if (val & CARD_OUT_EN) state->flags |= SS_OUTPUT_ENA;
val = exca_readb(socket, INT_GEN_CNT);
if (!(val & CARD_REST0)) state->flags |= SS_RESET;
if (val & CARD_TYPE_IO) state->flags |= SS_IOCARD;
return 0;
}
static inline uint8_t set_Vcc_value(u_char Vcc) static inline uint8_t set_Vcc_value(u_char Vcc)
{ {
switch (Vcc) { switch (Vcc) {
@ -431,7 +389,6 @@ static struct pccard_operations cardu_operations = {
.register_callback = cardu_register_callback, .register_callback = cardu_register_callback,
.inquire_socket = cardu_inquire_socket, .inquire_socket = cardu_inquire_socket,
.get_status = cardu_get_status, .get_status = cardu_get_status,
.get_socket = cardu_get_socket,
.set_socket = cardu_set_socket, .set_socket = cardu_set_socket,
.get_io_map = cardu_get_io_map, .get_io_map = cardu_get_io_map,
.set_io_map = cardu_set_io_map, .set_io_map = cardu_set_io_map,

View File

@ -49,7 +49,13 @@ MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only
#define to_cycles(ns) ((ns)/120) #define to_cycles(ns) ((ns)/120)
#define to_ns(cycles) ((cycles)*120) #define to_ns(cycles) ((cycles)*120)
/**
* yenta PCI irq probing.
* currently only used in the TI/EnE initialization code
*/
#ifdef CONFIG_YENTA_TI
static int yenta_probe_cb_irq(struct yenta_socket *socket); static int yenta_probe_cb_irq(struct yenta_socket *socket);
#endif
static unsigned int override_bios; static unsigned int override_bios;
@ -224,95 +230,6 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
return 0; return 0;
} }
static void yenta_get_power(struct yenta_socket *socket, socket_state_t *state)
{
if (!(cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) &&
(socket->flags & YENTA_16BIT_POWER_EXCA)) {
u8 reg, vcc, vpp;
reg = exca_readb(socket, I365_POWER);
vcc = reg & I365_VCC_MASK;
vpp = reg & I365_VPP1_MASK;
state->Vcc = state->Vpp = 0;
if (socket->flags & YENTA_16BIT_POWER_DF) {
if (vcc == I365_VCC_3V)
state->Vcc = 33;
if (vcc == I365_VCC_5V)
state->Vcc = 50;
if (vpp == I365_VPP1_5V)
state->Vpp = state->Vcc;
if (vpp == I365_VPP1_12V)
state->Vpp = 120;
} else {
if (reg & I365_VCC_5V) {
state->Vcc = 50;
if (vpp == I365_VPP1_5V)
state->Vpp = 50;
if (vpp == I365_VPP1_12V)
state->Vpp = 120;
}
}
} else {
u32 control;
control = cb_readl(socket, CB_SOCKET_CONTROL);
switch (control & CB_SC_VCC_MASK) {
case CB_SC_VCC_5V: state->Vcc = 50; break;
case CB_SC_VCC_3V: state->Vcc = 33; break;
default: state->Vcc = 0;
}
switch (control & CB_SC_VPP_MASK) {
case CB_SC_VPP_12V: state->Vpp = 120; break;
case CB_SC_VPP_5V: state->Vpp = 50; break;
case CB_SC_VPP_3V: state->Vpp = 33; break;
default: state->Vpp = 0;
}
}
}
static int yenta_get_socket(struct pcmcia_socket *sock, socket_state_t *state)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
u8 reg;
u32 control;
control = cb_readl(socket, CB_SOCKET_CONTROL);
yenta_get_power(socket, state);
state->io_irq = socket->io_irq;
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
u16 bridge = config_readw(socket, CB_BRIDGE_CONTROL);
if (bridge & CB_BRIDGE_CRST)
state->flags |= SS_RESET;
return 0;
}
/* 16-bit card state.. */
reg = exca_readb(socket, I365_POWER);
state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
reg = exca_readb(socket, I365_INTCTL);
state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
reg = exca_readb(socket, I365_CSCINT);
state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
if (state->flags & SS_IOCARD) {
state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
} else {
state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
}
return 0;
}
static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state) static void yenta_set_power(struct yenta_socket *socket, socket_state_t *state)
{ {
/* some birdges require to use the ExCA registers to power 16bit cards */ /* some birdges require to use the ExCA registers to power 16bit cards */
@ -531,6 +448,9 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
csc = exca_readb(socket, I365_CSC); csc = exca_readb(socket, I365_CSC);
if (!(cb_event || csc))
return IRQ_NONE;
events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ; events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ;
events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0; events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) { if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
@ -544,10 +464,7 @@ static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (events) if (events)
pcmcia_parse_events(&socket->socket, events); pcmcia_parse_events(&socket->socket, events);
if (cb_event || csc) return IRQ_HANDLED;
return IRQ_HANDLED;
return IRQ_NONE;
} }
static void yenta_interrupt_wrapper(unsigned long data) static void yenta_interrupt_wrapper(unsigned long data)
@ -828,17 +745,24 @@ static struct pccard_operations yenta_socket_operations = {
.init = yenta_sock_init, .init = yenta_sock_init,
.suspend = yenta_sock_suspend, .suspend = yenta_sock_suspend,
.get_status = yenta_get_status, .get_status = yenta_get_status,
.get_socket = yenta_get_socket,
.set_socket = yenta_set_socket, .set_socket = yenta_set_socket,
.set_io_map = yenta_set_io_map, .set_io_map = yenta_set_io_map,
.set_mem_map = yenta_set_mem_map, .set_mem_map = yenta_set_mem_map,
}; };
#ifdef CONFIG_YENTA_TI
#include "ti113x.h" #include "ti113x.h"
#endif
#ifdef CONFIG_YENTA_RICOH
#include "ricoh.h" #include "ricoh.h"
#endif
#ifdef CONFIG_YENTA_TOSHIBA
#include "topic.h" #include "topic.h"
#endif
#ifdef CONFIG_YENTA_O2
#include "o2micro.h" #include "o2micro.h"
#endif
enum { enum {
CARDBUS_TYPE_DEFAULT = -1, CARDBUS_TYPE_DEFAULT = -1,
@ -858,6 +782,7 @@ enum {
* initialization sequences etc details. List them here.. * initialization sequences etc details. List them here..
*/ */
static struct cardbus_type cardbus_type[] = { static struct cardbus_type cardbus_type[] = {
#ifdef CONFIG_YENTA_TI
[CARDBUS_TYPE_TI] = { [CARDBUS_TYPE_TI] = {
.override = ti_override, .override = ti_override,
.save_state = ti_save_state, .save_state = ti_save_state,
@ -882,27 +807,36 @@ static struct cardbus_type cardbus_type[] = {
.restore_state = ti_restore_state, .restore_state = ti_restore_state,
.sock_init = ti_init, .sock_init = ti_init,
}, },
#endif
#ifdef CONFIG_YENTA_RICOH
[CARDBUS_TYPE_RICOH] = { [CARDBUS_TYPE_RICOH] = {
.override = ricoh_override, .override = ricoh_override,
.save_state = ricoh_save_state, .save_state = ricoh_save_state,
.restore_state = ricoh_restore_state, .restore_state = ricoh_restore_state,
}, },
#endif
#ifdef CONFIG_YENTA_TOSHIBA
[CARDBUS_TYPE_TOPIC95] = { [CARDBUS_TYPE_TOPIC95] = {
.override = topic95_override, .override = topic95_override,
}, },
[CARDBUS_TYPE_TOPIC97] = { [CARDBUS_TYPE_TOPIC97] = {
.override = topic97_override, .override = topic97_override,
}, },
#endif
#ifdef CONFIG_YENTA_O2
[CARDBUS_TYPE_O2MICRO] = { [CARDBUS_TYPE_O2MICRO] = {
.override = o2micro_override, .override = o2micro_override,
.restore_state = o2micro_restore_state, .restore_state = o2micro_restore_state,
}, },
#endif
#ifdef CONFIG_YENTA_TI
[CARDBUS_TYPE_ENE] = { [CARDBUS_TYPE_ENE] = {
.override = ene_override, .override = ene_override,
.save_state = ti_save_state, .save_state = ti_save_state,
.restore_state = ti_restore_state, .restore_state = ti_restore_state,
.sock_init = ti_init, .sock_init = ti_init,
}, },
#endif
}; };
@ -948,6 +882,12 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas
} }
/**
* yenta PCI irq probing.
* currently only used in the TI/EnE initialization code
*/
#ifdef CONFIG_YENTA_TI
/* interrupt handler, only used during probing */ /* interrupt handler, only used during probing */
static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *regs)
{ {
@ -1000,6 +940,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket)
return (int) socket->probe_status; return (int) socket->probe_status;
} }
#endif /* CONFIG_YENTA_TI */
/* /*
@ -1078,10 +1019,9 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
return -ENODEV; return -ENODEV;
} }
socket = kmalloc(sizeof(struct yenta_socket), GFP_KERNEL); socket = kzalloc(sizeof(struct yenta_socket), GFP_KERNEL);
if (!socket) if (!socket)
return -ENOMEM; return -ENOMEM;
memset(socket, 0, sizeof(*socket));
/* prepare pcmcia_socket */ /* prepare pcmcia_socket */
socket->socket.ops = &yenta_socket_operations; socket->socket.ops = &yenta_socket_operations;
@ -1263,6 +1203,7 @@ static struct pci_device_id yenta_table [] = {
* advanced overrides instead. (I can't get the * advanced overrides instead. (I can't get the
* data sheets for these devices. --rmk) * data sheets for these devices. --rmk)
*/ */
#ifdef CONFIG_YENTA_TI
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210, TI),
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130, TI113X),
@ -1305,18 +1246,25 @@ static struct pci_device_id yenta_table [] = {
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
#endif /* CONFIG_YENTA_TI */
#ifdef CONFIG_YENTA_RICOH
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, RICOH),
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478, RICOH),
#endif
#ifdef CONFIG_YENTA_TOSHIBA
CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95), CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95, TOPIC95),
CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97), CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97, TOPIC97),
CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97), CB_ID(PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC100, TOPIC97),
#endif
#ifdef CONFIG_YENTA_O2
CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO), CB_ID(PCI_VENDOR_ID_O2, PCI_ANY_ID, O2MICRO),
#endif
/* match any cardbus bridge */ /* match any cardbus bridge */
CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT),

View File

@ -95,27 +95,21 @@ typedef struct scsi_info_t {
} scsi_info_t; } scsi_info_t;
static void aha152x_release_cs(dev_link_t *link); static void aha152x_release_cs(dev_link_t *link);
static int aha152x_event(event_t event, int priority, static void aha152x_detach(struct pcmcia_device *p_dev);
event_callback_args_t *args); static void aha152x_config_cs(dev_link_t *link);
static dev_link_t *aha152x_attach(void);
static void aha152x_detach(dev_link_t *);
static dev_link_t *dev_list; static dev_link_t *dev_list;
static dev_info_t dev_info = "aha152x_cs";
static dev_link_t *aha152x_attach(void) static int aha152x_attach(struct pcmcia_device *p_dev)
{ {
scsi_info_t *info; scsi_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
DEBUG(0, "aha152x_attach()\n"); DEBUG(0, "aha152x_attach()\n");
/* Create new SCSI device */ /* Create new SCSI 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));
link = &info->link; link->priv = info; link = &info->link; link->priv = info;
@ -129,26 +123,20 @@ static dev_link_t *aha152x_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;
/* 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; aha152x_config_cs(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);
aha152x_detach(link);
return NULL;
}
return link;
} /* aha152x_attach */ } /* aha152x_attach */
/*====================================================================*/ /*====================================================================*/
static void aha152x_detach(dev_link_t *link) static void aha152x_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
dev_link_t **linkp; dev_link_t **linkp;
DEBUG(0, "aha152x_detach(0x%p)\n", link); DEBUG(0, "aha152x_detach(0x%p)\n", link);
@ -162,9 +150,6 @@ static void aha152x_detach(dev_link_t *link)
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
aha152x_release_cs(link); aha152x_release_cs(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */ /* Unlink device structure, free bits */
*linkp = link->next; *linkp = link->next;
kfree(link->priv); kfree(link->priv);
@ -272,44 +257,31 @@ static void aha152x_release_cs(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int aha152x_event(event_t event, int priority, static int aha152x_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);
scsi_info_t *info = link->priv;
DEBUG(0, "aha152x_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
aha152x_release_cs(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
aha152x_config_cs(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)
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME: return 0;
}
static int aha152x_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = 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) {
Scsi_Cmnd tmp; Scsi_Cmnd tmp;
pcmcia_request_configuration(link->handle, &link->conf); pcmcia_request_configuration(link->handle, &link->conf);
tmp.device->host = info->host; tmp.device->host = info->host;
aha152x_host_reset(&tmp); aha152x_host_reset(&tmp);
} }
break;
} return 0;
return 0;
} }
static struct pcmcia_device_id aha152x_ids[] = { static struct pcmcia_device_id aha152x_ids[] = {
@ -327,10 +299,11 @@ static struct pcmcia_driver aha152x_cs_driver = {
.drv = { .drv = {
.name = "aha152x_cs", .name = "aha152x_cs",
}, },
.attach = aha152x_attach, .probe = aha152x_attach,
.event = aha152x_event, .remove = aha152x_detach,
.detach = aha152x_detach,
.id_table = aha152x_ids, .id_table = aha152x_ids,
.suspend = aha152x_suspend,
.resume = aha152x_resume,
}; };
static int __init init_aha152x_cs(void) static int __init init_aha152x_cs(void)

View File

@ -80,29 +80,19 @@ typedef struct scsi_info_t {
static void fdomain_release(dev_link_t *link); static void fdomain_release(dev_link_t *link);
static int fdomain_event(event_t event, int priority, static void fdomain_detach(struct pcmcia_device *p_dev);
event_callback_args_t *args); static void fdomain_config(dev_link_t *link);
static dev_link_t *fdomain_attach(void); static int fdomain_attach(struct pcmcia_device *p_dev)
static void fdomain_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
static dev_info_t dev_info = "fdomain_cs";
static dev_link_t *fdomain_attach(void)
{ {
scsi_info_t *info; scsi_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
DEBUG(0, "fdomain_attach()\n"); DEBUG(0, "fdomain_attach()\n");
/* Create new SCSI device */ /* Create new SCSI 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));
link = &info->link; link->priv = info; link = &info->link; link->priv = info;
link->io.NumPorts1 = 0x10; link->io.NumPorts1 = 0x10;
@ -115,46 +105,27 @@ static dev_link_t *fdomain_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;
/* 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; fdomain_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);
fdomain_detach(link);
return NULL;
}
return link;
} /* fdomain_attach */ } /* fdomain_attach */
/*====================================================================*/ /*====================================================================*/
static void fdomain_detach(dev_link_t *link) static void fdomain_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "fdomain_detach(0x%p)\n", link); DEBUG(0, "fdomain_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)
fdomain_release(link); fdomain_release(link);
if (link->handle) kfree(link->priv);
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(link->priv);
} /* fdomain_detach */ } /* fdomain_detach */
/*====================================================================*/ /*====================================================================*/
@ -256,43 +227,29 @@ static void fdomain_release(dev_link_t *link)
/*====================================================================*/ /*====================================================================*/
static int fdomain_event(event_t event, int priority, static int fdomain_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);
DEBUG(1, "fdomain_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
fdomain_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
fdomain_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)
pcmcia_release_configuration(link->handle); 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);
fdomain_16x0_bus_reset(NULL);
}
break;
}
return 0;
} /* fdomain_event */
return 0;
}
static int fdomain_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);
fdomain_16x0_bus_reset(NULL);
}
return 0;
}
static struct pcmcia_device_id fdomain_ids[] = { static struct pcmcia_device_id fdomain_ids[] = {
PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20), PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "SCSI PCMCIA Card", 0xe3736c88, 0x859cad20),
@ -307,10 +264,11 @@ static struct pcmcia_driver fdomain_cs_driver = {
.drv = { .drv = {
.name = "fdomain_cs", .name = "fdomain_cs",
}, },
.attach = fdomain_attach, .probe = fdomain_attach,
.event = fdomain_event, .remove = fdomain_detach,
.detach = fdomain_detach,
.id_table = fdomain_ids, .id_table = fdomain_ids,
.suspend = fdomain_suspend,
.resume = fdomain_resume,
}; };
static int __init init_fdomain_cs(void) static int __init init_fdomain_cs(void)
@ -321,7 +279,6 @@ static int __init init_fdomain_cs(void)
static void __exit exit_fdomain_cs(void) static void __exit exit_fdomain_cs(void)
{ {
pcmcia_unregister_driver(&fdomain_cs_driver); pcmcia_unregister_driver(&fdomain_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_fdomain_cs); module_init(init_fdomain_cs);

View File

@ -104,9 +104,6 @@ static struct scsi_host_template nsp_driver_template = {
#endif #endif
}; };
static dev_link_t *dev_list = NULL;
static dev_info_t dev_info = {"nsp_cs"};
static nsp_hw_data nsp_data_base; /* attach <-> detect glue */ static nsp_hw_data nsp_data_base; /* attach <-> detect glue */
@ -1596,19 +1593,17 @@ static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt)
configure the card at this point -- we wait until we receive a configure the card at this point -- we wait until we receive a
card insertion event. card insertion event.
======================================================================*/ ======================================================================*/
static dev_link_t *nsp_cs_attach(void) static int nsp_cs_attach(struct pcmcia_device *p_dev)
{ {
scsi_info_t *info; scsi_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
nsp_hw_data *data = &nsp_data_base; nsp_hw_data *data = &nsp_data_base;
nsp_dbg(NSP_DEBUG_INIT, "in"); nsp_dbg(NSP_DEBUG_INIT, "in");
/* Create new SCSI device */ /* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) { return NULL; } if (info == NULL) { return -ENOMEM; }
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
@ -1636,23 +1631,14 @@ static dev_link_t *nsp_cs_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->handle = p_dev;
p_dev->instance = link;
/* Register with Card Services */ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
link->next = dev_list; nsp_cs_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 != CS_SUCCESS) {
cs_error(link->handle, RegisterClient, ret);
nsp_cs_detach(link);
return NULL;
}
nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link);
return link; return 0;
} /* nsp_cs_attach */ } /* nsp_cs_attach */
@ -1662,35 +1648,19 @@ static dev_link_t *nsp_cs_attach(void)
structures are freed. Otherwise, the structures will be freed structures are freed. Otherwise, the structures will be freed
when the device is released. when the device is released.
======================================================================*/ ======================================================================*/
static void nsp_cs_detach(dev_link_t *link) static void nsp_cs_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link); nsp_dbg(NSP_DEBUG_INIT, "in, link=0x%p", link);
/* Locate device structure */ if (link->state & DEV_CONFIG) {
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { ((scsi_info_t *)link->priv)->stop = 1;
if (*linkp == link) {
break;
}
}
if (*linkp == NULL) {
return;
}
if (link->state & DEV_CONFIG)
nsp_cs_release(link); nsp_cs_release(link);
/* Break the link with Card Services */
if (link->handle) {
pcmcia_deregister_client(link->handle);
} }
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(link->priv); kfree(link->priv);
link->priv = NULL; link->priv = NULL;
} /* nsp_cs_detach */ } /* nsp_cs_detach */
@ -2021,99 +1991,58 @@ static void nsp_cs_release(dev_link_t *link)
#endif #endif
} /* nsp_cs_release */ } /* nsp_cs_release */
/*====================================================================== static int nsp_cs_suspend(struct pcmcia_device *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.
When a CARD_REMOVAL event is received, we immediately set a 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 nsp_cs_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(dev);
scsi_info_t *info = link->priv; scsi_info_t *info = link->priv;
nsp_hw_data *data; nsp_hw_data *data;
nsp_dbg(NSP_DEBUG_INIT, "in, event=0x%08x", event); link->state |= DEV_SUSPEND;
switch (event) { nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
case CS_EVENT_CARD_REMOVAL:
nsp_dbg(NSP_DEBUG_INIT, "event: remove");
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
((scsi_info_t *)link->priv)->stop = 1;
nsp_cs_release(link);
}
break;
case CS_EVENT_CARD_INSERTION: if (info->host != NULL) {
nsp_dbg(NSP_DEBUG_INIT, "event: insert"); nsp_msg(KERN_INFO, "clear SDTR status");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,68))
info->bus = args->bus;
#endif
nsp_cs_config(link);
break;
case CS_EVENT_PM_SUSPEND: data = (nsp_hw_data *)info->host->hostdata;
nsp_dbg(NSP_DEBUG_INIT, "event: suspend");
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
/* Mark the device as stopped, to block IO until later */
nsp_dbg(NSP_DEBUG_INIT, "event: reset physical");
if (info->host != NULL) { nsphw_init_sync(data);
nsp_msg(KERN_INFO, "clear SDTR status");
data = (nsp_hw_data *)info->host->hostdata;
nsphw_init_sync(data);
}
info->stop = 1;
if (link->state & DEV_CONFIG) {
pcmcia_release_configuration(link->handle);
}
break;
case CS_EVENT_PM_RESUME:
nsp_dbg(NSP_DEBUG_INIT, "event: resume");
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
nsp_dbg(NSP_DEBUG_INIT, "event: reset");
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
}
info->stop = 0;
if (info->host != NULL) {
nsp_msg(KERN_INFO, "reset host and bus");
data = (nsp_hw_data *)info->host->hostdata;
nsphw_init (data);
nsp_bus_reset(data);
}
break;
default:
nsp_dbg(NSP_DEBUG_INIT, "event: unknown");
break;
} }
nsp_dbg(NSP_DEBUG_INIT, "end");
info->stop = 1;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0; return 0;
} /* nsp_cs_event */ }
static int nsp_cs_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
scsi_info_t *info = link->priv;
nsp_hw_data *data;
nsp_dbg(NSP_DEBUG_INIT, "event: resume");
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_request_configuration(link->handle, &link->conf);
info->stop = 0;
if (info->host != NULL) {
nsp_msg(KERN_INFO, "reset host and bus");
data = (nsp_hw_data *)info->host->hostdata;
nsphw_init (data);
nsp_bus_reset(data);
}
return 0;
}
/*======================================================================* /*======================================================================*
* module entry point * module entry point
@ -2136,10 +2065,11 @@ static struct pcmcia_driver nsp_driver = {
.drv = { .drv = {
.name = "nsp_cs", .name = "nsp_cs",
}, },
.attach = nsp_cs_attach, .probe = nsp_cs_attach,
.event = nsp_cs_event, .remove = nsp_cs_detach,
.detach = nsp_cs_detach,
.id_table = nsp_cs_ids, .id_table = nsp_cs_ids,
.suspend = nsp_cs_suspend,
.resume = nsp_cs_resume,
}; };
#endif #endif
@ -2171,7 +2101,6 @@ static void __exit nsp_cs_exit(void)
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68))
pcmcia_unregister_driver(&nsp_driver); pcmcia_unregister_driver(&nsp_driver);
BUG_ON(dev_list != NULL);
#else #else
unregister_pcmcia_driver(&dev_info); unregister_pcmcia_driver(&dev_info);
/* XXX: this really needs to move into generic code.. */ /* XXX: this really needs to move into generic code.. */

View File

@ -296,11 +296,9 @@ typedef struct _nsp_hw_data {
*/ */
/* Card service functions */ /* Card service functions */
static dev_link_t *nsp_cs_attach (void); static void nsp_cs_detach (struct pcmcia_device *p_dev);
static void nsp_cs_detach (dev_link_t *link);
static void nsp_cs_release(dev_link_t *link); static void nsp_cs_release(dev_link_t *link);
static void nsp_cs_config (dev_link_t *link); static void nsp_cs_config (dev_link_t *link);
static int nsp_cs_event (event_t event, int priority, event_callback_args_t *args);
/* Linux SCSI subsystem specific functions */ /* Linux SCSI subsystem specific functions */
static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht); static struct Scsi_Host *nsp_detect (struct scsi_host_template *sht);

View File

@ -98,15 +98,8 @@ typedef struct scsi_info_t {
} scsi_info_t; } scsi_info_t;
static void qlogic_release(dev_link_t *link); static void qlogic_release(dev_link_t *link);
static int qlogic_event(event_t event, int priority, event_callback_args_t * args); static void qlogic_detach(struct pcmcia_device *p_dev);
static void qlogic_config(dev_link_t * link);
static dev_link_t *qlogic_attach(void);
static void qlogic_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
static dev_info_t dev_info = "qlogic_cs";
static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host, static struct Scsi_Host *qlogic_detect(struct scsi_host_template *host,
dev_link_t *link, int qbase, int qlirq) dev_link_t *link, int qbase, int qlirq)
@ -163,19 +156,17 @@ free_scsi_host:
err: err:
return NULL; return NULL;
} }
static dev_link_t *qlogic_attach(void) static int qlogic_attach(struct pcmcia_device *p_dev)
{ {
scsi_info_t *info; scsi_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
DEBUG(0, "qlogic_attach()\n"); DEBUG(0, "qlogic_attach()\n");
/* Create new SCSI device */ /* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return -ENOMEM;
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
@ -189,45 +180,26 @@ static dev_link_t *qlogic_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;
/* 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);
qlogic_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
qlogic_config(link);
return 0;
} /* qlogic_attach */ } /* qlogic_attach */
/*====================================================================*/ /*====================================================================*/
static void qlogic_detach(dev_link_t * link) static void qlogic_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "qlogic_detach(0x%p)\n", link); DEBUG(0, "qlogic_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)
qlogic_release(link); qlogic_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits */
*linkp = link->next;
kfree(link->priv); kfree(link->priv);
} /* qlogic_detach */ } /* qlogic_detach */
@ -349,48 +321,39 @@ static void qlogic_release(dev_link_t *link)
/*====================================================================*/ /*====================================================================*/
static int qlogic_event(event_t event, int priority, event_callback_args_t * args) static int qlogic_suspend(struct pcmcia_device *dev)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
DEBUG(1, "qlogic_event(0x%06x)\n", event); link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
qlogic_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
qlogic_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) {
scsi_info_t *info = link->priv;
pcmcia_request_configuration(link->handle, &link->conf);
if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {
outb(0x80, link->io.BasePort1 + 0xd);
outb(0x24, link->io.BasePort1 + 0x9);
outb(0x04, link->io.BasePort1 + 0xd);
}
/* Ugggglllyyyy!!! */
qlogicfas408_bus_reset(NULL);
}
break;
}
return 0; return 0;
} /* qlogic_event */ }
static int qlogic_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
scsi_info_t *info = link->priv;
pcmcia_request_configuration(link->handle, &link->conf);
if ((info->manf_id == MANFID_MACNICA) ||
(info->manf_id == MANFID_PIONEER) ||
(info->manf_id == 0x0098)) {
outb(0x80, link->io.BasePort1 + 0xd);
outb(0x24, link->io.BasePort1 + 0x9);
outb(0x04, link->io.BasePort1 + 0xd);
}
/* Ugggglllyyyy!!! */
qlogicfas408_bus_reset(NULL);
}
return 0;
}
static struct pcmcia_device_id qlogic_ids[] = { static struct pcmcia_device_id qlogic_ids[] = {
PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6), PCMCIA_DEVICE_PROD_ID12("EIger Labs", "PCMCIA-to-SCSI Adapter", 0x88395fa7, 0x33b7a5e6),
@ -419,10 +382,11 @@ static struct pcmcia_driver qlogic_cs_driver = {
.drv = { .drv = {
.name = "qlogic_cs", .name = "qlogic_cs",
}, },
.attach = qlogic_attach, .probe = qlogic_attach,
.event = qlogic_event, .remove = qlogic_detach,
.detach = qlogic_detach,
.id_table = qlogic_ids, .id_table = qlogic_ids,
.suspend = qlogic_suspend,
.resume = qlogic_resume,
}; };
static int __init init_qlogic_cs(void) static int __init init_qlogic_cs(void)
@ -433,7 +397,6 @@ static int __init init_qlogic_cs(void)
static void __exit exit_qlogic_cs(void) static void __exit exit_qlogic_cs(void)
{ {
pcmcia_unregister_driver(&qlogic_cs_driver); pcmcia_unregister_driver(&qlogic_cs_driver);
BUG_ON(dev_list != NULL);
} }
MODULE_AUTHOR("Tom Zerucha, Michael Griffith"); MODULE_AUTHOR("Tom Zerucha, Michael Griffith");

View File

@ -228,15 +228,6 @@ enum Phase {
/* ================================================================== */ /* ================================================================== */
/*
* Global (within this module) variables other than
* sym53c500_driver_template (the scsi_host_template).
*/
static dev_link_t *dev_list;
static dev_info_t dev_info = "sym53c500_cs";
/* ================================================================== */
static void static void
chip_init(int io_port) chip_init(int io_port)
{ {
@ -872,96 +863,70 @@ cs_failed:
return; return;
} /* SYM53C500_config */ } /* SYM53C500_config */
static int static int sym53c500_suspend(struct pcmcia_device *dev)
SYM53C500_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(dev);
link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0;
}
static int sym53c500_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
struct scsi_info_t *info = link->priv; struct scsi_info_t *info = link->priv;
DEBUG(1, "SYM53C500_event(0x%06x)\n", event); link->state &= ~DEV_SUSPEND;
if (link->state & DEV_CONFIG) {
pcmcia_request_configuration(link->handle, &link->conf);
switch (event) { /* See earlier comment about manufacturer IDs. */
case CS_EVENT_CARD_REMOVAL: if ((info->manf_id == MANFID_MACNICA) ||
link->state &= ~DEV_PRESENT; (info->manf_id == MANFID_PIONEER) ||
if (link->state & DEV_CONFIG) (info->manf_id == 0x0098)) {
SYM53C500_release(link); outb(0x80, link->io.BasePort1 + 0xd);
break; outb(0x24, link->io.BasePort1 + 0x9);
case CS_EVENT_CARD_INSERTION: outb(0x04, link->io.BasePort1 + 0xd);
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
SYM53C500_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);
/* See earlier comment about manufacturer IDs. */
if ((info->manf_id == MANFID_MACNICA) ||
(info->manf_id == MANFID_PIONEER) ||
(info->manf_id == 0x0098)) {
outb(0x80, link->io.BasePort1 + 0xd);
outb(0x24, link->io.BasePort1 + 0x9);
outb(0x04, link->io.BasePort1 + 0xd);
}
/*
* If things don't work after a "resume",
* this is a good place to start looking.
*/
SYM53C500_int_host_reset(link->io.BasePort1);
} }
break; /*
* If things don't work after a "resume",
* this is a good place to start looking.
*/
SYM53C500_int_host_reset(link->io.BasePort1);
} }
return 0; return 0;
} /* SYM53C500_event */ }
static void static void
SYM53C500_detach(dev_link_t *link) SYM53C500_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DEBUG(0, "SYM53C500_detach(0x%p)\n", link); DEBUG(0, "SYM53C500_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)
SYM53C500_release(link); SYM53C500_release(link);
if (link->handle)
pcmcia_deregister_client(link->handle);
/* Unlink device structure, free bits. */
*linkp = link->next;
kfree(link->priv); kfree(link->priv);
link->priv = NULL; link->priv = NULL;
} /* SYM53C500_detach */ } /* SYM53C500_detach */
static dev_link_t * static int
SYM53C500_attach(void) SYM53C500_attach(struct pcmcia_device *p_dev)
{ {
struct scsi_info_t *info; struct scsi_info_t *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
DEBUG(0, "SYM53C500_attach()\n"); DEBUG(0, "SYM53C500_attach()\n");
/* Create new SCSI device */ /* Create new SCSI device */
info = kmalloc(sizeof(*info), GFP_KERNEL); info = kmalloc(sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return -ENOMEM;
memset(info, 0, sizeof(*info)); memset(info, 0, sizeof(*info));
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
@ -975,20 +940,13 @@ SYM53C500_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;
/* 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);
SYM53C500_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
SYM53C500_config(link);
return 0;
} /* SYM53C500_attach */ } /* SYM53C500_attach */
MODULE_AUTHOR("Bob Tracy <rct@frus.com>"); MODULE_AUTHOR("Bob Tracy <rct@frus.com>");
@ -1008,10 +966,11 @@ static struct pcmcia_driver sym53c500_cs_driver = {
.drv = { .drv = {
.name = "sym53c500_cs", .name = "sym53c500_cs",
}, },
.attach = SYM53C500_attach, .probe = SYM53C500_attach,
.event = SYM53C500_event, .remove = SYM53C500_detach,
.detach = SYM53C500_detach,
.id_table = sym53c500_ids, .id_table = sym53c500_ids,
.suspend = sym53c500_suspend,
.resume = sym53c500_resume,
}; };
static int __init static int __init

View File

@ -114,15 +114,7 @@ struct serial_cfg_mem {
static void serial_config(dev_link_t * link); static void serial_config(dev_link_t * link);
static int serial_event(event_t event, int priority,
event_callback_args_t * args);
static dev_info_t dev_info = "serial_cs";
static dev_link_t *serial_attach(void);
static void serial_detach(dev_link_t *);
static dev_link_t *dev_list = NULL;
/*====================================================================== /*======================================================================
@ -159,8 +151,9 @@ static void serial_remove(dev_link_t *link)
} }
} }
static void serial_suspend(dev_link_t *link) static int serial_suspend(struct pcmcia_device *dev)
{ {
dev_link_t *link = dev_to_instance(dev);
link->state |= DEV_SUSPEND; link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG) { if (link->state & DEV_CONFIG) {
@ -173,10 +166,13 @@ static void serial_suspend(dev_link_t *link)
if (!info->slave) if (!info->slave)
pcmcia_release_configuration(link->handle); pcmcia_release_configuration(link->handle);
} }
return 0;
} }
static void serial_resume(dev_link_t *link) static int serial_resume(struct pcmcia_device *dev)
{ {
dev_link_t *link = dev_to_instance(dev);
link->state &= ~DEV_SUSPEND; link->state &= ~DEV_SUSPEND;
if (DEV_OK(link)) { if (DEV_OK(link)) {
@ -189,6 +185,8 @@ static void serial_resume(dev_link_t *link)
for (i = 0; i < info->ndev; i++) for (i = 0; i < info->ndev; i++)
serial8250_resume_port(info->line[i]); serial8250_resume_port(info->line[i]);
} }
return 0;
} }
/*====================================================================== /*======================================================================
@ -199,19 +197,17 @@ static void serial_resume(dev_link_t *link)
======================================================================*/ ======================================================================*/
static dev_link_t *serial_attach(void) static int serial_probe(struct pcmcia_device *p_dev)
{ {
struct serial_info *info; struct serial_info *info;
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
DEBUG(0, "serial_attach()\n"); DEBUG(0, "serial_attach()\n");
/* Create new serial device */ /* Create new serial device */
info = kmalloc(sizeof (*info), GFP_KERNEL); info = kmalloc(sizeof (*info), GFP_KERNEL);
if (!info) if (!info)
return NULL; return -ENOMEM;
memset(info, 0, sizeof (*info)); memset(info, 0, sizeof (*info));
link = &info->link; link = &info->link;
link->priv = info; link->priv = info;
@ -227,20 +223,12 @@ static dev_link_t *serial_attach(void)
} }
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; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.dev_info = &dev_info; serial_config(link);
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);
serial_detach(link);
return NULL;
}
return link; return 0;
} }
/*====================================================================== /*======================================================================
@ -252,21 +240,13 @@ static dev_link_t *serial_attach(void)
======================================================================*/ ======================================================================*/
static void serial_detach(dev_link_t * link) static void serial_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct serial_info *info = link->priv; struct serial_info *info = link->priv;
dev_link_t **linkp;
int ret;
DEBUG(0, "serial_detach(0x%p)\n", link); DEBUG(0, "serial_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp == NULL)
return;
/* /*
* Ensure any outstanding scheduled tasks are completed. * Ensure any outstanding scheduled tasks are completed.
*/ */
@ -277,14 +257,7 @@ static void serial_detach(dev_link_t * link)
*/ */
serial_remove(link); serial_remove(link);
if (link->handle) { /* free bits */
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);
} }
@ -718,54 +691,6 @@ void serial_config(dev_link_t * link)
kfree(cfg_mem); kfree(cfg_mem);
} }
/*======================================================================
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 serial drivers from
talking to the ports.
======================================================================*/
static int
serial_event(event_t event, int priority, event_callback_args_t * args)
{
dev_link_t *link = args->client_data;
struct serial_info *info = link->priv;
DEBUG(1, "serial_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
serial_remove(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
serial_config(link);
break;
case CS_EVENT_PM_SUSPEND:
serial_suspend(link);
break;
case CS_EVENT_RESET_PHYSICAL:
if ((link->state & DEV_CONFIG) && !info->slave)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
serial_resume(link);
break;
case CS_EVENT_CARD_RESET:
if (DEV_OK(link) && !info->slave)
pcmcia_request_configuration(link->handle, &link->conf);
break;
}
return 0;
}
static struct pcmcia_device_id serial_ids[] = { static struct pcmcia_device_id serial_ids[] = {
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021), PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0057, 0x0021),
PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a), PCMCIA_PFC_DEVICE_MANF_CARD(1, 0x0089, 0x110a),
@ -877,10 +802,11 @@ static struct pcmcia_driver serial_cs_driver = {
.drv = { .drv = {
.name = "serial_cs", .name = "serial_cs",
}, },
.attach = serial_attach, .probe = serial_probe,
.event = serial_event, .remove = serial_detach,
.detach = serial_detach,
.id_table = serial_ids, .id_table = serial_ids,
.suspend = serial_suspend,
.resume = serial_resume,
}; };
static int __init init_serial_cs(void) static int __init init_serial_cs(void)
@ -891,7 +817,6 @@ static int __init init_serial_cs(void)
static void __exit exit_serial_cs(void) static void __exit exit_serial_cs(void)
{ {
pcmcia_unregister_driver(&serial_cs_driver); pcmcia_unregister_driver(&serial_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_serial_cs); module_init(init_serial_cs);

View File

@ -34,24 +34,19 @@ typedef struct ixj_info_t {
struct ixj *port; struct ixj *port;
} ixj_info_t; } ixj_info_t;
static dev_link_t *ixj_attach(void); static void ixj_detach(struct pcmcia_device *p_dev);
static void ixj_detach(dev_link_t *);
static void ixj_config(dev_link_t * link); static void ixj_config(dev_link_t * link);
static void ixj_cs_release(dev_link_t * link); static void ixj_cs_release(dev_link_t * link);
static int ixj_event(event_t event, int priority, event_callback_args_t * args);
static dev_info_t dev_info = "ixj_cs";
static dev_link_t *dev_list = NULL;
static dev_link_t *ixj_attach(void) static int ixj_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg;
dev_link_t *link; dev_link_t *link;
int ret;
DEBUG(0, "ixj_attach()\n"); DEBUG(0, "ixj_attach()\n");
/* Create new ixj device */ /* Create new ixj 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;
memset(link, 0, sizeof(struct dev_link_t)); memset(link, 0, sizeof(struct dev_link_t));
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
@ -61,44 +56,29 @@ static dev_link_t *ixj_attach(void)
link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL); link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
if (!link->priv) { if (!link->priv) {
kfree(link); kfree(link);
return NULL; return -ENOMEM;
} }
memset(link->priv, 0, sizeof(struct ixj_info_t)); memset(link->priv, 0, sizeof(struct ixj_info_t));
/* Register with Card Services */
link->next = dev_list; link->handle = p_dev;
dev_list = link; p_dev->instance = link;
client_reg.dev_info = &dev_info;
client_reg.Version = 0x0210; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
client_reg.event_callback_args.client_data = link; ixj_config(link);
ret = pcmcia_register_client(&link->handle, &client_reg);
if (ret != CS_SUCCESS) { return 0;
cs_error(link->handle, RegisterClient, ret);
ixj_detach(link);
return NULL;
}
return link;
} }
static void ixj_detach(dev_link_t * link) static void ixj_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
int ret;
DEBUG(0, "ixj_detach(0x%p)\n", link); DEBUG(0, "ixj_detach(0x%p)\n", link);
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp == NULL)
return;
link->state &= ~DEV_RELEASE_PENDING; link->state &= ~DEV_RELEASE_PENDING;
if (link->state & DEV_CONFIG) if (link->state & DEV_CONFIG)
ixj_cs_release(link); ixj_cs_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(link->priv); kfree(link->priv);
kfree(link); kfree(link);
} }
@ -255,37 +235,25 @@ static void ixj_cs_release(dev_link_t *link)
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
static int ixj_event(event_t event, int priority, event_callback_args_t * args) static int ixj_suspend(struct pcmcia_device *dev)
{ {
dev_link_t *link = args->client_data; dev_link_t *link = dev_to_instance(dev);
DEBUG(1, "ixj_event(0x%06x)\n", event);
switch (event) { link->state |= DEV_SUSPEND;
case CS_EVENT_CARD_REMOVAL: if (link->state & DEV_CONFIG)
link->state &= ~DEV_PRESENT; pcmcia_release_configuration(link->handle);
if (link->state & DEV_CONFIG) {
link->state |= DEV_RELEASE_PENDING; return 0;
ixj_cs_release(link); }
}
break; static int ixj_resume(struct pcmcia_device *dev)
case CS_EVENT_CARD_INSERTION: {
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; dev_link_t *link = dev_to_instance(dev);
ixj_config(link);
break; link->state &= ~DEV_SUSPEND;
case CS_EVENT_PM_SUSPEND: if (DEV_OK(link))
link->state |= DEV_SUSPEND; pcmcia_request_configuration(link->handle, &link->conf);
/* 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;
} }
@ -300,10 +268,11 @@ static struct pcmcia_driver ixj_driver = {
.drv = { .drv = {
.name = "ixj_cs", .name = "ixj_cs",
}, },
.attach = ixj_attach, .probe = ixj_attach,
.event = ixj_event, .remove = ixj_detach,
.detach = ixj_detach,
.id_table = ixj_ids, .id_table = ixj_ids,
.suspend = ixj_suspend,
.resume = ixj_resume,
}; };
static int __init ixj_pcmcia_init(void) static int __init ixj_pcmcia_init(void)
@ -314,7 +283,6 @@ static int __init ixj_pcmcia_init(void)
static void ixj_pcmcia_exit(void) static void ixj_pcmcia_exit(void)
{ {
pcmcia_unregister_driver(&ixj_driver); pcmcia_unregister_driver(&ixj_driver);
BUG_ON(dev_list != NULL);
} }
module_init(ixj_pcmcia_init); module_init(ixj_pcmcia_init);

View File

@ -66,13 +66,13 @@ module_param(pc_debug, int, 0644);
static const char driver_name[DEV_NAME_LEN] = "sl811_cs"; static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
static dev_link_t *dev_list = NULL;
typedef struct local_info_t { typedef struct local_info_t {
dev_link_t link; dev_link_t link;
dev_node_t node; dev_node_t node;
} local_info_t; } local_info_t;
static void sl811_cs_release(dev_link_t * link);
/*====================================================================*/ /*====================================================================*/
static void release_platform_dev(struct device * dev) static void release_platform_dev(struct device * dev)
@ -138,26 +138,16 @@ static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
/*====================================================================*/ /*====================================================================*/
static void sl811_cs_detach(dev_link_t *link) static void sl811_cs_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t **linkp; dev_link_t *link = dev_to_instance(p_dev);
DBG(0, "sl811_cs_detach(0x%p)\n", link); DBG(0, "sl811_cs_detach(0x%p)\n", link);
/* Locate device structure */ link->state &= ~DEV_PRESENT;
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) { if (link->state & DEV_CONFIG)
if (*linkp == link) sl811_cs_release(link);
break;
}
if (*linkp == NULL)
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);
} }
@ -167,13 +157,6 @@ static void sl811_cs_release(dev_link_t * link)
DBG(0, "sl811_cs_release(0x%p)\n", link); DBG(0, "sl811_cs_release(0x%p)\n", link);
if (link->open) {
DBG(1, "sl811_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
/* Unlink the device chain */ /* Unlink the device chain */
link->dev = NULL; link->dev = NULL;
@ -184,9 +167,6 @@ static void sl811_cs_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)
sl811_cs_detach(link);
} }
static void sl811_cs_config(dev_link_t *link) static void sl811_cs_config(dev_link_t *link)
@ -323,55 +303,36 @@ cs_failed:
} }
} }
static int static int sl811_suspend(struct pcmcia_device *dev)
sl811_cs_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(dev);
DBG(1, "sl811_cs_event(0x%06x)\n", event); link->state |= DEV_SUSPEND;
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG)
sl811_cs_release(link);
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
sl811_cs_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);
DBG(0, "reset sl811-hcd here?\n");
break;
}
return 0; return 0;
} }
static dev_link_t *sl811_cs_attach(void) static int sl811_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;
}
static int sl811_cs_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;
local = kmalloc(sizeof(local_info_t), GFP_KERNEL); local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local) if (!local)
return NULL; return -ENOMEM;
memset(local, 0, sizeof(local_info_t)); memset(local, 0, sizeof(local_info_t));
link = &local->link; link = &local->link;
link->priv = local; link->priv = local;
@ -385,21 +346,13 @@ static dev_link_t *sl811_cs_attach(void)
link->conf.Vcc = 33; link->conf.Vcc = 33;
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_t *) &driver_name;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
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);
sl811_cs_detach(link);
return NULL;
}
return link; link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
sl811_cs_config(link);
return 0;
} }
static struct pcmcia_device_id sl811_ids[] = { static struct pcmcia_device_id sl811_ids[] = {
@ -413,10 +366,11 @@ static struct pcmcia_driver sl811_cs_driver = {
.drv = { .drv = {
.name = (char *)driver_name, .name = (char *)driver_name,
}, },
.attach = sl811_cs_attach, .probe = sl811_cs_attach,
.event = sl811_cs_event, .remove = sl811_cs_detach,
.detach = sl811_cs_detach,
.id_table = sl811_ids, .id_table = sl811_ids,
.suspend = sl811_suspend,
.resume = sl811_resume,
}; };
/*====================================================================*/ /*====================================================================*/

View File

@ -382,7 +382,6 @@ enum service {
struct pcmcia_socket; struct pcmcia_socket;
int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg); int pcmcia_access_configuration_register(struct pcmcia_device *p_dev, conf_reg_t *reg);
int pcmcia_deregister_client(struct pcmcia_device *p_dev);
int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config); int pcmcia_get_configuration_info(struct pcmcia_device *p_dev, config_info_t *config);
int pcmcia_get_first_window(window_handle_t *win, win_req_t *req); int pcmcia_get_first_window(window_handle_t *win, win_req_t *req);
int pcmcia_get_next_window(window_handle_t *win, win_req_t *req); int pcmcia_get_next_window(window_handle_t *win, win_req_t *req);
@ -390,7 +389,6 @@ int pcmcia_get_status(struct pcmcia_device *p_dev, cs_status_t *status);
int pcmcia_get_mem_page(window_handle_t win, memreq_t *req); int pcmcia_get_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_map_mem_page(window_handle_t win, memreq_t *req); int pcmcia_map_mem_page(window_handle_t win, memreq_t *req);
int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod); int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);
int pcmcia_register_client(client_handle_t *handle, client_reg_t *req);
int pcmcia_release_configuration(struct pcmcia_device *p_dev); int pcmcia_release_configuration(struct pcmcia_device *p_dev);
int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req); int pcmcia_release_io(struct pcmcia_device *p_dev, io_req_t *req);
int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req); int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req);

View File

@ -133,10 +133,12 @@ typedef struct dev_link_t {
struct pcmcia_socket; struct pcmcia_socket;
struct pcmcia_driver { struct pcmcia_driver {
dev_link_t *(*attach)(void); int (*probe) (struct pcmcia_device *dev);
int (*event) (event_t event, int priority, void (*remove) (struct pcmcia_device *dev);
event_callback_args_t *);
void (*detach)(dev_link_t *); int (*suspend) (struct pcmcia_device *dev);
int (*resume) (struct pcmcia_device *dev);
struct module *owner; struct module *owner;
struct pcmcia_device_id *id_table; struct pcmcia_device_id *id_table;
struct device_driver drv; struct device_driver drv;
@ -164,7 +166,6 @@ struct pcmcia_device {
/* deprecated, a cleaned up version will be moved into this /* deprecated, a cleaned up version will be moved into this
struct soon */ struct soon */
dev_link_t *instance; dev_link_t *instance;
event_callback_args_t event_callback_args;
u_int state; u_int state;
/* information about this device */ /* information about this device */
@ -193,6 +194,8 @@ struct pcmcia_device {
#define handle_to_pdev(handle) (handle) #define handle_to_pdev(handle) (handle)
#define handle_to_dev(handle) (handle->dev) #define handle_to_dev(handle) (handle->dev)
#define dev_to_instance(dev) (dev->instance)
/* error reporting */ /* error reporting */
void cs_error(client_handle_t handle, int func, int ret); void cs_error(client_handle_t handle, int func, int ret);

View File

@ -118,16 +118,14 @@ struct pcmcia_socket;
struct pccard_operations { struct pccard_operations {
int (*init)(struct pcmcia_socket *sock); int (*init)(struct pcmcia_socket *sock);
int (*suspend)(struct pcmcia_socket *sock); int (*suspend)(struct pcmcia_socket *sock);
int (*register_callback)(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info);
int (*get_status)(struct pcmcia_socket *sock, u_int *value); int (*get_status)(struct pcmcia_socket *sock, u_int *value);
int (*get_socket)(struct pcmcia_socket *sock, socket_state_t *state);
int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state); int (*set_socket)(struct pcmcia_socket *sock, socket_state_t *state);
int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io); int (*set_io_map)(struct pcmcia_socket *sock, struct pccard_io_map *io);
int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem); int (*set_mem_map)(struct pcmcia_socket *sock, struct pccard_mem_map *mem);
}; };
struct pccard_resource_ops { struct pccard_resource_ops {
void (*validate_mem) (struct pcmcia_socket *s); int (*validate_mem) (struct pcmcia_socket *s);
int (*adjust_io_region) (struct resource *res, int (*adjust_io_region) (struct resource *res,
unsigned long r_start, unsigned long r_start,
unsigned long r_end, unsigned long r_end,

View File

@ -52,16 +52,13 @@ MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
/* /*
*/ */
static dev_info_t dev_info = "snd-pdaudiocf";
static struct snd_card *card_list[SNDRV_CARDS]; static struct snd_card *card_list[SNDRV_CARDS];
static dev_link_t *dev_list;
/* /*
* prototypes * prototypes
*/ */
static void pdacf_config(dev_link_t *link); static void pdacf_config(dev_link_t *link);
static int pdacf_event(event_t event, int priority, event_callback_args_t *args); static void snd_pdacf_detach(struct pcmcia_device *p_dev);
static void snd_pdacf_detach(dev_link_t *link);
static void pdacf_release(dev_link_t *link) static void pdacf_release(dev_link_t *link)
{ {
@ -83,10 +80,6 @@ static int snd_pdacf_free(struct snd_pdacf *pdacf)
pdacf_release(link); pdacf_release(link);
/* Break the link with Card Services */
if (link->handle)
pcmcia_deregister_client(link->handle);
card_list[pdacf->index] = NULL; card_list[pdacf->index] = NULL;
pdacf->card = NULL; pdacf->card = NULL;
@ -103,11 +96,10 @@ static int snd_pdacf_dev_free(struct snd_device *device)
/* /*
* snd_pdacf_attach - attach callback for cs * snd_pdacf_attach - attach callback for cs
*/ */
static dev_link_t *snd_pdacf_attach(void) static int snd_pdacf_attach(struct pcmcia_device *p_dev)
{ {
client_reg_t client_reg; /* Register with cardmgr */ int i;
dev_link_t *link; /* Info for cardmgr */ dev_link_t *link; /* Info for cardmgr */
int i, ret;
struct snd_pdacf *pdacf; struct snd_pdacf *pdacf;
struct snd_card *card; struct snd_card *card;
static struct snd_device_ops ops = { static struct snd_device_ops ops = {
@ -122,26 +114,26 @@ static dev_link_t *snd_pdacf_attach(void)
} }
if (i >= SNDRV_CARDS) { if (i >= SNDRV_CARDS) {
snd_printk(KERN_ERR "pdacf: too many cards found\n"); snd_printk(KERN_ERR "pdacf: too many cards found\n");
return NULL; return -EINVAL;
} }
if (! enable[i]) if (! enable[i])
return NULL; /* disabled explicitly */ return -ENODEV; /* disabled explicitly */
/* ok, create a card instance */ /* ok, create a card instance */
card = snd_card_new(index[i], id[i], THIS_MODULE, 0); card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
if (card == NULL) { if (card == NULL) {
snd_printk(KERN_ERR "pdacf: cannot create a card instance\n"); snd_printk(KERN_ERR "pdacf: cannot create a card instance\n");
return NULL; return -ENOMEM;
} }
pdacf = snd_pdacf_create(card); pdacf = snd_pdacf_create(card);
if (! pdacf) if (! pdacf)
return NULL; return -EIO;
if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) { if (snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops) < 0) {
kfree(pdacf); kfree(pdacf);
snd_card_free(card); snd_card_free(card);
return NULL; return -ENODEV;
} }
pdacf->index = i; pdacf->index = i;
@ -165,22 +157,12 @@ static dev_link_t *snd_pdacf_attach(void)
link->conf.Present = PRESENT_OPTION; link->conf.Present = PRESENT_OPTION;
/* Chain drivers */ /* Chain drivers */
link->next = dev_list; link->next = NULL;
dev_list = link;
/* Register with Card Services */ link->handle = p_dev;
client_reg.dev_info = &dev_info; pdacf_config(link);
client_reg.Version = 0x0210;
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);
snd_pdacf_detach(link);
return NULL;
}
return link;
} }
@ -227,21 +209,13 @@ static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq
/* /*
* snd_pdacf_detach - detach callback for cs * snd_pdacf_detach - detach callback for cs
*/ */
static void snd_pdacf_detach(dev_link_t *link) static void snd_pdacf_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct snd_pdacf *chip = link->priv; struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "pdacf_detach called\n"); snd_printdd(KERN_DEBUG "pdacf_detach called\n");
/* Remove the interface data from the linked list */
{
dev_link_t **linkp;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link)
break;
if (*linkp)
*linkp = link->next;
}
if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED) if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED)
snd_pdacf_powerdown(chip); snd_pdacf_powerdown(chip);
chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */ chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */
@ -310,62 +284,51 @@ failed:
pcmcia_release_irq(link->handle, &link->irq); pcmcia_release_irq(link->handle, &link->irq);
} }
/* #ifdef CONFIG_PM
* event callback
*/ static int pdacf_suspend(struct pcmcia_device *dev)
static int pdacf_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(dev);
struct snd_pdacf *chip = link->priv; struct snd_pdacf *chip = link->priv;
switch (event) { snd_printdd(KERN_DEBUG "SUSPEND\n");
case CS_EVENT_CARD_REMOVAL: link->state |= DEV_SUSPEND;
snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); if (chip) {
link->state &= ~DEV_PRESENT; snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
if (link->state & DEV_CONFIG) { snd_pdacf_suspend(chip, PMSG_SUSPEND);
chip->chip_status |= PDAUDIOCF_STAT_IS_STALE;
}
break;
case CS_EVENT_CARD_INSERTION:
snd_printdd(KERN_DEBUG "CARD_INSERTION..\n");
link->state |= DEV_PRESENT;
pdacf_config(link);
break;
#ifdef CONFIG_PM
case CS_EVENT_PM_SUSPEND:
snd_printdd(KERN_DEBUG "SUSPEND\n");
link->state |= DEV_SUSPEND;
if (chip) {
snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
snd_pdacf_suspend(chip, PMSG_SUSPEND);
}
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
snd_printdd(KERN_DEBUG "RESUME\n");
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
snd_printdd(KERN_DEBUG "CARD_RESET\n");
if (DEV_OK(link)) {
snd_printdd(KERN_DEBUG "requestconfig...\n");
pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
snd_pdacf_resume(chip);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
break;
#endif
} }
snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0; return 0;
} }
static int pdacf_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
struct snd_pdacf *chip = link->priv;
snd_printdd(KERN_DEBUG "RESUME\n");
link->state &= ~DEV_SUSPEND;
snd_printdd(KERN_DEBUG "CARD_RESET\n");
if (DEV_OK(link)) {
snd_printdd(KERN_DEBUG "requestconfig...\n");
pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
snd_pdacf_resume(chip);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
return 0;
}
#endif
/* /*
* Module entry points * Module entry points
*/ */
@ -380,10 +343,14 @@ static struct pcmcia_driver pdacf_cs_driver = {
.drv = { .drv = {
.name = "snd-pdaudiocf", .name = "snd-pdaudiocf",
}, },
.attach = snd_pdacf_attach, .probe = snd_pdacf_attach,
.event = pdacf_event, .remove = snd_pdacf_detach,
.detach = snd_pdacf_detach,
.id_table = snd_pdacf_ids, .id_table = snd_pdacf_ids,
#ifdef CONFIG_PM
.suspend = pdacf_suspend,
.resume = pdacf_resume,
#endif
}; };
static int __init init_pdacf(void) static int __init init_pdacf(void)
@ -394,7 +361,6 @@ static int __init init_pdacf(void)
static void __exit exit_pdacf(void) static void __exit exit_pdacf(void)
{ {
pcmcia_unregister_driver(&pdacf_cs_driver); pcmcia_unregister_driver(&pdacf_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_pdacf); module_init(init_pdacf);

View File

@ -55,11 +55,6 @@ MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard.");
*/ */
static unsigned int card_alloc; static unsigned int card_alloc;
static dev_link_t *dev_list; /* Linked list of devices */
static dev_info_t dev_info = "snd-vxpocket";
static int vxpocket_event(event_t event, int priority, event_callback_args_t *args);
/* /*
@ -73,11 +68,6 @@ static void vxpocket_release(dev_link_t *link)
pcmcia_release_irq(link->handle, &link->irq); pcmcia_release_irq(link->handle, &link->irq);
link->state &= ~DEV_CONFIG; link->state &= ~DEV_CONFIG;
} }
if (link->handle) {
/* Break the link with Card Services */
pcmcia_deregister_client(link->handle);
link->handle = NULL;
}
} }
/* /*
@ -144,11 +134,9 @@ static struct snd_vx_hardware vxp440_hw = {
*/ */
static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl) static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
{ {
client_reg_t client_reg; /* Register with cardmgr */
dev_link_t *link; /* Info for cardmgr */ dev_link_t *link; /* Info for cardmgr */
struct vx_core *chip; struct vx_core *chip;
struct snd_vxpocket *vxp; struct snd_vxpocket *vxp;
int ret;
static struct snd_device_ops ops = { static struct snd_device_ops ops = {
.dev_free = snd_vxpocket_dev_free, .dev_free = snd_vxpocket_dev_free,
}; };
@ -184,26 +172,6 @@ static struct snd_vxpocket *snd_vxpocket_new(struct snd_card *card, int ibl)
link->conf.ConfigIndex = 1; link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION; link->conf.Present = PRESENT_OPTION;
/* Register with Card Services */
memset(&client_reg, 0, sizeof(client_reg));
client_reg.dev_info = &dev_info;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL
#ifdef CONFIG_PM
| CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET
| CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME
#endif
;
client_reg.event_handler = &vxpocket_event;
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);
return NULL;
}
return vxp; return vxp;
} }
@ -317,67 +285,55 @@ failed:
kfree(parse); kfree(parse);
} }
#ifdef CONFIG_PM
/* static int vxp_suspend(struct pcmcia_device *dev)
* event callback
*/
static int vxpocket_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(dev);
struct vx_core *chip = link->priv; struct vx_core *chip = link->priv;
switch (event) { snd_printdd(KERN_DEBUG "SUSPEND\n");
case CS_EVENT_CARD_REMOVAL: link->state |= DEV_SUSPEND;
snd_printdd(KERN_DEBUG "CARD_REMOVAL..\n"); if (chip) {
link->state &= ~DEV_PRESENT; snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
if (link->state & DEV_CONFIG) snd_vx_suspend(chip, PMSG_SUSPEND);
chip->chip_status |= VX_STAT_IS_STALE;
break;
case CS_EVENT_CARD_INSERTION:
snd_printdd(KERN_DEBUG "CARD_INSERTION..\n");
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
vxpocket_config(link);
break;
#ifdef CONFIG_PM
case CS_EVENT_PM_SUSPEND:
snd_printdd(KERN_DEBUG "SUSPEND\n");
link->state |= DEV_SUSPEND;
if (chip) {
snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
snd_vx_suspend(chip, PMSG_SUSPEND);
}
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
break;
case CS_EVENT_PM_RESUME:
snd_printdd(KERN_DEBUG "RESUME\n");
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
snd_printdd(KERN_DEBUG "CARD_RESET\n");
if (DEV_OK(link)) {
//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
snd_printdd(KERN_DEBUG "requestconfig...\n");
pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
snd_vx_resume(chip);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
break;
#endif
} }
snd_printdd(KERN_DEBUG "RESET_PHYSICAL\n");
if (link->state & DEV_CONFIG)
pcmcia_release_configuration(link->handle);
return 0; return 0;
} }
static int vxp_resume(struct pcmcia_device *dev)
{
dev_link_t *link = dev_to_instance(dev);
struct vx_core *chip = link->priv;
snd_printdd(KERN_DEBUG "RESUME\n");
link->state &= ~DEV_SUSPEND;
snd_printdd(KERN_DEBUG "CARD_RESET\n");
if (DEV_OK(link)) {
//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
snd_printdd(KERN_DEBUG "requestconfig...\n");
pcmcia_request_configuration(link->handle, &link->conf);
if (chip) {
snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
snd_vx_resume(chip);
}
}
snd_printdd(KERN_DEBUG "resume done!\n");
return 0;
}
#endif
/* /*
*/ */
static dev_link_t *vxpocket_attach(void) static int vxpocket_attach(struct pcmcia_device *p_dev)
{ {
struct snd_card *card; struct snd_card *card;
struct snd_vxpocket *vxp; struct snd_vxpocket *vxp;
@ -390,22 +346,22 @@ static dev_link_t *vxpocket_attach(void)
} }
if (i >= SNDRV_CARDS) { if (i >= SNDRV_CARDS) {
snd_printk(KERN_ERR "vxpocket: too many cards found\n"); snd_printk(KERN_ERR "vxpocket: too many cards found\n");
return NULL; return -EINVAL;
} }
if (! enable[i]) if (! enable[i])
return NULL; /* disabled explicitly */ return -ENODEV; /* disabled explicitly */
/* ok, create a card instance */ /* ok, create a card instance */
card = snd_card_new(index[i], id[i], THIS_MODULE, 0); card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
if (card == NULL) { if (card == NULL) {
snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
return NULL; return -ENOMEM;
} }
vxp = snd_vxpocket_new(card, ibl[i]); vxp = snd_vxpocket_new(card, ibl[i]);
if (! vxp) { if (! vxp) {
snd_card_free(card); snd_card_free(card);
return NULL; return -ENODEV;
} }
card->private_data = vxp; card->private_data = vxp;
@ -413,17 +369,21 @@ static dev_link_t *vxpocket_attach(void)
card_alloc |= 1 << i; card_alloc |= 1 << i;
/* Chain drivers */ /* Chain drivers */
vxp->link.next = dev_list; vxp->link.next = NULL;
dev_list = &vxp->link;
return &vxp->link; vxp->link.handle = p_dev;
vxp->link.state |= DEV_PRESENT | DEV_CONFIG_PENDING;
p_dev->instance = &vxp->link;
vxpocket_config(&vxp->link);
return 0;
} }
static void vxpocket_detach(dev_link_t *link) static void vxpocket_detach(struct pcmcia_device *p_dev)
{ {
dev_link_t *link = dev_to_instance(p_dev);
struct snd_vxpocket *vxp; struct snd_vxpocket *vxp;
struct vx_core *chip; struct vx_core *chip;
dev_link_t **linkp;
if (! link) if (! link)
return; return;
@ -432,13 +392,6 @@ static void vxpocket_detach(dev_link_t *link)
chip = (struct vx_core *)vxp; chip = (struct vx_core *)vxp;
card_alloc &= ~(1 << vxp->index); card_alloc &= ~(1 << vxp->index);
/* Remove the interface data from the linked list */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) {
*linkp = link->next;
break;
}
chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */
snd_card_disconnect(chip->card); snd_card_disconnect(chip->card);
vxpocket_release(link); vxpocket_release(link);
@ -460,10 +413,13 @@ static struct pcmcia_driver vxp_cs_driver = {
.drv = { .drv = {
.name = "snd-vxpocket", .name = "snd-vxpocket",
}, },
.attach = vxpocket_attach, .probe = vxpocket_attach,
.detach = vxpocket_detach, .remove = vxpocket_detach,
.event = vxpocket_event,
.id_table = vxp_ids, .id_table = vxp_ids,
#ifdef CONFIG_PM
.suspend = vxp_suspend,
.resume = vxp_resume,
#endif
}; };
static int __init init_vxpocket(void) static int __init init_vxpocket(void)
@ -474,7 +430,6 @@ static int __init init_vxpocket(void)
static void __exit exit_vxpocket(void) static void __exit exit_vxpocket(void)
{ {
pcmcia_unregister_driver(&vxp_cs_driver); pcmcia_unregister_driver(&vxp_cs_driver);
BUG_ON(dev_list != NULL);
} }
module_init(init_vxpocket); module_init(init_vxpocket);