All of lore.kernel.org
 help / color / mirror / Atom feed
From: Adam Belay <ambx1@neo.rr.com>
To: linux-kernel@vger.kernel.org
Subject: Re: [PATCH] PnP Updates for 2.6.0-test2
Date: Tue, 5 Aug 2003 22:17:03 +0000	[thread overview]
Message-ID: <20030805221703.GF13275@neo.rr.com> (raw)
In-Reply-To: <20030805221415.GB13275@neo.rr.com>

# --------------------------------------------
# 03/08/05	ambx1@neo.rr.com	1.1111
# [PNPBIOS] Move low level code into a separate file
# 
# This patch moves the low level bios calls to a separate file, 
# "bioscalls.c".  It is a cleanup that will improve organization of the
# pnpbios driver code.
# --------------------------------------------
#
diff -Nru a/drivers/pnp/pnpbios/Makefile b/drivers/pnp/pnpbios/Makefile
--- a/drivers/pnp/pnpbios/Makefile	Tue Aug  5 21:24:45 2003
+++ b/drivers/pnp/pnpbios/Makefile	Tue Aug  5 21:24:45 2003
@@ -4,4 +4,4 @@
 
 pnpbios-proc-$(CONFIG_PROC_FS) = proc.o
 
-obj-y := core.o rsparser.o $(pnpbios-proc-y)
+obj-y := core.o bioscalls.o rsparser.o $(pnpbios-proc-y)
diff -Nru a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/pnp/pnpbios/bioscalls.c	Tue Aug  5 21:24:45 2003
@@ -0,0 +1,627 @@
+/*
+ * bioscalls.c - the lowlevel layer of the PnPBIOS driver
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/pnpbios.h>
+#include <linux/device.h>
+#include <linux/pnp.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <asm/desc.h>
+#include <linux/slab.h>
+#include <linux/kmod.h>
+#include <linux/completion.h>
+#include <linux/spinlock.h>
+#include <asm/system.h>
+#include <asm/byteorder.h>
+
+
+/* PnP BIOS signature: "$PnP" */
+#define PNP_SIGNATURE   (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
+
+#pragma pack(1)
+union pnp_bios_expansion_header {
+	struct {
+		u32 signature;    /* "$PnP" */
+		u8 version;	  /* in BCD */
+		u8 length;	  /* length in bytes, currently 21h */
+		u16 control;	  /* system capabilities */
+		u8 checksum;	  /* all bytes must add up to 0 */
+
+		u32 eventflag;    /* phys. address of the event flag */
+		u16 rmoffset;     /* real mode entry point */
+		u16 rmcseg;
+		u16 pm16offset;   /* 16 bit protected mode entry */
+		u32 pm16cseg;
+		u32 deviceID;	  /* EISA encoded system ID or 0 */
+		u16 rmdseg;	  /* real mode data segment */
+		u32 pm16dseg;	  /* 16 bit pm data segment base */
+	} fields;
+	char chars[0x21];	  /* To calculate the checksum */
+};
+#pragma pack()
+
+static union pnp_bios_expansion_header * pnp_bios_hdr = NULL;
+
+/*
+ * Call this only after init time
+ */
+static int pnp_bios_present(void)
+{
+	return (pnp_bios_hdr != NULL);
+}
+
+static struct {
+	u16	offset;
+	u16	segment;
+} pnp_bios_callpoint;
+
+
+/* The PnP BIOS entries in the GDT */
+#define PNP_GDT    (GDT_ENTRY_PNPBIOS_BASE * 8)
+
+#define PNP_CS32   (PNP_GDT+0x00)	/* segment for calling fn */
+#define PNP_CS16   (PNP_GDT+0x08)	/* code segment for BIOS */
+#define PNP_DS     (PNP_GDT+0x10)	/* data segment for BIOS */
+#define PNP_TS1    (PNP_GDT+0x18)	/* transfer data segment */
+#define PNP_TS2    (PNP_GDT+0x20)	/* another data segment */
+
+/*
+ * These are some opcodes for a "static asmlinkage"
+ * As this code is *not* executed inside the linux kernel segment, but in a
+ * alias at offset 0, we need a far return that can not be compiled by
+ * default (please, prove me wrong! this is *really* ugly!)
+ * 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"
+	"pnp_bios_callfunc:\n"
+	"	pushl %edx	\n"
+	"	pushl %ecx	\n"
+	"	pushl %ebx	\n"
+	"	pushl %eax	\n"
+	"	lcallw *pnp_bios_callpoint\n"
+	"	addl $16, %esp	\n"
+	"	lret		\n"
+	".previous		\n"
+);
+
+#define Q_SET_SEL(cpu, selname, address, size) \
+do { \
+set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
+set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+} while(0)
+
+#define Q2_SET_SEL(cpu, selname, address, size) \
+do { \
+set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
+set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
+} while(0)
+
+static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
+
+/*
+ * 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;
+
+static spinlock_t pnp_bios_lock;
+
+
+/*
+ * Support Functions
+ */
+
+static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
+				u16 arg4, u16 arg5, u16 arg6, u16 arg7,
+				void *ts1_base, u32 ts1_size,
+				void *ts2_base, u32 ts2_size)
+{
+	unsigned long flags;
+	u16 status;
+	struct desc_struct save_desc_40;
+	int cpu;
+
+	/*
+	 * PnP BIOSes are generally not terribly re-entrant.
+	 * Also, don't rely on them to save everything correctly.
+	 */
+	if(pnp_bios_is_utter_crap)
+		return PNP_FUNCTION_NOT_SUPPORTED;
+
+	cpu = get_cpu();
+	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
+	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+
+	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
+	spin_lock_irqsave(&pnp_bios_lock, flags);
+
+	/* The lock prevents us bouncing CPU here */
+	if (ts1_size)
+		Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
+	if (ts2_size)
+		Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
+
+	__asm__ __volatile__(
+	        "pushl %%ebp\n\t"
+		"pushl %%edi\n\t"
+		"pushl %%esi\n\t"
+		"pushl %%ds\n\t"
+		"pushl %%es\n\t"
+		"pushl %%fs\n\t"
+		"pushl %%gs\n\t"
+		"pushfl\n\t"
+		"movl %%esp, pnp_bios_fault_esp\n\t"
+		"movl $1f, pnp_bios_fault_eip\n\t"
+		"lcall %5,%6\n\t"
+		"1:popfl\n\t"
+		"popl %%gs\n\t"
+		"popl %%fs\n\t"
+		"popl %%es\n\t"
+		"popl %%ds\n\t"
+	        "popl %%esi\n\t"
+		"popl %%edi\n\t"
+		"popl %%ebp\n\t"
+		: "=a" (status)
+		: "0" ((func) | (((u32)arg1) << 16)),
+		  "b" ((arg2) | (((u32)arg3) << 16)),
+		  "c" ((arg4) | (((u32)arg5) << 16)),
+		  "d" ((arg6) | (((u32)arg7) << 16)),
+		  "i" (PNP_CS32),
+		  "i" (0)
+		: "memory"
+	);
+	spin_unlock_irqrestore(&pnp_bios_lock, flags);
+
+	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+	put_cpu();
+
+	/* If we get here and this is set then the PnP BIOS faulted on us. */
+	if(pnp_bios_is_utter_crap)
+	{
+		printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
+		printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"nobiospnp\" option to operate stably\n");
+		printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n");
+	}
+
+	return status;
+}
+
+void pnpbios_print_status(const char * module, u16 status)
+{
+	switch(status) {
+	case PNP_SUCCESS:
+		printk(KERN_ERR "PnPBIOS: %s: function successful\n", module);
+		break;
+	case PNP_NOT_SET_STATICALLY:
+		printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n", module);
+		break;
+	case PNP_UNKNOWN_FUNCTION:
+		printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n", module);
+		break;
+	case PNP_FUNCTION_NOT_SUPPORTED:
+		printk(KERN_ERR "PnPBIOS: %s: function not supported on this system\n", module);
+		break;
+	case PNP_INVALID_HANDLE:
+		printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module);
+		break;
+	case PNP_BAD_PARAMETER:
+		printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n", module);
+		break;
+	case PNP_SET_FAILED:
+		printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n", module);
+		break;
+	case PNP_EVENTS_NOT_PENDING:
+		printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module);
+		break;
+	case PNP_SYSTEM_NOT_DOCKED:
+		printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n", module);
+		break;
+	case PNP_NO_ISA_PNP_CARDS:
+		printk(KERN_ERR "PnPBIOS: %s: no isapnp cards are installed on this system\n", module);
+		break;
+	case PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES:
+		printk(KERN_ERR "PnPBIOS: %s: cannot determine the capabilities of the docking station\n", module);
+		break;
+	case PNP_CONFIG_CHANGE_FAILED_NO_BATTERY:
+		printk(KERN_ERR "PnPBIOS: %s: unable to undock, the system does not have a battery\n", module);
+		break;
+	case PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT:
+		printk(KERN_ERR "PnPBIOS: %s: could not dock due to resource conflicts\n", module);
+		break;
+	case PNP_BUFFER_TOO_SMALL:
+		printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n", module);
+		break;
+	case PNP_USE_ESCD_SUPPORT:
+		printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module);
+		break;
+	case PNP_MESSAGE_NOT_SUPPORTED:
+		printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n", module);
+		break;
+	case PNP_HARDWARE_ERROR:
+		printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", module);
+		break;
+	default:
+		printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module, status);
+		break;
+	}
+}
+
+
+/*
+ * PnP BIOS Low Level Calls
+ */
+
+#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
+#define PNP_SEND_MESSAGE			0x04
+#define PNP_GET_DOCKING_STATION_INFORMATION	0x05
+#define PNP_SET_STATIC_ALLOCED_RES_INFO		0x09
+#define PNP_GET_STATIC_ALLOCED_RES_INFO		0x0a
+#define PNP_GET_APM_ID_TABLE			0x0b
+#define PNP_GET_PNP_ISA_CONFIG_STRUC		0x40
+#define PNP_GET_ESCD_INFO			0x41
+#define PNP_READ_ESCD				0x42
+#define PNP_WRITE_ESCD				0x43
+
+/*
+ * Call PnP BIOS with function 0x00, "get number of system device nodes"
+ */
+static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0,
+			       data, sizeof(struct pnp_dev_node_info), 0, 0);
+	data->no_nodes &= 0xff;
+	return status;
+}
+
+int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
+{
+	int status = __pnp_bios_dev_node_info( data );
+	if ( status )
+		pnpbios_print_status( "dev_node_info", status );
+	return status;
+}
+
+/*
+ * Note that some PnP BIOSes (e.g., 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"
+ * Input: *nodenum = desired node,
+ *        boot = whether to get nonvolatile boot (!=0)
+ *               or volatile current (0) config
+ * Output: *nodenum=next node or 0xff if no more nodes
+ */
+static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	if ( !boot && pnpbios_dont_use_current_config )
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
+			       nodenum, sizeof(char), data, 65536);
+	return status;
+}
+
+int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
+{
+	int status;
+	status =  __pnp_bios_get_dev_node( nodenum, boot, data );
+	if ( status )
+		pnpbios_print_status( "get_dev_node", status );
+	return status;
+}
+
+
+/*
+ * Call PnP BIOS with function 0x02, "set system device node"
+ * Input: *nodenum = desired node, 
+ *        boot = whether to set nonvolatile boot (!=0)
+ *               or volatile current (0) config
+ */
+static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	if ( !boot && pnpbios_dont_use_current_config )
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0,
+			       data, 65536, 0, 0);
+	return status;
+}
+
+int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
+{
+	int status;
+	status =  __pnp_bios_set_dev_node( nodenum, boot, data );
+	if ( status ) {
+		pnpbios_print_status( "set_dev_node", status );
+		return status;
+	}
+	if ( !boot ) { /* Update devlist */
+		status =  pnp_bios_get_dev_node( &nodenum, boot, data );
+		if ( status )
+			return status;
+	}
+	return status;
+}
+
+#if needed
+/*
+ * Call PnP BIOS with function 0x03, "get event"
+ */
+static int pnp_bios_get_event(u16 *event)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
+			       event, sizeof(u16), 0, 0);
+	return status;
+}
+#endif
+
+#if needed
+/*
+ * Call PnP BIOS with function 0x04, "send message"
+ */
+static int pnp_bios_send_message(u16 message)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	return status;
+}
+#endif
+
+/*
+ * Call PnP BIOS with function 0x05, "get docking station information"
+ */
+int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       data, sizeof(struct pnp_docking_station_info), 0, 0);
+	return status;
+}
+
+#if needed
+/*
+ * Call PnP BIOS with function 0x09, "set statically allocated resource
+ * information"
+ */
+static int pnp_bios_set_stat_res(char *info)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       info, *((u16 *) info), 0, 0);
+	return status;
+}
+#endif
+
+/*
+ * Call PnP BIOS with function 0x0a, "get statically allocated resource
+ * information"
+ */
+static int __pnp_bios_get_stat_res(char *info)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       info, 65536, 0, 0);
+	return status;
+}
+
+int pnp_bios_get_stat_res(char *info)
+{
+	int status;
+	status = __pnp_bios_get_stat_res( info );
+	if ( status )
+		pnpbios_print_status( "get_stat_res", status );
+	return status;
+}
+
+#if needed
+/*
+ * Call PnP BIOS with function 0x0b, "get APM id table"
+ */
+static int pnp_bios_apm_id_table(char *table, u16 *size)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0,
+			       table, *size, size, sizeof(u16));
+	return status;
+}
+#endif
+
+/*
+ * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
+ */
+static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
+			       data, sizeof(struct pnp_isa_config_struc), 0, 0);
+	return status;
+}
+
+int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
+{
+	int status;
+	status = __pnp_bios_isapnp_config( data );
+	if ( status )
+		pnpbios_print_status( "isapnp_config", status );
+	return status;
+}
+
+/*
+ * Call PnP BIOS with function 0x41, "get ESCD info"
+ */
+static int __pnp_bios_escd_info(struct escd_info_struc *data)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return ESCD_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS,
+			       data, sizeof(struct escd_info_struc), 0, 0);
+	return status;
+}
+
+int pnp_bios_escd_info(struct escd_info_struc *data)
+{
+	int status;
+	status = __pnp_bios_escd_info( data );
+	if ( status )
+		pnpbios_print_status( "escd_info", status );
+	return status;
+}
+
+/*
+ * Call PnP BIOS function 0x42, "read ESCD"
+ * nvram_base is determined by calling escd_info
+ */
+static int __pnp_bios_read_escd(char *data, u32 nvram_base)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return ESCD_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
+			       data, 65536, (void *)nvram_base, 65536);
+	return status;
+}
+
+int pnp_bios_read_escd(char *data, u32 nvram_base)
+{
+	int status;
+	status = __pnp_bios_read_escd( data, nvram_base );
+	if ( status )
+		pnpbios_print_status( "read_escd", status );
+	return status;
+}
+
+#if needed
+/*
+ * Call PnP BIOS function 0x43, "write ESCD"
+ */
+static int pnp_bios_write_escd(char *data, u32 nvram_base)
+{
+	u16 status;
+	if (!pnp_bios_present())
+		return ESCD_FUNCTION_NOT_SUPPORTED;
+	status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
+			       data, 65536, nvram_base, 65536);
+	return status;
+}
+#endif
+
+
+/*
+ * Probing and Initialization
+ */
+
+static void pnpbios_prepare_bios_calls(union pnp_bios_expansion_header *header)
+{
+	int i;
+	spin_lock_init(&pnp_bios_lock);
+	pnp_bios_callpoint.offset = header->fields.pm16offset;
+	pnp_bios_callpoint.segment = PNP_CS16;
+
+	set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
+	_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
+	for(i=0; i < NR_CPUS; i++)
+	{
+		Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
+		Q_SET_SEL(i, PNP_CS16, header->fields.pm16cseg, 64 * 1024);
+		Q_SET_SEL(i, PNP_DS, header->fields.pm16dseg, 64 * 1024);
+	}
+}
+
+int pnpbios_probe_installation(void)
+{
+	union pnp_bios_expansion_header *check;
+	u8 sum;
+	int length, i;
+
+	printk(KERN_INFO "PnPBIOS: Scanning system for PnP BIOS support...\n");
+
+	/*
+ 	 * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS
+	 * structure and, if one is found, sets up the selectors and
+	 * entry points
+	 */
+	for (check = (union pnp_bios_expansion_header *) __va(0xf0000);
+	     check < (union pnp_bios_expansion_header *) __va(0xffff0);
+	     ((void *) (check)) += 16) {
+		if (check->fields.signature != PNP_SIGNATURE)
+			continue;
+		printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", check);
+		length = check->fields.length;
+		if (!length) {
+			printk(KERN_ERR "PnPBIOS: installation structure is invalid, skipping\n");
+			continue;
+		}
+		for (sum = 0, i = 0; i < length; i++)
+			sum += check->chars[i];
+		if (sum) {
+			printk(KERN_ERR "PnPBIOS: installation structure is corrupted, skipping\n");
+			continue;
+		}
+		if (check->fields.version < 0x10) {
+			printk(KERN_WARNING "PnPBIOS: PnP BIOS version %d.%d is not supported\n",
+			       check->fields.version >> 4,
+			       check->fields.version & 15);
+			continue;
+		}
+		printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n",
+                       check->fields.version >> 4, check->fields.version & 15,
+		       check->fields.pm16cseg, check->fields.pm16offset,
+		       check->fields.pm16dseg);
+		pnp_bios_hdr = check;
+		pnpbios_prepare_bios_calls(check);
+		return 1;
+	}
+
+	printk(KERN_INFO "PnPBIOS: PnP BIOS support was not detected.\n");
+	return 0;
+}
diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
--- a/drivers/pnp/pnpbios/core.c	Tue Aug  5 21:24:45 2003
+++ b/drivers/pnp/pnpbios/core.c	Tue Aug  5 21:24:45 2003
@@ -74,242 +74,8 @@
  *
  */
 
-/* PnP BIOS signature: "$PnP" */
-#define PNP_SIGNATURE   (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
-
-#pragma pack(1)
-union pnp_bios_expansion_header {
-	struct {
-		u32 signature;    /* "$PnP" */
-		u8 version;	  /* in BCD */
-		u8 length;	  /* length in bytes, currently 21h */
-		u16 control;	  /* system capabilities */
-		u8 checksum;	  /* all bytes must add up to 0 */
-
-		u32 eventflag;    /* phys. address of the event flag */
-		u16 rmoffset;     /* real mode entry point */
-		u16 rmcseg;
-		u16 pm16offset;   /* 16 bit protected mode entry */
-		u32 pm16cseg;
-		u32 deviceID;	  /* EISA encoded system ID or 0 */
-		u16 rmdseg;	  /* real mode data segment */
-		u32 pm16dseg;	  /* 16 bit pm data segment base */
-	} fields;
-	char chars[0x21];	  /* To calculate the checksum */
-};
-#pragma pack()
-
-static struct {
-	u16	offset;
-	u16	segment;
-} pnp_bios_callpoint;
-
-static union pnp_bios_expansion_header * pnp_bios_hdr = NULL;
 struct pnp_dev_node_info node_info;
 
-/* The PnP BIOS entries in the GDT */
-#define PNP_GDT    (GDT_ENTRY_PNPBIOS_BASE * 8)
-
-#define PNP_CS32   (PNP_GDT+0x00)	/* segment for calling fn */
-#define PNP_CS16   (PNP_GDT+0x08)	/* code segment for BIOS */
-#define PNP_DS     (PNP_GDT+0x10)	/* data segment for BIOS */
-#define PNP_TS1    (PNP_GDT+0x18)	/* transfer data segment */
-#define PNP_TS2    (PNP_GDT+0x20)	/* another data segment */
-
-/* 
- * These are some opcodes for a "static asmlinkage"
- * As this code is *not* executed inside the linux kernel segment, but in a
- * alias at offset 0, we need a far return that can not be compiled by
- * default (please, prove me wrong! this is *really* ugly!) 
- * 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"
-	"pnp_bios_callfunc:\n"
-	"	pushl %edx	\n"
-	"	pushl %ecx	\n"
-	"	pushl %ebx	\n"
-	"	pushl %eax	\n"
-	"	lcallw *pnp_bios_callpoint\n"
-	"	addl $16, %esp	\n"
-	"	lret		\n"
-	".previous		\n"
-);
-
-#define Q_SET_SEL(cpu, selname, address, size) \
-do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
-} while(0)
-
-#define Q2_SET_SEL(cpu, selname, address, size) \
-do { \
-set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
-set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
-} while(0)
-
-static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
-
-/*
- * 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;
-
-static spinlock_t pnp_bios_lock;
-
-static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
-				u16 arg4, u16 arg5, u16 arg6, u16 arg7,
-				void *ts1_base, u32 ts1_size,
-				void *ts2_base, u32 ts2_size)
-{
-	unsigned long flags;
-	u16 status;
-	struct desc_struct save_desc_40;
-	int cpu;
-
-	/*
-	 * PnP BIOSes are generally not terribly re-entrant.
-	 * Also, don't rely on them to save everything correctly.
-	 */
-	if(pnp_bios_is_utter_crap)
-		return PNP_FUNCTION_NOT_SUPPORTED;
-
-	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
-
-	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
-	spin_lock_irqsave(&pnp_bios_lock, flags);
-
-	/* The lock prevents us bouncing CPU here */
-	if (ts1_size)
-		Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
-	if (ts2_size)
-		Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
-
-	__asm__ __volatile__(
-	        "pushl %%ebp\n\t"
-		"pushl %%edi\n\t"
-		"pushl %%esi\n\t"
-		"pushl %%ds\n\t"
-		"pushl %%es\n\t"
-		"pushl %%fs\n\t"
-		"pushl %%gs\n\t"
-		"pushfl\n\t"
-		"movl %%esp, pnp_bios_fault_esp\n\t"
-		"movl $1f, pnp_bios_fault_eip\n\t"
-		"lcall %5,%6\n\t"
-		"1:popfl\n\t"
-		"popl %%gs\n\t"
-		"popl %%fs\n\t"
-		"popl %%es\n\t"
-		"popl %%ds\n\t"
-	        "popl %%esi\n\t"
-		"popl %%edi\n\t"
-		"popl %%ebp\n\t"
-		: "=a" (status)
-		: "0" ((func) | (((u32)arg1) << 16)),
-		  "b" ((arg2) | (((u32)arg3) << 16)),
-		  "c" ((arg4) | (((u32)arg5) << 16)),
-		  "d" ((arg6) | (((u32)arg7) << 16)),
-		  "i" (PNP_CS32),
-		  "i" (0)
-		: "memory"
-	);
-	spin_unlock_irqrestore(&pnp_bios_lock, flags);
-
-	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
-	put_cpu();
-	
-	/* If we get here and this is set then the PnP BIOS faulted on us. */
-	if(pnp_bios_is_utter_crap)
-	{
-		printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
-		printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"nobiospnp\" option to operate stably\n");
-		printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n");
-	}
-
-	return status;
-}
-
-
-/*
- *
- * UTILITY FUNCTIONS
- *
- */
-
-static void pnpbios_print_status(const char * module, u16 status)
-{
-	switch(status) {
-	case PNP_SUCCESS:
-		printk(KERN_ERR "PnPBIOS: %s: function successful\n", module);
-		break;
-	case PNP_NOT_SET_STATICALLY:
-		printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n", module);
-		break;
-	case PNP_UNKNOWN_FUNCTION:
-		printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n", module);
-		break;
-	case PNP_FUNCTION_NOT_SUPPORTED:
-		printk(KERN_ERR "PnPBIOS: %s: function not supported on this system\n", module);
-		break;
-	case PNP_INVALID_HANDLE:
-		printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module);
-		break;
-	case PNP_BAD_PARAMETER:
-		printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n", module);
-		break;
-	case PNP_SET_FAILED:
-		printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n", module);
-		break;
-	case PNP_EVENTS_NOT_PENDING:
-		printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module);
-		break;
-	case PNP_SYSTEM_NOT_DOCKED:
-		printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n", module);
-		break;
-	case PNP_NO_ISA_PNP_CARDS:
-		printk(KERN_ERR "PnPBIOS: %s: no isapnp cards are installed on this system\n", module);
-		break;
-	case PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES:
-		printk(KERN_ERR "PnPBIOS: %s: cannot determine the capabilities of the docking station\n", module);
-		break;
-	case PNP_CONFIG_CHANGE_FAILED_NO_BATTERY:
-		printk(KERN_ERR "PnPBIOS: %s: unable to undock, the system does not have a battery\n", module);
-		break;
-	case PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT:
-		printk(KERN_ERR "PnPBIOS: %s: could not dock due to resource conflicts\n", module);
-		break;
-	case PNP_BUFFER_TOO_SMALL:
-		printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n", module);
-		break;
-	case PNP_USE_ESCD_SUPPORT:
-		printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module);
-		break;
-	case PNP_MESSAGE_NOT_SUPPORTED:
-		printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n", module);
-		break;
-	case PNP_HARDWARE_ERROR:
-		printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", module);
-		break;
-	default:
-		printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module, status);
-		break;
-	}
-}
-
 void *pnpbios_kmalloc(size_t size, int f)
 {
 	void *p = kmalloc( size, f );
@@ -321,308 +87,6 @@
 }
 
 /*
- * Call this only after init time
- */
-static int pnp_bios_present(void)
-{
-	return (pnp_bios_hdr != NULL);
-}
-
-
-/*
- *
- * PnP BIOS ACCESS 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
-#define PNP_SEND_MESSAGE                0x04
-#define PNP_GET_DOCKING_STATION_INFORMATION 0x05
-#define PNP_SET_STATIC_ALLOCED_RES_INFO 0x09
-#define PNP_GET_STATIC_ALLOCED_RES_INFO 0x0a
-#define PNP_GET_APM_ID_TABLE            0x0b
-#define PNP_GET_PNP_ISA_CONFIG_STRUC    0x40
-#define PNP_GET_ESCD_INFO               0x41
-#define PNP_READ_ESCD                   0x42
-#define PNP_WRITE_ESCD                  0x43
-
-/*
- * Call PnP BIOS with function 0x00, "get number of system device nodes"
- */
-static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0,
-			       data, sizeof(struct pnp_dev_node_info), 0, 0);
-	data->no_nodes &= 0xff;
-	return status;
-}
-
-int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
-{
-	int status = __pnp_bios_dev_node_info( data );
-	if ( status )
-		pnpbios_print_status( "dev_node_info", status );
-	return status;
-}
-
-/*
- * Note that some PnP BIOSes (e.g., 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"
- * Input: *nodenum = desired node, 
- *        boot = whether to get nonvolatile boot (!=0)
- *               or volatile current (0) config
- * Output: *nodenum=next node or 0xff if no more nodes
- */
-static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	if ( !boot && pnpbios_dont_use_current_config )
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
-			       nodenum, sizeof(char), data, 65536);
-	return status;
-}
-
-int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
-{
-	int status;
-	status =  __pnp_bios_get_dev_node( nodenum, boot, data );
-	if ( status )
-		pnpbios_print_status( "get_dev_node", status );
-	return status;
-}
-
-
-/*
- * Call PnP BIOS with function 0x02, "set system device node"
- * Input: *nodenum = desired node, 
- *        boot = whether to set nonvolatile boot (!=0)
- *               or volatile current (0) config
- */
-static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	if ( !boot && pnpbios_dont_use_current_config )
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0,
-			       data, 65536, 0, 0);
-	return status;
-}
-
-int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
-{
-	int status;
-	status =  __pnp_bios_set_dev_node( nodenum, boot, data );
-	if ( status ) {
-		pnpbios_print_status( "set_dev_node", status );
-		return status;
-	}
-	if ( !boot ) { /* Update devlist */
-		status =  pnp_bios_get_dev_node( &nodenum, boot, data );
-		if ( status )
-			return status;
-	}
-	return status;
-}
-
-#if needed
-/*
- * Call PnP BIOS with function 0x03, "get event"
- */
-static int pnp_bios_get_event(u16 *event)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
-			       event, sizeof(u16), 0, 0);
-	return status;
-}
-#endif
-
-#if needed
-/* 
- * Call PnP BIOS with function 0x04, "send message"
- */
-static int pnp_bios_send_message(u16 message)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-	return status;
-}
-#endif
-
-#ifdef CONFIG_HOTPLUG
-/*
- * 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;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       data, sizeof(struct pnp_docking_station_info), 0, 0);
-	return status;
-}
-#endif
-
-#if needed
-/*
- * Call PnP BIOS with function 0x09, "set statically allocated resource
- * information"
- */
-static int pnp_bios_set_stat_res(char *info)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       info, *((u16 *) info), 0, 0);
-	return status;
-}
-#endif
-
-/*
- * Call PnP BIOS with function 0x0a, "get statically allocated resource
- * information"
- */
-static int __pnp_bios_get_stat_res(char *info)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       info, 65536, 0, 0);
-	return status;
-}
-
-int pnp_bios_get_stat_res(char *info)
-{
-	int status;
-	status = __pnp_bios_get_stat_res( info );
-	if ( status )
-		pnpbios_print_status( "get_stat_res", status );
-	return status;
-}
-
-#if needed
-/*
- * Call PnP BIOS with function 0x0b, "get APM id table"
- */
-static int pnp_bios_apm_id_table(char *table, u16 *size)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0,
-			       table, *size, size, sizeof(u16));
-	return status;
-}
-#endif
-
-/*
- * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
- */
-static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return PNP_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
-			       data, sizeof(struct pnp_isa_config_struc), 0, 0);
-	return status;
-}
-
-int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
-{
-	int status;
-	status = __pnp_bios_isapnp_config( data );
-	if ( status )
-		pnpbios_print_status( "isapnp_config", status );
-	return status;
-}
-
-/*
- * Call PnP BIOS with function 0x41, "get ESCD info"
- */
-static int __pnp_bios_escd_info(struct escd_info_struc *data)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return ESCD_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS,
-			       data, sizeof(struct escd_info_struc), 0, 0);
-	return status;
-}
-
-int pnp_bios_escd_info(struct escd_info_struc *data)
-{
-	int status;
-	status = __pnp_bios_escd_info( data );
-	if ( status )
-		pnpbios_print_status( "escd_info", status );
-	return status;
-}
-
-/*
- * Call PnP BIOS function 0x42, "read ESCD"
- * nvram_base is determined by calling escd_info
- */
-static int __pnp_bios_read_escd(char *data, u32 nvram_base)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return ESCD_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
-			       data, 65536, (void *)nvram_base, 65536);
-	return status;
-}
-
-int pnp_bios_read_escd(char *data, u32 nvram_base)
-{
-	int status;
-	status = __pnp_bios_read_escd( data, nvram_base );
-	if ( status )
-		pnpbios_print_status( "read_escd", status );
-	return status;
-}
-
-#if needed
-/*
- * Call PnP BIOS function 0x43, "write ESCD"
- */
-static int pnp_bios_write_escd(char *data, u32 nvram_base)
-{
-	u16 status;
-	if (!pnp_bios_present())
-		return ESCD_FUNCTION_NOT_SUPPORTED;
-	status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
-			       data, 65536, nvram_base, 65536);
-	return status;
-}
-#endif
-
-
-/*
  *
  * DOCKING FUNCTIONS
  *
@@ -874,15 +338,8 @@
 	unsigned int nodes_got = 0;
 	unsigned int devs = 0;
 	struct pnp_bios_node *node;
-	struct pnp_dev_node_info node_info;
 	struct pnp_dev *dev;
 
-	if (!pnp_bios_present())
-		return;
-
-	if (pnp_bios_dev_node_info(&node_info) != 0)
-		return;
-
 	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return;
@@ -957,68 +414,15 @@
 
 int __init pnpbios_init(void)
 {
-	union pnp_bios_expansion_header *check;
-	u8 sum;
-	int i, length, r;
-
-	spin_lock_init(&pnp_bios_lock);
-
+	int ret;
 	if(pnpbios_disabled || (dmi_broken & BROKEN_PNP_BIOS)) {
 		printk(KERN_INFO "PnPBIOS: Disabled\n");
 		return -ENODEV;
-	} else
-		printk(KERN_INFO "PnPBIOS: Scanning system for PnP BIOS support...\n");
-
-	/*
- 	 * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS
-	 * structure and, if one is found, sets up the selectors and
-	 * entry points
-	 */
-	for (check = (union pnp_bios_expansion_header *) __va(0xf0000);
-	     check < (union pnp_bios_expansion_header *) __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: PnP BIOS version %d.%d is not supported\n",
-			       check->fields.version >> 4,
-			       check->fields.version & 15);
-			continue;
-		}
-		printk(KERN_INFO "PnPBIOS: Found PnP BIOS installation structure at 0x%p\n", check);
-		printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry 0x%x:0x%x, dseg 0x%x\n",
-                       check->fields.version >> 4, check->fields.version & 15,
-		       check->fields.pm16cseg, check->fields.pm16offset,
-		       check->fields.pm16dseg);
-		pnp_bios_callpoint.offset = check->fields.pm16offset;
-		pnp_bios_callpoint.segment = PNP_CS16;
-		pnp_bios_hdr = check;
-
-		set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
-		_set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
-		for(i=0; i < NR_CPUS; i++)
-		{
-			Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
-			Q_SET_SEL(i, PNP_CS16, check->fields.pm16cseg, 64 * 1024);
-			Q_SET_SEL(i, PNP_DS, check->fields.pm16dseg, 64 * 1024);
-		}
-		break;
-	}
-	if (!pnp_bios_present()) {
-		printk(KERN_INFO "PnPBIOS: A PnP BIOS was not detected.\n");
-		return -ENODEV;
 	}
 
-	/*
-	 * we found a pnpbios, now let's load the rest of the driver
-	 */
+	/* scan the system for pnpbios support */
+	if (!pnpbios_probe_installation())
+		return -ENODEV;
 
 	/* read the node info */
 	if (pnp_bios_dev_node_info(&node_info)) {
@@ -1031,9 +435,9 @@
 
 #ifdef CONFIG_PROC_FS
 	/* start the proc interface */
-	r = pnpbios_proc_init();
-	if (r)
-		return r;
+	ret = pnpbios_proc_init();
+	if (ret)
+		return ret;
 #endif
 
 	/* scan for pnpbios devices */
diff -Nru a/drivers/pnp/pnpbios/pnpbios.h b/drivers/pnp/pnpbios/pnpbios.h
--- a/drivers/pnp/pnpbios/pnpbios.h	Tue Aug  5 21:24:45 2003
+++ b/drivers/pnp/pnpbios/pnpbios.h	Tue Aug  5 21:24:45 2003
@@ -6,3 +6,6 @@
 extern int pnpbios_read_resources_from_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
 extern int pnpbios_write_resources_to_node(struct pnp_resource_table *res, struct pnp_bios_node * node);
 extern void pnpid32_to_pnpid(u32 id, char *str);
+
+extern void pnpbios_print_status(const char * module, u16 status);
+extern int pnpbios_probe_installation(void);
diff -Nru a/include/linux/pnpbios.h b/include/linux/pnpbios.h
--- a/include/linux/pnpbios.h	Tue Aug  5 21:24:45 2003
+++ b/include/linux/pnpbios.h	Tue Aug  5 21:24:45 2003
@@ -146,6 +146,7 @@
 extern int pnp_bios_isapnp_config (struct pnp_isa_config_struc *data);
 extern int pnp_bios_escd_info (struct escd_info_struc *data);
 extern int pnp_bios_read_escd (char *data, u32 nvram_base);
+extern int pnp_bios_dock_station_info(struct pnp_docking_station_info *data);
 #if needed
 extern int pnp_bios_get_event (u16 *message);
 extern int pnp_bios_send_message (u16 message);

  parent reply	other threads:[~2003-08-06  2:54 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-08-05 22:14 [PATCH] PnP Updates for 2.6.0-test2 Adam Belay
2003-08-05 22:15 ` Adam Belay
2003-08-05 22:15 ` Adam Belay
2003-08-05 22:16 ` Adam Belay
2003-08-05 22:17 ` Adam Belay [this message]
2003-08-05 22:17 ` Adam Belay
2003-08-05 22:18 ` Adam Belay

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=20030805221703.GF13275@neo.rr.com \
    --to=ambx1@neo.rr.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.