The Intel PIIX4 chip (and most of its imitators) has only three general purpose I/Os (GPIO) that can be used for wake-up signaling. Because these pins frequently must be dedicated to such things as the Advanced Configuration and Power Interface (ACPI) embedded controller or other run-time ACPI notifications, most machine designers have ended up building machines with all possible wake signals wire-OR'd together on one GPIO.
In an ACPI machine, that is supposed to be handled this way: The general purpose event (GPE) that has all the wake signals attached to it is asserted, generating a system control interrupt (SCI). In response to the interrupt, the ACPI driver finds the asserted GPE and runs an ACPI control method associated with it.
When a power management event (PME#) is asserted, the code in this example is interpreted by the ACPI driver in response to the SCI. But this code doesn't clear the underlying PME#.
Nor could it. A bug in the ACPI 1.0 specification tells a machine designer to do a Notify when a PME# occurs. Because the Notify is an asynchronous event, it doesn't guarantee that the PME# is handled before the method completes. Furthermore, to handle the PME#, the PME-enable bit in the specific PCI device must be cleared. And that bit belongs to the PCI driver, not the ACPI driver, making it impossible to safely clear the bit in ACPI code.
The steps the machine goes through look like this:
1. PME# is asserted by a PCI device.
2. GPE 0 is asserted in the PIIX4.
3. An SCI interrupt is generated.
4. The ACPI driver responds to the interrupt by masking GPE 0.
5. The ACPI driver interprets the GPE._L00 control method, which checks the lid switch and the power button to see if they have been pressed. Neither has.
6. The control method issues a Notify. In response, the ACPI driver sends a message to the PCI driver, telling it that some device on the bus has issued PME#.
7. The ACPI driver unmasks GPE 0.
8. Because the source of the PME# signal has not been addressed, another SCI is asserted, and the process goes back to step 3.
At this point, Windows 2000 is in an endless loop processing the GPE and the machine must be reset. One correct way to deal with this problem would be to connect the signals to the PIIX4 to a dedicated GPE.
In this case, there is a single GPE dedicated to the PME# signal. Windows 2000 will enable the GPE only when a device on the PCI bus is armed for wake and mask the GPE while processing the PME# event. The GPE will remain masked until another request for a device to wake is initiated. This allows the PME# to assert until the PCI driver can clear PME_Status without causing continuous GPE processing. Machines with multiple-root PCI buses must have a separate GPE for each root.
Many modern system designs have employed multiple PCI buses. PME# in these systems is usually connected by wire-ORing all of the PME# from all PCI devices together and connecting the signal group to a single GPE. This design will hang the system during a wake initiated by a PCI device if more than one PCI device is enabled to wake the system.
The main issue with this design is seen when a device is placed in one of the slots and armed to wake the system while the integrated network interface card (NIC) is armed to wake the system. That scenario causes a race condition in the PCI driver. For example:
1. If a modem in a slot on PCI3 and the NIC on PCI2 are both requested to be armed for wake, the PCI driver will set PME_En on both devices and send two WAIT_WAKE IRPs to the ACPI driver, one for the modem on PCI3 and one for the NIC on PCI2. The ACPI driver will set the GPE_En.
2. If the NIC on PCI2 receives a packet directed at it, it will assert the PME#, causing an SCI_INT to be generated. The ACPI driver will mask the GPE and run the associated _L0x method.
3. When the _L0x method issues Notify (PCI2,0x2) and Notify (PCI3,0x2), the ACPI driver will complete both pending because Notifies were sent to both PCI buses.
4. If the PCI driver completes the scan of PCI3, reads PME_Status clear, and sends a WAKE_WAIT IRP back to the ACPI driver before the scan of PCI2 completes, then the ACPI driver will set GPE_EN. Because GPE_STS is still set, an SCI_INT will be generated. The ACPI driver will mask the GPE and run the _L0x method.
5. When the _L0x method issues Notify (PCI2,0x2) and Notify (PCI3,0x2), the ACPI driver has a WAIT_WAKE IRP pending on PCI2 and will complete the WAIT_WAKE IRP.
6. The PCI driver starts and completes the scan of PCI2, reads PME_Status clear, and sends a WAKE_WAIT IRP back to the ACPI driver.
7. At this point, the ACPI driver is caught in the continuous loop of completing and receiving WAIT_WAKE IRPs on PCI0. The machine must be reset to escape the loop.
The optimal way to fix this is to wire the PME# signal groups from each bus to a dedicated GPE .
Another way to fix the problem: Add glue logic to process which PME# signal group has been asserted when there are not enough GPEs in the power management logic of the core chip set that can generate SCIs.
This design is typically accomplished using an embedded controller (EC), routing the PME# signal groups to dedicated inputs on the EC, and routing one output to the power management logic.
In this design, the EC samples only the falling edge of the signals and, when asserting the output to the first GPE, pulls the line low for a minimum of 10 microseconds and a maximum of 100 microseconds.
The method in the \GPE namespace is edge-triggered.