]>
Commit | Line | Data |
---|---|---|
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 | 25 | enum { |
43217e40 MM |
26 | kACPIMethodAddressSpaceRead = 0, |
27 | kACPIMethodAddressSpaceWrite = 1, | |
28 | kACPIMethodDebuggerCommand = 2, | |
29 | kACPIMethodCount | |
7cb1afbe RY |
30 | }; |
31 | ||
32 | #pragma pack(1) | |
33 | ||
34 | typedef UInt32 IOACPIAddressSpaceID; | |
35 | ||
36 | enum { | |
37 | kIOACPIAddressSpaceIDSystemMemory = 0, | |
38 | kIOACPIAddressSpaceIDSystemIO = 1, | |
39 | kIOACPIAddressSpaceIDPCIConfiguration = 2, | |
40 | kIOACPIAddressSpaceIDEmbeddedController = 3, | |
41 | kIOACPIAddressSpaceIDSMBus = 4 | |
42 | }; | |
43 | ||
44 | /* | |
45 | * 64-bit ACPI address | |
46 | */ | |
47 | union 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 | }; | |
58 | typedef union IOACPIAddress IOACPIAddress; | |
59 | ||
60 | #pragma pack() | |
61 | ||
62 | struct AddressSpaceParam { | |
43217e40 MM |
63 | UInt64 value; |
64 | UInt32 spaceID; | |
65 | IOACPIAddress address; | |
66 | UInt32 bitWidth; | |
67 | UInt32 bitOffset; | |
68 | UInt32 options; | |
7cb1afbe RY |
69 | }; |
70 | typedef struct AddressSpaceParam AddressSpaceParam; | |
71 | ||
7cb1afbe RY |
72 | static void |
73 | darwin_config(struct pci_access *a UNUSED) | |
74 | { | |
75 | } | |
76 | ||
77 | static int | |
78 | darwin_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 | ||
101 | static void | |
102 | darwin_init(struct pci_access *a UNUSED) | |
103 | { | |
104 | } | |
105 | ||
106 | static void | |
107 | darwin_cleanup(struct pci_access *a UNUSED) | |
108 | { | |
109 | } | |
110 | ||
111 | static int | |
112 | darwin_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 | ¶m, sizeof(param), | |
136 | ¶m, &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 | ||
155 | static int | |
156 | darwin_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 | ¶m, 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 | 199 | struct 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 | }; |