mirror of
				https://github.com/taigrr/gopher-os
				synced 2025-01-18 04:43:13 -08:00 
			
		
		
		
	acpi: move entity visitor code to the entity pkg
This commit is contained in:
		
							parent
							
								
									38143ab510
								
							
						
					
					
						commit
						7e419ae20e
					
				
							
								
								
									
										64
									
								
								src/gopheros/device/acpi/aml/entity/visitor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/gopheros/device/acpi/aml/entity/visitor.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					package entity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Visitor is a function invoked by the VM for each AML tree entity that matches
 | 
				
			||||||
 | 
					// a particular type. The return value controls whether the children of this
 | 
				
			||||||
 | 
					// entity should also be visited.
 | 
				
			||||||
 | 
					type Visitor func(depth int, obj Entity) (keepRecursing bool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Type defines the type of entity that visitors should inspect.
 | 
				
			||||||
 | 
					type Type uint8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The list of supported Type values. TypeAny works as a wildcard
 | 
				
			||||||
 | 
					// allowing the visitor to inspect all entities in the AML tree.
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TypeAny Type = iota
 | 
				
			||||||
 | 
						TypeDevice
 | 
				
			||||||
 | 
						TypeProcessor
 | 
				
			||||||
 | 
						TypePowerResource
 | 
				
			||||||
 | 
						TypeThermalZone
 | 
				
			||||||
 | 
						TypeMethod
 | 
				
			||||||
 | 
						TypeMutex
 | 
				
			||||||
 | 
						TypeEvent
 | 
				
			||||||
 | 
						TypeField
 | 
				
			||||||
 | 
						TypeIndexField
 | 
				
			||||||
 | 
						TypeBankField
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Visit descends a scope hierarchy and invokes visitorFn for each entity
 | 
				
			||||||
 | 
					// that matches entType.
 | 
				
			||||||
 | 
					func Visit(depth int, ent Entity, entType Type, visitorFn Visitor) bool {
 | 
				
			||||||
 | 
						op := ent.Opcode()
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case (entType == TypeAny) ||
 | 
				
			||||||
 | 
							(entType == TypeDevice && op == OpDevice) ||
 | 
				
			||||||
 | 
							(entType == TypeProcessor && op == OpProcessor) ||
 | 
				
			||||||
 | 
							(entType == TypePowerResource && op == OpPowerRes) ||
 | 
				
			||||||
 | 
							(entType == TypeThermalZone && op == OpThermalZone) ||
 | 
				
			||||||
 | 
							(entType == TypeMethod && op == OpMethod) ||
 | 
				
			||||||
 | 
							(entType == TypeMutex && op == OpMutex) ||
 | 
				
			||||||
 | 
							(entType == TypeEvent && op == OpEvent) ||
 | 
				
			||||||
 | 
							(entType == TypeField && op == OpField) ||
 | 
				
			||||||
 | 
							(entType == TypeIndexField && op == OpIndexField) ||
 | 
				
			||||||
 | 
							(entType == TypeBankField && op == OpBankField):
 | 
				
			||||||
 | 
							// If the visitor returned false we should not visit the children
 | 
				
			||||||
 | 
							if !visitorFn(depth, ent) {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Visit any args that are also entities
 | 
				
			||||||
 | 
							for _, arg := range ent.Args() {
 | 
				
			||||||
 | 
								if argEnt, isEnt := arg.(Entity); isEnt && !Visit(depth+1, argEnt, entType, visitorFn) {
 | 
				
			||||||
 | 
									return false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If the entity defines a scope we need to visit the child entities.
 | 
				
			||||||
 | 
						if container, isContainer := ent.(Container); isContainer {
 | 
				
			||||||
 | 
							for _, child := range container.Children() {
 | 
				
			||||||
 | 
								_ = Visit(depth+1, child, entType, visitorFn)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										93
									
								
								src/gopheros/device/acpi/aml/entity/visitor_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/gopheros/device/acpi/aml/entity/visitor_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					package entity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestScopeVisit(t *testing.T) {
 | 
				
			||||||
 | 
						tableHandle := uint8(42)
 | 
				
			||||||
 | 
						keepRecursing := func(Entity) bool { return true }
 | 
				
			||||||
 | 
						stopRecursing := func(Entity) bool { return false }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Append special entities under IDE0
 | 
				
			||||||
 | 
						root := NewScope(tableHandle, "IDE0")
 | 
				
			||||||
 | 
						root.Append(NewDevice(tableHandle, "DEV0"))
 | 
				
			||||||
 | 
						root.Append(NewProcessor(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewProcessor(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewPowerResource(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewPowerResource(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewPowerResource(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewThermalZone(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewThermalZone(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewThermalZone(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewThermalZone(tableHandle, "FOO0"))
 | 
				
			||||||
 | 
						root.Append(NewMethod(tableHandle, "MTH0"))
 | 
				
			||||||
 | 
						root.Append(NewMethod(tableHandle, "MTH1"))
 | 
				
			||||||
 | 
						root.Append(NewMethod(tableHandle, "MTH2"))
 | 
				
			||||||
 | 
						root.Append(NewMethod(tableHandle, "MTH3"))
 | 
				
			||||||
 | 
						root.Append(NewMethod(tableHandle, "MTH4"))
 | 
				
			||||||
 | 
						root.Append(NewMutex(tableHandle))
 | 
				
			||||||
 | 
						root.Append(NewMutex(tableHandle))
 | 
				
			||||||
 | 
						root.Append(NewEvent(tableHandle))
 | 
				
			||||||
 | 
						root.Append(NewEvent(tableHandle))
 | 
				
			||||||
 | 
						root.Append(NewEvent(tableHandle))
 | 
				
			||||||
 | 
						root.Append(NewField(tableHandle))
 | 
				
			||||||
 | 
						root.Append(NewIndexField(tableHandle))
 | 
				
			||||||
 | 
						root.Append(NewBankField(tableHandle))
 | 
				
			||||||
 | 
						root.Append(&Invocation{
 | 
				
			||||||
 | 
							Generic: Generic{
 | 
				
			||||||
 | 
								op: OpMethodInvocation,
 | 
				
			||||||
 | 
								args: []interface{}{
 | 
				
			||||||
 | 
									NewConst(OpOne, tableHandle, uint64(1)),
 | 
				
			||||||
 | 
									NewConst(OpDwordPrefix, tableHandle, uint64(2)),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						specs := []struct {
 | 
				
			||||||
 | 
							searchType      Type
 | 
				
			||||||
 | 
							keepRecursingFn func(Entity) bool
 | 
				
			||||||
 | 
							wantHits        int
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{TypeAny, keepRecursing, 27},
 | 
				
			||||||
 | 
							{TypeAny, stopRecursing, 1},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								TypeAny,
 | 
				
			||||||
 | 
								func(ent Entity) bool {
 | 
				
			||||||
 | 
									// Stop recursing after visiting the Invocation entity
 | 
				
			||||||
 | 
									_, isInv := ent.(*Invocation)
 | 
				
			||||||
 | 
									return !isInv
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								25,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								TypeAny,
 | 
				
			||||||
 | 
								func(ent Entity) bool {
 | 
				
			||||||
 | 
									// Stop recursing after visiting the first Const entity
 | 
				
			||||||
 | 
									_, isConst := ent.(*Const)
 | 
				
			||||||
 | 
									return !isConst
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								26,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{TypeDevice, keepRecursing, 1},
 | 
				
			||||||
 | 
							{TypeProcessor, keepRecursing, 2},
 | 
				
			||||||
 | 
							{TypePowerResource, keepRecursing, 3},
 | 
				
			||||||
 | 
							{TypeThermalZone, keepRecursing, 4},
 | 
				
			||||||
 | 
							{TypeMethod, keepRecursing, 5},
 | 
				
			||||||
 | 
							{TypeMutex, keepRecursing, 2},
 | 
				
			||||||
 | 
							{TypeEvent, keepRecursing, 3},
 | 
				
			||||||
 | 
							{TypeField, keepRecursing, 1},
 | 
				
			||||||
 | 
							{TypeIndexField, keepRecursing, 1},
 | 
				
			||||||
 | 
							{TypeBankField, keepRecursing, 1},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for specIndex, spec := range specs {
 | 
				
			||||||
 | 
							var hits int
 | 
				
			||||||
 | 
							Visit(0, root, spec.searchType, func(_ int, obj Entity) bool {
 | 
				
			||||||
 | 
								hits++
 | 
				
			||||||
 | 
								return spec.keepRecursingFn(obj)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if hits != spec.wantHits {
 | 
				
			||||||
 | 
								t.Errorf("[spec %d] expected visitor to be called %d times; got %d", specIndex, spec.wantHits, hits)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user