xref: /xnu-8020.140.41/iokit/IOKit/IOReportMacros.h (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
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