]> git.ipfire.org Git - thirdparty/pciutils.git/blame - lib/darwin.c
maint/release: Perl does not have "." in @INC any longer
[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
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 23enum {
43217e40
MM
24 kACPIMethodAddressSpaceRead = 0,
25 kACPIMethodAddressSpaceWrite = 1,
26 kACPIMethodDebuggerCommand = 2,
27 kACPIMethodCount
7cb1afbe
RY
28};
29
30#pragma pack(1)
31
32typedef UInt32 IOACPIAddressSpaceID;
33
34enum {
35 kIOACPIAddressSpaceIDSystemMemory = 0,
36 kIOACPIAddressSpaceIDSystemIO = 1,
37 kIOACPIAddressSpaceIDPCIConfiguration = 2,
38 kIOACPIAddressSpaceIDEmbeddedController = 3,
39 kIOACPIAddressSpaceIDSMBus = 4
40};
41
42/*
43 * 64-bit ACPI address
44 */
45union 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};
56typedef union IOACPIAddress IOACPIAddress;
57
58#pragma pack()
59
60struct AddressSpaceParam {
43217e40
MM
61 UInt64 value;
62 UInt32 spaceID;
63 IOACPIAddress address;
64 UInt32 bitWidth;
65 UInt32 bitOffset;
66 UInt32 options;
7cb1afbe
RY
67};
68typedef struct AddressSpaceParam AddressSpaceParam;
69
7cb1afbe
RY
70static void
71darwin_config(struct pci_access *a UNUSED)
72{
73}
74
75static int
76darwin_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
99static void
100darwin_init(struct pci_access *a UNUSED)
101{
102}
103
104static void
105darwin_cleanup(struct pci_access *a UNUSED)
106{
107}
108
109static int
110darwin_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 &param, sizeof(param),
134 &param, &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
153static int
154darwin_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 &param, 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
197struct 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};