public static void WriteField(ACPIObject val, ACPIObject.FieldUnitData fd, IMachineInterface mi) { ACPIObject.OpRegionData oprd = fd.OpRegion.Data as ACPIObject.OpRegionData; ulong addr = oprd.Offset; if ((fd.BitOffset % 8) != 0) { throw new NotImplementedException(); } addr += (ulong)(fd.BitOffset / 8); ulong mask = 0xffffffffffffffff; int alength = 0; switch (fd.Access) { case ACPIObject.FieldUnitData.AccessType.ByteAcc: alength = 8; break; case ACPIObject.FieldUnitData.AccessType.WordAcc: alength = 16; break; case ACPIObject.FieldUnitData.AccessType.DWordAcc: alength = 32; break; case ACPIObject.FieldUnitData.AccessType.QWordAcc: alength = 64; break; case ACPIObject.FieldUnitData.AccessType.AnyAcc: alength = fd.BitLength; break; } if (alength <= 8) { alength = 8; } else if (alength <= 16) { alength = 16; } else if (alength <= 32) { alength = 32; } else if (alength <= 64) { alength = 64; } else { throw new Exception("Unsupported access length: " + alength.ToString()); } switch (oprd.RegionSpace) { case 0: // SystemMemory switch (alength) { case 8: mi.WriteMemoryByte(addr, (byte)val); break; case 16: mi.WriteMemoryWord(addr, (ushort)val); break; case 32: mi.WriteMemoryDWord(addr, (uint)val); break; case 64: mi.WriteMemoryQWord(addr, val); break; } break; case 1: // SystemIO switch (alength) { case 8: mi.WriteIOByte(addr, (byte)val); break; case 16: mi.WriteIOWord(addr, (ushort)val); break; case 32: mi.WriteIODWord(addr, (uint)val); break; case 64: mi.WriteIOQWord(addr, val); break; } break; default: throw new NotImplementedException(); } }
public static ACPIObject ReadField(ACPIObject.FieldUnitData fd, IMachineInterface mi) { ACPIObject.OpRegionData oprd = fd.OpRegion.Data as ACPIObject.OpRegionData; ulong addr = oprd.Offset; if ((fd.BitOffset % 8) != 0) { throw new NotImplementedException(); } addr += (ulong)(fd.BitOffset / 8); ulong res = 0; ulong mask = 0xffffffffffffffff; int alength = 0; switch (fd.Access) { case ACPIObject.FieldUnitData.AccessType.ByteAcc: alength = 8; break; case ACPIObject.FieldUnitData.AccessType.WordAcc: alength = 16; break; case ACPIObject.FieldUnitData.AccessType.DWordAcc: alength = 32; break; case ACPIObject.FieldUnitData.AccessType.QWordAcc: alength = 64; break; case ACPIObject.FieldUnitData.AccessType.AnyAcc: alength = fd.BitLength; break; } if (alength <= 8) { alength = 8; } else if (alength <= 16) { alength = 16; } else if (alength <= 32) { alength = 32; } else if (alength <= 64) { alength = 64; } else { throw new Exception("Unsupported access length: " + alength.ToString()); } switch (oprd.RegionSpace) { case 0: // SystemMemory switch (alength) { case 8: res = (ulong)mi.ReadMemoryByte(addr); break; case 16: res = (ulong)mi.ReadMemoryWord(addr); break; case 32: res = (ulong)mi.ReadMemoryDWord(addr); break; case 64: res = (ulong)mi.ReadMemoryQWord(addr); break; } break; case 1: // SystemIO switch (alength) { case 8: res = (ulong)mi.ReadIOByte(addr); break; case 16: res = (ulong)mi.ReadIOWord(addr); break; case 32: res = (ulong)mi.ReadIODWord(addr); break; case 64: res = (ulong)mi.ReadIOQWord(addr); break; } break; case 2: // PCI Conf space { /* ACPI divides the index into 4x 16-bit words: * - highest is reserved (0) * - next is PCI device number * - next is PCI function number * - lowest is offset in configuration space * * ACPI enforces that only bus 0 is used */ ulong bus = 0; ulong idx = (ulong)fd.BitOffset / 8UL; ulong device = (idx >> 32) & 0x1f; // 5 bits for a PCI Device ulong func = (idx >> 16) & 0x7; // 3 bits for function number ulong offset = idx & 0xff; // 8 bits for register number ulong act_offset = offset & 0xfc; // enforce 32-bit access ulong pci_addr = act_offset | (func << 8) | (device << 11); mi.WriteIODWord(0xcf8, (uint)pci_addr); uint v = mi.ReadIODWord(0xcfc); res = (ulong)(v >> (int)(offset - act_offset)); } break; default: throw new NotImplementedException(); } mask >>= (64 - fd.BitLength); res &= mask; return(new ACPIObject(ACPIObject.DataType.Integer, res)); }