]>
git.saurik.com Git - apple/xnu.git/blob - iokit/IOKit/IOReportMacros.h
2 * Copyright (c) 2012-2020 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #ifndef _IOREPORT_MACROS_H_
30 #define _IOREPORT_MACROS_H_
32 #include "IOReportTypes.h"
39 #ifndef IOREPORT_ABORT
40 #define IOREPORT_ABORT panic
46 * These macros allow non-I/O Kit software to generate IOReporting
47 * reports. Clients must prevent concurrent access to any given
48 * report buffer from multiple threads.
50 * While these macros allow non-I/O Kit software to participate
51 * in IOReporting, an IOService instance must lend its driver ID,
52 * respond to the appropriate IOService overrides, and shuttle
53 * data back and forth. In some cases, it may be useful to have
54 * the I/O Kit driver initialize the report buffer with the
59 /* ----- Reporting Single Integers (SimpleReport) ----- */
62 * The buffer size required for a SimpleReport.
65 #define SIMPLEREPORT_BUFSIZE (sizeof(IOReportElement))
69 * Initialize a buffer to hold a SimpleReport.
71 * void* buffer - ptr to SIMPLEREPORT_BUFSIZE bytes
72 * size_t bufSize - sanity check of buffer's size
73 * uint64_t providerID - registry Entry ID of the reporting service
74 * uint64_t channelID - the report's channel ID
75 * IOReportCategories categories - categories of this channel
77 * If the buffer is not of sufficient size, the macro calls IOREPORT_ABORT().
78 * If that returns, the buffer is left full of '&'.
81 #define SIMPLEREPORT_INIT(buf, bufSize, providerID, channelID, cats) \
83 memset((buf), '&', (bufSize)); \
84 IOReportElement *__elem = (IOReportElement *)(buf); \
85 IOSimpleReportValues *__vals; \
86 if ((bufSize) >= SIMPLEREPORT_BUFSIZE) { \
87 __elem->provider_id = (providerID); \
88 __elem->channel_id = (channelID); \
89 __elem->channel_type.report_format = kIOReportFormatSimple; \
90 __elem->channel_type.reserved = 0; \
91 __elem->channel_type.categories = (cats); \
92 __elem->channel_type.nelements = 1; \
93 __elem->channel_type.element_idx = 0; \
94 __elem->timestamp = 0; \
95 __vals = (IOSimpleReportValues*)&__elem->values; \
96 __vals->simple_value = kIOReportInvalidIntValue; \
99 IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
105 * Set a SimpleReport to a new value.
107 * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
108 * int64_t new_value - new value for the report
111 #define SIMPLEREPORT_SETVALUE(simp_buf, new_value) \
113 IOReportElement *__elem = (IOReportElement *)(simp_buf); \
114 IOSimpleReportValues *__vals; \
115 __vals = (IOSimpleReportValues*)&__elem->values; \
116 __vals->simple_value = (new_value); \
121 * Increment the value of a SimpleReport.
123 * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
124 * int64_t increment - amount by which to increment the value
126 #define SIMPLEREPORT_INCREMENTVALUE(simp_buf, new_value) \
128 IOReportElement *__elem = (IOReportElement *)(simp_buf); \
129 IOSimpleReportValues *__vals; \
130 __vals = (IOSimpleReportValues*)&__elem->values; \
131 __vals->simple_value += (new_value); \
136 * Prepare a SimpleReport for
137 * IOService::updateReport(kIOReportCopyChannelData...)
139 * void* simp_buf - Ptr to memory updated by SIMPLEREPORT_SETVALUE()
140 * void* ptr2cpy - On return, 'ptr2cpy' points to the memory that needs to be
141 * copied for kIOReportCopyChannelData.
142 * size_t size2cpy - On return, 'size2cpy' is set to the size of the report
143 * data that needs to be copied for kIOReportCopyChannelData.
146 #define SIMPLEREPORT_UPDATEPREP(simp_buf, ptr2cpy, size2cpy) \
148 (ptr2cpy) = (simp_buf); \
149 (size2cpy) = sizeof(IOReportElement); \
154 * Update the result field received as a parameter for
155 * kIOReportGetDimensions & kIOReportCopyChannelData actions.
157 * IOReportConfigureAction action - configure/updateReport() 'action' param
158 * void* result - configure/updateReport() 'result' param
161 #define SIMPLEREPORT_UPDATERES(action, result) \
163 if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
164 int *__nElements = (int *)(result); \
171 * Get the 64-bit channel ID of a SimpleReport.
173 * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
176 #define SIMPLEREPORT_GETCHID(simp_buf) \
177 (((IOReportElement *)(simp_buf))->channel_id)
180 * Get the IOReportChannelType of a SimpleReport.
182 * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
185 #define SIMPLEREPORT_GETCHTYPE(simp_buf) \
186 (*(uint64_t*)&(((IOReportElement *)(simp_buf))->channel_type))
190 * Get the integer value of a SimpleReport.
192 * void* simp_buf - memory initialized by SIMPLEREPORT_INIT()
195 #define SIMPLEREPORT_GETVALUE(simp_buf) \
196 (((IOSimpleReportValues*)&(((IOReportElement*)(simp_buf))->values)) \
200 /* ----- State Machine Reporting (StateReport) ----- */
202 // Internal struct for StateReport
206 IOReportElement elem
[]; // Array of elements
210 * Determine the size required for a StateReport buffer.
212 * int nstates - number of states to be reported
214 #define STATEREPORT_BUFSIZE(nstates) \
215 (sizeof(IOStateReportInfo) + (nstates) * sizeof(IOReportElement))
219 * Initialize a StateReport buffer.
221 * uint16_t nstates - number of states to be reported
222 * void* buffer - ptr to STATEREPORT_BUFSIZE(nstates) bytes
223 * size_t bufSize - sanity check of buffer's size
224 * uint64_t providerID - registry Entry ID of the reporting service
225 * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID()
226 * IOReportCategories categories - categories of this channel
228 * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT.
229 * If that returns, the buffer is left full of '&'.
231 #define STATEREPORT_INIT(nstates, buf, bufSize, providerID, channelID, cats) \
233 memset((buf), '&', (bufSize)); \
234 IOStateReportInfo *__info = (IOStateReportInfo *)(buf); \
235 IOStateReportValues *__rep; \
236 IOReportElement *__elem; \
237 if ((bufSize) >= STATEREPORT_BUFSIZE(nstates)) { \
238 for (uint16_t __no = 0; __no < (nstates); __no++) { \
239 __elem = &(__info->elem[__no]); \
240 __rep = (IOStateReportValues *) &(__elem->values); \
241 __elem->provider_id = (providerID); \
242 __elem->channel_id = (channelID); \
243 __elem->channel_type.report_format = kIOReportFormatState; \
244 __elem->channel_type.reserved = 0; \
245 __elem->channel_type.categories = (cats); \
246 __elem->channel_type.nelements = (nstates); \
247 __elem->channel_type.element_idx = __no; \
248 __elem->timestamp = 0; \
249 __rep->state_id = __no; \
250 __rep->intransitions = 0; \
251 __rep->upticks = 0; \
252 __rep->last_intransition = 0; \
254 __info->curr_state = 0; \
255 __info->update_ts = 0; \
258 IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
263 * Initialize the state id field of a state with the specified value. By
264 * default, STATEREPORT_INIT() initializes the state IDs with the index of
265 * that state. This macro can be used to provide a more descriptive state id.
267 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
268 * unsigned stateIdx - index of the state, out of bounds -> no-op
269 * uint64_t stateID - new state id, see IOREPORT_MAKEID()
271 #define STATEREPORT_SETSTATEID(state_buf, stateIdx, stateID) \
273 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
274 IOStateReportValues *__rep; \
275 if ((stateIdx) < __info->elem[0].channel_type.nelements) { \
276 __rep = (IOStateReportValues*) &(__info->elem[(stateIdx)].values); \
277 __rep->state_id = (stateID); \
283 * Set the state of a StateReport.
285 * void* state_buf - pointer to memory initialized by STATEREPORT_INIT()
286 * unsigned newStateIdx - index of new state, out of bounds -> no-op
287 * uint64_t changeTime - time at which the transition occurred
289 #define STATEREPORT_SETSTATE(state_buf, newStateIdx, changeTime) \
291 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
292 IOStateReportValues *__rep; \
293 if ((newStateIdx) < __info->elem[0].channel_type.nelements ) { \
294 __rep = (IOStateReportValues*) &(__info->elem[__info->curr_state].values); \
295 if (__info->update_ts) \
296 __rep->upticks += (changeTime) - __info->update_ts; \
297 __info->elem[(newStateIdx)].timestamp = (changeTime); \
298 __rep = (IOStateReportValues*) &(__info->elem[(newStateIdx)].values); \
299 __rep->intransitions++; \
300 __info->curr_state = (newStateIdx); \
301 __info->update_ts = (changeTime); \
306 * Prepare a StateReport for
307 * IOService::updateReport(kIOReportCopyChannelData...)
309 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
310 * uint64_t currentTime - current timestamp
311 * void* ptr2cpy - filled in with pointer to buffer to be copied out
312 * size_t size2cpy - filled in with the size of the buffer to copy out
314 #define STATEREPORT_UPDATEPREP(state_buf, currentTime, ptr2cpy, size2cpy) \
316 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
317 IOReportElement *__elem; \
318 IOStateReportValues *__state; \
319 (size2cpy) = __info->elem[0].channel_type.nelements * sizeof(IOReportElement); \
320 (ptr2cpy) = (void *) &__info->elem[0]; \
321 if (__info->update_ts) { \
322 __elem = &__info->elem[__info->curr_state]; \
323 __state = (IOStateReportValues *)&__elem->values; \
324 __elem->timestamp = (currentTime); \
325 __state->upticks += (currentTime) - __info->update_ts; \
326 __info->update_ts = (currentTime); \
331 * Update the result field received as a parameter for kIOReportGetDimensions &
332 * kIOReportCopyChannelData actions.
334 * void* state_buf - memory initialized by STATEREPORT_INIT()
335 * IOReportConfigureAction action - configure/updateReport() 'action'
336 * void* result - configure/updateReport() 'result'
339 #define STATEREPORT_UPDATERES(state_buf, action, result) \
341 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
342 IOReportElement *__elem; \
343 int *__nElements = (int *)(result); \
344 if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
345 __elem = &(__info->elem[0]); \
346 *__nElements += __elem->channel_type.nelements; \
352 * Get the 64-bit channel ID of a StateReport.
354 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
356 #define STATEREPORT_GETCHID(state_buf) \
357 (((IOStateReportInfo *)(state_buf))->elem[0].channel_id)
360 * Get the IOReportChannelType of a StateReport.
362 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
364 #define STATEREPORT_GETCHTYPE(state_buf) \
365 (*(uint64_t*)&(((IOStateReportInfo *)(state_buf))->elem[0].channel_type))
368 * Get the number of transitions into a given state.
370 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
371 * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue
374 #define STATEREPORT_GETTRANSITIONS(state_buf, stateIdx) \
375 (((stateIdx) < ((IOStateReportInfo *)(state_buf))->elem[0].channel_type.nelements) \
376 ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->intransitions \
377 : kIOReportInvalidValue)
380 * Get the total number of ticks spent in a given state.
382 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
383 * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue
385 #define STATEREPORT_GETTICKS(state_buf, stateIdx) \
386 (((stateIdx) < ((IOStateReportInfo*)(state_buf))->elem[0].channel_type.nelements) \
387 ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->upticks \
388 : kIOReportInvalidValue)
391 /* ----- Reporting an Array of Integers (SimpleArrayReport) ----- */
394 * Determine the buffer size for a SimpleArrayReport.
396 * int nValues - number of values to be reported
399 #define SIMPLEARRAY_BUFSIZE(nValues) \
400 ((((nValues)/IOR_VALUES_PER_ELEMENT) + (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1:0)) \
401 * sizeof(IOReportElement))
404 * Initialize a buffer for use as a SimpleArrayReport.
406 * int nValues - number of elements to be reported
407 * void* buf - ptr to SIMPLEARRAY_BUFSIZE(nValues) bytes
408 * size_t bufSize - sanity check of buffer's size
409 * uint64_t providerID - registry Entry ID of the reporting service
410 * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID()
411 * IOReportCategories categories - categories of this channel
413 * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT().
414 * If that returns, the buffer is left full of '&'.
417 #define SIMPLEARRAY_INIT(nValues, buf, bufSize, providerID, channelID, cats) \
419 memset((buf), '&', (bufSize)); \
420 IOSimpleArrayReportValues *__rep; \
421 IOReportElement *__elem; \
422 uint32_t __nElems = (((nValues) / IOR_VALUES_PER_ELEMENT) + \
423 (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1 : 0)); \
424 if ((bufSize) >= SIMPLEARRAY_BUFSIZE(nValues)) { \
425 for (unsigned __no = 0; __no < __nElems; __no++) { \
426 __elem = &(((IOReportElement *)(buf))[__no]); \
427 __rep = (IOSimpleArrayReportValues *) &(__elem->values); \
428 __elem->provider_id = (providerID); \
429 __elem->channel_id = (channelID); \
430 __elem->channel_type.report_format = kIOReportFormatSimpleArray; \
431 __elem->channel_type.reserved = 0; \
432 __elem->channel_type.categories = (cats); \
433 __elem->channel_type.nelements = (__nElems); \
434 __elem->channel_type.element_idx = __no; \
435 __elem->timestamp = 0; \
436 __rep->simple_values[0] = kIOReportInvalidIntValue; \
437 __rep->simple_values[1] = kIOReportInvalidIntValue; \
438 __rep->simple_values[2] = kIOReportInvalidIntValue; \
439 __rep->simple_values[3] = kIOReportInvalidIntValue; \
443 IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
448 /* SimpleArrayReport helpers */
450 #define __SA_FINDREP(array_buf, idx) \
451 IOSimpleArrayReportValues *__rep; \
452 IOReportElement *__elem; \
453 unsigned __elemIdx = (idx) / IOR_VALUES_PER_ELEMENT; \
454 unsigned __valueIdx = (idx) % IOR_VALUES_PER_ELEMENT; \
455 __elem = &(((IOReportElement *)(array_buf))[0]); \
456 if (__elemIdx < __elem->channel_type.nelements) { \
457 __elem = &(((IOReportElement *)(array_buf))[__elemIdx]); \
458 __rep = (IOSimpleArrayReportValues *) &(__elem->values); \
460 #define __SA_MAXINDEX(array_buf) \
461 ((((IOReportElement*)(array_buf))->channel_type.nelements) \
462 * IOR_VALUES_PER_ELEMENT) - 1
465 * Set a value at a specified index in a SimpleArrayReport.
467 * void* array_bufbuf - ptr to memory initialized by SIMPLEARRAY_INIT()
468 * unsigned idx - array index, out of bounds -> no-op
469 * uint64_t newValue - new value to be stored at array[idx]
471 #define SIMPLEARRAY_SETVALUE(array_buf, idx, newValue) \
473 __SA_FINDREP((array_buf), (idx)) \
474 __rep->simple_values[__valueIdx] = (newValue); \
479 * Increment an array value within a SimpleArrayReport.
481 * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
482 * unsigned idx - array index to increment, out of bounds -> no-op
483 * int64_t value - amount by which to increment array[idx]
485 #define SIMPLEARRAY_INCREMENTVALUE(array_buf, idx, value) \
487 __SA_FINDREP((array_buf), (idx)) \
488 __rep->simple_values[__valueIdx] += (value); \
494 * Prepare a SimpleArrayReport for
495 * IOService::updateReport(kIOReportCopyChannelData...)
497 * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
498 * void* ptr2cpy - filled in with pointer to buffer to be copied out
499 * size_t size2cpy - filled in with the size of the buffer to copy out
502 #define SIMPLEARRAY_UPDATEPREP(array_buf, ptr2cpy, size2cpy) \
504 IOReportElement *__elem; \
505 __elem = &(((IOReportElement *)(array_buf))[0]); \
506 (ptr2cpy) = (void *) (array_buf); \
507 (size2cpy) = __elem->channel_type.nelements * sizeof(IOReportElement); \
512 * Update the result field received as a parameter for kIOReportGetDimensions &
513 * kIOReportCopyChannelData actions.
515 * void* array_buf - memory initialized by SIMPLEARRAY_INIT()
516 * IOReportConfigureAction action - configure/updateReport() 'action'
517 * void* result - configure/updateReport() 'result'
520 #define SIMPLEARRAY_UPDATERES(array_buf, action, result) \
522 IOReportElement *__elem; \
523 int *__nElements = (int *)(result); \
524 __elem = &(((IOReportElement *)(array_buf))[0]); \
525 if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
526 *__nElements += __elem->channel_type.nelements; \
532 * Get the 64-bit channel ID of a SimpleArrayReport.
534 * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
536 #define SIMPLEARRAY_GETCHID(array_buf) \
537 (((IOReportElement *)(array_buf))->channel_id)
541 * Get the IOReportChannelType of a SimpleArrayReport.
543 * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
545 #define SIMPLEARRAY_GETCHTYPE(array_buf) \
546 (*(uint64_t*)&(((IOReportElement *)(array_buf))->channel_type))
549 * Get a value from a SimpleArrayReport.
551 * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT()
552 * unsigned idx - index of the value, out of bounds -> kIOReportInvalidValue
554 #define SIMPLEARRAY_GETVALUE(array_buf, idx) \
555 (((idx) > __SA_MAXINDEX(array_buf) || (idx) < 0) ? kIOReportInvalidIntValue : \
556 ((IOSimpleArrayReportValues*)&( \
557 ((IOReportElement*)(array_buf))[(idx) / IOR_VALUES_PER_ELEMENT].values)) \
558 ->simple_values[(idx) % IOR_VALUES_PER_ELEMENT])
561 /* ----- Histogram Reporting (HistogramReport) ----- */
563 // Internal struct for HistogramReport
566 IOReportElement elem
[]; // Array of elements
570 * Determine the size required for a HistogramReport buffer.
572 * int nbuckets - number of buckets in the histogram
574 #define HISTREPORT_BUFSIZE(nbuckets) \
575 (sizeof(IOHistReportInfo) + ((nbuckets) * sizeof(IOReportElement)))
578 * Initialize a HistogramReport buffer. Supports only linear scale histogram.
580 * uint16_t nbuckets - number of buckets data is combined into
581 * uint32_t bucketWidth - size of each bucket
582 * void* buffer - ptr to HISTREPORT_BUFSIZE(nbuckets) bytes
583 * size_t bufSize - sanity check of buffer's size
584 * uint64_t providerID - registry Entry ID of the reporting service
585 * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID()
586 * IOReportCategories categories - categories of this channel
588 * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT.
589 * If that returns, the buffer is left full of '&'.
591 #define HISTREPORT_INIT(nbuckets, bktSize, buf, bufSize, providerID, channelID, cats) \
593 memset((buf), '&', (bufSize)); \
594 IOHistReportInfo *__info = (IOHistReportInfo *)(buf); \
595 IOReportElement *__elem; \
596 IOHistogramReportValues *__rep; \
597 if ((bufSize) >= HISTREPORT_BUFSIZE(nbuckets)) { \
598 __info->bucketWidth = (bktSize); \
599 for (uint16_t __no = 0; __no < (nbuckets); __no++) { \
600 __elem = &(__info->elem[__no]); \
601 __rep = (IOHistogramReportValues *) &(__elem->values); \
602 __elem->provider_id = (providerID); \
603 __elem->channel_id = (channelID); \
604 __elem->channel_type.report_format = kIOReportFormatHistogram; \
605 __elem->channel_type.reserved = 0; \
606 __elem->channel_type.categories = (cats); \
607 __elem->channel_type.nelements = (nbuckets); \
608 __elem->channel_type.element_idx = __no; \
609 __elem->timestamp = 0; \
610 memset(__rep, '\0', sizeof(IOHistogramReportValues)); \
614 IOREPORT_ABORT("bufSize is smaller than the required size\n"); \
619 * Update histogram with a new value.
622 * void* hist_buf - pointer to memory initialized by HISTREPORT_INIT()
623 * int64_t value - new value to add to the histogram
625 #define HISTREPORT_TALLYVALUE(hist_buf, value) \
627 IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \
628 IOReportElement *__elem; \
629 IOHistogramReportValues *__rep; \
630 for (unsigned __no = 0; __no < __info->elem[0].channel_type.nelements; __no++) { \
631 if ((value) <= __info->bucketWidth * (__no+1)) { \
632 __elem = &(__info->elem[__no]); \
633 __rep = (IOHistogramReportValues *) &(__elem->values); \
634 if (__rep->bucket_hits == 0) { \
635 __rep->bucket_min = __rep->bucket_max = (value); \
637 else if ((value) < __rep->bucket_min) { \
638 __rep->bucket_min = (value); \
640 else if ((value) > __rep->bucket_max) { \
641 __rep->bucket_max = (value); \
643 __rep->bucket_sum += (value); \
644 __rep->bucket_hits++; \
651 * Prepare a HistogramReport for
652 * IOService::updateReport(kIOReportCopyChannelData...)
654 * void* array_buf - ptr to memory initialized by HISTREPORT_INIT()
655 * void* ptr2cpy - filled in with pointer to buffer to be copied out
656 * size_t size2cpy - filled in with the size of the buffer to copy out
659 #define HISTREPORT_UPDATEPREP(hist_buf, ptr2cpy, size2cpy) \
661 IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \
662 (size2cpy) = __info->elem[0].channel_type.nelements * sizeof(IOReportElement); \
663 (ptr2cpy) = (void *) &__info->elem[0]; \
668 * Update the result field received as a parameter for kIOReportGetDimensions &
669 * kIOReportCopyChannelData actions.
671 * void* array_buf - memory initialized by HISTREPORT_INIT()
672 * IOReportConfigureAction action - configure/updateReport() 'action'
673 * void* result - configure/updateReport() 'result'
676 #define HISTREPORT_UPDATERES(hist_buf, action, result) \
678 IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \
679 int *__nElements = (int *)(result); \
680 if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
681 *__nElements += __info->elem[0].channel_type.nelements; \
686 * Get the 64-bit channel ID of a HistogramReport.
688 * void* hist_buf - ptr to memory initialized by HISTREPORT_INIT()
690 #define HISTREPORT_GETCHID(hist_buf) \
691 (((IOHistReportInfo *)(hist_buf))->elem[0].channel_id)
694 * Get the IOReportChannelType of a HistogramReport.
696 * void* hist_buf - ptr to memory initialized by HISTREPORT_INIT()
698 #define HISTREPORT_GETCHTYPE(hist_buf) \
699 (*(uint64_t*)&(((IOHistReportInfo *)(hist_buf))->elem[0].channel_type))
705 #endif // _IOREPORT_MACROS_H_