os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/specific/lcd.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/kernelhwsrv/bsptemplate/asspandvariant/template_variant/specific/lcd.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1009 @@
     1.4 +// Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of the License "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// template\Template_Variant\Specific\lcd.cpp
    1.18 +// Implementation of an LCD driver. 
    1.19 +// This file is part of the Template Base port
    1.20 +// N.B. This sample code assumes that the display supports setting the backlight on or off, 
    1.21 +// as well as adjusting the contrast and the brightness.
    1.22 +// 
    1.23 +//
    1.24 +
    1.25 +
    1.26 +
    1.27 +#include <videodriver.h>
    1.28 +#include "platform.h"
    1.29 +#include <nkern.h>
    1.30 +#include <kernel/kernel.h>
    1.31 +#include <kernel/kern_priv.h>
    1.32 +#include <kernel/kpower.h>
    1.33 +#include <template_assp_priv.h>
    1.34 +
    1.35 +
    1.36 +// TO DO: (mandatory)
    1.37 +// If the display supports Contrast and/or Brightness control then supply the following defines:
    1.38 +// This is only example code... you may need to modify it for your hardware
    1.39 +const TInt KConfigInitialDisplayContrast	= 128;
    1.40 +const TInt KConfigLcdMinDisplayContrast		= 1;
    1.41 +const TInt KConfigLcdMaxDisplayContrast		= 255;
    1.42 +const TInt KConfigInitialDisplayBrightness	= 128;
    1.43 +const TInt KConfigLcdMinDisplayBrightness	= 1;
    1.44 +const TInt KConfigLcdMaxDisplayBrightness	= 255;
    1.45 +
    1.46 +// TO DO: (mandatory)
    1.47 +// define a macro to calculate the screen buffer size
    1.48 +// This is only example code... you may need to modify it for your hardware
    1.49 +// aBpp is the number of bits-per-pixel, aPpl is the number of pixels per line and 
    1.50 +// aLpp number of lines per panel
    1.51 +#define FRAME_BUFFER_SIZE(aBpp,aPpl,aLpp)	(aBpp*aPpl*aLpp)/8	
    1.52 +																
    1.53 +
    1.54 +// TO DO: (mandatory)
    1.55 +// define the physical screen dimensions
    1.56 +// This is only example code... you need to modify it for your hardware
    1.57 +const TUint	KConfigLcdWidth					= 640;		// 640 pixels per line
    1.58 +const TUint	KConfigLcdHeight				= 480;		// 480 lines per panel
    1.59 +
    1.60 +// TO DO: (mandatory)
    1.61 +// define the characteristics of the LCD display
    1.62 +// This is only example code... you need to modify it for your hardware
    1.63 +const TBool	KConfigLcdIsMono				= EFalse;
    1.64 +const TBool	KConfigLcdPixelOrderLandscape	= ETrue;
    1.65 +const TBool	KConfigLcdPixelOrderRGB			= ETrue;
    1.66 +const TInt	KConfigLcdMaxDisplayColors		= 65536;
    1.67 +
    1.68 +
    1.69 +// TO DO: (mandatory)
    1.70 +// define the display dimensions in TWIPs
    1.71 +// A TWIP is a 20th of a point.  A point is a 72nd of an inch
    1.72 +// Therefore a TWIP is a 1440th of an inch
    1.73 +// This is only example code... you need to modify it for your hardware
    1.74 +const TInt	KConfigLcdWidthInTwips			= 9638;		// = 6.69 inches
    1.75 +const TInt	KConfigLcdHeightInTwips			= 7370;		// = 5.11 inches
    1.76 +
    1.77 +// TO DO: (mandatory)
    1.78 +// define the available display modes
    1.79 +// This is only example code... you need to modify it for your hardware
    1.80 +const TInt  KConfigLcdNumberOfDisplayModes	= 1;
    1.81 +const TInt  KConfigLcdInitialDisplayMode	= 0;
    1.82 +struct SLcdConfig
    1.83 +	{
    1.84 +	TInt iMode;
    1.85 +	TInt iOffsetToFirstVideoBuffer;
    1.86 +	TInt iLenghtOfVideoBufferInBytes;
    1.87 +	TInt iOffsetBetweenLines;
    1.88 +	TBool iIsPalettized;
    1.89 +	TInt iBitsPerPixel;
    1.90 +	};
    1.91 +static const SLcdConfig Lcd_Mode_Config[KConfigLcdNumberOfDisplayModes]=
    1.92 +	{
    1.93 +		{
    1.94 +		0,								// iMode
    1.95 +		0,								// iOffsetToFirstVideoBuffer
    1.96 +		FRAME_BUFFER_SIZE(8, KConfigLcdWidth, KConfigLcdHeight),	// iLenghtOfVideoBufferInBytes
    1.97 +		KConfigLcdWidth,				// iOffsetBetweenLines
    1.98 +		ETrue,							// iIsPalettized
    1.99 +		8								// iBitsPerPixel
   1.100 +		}
   1.101 +	};	
   1.102 +
   1.103 +
   1.104 +
   1.105 +_LIT(KLitLcd,"LCD");
   1.106 +
   1.107 +//
   1.108 +// TO DO: (optional)
   1.109 +//
   1.110 +// Add any private functions and data you require
   1.111 +//
   1.112 +NONSHARABLE_CLASS(DLcdPowerHandler) : public DPowerHandler
   1.113 +	{
   1.114 +public: 
   1.115 +	DLcdPowerHandler();
   1.116 +	~DLcdPowerHandler();
   1.117 +	
   1.118 +	// from DPowerHandler
   1.119 +	void PowerDown(TPowerState);
   1.120 +	void PowerUp();
   1.121 +
   1.122 +	void PowerUpDfc();
   1.123 +	void PowerDownDfc();
   1.124 +
   1.125 +	TInt Create();
   1.126 +	void DisplayOn();
   1.127 +	void DisplayOff();
   1.128 +	TInt HalFunction(TInt aFunction, TAny* a1, TAny* a2);
   1.129 +
   1.130 +	void PowerUpLcd(TBool aSecure);
   1.131 +	void PowerDownLcd();
   1.132 +
   1.133 +	void ScreenInfo(TScreenInfoV01& aInfo);
   1.134 +	void WsSwitchOnScreen();
   1.135 +	void WsSwitchOffScreen();
   1.136 +	void HandleMsg();
   1.137 +	void SwitchDisplay(TBool aSecure);
   1.138 +
   1.139 +	void SetBacklightState(TBool aState);
   1.140 +	void BacklightOn();
   1.141 +	void BacklightOff();
   1.142 +	TInt SetContrast(TInt aContrast);
   1.143 +	TInt SetBrightness(TInt aBrightness);
   1.144 +
   1.145 +private:
   1.146 +	TInt SetPaletteEntry(TInt aEntry, TInt aColor);
   1.147 +	TInt GetPaletteEntry(TInt aEntry, TInt* aColor);
   1.148 +	TInt NumberOfPaletteEntries();
   1.149 +	TInt GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure);
   1.150 +	TInt GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo);
   1.151 +	TInt SetDisplayMode(TInt aMode);
   1.152 +	void SplashScreen();
   1.153 +	TInt GetDisplayColors(TInt* aColors);
   1.154 +
   1.155 +private:
   1.156 +	TBool iIsPalettized;
   1.157 +	TBool iDisplayOn;				// to prevent a race condition with WServer trying to power up/down at the same time
   1.158 +	DPlatChunkHw* iChunk;
   1.159 +	DPlatChunkHw* iSecureChunk;
   1.160 +	TBool iWsSwitchOnScreen;
   1.161 + 	TBool iSecureDisplay;
   1.162 +	TDynamicDfcQue* iDfcQ;
   1.163 +	TMessageQue iMsgQ;
   1.164 +	TDfc iPowerUpDfc;
   1.165 +	TDfc iPowerDownDfc;	
   1.166 +	TVideoInfoV01 iVideoInfo;
   1.167 +	TVideoInfoV01 iSecureVideoInfo;
   1.168 +	NFastMutex iLock;				// protects against being preempted whilst manipulating iVideoInfo/iSecureVideoInfo
   1.169 +	TPhysAddr ivRamPhys;
   1.170 +	TPhysAddr iSecurevRamPhys;
   1.171 +
   1.172 +	TBool iBacklightOn;
   1.173 +	TInt iContrast;
   1.174 +	TInt iBrightness;
   1.175 +	};
   1.176 +
   1.177 +
   1.178 +/**
   1.179 +HAL handler function
   1.180 +
   1.181 +@param	aPtr a pointer to an instance of DLcdPowerHandler
   1.182 +@param	aFunction the function number
   1.183 +@param	a1 an arbitrary parameter
   1.184 +@param	a2 an arbitrary parameter
   1.185 +*/
   1.186 +LOCAL_C TInt halFunction(TAny* aPtr, TInt aFunction, TAny* a1, TAny* a2)
   1.187 +	{
   1.188 +	DLcdPowerHandler* pH=(DLcdPowerHandler*)aPtr;
   1.189 +	return pH->HalFunction(aFunction,a1,a2);
   1.190 +	}
   1.191 +
   1.192 +/**
   1.193 +DFC for receiving messages from the power handler
   1.194 +@param	aPtr a pointer to an instance of DLcdPowerHandler
   1.195 +*/
   1.196 +void rxMsg(TAny* aPtr)
   1.197 +	{
   1.198 +	DLcdPowerHandler& h=*(DLcdPowerHandler*)aPtr;
   1.199 +	h.HandleMsg();
   1.200 +	}
   1.201 +
   1.202 +/**
   1.203 +DFC for powering up the device
   1.204 +
   1.205 +@param aPtr	aPtr a pointer to an instance of DLcdPowerHandler
   1.206 +*/
   1.207 +void power_up_dfc(TAny* aPtr)
   1.208 +	{
   1.209 +	((DLcdPowerHandler*)aPtr)->PowerUpDfc();
   1.210 +	}
   1.211 +
   1.212 +/**
   1.213 +DFC for powering down the device
   1.214 +
   1.215 +@param aPtr	aPtr a pointer to an instance of DLcdPowerHandler
   1.216 +*/
   1.217 +void power_down_dfc(TAny* aPtr)
   1.218 +	{
   1.219 +	((DLcdPowerHandler*)aPtr)->PowerDownDfc();
   1.220 +	}
   1.221 +
   1.222 +
   1.223 +/**
   1.224 +Default constructor
   1.225 +*/
   1.226 +DLcdPowerHandler::DLcdPowerHandler() :
   1.227 +		DPowerHandler(KLitLcd),
   1.228 +		iMsgQ(rxMsg,this,NULL,1),
   1.229 +		iPowerUpDfc(&power_up_dfc,this,6),
   1.230 +		iPowerDownDfc(&power_down_dfc,this,7),
   1.231 +		iBacklightOn(EFalse),
   1.232 +		iContrast(KConfigInitialDisplayContrast),
   1.233 +		iBrightness(KConfigInitialDisplayBrightness)
   1.234 +	{
   1.235 +	}
   1.236 +
   1.237 +DLcdPowerHandler::~DLcdPowerHandler()
   1.238 +	{
   1.239 +	if (iDfcQ)
   1.240 +		iDfcQ->Destroy();
   1.241 +	}
   1.242 +
   1.243 +/**
   1.244 +Second-phase constructor 
   1.245 +
   1.246 +Called by factory function at ordinal 0
   1.247 +*/
   1.248 +TInt DLcdPowerHandler::Create()
   1.249 +	{
   1.250 +	const TInt KLCDDfcQPriority=27; // Equal to Kern::DfcQue0() priority
   1.251 +	TInt r = Kern::DynamicDfcQCreate(iDfcQ, KLCDDfcQPriority, _L("LCDPowerHandler"));
   1.252 +	if (r != KErrNone)
   1.253 +		{
   1.254 +		return r;
   1.255 +		}
   1.256 +
   1.257 +	// map the video RAM
   1.258 +	TInt vSize = ((TemplateAssp*)Arch::TheAsic())->VideoRamSize();
   1.259 +	ivRamPhys = TTemplate::VideoRamPhys();				// EXAMPLE ONLY: assume TTemplate interface class
   1.260 +	r = DPlatChunkHw::New(iChunk,ivRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
   1.261 +	if (r != KErrNone)
   1.262 +		return r;
   1.263 +	
   1.264 +	//create "secure" screen immediately after normal one
   1.265 +	iSecurevRamPhys =  ivRamPhys + vSize;
   1.266 +	TInt r2 = DPlatChunkHw::New(iSecureChunk,iSecurevRamPhys,vSize,EMapAttrUserRw|EMapAttrBufferedC);
   1.267 +	if (r2 != KErrNone)
   1.268 +		return r2;
   1.269 +
   1.270 +	TUint* pV=(TUint*)iChunk->LinearAddress();
   1.271 +
   1.272 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("DLcdPowerHandler::Create: VideoRamSize=%x, VideoRamPhys=%08x, VideoRamLin=%08x",vSize,ivRamPhys,pV));
   1.273 +
   1.274 +	// TO DO: (mandatory)
   1.275 +	// initialise the palette for the initial display mode
   1.276 +	// NOTE: the palette could either be a buffer allocated in system RAM (usually contiguous to Video buffer)
   1.277 +	//		 or could be offered as part of the hardware block that implemenst the lcd control
   1.278 +	//
   1.279 +
   1.280 +	TUint* pV2=(TUint*)iSecureChunk->LinearAddress();
   1.281 +
   1.282 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("DLcdPowerHandler::Create: Secure display VideoRamSize=%x, VideoRamPhys=%08x, VideoRamLin=%08x",vSize,iSecurevRamPhys,pV2));
   1.283 +
   1.284 +	// TO DO: (mandatory)
   1.285 +	// initialise the secure screen's palette for the initial display mode
   1.286 +	//
   1.287 +	
   1.288 +	// setup the video info structure, this'll be used to remember the video settings
   1.289 +	iVideoInfo.iDisplayMode = KConfigLcdInitialDisplayMode;
   1.290 +	iVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetToFirstVideoBuffer;
   1.291 +	iVideoInfo.iIsPalettized = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iIsPalettized;
   1.292 +	iVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iOffsetBetweenLines;
   1.293 +	iVideoInfo.iBitsPerPixel = Lcd_Mode_Config[KConfigLcdInitialDisplayMode].iBitsPerPixel;
   1.294 +
   1.295 +	iVideoInfo.iSizeInPixels.iWidth = KConfigLcdWidth;
   1.296 +	iVideoInfo.iSizeInPixels.iHeight = KConfigLcdHeight;
   1.297 +	iVideoInfo.iSizeInTwips.iWidth = KConfigLcdWidthInTwips;
   1.298 +	iVideoInfo.iSizeInTwips.iHeight = KConfigLcdHeightInTwips;
   1.299 +	iVideoInfo.iIsMono = KConfigLcdIsMono;
   1.300 +	iVideoInfo.iVideoAddress=(TInt)pV;
   1.301 +	iVideoInfo.iIsPixelOrderLandscape = KConfigLcdPixelOrderLandscape;
   1.302 +	iVideoInfo.iIsPixelOrderRGB = KConfigLcdPixelOrderRGB;
   1.303 +
   1.304 +	iSecureVideoInfo = iVideoInfo;
   1.305 +	iSecureVideoInfo.iVideoAddress = (TInt)pV2;
   1.306 +
   1.307 +	iDisplayOn = EFalse;
   1.308 +	iSecureDisplay = EFalse;
   1.309 +
   1.310 +	// install the HAL function
   1.311 +	r=Kern::AddHalEntry(EHalGroupDisplay, halFunction, this);
   1.312 +	if (r!=KErrNone)
   1.313 +		return r;
   1.314 +
   1.315 +	iPowerUpDfc.SetDfcQ(iDfcQ);
   1.316 +	iPowerDownDfc.SetDfcQ(iDfcQ);
   1.317 +	iMsgQ.SetDfcQ(iDfcQ);
   1.318 +	iMsgQ.Receive();
   1.319 +
   1.320 +	// install the power handler
   1.321 +	// power up the screen
   1.322 +	Add();
   1.323 +	DisplayOn();
   1.324 +
   1.325 +	SplashScreen();
   1.326 +	
   1.327 +	return KErrNone;
   1.328 +	}
   1.329 +
   1.330 +/**
   1.331 +Turn the display on
   1.332 +May be called as a result of a power transition or from the HAL
   1.333 +If called from HAL, then the display may be already be on (iDisplayOn == ETrue)
   1.334 +*/
   1.335 +void DLcdPowerHandler::DisplayOn()
   1.336 +	{
   1.337 +	__KTRACE_OPT(KPOWER, Kern::Printf("DisplayOn %d", iDisplayOn));
   1.338 +	if (!iDisplayOn)				// may have been powered up already
   1.339 +		{
   1.340 +		iDisplayOn = ETrue;
   1.341 +		PowerUpLcd(iSecureDisplay);
   1.342 +		SetContrast(iContrast);
   1.343 +		SetBrightness(iBrightness);
   1.344 +		}
   1.345 +	}
   1.346 +
   1.347 +/**
   1.348 +Turn the display off
   1.349 +May be called as a result of a power transition or from the HAL
   1.350 +If called from Power Manager, then the display may be already be off (iDisplayOn == EFalse)
   1.351 +if the platform is in silent running mode
   1.352 +*/
   1.353 +void DLcdPowerHandler::DisplayOff()
   1.354 +	{
   1.355 +	__KTRACE_OPT(KPOWER, Kern::Printf("DisplayOff %d", iDisplayOn));
   1.356 +	if (iDisplayOn)
   1.357 +		{
   1.358 +		iDisplayOn = EFalse;
   1.359 +		PowerDownLcd();
   1.360 +		}
   1.361 +	}
   1.362 +
   1.363 +/**
   1.364 +Switch between secure and non-secure displays
   1.365 +
   1.366 +@param aSecure ETrue if switching to secure display
   1.367 +*/
   1.368 +void DLcdPowerHandler::SwitchDisplay(TBool aSecure)
   1.369 + 	{
   1.370 + 	if (aSecure)
   1.371 + 		{
   1.372 + 		if (!iSecureDisplay)
   1.373 + 			{
   1.374 + 			//switch to secure display
   1.375 + 			DisplayOff();
   1.376 + 			iSecureDisplay = ETrue;
   1.377 + 			DisplayOn();
   1.378 + 			}
   1.379 + 		}
   1.380 + 	else
   1.381 + 		{
   1.382 + 		if (iSecureDisplay)
   1.383 + 			{
   1.384 + 			//switch from secure display
   1.385 + 			DisplayOff();
   1.386 + 			iSecureDisplay = EFalse;
   1.387 + 			DisplayOn();
   1.388 + 			}
   1.389 + 		}
   1.390 + 	}
   1.391 +
   1.392 +/**
   1.393 +DFC to power up the display
   1.394 +*/
   1.395 +void DLcdPowerHandler::PowerUpDfc()
   1.396 +	{
   1.397 +	__KTRACE_OPT(KPOWER, Kern::Printf("PowerUpDfc"));
   1.398 +	DisplayOn();
   1.399 +
   1.400 +	PowerUpDone();				// must be called from a different thread than PowerUp()
   1.401 +	}
   1.402 +
   1.403 +/**
   1.404 +DFC to power down the display
   1.405 +*/
   1.406 +void DLcdPowerHandler::PowerDownDfc()
   1.407 +	{
   1.408 +	__KTRACE_OPT(KPOWER, Kern::Printf("PowerDownDfc"));
   1.409 +	DisplayOff();
   1.410 +	PowerDownDone();			// must be called from a different thread than PowerUp()
   1.411 +	}
   1.412 +
   1.413 +/**
   1.414 +Schedule the power-down DFC
   1.415 +*/
   1.416 +void DLcdPowerHandler::PowerDown(TPowerState)
   1.417 +	{
   1.418 +	iPowerDownDfc.Enque();		// schedules DFC to execute on this driver's thread
   1.419 +	}
   1.420 +
   1.421 +/**
   1.422 +Schedule the power-up DFC
   1.423 +*/
   1.424 +void DLcdPowerHandler::PowerUp()
   1.425 +	{
   1.426 +	iPowerUpDfc.Enque();		// schedules DFC to execute on this driver's thread
   1.427 +	}
   1.428 +
   1.429 +/**
   1.430 +Power up the display
   1.431 +
   1.432 +@param aSecure ETrue if powering up the secure display
   1.433 +*/
   1.434 +void DLcdPowerHandler::PowerUpLcd(TBool aSecure)
   1.435 +    {
   1.436 +
   1.437 +	// TO DO: (mandatory)
   1.438 +	// Power up the display and configure it ready for use
   1.439 +	// Examples of things that may need initializing are:
   1.440 +	// panel dimensions
   1.441 +	// line & frame timings
   1.442 +	// bits-per-pixel
   1.443 +	// Configuring the DMA engine to map the video buffer in ivRamPhys or iSecurevRamPhys
   1.444 +	// contrast, brightness, backlight
   1.445 +	// power
   1.446 +	// etc. etc.
   1.447 +	//
   1.448 +    }
   1.449 +
   1.450 +/**
   1.451 +Power down the display and the backlight
   1.452 +*/
   1.453 +void DLcdPowerHandler::PowerDownLcd()
   1.454 +    {
   1.455 +	SetBacklightState(EFalse);
   1.456 +
   1.457 +	// TO DO: (mandatory)
   1.458 +	// Power down the display & disable LCD DMA.
   1.459 +	// May need to wait until the current frame has been output
   1.460 +	//
   1.461 +    }
   1.462 +
   1.463 +/**
   1.464 +Set the Lcd contrast
   1.465 +
   1.466 +@param aValue the contrast setting
   1.467 +*/
   1.468 +TInt DLcdPowerHandler::SetContrast(TInt aValue)
   1.469 +	{
   1.470 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetContrast(%d)", aValue));
   1.471 +
   1.472 +	if (aValue >= KConfigLcdMinDisplayContrast && aValue <= KConfigLcdMaxDisplayContrast)
   1.473 +		{
   1.474 +		iContrast=aValue;
   1.475 +		
   1.476 +		// TO DO: (mandatory)
   1.477 +		// set the contrast
   1.478 +		//
   1.479 +		return KErrNone;
   1.480 +		}
   1.481 +
   1.482 +	return KErrArgument;
   1.483 +	}
   1.484 +
   1.485 +/**
   1.486 +Set the Lcd brightness
   1.487 +
   1.488 +@param aValue the brightness setting
   1.489 +*/
   1.490 +TInt DLcdPowerHandler::SetBrightness(TInt aValue)
   1.491 +	{
   1.492 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetBrightness(%d)", aValue));
   1.493 +
   1.494 +	if (aValue >= KConfigLcdMinDisplayBrightness && aValue <= KConfigLcdMaxDisplayBrightness)
   1.495 +		{
   1.496 +		iBrightness=aValue;
   1.497 +
   1.498 +		// TO DO: (mandatory)
   1.499 +		// set the brightness
   1.500 +		//
   1.501 +		return KErrNone;
   1.502 +		}
   1.503 +	return KErrArgument;
   1.504 +	}
   1.505 +
   1.506 +/**
   1.507 +Turn the backlight on
   1.508 +*/
   1.509 +void DLcdPowerHandler::BacklightOn()
   1.510 +    {
   1.511 +	// TO DO: (mandatory)
   1.512 +	// turn the backlight on
   1.513 +	//
   1.514 +    }
   1.515 +
   1.516 +/**
   1.517 +Turn the backlight off
   1.518 +*/
   1.519 +void DLcdPowerHandler::BacklightOff()
   1.520 +    {
   1.521 +	// TO DO: (mandatory)
   1.522 +	// turn the backlight off
   1.523 +	//
   1.524 +    }
   1.525 +
   1.526 +/**
   1.527 +Set the state of the backlight
   1.528 +
   1.529 +@param aState ETrue if setting the backlight on
   1.530 +*/
   1.531 +void DLcdPowerHandler::SetBacklightState(TBool aState)
   1.532 +	{
   1.533 +	iBacklightOn=aState;
   1.534 +	if (iBacklightOn)
   1.535 +		BacklightOn();
   1.536 +	else
   1.537 +		BacklightOff();
   1.538 +	}
   1.539 +
   1.540 +void DLcdPowerHandler::ScreenInfo(TScreenInfoV01& anInfo)
   1.541 +	{
   1.542 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("DLcdPowerHandler::ScreenInfo"));
   1.543 +	anInfo.iWindowHandleValid=EFalse;
   1.544 +	anInfo.iWindowHandle=NULL;
   1.545 +	anInfo.iScreenAddressValid=ETrue;
   1.546 +	anInfo.iScreenAddress=(TAny *)(iChunk->LinearAddress());
   1.547 +	anInfo.iScreenSize.iWidth=KConfigLcdWidth;
   1.548 +	anInfo.iScreenSize.iHeight=KConfigLcdHeight;
   1.549 +	}
   1.550 +
   1.551 +/**
   1.552 +Handle a message from the power handler
   1.553 +*/
   1.554 +void DLcdPowerHandler::HandleMsg(void)
   1.555 +	{
   1.556 +	
   1.557 +	TMessageBase* msg = iMsgQ.iMessage;
   1.558 +	if (msg == NULL)
   1.559 +		return;
   1.560 +
   1.561 +	if (msg->iValue)
   1.562 +		DisplayOn();
   1.563 +	else
   1.564 +		DisplayOff();
   1.565 +	msg->Complete(KErrNone,ETrue);
   1.566 +	}
   1.567 +
   1.568 +/**
   1.569 +Send a message to the power-handler message queue to turn the display on
   1.570 +*/
   1.571 +void DLcdPowerHandler::WsSwitchOnScreen()
   1.572 +	{
   1.573 +	TThreadMessage& m=Kern::Message();
   1.574 +	m.iValue = ETrue;
   1.575 +	m.SendReceive(&iMsgQ);		// send a message and block Client thread until keyboard has been powered up
   1.576 +	}
   1.577 +
   1.578 +/**
   1.579 +Send a message to the power-handler message queue to turn the display off
   1.580 +*/
   1.581 +void DLcdPowerHandler::WsSwitchOffScreen()
   1.582 +	{
   1.583 +	TThreadMessage& m=Kern::Message();
   1.584 +	m.iValue = EFalse;
   1.585 +	m.SendReceive(&iMsgQ);		// send a message and block Client thread until keyboard has been powered down
   1.586 +	}
   1.587 +
   1.588 +/**
   1.589 +Return information about the current display mode
   1.590 +
   1.591 +@param	aInfo a structure supplied by the caller to be filled by this function.
   1.592 +@param	aSecure ETrue if requesting information about the secure display
   1.593 +@return	KErrNone if successful
   1.594 +*/
   1.595 +TInt DLcdPowerHandler::GetCurrentDisplayModeInfo(TVideoInfoV01& aInfo, TBool aSecure)
   1.596 +	{
   1.597 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("GetCurrentDisplayModeInfo"));
   1.598 +	NKern::FMWait(&iLock);
   1.599 +	if (aSecure)
   1.600 + 		aInfo = iSecureVideoInfo;
   1.601 + 	else
   1.602 + 		aInfo = iVideoInfo;
   1.603 +	NKern::FMSignal(&iLock);
   1.604 +	return KErrNone;
   1.605 +	}
   1.606 +
   1.607 +/**
   1.608 +Return information about the specified display mode
   1.609 +
   1.610 +@param	aMode the display mode to query
   1.611 +@param	aInfo a structure supplied by the caller to be filled by this function.
   1.612 +@return	KErrNone if successful
   1.613 +*/
   1.614 +TInt DLcdPowerHandler::GetSpecifiedDisplayModeInfo(TInt aMode, TVideoInfoV01& aInfo)
   1.615 +	{
   1.616 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("GetSpecifiedDisplayModeInfo mode is %d",aMode));
   1.617 +
   1.618 +	if (aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
   1.619 +		return KErrArgument;
   1.620 +
   1.621 +	NKern::FMWait(&iLock);
   1.622 +	aInfo = iVideoInfo;
   1.623 +	NKern::FMSignal(&iLock);
   1.624 +
   1.625 +	if (aMode != aInfo.iDisplayMode)
   1.626 +		{
   1.627 +		aInfo.iOffsetToFirstPixel=Lcd_Mode_Config[aMode].iOffsetToFirstVideoBuffer;
   1.628 +		aInfo.iIsPalettized = Lcd_Mode_Config[aMode].iIsPalettized;
   1.629 +		aInfo.iOffsetBetweenLines=Lcd_Mode_Config[aMode].iOffsetBetweenLines;
   1.630 +		aInfo.iBitsPerPixel = Lcd_Mode_Config[aMode].iBitsPerPixel;
   1.631 +		}
   1.632 +	return KErrNone;
   1.633 +	}
   1.634 +
   1.635 +/**
   1.636 +Set the display mode
   1.637 +
   1.638 +@param	aMode the display mode to set
   1.639 +*/
   1.640 +TInt DLcdPowerHandler::SetDisplayMode(TInt aMode)
   1.641 +	{
   1.642 +
   1.643 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetDisplayMode = %d", aMode));
   1.644 +
   1.645 +	if (aMode < 0 || aMode >= KConfigLcdNumberOfDisplayModes)
   1.646 +		return KErrArgument;
   1.647 +
   1.648 +	NKern::FMWait(&iLock);
   1.649 +
   1.650 +	// store the current mode
   1.651 +	iVideoInfo.iDisplayMode = aMode;
   1.652 +	iVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[aMode].iOffsetToFirstVideoBuffer;
   1.653 +	iVideoInfo.iIsPalettized = Lcd_Mode_Config[aMode].iIsPalettized;
   1.654 +	iVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[aMode].iOffsetBetweenLines;
   1.655 +	iVideoInfo.iBitsPerPixel = Lcd_Mode_Config[aMode].iBitsPerPixel;
   1.656 +
   1.657 +	// store the current mode for secure screen
   1.658 +	iSecureVideoInfo.iDisplayMode = aMode;
   1.659 +	iSecureVideoInfo.iOffsetToFirstPixel = Lcd_Mode_Config[aMode].iOffsetToFirstVideoBuffer;
   1.660 +	iSecureVideoInfo.iIsPalettized = Lcd_Mode_Config[aMode].iIsPalettized;
   1.661 +	iSecureVideoInfo.iOffsetBetweenLines = Lcd_Mode_Config[aMode].iOffsetBetweenLines;
   1.662 +	iSecureVideoInfo.iBitsPerPixel = Lcd_Mode_Config[aMode].iBitsPerPixel;
   1.663 +	
   1.664 +	// TO DO: (mandatory)
   1.665 +	// set bits per pixel on hardware
   1.666 +	// May need to reconfigure DMA if video buffer size and location have changed
   1.667 +	//
   1.668 +	NKern::FMSignal(&iLock);
   1.669 +
   1.670 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetDisplayMode mode = %d, otfp = %d, palettized = %d, bpp = %d, obl = %d",
   1.671 +		aMode, iVideoInfo.iOffsetToFirstPixel, iVideoInfo.iIsPalettized, iVideoInfo.iBitsPerPixel, iVideoInfo.iOffsetBetweenLines));
   1.672 +
   1.673 +	return KErrNone;
   1.674 +	}
   1.675 +
   1.676 +/**
   1.677 +Fill the video memory with an initial pattern or image
   1.678 +This will be displayed on boot-up
   1.679 +*/
   1.680 +void DLcdPowerHandler::SplashScreen()
   1.681 +	{
   1.682 +	// TO DO: (optional)
   1.683 +	// replace the example code below to display a different spash screen
   1.684 +
   1.685 +	// initialise the video ram to be a splash screen
   1.686 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("SplashScreen"));
   1.687 +
   1.688 +	TUint x,y;
   1.689 +	TUint8 * p = (TUint8*)(iVideoInfo.iVideoAddress + iVideoInfo.iOffsetToFirstPixel);
   1.690 +
   1.691 +	//draw >< on screen
   1.692 +	TUint rsh = KConfigLcdHeight;
   1.693 +	TUint rsw = KConfigLcdWidth;
   1.694 +	for (y = 0; y < rsh>>1; y++)
   1.695 +		{
   1.696 +		TUint8* q = p;
   1.697 +		for (x = 0; x < rsw; x++)
   1.698 +			*p++ = (x < y || (rsw-x<y)) ? 1 : 2;
   1.699 +		p = q + iVideoInfo.iOffsetBetweenLines;
   1.700 +		}
   1.701 +	for (y = rsh>>1; y < rsh; y++)
   1.702 +		{
   1.703 +		TUint8* q = p;
   1.704 +		for (x = 0; x < rsw; x++)
   1.705 +			*p++ = ((x < rsh-y) || (rsw-x<rsh-y)) ? 1 : 2;
   1.706 +		p = q + iVideoInfo.iOffsetBetweenLines;
   1.707 +		}
   1.708 +
   1.709 +	p = (TUint8*)(iSecureVideoInfo.iVideoAddress + iSecureVideoInfo.iOffsetToFirstPixel);
   1.710 +
   1.711 +	//draw >< on secure screen
   1.712 +	for (y = 0; y < rsh>>1; y++)
   1.713 +		{
   1.714 +		TUint8* q = p;
   1.715 +		for (x = 0; x < rsw; x++)
   1.716 +			*p++ = (x < y || (rsw-x<y)) ? 1 : 2;
   1.717 +		p = q + iSecureVideoInfo.iOffsetBetweenLines;
   1.718 +		}
   1.719 +	for (y = rsh>>1; y < rsh; y++)
   1.720 +		{
   1.721 +		TUint8* q = p;
   1.722 +		for (x = 0; x < rsw; x++)
   1.723 +			*p++ = ((x < rsh-y) || (rsw-x<rsh-y)) ? 1 : 2;
   1.724 +		p = q + iSecureVideoInfo.iOffsetBetweenLines;
   1.725 +		}
   1.726 +	}
   1.727 +
   1.728 +
   1.729 +/**
   1.730 +Get the size of the pallete
   1.731 +
   1.732 +@return	the number of pallete entries
   1.733 +*/
   1.734 +TInt DLcdPowerHandler::NumberOfPaletteEntries()		//only call when holding mutex
   1.735 +	{
   1.736 +	// TO DO: (mandatory)
   1.737 +	// Calculate the number of Palette entries - this is normally 
   1.738 +	// calculated from the bits per-pixel.
   1.739 +	// This is only example code... you may need to modify it for your hardware
   1.740 +	//
   1.741 +	TInt num = iVideoInfo.iIsPalettized ? 1<<iVideoInfo.iBitsPerPixel : 0;
   1.742 +
   1.743 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("NumberOfPaletteEntries = %d", num));
   1.744 +
   1.745 +	return num;
   1.746 +	}
   1.747 +
   1.748 +
   1.749 +/** 
   1.750 +Retrieve the palette entry at a particular offset
   1.751 +
   1.752 +@param	aEntry the palette index
   1.753 +@param	aColor a caller-supplied pointer to a location where the returned RGB color is to be stored
   1.754 +@return	KErrNone if successful
   1.755 +		KErrNotSupported if the current vide mode does not support a palette
   1.756 +		KErrArgument if aEntry is out of range
   1.757 +*/
   1.758 +TInt DLcdPowerHandler::GetPaletteEntry(TInt aEntry, TInt* aColor)
   1.759 +	{
   1.760 +	NKern::FMWait(&iLock);
   1.761 +	if (!iVideoInfo.iIsPalettized)
   1.762 +		{
   1.763 +		NKern::FMSignal(&iLock);
   1.764 +		return KErrNotSupported;
   1.765 +		}
   1.766 +
   1.767 +	if ((aEntry < 0) || (aEntry >= NumberOfPaletteEntries()))
   1.768 +		{
   1.769 +		NKern::FMSignal(&iLock);
   1.770 +		return KErrArgument;
   1.771 +		}
   1.772 +
   1.773 +	// TO DO: (mandatory)
   1.774 +	// read the RGB value of the palette entry into aColor
   1.775 +	// NOTE: the palette could either be a buffer allocated in system RAM (usually contiguous to Video buffer)
   1.776 +	//		 or could be offered as part of the hardware block that implemenst the lcd control
   1.777 +	//
   1.778 +	NKern::FMSignal(&iLock);
   1.779 +
   1.780 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("GetPaletteEntry %d color 0x%x", aEntry, aColor));
   1.781 +
   1.782 +	return KErrNone;
   1.783 +	}
   1.784 +
   1.785 +/** 
   1.786 +Set the palette entry at a particular offset
   1.787 +
   1.788 +@param	aEntry the palette index
   1.789 +@param	aColor the RGB color to store
   1.790 +@return	KErrNone if successful
   1.791 +		KErrNotSupported if the current vide mode does not support a palette
   1.792 +		KErrArgument if aEntry is out of range
   1.793 +*/
   1.794 +TInt DLcdPowerHandler::SetPaletteEntry(TInt aEntry, TInt aColor)
   1.795 +	{
   1.796 +
   1.797 +	NKern::FMWait(&iLock);
   1.798 +	if (!iVideoInfo.iIsPalettized)
   1.799 +		{
   1.800 +		NKern::FMSignal(&iLock);
   1.801 +		return KErrNotSupported;
   1.802 +		}
   1.803 +
   1.804 +	if ((aEntry < 0) || (aEntry >= NumberOfPaletteEntries()))	//check entry in range
   1.805 +		{
   1.806 +		NKern::FMSignal(&iLock);
   1.807 +		return KErrArgument;
   1.808 +		}
   1.809 +
   1.810 +	// TO DO: (mandatory)
   1.811 +	// update the palette entry for the secure and non-secure screen
   1.812 +	// NOTE: the palette could either be a buffer allocated in system RAM (usually contiguous to Video buffer)
   1.813 +	//		 or could be offered as part of the hardware block that implemenst the lcd control
   1.814 +	//
   1.815 +	__KTRACE_OPT(KEXTENSION,Kern::Printf("SetPaletteEntry %d to 0x%x", aEntry, aColor ));
   1.816 +
   1.817 +	return KErrNone;
   1.818 +	}
   1.819 +
   1.820 +/**
   1.821 +a HAL entry handling function for HAL group attribute EHalGroupDisplay
   1.822 +
   1.823 +@param	a1 an arbitrary argument
   1.824 +@param	a2 an arbitrary argument
   1.825 +@return	KErrNone if successful
   1.826 +*/
   1.827 +TInt DLcdPowerHandler::HalFunction(TInt aFunction, TAny* a1, TAny* a2)
   1.828 +	{
   1.829 +	__e32_memory_barrier(); // Ensure changes from other clients are picked up
   1.830 +
   1.831 +	TInt r=KErrNone;
   1.832 +	switch(aFunction)
   1.833 +		{
   1.834 +		case EDisplayHalScreenInfo:
   1.835 +			{
   1.836 +			TPckgBuf<TScreenInfoV01> vPckg;
   1.837 +			ScreenInfo(vPckg());
   1.838 +			Kern::InfoCopy(*(TDes8*)a1,vPckg);
   1.839 +			break;
   1.840 +			}
   1.841 +
   1.842 +		case EDisplayHalWsRegisterSwitchOnScreenHandling:
   1.843 +			iWsSwitchOnScreen=(TBool)a1;
   1.844 +			break;
   1.845 +		
   1.846 +		case EDisplayHalWsSwitchOnScreen:
   1.847 +			WsSwitchOnScreen();
   1.848 +			break;
   1.849 +
   1.850 +		case EDisplayHalMaxDisplayContrast:
   1.851 +			{
   1.852 +			TInt mc=KConfigLcdMaxDisplayContrast;
   1.853 +			kumemput32(a1,&mc,sizeof(mc));
   1.854 +			break;
   1.855 +			}
   1.856 +		case EDisplayHalSetDisplayContrast:
   1.857 +			if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayContrast")))
   1.858 +				return KErrPermissionDenied;
   1.859 +			r=SetContrast(TInt(a1));
   1.860 +			break;
   1.861 +		
   1.862 +		case EDisplayHalDisplayContrast:
   1.863 +			kumemput32(a1,&iContrast,sizeof(iContrast));
   1.864 +			break;
   1.865 +
   1.866 +		case EDisplayHalMaxDisplayBrightness:
   1.867 +			{
   1.868 +			TInt mc=KConfigLcdMaxDisplayBrightness;
   1.869 +			kumemput32(a1,&mc,sizeof(mc));
   1.870 +			break;
   1.871 +			}
   1.872 +		
   1.873 +		case EDisplayHalSetDisplayBrightness:
   1.874 +			if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetDisplayBrightness")))
   1.875 +				return KErrPermissionDenied;
   1.876 +			r=SetBrightness(TInt(a1));
   1.877 +			break;
   1.878 +		
   1.879 +		case EDisplayHalDisplayBrightness:
   1.880 +			kumemput32(a1,&iBrightness,sizeof(iBrightness));
   1.881 +			break;
   1.882 +		
   1.883 +		case EDisplayHalSetBacklightOn:
   1.884 +			if(!Kern::CurrentThreadHasCapability(ECapabilityWriteDeviceData,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetBacklightOn")))
   1.885 +				return KErrPermissionDenied;
   1.886 +			if (Kern::MachinePowerStatus()<ELow)
   1.887 +				r=KErrBadPower;
   1.888 +			else
   1.889 +				SetBacklightState(TBool(a1));
   1.890 +			break;
   1.891 +		
   1.892 +		case EDisplayHalBacklightOn:
   1.893 +			kumemput32(a1,&iBacklightOn,sizeof(TInt));
   1.894 +			break;
   1.895 +
   1.896 +		case EDisplayHalModeCount:
   1.897 +			{
   1.898 +			TInt ndm = KConfigLcdNumberOfDisplayModes;
   1.899 +			kumemput32(a1, &ndm, sizeof(ndm));
   1.900 +			break;
   1.901 +			}
   1.902 +		
   1.903 +		case EDisplayHalSetMode:
   1.904 +			if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetMode")))
   1.905 +				return KErrPermissionDenied;
   1.906 +			r = SetDisplayMode((TInt)a1);
   1.907 +			break;
   1.908 +		
   1.909 +		case EDisplayHalMode:
   1.910 +			kumemput32(a1, &iVideoInfo.iDisplayMode, sizeof(iVideoInfo.iDisplayMode));
   1.911 +			break;
   1.912 +
   1.913 +		case EDisplayHalSetPaletteEntry:
   1.914 +			if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetPaletteEntry")))
   1.915 +				return KErrPermissionDenied;
   1.916 +			r = SetPaletteEntry((TInt)a1, (TInt)a2);
   1.917 +			break;
   1.918 +		
   1.919 +		case EDisplayHalPaletteEntry:
   1.920 +			{
   1.921 +			TInt entry;
   1.922 +			kumemget32(&entry, a1, sizeof(TInt));
   1.923 +			TInt x;
   1.924 +			r = GetPaletteEntry(entry, &x);
   1.925 +			if (r == KErrNone)
   1.926 +				kumemput32(a2, &x, sizeof(x));
   1.927 +			break;
   1.928 +			}
   1.929 +		
   1.930 +		case EDisplayHalSetState:
   1.931 +			{
   1.932 +			if(!Kern::CurrentThreadHasCapability(ECapabilityPowerMgmt,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetState")))
   1.933 +				return KErrPermissionDenied;
   1.934 +			if ((TBool)a1)
   1.935 +				{
   1.936 +				WsSwitchOnScreen();
   1.937 +				}
   1.938 +			else
   1.939 +				{
   1.940 +				WsSwitchOffScreen();
   1.941 +				}
   1.942 +			break;
   1.943 +			}
   1.944 +
   1.945 +		case EDisplayHalState:
   1.946 +			kumemput32(a1, &iDisplayOn, sizeof(TBool));
   1.947 +			break;
   1.948 +
   1.949 +		case EDisplayHalColors:
   1.950 +			{
   1.951 +			TInt mdc = KConfigLcdMaxDisplayColors;
   1.952 +			kumemput32(a1, &mdc, sizeof(mdc));
   1.953 +			break;
   1.954 +			}
   1.955 +
   1.956 +		case EDisplayHalCurrentModeInfo:
   1.957 +			{
   1.958 +			TPckgBuf<TVideoInfoV01> vPckg;
   1.959 +			r = GetCurrentDisplayModeInfo(vPckg(), (TBool)a2);
   1.960 +			if (KErrNone == r)
   1.961 +				Kern::InfoCopy(*(TDes8*)a1,vPckg);
   1.962 +			}
   1.963 +			break;
   1.964 +
   1.965 +		case EDisplayHalSpecifiedModeInfo:
   1.966 +			{
   1.967 +			TPckgBuf<TVideoInfoV01> vPckg;
   1.968 +			TInt mode;
   1.969 +			kumemget32(&mode, a1, sizeof(mode));
   1.970 +			r = GetSpecifiedDisplayModeInfo(mode, vPckg());
   1.971 +			if (KErrNone == r)
   1.972 +				Kern::InfoCopy(*(TDes8*)a2,vPckg);
   1.973 +			}
   1.974 +			break;
   1.975 +			
   1.976 +		case EDisplayHalSecure:
   1.977 +			kumemput32(a1, &iSecureDisplay, sizeof(TBool));
   1.978 +			break;
   1.979 +
   1.980 +		case EDisplayHalSetSecure:
   1.981 +			{
   1.982 +			if(!Kern::CurrentThreadHasCapability(ECapabilityMultimediaDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by Hal function EDisplayHalSetSecure")))
   1.983 +				return KErrPermissionDenied;
   1.984 +			SwitchDisplay((TBool)a1);
   1.985 +			}
   1.986 +			break;
   1.987 +
   1.988 +		default:
   1.989 +			r=KErrNotSupported;
   1.990 +			break;
   1.991 +		}
   1.992 +
   1.993 +	__e32_memory_barrier(); // Ensure any changes are propagated to other clients
   1.994 +
   1.995 +	return r;
   1.996 +	}
   1.997 +
   1.998 +
   1.999 +DECLARE_STANDARD_EXTENSION()
  1.1000 +	{
  1.1001 +	__KTRACE_OPT(KPOWER,Kern::Printf("Starting LCD power manager"));
  1.1002 +
  1.1003 +	// create LCD power handler
  1.1004 +	TInt r=KErrNoMemory;
  1.1005 +	DLcdPowerHandler* pH=new DLcdPowerHandler;
  1.1006 +	if (pH)
  1.1007 +		r=pH->Create();
  1.1008 +
  1.1009 +	__KTRACE_OPT(KPOWER,Kern::Printf("Returns %d",r));
  1.1010 +	return r;
  1.1011 +	}
  1.1012 +