commit 677150ec41092005c41860ffbfa7703b930b15a3 Author: Kbz-8 Date: Wed Jul 1 16:28:57 2026 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4726c77 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.zig-cache/ +zig-out/ +zig-pkg/ +*.o +*.a +*.so +*.dylib +*.dll diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..21f254f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 kbz_8 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f200579 --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# miclib Zig wrapper + +Zig 0.16 wrapper for Intel/CIRCL `miclib.h` / `libmicmgmt`. + +This repo does **not** vendor MPSS, `miclib.h`, `scif.h`, `libmicmgmt`, or `libscif`. +Install/build miclib separately, then point Zig at the include/library directories. + +## Build + +```sh +zig build \ + -Dmiclib_include=/usr/local/include \ + -Dmiclib_libdir=/usr/local/lib +``` + +The default miclib system library name is `micmgmt`, which links `-lmicmgmt`. +Override it if your install uses another name: + +```sh +zig build -Dmiclib_name=micmgmt +``` + +`miclib.h` includes `scif.h`, so `-Dmiclib_include` must reference a directory where both headers are visible. +The build script links `micmgmt`, `scif`, libc, and libc++ because the upstream implementation is C++ with a C ABI. + +## Use as a dependency + +```sh +zig fetch --save git+https://git.kbz8.me/kbz_8/miclib-zig.git +``` + +Then in your `build.zig`: + +```zig +const miclib_dep = b.dependency("miclib", .{ + .target = target, + .optimize = optimize, + .miclib_include = "/usr/local/include", + .miclib_libdir = "/usr/local/lib", +}); + +exe.root_module.addImport("miclib", miclib_dep.module("miclib")); +``` + +Then in Zig: + +```zig +const mic = @import("miclib"); + +var list = try mic.DeviceList.init(); +defer list.deinit(); + +const count = try list.count(); +for (0..count) |index| { + const device_num = try list.deviceAtIndex(index); + var device = try mic.Device.open(device_num); + defer device.deinit(); + + var memory = try device.memoryInfo(); + defer memory.deinit(); + + const mem_mib = try memory.size(); + _ = mem_mib; +} +``` diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..57ada2e --- /dev/null +++ b/build.zig @@ -0,0 +1,84 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const miclib_include = b.option( + []const u8, + "miclib_include", + "Directory containing miclib.h and scif.h. Example: -Dmiclib_include=/usr/local/include", + ); + + const miclib_libdir = b.option( + []const u8, + "miclib_libdir", + "Directory containing libmicmgmt.so/libscif.so. Example: -Dmiclib_libdir=/usr/local/lib", + ); + + const miclib_name = b.option( + []const u8, + "miclib_name", + "System library name for miclib without lib/extension. Default: micmgmt", + ) orelse "micmgmt"; + + const module = b.addModule("miclib", .{ + .root_source_file = b.path("src/lib.zig"), + .target = target, + .optimize = optimize, + .link_libc = true, + }); + configureMiclibModule(module, miclib_include, miclib_libdir, miclib_name); + + const test_module = b.createModule(.{ + .root_source_file = b.path("src/lib.zig"), + .target = target, + .optimize = optimize, + .link_libc = true, + }); + configureMiclibModule(test_module, miclib_include, miclib_libdir, miclib_name); + + const c_includes = b.addTranslateC(.{ + .root_source_file = b.path("src/c_includes.h"), + .target = target, + .optimize = optimize, + .link_libc = true, + }); + + module.addImport("miclib_c", c_includes.createModule()); + + const lib_tests = b.addTest(.{ .root_module = test_module }); + const run_tests = b.addRunArtifact(lib_tests); + const test_step = b.step("test", "Run unit tests"); + test_step.dependOn(&run_tests.step); + + const enumerate_module = b.createModule(.{ + .root_source_file = b.path("examples/enumerate.zig"), + .target = target, + .optimize = optimize, + .imports = &.{.{ .name = "miclib", .module = module }}, + }); + + const enumerate = b.addExecutable(.{ + .name = "miclib-enumerate", + .root_module = enumerate_module, + }); + + b.installArtifact(enumerate); + + const run_enumerate = b.addRunArtifact(enumerate); + const run_step = b.step("example", "Run examples/enumerate.zig"); + run_step.dependOn(&run_enumerate.step); +} + +fn configureMiclibModule(module: *std.Build.Module, miclib_include: ?[]const u8, miclib_libdir: ?[]const u8, miclib_name: []const u8) void { + if (miclib_include) |path| + module.addIncludePath(.{ .cwd_relative = path }); + + if (miclib_libdir) |path| + module.addLibraryPath(.{ .cwd_relative = path }); + + module.link_libcpp = true; + module.linkSystemLibrary(miclib_name, .{}); + module.linkSystemLibrary("scif", .{}); +} diff --git a/build.zig.zon b/build.zig.zon new file mode 100644 index 0000000..9bdb3fb --- /dev/null +++ b/build.zig.zon @@ -0,0 +1,16 @@ +.{ + .name = .miclib, + .version = "1.0.0", + .fingerprint = 0xee5712284bf0b001, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + "examples", + "README.md", + "LICENSE", + "third_party", + }, +} diff --git a/examples/enumerate.zig b/examples/enumerate.zig new file mode 100644 index 0000000..7b596c1 --- /dev/null +++ b/examples/enumerate.zig @@ -0,0 +1,116 @@ +const std = @import("std"); +const mic = @import("miclib"); + +pub fn main() !void { + var devices = mic.DeviceList.init() catch |err| { + std.debug.print("mic_get_devices failed: {s}\n", .{@errorName(err)}); + printLastMicError(); + return err; + }; + defer devices.deinit(); + + const count = try devices.count(); + std.debug.print("found {} MIC device(s)\n", .{count}); + + for (0..count) |index| { + const device_num = try devices.deviceAtIndex(index); + var device = mic.Device.open(device_num) catch |err| { + std.debug.print("mic{}: open failed: {s}\n", .{ device_num, @errorName(err) }); + printLastMicError(); + continue; + }; + defer device.deinit(); + + try printDevice(device_num, device); + } +} + +fn printDevice(device_num: u32, device: mic.Device) !void { + var buffer: [mic.default_string_buffer_len]u8 = undefined; + + const device_type = device.deviceType() catch 0; + std.debug.print("\nmic{}: {s}\n", .{ device_num, device.name() }); + std.debug.print(" type: {}{s}\n", .{ device_type, if (device_type == mic.knc_id) " (KNC)" else "" }); + + if (device.serialNumber(buffer[0..])) |serial| { + std.debug.print(" serial: {s}\n", .{serial}); + } else |err| printSkipped("serial", err); + + if (device.siliconSku(buffer[0..])) |sku| { + std.debug.print(" sku: {s}\n", .{sku}); + } else |err| printSkipped("sku", err); + + if (device.pciConfig()) |pci_value| { + var pci = pci_value; + defer pci.deinit(); + + std.debug.print(" pci: {x:0>4}:{x:0>2}:{x:0>2}, vendor={x:0>4}, device={x:0>4}\n", .{ + pci.domainId() catch 0, + pci.busNumber() catch 0, + pci.deviceNumber() catch 0, + pci.vendorId() catch 0, + pci.deviceId() catch 0, + }); + + if (pci.linkSpeed(buffer[0..])) |speed| { + std.debug.print(" pci-link: {s} x{}\n", .{ speed, pci.linkWidth() catch 0 }); + } else |err| printSkipped("pci-link", err); + } else |err| printSkipped("pci", err); + + if (device.coresInfo()) |cores_value| { + var cores = cores_value; + defer cores.deinit(); + + std.debug.print(" cores: {}, freq={} MHz, voltage={} mV\n", .{ + cores.count() catch 0, + cores.frequency() catch 0, + cores.voltage() catch 0, + }); + } else |err| printSkipped("cores", err); + + if (device.memoryInfo()) |memory_value| { + var memory = memory_value; + defer memory.deinit(); + + const memory_type = memory.memoryType(buffer[0..]) catch "unknown"; + std.debug.print(" memory: {} MiB, type={s}, freq={} MHz, ecc={}\n", .{ + memory.size() catch 0, + memory_type, + memory.frequency() catch 0, + memory.eccMode() catch 0, + }); + } else |err| printSkipped("memory", err); + + if (device.thermalInfo()) |thermal_value| { + var thermal = thermal_value; + defer thermal.deinit(); + + std.debug.print(" thermals: die={} C, fan={} RPM, pwm={}\n", .{ + thermal.dieTemp() catch 0, + thermal.fanRpm() catch 0, + thermal.fanPwm() catch 0, + }); + } else |err| printSkipped("thermals", err); + + if (device.versionInfo()) |version_value| { + var version = version_value; + defer version.deinit(); + + if (version.uosVersion(buffer[0..])) |uos| { + std.debug.print(" uos: {s}\n", .{uos}); + } else |err| printSkipped("uos", err); + + if (version.flashVersion(buffer[0..])) |flash| { + std.debug.print(" flash: {s}\n", .{flash}); + } else |err| printSkipped("flash", err); + } else |err| printSkipped("version", err); +} + +fn printSkipped(name: []const u8, err: anyerror) void { + std.debug.print(" {s}: unavailable ({s})\n", .{ name, @errorName(err) }); +} + +fn printLastMicError() void { + const last = mic.lastErrorString(); + if (last.len != 0) std.debug.print("miclib: {s}\n", .{last}); +} diff --git a/src/c_includes.h b/src/c_includes.h new file mode 100644 index 0000000..77bc711 --- /dev/null +++ b/src/c_includes.h @@ -0,0 +1 @@ +#include diff --git a/src/lib.zig b/src/lib.zig new file mode 100644 index 0000000..48a2251 --- /dev/null +++ b/src/lib.zig @@ -0,0 +1,1045 @@ +//! Zig wrapper for Intel/CIRCL miclib. +//! +//! This package keeps complete access to the C API through `miclib.c`, while +//! also providing small RAII-style wrappers around the opaque miclib handles. +//! +//! The wrapped library is the C ABI exported by `miclib.h` / `libmicmgmt`. +//! Most getters copy into caller-provided buffers to avoid hidden allocation. + +const std = @import("std"); + +pub const c = @import("miclib_c"); + +pub const MicError = error{ + Invalid, + AccessDenied, + NotFound, + UnsupportedDevice, + NotImplemented, + DriverInitFailed, + DriverNotLoaded, + IoctlFailed, + NoMemory, + OutOfRange, + Internal, + System, + Scif, + Ras, + Stack, + WmiParameterReadFailed, + WindowsUnsupported, + WmiFailed, + Unknown, +}; + +pub const knc_id: u32 = c.KNC_ID; +pub const flash_op_status: c_int = c.FLASH_OP_STATUS; +pub const smc_op_status: c_int = c.SMC_OP_STATUS; +pub const default_string_buffer_len: usize = 256; + +pub fn isFlashOperationStatus(status: c_int) bool { + return (status & c.FLASH_OP_STATUS) != 0; +} + +pub fn isSmcOperationStatus(status: c_int) bool { + return (status & c.SMC_OP_STATUS) != 0; +} + +pub fn check(result: c_int) MicError!void { + switch (result) { + c.E_MIC_SUCCESS => {}, + c.E_MIC_INVAL => return error.Invalid, + c.E_MIC_ACCESS => return error.AccessDenied, + c.E_MIC_NOENT => return error.NotFound, + c.E_MIC_UNSUPPORTED_DEV => return error.UnsupportedDevice, + c.E_MIC_NOT_IMPLEMENTED => return error.NotImplemented, + c.E_MIC_DRIVER_INIT => return error.DriverInitFailed, + c.E_MIC_DRIVER_NOT_LOADED => return error.DriverNotLoaded, + c.E_MIC_IOCTL_FAILED => return error.IoctlFailed, + c.E_MIC_ERROR_NOT_FOUND => return error.NotFound, + c.E_MIC_NOMEM => return error.NoMemory, + c.E_MIC_RANGE => return error.OutOfRange, + c.E_MIC_INTERNAL => return error.Internal, + c.E_MIC_SYSTEM => return error.System, + c.E_MIC_SCIF_ERROR => return error.Scif, + c.E_MIC_RAS_ERROR => return error.Ras, + c.E_MIC_STACK => return error.Stack, + c.E_MIC_GET_WMI_PARAM_VALUE_FAILED => return error.WmiParameterReadFailed, + c.E_NO_WINDOWS_SUPPORT => return error.WindowsUnsupported, + c.E_WMI_FAILED => return error.WmiFailed, + else => return error.Unknown, + } +} + +pub fn lastErrorString() []const u8 { + return cString(c.mic_get_error_string()); +} + +pub fn clearLastErrorString() MicError!void { + try check(c.mic_clear_error_string()); +} + +pub fn rasErrno() c_int { + return c.mic_get_ras_errno(); +} + +pub fn rasErrorString(ras_errno: c_int) []const u8 { + return cString(c.mic_get_ras_error_string(ras_errno)); +} + +pub fn cString(ptr: [*c]const u8) []const u8 { + if (ptr == null) return ""; + + var len: usize = 0; + while (ptr[len] != 0) : (len += 1) {} + return ptr[0..len]; +} + +pub fn trimCString(buffer: []const u8) []const u8 { + const len = std.mem.indexOfScalar(u8, buffer, 0) orelse buffer.len; + return buffer[0..len]; +} + +fn ensureHandle(comptime T: type, maybe_handle: ?*T) MicError!*T { + return maybe_handle orelse error.Unknown; +} + +fn intToUsize(value: c_int) MicError!usize { + if (value < 0) return error.OutOfRange; + return @as(usize, @intCast(value)); +} + +fn usizeToCInt(value: usize) MicError!c_int { + if (value > @as(usize, @intCast(std.math.maxInt(c_int)))) return error.OutOfRange; + return @as(c_int, @intCast(value)); +} + +fn getValue(comptime T: type, comptime func: anytype, handle: anytype) MicError!T { + var value: T = 0; + try check(func(handle, &value)); + return value; +} + +fn getBoolInt(comptime func: anytype, handle: anytype) MicError!bool { + return (try getValue(c_int, func, handle)) != 0; +} + +fn getBoolU32(comptime func: anytype, handle: anytype) MicError!bool { + return (try getValue(u32, func, handle)) != 0; +} + +fn getString(comptime func: anytype, handle: anytype, buffer: []u8) MicError![]const u8 { + if (buffer.len == 0) return error.OutOfRange; + + var size: usize = buffer.len; + try check(func(handle, buffer.ptr, &size)); + return trimCString(buffer[0..@min(size, buffer.len)]); +} + +pub const DeviceList = struct { + handle: *c.struct_mic_devices_list, + + pub fn init() MicError!DeviceList { + var handle: ?*c.struct_mic_devices_list = null; + try check(c.mic_get_devices(&handle)); + return .{ .handle = try ensureHandle(c.struct_mic_devices_list, handle) }; + } + + pub fn deinit(self: *DeviceList) void { + _ = c.mic_free_devices(self.handle); + } + + pub fn count(self: DeviceList) MicError!usize { + var ndevices: c_int = 0; + try check(c.mic_get_ndevices(self.handle, &ndevices)); + return intToUsize(ndevices); + } + + pub fn deviceAtIndex(self: DeviceList, index: usize) MicError!u32 { + var device: c_int = 0; + try check(c.mic_get_device_at_index(self.handle, try usizeToCInt(index), &device)); + if (device < 0) return error.OutOfRange; + return @as(u32, @intCast(device)); + } +}; + +pub const Device = struct { + handle: *c.struct_mic_device, + + pub fn open(device_num: u32) MicError!Device { + var handle: ?*c.struct_mic_device = null; + try check(c.mic_open_device(&handle, device_num)); + return .{ .handle = try ensureHandle(c.struct_mic_device, handle) }; + } + + pub fn deinit(self: *Device) void { + _ = c.mic_close_device(self.handle); + } + + pub fn enterMaintMode(self: Device) MicError!void { + try check(c.mic_enter_maint_mode(self.handle)); + } + + pub fn leaveMaintMode(self: Device) MicError!void { + try check(c.mic_leave_maint_mode(self.handle)); + } + + pub fn inMaintMode(self: Device) MicError!bool { + return getBoolInt(c.mic_in_maint_mode, self.handle); + } + + pub fn inReadyState(self: Device) MicError!bool { + return getBoolInt(c.mic_in_ready_state, self.handle); + } + + pub fn postCode(self: Device, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_post_code, self.handle, buffer); + } + + pub fn deviceType(self: Device) MicError!u32 { + return getValue(u32, c.mic_get_device_type, self.handle); + } + + pub fn name(self: Device) []const u8 { + return cString(c.mic_get_device_name(self.handle)); + } + + pub fn siliconSku(self: Device, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_silicon_sku, self.handle, buffer); + } + + pub fn serialNumber(self: Device, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_serial_number, self.handle, buffer); + } + + pub fn uuid(self: Device, buffer: []u8) MicError![]const u8 { + if (buffer.len == 0) return error.OutOfRange; + + var size: usize = buffer.len; + try check(c.mic_get_uuid(self.handle, buffer.ptr, &size)); + return buffer[0..@min(size, buffer.len)]; + } + + pub fn sysfsAttribute(self: Device, entry: [:0]const u8, buffer: []u8) MicError![]const u8 { + if (buffer.len == 0) return error.OutOfRange; + + var size: usize = buffer.len; + try check(c.mic_get_sysfs_attribute(self.handle, entry.ptr, buffer.ptr, &size)); + return trimCString(buffer[0..@min(size, buffer.len)]); + } + + pub fn isRasAvailable(self: Device) MicError!bool { + return getBoolInt(c.mic_is_ras_avail, self.handle); + } + + pub fn flashUpdateStart(self: Device, image: []const u8) MicError!FlashOperation { + var handle: ?*c.struct_mic_flash_op = null; + const image_ptr: ?*anyopaque = @ptrCast(@constCast(image.ptr)); + try check(c.mic_flash_update_start(self.handle, image_ptr, image.len, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_flash_op, handle), .kind = .update }; + } + + pub fn flashReadStart(self: Device, buffer: []u8) MicError!FlashOperation { + var handle: ?*c.struct_mic_flash_op = null; + const buffer_ptr: ?*anyopaque = @ptrCast(buffer.ptr); + try check(c.mic_flash_read_start(self.handle, buffer_ptr, buffer.len, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_flash_op, handle), .kind = .read }; + } + + pub fn setEccModeStart(self: Device, ecc_enabled: u16) MicError!FlashOperation { + var handle: ?*c.struct_mic_flash_op = null; + try check(c.mic_set_ecc_mode_start(self.handle, ecc_enabled, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_flash_op, handle), .kind = .set_ecc }; + } + + pub fn flashVendorDevice(self: Device, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_flash_vendor_device, self.handle, buffer); + } + + pub fn flashSize(self: Device) MicError!usize { + return getValue(usize, c.mic_flash_size, self.handle); + } + + pub fn flashActiveOffset(self: Device) MicError!c.off_t { + return getValue(c.off_t, c.mic_flash_active_offs, self.handle); + } + + pub fn flashVersion(self: Device, image: ?*anyopaque, buffer: []u8) MicError![]const u8 { + if (buffer.len == 0) return error.OutOfRange; + + try check(c.mic_flash_version(self.handle, image, buffer.ptr, buffer.len)); + return trimCString(buffer); + } + + pub fn pciConfig(self: Device) MicError!PciConfig { + return PciConfig.init(self); + } + + pub fn thermalInfo(self: Device) MicError!ThermalInfo { + return ThermalInfo.init(self); + } + + pub fn memoryInfo(self: Device) MicError!MemoryInfo { + return MemoryInfo.init(self); + } + + pub fn processorInfo(self: Device) MicError!ProcessorInfo { + return ProcessorInfo.init(self); + } + + pub fn coresInfo(self: Device) MicError!CoresInfo { + return CoresInfo.init(self); + } + + pub fn versionInfo(self: Device) MicError!VersionInfo { + return VersionInfo.init(self); + } + + pub fn powerUtilizationInfo(self: Device) MicError!PowerUtilizationInfo { + return PowerUtilizationInfo.init(self); + } + + pub fn powerLimit(self: Device) MicError!PowerLimit { + return PowerLimit.init(self); + } + + pub fn memoryUtilizationInfo(self: Device) MicError!MemoryUtilizationInfo { + return MemoryUtilizationInfo.init(self); + } + + pub fn ledAlert(self: Device) MicError!u32 { + return getValue(u32, c.mic_get_led_alert, self.handle); + } + + pub fn setLedAlert(self: Device, value: u32) MicError!void { + var mutable_value = value; + try check(c.mic_set_led_alert(self.handle, &mutable_value)); + } + + pub fn turboStateInfo(self: Device) MicError!TurboInfo { + return TurboInfo.init(self); + } + + pub fn setTurboMode(self: Device, mode: u32) MicError!void { + var mutable_mode = mode; + try check(c.mic_set_turbo_mode(self.handle, &mutable_mode)); + } + + pub fn throttleStateInfo(self: Device) MicError!ThrottleStateInfo { + return ThrottleStateInfo.init(self); + } + + pub fn uosPmConfig(self: Device) MicError!UosPmConfig { + return UosPmConfig.init(self); + } + + pub fn smcPersistenceFlag(self: Device) MicError!bool { + return getBoolInt(c.mic_get_smc_persistence_flag, self.handle); + } + + pub fn setSmcPersistenceFlag(self: Device, persist: bool) MicError!void { + try check(c.mic_set_smc_persistence_flag(self.handle, @as(c_int, @intFromBool(persist)))); + } + + pub fn setPowerLimit0(self: Device, power: u32, time_window: u32) MicError!void { + try check(c.mic_set_power_limit0(self.handle, power, time_window)); + } + + pub fn setPowerLimit1(self: Device, power: u32, time_window: u32) MicError!void { + try check(c.mic_set_power_limit1(self.handle, power, time_window)); + } +}; + +pub const FlashOperationKind = enum { + update, + read, + set_ecc, +}; + +pub const FlashOperation = struct { + handle: *c.struct_mic_flash_op, + kind: FlashOperationKind, + completed: bool = false, + + pub fn deinit(self: *FlashOperation) void { + if (!self.completed) self.done() catch {}; + } + + pub fn done(self: *FlashOperation) MicError!void { + if (self.completed) return; + + const result = switch (self.kind) { + .update => c.mic_flash_update_done(self.handle), + .read => c.mic_flash_read_done(self.handle), + .set_ecc => c.mic_set_ecc_mode_done(self.handle), + }; + try check(result); + self.completed = true; + } + + pub fn statusInfo(self: FlashOperation) MicError!FlashStatusInfo { + var handle: ?*c.struct_mic_flash_status_info = null; + try check(c.mic_get_flash_status_info(self.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_flash_status_info, handle) }; + } +}; + +pub const FlashStatusInfo = struct { + handle: *c.struct_mic_flash_status_info, + + pub fn deinit(self: *FlashStatusInfo) void { + _ = c.mic_free_flash_status_info(self.handle); + } + + pub fn progress(self: FlashStatusInfo) MicError!u32 { + return getValue(u32, c.mic_get_progress, self.handle); + } + + pub fn status(self: FlashStatusInfo) MicError!c_int { + return getValue(c_int, c.mic_get_status, self.handle); + } + + pub fn extendedStatus(self: FlashStatusInfo) MicError!c_int { + return getValue(c_int, c.mic_get_ext_status, self.handle); + } +}; + +pub const PciConfig = struct { + handle: *c.struct_mic_pci_config, + + pub fn init(device: Device) MicError!PciConfig { + var handle: ?*c.struct_mic_pci_config = null; + try check(c.mic_get_pci_config(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_pci_config, handle) }; + } + + pub fn deinit(self: *PciConfig) void { + _ = c.mic_free_pci_config(self.handle); + } + + pub fn domainId(self: PciConfig) MicError!u16 { + return getValue(u16, c.mic_get_pci_domain_id, self.handle); + } + + pub fn busNumber(self: PciConfig) MicError!u16 { + return getValue(u16, c.mic_get_bus_number, self.handle); + } + + pub fn deviceNumber(self: PciConfig) MicError!u16 { + return getValue(u16, c.mic_get_device_number, self.handle); + } + + pub fn vendorId(self: PciConfig) MicError!u16 { + return getValue(u16, c.mic_get_vendor_id, self.handle); + } + + pub fn deviceId(self: PciConfig) MicError!u16 { + return getValue(u16, c.mic_get_device_id, self.handle); + } + + pub fn revisionId(self: PciConfig) MicError!u8 { + return getValue(u8, c.mic_get_revision_id, self.handle); + } + + pub fn subsystemId(self: PciConfig) MicError!u16 { + return getValue(u16, c.mic_get_subsystem_id, self.handle); + } + + pub fn linkSpeed(self: PciConfig, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_link_speed, self.handle, buffer); + } + + pub fn linkWidth(self: PciConfig) MicError!u32 { + return getValue(u32, c.mic_get_link_width, self.handle); + } + + pub fn maxPayload(self: PciConfig) MicError!u32 { + return getValue(u32, c.mic_get_max_payload, self.handle); + } + + pub fn maxReadRequest(self: PciConfig) MicError!u32 { + return getValue(u32, c.mic_get_max_readreq, self.handle); + } + + pub fn classCode(self: PciConfig, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_pci_class_code, self.handle, buffer); + } +}; + +pub const ThermalInfo = struct { + handle: *c.struct_mic_thermal_info, + + pub fn init(device: Device) MicError!ThermalInfo { + var handle: ?*c.struct_mic_thermal_info = null; + try check(c.mic_get_thermal_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_thermal_info, handle) }; + } + + pub fn deinit(self: *ThermalInfo) void { + _ = c.mic_free_thermal_info(self.handle); + } + + pub fn smcHardwareRevision(self: ThermalInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_smc_hwrevision, self.handle, buffer); + } + + pub fn smcFirmwareVersion(self: ThermalInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_smc_fwversion, self.handle, buffer); + } + + pub fn isSmcBootLoaderVersionSupported(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_smc_boot_loader_ver_supported, self.handle); + } + + pub fn smcBootLoaderVersion(self: ThermalInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_smc_boot_loader_ver, self.handle, buffer); + } + + pub fn fscStatus(self: ThermalInfo) MicError!u32 { + return getValue(u32, c.mic_get_fsc_status, self.handle); + } + + pub fn dieTemp(self: ThermalInfo) MicError!u32 { + return getValue(u32, c.mic_get_die_temp, self.handle); + } + + pub fn isDieTempValid(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_die_temp_valid, self.handle); + } + + pub fn gddrTemp(self: ThermalInfo) MicError!u16 { + return getValue(u16, c.mic_get_gddr_temp, self.handle); + } + + pub fn isGddrTempValid(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_gddr_temp_valid, self.handle); + } + + pub fn fanInTemp(self: ThermalInfo) MicError!u16 { + return getValue(u16, c.mic_get_fanin_temp, self.handle); + } + + pub fn isFanInTempValid(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_fanin_temp_valid, self.handle); + } + + pub fn fanOutTemp(self: ThermalInfo) MicError!u16 { + return getValue(u16, c.mic_get_fanout_temp, self.handle); + } + + pub fn isFanOutTempValid(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_fanout_temp_valid, self.handle); + } + + pub fn vccpTemp(self: ThermalInfo) MicError!u16 { + return getValue(u16, c.mic_get_vccp_temp, self.handle); + } + + pub fn isVccpTempValid(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_vccp_temp_valid, self.handle); + } + + pub fn vddgTemp(self: ThermalInfo) MicError!u16 { + return getValue(u16, c.mic_get_vddg_temp, self.handle); + } + + pub fn isVddgTempValid(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_vddg_temp_valid, self.handle); + } + + pub fn vddqTemp(self: ThermalInfo) MicError!u16 { + return getValue(u16, c.mic_get_vddq_temp, self.handle); + } + + pub fn isVddqTempValid(self: ThermalInfo) MicError!bool { + return getBoolInt(c.mic_is_vddq_temp_valid, self.handle); + } + + pub fn fanRpm(self: ThermalInfo) MicError!u32 { + return getValue(u32, c.mic_get_fan_rpm, self.handle); + } + + pub fn fanPwm(self: ThermalInfo) MicError!u32 { + return getValue(u32, c.mic_get_fan_pwm, self.handle); + } +}; + +pub const MemoryInfo = struct { + handle: *c.struct_mic_device_mem, + + pub fn init(device: Device) MicError!MemoryInfo { + var handle: ?*c.struct_mic_device_mem = null; + try check(c.mic_get_memory_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_device_mem, handle) }; + } + + pub fn deinit(self: *MemoryInfo) void { + _ = c.mic_free_memory_info(self.handle); + } + + pub fn vendor(self: MemoryInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_memory_vendor, self.handle, buffer); + } + + pub fn revision(self: MemoryInfo) MicError!u32 { + return getValue(u32, c.mic_get_memory_revision, self.handle); + } + + pub fn density(self: MemoryInfo) MicError!u32 { + return getValue(u32, c.mic_get_memory_density, self.handle); + } + + pub fn size(self: MemoryInfo) MicError!u32 { + return getValue(u32, c.mic_get_memory_size, self.handle); + } + + pub fn speed(self: MemoryInfo) MicError!u32 { + return getValue(u32, c.mic_get_memory_speed, self.handle); + } + + pub fn memoryType(self: MemoryInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_memory_type, self.handle, buffer); + } + + pub fn frequency(self: MemoryInfo) MicError!u32 { + return getValue(u32, c.mic_get_memory_frequency, self.handle); + } + + pub fn voltage(self: MemoryInfo) MicError!u32 { + return getValue(u32, c.mic_get_memory_voltage, self.handle); + } + + pub fn eccMode(self: MemoryInfo) MicError!u16 { + return getValue(u16, c.mic_get_ecc_mode, self.handle); + } +}; + +pub const ProcessorModel = struct { + model: u16, + model_ext: u16, +}; + +pub const ProcessorFamily = struct { + family: u16, + family_ext: u16, +}; + +pub const ProcessorInfo = struct { + handle: *c.struct_mic_processor_info, + + pub fn init(device: Device) MicError!ProcessorInfo { + var handle: ?*c.struct_mic_processor_info = null; + try check(c.mic_get_processor_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_processor_info, handle) }; + } + + pub fn deinit(self: *ProcessorInfo) void { + _ = c.mic_free_processor_info(self.handle); + } + + pub fn model(self: ProcessorInfo) MicError!ProcessorModel { + var value: ProcessorModel = .{ .model = 0, .model_ext = 0 }; + try check(c.mic_get_processor_model(self.handle, &value.model, &value.model_ext)); + return value; + } + + pub fn family(self: ProcessorInfo) MicError!ProcessorFamily { + var value: ProcessorFamily = .{ .family = 0, .family_ext = 0 }; + try check(c.mic_get_processor_family(self.handle, &value.family, &value.family_ext)); + return value; + } + + pub fn processorType(self: ProcessorInfo) MicError!u16 { + return getValue(u16, c.mic_get_processor_type, self.handle); + } + + pub fn steppingId(self: ProcessorInfo) MicError!u32 { + return getValue(u32, c.mic_get_processor_steppingid, self.handle); + } + + pub fn stepping(self: ProcessorInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_processor_stepping, self.handle, buffer); + } +}; + +pub const CoresInfo = struct { + handle: *c.struct_mic_cores_info, + + pub fn init(device: Device) MicError!CoresInfo { + var handle: ?*c.struct_mic_cores_info = null; + try check(c.mic_get_cores_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_cores_info, handle) }; + } + + pub fn deinit(self: *CoresInfo) void { + _ = c.mic_free_cores_info(self.handle); + } + + pub fn count(self: CoresInfo) MicError!u32 { + return getValue(u32, c.mic_get_cores_count, self.handle); + } + + pub fn voltage(self: CoresInfo) MicError!u32 { + return getValue(u32, c.mic_get_cores_voltage, self.handle); + } + + pub fn frequency(self: CoresInfo) MicError!u32 { + return getValue(u32, c.mic_get_cores_frequency, self.handle); + } +}; + +pub const VersionInfo = struct { + handle: *c.struct_mic_version_info, + + pub fn init(device: Device) MicError!VersionInfo { + var handle: ?*c.struct_mic_version_info = null; + try check(c.mic_get_version_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_version_info, handle) }; + } + + pub fn deinit(self: *VersionInfo) void { + _ = c.mic_free_version_info(self.handle); + } + + pub fn uosVersion(self: VersionInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_uos_version, self.handle, buffer); + } + + pub fn flashVersion(self: VersionInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_flash_version, self.handle, buffer); + } + + pub fn fscStrap(self: VersionInfo, buffer: []u8) MicError![]const u8 { + return getString(c.mic_get_fsc_strap, self.handle, buffer); + } +}; + +pub const PowerUtilizationInfo = struct { + handle: *c.struct_mic_power_util_info, + + pub fn init(device: Device) MicError!PowerUtilizationInfo { + var handle: ?*c.struct_mic_power_util_info = null; + try check(c.mic_get_power_utilization_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_power_util_info, handle) }; + } + + pub fn deinit(self: *PowerUtilizationInfo) void { + _ = c.mic_free_power_utilization_info(self.handle); + } + + pub fn totalPowerReadingsW0(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_total_power_readings_w0, self.handle); + } + pub fn totalPowerSensorStatusW0(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_total_power_sensor_sts_w0, self.handle); + } + pub fn totalPowerReadingsW1(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_total_power_readings_w1, self.handle); + } + pub fn totalPowerSensorStatusW1(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_total_power_sensor_sts_w1, self.handle); + } + pub fn instantaneousPowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_inst_power_readings, self.handle); + } + pub fn instantaneousPowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_inst_power_sensor_sts, self.handle); + } + pub fn maxInstantaneousPowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_max_inst_power_readings, self.handle); + } + pub fn maxInstantaneousPowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_max_inst_power_sensor_sts, self.handle); + } + pub fn pciePowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_pcie_power_readings, self.handle); + } + pub fn pciePowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_pcie_power_sensor_sts, self.handle); + } + pub fn c2x3PowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_c2x3_power_readings, self.handle); + } + pub fn c2x3PowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_c2x3_power_sensor_sts, self.handle); + } + pub fn c2x4PowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_c2x4_power_readings, self.handle); + } + pub fn c2x4PowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_c2x4_power_sensor_sts, self.handle); + } + pub fn vccpPowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vccp_power_readings, self.handle); + } + pub fn vccpPowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vccp_power_sensor_sts, self.handle); + } + pub fn vccpCurrentReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vccp_current_readings, self.handle); + } + pub fn vccpCurrentSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vccp_current_sensor_sts, self.handle); + } + pub fn vccpVoltageReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vccp_voltage_readings, self.handle); + } + pub fn vccpVoltageSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vccp_voltage_sensor_sts, self.handle); + } + pub fn vddgPowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddg_power_readings, self.handle); + } + pub fn vddgPowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddg_power_sensor_sts, self.handle); + } + pub fn vddgCurrentReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddg_current_readings, self.handle); + } + pub fn vddgCurrentSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddg_current_sensor_sts, self.handle); + } + pub fn vddgVoltageReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddg_voltage_readings, self.handle); + } + pub fn vddgVoltageSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddg_voltage_sensor_sts, self.handle); + } + pub fn vddqPowerReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddq_power_readings, self.handle); + } + pub fn vddqPowerSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddq_power_sensor_sts, self.handle); + } + pub fn vddqCurrentReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddq_current_readings, self.handle); + } + pub fn vddqCurrentSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddq_current_sensor_sts, self.handle); + } + pub fn vddqVoltageReadings(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddq_voltage_readings, self.handle); + } + pub fn vddqVoltageSensorStatus(self: PowerUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_vddq_voltage_sensor_sts, self.handle); + } +}; + +pub const PowerLimit = struct { + handle: *c.struct_mic_power_limit, + + pub fn init(device: Device) MicError!PowerLimit { + var handle: ?*c.struct_mic_power_limit = null; + try check(c.mic_get_power_limit(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_power_limit, handle) }; + } + + pub fn deinit(self: *PowerLimit) void { + _ = c.mic_free_power_limit(self.handle); + } + + pub fn physicalLimit(self: PowerLimit) MicError!u32 { + return getValue(u32, c.mic_get_power_phys_limit, self.handle); + } + pub fn highWatermark(self: PowerLimit) MicError!u32 { + return getValue(u32, c.mic_get_power_hmrk, self.handle); + } + pub fn lowWatermark(self: PowerLimit) MicError!u32 { + return getValue(u32, c.mic_get_power_lmrk, self.handle); + } + pub fn timeWindow0(self: PowerLimit) MicError!u32 { + return getValue(u32, c.mic_get_time_window0, self.handle); + } + pub fn timeWindow1(self: PowerLimit) MicError!u32 { + return getValue(u32, c.mic_get_time_window1, self.handle); + } +}; + +pub const MemoryUtilizationInfo = struct { + handle: *c.struct_mic_memory_util_info, + + pub fn init(device: Device) MicError!MemoryUtilizationInfo { + var handle: ?*c.struct_mic_memory_util_info = null; + try check(c.mic_get_memory_utilization_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_memory_util_info, handle) }; + } + + pub fn deinit(self: *MemoryUtilizationInfo) void { + _ = c.mic_free_memory_utilization_info(self.handle); + } + + pub fn totalMemorySize(self: MemoryUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_total_memory_size, self.handle); + } + pub fn availableMemorySize(self: MemoryUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_available_memory_size, self.handle); + } + pub fn memoryBuffersSize(self: MemoryUtilizationInfo) MicError!u32 { + return getValue(u32, c.mic_get_memory_buffers_size, self.handle); + } +}; + +pub const CoreUtil = struct { + handle: *c.struct_mic_core_util, + + pub fn init() MicError!CoreUtil { + var handle: ?*c.struct_mic_core_util = null; + try check(c.mic_alloc_core_util(&handle)); + return .{ .handle = try ensureHandle(c.struct_mic_core_util, handle) }; + } + + pub fn deinit(self: *CoreUtil) void { + _ = c.mic_free_core_util(self.handle); + } + + pub fn update(self: CoreUtil, device: Device) MicError!void { + try check(c.mic_update_core_util(device.handle, self.handle)); + } + + pub fn idleCounters(self: CoreUtil, counters: []u64) MicError!void { + if (counters.len == 0) return error.OutOfRange; + try check(c.mic_get_idle_counters(self.handle, counters.ptr)); + } + + pub fn niceCounters(self: CoreUtil, counters: []u64) MicError!void { + if (counters.len == 0) return error.OutOfRange; + try check(c.mic_get_nice_counters(self.handle, counters.ptr)); + } + + pub fn systemCounters(self: CoreUtil, counters: []u64) MicError!void { + if (counters.len == 0) return error.OutOfRange; + try check(c.mic_get_sys_counters(self.handle, counters.ptr)); + } + + pub fn userCounters(self: CoreUtil, counters: []u64) MicError!void { + if (counters.len == 0) return error.OutOfRange; + try check(c.mic_get_user_counters(self.handle, counters.ptr)); + } + + pub fn idleSum(self: CoreUtil) MicError!u64 { + return getValue(u64, c.mic_get_idle_sum, self.handle); + } + pub fn systemSum(self: CoreUtil) MicError!u64 { + return getValue(u64, c.mic_get_sys_sum, self.handle); + } + pub fn niceSum(self: CoreUtil) MicError!u64 { + return getValue(u64, c.mic_get_nice_sum, self.handle); + } + pub fn userSum(self: CoreUtil) MicError!u64 { + return getValue(u64, c.mic_get_user_sum, self.handle); + } + pub fn jiffyCounter(self: CoreUtil) MicError!u64 { + return getValue(u64, c.mic_get_jiffy_counter, self.handle); + } + pub fn numCores(self: CoreUtil) MicError!u16 { + return getValue(u16, c.mic_get_num_cores, self.handle); + } + pub fn threadsPerCore(self: CoreUtil) MicError!u16 { + return getValue(u16, c.mic_get_threads_core, self.handle); + } + pub fn tickCount(self: CoreUtil) MicError!u32 { + return getValue(u32, c.mic_get_tick_count, self.handle); + } + + pub fn counterCount(self: CoreUtil) MicError!usize { + return @as(usize, try self.numCores()) * @as(usize, try self.threadsPerCore()); + } +}; + +pub const TurboInfo = struct { + handle: *c.struct_mic_turbo_info, + + pub fn init(device: Device) MicError!TurboInfo { + var handle: ?*c.struct_mic_turbo_info = null; + try check(c.mic_get_turbo_state_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_turbo_info, handle) }; + } + + pub fn deinit(self: *TurboInfo) void { + _ = c.mic_free_turbo_info(self.handle); + } + + pub fn state(self: TurboInfo) MicError!u32 { + return getValue(u32, c.mic_get_turbo_state, self.handle); + } + pub fn mode(self: TurboInfo) MicError!u32 { + return getValue(u32, c.mic_get_turbo_mode, self.handle); + } + pub fn isStateValid(self: TurboInfo) MicError!bool { + return getBoolU32(c.mic_get_turbo_state_valid, self.handle); + } +}; + +pub const ThrottleStateInfo = struct { + handle: *c.struct_mic_throttle_state_info, + + pub fn init(device: Device) MicError!ThrottleStateInfo { + var handle: ?*c.struct_mic_throttle_state_info = null; + try check(c.mic_get_throttle_state_info(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_throttle_state_info, handle) }; + } + + pub fn deinit(self: *ThrottleStateInfo) void { + _ = c.mic_free_throttle_state_info(self.handle); + } + + pub fn thermalActive(self: ThrottleStateInfo) MicError!bool { + return getBoolInt(c.mic_get_thermal_ttl_active, self.handle); + } + pub fn thermalCurrentLength(self: ThrottleStateInfo) MicError!u32 { + return getValue(u32, c.mic_get_thermal_ttl_current_len, self.handle); + } + pub fn thermalCount(self: ThrottleStateInfo) MicError!u32 { + return getValue(u32, c.mic_get_thermal_ttl_count, self.handle); + } + pub fn thermalTime(self: ThrottleStateInfo) MicError!u32 { + return getValue(u32, c.mic_get_thermal_ttl_time, self.handle); + } + pub fn powerActive(self: ThrottleStateInfo) MicError!bool { + return getBoolInt(c.mic_get_power_ttl_active, self.handle); + } + pub fn powerCurrentLength(self: ThrottleStateInfo) MicError!u32 { + return getValue(u32, c.mic_get_power_ttl_current_len, self.handle); + } + pub fn powerCount(self: ThrottleStateInfo) MicError!u32 { + return getValue(u32, c.mic_get_power_ttl_count, self.handle); + } + pub fn powerTime(self: ThrottleStateInfo) MicError!u32 { + return getValue(u32, c.mic_get_power_ttl_time, self.handle); + } +}; + +pub const UosPmConfig = struct { + handle: *c.struct_mic_uos_pm_config, + + pub fn init(device: Device) MicError!UosPmConfig { + var handle: ?*c.struct_mic_uos_pm_config = null; + try check(c.mic_get_uos_pm_config(device.handle, &handle)); + return .{ .handle = try ensureHandle(c.struct_mic_uos_pm_config, handle) }; + } + + pub fn deinit(self: *UosPmConfig) void { + _ = c.mic_free_uos_pm_config(self.handle); + } + + pub fn cpuFreqMode(self: UosPmConfig) MicError!c_int { + return getValue(c_int, c.mic_get_cpufreq_mode, self.handle); + } + pub fn coreC6Mode(self: UosPmConfig) MicError!c_int { + return getValue(c_int, c.mic_get_corec6_mode, self.handle); + } + pub fn pc3Mode(self: UosPmConfig) MicError!c_int { + return getValue(c_int, c.mic_get_pc3_mode, self.handle); + } + pub fn pc6Mode(self: UosPmConfig) MicError!c_int { + return getValue(c_int, c.mic_get_pc6_mode, self.handle); + } +}; + +test "error mapping keeps success successful" { + try check(c.E_MIC_SUCCESS); +} + +test "trim c string" { + try std.testing.expectEqualStrings("abc", trimCString("abc\x00def")); +} diff --git a/third_party/NOTICES.md b/third_party/NOTICES.md new file mode 100644 index 0000000..7e06cd4 --- /dev/null +++ b/third_party/NOTICES.md @@ -0,0 +1,7 @@ +# Third-party notices + +This package is a Zig wrapper only. It does not vendor or redistribute Intel/CIRCL `miclib.h`, `scif.h`, `libmicmgmt`, `libscif`, MPSS, or any Xeon Phi firmware/tooling. + +The upstream `CIRCL/miclib` repository describes itself as `miclib v3.6.1 (Intel Xeon Phi Coprocessor) for Ubuntu LTS 14.04 Trusty (extracted from mpss-micmgmt)`. + +The upstream `miclib.h` header is licensed under LGPL-2.1 text in its header comments and carries Intel notices. Link and distribute the native library according to the license terms that apply to your installed MPSS/miclib build.