Re: PnP BIOS + 2.4.9-ac16 = no boot

Thomas Hood
2001-09-28T14:33:58Z

[-- Attachment #1: Type: text/plain, Size: 220 bytes --]

Hi Stelian.

Try this patch. It is a modification of the latest
pnpbios driver patch to 2.4.9-ac16 which includes
hacks to work on a Vaio laptop. If this works then
I'll clean it up a bit and submit to Alan.

--
Thomas

[-- Attachment #2: thood-pnpbiosvaio-patch-20010928-3 --]
[-- Type: text/plain, Size: 13821 bytes --]

diff -Naur -5 pnp_ORIG/pnp_bios.c pnp/pnp_bios.c
--- pnp_ORIG/pnp_bios.c Thu Sep 27 15:21:46 2001
+++ pnp/pnp_bios.c Fri Sep 28 10:25:38 2001
@@ -484,11 +484,11 @@
envp [i++] = scratch;
scratch += sprintf (scratch, "ACTION=%s", dock?"add":"remove") + 1;

/* Report the ident for the dock */
envp [i++] = scratch;
- scratch += sprintf (scratch, "DOCK=%x/%x/%x",
+ scratch += sprintf (scratch, "DOCK=0x%x/0x%x/0x%x",
info->location_id, info->serial, info->capabilities);
envp[i] = 0;

value = call_usermodehelper (argv [0], argv, envp);
kfree (buf);
@@ -552,14 +552,13 @@
complete_and_exit(&unload_sem, 0);
}

#endif

-/*
- * Searches the defined area (0xf0000-0xffff0) for a valid PnP BIOS
- * structure and, if found one, sets up the selectors and entry points
- */
+extern int is_sony_vaio_laptop;
+int pnp_bios_dont_use_current;
+EXPORT_SYMBOL(pnp_bios_dont_use_current);

static int pnp_bios_disabled;

static int disable_pnp_bios(char *str)
{
@@ -567,10 +566,15 @@
return 0;
}

__setup("nobiospnp", disable_pnp_bios);

+/*
+ * Searches the defined area (0xf0000-0xffff0) for a valid PnP BIOS
+ * structure and, if found one, sets up the selectors and entry points
+ */
+
void pnp_bios_init(void)
{
union pnpbios *check;
u8 sum;
int i, length;
@@ -580,10 +584,16 @@
if(pnp_bios_disabled)
{
printk(KERN_INFO "PNP BIOS services disabled.\n");
return;
}
+
+ if ( is_sony_vaio_laptop )
+ pnp_bios_dont_use_current = 1;
+ else
+ pnp_bios_dont_use_current = 0;
+
for (check = (union pnpbios *) __va(0xf0000);
check < (union pnpbios *) __va(0xffff0);
((void *) (check)) += 16) {
if (check->fields.signature != PNP_SIGNATURE)
continue;
@@ -593,18 +603,18 @@
for (sum = 0, i = 0; i < length; i++)
sum += check->chars[i];
if (sum)
continue;
if (check->fields.version < 0x10) {
- printk(KERN_WARNING "PnP: unsupported version %d.%d",
+ printk(KERN_WARNING "PnPBIOS: unsupported version %d.%d",
check->fields.version >> 4,
check->fields.version & 15);
continue;
}
- printk(KERN_INFO "PnP: PNP BIOS installation structure at 0x%p\n",
+ printk(KERN_INFO "PnPBIOS: PnP BIOS installation structure at 0x%p\n",
check);
- printk(KERN_INFO "PnP: PNP BIOS version %d.%d, entry at %x:%x, dseg at %x\n",
+ printk(KERN_INFO "PnPBIOS: PnP BIOS version %d.%d, entry at 0x%x:0x%x, dseg at 0x%x\n",
check->fields.version >> 4, check->fields.version & 15,
check->fields.pm16cseg, check->fields.pm16offset,
check->fields.pm16dseg);
Q2_SET_SEL(PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
Q_SET_SEL(PNP_CS16, check->fields.pm16cseg, 64 * 1024);
@@ -644,33 +654,49 @@
EXPORT_SYMBOL(pnp_bios_present);
EXPORT_SYMBOL(pnp_bios_dev_node_info);

static void inline pnpbios_add_irqresource(struct pci_dev *dev, int irq)
{
+ // Permit irq==-1 which signifies "disabled"
int i = 0;
- while (dev->irq_resource[i].start && i < DEVICE_COUNT_IRQ) i++;
- if (i < DEVICE_COUNT_IRQ)
+ while (!(dev->irq_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_IRQ) i++;
+ if (i < DEVICE_COUNT_IRQ) {
dev->irq_resource[i].start = irq;
+ dev->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
+ }
}

static void inline pnpbios_add_dmaresource(struct pci_dev *dev, int dma)
{
+ // Permit dma==-1 which signifies "disabled"
int i = 0;
- while (dev->dma_resource[i].start && i < DEVICE_COUNT_DMA) i++;
- if (i < DEVICE_COUNT_DMA)
+ while (!(dev->dma_resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_DMA) i++;
+ if (i < DEVICE_COUNT_DMA) {
dev->dma_resource[i].start = dma;
+ dev->dma_resource[i].flags = IORESOURCE_DMA; // Also clears _UNSET flag
+ }
}

-static void __init pnpbios_add_ioresource(struct pci_dev *dev, int io,
- int len, int flags)
+static void __init pnpbios_add_ioresource(struct pci_dev *dev, int io, int len)
{
int i = 0;
- while (dev->resource[i].start && i < DEVICE_COUNT_RESOURCE) i++;
+ while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
if (i < DEVICE_COUNT_RESOURCE) {
dev->resource[i].start = io;
dev->resource[i].end = io + len;
- dev->resource[i].flags = flags;
+ dev->resource[i].flags = IORESOURCE_IO; // Also clears _UNSET flag
+ }
+}
+
+static void __init pnpbios_add_memresource(struct pci_dev *dev, int io, int len)
+{
+ int i = 0;
+ while (!(dev->resource[i].flags & IORESOURCE_UNSET) && i < DEVICE_COUNT_RESOURCE) i++;
+ if (i < DEVICE_COUNT_RESOURCE) {
+ dev->resource[i].start = io;
+ dev->resource[i].end = io + len;
+ dev->resource[i].flags = IORESOURCE_MEM; // Also clears _UNSET flag
}
}

static char * __init pnpid32_to_pnpid(u32 id);

@@ -678,22 +704,22 @@
* request I/O ports which are used according to the PnP BIOS
* to avoid I/O conflicts.
*/
static void mboard_request(char *pnpid, int io, int len)
{
- struct ressource *res;
+ struct resource *res;

if (0 != strcmp(pnpid,"PNP0c01") && /* memory controller */
0 != strcmp(pnpid,"PNP0c02")) /* system peripheral: other */
return;

if (io < 0x100) {
/*
* below 0x100 is only standard PC hardware
* (pics, kbd, timer, dma, ...)
*
- * We should not get ressource conflicts there,
+ * We should not get resource conflicts there,
* and the kernel reserves these anyway
* (see arch/i386/kernel/setup.c).
*/
return;
}
@@ -714,75 +740,91 @@

/* parse PNPBIOS "Allocated Resources Block" and fill IO,IRQ,DMA into pci_dev */
static void __init pnpbios_rawdata_2_pci_dev(struct pnp_bios_node *node, struct pci_dev *pci_dev)
{
unsigned char *p = node->data, *lastp=NULL;
- int mask,i,io,irq,len,dma;

- memset(pci_dev, 0, sizeof(struct pci_dev));
while ( (char *)p < ((char *)node->data + node->size )) {
if(p==lastp) break;

if( p[0] & 0x80 ) {// large item
switch (p[0] & 0x7f) {
case 0x01: // memory
- io = *(short *) &p[4];
- len = *(short *) &p[10];
- pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_MEM);
+ {
+ int io = *(short *) &p[4];
+ int len = *(short *) &p[10];
+ pnpbios_add_memresource(pci_dev, io, len);
break;
+ }
case 0x02: // device name
- len = *(short *) &p[1];
+ {
+ int len = *(short *) &p[1];
memcpy(pci_dev->name, p + 3, len >= 80 ? 79 : len);
break;
+ }
case 0x05: // 32-bit memory
- io = *(int *) &p[4];
- len = *(int *) &p[16];
- pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_MEM);
+ {
+ int io = *(int *) &p[4];
+ int len = *(int *) &p[16];
+ pnpbios_add_memresource(pci_dev, io, len);
break;
+ }
case 0x06: // fixed location 32-bit memory
- io = *(int *) &p[4];
- len = *(int *) &p[8];
- pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_MEM);
+ {
+ int io = *(int *) &p[4];
+ int len = *(int *) &p[8];
+ pnpbios_add_memresource(pci_dev, io, len);
break;
}
+ } /* switch */
lastp = p+3;
p = p + p[1] + p[2]*256 + 3;
continue;
}
if ((p[0]>>3) == 0x0f) // end tag
break;
switch (p[0]>>3) {
case 0x04: // irq
- irq = -1;
+ {
+ int i, mask, irq = -1; // "disabled"
mask= p[1] + p[2]*256;
for (i=0;i<16;i++, mask=mask>>1)
- if(mask &0x01) irq=i;
+ if(mask & 0x01) irq=i;
pnpbios_add_irqresource(pci_dev, irq);
break;
+ }
case 0x05: // dma
- dma = -1;
+ {
+ int i, mask, dma = -1; // "disabled"
mask = p[1];
for (i=0;i<8;i++, mask = mask>>1)
- if(mask&0x01) dma=i;
+ if(mask & 0x01) dma=i;
pnpbios_add_dmaresource(pci_dev, dma);
break;
+ }
case 0x08: // io
- io= p[2] + p[3] *256;
- len = p[7];
- pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_IO);
+ {
+ int io= p[2] + p[3] *256;
+ int len = p[7];
+ pnpbios_add_ioresource(pci_dev, io, len);
mboard_request(pnpid32_to_pnpid(node->eisa_id),io,len);
break;
+ }
case 0x09: // fixed location io
- io = p[1] + p[2] * 256;
- len = p[3];
- pnpbios_add_ioresource(pci_dev, io, len, IORESOURCE_IO);
+ {
+ int io = p[1] + p[2] * 256;
+ int len = p[3];
+ pnpbios_add_ioresource(pci_dev, io, len);
break;
- }
+ }
+ } /* switch */
lastp=p+1;
p = p + (p[0] & 0x07) + 1;

- }
+ } /* while */
+
+ return;
}

#define HEX(id,a) hex[((id)>>a) & 15]
#define CHAR(id,a) (0x40 + (((id)>>a) & 31))

@@ -816,21 +858,49 @@
/* FIXME: Need to check for re-add of existing node */
list_add_tail(&dev->global_list, &pnpbios_devices);
return 0;
}

+static struct pci_dev * __init pnpbios_kmalloc_pci_dev( void )
+{
+ struct pci_dev *dev;
+ int i;
+
+ dev = kmalloc( sizeof(struct pci_dev), GFP_KERNEL );
+ if (!dev)
+ return NULL;
+
+ memset(dev,0,sizeof(struct pci_dev));
+
+ for (i=0;i<DEVICE_COUNT_RESOURCE;i++) {
+ /* dev->resource[i].start = 0; */
+ dev->resource[i].flags = IORESOURCE_UNSET;
+ }
+ for (i=0;i<DEVICE_COUNT_IRQ;i++) {
+ dev->irq_resource[i].start = (unsigned long)-1; // "disabled"
+ dev->irq_resource[i].flags = IORESOURCE_UNSET;
+ }
+ for (i=0;i<DEVICE_COUNT_DMA;i++) {
+ dev->dma_resource[i].start = (unsigned long)-1; // "disabled"
+ dev->dma_resource[i].flags = IORESOURCE_UNSET;
+ }
+
+ return dev;
+}
+
/*
* Build the list of pci_dev objects from the PnP table
*/

static void __init pnpbios_build_devlist(void)
{
- int i, devs = 0;
+ int i;
+ int nodes_got = 0;
struct pnp_bios_node *node;
struct pnp_dev_node_info node_info;
struct pci_dev *dev;
- int num;
+ int nodenum;
char *pnpid;

if (!pnp_bios_present ())
return;
@@ -840,33 +910,33 @@

node = kmalloc(node_info.max_node_size, GFP_KERNEL);
if (!node)
return;

- for(i=0;i<0xff;i++) {
- dev = kmalloc(sizeof (struct pci_dev), GFP_KERNEL);
+ for(i=0,nodenum=0;i<0xff && nodenum!=0xff;i++) {
+ int thisnodenum = nodenum;
+ if (pnp_bios_get_dev_node(
+ (u8 *)&nodenum,
+ pnp_bios_dont_use_current ? (char) 1 : (char ) 0,
+ node)
+ )
+ continue;
+ nodes_got++;
+ dev = pnpbios_kmalloc_pci_dev();
if (!dev)
break;
-
- if (pnp_bios_get_dev_node((u8 *)&num, (char )0 , node))
- continue;
-
- devs++;
pnpbios_rawdata_2_pci_dev(node,dev);
- dev->devfn=num;
+ dev->devfn=thisnodenum;
pnpid = pnpid32_to_pnpid(node->eisa_id);
memcpy(dev->name,"PNPBIOS",8);
memcpy(dev->slot_name,pnpid,8);
if(pnpbios_insert_device(dev)<0)
kfree(dev);
}
kfree(node);

- if (devs)
- printk(KERN_INFO "PnP: %i device%s detected total\n", devs, devs > 1 ? "s" : "");
- else
- printk(KERN_INFO "PnP: No devices found\n");
+ printk(KERN_INFO "PnPBIOS: %i node%s reported by PnP BIOS\n", nodes_got, nodes_got != 1 ? "s" : "");
}

/*
* The public interface to PnP BIOS enumeration
diff -Naur -5 pnp_ORIG/pnp_proc.c pnp/pnp_proc.c
--- pnp_ORIG/pnp_proc.c Thu Sep 27 15:21:46 2001
+++ pnp/pnp_proc.c Fri Sep 28 10:28:31 2001
@@ -13,10 +13,11 @@
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/pnp_bios.h>

+extern int pnp_bios_dont_use_current;
static struct proc_dir_entry *proc_pnp = NULL;
static struct proc_dir_entry *proc_pnp_boot = NULL;
static struct pnp_dev_node_info node_info;

static int proc_read_devices(char *buf, char **start, off_t pos,
@@ -31,11 +32,11 @@
return 0;
}
node = kmalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) return -ENOMEM;
for (num = 0; num != 0xff; ) {
- pnp_bios_get_dev_node(&num, 0, node);
+ pnp_bios_get_dev_node(&num, 1, node);
p += sprintf(p, "%02x\t%08x\t%02x:%02x:%02x\t%04x\n",
node->handle, node->eisa_id,
node->type_code[0], node->type_code[1],
node->type_code[2], node->flags);
}
@@ -103,18 +104,20 @@

node = kmalloc(node_info.max_node_size, GFP_KERNEL);
if (!node) return;
for (num = 0; num != 0xff; ) {
//sprintf(name, "%02x", num);
- if (pnp_bios_get_dev_node(&num, 0, node) != 0)
+ if (pnp_bios_get_dev_node(&num, 1, node) != 0)
break;
sprintf(name, "%02x", node->handle);
- ent = create_proc_entry(name, 0, proc_pnp);
- if (ent) {
- ent->read_proc = proc_read_node;
- ent->write_proc = proc_write_node;
- ent->data = (void *)(long)(node->handle);
+ if ( !pnp_bios_dont_use_current ) {
+ ent = create_proc_entry(name, 0, proc_pnp);
+ if (ent) {
+ ent->read_proc = proc_read_node;
+ ent->write_proc = proc_write_node;
+ ent->data = (void *)(long)(node->handle);
+ }
}
ent = create_proc_entry(name, 0, proc_pnp_boot);
if (ent) {
ent->read_proc = proc_read_node;
ent->write_proc = proc_write_node;
@@ -130,11 +133,13 @@
char name[3];

if (!proc_pnp) return;
for (num = 0; num != 0xff; num++) {
sprintf(name, "%02x", num);
- remove_proc_entry(name, proc_pnp);
+ if ( !pnp_bios_dont_use_current ) {
+ remove_proc_entry(name, proc_pnp);
+ }
remove_proc_entry(name, proc_pnp_boot);
}
remove_proc_entry("boot", proc_pnp);
remove_proc_entry("devices", proc_pnp);
remove_proc_entry("pnp", proc_bus);