]>
Commit | Line | Data |
---|---|---|
39236c6e | 1 | /* |
fe8ab488 | 2 | * Copyright (c) 2012-2014 Apple Computer, Inc. All Rights Reserved. |
39236c6e A |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ | |
fe8ab488 | 5 | * |
39236c6e A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
fe8ab488 | 14 | * |
39236c6e A |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
fe8ab488 | 17 | * |
39236c6e A |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
fe8ab488 | 25 | * |
39236c6e A |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ | |
28 | ||
29 | #ifndef _IOREPORT_MACROS_H_ | |
30 | #define _IOREPORT_MACROS_H_ | |
31 | ||
32 | #include "IOReportTypes.h" | |
33 | ||
34 | #ifdef __cplusplus | |
35 | extern "C" { | |
36 | #endif | |
37 | ||
fe8ab488 A |
38 | #ifndef IOREPORT_ABORT |
39 | #define IOREPORT_ABORT panic | |
40 | #endif | |
41 | ||
39236c6e A |
42 | /* |
43 | Background | |
44 | ||
45 | These macros allow non-I/O Kit software to generate IOReporting | |
46 | reports. Clients must prevent concurrent access to any given | |
47 | report buffer from multiple threads. | |
48 | ||
49 | While these macros allow non-I/O Kit software to participate | |
50 | in IOReporting, an IOService instance must lend its driver ID, | |
51 | respond to the appropriate IOService overrides, and shuttle | |
52 | data back and forth. In some cases, it may be useful to have | |
53 | the I/O Kit driver initialize the report buffer with the | |
54 | appropriate macro. | |
55 | */ | |
56 | ||
fe8ab488 A |
57 | |
58 | /* ----- Reporting Single Integers (SimpleReport) ----- */ | |
59 | ||
39236c6e | 60 | /* |
fe8ab488 | 61 | * The buffer size required for a SimpleReport. |
39236c6e | 62 | */ |
fe8ab488 | 63 | |
39236c6e A |
64 | #define SIMPLEREPORT_BUFSIZE (sizeof(IOReportElement)) |
65 | ||
fe8ab488 | 66 | |
39236c6e | 67 | /* |
fe8ab488 | 68 | * Initialize a buffer to hold a SimpleReport. |
39236c6e A |
69 | * |
70 | * void* buffer - ptr to SIMPLEREPORT_BUFSIZE bytes | |
71 | * size_t bufSize - sanity check of buffer's size | |
72 | * uint64_t providerID - registry Entry ID of the reporting service | |
73 | * uint64_t channelID - the report's channel ID | |
74 | * IOReportCategories categories - categories of this channel | |
75 | * | |
fe8ab488 A |
76 | * If the buffer is not of sufficient size, the macro calls IOREPORT_ABORT(). |
77 | * If that returns, the buffer is filled with 0xbadcafe. | |
39236c6e | 78 | */ |
fe8ab488 | 79 | |
39236c6e A |
80 | #define SIMPLEREPORT_INIT(buffer, bufSize, providerID, channelID, cats) \ |
81 | do { \ | |
82 | IOReportElement *__elem = (IOReportElement *)(buffer); \ | |
83 | IOSimpleReportValues *__vals; \ | |
84 | if ((bufSize) >= SIMPLEREPORT_BUFSIZE) { \ | |
85 | __elem->channel_id = (channelID); \ | |
86 | __elem->provider_id = (providerID); \ | |
87 | __elem->channel_type.report_format = kIOReportFormatSimple; \ | |
88 | __elem->channel_type.reserved = 0; \ | |
89 | __elem->channel_type.categories = (cats); \ | |
90 | __elem->channel_type.nelements = 1; \ | |
91 | __elem->channel_type.element_idx = 0; \ | |
92 | __elem->timestamp = 0; \ | |
fe8ab488 A |
93 | __vals = (IOSimpleReportValues*)&__elem->values; \ |
94 | __vals->simple_value = kIOReportInvalidIntValue; \ | |
39236c6e A |
95 | } \ |
96 | else { \ | |
fe8ab488 A |
97 | IOREPORT_ABORT("bufSize is smaller than the required size\n"); \ |
98 | __POLLUTE_BUF((buffer), (bufSize)); \ | |
39236c6e A |
99 | } \ |
100 | } while(0) | |
101 | ||
102 | ||
103 | /* | |
fe8ab488 | 104 | * Set a SimpleReport to a new value. |
39236c6e | 105 | * |
fe8ab488 A |
106 | * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() |
107 | * int64_t new_value - new value for the report | |
39236c6e | 108 | */ |
fe8ab488 | 109 | |
39236c6e A |
110 | #define SIMPLEREPORT_SETVALUE(simp_buf, new_value) \ |
111 | do { \ | |
112 | IOReportElement *__elem = (IOReportElement *)(simp_buf); \ | |
113 | IOSimpleReportValues *__vals; \ | |
114 | __vals = (IOSimpleReportValues*)&__elem->values; \ | |
115 | __vals->simple_value = (new_value); \ | |
116 | } while(0) | |
117 | ||
fe8ab488 | 118 | |
39236c6e | 119 | /* |
fe8ab488 A |
120 | * Increment the value of a SimpleReport. |
121 | * | |
122 | * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() | |
123 | * int64_t increment - amount by which to increment the value | |
124 | */ | |
125 | #define SIMPLEREPORT_INCREMENTVALUE(simp_buf, new_value) \ | |
126 | do { \ | |
127 | IOReportElement *__elem = (IOReportElement *)(simp_buf); \ | |
128 | IOSimpleReportValues *__vals; \ | |
129 | __vals = (IOSimpleReportValues*)&__elem->values; \ | |
130 | __vals->simple_value += (new_value); \ | |
131 | } while(0) | |
132 | ||
133 | ||
134 | /* | |
135 | * Prepare a SimpleReport for | |
39236c6e A |
136 | * IOService::updateReport(kIOReportCopyChannelData...) |
137 | * | |
138 | * void* simp_buf - Ptr to memory updated by SIMPLEREPORT_SETVALUE() | |
139 | * void* ptr2cpy - On return, 'ptr2cpy' points to the memory that needs to be | |
140 | * copied for kIOReportCopyChannelData. | |
141 | * size_t size2cpy - On return, 'size2cpy' is set to the size of the report | |
142 | * data that needs to be copied for kIOReportCopyChannelData. | |
143 | */ | |
fe8ab488 | 144 | |
39236c6e A |
145 | #define SIMPLEREPORT_UPDATEPREP(simp_buf, ptr2cpy, size2cpy) \ |
146 | do { \ | |
147 | (ptr2cpy) = (simp_buf); \ | |
148 | (size2cpy) = sizeof(IOReportElement); \ | |
149 | } while(0) | |
150 | ||
151 | ||
152 | /* | |
fe8ab488 | 153 | * Update the result field received as a parameter for |
39236c6e A |
154 | * kIOReportGetDimensions & kIOReportCopyChannelData actions. |
155 | * | |
156 | * IOReportConfigureAction action - configure/updateReport() 'action' param | |
157 | * void* result - configure/updateReport() 'result' param | |
158 | */ | |
159 | ||
160 | #define SIMPLEREPORT_UPDATERES(action, result) \ | |
161 | do { \ | |
162 | if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \ | |
163 | int *__nElements = (int *)(result); \ | |
164 | *__nElements += 1; \ | |
165 | } \ | |
166 | } while (0) | |
167 | ||
168 | ||
39236c6e | 169 | /* |
fe8ab488 | 170 | * Get the 64-bit channel ID of a SimpleReport. |
39236c6e A |
171 | * |
172 | * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() | |
173 | */ | |
174 | ||
175 | #define SIMPLEREPORT_GETCHID(simp_buf) \ | |
fe8ab488 A |
176 | (((IOReportElement *)(simp_buf))->channel_id) |
177 | ||
178 | /* | |
179 | * Get the IOReportChannelType of a SimpleReport. | |
180 | * | |
181 | * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() | |
182 | */ | |
183 | ||
184 | #define SIMPLEREPORT_GETCHTYPE(simp_buf) \ | |
185 | (*(uint64_t*)&(((IOReportElement *)(simp_buf))->channel_type)) | |
186 | ||
187 | ||
188 | /* | |
189 | * Get the integer value of a SimpleReport. | |
190 | * | |
191 | * void* simp_buf - memory initialized by SIMPLEREPORT_INIT() | |
192 | */ | |
193 | ||
194 | #define SIMPLEREPORT_GETVALUE(simp_buf) \ | |
195 | (((IOSimpleReportValues*)&(((IOReportElement*)(simp_buf))->values)) \ | |
196 | ->simple_value) | |
39236c6e A |
197 | |
198 | ||
fe8ab488 | 199 | /* ----- State Machine Reporting (StateReport) ----- */ |
39236c6e | 200 | |
fe8ab488 | 201 | // Internal struct for StateReport |
39236c6e A |
202 | typedef struct { |
203 | uint16_t curr_state; | |
204 | uint64_t update_ts; | |
205 | IOReportElement elem[]; // Array of elements | |
206 | } IOStateReportInfo; | |
207 | ||
208 | /* | |
fe8ab488 | 209 | * Determine the size required for a StateReport buffer. |
39236c6e | 210 | * |
fe8ab488 | 211 | * int nstates - number of states to be reported |
39236c6e A |
212 | */ |
213 | #define STATEREPORT_BUFSIZE(nstates) \ | |
214 | (sizeof(IOStateReportInfo) + (nstates) * sizeof(IOReportElement)) | |
215 | ||
216 | ||
217 | /* | |
fe8ab488 | 218 | * Initialize a StateReport buffer. |
39236c6e A |
219 | * |
220 | * int nstates - number of states to be reported | |
221 | * void* buffer - ptr to STATEREPORT_BUFSIZE(nstates) bytes | |
222 | * size_t bufSize - sanity check of buffer's size | |
223 | * uint64_t providerID - registry Entry ID of the reporting service | |
224 | * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID() | |
225 | * IOReportCategories categories - categories of this channel | |
226 | * | |
fe8ab488 A |
227 | * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT. |
228 | * If that returns, the buffer is filled with 0xbadcafe. | |
39236c6e A |
229 | */ |
230 | #define STATEREPORT_INIT(nstates, buf, bufSize, providerID, channelID, cats) \ | |
231 | do { \ | |
232 | IOStateReportInfo *__info = (IOStateReportInfo *)(buf); \ | |
233 | IOStateReportValues *__rep; \ | |
234 | IOReportElement *__elem; \ | |
235 | if ((bufSize) >= STATEREPORT_BUFSIZE(nstates)) { \ | |
236 | for (unsigned __no = 0; __no < (nstates); __no++) { \ | |
237 | __elem = &(__info->elem[__no]); \ | |
238 | __rep = (IOStateReportValues *) &(__elem->values); \ | |
239 | __elem->channel_id = (channelID); \ | |
240 | __elem->provider_id = (providerID); \ | |
241 | __elem->channel_type.report_format = kIOReportFormatState; \ | |
242 | __elem->channel_type.reserved = 0; \ | |
243 | __elem->channel_type.categories = (cats); \ | |
244 | __elem->channel_type.nelements = (nstates); \ | |
245 | __elem->channel_type.element_idx = __no; \ | |
246 | __elem->timestamp = 0; \ | |
247 | __rep->state_id = __no; \ | |
248 | __rep->intransitions = 0; \ | |
249 | __rep->upticks = 0; \ | |
250 | } \ | |
251 | __info->curr_state = 0; \ | |
252 | __info->update_ts = 0; \ | |
253 | } \ | |
254 | else { \ | |
fe8ab488 A |
255 | IOREPORT_ABORT("bufSize is smaller than the required size\n"); \ |
256 | __POLLUTE_BUF((buf), (bufSize)); \ | |
39236c6e A |
257 | } \ |
258 | } while(0) | |
259 | ||
260 | /* | |
fe8ab488 A |
261 | * Initialize the state id field of a state with the specified value. By |
262 | * default, STATEREPORT_INIT() initializes the state IDs with the index of | |
39236c6e A |
263 | * that state. This macro can be used to provide a more descriptive state id. |
264 | * | |
265 | * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() | |
266 | * unsigned stateIdx - index of the state, out of bounds -> no-op | |
267 | * uint64_t stateID - new state id, see IOREPORT_MAKEID() | |
268 | */ | |
269 | #define STATEREPORT_SETSTATEID(state_buf, stateIdx, stateID) \ | |
270 | do { \ | |
271 | IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \ | |
272 | IOStateReportValues *__rep; \ | |
273 | if ((stateIdx) < __info->elem[0].channel_type.nelements) { \ | |
274 | __rep = (IOStateReportValues*) &(__info->elem[(stateIdx)].values); \ | |
275 | __rep->state_id = (stateID); \ | |
276 | } \ | |
277 | } while (0) | |
278 | ||
279 | ||
280 | /* | |
fe8ab488 | 281 | * Set the state of a StateReport. |
39236c6e A |
282 | * |
283 | * void* state_buf - pointer to memory initialized by STATEREPORT_INIT() | |
284 | * unsigned newStateIdx - index of new state, out of bounds -> no-op | |
285 | * uint64_t changeTime - time at which the transition occurred | |
286 | */ | |
287 | #define STATEREPORT_SETSTATE(state_buf, newStateIdx, changeTime) \ | |
288 | do { \ | |
289 | IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \ | |
290 | IOStateReportValues *__rep; \ | |
291 | if ((newStateIdx) < __info->elem[0].channel_type.nelements ) { \ | |
292 | __rep = (IOStateReportValues*) &(__info->elem[__info->curr_state].values); \ | |
293 | if (__info->update_ts) \ | |
294 | __rep->upticks += (changeTime) - __info->update_ts; \ | |
295 | __info->elem[(newStateIdx)].timestamp = (changeTime); \ | |
296 | __rep = (IOStateReportValues*) &(__info->elem[(newStateIdx)].values); \ | |
297 | __rep->intransitions++; \ | |
298 | __info->curr_state = (newStateIdx); \ | |
299 | __info->update_ts = (changeTime); \ | |
300 | } \ | |
301 | } while(0) | |
302 | ||
303 | /* | |
fe8ab488 A |
304 | * Prepare a StateReport for |
305 | * IOService::updateReport(kIOReportCopyChannelData...) | |
39236c6e A |
306 | * |
307 | * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() | |
308 | * uint64_t currentTime - current timestamp | |
309 | * void* ptr2cpy - filled in with pointer to buffer to be copied out | |
310 | * size_t size2cpy - filled in with the size of the buffer to copy out | |
311 | */ | |
312 | #define STATEREPORT_UPDATEPREP(state_buf, currentTime, ptr2cpy, size2cpy) \ | |
313 | do { \ | |
314 | IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \ | |
315 | IOReportElement *__elem; \ | |
316 | IOStateReportValues *__state; \ | |
317 | (size2cpy) = __info->elem[0].channel_type.nelements * sizeof(IOReportElement); \ | |
318 | (ptr2cpy) = (void *) &__info->elem[0]; \ | |
319 | if (__info->update_ts) { \ | |
320 | __elem = &__info->elem[__info->curr_state]; \ | |
321 | __state = (IOStateReportValues *)&__elem->values; \ | |
322 | __elem->timestamp = (currentTime); \ | |
323 | __state->upticks += (currentTime) - __info->update_ts; \ | |
324 | __info->update_ts = (currentTime); \ | |
325 | } \ | |
326 | } while(0) | |
327 | ||
328 | /* | |
fe8ab488 | 329 | * Update the result field received as a parameter for kIOReportGetDimensions & |
39236c6e A |
330 | * kIOReportCopyChannelData actions. |
331 | * | |
332 | * void* state_buf - memory initialized by STATEREPORT_INIT() | |
333 | * IOReportConfigureAction action - configure/updateReport() 'action' | |
334 | * void* result - configure/updateReport() 'result' | |
335 | */ | |
336 | ||
337 | #define STATEREPORT_UPDATERES(state_buf, action, result) \ | |
338 | do { \ | |
339 | IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \ | |
340 | IOReportElement *__elem; \ | |
341 | int *__nElements = (int *)(result); \ | |
342 | if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \ | |
343 | __elem = &(__info->elem[0]); \ | |
344 | *__nElements += __elem->channel_type.nelements; \ | |
345 | } \ | |
346 | } while (0) | |
347 | ||
348 | ||
39236c6e | 349 | /* |
fe8ab488 | 350 | * Get the 64-bit channel ID of a StateReport. |
39236c6e A |
351 | * |
352 | * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() | |
353 | */ | |
39236c6e A |
354 | #define STATEREPORT_GETCHID(state_buf) \ |
355 | (((IOStateReportInfo *)(state_buf))->elem[0].channel_id) | |
356 | ||
357 | /* | |
fe8ab488 A |
358 | * Get the IOReportChannelType of a StateReport. |
359 | * | |
360 | * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() | |
361 | */ | |
362 | #define STATEREPORT_GETCHTYPE(state_buf) \ | |
363 | (*(uint64_t*)&(((IOStateReportInfo *)(state_buf))->elem[0].channel_type)) | |
364 | ||
365 | /* | |
366 | * Get the number of transitions into a given state. | |
39236c6e A |
367 | * |
368 | * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() | |
369 | * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue | |
370 | * | |
371 | */ | |
39236c6e A |
372 | #define STATEREPORT_GETTRANSITIONS(state_buf, stateIdx) \ |
373 | (((stateIdx) < ((IOStateReportInfo *)(state_buf))->elem[0].channel_type.nelements) \ | |
374 | ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->intransitions \ | |
375 | : kIOReportInvalidValue) | |
376 | ||
377 | /* | |
fe8ab488 | 378 | * Get the total number of ticks spent in a given state. |
39236c6e A |
379 | * |
380 | * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() | |
381 | * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue | |
382 | */ | |
39236c6e A |
383 | #define STATEREPORT_GETTICKS(state_buf, stateIdx) \ |
384 | (((stateIdx) < ((IOStateReportInfo*)(state_buf))->elem[0].channel_type.nelements) \ | |
385 | ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->upticks \ | |
386 | : kIOReportInvalidValue) | |
387 | ||
388 | ||
fe8ab488 A |
389 | /* ----- Reporting an Array of Integers (SimpleArrayReport) ----- */ |
390 | ||
391 | /* | |
392 | * Determine the buffer size for a SimpleArrayReport. | |
393 | * | |
394 | * int nValues - number of values to be reported | |
395 | */ | |
396 | ||
397 | #define SIMPLEARRAY_BUFSIZE(nValues) \ | |
398 | ((((nValues)/IOR_VALUES_PER_ELEMENT) + (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1:0)) \ | |
399 | * sizeof(IOReportElement)) | |
400 | ||
401 | /* | |
402 | * Initialize a buffer for use as a SimpleArrayReport. | |
403 | * | |
404 | * int nValues - number of elements to be reported | |
405 | * void* buf - ptr to SIMPLEARRAY_BUFSIZE(nValues) bytes | |
406 | * size_t bufSize - sanity check of buffer's size | |
407 | * uint64_t providerID - registry Entry ID of the reporting service | |
408 | * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID() | |
409 | * IOReportCategories categories - categories of this channel | |
410 | * | |
411 | * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT() | |
412 | * and, if that returns, fills the buffer with 0xbadcafe. | |
413 | */ | |
414 | ||
415 | #define SIMPLEARRAY_INIT(nValues, buf, bufSize, providerID, channelID, cats) \ | |
416 | do { \ | |
417 | IOSimpleArrayReportValues *__rep; \ | |
418 | IOReportElement *__elem; \ | |
419 | uint32_t __nElems = (((nValues) / IOR_VALUES_PER_ELEMENT) + \ | |
420 | (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1 : 0)); \ | |
421 | if ((bufSize) >= SIMPLEARRAY_BUFSIZE(nValues)) { \ | |
422 | for (unsigned __no = 0; __no < __nElems; __no++) { \ | |
423 | __elem = &(((IOReportElement *)(buf))[__no]); \ | |
424 | __rep = (IOSimpleArrayReportValues *) &(__elem->values); \ | |
425 | __elem->channel_id = (channelID); \ | |
426 | __elem->provider_id = (providerID); \ | |
427 | __elem->channel_type.report_format = kIOReportFormatSimpleArray; \ | |
428 | __elem->channel_type.reserved = 0; \ | |
429 | __elem->channel_type.categories = (cats); \ | |
430 | __elem->channel_type.nelements = (__nElems); \ | |
431 | __elem->channel_type.element_idx = __no; \ | |
432 | __elem->timestamp = 0; \ | |
433 | __rep->simple_values[0] = kIOReportInvalidIntValue; \ | |
434 | __rep->simple_values[1] = kIOReportInvalidIntValue; \ | |
435 | __rep->simple_values[2] = kIOReportInvalidIntValue; \ | |
436 | __rep->simple_values[3] = kIOReportInvalidIntValue; \ | |
437 | } \ | |
438 | } \ | |
439 | else { \ | |
440 | IOREPORT_ABORT("bufSize is smaller than the required size\n"); \ | |
441 | __POLLUTE_BUF((buf), (bufSize)); \ | |
442 | } \ | |
443 | } while(0) | |
444 | ||
445 | ||
446 | /* SimpleArrayReport helpers */ | |
447 | ||
448 | #define __SA_FINDREP(array_buf, idx) \ | |
449 | IOSimpleArrayReportValues *__rep; \ | |
450 | IOReportElement *__elem; \ | |
451 | unsigned __elemIdx = (idx) / IOR_VALUES_PER_ELEMENT; \ | |
452 | unsigned __valueIdx = (idx) % IOR_VALUES_PER_ELEMENT; \ | |
453 | __elem = &(((IOReportElement *)(array_buf))[0]); \ | |
454 | if (__elemIdx < __elem->channel_type.nelements) { \ | |
455 | __elem = &(((IOReportElement *)(array_buf))[__elemIdx]); \ | |
456 | __rep = (IOSimpleArrayReportValues *) &(__elem->values); \ | |
457 | ||
458 | #define __SA_MAXINDEX(array_buf) \ | |
459 | ((((IOReportElement*)(array_buf))->channel_type.nelements) \ | |
460 | * IOR_VALUES_PER_ELEMENT) - 1 | |
461 | ||
462 | /* | |
463 | * Set a value at a specified index in a SimpleArrayReport. | |
464 | * | |
465 | * void* array_bufbuf - ptr to memory initialized by SIMPLEARRAY_INIT() | |
466 | * unsigned idx - array index, out of bounds -> no-op | |
467 | * uint64_t newValue - new value to be stored at array[idx] | |
468 | */ | |
469 | #define SIMPLEARRAY_SETVALUE(array_buf, idx, newValue) \ | |
470 | do { \ | |
471 | __SA_FINDREP((array_buf), (idx)) \ | |
472 | __rep->simple_values[__valueIdx] = (newValue); \ | |
473 | } \ | |
474 | } while(0) | |
475 | ||
476 | /* | |
477 | * Increment an array value within a SimpleArrayReport. | |
478 | * | |
479 | * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() | |
480 | * unsigned idx - array index to increment, out of bounds -> no-op | |
481 | * int64_t value - amount by which to increment array[idx] | |
482 | */ | |
483 | #define SIMPLEARRAY_INCREMENTVALUE(array_buf, idx, value) \ | |
484 | do { \ | |
485 | __SA_FINDREP((array_buf), (idx)) \ | |
486 | __rep->simple_values[__valueIdx] += (value); \ | |
487 | } \ | |
488 | } while(0) | |
489 | ||
490 | ||
491 | /* | |
492 | * Prepare a SimpleArrayReport for | |
493 | * IOService::updateReport(kIOReportCopyChannelData...) | |
494 | * | |
495 | * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() | |
496 | * void* ptr2cpy - filled in with pointer to buffer to be copied out | |
497 | * size_t size2cpy - filled in with the size of the buffer to copy out | |
498 | */ | |
499 | ||
500 | #define SIMPLEARRAY_UPDATEPREP(array_buf, ptr2cpy, size2cpy) \ | |
501 | do { \ | |
502 | IOReportElement *__elem; \ | |
503 | __elem = &(((IOReportElement *)(array_buf))[0]); \ | |
504 | (ptr2cpy) = (void *) (array_buf); \ | |
505 | (size2cpy) = __elem->channel_type.nelements * sizeof(IOReportElement); \ | |
506 | } while(0) | |
507 | ||
508 | ||
509 | /* | |
510 | * Update the result field received as a parameter for kIOReportGetDimensions & | |
511 | * kIOReportCopyChannelData actions. | |
512 | * | |
513 | * void* array_buf - memory initialized by SIMPLEARRAY_INIT() | |
514 | * IOReportConfigureAction action - configure/updateReport() 'action' | |
515 | * void* result - configure/updateReport() 'result' | |
516 | */ | |
517 | ||
518 | #define SIMPLEARRAY_UPDATERES(array_buf, action, result) \ | |
39236c6e | 519 | do { \ |
fe8ab488 A |
520 | IOReportElement *__elem; \ |
521 | int *__nElements = (int *)(result); \ | |
522 | __elem = &(((IOReportElement *)(array_buf))[0]); \ | |
523 | if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \ | |
524 | *__nElements += __elem->channel_type.nelements; \ | |
525 | } \ | |
39236c6e A |
526 | } while (0) |
527 | ||
fe8ab488 A |
528 | |
529 | /* | |
530 | * Get the 64-bit channel ID of a SimpleArrayReport. | |
531 | * | |
532 | * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() | |
533 | */ | |
534 | #define SIMPLEARRAY_GETCHID(array_buf) \ | |
535 | (((IOReportElement *)(array_buf))->channel_id) | |
536 | ||
537 | ||
538 | /* | |
539 | * Get the IOReportChannelType of a SimpleArrayReport. | |
540 | * | |
541 | * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() | |
542 | */ | |
543 | #define SIMPLEARRAY_GETCHTYPE(array_buf) \ | |
544 | (*(uint64_t*)&(((IOReportElement *)(array_buf))->channel_type)) | |
545 | ||
546 | /* | |
547 | * Get a value from a SimpleArrayReport. | |
548 | * | |
549 | * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() | |
550 | * unsigned idx - index of the value, out of bounds -> kIOReportInvalidValue | |
551 | */ | |
552 | #define SIMPLEARRAY_GETVALUE(array_buf, idx) \ | |
553 | (((idx) > __SA_MAXINDEX(array_buf) || (idx) < 0) ? kIOReportInvalidIntValue : \ | |
554 | ((IOSimpleArrayReportValues*)&( \ | |
555 | ((IOReportElement*)(array_buf))[(idx) / IOR_VALUES_PER_ELEMENT].values)) \ | |
556 | ->simple_values[(idx) % IOR_VALUES_PER_ELEMENT]) | |
557 | ||
558 | ||
559 | /* generic utilities */ | |
560 | ||
561 | #define __POLLUTE_BUF(buf, bufSize) \ | |
562 | do { \ | |
563 | int __cnt = (bufSize)/sizeof(uint32_t); \ | |
564 | while (--__cnt >= 0) \ | |
565 | ((uint32_t*)(buf))[__cnt] = 0xbadcafe; \ | |
566 | } while (0) | |
567 | ||
39236c6e A |
568 | #ifdef __cplusplus |
569 | } | |
570 | #endif | |
571 | ||
572 | #endif // _IOREPORT_MACROS_H_ | |
573 | ||
574 |