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