Commit 6cbb2ab5 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://linux-pnp.bkbits.net/linux-pnp

into home.transmeta.com:/home/torvalds/v2.5/linux
parents a104ba57 a36e0e18
...@@ -30,15 +30,6 @@ config PNP_NAMES ...@@ -30,15 +30,6 @@ config PNP_NAMES
If unsure, say Y. If unsure, say Y.
config PNP_CARD
bool "Plug and Play card services"
depends on PNP
help
Select Y if you want the PnP Layer to manage cards. Cards are groups
of PnP devices. Some drivers, especially PnP sound card drivers, use
these cards. If you want to use the protocol ISAPNP you will need to
say Y here.
config PNP_DEBUG config PNP_DEBUG
bool "PnP Debug Messages" bool "PnP Debug Messages"
depends on PNP depends on PNP
...@@ -51,7 +42,7 @@ comment "Protocols" ...@@ -51,7 +42,7 @@ comment "Protocols"
config ISAPNP config ISAPNP
bool "ISA Plug and Play support (EXPERIMENTAL)" bool "ISA Plug and Play support (EXPERIMENTAL)"
depends on PNP && EXPERIMENTAL && PNP_CARD depends on PNP && EXPERIMENTAL
help help
Say Y here if you would like support for ISA Plug and Play devices. Say Y here if you would like support for ISA Plug and Play devices.
Some information is in <file:Documentation/isapnp.txt>. Some information is in <file:Documentation/isapnp.txt>.
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
# Makefile for the Linux Plug-and-Play Support. # Makefile for the Linux Plug-and-Play Support.
# #
pnp-card-$(CONFIG_PNP_CARD) = card.o obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o
obj-y := core.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o $(pnp-card-y)
obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_PNPBIOS) += pnpbios/
obj-$(CONFIG_ISAPNP) += isapnp/ obj-$(CONFIG_ISAPNP) += isapnp/
...@@ -16,15 +16,14 @@ ...@@ -16,15 +16,14 @@
#endif #endif
#include <linux/pnp.h> #include <linux/pnp.h>
#include <linux/init.h>
#include "base.h" #include "base.h"
LIST_HEAD(pnp_cards); LIST_HEAD(pnp_cards);
static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp_card *card)
static const struct pnp_card_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card)
{ {
const struct pnp_card_id *drv_id = drv->id_table; const struct pnp_card_id * drv_id = drv->id_table;
while (*drv_id->id){ while (*drv_id->id){
if (compare_pnp_id(card->id,drv_id->id)) if (compare_pnp_id(card->id,drv_id->id))
return drv_id; return drv_id;
...@@ -33,31 +32,33 @@ static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp ...@@ -33,31 +32,33 @@ static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp
return NULL; return NULL;
} }
static int card_bus_match(struct device *dev, struct device_driver *drv) static void generic_card_remove(struct pnp_dev * dev)
{ {
struct pnp_card * card = to_pnp_card(dev); dev->card_link = NULL;
struct pnpc_driver * pnp_drv = to_pnpc_driver(drv);
if (match_card(pnp_drv, card) == NULL)
return 0;
return 1;
} }
struct bus_type pnpc_bus_type = { static void generic_card_remove_first(struct pnp_dev * dev)
.name = "pnp_card", {
.match = card_bus_match, struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver);
}; if (!dev->card || !drv)
return;
if (drv->remove)
drv->remove(dev->card_link);
drv->link.remove = &generic_card_remove;
kfree(dev->card_link);
generic_card_remove(dev);
}
/** /**
* pnpc_add_id - adds an EISA id to the specified card * pnp_add_card_id - adds an EISA id to the specified card
* @id: pointer to a pnp_id structure * @id: pointer to a pnp_id structure
* @card: pointer to the desired card * @card: pointer to the desired card
* *
*/ */
int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card)
{ {
struct pnp_id *ptr; struct pnp_id * ptr;
if (!id) if (!id)
return -EINVAL; return -EINVAL;
if (!card) if (!card)
...@@ -73,7 +74,7 @@ int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) ...@@ -73,7 +74,7 @@ int pnpc_add_id(struct pnp_id *id, struct pnp_card *card)
return 0; return 0;
} }
static void pnpc_free_ids(struct pnp_card *card) static void pnp_free_card_ids(struct pnp_card * card)
{ {
struct pnp_id * id; struct pnp_id * id;
struct pnp_id *next; struct pnp_id *next;
...@@ -90,47 +91,51 @@ static void pnpc_free_ids(struct pnp_card *card) ...@@ -90,47 +91,51 @@ static void pnpc_free_ids(struct pnp_card *card)
static void pnp_release_card(struct device *dmdev) static void pnp_release_card(struct device *dmdev)
{ {
struct pnp_card * card = to_pnp_card(dmdev); struct pnp_card * card = to_pnp_card(dmdev);
pnpc_free_ids(card); pnp_free_card_ids(card);
kfree(card); kfree(card);
} }
/** /**
* pnpc_add_card - adds a PnP card to the PnP Layer * pnp_add_card - adds a PnP card to the PnP Layer
* @card: pointer to the card to add * @card: pointer to the card to add
*/ */
int pnpc_add_card(struct pnp_card *card) int pnp_add_card(struct pnp_card * card)
{ {
int error = 0; int error;
struct list_head * pos;
if (!card || !card->protocol) if (!card || !card->protocol)
return -EINVAL; return -EINVAL;
sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number); sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number);
INIT_LIST_HEAD(&card->rdevs);
card->dev.parent = &card->protocol->dev; card->dev.parent = &card->protocol->dev;
card->dev.bus = &pnpc_bus_type; card->dev.bus = NULL;
card->dev.release = &pnp_release_card; card->dev.release = &pnp_release_card;
card->status = PNP_READY;
error = device_register(&card->dev); error = device_register(&card->dev);
if (error == 0){ if (error == 0) {
struct list_head *pos;
spin_lock(&pnp_lock); spin_lock(&pnp_lock);
list_add_tail(&card->global_list, &pnp_cards); list_add_tail(&card->global_list, &pnp_cards);
list_add_tail(&card->protocol_list, &card->protocol->cards); list_add_tail(&card->protocol_list, &card->protocol->cards);
spin_unlock(&pnp_lock); spin_unlock(&pnp_lock);
/* we wait until now to add devices in order to ensure the drivers
* will be able to use all of the related devices on the card
* without waiting any unresonable length of time */
list_for_each(pos,&card->devices){ list_for_each(pos,&card->devices){
struct pnp_dev *dev = card_to_pnp_dev(pos); struct pnp_dev *dev = card_to_pnp_dev(pos);
__pnp_add_device(dev); __pnp_add_device(dev);
} }
} } else
pnp_err("sysfs failure, card '%s' will be unavailable", card->dev.bus_id);
return error; return error;
} }
/** /**
* pnpc_remove_card - removes a PnP card from the PnP Layer * pnp_remove_card - removes a PnP card from the PnP Layer
* @card: pointer to the card to remove * @card: pointer to the card to remove
*/ */
void pnpc_remove_card(struct pnp_card *card) void pnp_remove_card(struct pnp_card * card)
{ {
struct list_head *pos, *temp; struct list_head *pos, *temp;
if (!card) if (!card)
...@@ -142,22 +147,24 @@ void pnpc_remove_card(struct pnp_card *card) ...@@ -142,22 +147,24 @@ void pnpc_remove_card(struct pnp_card *card)
spin_unlock(&pnp_lock); spin_unlock(&pnp_lock);
list_for_each_safe(pos,temp,&card->devices){ list_for_each_safe(pos,temp,&card->devices){
struct pnp_dev *dev = card_to_pnp_dev(pos); struct pnp_dev *dev = card_to_pnp_dev(pos);
pnpc_remove_device(dev); pnp_remove_card_device(dev);
} }
} }
/** /**
* pnpc_add_device - adds a device to the specified card * pnp_add_card_device - adds a device to the specified card
* @card: pointer to the card to add to * @card: pointer to the card to add to
* @dev: pointer to the device to add * @dev: pointer to the device to add
*/ */
int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev)
{ {
if (!dev || !dev->protocol || !card) if (!card || !dev || !dev->protocol)
return -EINVAL; return -EINVAL;
dev->dev.parent = &card->dev; dev->dev.parent = &card->dev;
sprintf(dev->dev.bus_id, "%02x:%02x.%02x", dev->protocol->number, card->number,dev->number); dev->card_link = NULL;
snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", dev->protocol->number,
card->number,dev->number);
spin_lock(&pnp_lock); spin_lock(&pnp_lock);
dev->card = card; dev->card = card;
list_add_tail(&dev->card_list, &card->devices); list_add_tail(&dev->card_list, &card->devices);
...@@ -166,12 +173,12 @@ int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) ...@@ -166,12 +173,12 @@ int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev)
} }
/** /**
* pnpc_remove_device- removes a device from the specified card * pnp_remove_card_device- removes a device from the specified card
* @card: pointer to the card to remove from * @card: pointer to the card to remove from
* @dev: pointer to the device to remove * @dev: pointer to the device to remove
*/ */
void pnpc_remove_device(struct pnp_dev *dev) void pnp_remove_card_device(struct pnp_dev * dev)
{ {
spin_lock(&pnp_lock); spin_lock(&pnp_lock);
dev->card = NULL; dev->card = NULL;
...@@ -182,20 +189,21 @@ void pnpc_remove_device(struct pnp_dev *dev) ...@@ -182,20 +189,21 @@ void pnpc_remove_device(struct pnp_dev *dev)
/** /**
* pnp_request_card_device - Searches for a PnP device under the specified card * pnp_request_card_device - Searches for a PnP device under the specified card
* @card: pointer to the card to search under, cannot be NULL * @lcard: pointer to the card link, cannot be NULL
* @id: pointer to a PnP ID structure that explains the rules for finding the device * @id: pointer to a PnP ID structure that explains the rules for finding the device
* @from: Starting place to search from. If NULL it will start from the begining. * @from: Starting place to search from. If NULL it will start from the begining.
*
* Will activate the device
*/ */
struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from)
{ {
struct list_head *pos; struct list_head * pos;
struct pnp_dev *dev; struct pnp_dev * dev;
struct pnpc_driver *cdrv; struct pnp_card_driver * drv;
if (!card || !id) struct pnp_card * card;
if (!clink || !id)
goto done; goto done;
card = clink->card;
drv = clink->driver;
if (!from) { if (!from) {
pos = card->devices.next; pos = card->devices.next;
} else { } else {
...@@ -205,7 +213,7 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, ...@@ -205,7 +213,7 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id,
} }
while (pos != &card->devices) { while (pos != &card->devices) {
dev = card_to_pnp_dev(pos); dev = card_to_pnp_dev(pos);
if (compare_pnp_id(dev->id,id)) if ((!dev->card_link) && compare_pnp_id(dev->id,id))
goto found; goto found;
pos = pos->next; pos = pos->next;
} }
...@@ -214,168 +222,93 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, ...@@ -214,168 +222,93 @@ struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id,
return NULL; return NULL;
found: found:
if (pnp_device_attach(dev) < 0) down_write(&dev->dev.bus->subsys.rwsem);
return NULL; dev->card_link = clink;
cdrv = to_pnpc_driver(card->dev.driver); dev->dev.driver = &drv->link.driver;
if (dev->active == 0) { if (drv->link.driver.probe) {
if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) { if (drv->link.driver.probe(&dev->dev)) {
if(pnp_activate_dev(dev)<0) { dev->dev.driver = NULL;
pnp_device_detach(dev); return NULL;
return NULL;
}
} }
} else {
if ((cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE))
pnp_disable_dev(dev);
} }
spin_lock(&pnp_lock); device_bind_driver(&dev->dev);
list_add_tail(&dev->rdev_list, &card->rdevs); up_write(&dev->dev.bus->subsys.rwsem);
spin_unlock(&pnp_lock);
return dev; return dev;
} }
/** /**
* pnp_release_card_device - call this when the driver no longer needs the device * pnp_release_card_device - call this when the driver no longer needs the device
* @dev: pointer to the PnP device stucture * @dev: pointer to the PnP device stucture
*
* Will disable the device
*/ */
void pnp_release_card_device(struct pnp_dev *dev) void pnp_release_card_device(struct pnp_dev * dev)
{
spin_lock(&pnp_lock);
list_del(&dev->rdev_list);
spin_unlock(&pnp_lock);
pnp_device_detach(dev);
}
static void pnpc_recover_devices(struct pnp_card *card)
{
struct list_head *pos, *temp;
list_for_each_safe(pos,temp,&card->rdevs){
struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list);
pnp_release_card_device(dev);
}
}
int pnpc_attach(struct pnp_card *pnp_card)
{
spin_lock(&pnp_lock);
if(pnp_card->status != PNP_READY){
spin_unlock(&pnp_lock);
return -EBUSY;
}
pnp_card->status = PNP_ATTACHED;
spin_unlock(&pnp_lock);
return 0;
}
void pnpc_detach(struct pnp_card *pnp_card)
{
spin_lock(&pnp_lock);
if (pnp_card->status == PNP_ATTACHED)
pnp_card->status = PNP_READY;
spin_unlock(&pnp_lock);
pnpc_recover_devices(pnp_card);
}
static int pnpc_card_probe(struct device *dev)
{
int error = 0;
struct pnpc_driver *drv = to_pnpc_driver(dev->driver);
struct pnp_card *card = to_pnp_card(dev);
const struct pnp_card_id *card_id = NULL;
pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name);
error = pnpc_attach(card);
if (error < 0)
return error;
if (drv->probe) {
card_id = match_card(drv, card);
if (card_id != NULL)
error = drv->probe(card, card_id);
if (error >= 0){
card->driver = drv;
error = 0;
} else
pnpc_detach(card);
}
return error;
}
static int pnpc_card_remove(struct device *dev)
{ {
struct pnp_card * card = to_pnp_card(dev); struct pnp_card_driver * drv = dev->card_link->driver;
struct pnpc_driver * drv = card->driver; if (!drv)
return;
if (drv) { down_write(&dev->dev.bus->subsys.rwsem);
if (drv->remove) drv->link.remove = &generic_card_remove;
drv->remove(card); device_release_driver(&dev->dev);
card->driver = NULL; drv->link.remove = &generic_card_remove_first;
} up_write(&dev->dev.bus->subsys.rwsem);
pnpc_detach(card);
return 0;
} }
/** /**
* pnpc_register_driver - registers a PnP card driver with the PnP Layer * pnp_register_card_driver - registers a PnP card driver with the PnP Layer
* @cdrv: pointer to the driver to register * @drv: pointer to the driver to register
*/ */
int pnpc_register_driver(struct pnpc_driver * drv) int pnp_register_card_driver(struct pnp_card_driver * drv)
{ {
int count; int count = 0;
struct list_head *pos; struct list_head *pos, *temp;
drv->driver.name = drv->name;
drv->driver.bus = &pnpc_bus_type;
drv->driver.probe = pnpc_card_probe;
drv->driver.remove = pnpc_card_remove;
pnp_dbg("the card driver '%s' has been registered", drv->name);
count = driver_register(&drv->driver);
/* get the number of initial matches */ drv->link.name = drv->name;
if (count >= 0){ drv->link.id_table = NULL; /* this will disable auto matching */
count = 0; drv->link.flags = drv->flags;
list_for_each(pos,&drv->driver.devices){ drv->link.probe = NULL;
count++; drv->link.remove = &generic_card_remove_first;
pnp_register_driver(&drv->link);
list_for_each_safe(pos,temp,&pnp_cards){
struct pnp_card *card = list_entry(pos, struct pnp_card, global_list);
const struct pnp_card_id *id = match_card(drv,card);
if (id) {
struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link));
if (!clink)
continue;
clink->card = card;
clink->driver = drv;
if (drv->probe) {
if (drv->probe(clink, id)>=0)
count++;
} else
count++;
} }
} }
return count; return count;
} }
/** /**
* pnpc_unregister_driver - unregisters a PnP card driver from the PnP Layer * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer
* @cdrv: pointer to the driver to unregister * @drv: pointer to the driver to unregister
*
* Automatically disables requested devices
*/ */
void pnpc_unregister_driver(struct pnpc_driver *drv) void pnp_unregister_card_driver(struct pnp_card_driver * drv)
{ {
driver_unregister(&drv->driver); pnp_unregister_driver(&drv->link);
pnp_dbg("the card driver '%s' has been unregistered", drv->name);
}
static int __init pnp_card_init(void) pnp_dbg("the card driver '%s' has been unregistered", drv->name);
{
printk(KERN_INFO "pnp: Enabling Plug and Play Card Services.\n");
return bus_register(&pnpc_bus_type);
} }
subsys_initcall(pnp_card_init); EXPORT_SYMBOL(pnp_add_card);
EXPORT_SYMBOL(pnp_remove_card);
EXPORT_SYMBOL(pnpc_add_card); EXPORT_SYMBOL(pnp_add_card_device);
EXPORT_SYMBOL(pnpc_remove_card); EXPORT_SYMBOL(pnp_remove_card_device);
EXPORT_SYMBOL(pnpc_add_device); EXPORT_SYMBOL(pnp_add_card_id);
EXPORT_SYMBOL(pnpc_remove_device);
EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_request_card_device);
EXPORT_SYMBOL(pnp_release_card_device); EXPORT_SYMBOL(pnp_release_card_device);
EXPORT_SYMBOL(pnpc_register_driver); EXPORT_SYMBOL(pnp_register_card_driver);
EXPORT_SYMBOL(pnpc_unregister_driver); EXPORT_SYMBOL(pnp_unregister_card_driver);
EXPORT_SYMBOL(pnpc_add_id);
EXPORT_SYMBOL(pnpc_attach);
EXPORT_SYMBOL(pnpc_detach);
...@@ -53,12 +53,11 @@ int compare_pnp_id(struct pnp_id *pos, const char *id) ...@@ -53,12 +53,11 @@ int compare_pnp_id(struct pnp_id *pos, const char *id)
static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev) static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev)
{ {
const struct pnp_device_id *drv_id = drv->id_table; const struct pnp_device_id *drv_id = drv->id_table;
if (!drv) if (!drv_id)
return NULL; return NULL;
if (!dev)
return NULL; while (*drv_id->id) {
while (*drv_id->id){ if (compare_pnp_id(dev->id, drv_id->id))
if (compare_pnp_id(dev->id,drv_id->id))
return drv_id; return drv_id;
drv_id++; drv_id++;
} }
...@@ -102,14 +101,19 @@ static int pnp_device_probe(struct device *dev) ...@@ -102,14 +101,19 @@ static int pnp_device_probe(struct device *dev)
return error; return error;
if (pnp_dev->active == 0) { if (pnp_dev->active == 0) {
if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) { if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) {
error = pnp_activate_dev(pnp_dev); error = pnp_activate_dev(pnp_dev);
if (error < 0) if (error < 0)
return error; return error;
} }
} else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE)
== PNP_DRIVER_RES_DISABLE) {
error = pnp_disable_dev(pnp_dev);
if (error < 0)
return error;
} }
error = 0; error = 0;
if (pnp_drv->probe && pnp_dev->active) { if (pnp_drv->probe) {
dev_id = match_device(pnp_drv, pnp_dev); dev_id = match_device(pnp_drv, pnp_dev);
if (dev_id != NULL) if (dev_id != NULL)
error = pnp_drv->probe(pnp_dev, dev_id); error = pnp_drv->probe(pnp_dev, dev_id);
...@@ -117,9 +121,8 @@ static int pnp_device_probe(struct device *dev) ...@@ -117,9 +121,8 @@ static int pnp_device_probe(struct device *dev)
if (error >= 0){ if (error >= 0){
pnp_dev->driver = pnp_drv; pnp_dev->driver = pnp_drv;
error = 0; error = 0;
} } else
else goto fail;
goto fail;
return error; return error;
fail: fail:
......
...@@ -332,11 +332,18 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf) ...@@ -332,11 +332,18 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
buffer->buffer = buf; buffer->buffer = buf;
buffer->curr = buffer->buffer; buffer->curr = buffer->buffer;
pnp_printf(buffer,"mode = ");
if (dev->config_mode & PNP_CONFIG_MANUAL)
pnp_printf(buffer,"manual\n");
else
pnp_printf(buffer,"auto\n");
pnp_printf(buffer,"state = "); pnp_printf(buffer,"state = ");
if (dev->active) if (dev->active)
pnp_printf(buffer,"active\n"); pnp_printf(buffer,"active\n");
else else
pnp_printf(buffer,"disabled\n"); pnp_printf(buffer,"disabled\n");
for (i = 0; i < PNP_MAX_PORT; i++) { for (i = 0; i < PNP_MAX_PORT; i++) {
if (pnp_port_valid(dev, i)) { if (pnp_port_valid(dev, i)) {
pnp_printf(buffer,"io"); pnp_printf(buffer,"io");
...@@ -402,13 +409,13 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count ...@@ -402,13 +409,13 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
retval = pnp_activate_dev(dev); retval = pnp_activate_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf,"auto-config",11)) { if (!strnicmp(buf,"auto",4)) {
if (dev->active) if (dev->active)
goto done; goto done;
retval = pnp_auto_config_dev(dev); retval = pnp_auto_config_dev(dev);
goto done; goto done;
} }
if (!strnicmp(buf,"clear-config",12)) { if (!strnicmp(buf,"clear",5)) {
if (dev->active) if (dev->active)
goto done; goto done;
spin_lock(&pnp_lock); spin_lock(&pnp_lock);
......
...@@ -626,7 +626,7 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) ...@@ -626,7 +626,7 @@ isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
isapnp_peek(name, size1); isapnp_peek(name, size1);
name[size1] = '\0'; name[size1] = '\0';
*size -= size1; *size -= size1;
/* clean whitespace from end of string */ /* clean whitespace from end of string */
while (size1 > 0 && name[--size1] == ' ') while (size1 > 0 && name[--size1] == ' ')
name[size1] = '\0'; name[size1] = '\0';
...@@ -647,7 +647,7 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -647,7 +647,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
return 1; return 1;
if (pnp_build_resource(dev, 0) == NULL) if (pnp_build_resource(dev, 0) == NULL)
return 1; return 1;
pnpc_add_device(card,dev); pnp_add_card_device(card,dev);
while (1) { while (1) {
if (isapnp_read_tag(&type, &size)<0) if (isapnp_read_tag(&type, &size)<0)
return 1; return 1;
...@@ -659,7 +659,7 @@ static int __init isapnp_create_device(struct pnp_card *card, ...@@ -659,7 +659,7 @@ static int __init isapnp_create_device(struct pnp_card *card,
if ((dev = isapnp_parse_device(card, size, number++)) == NULL) if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
return 1; return 1;
pnp_build_resource(dev,0); pnp_build_resource(dev,0);
pnpc_add_device(card,dev); pnp_add_card_device(card,dev);
size = 0; size = 0;
skip = 0; skip = 0;
} else { } else {
...@@ -852,7 +852,7 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor, ...@@ -852,7 +852,7 @@ static void isapnp_parse_card_id(struct pnp_card * card, unsigned short vendor,
device & 0x0f, device & 0x0f,
(device >> 12) & 0x0f, (device >> 12) & 0x0f,
(device >> 8) & 0x0f); (device >> 8) & 0x0f);
pnpc_add_id(id,card); pnp_add_card_id(id,card);
} }
...@@ -962,7 +962,7 @@ static int __init isapnp_build_device_list(void) ...@@ -962,7 +962,7 @@ static int __init isapnp_build_device_list(void)
isapnp_parse_current_resources(dev, &dev->res); isapnp_parse_current_resources(dev, &dev->res);
} }
pnpc_add_card(card); pnp_add_card(card);
} }
isapnp_wait(); isapnp_wait();
return 0; return 0;
......
...@@ -532,6 +532,39 @@ int pnp_auto_config_dev(struct pnp_dev *dev) ...@@ -532,6 +532,39 @@ int pnp_auto_config_dev(struct pnp_dev *dev)
return error; return error;
} }
static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab)
{
int idx;
for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO)
continue;
ctab->irq_resource[idx].start = ntab->irq_resource[idx].start;
ctab->irq_resource[idx].end = ntab->irq_resource[idx].end;
ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags;
}
for (idx = 0; idx < PNP_MAX_DMA; idx++) {
if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO)
continue;
ctab->dma_resource[idx].start = ntab->dma_resource[idx].start;
ctab->dma_resource[idx].end = ntab->dma_resource[idx].end;
ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags;
}
for (idx = 0; idx < PNP_MAX_PORT; idx++) {
if (ntab->port_resource[idx].flags & IORESOURCE_AUTO)
continue;
ctab->port_resource[idx].start = ntab->port_resource[idx].start;
ctab->port_resource[idx].end = ntab->port_resource[idx].end;
ctab->port_resource[idx].flags = ntab->port_resource[idx].flags;
}
for (idx = 0; idx < PNP_MAX_MEM; idx++) {
if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO)
continue;
ctab->irq_resource[idx].start = ntab->mem_resource[idx].start;
ctab->irq_resource[idx].end = ntab->mem_resource[idx].end;
ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags;
}
}
/** /**
* pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
* @dev: pointer to the desired device * @dev: pointer to the desired device
...@@ -554,7 +587,7 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res, ...@@ -554,7 +587,7 @@ int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table * res,
*bak = dev->res; *bak = dev->res;
spin_lock(&pnp_lock); spin_lock(&pnp_lock);
dev->res = *res; pnp_process_manual_resources(&dev->res, res);
if (!(mode & PNP_CONFIG_FORCE)) { if (!(mode & PNP_CONFIG_FORCE)) {
for (i = 0; i < PNP_MAX_PORT; i++) { for (i = 0; i < PNP_MAX_PORT; i++) {
if(pnp_check_port(dev,i)) if(pnp_check_port(dev,i))
...@@ -681,7 +714,7 @@ int pnp_disable_dev(struct pnp_dev *dev) ...@@ -681,7 +714,7 @@ int pnp_disable_dev(struct pnp_dev *dev)
return -1; return -1;
} }
dev->active = 0; /* just in case the protocol doesn't do this */ dev->active = 0; /* just in case the protocol doesn't do this */
pnp_dbg("the device '%s' has been disabled.", dev->dev.bus_id); pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id);
return 0; return 0;
} }
......
...@@ -558,25 +558,25 @@ void pnp_init_resource_table(struct pnp_resource_table *table) ...@@ -558,25 +558,25 @@ void pnp_init_resource_table(struct pnp_resource_table *table)
table->irq_resource[idx].name = NULL; table->irq_resource[idx].name = NULL;
table->irq_resource[idx].start = -1; table->irq_resource[idx].start = -1;
table->irq_resource[idx].end = -1; table->irq_resource[idx].end = -1;
table->irq_resource[idx].flags = 0; table->irq_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_DMA; idx++) { for (idx = 0; idx < PNP_MAX_DMA; idx++) {
table->dma_resource[idx].name = NULL; table->dma_resource[idx].name = NULL;
table->dma_resource[idx].start = -1; table->dma_resource[idx].start = -1;
table->dma_resource[idx].end = -1; table->dma_resource[idx].end = -1;
table->dma_resource[idx].flags = 0; table->dma_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_PORT; idx++) { for (idx = 0; idx < PNP_MAX_PORT; idx++) {
table->port_resource[idx].name = NULL; table->port_resource[idx].name = NULL;
table->port_resource[idx].start = 0; table->port_resource[idx].start = 0;
table->port_resource[idx].end = 0; table->port_resource[idx].end = 0;
table->port_resource[idx].flags = 0; table->port_resource[idx].flags = IORESOURCE_AUTO;
} }
for (idx = 0; idx < PNP_MAX_MEM; idx++) { for (idx = 0; idx < PNP_MAX_MEM; idx++) {
table->mem_resource[idx].name = NULL; table->mem_resource[idx].name = NULL;
table->mem_resource[idx].start = 0; table->mem_resource[idx].start = 0;
table->mem_resource[idx].end = 0; table->mem_resource[idx].end = 0;
table->mem_resource[idx].flags = 0; table->mem_resource[idx].flags = IORESOURCE_AUTO;
} }
} }
......
...@@ -93,8 +93,8 @@ static int system_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *de ...@@ -93,8 +93,8 @@ static int system_pnp_probe(struct pnp_dev * dev, const struct pnp_device_id *de
static struct pnp_driver system_pnp_driver = { static struct pnp_driver system_pnp_driver = {
.name = "system", .name = "system",
.flags = PNP_DRIVER_DO_NOT_ACTIVATE,
.id_table = pnp_dev_table, .id_table = pnp_dev_table,
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
.probe = system_pnp_probe, .probe = system_pnp_probe,
.remove = NULL, .remove = NULL,
}; };
......
...@@ -138,11 +138,8 @@ struct pnp_card { ...@@ -138,11 +138,8 @@ struct pnp_card {
struct list_head global_list; /* node in global list of cards */ struct list_head global_list; /* node in global list of cards */
struct list_head protocol_list; /* node in protocol's list of cards */ struct list_head protocol_list; /* node in protocol's list of cards */
struct list_head devices; /* devices attached to the card */ struct list_head devices; /* devices attached to the card */
struct list_head rdevs; /* a list of devices requested by the card driver */
int status;
struct pnp_protocol * protocol; struct pnp_protocol * protocol;
struct pnpc_driver * driver;
struct pnp_id * id; /* contains supported EISA IDs*/ struct pnp_id * id; /* contains supported EISA IDs*/
void * protocol_data; /* Used to store protocol specific data */ void * protocol_data; /* Used to store protocol specific data */
...@@ -161,24 +158,30 @@ struct pnp_card { ...@@ -161,24 +158,30 @@ struct pnp_card {
(card) != global_to_pnp_card(&pnp_cards); \ (card) != global_to_pnp_card(&pnp_cards); \
(card) = global_to_pnp_card((card)->global_list.next)) (card) = global_to_pnp_card((card)->global_list.next))
static inline void *pnpc_get_drvdata (struct pnp_card *pcard) static inline void *pnp_get_card_protodata (struct pnp_card *pcard)
{ {
return dev_get_drvdata(&pcard->dev); return pcard->protocol_data;
} }
static inline void pnpc_set_drvdata (struct pnp_card *pcard, void *data) static inline void pnp_set_card_protodata (struct pnp_card *pcard, void *data)
{ {
dev_set_drvdata(&pcard->dev, data); pcard->protocol_data = data;
} }
static inline void *pnpc_get_protodata (struct pnp_card *pcard) struct pnp_card_link {
struct pnp_card * card;
struct pnp_card_driver * driver;
void * driver_data;
};
static inline void *pnp_get_card_drvdata (struct pnp_card_link *pcard)
{ {
return pcard->protocol_data; return pcard->driver_data;
} }
static inline void pnpc_set_protodata (struct pnp_card *pcard, void *data) static inline void pnp_set_card_drvdata (struct pnp_card_link *pcard, void *data)
{ {
pcard->protocol_data = data; pcard->driver_data = data;
} }
struct pnp_dev { struct pnp_dev {
...@@ -196,6 +199,7 @@ struct pnp_dev { ...@@ -196,6 +199,7 @@ struct pnp_dev {
struct pnp_protocol * protocol; struct pnp_protocol * protocol;
struct pnp_card * card; /* card the device is attached to, none if NULL */ struct pnp_card * card; /* card the device is attached to, none if NULL */
struct pnp_driver * driver; struct pnp_driver * driver;
struct pnp_card_link * card_link;
struct pnp_id * id; /* supported EISA IDs*/ struct pnp_id * id; /* supported EISA IDs*/
struct pnp_resource_table res; /* contains the currently chosen resources */ struct pnp_resource_table res; /* contains the currently chosen resources */
...@@ -299,11 +303,8 @@ struct pnp_card_id { ...@@ -299,11 +303,8 @@ struct pnp_card_id {
} devs[PNP_MAX_DEVICES]; /* logical devices */ } devs[PNP_MAX_DEVICES]; /* logical devices */
}; };
#define PNP_DRIVER_DO_NOT_ACTIVATE (1<<0)
struct pnp_driver { struct pnp_driver {
struct list_head node; char * name;
char *name;
const struct pnp_device_id *id_table; const struct pnp_device_id *id_table;
unsigned int flags; unsigned int flags;
int (*probe) (struct pnp_dev *dev, const struct pnp_device_id *dev_id); int (*probe) (struct pnp_dev *dev, const struct pnp_device_id *dev_id);
...@@ -311,21 +312,22 @@ struct pnp_driver { ...@@ -311,21 +312,22 @@ struct pnp_driver {
struct device_driver driver; struct device_driver driver;
}; };
#define to_pnp_driver(drv) container_of(drv,struct pnp_driver, driver) #define to_pnp_driver(drv) container_of(drv, struct pnp_driver, driver)
#define PNPC_DRIVER_DO_NOT_ACTIVATE (1<<0)
struct pnpc_driver { struct pnp_card_driver {
struct list_head node; char * name;
char *name;
const struct pnp_card_id *id_table; const struct pnp_card_id *id_table;
unsigned int flags; unsigned int flags;
int (*probe) (struct pnp_card *card, const struct pnp_card_id *card_id); int (*probe) (struct pnp_card_link *card, const struct pnp_card_id *card_id);
void (*remove) (struct pnp_card *card); void (*remove) (struct pnp_card_link *card);
struct device_driver driver; struct pnp_driver link;
}; };
#define to_pnpc_driver(drv) container_of(drv,struct pnpc_driver, driver) #define to_pnp_card_driver(drv) container_of(drv, struct pnp_card_driver, link)
/* pnp driver flags */
#define PNP_DRIVER_RES_DO_NOT_CHANGE 0x0001 /* do not change the state of the device */
#define PNP_DRIVER_RES_DISABLE 0x0003 /* ensure the device is disabled */
/* /*
...@@ -366,9 +368,21 @@ int pnp_register_protocol(struct pnp_protocol *protocol); ...@@ -366,9 +368,21 @@ int pnp_register_protocol(struct pnp_protocol *protocol);
void pnp_unregister_protocol(struct pnp_protocol *protocol); void pnp_unregister_protocol(struct pnp_protocol *protocol);
int pnp_add_device(struct pnp_dev *dev); int pnp_add_device(struct pnp_dev *dev);
void pnp_remove_device(struct pnp_dev *dev); void pnp_remove_device(struct pnp_dev *dev);
extern struct list_head pnp_global;
int pnp_device_attach(struct pnp_dev *pnp_dev); int pnp_device_attach(struct pnp_dev *pnp_dev);
void pnp_device_detach(struct pnp_dev *pnp_dev); void pnp_device_detach(struct pnp_dev *pnp_dev);
extern struct list_head pnp_global;
/* card */
int pnp_add_card(struct pnp_card *card);
void pnp_remove_card(struct pnp_card *card);
int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev);
void pnp_remove_card_device(struct pnp_dev *dev);
int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card);
struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from);
void pnp_release_card_device(struct pnp_dev * dev);
int pnp_register_card_driver(struct pnp_card_driver * drv);
void pnp_unregister_card_driver(struct pnp_card_driver * drv);
extern struct list_head pnp_cards;
/* resource */ /* resource */
struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent); struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent);
...@@ -413,6 +427,17 @@ static inline void pnp_remove_device(struct pnp_dev *dev) { } ...@@ -413,6 +427,17 @@ static inline void pnp_remove_device(struct pnp_dev *dev) { }
static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; }
static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; }
/* card */
static inline int pnp_add_card(struct pnp_card *card) { return -ENODEV; }
static inline void pnp_remove_card(struct pnp_card *card) { ; }
static inline int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
static inline void pnp_remove_card_device(struct pnp_dev *dev) { ; }
static inline int pnp_add_card_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
static inline struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) { return -ENODEV; }
static inline void pnp_release_card_device(struct pnp_dev * dev) { ; }
static inline int pnp_register_card_driver(struct pnp_card_driver * drv) { return -ENODEV; }
static inline void pnp_unregister_card_driver(struct pnp_card_driver * drv) { ; }
/* resource */ /* resource */
static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; } static inline struct pnp_resources * pnp_build_resource(struct pnp_dev *dev, int dependent) { return NULL; }
static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; } static inline struct pnp_resources * pnp_find_resources(struct pnp_dev *dev, int depnum) { return NULL; }
...@@ -446,37 +471,6 @@ static inline unsigned char * pnp_write_resources(unsigned char * p, unsigned ch ...@@ -446,37 +471,6 @@ static inline unsigned char * pnp_write_resources(unsigned char * p, unsigned ch
#endif /* CONFIG_PNP */ #endif /* CONFIG_PNP */
#if defined(CONFIG_PNP_CARD)
/* card */
int pnpc_add_card(struct pnp_card *card);
void pnpc_remove_card(struct pnp_card *card);
int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev);
void pnpc_remove_device(struct pnp_dev *dev);
struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from);
void pnp_release_card_device(struct pnp_dev *dev);
int pnpc_register_driver(struct pnpc_driver * drv);
void pnpc_unregister_driver(struct pnpc_driver *drv);
int pnpc_add_id(struct pnp_id *id, struct pnp_card *card);
extern struct list_head pnp_cards;
int pnpc_attach(struct pnp_card *card);
void pnpc_detach(struct pnp_card *card);
#else
/* card */
static inline int pnpc_add_card(struct pnp_card *card) { return -ENODEV; }
static inline void pnpc_remove_card(struct pnp_card *card) { ; }
static inline int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) { return -ENODEV; }
static inline void pnpc_remove_device(struct pnp_dev *dev) { ; }
static inline struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) { return NULL; }
static inline void pnp_release_card_device(struct pnp_dev *dev) { ; }
static inline int pnpc_register_driver(struct pnpc_driver *drv) { return -ENODEV; }
static inline void pnpc_unregister_driver(struct pnpc_driver *drv) { ; }
static inline int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) { return -ENODEV; }
#endif /* CONFIG_PNP_CARD */
#define pnp_err(format, arg...) printk(KERN_ERR "pnp: " format "\n" , ## arg) #define pnp_err(format, arg...) printk(KERN_ERR "pnp: " format "\n" , ## arg)
#define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg) #define pnp_info(format, arg...) printk(KERN_INFO "pnp: " format "\n" , ## arg)
#define pnp_warn(format, arg...) printk(KERN_WARNING "pnp: " format "\n" , ## arg) #define pnp_warn(format, arg...) printk(KERN_WARNING "pnp: " format "\n" , ## arg)
......
...@@ -24,11 +24,7 @@ ...@@ -24,11 +24,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/time.h> #include <linux/time.h>
#ifndef LINUX_ISAPNP_H #include <linux/pnp.h>
#include <linux/isapnp.h>
#define isapnp_card pci_bus
#define isapnp_dev pci_dev
#endif
#include <sound/core.h> #include <sound/core.h>
#define SNDRV_GET_ID #define SNDRV_GET_ID
#include <sound/initval.h> #include <sound/initval.h>
...@@ -96,167 +92,124 @@ MODULE_PARM_DESC(dma16, "16-bit DMA # for als100 driver."); ...@@ -96,167 +92,124 @@ MODULE_PARM_DESC(dma16, "16-bit DMA # for als100 driver.");
MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC); MODULE_PARM_SYNTAX(dma16, SNDRV_DMA16_DESC);
struct snd_card_als100 { struct snd_card_als100 {
#ifdef __ISAPNP__ int dev_no;
struct isapnp_dev *dev; struct pnp_dev *dev;
struct isapnp_dev *devmpu; struct pnp_dev *devmpu;
struct isapnp_dev *devopl; struct pnp_dev *devopl;
#endif /* __ISAPNP__ */
}; };
static snd_card_t *snd_als100_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; static struct pnp_card_id snd_als100_pnpids[] __devinitdata = {
#ifdef __ISAPNP__
static struct isapnp_card *snd_als100_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
static const struct isapnp_card_id *snd_als100_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
#define ISAPNP_ALS100(_va, _vb, _vc, _device, _audio, _mpu401, _opl) \
{ \
ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
devs : { ISAPNP_DEVICE_ID('@', '@', '@', _audio), \
ISAPNP_DEVICE_ID('@', 'X', '@', _mpu401), \
ISAPNP_DEVICE_ID('@', 'H', '@', _opl) } \
}
static struct isapnp_card_id snd_als100_pnpids[] __devinitdata = {
/* ALS100 - PRO16PNP */ /* ALS100 - PRO16PNP */
ISAPNP_ALS100('A','L','S',0x0001,0x0001,0x0001,0x0001), { .id = "ALS0001", .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" }, } },
/* ALS110 - MF1000 - Digimate 3D Sound */ /* ALS110 - MF1000 - Digimate 3D Sound */
ISAPNP_ALS100('A','L','S',0x0110,0x1001,0x1001,0x1001), { .id = "ALS0110", .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" }, } },
/* ALS120 */ /* ALS120 */
ISAPNP_ALS100('A','L','S',0x0120,0x2001,0x2001,0x2001), { .id = "ALS0120", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } },
/* ALS200 */ /* ALS200 */
ISAPNP_ALS100('A','L','S',0x0200,0x0020,0x0020,0x0001), { .id = "ALS0200", .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" }, } },
/* RTL3000 */ /* RTL3000 */
ISAPNP_ALS100('R','T','L',0x3000,0x2001,0x2001,0x2001), { .id = "RTL3000", .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" }, } },
{ ISAPNP_CARD_END, } { .id = "", } /* end */
}; };
ISAPNP_CARD_TABLE(snd_als100_pnpids); MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
#endif /* __ISAPNP__ */
#define DRIVER_NAME "snd-card-als100" #define DRIVER_NAME "snd-card-als100"
static int __devinit snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard,
#ifdef __ISAPNP__ struct pnp_card_link *card,
static int __init snd_card_als100_isapnp(int dev, struct snd_card_als100 *acard) const struct pnp_card_id *id)
{ {
const struct isapnp_card_id *id = snd_als100_isapnp_id[dev]; struct pnp_dev *pdev;
struct isapnp_card *card = snd_als100_isapnp_cards[dev]; struct pnp_resource_table * cfg = kmalloc(GFP_ATOMIC, sizeof(struct pnp_resource_table));
struct isapnp_dev *pdev; int err;
if (!cfg)
acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL); return -ENOMEM;
if (acard->dev->active) { acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
acard->dev = NULL; if (acard->dev == NULL) {
return -EBUSY; kfree(cfg);
} return -ENODEV;
acard->devmpu = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
if (acard->devmpu->active) {
acard->dev = acard->devmpu = NULL;
return -EBUSY;
}
acard->devopl = isapnp_find_dev(card, id->devs[2].vendor, id->devs[2].function, NULL);
if (acard->devopl->active) {
acard->dev = acard->devmpu = acard->devopl = NULL;
return -EBUSY;
} }
acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu);
pdev = acard->dev; pdev = acard->dev;
if (pdev->prepare(pdev)<0)
return -EAGAIN;
pnp_init_resource_table(cfg);
/* override resources */
if (port[dev] != SNDRV_AUTO_PORT) if (port[dev] != SNDRV_AUTO_PORT)
isapnp_resource_change(&pdev->resource[0], port[dev], 16); pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
if (dma8[dev] != SNDRV_AUTO_DMA) if (dma8[dev] != SNDRV_AUTO_DMA)
isapnp_resource_change(&pdev->dma_resource[0], dma8[dev], pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
1);
if (dma16[dev] != SNDRV_AUTO_DMA) if (dma16[dev] != SNDRV_AUTO_DMA)
isapnp_resource_change(&pdev->dma_resource[1], dma16[dev], pnp_resource_change(&cfg->dma_resource[1], dma16[dev], 1);
1);
if (irq[dev] != SNDRV_AUTO_IRQ) if (irq[dev] != SNDRV_AUTO_IRQ)
isapnp_resource_change(&pdev->irq_resource[0], irq[dev], 1); pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
if (pdev->activate(pdev)<0) { printk(KERN_ERR PFX "AUDIO the requested resources are invalid, using auto config\n");
printk(KERN_ERR PFX "AUDIO isapnp configure failure\n"); err = pnp_activate_dev(pdev);
return -EBUSY; if (err < 0) {
printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
return err;
} }
port[dev] = pnp_port_start(pdev, 0);
port[dev] = pdev->resource[0].start; dma8[dev] = pnp_dma(pdev, 1);
dma8[dev] = pdev->dma_resource[1].start; dma16[dev] = pnp_dma(pdev, 0);
dma16[dev] = pdev->dma_resource[0].start; irq[dev] = pnp_irq(pdev, 0);
irq[dev] = pdev->irq_resource[0].start;
pdev = acard->devmpu; pdev = acard->devmpu;
if (pdev == NULL || pdev->prepare(pdev)<0) { if (pdev != NULL) {
mpu_port[dev] = -1; pnp_init_resource_table(cfg);
return 0; if (mpu_port[dev] != SNDRV_AUTO_PORT)
} pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
if (mpu_port[dev] != SNDRV_AUTO_PORT) pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
isapnp_resource_change(&pdev->resource[0], mpu_port[dev], if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
2); printk(KERN_ERR PFX "MPU401 the requested resources are invalid, using auto config\n");
if (mpu_irq[dev] != SNDRV_AUTO_IRQ) err = pnp_activate_dev(pdev);
isapnp_resource_change(&pdev->irq_resource[0], mpu_irq[dev], if (err < 0)
1); goto __mpu_error;
mpu_port[dev] = pnp_port_start(pdev, 0);
if (pdev->activate(pdev)<0) { mpu_irq[dev] = pnp_irq(pdev, 0);
printk(KERN_ERR PFX "MPU-401 isapnp configure failure\n");
mpu_port[dev] = -1;
acard->devmpu = NULL;
} else { } else {
mpu_port[dev] = pdev->resource[0].start; __mpu_error:
mpu_irq[dev] = pdev->irq_resource[0].start; if (pdev) {
pnp_release_card_device(pdev);
printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
}
acard->devmpu = NULL;
mpu_port[dev] = -1;
} }
pdev = acard->devopl; pdev = acard->devopl;
if (pdev == NULL || pdev->prepare(pdev)<0) { if (pdev != NULL) {
fm_port[dev] = -1; pnp_init_resource_table(cfg);
return 0; if (fm_port[dev] != SNDRV_AUTO_PORT)
} pnp_resource_change(&cfg->port_resource[0], fm_port[dev], 4);
if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
if (fm_port[dev] != SNDRV_AUTO_PORT) printk(KERN_ERR PFX "OPL3 the requested resources are invalid, using auto config\n");
isapnp_resource_change(&pdev->resource[0], fm_port[dev], 4); err = pnp_activate_dev(pdev);
if (err < 0)
if (pdev->activate(pdev)<0) { goto __fm_error;
printk(KERN_ERR PFX "OPL isapnp configure failure\n"); fm_port[dev] = pnp_port_start(pdev, 0);
fm_port[dev] = -1;
acard->devopl = NULL;
} else { } else {
fm_port[dev] = pdev->resource[0].start; __fm_error:
if (pdev) {
pnp_release_card_device(pdev);
printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n");
}
acard->devopl = NULL;
fm_port[dev] = -1;
} }
kfree(cfg);
return 0; return 0;
} }
static void snd_card_als100_deactivate(struct snd_card_als100 *acard) static int __init snd_card_als100_probe(int dev,
{ struct pnp_card_link *pcard,
if (acard->dev) { const struct pnp_card_id *pid)
acard->dev->deactivate(acard->dev);
acard->dev = NULL;
}
if (acard->devmpu) {
acard->devmpu->deactivate(acard->devmpu);
acard->devmpu = NULL;
}
if (acard->devopl) {
acard->devopl->deactivate(acard->devopl);
acard->devopl = NULL;
}
}
#endif /* __ISAPNP__ */
static void snd_card_als100_free(snd_card_t *card)
{
struct snd_card_als100 *acard = (struct snd_card_als100 *)card->private_data;
if (acard) {
#ifdef __ISAPNP__
snd_card_als100_deactivate(acard);
#endif /* __ISAPNP__ */
}
}
static int __init snd_card_als100_probe(int dev)
{ {
int error; int error;
sb_t *chip; sb_t *chip;
...@@ -268,18 +221,11 @@ static int __init snd_card_als100_probe(int dev) ...@@ -268,18 +221,11 @@ static int __init snd_card_als100_probe(int dev)
sizeof(struct snd_card_als100))) == NULL) sizeof(struct snd_card_als100))) == NULL)
return -ENOMEM; return -ENOMEM;
acard = (struct snd_card_als100 *)card->private_data; acard = (struct snd_card_als100 *)card->private_data;
card->private_free = snd_card_als100_free;
#ifdef __ISAPNP__ if ((error = snd_card_als100_isapnp(dev, acard, pcard, pid))) {
if ((error = snd_card_als100_isapnp(dev, acard))) {
snd_card_free(card); snd_card_free(card);
return error; return error;
} }
#else
printk(KERN_ERR PFX "you have to enable PnP support ...\n");
snd_card_free(card);
return -ENOSYS;
#endif /* __ISAPNP__ */
if ((error = snd_sbdsp_create(card, port[dev], if ((error = snd_sbdsp_create(card, port[dev],
irq[dev], irq[dev],
...@@ -336,13 +282,12 @@ static int __init snd_card_als100_probe(int dev) ...@@ -336,13 +282,12 @@ static int __init snd_card_als100_probe(int dev)
snd_card_free(card); snd_card_free(card);
return error; return error;
} }
snd_als100_cards[dev] = card; pnp_set_card_drvdata(pcard, card);
return 0; return 0;
} }
#ifdef __ISAPNP__ static int __devinit snd_als100_pnp_detect(struct pnp_card_link *card,
static int __init snd_als100_isapnp_detect(struct isapnp_card *card, const struct pnp_card_id *id)
const struct isapnp_card_id *id)
{ {
static int dev; static int dev;
int res; int res;
...@@ -350,9 +295,7 @@ static int __init snd_als100_isapnp_detect(struct isapnp_card *card, ...@@ -350,9 +295,7 @@ static int __init snd_als100_isapnp_detect(struct isapnp_card *card,
for ( ; dev < SNDRV_CARDS; dev++) { for ( ; dev < SNDRV_CARDS; dev++) {
if (!enable[dev]) if (!enable[dev])
continue; continue;
snd_als100_isapnp_cards[dev] = card; res = snd_card_als100_probe(dev, card, id);
snd_als100_isapnp_id[dev] = id;
res = snd_card_als100_probe(dev);
if (res < 0) if (res < 0)
return res; return res;
dev++; dev++;
...@@ -360,17 +303,28 @@ static int __init snd_als100_isapnp_detect(struct isapnp_card *card, ...@@ -360,17 +303,28 @@ static int __init snd_als100_isapnp_detect(struct isapnp_card *card,
} }
return -ENODEV; return -ENODEV;
} }
#endif
static void __devexit snd_als100_pnp_remove(struct pnp_card_link * pcard)
{
snd_card_t *card = (snd_card_t *) pnp_get_card_drvdata(pcard);
snd_card_disconnect(card);
snd_card_free_in_thread(card);
}
static struct pnp_card_driver als100_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "als100",
.id_table = snd_als100_pnpids,
.probe = snd_als100_pnp_detect,
.remove = __devexit_p(snd_als100_pnp_remove),
};
static int __init alsa_card_als100_init(void) static int __init alsa_card_als100_init(void)
{ {
int cards = 0; int cards = 0;
#ifdef __ISAPNP__ cards += pnp_register_card_driver(&als100_pnpc_driver);
cards += isapnp_probe_cards(snd_als100_pnpids, snd_als100_isapnp_detect);
#else
printk(KERN_ERR PFX "you have to enable ISA PnP support.\n");
#endif
#ifdef MODULE #ifdef MODULE
if (!cards) if (!cards)
printk(KERN_ERR "no ALS100 based soundcards found\n"); printk(KERN_ERR "no ALS100 based soundcards found\n");
...@@ -380,10 +334,7 @@ static int __init alsa_card_als100_init(void) ...@@ -380,10 +334,7 @@ static int __init alsa_card_als100_init(void)
static void __exit alsa_card_als100_exit(void) static void __exit alsa_card_als100_exit(void)
{ {
int dev; pnp_unregister_card_driver(&als100_pnpc_driver);
for (dev = 0; dev < SNDRV_CARDS; dev++)
snd_card_free(snd_als100_cards[dev]);
} }
module_init(alsa_card_als100_init) module_init(alsa_card_als100_init)
......
...@@ -32,9 +32,9 @@ ...@@ -32,9 +32,9 @@
#include "sound_config.h" #include "sound_config.h"
#include "sb_mixer.h" #include "sb_mixer.h"
#include "sb.h" #include "sb.h"
#ifdef CONFIG_PNP_CARD #ifdef CONFIG_PNP
#include <linux/pnp.h> #include <linux/pnp.h>
#endif #endif /* CONFIG_PNP */
#include "sb_card.h" #include "sb_card.h"
MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver"); MODULE_DESCRIPTION("OSS Soundblaster ISA PnP and legacy sound driver");
...@@ -54,7 +54,7 @@ static int __initdata sm_games = 0; /* Logitech soundman games? */ ...@@ -54,7 +54,7 @@ static int __initdata sm_games = 0; /* Logitech soundman games? */
struct sb_card_config *legacy = NULL; struct sb_card_config *legacy = NULL;
#ifdef CONFIG_PNP_CARD #ifdef CONFIG_PNP
static int __initdata pnp = 1; static int __initdata pnp = 1;
/* /*
static int __initdata uart401 = 0; static int __initdata uart401 = 0;
...@@ -85,7 +85,7 @@ module_param(acer, int, 000); ...@@ -85,7 +85,7 @@ module_param(acer, int, 000);
MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks "\ MODULE_PARM_DESC(acer, "Set this to detect cards in some ACER notebooks "\
"(doesn't work with pnp)"); "(doesn't work with pnp)");
#ifdef CONFIG_PNP_CARD #ifdef CONFIG_PNP
module_param(pnp, int, 000); module_param(pnp, int, 000);
MODULE_PARM_DESC(pnp, "Went set to 0 will disable detection using PnP. "\ MODULE_PARM_DESC(pnp, "Went set to 0 will disable detection using PnP. "\
"Default is 1.\n"); "Default is 1.\n");
...@@ -95,7 +95,7 @@ module_param(uart401, int, 000); ...@@ -95,7 +95,7 @@ module_param(uart401, int, 000);
MODULE_PARM_DESC(uart401, "When set to 1, will attempt to detect and enable"\ MODULE_PARM_DESC(uart401, "When set to 1, will attempt to detect and enable"\
"the mpu on some clones"); "the mpu on some clones");
*/ */
#endif /* CONFIG_PNP_CARD */ #endif /* CONFIG_PNP */
/* OSS subsystem card registration shared by PnP and legacy routines */ /* OSS subsystem card registration shared by PnP and legacy routines */
static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo) static int sb_register_oss(struct sb_card_config *scc, struct sb_module_options *sbmo)
...@@ -157,7 +157,7 @@ static int sb_init_legacy(void) ...@@ -157,7 +157,7 @@ static int sb_init_legacy(void)
return sb_register_oss(legacy, &sbmo); return sb_register_oss(legacy, &sbmo);
} }
#ifdef CONFIG_PNP_CARD #ifdef CONFIG_PNP
/* Populate the OSS subsystem structures with information from PnP */ /* Populate the OSS subsystem structures with information from PnP */
static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc) static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
...@@ -224,7 +224,7 @@ static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc) ...@@ -224,7 +224,7 @@ static void sb_dev2cfg(struct pnp_dev *dev, struct sb_card_config *scc)
} }
/* Probe callback function for the PnP API */ /* Probe callback function for the PnP API */
static int sb_pnp_probe(struct pnp_card *card, const struct pnp_card_id *card_id) static int sb_pnp_probe(struct pnp_card_link *card, const struct pnp_card_id *card_id)
{ {
struct sb_card_config *scc; struct sb_card_config *scc;
struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */ struct sb_module_options sbmo = {0}; /* Default to 0 for PnP */
...@@ -252,14 +252,14 @@ static int sb_pnp_probe(struct pnp_card *card, const struct pnp_card_id *card_id ...@@ -252,14 +252,14 @@ static int sb_pnp_probe(struct pnp_card *card, const struct pnp_card_id *card_id
"dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq, "dma=%d, dma16=%d\n", scc->conf.io_base, scc->conf.irq,
scc->conf.dma, scc->conf.dma2); scc->conf.dma, scc->conf.dma2);
pnpc_set_drvdata(card, scc); pnp_set_card_drvdata(card, scc);
return sb_register_oss(scc, &sbmo); return sb_register_oss(scc, &sbmo);
} }
static void sb_pnp_remove(struct pnp_card *card) static void sb_pnp_remove(struct pnp_card_link *card)
{ {
struct sb_card_config *scc = pnpc_get_drvdata(card); struct sb_card_config *scc = pnp_get_card_drvdata(card);
if(!scc) if(!scc)
return; return;
...@@ -269,13 +269,13 @@ static void sb_pnp_remove(struct pnp_card *card) ...@@ -269,13 +269,13 @@ static void sb_pnp_remove(struct pnp_card *card)
sb_unload(scc); sb_unload(scc);
} }
static struct pnpc_driver sb_pnp_driver = { static struct pnp_card_driver sb_pnp_driver = {
.name = "OSS SndBlstr", /* 16 character limit */ .name = "OSS SndBlstr", /* 16 character limit */
.id_table = sb_pnp_card_table, .id_table = sb_pnp_card_table,
.probe = sb_pnp_probe, .probe = sb_pnp_probe,
.remove = sb_pnp_remove, .remove = sb_pnp_remove,
}; };
#endif /* CONFIG_PNP_CARD */ #endif /* CONFIG_PNP */
static int __init sb_init(void) static int __init sb_init(void)
{ {
...@@ -293,9 +293,9 @@ static int __init sb_init(void) ...@@ -293,9 +293,9 @@ static int __init sb_init(void)
printk(KERN_ERR "sb: Error: At least io, irq, and dma "\ printk(KERN_ERR "sb: Error: At least io, irq, and dma "\
"must be set for legacy cards.\n"); "must be set for legacy cards.\n");
#ifdef CONFIG_PNP_CARD #ifdef CONFIG_PNP
if(pnp) { if(pnp) {
pres = pnpc_register_driver(&sb_pnp_driver); pres = pnp_register_card_driver(&sb_pnp_driver);
} }
#endif #endif
printk(KERN_INFO "sb: Init: Done\n"); printk(KERN_INFO "sb: Init: Done\n");
...@@ -315,8 +315,8 @@ static void __exit sb_exit(void) ...@@ -315,8 +315,8 @@ static void __exit sb_exit(void)
sb_unload(legacy); sb_unload(legacy);
} }
#ifdef CONFIG_PNP_CARD #ifdef CONFIG_PNP
pnpc_unregister_driver(&sb_pnp_driver); pnp_unregister_card_driver(&sb_pnp_driver);
#endif #endif
if (smw_free) { if (smw_free) {
......
...@@ -16,7 +16,7 @@ struct sb_card_config { ...@@ -16,7 +16,7 @@ struct sb_card_config {
int mpu; int mpu;
}; };
#ifdef CONFIG_PNP_CARD #ifdef CONFIG_PNP
/* /*
* SoundBlaster PnP tables and structures. * SoundBlaster PnP tables and structures.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment