2002-03-08 23:00:09

by Thomas Hood

[permalink] [raw]
Subject: PnP BIOS driver status

A couple people have asked me about the status of the
PnP BIOS driver, so I thought I'd post an update.

History: During the pre-Tosatti 2.4-ac series the driver was
hammered into a reliable form. However it never entered the
mainline kernel series.

The driver was then stripped down to the core functionality
required to make the lspnp and setpnp utilities work.
pnpbios_register_driver() and pnpbios_unregister_driver() are
still there but aren't used by anything. Additional /proc/
interface files were then added to allow reading of ESCD info.

The latest version of the driver seems nice 'n' stable and can
be found in Alan's latest 2.4 patches.

Current 2.5 kernels also contain the driver, but it's a bit out
of date. There's a patch in 2.5-dj but that's also out of date.
("Out of date" here means "missing new features and some
cleanups".) Once DJ releases a 2.5.6-dj I'll send him a patch
to bring his tree up to date. Then he can pass it on to Linus.

--
Thomas Hood


2002-03-08 23:15:19

by Dave Jones

[permalink] [raw]
Subject: Re: PnP BIOS driver status

On Fri, Mar 08, 2002 at 06:00:40PM -0500, Thomas Hood wrote:

> Current 2.5 kernels also contain the driver, but it's a bit out
> of date. There's a patch in 2.5-dj but that's also out of date.
> ("Out of date" here means "missing new features and some
> cleanups".)

The bits that handle ESCD ? I merged that.

> Once DJ releases a 2.5.6-dj I'll send him a patch
> to bring his tree up to date. Then he can pass it on to Linus.

You may have to wait a while. Most of my life just got packed
into boxes, and is about to go out the door to a new home.
It'll take a week or so to get back on my feet.

--
| Dave Jones. http://www.codemonkey.org.uk
| SuSE Labs

2002-03-09 00:43:22

by Thomas Hood

[permalink] [raw]
Subject: Re: PnP BIOS driver status

On Fri, 2002-03-08 at 18:14, Dave Jones wrote:
> The bits that handle ESCD ? I merged that.

Here are the additional bits from the -ac tree, diffed
against 2.5.6 + 2.5.5-dj3 patch. The changes include:

- Improve some comments
- Postpone starting the kernel thread (Alan Cox)
- Call kernel thread 'kpnpbiosd' instead of 'kpnpbios'
- Consolidate printing of error messages to save space
- Add __init and __exit tags and return appropriate error codes
- Print slightly more consistent messages
- Get closer to supporting build-as-module

--
Thomas

--- linux-2.5.6_2.5.5-dj3/include/linux/pnpbios.h_DJ Fri Mar 8 18:37:58 2002
+++ linux-2.5.6_2.5.5-dj3/include/linux/pnpbios.h Fri Mar 8 19:12:25 2002
@@ -143,7 +143,8 @@
extern int pnpbios_dont_use_current_config;
extern void *pnpbios_kmalloc(size_t size, int f);
extern int pnpbios_init (void);
-extern void pnpbios_proc_init (void);
+extern int pnpbios_proc_init (void);
+extern void pnpbios_proc_exit (void);

extern int pnp_bios_dev_node_info (struct pnp_dev_node_info *data);
extern int pnp_bios_get_dev_node (u8 *nodenum, char config, struct pnp_bios_node *data);
--- linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_core.c_DJ Fri Mar 8 18:40:02 2002
+++ linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_core.c Fri Mar 8 19:09:39 2002
@@ -4,7 +4,7 @@
* Originally (C) 1998 Christian Schmidt <[email protected]>
* Modifications (c) 1998 Tom Lees <[email protected]>
* Minor reorganizations by David Hinds <[email protected]>
- * Modifications (c) 2001 by Thomas Hood <[email protected]>
+ * Modifications (c) 2001,2002 by Thomas Hood <[email protected]>
*
* 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
@@ -205,6 +205,11 @@
*
*/

+static void pnpbios_warn_unexpected_status(const char * module, u16 status)
+{
+ printk(KERN_ERR "PnPBIOS: %s: Unexpected status 0x%x\n", module, status);
+}
+
void *pnpbios_kmalloc(size_t size, int f)
{
void *p = kmalloc( size, f );
@@ -251,7 +256,7 @@
static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_dev_node_info));
status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0);
@@ -263,7 +268,7 @@
{
int status = __pnp_bios_dev_node_info( data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: dev_node_info: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "dev_node_info", status );
return status;
}

@@ -284,7 +289,7 @@
static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
@@ -299,7 +304,7 @@
int status;
status = __pnp_bios_get_dev_node( nodenum, boot, data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: get_dev_node: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "get_dev_node", status );
return status;
}

@@ -313,7 +318,7 @@
static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
@@ -327,7 +332,7 @@
int status;
status = __pnp_bios_set_dev_node( nodenum, boot, data );
if ( status ) {
- printk(KERN_WARNING "PnPBIOS: set_dev_node: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "set_dev_node", status );
return status;
}
if ( !boot ) { /* Update devlist */
@@ -347,7 +352,7 @@
static int pnp_bios_get_event(u16 *event)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, event, sizeof(u16));
status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0);
@@ -362,7 +367,7 @@
static int pnp_bios_send_message(u16 message)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0);
return status;
@@ -376,7 +381,7 @@
static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_docking_station_info));
status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
@@ -392,7 +397,7 @@
static int pnp_bios_set_stat_res(char *info)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, info, *((u16 *) info));
status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
@@ -407,7 +412,7 @@
static int __pnp_bios_get_stat_res(char *info)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, info, 64 * 1024);
status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
@@ -419,7 +424,7 @@
int status;
status = __pnp_bios_get_stat_res( info );
if ( status )
- printk(KERN_WARNING "PnPBIOS: get_stat_res: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "get_stat_res", status );
return status;
}

@@ -430,7 +435,7 @@
static int pnp_bios_apm_id_table(char *table, u16 *size)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, table, *size);
Q2_SET_SEL(PNP_TS2, size, sizeof(u16));
@@ -445,7 +450,7 @@
static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_isa_config_struc));
status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
@@ -457,7 +462,7 @@
int status;
status = __pnp_bios_isapnp_config( data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: isapnp_config: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "isapnp_config", status );
return status;
}

@@ -467,7 +472,7 @@
static int __pnp_bios_escd_info(struct escd_info_struc *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, data, sizeof(struct escd_info_struc));
status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS);
@@ -479,7 +484,7 @@
int status;
status = __pnp_bios_escd_info( data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: escd_info: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "escd_info", status );
return status;
}

@@ -490,7 +495,7 @@
static int __pnp_bios_read_escd(char *data, u32 nvram_base)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
set_base(gdt[PNP_TS2 >> 3], nvram_base);
@@ -504,7 +509,7 @@
int status;
status = __pnp_bios_read_escd( data, nvram_base );
if ( status )
- printk(KERN_ERR "PnPBIOS: read_escd: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "read_escd", status );
return status;
}

@@ -515,7 +520,7 @@
static int pnp_bios_write_escd(char *data, u32 nvram_base)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
set_base(gdt[PNP_TS2 >> 3], nvram_base);
@@ -602,10 +607,10 @@
int docked = -1, d = 0;
daemonize();
reparent_to_init();
- strcpy(current->comm, "kpnpbios");
+ strcpy(current->comm, "kpnpbiosd");
while(!unloading && !signal_pending(current))
{
- int err;
+ int status;

/*
* Poll every 2 seconds
@@ -615,9 +620,9 @@
if(signal_pending(current))
break;

- err = pnp_bios_dock_station_info(&now);
+ status = pnp_bios_dock_station_info(&now);

- switch(err)
+ switch(status)
{
/*
* No dock to manage
@@ -631,7 +636,7 @@
d = 1;
break;
default:
- printk(KERN_WARNING "PnPBIOS: pnp_dock_thread: Unexpected status 0x%x\n", err);
+ pnpbios_warn_unexpected_status( "pnp_dock_thread", status );
continue;
}
if(d != docked)
@@ -874,13 +879,13 @@
static void __init build_devlist(void)
{
u8 nodenum;
- int nodes_got = 0;
- int devs = 0;
+ unsigned int nodes_got = 0;
+ unsigned int devs = 0;
struct pnp_bios_node *node;
struct pnp_dev_node_info node_info;
struct pci_dev *dev;

- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return;

if (pnp_bios_dev_node_info(&node_info) != 0)
@@ -912,7 +917,7 @@
else
devs++;
if (nodenum <= thisnodenum) {
- printk(KERN_ERR "PnPBIOS: build_devlist(): Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (int)nodenum, (int)thisnodenum);
+ printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum);
break;
}
}
@@ -1215,14 +1220,14 @@
{
union pnp_bios_expansion_header *check;
u8 sum;
- int i, length;
+ int i, length, r;

spin_lock_init(&pnp_bios_lock);
spin_lock_init(&pnpbios_devices_lock);

if(pnpbios_disabled) {
printk(KERN_INFO "PnPBIOS: Disabled\n");
- return 0;
+ return -ENODEV;
}

if ( is_sony_vaio_laptop )
@@ -1264,12 +1269,21 @@
pnp_bios_hdr = check;
break;
}
+ if (!pnp_bios_present())
+ return -ENODEV;
build_devlist();
if ( ! dont_reserve_resources )
reserve_resources();
#ifdef CONFIG_PROC_FS
- pnpbios_proc_init();
+ r = pnpbios_proc_init();
+ if (r)
+ return r;
#endif
+ return 0;
+}
+
+static int __init pnpbios_thread_init(void)
+{
#ifdef CONFIG_HOTPLUG
init_completion(&unload_sem);
if(kernel_thread(pnp_dock_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL)>0)
@@ -1278,23 +1292,46 @@
return 0;
}

-#ifdef MODULE
+#ifndef MODULE
+
+/* init/main.c calls pnpbios_init early */
+
+/* Start the kernel thread later: */
+module_init(pnpbios_thread_init);
+
+#else
+
+/*
+ * N.B.: Building pnpbios as a module hasn't been fully implemented
+ */

MODULE_LICENSE("GPL");

-/* We have to run it early and not as a module. */
-module_init(pnpbios_init);
+static int __init pnpbios_init_all(void)
+{
+ int r;

-#ifdef CONFIG_HOTPLUG
-static void pnpbios_exit(void)
+ r = pnpbios_init();
+ if (r)
+ return r;
+ r = pnpbios_thread_init();
+ if (r)
+ return r;
+ return 0;
+}
+
+static void __exit pnpbios_exit(void)
{
- /* free_resources() ought to go here */
- /* pnpbios_proc_done() */
+#ifdef CONFIG_HOTPLUG
unloading = 1;
wait_for_completion(&unload_sem);
+#endif
+ pnpbios_proc_exit();
+ /* We ought to free resources here */
+ return;
}

+module_init(pnpbios_init_all);
module_exit(pnpbios_exit);

-#endif
#endif
--- linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_proc.c_DJ Fri Mar 8 18:37:58 2002
+++ linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_proc.c Fri Mar 8 19:10:32 2002
@@ -2,7 +2,20 @@
* /proc/bus/pnp interface for Plug and Play devices
*
* Written by David Hinds, [email protected]
- * Modified by Thomas Hood, jdthood_AT_mail.com
+ * Modified by Thomas Hood, [email protected]
+ *
+ * The .../devices and .../<node> and .../boot/<node> files are
+ * utilized by the lspnp and setpnp utilities, supplied with the
+ * pcmcia-cs package.
+ * http://pcmcia-cs.sourceforge.net
+ *
+ * The .../escd file is utilized by the lsescd utility written by
+ * Gunther Mayer.
+ * http://home.t-online.de/home/gunther.mayer/lsescd
+ *
+ * The .../legacy_device_resources file is not used yet.
+ *
+ * The other files are human-readable.
*/

//#include <pcmcia/config.h>
@@ -66,7 +79,7 @@

/* sanity check */
if (escd.escd_size > (32*1024)) {
- printk(KERN_ERR "PnPBIOS: Error: ESCD size is too great\n");
+ printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size is too great\n");
return -EFBIG;
}

@@ -122,7 +135,7 @@
node->type_code[0], node->type_code[1],
node->type_code[2], node->flags);
if (nodenum <= thisnodenum) {
- printk(KERN_ERR "PnPBIOS: proc_read_devices(): Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (int)nodenum, (int)thisnodenum);
+ printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_read_devices:", (unsigned int)nodenum, (unsigned int)thisnodenum);
*eof = 1;
break;
}
@@ -177,20 +190,22 @@
* work and the pnpbios_dont_use_current_config flag
* should already have been set to the appropriate value
*/
-void pnpbios_proc_init( void )
+int __init pnpbios_proc_init( void )
{
struct pnp_bios_node *node;
struct proc_dir_entry *ent;
char name[3];
- int i;
u8 nodenum;

- if (pnp_bios_dev_node_info(&node_info) != 0) return;
+ if (pnp_bios_dev_node_info(&node_info))
+ return -EIO;

proc_pnp = proc_mkdir("pnp", proc_bus);
- if (!proc_pnp) return;
+ if (!proc_pnp)
+ return -EIO;
proc_pnp_boot = proc_mkdir("boot", proc_pnp);
- if (!proc_pnp_boot) return;
+ if (!proc_pnp_boot)
+ return -EIO;
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);
@@ -198,8 +213,11 @@
create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL);

node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
- if (!node) return;
- for (i=0,nodenum = 0; i<0xff && nodenum != 0xff; i++) {
+ if (!node)
+ return -ENOMEM;
+
+ for (nodenum=0; nodenum<0xff; ) {
+ u8 thisnodenum = nodenum;
if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0)
break;
sprintf(name, "%02x", node->handle);
@@ -217,11 +235,17 @@
ent->write_proc = proc_write_node;
ent->data = (void *)(long)(node->handle+0x100);
}
+ if (nodenum <= thisnodenum) {
+ printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_init:", (unsigned int)nodenum, (unsigned int)thisnodenum);
+ break;
+ }
}
kfree(node);
+
+ return 0;
}

-void pnpbios_proc_done(void)
+void __exit pnpbios_proc_exit(void)
{
int i;
char name[3];
@@ -241,4 +265,6 @@
remove_proc_entry("devices", proc_pnp);
remove_proc_entry("boot", proc_pnp);
remove_proc_entry("pnp", proc_bus);
+
+ return;
}

2002-03-09 01:00:43

by Brian Gerst

[permalink] [raw]
Subject: Re: PnP BIOS driver status

Thomas Hood wrote:
>
> A couple people have asked me about the status of the
> PnP BIOS driver, so I thought I'd post an update.
>
> History: During the pre-Tosatti 2.4-ac series the driver was
> hammered into a reliable form. However it never entered the
> mainline kernel series.
>
> The driver was then stripped down to the core functionality
> required to make the lspnp and setpnp utilities work.
> pnpbios_register_driver() and pnpbios_unregister_driver() are
> still there but aren't used by anything. Additional /proc/
> interface files were then added to allow reading of ESCD info.
>
> The latest version of the driver seems nice 'n' stable and can
> be found in Alan's latest 2.4 patches.
>
> Current 2.5 kernels also contain the driver, but it's a bit out
> of date. There's a patch in 2.5-dj but that's also out of date.
> ("Out of date" here means "missing new features and some
> cleanups".) Once DJ releases a 2.5.6-dj I'll send him a patch
> to bring his tree up to date. Then he can pass it on to Linus.

The current driver is not SMP-safe. It is modifying the GDT descriptors
outside of the pnp_bios_lock. Also, you can remove the __cli(), as
spin_lock_irq() already turns off interrupts.

--

Brian Gerst

2002-03-09 01:10:15

by Alan

[permalink] [raw]
Subject: Re: PnP BIOS driver status

> The current driver is not SMP-safe. It is modifying the GDT descriptors
> outside of the pnp_bios_lock. Also, you can remove the __cli(), as
> spin_lock_irq() already turns off interrupts.

The GDT descriptors are private to the PNP BIOS and constant values once
set up. No PnPBIOS call is made before the configuration is done.

Seems ok to me - or am I missing something ?

2002-03-09 01:09:54

by Thomas Hood

[permalink] [raw]
Subject: Re: PnP BIOS driver status

On Fri, 2002-03-08 at 20:00, Brian Gerst wrote:
> The current driver is not SMP-safe.

That's true.

> It is modifying the GDT descriptors
> outside of the pnp_bios_lock. Also, you can remove the __cli(), as
> spin_lock_irq() already turns off interrupts.

I'd welcome a patch like the return of a kidnapped pet.

--
Thomas

2002-03-09 01:38:36

by Brian Gerst

[permalink] [raw]
Subject: Re: PnP BIOS driver status

Alan Cox wrote:
>
> > The current driver is not SMP-safe. It is modifying the GDT descriptors
> > outside of the pnp_bios_lock. Also, you can remove the __cli(), as
> > spin_lock_irq() already turns off interrupts.
>
> The GDT descriptors are private to the PNP BIOS and constant values once
> set up. No PnPBIOS call is made before the configuration is done.
>
> Seems ok to me - or am I missing something ?

Two user processes calling functions through /proc...

--

Brian Gerst

2002-03-09 01:45:39

by Alan

[permalink] [raw]
Subject: Re: PnP BIOS driver status

> > The GDT descriptors are private to the PNP BIOS and constant values once
> > set up. No PnPBIOS call is made before the configuration is done.
> >
> > Seems ok to me - or am I missing something ?
>
> Two user processes calling functions through /proc...

The GDT descriptors are set up before /proc comes into being. I'm checking
2.4 code here - has someone left old stuff in 2.5 ?

2002-03-09 01:52:10

by Brian Gerst

[permalink] [raw]
Subject: Re: PnP BIOS driver status

Alan Cox wrote:
>
> > > The GDT descriptors are private to the PNP BIOS and constant values once
> > > set up. No PnPBIOS call is made before the configuration is done.
> > >
> > > Seems ok to me - or am I missing something ?
> >
> > Two user processes calling functions through /proc...
>
> The GDT descriptors are set up before /proc comes into being. I'm checking
> 2.4 code here - has someone left old stuff in 2.5 ?

PNP_TS1 and PNP_TS2 are changed on every call to the bios to point to
where the data for the 32-bit code lives.

--

Brian Gerst

2002-03-09 02:11:14

by Alan

[permalink] [raw]
Subject: Re: PnP BIOS driver status

> > The GDT descriptors are set up before /proc comes into being. I'm checking
> > 2.4 code here - has someone left old stuff in 2.5 ?
>
> PNP_TS1 and PNP_TS2 are changed on every call to the bios to point to
> where the data for the 32-bit code lives.

Got you - yes Thomas he's absolutely right. The lock needs to be taken
by the callers before they set the PNP_TS* entries.

2002-03-09 02:24:07

by Thomas Hood

[permalink] [raw]
Subject: Re: PnP BIOS driver status

On Fri, 2002-03-08 at 21:26, Alan Cox wrote:
> Got you - yes Thomas he's absolutely right. The lock needs to be
> taken by the callers before they set the PNP_TS* entries.

Yep. I'll submit a patch to Alan and update the one I just
posted for DJ.

--
Thomas

2002-03-09 02:24:38

by Brian Gerst

[permalink] [raw]
Subject: Re: PnP BIOS driver status

diff -urN linux-2.5.6/drivers/pnp/pnpbios_core.c linux/drivers/pnp/pnpbios_core.c
--- linux-2.5.6/drivers/pnp/pnpbios_core.c Fri Mar 8 07:51:30 2002
+++ linux/drivers/pnp/pnpbios_core.c Fri Mar 8 21:15:58 2002
@@ -141,7 +141,9 @@
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)
+ 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;
@@ -155,7 +157,12 @@

/* On some boxes IRQ's during PnP BIOS calls are deadly. */
spin_lock_irqsave(&pnp_bios_lock, flags);
- __cli();
+
+ if (ts1_size)
+ Q2_SET_SEL(PNP_TS1, ts1_base, ts1_size);
+ if (ts2_size)
+ Q2_SET_SEL(PNP_TS2, ts2_base, ts2_size);
+
__asm__ __volatile__(
"pushl %%ebp\n\t"
"pushl %%edi\n\t"
@@ -253,8 +260,8 @@
u16 status;
if (!pnp_bios_present ())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_dev_node_info));
- status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0);
+ 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;
}
@@ -288,9 +295,8 @@
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, nodenum, sizeof(char));
- Q2_SET_SEL(PNP_TS2, data, 64 * 1024);
- status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0);
+ 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;
}

@@ -317,8 +323,8 @@
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
- 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);
+ 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;
}

@@ -352,8 +358,8 @@
u16 status;
if (!pnp_bios_present ())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, event, sizeof(u16));
- status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0);
+ status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
+ event, sizeof(u16), 0, 0);
return status;
}
#endif
@@ -367,7 +373,7 @@
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);
+ status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return status;
}
#endif
@@ -381,8 +387,8 @@
u16 status;
if (!pnp_bios_present ())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_docking_station_info));
- status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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
@@ -397,8 +403,8 @@
u16 status;
if (!pnp_bios_present ())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, info, *((u16 *) info));
- status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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
@@ -413,8 +419,8 @@
u16 status;
if (!pnp_bios_present ())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, info, 64 * 1024);
- status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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;
}
#endif
@@ -428,9 +434,8 @@
u16 status;
if (!pnp_bios_present ())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, table, *size);
- Q2_SET_SEL(PNP_TS2, size, sizeof(u16));
- status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0);
+ 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
@@ -444,8 +449,8 @@
u16 status;
if (!pnp_bios_present ())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_isa_config_struc));
- status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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;
}
#endif
@@ -459,8 +464,8 @@
u16 status;
if (!pnp_bios_present ())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct escd_info_struc));
- status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS);
+ 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;
}
#endif
@@ -475,10 +480,8 @@
u16 status;
if (!pnp_bios_present ())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
- set_base(gdt[PNP_TS2 >> 3], nvram_base);
- set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
- status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
+ data, 65536, nvram_base, 65536);
return status;
}
#endif
@@ -492,10 +495,8 @@
u16 status;
if (!pnp_bios_present ())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
- set_base(gdt[PNP_TS2 >> 3], nvram_base);
- set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
- status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ 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


Attachments:
pnpbios-segs-1 (6.21 kB)

2002-03-09 07:19:04

by Thomas Hood

[permalink] [raw]
Subject: Re: PnP BIOS driver status

Here the patch for Alan (which also includes the
kpnpbios -> kpnpbiosd change):

--- linux-2.4.19-pre2-ac3/drivers/pnp/pnpbios_core.c_ORIG Fri Mar 8 17:35:44 2002
+++ linux-2.4.19-pre2-ac3/drivers/pnp/pnpbios_core.c Fri Mar 8 21:43:10 2002
@@ -139,10 +139,16 @@

static spinlock_t pnp_bios_lock;

+/*
+ * call_pnp_bios
+ *
+ * Call with the pnp_bios_lock held and with irqs disabled.
+ * On some boxes IRQ's during PnP BIOS calls are deadly.
+ */
+
static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
u16 arg4, u16 arg5, u16 arg6, u16 arg7)
{
- unsigned long flags;
u16 status;

/*
@@ -152,9 +158,6 @@
if(pnp_bios_is_utter_crap)
return PNP_FUNCTION_NOT_SUPPORTED;

- /* On some boxes IRQ's during PnP BIOS calls are deadly. */
- spin_lock_irqsave(&pnp_bios_lock, flags);
- __cli();
__asm__ __volatile__(
"pushl %%ebp\n\t"
"pushl %%edi\n\t"
@@ -184,7 +187,6 @@
"i" (0)
: "memory"
);
- spin_unlock_irqrestore(&pnp_bios_lock, flags);

/* If we get here and this is set then the PnP BIOS faulted on us. */
if(pnp_bios_is_utter_crap)
@@ -220,7 +222,7 @@
/*
* Call this only after init time
*/
-static int pnp_bios_present(void)
+static inline int pnp_bios_present(void)
{
return (pnp_bios_hdr != NULL);
}
@@ -254,11 +256,14 @@
*/
static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_dev_node_info));
status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
data->no_nodes &= 0xff;
return status;
}
@@ -287,14 +292,17 @@
*/
static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, nodenum, sizeof(char));
Q2_SET_SEL(PNP_TS2, data, 64 * 1024);
status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}

@@ -316,13 +324,16 @@
*/
static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
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);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}

@@ -350,11 +361,14 @@
*/
static int pnp_bios_get_event(u16 *event)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, event, sizeof(u16));
status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}
#endif
@@ -365,10 +379,13 @@
*/
static int pnp_bios_send_message(u16 message)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}
#endif
@@ -379,11 +396,14 @@
*/
static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_docking_station_info));
status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}
#endif
@@ -395,11 +415,14 @@
*/
static int pnp_bios_set_stat_res(char *info)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, info, *((u16 *) info));
status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}
#endif
@@ -410,11 +433,14 @@
*/
static int __pnp_bios_get_stat_res(char *info)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, info, 64 * 1024);
status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}

@@ -433,12 +459,15 @@
*/
static int pnp_bios_apm_id_table(char *table, u16 *size)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, table, *size);
Q2_SET_SEL(PNP_TS2, size, sizeof(u16));
status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}
#endif
@@ -448,11 +477,14 @@
*/
static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_isa_config_struc));
status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}

@@ -470,11 +502,14 @@
*/
static int __pnp_bios_escd_info(struct escd_info_struc *data)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, data, sizeof(struct escd_info_struc));
status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}

@@ -493,13 +528,16 @@
*/
static int __pnp_bios_read_escd(char *data, u32 nvram_base)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
set_base(gdt[PNP_TS2 >> 3], nvram_base);
set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}

@@ -518,13 +556,16 @@
*/
static int pnp_bios_write_escd(char *data, u32 nvram_base)
{
+ unsigned long flags;
u16 status;
if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
+ spin_lock_irqsave(&pnp_bios_lock, flags);
Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
set_base(gdt[PNP_TS2 >> 3], nvram_base);
set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
return status;
}
#endif
@@ -606,7 +647,7 @@
int docked = -1, d = 0;
daemonize();
reparent_to_init();
- strcpy(current->comm, "kpnpbios");
+ strcpy(current->comm, "kpnpbiosd");
while(!unloading && !signal_pending(current))
{
int status;

2002-03-09 07:18:59

by Thomas Hood

[permalink] [raw]
Subject: Re: PnP BIOS driver status

On Fri, 2002-03-08 at 21:23, Brian Gerst wrote:
> How does this patch look? Against 2.5.6

Better than mine.

Alan: I suggest applying Brian's patch plus the
change from 'kpnpbios' to 'kpnpbiosd'.

I'll integrate Brian's patch into my patch for David
Jones's patch to 2.5.x ... tomorrow.

2002-03-09 14:44:28

by Thomas Hood

[permalink] [raw]
Subject: Re: PnP BIOS driver status

Alan: I just tried to apply Brian's patch and noticed that
it was against 2.5.6. Here is his patch versus 2.4.19-pre2-ac3
with the kpnpbios -> kpnpbiosd change added in.
// Thomas

--- linux-2.4.19-pre2-ac3/drivers/pnp/pnpbios_core.c_ORIG Fri Mar 8 17:35:44 2002
+++ linux-2.4.19-pre2-ac3/drivers/pnp/pnpbios_core.c Sat Mar 9 09:39:56 2002
@@ -140,7 +140,9 @@
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)
+ 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;
@@ -154,7 +156,12 @@

/* On some boxes IRQ's during PnP BIOS calls are deadly. */
spin_lock_irqsave(&pnp_bios_lock, flags);
- __cli();
+
+ if (ts1_size)
+ Q2_SET_SEL(PNP_TS1, ts1_base, ts1_size);
+ if (ts2_size)
+ Q2_SET_SEL(PNP_TS2, ts2_base, ts2_size);
+
__asm__ __volatile__(
"pushl %%ebp\n\t"
"pushl %%edi\n\t"
@@ -220,7 +227,7 @@
/*
* Call this only after init time
*/
-static int pnp_bios_present(void)
+static inline int pnp_bios_present(void)
{
return (pnp_bios_hdr != NULL);
}
@@ -257,8 +264,8 @@
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_dev_node_info));
- status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0);
+ 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;
}
@@ -292,9 +299,8 @@
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, nodenum, sizeof(char));
- Q2_SET_SEL(PNP_TS2, data, 64 * 1024);
- status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0);
+ 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;
}

@@ -321,8 +327,8 @@
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
- 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);
+ 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;
}

@@ -353,8 +359,8 @@
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, event, sizeof(u16));
- status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0);
+ status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
+ event, sizeof(u16), 0, 0);
return status;
}
#endif
@@ -368,7 +374,7 @@
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);
+ status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return status;
}
#endif
@@ -382,8 +388,8 @@
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_docking_station_info));
- status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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
@@ -398,8 +404,8 @@
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, info, *((u16 *) info));
- status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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
@@ -413,8 +419,8 @@
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, info, 64 * 1024);
- status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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;
}

@@ -436,9 +442,8 @@
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, table, *size);
- Q2_SET_SEL(PNP_TS2, size, sizeof(u16));
- status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0);
+ 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
@@ -451,8 +456,8 @@
u16 status;
if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_isa_config_struc));
- status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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;
}

@@ -473,8 +478,8 @@
u16 status;
if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct escd_info_struc));
- status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS);
+ 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;
}

@@ -496,10 +501,8 @@
u16 status;
if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
- set_base(gdt[PNP_TS2 >> 3], nvram_base);
- set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
- status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
+ data, 65536, nvram_base, 65536);
return status;
}

@@ -521,10 +524,8 @@
u16 status;
if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
- set_base(gdt[PNP_TS2 >> 3], nvram_base);
- set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
- status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ 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
@@ -606,7 +607,7 @@
int docked = -1, d = 0;
daemonize();
reparent_to_init();
- strcpy(current->comm, "kpnpbios");
+ strcpy(current->comm, "kpnpbiosd");
while(!unloading && !signal_pending(current))
{
int status;

2002-03-09 15:10:55

by Thomas Hood

[permalink] [raw]
Subject: Re: PnP BIOS driver status

Here are the additional bits from the -ac tree, plus Brian's
SMP fix, diffed against 2.5.6 + 2.5.5-dj3 patch. The changes
include:

- Improve some comments
- Postpone starting the kernel thread (Alan Cox)
- Call kernel thread 'kpnpbiosd' instead of 'kpnpbios'
- Consolidate printing of error messages to save space
- Add __init and __exit tags and return appropriate error codes
- Print slightly more consistent messages
- Get closer to supporting build-as-module
- Make SMP safe (Brian Gerst)

--
Thomas

--- linux-2.5.6_2.5.5-dj3/include/linux/pnpbios.h_DJ Fri Mar 8 18:37:58 2002
+++ linux-2.5.6_2.5.5-dj3/include/linux/pnpbios.h Fri Mar 8 19:43:25 2002
@@ -143,7 +143,8 @@
extern int pnpbios_dont_use_current_config;
extern void *pnpbios_kmalloc(size_t size, int f);
extern int pnpbios_init (void);
-extern void pnpbios_proc_init (void);
+extern int pnpbios_proc_init (void);
+extern void pnpbios_proc_exit (void);

extern int pnp_bios_dev_node_info (struct pnp_dev_node_info *data);
extern int pnp_bios_get_dev_node (u8 *nodenum, char config, struct pnp_bios_node *data);
--- linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_core.c_DJ Fri Mar 8 18:40:02 2002
+++ linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_core.c Sat Mar 9 10:08:21 2002
@@ -4,7 +4,7 @@
* Originally (C) 1998 Christian Schmidt <[email protected]>
* Modifications (c) 1998 Tom Lees <[email protected]>
* Minor reorganizations by David Hinds <[email protected]>
- * Modifications (c) 2001 by Thomas Hood <[email protected]>
+ * Modifications (c) 2001,2002 by Thomas Hood <[email protected]>
*
* 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
@@ -141,7 +141,9 @@
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)
+ 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;
@@ -155,7 +157,12 @@

/* On some boxes IRQ's during PnP BIOS calls are deadly. */
spin_lock_irqsave(&pnp_bios_lock, flags);
- __cli();
+
+ if (ts1_size)
+ Q2_SET_SEL(PNP_TS1, ts1_base, ts1_size);
+ if (ts2_size)
+ Q2_SET_SEL(PNP_TS2, ts2_base, ts2_size);
+
__asm__ __volatile__(
"pushl %%ebp\n\t"
"pushl %%edi\n\t"
@@ -205,6 +212,11 @@
*
*/

+static void pnpbios_warn_unexpected_status(const char * module, u16 status)
+{
+ printk(KERN_ERR "PnPBIOS: %s: Unexpected status 0x%x\n", module, status);
+}
+
void *pnpbios_kmalloc(size_t size, int f)
{
void *p = kmalloc( size, f );
@@ -216,7 +228,7 @@
/*
* Call this only after init time
*/
-static int pnp_bios_present(void)
+static inline int pnp_bios_present(void)
{
return (pnp_bios_hdr != NULL);
}
@@ -251,10 +263,10 @@
static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_dev_node_info));
- status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0);
+ 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;
}
@@ -263,7 +275,7 @@
{
int status = __pnp_bios_dev_node_info( data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: dev_node_info: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "dev_node_info", status );
return status;
}

@@ -284,13 +296,12 @@
static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, nodenum, sizeof(char));
- Q2_SET_SEL(PNP_TS2, data, 64 * 1024);
- status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0);
+ 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;
}

@@ -299,7 +310,7 @@
int status;
status = __pnp_bios_get_dev_node( nodenum, boot, data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: get_dev_node: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "get_dev_node", status );
return status;
}

@@ -313,12 +324,12 @@
static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
if ( !boot & pnpbios_dont_use_current_config )
return PNP_FUNCTION_NOT_SUPPORTED;
- 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);
+ 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;
}

@@ -327,7 +338,7 @@
int status;
status = __pnp_bios_set_dev_node( nodenum, boot, data );
if ( status ) {
- printk(KERN_WARNING "PnPBIOS: set_dev_node: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "set_dev_node", status );
return status;
}
if ( !boot ) { /* Update devlist */
@@ -347,10 +358,10 @@
static int pnp_bios_get_event(u16 *event)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, event, sizeof(u16));
- status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0);
+ status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
+ event, sizeof(u16), 0, 0);
return status;
}
#endif
@@ -362,9 +373,9 @@
static int pnp_bios_send_message(u16 message)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0);
+ status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
return status;
}
#endif
@@ -376,10 +387,10 @@
static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_docking_station_info));
- status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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
@@ -392,10 +403,10 @@
static int pnp_bios_set_stat_res(char *info)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, info, *((u16 *) info));
- status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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
@@ -407,10 +418,10 @@
static int __pnp_bios_get_stat_res(char *info)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, info, 64 * 1024);
- status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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;
}

@@ -419,7 +430,7 @@
int status;
status = __pnp_bios_get_stat_res( info );
if ( status )
- printk(KERN_WARNING "PnPBIOS: get_stat_res: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "get_stat_res", status );
return status;
}

@@ -430,11 +441,10 @@
static int pnp_bios_apm_id_table(char *table, u16 *size)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, table, *size);
- Q2_SET_SEL(PNP_TS2, size, sizeof(u16));
- status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0);
+ 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
@@ -445,10 +455,10 @@
static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return PNP_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct pnp_isa_config_struc));
- status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0);
+ 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;
}

@@ -457,7 +467,7 @@
int status;
status = __pnp_bios_isapnp_config( data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: isapnp_config: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "isapnp_config", status );
return status;
}

@@ -467,10 +477,10 @@
static int __pnp_bios_escd_info(struct escd_info_struc *data)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, sizeof(struct escd_info_struc));
- status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS);
+ 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;
}

@@ -479,7 +489,7 @@
int status;
status = __pnp_bios_escd_info( data );
if ( status )
- printk(KERN_WARNING "PnPBIOS: escd_info: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "escd_info", status );
return status;
}

@@ -490,12 +500,10 @@
static int __pnp_bios_read_escd(char *data, u32 nvram_base)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
- set_base(gdt[PNP_TS2 >> 3], nvram_base);
- set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
- status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ 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;
}

@@ -504,7 +512,7 @@
int status;
status = __pnp_bios_read_escd( data, nvram_base );
if ( status )
- printk(KERN_ERR "PnPBIOS: read_escd: Unexpected status 0x%x\n", status);
+ pnpbios_warn_unexpected_status( "read_escd", status );
return status;
}

@@ -515,12 +523,10 @@
static int pnp_bios_write_escd(char *data, u32 nvram_base)
{
u16 status;
- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return ESCD_FUNCTION_NOT_SUPPORTED;
- Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
- set_base(gdt[PNP_TS2 >> 3], nvram_base);
- set_limit(gdt[PNP_TS2 >> 3], 64 * 1024);
- status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0);
+ status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
+ data, 65536, (void *)nvram_base, 65536);
return status;
}
#endif
@@ -602,10 +608,10 @@
int docked = -1, d = 0;
daemonize();
reparent_to_init();
- strcpy(current->comm, "kpnpbios");
+ strcpy(current->comm, "kpnpbiosd");
while(!unloading && !signal_pending(current))
{
- int err;
+ int status;

/*
* Poll every 2 seconds
@@ -615,9 +621,9 @@
if(signal_pending(current))
break;

- err = pnp_bios_dock_station_info(&now);
+ status = pnp_bios_dock_station_info(&now);

- switch(err)
+ switch(status)
{
/*
* No dock to manage
@@ -631,7 +637,7 @@
d = 1;
break;
default:
- printk(KERN_WARNING "PnPBIOS: pnp_dock_thread: Unexpected status 0x%x\n", err);
+ pnpbios_warn_unexpected_status( "pnp_dock_thread", status );
continue;
}
if(d != docked)
@@ -874,13 +880,13 @@
static void __init build_devlist(void)
{
u8 nodenum;
- int nodes_got = 0;
- int devs = 0;
+ unsigned int nodes_got = 0;
+ unsigned int devs = 0;
struct pnp_bios_node *node;
struct pnp_dev_node_info node_info;
struct pci_dev *dev;

- if (!pnp_bios_present ())
+ if (!pnp_bios_present())
return;

if (pnp_bios_dev_node_info(&node_info) != 0)
@@ -912,7 +918,7 @@
else
devs++;
if (nodenum <= thisnodenum) {
- printk(KERN_ERR "PnPBIOS: build_devlist(): Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (int)nodenum, (int)thisnodenum);
+ printk(KERN_ERR "PnPBIOS: build_devlist: Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (unsigned int)nodenum, (unsigned int)thisnodenum);
break;
}
}
@@ -1215,14 +1221,14 @@
{
union pnp_bios_expansion_header *check;
u8 sum;
- int i, length;
+ int i, length, r;

spin_lock_init(&pnp_bios_lock);
spin_lock_init(&pnpbios_devices_lock);

if(pnpbios_disabled) {
printk(KERN_INFO "PnPBIOS: Disabled\n");
- return 0;
+ return -ENODEV;
}

if ( is_sony_vaio_laptop )
@@ -1264,12 +1270,21 @@
pnp_bios_hdr = check;
break;
}
+ if (!pnp_bios_present())
+ return -ENODEV;
build_devlist();
if ( ! dont_reserve_resources )
reserve_resources();
#ifdef CONFIG_PROC_FS
- pnpbios_proc_init();
+ r = pnpbios_proc_init();
+ if (r)
+ return r;
#endif
+ return 0;
+}
+
+static int __init pnpbios_thread_init(void)
+{
#ifdef CONFIG_HOTPLUG
init_completion(&unload_sem);
if(kernel_thread(pnp_dock_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL)>0)
@@ -1278,23 +1293,46 @@
return 0;
}

-#ifdef MODULE
+#ifndef MODULE
+
+/* init/main.c calls pnpbios_init early */
+
+/* Start the kernel thread later: */
+module_init(pnpbios_thread_init);
+
+#else
+
+/*
+ * N.B.: Building pnpbios as a module hasn't been fully implemented
+ */

MODULE_LICENSE("GPL");

-/* We have to run it early and not as a module. */
-module_init(pnpbios_init);
+static int __init pnpbios_init_all(void)
+{
+ int r;

-#ifdef CONFIG_HOTPLUG
-static void pnpbios_exit(void)
+ r = pnpbios_init();
+ if (r)
+ return r;
+ r = pnpbios_thread_init();
+ if (r)
+ return r;
+ return 0;
+}
+
+static void __exit pnpbios_exit(void)
{
- /* free_resources() ought to go here */
- /* pnpbios_proc_done() */
+#ifdef CONFIG_HOTPLUG
unloading = 1;
wait_for_completion(&unload_sem);
+#endif
+ pnpbios_proc_exit();
+ /* We ought to free resources here */
+ return;
}

+module_init(pnpbios_init_all);
module_exit(pnpbios_exit);

-#endif
#endif
--- linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_proc.c_DJ Fri Mar 8 18:37:58 2002
+++ linux-2.5.6_2.5.5-dj3/drivers/pnp/pnpbios_proc.c Fri Mar 8 19:10:32 2002
@@ -2,7 +2,20 @@
* /proc/bus/pnp interface for Plug and Play devices
*
* Written by David Hinds, [email protected]
- * Modified by Thomas Hood, jdthood_AT_mail.com
+ * Modified by Thomas Hood, [email protected]
+ *
+ * The .../devices and .../<node> and .../boot/<node> files are
+ * utilized by the lspnp and setpnp utilities, supplied with the
+ * pcmcia-cs package.
+ * http://pcmcia-cs.sourceforge.net
+ *
+ * The .../escd file is utilized by the lsescd utility written by
+ * Gunther Mayer.
+ * http://home.t-online.de/home/gunther.mayer/lsescd
+ *
+ * The .../legacy_device_resources file is not used yet.
+ *
+ * The other files are human-readable.
*/

//#include <pcmcia/config.h>
@@ -66,7 +79,7 @@

/* sanity check */
if (escd.escd_size > (32*1024)) {
- printk(KERN_ERR "PnPBIOS: Error: ESCD size is too great\n");
+ printk(KERN_ERR "PnPBIOS: proc_read_escd: ESCD size is too great\n");
return -EFBIG;
}

@@ -122,7 +135,7 @@
node->type_code[0], node->type_code[1],
node->type_code[2], node->flags);
if (nodenum <= thisnodenum) {
- printk(KERN_ERR "PnPBIOS: proc_read_devices(): Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", (int)nodenum, (int)thisnodenum);
+ printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_read_devices:", (unsigned int)nodenum, (unsigned int)thisnodenum);
*eof = 1;
break;
}
@@ -177,20 +190,22 @@
* work and the pnpbios_dont_use_current_config flag
* should already have been set to the appropriate value
*/
-void pnpbios_proc_init( void )
+int __init pnpbios_proc_init( void )
{
struct pnp_bios_node *node;
struct proc_dir_entry *ent;
char name[3];
- int i;
u8 nodenum;

- if (pnp_bios_dev_node_info(&node_info) != 0) return;
+ if (pnp_bios_dev_node_info(&node_info))
+ return -EIO;

proc_pnp = proc_mkdir("pnp", proc_bus);
- if (!proc_pnp) return;
+ if (!proc_pnp)
+ return -EIO;
proc_pnp_boot = proc_mkdir("boot", proc_pnp);
- if (!proc_pnp_boot) return;
+ if (!proc_pnp_boot)
+ return -EIO;
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);
@@ -198,8 +213,11 @@
create_proc_read_entry("legacy_device_resources", 0, proc_pnp, proc_read_legacyres, NULL);

node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
- if (!node) return;
- for (i=0,nodenum = 0; i<0xff && nodenum != 0xff; i++) {
+ if (!node)
+ return -ENOMEM;
+
+ for (nodenum=0; nodenum<0xff; ) {
+ u8 thisnodenum = nodenum;
if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0)
break;
sprintf(name, "%02x", node->handle);
@@ -217,11 +235,17 @@
ent->write_proc = proc_write_node;
ent->data = (void *)(long)(node->handle+0x100);
}
+ if (nodenum <= thisnodenum) {
+ printk(KERN_ERR "%s Node number 0x%x is out of sequence following node 0x%x. Aborting.\n", "PnPBIOS: proc_init:", (unsigned int)nodenum, (unsigned int)thisnodenum);
+ break;
+ }
}
kfree(node);
+
+ return 0;
}

-void pnpbios_proc_done(void)
+void __exit pnpbios_proc_exit(void)
{
int i;
char name[3];
@@ -241,4 +265,6 @@
remove_proc_entry("devices", proc_pnp);
remove_proc_entry("boot", proc_pnp);
remove_proc_entry("pnp", proc_bus);
+
+ return;
}