windows-nt/Source/XPSP1/NT/base/busdrv/pccard/pcmcibus/cl.c

234 lines
5.5 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
cl.c
Abstract:
This module contains the code that contains
Cirrus Logic controller specific initialization and
other dispatches
Author:
Ravisankar Pudipeddi (ravisp) 1-Nov-97
Environment:
Kernel mode
Revision History :
Neil Sandlin (neilsa) 3-Mar-99
new setpower routine interface
--*/
#include "pch.h"
VOID
CLInitialize(IN PFDO_EXTENSION FdoExtension)
/*++
Routine Description:
Initialize Cirrus Logic cardbus controllers
Arguments:
FdoExtension - Pointer to the device extension for the controller FDO
Return Value:
None
--*/
{
UCHAR byte, revisionID;
USHORT word;
byte = PcicReadSocket(FdoExtension->SocketList,
PCIC_CL_MISC_CTRL3);
if ((FdoExtension->ControllerType == PcmciaCLPD6832) &&
((byte & CL_MC3_INTMODE_MASK) == CL_MC3_INTMODE_EXTHW)) {
FdoExtension->LegacyIrqMask = 0xd8b8; //3,4,5,7,11,12,14,15
}
GetPciConfigSpace(FdoExtension, CFGSPACE_REV_ID, &revisionID, 1);
if (FdoExtension->ControllerType == PcmciaCLPD6832) {
//disable CSC IRQ routing (use PCI interrupt for CSC)
GetPciConfigSpace(FdoExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
word &= ~BCTRL_CL_CSCIRQROUTING_ENABLE;
SetPciConfigSpace(FdoExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
}
else {
//disable CSC IRQ routing (use PCI interrupt for CSC)
GetPciConfigSpace(FdoExtension, CFGSPACE_CL_CFGMISC1, &byte, 1);
byte &= ~CL_CFGMISC1_ISACSC;
SetPciConfigSpace(FdoExtension, CFGSPACE_CL_CFGMISC1, &byte, 1);
}
//enable speaker
byte = PcicReadSocket(FdoExtension->SocketList, PCIC_CL_MISC_CTRL1);
byte |= CL_MC1_SPKR_ENABLE;
PcicWriteSocket(FdoExtension->SocketList, PCIC_CL_MISC_CTRL1, byte);
byte = PcicReadSocket(FdoExtension->SocketList, PCIC_CL_DEV_IMP_C);
if (byte & (CL_IMPC_ZVP_A | CL_IMPC_ZVP_B)) {
//enable multimedia support (i.e. ZV)
byte = PcicReadSocket(FdoExtension->SocketList,PCIC_CL_MISC_CTRL3);
byte |= CL_MC3_MM_ARM;
PcicWriteSocket(FdoExtension->SocketList, PCIC_CL_MISC_CTRL3,byte);
}
}
NTSTATUS
CLSetPower(
IN PSOCKET SocketPtr,
IN BOOLEAN Enable,
OUT PULONG pDelayTime
)
/*++
Routine Description:
Set power to the specified socket.
Arguments:
SocketPtr - the socket to set
Enable - TRUE means to set power - FALSE is to turn it off.
pDelayTime - specifies delay (msec) to occur after the current phase
Return Value:
STATUS_MORE_PROCESSING_REQUIRED - increment phase, perform delay, recall
other status values terminate sequence
--*/
{
NTSTATUS status;
UCHAR oldPower, newPower, oldMiscCtrl, newMiscCtrl;
if (IsCardBusCardInSocket(SocketPtr)) {
//
// Hand over to generic power setting routine
//
return(CBSetPower(SocketPtr, Enable, pDelayTime));
}
switch(SocketPtr->PowerPhase) {
case 1:
//
// R2 card - special handling
//
oldPower = PcicReadSocket(SocketPtr, PCIC_PWR_RST);
oldMiscCtrl = PcicReadSocket(SocketPtr, PCIC_CL_MISC_CTRL1);
//
// Set new vcc
//
newPower = (Enable ? PC_CARDPWR_ENABLE: 0);
//
// Since we always set 5V for R2 cards, we let MISC control be 0
// other wise it should be CL_MC1_VCC_3V if the vcc was 3.3V
//
newMiscCtrl = 0;
//
// Set vpp
//
if (Enable) {
//
// We - as always - set vpp to vcc..
//
newPower |= PC_VPP_SETTO_VCC;
}
//
// Don't nuke the non-power related bits in the register..
//
newPower |= (oldPower & PC_PWRON_BITS);
newMiscCtrl |= (oldMiscCtrl & ~CL_MC1_VCC_33V);
//
// If Vcc is turned off, reset OUTPUT_ENABLE & AUTOPWR_ENABLE
//
if (!(newPower & PC_CARDPWR_ENABLE)) {
newPower &= ~PC_PWRON_BITS;
}
//
// Only set power if nothing's changed..
//
status = STATUS_SUCCESS;
if ((newPower != oldPower) || (newMiscCtrl != oldMiscCtrl)) {
PcicWriteSocket(SocketPtr, PCIC_PWR_RST, newPower);
PcicWriteSocket(SocketPtr, PCIC_CL_MISC_CTRL1, newMiscCtrl);
//
// Allow ramp up.. (actually we don't need to this if
// Enable was FALSE). Keep it for paranoia's sake
//
*pDelayTime = PcicStallPower;
SocketPtr->PowerData = (ULONG) newPower;
status = STATUS_MORE_PROCESSING_REQUIRED;
}
break;
case 2:
newPower = (UCHAR) SocketPtr->PowerData;
if ((newPower & PC_CARDPWR_ENABLE) &&
((newPower & PC_PWRON_BITS) != PC_PWRON_BITS)) {
//
// More paranoia?
//
newPower |= PC_PWRON_BITS;
PcicWriteSocket(SocketPtr, PCIC_PWR_RST, newPower);
}
status = STATUS_SUCCESS;
break;
default:
ASSERT(FALSE);
status = STATUS_UNSUCCESSFUL;
}
return status;
}
BOOLEAN
CLSetZV(
IN PSOCKET Socket,
IN BOOLEAN Enable
)
{
UCHAR bData;
if (Enable) {
bData = PcicReadSocket(Socket, PCIC_CL_MISC_CTRL1);
bData |= CL_MC1_MM_ENABLE;
bData &= ~CL_MC1_SPKR_ENABLE;
PcicWriteSocket(Socket, PCIC_CL_MISC_CTRL1, bData);
} else {
bData = PcicReadSocket(Socket, PCIC_CL_MISC_CTRL1);
bData &= ~CL_MC1_MM_ENABLE;
bData |= CL_MC1_SPKR_ENABLE;
PcicWriteSocket(Socket, PCIC_CL_MISC_CTRL1, bData);
}
return TRUE;
}