]> git.ipfire.org Git - thirdparty/pciutils.git/blame - lib/darwin.c
lspci: add VirtIO SharedMemory capability support
[thirdparty/pciutils.git] / lib / darwin.c
CommitLineData
7cb1afbe 1/*
43217e40 2 * The PCI Library -- Darwin kIOACPI access
7cb1afbe 3 *
43217e40 4 * Copyright (c) 2013 Apple, Inc.
7cb1afbe 5 *
61829219
MM
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
7cb1afbe
RY
9 */
10
11#include <errno.h>
12#include <fcntl.h>
13#include <stdio.h>
14#include <string.h>
15#include <unistd.h>
16#include <stdint.h>
17
18#include "internal.h"
19
20#include <mach/mach_error.h>
21#include <CoreFoundation/CoreFoundation.h>
22#include <IOKit/IOKitLib.h>
23#include <IOKit/IOKitKeys.h>
24
7cb1afbe 25enum {
43217e40
MM
26 kACPIMethodAddressSpaceRead = 0,
27 kACPIMethodAddressSpaceWrite = 1,
28 kACPIMethodDebuggerCommand = 2,
29 kACPIMethodCount
7cb1afbe
RY
30};
31
32#pragma pack(1)
33
34typedef UInt32 IOACPIAddressSpaceID;
35
36enum {
37 kIOACPIAddressSpaceIDSystemMemory = 0,
38 kIOACPIAddressSpaceIDSystemIO = 1,
39 kIOACPIAddressSpaceIDPCIConfiguration = 2,
40 kIOACPIAddressSpaceIDEmbeddedController = 3,
41 kIOACPIAddressSpaceIDSMBus = 4
42};
43
44/*
45 * 64-bit ACPI address
46 */
47union IOACPIAddress {
48 UInt64 addr64;
49 struct {
43217e40
MM
50 unsigned int offset :16;
51 unsigned int function :3;
52 unsigned int device :5;
53 unsigned int bus :8;
54 unsigned int segment :16;
55 unsigned int reserved :16;
7cb1afbe
RY
56 } pci;
57};
58typedef union IOACPIAddress IOACPIAddress;
59
60#pragma pack()
61
62struct AddressSpaceParam {
43217e40
MM
63 UInt64 value;
64 UInt32 spaceID;
65 IOACPIAddress address;
66 UInt32 bitWidth;
67 UInt32 bitOffset;
68 UInt32 options;
7cb1afbe
RY
69};
70typedef struct AddressSpaceParam AddressSpaceParam;
71
7cb1afbe
RY
72static void
73darwin_config(struct pci_access *a UNUSED)
74{
75}
76
77static int
78darwin_detect(struct pci_access *a)
79{
43217e40
MM
80 io_registry_entry_t service;
81 io_connect_t connect;
82 kern_return_t status;
83
84 service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleACPIPlatformExpert"));
85 if (service)
86 {
87 status = IOServiceOpen(service, mach_task_self(), 0, &connect);
88 IOObjectRelease(service);
89 }
7cb1afbe
RY
90
91 if (!service || (kIOReturnSuccess != status))
43217e40
MM
92 {
93 a->warning("Cannot open AppleACPIPlatformExpert (add boot arg debug=0x144 & run as root)");
94 return 0;
95 }
7cb1afbe
RY
96 a->debug("...using AppleACPIPlatformExpert");
97 a->fd = connect;
98 return 1;
99}
100
101static void
102darwin_init(struct pci_access *a UNUSED)
103{
104}
105
106static void
107darwin_cleanup(struct pci_access *a UNUSED)
108{
109}
110
111static int
112darwin_read(struct pci_dev *d, int pos, byte *buf, int len)
113{
114 if (!(len == 1 || len == 2 || len == 4))
115 return pci_generic_block_read(d, pos, buf, len);
116
43217e40
MM
117 AddressSpaceParam param;
118 kern_return_t status;
119
120 param.spaceID = kIOACPIAddressSpaceIDPCIConfiguration;
121 param.bitWidth = len * 8;
122 param.bitOffset = 0;
123 param.options = 0;
124
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;
131 param.value = -1ULL;
132
133 size_t outSize = sizeof(param);
134 status = IOConnectCallStructMethod(d->access->fd, kACPIMethodAddressSpaceRead,
135 &param, sizeof(param),
136 &param, &outSize);
7cb1afbe 137 if ((kIOReturnSuccess != status))
43217e40 138 d->access->error("darwin_read: kACPIMethodAddressSpaceRead failed: %s", mach_error_string(status));
7cb1afbe
RY
139
140 switch (len)
43217e40 141 {
7cb1afbe
RY
142 case 1:
143 buf[0] = (u8) param.value;
144 break;
145 case 2:
146 ((u16 *) buf)[0] = cpu_to_le16((u16) param.value);
147 break;
148 case 4:
149 ((u32 *) buf)[0] = cpu_to_le32((u32) param.value);
150 break;
43217e40 151 }
7cb1afbe
RY
152 return 1;
153}
154
155static int
156darwin_write(struct pci_dev *d, int pos, byte *buf, int len)
157{
158 if (!(len == 1 || len == 2 || len == 4))
159 return pci_generic_block_write(d, pos, buf, len);
160
43217e40
MM
161 AddressSpaceParam param;
162 kern_return_t status;
163
164 param.spaceID = kIOACPIAddressSpaceIDPCIConfiguration;
165 param.bitWidth = len * 8;
166 param.bitOffset = 0;
167 param.options = 0;
7cb1afbe 168
43217e40
MM
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;
7cb1afbe 175
7cb1afbe 176 switch (len)
43217e40 177 {
7cb1afbe
RY
178 case 1:
179 param.value = buf[0];
180 break;
181 case 2:
182 param.value = le16_to_cpu(((u16 *) buf)[0]);
183 break;
184 case 4:
185 param.value = le32_to_cpu(((u32 *) buf)[0]);
186 break;
43217e40 187 }
7cb1afbe 188
43217e40
MM
189 size_t outSize = 0;
190 status = IOConnectCallStructMethod(d->access->fd, kACPIMethodAddressSpaceWrite,
191 &param, sizeof(param),
192 NULL, &outSize);
7cb1afbe 193 if ((kIOReturnSuccess != status))
43217e40 194 d->access->error("darwin_read: kACPIMethodAddressSpaceWrite failed: %s", mach_error_string(status));
7cb1afbe
RY
195
196 return 1;
197}
198
66e0afd0 199struct pci_methods pm_darwin = {
1660c737
MM
200 .name = "darwin",
201 .help = "Darwin",
202 .config = darwin_config,
203 .detect = darwin_detect,
204 .init = darwin_init,
205 .cleanup = darwin_cleanup,
206 .scan = pci_generic_scan,
207 .fill_info = pci_generic_fill_info,
208 .read = darwin_read,
209 .write = darwin_write,
7cb1afbe 210};