mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-04-29 03:00:14 -04:00
tbgpu: shim binary + remote apl pci dev (#14124)
* shim binary + remote pci dev * v2 * rip out apl * cmds * rename * clean * remove * rm gitignore * ui * install * linter * um * cleaner * assets * normal install in ui * cleaner app * install script * support fd mmap * cleaner * kill server when disconn * rename + pcidevs * sign * install and reinstall * no sip install * will trigger update * nv * ugh * this * fix * nv * use nosip sign * auto install * remove * mypy * upd * ditto * print * simpler * ditto * um * simpler * upd * upd * cleaner * autogen * cleaner * move * annotations * server cleaner
This commit is contained in:
6
.github/workflows/autogen.yml
vendored
6
.github/workflows/autogen.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
run: sudo apt-get install -y --no-install-recommends libclang-20-dev llvm-20-dev hip-dev libusb-1.0-0-dev
|
||||
- name: Regenerate autogen files
|
||||
run: |
|
||||
find tinygrad/runtime/autogen -type f -name "*.py" -not -name "__init__.py" -not -name "comgr_3.py" -not -name "metal.py" -not -name "libclang.py" -delete
|
||||
find tinygrad/runtime/autogen -type f -name "*.py" -not -name "__init__.py" -not -name "comgr_3.py" -not -name "metal.py" -not -name "iokit.py" -not -name "corefoundation.py" -not -name "libclang.py" -delete
|
||||
python3 -c "from tinygrad.runtime.autogen import opencl"
|
||||
python3 -c "from tinygrad.runtime.autogen import cuda, nvrtc, nvjitlink, nv_570, nv_580, nv"
|
||||
python3 -c "from tinygrad.runtime.autogen import comgr, hsa, hip, amd_gpu, sqtt, rocprof, amdgpu_kd"
|
||||
@@ -83,8 +83,8 @@ jobs:
|
||||
llvm: 'true'
|
||||
- name: Regenerate autogen files
|
||||
run: |
|
||||
rm tinygrad/runtime/autogen/metal.py
|
||||
LIBCLANG_PATH=/opt/homebrew/opt/llvm@20/lib/libclang.dylib python3 -c "from tinygrad.runtime.autogen import metal"
|
||||
rm tinygrad/runtime/autogen/metal.py tinygrad/runtime/autogen/iokit.py tinygrad/runtime/autogen/corefoundation.py
|
||||
LIBCLANG_PATH=/opt/homebrew/opt/llvm@20/lib/libclang.dylib python3 -c "from tinygrad.runtime.autogen import metal, iokit, corefoundation"
|
||||
- name: Check for differences
|
||||
run: |
|
||||
if ! git diff --quiet; then
|
||||
|
||||
22
extra/usbgpu/tbgpu/install_tinygpu.sh
Executable file
22
extra/usbgpu/tbgpu/install_tinygpu.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
APP_PATH="/Applications/TinyGPU.app"
|
||||
DEXT_ID="org.tinygrad.tinygpu.edriver"
|
||||
|
||||
# Install app if not present. TODO: url
|
||||
if [[ ! -d "$APP_PATH" ]]; then
|
||||
echo "TinyGPU.app not found in /Applications"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ask user to install
|
||||
read -n1 -p "Install TinyGPU driver extension now? [y/N] " answer
|
||||
echo
|
||||
|
||||
if [[ "$answer" =~ ^[Yy]$ ]]; then
|
||||
"$APP_PATH/Contents/MacOS/TinyGPU" install
|
||||
else
|
||||
echo "Skipped."
|
||||
exit 0
|
||||
fi
|
||||
@@ -0,0 +1 @@
|
||||
int run_server(const char *sock_path);
|
||||
@@ -1,19 +1,48 @@
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
private let dextID = "org.tinygrad.tinygpu.edriver"
|
||||
|
||||
@main
|
||||
struct TinyGPUApp: App {
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||
private static var runner: TinyGPUCLIRunner? // prevent dealloc before callback
|
||||
@State private var text = ""
|
||||
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
TinyGPUView()
|
||||
}
|
||||
init() {
|
||||
guard CommandLine.arguments.count > 1 else { return }
|
||||
Self.runner = TinyGPUCLIRunner(dextID)
|
||||
Self.runner?.run(args: CommandLine.arguments) { exit($0.rawValue) }
|
||||
dispatchMain()
|
||||
}
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup("TinyGPU") {
|
||||
ScrollView {
|
||||
Text(text).font(.custom("Menlo", size: 11)).frame(maxWidth: .infinity, alignment: .leading).padding(8)
|
||||
}
|
||||
.frame(width: 500, height: 300).padding()
|
||||
.onAppear { setup() }
|
||||
}
|
||||
.commands { CommandGroup(replacing: .newItem) {} }
|
||||
}
|
||||
|
||||
func setup() {
|
||||
let bundlePath = Bundle.main.bundlePath
|
||||
guard bundlePath.hasPrefix("/Applications/") else {
|
||||
var error: NSDictionary?
|
||||
NSAppleScript(source: "do shell script \"mv '\(bundlePath)' '/Applications/'\" with administrator privileges")?.executeAndReturnError(&error)
|
||||
text = error == nil ? "Moved! Please reopen from /Applications/\n" : "Move TinyGPU to /Applications first.\n"
|
||||
return
|
||||
}
|
||||
let state = TinyGPUCLIRunner.queryDextState(dextID)
|
||||
if state == .unloaded || state == .activating {
|
||||
Self.runner = TinyGPUCLIRunner(dextID)
|
||||
Self.runner?.run(args: ["", "install"]) { _ in }
|
||||
}
|
||||
text = "TinyGPU - Remote PCI Device Server\n\n" + TinyGPUCLIRunner.statusText(state)
|
||||
}
|
||||
}
|
||||
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { true }
|
||||
}
|
||||
|
||||
122
extra/usbgpu/tbgpu/installer/Shared/TinyGPUCLIRunner.swift
Normal file
122
extra/usbgpu/tbgpu/installer/Shared/TinyGPUCLIRunner.swift
Normal file
@@ -0,0 +1,122 @@
|
||||
import Foundation
|
||||
import SystemExtensions
|
||||
|
||||
enum TinyGPUCLIExit: Int32 { case ok = 0, usage = 2, failed = 3, needsApproval = 4 }
|
||||
enum DextState { case unloaded, activating, needsApproval, activated }
|
||||
|
||||
final class TinyGPUCLIRunner: NSObject, OSSystemExtensionRequestDelegate {
|
||||
private let dextID: String
|
||||
private var done: ((TinyGPUCLIExit) -> Void)?
|
||||
private var isInstall = true
|
||||
|
||||
init(_ dextID: String) { self.dextID = dextID }
|
||||
|
||||
static func queryDextState(_ bundleID: String) -> DextState {
|
||||
let p = Process()
|
||||
p.executableURL = URL(fileURLWithPath: "/usr/bin/systemextensionsctl")
|
||||
p.arguments = ["list"]
|
||||
let pipe = Pipe()
|
||||
p.standardOutput = pipe
|
||||
p.standardError = Pipe()
|
||||
guard (try? p.run()) != nil else { return .unloaded }
|
||||
p.waitUntilExit()
|
||||
|
||||
guard let output = String(data: pipe.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8),
|
||||
let line = output.split(separator: "\n").first(where: { $0.contains(bundleID) }) else { return .unloaded }
|
||||
if line.contains("[activated enabled]") { return .activated }
|
||||
if line.contains("[activated waiting for user]") { return .needsApproval }
|
||||
return line.contains("terminated waiting to uninstall") ? .unloaded : .activating
|
||||
}
|
||||
|
||||
private static let approvalHelp = """
|
||||
Please go to System Settings > Privacy & Security and allow the extension.
|
||||
|
||||
If previously disabled: System Settings > General > Login Items & Extensions > Driver Extensions > Toggle TinyGPU ON
|
||||
|
||||
"""
|
||||
|
||||
static func statusText(_ state: DextState) -> String {
|
||||
switch state {
|
||||
case .unloaded: return "Driver extension not installed.\n\n"
|
||||
case .activating: return "Extension is activating...\n\n"
|
||||
case .needsApproval: return "Extension awaiting approval.\n\n" + approvalHelp
|
||||
case .activated: return "Extension is ready! Run tinygrad to use your eGPU.\n\n"
|
||||
}
|
||||
}
|
||||
|
||||
func run(args: [String], done: @escaping (TinyGPUCLIExit) -> Void) {
|
||||
self.done = done
|
||||
guard args.count > 1 else { return usage() }
|
||||
|
||||
switch args[1] {
|
||||
case "status":
|
||||
print(Self.statusText(Self.queryDextState(dextID)))
|
||||
done(.ok)
|
||||
case "install":
|
||||
if Self.queryDextState(dextID) == .needsApproval { print(Self.statusText(.needsApproval)); return done(.needsApproval) }
|
||||
print("Installing TinyGPU driver extension...\nYou may need to approve in System Settings.\n")
|
||||
submitRequest(activate: true)
|
||||
case "uninstall":
|
||||
guard Self.queryDextState(dextID) != .unloaded else { print("Not installed.\n"); return done(.ok) }
|
||||
print("Uninstalling TinyGPU driver extension...\n")
|
||||
isInstall = false
|
||||
submitRequest(activate: false)
|
||||
case "server":
|
||||
guard args.count > 2 else { print("Error: server requires socket path\n"); return usage() }
|
||||
done(run_server(args[2]) == 0 ? .ok : .failed)
|
||||
case "help", "-h", "--help":
|
||||
usage(); done(.ok)
|
||||
default:
|
||||
print("Unknown command: \(args[1])\n"); usage()
|
||||
}
|
||||
}
|
||||
|
||||
private func usage() {
|
||||
print("""
|
||||
Usage: TinyGPU <command>
|
||||
status Show extension status
|
||||
install Install the driver extension
|
||||
uninstall Remove the driver extension
|
||||
server <path> Start server on Unix socket
|
||||
""")
|
||||
done?(.usage)
|
||||
}
|
||||
|
||||
private func submitRequest(activate: Bool) {
|
||||
let req = activate
|
||||
? OSSystemExtensionRequest.activationRequest(forExtensionWithIdentifier: dextID, queue: .main)
|
||||
: OSSystemExtensionRequest.deactivationRequest(forExtensionWithIdentifier: dextID, queue: .main)
|
||||
req.delegate = self
|
||||
OSSystemExtensionManager.shared.submitRequest(req)
|
||||
}
|
||||
|
||||
// MARK: - OSSystemExtensionRequestDelegate
|
||||
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
|
||||
print("\nUser approval required!\n\n\(Self.approvalHelp)After approval, connect the gpu and use it with tinygrad.\n")
|
||||
done?(.needsApproval)
|
||||
}
|
||||
|
||||
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
|
||||
switch result {
|
||||
case .completed: print("Driver extension \(isInstall ? "installed" : "uninstalled") successfully!\n")
|
||||
case .willCompleteAfterReboot: print("Will complete after reboot.\n")
|
||||
@unknown default: print("Completed: \(result)\n")
|
||||
}
|
||||
done?(.ok)
|
||||
}
|
||||
|
||||
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
|
||||
print("\nError: \(error.localizedDescription)\n")
|
||||
let code = (error as NSError).code
|
||||
if code == 4 { print("Missing entitlements. Rebuild with proper signing.\n") }
|
||||
else if code == 8 { print("Extension not found in app bundle.\n") }
|
||||
else if code == 9 { print("Extension disabled by user.\n\n\(Self.approvalHelp)") }
|
||||
done?(.failed)
|
||||
}
|
||||
|
||||
func request(_ request: OSSystemExtensionRequest, actionForReplacingExtension existing: OSSystemExtensionProperties,
|
||||
withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
|
||||
print("Updating v\(existing.bundleShortVersion) -> v\(ext.bundleShortVersion)...\n")
|
||||
return .replace
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import SwiftUI
|
||||
|
||||
struct TinyGPUView: View {
|
||||
@ObservedObject var viewModel = TinyGPUViewModel()
|
||||
|
||||
var body: some View {
|
||||
#if os(macOS)
|
||||
VStack(alignment: .center) {
|
||||
Text("TinyGPU Intsaller")
|
||||
.padding()
|
||||
.font(.title)
|
||||
Text(self.viewModel.dextLoadingState)
|
||||
.multilineTextAlignment(.center)
|
||||
HStack {
|
||||
Button(
|
||||
action: {
|
||||
self.viewModel.activateMyDext()
|
||||
}, label: {
|
||||
Text("Install extension")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
.frame(width: 500, height: 200, alignment: .center)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
struct TinyGPUView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TinyGPUView()
|
||||
}
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
import Foundation
|
||||
import os.log
|
||||
import SystemExtensions
|
||||
|
||||
class TinyGPUDriverLoadingStateMachine {
|
||||
enum State { case unloaded, activating, needsApproval, activated, activationError }
|
||||
}
|
||||
|
||||
class TinyGPUViewModel: NSObject {
|
||||
|
||||
@Published private var state: TinyGPUDriverLoadingStateMachine.State = .unloaded
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
refreshInitialDextState()
|
||||
}
|
||||
|
||||
private func refreshInitialDextState() {
|
||||
#if os(macOS)
|
||||
Task.detached { [dextIdentifier] in
|
||||
let newState = Self.queryDextState(bundleID: dextIdentifier)
|
||||
await MainActor.run { self.state = newState }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
private static func queryDextState(bundleID: String) -> TinyGPUDriverLoadingStateMachine.State {
|
||||
let tool = "/usr/bin/systemextensionsctl"
|
||||
let p = Process()
|
||||
p.executableURL = URL(fileURLWithPath: tool)
|
||||
p.arguments = ["list"]
|
||||
|
||||
let pipe = Pipe()
|
||||
p.standardOutput = pipe
|
||||
p.standardError = Pipe()
|
||||
|
||||
do {
|
||||
try p.run()
|
||||
p.waitUntilExit()
|
||||
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||
guard let output = String(data: data, encoding: .utf8) else { return .unloaded }
|
||||
|
||||
// Look for our bundle id line
|
||||
if let line = output.split(separator: "\n").first(where: { $0.contains(bundleID) }) {
|
||||
if line.contains("[activated enabled]") { return .activated }
|
||||
if line.contains("[activated waiting for user]") { return .needsApproval }
|
||||
if line.contains("terminated waiting to uninstall") { return .unloaded }
|
||||
return .activating
|
||||
} else {
|
||||
return .unloaded
|
||||
}
|
||||
} catch {
|
||||
return .unloaded
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
private let dextIdentifier: String = "org.tinygrad.tinygpu.edriver"
|
||||
|
||||
public var dextLoadingState: String {
|
||||
switch state {
|
||||
case .unloaded:
|
||||
return "TinyGPUDriver isn't loaded."
|
||||
case .activating:
|
||||
return "Activating TinyGPUDriver, please wait."
|
||||
case .needsApproval:
|
||||
return "Please follow the prompt to approve TinyGPUDriver."
|
||||
case .activated:
|
||||
return "TinyGPUDriver has been activated and is ready to use. You can close the installer."
|
||||
case .activationError:
|
||||
return "TinyGPUDriver has experienced an error during activation.\nPlease check the logs to find the error."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension TinyGPUViewModel: ObservableObject {
|
||||
|
||||
#if os(macOS)
|
||||
func activateMyDext() {
|
||||
activateExtension(dextIdentifier)
|
||||
}
|
||||
|
||||
func deactivateMyDext() {
|
||||
deactivateExtension(dextIdentifier)
|
||||
}
|
||||
|
||||
func activateExtension(_ dextIdentifier: String) {
|
||||
|
||||
let request = OSSystemExtensionRequest
|
||||
.activationRequest(forExtensionWithIdentifier: dextIdentifier,
|
||||
queue: .main)
|
||||
request.delegate = self
|
||||
OSSystemExtensionManager.shared.submitRequest(request)
|
||||
|
||||
self.state = .activating
|
||||
}
|
||||
|
||||
func deactivateExtension(_ dextIdentifier: String) {
|
||||
|
||||
let request = OSSystemExtensionRequest.deactivationRequest(forExtensionWithIdentifier: dextIdentifier, queue: .main)
|
||||
request.delegate = self
|
||||
OSSystemExtensionManager.shared.submitRequest(request)
|
||||
|
||||
self.state = .unloaded
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
extension TinyGPUViewModel: OSSystemExtensionRequestDelegate {
|
||||
|
||||
func request(
|
||||
_ request: OSSystemExtensionRequest,
|
||||
actionForReplacingExtension existing: OSSystemExtensionProperties,
|
||||
withExtension ext: OSSystemExtensionProperties) -> OSSystemExtensionRequest.ReplacementAction {
|
||||
|
||||
var replacementAction: OSSystemExtensionRequest.ReplacementAction
|
||||
|
||||
os_log("sysex actionForReplacingExtension: %@ %@", existing, ext)
|
||||
|
||||
replacementAction = .replace
|
||||
self.state = .activating
|
||||
return replacementAction
|
||||
}
|
||||
|
||||
func requestNeedsUserApproval(_ request: OSSystemExtensionRequest) {
|
||||
os_log("sysex requestNeedsUserApproval")
|
||||
self.state = .needsApproval
|
||||
}
|
||||
|
||||
func request(_ request: OSSystemExtensionRequest, didFinishWithResult result: OSSystemExtensionRequest.Result) {
|
||||
os_log("sysex didFinishWithResult: %d", result.rawValue)
|
||||
self.state = .activated
|
||||
}
|
||||
|
||||
func request(_ request: OSSystemExtensionRequest, didFailWithError error: Error) {
|
||||
os_log("sysex didFailWithError: %@", error.localizedDescription)
|
||||
self.state = .activationError
|
||||
}
|
||||
}
|
||||
#endif
|
||||
277
extra/usbgpu/tbgpu/installer/Shared/server.c
Normal file
277
extra/usbgpu/tbgpu/installer/Shared/server.c
Normal file
@@ -0,0 +1,277 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOMessage.h>
|
||||
#include <mach/mach.h>
|
||||
|
||||
// Protocol
|
||||
|
||||
enum {
|
||||
CMD_MAP_BAR = 1, // map PCI BAR, returns size
|
||||
CMD_MAP_SYSMEM_FD = 2, // alloc DMA memory, returns fd via SCM_RIGHTS
|
||||
CMD_CFG_READ = 3, // read PCI config space
|
||||
CMD_CFG_WRITE = 4, // write PCI config space
|
||||
CMD_RESET = 5, // reset device
|
||||
CMD_MMIO_READ = 6, // bulk read from BAR
|
||||
CMD_MMIO_WRITE = 7, // bulk write to BAR
|
||||
RESP_OK = 0, RESP_ERR = 1,
|
||||
};
|
||||
|
||||
typedef struct { uint8_t cmd, bar; uint64_t offset, size, value; } __attribute__((packed)) request_t;
|
||||
typedef struct { uint8_t status; uint64_t value, addr; } __attribute__((packed)) response_t;
|
||||
|
||||
// Constants and state
|
||||
|
||||
#define BULK_BUF_SIZE (64 << 20)
|
||||
#define MAX_BARS 6
|
||||
#define MAX_SYSMEM 128
|
||||
|
||||
static uint8_t g_bulk_buf[BULK_BUF_SIZE];
|
||||
static io_connect_t g_conn = IO_OBJECT_NULL;
|
||||
static int g_client_active = 0;
|
||||
|
||||
static struct { mach_vm_address_t addr; mach_vm_size_t size; } g_bars[MAX_BARS];
|
||||
static struct { mach_vm_address_t addr; mach_vm_size_t size; int shm_fd; char shm_name[32]; } g_sysmem[MAX_SYSMEM];
|
||||
static int g_sysmem_count = 0;
|
||||
|
||||
// Utilities
|
||||
|
||||
static void recvall(int fd, void *buf, size_t len) {
|
||||
for (size_t off = 0; off < len; ) {
|
||||
ssize_t r = recv(fd, (uint8_t*)buf + off, len - off, 0);
|
||||
if (r <= 0) break;
|
||||
off += r;
|
||||
}
|
||||
}
|
||||
|
||||
// MMIO requires 32-bit aligned volatile accesses
|
||||
static void mmio_copy(void *dst, void *src, size_t len) {
|
||||
volatile uint32_t *d = dst, *s = src;
|
||||
for (size_t i = 0; i < len / 4; i++) d[i] = s[i];
|
||||
for (size_t i = len & ~3; i < len; i++) ((volatile uint8_t*)dst)[i] = ((volatile uint8_t*)src)[i];
|
||||
}
|
||||
|
||||
static int send_response(int fd, response_t *resp, int send_fd) {
|
||||
char cmsgbuf[CMSG_SPACE(sizeof(int))];
|
||||
struct iovec iov = {resp, sizeof(*resp)};
|
||||
struct msghdr msg = {.msg_iov = &iov, .msg_iovlen = 1};
|
||||
|
||||
if (send_fd >= 0) {
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = sizeof(cmsgbuf);
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
*cmsg = (struct cmsghdr){.cmsg_level = SOL_SOCKET, .cmsg_type = SCM_RIGHTS, .cmsg_len = CMSG_LEN(sizeof(int))};
|
||||
memcpy(CMSG_DATA(cmsg), &send_fd, sizeof(int));
|
||||
}
|
||||
return sendmsg(fd, &msg, 0) > 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
static void send_error(int fd, const char *msg) {
|
||||
response_t resp = {.status = RESP_ERR, .value = strlen(msg)};
|
||||
send_response(fd, &resp, -1);
|
||||
send(fd, msg, strlen(msg), 0);
|
||||
}
|
||||
|
||||
// Driver interface
|
||||
|
||||
static void on_disconnect(void *refcon, io_service_t svc, uint32_t msg, void *arg) {
|
||||
if (msg == kIOMessageServiceIsTerminated) _exit(0);
|
||||
}
|
||||
|
||||
static io_connect_t open_tinygpu(void) {
|
||||
static io_object_t notif;
|
||||
io_service_t svc = IOServiceGetMatchingService(kIOMainPortDefault, IOServiceNameMatching("tinygpu"));
|
||||
if (!svc) return IO_OBJECT_NULL;
|
||||
|
||||
if (!notif) {
|
||||
IONotificationPortRef port = IONotificationPortCreate(kIOMainPortDefault);
|
||||
IONotificationPortSetDispatchQueue(port, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0));
|
||||
IOServiceAddInterestNotification(port, svc, kIOGeneralInterest, on_disconnect, NULL, ¬if);
|
||||
}
|
||||
|
||||
io_connect_t conn;
|
||||
kern_return_t kr = IOServiceOpen(svc, mach_task_self(), 0, &conn);
|
||||
IOObjectRelease(svc);
|
||||
return kr == KERN_SUCCESS ? conn : IO_OBJECT_NULL;
|
||||
}
|
||||
|
||||
static int dext_rpc(uint32_t sel, uint64_t *in, uint32_t in_cnt, uint64_t *out_val) {
|
||||
uint64_t out[2];
|
||||
uint32_t out_cnt = 2;
|
||||
if (IOConnectCallMethod(g_conn, sel, in, in_cnt, NULL, 0, out, &out_cnt, NULL, NULL) != KERN_SUCCESS) return -1;
|
||||
if (out_val) *out_val = out[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int map_bar(uint32_t bar, response_t *resp) {
|
||||
if (bar >= MAX_BARS) return -1;
|
||||
if (!g_bars[bar].addr && IOConnectMapMemory64(g_conn, bar, mach_task_self(), &g_bars[bar].addr, &g_bars[bar].size, kIOMapAnywhere)) return -1;
|
||||
resp->addr = g_bars[bar].addr;
|
||||
resp->value = g_bars[bar].size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int map_sysmem_fd(uint64_t size, response_t *resp, int *out_fd) {
|
||||
if (g_sysmem_count >= MAX_SYSMEM) return -1;
|
||||
int idx = g_sysmem_count;
|
||||
int fd = -1;
|
||||
void *ptr = MAP_FAILED;
|
||||
char shm_name[32];
|
||||
|
||||
// page-align, min 16KB for IOMemoryDescriptor
|
||||
size_t alloc_sz = (size + 0xfff) & ~0xfff;
|
||||
if (alloc_sz < 0x4000) alloc_sz = 0x4000;
|
||||
|
||||
snprintf(shm_name, sizeof(shm_name), "/tinygpu_%d", idx);
|
||||
shm_unlink(shm_name);
|
||||
if ((fd = shm_open(shm_name, O_CREAT | O_RDWR, 0600)) < 0) goto fail;
|
||||
if (ftruncate(fd, alloc_sz) < 0) goto fail;
|
||||
if ((ptr = mmap(NULL, alloc_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) goto fail;
|
||||
|
||||
// PrepareDMA writes physical addresses to output buffer, copy to shared mem
|
||||
uint8_t paddr_buf[8192] = {0};
|
||||
size_t out_sz = sizeof(paddr_buf);
|
||||
if (IOConnectCallStructMethod(g_conn, 3, ptr, alloc_sz, paddr_buf, &out_sz) != KERN_SUCCESS) goto fail;
|
||||
memcpy(ptr, paddr_buf, out_sz);
|
||||
|
||||
g_sysmem[idx] = (typeof(g_sysmem[idx])){.addr = (mach_vm_address_t)ptr, .size = alloc_sz, .shm_fd = fd};
|
||||
strncpy(g_sysmem[idx].shm_name, shm_name, sizeof(g_sysmem[idx].shm_name));
|
||||
g_sysmem_count++;
|
||||
|
||||
*resp = (response_t){.addr = idx, .value = alloc_sz};
|
||||
*out_fd = fd;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (ptr != MAP_FAILED) munmap(ptr, alloc_sz);
|
||||
if (fd >= 0) close(fd);
|
||||
shm_unlink(shm_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int validate_bar(uint8_t bar, uint64_t off, uint64_t sz) {
|
||||
return (bar < MAX_BARS && g_bars[bar].addr && off + sz <= g_bars[bar].size && sz <= BULK_BUF_SIZE) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void cleanup(void) {
|
||||
for (int i = 0; i < MAX_BARS; i++)
|
||||
if (g_bars[i].addr) { IOConnectUnmapMemory64(g_conn, i, mach_task_self(), g_bars[i].addr); g_bars[i].addr = 0; }
|
||||
|
||||
for (int i = 0; i < g_sysmem_count; i++) {
|
||||
munmap((void*)g_sysmem[i].addr, g_sysmem[i].size);
|
||||
close(g_sysmem[i].shm_fd);
|
||||
shm_unlink(g_sysmem[i].shm_name);
|
||||
}
|
||||
|
||||
g_sysmem_count = 0;
|
||||
if (g_conn != IO_OBJECT_NULL) { IOServiceClose(g_conn); g_conn = IO_OBJECT_NULL; }
|
||||
}
|
||||
|
||||
static void handle_client(int fd) {
|
||||
int bufsize = BULK_BUF_SIZE;
|
||||
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
|
||||
printf("client connected\n");
|
||||
|
||||
g_conn = open_tinygpu();
|
||||
if (g_conn == IO_OBJECT_NULL) {
|
||||
fprintf(stderr, "failed to connect to tinygpu driver\n");
|
||||
request_t req; recv(fd, &req, sizeof(req), 0);
|
||||
send_error(fd, "Driver not available. Check: System Report > PCI for GPU, System Settings > Privacy & Security.");
|
||||
return;
|
||||
}
|
||||
|
||||
request_t req;
|
||||
response_t resp;
|
||||
while (recv(fd, &req, sizeof(req), 0) == sizeof(req)) {
|
||||
resp = (response_t){0};
|
||||
|
||||
switch (req.cmd) {
|
||||
case CMD_MAP_BAR:
|
||||
resp.status = map_bar(req.bar, &resp) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case CMD_MAP_SYSMEM_FD: {
|
||||
int shm_fd = -1;
|
||||
resp.status = map_sysmem_fd(req.size, &resp, &shm_fd) ? 1 : 0;
|
||||
send_response(fd, &resp, shm_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
case CMD_CFG_READ: {
|
||||
uint64_t in[2] = {req.offset, req.size};
|
||||
resp.status = dext_rpc(0, in, 2, &resp.value) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_CFG_WRITE: {
|
||||
uint64_t in[3] = {req.offset, req.size, req.value};
|
||||
resp.status = dext_rpc(1, in, 3, NULL) ? 1 : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_RESET:
|
||||
resp.status = dext_rpc(2, NULL, 0, NULL) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case CMD_MMIO_READ:
|
||||
if (validate_bar(req.bar, req.offset, req.size)) { resp.status = 1; break; }
|
||||
mmio_copy(g_bulk_buf, (void*)(g_bars[req.bar].addr + req.offset), req.size);
|
||||
resp.value = req.size;
|
||||
send_response(fd, &resp, -1);
|
||||
send(fd, g_bulk_buf, req.size, 0);
|
||||
continue;
|
||||
|
||||
case CMD_MMIO_WRITE:
|
||||
recvall(fd, g_bulk_buf, req.size);
|
||||
if (!validate_bar(req.bar, req.offset, req.size))
|
||||
mmio_copy((void*)(g_bars[req.bar].addr + req.offset), g_bulk_buf, req.size);
|
||||
continue;
|
||||
|
||||
default:
|
||||
resp.status = 1;
|
||||
}
|
||||
send_response(fd, &resp, -1);
|
||||
}
|
||||
|
||||
printf("client disconnected\n");
|
||||
cleanup();
|
||||
}
|
||||
|
||||
int run_server(const char *sock_path) {
|
||||
int server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (server_fd < 0) { perror("socket"); return 1; }
|
||||
|
||||
struct sockaddr_un addr = {.sun_family = AF_UNIX};
|
||||
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
|
||||
unlink(sock_path);
|
||||
|
||||
if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { perror("bind"); close(server_fd); return 1; }
|
||||
if (listen(server_fd, 1) < 0) { perror("listen"); close(server_fd); return 1; }
|
||||
printf("listening on %s\n", sock_path);
|
||||
|
||||
while (1) {
|
||||
int client_fd = accept(server_fd, NULL, NULL);
|
||||
if (client_fd < 0) { if (errno == EINTR) continue; perror("accept"); break; }
|
||||
if (g_client_active) { printf("rejected: client already connected\n"); close(client_fd); continue; }
|
||||
g_client_active = 1;
|
||||
handle_client(client_fd);
|
||||
g_client_active = 0;
|
||||
close(client_fd);
|
||||
}
|
||||
|
||||
close(server_fd);
|
||||
unlink(sock_path);
|
||||
cleanup();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<svg viewBox="0 0 130 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- t -->
|
||||
<rect x="10" y="0" width="10" height="40" fill="#000000"></rect>
|
||||
<rect x="0" y="10" width="30" height="10" fill="#000000"></rect>
|
||||
<rect x="10" y="30" width="20" height="10" fill="#000000"></rect>
|
||||
<!-- i -->
|
||||
<rect x="40" y="0" width="10" height="10" fill="#000000"></rect>
|
||||
<rect x="40" y="20" width="10" height="20" fill="#000000"></rect>
|
||||
<!-- n -->
|
||||
<rect x="60" y="10" width="10" height="30" fill="#000000"></rect>
|
||||
<rect x="60" y="10" width="20" height="10" fill="#000000"></rect>
|
||||
<rect x="80" y="20" width="10" height="20" fill="#000000"></rect>
|
||||
<!-- y -->
|
||||
<rect x="100" y="10" width="10" height="20" fill="#000000"></rect>
|
||||
<rect x="100" y="20" width="30" height="10" fill="#000000"></rect>
|
||||
<rect x="120" y="10" width="10" height="30" fill="#000000"></rect>
|
||||
<rect x="100" y="40" width="20" height="10" fill="#000000"></rect>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
52
extra/usbgpu/tbgpu/installer/Shared/tiny_icon.icon/icon.json
Normal file
52
extra/usbgpu/tbgpu/installer/Shared/tiny_icon.icon/icon.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"fill" : "automatic",
|
||||
"groups" : [
|
||||
{
|
||||
"layers" : [
|
||||
{
|
||||
"fill-specializations" : [
|
||||
{
|
||||
"value" : "automatic"
|
||||
},
|
||||
{
|
||||
"appearance" : "dark",
|
||||
"value" : {
|
||||
"solid" : "display-p3:0.94011,0.96611,0.94301,1.00000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"appearance" : "tinted",
|
||||
"value" : {
|
||||
"solid" : "display-p3:0.79528,0.79528,0.79528,1.00000"
|
||||
}
|
||||
}
|
||||
],
|
||||
"hidden" : false,
|
||||
"image-name" : "tiny.svg",
|
||||
"name" : "tiny_svg",
|
||||
"position" : {
|
||||
"scale" : 5,
|
||||
"translation-in-points" : [
|
||||
0,
|
||||
19
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"shadow" : {
|
||||
"kind" : "neutral",
|
||||
"opacity" : 0.5
|
||||
},
|
||||
"translucency" : {
|
||||
"enabled" : true,
|
||||
"value" : 0.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"supported-platforms" : {
|
||||
"circles" : [
|
||||
"watchOS"
|
||||
],
|
||||
"squares" : "shared"
|
||||
}
|
||||
}
|
||||
@@ -7,13 +7,14 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0A52E8692F18FC6900A816CD /* tiny_icon.icon in Resources */ = {isa = PBXBuildFile; fileRef = 0A52E8682F18FC6900A816CD /* tiny_icon.icon */; };
|
||||
0A5C11DD2F18E466006DBBCA /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 0A5C11DC2F18E461006DBBCA /* server.c */; };
|
||||
0ACB55392E9CB880007029EF /* PCIDriverKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0ACB55382E9CB880007029EF /* PCIDriverKit.framework */; };
|
||||
0AD7C2E52F18DEBC00562D1A /* TinyGPUCLIRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AD7C2E42F18DEB800562D1A /* TinyGPUCLIRunner.swift */; };
|
||||
54798269286A3512009785F6 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 54798268286A3512009785F6 /* CoreAudio.framework */; };
|
||||
549EB121286A1A37009D38AB /* TinyGPUViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 549EB11F286A1A37009D38AB /* TinyGPUViewModel.swift */; };
|
||||
549EB123286A1D48009D38AB /* org.tinygrad.tinygpu.edriver.dext in Embed System Extensions */ = {isa = PBXBuildFile; fileRef = C5B7D9BC26128AC50089B4C3 /* org.tinygrad.tinygpu.edriver.dext */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
549EB131286A2B98009D38AB /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 549EB130286A2B98009D38AB /* IOKit.framework */; };
|
||||
54E42BC8286A1697000E1E9A /* TinyGPUApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E42BB8286A1696000E1E9A /* TinyGPUApp.swift */; };
|
||||
54E42BCA286A1697000E1E9A /* TinyGPUView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54E42BB9286A1696000E1E9A /* TinyGPUView.swift */; };
|
||||
54E42BCC286A1697000E1E9A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 54E42BBA286A1697000E1E9A /* Assets.xcassets */; };
|
||||
C5B7D9C326128AC50089B4C3 /* TinyGPUDriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C5B7D9C226128AC50089B4C3 /* TinyGPUDriver.cpp */; };
|
||||
C5B7D9C526128AC50089B4C3 /* TinyGPUDriver.iig in Sources */ = {isa = PBXBuildFile; fileRef = C5B7D9C426128AC50089B4C3 /* TinyGPUDriver.iig */; };
|
||||
@@ -34,6 +35,15 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
0AD7C2DB2F18D7D500562D1A /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 6;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
549EB122286A1D3A009D38AB /* Embed System Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -48,13 +58,18 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0A52E8682F18FC6900A816CD /* tiny_icon.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; path = tiny_icon.icon; sourceTree = "<group>"; };
|
||||
0A5C11DC2F18E461006DBBCA /* server.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = "<group>"; };
|
||||
0A5C11DE2F18E468006DBBCA /* TinyGPU-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TinyGPU-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
0ACB55382E9CB880007029EF /* PCIDriverKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PCIDriverKit.framework; path = System/DriverKit/System/Library/Frameworks/PCIDriverKit.framework; sourceTree = SDKROOT; };
|
||||
0AD7C2D62F18D3DB00562D1A /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
0AD7C2D82F18D3E300562D1A /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX26.2.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; };
|
||||
0AD7C2E42F18DEB800562D1A /* TinyGPUCLIRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinyGPUCLIRunner.swift; sourceTree = "<group>"; };
|
||||
0AFA851D2F1CE486005FDAC2 /* TinyGPUDriver.Release.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = TinyGPUDriver.Release.entitlements; sourceTree = "<group>"; };
|
||||
54798268286A3512009785F6 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk/System/Library/Frameworks/CoreAudio.framework; sourceTree = DEVELOPER_DIR; };
|
||||
549EB11F286A1A37009D38AB /* TinyGPUViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinyGPUViewModel.swift; sourceTree = "<group>"; usesTabs = 1; };
|
||||
549EB130286A2B98009D38AB /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
549EB132286A2B9D009D38AB /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS16.0.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
|
||||
54E42BB8286A1696000E1E9A /* TinyGPUApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinyGPUApp.swift; sourceTree = "<group>"; };
|
||||
54E42BB9286A1696000E1E9A /* TinyGPUView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinyGPUView.swift; sourceTree = "<group>"; };
|
||||
54E42BBA286A1697000E1E9A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
54E42BC4286A1697000E1E9A /* TinyGPU.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TinyGPU.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
54E42BC6286A1697000E1E9A /* macOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = macOS.entitlements; sourceTree = "<group>"; };
|
||||
@@ -102,10 +117,12 @@
|
||||
54E42BB7286A1696000E1E9A /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0A5C11DC2F18E461006DBBCA /* server.c */,
|
||||
0AD7C2E42F18DEB800562D1A /* TinyGPUCLIRunner.swift */,
|
||||
54E42BB8286A1696000E1E9A /* TinyGPUApp.swift */,
|
||||
54E42BB9286A1696000E1E9A /* TinyGPUView.swift */,
|
||||
549EB11F286A1A37009D38AB /* TinyGPUViewModel.swift */,
|
||||
54E42BBA286A1697000E1E9A /* Assets.xcassets */,
|
||||
0A52E8682F18FC6900A816CD /* tiny_icon.icon */,
|
||||
0A5C11DE2F18E468006DBBCA /* TinyGPU-Bridging-Header.h */,
|
||||
);
|
||||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
@@ -142,6 +159,8 @@
|
||||
C5B7D9BE26128AC50089B4C3 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0AD7C2D82F18D3E300562D1A /* CoreFoundation.framework */,
|
||||
0AD7C2D62F18D3DB00562D1A /* IOKit.framework */,
|
||||
0ACB55382E9CB880007029EF /* PCIDriverKit.framework */,
|
||||
54798268286A3512009785F6 /* CoreAudio.framework */,
|
||||
549EB130286A2B98009D38AB /* IOKit.framework */,
|
||||
@@ -168,6 +187,7 @@
|
||||
C5D787AB261667FC006047E5 /* TinyGPUDriverUserClient.iig */,
|
||||
C5B7D9C626128AC50089B4C3 /* Info.plist */,
|
||||
C5B7D9CE26128B150089B4C3 /* TinyGPUDriver.entitlements */,
|
||||
0AFA851D2F1CE486005FDAC2 /* TinyGPUDriver.Release.entitlements */,
|
||||
);
|
||||
path = TinyGPUDriverExtension;
|
||||
sourceTree = "<group>";
|
||||
@@ -185,21 +205,22 @@
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
54E42BC3286A1697000E1E9A /* TinyGPU Installer (macOS) */ = {
|
||||
54E42BC3286A1697000E1E9A /* TinyGPU */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 54E42BD2286A1697000E1E9A /* Build configuration list for PBXNativeTarget "TinyGPU Installer (macOS)" */;
|
||||
buildConfigurationList = 54E42BD2286A1697000E1E9A /* Build configuration list for PBXNativeTarget "TinyGPU" */;
|
||||
buildPhases = (
|
||||
54E42BC0286A1697000E1E9A /* Sources */,
|
||||
54E42BC1286A1697000E1E9A /* Frameworks */,
|
||||
54E42BC2286A1697000E1E9A /* Resources */,
|
||||
549EB122286A1D3A009D38AB /* Embed System Extensions */,
|
||||
0AD7C2DB2F18D7D500562D1A /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
549EB127286A1D66009D38AB /* PBXTargetDependency */,
|
||||
);
|
||||
name = "TinyGPU Installer (macOS)";
|
||||
name = TinyGPU;
|
||||
productName = "SimpleAudioDriverExtension2 (macOS)";
|
||||
productReference = 54E42BC4286A1697000E1E9A /* TinyGPU.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
@@ -236,7 +257,7 @@
|
||||
TargetAttributes = {
|
||||
54E42BC3286A1697000E1E9A = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
LastSwiftMigration = 1400;
|
||||
LastSwiftMigration = 2620;
|
||||
};
|
||||
C5B7D9BB26128AC50089B4C3 = {
|
||||
CreatedOnToolsVersion = 13.0;
|
||||
@@ -257,7 +278,7 @@
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
C5B7D9BB26128AC50089B4C3 /* TinyGPUDriver */,
|
||||
54E42BC3286A1697000E1E9A /* TinyGPU Installer (macOS) */,
|
||||
54E42BC3286A1697000E1E9A /* TinyGPU */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -268,6 +289,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
54E42BCC286A1697000E1E9A /* Assets.xcassets in Resources */,
|
||||
0A52E8692F18FC6900A816CD /* tiny_icon.icon in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -285,9 +307,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
549EB121286A1A37009D38AB /* TinyGPUViewModel.swift in Sources */,
|
||||
54E42BCA286A1697000E1E9A /* TinyGPUView.swift in Sources */,
|
||||
54E42BC8286A1697000E1E9A /* TinyGPUApp.swift in Sources */,
|
||||
0A5C11DD2F18E466006DBBCA /* server.c in Sources */,
|
||||
0AD7C2E52F18DEBC00562D1A /* TinyGPUCLIRunner.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -316,12 +338,12 @@
|
||||
54E42BCF286A1697000E1E9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = tiny_icon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@@ -331,19 +353,21 @@
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.1;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.installer;
|
||||
PRODUCT_NAME = TinyGPU;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Shared/TinyGPU-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
@@ -352,12 +376,12 @@
|
||||
54E42BD0286A1697000E1E9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = tiny_icon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = macOS/macOS.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
@@ -367,19 +391,21 @@
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 12.1;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.installer;
|
||||
PRODUCT_NAME = TinyGPU;
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Shared/TinyGPU-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
@@ -477,6 +503,7 @@
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DRIVERKIT_DEPLOYMENT_TARGET = 21.0;
|
||||
@@ -502,26 +529,29 @@
|
||||
buildSettings = {
|
||||
AD_HOC_CODE_SIGNING_ALLOWED = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = TinyGPUDriverExtension/TinyGPUDriver.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEVELOPMENT_TEAM = 9YG3G8543N;
|
||||
DRIVERKIT_DEPLOYMENT_TARGET = 21.0;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
EXCLUDED_ARCHS = "";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SDKROOT)/System/DriverKit/System/Library/Frameworks",
|
||||
);
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = TinyGPUDriverExtension/Info.plist;
|
||||
INFOPLIST_KEY_OSBundleUsageDescription = "Sample Code Audio Driver Kit Extension";
|
||||
MARKETING_VERSION = 1.0;
|
||||
INFOPLIST_KEY_OSBundleUsageDescription = "TinyGPU Driver";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.edriver;
|
||||
PRODUCT_NAME = "$(inherited)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||
SDKROOT = driverkit;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = driverkit;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -529,34 +559,40 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
AD_HOC_CODE_SIGNING_ALLOWED = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = TinyGPUDriverExtension/TinyGPUDriver.entitlements;
|
||||
CODE_SIGN_IDENTITY = "-";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = 9YG3G8543N;
|
||||
CODE_SIGN_ENTITLEMENTS = TinyGPUDriverExtension/TinyGPUDriver.Release.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=driverkit*]" = "Apple Development";
|
||||
CODE_SIGN_STYLE = Manual;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEVELOPMENT_TEAM = "";
|
||||
"DEVELOPMENT_TEAM[sdk=driverkit*]" = 9YG3G8543N;
|
||||
DRIVERKIT_DEPLOYMENT_TARGET = 21.0;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
EXCLUDED_ARCHS = "";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(SDKROOT)/System/DriverKit/System/Library/Frameworks",
|
||||
);
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = TinyGPUDriverExtension/Info.plist;
|
||||
INFOPLIST_KEY_OSBundleUsageDescription = "Sample Code Audio Driver Kit Extension";
|
||||
MARKETING_VERSION = 1.0;
|
||||
INFOPLIST_KEY_OSBundleUsageDescription = "TinyGPU Driver";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 17.6;
|
||||
MARKETING_VERSION = 1.0.0;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.tinygrad.tinygpu.edriver;
|
||||
PRODUCT_NAME = "$(inherited)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||
SDKROOT = driverkit;
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = driverkit;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
54E42BD2286A1697000E1E9A /* Build configuration list for PBXNativeTarget "TinyGPU Installer (macOS)" */ = {
|
||||
54E42BD2286A1697000E1E9A /* Build configuration list for PBXNativeTarget "TinyGPU" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
54E42BCF286A1697000E1E9A /* Debug */,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.driverkit</key>
|
||||
<true/>
|
||||
<key>com.apple.developer.driverkit.transport.pci</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IOPCIPrimaryMatch</key>
|
||||
<string>0xFFFFFFFF&0x00000000</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>com.apple.developer.driverkit.allow-any-userclient-access</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.application-identifier</key>
|
||||
<string>9YG3G8543N.org.tinygrad.tinygpu.edriver</string>
|
||||
<key>com.apple.developer.driverkit</key>
|
||||
<true/>
|
||||
<key>com.apple.developer.driverkit.transport.pci</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IOPCIPrimaryMatch</key>
|
||||
<string>4098</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -11,7 +11,5 @@
|
||||
<string>0xFFFFFFFF&0x00000000</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>com.apple.developer.driverkit.allow-any-userclient-access</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
33
extra/usbgpu/tbgpu/installer/build_and_sign.sh
Executable file
33
extra/usbgpu/tbgpu/installer/build_and_sign.sh
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -alltargets -configuration Release build
|
||||
|
||||
cp "../profiles/devid_provisioning.provisionprofile" "./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.edriver.dext/embedded.provisionprofile"
|
||||
cp "../profiles/installer_provisioning.provisionprofile" "./build/Release/TinyGPU.app/Contents/embedded.provisionprofile"
|
||||
|
||||
codesign \
|
||||
--sign "Developer ID Application: tinygrad, Corp. (9YG3G8543N)" \
|
||||
--entitlements ./TinyGPUDriverExtension/TinyGPUDriver.Release.entitlements \
|
||||
--verbose \
|
||||
--options runtime \
|
||||
--timestamp \
|
||||
--force \
|
||||
./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.edriver.dext
|
||||
|
||||
codesign \
|
||||
--sign "Developer ID Application: tinygrad, Corp. (9YG3G8543N)" \
|
||||
--entitlements ./macOS/macOS.entitlements \
|
||||
--options runtime \
|
||||
--verbose \
|
||||
--timestamp \
|
||||
--force \
|
||||
./build/Release/TinyGPU.app
|
||||
|
||||
codesign --verify --deep --strict --verbose=4 ./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.edriver.dext
|
||||
|
||||
codesign --verify --deep --strict --verbose=4 ./build/Release/TinyGPU.app
|
||||
|
||||
spctl -a -vv ./build/Release/TinyGPU.app
|
||||
|
||||
spctl -a -vv ./build/Release/TinyGPU.app/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.edriver.dext
|
||||
52
extra/usbgpu/tbgpu/installer/install_nosip.sh
Executable file
52
extra/usbgpu/tbgpu/installer/install_nosip.sh
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Check SIP status if not building only
|
||||
if [[ "$1" != "--build" ]]; then
|
||||
SIP_STATUS=$(csrutil status 2>&1)
|
||||
if [[ "$SIP_STATUS" == *"enabled"* ]]; then
|
||||
echo "ERROR: System Integrity Protection (SIP) is enabled."
|
||||
echo "This dev build requires SIP to be disabled to load unsigned dexts."
|
||||
echo ""
|
||||
echo "To disable SIP:"
|
||||
echo " 1. Restart and hold Power button (M1+) or Cmd+R (Intel)"
|
||||
echo " 2. Open Terminal from Recovery menu"
|
||||
echo " 3. Run: csrutil disable"
|
||||
echo " 4. Restart"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "SIP is disabled, proceeding with dev build..."
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Build without code signing
|
||||
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -alltargets -configuration Debug build
|
||||
|
||||
APP_PATH="./build/Debug/TinyGPU.app"
|
||||
DEXT_PATH="$APP_PATH/Contents/Library/SystemExtensions/org.tinygrad.tinygpu.edriver.dext"
|
||||
|
||||
# Ad-hoc sign with dev entitlements (matches any GPU)
|
||||
codesign --sign - --entitlements ./TinyGPUDriverExtension/TinyGPUDriver.NoSIP.entitlements --force --timestamp --verbose "$DEXT_PATH"
|
||||
codesign --sign - --entitlements ./macOS/macOS.entitlements --force --timestamp --verbose "$APP_PATH"
|
||||
|
||||
echo "Build complete: $APP_PATH"
|
||||
|
||||
if [[ "$1" == "--build" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Install
|
||||
echo "Installing to /Applications..."
|
||||
|
||||
if [ -d "/Applications/TinyGPU.app" ]; then
|
||||
echo "Removing existing /Applications/TinyGPU.app..."
|
||||
rm -rf "/Applications/TinyGPU.app"
|
||||
fi
|
||||
|
||||
cp -r "$APP_PATH" /Applications/
|
||||
echo "Installed to /Applications/TinyGPU.app"
|
||||
|
||||
echo "Activating driver extension..."
|
||||
/Applications/TinyGPU.app/Contents/MacOS/TinyGPU install
|
||||
@@ -8,5 +8,9 @@
|
||||
<true/>
|
||||
<key>com.apple.developer.system-extension.install</key>
|
||||
<true/>
|
||||
<key>com.apple.developer.driverkit.userclient-access</key>
|
||||
<array>
|
||||
<string>org.tinygrad.tinygpu.edriver</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
5
extra/usbgpu/tbgpu/installer/notary_tool.sh
Executable file
5
extra/usbgpu/tbgpu/installer/notary_tool.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
ditto -c -k --keepParent ./build/Release/TinyGPU.app ./build/Release/TinyGPU.zip
|
||||
xcrun notarytool submit ./build/Release/TinyGPU.zip --keychain-profile "hgwJFhdheiIEy82nDN" --wait
|
||||
2
extra/usbgpu/tbgpu/kill_tinygpu.sh
Executable file
2
extra/usbgpu/tbgpu/kill_tinygpu.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
pkill -f "tinygpu.sock"
|
||||
@@ -1,39 +0,0 @@
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <mach/mach.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static io_connect_t open_uc_by_name(const char *svc_name) {
|
||||
io_connect_t conn = IO_OBJECT_NULL;
|
||||
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceNameMatching(svc_name));
|
||||
if (!service) { fprintf(stderr, "service not found: %s\n", svc_name); return IO_OBJECT_NULL; }
|
||||
kern_return_t kr = IOServiceOpen(service, mach_task_self(), /*type*/0, &conn);
|
||||
IOObjectRelease(service);
|
||||
if (kr) { fprintf(stderr, "IOServiceOpen 0x%x\n", kr); return IO_OBJECT_NULL; }
|
||||
return conn;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
uint32_t bar = (argc > 1) ? (uint32_t)strtoul(argv[1], NULL, 0) : 0; // pick BAR index
|
||||
io_connect_t conn = open_uc_by_name("tinygpu");
|
||||
if (!conn) return 2;
|
||||
|
||||
mach_vm_address_t addr = 0;
|
||||
mach_vm_size_t size = 0;
|
||||
kern_return_t kr = IOConnectMapMemory64(conn, bar, mach_task_self(), &addr, &size, kIOMapAnywhere);
|
||||
if (kr) { fprintf(stderr, "Map BAR%u failed 0x%x\n", bar, kr); IOServiceClose(conn); return 3; }
|
||||
|
||||
printf("BAR%u mapped at 0x%llx, size 0x%llx\n", bar, (unsigned long long)addr, (unsigned long long)size);
|
||||
|
||||
// example: read a 32-bit register at offset 0x0 (make sure it’s safe!)
|
||||
volatile uint32_t *mmio = (volatile uint32_t*)(uintptr_t)addr;
|
||||
uint32_t v = mmio[0];
|
||||
printf("mmio[0]=0x%08x\n", v);
|
||||
|
||||
kr = IOConnectUnmapMemory64(conn, bar, mach_task_self(), addr);
|
||||
if (kr) fprintf(stderr, "Unmap failed 0x%x\n", kr);
|
||||
|
||||
IOServiceClose(conn);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import ctypes, ctypes.util, sys
|
||||
|
||||
cf = ctypes.CDLL(ctypes.util.find_library("CoreFoundation"))
|
||||
iokit = ctypes.CDLL(ctypes.util.find_library("IOKit"))
|
||||
libsys = ctypes.CDLL(ctypes.util.find_library("System"))
|
||||
|
||||
kern_return_t = ctypes.c_int
|
||||
mach_port_t = ctypes.c_uint
|
||||
io_object_t = mach_port_t
|
||||
io_service_t = io_object_t
|
||||
io_connect_t = mach_port_t
|
||||
CFMutableDictionaryRef = ctypes.c_void_p
|
||||
CFStringRef = ctypes.c_void_p
|
||||
|
||||
kIOMasterPortDefault = mach_port_t(0)
|
||||
|
||||
libsys.mach_task_self_.restype = mach_port_t
|
||||
|
||||
iokit.IOServiceNameMatching.argtypes = [ctypes.c_char_p]
|
||||
iokit.IOServiceNameMatching.restype = CFMutableDictionaryRef
|
||||
|
||||
iokit.IOServiceGetMatchingService.argtypes = [mach_port_t, CFMutableDictionaryRef]
|
||||
iokit.IOServiceGetMatchingService.restype = io_service_t
|
||||
|
||||
iokit.IOObjectRelease.argtypes = [io_object_t]
|
||||
iokit.IOObjectRelease.restype = kern_return_t
|
||||
|
||||
iokit.IOServiceOpen.argtypes = [io_service_t, mach_port_t, ctypes.c_uint32, ctypes.POINTER(io_connect_t)]
|
||||
iokit.IOServiceOpen.restype = kern_return_t
|
||||
|
||||
iokit.IOConnectCallMethod.argtypes = [io_connect_t, ctypes.c_uint32, ctypes.POINTER(ctypes.c_uint64), ctypes.c_uint32, ctypes.c_void_p,
|
||||
ctypes.c_size_t, ctypes.POINTER(ctypes.c_uint64), ctypes.POINTER(ctypes.c_uint32), ctypes.c_void_p, ctypes.POINTER(ctypes.c_size_t)]
|
||||
iokit.IOConnectCallMethod.restype = kern_return_t
|
||||
|
||||
def open_userclient_by_name(name: str, uc_type: int = 0) -> io_connect_t:
|
||||
mdict = iokit.IOServiceNameMatching(name.encode("utf-8"))
|
||||
if not mdict: raise RuntimeError("IOServiceNameMatching returned NULL")
|
||||
|
||||
# Grab the first matching service
|
||||
service = iokit.IOServiceGetMatchingService(kIOMasterPortDefault, mdict)
|
||||
if not service: raise RuntimeError(f'service "{name}" not found')
|
||||
|
||||
# print("lol", service)
|
||||
# print(libsys.mach_task_self_)
|
||||
# cast libsys.mach_task_self_ to uint and print
|
||||
# print("lol", ctypes.cast(libsys.mach_task_self_, ctypes.POINTER(ctypes.c_uint)).contents.value)
|
||||
|
||||
try:
|
||||
# Open user client (type -> passed to NewUserClient_Impl)
|
||||
conn = io_connect_t(0)
|
||||
# print("lol", libsys.mach_task_self_)
|
||||
kr = iokit.IOServiceOpen(service, ctypes.cast(libsys.mach_task_self_, ctypes.POINTER(ctypes.c_uint)).contents.value,
|
||||
ctypes.c_uint32(uc_type), ctypes.byref(conn))
|
||||
if kr != 0: raise OSError(kr, f"IOServiceOpen failed (0x{kr:08x})")
|
||||
return conn
|
||||
finally: iokit.IOObjectRelease(service)
|
||||
|
||||
def external_method(conn: io_connect_t, selector: int = 0) -> int:
|
||||
# no scalars in/out, no struct in/out — just ping selector 0
|
||||
in_scalars = ctypes.POINTER(ctypes.c_uint64)() # NULL
|
||||
out_scalars = (ctypes.c_uint64 * 1)() # space if driver returns something
|
||||
out_scalars_cnt = ctypes.c_uint32(0) # driver can set this
|
||||
|
||||
return iokit.IOConnectCallMethod(conn, ctypes.c_uint32(selector), in_scalars, ctypes.c_uint32(0), None, ctypes.c_size_t(0),
|
||||
out_scalars, ctypes.byref(out_scalars_cnt), None, ctypes.byref(ctypes.c_size_t(0)))
|
||||
|
||||
def close_userclient(conn: io_connect_t) -> None:
|
||||
# IOServiceClose is a macro; exported symbol is IOServiceClose in IOKit
|
||||
iokit.IOServiceClose.argtypes = [io_connect_t]
|
||||
iokit.IOServiceClose.restype = kern_return_t
|
||||
iokit.IOServiceClose(conn)
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
conn = open_userclient_by_name("tinygpu", uc_type=0)
|
||||
kr = external_method(conn, selector=0)
|
||||
print(f"ExternalMethod(0) -> 0x{kr:08x}")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
finally:
|
||||
if 'conn' in locals() and conn.value: close_userclient(conn)
|
||||
@@ -141,4 +141,9 @@ def __getattr__(nm):
|
||||
return load("metal", "'Metal'", [f"{macossdk}/System/Library/Frameworks/Metal.framework/Headers/MTL{s}.h" for s in
|
||||
["ComputeCommandEncoder", "ComputePipeline", "CommandQueue", "Device", "IndirectCommandBuffer", "Resource", "CommandEncoder"]],
|
||||
args=["-xobjective-c","-isysroot",macossdk], types={"dispatch_data_t":"objc.id_"})
|
||||
case "iokit": return load("iokit", "'IOKit'", [f"{macossdk}/System/Library/Frameworks/IOKit.framework/Headers/IOKitLib.h"],
|
||||
args=["-isysroot", macossdk])
|
||||
case "corefoundation": return load("corefoundation", "'CoreFoundation'",
|
||||
[f"{macossdk}/System/Library/Frameworks/CoreFoundation.framework/Headers/CF{s}.h" for s in ["String", "Data"]],
|
||||
args=["-isysroot", macossdk])
|
||||
case _: raise AttributeError(f"no such autogen: {nm}")
|
||||
|
||||
345
tinygrad/runtime/autogen/corefoundation.py
Normal file
345
tinygrad/runtime/autogen/corefoundation.py
Normal file
@@ -0,0 +1,345 @@
|
||||
# mypy: disable-error-code="empty-body"
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
from typing import Annotated, Literal, TypeAlias
|
||||
from tinygrad.runtime.support.c import _IO, _IOW, _IOR, _IOWR
|
||||
from tinygrad.runtime.support import c
|
||||
dll = c.DLL('corefoundation', 'CoreFoundation')
|
||||
CFStringEncoding: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
CFStringBuiltInEncodings: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
class _anonenum0(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
kCFStringEncodingMacRoman = _anonenum0.define('kCFStringEncodingMacRoman', 0)
|
||||
kCFStringEncodingWindowsLatin1 = _anonenum0.define('kCFStringEncodingWindowsLatin1', 1280)
|
||||
kCFStringEncodingISOLatin1 = _anonenum0.define('kCFStringEncodingISOLatin1', 513)
|
||||
kCFStringEncodingNextStepLatin = _anonenum0.define('kCFStringEncodingNextStepLatin', 2817)
|
||||
kCFStringEncodingASCII = _anonenum0.define('kCFStringEncodingASCII', 1536)
|
||||
kCFStringEncodingUnicode = _anonenum0.define('kCFStringEncodingUnicode', 256)
|
||||
kCFStringEncodingUTF8 = _anonenum0.define('kCFStringEncodingUTF8', 134217984)
|
||||
kCFStringEncodingNonLossyASCII = _anonenum0.define('kCFStringEncodingNonLossyASCII', 3071)
|
||||
kCFStringEncodingUTF16 = _anonenum0.define('kCFStringEncodingUTF16', 256)
|
||||
kCFStringEncodingUTF16BE = _anonenum0.define('kCFStringEncodingUTF16BE', 268435712)
|
||||
kCFStringEncodingUTF16LE = _anonenum0.define('kCFStringEncodingUTF16LE', 335544576)
|
||||
kCFStringEncodingUTF32 = _anonenum0.define('kCFStringEncodingUTF32', 201326848)
|
||||
kCFStringEncodingUTF32BE = _anonenum0.define('kCFStringEncodingUTF32BE', 402653440)
|
||||
kCFStringEncodingUTF32LE = _anonenum0.define('kCFStringEncodingUTF32LE', 469762304)
|
||||
|
||||
CFTypeID: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
@dll.bind
|
||||
def CFStringGetTypeID() -> CFTypeID: ...
|
||||
class struct___CFAllocator(ctypes.Structure): pass
|
||||
CFAllocatorRef: TypeAlias = c.POINTER[struct___CFAllocator]
|
||||
ConstStr255Param: TypeAlias = c.POINTER[Annotated[int, ctypes.c_ubyte]]
|
||||
class struct___CFString(ctypes.Structure): pass
|
||||
CFStringRef: TypeAlias = c.POINTER[struct___CFString]
|
||||
@dll.bind
|
||||
def CFStringCreateWithPascalString(alloc:CFAllocatorRef, pStr:ConstStr255Param, encoding:CFStringEncoding) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateWithCString(alloc:CFAllocatorRef, cStr:c.POINTER[Annotated[bytes, ctypes.c_char]], encoding:CFStringEncoding) -> CFStringRef: ...
|
||||
UInt8: TypeAlias = Annotated[int, ctypes.c_ubyte]
|
||||
CFIndex: TypeAlias = Annotated[int, ctypes.c_int64]
|
||||
Boolean: TypeAlias = Annotated[int, ctypes.c_ubyte]
|
||||
@dll.bind
|
||||
def CFStringCreateWithBytes(alloc:CFAllocatorRef, bytes:c.POINTER[UInt8], numBytes:CFIndex, encoding:CFStringEncoding, isExternalRepresentation:Boolean) -> CFStringRef: ...
|
||||
UniChar: TypeAlias = Annotated[int, ctypes.c_uint16]
|
||||
@dll.bind
|
||||
def CFStringCreateWithCharacters(alloc:CFAllocatorRef, chars:c.POINTER[UniChar], numChars:CFIndex) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateWithPascalStringNoCopy(alloc:CFAllocatorRef, pStr:ConstStr255Param, encoding:CFStringEncoding, contentsDeallocator:CFAllocatorRef) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateWithCStringNoCopy(alloc:CFAllocatorRef, cStr:c.POINTER[Annotated[bytes, ctypes.c_char]], encoding:CFStringEncoding, contentsDeallocator:CFAllocatorRef) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateWithBytesNoCopy(alloc:CFAllocatorRef, bytes:c.POINTER[UInt8], numBytes:CFIndex, encoding:CFStringEncoding, isExternalRepresentation:Boolean, contentsDeallocator:CFAllocatorRef) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateWithCharactersNoCopy(alloc:CFAllocatorRef, chars:c.POINTER[UniChar], numChars:CFIndex, contentsDeallocator:CFAllocatorRef) -> CFStringRef: ...
|
||||
@c.record
|
||||
class CFRange(c.Struct):
|
||||
SIZE = 16
|
||||
location: Annotated[CFIndex, 0]
|
||||
length: Annotated[CFIndex, 8]
|
||||
@dll.bind
|
||||
def CFStringCreateWithSubstring(alloc:CFAllocatorRef, str:CFStringRef, range:CFRange) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateCopy(alloc:CFAllocatorRef, theString:CFStringRef) -> CFStringRef: ...
|
||||
class struct___CFDictionary(ctypes.Structure): pass
|
||||
CFDictionaryRef: TypeAlias = c.POINTER[struct___CFDictionary]
|
||||
@dll.bind
|
||||
def CFStringCreateWithFormat(alloc:CFAllocatorRef, formatOptions:CFDictionaryRef, format:CFStringRef) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateWithFormatAndArguments(alloc:CFAllocatorRef, formatOptions:CFDictionaryRef, format:CFStringRef, arguments:Annotated[int, ctypes.c_int32]) -> CFStringRef: ...
|
||||
class struct___CFError(ctypes.Structure): pass
|
||||
CFErrorRef: TypeAlias = c.POINTER[struct___CFError]
|
||||
@dll.bind
|
||||
def CFStringCreateStringWithValidatedFormat(alloc:CFAllocatorRef, formatOptions:CFDictionaryRef, validFormatSpecifiers:CFStringRef, format:CFStringRef, errorPtr:c.POINTER[CFErrorRef]) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateStringWithValidatedFormatAndArguments(alloc:CFAllocatorRef, formatOptions:CFDictionaryRef, validFormatSpecifiers:CFStringRef, format:CFStringRef, arguments:Annotated[int, ctypes.c_int32], errorPtr:c.POINTER[CFErrorRef]) -> CFStringRef: ...
|
||||
CFMutableStringRef: TypeAlias = c.POINTER[struct___CFString]
|
||||
@dll.bind
|
||||
def CFStringCreateMutable(alloc:CFAllocatorRef, maxLength:CFIndex) -> CFMutableStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateMutableCopy(alloc:CFAllocatorRef, maxLength:CFIndex, theString:CFStringRef) -> CFMutableStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateMutableWithExternalCharactersNoCopy(alloc:CFAllocatorRef, chars:c.POINTER[UniChar], numChars:CFIndex, capacity:CFIndex, externalCharactersAllocator:CFAllocatorRef) -> CFMutableStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringGetLength(theString:CFStringRef) -> CFIndex: ...
|
||||
@dll.bind
|
||||
def CFStringGetCharacterAtIndex(theString:CFStringRef, idx:CFIndex) -> UniChar: ...
|
||||
@dll.bind
|
||||
def CFStringGetCharacters(theString:CFStringRef, range:CFRange, buffer:c.POINTER[UniChar]) -> None: ...
|
||||
StringPtr: TypeAlias = c.POINTER[Annotated[int, ctypes.c_ubyte]]
|
||||
@dll.bind
|
||||
def CFStringGetPascalString(theString:CFStringRef, buffer:StringPtr, bufferSize:CFIndex, encoding:CFStringEncoding) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringGetCString(theString:CFStringRef, buffer:c.POINTER[Annotated[bytes, ctypes.c_char]], bufferSize:CFIndex, encoding:CFStringEncoding) -> Boolean: ...
|
||||
ConstStringPtr: TypeAlias = c.POINTER[Annotated[int, ctypes.c_ubyte]]
|
||||
@dll.bind
|
||||
def CFStringGetPascalStringPtr(theString:CFStringRef, encoding:CFStringEncoding) -> ConstStringPtr: ...
|
||||
@dll.bind
|
||||
def CFStringGetCStringPtr(theString:CFStringRef, encoding:CFStringEncoding) -> c.POINTER[Annotated[bytes, ctypes.c_char]]: ...
|
||||
@dll.bind
|
||||
def CFStringGetCharactersPtr(theString:CFStringRef) -> c.POINTER[UniChar]: ...
|
||||
@dll.bind
|
||||
def CFStringGetBytes(theString:CFStringRef, range:CFRange, encoding:CFStringEncoding, lossByte:UInt8, isExternalRepresentation:Boolean, buffer:c.POINTER[UInt8], maxBufLen:CFIndex, usedBufLen:c.POINTER[CFIndex]) -> CFIndex: ...
|
||||
class struct___CFData(ctypes.Structure): pass
|
||||
CFDataRef: TypeAlias = c.POINTER[struct___CFData]
|
||||
@dll.bind
|
||||
def CFStringCreateFromExternalRepresentation(alloc:CFAllocatorRef, data:CFDataRef, encoding:CFStringEncoding) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateExternalRepresentation(alloc:CFAllocatorRef, theString:CFStringRef, encoding:CFStringEncoding, lossByte:UInt8) -> CFDataRef: ...
|
||||
@dll.bind
|
||||
def CFStringGetSmallestEncoding(theString:CFStringRef) -> CFStringEncoding: ...
|
||||
@dll.bind
|
||||
def CFStringGetFastestEncoding(theString:CFStringRef) -> CFStringEncoding: ...
|
||||
@dll.bind
|
||||
def CFStringGetSystemEncoding() -> CFStringEncoding: ...
|
||||
@dll.bind
|
||||
def CFStringGetMaximumSizeForEncoding(length:CFIndex, encoding:CFStringEncoding) -> CFIndex: ...
|
||||
@dll.bind
|
||||
def CFStringGetFileSystemRepresentation(string:CFStringRef, buffer:c.POINTER[Annotated[bytes, ctypes.c_char]], maxBufLen:CFIndex) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringGetMaximumSizeOfFileSystemRepresentation(string:CFStringRef) -> CFIndex: ...
|
||||
@dll.bind
|
||||
def CFStringCreateWithFileSystemRepresentation(alloc:CFAllocatorRef, buffer:c.POINTER[Annotated[bytes, ctypes.c_char]]) -> CFStringRef: ...
|
||||
CFStringCompareFlags: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
class _anonenum1(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
kCFCompareCaseInsensitive = _anonenum1.define('kCFCompareCaseInsensitive', 1)
|
||||
kCFCompareBackwards = _anonenum1.define('kCFCompareBackwards', 4)
|
||||
kCFCompareAnchored = _anonenum1.define('kCFCompareAnchored', 8)
|
||||
kCFCompareNonliteral = _anonenum1.define('kCFCompareNonliteral', 16)
|
||||
kCFCompareLocalized = _anonenum1.define('kCFCompareLocalized', 32)
|
||||
kCFCompareNumerically = _anonenum1.define('kCFCompareNumerically', 64)
|
||||
kCFCompareDiacriticInsensitive = _anonenum1.define('kCFCompareDiacriticInsensitive', 128)
|
||||
kCFCompareWidthInsensitive = _anonenum1.define('kCFCompareWidthInsensitive', 256)
|
||||
kCFCompareForcedOrdering = _anonenum1.define('kCFCompareForcedOrdering', 512)
|
||||
|
||||
class struct___CFLocale(ctypes.Structure): pass
|
||||
CFLocaleRef: TypeAlias = c.POINTER[struct___CFLocale]
|
||||
CFComparisonResult: TypeAlias = Annotated[int, ctypes.c_int64]
|
||||
@dll.bind
|
||||
def CFStringCompareWithOptionsAndLocale(theString1:CFStringRef, theString2:CFStringRef, rangeToCompare:CFRange, compareOptions:CFStringCompareFlags, locale:CFLocaleRef) -> CFComparisonResult: ...
|
||||
@dll.bind
|
||||
def CFStringCompareWithOptions(theString1:CFStringRef, theString2:CFStringRef, rangeToCompare:CFRange, compareOptions:CFStringCompareFlags) -> CFComparisonResult: ...
|
||||
@dll.bind
|
||||
def CFStringCompare(theString1:CFStringRef, theString2:CFStringRef, compareOptions:CFStringCompareFlags) -> CFComparisonResult: ...
|
||||
@dll.bind
|
||||
def CFStringFindWithOptionsAndLocale(theString:CFStringRef, stringToFind:CFStringRef, rangeToSearch:CFRange, searchOptions:CFStringCompareFlags, locale:CFLocaleRef, result:c.POINTER[CFRange]) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringFindWithOptions(theString:CFStringRef, stringToFind:CFStringRef, rangeToSearch:CFRange, searchOptions:CFStringCompareFlags, result:c.POINTER[CFRange]) -> Boolean: ...
|
||||
class struct___CFArray(ctypes.Structure): pass
|
||||
CFArrayRef: TypeAlias = c.POINTER[struct___CFArray]
|
||||
@dll.bind
|
||||
def CFStringCreateArrayWithFindResults(alloc:CFAllocatorRef, theString:CFStringRef, stringToFind:CFStringRef, rangeToSearch:CFRange, compareOptions:CFStringCompareFlags) -> CFArrayRef: ...
|
||||
@dll.bind
|
||||
def CFStringFind(theString:CFStringRef, stringToFind:CFStringRef, compareOptions:CFStringCompareFlags) -> CFRange: ...
|
||||
@dll.bind
|
||||
def CFStringHasPrefix(theString:CFStringRef, prefix:CFStringRef) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringHasSuffix(theString:CFStringRef, suffix:CFStringRef) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringGetRangeOfComposedCharactersAtIndex(theString:CFStringRef, theIndex:CFIndex) -> CFRange: ...
|
||||
class struct___CFCharacterSet(ctypes.Structure): pass
|
||||
CFCharacterSetRef: TypeAlias = c.POINTER[struct___CFCharacterSet]
|
||||
@dll.bind
|
||||
def CFStringFindCharacterFromSet(theString:CFStringRef, theSet:CFCharacterSetRef, rangeToSearch:CFRange, searchOptions:CFStringCompareFlags, result:c.POINTER[CFRange]) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringGetLineBounds(theString:CFStringRef, range:CFRange, lineBeginIndex:c.POINTER[CFIndex], lineEndIndex:c.POINTER[CFIndex], contentsEndIndex:c.POINTER[CFIndex]) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringGetParagraphBounds(string:CFStringRef, range:CFRange, parBeginIndex:c.POINTER[CFIndex], parEndIndex:c.POINTER[CFIndex], contentsEndIndex:c.POINTER[CFIndex]) -> None: ...
|
||||
CFOptionFlags: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
UTF32Char: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def CFStringGetHyphenationLocationBeforeIndex(string:CFStringRef, location:CFIndex, limitRange:CFRange, options:CFOptionFlags, locale:CFLocaleRef, character:c.POINTER[UTF32Char]) -> CFIndex: ...
|
||||
@dll.bind
|
||||
def CFStringIsHyphenationAvailableForLocale(locale:CFLocaleRef) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringCreateByCombiningStrings(alloc:CFAllocatorRef, theArray:CFArrayRef, separatorString:CFStringRef) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringCreateArrayBySeparatingStrings(alloc:CFAllocatorRef, theString:CFStringRef, separatorString:CFStringRef) -> CFArrayRef: ...
|
||||
SInt32: TypeAlias = Annotated[int, ctypes.c_int32]
|
||||
@dll.bind
|
||||
def CFStringGetIntValue(str:CFStringRef) -> SInt32: ...
|
||||
@dll.bind
|
||||
def CFStringGetDoubleValue(str:CFStringRef) -> Annotated[float, ctypes.c_double]: ...
|
||||
@dll.bind
|
||||
def CFStringAppend(theString:CFMutableStringRef, appendedString:CFStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringAppendCharacters(theString:CFMutableStringRef, chars:c.POINTER[UniChar], numChars:CFIndex) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringAppendPascalString(theString:CFMutableStringRef, pStr:ConstStr255Param, encoding:CFStringEncoding) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringAppendCString(theString:CFMutableStringRef, cStr:c.POINTER[Annotated[bytes, ctypes.c_char]], encoding:CFStringEncoding) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringAppendFormat(theString:CFMutableStringRef, formatOptions:CFDictionaryRef, format:CFStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringAppendFormatAndArguments(theString:CFMutableStringRef, formatOptions:CFDictionaryRef, format:CFStringRef, arguments:Annotated[int, ctypes.c_int32]) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringInsert(str:CFMutableStringRef, idx:CFIndex, insertedStr:CFStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringDelete(theString:CFMutableStringRef, range:CFRange) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringReplace(theString:CFMutableStringRef, range:CFRange, replacement:CFStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringReplaceAll(theString:CFMutableStringRef, replacement:CFStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringFindAndReplace(theString:CFMutableStringRef, stringToFind:CFStringRef, replacementString:CFStringRef, rangeToSearch:CFRange, compareOptions:CFStringCompareFlags) -> CFIndex: ...
|
||||
@dll.bind
|
||||
def CFStringSetExternalCharactersNoCopy(theString:CFMutableStringRef, chars:c.POINTER[UniChar], length:CFIndex, capacity:CFIndex) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringPad(theString:CFMutableStringRef, padString:CFStringRef, length:CFIndex, indexIntoPad:CFIndex) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringTrim(theString:CFMutableStringRef, trimString:CFStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringTrimWhitespace(theString:CFMutableStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringLowercase(theString:CFMutableStringRef, locale:CFLocaleRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringUppercase(theString:CFMutableStringRef, locale:CFLocaleRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringCapitalize(theString:CFMutableStringRef, locale:CFLocaleRef) -> None: ...
|
||||
CFStringNormalizationForm: TypeAlias = Annotated[int, ctypes.c_int64]
|
||||
class _anonenum2(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
kCFStringNormalizationFormD = _anonenum2.define('kCFStringNormalizationFormD', 0)
|
||||
kCFStringNormalizationFormKD = _anonenum2.define('kCFStringNormalizationFormKD', 1)
|
||||
kCFStringNormalizationFormC = _anonenum2.define('kCFStringNormalizationFormC', 2)
|
||||
kCFStringNormalizationFormKC = _anonenum2.define('kCFStringNormalizationFormKC', 3)
|
||||
|
||||
@dll.bind
|
||||
def CFStringNormalize(theString:CFMutableStringRef, theForm:CFStringNormalizationForm) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringFold(theString:CFMutableStringRef, theFlags:CFStringCompareFlags, theLocale:CFLocaleRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFStringTransform(string:CFMutableStringRef, range:c.POINTER[CFRange], transform:CFStringRef, reverse:Boolean) -> Boolean: ...
|
||||
try: kCFStringTransformStripCombiningMarks = CFStringRef.in_dll(dll, 'kCFStringTransformStripCombiningMarks') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformToLatin = CFStringRef.in_dll(dll, 'kCFStringTransformToLatin') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformFullwidthHalfwidth = CFStringRef.in_dll(dll, 'kCFStringTransformFullwidthHalfwidth') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinKatakana = CFStringRef.in_dll(dll, 'kCFStringTransformLatinKatakana') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinHiragana = CFStringRef.in_dll(dll, 'kCFStringTransformLatinHiragana') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformHiraganaKatakana = CFStringRef.in_dll(dll, 'kCFStringTransformHiraganaKatakana') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformMandarinLatin = CFStringRef.in_dll(dll, 'kCFStringTransformMandarinLatin') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinHangul = CFStringRef.in_dll(dll, 'kCFStringTransformLatinHangul') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinArabic = CFStringRef.in_dll(dll, 'kCFStringTransformLatinArabic') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinHebrew = CFStringRef.in_dll(dll, 'kCFStringTransformLatinHebrew') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinThai = CFStringRef.in_dll(dll, 'kCFStringTransformLatinThai') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinCyrillic = CFStringRef.in_dll(dll, 'kCFStringTransformLatinCyrillic') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformLatinGreek = CFStringRef.in_dll(dll, 'kCFStringTransformLatinGreek') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformToXMLHex = CFStringRef.in_dll(dll, 'kCFStringTransformToXMLHex') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformToUnicodeName = CFStringRef.in_dll(dll, 'kCFStringTransformToUnicodeName') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
try: kCFStringTransformStripDiacritics = CFStringRef.in_dll(dll, 'kCFStringTransformStripDiacritics') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
@dll.bind
|
||||
def CFStringIsEncodingAvailable(encoding:CFStringEncoding) -> Boolean: ...
|
||||
@dll.bind
|
||||
def CFStringGetListOfAvailableEncodings() -> c.POINTER[CFStringEncoding]: ...
|
||||
@dll.bind
|
||||
def CFStringGetNameOfEncoding(encoding:CFStringEncoding) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringConvertEncodingToNSStringEncoding(encoding:CFStringEncoding) -> Annotated[int, ctypes.c_uint64]: ...
|
||||
@dll.bind
|
||||
def CFStringConvertNSStringEncodingToEncoding(encoding:Annotated[int, ctypes.c_uint64]) -> CFStringEncoding: ...
|
||||
UInt32: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def CFStringConvertEncodingToWindowsCodepage(encoding:CFStringEncoding) -> UInt32: ...
|
||||
@dll.bind
|
||||
def CFStringConvertWindowsCodepageToEncoding(codepage:UInt32) -> CFStringEncoding: ...
|
||||
@dll.bind
|
||||
def CFStringConvertIANACharSetNameToEncoding(theString:CFStringRef) -> CFStringEncoding: ...
|
||||
@dll.bind
|
||||
def CFStringConvertEncodingToIANACharSetName(encoding:CFStringEncoding) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def CFStringGetMostCompatibleMacStringEncoding(encoding:CFStringEncoding) -> CFStringEncoding: ...
|
||||
@c.record
|
||||
class CFStringInlineBuffer(c.Struct):
|
||||
SIZE = 184
|
||||
buffer: Annotated[c.Array[UniChar, Literal[64]], 0]
|
||||
theString: Annotated[CFStringRef, 128]
|
||||
directUniCharBuffer: Annotated[c.POINTER[UniChar], 136]
|
||||
directCStringBuffer: Annotated[c.POINTER[Annotated[bytes, ctypes.c_char]], 144]
|
||||
rangeToBuffer: Annotated[CFRange, 152]
|
||||
bufferedRangeStart: Annotated[CFIndex, 168]
|
||||
bufferedRangeEnd: Annotated[CFIndex, 176]
|
||||
CFTypeRef: TypeAlias = ctypes.c_void_p
|
||||
@dll.bind
|
||||
def CFShow(obj:CFTypeRef) -> None: ...
|
||||
@dll.bind
|
||||
def CFShowStr(str:CFStringRef) -> None: ...
|
||||
@dll.bind
|
||||
def __CFStringMakeConstantString(cStr:c.POINTER[Annotated[bytes, ctypes.c_char]]) -> CFStringRef: ...
|
||||
CFMutableDataRef: TypeAlias = c.POINTER[struct___CFData]
|
||||
@dll.bind
|
||||
def CFDataGetTypeID() -> CFTypeID: ...
|
||||
@dll.bind
|
||||
def CFDataCreate(allocator:CFAllocatorRef, bytes:c.POINTER[UInt8], length:CFIndex) -> CFDataRef: ...
|
||||
@dll.bind
|
||||
def CFDataCreateWithBytesNoCopy(allocator:CFAllocatorRef, bytes:c.POINTER[UInt8], length:CFIndex, bytesDeallocator:CFAllocatorRef) -> CFDataRef: ...
|
||||
@dll.bind
|
||||
def CFDataCreateCopy(allocator:CFAllocatorRef, theData:CFDataRef) -> CFDataRef: ...
|
||||
@dll.bind
|
||||
def CFDataCreateMutable(allocator:CFAllocatorRef, capacity:CFIndex) -> CFMutableDataRef: ...
|
||||
@dll.bind
|
||||
def CFDataCreateMutableCopy(allocator:CFAllocatorRef, capacity:CFIndex, theData:CFDataRef) -> CFMutableDataRef: ...
|
||||
@dll.bind
|
||||
def CFDataGetLength(theData:CFDataRef) -> CFIndex: ...
|
||||
@dll.bind
|
||||
def CFDataGetBytePtr(theData:CFDataRef) -> c.POINTER[UInt8]: ...
|
||||
@dll.bind
|
||||
def CFDataGetMutableBytePtr(theData:CFMutableDataRef) -> c.POINTER[UInt8]: ...
|
||||
@dll.bind
|
||||
def CFDataGetBytes(theData:CFDataRef, range:CFRange, buffer:c.POINTER[UInt8]) -> None: ...
|
||||
@dll.bind
|
||||
def CFDataSetLength(theData:CFMutableDataRef, length:CFIndex) -> None: ...
|
||||
@dll.bind
|
||||
def CFDataIncreaseLength(theData:CFMutableDataRef, extraLength:CFIndex) -> None: ...
|
||||
@dll.bind
|
||||
def CFDataAppendBytes(theData:CFMutableDataRef, bytes:c.POINTER[UInt8], length:CFIndex) -> None: ...
|
||||
@dll.bind
|
||||
def CFDataReplaceBytes(theData:CFMutableDataRef, range:CFRange, newBytes:c.POINTER[UInt8], newLength:CFIndex) -> None: ...
|
||||
@dll.bind
|
||||
def CFDataDeleteBytes(theData:CFMutableDataRef, range:CFRange) -> None: ...
|
||||
CFDataSearchFlags: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
class _anonenum3(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
kCFDataSearchBackwards = _anonenum3.define('kCFDataSearchBackwards', 1)
|
||||
kCFDataSearchAnchored = _anonenum3.define('kCFDataSearchAnchored', 2)
|
||||
|
||||
@dll.bind
|
||||
def CFDataFind(theData:CFDataRef, dataToFind:CFDataRef, searchRange:CFRange, compareOptions:CFDataSearchFlags) -> CFRange: ...
|
||||
c.init_records()
|
||||
__COREFOUNDATION_CFSTRING__ = 1 # type: ignore
|
||||
kCFStringEncodingInvalidId = (0xffffffff) # type: ignore
|
||||
CF_FORMAT_FUNCTION = lambda F,A: __attribute__((format(CFString, F, A))) # type: ignore
|
||||
CF_FORMAT_ARGUMENT = lambda A: __attribute__((format_arg(A))) # type: ignore
|
||||
__kCFStringInlineBufferLength = 64 # type: ignore
|
||||
__COREFOUNDATION_CFDATA__ = 1 # type: ignore
|
||||
279
tinygrad/runtime/autogen/iokit.py
Normal file
279
tinygrad/runtime/autogen/iokit.py
Normal file
@@ -0,0 +1,279 @@
|
||||
# mypy: disable-error-code="empty-body"
|
||||
from __future__ import annotations
|
||||
import ctypes
|
||||
from typing import Annotated, Literal, TypeAlias
|
||||
from tinygrad.runtime.support.c import _IO, _IOW, _IOR, _IOWR
|
||||
from tinygrad.runtime.support import c
|
||||
dll = c.DLL('iokit', 'IOKit')
|
||||
class struct_IONotificationPort(ctypes.Structure): pass
|
||||
IONotificationPortRef: TypeAlias = c.POINTER[struct_IONotificationPort]
|
||||
IOServiceMatchingCallback: TypeAlias = c.CFUNCTYPE[None, [ctypes.c_void_p, Annotated[int, ctypes.c_uint32]]]
|
||||
IOServiceInterestCallback: TypeAlias = c.CFUNCTYPE[None, [ctypes.c_void_p, Annotated[int, ctypes.c_uint32], Annotated[int, ctypes.c_uint32], ctypes.c_void_p]]
|
||||
mach_port_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
try: kIOMainPortDefault = mach_port_t.in_dll(dll, 'kIOMainPortDefault') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
kern_return_t: TypeAlias = Annotated[int, ctypes.c_int32]
|
||||
@dll.bind
|
||||
def IOMainPort(bootstrapPort:mach_port_t, mainPort:c.POINTER[mach_port_t]) -> kern_return_t: ...
|
||||
try: kIOMasterPortDefault = mach_port_t.in_dll(dll, 'kIOMasterPortDefault') # type: ignore
|
||||
except (ValueError,AttributeError): pass
|
||||
@dll.bind
|
||||
def IOMasterPort(bootstrapPort:mach_port_t, mainPort:c.POINTER[mach_port_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IONotificationPortCreate(mainPort:mach_port_t) -> IONotificationPortRef: ...
|
||||
@dll.bind
|
||||
def IONotificationPortDestroy(notify:IONotificationPortRef) -> None: ...
|
||||
class struct___CFRunLoopSource(ctypes.Structure): pass
|
||||
CFRunLoopSourceRef: TypeAlias = c.POINTER[struct___CFRunLoopSource]
|
||||
@dll.bind
|
||||
def IONotificationPortGetRunLoopSource(notify:IONotificationPortRef) -> CFRunLoopSourceRef: ...
|
||||
@dll.bind
|
||||
def IONotificationPortGetMachPort(notify:IONotificationPortRef) -> mach_port_t: ...
|
||||
@dll.bind
|
||||
def IONotificationPortSetImportanceReceiver(notify:IONotificationPortRef) -> kern_return_t: ...
|
||||
class struct_dispatch_queue_s(ctypes.Structure): pass
|
||||
dispatch_queue_t: TypeAlias = c.POINTER[struct_dispatch_queue_s]
|
||||
@dll.bind
|
||||
def IONotificationPortSetDispatchQueue(notify:IONotificationPortRef, queue:dispatch_queue_t) -> None: ...
|
||||
@c.record
|
||||
class mach_msg_header_t(c.Struct):
|
||||
SIZE = 24
|
||||
msgh_bits: Annotated[mach_msg_bits_t, 0]
|
||||
msgh_size: Annotated[mach_msg_size_t, 4]
|
||||
msgh_remote_port: Annotated[mach_port_t, 8]
|
||||
msgh_local_port: Annotated[mach_port_t, 12]
|
||||
msgh_voucher_port: Annotated[mach_port_name_t, 16]
|
||||
msgh_id: Annotated[mach_msg_id_t, 20]
|
||||
mach_msg_bits_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
mach_msg_size_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
mach_port_name_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
mach_msg_id_t: TypeAlias = Annotated[int, ctypes.c_int32]
|
||||
@dll.bind
|
||||
def IODispatchCalloutFromMessage(unused:ctypes.c_void_p, msg:c.POINTER[mach_msg_header_t], reference:ctypes.c_void_p) -> None: ...
|
||||
uint32_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def IOCreateReceivePort(msgType:uint32_t, recvPort:c.POINTER[mach_port_t]) -> kern_return_t: ...
|
||||
io_object_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def IOObjectRelease(object:io_object_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOObjectRetain(object:io_object_t) -> kern_return_t: ...
|
||||
io_name_t: TypeAlias = c.Array[Annotated[bytes, ctypes.c_char], Literal[128]]
|
||||
@dll.bind
|
||||
def IOObjectGetClass(object:io_object_t, className:io_name_t) -> kern_return_t: ...
|
||||
class struct___CFString(ctypes.Structure): pass
|
||||
CFStringRef: TypeAlias = c.POINTER[struct___CFString]
|
||||
@dll.bind
|
||||
def IOObjectCopyClass(object:io_object_t) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def IOObjectCopySuperclassForClass(classname:CFStringRef) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def IOObjectCopyBundleIdentifierForClass(classname:CFStringRef) -> CFStringRef: ...
|
||||
boolean_t: TypeAlias = Annotated[int, ctypes.c_int32]
|
||||
@dll.bind
|
||||
def IOObjectConformsTo(object:io_object_t, className:io_name_t) -> boolean_t: ...
|
||||
@dll.bind
|
||||
def IOObjectIsEqualTo(object:io_object_t, anObject:io_object_t) -> boolean_t: ...
|
||||
@dll.bind
|
||||
def IOObjectGetKernelRetainCount(object:io_object_t) -> uint32_t: ...
|
||||
@dll.bind
|
||||
def IOObjectGetUserRetainCount(object:io_object_t) -> uint32_t: ...
|
||||
@dll.bind
|
||||
def IOObjectGetRetainCount(object:io_object_t) -> uint32_t: ...
|
||||
io_iterator_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def IOIteratorNext(iterator:io_iterator_t) -> io_object_t: ...
|
||||
@dll.bind
|
||||
def IOIteratorReset(iterator:io_iterator_t) -> None: ...
|
||||
@dll.bind
|
||||
def IOIteratorIsValid(iterator:io_iterator_t) -> boolean_t: ...
|
||||
class struct___CFDictionary(ctypes.Structure): pass
|
||||
CFDictionaryRef: TypeAlias = c.POINTER[struct___CFDictionary]
|
||||
io_service_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def IOServiceGetMatchingService(mainPort:mach_port_t, matching:CFDictionaryRef) -> io_service_t: ...
|
||||
@dll.bind
|
||||
def IOServiceGetMatchingServices(mainPort:mach_port_t, matching:CFDictionaryRef, existing:c.POINTER[io_iterator_t]) -> kern_return_t: ...
|
||||
uintptr_t: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
@dll.bind
|
||||
def IOServiceAddNotification(mainPort:mach_port_t, notificationType:io_name_t, matching:CFDictionaryRef, wakePort:mach_port_t, reference:uintptr_t, notification:c.POINTER[io_iterator_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOServiceAddMatchingNotification(notifyPort:IONotificationPortRef, notificationType:io_name_t, matching:CFDictionaryRef, callback:IOServiceMatchingCallback, refCon:ctypes.c_void_p, notification:c.POINTER[io_iterator_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOServiceAddInterestNotification(notifyPort:IONotificationPortRef, service:io_service_t, interestType:io_name_t, callback:IOServiceInterestCallback, refCon:ctypes.c_void_p, notification:c.POINTER[io_object_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOServiceMatchPropertyTable(service:io_service_t, matching:CFDictionaryRef, matches:c.POINTER[boolean_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOServiceGetBusyState(service:io_service_t, busyState:c.POINTER[uint32_t]) -> kern_return_t: ...
|
||||
@c.record
|
||||
class struct_mach_timespec(c.Struct):
|
||||
SIZE = 8
|
||||
tv_sec: Annotated[Annotated[int, ctypes.c_uint32], 0]
|
||||
tv_nsec: Annotated[clock_res_t, 4]
|
||||
mach_timespec_t: TypeAlias = struct_mach_timespec
|
||||
clock_res_t: TypeAlias = Annotated[int, ctypes.c_int32]
|
||||
@dll.bind
|
||||
def IOServiceWaitQuiet(service:io_service_t, waitTime:c.POINTER[mach_timespec_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOKitGetBusyState(mainPort:mach_port_t, busyState:c.POINTER[uint32_t]) -> kern_return_t: ...
|
||||
IOOptionBits: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def IOKitWaitQuietWithOptions(mainPort:mach_port_t, waitTime:c.POINTER[mach_timespec_t], options:IOOptionBits) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOKitWaitQuiet(mainPort:mach_port_t, waitTime:c.POINTER[mach_timespec_t]) -> kern_return_t: ...
|
||||
task_port_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
io_connect_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def IOServiceOpen(service:io_service_t, owningTask:task_port_t, type:uint32_t, connect:c.POINTER[io_connect_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOServiceRequestProbe(service:io_service_t, options:uint32_t) -> kern_return_t: ...
|
||||
class _anonenum0(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
kIOServiceInteractionAllowed = _anonenum0.define('kIOServiceInteractionAllowed', 1)
|
||||
|
||||
@dll.bind
|
||||
def IOServiceAuthorize(service:io_service_t, options:uint32_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOServiceOpenAsFileDescriptor(service:io_service_t, oflag:Annotated[int, ctypes.c_int32]) -> Annotated[int, ctypes.c_int32]: ...
|
||||
@dll.bind
|
||||
def IOServiceClose(connect:io_connect_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectAddRef(connect:io_connect_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectRelease(connect:io_connect_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectGetService(connect:io_connect_t, service:c.POINTER[io_service_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectSetNotificationPort(connect:io_connect_t, type:uint32_t, port:mach_port_t, reference:uintptr_t) -> kern_return_t: ...
|
||||
mach_vm_address_t: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
mach_vm_size_t: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
@dll.bind
|
||||
def IOConnectMapMemory(connect:io_connect_t, memoryType:uint32_t, intoTask:task_port_t, atAddress:c.POINTER[mach_vm_address_t], ofSize:c.POINTER[mach_vm_size_t], options:IOOptionBits) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectMapMemory64(connect:io_connect_t, memoryType:uint32_t, intoTask:task_port_t, atAddress:c.POINTER[mach_vm_address_t], ofSize:c.POINTER[mach_vm_size_t], options:IOOptionBits) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectUnmapMemory(connect:io_connect_t, memoryType:uint32_t, fromTask:task_port_t, atAddress:mach_vm_address_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectUnmapMemory64(connect:io_connect_t, memoryType:uint32_t, fromTask:task_port_t, atAddress:mach_vm_address_t) -> kern_return_t: ...
|
||||
CFTypeRef: TypeAlias = ctypes.c_void_p
|
||||
@dll.bind
|
||||
def IOConnectSetCFProperties(connect:io_connect_t, properties:CFTypeRef) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectSetCFProperty(connect:io_connect_t, propertyName:CFStringRef, property:CFTypeRef) -> kern_return_t: ...
|
||||
uint64_t: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
size_t: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
@dll.bind
|
||||
def IOConnectCallMethod(connection:mach_port_t, selector:uint32_t, input:c.POINTER[uint64_t], inputCnt:uint32_t, inputStruct:ctypes.c_void_p, inputStructCnt:size_t, output:c.POINTER[uint64_t], outputCnt:c.POINTER[uint32_t], outputStruct:ctypes.c_void_p, outputStructCnt:c.POINTER[size_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectCallAsyncMethod(connection:mach_port_t, selector:uint32_t, wake_port:mach_port_t, reference:c.POINTER[uint64_t], referenceCnt:uint32_t, input:c.POINTER[uint64_t], inputCnt:uint32_t, inputStruct:ctypes.c_void_p, inputStructCnt:size_t, output:c.POINTER[uint64_t], outputCnt:c.POINTER[uint32_t], outputStruct:ctypes.c_void_p, outputStructCnt:c.POINTER[size_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectCallStructMethod(connection:mach_port_t, selector:uint32_t, inputStruct:ctypes.c_void_p, inputStructCnt:size_t, outputStruct:ctypes.c_void_p, outputStructCnt:c.POINTER[size_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectCallAsyncStructMethod(connection:mach_port_t, selector:uint32_t, wake_port:mach_port_t, reference:c.POINTER[uint64_t], referenceCnt:uint32_t, inputStruct:ctypes.c_void_p, inputStructCnt:size_t, outputStruct:ctypes.c_void_p, outputStructCnt:c.POINTER[size_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectCallScalarMethod(connection:mach_port_t, selector:uint32_t, input:c.POINTER[uint64_t], inputCnt:uint32_t, output:c.POINTER[uint64_t], outputCnt:c.POINTER[uint32_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectCallAsyncScalarMethod(connection:mach_port_t, selector:uint32_t, wake_port:mach_port_t, reference:c.POINTER[uint64_t], referenceCnt:uint32_t, input:c.POINTER[uint64_t], inputCnt:uint32_t, output:c.POINTER[uint64_t], outputCnt:c.POINTER[uint32_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectTrap0(connect:io_connect_t, index:uint32_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectTrap1(connect:io_connect_t, index:uint32_t, p1:uintptr_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectTrap2(connect:io_connect_t, index:uint32_t, p1:uintptr_t, p2:uintptr_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectTrap3(connect:io_connect_t, index:uint32_t, p1:uintptr_t, p2:uintptr_t, p3:uintptr_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectTrap4(connect:io_connect_t, index:uint32_t, p1:uintptr_t, p2:uintptr_t, p3:uintptr_t, p4:uintptr_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectTrap5(connect:io_connect_t, index:uint32_t, p1:uintptr_t, p2:uintptr_t, p3:uintptr_t, p4:uintptr_t, p5:uintptr_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectTrap6(connect:io_connect_t, index:uint32_t, p1:uintptr_t, p2:uintptr_t, p3:uintptr_t, p4:uintptr_t, p5:uintptr_t, p6:uintptr_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOConnectAddClient(connect:io_connect_t, client:io_connect_t) -> kern_return_t: ...
|
||||
io_registry_entry_t: TypeAlias = Annotated[int, ctypes.c_uint32]
|
||||
@dll.bind
|
||||
def IORegistryGetRootEntry(mainPort:mach_port_t) -> io_registry_entry_t: ...
|
||||
io_string_t: TypeAlias = c.Array[Annotated[bytes, ctypes.c_char], Literal[512]]
|
||||
@dll.bind
|
||||
def IORegistryEntryFromPath(mainPort:mach_port_t, path:io_string_t) -> io_registry_entry_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryCopyFromPath(mainPort:mach_port_t, path:CFStringRef) -> io_registry_entry_t: ...
|
||||
class _anonenum1(Annotated[int, ctypes.c_uint32], c.Enum): pass
|
||||
kIORegistryIterateRecursively = _anonenum1.define('kIORegistryIterateRecursively', 1)
|
||||
kIORegistryIterateParents = _anonenum1.define('kIORegistryIterateParents', 2)
|
||||
|
||||
@dll.bind
|
||||
def IORegistryCreateIterator(mainPort:mach_port_t, plane:io_name_t, options:IOOptionBits, iterator:c.POINTER[io_iterator_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryCreateIterator(entry:io_registry_entry_t, plane:io_name_t, options:IOOptionBits, iterator:c.POINTER[io_iterator_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryIteratorEnterEntry(iterator:io_iterator_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryIteratorExitEntry(iterator:io_iterator_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetName(entry:io_registry_entry_t, name:io_name_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetNameInPlane(entry:io_registry_entry_t, plane:io_name_t, name:io_name_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetLocationInPlane(entry:io_registry_entry_t, plane:io_name_t, location:io_name_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetPath(entry:io_registry_entry_t, plane:io_name_t, path:io_string_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryCopyPath(entry:io_registry_entry_t, plane:io_name_t) -> CFStringRef: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetRegistryEntryID(entry:io_registry_entry_t, entryID:c.POINTER[uint64_t]) -> kern_return_t: ...
|
||||
CFMutableDictionaryRef: TypeAlias = c.POINTER[struct___CFDictionary]
|
||||
class struct___CFAllocator(ctypes.Structure): pass
|
||||
CFAllocatorRef: TypeAlias = c.POINTER[struct___CFAllocator]
|
||||
@dll.bind
|
||||
def IORegistryEntryCreateCFProperties(entry:io_registry_entry_t, properties:c.POINTER[CFMutableDictionaryRef], allocator:CFAllocatorRef, options:IOOptionBits) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryCreateCFProperty(entry:io_registry_entry_t, key:CFStringRef, allocator:CFAllocatorRef, options:IOOptionBits) -> CFTypeRef: ...
|
||||
@dll.bind
|
||||
def IORegistryEntrySearchCFProperty(entry:io_registry_entry_t, plane:io_name_t, key:CFStringRef, allocator:CFAllocatorRef, options:IOOptionBits) -> CFTypeRef: ...
|
||||
io_struct_inband_t: TypeAlias = c.Array[Annotated[bytes, ctypes.c_char], Literal[4096]]
|
||||
@dll.bind
|
||||
def IORegistryEntryGetProperty(entry:io_registry_entry_t, propertyName:io_name_t, buffer:io_struct_inband_t, size:c.POINTER[uint32_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntrySetCFProperties(entry:io_registry_entry_t, properties:CFTypeRef) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntrySetCFProperty(entry:io_registry_entry_t, propertyName:CFStringRef, property:CFTypeRef) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetChildIterator(entry:io_registry_entry_t, plane:io_name_t, iterator:c.POINTER[io_iterator_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetChildEntry(entry:io_registry_entry_t, plane:io_name_t, child:c.POINTER[io_registry_entry_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetParentIterator(entry:io_registry_entry_t, plane:io_name_t, iterator:c.POINTER[io_iterator_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryGetParentEntry(entry:io_registry_entry_t, plane:io_name_t, parent:c.POINTER[io_registry_entry_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryInPlane(entry:io_registry_entry_t, plane:io_name_t) -> boolean_t: ...
|
||||
@dll.bind
|
||||
def IOServiceMatching(name:c.POINTER[Annotated[bytes, ctypes.c_char]]) -> CFMutableDictionaryRef: ...
|
||||
@dll.bind
|
||||
def IOServiceNameMatching(name:c.POINTER[Annotated[bytes, ctypes.c_char]]) -> CFMutableDictionaryRef: ...
|
||||
@dll.bind
|
||||
def IOBSDNameMatching(mainPort:mach_port_t, options:uint32_t, bsdName:c.POINTER[Annotated[bytes, ctypes.c_char]]) -> CFMutableDictionaryRef: ...
|
||||
@dll.bind
|
||||
def IOOpenFirmwarePathMatching(mainPort:mach_port_t, options:uint32_t, path:c.POINTER[Annotated[bytes, ctypes.c_char]]) -> CFMutableDictionaryRef: ...
|
||||
@dll.bind
|
||||
def IORegistryEntryIDMatching(entryID:uint64_t) -> CFMutableDictionaryRef: ...
|
||||
@dll.bind
|
||||
def IOServiceOFPathToBSDName(mainPort:mach_port_t, openFirmwarePath:io_name_t, bsdName:io_name_t) -> kern_return_t: ...
|
||||
IOAsyncCallback0: TypeAlias = c.CFUNCTYPE[None, [ctypes.c_void_p, Annotated[int, ctypes.c_int32]]]
|
||||
IOAsyncCallback1: TypeAlias = c.CFUNCTYPE[None, [ctypes.c_void_p, Annotated[int, ctypes.c_int32], ctypes.c_void_p]]
|
||||
IOAsyncCallback2: TypeAlias = c.CFUNCTYPE[None, [ctypes.c_void_p, Annotated[int, ctypes.c_int32], ctypes.c_void_p, ctypes.c_void_p]]
|
||||
IOAsyncCallback: TypeAlias = c.CFUNCTYPE[None, [ctypes.c_void_p, Annotated[int, ctypes.c_int32], c.POINTER[ctypes.c_void_p], Annotated[int, ctypes.c_uint32]]]
|
||||
vm_size_t: TypeAlias = Annotated[int, ctypes.c_uint64]
|
||||
@dll.bind
|
||||
def OSGetNotificationFromMessage(msg:c.POINTER[mach_msg_header_t], index:uint32_t, type:c.POINTER[uint32_t], reference:c.POINTER[uintptr_t], content:c.POINTER[ctypes.c_void_p], size:c.POINTER[vm_size_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOCatalogueSendData(mainPort:mach_port_t, flag:uint32_t, buffer:c.POINTER[Annotated[bytes, ctypes.c_char]], size:uint32_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOCatalogueTerminate(mainPort:mach_port_t, flag:uint32_t, description:io_name_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOCatalogueGetData(mainPort:mach_port_t, flag:uint32_t, buffer:c.POINTER[c.POINTER[Annotated[bytes, ctypes.c_char]]], size:c.POINTER[uint32_t]) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOCatalogueModuleLoaded(mainPort:mach_port_t, name:io_name_t) -> kern_return_t: ...
|
||||
@dll.bind
|
||||
def IOCatalogueReset(mainPort:mach_port_t, flag:uint32_t) -> kern_return_t: ...
|
||||
c.init_records()
|
||||
@@ -539,7 +539,7 @@ class NV_GSP(NV_IP):
|
||||
self.stat_q.wait_resp(nv.NV_VGPU_MSG_FUNCTION_SET_PAGE_DIRECTORY)
|
||||
|
||||
def rpc_set_gsp_system_info(self):
|
||||
def bdf_as_int(s): return 0x000 if s.startswith("usb") else (int(s[5:7],16)<<8) | (int(s[8:10],16)<<3) | int(s[-1],16)
|
||||
def bdf_as_int(s): return 0x000 if s.startswith("usb") or s.startswith("remote") else (int(s[5:7],16)<<8) | (int(s[8:10],16)<<3) | int(s[-1],16)
|
||||
|
||||
pcidev = self.nvdev.pci_dev
|
||||
data = nv.GspSystemInfo(gpuPhysAddr=pcidev.bar_info[0].addr, gpuPhysFbAddr=pcidev.bar_info[1].addr, gpuPhysInstAddr=pcidev.bar_info[3].addr,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import os, mmap, array, functools, ctypes, select, contextlib, dataclasses, sys, itertools
|
||||
from __future__ import annotations
|
||||
import os, mmap, array, functools, ctypes, select, contextlib, dataclasses, sys, itertools, struct, socket, subprocess, time, enum
|
||||
from typing import ClassVar
|
||||
from tinygrad.helpers import round_up, getenv, OSX, temp, ceildiv
|
||||
from tinygrad.runtime.autogen import libc, vfio, pci
|
||||
from tinygrad.helpers import round_up, getenv, OSX, temp, ceildiv, unwrap, fetch, system
|
||||
from tinygrad.runtime.autogen import libc, pci, vfio, iokit, corefoundation
|
||||
from tinygrad.runtime.support.hcq import FileIOInterface, MMIOInterface, HCQBuffer, hcq_filter_visible_devices
|
||||
from tinygrad.runtime.support.memory import MemoryManager, VirtMapping, AddrSpace
|
||||
from tinygrad.runtime.support.usb import ASM24Controller, USBMMIOInterface
|
||||
@@ -20,15 +21,9 @@ class _System:
|
||||
@functools.cached_property
|
||||
def atomic_lib(self): return ctypes.CDLL(ctypes.util.find_library('atomic')) if sys.platform == "linux" else None
|
||||
|
||||
@functools.cached_property
|
||||
def iokit(self): return ctypes.CDLL(ctypes.util.find_library("IOKit"))
|
||||
|
||||
@functools.cached_property
|
||||
def libsys(self): return ctypes.CDLL(ctypes.util.find_library("System"))
|
||||
|
||||
@functools.cached_property
|
||||
def mach_task_self(self): return ctypes.cast(self.libsys.mach_task_self_, ctypes.POINTER(ctypes.c_uint)).contents.value
|
||||
|
||||
@functools.cached_property
|
||||
def pagemap(self) -> FileIOInterface:
|
||||
self.write_sysfs("/proc/sys/vm/compact_unevictable_allowed", "0", "Failed to disable migration of locked pages")
|
||||
@@ -46,28 +41,6 @@ class _System:
|
||||
return vfio_fd
|
||||
except OSError: return None
|
||||
|
||||
@functools.cached_property
|
||||
def macos_tinygpu_conn(self):
|
||||
self.iokit.IOServiceNameMatching.restype = ctypes.c_void_p # CFMutableDictionaryRef
|
||||
if not (mdict:=self.iokit.IOServiceNameMatching("tinygpu".encode("utf-8"))): raise RuntimeError("IOServiceNameMatching returned NULL")
|
||||
if not (service:=self.iokit.IOServiceGetMatchingService(ctypes.c_uint(0), ctypes.c_void_p(mdict))):
|
||||
raise RuntimeError('Service "tinygpu" is not running')
|
||||
if self.iokit.IOServiceOpen(service, self.mach_task_self, ctypes.c_uint32(0), ctypes.byref(conn:=ctypes.c_uint(0))):
|
||||
raise RuntimeError("IOServiceOpen failed")
|
||||
return conn
|
||||
|
||||
def iokit_pci_memmap(self, typ:int):
|
||||
if self.iokit.IOConnectMapMemory64(self.macos_tinygpu_conn, ctypes.c_uint32(typ), System.mach_task_self,
|
||||
ctypes.byref(addr:=ctypes.c_uint64(0)), ctypes.byref(size:=ctypes.c_uint64(0)), 0x1): raise RuntimeError(f"IOConnectMapMemory64({typ=}) failed")
|
||||
return MMIOInterface(addr.value, size.value)
|
||||
|
||||
def iokit_pci_rpc(self, sel:int, *args:int):
|
||||
in_scalars = (ctypes.c_uint64 * len(args))(*args) if args else ctypes.POINTER(ctypes.c_uint64)()
|
||||
if (self.iokit.IOConnectCallMethod(self.macos_tinygpu_conn, sel, in_scalars, len(args), None, ctypes.c_size_t(0),
|
||||
out_scalars:=(ctypes.c_uint64*16)(), ctypes.byref(outcnt:=ctypes.c_uint32(16)), None, ctypes.byref(ctypes.c_size_t(0)))):
|
||||
raise RuntimeError(f"IOConnectCallMethod({sel=}, {args=}) failed")
|
||||
return out_scalars[:outcnt.value]
|
||||
|
||||
def reserve_hugepages(self, cnt): os.system(f"sudo sh -c 'echo {cnt} > /proc/sys/vm/nr_hugepages'")
|
||||
|
||||
def memory_barrier(self): lib.atomic_thread_fence(__ATOMIC_SEQ_CST:=5) if (lib:=self.libsys if OSX else self.atomic_lib) is not None else None
|
||||
@@ -79,14 +52,24 @@ class _System:
|
||||
self.pagemap.seek(vaddr // mmap.PAGESIZE * 8)
|
||||
return [(x & ((1<<55) - 1)) * mmap.PAGESIZE for x in array.array('Q', self.pagemap.read(size//mmap.PAGESIZE*8, binary=True))]
|
||||
|
||||
def pci_scan_bus(self, target_vendor:int, target_devices:list[tuple[int, list[int]]], base_class:int|None=None) -> list[str]:
|
||||
result = []
|
||||
for pcibus in FileIOInterface("/sys/bus/pci/devices").listdir():
|
||||
vendor = int(FileIOInterface(f"/sys/bus/pci/devices/{pcibus}/vendor").read(), 16)
|
||||
device = int(FileIOInterface(f"/sys/bus/pci/devices/{pcibus}/device").read(), 16)
|
||||
if base_class is not None and int(FileIOInterface(f"/sys/bus/pci/devices/{pcibus}/class").read(), 16) >> 16 != base_class: continue
|
||||
if vendor == target_vendor and any((device & mask) in devlist for mask, devlist in target_devices): result.append(pcibus)
|
||||
return sorted(result)
|
||||
def pci_scan_bus(self, vendor:int, devices:list[tuple[int, list[int]]], base_class:int|None=None) -> list[str]:
|
||||
all_devs = []
|
||||
if OSX:
|
||||
def read_prop(svc, key) -> int:
|
||||
cfkey = corefoundation.CFStringCreateWithCString(None, key.encode(), corefoundation.kCFStringEncodingUTF8)
|
||||
cfdata = ctypes.cast(iokit.IORegistryEntryCreateCFProperty(svc, ctypes.cast(cfkey, iokit.CFStringRef), None, 0), corefoundation.CFDataRef)
|
||||
corefoundation.CFDataGetBytes(cfdata, corefoundation.CFRange(0, corefoundation.CFDataGetLength(cfdata)), buf:=(ctypes.c_uint8*8)())
|
||||
return int.from_bytes(bytes(buf), "little")
|
||||
|
||||
iokit.IOServiceGetMatchingServices(0, iokit.IOServiceMatching(b"IOPCIDevice"), ctypes.byref(iterator:=ctypes.c_uint()))
|
||||
while svc:=iokit.IOIteratorNext(iterator): all_devs.append((v:=read_prop(svc, "vendor-id"), d:=read_prop(svc, "device-id"), f"{v:x}:{d:x}"))
|
||||
else:
|
||||
for pcibus in FileIOInterface("/sys/bus/pci/devices").listdir():
|
||||
if base_class is not None and int(FileIOInterface(f"/sys/bus/pci/devices/{pcibus}/class").read(), 16) >> 16 != base_class: continue
|
||||
all_devs.append((int(FileIOInterface(f"/sys/bus/pci/devices/{pcibus}/vendor").read(), 16),
|
||||
int(FileIOInterface(f"/sys/bus/pci/devices/{pcibus}/device").read(), 16), pcibus))
|
||||
|
||||
return sorted([val for vendor, device, val in all_devs if vendor == vendor and any((device & mask) in devlist for mask, devlist in devices)])
|
||||
|
||||
def pci_setup_usb_bars(self, usb:ASM24Controller, gpu_bus:int, mem_base:int, pref_mem_base:int) -> dict[int, PCIBarInfo]:
|
||||
for bus in range(gpu_bus):
|
||||
@@ -154,6 +137,8 @@ class _System:
|
||||
|
||||
System = _System()
|
||||
|
||||
# *** PCI Devices
|
||||
|
||||
class PCIDevice:
|
||||
def __init__(self, devpref:str, pcibus:str, bars:list[int], resize_bars:list[int]|None=None):
|
||||
self.lock_fd = System.flock_acquire(f"{devpref.lower()}_{pcibus.lower()}.lock")
|
||||
@@ -210,21 +195,6 @@ class PCIDevice:
|
||||
return MMIOInterface(loc, sz, fmt=fmt)
|
||||
def reset(self): os.system(f"sudo sh -c 'echo 1 > /sys/bus/pci/devices/{self.pcibus}/reset'")
|
||||
|
||||
class APLPCIDevice(PCIDevice):
|
||||
def __init__(self, devpref:str, pcibus:str, bars:list[int], resize_bars:list[int]|None=None):
|
||||
self.lock_fd = System.flock_acquire(f"{devpref.lower()}_{pcibus.lower()}.lock")
|
||||
self.pcibus, self.bars = pcibus, {b: System.iokit_pci_memmap(b) for b in bars}
|
||||
self.bar_info = {b:PCIBarInfo(0, self.bars[b].nbytes-1 if b in self.bars else 0) for b in range(6)} # NOTE: fake bar info for nv.
|
||||
def alloc_sysmem(self, size:int, vaddr:int=0, contiguous:bool=False) -> tuple[MMIOInterface, list[int]]:
|
||||
sysmem_view = System.iokit_pci_memmap(round_up(size, mmap.PAGESIZE))
|
||||
paddrs = list(itertools.takewhile(lambda p: p[1] != 0, zip(sysmem_view.view(fmt='Q')[0::2], sysmem_view.view(fmt='Q')[1::2])))
|
||||
assert not contiguous or len(paddrs) == 1, "not contiguous, but required"
|
||||
return sysmem_view, [p + i for p, sz in paddrs for i in range(0, sz, 0x1000)][:ceildiv(size, 0x1000)]
|
||||
def map_bar(self, bar:int, off:int=0, addr:int=0, size:int|None=None, fmt='B') -> MMIOInterface: return self.bars[bar].view(off, size, fmt)
|
||||
def read_config(self, offset:int, size:int): return System.iokit_pci_rpc(__TinyGPURPCReadCfg:=0, offset, size)[0]
|
||||
def write_config(self, offset:int, value:int, size:int): System.iokit_pci_rpc(__TinyGPURPCWriteCfg:=1, offset, size, value)
|
||||
def reset(self): System.iokit_pci_rpc(__TinyGPURPCReset:=2)
|
||||
|
||||
class USBPCIDevice(PCIDevice):
|
||||
def __init__(self, devpref:str, pcibus:str, bars:list[int], resize_bars:list[int]|None=None):
|
||||
self.lock_fd = System.flock_acquire(f"{devpref.lower()}_{pcibus.lower()}.lock")
|
||||
@@ -286,10 +256,101 @@ class LNXPCIIfaceBase:
|
||||
|
||||
self.dev_impl.mm.map_range(int(b.va_addr), round_up(b.size, 0x1000), paddrs, aspace=aspace, snooped=snooped, uncached=uncached)
|
||||
|
||||
class APLPCIIfaceBase(LNXPCIIfaceBase):
|
||||
def __init__(self, dev, dev_id, vendor, devices, bars, vram_bar, va_start, va_size, base_class:int|None=None):
|
||||
self.pci_dev, self.dev, self.vram_bar = APLPCIDevice(dev.__class__.__name__[:2], pcibus=f'usb4:{dev_id}', bars=bars), dev, vram_bar
|
||||
assert (read_vendor:=self.pci_dev.read_config(pci.PCI_VENDOR_ID, 2)) == vendor, f"Vendor ID mismatch: expected {vendor:#x}, got {read_vendor:#x}"
|
||||
def map(self, b:HCQBuffer): raise RuntimeError(f"map failed: {b.owner} -> {self.dev}")
|
||||
# *** Remote PCI Devices
|
||||
|
||||
PCIIfaceBase:type = APLPCIIfaceBase if OSX else LNXPCIIfaceBase
|
||||
class RemoteCmd(enum.IntEnum): MAP_BAR, MAP_SYSMEM_FD, CFG_READ, CFG_WRITE, RESET, MMIO_READ, MMIO_WRITE = 1, 2, 3, 4, 5, 6, 7
|
||||
|
||||
class RemoteMMIOInterface(MMIOInterface):
|
||||
def __init__(self, dev:RemotePCIDevice, residx:int, nbytes:int, fmt='B', off=0):
|
||||
self.dev, self.residx, self.nbytes, self.fmt, self.off, self.el_sz = dev, residx, nbytes, fmt, off, struct.calcsize(fmt)
|
||||
|
||||
def __getitem__(self, index):
|
||||
sl = index if isinstance(index, slice) else slice(index, index + 1)
|
||||
start, stop = (sl.start or 0) * self.el_sz, (sl.stop or len(self)) * self.el_sz
|
||||
data = self.dev._bulk_read(RemoteCmd.MMIO_READ, self.residx, self.off + start, stop - start)
|
||||
result = data if self.fmt == 'B' else list(struct.unpack(f'<{(stop - start) // self.el_sz}{self.fmt}', data))
|
||||
return result if isinstance(index, slice) else result[0]
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
start = (index.start or 0) * self.el_sz if isinstance(index, slice) else index * self.el_sz
|
||||
data = (val if self.fmt == 'B' else struct.pack(f'<{len(val)}{self.fmt}', *val)) if isinstance(index, slice) else struct.pack(f'<{self.fmt}', val)
|
||||
self.dev._bulk_write(RemoteCmd.MMIO_WRITE, self.residx, self.off + start, data)
|
||||
|
||||
def view(self, offset:int=0, size:int|None=None, fmt=None):
|
||||
return RemoteMMIOInterface(self.dev, self.residx, size or (self.nbytes - offset), fmt or self.fmt, self.off + offset)
|
||||
|
||||
class RemotePCIDevice(PCIDevice):
|
||||
def __init__(self, devpref:str, pcibus:str, bars:list[int], sock:socket.socket):
|
||||
self.lock_fd = System.flock_acquire(f"{devpref.lower()}_{pcibus.lower()}.lock")
|
||||
self.pcibus, self.sock = pcibus, sock
|
||||
for buft in [socket.SO_SNDBUF, socket.SO_RCVBUF]: self.sock.setsockopt(socket.SOL_SOCKET, buft, 64 << 20)
|
||||
self.bar_info = {b: PCIBarInfo(0, self._rpc(RemoteCmd.MAP_BAR, b)[0]) for b in bars}
|
||||
|
||||
def _recvall(self, n:int) -> bytes:
|
||||
data = b''
|
||||
while len(data) < n and (chunk:=self.sock.recv(n - len(data))): data += chunk
|
||||
if len(data) < n: raise RuntimeError("Connection closed")
|
||||
return data
|
||||
|
||||
def _recv_with_fd(self) -> tuple[bytes, int|None]:
|
||||
msg, anc, _, _ = self.sock.recvmsg(17, socket.CMSG_LEN(4))
|
||||
return msg, struct.unpack('<i', anc[0][2][:4])[0]
|
||||
|
||||
def _rpc(self, cmd:int, *args:int, readout_size:int=0, has_fd=False) -> tuple[int, int, bytes|None, int|None]:
|
||||
self.sock.sendall(struct.pack('<BBQQQ', cmd, *(*args, 0, 0, 0, 0)[:4]))
|
||||
msg, fd = self._recv_with_fd() if has_fd else (self._recvall(17), None)
|
||||
if (resp:=struct.unpack('<BQQ', msg))[0] != 0:
|
||||
raise RuntimeError(f"RPC failed: {self._recvall(resp[1]).decode('utf-8') if resp[1] > 0 else 'unknown error'}")
|
||||
return (resp[1], resp[2]) + ((self._recvall(readout_size) if readout_size > 0 else None),) + (fd,)
|
||||
|
||||
def _bulk_read(self, cmd:int, idx:int, offset:int, size:int) -> bytes: return unwrap(self._rpc(cmd, idx, offset, size, readout_size=size)[2])
|
||||
def _bulk_write(self, cmd:int, idx:int, offset:int, data:bytes): self.sock.sendall(struct.pack('<BBQQQ', cmd, idx, offset, len(data), 0) + data)
|
||||
|
||||
def alloc_sysmem(self, size:int, vaddr:int=0, contiguous:bool=False) -> tuple[MMIOInterface, list[int]]:
|
||||
mapped_size, _, _, fd = self._rpc(RemoteCmd.MAP_SYSMEM_FD, 0, 0, size, has_fd=True)
|
||||
memview = MMIOInterface(FileIOInterface(fd=fd).mmap(0, mapped_size, mmap.PROT_READ | mmap.PROT_WRITE, mmap.MAP_SHARED, 0), mapped_size, fmt='B')
|
||||
|
||||
# paddrs are returned as (paddr, size) pairs until a (paddr=0, size=0) terminator in the beginning of the mapping.
|
||||
paddrs_raw = list(itertools.takewhile(lambda p: p[1] != 0, zip(memview.view(fmt='Q')[0::2], memview.view(fmt='Q')[1::2])))
|
||||
return memview, [p + i for p, sz in paddrs_raw for i in range(0, sz, 0x1000)][:ceildiv(size, 0x1000)]
|
||||
def read_config(self, offset:int, size:int): return self._rpc(RemoteCmd.CFG_READ, 0, offset, size)[0]
|
||||
def write_config(self, offset:int, value:int, size:int): self._rpc(RemoteCmd.CFG_WRITE, 0, offset, size, value)
|
||||
def reset(self): self._rpc(RemoteCmd.RESET, 0, 0, 0)
|
||||
def map_bar(self, bar:int, off:int=0, addr:int=0, size:int|None=None, fmt='B') -> MMIOInterface:
|
||||
return RemoteMMIOInterface(self, bar, size or self.bar_info[bar].size, fmt).view(off, size, fmt)
|
||||
|
||||
class APLRemotePCIDevice(RemotePCIDevice):
|
||||
APP_PATH = "/Applications/TinyGPU.app/Contents/MacOS/TinyGPU"
|
||||
|
||||
@staticmethod
|
||||
def install_tinygpu():
|
||||
print("Downloading TinyGPU.app...")
|
||||
system(f"ditto -xk {fetch('https://github.com/nimlgen/tinygpu_releases/raw/8120b5508b43149d27bf22f9a4e6d7c5a4b401e9/TinyGPU.zip')} /Applications")
|
||||
print(system(f"{APLRemotePCIDevice.APP_PATH} install"))
|
||||
|
||||
def __init__(self, devpref:str, pcibus:str, bars:list[int], resize_bars:list[int]|None=None):
|
||||
sock_path, sock = getenv("APL_REMOTE_SOCK", temp("tinygpu.sock")), socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
for i in range(100):
|
||||
with contextlib.suppress(ConnectionRefusedError, FileNotFoundError):
|
||||
sock.connect(sock_path)
|
||||
break
|
||||
if i == 0: subprocess.Popen([self.APP_PATH, "server", sock_path], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
time.sleep(0.05)
|
||||
else: raise RuntimeError(f"Failed to connect to TinyGPU server at {sock_path}.")
|
||||
super().__init__(devpref, pcibus, bars, sock)
|
||||
|
||||
class APLRemoteIfaceBase(LNXPCIIfaceBase):
|
||||
def __init__(self, dev, dev_id, vendor, devices:list[tuple[int, list[int]]], bars, vram_bar, va_start, va_size, base_class:int|None=None):
|
||||
if not (cls:=type(self)).gpus:
|
||||
cls.gpus = System.pci_scan_bus(vendor, devices, base_class)
|
||||
if not cls.gpus: raise RuntimeError("No supported GPUs found")
|
||||
if not os.path.exists(APLRemotePCIDevice.APP_PATH): APLRemotePCIDevice.install_tinygpu()
|
||||
self.pci_dev = APLRemotePCIDevice(dev.__class__.__name__[:2], f'remote:{dev_id}', bars)
|
||||
self.dev, self.vram_bar = dev, vram_bar
|
||||
|
||||
def free(self, b:HCQBuffer):
|
||||
for dev in b.mapped_devs[1:]: dev.iface.dev_impl.mm.unmap_range(b.va_addr, b.size)
|
||||
|
||||
def map(self, b:HCQBuffer): raise RuntimeError(f"P2P mapping not supported for remote devices: {b.owner} -> {self.dev}")
|
||||
|
||||
PCIIfaceBase:type = APLRemoteIfaceBase if OSX else LNXPCIIfaceBase
|
||||
|
||||
Reference in New Issue
Block a user