2 * The PCI Library -- Darwin kIOACPI access
4 * Copyright (c) 2013 Apple, Inc.
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
8 * SPDX-License-Identifier: GPL-2.0-or-later
20 #include <mach/mach_error.h>
21 #include <CoreFoundation/CoreFoundation.h>
22 #include <IOKit/IOKitLib.h>
23 #include <IOKit/IOKitKeys.h>
26 kACPIMethodAddressSpaceRead = 0,
27 kACPIMethodAddressSpaceWrite = 1,
28 kACPIMethodDebuggerCommand = 2,
34 typedef UInt32 IOACPIAddressSpaceID;
37 kIOACPIAddressSpaceIDSystemMemory = 0,
38 kIOACPIAddressSpaceIDSystemIO = 1,
39 kIOACPIAddressSpaceIDPCIConfiguration = 2,
40 kIOACPIAddressSpaceIDEmbeddedController = 3,
41 kIOACPIAddressSpaceIDSMBus = 4
50 unsigned int offset :16;
51 unsigned int function :3;
52 unsigned int device :5;
54 unsigned int segment :16;
55 unsigned int reserved :16;
58 typedef union IOACPIAddress IOACPIAddress;
62 struct AddressSpaceParam {
65 IOACPIAddress address;
70 typedef struct AddressSpaceParam AddressSpaceParam;
73 darwin_config(struct pci_access *a UNUSED)
78 darwin_detect(struct pci_access *a)
80 io_registry_entry_t service;
84 service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleACPIPlatformExpert"));
87 status = IOServiceOpen(service, mach_task_self(), 0, &connect);
88 IOObjectRelease(service);
91 if (!service || (kIOReturnSuccess != status))
93 a->warning("Cannot open AppleACPIPlatformExpert (add boot arg debug=0x144 & run as root)");
96 a->debug("...using AppleACPIPlatformExpert");
102 darwin_init(struct pci_access *a UNUSED)
107 darwin_cleanup(struct pci_access *a UNUSED)
112 darwin_read(struct pci_dev *d, int pos, byte *buf, int len)
114 if (!(len == 1 || len == 2 || len == 4))
115 return pci_generic_block_read(d, pos, buf, len);
117 AddressSpaceParam param;
118 kern_return_t status;
120 param.spaceID = kIOACPIAddressSpaceIDPCIConfiguration;
121 param.bitWidth = len * 8;
125 param.address.pci.offset = pos;
126 param.address.pci.function = d->func;
127 param.address.pci.device = d->dev;
128 param.address.pci.bus = d->bus;
129 param.address.pci.segment = d->domain;
130 param.address.pci.reserved = 0;
133 size_t outSize = sizeof(param);
134 status = IOConnectCallStructMethod(d->access->fd, kACPIMethodAddressSpaceRead,
135 ¶m, sizeof(param),
137 if ((kIOReturnSuccess != status))
138 d->access->error("darwin_read: kACPIMethodAddressSpaceRead failed: %s", mach_error_string(status));
143 buf[0] = (u8) param.value;
146 ((u16 *) buf)[0] = cpu_to_le16((u16) param.value);
149 ((u32 *) buf)[0] = cpu_to_le32((u32) param.value);
156 darwin_write(struct pci_dev *d, int pos, byte *buf, int len)
158 if (!(len == 1 || len == 2 || len == 4))
159 return pci_generic_block_write(d, pos, buf, len);
161 AddressSpaceParam param;
162 kern_return_t status;
164 param.spaceID = kIOACPIAddressSpaceIDPCIConfiguration;
165 param.bitWidth = len * 8;
169 param.address.pci.offset = pos;
170 param.address.pci.function = d->func;
171 param.address.pci.device = d->dev;
172 param.address.pci.bus = d->bus;
173 param.address.pci.segment = d->domain;
174 param.address.pci.reserved = 0;
179 param.value = buf[0];
182 param.value = le16_to_cpu(((u16 *) buf)[0]);
185 param.value = le32_to_cpu(((u32 *) buf)[0]);
190 status = IOConnectCallStructMethod(d->access->fd, kACPIMethodAddressSpaceWrite,
191 ¶m, sizeof(param),
193 if ((kIOReturnSuccess != status))
194 d->access->error("darwin_read: kACPIMethodAddressSpaceWrite failed: %s", mach_error_string(status));
199 struct pci_methods pm_darwin = {
207 pci_generic_fill_info,
212 NULL /* dev_cleanup */