X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/39236c6e673c41db228275375ab7fdb0f837b292..a39ff7e25e19b3a8c3020042a3872ca9ec9659f1:/iokit/IOKit/IOReportMacros.h diff --git a/iokit/IOKit/IOReportMacros.h b/iokit/IOKit/IOReportMacros.h index 24f7607ff..f3b5a015a 100644 --- a/iokit/IOKit/IOReportMacros.h +++ b/iokit/IOKit/IOReportMacros.h @@ -1,10 +1,8 @@ /* - * @APPLE_LICENSE_HEADER_START@ - * - * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved. + * Copyright (c) 2012-2014 Apple Computer, Inc. All Rights Reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -13,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -24,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ @@ -32,11 +30,16 @@ #define _IOREPORT_MACROS_H_ #include "IOReportTypes.h" +#include #ifdef __cplusplus extern "C" { #endif +#ifndef IOREPORT_ABORT +#define IOREPORT_ABORT panic +#endif + /* Background @@ -52,13 +55,18 @@ extern "C" { appropriate macro. */ + +/* ----- Reporting Single Integers (SimpleReport) ----- */ + /* - * Returns the buffer size required for a Simple report. + * The buffer size required for a SimpleReport. */ + #define SIMPLEREPORT_BUFSIZE (sizeof(IOReportElement)) + /* - * Initialize a buffer to hold a Simple (integer) report. + * Initialize a buffer to hold a SimpleReport. * * void* buffer - ptr to SIMPLEREPORT_BUFSIZE bytes * size_t bufSize - sanity check of buffer's size @@ -66,40 +74,40 @@ extern "C" { * uint64_t channelID - the report's channel ID * IOReportCategories categories - categories of this channel * - * If the buffer is not of sufficient size, the macro performs a - * null pointer reference to trigger a segfault. Then, the buffer is - * filled with 0xbadcafe. + * If the buffer is not of sufficient size, the macro calls IOREPORT_ABORT(). + * If that returns, the buffer is left full of '&'. */ -#define SIMPLEREPORT_INIT(buffer, bufSize, providerID, channelID, cats) \ + +#define SIMPLEREPORT_INIT(buf, bufSize, providerID, channelID, cats) \ do { \ - IOReportElement *__elem = (IOReportElement *)(buffer); \ + memset((buf), '&', (bufSize)); \ + IOReportElement *__elem = (IOReportElement *)(buf); \ IOSimpleReportValues *__vals; \ if ((bufSize) >= SIMPLEREPORT_BUFSIZE) { \ - __elem->channel_id = (channelID); \ __elem->provider_id = (providerID); \ + __elem->channel_id = (channelID); \ __elem->channel_type.report_format = kIOReportFormatSimple; \ __elem->channel_type.reserved = 0; \ __elem->channel_type.categories = (cats); \ __elem->channel_type.nelements = 1; \ __elem->channel_type.element_idx = 0; \ __elem->timestamp = 0; \ - __vals = (IOSimpleReportValues*)&__elem->values; \ - __vals->simple_value = kIOReportInvalidValue; \ + __vals = (IOSimpleReportValues*)&__elem->values; \ + __vals->simple_value = kIOReportInvalidIntValue; \ } \ else { \ - uint32_t *__nptr = NULL; \ - *__nptr = 1; \ - POLLUTE_BUF((buffer), (bufSize)); \ + IOREPORT_ABORT("bufSize is smaller than the required size\n"); \ } \ } while(0) /* - * Sets the SimpleReport channel to a new value. + * Set a SimpleReport to a new value. * - * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() - * uint64_t new_value - new value for the channel + * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() + * int64_t new_value - new value for the report */ + #define SIMPLEREPORT_SETVALUE(simp_buf, new_value) \ do { \ IOReportElement *__elem = (IOReportElement *)(simp_buf); \ @@ -108,8 +116,24 @@ do { \ __vals->simple_value = (new_value); \ } while(0) + +/* + * Increment the value of a SimpleReport. + * + * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() + * int64_t increment - amount by which to increment the value + */ +#define SIMPLEREPORT_INCREMENTVALUE(simp_buf, new_value) \ +do { \ + IOReportElement *__elem = (IOReportElement *)(simp_buf); \ + IOSimpleReportValues *__vals; \ + __vals = (IOSimpleReportValues*)&__elem->values; \ + __vals->simple_value += (new_value); \ +} while(0) + + /* - * Prepare simple report buffer for + * Prepare a SimpleReport for * IOService::updateReport(kIOReportCopyChannelData...) * * void* simp_buf - Ptr to memory updated by SIMPLEREPORT_SETVALUE() @@ -118,6 +142,7 @@ do { \ * size_t size2cpy - On return, 'size2cpy' is set to the size of the report * data that needs to be copied for kIOReportCopyChannelData. */ + #define SIMPLEREPORT_UPDATEPREP(simp_buf, ptr2cpy, size2cpy) \ do { \ (ptr2cpy) = (simp_buf); \ @@ -126,7 +151,7 @@ do { \ /* - * Updates the result field received as a parameter for + * Update the result field received as a parameter for * kIOReportGetDimensions & kIOReportCopyChannelData actions. * * IOReportConfigureAction action - configure/updateReport() 'action' param @@ -142,20 +167,39 @@ do { \ } while (0) - /* - * Returns the channel id from the buffer previously initialized by - * SIMPLEREPORT_INIT(). + * Get the 64-bit channel ID of a SimpleReport. * * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() */ #define SIMPLEREPORT_GETCHID(simp_buf) \ - (((IOReportElement *)(simp_buf))->channel_id); \ + (((IOReportElement *)(simp_buf))->channel_id) + +/* + * Get the IOReportChannelType of a SimpleReport. + * + * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() + */ + +#define SIMPLEREPORT_GETCHTYPE(simp_buf) \ + (*(uint64_t*)&(((IOReportElement *)(simp_buf))->channel_type)) + + +/* + * Get the integer value of a SimpleReport. + * + * void* simp_buf - memory initialized by SIMPLEREPORT_INIT() + */ +#define SIMPLEREPORT_GETVALUE(simp_buf) \ + (((IOSimpleReportValues*)&(((IOReportElement*)(simp_buf))->values)) \ + ->simple_value) -// Internal struct for State report buffer +/* ----- State Machine Reporting (StateReport) ----- */ + +// Internal struct for StateReport typedef struct { uint16_t curr_state; uint64_t update_ts; @@ -163,16 +207,16 @@ typedef struct { } IOStateReportInfo; /* - * Returns the size required to be allocated for using STATEREPORT_*() + * Determine the size required for a StateReport buffer. * - * int nstates - number of states for the intended channel + * int nstates - number of states to be reported */ #define STATEREPORT_BUFSIZE(nstates) \ (sizeof(IOStateReportInfo) + (nstates) * sizeof(IOReportElement)) /* - * Initializes a buffer so it can be used with STATEREPORT_*(). + * Initialize a StateReport buffer. * * int nstates - number of states to be reported * void* buffer - ptr to STATEREPORT_BUFSIZE(nstates) bytes @@ -181,12 +225,12 @@ typedef struct { * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID() * IOReportCategories categories - categories of this channel * - * If the buffer is not of sufficient size, the macro performs a - * null pointer reference to trigger a segfault. Then, the buffer is - * filled with 0xbadcafe. + * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT. + * If that returns, the buffer is left full of '&'. */ #define STATEREPORT_INIT(nstates, buf, bufSize, providerID, channelID, cats) \ do { \ + memset((buf), '&', (bufSize)); \ IOStateReportInfo *__info = (IOStateReportInfo *)(buf); \ IOStateReportValues *__rep; \ IOReportElement *__elem; \ @@ -194,8 +238,8 @@ do { \ for (unsigned __no = 0; __no < (nstates); __no++) { \ __elem = &(__info->elem[__no]); \ __rep = (IOStateReportValues *) &(__elem->values); \ - __elem->channel_id = (channelID); \ __elem->provider_id = (providerID); \ + __elem->channel_id = (channelID); \ __elem->channel_type.report_format = kIOReportFormatState; \ __elem->channel_type.reserved = 0; \ __elem->channel_type.categories = (cats); \ @@ -205,20 +249,19 @@ do { \ __rep->state_id = __no; \ __rep->intransitions = 0; \ __rep->upticks = 0; \ + __rep->last_intransition = 0; \ } \ __info->curr_state = 0; \ __info->update_ts = 0; \ } \ else { \ - int *__nptr = NULL; \ - *__nptr = 1; \ - POLLUTE_BUF((buf), (bufSize)); \ + IOREPORT_ABORT("bufSize is smaller than the required size\n"); \ } \ } while(0) /* - * Initializes the state id field of a state with the specified value. By - * default, STATEREPORT_INIT initializes the state id with the index of + * Initialize the state id field of a state with the specified value. By + * default, STATEREPORT_INIT() initializes the state IDs with the index of * that state. This macro can be used to provide a more descriptive state id. * * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() @@ -237,7 +280,7 @@ do { \ /* - * Set the state of a State report. + * Set the state of a StateReport. * * void* state_buf - pointer to memory initialized by STATEREPORT_INIT() * unsigned newStateIdx - index of new state, out of bounds -> no-op @@ -260,7 +303,8 @@ do { \ } while(0) /* - * Prepare StateReport for UpdateReport call + * Prepare a StateReport for + * IOService::updateReport(kIOReportCopyChannelData...) * * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() * uint64_t currentTime - current timestamp @@ -284,7 +328,7 @@ do { \ } while(0) /* - * Updates the result field received as a parameter for kIOReportGetDimensions & + * Update the result field received as a parameter for kIOReportGetDimensions & * kIOReportCopyChannelData actions. * * void* state_buf - memory initialized by STATEREPORT_INIT() @@ -304,49 +348,356 @@ do { \ } while (0) - /* - * Returns the channel id from the buffer previously initialized by STATEREPORT_INIT(). + * Get the 64-bit channel ID of a StateReport. * * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() */ - #define STATEREPORT_GETCHID(state_buf) \ (((IOStateReportInfo *)(state_buf))->elem[0].channel_id) /* - * Returns number of transitions occurred from the given state + * Get the IOReportChannelType of a StateReport. + * + * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() + */ +#define STATEREPORT_GETCHTYPE(state_buf) \ + (*(uint64_t*)&(((IOStateReportInfo *)(state_buf))->elem[0].channel_type)) + +/* + * Get the number of transitions into a given state. * * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue * */ - #define STATEREPORT_GETTRANSITIONS(state_buf, stateIdx) \ (((stateIdx) < ((IOStateReportInfo *)(state_buf))->elem[0].channel_type.nelements) \ ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->intransitions \ : kIOReportInvalidValue) /* - * Returns the total number of ticks spent in the given state. + * Get the total number of ticks spent in a given state. * * void* state_buf - ptr to memory initialized by STATEREPORT_INIT() * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue */ - #define STATEREPORT_GETTICKS(state_buf, stateIdx) \ (((stateIdx) < ((IOStateReportInfo*)(state_buf))->elem[0].channel_type.nelements) \ ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->upticks \ : kIOReportInvalidValue) -#define POLLUTE_BUF(buf, bufSize) \ +/* ----- Reporting an Array of Integers (SimpleArrayReport) ----- */ + +/* + * Determine the buffer size for a SimpleArrayReport. + * + * int nValues - number of values to be reported + */ + +#define SIMPLEARRAY_BUFSIZE(nValues) \ + ((((nValues)/IOR_VALUES_PER_ELEMENT) + (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1:0)) \ + * sizeof(IOReportElement)) + +/* + * Initialize a buffer for use as a SimpleArrayReport. + * + * int nValues - number of elements to be reported + * void* buf - ptr to SIMPLEARRAY_BUFSIZE(nValues) bytes + * size_t bufSize - sanity check of buffer's size + * uint64_t providerID - registry Entry ID of the reporting service + * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID() + * IOReportCategories categories - categories of this channel + * + * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT(). + * If that returns, the buffer is left full of '&'. + */ + +#define SIMPLEARRAY_INIT(nValues, buf, bufSize, providerID, channelID, cats) \ +do { \ + memset((buf), '&', (bufSize)); \ + IOSimpleArrayReportValues *__rep; \ + IOReportElement *__elem; \ + uint32_t __nElems = (((nValues) / IOR_VALUES_PER_ELEMENT) + \ + (((nValues) % IOR_VALUES_PER_ELEMENT) ? 1 : 0)); \ + if ((bufSize) >= SIMPLEARRAY_BUFSIZE(nValues)) { \ + for (unsigned __no = 0; __no < __nElems; __no++) { \ + __elem = &(((IOReportElement *)(buf))[__no]); \ + __rep = (IOSimpleArrayReportValues *) &(__elem->values); \ + __elem->provider_id = (providerID); \ + __elem->channel_id = (channelID); \ + __elem->channel_type.report_format = kIOReportFormatSimpleArray; \ + __elem->channel_type.reserved = 0; \ + __elem->channel_type.categories = (cats); \ + __elem->channel_type.nelements = (__nElems); \ + __elem->channel_type.element_idx = __no; \ + __elem->timestamp = 0; \ + __rep->simple_values[0] = kIOReportInvalidIntValue; \ + __rep->simple_values[1] = kIOReportInvalidIntValue; \ + __rep->simple_values[2] = kIOReportInvalidIntValue; \ + __rep->simple_values[3] = kIOReportInvalidIntValue; \ + } \ + } \ + else { \ + IOREPORT_ABORT("bufSize is smaller than the required size\n"); \ + } \ +} while(0) + + +/* SimpleArrayReport helpers */ + + #define __SA_FINDREP(array_buf, idx) \ + IOSimpleArrayReportValues *__rep; \ + IOReportElement *__elem; \ + unsigned __elemIdx = (idx) / IOR_VALUES_PER_ELEMENT; \ + unsigned __valueIdx = (idx) % IOR_VALUES_PER_ELEMENT; \ + __elem = &(((IOReportElement *)(array_buf))[0]); \ + if (__elemIdx < __elem->channel_type.nelements) { \ + __elem = &(((IOReportElement *)(array_buf))[__elemIdx]); \ + __rep = (IOSimpleArrayReportValues *) &(__elem->values); \ + + #define __SA_MAXINDEX(array_buf) \ + ((((IOReportElement*)(array_buf))->channel_type.nelements) \ + * IOR_VALUES_PER_ELEMENT) - 1 + +/* + * Set a value at a specified index in a SimpleArrayReport. + * + * void* array_bufbuf - ptr to memory initialized by SIMPLEARRAY_INIT() + * unsigned idx - array index, out of bounds -> no-op + * uint64_t newValue - new value to be stored at array[idx] + */ +#define SIMPLEARRAY_SETVALUE(array_buf, idx, newValue) \ +do { \ + __SA_FINDREP((array_buf), (idx)) \ + __rep->simple_values[__valueIdx] = (newValue); \ + } \ +} while(0) + +/* + * Increment an array value within a SimpleArrayReport. + * + * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() + * unsigned idx - array index to increment, out of bounds -> no-op + * int64_t value - amount by which to increment array[idx] + */ +#define SIMPLEARRAY_INCREMENTVALUE(array_buf, idx, value) \ +do { \ + __SA_FINDREP((array_buf), (idx)) \ + __rep->simple_values[__valueIdx] += (value); \ + } \ +} while(0) + + +/* + * Prepare a SimpleArrayReport for + * IOService::updateReport(kIOReportCopyChannelData...) + * + * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() + * void* ptr2cpy - filled in with pointer to buffer to be copied out + * size_t size2cpy - filled in with the size of the buffer to copy out + */ + +#define SIMPLEARRAY_UPDATEPREP(array_buf, ptr2cpy, size2cpy) \ +do { \ + IOReportElement *__elem; \ + __elem = &(((IOReportElement *)(array_buf))[0]); \ + (ptr2cpy) = (void *) (array_buf); \ + (size2cpy) = __elem->channel_type.nelements * sizeof(IOReportElement); \ +} while(0) + + +/* + * Update the result field received as a parameter for kIOReportGetDimensions & + * kIOReportCopyChannelData actions. + * + * void* array_buf - memory initialized by SIMPLEARRAY_INIT() + * IOReportConfigureAction action - configure/updateReport() 'action' + * void* result - configure/updateReport() 'result' + */ + +#define SIMPLEARRAY_UPDATERES(array_buf, action, result) \ +do { \ + IOReportElement *__elem; \ + int *__nElements = (int *)(result); \ + __elem = &(((IOReportElement *)(array_buf))[0]); \ + if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \ + *__nElements += __elem->channel_type.nelements; \ + } \ +} while (0) + + +/* + * Get the 64-bit channel ID of a SimpleArrayReport. + * + * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() + */ +#define SIMPLEARRAY_GETCHID(array_buf) \ + (((IOReportElement *)(array_buf))->channel_id) + + +/* + * Get the IOReportChannelType of a SimpleArrayReport. + * + * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT() + */ +#define SIMPLEARRAY_GETCHTYPE(array_buf) \ + (*(uint64_t*)&(((IOReportElement *)(array_buf))->channel_type)) + +/* + * Get a value from a SimpleArrayReport. + * + * void* array_buf - ptr to memory initialized by SIMPLEARRAY_INIT() + * unsigned idx - index of the value, out of bounds -> kIOReportInvalidValue + */ +#define SIMPLEARRAY_GETVALUE(array_buf, idx) \ + (((idx) > __SA_MAXINDEX(array_buf) || (idx) < 0) ? kIOReportInvalidIntValue : \ + ((IOSimpleArrayReportValues*)&( \ + ((IOReportElement*)(array_buf))[(idx) / IOR_VALUES_PER_ELEMENT].values)) \ + ->simple_values[(idx) % IOR_VALUES_PER_ELEMENT]) + + +/* ----- Histogram Reporting (HistogramReport) ----- */ + +// Internal struct for HistogramReport +typedef struct { + int bucketWidth; + IOReportElement elem[]; // Array of elements +} IOHistReportInfo; + +/* + * Determine the size required for a HistogramReport buffer. + * + * int nbuckets - number of buckets in the histogram + */ +#define HISTREPORT_BUFSIZE(nbuckets) \ + (sizeof(IOHistReportInfo) + ((nbuckets) * sizeof(IOReportElement))) + +/* + * Initialize a HistogramReport buffer. Supports only linear scale histogram. + * + * int nbuckets - number of buckets data is combined into + * uint32_t bucketWidth - size of each bucket + * void* buffer - ptr to HISTREPORT_BUFSIZE(nbuckets) bytes + * size_t bufSize - sanity check of buffer's size + * uint64_t providerID - registry Entry ID of the reporting service + * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID() + * IOReportCategories categories - categories of this channel + * + * If the buffer is not of sufficient size, the macro invokes IOREPORT_ABORT. + * If that returns, the buffer is left full of '&'. + */ +#define HISTREPORT_INIT(nbuckets, bktSize, buf, bufSize, providerID, channelID, cats) \ +do { \ + memset((buf), '&', (bufSize)); \ + IOHistReportInfo *__info = (IOHistReportInfo *)(buf); \ + IOReportElement *__elem; \ + IOHistogramReportValues *__rep; \ + if ((bufSize) >= HISTREPORT_BUFSIZE(nbuckets)) { \ + __info->bucketWidth = (bktSize); \ + for (unsigned __no = 0; __no < (nbuckets); __no++) { \ + __elem = &(__info->elem[__no]); \ + __rep = (IOHistogramReportValues *) &(__elem->values); \ + __elem->provider_id = (providerID); \ + __elem->channel_id = (channelID); \ + __elem->channel_type.report_format = kIOReportFormatHistogram; \ + __elem->channel_type.reserved = 0; \ + __elem->channel_type.categories = (cats); \ + __elem->channel_type.nelements = (nbuckets); \ + __elem->channel_type.element_idx = __no; \ + __elem->timestamp = 0; \ + memset(__rep, '\0', sizeof(IOHistogramReportValues)); \ + } \ + } \ + else { \ + IOREPORT_ABORT("bufSize is smaller than the required size\n"); \ + } \ +} while (0) + +/* + * Update histogram with a new value. + * + * + * void* hist_buf - pointer to memory initialized by HISTREPORT_INIT() + * int64_t value - new value to add to the histogram + */ +#define HISTREPORT_TALLYVALUE(hist_buf, value) \ +do { \ + IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \ + IOReportElement *__elem; \ + IOHistogramReportValues *__rep; \ + for (unsigned __no = 0; __no < __info->elem[0].channel_type.nelements; __no++) { \ + if ((value) <= __info->bucketWidth * (__no+1)) { \ + __elem = &(__info->elem[__no]); \ + __rep = (IOHistogramReportValues *) &(__elem->values); \ + if (__rep->bucket_hits == 0) { \ + __rep->bucket_min = __rep->bucket_max = (value); \ + } \ + else if ((value) < __rep->bucket_min) { \ + __rep->bucket_min = (value); \ + } \ + else if ((value) > __rep->bucket_max) { \ + __rep->bucket_max = (value); \ + } \ + __rep->bucket_sum += (value); \ + __rep->bucket_hits++; \ + break; \ + } \ + } \ +} while (0) + +/* + * Prepare a HistogramReport for + * IOService::updateReport(kIOReportCopyChannelData...) + * + * void* array_buf - ptr to memory initialized by HISTREPORT_INIT() + * void* ptr2cpy - filled in with pointer to buffer to be copied out + * size_t size2cpy - filled in with the size of the buffer to copy out + */ + +#define HISTREPORT_UPDATEPREP(hist_buf, ptr2cpy, size2cpy) \ +do { \ + IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \ + (size2cpy) = __info->elem[0].channel_type.nelements * sizeof(IOReportElement); \ + (ptr2cpy) = (void *) &__info->elem[0]; \ +} while(0) + + +/* + * Update the result field received as a parameter for kIOReportGetDimensions & + * kIOReportCopyChannelData actions. + * + * void* array_buf - memory initialized by HISTREPORT_INIT() + * IOReportConfigureAction action - configure/updateReport() 'action' + * void* result - configure/updateReport() 'result' + */ + +#define HISTREPORT_UPDATERES(hist_buf, action, result) \ do { \ - int __cnt = (bufSize)/sizeof(uint32_t); \ - while (--__cnt >= 0) \ - ((uint32_t*)(buf))[__cnt] = 0xbadcafe; \ + IOHistReportInfo *__info = (IOHistReportInfo *)(hist_buf); \ + int *__nElements = (int *)(result); \ + if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \ + *__nElements += __info->elem[0].channel_type.nelements; \ + } \ } while (0) +/* + * Get the 64-bit channel ID of a HistogramReport. + * + * void* hist_buf - ptr to memory initialized by HISTREPORT_INIT() + */ +#define HISTREPORT_GETCHID(hist_buf) \ + (((IOHistReportInfo *)(hist_buf))->elem[0].channel_id) + +/* + * Get the IOReportChannelType of a HistogramReport. + * + * void* hist_buf - ptr to memory initialized by HISTREPORT_INIT() + */ +#define HISTREPORT_GETCHTYPE(hist_buf) \ + (*(uint64_t*)&(((IOHistReportInfo *)(hist_buf))->elem[0].channel_type)) + #ifdef __cplusplus } #endif