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 @@
* 2001-11-07 Added isapnp_{,un}register_driver calls along the lines
* of the pci driver interface
* 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>
......@@ -56,13 +58,10 @@ LIST_HEAD(isapnp_devices);
#define ISAPNP_DEBUG
#endif
struct resource *pidxr_res;
struct resource *pnpwrp_res;
struct resource *isapnp_rdp_res;
int isapnp_disable; /* Disable ISA PnP */
int isapnp_rdp; /* Read Data Port */
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_verbose = 1; /* verbose mode */
int isapnp_reserve_irq[16] = { [0 ... 15] = -1 }; /* reserve (don't use) some IRQ */
......@@ -78,6 +77,8 @@ MODULE_PARM(isapnp_rdp, "i");
MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
MODULE_PARM(isapnp_reset, "i");
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_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
MODULE_PARM(isapnp_verbose, "i");
......@@ -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)
{
int i;
int i, mindma =1;
struct pci_dev *dev;
/* Some machines allow DMA 0, but others don't. In fact on some
boxes DMA 0 is the memory refresh. Play safe */
if (dma < 1 || dma == 4 || dma > 7)
if (isapnp_allow_dma0 == 1)
mindma = 0;
if (dma < mindma || dma == 4 || dma > 7)
return 1;
for (i = 0; i < 8; i++) {
if (isapnp_reserve_dma[i] == dma)
......@@ -2150,19 +2152,13 @@ static void isapnp_free_card(struct pci_bus *card)
kfree(card);
}
#endif /* MODULE */
static void isapnp_free_all_resources(void)
{
#ifdef ISAPNP_REGION_OK
if (pidxr_res)
release_resource(pidxr_res);
release_region(_PIDXR, 1);
#endif
if (pnpwrp_res)
release_resource(pnpwrp_res);
if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff && isapnp_rdp_res)
release_resource(isapnp_rdp_res);
#ifdef MODULE
release_region(_PNPWRP, 1);
release_region(isapnp_rdp, 1);
#ifdef CONFIG_PROC_FS
isapnp_proc_done();
#endif
......@@ -2171,9 +2167,10 @@ static void isapnp_free_all_resources(void)
list_del(list);
isapnp_free_card(pci_bus_b(list));
}
#endif
}
#endif /* MODULE */
static int isapnp_announce_device(struct isapnp_driver *drv,
struct pci_dev *dev)
{
......@@ -2290,6 +2287,8 @@ static inline int isapnp_init_device_tree(void)
struct pci_bus *card;
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) {
struct list_head *devlist;
......@@ -2327,14 +2326,12 @@ int __init isapnp_init(void)
return 0;
}
#ifdef ISAPNP_REGION_OK
pidxr_res=request_region(_PIDXR, 1, "isapnp index");
if(!pidxr_res) {
if (!request_region(_PIDXR, 1, "isapnp index")) {
printk(KERN_ERR "isapnp: Index Register 0x%x already used\n", _PIDXR);
return -EBUSY;
}
#endif
pnpwrp_res=request_region(_PNPWRP, 1, "isapnp write");
if(!pnpwrp_res) {
if (!request_region(_PNPWRP, 1, "isapnp write")) {
printk(KERN_ERR "isapnp: Write Data Register 0x%x already used\n", _PNPWRP);
#ifdef ISAPNP_REGION_OK
release_region(_PIDXR, 1);
......@@ -2350,13 +2347,12 @@ int __init isapnp_init(void)
printk(KERN_INFO "isapnp: Scanning for PnP cards...\n");
if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {
isapnp_rdp |= 3;
isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");
if(!isapnp_rdp_res) {
if (!request_region(isapnp_rdp, 1, "isapnp read")) {
printk(KERN_ERR "isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);
#ifdef ISAPNP_REGION_OK
release_region(_PIDXR, 1);
#endif
release_region(isapnp_rdp, 1);
release_region(_PNPWRP, 1);
return -EBUSY;
}
isapnp_set_rdp();
......@@ -2366,12 +2362,15 @@ int __init isapnp_init(void)
cards = isapnp_isolate();
if (cards < 0 ||
(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;
printk(KERN_INFO "isapnp: No Plug & Play device found\n");
return 0;
}
isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");
request_region(isapnp_rdp, 1, "isapnp read");
}
isapnp_build_device_list();
cards = 0;
......
......@@ -950,6 +950,22 @@ static void isapnp_set_dmaresource(struct resource *res, int dma)
res->start = res->end = 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)
{
......@@ -1036,6 +1052,8 @@ static int isapnp_decode_line(char *line)
char cmd[32];
line = isapnp_get_str(cmd, line, sizeof(cmd));
if (!strcmp(cmd, "allow_dma0"))
return isapnp_set_allow_dma0(line);
if (!strcmp(cmd, "card"))
return isapnp_set_card(line);
if (!strcmp(cmd, "csn"))
......
......@@ -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("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", 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);
node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
......
......@@ -102,6 +102,28 @@ static void __init quirk_sb16audio_resources(struct pci_dev *dev)
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
* Cards or devices that need some tweaking due to broken hardware
......@@ -133,6 +155,8 @@ static struct isapnp_fixup isapnp_fixups[] __initdata = {
quirk_sb16audio_resources },
{ ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0045),
quirk_sb16audio_resources },
{ ISAPNP_VENDOR('Y','M','H'), ISAPNP_DEVICE(0x0021),
quirk_opl3sax_resources },
{ 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