public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: jdthood@home.dhs.org (Thomas Hood)
To: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] PnPBIOS 2.4.9-ac1[56] additional fixes
Date: Sun, 30 Sep 2001 13:49:33 -0400 (EDT)	[thread overview]
Message-ID: <20010930174933.03997587@thanatos.toad.net> (raw)

Here are the additional fixes to the PnP BIOS driver, now
appended rather than attached, as per the SubmittingPatches
file.  Applies cleanly against -ac18.


diff -Naur -5 linux-2.4.9-ac16-pnpbiosviaofix/drivers/pnp/pnp_bios.c linux-2.4.9-ac16-pnpbiosfix/drivers/pnp/pnp_bios.c
--- linux-2.4.9-ac16-pnpbiosviaofix/drivers/pnp/pnp_bios.c	Fri Sep 28 22:28:31 2001
+++ linux-2.4.9-ac16-pnpbiosfix/drivers/pnp/pnp_bios.c	Fri Sep 28 23:19:58 2001
@@ -1,11 +1,12 @@
 /*
- * PnP bios services
+ * PnP BIOS services
  * 
  * Originally (C) 1998 Christian Schmidt (chr.schmidt@tu-bs.de)
  * Modifications (c) 1998 Tom Lees <tom@lpsg.demon.co.uk>
  * Minor reorganizations by David Hinds <dahinds@users.sourceforge.net>
+ * More modifications by Thomas Hood <jdthood_AT_yahoo.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2, or (at your option) any
  * later version.
@@ -17,13 +18,12 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- *   Reference:
- *   Compaq Computer Corporation, Phoenix Technologies Ltd., Intel 
- *   Corporation. 
+ *   References:
+ *   Compaq Computer Corporation, Phoenix Technologies Ltd., Intel Corporation
  *   Plug and Play BIOS Specification, Version 1.0A, May 5, 1994
  *   Plug and Play BIOS Clarification Paper, October 6, 1994
  *
  */
 
@@ -46,14 +46,10 @@
 #include <linux/spinlock.h>
 
 /* PnP bios signature: "$PnP" */
 #define PNP_SIGNATURE   (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
 
-extern int is_sony_vaio_laptop;
-
-static void pnpbios_build_devlist(void);
-
 /*
  * This is the standard structure used to identify the entry point
  * to the Plug and Play bios
  */
 #pragma pack(1)
@@ -104,10 +100,11 @@
  * This is the only way to get the bios to return into the kernel code,
  * because the bios code runs in 16 bit protected mode and therefore can only
  * return to the caller if the call is within the first 64kB, and the linux
  * kernel begins at offset 3GB...
  */
+
 asmlinkage void pnp_bios_callfunc(void);
 
 __asm__(
 	".text			\n"
 	__ALIGN_STR "\n"
@@ -129,11 +126,11 @@
 #define Q2_SET_SEL(selname, address, size) \
 set_base (gdt [(selname) >> 3], (u32)(address)); \
 set_limit (gdt [(selname) >> 3], size)
 
 /*
- * Callable Functions
+ * Callable PnP BIOS functions
  */
 #define PNP_GET_NUM_SYS_DEV_NODES       0x00
 #define PNP_GET_SYS_DEV_NODE            0x01
 #define PNP_SET_SYS_DEV_NODE            0x02
 #define PNP_GET_EVENT                   0x03
@@ -147,12 +144,12 @@
 #define PNP_READ_ESCD                   0x42
 #define PNP_WRITE_ESCD                  0x43
 
 
 /*
- *	At some point we want to use this stack frame pointer to unwind
- *	after PnP BIOS oopses. 
+ * At some point we want to use this stack frame pointer to unwind
+ * after PnP BIOS oopses. 
  */
  
 u32 pnp_bios_fault_esp;
 u32 pnp_bios_fault_eip;
 u32 pnp_bios_is_utter_crap = 0;
@@ -169,11 +166,11 @@
 	 *	PnPBIOS is generally not terribly re-entrant.
 	 *	Also don't rely on it to save everything correctly
  	 *
  	 *	On some boxes IRQ's during PnP bios calls seem fatal
 	 */
-	
+
 	if(pnp_bios_is_utter_crap)
 		return PNP_FUNCTION_NOT_SUPPORTED;
 		
 	spin_lock_irqsave(&pnp_bios_lock, flags);
 	__cli();
@@ -218,11 +215,17 @@
 		
 	return status;
 }
 
 /*
- * Call pnp bios with function 0x00, "get number of system device nodes"
+ *
+ * PnP BIOS ACCESS FUNCTIONS
+ *
+ */
+
+/*
+ * Call PnP BIOS with function 0x00, "get number of system device nodes"
  */
 
 int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
 {
 	u16 status;
@@ -232,14 +235,22 @@
 	status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0);
 	data->no_nodes &= 0xff;
 	return status;
 }
 
+/*
+ * Note that some PnP BIOSes (on Sony Vaio laptops) die a horrible
+ * death if they are asked to access the "current" configuration
+ * Therefore, if it's a matter of indifference, it's better to call
+ * get_dev_node() and set_dev_node() with boot=1 rather than with boot=0.
+ */
+
 /* 
- * Call pnp bios with function 0x01, "get system device node"
+ * Call PnP BIOS with function 0x01, "get system device node"
  * Input: *nodenum = desired node, 
- *        boot = whether to get static boot (!=0) or dynamic current (0) config
+ *        boot = whether to get nonvolatile boot (!=0)
+ *               or volatile current (0) config
  * Output: *nodenum=next node or 0xff if no more nodes
  */
 
 int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
 {
@@ -251,13 +262,14 @@
 	status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0);
 	return status;
 }
 
 /*
- * Call pnp bios with function 0x02, "set system device node"
+ * Call PnP BIOS with function 0x02, "set system device node"
  * Input: *nodenum = desired node, 
- *        boot = whether to set static boot (!=0) or dynamic current (0) config
+ *        boot = whether to set nonvolatile boot (!=0)
+ *               or volatile current (0) config
  */
 
 int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
 {
 	u16 status;
@@ -266,15 +278,14 @@
 	Q2_SET_SEL(PNP_TS1, data, /* *((u16 *) data)*/ 65536);
 	status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0);
 	return status;
 }
 
+#if needed
 /*
- * Call pnp bios with function 0x03, "get event"
+ * Call PnP BIOS with function 0x03, "get event"
  */
-#if needed
-
 static int pnp_bios_get_event(u16 *event)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -282,14 +293,14 @@
 	status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0);
 	return status;
 }
 #endif
 
+#if needed
 /* 
- * Call pnp bios with function 0x04, "send message"
+ * Call PnP BIOS with function 0x04, "send message"
  */
-#if needed
 static int pnp_bios_send_message(u16 message)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -298,11 +309,11 @@
 }
 #endif
 
 #ifdef CONFIG_HOTPLUG
 /*
- * Call pnp bios with function 0x05, "get docking station information"
+ * Call PnP BIOS with function 0x05, "get docking station information"
  */
 
 static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
 {
 	u16 status;
@@ -312,15 +323,15 @@
 	status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
 	return status;
 }
 #endif
 
+#if needed
 /*
- * Call pnp bios with function 0x09, "set statically allocated resource
+ * Call PnP BIOS with function 0x09, "set statically allocated resource
  * information"
  */
-#if needed
 static int pnp_bios_set_stat_res(char *info)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -328,15 +339,15 @@
 	status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
 	return status;
 }
 #endif
 
+#if needed
 /*
- * Call pnp bios with function 0x0a, "get statically allocated resource
+ * Call PnP BIOS with function 0x0a, "get statically allocated resource
  * information"
  */
-#if needed
 static int pnp_bios_get_stat_res(char *info)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -344,14 +355,14 @@
 	status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
 	return status;
 }
 #endif
 
+#if needed
 /*
- * Call pnp bios with function 0x0b, "get APM id table"
+ * Call PnP BIOS with function 0x0b, "get APM id table"
  */
-#if needed
 static int pnp_bios_apm_id_table(char *table, u16 *size)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -360,14 +371,14 @@
 	status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0);
 	return status;
 }
 #endif
 
+#if needed
 /*
- * Call pnp bios with function 0x40, "get isa pnp configuration structure"
+ * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
  */
-#if needed
 static int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
@@ -375,14 +386,14 @@
 	status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
 	return status;
 }
 #endif
 
+#if needed
 /*
- * Call pnp bios with function 0x41, "get ESCD info"
+ * Call PnP BIOS with function 0x41, "get ESCD info"
  */
-#if needed
 static int pnp_bios_escd_info(struct escd_info_struc *data)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
@@ -390,15 +401,15 @@
 	status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS);
 	return status;
 }
 #endif
 
+#if needed
 /*
- * Call pnp bios function 0x42, "read ESCD"
+ * Call PnP BIOS function 0x42, "read ESCD"
  * nvram_base is determined by calling escd_info
  */
-#if needed
 static int pnp_bios_read_escd(char *data, u32 nvram_base)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
@@ -408,14 +419,14 @@
 	status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
 	return status;
 }
 #endif
 
+#if needed
 /*
- * Call pnp bios function 0x43, "write ESCD"
+ * Call PnP BIOS function 0x43, "write ESCD"
  */
-#if needed
 static int pnp_bios_write_escd(char *data, u32 nvram_base)
 {
 	u16 status;
 	if (!pnp_bios_present ())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
@@ -425,26 +436,28 @@
 	status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
 	return status;
 }
 #endif
 
-int pnp_bios_present(void)
-{
-	return (pnp_bios_inst_struc != NULL);
-}
-
-#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pnp_bios_dev_node_info);
+EXPORT_SYMBOL(pnp_bios_get_dev_node);
+EXPORT_SYMBOL(pnp_bios_set_dev_node);
 
 /*
- *	Manage PnP docking
+ *
+ * PnP DOCKING FUNCTIONS
+ *
  */
 
+#ifdef CONFIG_HOTPLUG
+
 static int unloading = 0;
+
 static struct completion unload_sem;
 
 /*
- *	Much of this belongs in a shared routine somewhere
+ * (Much of this belongs in a shared routine somewhere)
  */
  
 static int pnp_dock_event(int dock, struct pnp_docking_station_info *info)
 {
 	char *argv [3], **envp, *buf, *scratch;
@@ -496,11 +509,11 @@
 	kfree (envp);
 	return 0;
 }
 
 /*
- *	Poll the PnP docking at a regular interval
+ * Poll the PnP docking at a regular interval
  */
  
 static int pnp_dock_thread(void * unused)
 {
 	static struct pnp_docking_station_info now;
@@ -511,13 +524,12 @@
 	while(!unloading && !signal_pending(current))
 	{
 		int err;
 		
 		/*
-		 *	Poll every 2 seconds
+		 * Poll every 2 seconds
 		 */
-		 
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(HZ*2);
 		if(signal_pending(current))
 			break;
 
@@ -525,11 +537,11 @@
 
 
 		switch(err)
 		{
 			/*
-			 *	No dock to manage
+			 * No dock to manage
 			 */
 			case PNP_FUNCTION_NOT_SUPPORTED:
 				complete_and_exit(&unload_sem, 0);
 			case PNP_SYSTEM_NOT_DOCKED:
 				d = 0;
@@ -553,137 +565,57 @@
 	complete_and_exit(&unload_sem, 0);
 }
 
 #endif
 
-/* 
- * Searches the defined area (0xf0000-0xffff0) for a valid PnP BIOS
- * structure and, if found one, sets up the selectors and entry points
+/*
+ *
+ * NODE DATA HANDLING FUNCTIONS
+ *
  */
 
-static int pnp_bios_disabled;
-static int pnp_bios_dont_use_current_config;
-
-static int disable_pnp_bios(char *str)
-{
-	pnp_bios_disabled=1;
-	return 0;
-}
-
-static int disable_use_of_current_config(char *str)
-{
-	pnp_bios_dont_use_current_config=1;
-	return 0;
-}
-
-__setup("nobiospnp", disable_pnp_bios);
-__setup("nobioscurrpnp", disable_use_of_current_config);
-
-void pnp_bios_init(void)
-{
-	union pnpbios *check;
-	u8 sum;
-	int i, length;
-
-	spin_lock_init(&pnp_bios_lock);
-
-	if(pnp_bios_disabled)
-	{
-		printk(KERN_INFO "PNP BIOS services disabled.\n");
-		return;
-	}
-
-	if ( is_sony_vaio_laptop )
-		pnp_bios_dont_use_current_config = 1;
-
-	for (check = (union pnpbios *) __va(0xf0000);
-	     check < (union pnpbios *) __va(0xffff0);
-	     ((void *) (check)) += 16) {
-		if (check->fields.signature != PNP_SIGNATURE)
-			continue;
-		length = check->fields.length;
-		if (!length)
-			continue;
-		for (sum = 0, i = 0; i < length; i++)
-			sum += check->chars[i];
-		if (sum)
-			continue;
-		if (check->fields.version < 0x10) {
-			printk(KERN_WARNING "PnP: unsupported version %d.%d",
-			       check->fields.version >> 4,
-			       check->fields.version & 15);
-			continue;
-		}
-		printk(KERN_INFO "PnP: PNP BIOS installation structure at 0x%p\n",
-		       check);
-		printk(KERN_INFO "PnP: PNP BIOS version %d.%d, entry at %x:%x, dseg at %x\n",
-                       check->fields.version >> 4, check->fields.version & 15,
-		       check->fields.pm16cseg, check->fields.pm16offset,
-		       check->fields.pm16dseg);
-		Q2_SET_SEL(PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
-		Q_SET_SEL(PNP_CS16, check->fields.pm16cseg, 64 * 1024);
-		Q_SET_SEL(PNP_DS, check->fields.pm16dseg, 64 * 1024);
-		pnp_bios_callpoint.offset = check->fields.pm16offset;
-		pnp_bios_callpoint.segment = PNP_CS16;
-		pnp_bios_inst_struc = check;
-		break;
-	}
-	pnpbios_build_devlist();
-#ifdef CONFIG_PROC_FS
-	pnp_proc_init( pnp_bios_dont_use_current_config );
-#endif
-#ifdef CONFIG_HOTPLUG	
-	init_completion(&unload_sem);
-	if(kernel_thread(pnp_dock_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL)>0)
-		unloading = 0;
-#endif		
-}
-
-#ifdef MODULE
-/* We have to run it early and specifically in non modular.. */
-module_init(pnp_bios_init);
-
-#ifdef CONFIG_HOTPLUG
-static void pnp_bios_exit(void)
-{
-	unloading = 1;
-	wait_for_completion(&unload_sem);
-}
-
-module_exit(pnp_bios_exit);
-#endif
-#endif
-
-EXPORT_SYMBOL(pnp_bios_get_dev_node);
-EXPORT_SYMBOL(pnp_bios_present);
-EXPORT_SYMBOL(pnp_bios_dev_node_info);
-
 static void inline pnpbios_add_irqresource(struct pci_dev *dev, int irq)
 {
+	// Permit irq==-1 which signifies "disabled"
 	int i = 0;
-	while (dev->irq_resource[i].start && i < DEVICE_COUNT_IRQ) i++;
-	if (i < DEVICE_COUNT_IRQ)
+	while (!(dev->irq_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_IRQ) i++;
+	if (i < DEVICE_COUNT_IRQ) {
 		dev->irq_resource[i].start = irq;
+		dev->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
+	}
 }
 
 static void inline pnpbios_add_dmaresource(struct pci_dev *dev, int dma)
 {
+	// Permit dma==-1 which signifies "disabled"
 	int i = 0;
-	while (dev->dma_resource[i].start && i < DEVICE_COUNT_DMA) i++;
-	if (i < DEVICE_COUNT_DMA)
+	while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++;
+	if (i < DEVICE_COUNT_DMA) {
 		dev->dma_resource[i].start = dma;
+		dev->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
+	}
+}
+
+static void __init pnpbios_add_ioresource(struct pci_dev *dev, int io, int len)
+{
+	int i = 0;
+	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
+	if (i < DEVICE_COUNT_RESOURCE) {
+		dev->resource[i].start = io;
+		dev->resource[i].end = io + len;
+		dev->resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
+	}
 }
 
-static void __init pnpbios_add_ioresource(struct pci_dev *dev, int io, 
-					  int len, int flags)
+static void __init pnpbios_add_memresource(struct pci_dev *dev, int io, int len)
 {
 	int i = 0;
-	while (dev->resource[i].start && i < DEVICE_COUNT_RESOURCE) i++;
+	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
 	if (i < DEVICE_COUNT_RESOURCE) {
 		dev->resource[i].start = io;
 		dev->resource[i].end = io + len;
-		dev->resource[i].flags = flags;
+		dev->resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
 	}
 }
 
 static char * __init pnpid32_to_pnpid(u32 id);
 
@@ -691,120 +623,162 @@
  * request I/O ports which are used according to the PnP BIOS
  * to avoid I/O conflicts.
  */
 static void mboard_request(char *pnpid, int io, int len)
 {
-    struct ressource *res;
+	struct resource *res;
     
-    if (0 != strcmp(pnpid,"PNP0c01") &&  /* memory controller */
-	0 != strcmp(pnpid,"PNP0c02"))    /* system peripheral: other */
-	return;
+	if (
+		0 != strcmp(pnpid,"PNP0c01") &&  /* memory controller */
+		0 != strcmp(pnpid,"PNP0c02")     /* system peripheral: other */
+	) {
+		return;
+	}
+
+	if (io < 0x100) {
+		/*
+		 * below 0x100 is only standard PC hardware
+		 * (pics, kbd, timer, dma, ...)
+		 *
+		 * We should not get resource conflicts there,
+		 * and the kernel reserves these anyway
+		 * (see arch/i386/kernel/setup.c).
+		 */
+		return;
+	}
 
-    if (io < 0x100) {
 	/*
-	 * below 0x100 is only standard PC hardware
-	 * (pics, kbd, timer, dma, ...)
+	 * anything else we'll try reserve to avoid these ranges are
+	 * assigned to someone (CardBus bridges for example) and thus are
+	 * triggering resource conflicts.
 	 *
-	 * We should not get ressource conflicts there,
-	 * and the kernel reserves these anyway
-	 * (see arch/i386/kernel/setup.c).
+	 * failures at this point are usually harmless. pci quirks for
+	 * example do reserve stuff they know about too, so we might have
+	 * double reservations here.
 	 */
-	return;
-    }
+	res = request_region(io,len,pnpid);
+	printk("PnPBIOS: %s: request 0x%x-0x%x%s\n",
+		pnpid,io,io+len,NULL != res ? " ok" : "");
 
-    /*
-     * anything else we'll try reserve to avoid these ranges are
-     * assigned to someone (CardBus bridges for example) and thus are
-     * triggering resource conflicts.
-     *
-     * failures at this point are usually harmless. pci quirks for
-     * example do reserve stuff they know about too, so we might have
-     * double reservations here.
-     */
-    res = request_region(io,len,pnpid);
-    printk("PnPBIOS: %s: request 0x%x-0x%x%s\n",
-	   pnpid,io,io+len,NULL != res ? " ok" : "");
+	return;
 }
 
 /* parse PNPBIOS "Allocated Resources Block" and fill IO,IRQ,DMA into pci_dev */
-static void __init pnpbios_rawdata_2_pci_dev(struct pnp_bios_node *node, struct pci_dev *pci_dev)
+static void __init pnpbios_rawdata_2_pci_dev(struct pnp_bios_node *node, struct pci_dev *dev)
 {
 	unsigned char *p = node->data, *lastp=NULL;
-        int mask,i,io,irq,len,dma;
+	int i;
 
-	memset(pci_dev, 0, sizeof(struct pci_dev));
+	/*
+	 * First, set dev contents to default values
+	 */
+	memset(dev,0,sizeof(struct pci_dev));
+	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
+	/*	dev->resource[i].start = 0; */
+		dev->resource[i].flags = IORESOURCE_UNSET;
+	}
+	for (i=0;i<DEVICE_COUNT_IRQ;i++) {
+		dev->irq_resource[i].start = (unsigned long)-1;  // "disabled"
+		dev->irq_resource[i].flags = IORESOURCE_UNSET;
+	}
+	for (i=0;i<DEVICE_COUNT_DMA;i++) {
+		dev->dma_resource[i].start = (unsigned long)-1;  // "disabled"
+		dev->dma_resource[i].flags = IORESOURCE_UNSET;
+	}
+
+	/*
+	 * Fill in dev info
+	 */
         while ( (char *)p < ((char *)node->data + node->size )) {
         	if(p==lastp) break;
 
                 if( p[0] & 0x80 ) {// large item
 			switch (p[0] & 0x7f) {
 			case 0x01: // memory
-				io = *(short *) &p[4];
-				len = *(short *) &p[10];
-				pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_MEM);
+			{
+				int io = *(short *) &p[4];
+				int len = *(short *) &p[10];
+				pnpbios_add_memresource(dev, io, len);
 				break;
+			}
 			case 0x02: // device name
-				len = *(short *) &p[1];
-				memcpy(pci_dev->name, p + 3, len >= 80 ? 79 : len);
+			{
+				int len = *(short *) &p[1];
+				memcpy(dev->name, p + 3, len >= 80 ? 79 : len);
 				break;
+			}
 			case 0x05: // 32-bit memory
-				io = *(int *) &p[4];
-				len = *(int *) &p[16];
-				pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_MEM);
+			{
+				int io = *(int *) &p[4];
+				int len = *(int *) &p[16];
+				pnpbios_add_memresource(dev, io, len);
 				break;
+			}
 			case 0x06: // fixed location 32-bit memory
-				io = *(int *) &p[4];
-				len = *(int *) &p[8];
-				pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_MEM);
+			{
+				int io = *(int *) &p[4];
+				int len = *(int *) &p[8];
+				pnpbios_add_memresource(dev, io, len);
 				break;
 			}
+			} /* switch */
                         lastp = p+3;
                         p = p + p[1] + p[2]*256 + 3;
                         continue;
                 }
                 if ((p[0]>>3) == 0x0f) // end tag
                         break;
                 switch (p[0]>>3) {
                 case 0x04: // irq
-                        irq = -1;
+                {
+                        int i, mask, irq = -1; // "disabled"
                         mask= p[1] + p[2]*256;
                         for (i=0;i<16;i++, mask=mask>>1)
-                                if(mask &0x01) irq=i;
-			pnpbios_add_irqresource(pci_dev, irq);
+                                if(mask & 0x01) irq=i;
+			pnpbios_add_irqresource(dev, irq);
                         break;
+                }
                 case 0x05: // dma
-                        dma = -1;
+                {
+                        int i, mask, dma = -1; // "disabled"
                         mask = p[1];
                         for (i=0;i<8;i++, mask = mask>>1)
-                                if(mask&0x01) dma=i;
-			pnpbios_add_dmaresource(pci_dev, dma);
+                                if(mask & 0x01) dma=i;
+			pnpbios_add_dmaresource(dev, dma);
                         break;
+                }
                 case 0x08: // io
-			io= p[2] + p[3] *256;
-			len = p[7];
-			pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_IO);
+                {
+			int io= p[2] + p[3] *256;
+			int len = p[7];
+			pnpbios_add_ioresource(dev, io, len);
 			mboard_request(pnpid32_to_pnpid(node->eisa_id),io,len);
                         break;
+                }
 		case 0x09: // fixed location io
-			io = p[1] + p[2] * 256;
-			len = p[3];
-			pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_IO);
+		{
+			int io = p[1] + p[2] * 256;
+			int len = p[3];
+			pnpbios_add_ioresource(dev, io, len);
 			break;
-                }
+		}
+                } /* switch */
                 lastp=p+1;
                 p = p + (p[0] & 0x07) + 1;
 
-        }
+        } /* while */
+
+        return;
 }
 
 #define HEX(id,a) hex[((id)>>a) & 15]
 #define CHAR(id,a) (0x40 + (((id)>>a) & 31))
 
 static char * __init pnpid32_to_pnpid(u32 id)
 {
 	const char *hex = "0123456789abcdef";
-        static char str[8];
+	static char str[8];
 	id = be32_to_cpu(id);
 	str[0] = CHAR(id, 26);
 	str[1] = CHAR(id, 21);
 	str[2] = CHAR(id,16);
 	str[3] = HEX(id, 12);
@@ -817,15 +791,24 @@
 
 #undef CHAR
 #undef HEX  
 
 /*
- *	PnPBIOS public device management layer
+ *
+ * PnP BIOS PUBLIC DEVICE MANAGEMENT LAYER FUNCTIONS
+ *
  */
 
 static LIST_HEAD(pnpbios_devices);
 
+int pnp_bios_present(void)
+{
+	return (pnp_bios_inst_struc != NULL);
+}
+
+EXPORT_SYMBOL(pnp_bios_present);
+
 static int __init pnpbios_insert_device(struct pci_dev *dev)
 {
 	/* FIXME: Need to check for re-add of existing node */
 	list_add_tail(&dev->global_list, &pnpbios_devices);
 	return 0;
@@ -835,70 +818,70 @@
  *	Build the list of pci_dev objects from the PnP table
  */
  
 static void __init pnpbios_build_devlist(void)
 {
-	int i, devs = 0;
+	int i;
+	int nodenum;
+	int nodes_got = 0;
 	struct pnp_bios_node *node;
-        struct pnp_dev_node_info node_info;
+	struct pnp_dev_node_info node_info;
 	struct pci_dev *dev;
-	int num;
 	char *pnpid;
 
 	
-        if (!pnp_bios_present ())
-                return;
+	if (!pnp_bios_present ())
+		return;
 
-        if (pnp_bios_dev_node_info(&node_info) != 0)
-                return;
+	if (pnp_bios_dev_node_info(&node_info) != 0)
+		return;
 
-        node = kmalloc(node_info.max_node_size, GFP_KERNEL);
-        if (!node)
-                return;
+	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
+	if (!node)
+		return;
 
-	for(i=0;i<0xff;i++) {
+	for(i=0,nodenum=0;i<0xff && nodenum!=0xff;i++) {
+		int thisnodenum = nodenum;
+		if (pnp_bios_get_dev_node((u8 *)&nodenum, (char )1 , node))
+			continue;
+		nodes_got++;
 		dev =  kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
 		if (!dev)
 			break;
-
-		// For now we scan the "boot" config because some BIOSes
-		// oops when their "current" configs are accessed
-                if (pnp_bios_get_dev_node((u8 *)&num, (char )1 , node))
-			continue;
-
-		devs++;
 		pnpbios_rawdata_2_pci_dev(node,dev);
-		dev->devfn=num;
+		dev->devfn=thisnodenum;
 		pnpid = pnpid32_to_pnpid(node->eisa_id);
 		memcpy(dev->name,"PNPBIOS",8);
 		memcpy(dev->slot_name,pnpid,8);
 		if(pnpbios_insert_device(dev)<0)
 			kfree(dev);
 	}
 	kfree(node);
 
-	if (devs)
-		printk(KERN_INFO "PnP: %i device%s detected total\n", devs, devs > 1 ? "s" : "");
-	else
-		printk(KERN_INFO "PnP: No devices found\n");
+	printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS\n", nodes_got, nodes_got != 1 ? "s" : "");
 }
 
 
 /*
- *	The public interface to PnP BIOS enumeration
+ *
+ * PUBLIC INTERFACE FUNCTIONS to PnP BIOS ENUMERATION
+ *
+ */
+
+/*
+ * Find device in list
  */
- 
 struct pci_dev *pnpbios_find_device(char *pnpid, struct pci_dev *prev)
 {
 	struct pci_dev *dev;
 	int num;
 
 	if(prev==NULL)
 		num=0; /* Start from beginning */
 	else
 		num=prev->devfn + 1; /* Encode node number here */
-	
+
 
 	pnpbios_for_each_dev(dev)
 	{
 		if(dev->devfn >= num)
 		{
@@ -1017,6 +1000,108 @@
 	}
 }
 
 EXPORT_SYMBOL(pnpbios_unregister_driver);
 
+/* 
+ *
+ * INIT AND EXIT
+ *
+ *
+ * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS
+ * structure and, if one is found, sets up the selectors and
+ * entry points
+ */
+
+extern int is_sony_vaio_laptop;
+
+static int pnp_bios_disabled;
+static int pnp_bios_dont_use_current_config;
+
+static int disable_pnp_bios(char *str)
+{
+	pnp_bios_disabled=1;
+	return 0;
+}
+
+static int disable_use_of_current_config(char *str)
+{
+	pnp_bios_dont_use_current_config=1;
+	return 0;
+}
+
+__setup("nobiospnp", disable_pnp_bios);
+__setup("nobioscurrpnp", disable_use_of_current_config);
+
+void pnp_bios_init(void)
+{
+	union pnpbios *check;
+	u8 sum;
+	int i, length;
+
+	spin_lock_init(&pnp_bios_lock);
+
+	if(pnp_bios_disabled) {
+		printk(KERN_INFO "PnPBIOS: driver disabled.\n");
+		return;
+	}
+
+	if ( is_sony_vaio_laptop )
+		pnp_bios_dont_use_current_config = 1;
+
+	for (check = (union pnpbios *) __va(0xf0000);
+	     check < (union pnpbios *) __va(0xffff0);
+	     ((void *) (check)) += 16) {
+		if (check->fields.signature != PNP_SIGNATURE)
+			continue;
+		length = check->fields.length;
+		if (!length)
+			continue;
+		for (sum = 0, i = 0; i < length; i++)
+			sum += check->chars[i];
+		if (sum)
+			continue;
+		if (check->fields.version < 0x10) {
+			printk(KERN_WARNING "PnPBIOS: unsupported version %d.%d",
+			       check->fields.version >> 4,
+			       check->fields.version & 15);
+			continue;
+		}
+		printk(KERN_INFO "PnPBIOS: PnP BIOS installation structure at 0x%p\n",
+		       check);
+		printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry at 0x%x:0x%x, dseg at 0x%x\n",
+                       check->fields.version >> 4, check->fields.version & 15,
+		       check->fields.pm16cseg, check->fields.pm16offset,
+		       check->fields.pm16dseg);
+		Q2_SET_SEL(PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
+		Q_SET_SEL(PNP_CS16, check->fields.pm16cseg, 64 * 1024);
+		Q_SET_SEL(PNP_DS, check->fields.pm16dseg, 64 * 1024);
+		pnp_bios_callpoint.offset = check->fields.pm16offset;
+		pnp_bios_callpoint.segment = PNP_CS16;
+		pnp_bios_inst_struc = check;
+		break;
+	}
+	pnpbios_build_devlist();
+#ifdef CONFIG_PROC_FS
+	pnp_proc_init( pnp_bios_dont_use_current_config );
+#endif
+#ifdef CONFIG_HOTPLUG	
+	init_completion(&unload_sem);
+	if(kernel_thread(pnp_dock_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL)>0)
+		unloading = 0;
+#endif		
+}
 
+#ifdef MODULE
+/* We have to run it early and specifically in non modular.. */
+module_init(pnp_bios_init);
+
+#ifdef CONFIG_HOTPLUG
+static void pnp_bios_exit(void)
+{
+	unloading = 1;
+	wait_for_completion(&unload_sem);
+}
+
+module_exit(pnp_bios_exit);
+#endif
+#endif
diff -Naur -5 linux-2.4.9-ac16-pnpbiosviaofix/drivers/pnp/pnp_proc.c linux-2.4.9-ac16-pnpbiosfix/drivers/pnp/pnp_proc.c
--- linux-2.4.9-ac16-pnpbiosviaofix/drivers/pnp/pnp_proc.c	Fri Sep 28 22:28:31 2001
+++ linux-2.4.9-ac16-pnpbiosfix/drivers/pnp/pnp_proc.c	Fri Sep 28 23:07:53 2001
@@ -18,64 +18,65 @@
 static struct proc_dir_entry *proc_pnp = NULL;
 static struct proc_dir_entry *proc_pnp_boot = NULL;
 static struct pnp_dev_node_info node_info;
 
 static int proc_read_devices(char *buf, char **start, off_t pos,
-			     int count, int *eof, void *data)
+                             int count, int *eof, void *data)
 {
 	struct pnp_bios_node *node;
-	u8 num;
+	int i;
+	u8 nodenum;
 	char *p = buf;
 
 	if (pos != 0) {
 	    *eof = 1;
 	    return 0;
 	}
 	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	for (num = 0; num != 0xff; ) {
-		pnp_bios_get_dev_node(&num, 1, node);
+	for (i=0,nodenum=0;i<0xff && nodenum!=0xff; i++) {
+		pnp_bios_get_dev_node(&nodenum, 1, node);
 		p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
 			     node->handle, node->eisa_id,
 			     node->type_code[0], node->type_code[1],
 			     node->type_code[2], node->flags);
 	}
 	kfree(node);
 	return (p-buf);
 }
 
 static int proc_read_node(char *buf, char **start, off_t pos,
-			  int count, int *eof, void *data)
+                          int count, int *eof, void *data)
 {
 	struct pnp_bios_node *node;
 	int boot = (long)data >> 8;
-	u8 num = (long)data;
+	u8 nodenum = (long)data;
 	int len;
 
 	if (pos != 0) {
 	    *eof = 1;
 	    return 0;
 	}
 	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	pnp_bios_get_dev_node(&num, boot, node);
+	pnp_bios_get_dev_node(&nodenum, boot, node);
 	len = node->size - sizeof(struct pnp_bios_node);
 	memcpy(buf, node->data, len);
 	kfree(node);
 	return len;
 }
 
 static int proc_write_node(struct file *file, const char *buf,
-			   unsigned long count, void *data)
+                           unsigned long count, void *data)
 {
 	struct pnp_bios_node *node;
 	int boot = (long)data >> 8;
-	u8 num = (long)data;
+	u8 nodenum = (long)data;
 
 	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	pnp_bios_get_dev_node(&num, boot, node);
+	pnp_bios_get_dev_node(&nodenum, boot, node);
 	if (count != node->size - sizeof(struct pnp_bios_node))
 		return -EINVAL;
 	memcpy(node->data, buf, count);
 	if (pnp_bios_set_dev_node(node->handle, boot, node) != 0)
 	    return -EINVAL;
@@ -88,33 +89,31 @@
 void pnp_proc_init( int dont_use_current )
 {
 	struct pnp_bios_node *node;
 	struct proc_dir_entry *ent;
 	char name[3];
-	u8 num;
+	int i;
+	u8 nodenum;
 
 	pnp_proc_dont_use_current_config = dont_use_current;
 
 	if (!pnp_bios_present()) return;
-	if (pnp_bios_dev_node_info(&node_info) != 0)
-		return;
+	if (pnp_bios_dev_node_info(&node_info) != 0) return;
 	
 	proc_pnp = proc_mkdir("pnp", proc_bus);
 	if (!proc_pnp) return;
 	proc_pnp_boot = proc_mkdir("boot", proc_pnp);
 	if (!proc_pnp_boot) return;
-	create_proc_read_entry("devices", 0, proc_pnp,
-			       proc_read_devices, NULL);
+	create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL);
 	
 	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return;
-	for (num = 0; num != 0xff; ) {
-		//sprintf(name, "%02x", num);
-		if (pnp_bios_get_dev_node(&num, 1, node) != 0)
+	for (i=0,nodenum = 0; i<0xff && nodenum != 0xff; i++) {
+		if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0)
 			break;
 		sprintf(name, "%02x", node->handle);
-		if ( !dont_use_current ) {
+		if ( !pnp_proc_dont_use_current_config ) {
 			ent = create_proc_entry(name, 0, proc_pnp);
 			if (ent) {
 				ent->read_proc = proc_read_node;
 				ent->write_proc = proc_write_node;
 				ent->data = (void *)(long)(node->handle);
@@ -130,16 +129,17 @@
 	kfree(node);
 }
 
 void pnp_proc_done(void)
 {
-	u8 num;
+	int i;
 	char name[3];
 	
 	if (!proc_pnp) return;
-	for (num = 0; num != 0xff; num++) {
-		sprintf(name, "%02x", num);
+
+	for (i=0; i<0xff; i++) {
+		sprintf(name, "%02x", i);
 		if ( !pnp_proc_dont_use_current_config )
 			remove_proc_entry(name, proc_pnp);
 		remove_proc_entry(name, proc_pnp_boot);
 	}
 	remove_proc_entry("boot", proc_pnp);

             reply	other threads:[~2001-09-30 17:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-09-30 17:49 Thomas Hood [this message]
2001-09-30 18:01 ` [PATCH] PnPBIOS 2.4.9-ac1[56] additional fixes Alan Cox
  -- strict thread matches above, loose matches on Subject: below --
2001-09-29  3:51 Thomas Hood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20010930174933.03997587@thanatos.toad.net \
    --to=jdthood@home.dhs.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox