internal ACPIObject Evaluate(IMachineInterface mi, Namespace.State s, Namespace n) { if (this == null) { throw new Exception("passed null pointer as this"); } /* Evaluate as much as we can */ switch (Type) { case DataType.Arg: return(s.Args[(int)Data]); case DataType.Buffer: return(this); case DataType.BufferField: { BufferFieldData bfd = Data as BufferFieldData; ACPIObject new_buf = bfd.Buffer.EvaluateTo(DataType.Buffer, mi, s, n); if (bfd.BitOffset % 8 != 0) { throw new NotImplementedException("BitOffset not divisible by 8"); } if (bfd.BitLength % 8 != 0) { throw new NotImplementedException("BitLength not divisible by 8"); } int byte_offset = bfd.BitOffset / 8; int byte_length = bfd.BitLength / 8; byte[] ret = new byte[byte_length]; byte[] src = (byte[])new_buf.Data; for (int i = 0; i < byte_length; i++) { ret[i] = src[byte_offset + i]; } return(new ACPIObject(DataType.Buffer, ret)); } case DataType.DDBHandle: throw new NotImplementedException("DDBHandle"); case DataType.Device: return(this); case DataType.Event: return(this); case DataType.FieldUnit: if (Data is FieldUnitData) { FieldUnitData fud = Data as FieldUnitData; ACPIObject op_region = fud.OpRegion; if (op_region.Type != DataType.OpRegion) { throw new Exception("Read from FieldUnit with invalid OpRegion type (" + op_region.Type.ToString() + ")"); } OpRegionData ord = op_region.Data as OpRegionData; /* Ensure the requested field index is within the opregion */ int byte_offset = fud.BitOffset / 8; int byte_length = fud.BitLength / 8; if ((ulong)byte_offset + (ulong)byte_length > ord.Length) { throw new Exception("Read: attempt to read to field beyond length of opregion (offset: " + byte_offset.ToString() + ", length: " + byte_length.ToString() + ", OpRegion.Length: " + ord.Length + ")"); } if (fud.BitOffset % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned offset (" + fud.BitOffset.ToString() + ")"); } if (fud.BitLength % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned length (" + fud.BitLength.ToString() + ")"); } /* Do the read depending on the op region type */ switch (ord.RegionSpace) { case 0: // Memory switch (byte_length) { case 1: return(mi.ReadMemoryByte(ord.Offset + (ulong)byte_offset)); case 2: return(mi.ReadMemoryWord(ord.Offset + (ulong)byte_offset)); case 4: return(mi.ReadMemoryDWord(ord.Offset + (ulong)byte_offset)); case 8: return(mi.ReadMemoryQWord(ord.Offset + (ulong)byte_offset)); default: throw new NotImplementedException("Read: unsupported byte length: " + byte_length.ToString()); } case 1: // IO switch (byte_length) { case 1: return(mi.ReadIOByte(ord.Offset + (ulong)byte_offset)); case 2: return(mi.ReadIOWord(ord.Offset + (ulong)byte_offset)); case 4: return(mi.ReadIODWord(ord.Offset + (ulong)byte_offset)); case 8: return(mi.ReadIOQWord(ord.Offset + (ulong)byte_offset)); default: throw new NotImplementedException("Read: unsupported byte length: " + byte_length.ToString()); } case 2: // PCI Configuration space { // try and get the _ADR object for the current device ACPIObject adr = n.Evaluate(ord.Device.ToString() + "._ADR", mi).EvaluateTo(DataType.Integer, mi, s, n); if (adr == null) { throw new Exception(ord.Device.ToString() + "._ADR failed"); } uint bus = 0; uint device = ((uint)adr.IntegerData >> 16) & 0xffffU; uint func = (uint)adr.IntegerData & 0xffffU; uint offset = (uint)ord.Offset + (uint)byte_offset; System.Diagnostics.Debugger.Log(0, "acpipc", "Read from PCI conf space for: " + ord.Device.ToString() + ", _ADR: (" + adr.Type.ToString() + ") " + adr.IntegerData.ToString("X")); switch (byte_length) { case 1: return(mi.ReadPCIByte(bus, device, func, offset)); case 2: return(mi.ReadPCIWord(bus, device, func, offset)); case 4: return(mi.ReadPCIDWord(bus, device, func, offset)); default: throw new NotImplementedException("Read: unsupported byte length: " + byte_length.ToString()); } } default: throw new NotImplementedException("Read: unsupported OpRegion type: " + ord.ToString()); } } else if (Data is IndexFieldUnitData) { var ifud = Data as IndexFieldUnitData; /* Ensure the requested field index is byte aligned */ int byte_offset = ifud.BitOffset / 8; int byte_length = ifud.BitLength / 8; if (ifud.BitOffset % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned offset (" + ifud.BitOffset.ToString() + ")"); } if (ifud.BitLength % 8 != 0) { throw new NotImplementedException("Read: non-byte aligned length (" + ifud.BitLength.ToString() + ")"); } /* Write to index port, read from data port */ ifud.Index.Write((ulong)byte_offset, mi, s, n); var ret = ifud.Data.Evaluate(mi, s, n); switch (byte_length) { case 1: ret.Data = ret.IntegerData & 0xffU; break; case 2: ret.Data = ret.IntegerData & 0xffffU; break; } return(ret); } throw new NotSupportedException("Invalid FieldUnit data type: " + Data.ToString()); case DataType.Integer: return(this); case DataType.Local: return(s.Locals[(int)Data]); case DataType.Method: { Namespace.State new_state = new Namespace.State(); if (s.IsMethodExec) { new_state.Args = s.Args; } else { new_state.Args = new Dictionary <int, ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()); } new_state.Locals = new Dictionary <int, ACPIObject>(new tysos.Program.MyGenericEqualityComparer <int>()); ACPIObject ret; new_state.Scope = Name; MethodData md = Data as MethodData; int midx = md.Offset; //System.Diagnostics.Debugger.Log(0, "acpipc", "Begin evaluating method: " + Name.ToString()); if (md == null) { throw new Exception("Method object has no MethodData"); } if (md.Builtin != null) { return(md.Builtin.Execute(new_state)); } if (!n.ParseTermList(md.AML, ref midx, md.Length, out ret, new_state)) { throw new Exception(); } return(ret); } case DataType.Mutex: return(this); case DataType.ObjectReference: //System.Diagnostics.Debugger.Log(0, "acpipc", "Begin evaluating object reference: " + ((ACPIObject.ObjRefData)Data).ToString()); return(this); case DataType.OpRegion: return(this); case DataType.Package: return(this); case DataType.PowerResource: return(this); case DataType.Processor: return(this); case DataType.String: return(this); case DataType.ThermalZone: return(this); case DataType.Uninitialized: return(this); default: throw new NotImplementedException(); } }