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