]> mj.ucw.cz Git - pciutils.git/blob - lib/darwin-device.c
Import initial Darwin Support from Apple
[pciutils.git] / lib / darwin-device.c
1 /*
2  *      The PCI Library -- FreeBSD /dev/pci access
3  *
4  *      Copyright (c) 1999 Jari Kirma <kirma@cs.hut.fi>
5  *      Updated in 2003 by Samy Al Bahra <samy@kerneled.com>
6  *
7  *      Can be freely distributed and used under the terms of the GNU GPL.
8  */
9
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <stdint.h>
16
17 #include "internal.h"
18
19 #include <mach/mach_error.h>
20 #include <CoreFoundation/CoreFoundation.h>
21 #include <IOKit/IOKitLib.h>
22 #include <IOKit/IOKitKeys.h>
23
24
25 enum {
26         kACPIMethodAddressSpaceRead             = 0,
27         kACPIMethodAddressSpaceWrite    = 1,
28         kACPIMethodDebuggerCommand              = 2,
29         kACPIMethodCount
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 {
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;
56     } pci;
57 };
58 typedef union IOACPIAddress IOACPIAddress;
59
60 #pragma pack()
61
62 struct AddressSpaceParam {
63         UInt64                  value;
64         UInt32                  spaceID;
65         IOACPIAddress   address;
66         UInt32                  bitWidth;
67         UInt32                  bitOffset;
68         UInt32                  options;
69 };
70 typedef struct AddressSpaceParam AddressSpaceParam;
71
72
73 static void
74 darwin_config(struct pci_access *a UNUSED)
75 {
76 }
77
78 static int
79 darwin_detect(struct pci_access *a)
80 {
81         io_registry_entry_t    service;
82         io_connect_t           connect;
83         kern_return_t          status;
84
85         service = IOServiceGetMatchingService(kIOMasterPortDefault, 
86                                                                                                                                                                         IOServiceMatching("AppleACPIPlatformExpert"));
87         if (service) 
88         {
89                 status = IOServiceOpen(service, mach_task_self(), 0, &connect);
90                 IOObjectRelease(service);
91         }
92
93   if (!service || (kIOReturnSuccess != status))
94         {
95                 a->warning("Cannot open AppleACPIPlatformExpert (add boot arg debug=0x144 & run as root)");
96                 return 0;
97         }
98   a->debug("...using AppleACPIPlatformExpert");
99   a->fd = connect;
100   return 1;
101 }
102
103 static void
104 darwin_init(struct pci_access *a UNUSED)
105 {
106 }
107
108 static void
109 darwin_cleanup(struct pci_access *a UNUSED)
110 {
111 }
112
113 static int
114 darwin_read(struct pci_dev *d, int pos, byte *buf, int len)
115 {
116   if (!(len == 1 || len == 2 || len == 4))
117     return pci_generic_block_read(d, pos, buf, len);
118
119         AddressSpaceParam param;
120         kern_return_t     status;
121
122         param.spaceID   = kIOACPIAddressSpaceIDPCIConfiguration;
123         param.bitWidth  = len * 8;
124         param.bitOffset = 0;
125         param.options   = 0;
126
127         param.address.pci.offset   = pos;
128         param.address.pci.function = d->func;
129         param.address.pci.device   = d->dev;
130         param.address.pci.bus      = d->bus;
131         param.address.pci.segment  = d->domain;
132         param.address.pci.reserved = 0;
133         param.value                = -1ULL;
134
135         size_t outSize = sizeof(param);
136         status = IOConnectCallStructMethod(d->access->fd, kACPIMethodAddressSpaceRead,
137                                                                                                                                                                         &param, sizeof(param),
138                                                                                                                                                                         &param, &outSize);
139   if ((kIOReturnSuccess != status))
140         {
141                 d->access->error("darwin_read: kACPIMethodAddressSpaceRead failed: %s",
142                                                         mach_error_string(status));
143         }
144
145   switch (len)
146         {
147     case 1:
148       buf[0] = (u8) param.value;
149       break;
150     case 2:
151       ((u16 *) buf)[0] = cpu_to_le16((u16) param.value);
152       break;
153     case 4:
154       ((u32 *) buf)[0] = cpu_to_le32((u32) param.value);
155       break;
156         }
157   return 1;
158 }
159
160 static int
161 darwin_write(struct pci_dev *d, int pos, byte *buf, int len)
162 {
163   if (!(len == 1 || len == 2 || len == 4))
164     return pci_generic_block_write(d, pos, buf, len);
165
166         AddressSpaceParam param;
167         kern_return_t     status;
168
169         param.spaceID   = kIOACPIAddressSpaceIDPCIConfiguration;
170         param.bitWidth  = len * 8;
171         param.bitOffset = 0;
172         param.options   = 0;
173
174         param.address.pci.offset   = pos;
175         param.address.pci.function = d->func;
176         param.address.pci.device   = d->dev;
177         param.address.pci.bus      = d->bus;
178         param.address.pci.segment  = d->domain;
179         param.address.pci.reserved = 0;
180   switch (len)
181         {
182     case 1:
183       param.value = buf[0];
184       break;
185     case 2:
186       param.value = le16_to_cpu(((u16 *) buf)[0]);
187       break;
188     case 4:
189       param.value = le32_to_cpu(((u32 *) buf)[0]);
190       break;
191         }
192
193         size_t outSize = 0;
194         status = IOConnectCallStructMethod(d->access->fd, kACPIMethodAddressSpaceWrite,
195                                                                                                                                                                         &param, sizeof(param),
196                                                                                                                                                                         NULL, &outSize);
197   if ((kIOReturnSuccess != status))
198         {
199                 d->access->error("darwin_read: kACPIMethodAddressSpaceWrite failed: %s",
200                                                         mach_error_string(status));
201         }
202
203   return 1;
204 }
205
206 struct pci_methods pm_darwin_device = {
207   "darwin-device",
208   "Darwin device",
209   darwin_config,
210   darwin_detect,
211   darwin_init,
212   darwin_cleanup,
213   pci_generic_scan,
214   pci_generic_fill_info,
215   darwin_read,
216   darwin_write,
217   NULL,                                 /* read_vpd */
218   NULL,                                 /* dev_init */
219   NULL                                  /* dev_cleanup */
220 };