1/* 2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#ifndef _IOKERNELDEBUGGER_H 24#define _IOKERNELDEBUGGER_H 25 26#include <IOKit/IOService.h> 27 28/*! @typedef IODebuggerRxHandler 29 @discussion Defines the receive handler that must be implemented 30 by the target to service KDP receive requests. This handler is called 31 by kdpReceiveDispatcher(). 32 @param target The target object. 33 @param buffer KDP receive buffer. The buffer allocated has room for 34 1518 bytes. The receive handler must not overflow this buffer. 35 @param length The amount of data received and placed into the buffer. 36 Set to 0 if no frame was received during the poll interval. 37 @param timeout The amount of time to poll in milliseconds while waiting 38 for a frame to arrive. */ 39 40typedef void (*IODebuggerRxHandler)( IOService * target, 41 void * buffer, 42 UInt32 * length, 43 UInt32 timeout ); 44 45/*! @typedef IODebuggerTxHandler 46 @discussion Defines the transmit handler that must be implemented 47 by the target to service KDP transmit requests. This handler is called 48 by kdpTransmitDispatcher(). 49 @param target The target object. 50 @param buffer KDP transmit buffer. This buffer contains a KDP frame 51 to be sent on the network. 52 @param length The number of bytes in the transmit buffer. */ 53 54typedef void (*IODebuggerTxHandler)( IOService * target, 55 void * buffer, 56 UInt32 length ); 57 58/*! @typedef IODebuggerLinkStatusHandler 59 @discussion Defines the link up handler that must be implemented 60 by the target to service KDP link status requests. This handler is called 61 by kdpLinkStatusDispatcher(). 62 @param target The target object. 63 @result Return link status. 64*/ 65 66typedef UInt32 (*IODebuggerLinkStatusHandler)( IOService * target); 67 68/*! @typedef IODebuggerSetModeHandler 69 @discussion Defines the mode handler that must be implemented 70 by the target to service KDP link status requests. This handler is called 71 by kdpSetModeDispatcher(). 72 @param target The target object. 73 @param active True if entering KDP and false if exiting KDP. 74 @result Return true on success and false on failure. 75*/ 76 77typedef bool (*IODebuggerSetModeHandler)( IOService * target, bool active); 78 79/*! @typedef IODebuggerLockState 80 @discussion Defines flags returned by IOKernelDebugger::lock(). 81 @constant kIODebuggerLockTaken Set if the debugger lock was taken. */ 82 83typedef enum { 84 kIODebuggerLockTaken = 0x1 85} IODebuggerLockState; 86 87/*! @class IOKernelDebugger 88 @abstract Kernel debugger nub. 89 @discussion This object interfaces with the KDP 90 (kernel debugger protocol) module and dispatches KDP requests to its 91 target (provider). The target, designated as the debugger device, must 92 implement a pair of handler functions that are called to handle KDP 93 transmit and receive requests during a debugging session. Only a single 94 IOKernelDebugger in the system can be active at a given time. The 95 active IOKernelDebugger is the one that has an IOKDP object attached 96 as a client. 97 98 The debugger device is usually a subclass of IOEthernetController. 99 However, any IOService can service an IOKernelDebugger client, 100 implement the two polled mode handlers, and transport the KDP 101 packets through a data channel. However, KDP assumes that the 102 debugger device is an Ethernet interface and therefore it will 103 always send, and expect to receive, an Ethernet frame. */ 104 105class IOKernelDebugger : public IOService 106{ 107 OSDeclareDefaultStructors( IOKernelDebugger ) 108 109protected: 110 IOService * _target; // target (provider) 111 IODebuggerTxHandler _txHandler; // target's transmit handler. 112 IODebuggerRxHandler _rxHandler; // target's receive handler. 113 IOService * _client; // client that has opened us. 114 bool _pmDisabled; // true if disabled by PM. 115 116 struct ExpansionData { 117 thread_call_t activationChangeThreadCall; 118 UInt32 stateVars[2]; 119 IONotifier * interfaceNotifier; 120 IODebuggerLinkStatusHandler linkStatusHandler; // target's link status handler. 121 IODebuggerSetModeHandler setModeHandler; // target's KDP mode handler. 122 }; 123 124 /*! @var reserved 125 Reserved for future use. (Internal use only) */ 126 ExpansionData * _reserved; 127 128/*! @function kdpReceiveDispatcher 129 @abstract The KDP receive dispatch function. 130 @discussion Field KDP receives requests, then dispatches the call to the 131 registered receiver handler. 132 @param buffer KDP receive buffer. The buffer allocated by KDP has room 133 for 1518 bytes. The receive handler must not overflow this buffer. 134 @param length The amount of data received and placed into the buffer. 135 Set to 0 if a frame was not received during the poll interval. 136 @param timeout The amount of time to poll in milliseconds while waiting 137 for a frame to arrive. 138*/ 139 140 static void kdpReceiveDispatcher(void * buffer, 141 UInt32 * length, 142 UInt32 timeout); 143 144/*! @function kdpTransmitDispatcher 145 @abstract The KDP transmit dispatch function. 146 @discussion Field KDP transmit requests, then dispatches the call to the 147 registered transmit handler. 148 @param buffer KDP transmit buffer. This buffer contains a KDP frame to 149 be sent on the network. 150 @param length The number of bytes in the transmit buffer. 151*/ 152 153 static void kdpTransmitDispatcher(void * buffer, UInt32 length); 154 155/*! @function kdpLinkStatusDispatcher 156 @abstract The KDP link status dispatch function. 157 @discussion Field KDP link status requests, then dispatches the call to the 158 registered link up handler. 159 @result Return link status. 160*/ 161 162 static UInt32 kdpLinkStatusDispatcher(void); 163 164 165/*! @function kdpSetModeDispatcher 166 @abstract The KDP set mode dispatch function. 167 @discussion Field KDP set mode requests, then dispatches the call to the 168 registered set mode handler. 169 @param active TRUE if entering KDP. FALSE if leaving KDP. 170 @result Return TRUE if the link is up and data can be sent/received. Otherwise, 171 return FALSE. 172*/ 173 174 static boolean_t kdpSetModeDispatcher(boolean_t active); 175 176/*! @function free 177 @abstract Frees the IOKernelDebugger instance. */ 178 179 virtual void free(); 180 181/*! @function nullTxHandler 182 @abstract Null transmit handler. 183 @discussion This function is registered as the transmit handler when an 184 IOKernelDebugger object surrenders its status as the active debugger nub. 185 Until another IOKernelDebugger object gets promoted, this function will 186 handle polled transmit requests from KDP. This function does nothing 187 useful. 188*/ 189 190 static void nullTxHandler( IOService * target, 191 void * buffer, 192 UInt32 length ); 193 194/*! @function nullRxHandler 195 @abstract Null receive handler. 196 @discussion This function is registered as the receive handler when an 197 IOKernelDebugger object surrenders its status as the active debugger nub. 198 Until another IOKernelDebugger object gets promoted, this function will 199 handle polled receive requests from KDP. This function does nothing 200 except to log a warning message. 201*/ 202 203 static void nullRxHandler( IOService * target, 204 void * buffer, 205 UInt32 * length, 206 UInt32 timeout ); 207 208/*! @function nullLinkStatusHandler 209 @abstract Null link status handler. 210 @discussion This function is registered as the link status handler when an 211 IOKernelDebugger object surrenders its status as the active debugger nub. 212 Until another IOKernelDebugger object gets promoted, this function will 213 handle polled link status requests from KDP. 214 @result This function will always report link up. 215*/ 216 217 static UInt32 nullLinkStatusHandler( IOService * target); 218 219/*! @function nullSetModeHandler 220 @abstract Null set mode handler. 221 @discussion This function is registered as the set mode handler when an 222 IOKernelDebugger object surrenders its status as the active debugger nub. 223 Until another IOKernelDebugger object gets promoted, this function will 224 handle set mode requests from KDP. 225 @result This function will always return true. 226*/ 227 228 static bool nullSetModeHandler( IOService * target, bool active); 229 230/*! @function registerHandler 231 @abstract Registers the target and the handler functions. 232 @discussion This method is called by handleOpen() and handleClose() 233 to register or unregister the target and its handler functions. 234 @param target The target object. 235 @param txHandler The transmit handler function. The null handler is 236 registered if the argument is zero. 237 @param rxHandler The receive handler function. The null handler is 238 @param linkUpHandler The linkup handler function. The null handler is 239 registered if the argument is zero. 240*/ 241 242 static void registerHandler( IOService * target, 243 IODebuggerTxHandler txHandler = 0, 244 IODebuggerRxHandler rxHandler = 0, 245 IODebuggerLinkStatusHandler linkUpHandler = 0, 246 IODebuggerSetModeHandler setModeHandler = 0); 247 248/*! @function powerStateWillChangeTo 249 @abstract Handles notification that the network controller will change 250 power state. 251 @discussion If the controller is about to become unusable, then the 252 controller's handlers are unregistered, and the controller is disabled. 253 @param flags Describe the capability of the controller in the new power 254 state. 255 @param stateNumber The number of the state in the state array that the 256 controller is switching to. 257 @param policyMaker The policy maker that manages the controller's 258 power state. 259 @result Returns the constant 3000000, to indicate a maximum of 3 seconds for the 260 preparation to complete, and an acknowledgement delivered to the 261 policy maker. 262*/ 263 264 virtual IOReturn powerStateWillChangeTo( IOPMPowerFlags flags, 265 unsigned long stateNumber, 266 IOService * policyMaker ); 267 268/*! @function powerStateDidChangeTo 269 @abstract Handles notification that the network controller did change 270 power state. 271 @discussion If the controller became usable, then the controller is 272 re-enabled, and the controller's handlers are re-registered. 273 @param flags Description of the capability of the controller in the new power 274 state. 275 @param stateNumber The number of the state in the state array that the 276 controller is switching to. 277 @param policyMaker The policy maker that manages the controller's 278 power state. 279 @result Returns the constant 3000000, to indicate a maximum of 3 seconds for the 280 preparation to complete, and an acknowledgement delivered to the 281 policy maker. 282*/ 283 284 virtual IOReturn powerStateDidChangeTo( IOPMPowerFlags flags, 285 unsigned long stateNumber, 286 IOService * policyMaker ); 287 288/*! @function handleOpen 289 @abstract Handles a client open. 290 @discussion This method is called by IOService::open() to handle an 291 open from a client (IOKDP) with the arbitration lock held. 292 @param forClient The client (IOKDP) requesting the open. 293 @param options Options passed to the open() call. Not used. 294 @param arg A family defined argument passed to the open() call. Not used. 295 @result Returns true on success, false otherwise. 296*/ 297 298 virtual bool handleOpen( IOService * forClient, 299 IOOptionBits options, 300 void * arg ); 301 302/*! @function handleClose 303 @abstract Handles a client close. 304 @discussion This method is called by IOService::close() to handle a 305 close from a client with the arbitration lock held. 306 @param forClient The client (IOKDP) requesting the close. 307 @param options Options passed to the close() call. Not used. 308*/ 309 310 virtual void handleClose( IOService * forClient, 311 IOOptionBits options ); 312 313/*! @function handleIsOpen 314 @abstract Queries whether a client has an open on this object. 315 @discussion This method is called by IOService::isOpen() with the 316 arbitration lock held. 317 @result Returns true if the specified client, or any client if none (0) is 318 specified, presently has an open on this object. 319*/ 320 321 virtual bool handleIsOpen( const IOService * forClient ) const; 322 323 static bool interfacePublished( 324 void *target, void *param, IOService *service, IONotifier *notifier ); 325 326public: 327 328/*! @function lock 329 @abstract Takes the debugger lock conditionally. 330 @discussion This method takes the debugger lock if the object given matches the 331 target registered by registerHandler(). 332 @param target The target or provider of an IOKernelDebugger object. 333 @result Returns kIODebuggerLockTaken if the lock was taken, or 0 otherwise. 334*/ 335 336 static IODebuggerLockState lock( IOService * target ); 337 338/*! @function unlock 339 @abstract Releases the debugger lock. 340 @discussion This method releases the debugger lock if the kIODebuggerLockTaken flag is 341 set in the argument. 342*/ 343 344 static void unlock( IODebuggerLockState state ); 345 346/*! @function init 347 @abstract Initializes an IOKernelDebugger instance. 348 @param target The target object that implements the debugger handlers. 349 @param txHandler The target's transmit handler. A pointer to a 'C' function. 350 @param rxHandler The target's receive handler. A pointer to a 'C' function. 351 @param linkStatusHandler The target's link status handler. A pointer to a 'C' function. 352 @param setModeHandler The target's set mode handler. A pointer to a 'C' function. 353 @result Returns true if the instance initialized successfully, false otherwise. 354*/ 355 356 virtual bool init( IOService * target, 357 IODebuggerTxHandler txHandler, 358 IODebuggerRxHandler rxHandler, 359 IODebuggerLinkStatusHandler linkUpHandler, 360 IODebuggerSetModeHandler setModeHandler); 361 362/*! @function debugger 363 @abstract Factory method that performs allocation and initialization 364 of an IOKernelDebugger object. 365 @param target The target object that implements the debugger handlers. 366 @param txHandler The target's transmit handler. A pointer to a 'C' function. 367 @param rxHandler The target's receive handler. A pointer to a 'C' function. 368 @param linkStatusHandler The target's link status handler. A pointer to a 'C' function. 369 @param setModeHandler The target's set mode handler. A pointer to a 'C' function. 370 @result Returns an IOKernelDebugger instance on success, 0 otherwise. 371*/ 372 373 static IOKernelDebugger * debugger( IOService * target, 374 IODebuggerTxHandler txHandler, 375 IODebuggerRxHandler rxHandler, 376 IODebuggerLinkStatusHandler linkStatusHandler, 377 IODebuggerSetModeHandler setModeHandler); 378 379 /* 380 * Entry point for generic messages delivered from the provider. 381 */ 382 383 virtual IOReturn message( UInt32 type, IOService * provider, void * arg ); 384 385/*! @function signalDebugger 386 @abstract Signal the kernel to enter the debugger when safe. 387*/ 388 static void signalDebugger(void); 389 390 // Virtual function padding 391 OSMetaClassDeclareReservedUnused( IOKernelDebugger, 0); 392 OSMetaClassDeclareReservedUnused( IOKernelDebugger, 1); 393 OSMetaClassDeclareReservedUnused( IOKernelDebugger, 2); 394 OSMetaClassDeclareReservedUnused( IOKernelDebugger, 3); 395}; 396 397// Concise form of the lock()/unlock() static member functions. 398// 399#define IODebuggerLock IOKernelDebugger::lock 400#define IODebuggerUnlock IOKernelDebugger::unlock 401 402#endif /* !_IOKERNELDEBUGGER_H */ 403