--- grub-0.91/netboot/pci.c.org	Thu Jan  3 08:23:29 2002
+++ grub-0.91/netboot/pci.c	Thu Mar 21 17:43:38 2002
@@ -499,3 +499,97 @@
 		pcibios_write_config_byte(p->bus, p->devfn, PCI_LATENCY_TIMER, 32);
 	}
 }
+
+#define EIO              5      /* I/O error */
+#define EINVAL          22      /* Invalid argument */
+
+#define PCI_STATUS              0x06    /* 16 bits */
+#define  PCI_STATUS_CAP_LIST    0x10    /* Support Capability List */
+#define PCI_CAPABILITY_LIST     0x34    /* Offset of first capability list entry */
+
+#define PCI_CB_CAPABILITY_LIST  0x14
+
+#define PCI_CAP_LIST_ID         0       /* Capability ID */
+#define  PCI_CAP_ID_PM          0x01    /* Power Management */
+#define PCI_CAP_LIST_NEXT       1       /* Next capability in the list */
+
+#define  PCI_HEADER_TYPE_NORMAL 0
+#define  PCI_HEADER_TYPE_BRIDGE 1
+#define  PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_PM_PMC              2       /* PM Capabilities Register */
+#define  PCI_PM_CAP_PME_MASK    0xF800  /* PME Mask of all supported states */
+#define PCI_PM_CTRL             4       /* PM control and status register */
+#define  PCI_PM_CTRL_STATE_MASK 0x0003  /* Current power state (D0 to D3) */
+#define  PCI_PM_CTRL_PME_ENABLE 0x0100  /* PME pin enable */
+#define  PCI_PM_CTRL_PME_STATUS 0x8000  /* PME pin status */
+
+static __inline__ int ffs(int x)
+{
+    int r;
+
+    __asm__("bsfl %1,%0\n\t"
+                "jnz 1f\n\t"
+                "movl $-1,%0\n"
+	    "1:" : "=r" (r) : "g" (x));
+    return r+1;
+}
+
+int
+pci_find_capability(int bus, int devfn, int cap)
+{
+	unsigned short status;
+	unsigned char pos, id;
+	int ttl = 48;
+
+	pcibios_read_config_word(bus, devfn, PCI_STATUS, &status);
+	if (!(status & PCI_STATUS_CAP_LIST))
+		return 0;
+	pcibios_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos); /* no cardbus */
+	while (ttl-- && pos >= 0x40) {
+		pos &= ~3;
+		pcibios_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pcibios_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
+	}
+	return 0;
+}
+
+int pci_enable_wake(int bus, int devfn, unsigned int state, int enable)
+{
+	int pm;
+	unsigned short value;
+
+	/* find PCI PM capability in list */
+	pm = pci_find_capability(bus, devfn, PCI_CAP_ID_PM);
+
+	/* If device doesn't support PM Capabilities, but request is to disable
+	 * wake events, it's a nop; otherwise fail */
+	if (!pm) 
+		return enable ? -EIO : 0; 
+
+	/* Check device's ability to generate PME# */
+	pcibios_read_config_word(bus, devfn, pm+PCI_PM_PMC,&value);
+
+	value &= PCI_PM_CAP_PME_MASK;
+	value >>= ffs(value);   /* First bit of mask */
+
+	/* Check if it can generate PME# from requested state. */
+	if (!value || !(value & (1 << state))) 
+		return enable ? -EINVAL : 0;
+
+	pcibios_read_config_word(bus, devfn, pm + PCI_PM_CTRL, &value);
+
+	/* Clear PME_Status by writing 1 to it and enable PME# */
+	value |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE;
+
+	if (!enable)
+		value &= ~PCI_PM_CTRL_PME_ENABLE;
+
+	pcibios_write_config_word(bus, devfn, pm + PCI_PM_CTRL, value);
+	
+	return 0;
+}
--- grub-0.91/netboot/pci.h.org	Thu Jan  3 08:23:29 2002
+++ grub-0.91/netboot/pci.h	Thu Mar 21 17:43:38 2002
@@ -189,4 +189,8 @@
 extern int pcibios_read_config_dword(unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int *value);
 extern int pcibios_write_config_dword(unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int value);
 void adjust_pci_device(struct pci_device *p);
+
+int pci_find_capability(int bus, int devfn, int cap);
+int pci_enable_wake(int bus, int devfn, unsigned int state, int enable);
+
 #endif	/* PCI_H */
--- grub-0.91/netboot/3c90x.c.org	Thu Jan  3 08:23:29 2002
+++ grub-0.91/netboot/3c90x.c	Thu Mar 21 17:46:51 2002
@@ -917,6 +917,7 @@
     a3c90x_internal_IssueCommand(INF_3C90X.IOAddr,
                                  cmdAcknowledgeInterrupt, 0x661);
 
+    pci_enable_wake(pci->bus, pci->devfn, 0, 1);
     /** Set our exported functions **/
     nic->reset    = a3c90x_reset;
     nic->poll     = a3c90x_poll;
