HOME
ACPI FAQ

[Updated June 29, 1998]
What are the requirements for a battery to be described as a Smart Battery in the ACPI NameSpace (that is, using a _HID object value of "ACPI0002")?

Please refer to sections 11.1.4.1 and 11.1.4.2 in the ACPI specification.

For a smart battery subsystem with a maximum of one smart battery and a charger (see the following diagram), all of the commands found in the Smart Battery Data Specification and the Smart Battery Charger Specification must flow over the System Management Bus (SMBus) interface in order for the battery to be described as a Smart Battery. The only exception to this statement is the Manufacturer's Access command (0x00), described in section 5.1 of the Smart Battery Data Specification. This command is optional.

Figure 11-1. Single Smart Battery Subsystem

The ASL code from the ACPI specification shows the use of the _HID object with a value of "ACPI0002."

Device(EC0) {
	Name(_HID, EISAID("PNP0C09"))
	Name(_CRS, 
		ResourceTemplate(){		// port 0x62 and 0x66
			IO(Decode16, 0x62, 0x62, 0, 1),
			IO(Decode16, 0x66, 0x66, 0, 1)
			}
	)
	Name(_GPE, 0)
	Device (SMB0) {
		Name(_HID, "ACPI0001")			// Smart Battery Host Controller
		Name(_EC, 0x8030)			// EC offset (0x80), Query (0x30)
			Device(SBS0){			// Smart Battery Subsystem
				Name(_HID, "ACPI0002")	// Smart Battery Subsystem ID
				Name(_SBS, 0x1)		// Indicates support for one battery
			}	// end of SBS0	
		}		// end of SMB0
	}			// end of EC

The same holds for a smart battery subsystem with multiple smart batteries, a charger, and a selector (see the following diagram). All of the commands found in the Smart Battery Data Specification (again, with the exception of the Manufacturer's Access command), the Smart Battery Charger Specification, and the Smart Battery Selector Specification must flow over the SMBus interface in order for the battery to be described as a Smart Battery.

Figure 11-2. Multiple Smart Battery Subsystem

The ASL code from the ACPI specification shows the use of the _HID object with a value of "ACPI0002."

Device(EC1) {
	Name(_HID, EISAID("PNP0C09"))
	Name(_CRS, 
		ResourceTemplate(){		// port 0x100 and 0x101
			IO(Decode16, 0x100, 0x100, 0, 2) 
			}
		)
	Name(_GPE, 1)
	Device (SMB1) {
		Name(_HID, "ACPI0001")		// Smart Battery Host Controller
		Name(_EC, 0x9031)		// EC offset (0x90), Query (0x31)
		Device(SBS1){			// Smart Battery Subsystem
			Name(_HID, "ACPI0002")	// Smart Battery Subsystem ID
			Name(_SBS, 0x3)		// Indicates support for three batteries
			}	// end of SBS1	
		}		// end of SMB1
	}			// end of EC

See section 13.9 of the ACPI Specification ("SMBus Host Controller Interface via Embedded Controller") for a description of the System Management Bus host interface.

If any one Smart Battery command found in the Smart Battery Data Specification is not supported, does this then require describing the battery in the ACPI Name Space as a Control Method Battery? If so, must all the control methods in the ACPI specification for the control method battery be supported?

Yes. If the battery fails to support even one of the commands specified in the Smart Battery Data Specification, then the battery must instead be described as a Control Method Battery and as such must support all of the control methods outlined in section 11.2.2 of the ACPI Specification.

How is SyncLevel used in the Mutex object?

The SyncLevel value is a debugging aid. It is used to ensure Mutexes are acquired in the proper order to prevent deadlocks. It accomplishes this by verifying that the Mutex levels do not go backwards. For example, if one piece of code acquires Mutex-A followed by Mutex-B, and some time later another code acquires Mutex-B followed by Mutex-A, this would present the opportunity for a deadlock.

By numbering the levels of the Mutex objects, a developer can learn where the internal ordering of the Mutexes has been broken before shipping a product (as an out-of-order usage will cause a crash).

Does an enabled general purpose event (GPE) always have to generate a system control interrupt (SCI)?

Yes. All enabled GPEs always must generate an SCI. In addition, wake event GPEs must also wake the computer. Note that it is not adequate to only wake the computer.

The operating system uses the SCI interrupt to process ACPI events signaled by GPEs, whether the system is asleep or awake when the event occurs. In other words, the wake event has the side effect of causing the system to wake up if it is asleep, but its primary purpose is to generate an SCI that notifies the operating system that the event has occurred. This is a key part of power conservation while the system is awake (that is, working). In G0 (the Working state), devices will often be placed in low-power states (D1-D3) to save energy while waiting for events. Wake-up signaling was defined because devices that are in low power states cannot communicate with the system (no interrupts or I/O or Memory accesses to the device are possible.) The operating system uses wake-up signaling to, for example, wait for a PC card insertion. The controller is placed in D1 or D2 if there are no cards in the slots, and the controller will signal wake-up when a card is inserted, even if the computer is already awake. The situation is the same for a modem that is placed into "answer" mode by an application. It will be placed into a low power state and rely on the wake-up signaling to alert the operating system when the phone rings. The same rule would also apply for a net card that has lost its link connection, and so on.

Can an embedded controller (EC) report both wake and non-wake events?

Yes. However, separate signals must be used. The EC's service interrupt signal (used to generate a system control interrupt (SCI) to notify the EC driver that service is required) must be dedicated to runtime (S0 state) communication with the EC. Any wake-up event(s) must be connected to a separate general purpose event (GPE) register bit. This follows from the ACPI specification's requirement to not mix wake and non-wake events on the same GPE.

The reason for this is wake and non-wake events must be enabled and disabled independently of each other. Wake-up GPEs will be disabled until they are explicitly enabled due to a request from a driver or application. This obviously will have a very bad effect on the normal operation of a device that depends on a non-wake, runtime event connected to the same GPE.

In the specific case of the EC there exists a time window during which wrong behavior can occur if the EC's GPE should happen to be enabled as a wake event. When going to sleep, the operating system enables wake events shortly before putting the machine to sleep. Since the EC does not know when this occurs, and since it occurs before the hardware actually goes to sleep, there is a time window here during which a non-wakeup (runtime) EC event could cause the system to wake up just as it is going to sleep. The requirement to put wake and non-wake events on separate GPEs eliminates this problem.

If the operating system forgets to set the enable bit on my Power Button status bit, there is no way to turn the system back on. What do I do?

The Power (and Sleep) Button event should always power-on (or wake, in the case of the Sleep Button) the system, even if the enable bit is not set.

I have dual root PCI buses that both support #PME signals. Can I hook these together as well as to the same GPE bit?

This scenario, while possible, is not advised. Wake-up latency will be severely affected. It is strongly recommended that systems with multiple root buses use GPE bits for each root bus. The latency in traversing multiple entire bus hierarchies can be significant and wake-up performance can be enhanced by separating buses.

How do I report a CPU-to-PCI bridge (root PCI Bus) in the ACPI NameSpace?

Each root PCI bus must contain _HID, _ADR, _CRS and _PRT objects. _STA, and _DIS are unnecessary and are not allowed. _PRS and _SRS must be included if the bridge's resources are programmable (NotFixed).

\_SB_
	..
	PCI0
		_HID
		_ADR
		_CRS
		_PRT
		..
	..
	..

1) _HID is required in order for the OS to load the PCI bus driver. For the _HID, use:

	Name(_HID, EISAID("PNP0A03"))
	

2) _ADR is required so that the OS can access the bridge's configuration space. For the _ADR, use the bridge's PCI Device and Function numbers:

	Name(_ADR,0x00000000)   //Example only; dev/func numbers may be different

3) _CRS is required so that the OS can distinguish between root buses, and determine which of the global system resources are allocated to each. The _CRS must contain resource descriptors for the bus number, all resources consumed, and all resources consumed-and-produced (passed-through to the secondary bus). Intel architecture platforms must describe consumed resources using PNPISA-compatible descriptors only (no WORD or DWORD address space descriptors - types 7 and 8 in the ACPI spec section 6.4.3.5.3). The bus number, and consumed-and-produced resources must be reported using the WORD or DWORD address descriptors, as illustrated in the example later.

The intent of the _CRS for the PCI bus is to allow the operating system to answer the following question: What are the memory and I/O ranges decoded by the PCI bus (or passed on to its children)? For instance, on Intel Architecture machines, ISA cards may respond to addresses in the range 0xc8000-0xdffff. Since the ISA bus is typically behind the PCI-ISA bridge, the PCI bus will decode and respond to any address in this range. Thus, this memory range must be declared in the _CRS for the PCI0.

By using the guideline above, it becomes clear that since the main memory in the machine is not on the PCI bus, it should not be included as a part of the _CRS for PCI0. Since the main memory (RAM) in any machine is variable, the BIOS must dynamically calculate the amount of memory in the machine and use a control method to set up the MIN and MAX fields for the appropriate DWORD address descriptor. The following example will show this.

For Windows NT 5.0, the following additional requirements must be observed in any BIOS. The values in the _GRA, _LEN and alignment field must be correctly setup for each descriptor. The flags on each descriptor must also be setup according to the actual hardware.

If the host bridge is not re-programmable (this is the case for most Intel Architecture single-root bus machines), the MINFIXED and MAXFIXED flags must be set on each descriptor. In addition, the RESOURCEPRODUCER flag must be set. This flag setting actually sets up the field as both producer and consumer.

For the WORDBusNumber,WORDIO and DWORDMeory descriptors, the following rules must be observed.

  1. If the MINFIXED and MAXFIXED fields are set, _GRA = 0
  2. Length = Max - Min + 1
  3. _CRS for PCI0 should not claim main memory
  4. The following must always be true _MIN & _GRA == 0

Special notes:

  1. The WORD and DWORD descriptors shown below show a Range Length field that has been added in an errata (see the errata document for details)
  2. The IO descriptor has the alignment(_ALN) field while the address descriptors have the granularity(_GRA) field. These two are different. For fields containing the _GRA field, alignment is computed by the equation _ALN = _GRA+1
  3. Option ROMs which are shadowed should not be declared as a part of the _CRS for the root PCI bus since these addresses are decoded by the memory controller, not the PCI bus. In Intel architecture machines, the shadow ROMs are typically placed at the top of physical memory (i.e. 4GB). In addition, many chipsets (for instance, Intel 440 LX) have granularities which are larger than the typical 256KB (the 440 LX has a granularity of 2MB) for the shadow region. Be sure to consult your chipset datasheet for the details and program the _CRS accordingly.

The following example is taken from the ASL of a working machine. Please note, however, that this example should not be copied literally. Your machine may be configured differently and the vendor should implement the correct ASL which accurately describes the configuration particular to their machine. The intent of providing the example is to illustrate the points made above, not to provide ready-to-compile ASL.

Notice in the example below that the root PCI bus is consuming all the bus numbers instead of just one. This is because the other bus numbers will be passed on and assigned to the child busses. If there was only one bus number claimed by the root bus, it would not be possible to assign unique bus numbers to any of the child busses.

Device(PCI0) {			//This is a single root bus machine
   Name(CRES, ResourceTemplate() {
      WORDBusNumber(	        //Bus number resource (0); the bridge produces bus numbers for its subsequent buses
         ResourceProducer,      // bit 0 of general flags is 1
         MinFixed,	        // Range is fixed
         MaxFixed,	        // Range is fixed
         PosDecode,	        // PosDecode
         0x0000,		// Granularity
         0x0000,		// Min
         0x00ff,		// Max
         0x0000,		// Translation
         0x0100		        // Range Length = Max-Min+1
         )
      IO(			//Consumed resource (CF8-CFF)
         Decode16, 
         0x0cf8, 
         0xcf8, 
         1,
         8
         )
      WORDIO(			//Consumed-and-produced resource (all I/O below CF8)
         ResourceProducer, 	// bit 0 of general flags is 0
         MinFixed,	        // Range is fixed
         MaxFixed,		// Range is fixed
         PosDecode,		
         EntireRange,
         0x0000,		// Granularity
         0x0000,		// Min
         0x0cf7,		// Max
         0x0000,		// Translation
         0x0cf8			// Range Length
         )
      WORDIO(			//Consumed-and-produced resource (all I/O above CFF)
         ResourceProducer, 	// bit 0 of general flags is 0
         MinFixed,		// Range is fixed
         MaxFixed,		// Range is fixed
         PosDecode,		
         EntireRange,
         0x0000,		// Granularity
         0x0d00,		// Min
         0xffff,		// Max
         0x0000,		// Translation
         0xf300			// Range Length
         )
      DWORDMEMORY(		// descriptor for video RAM behind ISA bus
	 ResourceProducer	// bit 0 of general flags is 0
	 MinFixed		// Range is fixed
	 MaxFixed		// Range is Fixed
	 Cacheable,
	 ReadWrite,
	 0x00000000,		// Granularity
	 0x000a0000,		// Min
	 0x000bffff,		// Max
	 0x00000000,		// Translation
	 0x00020000		// Range Length
	)

      DWORDMEMORY(		// for device ROMs for ISA plugins devices
	 ResourceProducer	// bit 0 of general flags is 0
	 MinFixed		// Range is fixed
	 MaxFixed		// Range is Fixed
	 NonCacheable,
	 ReadWrite,
	 0x00000000,		// Granularity
	 0x000c8000,		// Min
	 0x000dffff,		// Max
	 0x00000000,		// Translation
	 0x00018000		// Range Length
	)

      DWORDMemory(		// Consumed-and-produced resource(all of memory space)
         ResourceProducer, 	// bit 0 of general flags is 0
         PosDecode,		// positive Decode
         MinFixed,		// Range is fixed
         MaxFixed,		// Range is fixed
         Cacheable,
         ReadWrite,
         0x00000000,		// Granularity
         0x02000000,		// Min (calculated dynamically)

         0xffdfffff,		//  Max = 4GB - 2MB
         0x00000000,		// Translation
         0xfdfc0000		// Range Length (calculated dynamically)
	 ,			// Optional field left blank
	 ,			// Optional field left blank
	 MEM3			// Name declaration for this descriptor
        )
    }		// end of CRES Buffer
    Method(_CRS,0) {
	CreateDWordField(CRES,\_SB.PCI0.MEM3._MIN,RAMT)
	CreateDWordField(CRES,\_SB.PCI0.MEM3._LEN.RAMR)
	// MLEN contains the amount of system memory which is detected
	// dynamically by the BIOS

	store(MLEN,RAMT)	// This will become the _MIN
	Subtract(0xffe00000,RAMT,RAMR)	// compute the _LEN
	Return(CRS)
	}	// end of _CRS method
)
   }				//End _CRS
)}				//End PCI0

4) _PRT is required to enable routing of interrupt vectors for the PCI interrupt lines on that bus. The _PRT must account for each root bus device or slot that has one of its PCI interrupt pins (INTA,INTB, INTC or INTD) wired to a system interrupt vector. In the _PRT, each pin is represented by a package of information, including the _ADR of the device, the PCI interrupt pin and the name of the device (a 'PCI Interrupt link') in the NameSpace that produces the system interrupt vector that this pin consumes.

	Name(_PRT, Package(){
		Package(){0x0004ffff, 0, LNKA, 0},  // Slot 1, INTA
		Package(){0x0004ffff, 1, LNKB, 0},  // Slot 1, INTB
		Package(){0x0004ffff, 2, LNKC, 0},  // Slot 1, INTC
		Package(){0x0004ffff, 3, LNKD, 0},  // Slot 1, INTD
		Package(){0x0005ffff, 0, LNKB, 0},  // Slot 2, INTA
		Package(){0x0005ffff, 1, LNKC, 0},  // Slot 2, INTB
		Package(){0x0005ffff, 2, LNKD, 0},  // Slot 2, INTC
		Package(){0x0005ffff, 3, LNKA, 0},  // Slot 2, INTD
		Package(){0x0006ffff, 0, LNKC, 0},  // Slot 3, INTA
		Package(){0x0006ffff, 1, LNKD, 0},  // Slot 3, INTB
		Package(){0x0006ffff, 2, LNKA, 0},  // Slot 3, INTC
		Package(){0x0006ffff, 3, LNKB, 0},  // Slot 3, INTD
	})

If there is more than one _PRT each can reference the same links if they use the same physical links. However, if they use physically different links, they must refer to different symbol names. Note: Symbol names may either be short names (in which case they are subject to normal ASL scoping rules), or full path names (see the related question, below).

Special Note: Static routing is not supported under Windows 98. You must use link nodes (as above) whenever the machine is using 8259-style interrupt controllers. When in APIC mode, however, you may use static routing. Also, if your machine uses some completely different interrupt controller (perhaps because it is an Alpha or non-PC x86), then you may use static routing as well. If your machine really is statically routed, and you are using 8259 PICs, then you must have link nodes, though the _PRS will have only one option.

But how about a multiple root bus machine? How do I report several CPU-to-PCI bridges (root PCI Buses) in the ACPI NameSpace?

In a multiple root-bus machine, each root bus requires the elements shown above, but the BusNumbers, I/O space and Memory space would be broken-up and allocated to different root buses. Each contiguous range of these resources will have its own resource descriptor in the _CRS for the root bus upon which the resource appears, as shown in the following example.

Also note that for a multiple root bus machine, _BBN is required for each bus. _BBN should provide the bus number assigned to this bus by the BIOS at boot time. This information is necessary because the _CRS for that PCI bus may contain references to a PCI operation region. And to correctly evaluate that operation region, the operating system needs to know what the PCI bus number is.

NOTE: The example below is intended only to show the difference between a single root bus machine and a multi-root bus machine and does NOT show all the fields necessary for a multi-root bus machine. The correct ASL depends on the configuration of the particular machine in question and the intent here it to illustrate, not to provide ready ASL code.

Device(PCI0) {			//This is the first of 2 root buses on this machine
   Name(_BBN, 0)		// This is the bus number for the 1st root bus
   Name(CRES, ResourceTemplate() {
      WORDBusNumber(	        //Bus number resource (0); the bridge produces bus numbers for its subsequent buses
         ResourceProducer,      // bit 0 of general flags is 1
         MinFixed,	        // Range is not fixed
         MaxFixed,	        // Range is not fixed
         PosDecode,	        // PosDecode
         0x0000,		// Granularity
         0x0000,		// Min
         0x007f,		// Max; half of the available bus numbers are reserved for this root bus
         0x0000,		// Translation
         0x0080		        // Range Length
         )
      IO(			//Consumed resource for 1st root bus(CF8-CFF)
         Decode16, 
         0x0cf8, 
         0xcf8, 
         1,
         8
         )
      WORDIO(			//Consumed-and-produced resource (all I/O below CF8 is assigned to this root bus)
         ResourceProducer, 	// bit 0 of general flags is 0
         MinFixed,	        // Range is fixed
         MaxFixed,		// Range is fixed
         PosDecode,		
         EntireRange,
         0x0000,		// Granularity
         0x0000,		// Min
         0x0cf7,		// Max
         0x0000,		// Translation
         0x0cf8			// Range Length
         )
      DWORDMEMORY(			// descriptor for video RAM behind ISA bus
	 ResourceProducer,	// bit 0 of general flags is 0
	 MinFixed,		// Range is fixed
	 MaxFixed,		// Range is Fixed
	 Cacheable,
	 ReadWrite,
	 0x00000000,		// Granularity
	 0x000a0000,		// Min
	 0x000bffff,		// Max
	 0x00000000,		// Translation
	 0x00020000		// Range Length
	)

      DWORDMEMORY(		// for device ROMs for ISA plugins devices
	 ResourceProducer,	// bit 0 of general flags is 0
	 MinFixed,		// Range is fixed
	 MaxFixed,		// Range is Fixed
	 NonCacheable,
	 ReadWrite,
	 0x00000000,		// Granularity
	 0x000c8000,		// Min
	 0x000dffff,		// Max
	 0x00000000,		// Translation
	 0x00018000		// Range Length
	)

      DWORDMemory(		// Consumed-and-produced resource(all of memory space)
         ResourceProducer, 	// bit 0 of general flags is 0
         PosDecode,		// positive Decode
         MinFixed,		// Range is fixed
         MaxFixed,		// Range is fixed
         Cacheable,
         ReadWrite,
         0x00000000,		// Granularity
         0x02000000,		// Min (calculated dynamically)
         0xffdfffff,		// Max = 4GB - 2MB
         0x00000000,		// Translation
         0xfdfc0000,		// Range Length (calculated dynamically)
	 ,			// Optional field left blank
	 ,			// Optional field left blank
	 MEM3			// Name declaration for this descriptor
        )
    }		// end of CRES Buffer
    Method(_CRS,0) {
	CreateDWordField(CRES,\_SB.PCI0.MEM3._MIN,RAMT)
	CreateDWordField(CRES,\_SB.PCI0.MEM3._LEN.RAMR)
	// MLEN contains the amount of system memory which is detected
	// dynamically by the BIOS

	store(MLEN,RAMT)	// This will become the _MIN
	Subtract(0xffe00000,RAMT,RAMR)	// compute the _LEN
	Return(CRS)
	}	// end of _CRS method


)}				//End PCI0

Device(PCI1) {			//This is the second of 2 root buses on this machine
   Name(_BBN,0x80)		// This is the bus number for the 2nd root bus
   Name(_CRS, ResourceTemplate() {
      WORDBusNumber(	        //Bus number resource (0); the bridge produces bus numbers for its subsequent buses
         ResourceProducer,      // bit 0 of general flags is 1
         MinNotFixed,	        // Range is not fixed
         MaxNotFixed,	        // Range is not fixed
         PosDecode,	        // PosDecode
         0x0000,		// Granularity
         0x0080,		// Min
         0x00ff,		// Max; the remaining available bus numbers are reserved for this root bus
         0x0000,		// Translation
         0x0080		        // Range Length
         )
      IO(			//Consumed resource (D00-D07)
         Decode16, 
         0x0d00, 
         0xd00, 
         1,
         8
         )
      WORDIO(			//Consumed-and-produced resource (all I/O above D07)
         ResourceProducer, 	// bit 0 of general flags is 0
         MinFixed,		// Range is fixed
         MaxFixed,		// Range is fixed
         PosDecode,		
         EntireRange,
         0x0000,		// Granularity
         0x0d08,		// Min
         0xffff,		// Max
         0x0000,		// Translation
         0xf2f8			// Range Length
         )
      DWORDMemory(		// Consumed-and-produced resource(all of memory space)
         ResourceProducer, 	// bit 0 of general flags is 0
         PosDecode,		// positive Decode
         MinFixed,		// Range is fixed
         MaxFixed,		// Range is fixed
         Cacheable,
         ReadWrite,
         0x00000000,		// Granularity
         0x02000000,		// Min (calculated dynamically)

         0xffdfffff,		// Max = 4GB - 2MB
         0x00000000,		// Translation
         0xfdfc0000,		// Range Length (calculated dynamically)
	 ,			// Optional field left blank
	 ,			// Optional field left blank
	 MEM3			// Name declaration for this descriptor
        )
    }		// end of CRES Buffer
    Method(_CRS,0) {
	CreateDWordField(CRES,\_SB.PCI1.MEM3._MIN,RAMT)
	CreateDWordField(CRES,\_SB.PCI1.MEM3._LEN.RAMR)
	// MLEN contains the amount of system memory which is detected
	// dynamically by the BIOS

	store(MLEN,RAMT)	// This will become the _MIN
	Subtract(0xffe00000,RAMT,RAMR)	// compute the _LEN
	Return(CRS)
	}	// end of _CRS method

      

)}				//End PCI1

On my multiple root bus machine the _PRTs are huge, and take-up a lot of AML storage (ROM space). Is there anyway to conserve bytes when I describe these?

There are three techniques available to minimize the number of AML bytes required to encode a namespace. They are: 1) The ASL scoping rules, 2) The relative operator (^), and 3), the ALIAS operator.

1 ) The first thing to keep in mind is to use the ASL scoping rules to your advantage. That is, as much as possible, use short names to refer to objects in the namespace by ensuring that the referenced object appears 'above' (within scope) of the reference. Note, however, that just putting everything at the root of the namespace is not recommended due to the performance impact of the interpreter having to do extensive searches to locate items. Instead, you should only locate objects as high up in the namespace as to be within the scope of all references to that object. Refer to the location of the PRQx field declaration in the following example:

    Scope (\_SB)
      {
        Device (PCI0)
          {
            Name (_HID, EisaID ("PNP0A03"))
            Name (_ADR, 0x00000000)
            Name (_PRT, Package ()
                          {
                            Package () {0x000EFFFF, 0, LNKA, 0},
                            ...
                          })
            Device (PCI1)
              {
                Name (_ADR, 0x000F0000)
                Name (_PRT, Package ()
                              {
                                Package () {0x0009FFFF, 0, LNKA, 0},
                                ...
                              })
              } // Close PCI1

            Name (_CRS, ResourceTemplate () {...} )

            Device (ISA)
              {
                Name (_ADR, 0x00070000)

                OperationRegion (P40C, PCI_Config, 0x60, 4)

                Device (SPK) {...}
                ...
              } // Close ISA
          } // Close PCI0

        Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
          {
            PRQ0, 8,
            PRQ1, 8,
            PRQ2, 8,
            PRQ3, 8
          }

        Device (LNKA)
          {
            Name (_HID, Eisaid ("PNP0C0F"))
            Name (_UID, 1)
            Name (_PRS, Buffer () { 0x23, 0xf8, 0x9e, 0x18, 0x79, 0x0 })
            Method (_DIS)
              {
                or (PRQ0, 0x80, PRQ0)
              }
            ...
          }
        ...
      } // Close _SB

By locating the PRQx fields under the PCI0 device, rather than under the P40C operation region, all references to it from within the PCI0 scope can use short names. Note that if these fields were shared amongst different root buses, the declaration would have to be moved up to the \_SB scope to be within scope for all references.

2) If an object must be located outside the scope of a reference to it, the relative operator can encode 4 bytes in 1, giving you some storage savings still.

3) Finally, if extensive references must be made to an object outside it's scope, significant storage space gains can be achieved by creating a short name alias for the full path to the object within the reference's scope, and referring to the alias instead.

[Updated June 29, 1998]
What are the rules for using _CRS, _STA, and related objects?
  • The _STA, _CRS, and _PRS objects must be present and must evaluate successfully.

  • _CRS and _PRS must return a buffer.

  • PCI bus bridges have special considerations, as described above.

What is the correct way to report chips that contain multiple functional devices (such as the Super I/O chips)?

ACPI NameSpace must model the functional hierarchy of the system. Chips are physical packages that do not necessarily represent the functional hierarchy. Functional devices must appear as child devices of the bus they are connected to. For example, a tree containing a Super I/O chip should be as follows:

\_SB
       PCI0
               ISA
                     COMA
                     COMB
                     LPT
                     SIR
                     EPP
                     ECP

The super I/O itself is not a device from an ACPI perspective. Each of the functional devices in that SIO is.

What about the OperationRegions that access the SuperI/O chip? Where do I put them?

OperationRegions and related NameSpace objects such as fields must appear as children of the device that provides the space they access. For example, an operation region in ISA I/O space must appear as a child of the ISA bus. The general rules are:

  • For PCI Config Space, OperationRegions appear as children of the PCI function whose config space is being accessed.

  • For EC space, OperationRegions appear as children of the EC device they are accessing.

  • For SMB Space, OperationRegions appear as children of the SMB controller device they are accessing.

  • For non-ISA I/O space and all of Memory, OperationRegions appear at the root (\_SB).

What about turning off the SuperI/O chip itself to save power? How can I do that if it does not appear in the NameSpace?

This is exactly what ACPI defined the power resource for. The SuperI/O chip can be modeled as a power resource that is common to all of the functions in the chip. Turning it on and off can be handled via a power resource that is shared amongst all devices in the SIO, and can be turned off when these other devices are off.