xref: /xnu-11215/iokit/IOKit/IOKernelReporters.h (revision e7776783)
1 /*
2  * Copyright (c) 2012-2016 Apple Inc.  All Rights Reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 /*
30  * FILE: IOReporter.h
31  * AUTH: Cyril & Soren (Core OS)
32  * DATE: 2012-2013 (Copyright Apple Inc.)
33  * DESC: IOReporting interfaces for I/O Kit drivers
34  *
35  */
36 
37 #ifndef _IOKERNEL_REPORTERS_H_
38 #define _IOKERNEL_REPORTERS_H_
39 
40 #include <machine/limits.h>
41 
42 #include <libkern/c++/OSPtr.h>
43 #include <IOKit/IOLib.h>
44 #include <IOKit/IOService.h>
45 #include <IOKit/IOLocks.h>
46 #include <IOKit/IOBufferMemoryDescriptor.h>
47 
48 #include <IOKit/IOReportTypes.h>
49 #include <IOKit/IOKernelReportStructs.h>
50 
51 #include <libkern/c++/OSPtr.h>
52 
53 typedef OSDictionary IOReportLegendEntry;
54 
55 /*******************************
56 *   TOC: this file contains
57 *    1. Introduction
58 *    2a. IOReporter class declaration (public & non-public members)
59 *    2b. static IOReporter methods unrelated to the class
60 *    3. IOReporter subclass declarations (public & non-public members)
61 *    4. IOReportLegend class declaration
62 *******************************/
63 
64 /*!
65  *  1. Introduction
66  *
67  *  IOReporting is a mechanism for I/O Kit drivers to gather statistics
68  *  (or other information) and make it available to various "observers,"
69  *  which are generally in user space. Requests for information come
70  *  through two new IOService methods: ::configureReport(...) and
71  *  ::updateReport(...). While not required (see IOReportTypes.h), drivers
72  *  will generally use IOReporter subclass instances to track the requested
73  *  information and respond to IOReporting requests. Drivers can use these
74  *  classes to track information, either all the time or between "enable"
75  *  and "disable" calls to IOService::configureReport().
76  *
77  *  Available information is organized into "channels." A channel is
78  *  uniquely identified by both driver (registry) ID and a 64-bit channel
79  *  ID. One way drivers can advertise their channels is by publishing
80  *  "legends" in the I/O Kit registry. In addition to collecting
81  *  information and responding to queries, IOReporter objects can produce
82  *  legend entries describing their channels. The IOReportLegend class
83  *  helps manage legend entries from multiple reporter objects as well
84  *  as with grouping channels logically for observers.
85  *
86  *  An important basic constraint of the current implementation is that
87  *  all channels reported by a particular reporter instance must share all
88  *  traits except channel ID and name.  Specifically, the channel type
89  *  (including report class, categories, & size) and units.  Additionally,
90  *  IOHistogramReporter currently only supports one channel at a time.
91  *
92  *  Currently, ::{configure/update}Report() can be called any time between
93  *  when a driver calls registerService() and when free() is called on
94  *  your driver. 12960947 tracks improvements / recommendations for
95  *  correctly handling these calls during termination.
96  *
97  * Locking
98  *  IOReporting only imposes concurrent access constraints when multiple
99  *  threads are accessing the same object.  Three levels of constraint apply
100  *  depending on a method's purpose:
101  *  1. Allocation/Teardown - same-instance concurrency UNSAFE, MAY BLOCK
102  *  2. Configuration - same-instance concurrency SAFE, MAY BLOCK
103  *  3. Update - same-instance concurrency SAFE, WILL NOT BLOCK
104  *
105  *  Configuration requires memory management which can block and must
106  *  be invoked with interrupts ENABLED (for example, NOT in the interrupt
107  *  context NOR with a spin lock -- like IOSimpleLock -- held).
108  *
109  *  Updates can be performed with interrupts disabled, but clients should
110  *  take into account that IOReporters' non-blocking currenency is achieved
111  *  with IOSimpleLockLockDisable/UnlockEnableInterrupts(): that is, by
112  *  disabling interrupts and taking a spin lock.  While IOReporting will
113  *  never hold a lock beyond a call into it, some time may be spent within
114  *  the call spin-waiting for the lock.  Clients holding their own
115  *  spin locks should carefully consider the impact of IOReporting's
116  *  (small) additional latency before calling it while holding a spin lock.
117  *
118  *  The documentation for each method indicates any concurrency guarantees.
119  */
120 
121 
122 /*********************************/
123 /*** 2a. IOReporter Base Class ***/
124 /*********************************/
125 
126 class IOReporter : public OSObject
127 {
128 	OSDeclareDefaultStructors(IOReporter);
129 
130 protected:
131 /*! @function   IOReporter::init
132  *   @abstract   base init() method, called by subclass initWith() methods
133  *
134  *   @param  reportingService - IOService associated with all channels
135  *   @param  channelType - type info for all channels (element_idx = 0)
136  *   @param  unit - description applied for all channels
137  *   @result     true on success, false otherwise
138  *
139  *   @discussion
140  *       init() establishes the parameters of all channels for this reporter
141  *       instance. Any channels added via addChannel() will be of this type
142  *       and have this unit.
143  *
144  *       IOReporter clients should use the static <subclass>::with() methods
145  *       below to obtain fully-initialized reporter instances.  ::free()
146  *       expects ::init() to have completed successfully.  On failure, any
147  *       allocations are cleaned up.
148  *
149  *   Locking: same-instance concurrency UNSAFE
150  */
151 	virtual bool init(IOService *reportingService,
152 	    IOReportChannelType channelType,
153 	    IOReportUnit unit);
154 
155 public:
156 
157 /*! @function   IOReporter::addChannel
158  *   @abstract   add an additional, similar channel to the reporter
159  *
160  *   @param  channelID - identifier for the channel to be added
161  *   @param  channelName - an optional human-readble name for the channel
162  *   @result     appropriate IOReturn code
163  *
164  *   @discussion
165  *       The reporter will allocate memory to track a new channel with the
166  *       provided ID and name (if any).  Its other traits (type, etc) will
167  *       be those provided when the reporter was initialized.  If no channel
168  *       name is provided and the channelID consists solely of ASCII bytes,
169  *       those bytes (ignoring any NUL bytes) will be used as the
170  *       human-readable channel name in user space.  The IOREPORT_MAKEID()
171  *       macro in IOReportTypes.h can be used to create ASCII channel IDs.
172  *
173  *   Locking: same-instance concurrency SAFE, MAY BLOCK
174  */
175 	IOReturn addChannel(uint64_t channelID, const char *channelName = NULL);
176 
177 /*! @function   IOReporter::createLegend
178  *   @abstract   create a legend entry represending this reporter's channels
179  *   @result     An IOReportLegendEntry object or NULL on failure.
180  *   @discussion
181  *       All channels added to the reporter will be represented
182  *       in the resulting legend entry.
183  *
184  *       Legends must be published togethar as an array under the
185  *       kIOReportLegendKey in the I/O Kit registry.  The IOReportLegend
186  *       class can be used to properly combine legend entries from multiple
187  *       reporters as well as to put channels into groups of interest to
188  *       observers.  When published, individual legend entries share
189  *       characteristics such as group and sub-group.  Multiple IOReporter
190  *       instances are required to produce independent legend entries which
191  *       can then be published with different characteristics.
192  *
193  *       Drivers wishing to publish legends should do so as part of their
194  *       ::start() routine.  As superclasses *may* have installed legend
195  *       entries, any existing existing legend should be retrieved and
196  *       IOReportLegend used to merge it with the new entries.
197  *
198  *       Recommendations for best practices are forthcoming.
199  *
200  *       Instead of calling createLegend on your reporter object and then
201  *       appending it manually to IOReportLegend, one may prefer to call
202  *       IOReportLegend::appendReporterLegend which creates and appends a
203  *       reporter's IOReportLegendEntry in a single call.
204  *
205  *   Locking: same-instance concurrency SAFE, MAY BLOCK
206  */
207 	OSPtr<IOReportLegendEntry> createLegend(void);
208 
209 /*! @function   IOReporter::configureReport
210  *   @abstract   track IOService::configureReport(), provide sizing info
211  *
212  *   @param  channelList - channels to configure
213  *   @param  action - enable/disable/size, etc (see IOReportTypes.h)
214  *   @param  result - *incremented* for kIOReportGetDimensions
215  *   @param  destination - action-specific default destination
216  *   @result     appropriate IOReturn code
217  *
218  *   @discussion
219  *       Any time a reporting driver's ::configureReport method is invoked,
220  *       this method should be invoked on each IOReporter that is being
221  *       used by that driver to report channels in channelList.
222  *
223  *       Any channels in channelList which are not tracked by this reporter
224  *       are ignored.  ::configureReport(kIOReportGetDimensions) expects
225  *       the full size of all channels, including any reported by
226  *       superclasses.  It is valid to call this routine on multiple
227  *       reporter objects in succession and they will increment 'result'
228  *       to provide the correct total.
229  *
230  *       In the initial release, this routine is only required to calculate
231  *       the response to kIOReportGetDimensions, but in the future it will
232  *       will enable functionality like "triggered polling" via
233  *       kIOReportNotifyHubOnChange.  Internally, it is already keeping
234  *       track of the number of times each channel has been enabled and
235  *       disabled.  13073064 tracks adding a method to see whether any
236  *       channels are currently being observed.
237  *
238  *       The static IOReporter::configureAllReports() will call this method
239  *       on multiple reporters grouped in an OSSet.
240  *
241  *   Locking: same-instance concurrency SAFE, MAY BLOCK
242  */
243 	IOReturn configureReport(IOReportChannelList *channelList,
244 	    IOReportConfigureAction action,
245 	    void *result,
246 	    void *destination);
247 
248 /*! @function   IOReporter::updateReport
249  *   @abstract   Produce standard reply to IOService::updateReport()
250  *
251  *   @param  channelList - channels to update
252  *   @param  action - copy/trace data (see IOReportTypes.h)
253  *   @param  result - action-specific return value (e.g. size of data)
254  *   @param  destination - destination for this update (action-specific)
255  *   @result     appropriate IOReturn code
256  *
257  *   @discussion
258  *       This method searches channelList for channels tracked by this
259  *       reporter, writes the corresponding data into 'destination', and
260  *       updates 'result'.  It should be possible to pass a given set of
261  *       IOService::updateReport() arguments to any and all reporters as
262  *       well as to super::updateReport() and get the right result.
263  *
264  *       The static IOReporter::updateAllReports() will call this method
265  *       on an OSSet of reporters.
266  *
267  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
268  */
269 	IOReturn updateReport(IOReportChannelList *channelList,
270 	    IOReportConfigureAction action,
271 	    void *result,
272 	    void *destination);
273 
274 /*! @function   IOReporter::free
275  *   @abstract   Releases the object and all its resources.
276  *
277  *   @discussion
278  *       ::free() [called on last ->release()] assumes that init() [called
279  *       by static ::with() methods] has completed successfully.
280  *
281  *   Locking: same-instance concurrency UNSAFE
282  */
283 	virtual void free(void) APPLE_KEXT_OVERRIDE;
284 
285 /*! @function	IOReporter::init
286  *   @abstract	Initialize global state
287  *
288  *   @discussion
289  *	::initialize() [called during IOStartIOKit] initializes all global
290  *	state for IOReporter objects.
291  *
292  */
293 	static void initialize(void);
294 
295 
296 /*********************************/
297 /*** 2b. Useful Static Methods ***/
298 /*********************************/
299 
300 /* The following static functions are intended to simplify the management
301  * of multiple reporters.  They may be superseded in the future by an
302  * IOReportManager class.
303  */
304 
305 /*! @function   IOReporter::configureAllReports
306  *   @abstract   call configureReport() on multiple IOReporter objects
307  *
308  *   @param  reporters - OSSet of IOReporter objects
309  *   @param  channelList - full list of channels to configure
310  *   @param  action - enable/disable/size, etc
311  *   @param  result - action-specific returned value
312  *   @param  destination - action-specific default destination
313  *   @result     success if all objects successfully complete
314  *               IOReporter::configureReport()
315  *
316  *   @discussion
317  *       The OSSet must only contain IOReporter instances.  The presence
318  *       of non-IOReporter instances will cause this function to return
319  *       kIOReturnBadArgument.  If any reporter returns an error, the
320  *       function will immediately return that error.
321  *
322  *       Per the IOReporter::configureReport() documentation, each
323  *       reporter will search channelList for channels it is reporting
324  *       and provide a partial response.
325  */
326 	static IOReturn configureAllReports(OSSet *reporters,
327 	    IOReportChannelList *channelList,
328 	    IOReportConfigureAction action,
329 	    void *result,
330 	    void *destination);
331 // FIXME: just put the function (inline-ish) here?
332 
333 /*! @function   IOReporter::updateAllReports
334  *   @abstract   call updateReport() on multiple IOReporter objects
335  *
336  *   @param  reporters - OSSet of IOReporter objects
337  *   @param  channelList - full list of channels to update
338  *   @param  action - type/style of update
339  *   @param  result - returned details about what was updated
340  *   @param  destination - destination for this update (action-specific)
341  *   @result     IOReturn code
342  *   @discussion
343  *       The OSSet must only contain IOReporter instances.  The presence
344  *       of non-IOReporter instances will cause this function to return
345  *       kIOReturnBadArgument.  If any reporter returns an error, the
346  *       function will immediately return that error.
347  *
348  *       Per the IOReporter::configureReport() documentation, each
349  *       reporter will search channelList for channels it is reporting
350  *       and provide a partial response.
351  */
352 	static IOReturn updateAllReports(OSSet *reporters,
353 	    IOReportChannelList *channelList,
354 	    IOReportConfigureAction action,
355 	    void *result,
356 	    void *destination);
357 // FIXME: just put the function (inline-ish) here?
358 
359 
360 /*  Protected (subclass-only) Methods
361  *
362  *   General subclassing is not encouraged as we intend to improve
363  *   internal interfaces.  If you need something that might require
364  *   a subclass, please file a bug against IOReporting/X and we will
365  *   help you.
366  *
367  *   One important concept for sub-classes (not clients) is that report
368  *   data is stored in IOReportElement structures (see IOReportTypes.h).
369  */
370 protected:
371 
372 /*! @function   IOReporter::lockReporterConfig
373  *   @function   IOReporter::unlockReporterConfig
374  *   @abstract   prevent concurrent reconfiguration of a reporter
375  *
376  *   @discussion
377  *       lockReporterConfig() takes a mutex-based lock intended to prevent
378  *       concurrent access to the reporter's configuration.  It is not
379  *       intended to prevent updates to the reporter's data.  As long as
380  *       all other requirements are met, it is safe to simultaneously hold
381  *       both the configuration and data locks on a single reporter.
382  *
383  *       lockReporterConfig() is used by routines such as addChannel().
384  *       See also lockReporter() and ::handle*Swap*() below.
385  */
386 	void lockReporterConfig(void);
387 	void unlockReporterConfig(void);
388 
389 /*! @function   IOReporter::lockReporter
390  *   @function   IOReporter::unlockReporter
391  *   @abstract   prevent concurrent access to a reporter's data
392  *
393  *   @discussion
394  *       This method grabs a lock intended to control access the reporter's
395  *       reporting data.  Sub-classes maninupating internal report values
396  *       must make sure the reporter is locked (usually by the most generic
397  *       public interface) before calling getElementValues(),
398  *       copyElementValues(), or setElementValues().
399  *
400  *       Subclasses should ensure that this lock is taken exactly once
401  *       before directly accessing reporter data.  For example,
402  *       [virtual] IOFooReporter::handleSetFoo(.) {
403  *           // assert(lock_held)
404  *           getElementValues(1..)
405  *           getElementValues(3..)
406  *           getElementValues(5..)
407  *           [calculate]
408  *           setElementValues(6..)
409  *       }
410  *       IOFooReporter::setFoo(.) {      // not virtual
411  *           lockReporter()
412  *           handleSetFoo(.)
413  *           unlockReporter()
414  *       }
415  *
416  *       IOReporter::handle*() use lockReporter() similarly.  For example,
417  *       the lock is taken by IOReporter::updateReport() and is already
418  *       held by the time any ::updateChannelValues() methods are called.
419  *
420  *       Subclasses cannot call this routine if the lock is already held.
421  *       That's why IOReporting generally only calls it from non-virtual
422  *       public methods.  In particular, this method should not be called
423  *       it from ::handle*() methods which exist to allow override after
424  *       the lock is taken.
425  *
426  *       Because lockReporter() uses a spin lock, it is SAFE to use in the
427  *       interrupt context.  For the same reason, however, it is UNSAFE
428  *       to perform any blocking blocking operations (including memory
429  *       allocations) while holding this lock.
430  */
431 	void lockReporter(void);
432 	void unlockReporter(void);
433 
434 /*!
435  *   @discussion
436  *       The ::handle*Swap* functions allow subclasses to safely reconfigure
437  *       their internal state.  A non-virtual function handles locking
438  *       and invokes the functions in order:
439  *       - lockReporterConfig()  // protecting instance vars but not content
440  *       - prepare / allocate buffers of the new size
441  *       - if error, bail (unlocking, of course)
442  *
443  *       - lockReporter()        // protecting data / blocking updates
444  *       - swap: preserve continuing data / install new buffers
445  *       - unlockReporter()
446  *
447  *       - deallocate now-unused buffers
448  *       - unlockReporterConfig()
449  */
450 /*! @function   IOReporter::handleSwapPrepare
451  *   @abstract   allocate memory in preparation for an instance variable swap
452  *
453  *   @param newNChannels   target number of channels
454  *   @result     IOReturn code
455  *
456  *   @discussion
457  *       ::handleSwapPrepare() is responsible for allocating appropriately-
458  *       sized buffers (based on the new number of channels) and storing
459  *       them in _swap* instance variables.  If returning and error, it
460  *       must deallocate any buffers and set to NULL any _swap* variables.
461  *
462  *   Locking: The caller must ensure that the *config* lock is HELD but
463  *            that the reporter (data) lock is *NOT HELD*.
464  */
465 	virtual IOReturn handleSwapPrepare(int newNChannels);
466 
467 /*! @function   IOReporter::handleAddChannelSwap
468  *   @abstract   update primary instance variables with new buffers
469  *
470  *   @param channel_id   ID of channel being added
471  *   @param symChannelName   optional channel name, in an allocated object
472  *   @result     IOReturn code
473  *
474  *   @discussion
475  *       handlAddChannelSwap() replaces the primary instance variables
476  *       with buffers allocated in handlePrepareSwap().  It copies the the
477  *       existing data into the appropriate portion of the new buffers.
478  *       Because it is specific to adding one channel, it assumes that the
479  *       target number of channels is one greater than the current value
480  *       of _nChannels.
481  *
482  *       IOReporter::handleAddChannelSwap() increments _nElements and
483  *       _nChannels.  To ensure that these variables describe the current
484  *       buffers throughout ::handle*Swap(), subclasses overriding this
485  *       method should call super::handleAddChannelSwap() after swapping
486  *       their own instance variables.
487  *
488  *       If returning an error, all implementations should leave their
489  *       instance variables as they found them (*unswapped*).  That ensures
490  *       handleSwapCleanup() cleans up the unused buffers regardless of
491  *       whether the swap was complete.
492  *
493  *       Pseudo-code incorporating these suggestions:
494  *       res = <err>; swapComplete = false;
495  *       if (<unexpected>)       goto finish
496  *       tmpBuf = _primaryBuf; _primaryBuf = _swapBuf; _swapBuf = _primaryBuf;
497  *       ...
498  *       swapComplete = true;
499  *       res = super::handle*Swap()
500  *       ...
501  *       finish:
502  *       if (res && swapComplete)    // unswap
503  *
504  *   Locking: The caller must ensure that BOTH the configuration and
505  *            reporter (data) locks are HELD.
506  */
507 	virtual IOReturn handleAddChannelSwap(uint64_t channel_id,
508 	    const OSSymbol *symChannelName);
509 
510 /*! @function   IOReporter::handleSwapCleanup
511  *   @abstract   release and forget unused buffers
512  *
513  *   @param swapNChannels   channel-relative size of the _swap buffers
514  *
515  *   @discussion
516  *       ::handleSwapCleanup() is responsible for deallocating the buffers
517  *       no longer used after a swap.  It must always be called if
518  *       SwapPrepare() completes successfully.  Because bufers may be
519  *       swapped in and out of existance, the _swap* variables may be
520  *       NULL and should be set to NULL when complete.
521  *
522  *   Locking: The caller must ensure that the *config* lock is HELD but
523  *            that the reporter (data) lock is *NOT HELD*.
524  */
525 	virtual void handleSwapCleanup(int swapNChannels);
526 
527 /*! @function   IOReporter::handleConfigureReport
528  *   @abstract   override vector for IOReporter::configureReport()
529  *               [parameters and result should exactly match]
530  *
531  *   @discussion
532  *       The public base class method takes the reporter lock, calls this
533  *       function, and then drops the lock.  Subclasses should not call
534  *       this function directly.
535  */
536 	virtual IOReturn handleConfigureReport(IOReportChannelList *channelList,
537 	    IOReportConfigureAction action,
538 	    void *result,
539 	    void *destination);
540 
541 /*! @function   IOReporter::handleUpdateReport
542  *   @abstract   override vector for IOReporter::updateReport()
543  *               [parameters and result should exactly match]
544  *
545  *   @discussion
546  *       The public base class method takes the reporter lock, calls this
547  *       function, and then drops the lock.  Subclasses should not call
548  *       this function directly.
549  *
550  *       This function may be overriden but the common case should be to
551  *       simply update reporter's specific values by overriding
552  *       IOReporter::updateChannelValues().
553  */
554 	virtual IOReturn handleUpdateReport(IOReportChannelList *channelList,
555 	    IOReportConfigureAction action,
556 	    void *result,
557 	    void *destination);
558 
559 /*  @function   IOReporter::handleCreateLegend
560  *   @abstract   override vector for IOReporter::createLegend()
561  *               [parameters and result should exactly match]
562  *
563  *   @discussion
564  *       The public base class method takes the reporter lock, calls this
565  *       function, and then drops the lock.  Subclasses should not call
566  *       this function directly.
567  */
568 	virtual OSPtr<IOReportLegendEntry> handleCreateLegend(void);
569 
570 /*! @function   IOReporter::updateChannelValues
571  *   @abstract   update channel values for IOReporter::updateReport()
572  *
573  *   @param  channel_index - logical (internal) index of the channel
574  *   @result     appropriate IOReturn code
575  *
576  *   @discussion
577  *       Internal reporter method to allow a subclass to update channel
578  *       data when updateReport() is called.  This routine handles the
579  *       common case of a subclass needing to refresh state in response
580  *       to IOReporter::updateReport().  It saves the complexity of
581  *       parsing the full parameters to IOReporter::updateReport().
582  *
583  *       The IOReporter base class implementation does not do anything
584  *       except return success.
585  *
586  *   Locking: IOReporter::updateReport() takes the reporter lock,
587  *            determines the indices involved, calls this function, and
588  *            then proceeds to provide values to the caller.  If subclasses
589  *            need to call this routine directly, they must ensure that
590  *            the reporter (data) lock is held: see
591  *            IOReporter::lockReporter().
592  */
593 	virtual IOReturn updateChannelValues(int channel_index);
594 
595 
596 /*! @function   IOReporter::updateReportChannel
597  *   @abstract   Internal method to extract channel data to a destination
598  *
599  *   @param  channel_index - offset into internal elements array
600  *   @param  nElements - incremented by the number of IOReportElements added
601  *   @param  destination - pointer to the destination buffer
602  *   @result     IOReturn code
603  *
604  *   @discussion
605  *       updateReportChannel() is used to extract a single channel's
606  *       data to the updateReport() destination.
607  *
608  *   Locking: Caller must ensure that the reporter (data) lock is held.
609  */
610 	IOReturn updateReportChannel(int channel_index,
611 	    int *nElements,
612 	    IOBufferMemoryDescriptor *destination);
613 
614 
615 /*! @function   IOReporter::setElementValues
616  *   @abstract   Atomically update a specific member of _elements[].
617  *
618  *   @param  element_index - index of the _element in internal array
619  *   @param  values - IORepoterElementValues to replace those at _elements[idx]
620  *   @param  record_time - optional mach_absolute_time to be used for metadata
621  *   @result     IOReturn code
622  *
623  *   @discussion
624  *       element_index can be obtained from getFirstElementIndex().  If
625  *       record_time is not provided, IOReporter::setElementValues() will
626  *       fetch the current mach_absolute_time.  If the current time is
627  *       already known, it is more efficient to pass it along.
628  *
629  *   Locking: Caller must ensure that the reporter (data) lock is held.
630  */
631 	virtual IOReturn setElementValues(int element_index,
632 	    IOReportElementValues *values,
633 	    uint64_t record_time = 0);
634 
635 /*! @function   IOReporter::getElementValues
636  *   @abstract   Internal method to directly access the values of an element
637  *
638  *   @param  element_index - index of the _element in internal array
639  *   @result     A pointer to the element values requested or NULL on failure
640  *
641  *   @discussion Locking: Caller must ensure that the reporter (data) lock is held.
642  *   The returned pointer is only valid until unlockReporter() is called.
643  */
644 	virtual const IOReportElementValues* getElementValues(int element_index);
645 
646 /*! @function   IOReporter::getFirstElementIndex
647  *   @abstract   Returns the first element index for a channel
648  *
649  *   @param  channel_id - ID of the channel
650  *   @param  element_index - pointer to the returned element_index
651  *   @result     appropriate IOReturn code
652  *
653  *   @discussion
654  *       For efficiently and thread-safely reading _elements
655  *
656  *   Locking: Caller must ensure that the reporter (data) lock is held.
657  */
658 	virtual IOReturn getFirstElementIndex(uint64_t channel_id,
659 	    int *element_index);
660 
661 /*! @function   IOReporter::getChannelIndex
662  *   @abstract   Returns the index of a channel from internal data structures
663  *
664  *   @param  channel_id - ID of the channel
665  *   @param  channel_index - pointer to the returned element_index
666  *   @result     appropriate IOReturn code
667  *
668  *   @discussion
669  *       For efficiently and thread-safely reading channels
670  *
671  *   Locking: Caller must ensure that the reporter (data) lock is held.
672  */
673 	virtual IOReturn getChannelIndex(uint64_t channel_id,
674 	    int *channel_index);
675 
676 /*! @function   IOReporter::getChannelIndices
677  *   @abstract   Returns the index of a channel and its corresponding
678  *               first element index from internal data structure
679  *
680  *    @param  channel_id - ID of the channel
681  *    @param  channel_index - pointer to the returned channel_index
682  *    @param  element_index - pointer to the returned element_index
683  *    @result     appropriate IOReturn code
684  *
685  *    @discussion
686  *       For efficiently and thread-safely reading channel elements.
687  *       It is commonly useful to get access to both channel and element
688  *       indices togther.  This convenience method allows sub-classes to
689  *       get both indices simultaneously.
690  *
691  *   Locking: Caller must ensure that the reporter (data) lock is held.
692  */
693 	virtual IOReturn getChannelIndices(uint64_t channel_id,
694 	    int *channel_index,
695 	    int *element_index);
696 
697 /*! @function   IOReporter::copyElementValues
698  *   @abstract   Copies the values of an internal element to *elementValues
699  *
700  *   @param  element_index - Index of the element to return values from
701  *   @param  elementValues - For returning the content of element values
702  *   @result     Returns the content of an element
703  *
704  *   @discussion
705  *       For efficiently and thread-safely reading _elements.
706  *       May need to find the index of the element first.
707  *
708  *   Locking: Caller must ensure that the reporter (data) lock is held.
709  */
710 	virtual IOReturn copyElementValues(int element_index,
711 	    IOReportElementValues *elementValues);
712 
713 /*! @function   IOReporter::legendWith
714  *   @abstract   Internal method to help create legend entries
715  *
716  *   @param  channelIDs - array of uint64_t channels IDs.
717  *   @param  channelNames - parrallel array of const char* channel names
718  *   @param  channelCount - number of channels, and size of channelIDs and channelNames
719  *   @param  channelType - the type of all channels in this legend
720  *   @param  unit - The unit for the quantity recorded by this reporter object
721  *
722  *   @result     An IOReportLegendEntry object or NULL on failure
723  *
724  *   @discussion
725  *       This static method is variant of IOReporter::legendWith that takes
726  *       raw arrays for the channelIDs and channelNames. It supports the static
727  *       createLegend() methods for the IOReporter subclasses.
728  *
729  *   Locking: SAFE to call concurrently (no static globals), MAY BLOCK
730  */
731 	static OSPtr<IOReportLegendEntry> legendWith(const uint64_t *channelIDs,
732 	    const char **channelNames,
733 	    int channelCount,
734 	    IOReportChannelType channelType,
735 	    IOReportUnit unit);
736 
737 // private methods
738 private:
739 /*! @function   IOReporter::copyChannelIDs
740  *   @abstract   return an an OSArray of the reporter's
741  *               channel IDs
742  *
743  *   @result     An OSArray of the repoter's channel ID's as OSNumbers
744  *
745  *   @discussion
746  *       This method is an internal helper function used to prepare a
747  *       legend entry.  It encapsulates the channel IDs in OSNumbers and
748  *       aggregates them in an OSArray used when building the IOReportLegend
749  *
750  *   Locking: Caller must ensure that the reporter (data) lock is held.
751  */
752 	OSPtr<OSArray> copyChannelIDs(void);
753 
754 /*! @function   IOReporter::legendWith
755  *   @abstract   Internal method to help create legend entries
756  *
757  *   @param  channelIDs - OSArray of OSNumber(uint64_t) channels IDs.
758  *   @param  channelNames - parrallel OSArray of OSSymbol(rich names)
759  *   @param  channelType - the type of all channels in this legend
760  *   @param  unit - The unit for the quantity recorded by this reporter object
761  *
762  *   @result     An IOReportLegendEntry object or NULL on failure
763  *
764  *   @discussion
765  *       This static method is the main legend creation function. It is called by
766  *       IOReporter sub-classes and is responsible for building an
767  *       IOReportLegendEntry corresponding to this reporter object.
768  *       This legend entry may be extended by the sub-class of IOReporter if
769  *       required.
770  *
771  *   Locking: SAFE to call concurrently (no static globals), MAY BLOCK
772  */
773 	static OSPtr<IOReportLegendEntry> legendWith(OSArray *channelIDs,
774 	    OSArray *channelNames,
775 	    IOReportChannelType channelType,
776 	    IOReportUnit unit);
777 
778 // protected instance variables (want to get rid of these)
779 protected:
780 	IOReportChannelType _channelType;
781 	uint64_t            _driver_id;     // driver reporting data
782 
783 // IOHistogramReporter accesses these; need to re-do its instantiation
784 	IOReportElement    *_elements;
785 	int                *_enableCounts;  // refcount kIOReportEnable/Disable
786 	uint16_t            _channelDimension;// Max channel size
787 	int                 _nElements;
788 	int                 _nChannels;     // Total Channels in this reporter
789 	OSPtr<OSArray>      _channelNames;
790 
791 // MUST be protected because check is a macro!
792 	bool                _reporterIsLocked;
793 	bool                _reporterConfigIsLocked;
794 
795 // Required for swapping inside addChannel
796 	IOReportElement    *_swapElements;
797 	int                *_swapEnableCounts;
798 
799 // private instance variables
800 private:
801 	IOReportUnit       _unit;
802 
803 	int                 _enabled;// 'enabled' if _enabled > 0
804 
805 	IOLock             *_configLock;
806 	IOInterruptState    _interruptState;
807 	IOSimpleLock       *_reporterLock;
808 };
809 
810 
811 /************************************/
812 /***** 3. IOReporter Subclasses *****/
813 /************************************/
814 
815 /*!
816  *   @class      IOSimpleReporter
817  *   @abstract   Report simple integers
818  *   @discussion
819  *       Each IOSimpleReporter can have an arbitrary number of channels,
820  *       each publishing a single integer value at any given time.
821  */
822 
823 class IOSimpleReporter : public IOReporter
824 {
825 	OSDeclareDefaultStructors(IOSimpleReporter);
826 
827 public:
828 
829 /*! @function   IOSimpleReporter::with
830  *   @abstract   create an initialized simple reporter
831  *
832  *   @param  reportingService - IOService associated with all channels
833  *   @param  categories - The category in which the report should be classified
834  *   @param  unit - The unit for the quantity recorded by the reporter object
835  *   @result     On success, an instance of IOSimpleReporter, else NULL
836  *
837  *   @discussion
838  *       Creates an instance of IOSimpleReporter object
839  *
840  *   Locking: SAFE to call concurrently (no static globals), MAY BLOCK.
841  */
842 	static OSPtr<IOSimpleReporter> with(IOService *reportingService,
843 	    IOReportCategories categories,
844 	    IOReportUnit unit);
845 
846 /*! @function   IOSimpleReporter::setValue
847  *   @abstract   Thread safely set a channel's value
848  *
849  *   @param  channel_id - ID of the channel for which the value needs to be set
850  *   @param  value - New channel value
851  *   @result     Appropriate IOReturn code
852  *
853  *   @discussion
854  *       Updates the value of a channel to the provided value.
855  *
856  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
857  */
858 	IOReturn setValue(uint64_t channel_id,
859 	    int64_t value);
860 
861 /*! @function   IOSimpleReporter::incrementValue
862  *   @abstract   Thread safely increment a channel's value by a given amount
863  *
864  *   @param  channel_id - ID of the channel for which the value needs to be incremented
865  *   @param  increment - Amount to be added to the current channel value
866  *   @result     Appropriate IOReturn code
867  *   @discussion
868  *       Increments the value of the channel ID by the provided amount.
869  *
870  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
871  */
872 	IOReturn incrementValue(uint64_t channel_id,
873 	    int64_t increment);
874 
875 /*! @function   IOSimpleReporter::getValue
876  *   @abstract   Thread safely access a channel value
877  *
878  *   @param  channel_id - ID of the channel to get a value from
879  *   @result     Returns the current value stored in the channel
880  *   @discussion
881  *       Accessor method to a channel's current stored value
882  *
883  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
884  */
885 	int64_t getValue(uint64_t channel_id);
886 
887 /*! @function   IOSimpleReporter::createLegend
888  *   @abstract   Creates a legend entry for an IOSimpleReporter
889  *
890  *   @param  channelIDs - array of uint64_t channels IDs.
891  *   @param  channelNames - parrallel array of const char* channel names
892  *   @param  channelCount - number of channels, and size of channelIDs and channelNames
893  *   @param  categories - The category in which the report should be classified
894  *   @param  unit - The unit for the quantity recorded by the reporter object
895  *
896  *   @result     An IOReportLegendEntry object or NULL on failure
897  *
898  *   @discussion
899  *       This static method supports creating a legend entry for an IOSimpleReporter
900  *       without actually having an IOSimpleReporter instance.
901  *       This can be used to lazily create IOReporters in IOService::configureReport()
902  *       rather than during driver initialization.
903  */
904 	static OSPtr<IOReportLegendEntry> createLegend(const uint64_t *channelIDs,
905 	    const char **channelNames,
906 	    int channelCount,
907 	    IOReportCategories categories,
908 	    IOReportUnit unit);
909 
910 protected:
911 
912 /*! @function   IOSimpleReporter::initWith
913  *   @abstract   instance method implementation called by IOSimpleReporter::with
914  *
915  *   @discussion
916  *       See description of parameters above
917  *
918  *   Locking: same-instance concurrency UNSAFE
919  */
920 	virtual bool initWith(IOService *reportingService,
921 	    IOReportCategories categories,
922 	    IOReportUnit unit);
923 
924 private:
925 };
926 
927 
928 
929 /*!
930  *   @class      IOStateReporter
931  *   @abstract   Report state machine data
932  *   @discussion
933  *       Each IOStateReporter can report information for an arbitrary number
934  *       of similar state machines.  All must have the same number of states.
935  */
936 class IOStateReporter : public IOReporter
937 {
938 	OSDeclareDefaultStructors(IOStateReporter);
939 
940 public:
941 
942 /*! @function   IOStateReporter::with
943  *   @abstract   State reporter static creation method
944  *
945  *   @param  reportingService - The I/O Kit service for this reporter's channels
946  *   @param  categories - The categories for this reporter's channels
947  *   @param  nstates - Maximum number of states for this reporter's channels
948  *   @param  unit - optional parameter if using override/increment...()
949  *   @result     on success, an IOStateReporter instance, else NULL
950  *
951  *   @discussion
952  *       Creates an instance of IOStateReporter.  The default time scale
953  *       is the current system's notion of mach_absolute_time().  Using a
954  *       non-default time scale requires the use of
955  *       override/incrementChannelState() instead of setState().
956  *       setState() always updates using mach_absolute_time().
957  *
958  *   Locking: SAFE to call concurrently (no static globals), MAY BLOCK
959  */
960 	static OSPtr<IOStateReporter> with(IOService *reportingService,
961 	    IOReportCategories categories,
962 	    int nstates,
963 	    IOReportUnit unit = kIOReportUnitHWTicks);
964 
965 /*! @function   IOStateReporter::setStateID
966  *   @abstract   Assign a non-default ID to a state
967  *
968  *   @param  channel_id - ID of channel containing the state in question
969  *   @param  state_index - index of state to give an ID: [0..(nstates-1)]
970  *   @param  state_id - 64-bit state ID, for ASCII, use IOREPORT_MAKEID
971  *
972  *   @result     Appropriate IOReturn code
973  *
974  *   @discussion
975  *       By default, IOStateReporter identifies its channel states by
976  *       numbering them from 0 to <nstates - 1>.  If setStateID is not
977  *       called to customize the state IDs, the numbered states will be
978  *       kept throughout the life of the object and it is safe to reference
979  *       those states by their indices.  Otherwise, after setStateID() has
980  *       been called, the ordering of states is no longer guaranteed and
981  *       the client must reference states by their assigned state ID.
982  *
983  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
984  */
985 	IOReturn setStateID(uint64_t channel_id,
986 	    int state_index,
987 	    uint64_t state_id);
988 
989 /*! @function   IOStateReporter::setChannelState
990  *   @abstract   Updates the current state of a channel to a new state
991  *
992  *   @param  channel_id - ID of the channel which is updated to a new state
993  *   @param  new_state_id - ID of the target state for this channel
994  *   @param  last_intransition - deprecated: time of most recent entry
995  *   @param  prev_state_residency - deprecated: time spent in previous state
996  *   @result     Appropriate IOReturn code
997  *
998  *   @discussion
999  *       setChannelState() updates the amount of time spent in the previous
1000  *       state (if any) and increments the number of transitions into the
1001  *       new state.  It also sets the target state's last transition time to
1002  *       the current time and enables internal time-keeping for the channel.
1003  *       In this mode, calls like getStateResidencyTime() and updateReport()
1004  *       automatically update a channel's time in state.
1005  *
1006  *       new_state_id identifies the target state as initialized
1007  *       (0..<nstates-1>) or as configured by setStateID().
1008  *
1009  *       Drivers wishing to compute and report their own time in state
1010  *       should use incrementChannelState() or overrideChannelState().  It
1011  *       is not currently possible for a driver to synchronize with the
1012  *       automatic time-keeping enabled by setChannelState().  The
1013  *       4-argument version of setChannelState() is thus impossible to
1014  *       use correctly.  In the future, there may be a setChannelState()
1015  *       which accepts a last_intransition parameter and uses it to
1016  *       automatically calculate time in state (ERs -> IOReporting / X).
1017  *
1018  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1019  */
1020 	IOReturn setChannelState(uint64_t channel_id,
1021 	    uint64_t new_state_id,
1022 	    uint64_t last_intransition,
1023 	    uint64_t prev_state_residency) __deprecated;
1024 
1025 /*! @function   IOStateReporter::setChannelState
1026  *   @abstract   Updates the current state of a channel to a new state
1027  *
1028  *   @param  channel_id - ID of the channel which is updated to a new state
1029  *   @param  new_state_id - ID of the target state for this channel
1030  *   @result     Appropriate IOReturn code
1031  *
1032  *   @discussion
1033  *       setChannelState() updates the amount of time spent in the previous
1034  *       state (if any) and increments the number of transitions into the
1035  *       new state.  It also sets the target state's last transition time to
1036  *       the current time and enables internal time-keeping for the channel.
1037  *       In this mode, calls like getStateResidencyTime() and updateReport()
1038  *       automatically update a channel's time in state.
1039  *
1040  *       new_state_id identifies the target state as initialized
1041  *       (0..<nstates-1>) or as configured by setStateID().
1042  *
1043  *       Drivers wishing to compute and report their own time in state
1044  *       should use incrementChannelState() or overrideChannelState().  It
1045  *       is not currently possible for a driver to synchronize with the
1046  *       automatic time-keeping enabled by setChannelState().  The
1047  *       4-argument version of setChannelState() is thus impossible to
1048  *       use correctly.  In the future, there may be a setChannelState()
1049  *       which accepts a last_intransition parameter and uses it to
1050  *       automatically calculate time in state (ERs -> IOReporting / X).
1051  *
1052  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1053  */
1054 	IOReturn setChannelState(uint64_t channel_id,
1055 	    uint64_t new_state_id);
1056 
1057 
1058 /*! @function   IOStateReporter::setState
1059  *   @abstract   Updates state for single channel reporters
1060  *
1061  *   @param  new_state_id - New state for the channel
1062  *   @result     Appropriate IOReturn code.
1063  *
1064  *   @discussion
1065  *       setState() is a convenience method for single-channel state
1066  *       reporter instances.  An error will be returned if the reporter
1067  *       in question has more than one channel.
1068  *
1069  *       See further discussion at setChannelState().
1070  *
1071  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1072  */
1073 	IOReturn setState(uint64_t new_state_id);
1074 
1075 /*! @function   IOStateReporter::setState
1076  *   @abstract   Updates state for single channel reporters
1077  *
1078  *   @param  new_state_id - New state for the channel
1079  *   @param  last_intransition - deprecated: time of most recent entry
1080  *   @param  prev_state_residency - deprecated: spent in previous state
1081  *   @result     Appropriate IOReturn code.
1082  *
1083  *   @discussion
1084  *       setState() is a convenience method for single-channel state
1085  *       reporter instances.  An error will be returned if the reporter
1086  *       in question has more than one channel.
1087  *
1088  *       See further discussion at setChannelState().
1089  *
1090  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1091  */
1092 	IOReturn setState(uint64_t new_state_id,
1093 	    uint64_t last_intransition,
1094 	    uint64_t prev_state_residency) __deprecated;
1095 
1096 /*! @function   IOStateReporter::overrideChannelState
1097  *   @abstract   Overrides state data for a channel with passed arguments
1098  *
1099  *   @param  channel_id - ID of the channel which state is to be updated
1100  *   @param  state_id - state id for the channel
1101  *   @param  time_in_state - time used as new total time in state
1102  *   @param  intransitions - total number of transitions into state
1103  *   @param  last_intransition - mach_absolute_time of most recent entry (opt)
1104  *   @result     Appropriate IOReturn code
1105  *
1106  *   @discussion
1107  *       overrideChannelState() sets a particular state's time in state
1108  *       and transition count to the values provided.  The optional
1109  *       last_intransition records the last time the channel transitioned
1110  *       into the given state.  Passing 0 for time_in_state and
1111  *       intransitions will force the current values to 0.  Passing 0
1112  *       for last_intransition for all states will disable the notion
1113  *       of a channel's "current state."
1114  *
1115  *       The most recent last_intransition (amongst all states in a channel)
1116  *       logically determines the current state.  If last_intransition is
1117  *       not provided for any state, the channel will not report a current
1118  *       For consistent results, it is important to either never specify
1119  *       last_intransition or to always specify it.
1120  *
1121  *       There is currently a bug in determining current state (13423273).
1122  *       The IOReportMacros.h macros only update the state's metadata
1123  *       timestamp and libIOReport only looks at the metadata timestamps
1124  *       to determine the current state.  Until that bug is fixed, whichever
1125  *       state is updated most recently will be considered the "current"
1126  *       state by libIOReport.
1127  *
1128  *       ::setState()'s automatic "time in state" updates are not supported
1129  *       when using overrideChannelState().  Clients must not use
1130  *       overrideChannelState() on any channel that has ::setState() called
1131  *       on it.  Unlike with ::setState(), clients using
1132  *       overrideChannelState() are responsible for ensuring that data is
1133  *       up to date for updateReport() calls.  The correct way to do this
1134  *       is for a driver's ::updateReport() method to push the most up to
1135  *       date values into the reporters before calling
1136  *       super::updateReport().
1137  *
1138  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1139  */
1140 	IOReturn overrideChannelState(uint64_t channel_id,
1141 	    uint64_t state_id,
1142 	    uint64_t time_in_state,
1143 	    uint64_t intransitions,
1144 	    uint64_t last_intransition = 0);
1145 
1146 /*! @function   IOStateReporter::incrementChannelState
1147  *   @abstract   Updates state data for a channel with passed arguments
1148  *
1149  *   @param  channel_id - ID of the channel which state is to be updated
1150  *   @param  state_id - state id for the channel
1151  *   @param  time_in_state - time to be accumulated for time in state
1152  *   @param  intransitions - number of transitions into state to be added
1153  *   @param  last_intransition - mach_absolute_time of most recent entry (opt)
1154  *   @result     Appropriate IOReturn code
1155  *
1156  *   @discussion
1157  *       incrementChannelState() adds time_in_state and intransitions
1158  *       to the current values stored for a particular state.  If provided,
1159  *       last_intransition overwrites the time the state was most recently
1160  *       entered.  Passing 0 for time_in_state and intransitions will have
1161  *       no effect.  Passing 0 for last_intransition for all states will
1162  *       disable the notion of a channel's "current state."
1163  *
1164  *       The most recent last_intransition (amongst all states in a channel)
1165  *       logically determines the current state.  If last_intransition is
1166  *       not provided for any state, the channel will not report a current
1167  *       For consistent results, it is important to either never specify
1168  *       last_intransition or to always specify it.
1169  *
1170  *       There is currently a bug in determining current state (13423273).
1171  *       The IOReportMacros.h macros only update the state's metadata
1172  *       timestamp and libIOReport only looks at the metadata timestamps
1173  *       to determine the current state.  Until that bug is fixed, whichever
1174  *       state is updated most recently will be considered the "current"
1175  *       state by libIOReport.
1176  *
1177  *       ::setState()'s automatic "time in state" updates are not supported
1178  *       when using incrementChannelState().  Clients must not use
1179  *       incrementChannelState() on any channel that has ::setState()
1180  *       called on it.  Unlike with ::setState(), clients using
1181  *       incrementChannelState() are responsible for ensuring that data
1182  *       is up to date for updateReport() calls.  The correct way to do
1183  *       this is for a driver's ::updateReport() method to push the most
1184  *       up to date values into the reporters before calling
1185  *       super::updateReport().
1186  *
1187  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1188  */
1189 	IOReturn incrementChannelState(uint64_t channel_id,
1190 	    uint64_t state_id,
1191 	    uint64_t time_in_state,
1192 	    uint64_t intransitions,
1193 	    uint64_t last_intransition = 0);
1194 
1195 /*! @function   IOStateReporter::setStateByIndices
1196  *   @abstract   update a channel state without validating channel_id
1197  *
1198  *   @param  channel_index - 0..<nChannels>, available from getChannelIndex()
1199  *   @param  new_state_index - New state (by index) for the channel
1200  *   @result     Appropriate IOReturn code
1201  *
1202  *   @discussion
1203  *       Similar to setState(), setStateByIndices() sets a channel's state
1204  *       without searching for the channel or state IDs.  It will perform
1205  *       bounds checking, but relies on the caller to properly indicate
1206  *       the indices of the channel and state.  Clients can rely on channels
1207  *       being added to IOStateReporter in order: the first channel will
1208  *       have index 0, the second index 1, etc.  Like ::setState(),
1209  *       "time in state" calculations are handled automatically.
1210  *
1211  *       setStateByIndices() is faster than than setChannelState(), but
1212  *       it should only be used where the latter's performance overhead
1213  *       might be a problem.  For example, many channels in a single
1214  *       reporter and high-frequency state changes.
1215  *
1216  *       Drivers wishing to compute and report their own time in state
1217  *       should use incrementChannelState() or overrideChannelState().  It
1218  *       is not currently possible for a driver to synchronize with the
1219  *       automatic time-keeping enabled by setStateByIndices().  The
1220  *       4-argument version of setChannelState() is thus impossible to
1221  *       use correctly.  In the future, there may be a setChannelState()
1222  *       which accepts a last_intransition parameter and uses it to
1223  *       automatically calculate time in state (ERs -> IOReporting / X).
1224  *
1225  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1226  */
1227 	IOReturn setStateByIndices(int channel_index,
1228 	    int new_state_index);
1229 
1230 /*! @function   IOStateReporter::setStateByIndices
1231  *   @abstract   update a channel state without validating channel_id
1232  *
1233  *   @param  channel_index - 0..<nChannels>, available from getChannelIndex()
1234  *   @param  new_state_index - New state (by index) for the channel
1235  *   @param  last_intransition - deprecated: time of most recent entry
1236  *   @param  prev_state_residency - deprecated: time spent in previous state
1237  *   @result     Appropriate IOReturn code
1238  *
1239  *   @discussion
1240  *       Similar to setState(), setStateByIndices() sets a channel's state
1241  *       without searching for the channel or state IDs.  It will perform
1242  *       bounds checking, but relies on the caller to properly indicate
1243  *       the indices of the channel and state.  Clients can rely on channels
1244  *       being added to IOStateReporter in order: the first channel will
1245  *       have index 0, the second index 1, etc.  Like ::setState(),
1246  *       "time in state" calculations are handled automatically.
1247  *
1248  *       setStateByIndices() is faster than than setChannelState(), but
1249  *       it should only be used where the latter's performance overhead
1250  *       might be a problem.  For example, many channels in a single
1251  *       reporter and high-frequency state changes.
1252  *
1253  *       Drivers wishing to compute and report their own time in state
1254  *       should use incrementChannelState() or overrideChannelState().  It
1255  *       is not currently possible for a driver to synchronize with the
1256  *       automatic time-keeping enabled by setStateByIndices().  The
1257  *       4-argument version of setChannelState() is thus impossible to
1258  *       use correctly.  In the future, there may be a setChannelState()
1259  *       which accepts a last_intransition parameter and uses it to
1260  *       automatically calculate time in state (ERs -> IOReporting / X).
1261  *
1262  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1263  */
1264 	IOReturn setStateByIndices(int channel_index,
1265 	    int new_state_index,
1266 	    uint64_t last_intransition,
1267 	    uint64_t prev_state_residency) __deprecated;
1268 
1269 /*! @function   IOStateReporter::getStateInTransitions
1270  *   @abstract   Accessor method for count of transitions into state
1271  *
1272  *   @param  channel_id - ID of the channel
1273  *   @param  state_id - State of the channel
1274  *   @result     Count of transitions into the requested state.
1275  *
1276  *   @discussion
1277  *       Some clients may need to consume internally the data aggregated by the
1278  *       reporter object. This method allows a client to retrieve the count of
1279  *       transitions into the requested state for the channel_id.
1280  *
1281  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1282  */
1283 	uint64_t getStateInTransitions(uint64_t channel_id,
1284 	    uint64_t state_id);
1285 
1286 /*! @function   IOStateReporter::getStateResidencyTime
1287  *   @abstract   Accessor method for time spent in a given state
1288  *
1289  *   @param  channel_id - ID of the channel
1290  *   @param  state_id - State of the channel
1291  *   @result     Absolute time spent in specified state
1292  *
1293  *   @discussion
1294  *       Some clients may need to consume internally the data aggregated
1295  *       by the by the reporter object.  This method allows a client to
1296  *       retrieve the absolute time a particular channel recorded as spent
1297  *       in a specified state.
1298  *
1299  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1300  */
1301 	uint64_t getStateResidencyTime(uint64_t channel_id,
1302 	    uint64_t state_id);
1303 
1304 /*! @function   IOStateReporter::getStateLastTransitionTime
1305  *   @abstract   Accessor method for last time a transition occured
1306  *
1307  *   @param  channel_id - ID of the channel
1308  *   @param  state_id - State of the channel
1309  *   @result     Absolute time for when the last transition occured
1310  *
1311  *   @discussion
1312  *       Some clients may need to consume internally the data aggregated
1313  *       by the by the reporter object.  This method allows a client to
1314  *       retrieve the absolute time stamp for when the last transition into
1315  *       a specific state was recorded.
1316  *
1317  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1318  */
1319 	uint64_t getStateLastTransitionTime(uint64_t channel_id, uint64_t state_id);
1320 
1321 /*! @function   [DEPRECATED] IOStateReporter::getStateLastChannelUpdateTime
1322  *   @abstract   Deprecated accessor for last time a channel was auto-updated
1323  *
1324  *   @param  channel_id - ID of the channel
1325  *   @result     Absolute time for last time the channel was updated
1326  *
1327  *   @discussion
1328  *       If a channel has had ::setState() called on it, calls such as
1329  *       getStateResidencyTime() or updateReport() will update time in the
1330  *       current state and update an internal "last channel update time."
1331  *       Because clients have no way to interlock with those methods, there
1332  *       is no sensible way to use this method and it will be removed in
1333  *       a future release.
1334  *
1335  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1336  */
1337 	uint64_t getStateLastChannelUpdateTime(uint64_t channel_id) __deprecated;
1338 
1339 /*! @function   IOStateReporter::createLegend
1340  *   @abstract   Creates a legend entry for an IOStateReporter
1341  *
1342  *   @param  channelIDs - array of uint64_t channels IDs.
1343  *   @param  channelNames - parrallel array of const char* channel names
1344  *   @param  channelCount - number of channels, and size of channelIDs and channelNames
1345  *   @param  nstates - Maximum number of states for this reporter's channels
1346  *   @param  categories - The category in which the report should be classified
1347  *   @param  unit - The unit for the quantity recorded by the reporter object
1348  *
1349  *   @result     An IOReportLegendEntry object or NULL on failure
1350  *
1351  *   @discussion
1352  *       This static method supports creating a legend entry for an IOStateReporter
1353  *       without actually having an IOStateReporter instance.
1354  *       This can be used to lazily create IOReporters in IOService::configureReport()
1355  *       rather than during driver initialization.
1356  */
1357 	static OSPtr<IOReportLegendEntry> createLegend(const uint64_t *channelIDs,
1358 	    const char **channelNames,
1359 	    int channelCount,
1360 	    int nstates,
1361 	    IOReportCategories categories,
1362 	    IOReportUnit unit);
1363 
1364 /*! @function   IOStateReporter::free
1365  *   @abstract   Releases the object and all its resources.
1366  *
1367  *   @discussion
1368  *       ::free() assumes that init() has completed.  Clients should use
1369  *       the static ::with() methods to obtain fully-initialized reporter
1370  *       instances.
1371  *
1372  *   Locking: same-instance concurrency UNSAFE
1373  */
1374 	virtual void free(void) APPLE_KEXT_OVERRIDE;
1375 
1376 protected:
1377 
1378 /*! @function   IOStateReporter::initWith
1379  *   @abstract   Instance method implementation called by ::with
1380  *
1381  *   @discussion
1382  *       See description of parameters above
1383  */
1384 	virtual bool initWith(IOService *reportingService,
1385 	    IOReportCategories categories,
1386 	    int16_t nstates, IOReportUnit unit);
1387 
1388 
1389 /*! @function   IOStateReporter::handleSwapPrepare
1390  *   @abstract   _swap* = <IOStateReporter-specific per-channel buffers>
1391  *   [see IOReporter::handle*Swap* for more info]
1392  */
1393 	virtual IOReturn handleSwapPrepare(int newNChannels) APPLE_KEXT_OVERRIDE;
1394 
1395 /*!
1396  *   @function   IOStateReporter::handleAddChannelSwap
1397  *   @abstract   swap in IOStateReporter's variables
1398  */
1399 	virtual IOReturn handleAddChannelSwap(uint64_t channel_id,
1400 	    const OSSymbol *symChannelName) APPLE_KEXT_OVERRIDE;
1401 
1402 /*!
1403  *   @function   IOStateReporter::handleSwapCleanup
1404  *   @abstract   clean up unused buffers in _swap*
1405  */
1406 	virtual void handleSwapCleanup(int swapNChannels) APPLE_KEXT_OVERRIDE;
1407 
1408 /*! @function   IOStateReporter::updateChannelValues
1409  *   @abstract   Update accounting of time spent in current state
1410  *
1411  *   @param  channel_index - internal index of the channel
1412  *   @result     appropriate IOReturn code
1413  *
1414  *   @discussion
1415  *       Internal State reporter method to account for the time spent in
1416  *       the current state when updateReport() is called on the reporter's
1417  *       channels.
1418  *
1419  *   Locking: Caller must ensure that the reporter (data) lock is held.
1420  */
1421 	virtual IOReturn updateChannelValues(int channel_index) APPLE_KEXT_OVERRIDE;
1422 
1423 /*! @function   IOStateReporter::handleSetStateByIndices
1424  *   @abstract   update a channel state without validating channel_id
1425  *
1426  *   @param  channel_index - 0..<nChannels>, available from getChannelIndex()
1427  *   @param  new_state_index - New state for the channel
1428  *   @param  last_intransition - to remove: time of most recent entry
1429  *   @param  prev_state_residency - to remove: time spent in previous state
1430  *   @result     Appropriate IOReturn code
1431  *
1432  *   @discussion
1433  *       Locked version of IOReporter::setStateByIndices().  This method may be
1434  *       overriden by sub-classes.
1435  *
1436  *   Locking: Caller must ensure that the reporter (data) lock is held.
1437  */
1438 	virtual IOReturn handleSetStateByIndices(int channel_index,
1439 	    int new_state_index,
1440 	    uint64_t last_intransition,
1441 	    uint64_t prev_state_residency);
1442 
1443 /*! @function   IOStateReporter::handleSetStateID
1444  *   @abstract   Assign a non-default ID to a state
1445  *
1446  *   @param  channel_id - ID of channel containing the state in question
1447  *   @param  state_index - index of state to give an ID: [0..(nstates-1)]
1448  *   @param  state_id - 64-bit state ID, for ASCII, use IOREPORT_MAKEID
1449  *
1450  *   @result     Appropriate IOReturn code
1451  *
1452  *   @discussion
1453  *       Locked version of IOReporter::setStateID(). This method may be
1454  *       overriden by sub-classes
1455  *
1456  *   Locking: Caller must ensure that the reporter (data) lock is held.
1457  */
1458 	virtual IOReturn handleSetStateID(uint64_t channel_id,
1459 	    int state_index,
1460 	    uint64_t state_id);
1461 
1462 /*! @function   IOStateReporter::handleOverrideChannelStateByIndices
1463  *   @abstract   Overrides state data for a channel with passed arguments
1464  *
1465  *   @param  channel_index - index of the channel which state is to be updated
1466  *   @param  state_index - index of the state id for the channel
1467  *   @param  time_in_state - time used as new total time in state
1468  *   @param  intransitions - total number of transitions into state
1469  *   @param  last_intransition - mach_absolute_time of most recent entry (opt)
1470  *   @result     Appropriate IOReturn code
1471  *
1472  *   @discussion
1473  *       Locked version of IOReporter::overrideChannelState().  This method
1474  *       may be overriden by sub-classes.
1475  *
1476  *   Locking: Caller must ensure that the reporter (data) lock is held.
1477  */
1478 	virtual IOReturn handleOverrideChannelStateByIndices(int channel_index,
1479 	    int state_index,
1480 	    uint64_t time_in_state,
1481 	    uint64_t intransitions,
1482 	    uint64_t last_intransition = 0);
1483 
1484 /*! @function   IOStateReporter::handleIncrementChannelStateByIndices
1485  *   @abstract   Updates state data for a channel with passed arguments
1486  *
1487  *   @param  channel_index - index of the channel which state is to be updated
1488  *   @param  state_index - index of the state id for the channel
1489  *   @param  time_in_state - time used as new total time in state
1490  *   @param  intransitions - total number of transitions into state
1491  *   @param  last_intransition - mach_absolute_time of most recent entry (opt)
1492  *   @result     Appropriate IOReturn code
1493  *
1494  *   @discussion
1495  *       Locked version of IOReporter::incrementChannelState(). This method
1496  *       may be overriden by sub-classes.
1497  *
1498  *   Locking: Caller must ensure that the reporter (data) lock is held.
1499  */
1500 	virtual IOReturn handleIncrementChannelStateByIndices(int channel_index,
1501 	    int state_index,
1502 	    uint64_t time_in_state,
1503 	    uint64_t intransitions,
1504 	    uint64_t last_intransition = 0);
1505 private:
1506 
1507 	int            *_currentStates;     // current states (per chonnel)
1508 	uint64_t       *_lastUpdateTimes;   // most recent auto-update
1509 
1510 // Required for swapping inside addChannel
1511 	int            *_swapCurrentStates;
1512 	uint64_t       *_swapLastUpdateTimes;
1513 
1514 	enum valueSelector {
1515 		kInTransitions,
1516 		kResidencyTime,
1517 		kLastTransitionTime
1518 	};
1519 	uint64_t _getStateValue(uint64_t channel_id,
1520 	    uint64_t state_id,
1521 	    enum valueSelector value);
1522 
1523 	IOReturn _getStateIndices(uint64_t channel_id,
1524 	    uint64_t state_id,
1525 	    int *channel_index,
1526 	    int *state_index);
1527 };
1528 
1529 
1530 /*!
1531  *   @class      IOHistogramReporter
1532  *   @abstract   Report histograms of values
1533  *   @discussion
1534  *       Each IOHistogramReporter can report one histogram representing
1535  *       how a given value has changed over time.
1536  */
1537 class IOHistogramReporter : public IOReporter
1538 {
1539 	OSDeclareDefaultStructors(IOHistogramReporter);
1540 
1541 public:
1542 /*! @function   IOHistogramReporter::with
1543  *   @abstract   Initializes the IOHistogramReporter instance variables and data structures
1544  *
1545  *   @param  reportingService - The I/O Kit service for this reporter's channels
1546  *   @param  categories - The categories in which the report should be classified
1547  *   @param  channelID - uint64_t channel identifier
1548  *   @param  channelName - rich channel name as char*
1549  *   @param  unit - The unit for the quantity recorded by the reporter object
1550  *   @param  nSegments - Number of segments to be extracted from the config data structure
1551  *   @param  config - Histograms require the caller to pass a configuration by segments
1552  *   @result     an instance of the IOSimpleReporter object or NULL on error
1553  *
1554  *   @discussion
1555  *       Creates an instance of histogram reporter object.
1556  *
1557  *  FIXME: need more explanation of the config
1558  *
1559  *       IOHistogramReporter currently only supports a single channel.
1560  *
1561  *
1562  */
1563 	static OSPtr<IOHistogramReporter> with(IOService *reportingService,
1564 	    IOReportCategories categories,
1565 	    uint64_t channelID,
1566 	    const char *channelName,
1567 	    IOReportUnit unit,
1568 	    int nSegments,
1569 	    IOHistogramSegmentConfig *config);
1570 
1571 /*! @function   IOHistogramReporter::addChannel
1572  *   @abstract   Override IOReporter::addChannel(*) to return an error
1573  *
1574  *   @result     kIOReturnUnsupported - doesn't support adding channels
1575  */
1576 	IOReturn
1577 	addChannel(__unused uint64_t channelID, __unused const char *channelName = NULL)
1578 	{
1579 		return kIOReturnUnsupported;
1580 	}
1581 
1582 /*! @function   IOHistogramReporter::overrideBucketValues
1583  *   @abstract   Override values of a bucket at specified index
1584  *
1585  *   @param  index - index of bucket to override
1586  *   @param  bucket_hits - new bucket hits count
1587  *   @param  bucket_min - new bucket minimum value
1588  *   @param  bucket_max - new bucket maximum value
1589  *   @param  bucket_sum - new bucket sum
1590  *   @result     Appropriate IOReturn code
1591  *
1592  *   @discussion
1593  *       Replaces data in the bucket at the specified index with the data pointed
1594  *       to by bucket. No sanity check is performed on the data. If the index
1595  *       is out of bounds, kIOReturnBadArgument is returned.
1596  *
1597  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1598  */
1599 
1600 	IOReturn overrideBucketValues(unsigned int index,
1601 	    uint64_t bucket_hits,
1602 	    int64_t bucket_min,
1603 	    int64_t bucket_max,
1604 	    int64_t bucket_sum);
1605 
1606 /*! @function   IOHistogramReporter::tallyValue
1607  *   @abstract   Add a new value to the histogram
1608  *
1609  *   @param  value - new value to add to the histogram
1610  *   @result     the index of the affected bucket, or -1 on error
1611  *
1612  *   @discussion
1613  *       The histogram reporter determines in which bucket the value
1614  *       falls and increments it.  The lowest and highest buckets
1615  *       extend to negative and positive infinity, respectively.
1616  *
1617  *   Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1618  */
1619 	int tallyValue(int64_t value);
1620 
1621 /*! @function   IOHistogramReporter::createLegend
1622  *   @abstract   Creates a legend entry for an IOStateReporter
1623  *
1624  *   @param  channelID - uint64_t channel identifier
1625  *   @param  channelName - rich channel name as char*
1626  *   @param  segmentCount - Number of segments to be extracted from the config data structure
1627  *   @param  config - Histograms require the caller to pass a configuration by segments
1628  *   @param  categories - The category in which the report should be classified
1629  *   @param  unit - The unit for the quantity recorded by the reporter object
1630  *
1631  *   @result     An IOReportLegendEntry object or NULL on failure
1632  *
1633  *   @discussion
1634  *       This static method supports creating a legend entry for an IOStateReporter
1635  *       without actually having an IOStateReporter instance.
1636  *       This can be used to lazily create IOReporters in IOService::configureReport()
1637  *       rather than during driver initialization.
1638  */
1639 	static OSPtr<IOReportLegendEntry> createLegend(const uint64_t channelID,
1640 	    const char *channelName,
1641 	    int segmentCount,
1642 	    IOHistogramSegmentConfig *config,
1643 	    IOReportCategories categories,
1644 	    IOReportUnit unit);
1645 
1646 /*! @function   IOHistogramReporter::free
1647  *   @abstract   Releases the object and all its resources.
1648  *
1649  *   @discussion
1650  *      ::free() assumes that init() has completed.  Clients should use
1651  *      the static ::with() methods to obtain fully-initialized reporter
1652  *      instances.
1653  *
1654  *   Locking: same-instance concurrency UNSAFE
1655  */
1656 	virtual void free(void) APPLE_KEXT_OVERRIDE;
1657 
1658 protected:
1659 
1660 /*! @function   IOHistogramReporter::initWith
1661  *   @abstract   instance method implementation called by ::with
1662  *
1663  *   @discussion
1664  *       See description of parameters above
1665  */
1666 	virtual bool initWith(IOService *reportingService,
1667 	    IOReportCategories categories,
1668 	    uint64_t channelID,
1669 	    const OSSymbol *channelName,
1670 	    IOReportUnit unit,
1671 	    int nSegments,
1672 	    IOHistogramSegmentConfig  *config);
1673 
1674 /*! @function   IOHistogramReporter::handleCreateLegend
1675  *   @abstract   Builds an IOReporting legend entry representing the channels of this reporter.
1676  *
1677  *   @result     An IOReportLegendEntry or NULL on failure
1678  *
1679  *   @discussion
1680  *       The returned legend entry may be appended to kIOReportLegendKey
1681  *       to be published by the caller in the IORegistry.  See the
1682  *       IOReportLegend class for more details.
1683  *
1684  *   Locking: same-instance concurrency SAFE, MAY BLOCK
1685  */
1686 	OSPtr<IOReportLegendEntry> handleCreateLegend(void) APPLE_KEXT_OVERRIDE;
1687 
1688 
1689 private:
1690 
1691 	int                         _segmentCount;
1692 	int64_t                    *_bucketBounds;
1693 	int                         _bucketCount;
1694 	IOHistogramSegmentConfig   *_histogramSegmentsConfig;
1695 };
1696 
1697 
1698 /***********************************/
1699 /***** 4. IOReportLegend Class *****/
1700 /***********************************/
1701 
1702 /*!
1703  *   @class      IOReportLegend
1704  *   @abstract   combine legend entries into a complete legend
1705  *   @discussion
1706  *       IOReportLegend adds metadata to legend entries and combines them
1707  *       into a single OSArray that can be published under the
1708  *       kIOReportLegendKey property in the I/O Kit registry.
1709  */
1710 class IOReportLegend : public OSObject
1711 {
1712 	OSDeclareDefaultStructors(IOReportLegend);
1713 
1714 public:
1715 /*! @function   IOReportLegend::with
1716  *   @abstract   Create an instance of IOReportLegend
1717  *
1718  *   @param  legend - OSArray of the legend possibly already present in registry
1719  *   @result     an instance of IOReportLegend, or NULL on failure
1720  *
1721  *   @discussion
1722  *       An IOReporting legend (an OSArray of legend entries) may be already
1723  *       present in the IORegistry.  Thus the recommended way to publish
1724  *       new entries is to append to any existing array as follows:
1725  *       1. call getProperty(kIOReportLegendKey) to get an existing legend.
1726  *
1727  *       2a. If it exists
1728  *       - OSDynamicCast to OSArray
1729  *       - and pass it to ::with()
1730  *       IOReportLegend *legendMaker = IOReportLegend::with(legend);
1731  *       The provided array is retained by IOReportLegend.
1732  *
1733  *       2b. If no legend already exists in the registry, pass NULL
1734  *       IOReportLegend *legend = IOReportLegend::with(NULL);
1735  *       This latter invocation will cause IOReportLegend to create a new
1736  *       array internally (also holding one reference).
1737  *
1738  *       At the cost of some registry churn, the static
1739  *       IOReportLegend::addReporterLegend() will handle the above, removing
1740  *       the need for any direct use of the IOReportLegend class.
1741  */
1742 	static OSPtr<IOReportLegend> with(OSArray *legend);
1743 
1744 /*! @function   IOReportLegend::addLegendEntry
1745  *   @abstract   Add a new legend entry
1746  *
1747  *   @param  legendEntry - entry to be added to the internal legend array
1748  *   @param  groupName - primary group name for this entry
1749  *   @param  subGroupName - secondary group name for this entry
1750  *   @result     appropriate IOReturn code
1751  *
1752  *   @discussion
1753  *       The entry will be retained as an element of the internal array.
1754  *       Legend entries are available from reporter objects.  Entries
1755  *       represent some number of channels with similar properties (such
1756  *       as group and sub-group).  Multiple legend entries with the same
1757  *       group names will be aggregated in user space.
1758  *
1759  *       Drivers that instantiate their reporter objects in response to
1760  *       IOService::configureReport(kIOReportDisable) will need to create
1761  *       temporary reporter objects for the purpose of creating their
1762  *       legend entries.  User-space legends are tracked by 12836893.
1763  */
1764 	IOReturn addLegendEntry(IOReportLegendEntry *legendEntry,
1765 	    const char *groupName,
1766 	    const char *subGroupName);
1767 
1768 /*! @function   IOReportLegend::addReporterLegend
1769  *   @abstract   Add a legend entry from a reporter object
1770  *
1771  *   @param  reporter - IOReporter to use to extract and append the legend
1772  *   @param  groupName - primary group name for this entry
1773  *   @param  subGroupName - secondary group name for this entry
1774  *   @result     appropriate IOReturn code
1775  *
1776  *   @discussion
1777  *       An IOReportLegendEntry will be created internally to this method from
1778  *       the IOReporter object passed in argument. The entry will be released
1779  *       internally after being appended to the IOReportLegend object.
1780  *       Legend entries are available from reporter objects.  Entries
1781  *       represent some number of channels with similar properties (such
1782  *       as group and sub-group).  Multiple legend entries with the same
1783  *       group names will be aggregated in user space.
1784  *
1785  *       Drivers that instantiate their reporter objects in response to
1786  *       IOService::configureReport(kIOReportDisable) will need to create
1787  *       temporary reporter objects for the purpose of creating their
1788  *       legend entries.  User-space legends are tracked by 12836893.
1789  *
1790  *       Locking: same-reportingService and same-IORLegend concurrency UNSAFE
1791  */
1792 	IOReturn addReporterLegend(IOReporter *reporter,
1793 	    const char *groupName,
1794 	    const char *subGroupName);
1795 
1796 /*! @function   IOReportLegend::addReporterLegend
1797  *   @abstract   Add a legend entry from a reporter object
1798  *
1799  *   @param  reportingService - IOService data provider into the reporter object
1800  *   @param  reporter - IOReporter to use to extract and append the legend
1801  *   @param  groupName - primary group name for this entry
1802  *   @param  subGroupName - secondary group name for this entry
1803  *   @result     appropriate IOReturn code
1804  *
1805  *   @discussion
1806  *       An IOReportLegendEntry will be created internally to this method from
1807  *       the IOReporter object passed in argument. The entry will be released
1808  *       internally after being appended to the IOReportLegend object.
1809  *       Legend entries are available from reporter objects.  Entries
1810  *       represent some number of channels with similar properties (such
1811  *       as group and sub-group).  Multiple legend entries with the same
1812  *       group names will be aggregated in user space.
1813  *
1814  *       Drivers that instantiate their reporter objects in response to
1815  *       IOService::configureReport(kIOReportDisable) will need to create
1816  *       temporary reporter objects for the purpose of creating their
1817  *       legend entries.  User-space legends are tracked by 12836893.
1818  *
1819  *       The static version of addReporterLegend adds the reporter's legend
1820  *       directly to reportingService's kIOReportLegendKey.  It is not
1821  *       possible to safely update kIOReportLegendKey from multiple threads.
1822  *
1823  *       Locking: same-reportingService and same-IORLegend concurrency UNSAFE
1824  */
1825 	static  IOReturn addReporterLegend(IOService *reportingService,
1826 	    IOReporter *reporter,
1827 	    const char *groupName,
1828 	    const char *subGroupName);
1829 
1830 /*! @function   IOReportLegend::getLegend
1831  *   @abstract   Accessor method to get the legend array
1832  *
1833  *   @result     Returns the OSObject holding the legend to be published by the driver
1834  *   @discussion
1835  *       This array will include all legend entries added to the object.
1836  */
1837 	OSArray* getLegend(void);
1838 
1839 /*! @function   IOReportLegend::free
1840  *   @abstract   Frees the IOReportLegend object
1841  *
1842  *   @discussion
1843  *       ::free() cleans up the reporter and anything it allocated.
1844  *
1845  *       ::free() releases the internal array (which was either passed
1846  *       to ::with() or created as a result of ::with(NULL)).  Assuming
1847  *       the caller extracted the array with getLegend() and published it
1848  *       in the I/O Kit registry, its ownership will now be with the
1849  *       registry.
1850  */
1851 	void free(void) APPLE_KEXT_OVERRIDE;
1852 
1853 
1854 
1855 protected:
1856 
1857 private:
1858 
1859 	OSPtr<OSArray>     _reportLegend;
1860 
1861 	IOReturn initWith(OSArray *legend);
1862 
1863 /*! @function   IOReportLegend::organizeLegend
1864  *   @abstract   Sets up the legend entry, organizing it with group and sub-group names
1865  *
1866  *   @param  groupName - Primary group name
1867  *   @param  subGroupName - Secondary group name
1868  *   @result     IOReturn code
1869  */
1870 	IOReturn organizeLegend(IOReportLegendEntry *legendEntry,
1871 	    const OSSymbol *groupName,
1872 	    const OSSymbol *subGroupName);
1873 
1874 // FUTURE POSSIBILITY (NOT IMPLEMENTED!)
1875 /*! @function   IOReportLegend::createReporters
1876  *   @abstract   Creates as many IOReporter objects as the legend contains
1877  *
1878  *   @param  legend - OSArray legend object containing the description of all reporters
1879  *           the driver is able to address
1880  *   @param  reporter - OSSet of reporter objects created by this call
1881  *   @result     IOReturn code kIOReturnSuccess if successful
1882  *
1883  *   @discussion
1884  *       NOT SUPPORTED at the time of writing
1885  *       Convenience method to create all the driver's reporter objects from a legend.
1886  *       Can be used when a legend is made public through the IORegistry but IOReporter
1887  *       objects have not yet been created to save memory, waiting for observers.
1888  *       Upon a call to configureReport via the IOService method, a driver could
1889  *       create all reporter objects on the fly using this function.
1890  */
1891 // For Future IOReporterManager...
1892 // static IOReturn createReporters(requestedChannels, legend);
1893 };
1894 
1895 #endif  /* ! _IOKERNEL_REPORTERS_H_ */
1896