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