public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Thomas Hood <jdthood@mail.com>
To: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Andrey Panin <pazke@orbita1.ru>, linux-kernel@vger.kernel.org
Subject: [PATCH] PnP BIOS patch against 2.4.12-ac2
Date: 15 Oct 2001 23:27:32 -0400	[thread overview]
Message-ID: <1003202856.12542.57.camel@thanatos> (raw)
In-Reply-To: <E15t6nz-000205-00@the-village.bc.nu>
In-Reply-To: <E15t6nz-000205-00@the-village.bc.nu>

Here's an updated patch, now against 2.4.12-ac2.

In addition to:
1) Fix bugs in resource reservation:
       - end of reserved range off by +1
       - didn't reserve _all_ system board resources
2) Change code so that set_dev_node updates the devlist, so
   drivers loaded after a setpnp will get up-to-date resource
   information.  Because I haven't protected devlist update
   code with locks, this feature isn't SMP safe yet.
3) Miscellaneous code cleanups.  Use "pnpbios" more consistently.
   Improve printk output.  Etc.
plus (I forget to mention):
4) Don't EXPORT_SYMBOL lowlevel PnP BIOS access functions since
   they aren't used by anything except the proc routines which
   don't need them to be EXPORT_SYMBOL to link to them.

this patch adds:
5) Declare announce_device in header (since it is EXPORT_SYMBOL
   in pnp_bios.c, presumably for a reason).

--
Thomas

The patch:
--- linux-2.4.12-ac2/init/main.c	Sun Oct 14 15:39:55 2001
+++ linux-2.4.12-ac2-fix/init/main.c	Sun Oct 14 15:59:44 2001
@@ -822,7 +822,7 @@
 	isapnp_init();
 #endif
 #ifdef CONFIG_PNPBIOS
-        pnp_bios_init();
+        pnpbios_init();
 #endif
 
 #ifdef CONFIG_TC
--- linux-2.4.12-ac2/include/linux/pnp_bios.h	Wed Oct 10 22:09:57 2001
+++ linux-2.4.12-ac2-fix/include/linux/pnp_bios.h	Mon Oct 15 23:04:21 2001
@@ -132,30 +132,37 @@
 	return (struct pnpbios_driver *)dev->driver;
 }
 
-extern void pnp_bios_init (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);
-extern int pnp_bios_set_dev_node (u8 nodenum, char config, struct pnp_bios_node *data);
-extern int pnp_bios_get_event (u16 *message);
-extern int pnp_bios_send_message (u16 message);
-extern int pnp_bios_set_stat_res (char *info);
-extern int pnp_bios_get_stat_res (char *info);
-extern int pnp_bios_apm_id_table (char *table, u16 *size);
-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_write_escd (char *data, u32 nvram_base);
-
-extern void pnp_proc_init ( int dont_use_current );
-
 #ifdef CONFIG_PNPBIOS
 #define pnpbios_for_each_dev(dev) \
 	for(dev = pnpbios_dev_g(pnpbios_devices.next); dev != pnpbios_dev_g(&pnpbios_devices); dev = pnpbios_dev_g(dev->global_list.next))
-extern int pnp_bios_present (void);
+
+/* exported functions */
 extern struct pci_dev *pnpbios_find_device(char *pnpid, struct pci_dev *dev);
-extern int pnpbios_register_driver(struct pnpbios_driver *drv);
+extern int  pnpbios_announce_device(struct pnpbios_driver *drv, struct pci_dev *dev);
+extern int  pnpbios_register_driver(struct pnpbios_driver *drv);
 extern void pnpbios_unregister_driver(struct pnpbios_driver *drv);
 
+/* non-exported functions */
+extern int  pnpbios_dont_use_current_config;
+extern void *pnpbios_kmalloc(size_t size, int f);
+extern void pnpbios_init (void);
+extern void pnpbios_proc_init (void);
+
+extern int pnpbios_dev_node_info (struct pnp_dev_node_info *data);
+extern int pnpbios_get_dev_node (u8 *nodenum, char config, struct pnp_bios_node *data);
+extern int pnpbios_set_dev_node (u8 nodenum, char config, struct pnp_bios_node *data);
+#if needed
+extern int pnpbios_get_event (u16 *message);
+extern int pnpbios_send_message (u16 message);
+extern int pnpbios_set_stat_res (char *info);
+extern int pnpbios_get_stat_res (char *info);
+extern int pnpbios_apm_id_table (char *table, u16 *size);
+extern int pnpbios_isapnp_config (struct pnp_isa_config_struc *data);
+extern int pnpbios_escd_info (struct escd_info_struc *data);
+extern int pnpbios_read_escd (char *data, u32 nvram_base);
+extern int pnpbios_write_escd (char *data, u32 nvram_base);
+#endif
+
 /*
  * a helper function which helps ensure correct pnpbios_driver
  * setup and cleanup for commonly-encountered hotplug/modular cases
@@ -189,22 +196,17 @@
 	return rc;
 }
 
-#else
+#else /* CONFIG_PNPBIOS */
 #define pnpbios_for_each_dev(dev)	for(dev = NULL; 0; )
 
-static __inline__ int pnp_bios_present (void)
-{
-	return 0;
-}
-
 static __inline__ struct pci_dev *pnpbios_find_device(char *pnpid, struct pci_dev *dev)
 {
 	return NULL;
 }
 
-static __inline__ int pnpbios_module_init(struct pnpbios_driver *drv) 
+static __inline__ int pnpbios_announce_device(struct pnpbios_driver *drv, struct pci_dev *dev)
 {
-	return -ENODEV; 
+	return 0;
 }
 
 static __inline__ int pnpbios_register_driver(struct pnpbios_driver *drv)
@@ -217,7 +219,12 @@
 	return;
 }
 
-#endif
+static __inline__ int pnpbios_module_init(struct pnpbios_driver *drv) 
+{
+	return -ENODEV; 
+}
+
+#endif /* CONFIG_PNPBIOS */
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_PNP_BIOS_H */
--- linux-2.4.12-ac2/drivers/pnp/pnp_bios.c	Wed Oct 10 22:09:19 2001
+++ linux-2.4.12-ac2-fix/drivers/pnp/pnp_bios.c	Mon Oct 15 23:13:34 2001
@@ -50,11 +50,17 @@
 #define PNP_SIGNATURE   (('$' << 0) + ('P' << 8) + ('n' << 16) + ('P' << 24))
 
 /*
+ * Forward declarations
+ */
+
+static void pnpbios_update_devlist( u8 nodenum, struct pnp_bios_node *data );
+
+/*
  * This is the standard structure used to identify the entry point
  * to the Plug and Play bios
  */
 #pragma pack(1)
-union pnpbios {
+union pnp_bios_expansion_header {
 	struct {
 		u32 signature;    /* "$PnP" */
 		u8 version;	  /* in BCD */
@@ -83,7 +89,7 @@
 	u16	segment;
 } pnp_bios_callpoint;
 
-static union pnpbios * pnp_bios_inst_struc = NULL;
+static union pnp_bios_expansion_header * pnp_bios_hdr = NULL;
 
 /* The PnP entries in the GDT */
 #define PNP_GDT		0x0060
@@ -214,12 +220,16 @@
 		printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n");
 	}
 
-//	if ( status ) printk(KERN_WARNING "PnPBIOS: BIOS returned error 0x%x from function 0x%x.\n", status, func);
-		
 	return status;
 }
 
-static void *pnp_bios_kmalloc(size_t size, int f)
+/*
+ *
+ * UTILITY FUNCTIONS
+ *
+ */
+
+void *pnpbios_kmalloc(size_t size, int f)
 {
 	void *p = kmalloc( size, f );
 	if ( p == NULL )
@@ -228,18 +238,29 @@
 }
 
 /*
+ * Call this only after init time
+ */
+static int pnp_bios_is_present(void)
+{
+	return (pnp_bios_hdr != NULL);
+}
+
+/*
  *
  * PnP BIOS ACCESS FUNCTIONS
  *
+ * pnp_bios_*  are local functions used to call the BIOS
+ * pnpbios_* are the public interface to these functions
+ *
  */
 
 /*
  * Call PnP BIOS with function 0x00, "get number of system device nodes"
  */
-static int pnp_bios_dev_node_info_silently(struct pnp_dev_node_info *data)
+static int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_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);
@@ -247,11 +268,11 @@
 	return status;
 }
 
-int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
+int pnpbios_dev_node_info(struct pnp_dev_node_info *data)
 {
-	u16 status = pnp_bios_dev_node_info_silently( data );
+	int status = pnp_bios_dev_node_info( data );
 	if ( status )
-		printk(KERN_WARNING "PnPBIOS: PnP BIOS dev_node_info function returned error status 0x%x\n", status);
+		printk(KERN_WARNING "PnPBIOS: dev_node_info: Unexpected status 0x%x\n", status);
 	return status;
 }
 
@@ -269,22 +290,25 @@
  *               or volatile current (0) config
  * Output: *nodenum=next node or 0xff if no more nodes
  */
-static int pnp_bios_get_dev_node_silently(u8 *nodenum, char boot, struct pnp_bios_node *data)
+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;
 	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);
 	return status;
 }
 
-int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
+int pnpbios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
 {
-	u16 status =  pnp_bios_get_dev_node_silently( nodenum, boot, data );
+	int status;
+	if (!pnp_bios_is_present ())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	if ( !boot & pnpbios_dont_use_current_config )
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status =  pnp_bios_get_dev_node( nodenum, boot, data );
 	if ( status )
-		printk(KERN_WARNING "PnPBIOS: PnP BIOS get_dev_node function returned error status 0x%x\n", status);
+		printk(KERN_WARNING "PnPBIOS: get_dev_node: Unexpected 0x%x\n", status);
 	return status;
 }
 
@@ -294,21 +318,35 @@
  *        boot = whether to set nonvolatile boot (!=0)
  *               or volatile current (0) config
  */
-static int pnp_bios_set_dev_node_silently(u8 nodenum, char boot, struct pnp_bios_node *data)
+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;
 	Q2_SET_SEL(PNP_TS1, data, /* *((u16 *) data)*/ 65536);
 	status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0);
 	return status;
 }
 
-int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
+int pnpbios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
 {
-	u16 status =  pnp_bios_set_dev_node_silently( nodenum, boot, data );
-	if ( status )
-		printk(KERN_WARNING "PnPBIOS: PnP BIOS set_dev_node function returned error status 0x%x\n", status);
+	int status;
+	if (!pnp_bios_is_present ())
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	if ( !boot & pnpbios_dont_use_current_config )
+		return PNP_FUNCTION_NOT_SUPPORTED;
+	status =  pnp_bios_set_dev_node( nodenum, boot, data );
+	if ( status ) {
+		printk(KERN_WARNING "PnPBIOS: set_dev_node: Unexpected set_dev_node status 0x%x\n", status);
+		return status;
+	}
+	if ( !boot ) { /* Update devlist */
+		u8 thisnodenum = nodenum;
+		status =  pnp_bios_get_dev_node( &nodenum, boot, data );
+		if ( status ) {
+			printk(KERN_WARNING "PnPBIOS: set_dev_node: Unexpected get_dev_node status 0x%x\n", status);
+			return status;
+		}
+		pnpbios_update_devlist( thisnodenum, data );
+	}
 	return status;
 }
 
@@ -319,7 +357,7 @@
 static int pnp_bios_get_event(u16 *event)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_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);
@@ -334,7 +372,7 @@
 static int pnp_bios_send_message(u16 message)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0);
 	return status;
@@ -348,7 +386,7 @@
 static int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_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);
@@ -364,7 +402,7 @@
 static int pnp_bios_set_stat_res(char *info)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_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);
@@ -380,7 +418,7 @@
 static int pnp_bios_get_stat_res(char *info)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_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);
@@ -395,7 +433,7 @@
 static int pnp_bios_apm_id_table(char *table, u16 *size)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_present ())
 		return PNP_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, table, *size);
 	Q2_SET_SEL(PNP_TS2, size, sizeof(u16));
@@ -411,7 +449,7 @@
 static int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_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);
@@ -426,7 +464,7 @@
 static int pnp_bios_escd_info(struct escd_info_struc *data)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_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);
@@ -442,7 +480,7 @@
 static int pnp_bios_read_escd(char *data, u32 nvram_base)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_present ())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
 	set_base(gdt[PNP_TS2 >> 3], nvram_base);
@@ -459,7 +497,7 @@
 static int pnp_bios_write_escd(char *data, u32 nvram_base)
 {
 	u16 status;
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_present ())
 		return ESCD_FUNCTION_NOT_SUPPORTED;
 	Q2_SET_SEL(PNP_TS1, data, 64 * 1024);
 	set_base(gdt[PNP_TS2 >> 3], nvram_base);
@@ -469,10 +507,6 @@
 }
 #endif
 
-EXPORT_SYMBOL(pnp_bios_dev_node_info);
-EXPORT_SYMBOL(pnp_bios_get_dev_node);
-EXPORT_SYMBOL(pnp_bios_set_dev_node);
-
 /*
  *
  * PnP DOCKING FUNCTIONS
@@ -482,7 +516,6 @@
 #ifdef CONFIG_HOTPLUG
 
 static int unloading = 0;
-
 static struct completion unload_sem;
 
 /*
@@ -499,10 +532,10 @@
 	if (!current->fs->root) {
 		return -EAGAIN;
 	}
-	if (!(envp = (char **) pnp_bios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
+	if (!(envp = (char **) pnpbios_kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
 		return -ENOMEM;
 	}
-	if (!(buf = pnp_bios_kmalloc (256, GFP_KERNEL))) {
+	if (!(buf = pnpbios_kmalloc (256, GFP_KERNEL))) {
 		kfree (envp);
 		return -ENOMEM;
 	}
@@ -579,7 +612,7 @@
 				d = 1;
 				break;
 			default:
-				printk(KERN_WARNING "PnPBIOS: Unexpected error 0x%x returned by BIOS.\n", err);
+				printk(KERN_WARNING "PnPBIOS: pnp_dock_thread: Unexpected status 0x%x returned by BIOS.\n", err);
 				continue;
 		}
 		if(d != docked)
@@ -587,7 +620,9 @@
 			if(pnp_dock_event(d, &now)==0)
 			{
 				docked = d;
-//				printk(KERN_INFO "PnPBIOS: Docking station %stached.\n", docked?"at":"de");
+#if 0
+				printk(KERN_INFO "PnPBIOS: Docking station %stached.\n", docked?"at":"de");
+#endif
 			}
 		}
 	}	
@@ -598,147 +633,62 @@
 
 /*
  *
- * NODE DATA HANDLING FUNCTIONS
+ * NODE DATA PARSING FUNCTIONS
  *
  */
 
-static void inline pnpbios_add_irqresource(struct pci_dev *dev, int irq)
+static void pnpbios_add_irqresource(struct pci_dev *dev, int irq)
 {
-	// Permit irq==-1 which signifies "disabled"
 	int i = 0;
 	while (!(dev->irq_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_IRQ) i++;
 	if (i < DEVICE_COUNT_IRQ) {
-		dev->irq_resource[i].start = irq;
+		dev->irq_resource[i].start = (unsigned long) irq;
 		dev->irq_resource[i].flags = IORESOURCE_IRQ;  // Also clears _UNSET flag
 	}
 }
 
-static void inline pnpbios_add_dmaresource(struct pci_dev *dev, int dma)
+static void pnpbios_add_dmaresource(struct pci_dev *dev, int dma)
 {
-	// Permit dma==-1 which signifies "disabled"
 	int i = 0;
 	while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++;
 	if (i < DEVICE_COUNT_DMA) {
-		dev->dma_resource[i].start = dma;
+		dev->dma_resource[i].start = (unsigned long) dma;
 		dev->dma_resource[i].flags = IORESOURCE_DMA;  // Also clears _UNSET flag
 	}
 }
 
-static void inline pnpbios_add_ioresource(struct pci_dev *dev, int io, int len)
+static void pnpbios_add_ioresource(struct pci_dev *dev, int io, int len)
 {
 	int i = 0;
 	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
 	if (i < DEVICE_COUNT_RESOURCE) {
-		dev->resource[i].start = io;
-		dev->resource[i].end = io + len;
+		dev->resource[i].start = (unsigned long) io;
+		dev->resource[i].end = (unsigned long)(io + len - 1);
 		dev->resource[i].flags = IORESOURCE_IO;  // Also clears _UNSET flag
 	}
 }
 
-static void inline pnpbios_add_memresource(struct pci_dev *dev, int mem, int len)
+static void pnpbios_add_memresource(struct pci_dev *dev, int mem, int len)
 {
 	int i = 0;
 	while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
 	if (i < DEVICE_COUNT_RESOURCE) {
-		dev->resource[i].start = mem;
-		dev->resource[i].end = mem + len;
+		dev->resource[i].start = (unsigned long) mem;
+		dev->resource[i].end = (unsigned long)(mem + len - 1);
 		dev->resource[i].flags = IORESOURCE_MEM;  // Also clears _UNSET flag
 	}
 }
 
-/*
- * request I/O ports which are used according to the PnP BIOS
- * to avoid I/O conflicts.
- */
-static void mboard_request(char *pnpid, int io, int len)
-{
-	struct resource *res;
-	char *regionid;
-    
-	if (
-		0 != strcmp(pnpid,"PNP0c01") &&  /* memory controller */
-		0 != strcmp(pnpid,"PNP0c02")     /* system peripheral: other */
-	) {
-		return;
-	}
-
-	if (io < 0x100) {
-		/*
-		 * Below 0x100 is only standard PC hardware
-		 * (pics, kbd, timer, dma, ...)
-		 *
-		 * We should not get resource conflicts there,
-		 * and the kernel reserves these anyway
-		 * (see arch/i386/kernel/setup.c).
-		 */
-		return;
-	}
-
-	/*
-	 * Anything else we'll try reserve to avoid these ranges are
-	 * assigned to someone (CardBus bridges for example) and thus are
-	 * triggering resource conflicts.
-	 *
-	 * Failures at this point are usually harmless. pci quirks for
-	 * example do reserve stuff they know about too, so we might have
-	 * double reservations here.
-	 *
-	 * We really shouldn't just reserve these regions, though, since
-	 * that prevents the device drivers from claiming them.
-	 */
-	regionid = pnp_bios_kmalloc(16, GFP_KERNEL);
-	if ( regionid == NULL )
-		return;
-	sprintf(regionid, "PnPBIOS %s", pnpid);
-	res = request_region(io,len,regionid);
-	if ( res == NULL )
-		kfree( regionid );
-	printk(
-		"PnPBIOS: %s: 0x%x-0x%x %s reserved\n",
-		pnpid, io, io+len-1,
-		NULL != res ? "has been" : "was already"
-	);
-
-	return;
-}
-
-
-#define HEX(id,a) hex[((id)>>a) & 15]
-#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
-
-static char * __init pnpid32_to_pnpid(u32 id)
-{
-	const char *hex = "0123456789abcdef";
-	static char str[8];
-	id = be32_to_cpu(id);
-	str[0] = CHAR(id, 26);
-	str[1] = CHAR(id, 21);
-	str[2] = CHAR(id,16);
-	str[3] = HEX(id, 12);
-	str[4] = HEX(id, 8);
-	str[5] = HEX(id, 4);
-	str[6] = HEX(id, 0);
-	str[7] = '\0';
-	return str;
-}                                              
-
-#undef CHAR
-#undef HEX  
-
-/*
- * parse PNPBIOS "Allocated Resources Block" and fill IO,IRQ,DMA into pci_dev
- */
-static void __init pnpbios_rawdata_2_pci_dev(struct pnp_bios_node *node, struct pci_dev *dev)
+static void pnpbios_node_resource_data_to_dev(struct pnp_bios_node *node, struct pci_dev *dev)
 {
 	unsigned char *p = node->data, *lastp=NULL;
 	int i;
 
 	/*
-	 * First, set dev contents to default values
+	 * First, set resource info to default values
 	 */
-	memset(dev,0,sizeof(struct pci_dev));
 	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
-	/*	dev->resource[i].start = 0; */
+		dev->resource[i].start = 0;  // "disabled"
 		dev->resource[i].flags = IORESOURCE_UNSET;
 	}
 	for (i=0;i<DEVICE_COUNT_IRQ;i++) {
@@ -751,7 +701,7 @@
 	}
 
 	/*
-	 * Fill in dev info
+	 * Fill in dev resource info
 	 */
         while ( (char *)p < ((char *)node->data + node->size )) {
         	if(p==lastp) break;
@@ -795,7 +745,7 @@
                 switch (p[0]>>3) {
                 case 0x04: // irq
                 {
-                        int i, mask, irq = -1; // "disabled"
+                        int i, mask, irq = -1;
                         mask= p[1] + p[2]*256;
                         for (i=0;i<16;i++, mask=mask>>1)
                                 if(mask & 0x01) irq=i;
@@ -804,7 +754,7 @@
                 }
                 case 0x05: // dma
                 {
-                        int i, mask, dma = -1; // "disabled"
+                        int i, mask, dma = -1;
                         mask = p[1];
                         for (i=0;i<8;i++, mask = mask>>1)
                                 if(mask & 0x01) dma=i;
@@ -816,7 +766,6 @@
 			int io= p[2] + p[3] *256;
 			int len = p[7];
 			pnpbios_add_ioresource(dev, io, len);
-			mboard_request(pnpid32_to_pnpid(node->eisa_id),io,len);
                         break;
                 }
 		case 0x09: // fixed location io
@@ -843,42 +792,53 @@
 
 static LIST_HEAD(pnpbios_devices);
 
-int pnp_bios_present(void)
-{
-	return (pnp_bios_inst_struc != NULL);
-}
-
-EXPORT_SYMBOL(pnp_bios_present);
-
-static int __init pnpbios_insert_device(struct pci_dev *dev)
+static int inline pnpbios_insert_device(struct pci_dev *dev)
 {
 	/* FIXME: Need to check for re-add of existing node */
 	list_add_tail(&dev->global_list, &pnpbios_devices);
 	return 0;
 }
 
-/*
- *	Build the list of pci_dev objects from the PnP table
- */
- 
+#define HEX(id,a) hex[((id)>>a) & 15]
+#define CHAR(id,a) (0x40 + (((id)>>a) & 31))
+//
+static void inline pnpid32_to_pnpid(u32 id, char *str)
+{
+	const char *hex = "0123456789abcdef";
+
+	id = be32_to_cpu(id);
+	str[0] = CHAR(id, 26);
+	str[1] = CHAR(id, 21);
+	str[2] = CHAR(id,16);
+	str[3] = HEX(id, 12);
+	str[4] = HEX(id, 8);
+	str[5] = HEX(id, 4);
+	str[6] = HEX(id, 0);
+	str[7] = '\0';
+
+	return;
+}                                              
+//
+#undef CHAR
+#undef HEX 
+
 static void __init pnpbios_build_devlist(void)
 {
 	int i;
 	int nodenum;
 	int nodes_got = 0;
+	int devs = 0;
 	struct pnp_bios_node *node;
 	struct pnp_dev_node_info node_info;
 	struct pci_dev *dev;
-	char *pnpid;
-
 	
-	if (!pnp_bios_present ())
+	if (!pnp_bios_is_present ())
 		return;
 
 	if (pnp_bios_dev_node_info(&node_info) != 0)
 		return;
 
-	node = pnp_bios_kmalloc(node_info.max_node_size, GFP_KERNEL);
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node)
 		return;
 
@@ -891,22 +851,45 @@
 		if (pnp_bios_get_dev_node((u8 *)&nodenum, (char )1 , node))
 			break;
 		nodes_got++;
-		dev =  pnp_bios_kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
+		dev =  pnpbios_kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
 		if (!dev)
 			break;
-		pnpbios_rawdata_2_pci_dev(node,dev);
+		memset(dev,0,sizeof(struct pci_dev));
 		dev->devfn=thisnodenum;
-		pnpid = pnpid32_to_pnpid(node->eisa_id);
 		memcpy(dev->name,"PNPBIOS",8);
-		memcpy(dev->slot_name,pnpid,8);
+		pnpid32_to_pnpid(node->eisa_id,dev->slot_name);
+		pnpbios_node_resource_data_to_dev(node,dev);
 		if(pnpbios_insert_device(dev)<0)
 			kfree(dev);
+		devs++;
 	}
 	kfree(node);
 
-	printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS\n", nodes_got, nodes_got != 1 ? "s" : "");
+	printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS; %i recorded by driver.\n",
+		nodes_got, nodes_got != 1 ? "s" : "", devs);
 }
 
+static struct pci_dev *pnpbios_find_device_by_nodenum( u8 nodenum )
+{
+	struct pci_dev *dev;
+
+	pnpbios_for_each_dev(dev) {
+		if(dev->devfn == nodenum)
+			return dev;
+	}
+
+	return NULL;
+}
+
+static void pnpbios_update_devlist( u8 nodenum, struct pnp_bios_node *data )
+{
+	struct pci_dev *dev = pnpbios_find_device_by_nodenum( nodenum );
+	if ( dev ) {
+		pnpbios_node_resource_data_to_dev(data,dev);
+	}
+
+	return;
+}
 
 /*
  *
@@ -920,22 +903,19 @@
 struct pci_dev *pnpbios_find_device(char *pnpid, struct pci_dev *prev)
 {
 	struct pci_dev *dev;
-	int num;
-
-	if(prev==NULL)
-		num=0; /* Start from beginning */
-	else
-		num=prev->devfn + 1; /* Encode node number here */
+	int nodenum;
 
+	nodenum = 0;
+	if(prev)
+		nodenum=prev->devfn + 1; /* Encode node number here */
 
-	pnpbios_for_each_dev(dev)
-	{
-		if(dev->devfn >= num)
-		{
+	pnpbios_for_each_dev(dev) {
+		if(dev->devfn >= nodenum) {
 			if(memcmp(dev->slot_name, pnpid, 7)==0)
 				return dev;
 		}
 	}
+
 	return NULL;
 }
 
@@ -969,8 +949,7 @@
 	return NULL;
 }
 
-static int
-pnpbios_announce_device(struct pnpbios_driver *drv, struct pci_dev *dev)
+int pnpbios_announce_device(struct pnpbios_driver *drv, struct pci_dev *dev)
 {
 	const struct pnpbios_device_id *id;
 	int ret = 0;
@@ -1049,54 +1028,145 @@
 
 EXPORT_SYMBOL(pnpbios_unregister_driver);
 
+/*
+ *
+ * RESOURCE RESERVATION FUNCTIONS
+ *
+ */
+
+static void __init pnpbios_reserve_resource_range(char *pnpid, int start, int end)
+{
+	struct resource *res;
+	char *regionid;
+
+	regionid = pnpbios_kmalloc(16, GFP_KERNEL);
+	if ( regionid == NULL )
+		return;
+	sprintf(regionid, "PnPBIOS %s", pnpid);
+	res = request_region(start,end-start+1,regionid);
+	if ( res == NULL )
+		kfree( regionid );
+	/*
+	 * Failures at this point are usually harmless. pci quirks for
+	 * example do reserve stuff they know about too, so we may well
+	 * have double reservations.
+	 */
+	printk(
+		"PnPBIOS: %s: 0x%x-0x%x %s reserved\n",
+		pnpid, start, end,
+		NULL != res ? "has been" : "was already"
+	);
+
+	return;
+}
+
+static void __init pnpbios_reserve_resources_of_dev( struct pci_dev *dev )
+{
+	int i;
+
+	for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
+		if ( dev->resource[i].flags & IORESOURCE_UNSET )
+			/* resource record not used */
+			break;
+		if ( dev->resource[i].start == 0 )
+			/* resource disabled */
+			continue;
+		if ( dev->resource[i].start < 0x100 )
+			/*
+			 * Below 0x100 is only standard PC hardware
+			 * (pics, kbd, timer, dma, ...)
+			 *
+			 * We should not get resource conflicts there,
+			 * and the kernel reserves these anyway
+			 * (see arch/i386/kernel/setup.c).
+			 */
+			continue;
+		if ( dev->resource[i].end < dev->resource[i].start )
+			/* insane */
+			continue;
+		pnpbios_reserve_resource_range(
+			dev->slot_name,
+			dev->resource[i].start,
+			dev->resource[i].end
+		);
+	}
+
+	return;
+}
+
+/*
+ * Reserve resources used by system board devices
+ *
+ * We really shouldn't just _reserve_ these regions since
+ * that prevents the device drivers from claiming them.
+ */
+static void __init pnpbios_reserve_resources( void )
+{
+	struct pci_dev *dev;
+
+	pnpbios_for_each_dev(dev) {
+		if (
+			0 != strcmp(dev->slot_name,"PNP0c01") &&  /* memory controller */
+			0 != strcmp(dev->slot_name,"PNP0c02")     /* system peripheral: other */
+		) {
+			continue;
+		}  
+		pnpbios_reserve_resources_of_dev(dev);
+	}
+
+	return;
+}
+
 /* 
  *
  * INIT AND EXIT
  *
  *
- * Search the defined area (0xf0000-0xffff0) for a valid PnP BIOS
- * structure and, if one is found, sets up the selectors and
- * entry points
  */
 
 extern int is_sony_vaio_laptop;
 
-static int pnp_bios_disabled;
-static int pnp_bios_dont_use_current_config;
+static int pnpbios_disabled;
+int pnpbios_dont_use_current_config;
 
-static int disable_pnp_bios(char *str)
+static int __init pnpbios_disable_pnp_bios(char *str)
 {
-	pnp_bios_disabled=1;
+	pnpbios_disabled=1;
 	return 0;
 }
 
-static int disable_use_of_current_config(char *str)
+static int __init pnpbios_disable_use_of_current_config(char *str)
 {
-	pnp_bios_dont_use_current_config=1;
+	pnpbios_dont_use_current_config=1;
 	return 0;
 }
 
-__setup("nobiospnp", disable_pnp_bios);
-__setup("nobioscurrpnp", disable_use_of_current_config);
+__setup("nobiospnp", pnpbios_disable_pnp_bios);
+__setup("nobioscurrpnp", pnpbios_disable_use_of_current_config);
 
-void pnp_bios_init(void)
+void __init pnpbios_init(void)
 {
-	union pnpbios *check;
+	union pnp_bios_expansion_header *check;
 	u8 sum;
 	int i, length;
 
 	spin_lock_init(&pnp_bios_lock);
 
-	if(pnp_bios_disabled) {
+	if(pnpbios_disabled) {
 		printk(KERN_INFO "PnPBIOS: Disabled.\n");
 		return;
 	}
 
 	if ( is_sony_vaio_laptop )
-		pnp_bios_dont_use_current_config = 1;
+		pnpbios_dont_use_current_config = 1;
 
-	for (check = (union pnpbios *) __va(0xf0000);
-	     check < (union pnpbios *) __va(0xffff0);
+	/*
+ 	 * 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;
@@ -1123,12 +1193,14 @@
 		Q_SET_SEL(PNP_DS, check->fields.pm16dseg, 64 * 1024);
 		pnp_bios_callpoint.offset = check->fields.pm16offset;
 		pnp_bios_callpoint.segment = PNP_CS16;
-		pnp_bios_inst_struc = check;
+		pnp_bios_hdr = check;
 		break;
 	}
+
 	pnpbios_build_devlist();
+	pnpbios_reserve_resources();
 #ifdef CONFIG_PROC_FS
-	pnp_proc_init( pnp_bios_dont_use_current_config );
+	pnpbios_proc_init();
 #endif
 #ifdef CONFIG_HOTPLUG	
 	init_completion(&unload_sem);
@@ -1142,16 +1214,18 @@
 MODULE_LICENSE("GPL");
 
 /* We have to run it early and specifically in non modular.. */
-module_init(pnp_bios_init);
+module_init(pnpbios_init);
 
 #ifdef CONFIG_HOTPLUG
-static void pnp_bios_exit(void)
+static void pnpbios_exit(void)
 {
+	/* free_resources() ought to go here */
+	/* pnpbios_proc_done() */
 	unloading = 1;
 	wait_for_completion(&unload_sem);
 }
 
-module_exit(pnp_bios_exit);
+module_exit(pnpbios_exit);
 
 #endif
 #endif
--- linux-2.4.12-ac2/drivers/pnp/pnp_proc.c	Wed Oct 10 22:09:19 2001
+++ linux-2.4.12-ac2-fix/drivers/pnp/pnp_proc.c	Sun Oct 14 15:59:44 2001
@@ -31,10 +31,10 @@
 	    *eof = 1;
 	    return 0;
 	}
-	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
 	for (i=0,nodenum=0;i<0xff && nodenum!=0xff; i++) {
-		if ( pnp_bios_get_dev_node(&nodenum, 1, node) )
+		if ( pnpbios_get_dev_node(&nodenum, 1, node) )
 			break;
 		p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
 			     node->handle, node->eisa_id,
@@ -57,9 +57,9 @@
 	    *eof = 1;
 	    return 0;
 	}
-	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	if ( pnp_bios_get_dev_node(&nodenum, boot, node) )
+	if ( pnpbios_get_dev_node(&nodenum, boot, node) )
 		return -EIO;
 	len = node->size - sizeof(struct pnp_bios_node);
 	memcpy(buf, node->data, len);
@@ -74,22 +74,25 @@
 	int boot = (long)data >> 8;
 	u8 nodenum = (long)data;
 
-	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return -ENOMEM;
-	if ( pnp_bios_get_dev_node(&nodenum, boot, node) )
+	if ( pnpbios_get_dev_node(&nodenum, boot, node) )
 		return -EIO;
 	if (count != node->size - sizeof(struct pnp_bios_node))
 		return -EINVAL;
 	memcpy(node->data, buf, count);
-	if (pnp_bios_set_dev_node(node->handle, boot, node) != 0)
+	if (pnpbios_set_dev_node(node->handle, boot, node) != 0)
 	    return -EINVAL;
 	kfree(node);
 	return count;
 }
 
-static int pnp_proc_dont_use_current_config;
-
-void pnp_proc_init( int dont_use_current )
+/*
+ * When this is called, pnpbios functions are assumed to
+ * work and the pnpbios_dont_use_current_config flag
+ * should already have been set to the appropriate value
+ */
+void pnpbios_proc_init( void )
 {
 	struct pnp_bios_node *node;
 	struct proc_dir_entry *ent;
@@ -97,10 +100,7 @@
 	int i;
 	u8 nodenum;
 
-	pnp_proc_dont_use_current_config = dont_use_current;
-
-	if (!pnp_bios_present()) return;
-	if (pnp_bios_dev_node_info(&node_info) != 0) return;
+	if (pnpbios_dev_node_info(&node_info) != 0) return;
 	
 	proc_pnp = proc_mkdir("pnp", proc_bus);
 	if (!proc_pnp) return;
@@ -108,13 +108,13 @@
 	if (!proc_pnp_boot) return;
 	create_proc_read_entry("devices", 0, proc_pnp, proc_read_devices, NULL);
 	
-	node = kmalloc(node_info.max_node_size, GFP_KERNEL);
+	node = pnpbios_kmalloc(node_info.max_node_size, GFP_KERNEL);
 	if (!node) return;
 	for (i=0,nodenum = 0; i<0xff && nodenum != 0xff; i++) {
-		if (pnp_bios_get_dev_node(&nodenum, 1, node) != 0)
+		if (pnpbios_get_dev_node(&nodenum, 1, node) != 0)
 			break;
 		sprintf(name, "%02x", node->handle);
-		if ( !pnp_proc_dont_use_current_config ) {
+		if ( !pnpbios_dont_use_current_config ) {
 			ent = create_proc_entry(name, 0, proc_pnp);
 			if (ent) {
 				ent->read_proc = proc_read_node;
@@ -132,7 +132,7 @@
 	kfree(node);
 }
 
-void pnp_proc_done(void)
+void pnpbios_proc_done(void)
 {
 	int i;
 	char name[3];
@@ -141,7 +141,7 @@
 
 	for (i=0; i<0xff; i++) {
 		sprintf(name, "%02x", i);
-		if ( !pnp_proc_dont_use_current_config )
+		if ( !pnpbios_dont_use_current_config )
 			remove_proc_entry(name, proc_pnp);
 		remove_proc_entry(name, proc_pnp_boot);
 	}


  parent reply	other threads:[~2001-10-16  3:29 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-10-13 15:40 [PATCH] PnP BIOS -- bugfix; update devlist on setpnp Thomas Hood
2001-10-15  6:37 ` Jurgen Botz
2001-10-15  9:45   ` Stelian Pop
2001-10-15 12:01     ` Andrey Panin
2001-10-15 12:25       ` Alan Cox
2001-10-15 21:49         ` Thomas Hood
2001-10-16  3:27         ` Thomas Hood [this message]
2001-10-16  7:58           ` [PATCH] PnP BIOS patch against 2.4.12-ac2 Jörg Ziuber
2001-10-16 21:44             ` Thomas Hood
2001-10-17  6:28               ` Jörg Ziuber
2001-10-17 13:41                 ` Thomas Hood
2001-10-17 14:43                   ` Jörg Ziuber
2001-10-17 20:43                     ` Thomas Hood
2001-10-15 14:15 ` [PATCH] PnP BIOS -- bugfix; update devlist on setpnp Ion Badulescu
2001-10-17  2:48 ` Steven A. DuChene

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=1003202856.12542.57.camel@thanatos \
    --to=jdthood@mail.com \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pazke@orbita1.ru \
    /path/to/YOUR_REPLY

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

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