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