]>
git.saurik.com Git - apple/xnu.git/blob - iokit/IOKit/IOReportMacros.h
2 * @APPLE_LICENSE_HEADER_START@
4 * Copyright (c) 2012 Apple Computer, Inc. All Rights Reserved.
6 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. The rights granted to you under the License
12 * may not be used to create, or enable the creation or redistribution of,
13 * unlawful or unlicensed copies of an Apple operating system, or to
14 * circumvent, violate, or enable the circumvention or violation of, any
15 * terms of an Apple operating system software license agreement.
17 * Please obtain a copy of the License at
18 * http://www.opensource.apple.com/apsl/ and read it before using this file.
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 #ifndef _IOREPORT_MACROS_H_
32 #define _IOREPORT_MACROS_H_
34 #include "IOReportTypes.h"
43 These macros allow non-I/O Kit software to generate IOReporting
44 reports. Clients must prevent concurrent access to any given
45 report buffer from multiple threads.
47 While these macros allow non-I/O Kit software to participate
48 in IOReporting, an IOService instance must lend its driver ID,
49 respond to the appropriate IOService overrides, and shuttle
50 data back and forth. In some cases, it may be useful to have
51 the I/O Kit driver initialize the report buffer with the
56 * Returns the buffer size required for a Simple report.
58 #define SIMPLEREPORT_BUFSIZE (sizeof(IOReportElement))
61 * Initialize a buffer to hold a Simple (integer) report.
63 * void* buffer - ptr to SIMPLEREPORT_BUFSIZE bytes
64 * size_t bufSize - sanity check of buffer's size
65 * uint64_t providerID - registry Entry ID of the reporting service
66 * uint64_t channelID - the report's channel ID
67 * IOReportCategories categories - categories of this channel
69 * If the buffer is not of sufficient size, the macro performs a
70 * null pointer reference to trigger a segfault. Then, the buffer is
71 * filled with 0xbadcafe.
73 #define SIMPLEREPORT_INIT(buffer, bufSize, providerID, channelID, cats) \
75 IOReportElement *__elem = (IOReportElement *)(buffer); \
76 IOSimpleReportValues *__vals; \
77 if ((bufSize) >= SIMPLEREPORT_BUFSIZE) { \
78 __elem->channel_id = (channelID); \
79 __elem->provider_id = (providerID); \
80 __elem->channel_type.report_format = kIOReportFormatSimple; \
81 __elem->channel_type.reserved = 0; \
82 __elem->channel_type.categories = (cats); \
83 __elem->channel_type.nelements = 1; \
84 __elem->channel_type.element_idx = 0; \
85 __elem->timestamp = 0; \
86 __vals = (IOSimpleReportValues*)&__elem->values; \
87 __vals->simple_value = kIOReportInvalidValue; \
90 uint32_t *__nptr = NULL; \
92 POLLUTE_BUF((buffer), (bufSize)); \
98 * Sets the SimpleReport channel to a new value.
100 * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
101 * uint64_t new_value - new value for the channel
103 #define SIMPLEREPORT_SETVALUE(simp_buf, new_value) \
105 IOReportElement *__elem = (IOReportElement *)(simp_buf); \
106 IOSimpleReportValues *__vals; \
107 __vals = (IOSimpleReportValues*)&__elem->values; \
108 __vals->simple_value = (new_value); \
112 * Prepare simple report buffer for
113 * IOService::updateReport(kIOReportCopyChannelData...)
115 * void* simp_buf - Ptr to memory updated by SIMPLEREPORT_SETVALUE()
116 * void* ptr2cpy - On return, 'ptr2cpy' points to the memory that needs to be
117 * copied for kIOReportCopyChannelData.
118 * size_t size2cpy - On return, 'size2cpy' is set to the size of the report
119 * data that needs to be copied for kIOReportCopyChannelData.
121 #define SIMPLEREPORT_UPDATEPREP(simp_buf, ptr2cpy, size2cpy) \
123 (ptr2cpy) = (simp_buf); \
124 (size2cpy) = sizeof(IOReportElement); \
129 * Updates the result field received as a parameter for
130 * kIOReportGetDimensions & kIOReportCopyChannelData actions.
132 * IOReportConfigureAction action - configure/updateReport() 'action' param
133 * void* result - configure/updateReport() 'result' param
136 #define SIMPLEREPORT_UPDATERES(action, result) \
138 if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
139 int *__nElements = (int *)(result); \
147 * Returns the channel id from the buffer previously initialized by
148 * SIMPLEREPORT_INIT().
150 * void* simp_buf - ptr to memory initialized by SIMPLEREPORT_INIT()
153 #define SIMPLEREPORT_GETCHID(simp_buf) \
154 (((IOReportElement *)(simp_buf))->channel_id); \
158 // Internal struct for State report buffer
162 IOReportElement elem
[]; // Array of elements
166 * Returns the size required to be allocated for using STATEREPORT_*()
168 * int nstates - number of states for the intended channel
170 #define STATEREPORT_BUFSIZE(nstates) \
171 (sizeof(IOStateReportInfo) + (nstates) * sizeof(IOReportElement))
175 * Initializes a buffer so it can be used with STATEREPORT_*().
177 * int nstates - number of states to be reported
178 * void* buffer - ptr to STATEREPORT_BUFSIZE(nstates) bytes
179 * size_t bufSize - sanity check of buffer's size
180 * uint64_t providerID - registry Entry ID of the reporting service
181 * uint64_t channelID - ID of this channel, see IOREPORT_MAKEID()
182 * IOReportCategories categories - categories of this channel
184 * If the buffer is not of sufficient size, the macro performs a
185 * null pointer reference to trigger a segfault. Then, the buffer is
186 * filled with 0xbadcafe.
188 #define STATEREPORT_INIT(nstates, buf, bufSize, providerID, channelID, cats) \
190 IOStateReportInfo *__info = (IOStateReportInfo *)(buf); \
191 IOStateReportValues *__rep; \
192 IOReportElement *__elem; \
193 if ((bufSize) >= STATEREPORT_BUFSIZE(nstates)) { \
194 for (unsigned __no = 0; __no < (nstates); __no++) { \
195 __elem = &(__info->elem[__no]); \
196 __rep = (IOStateReportValues *) &(__elem->values); \
197 __elem->channel_id = (channelID); \
198 __elem->provider_id = (providerID); \
199 __elem->channel_type.report_format = kIOReportFormatState; \
200 __elem->channel_type.reserved = 0; \
201 __elem->channel_type.categories = (cats); \
202 __elem->channel_type.nelements = (nstates); \
203 __elem->channel_type.element_idx = __no; \
204 __elem->timestamp = 0; \
205 __rep->state_id = __no; \
206 __rep->intransitions = 0; \
207 __rep->upticks = 0; \
209 __info->curr_state = 0; \
210 __info->update_ts = 0; \
213 int *__nptr = NULL; \
215 POLLUTE_BUF((buf), (bufSize)); \
220 * Initializes the state id field of a state with the specified value. By
221 * default, STATEREPORT_INIT initializes the state id with the index of
222 * that state. This macro can be used to provide a more descriptive state id.
224 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
225 * unsigned stateIdx - index of the state, out of bounds -> no-op
226 * uint64_t stateID - new state id, see IOREPORT_MAKEID()
228 #define STATEREPORT_SETSTATEID(state_buf, stateIdx, stateID) \
230 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
231 IOStateReportValues *__rep; \
232 if ((stateIdx) < __info->elem[0].channel_type.nelements) { \
233 __rep = (IOStateReportValues*) &(__info->elem[(stateIdx)].values); \
234 __rep->state_id = (stateID); \
240 * Set the state of a State report.
242 * void* state_buf - pointer to memory initialized by STATEREPORT_INIT()
243 * unsigned newStateIdx - index of new state, out of bounds -> no-op
244 * uint64_t changeTime - time at which the transition occurred
246 #define STATEREPORT_SETSTATE(state_buf, newStateIdx, changeTime) \
248 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
249 IOStateReportValues *__rep; \
250 if ((newStateIdx) < __info->elem[0].channel_type.nelements ) { \
251 __rep = (IOStateReportValues*) &(__info->elem[__info->curr_state].values); \
252 if (__info->update_ts) \
253 __rep->upticks += (changeTime) - __info->update_ts; \
254 __info->elem[(newStateIdx)].timestamp = (changeTime); \
255 __rep = (IOStateReportValues*) &(__info->elem[(newStateIdx)].values); \
256 __rep->intransitions++; \
257 __info->curr_state = (newStateIdx); \
258 __info->update_ts = (changeTime); \
263 * Prepare StateReport for UpdateReport call
265 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
266 * uint64_t currentTime - current timestamp
267 * void* ptr2cpy - filled in with pointer to buffer to be copied out
268 * size_t size2cpy - filled in with the size of the buffer to copy out
270 #define STATEREPORT_UPDATEPREP(state_buf, currentTime, ptr2cpy, size2cpy) \
272 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
273 IOReportElement *__elem; \
274 IOStateReportValues *__state; \
275 (size2cpy) = __info->elem[0].channel_type.nelements * sizeof(IOReportElement); \
276 (ptr2cpy) = (void *) &__info->elem[0]; \
277 if (__info->update_ts) { \
278 __elem = &__info->elem[__info->curr_state]; \
279 __state = (IOStateReportValues *)&__elem->values; \
280 __elem->timestamp = (currentTime); \
281 __state->upticks += (currentTime) - __info->update_ts; \
282 __info->update_ts = (currentTime); \
287 * Updates the result field received as a parameter for kIOReportGetDimensions &
288 * kIOReportCopyChannelData actions.
290 * void* state_buf - memory initialized by STATEREPORT_INIT()
291 * IOReportConfigureAction action - configure/updateReport() 'action'
292 * void* result - configure/updateReport() 'result'
295 #define STATEREPORT_UPDATERES(state_buf, action, result) \
297 IOStateReportInfo *__info = (IOStateReportInfo *)(state_buf); \
298 IOReportElement *__elem; \
299 int *__nElements = (int *)(result); \
300 if (((action) == kIOReportGetDimensions) || ((action) == kIOReportCopyChannelData)) { \
301 __elem = &(__info->elem[0]); \
302 *__nElements += __elem->channel_type.nelements; \
309 * Returns the channel id from the buffer previously initialized by STATEREPORT_INIT().
311 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
314 #define STATEREPORT_GETCHID(state_buf) \
315 (((IOStateReportInfo *)(state_buf))->elem[0].channel_id)
318 * Returns number of transitions occurred from the given state
320 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
321 * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue
325 #define STATEREPORT_GETTRANSITIONS(state_buf, stateIdx) \
326 (((stateIdx) < ((IOStateReportInfo *)(state_buf))->elem[0].channel_type.nelements) \
327 ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->intransitions \
328 : kIOReportInvalidValue)
331 * Returns the total number of ticks spent in the given state.
333 * void* state_buf - ptr to memory initialized by STATEREPORT_INIT()
334 * unsigned stateIdx - index of state, out of bounds -> kIOReportInvalidValue
337 #define STATEREPORT_GETTICKS(state_buf, stateIdx) \
338 (((stateIdx) < ((IOStateReportInfo*)(state_buf))->elem[0].channel_type.nelements) \
339 ? ((IOStateReportValues*)&(((IOStateReportInfo*)(state_buf))->elem[(stateIdx)].values))->upticks \
340 : kIOReportInvalidValue)
343 #define POLLUTE_BUF(buf, bufSize) \
345 int __cnt = (bufSize)/sizeof(uint32_t); \
346 while (--__cnt >= 0) \
347 ((uint32_t*)(buf))[__cnt] = 0xbadcafe; \
354 #endif // _IOREPORT_MACROS_H_