Commit 65e6aacc authored by Dave Jones's avatar Dave Jones Committed by Linus Torvalds

[PATCH] ISAPNP updates.

From 2.4, these diffs..
- Make use of dma channel 0 configurable
- request region cleanup
- fix list initialisation bug
- fix escd /proc security hole
- add opl3sax quirk
parent 6b1ad46e
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
* 2001-11-07 Added isapnp_{,un}register_driver calls along the lines * 2001-11-07 Added isapnp_{,un}register_driver calls along the lines
* of the pci driver interface * of the pci driver interface
* Kai Germaschewski <kai.germaschewski@gmx.de> * Kai Germaschewski <kai.germaschewski@gmx.de>
* 2002-06-06 Made the use of dma channel 0 configurable
* Gerald Teschl <gerald.teschl@univie.ac.at>
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -56,13 +58,10 @@ LIST_HEAD(isapnp_devices); ...@@ -56,13 +58,10 @@ LIST_HEAD(isapnp_devices);
#define ISAPNP_DEBUG #define ISAPNP_DEBUG
#endif #endif
struct resource *pidxr_res;
struct resource *pnpwrp_res;
struct resource *isapnp_rdp_res;
int isapnp_disable; /* Disable ISA PnP */ int isapnp_disable; /* Disable ISA PnP */
int isapnp_rdp; /* Read Data Port */ int isapnp_rdp; /* Read Data Port */
int isapnp_reset = 1; /* reset all PnP cards (deactivate) */ int isapnp_reset = 1; /* reset all PnP cards (deactivate) */
int isapnp_allow_dma0 = -1; /* allow dma 0 during auto activation: -1=off (:default), 0=off (set by user), 1=on */
int isapnp_skip_pci_scan; /* skip PCI resource scanning */ int isapnp_skip_pci_scan; /* skip PCI resource scanning */
int isapnp_verbose = 1; /* verbose mode */ int isapnp_verbose = 1; /* verbose mode */
int isapnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */ int isapnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
...@@ -78,6 +77,8 @@ MODULE_PARM(isapnp_rdp, "i"); ...@@ -78,6 +77,8 @@ MODULE_PARM(isapnp_rdp, "i");
MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port"); MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
MODULE_PARM(isapnp_reset, "i"); MODULE_PARM(isapnp_reset, "i");
MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards"); MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
MODULE_PARM(isapnp_allow_dma0, "i");
MODULE_PARM_DESC(isapnp_allow_dma0, "Allow dma value 0 during auto activation");
MODULE_PARM(isapnp_skip_pci_scan, "i"); MODULE_PARM(isapnp_skip_pci_scan, "i");
MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning"); MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
MODULE_PARM(isapnp_verbose, "i"); MODULE_PARM(isapnp_verbose, "i");
...@@ -1762,13 +1763,14 @@ static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx) ...@@ -1762,13 +1763,14 @@ static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx)
static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx) static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
{ {
int i; int i, mindma =1;
struct pci_dev *dev; struct pci_dev *dev;
/* Some machines allow DMA 0, but others don't. In fact on some /* Some machines allow DMA 0, but others don't. In fact on some
boxes DMA 0 is the memory refresh. Play safe */ boxes DMA 0 is the memory refresh. Play safe */
if (isapnp_allow_dma0 == 1)
if (dma < 1 || dma == 4 || dma > 7) mindma = 0;
if (dma < mindma || dma == 4 || dma > 7)
return 1; return 1;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
if (isapnp_reserve_dma[i] == dma) if (isapnp_reserve_dma[i] == dma)
...@@ -2150,19 +2152,13 @@ static void isapnp_free_card(struct pci_bus *card) ...@@ -2150,19 +2152,13 @@ static void isapnp_free_card(struct pci_bus *card)
kfree(card); kfree(card);
} }
#endif /* MODULE */
static void isapnp_free_all_resources(void) static void isapnp_free_all_resources(void)
{ {
#ifdef ISAPNP_REGION_OK #ifdef ISAPNP_REGION_OK
if (pidxr_res) release_region(_PIDXR, 1);
release_resource(pidxr_res);
#endif #endif
if (pnpwrp_res) release_region(_PNPWRP, 1);
release_resource(pnpwrp_res); release_region(isapnp_rdp, 1);
if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff && isapnp_rdp_res)
release_resource(isapnp_rdp_res);
#ifdef MODULE
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
isapnp_proc_done(); isapnp_proc_done();
#endif #endif
...@@ -2171,9 +2167,10 @@ static void isapnp_free_all_resources(void) ...@@ -2171,9 +2167,10 @@ static void isapnp_free_all_resources(void)
list_del(list); list_del(list);
isapnp_free_card(pci_bus_b(list)); isapnp_free_card(pci_bus_b(list));
} }
#endif
} }
#endif /* MODULE */
static int isapnp_announce_device(struct isapnp_driver *drv, static int isapnp_announce_device(struct isapnp_driver *drv,
struct pci_dev *dev) struct pci_dev *dev)
{ {
...@@ -2290,6 +2287,8 @@ static inline int isapnp_init_device_tree(void) ...@@ -2290,6 +2287,8 @@ static inline int isapnp_init_device_tree(void)
struct pci_bus *card; struct pci_bus *card;
struct pci_dev *parent = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); struct pci_dev *parent = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL);
INIT_LIST_HEAD(&isapnp_device_driver.devices);
isapnp_for_each_card(card) { isapnp_for_each_card(card) {
struct list_head *devlist; struct list_head *devlist;
...@@ -2327,14 +2326,12 @@ int __init isapnp_init(void) ...@@ -2327,14 +2326,12 @@ int __init isapnp_init(void)
return 0; return 0;
} }
#ifdef ISAPNP_REGION_OK #ifdef ISAPNP_REGION_OK
pidxr_res=request_region(_PIDXR, 1, "isapnp index"); if (!request_region(_PIDXR, 1, "isapnp index")) {
if(!pidxr_res) {
printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR); printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR);
return -EBUSY; return -EBUSY;
} }
#endif #endif
pnpwrp_res=request_region(_PNPWRP, 1, "isapnp write"); if (!request_region(_PNPWRP, 1, "isapnp write")) {
if(!pnpwrp_res) {
printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP); printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP);
#ifdef ISAPNP_REGION_OK #ifdef ISAPNP_REGION_OK
release_region(_PIDXR, 1); release_region(_PIDXR, 1);
...@@ -2350,13 +2347,12 @@ int __init isapnp_init(void) ...@@ -2350,13 +2347,12 @@ int __init isapnp_init(void)
printk(KERN_INFO "isapnp: Scanning for PnP cards...\n"); printk(KERN_INFO "isapnp: Scanning for PnP cards...\n");
if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) { if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {
isapnp_rdp |= 3; isapnp_rdp |= 3;
isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read"); if (!request_region(isapnp_rdp, 1, "isapnp read")) {
if(!isapnp_rdp_res) {
printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp); printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);
#ifdef ISAPNP_REGION_OK #ifdef ISAPNP_REGION_OK
release_region(_PIDXR, 1); release_region(_PIDXR, 1);
#endif #endif
release_region(isapnp_rdp, 1); release_region(_PNPWRP, 1);
return -EBUSY; return -EBUSY;
} }
isapnp_set_rdp(); isapnp_set_rdp();
...@@ -2366,12 +2362,15 @@ int __init isapnp_init(void) ...@@ -2366,12 +2362,15 @@ int __init isapnp_init(void)
cards = isapnp_isolate(); cards = isapnp_isolate();
if (cards < 0 || if (cards < 0 ||
(isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) { (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {
isapnp_free_all_resources(); #ifdef ISAPNP_REGION_OK
release_region(_PIDXR, 1);
#endif
release_region(_PNPWRP, 1);
isapnp_detected = 0; isapnp_detected = 0;
printk(KERN_INFO "isapnp: No Plug & Play device found\n"); printk(KERN_INFO "isapnp: No Plug & Play device found\n");
return 0; return 0;
} }
isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read"); request_region(isapnp_rdp, 1, "isapnp read");
} }
isapnp_build_device_list(); isapnp_build_device_list();
cards = 0; cards = 0;
......
...@@ -951,6 +951,22 @@ static void isapnp_set_dmaresource(struct resource *res, int dma) ...@@ -951,6 +951,22 @@ static void isapnp_set_dmaresource(struct resource *res, int dma)
res->flags = IORESOURCE_DMA; res->flags = IORESOURCE_DMA;
} }
extern int isapnp_allow_dma0;
static int isapnp_set_allow_dma0(char *line)
{
int i;
char value[32];
isapnp_get_str(value, line, sizeof(value));
i = simple_strtoul(value, NULL, 0);
if (i < 0 || i > 1) {
printk("isapnp: wrong value %i for allow_dma0\n", i);
return 1;
}
isapnp_allow_dma0 = i;
return 0;
}
static int isapnp_set_dma(char *line) static int isapnp_set_dma(char *line)
{ {
int idx, dma; int idx, dma;
...@@ -1036,6 +1052,8 @@ static int isapnp_decode_line(char *line) ...@@ -1036,6 +1052,8 @@ static int isapnp_decode_line(char *line)
char cmd[32]; char cmd[32];
line = isapnp_get_str(cmd, line, sizeof(cmd)); line = isapnp_get_str(cmd, line, sizeof(cmd));
if (!strcmp(cmd, "allow_dma0"))
return isapnp_set_allow_dma0(line);
if (!strcmp(cmd, "card")) if (!strcmp(cmd, "card"))
return isapnp_set_card(line); return isapnp_set_card(line);
if (!strcmp(cmd, "csn")) if (!strcmp(cmd, "csn"))
......
...@@ -218,7 +218,7 @@ int __init pnpbios_proc_init( void ) ...@@ -218,7 +218,7 @@ int __init pnpbios_proc_init( void )
create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL); create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL);
create_proc_read_entry("configuration_info", 0, proc_pnp, proc_read_pnpconfig, NULL); create_proc_read_entry("configuration_info", 0, proc_pnp, proc_read_pnpconfig, NULL);
create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, NULL); create_proc_read_entry("escd_info", 0, proc_pnp, proc_read_escdinfo, NULL);
create_proc_read_entry("escd", 0, proc_pnp, proc_read_escd, NULL); create_proc_read_entry("escd", S_IRUSR, proc_pnp, proc_read_escd, NULL);
create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL); create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL);
node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL); node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
......
...@@ -102,6 +102,28 @@ static void __init quirk_sb16audio_resources(struct pci_dev *dev) ...@@ -102,6 +102,28 @@ static void __init quirk_sb16audio_resources(struct pci_dev *dev)
return; return;
} }
extern int isapnp_allow_dma0;
static void __init quirk_opl3sax_resources(struct pci_dev *dev)
{
/* This really isn't a device quirk but isapnp core code
* doesn't allow a DMA channel of 0, afflicted card is an
* OPL3Sax where x=4.
*/
struct isapnp_resources *res;
int max;
res = (struct isapnp_resources *)dev->sysdata;
max = res->dma->map;
for (res = res->alt; res; res = res->alt) {
if (res->dma->map > max)
max = res->dma->map;
}
if (max == 1 && isapnp_allow_dma0 == -1) {
printk(KERN_INFO "isapnp: opl3sa4 quirk: Allowing dma 0.\n");
isapnp_allow_dma0 = 1;
}
return;
}
/* /*
* ISAPnP Quirks * ISAPnP Quirks
* Cards or devices that need some tweaking due to broken hardware * Cards or devices that need some tweaking due to broken hardware
...@@ -133,6 +155,8 @@ static struct isapnp_fixup isapnp_fixups[] __initdata = { ...@@ -133,6 +155,8 @@ static struct isapnp_fixup isapnp_fixups[] __initdata = {
quirk_sb16audio_resources }, quirk_sb16audio_resources },
{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045), { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
quirk_sb16audio_resources }, quirk_sb16audio_resources },
{ ISAPNP_VENDOR('Y','M','H'), ISAPNP_DEVICE(0x0021),
quirk_opl3sax_resources },
{ 0 } { 0 }
}; };
......
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