|
|
/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
cb.c
Abstract:
This module contains the code that contains generic (Yenta compliant) cardbus controller specific initialization and other dispatches
Author:
Ravisankar Pudipeddi (ravisp) 1-Nov-97 Neil Sandlin (neilsa) June 1 1999
Environment:
Kernel mode
Revision History :
Neil Sandlin (neilsa) 3-Mar-99 new setpower routine interface
--*/
#include "pch.h"
//
// Function Prototypes
//
BOOLEAN CBInitializePcmciaSocket( PSOCKET Socket );
NTSTATUS CBResetCard( PSOCKET Socket, PULONG pDelayTime ); BOOLEAN CBDetectCardInSocket( IN PSOCKET Socket );
BOOLEAN CBDetectCardChanged( IN PSOCKET Socket ); BOOLEAN CBDetectCardStatus( IN PSOCKET Socket ); BOOLEAN CBDetectReadyChanged( IN PSOCKET Socket );
NTSTATUS CBGetPowerRequirements( IN PSOCKET Socket ); BOOLEAN CBProcessConfigureRequest( IN PSOCKET Socket, IN PVOID ConfigRequest, IN PUCHAR Base ); BOOLEAN CBEnableDisableCardDetectEvent( IN PSOCKET Socket, IN BOOLEAN Enable ); ULONG CBGetIrqMask( IN PFDO_EXTENSION DeviceExtension ); ULONG CBReadCardMemory( IN PPDO_EXTENSION PdoExtension, IN MEMORY_SPACE MemorySpace, IN ULONG Offset, IN PUCHAR Buffer, IN ULONG Length ); ULONG CBWriteCardMemory( IN PPDO_EXTENSION PdoExtension, IN MEMORY_SPACE MemorySpace, IN ULONG Offset, IN PUCHAR Buffer, IN ULONG Length ); VOID CBEnableDisableWakeupEvent( IN PSOCKET Socket, IN PPDO_EXTENSION PdoExtension, IN BOOLEAN Enable ); BOOLEAN CBModifyMemoryWindow( IN PDEVICE_OBJECT Pdo, IN ULONGLONG HostBase, IN ULONGLONG CardBase OPTIONAL, IN BOOLEAN Enable, IN ULONG WindowSize OPTIONAL, IN UCHAR AccessSpeed OPTIONAL, IN UCHAR BusWidth OPTIONAL, IN BOOLEAN IsAttributeMemory OPTIONAL ); BOOLEAN CBSetVpp( IN PDEVICE_OBJECT Pdo, IN UCHAR Vpp ); BOOLEAN CBIsWriteProtected( IN PDEVICE_OBJECT Pdo );
//
// Function dispatch data block
//
PCMCIA_CTRL_BLOCK CBSupportFns = { CBInitializePcmciaSocket, CBResetCard, CBDetectCardInSocket, CBDetectCardChanged, CBDetectCardStatus, CBDetectReadyChanged, CBGetPowerRequirements, CBProcessConfigureRequest, CBEnableDisableCardDetectEvent, CBEnableDisableWakeupEvent, CBGetIrqMask, CBReadCardMemory, CBWriteCardMemory, CBModifyMemoryWindow, CBSetVpp, CBIsWriteProtected };
extern PCMCIA_CTRL_BLOCK PcicSupportFns;
//
// Support functions
//
NTSTATUS CBBuildSocketList( IN PFDO_EXTENSION FdoExtension ) /*++
Routine Description:
This routine builds the socket list for the given FDO. This is very simple for cardbus since there is always only 1 socket per controller.
Arguments:
FdoExtension - device extension for the controller
Return Value:
ntstatus
--*/ { PSOCKET socket = NULL; socket = ExAllocatePool(NonPagedPool, sizeof(SOCKET)); if (!socket) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(socket, sizeof(SOCKET));
FdoExtension->SocketList = socket;
socket->DeviceExtension = FdoExtension; socket->SocketFnPtr = &CBSupportFns; return STATUS_SUCCESS; }
BOOLEAN CBInitializePcmciaSocket( PSOCKET Socket ) /*++
Routine Description:
This routine will setup the controller into a state where the pcmcia support module will be able to issue commands to read device tuples from the cards in the sockets.
Arguments:
Socket - socket specific information
Return Value:
TRUE if successful FALSE if not successful
--*/ { UCHAR index; UCHAR reg; //
// Initialize exca registers
//
if (!PcicSupportFns.PCBInitializePcmciaSocket(Socket)) { return FALSE; }
//
// Clear pending events
//
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, 0x0000000F); //
// Since we may have just powered up, do a cvstest to make sure the socket registers
// are valid
//
if (CBDetectCardInSocket(Socket) && !IsDeviceFlagSet(Socket->DeviceExtension, PCMCIA_FDO_ON_DEBUG_PATH)) { CBIssueCvsTest(Socket); }
return TRUE; }
VOID CBIssueCvsTest( IN PSOCKET Socket ) /*++
Routine Description:
This routine forces the controller to reinterrogate the card type and voltage requirements. This is to insure correct values read from the socket registers.
Arguments:
Socket - socket specific information
Return Value:
none
--*/ { ULONG dwSktMask;
//
// Issue CVSTEST to interrogate card
// Disable interrupt temporarily because TI 12xx could cause spurious
// interrupt when playing with SktForce register.
//
dwSktMask = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG); CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, 0); CBWriteSocketRegister(Socket, CARDBUS_SOCKET_FORCE_EVENT_REG, SKTFORCE_CVSTEST); CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwSktMask);
// it would be nice to figure out a cleaner way to determine when interrogation is complete
PcmciaWait(300000); }
BOOLEAN CBEnableDeviceInterruptRouting( IN PSOCKET Socket ) /*++
Routine Description:
Arguments:
Socket - socket specific information
Return Value:
FALSE - irq to PCI TRUE - route to ISA
--*/ { USHORT word, orig_word; //
// set up IRQ routing
//
GetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2); orig_word = word;
if (IsCardBusCardInSocket(Socket) || (Is16BitCardInSocket(Socket) && IsSocketFlagSet(Socket, SOCKET_CB_ROUTE_R2_TO_PCI))) { //
// route to PCI
//
word &= ~BCTRL_IRQROUTING_ENABLE; } else { //
// route to ISA
//
word |= BCTRL_IRQROUTING_ENABLE; }
if (orig_word != word) { SetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2); }
// return TRUE for routing to ISA
return ((word & BCTRL_IRQROUTING_ENABLE) == BCTRL_IRQROUTING_ENABLE); }
NTSTATUS CBResetCard( PSOCKET Socket, OUT PULONG pDelayTime ) /*++
Routine Description:
Resets the pc-card in the given socket.
Arguments:
Socket - Pointer to the socket in which the pc-card resides 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 = STATUS_MORE_PROCESSING_REQUIRED; UCHAR byte; USHORT word; PFDO_EXTENSION deviceExtension=Socket->DeviceExtension; if (Is16BitCardInSocket(Socket)) { if (Socket->CardResetPhase == 2) { GetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2); //
// R2 card. Turn off write posting
//
word &= ~BCTRL_WRITE_POSTING_ENABLE; SetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2); } status = PcicSupportFns.PCBResetCard(Socket, pDelayTime); return status; }
switch(Socket->CardResetPhase) { case 1: //
// Reset via bridge control
//
GetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2); word |= BCTRL_CRST; SetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
Socket->PowerData = (ULONG) word; *pDelayTime = CBResetWidthDelay; break;
case 2: word = (USHORT)Socket->PowerData; word &= ~BCTRL_CRST; //
// CardBus card. Turn on write posting
//
word |= BCTRL_WRITE_POSTING_ENABLE; word &= ~BCTRL_IRQROUTING_ENABLE; //
// Hack: turn of write posting for topic95 to avoid hardware
// bug with intel NICs
//
if (deviceExtension->ControllerType == PcmciaTopic95) { word &= ~BCTRL_WRITE_POSTING_ENABLE; } //
// Stop bridge control reset
//
SetPciConfigSpace(deviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2);
*pDelayTime = CBResetSetupDelay; break; case 3: status = STATUS_SUCCESS; break;
default: ASSERT(FALSE); status = STATUS_UNSUCCESSFUL; }
return status; }
BOOLEAN CBDetectCardInSocket( IN PSOCKET Socket ) /*++
Routine Description:
This routine will determine if a card is in the socket
Arguments:
Socket -- Socket information
Return Value:
TRUE if card is present.
--*/ { ULONG state; BOOLEAN cardPresent=FALSE;
//
// Read the CARDBUS status register to see if the card is in there.
//
state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG); if ((state & SKTSTATE_CCD_MASK) == 0) { cardPresent = TRUE; } return(cardPresent); }
BOOLEAN CBDetectCardChanged( IN PSOCKET Socket ) /*++
Routine Description:
This routine will determine if socket's card insertion status has changed.
Arguments:
Socket -- Socket info.
Return Value:
TRUE if card insertion status has changed.
--*/ { BOOLEAN retVal = FALSE; ULONG tmp; //
// Read SOCKET Event register to see if CD's changed
//
tmp = CBReadSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG); if ((tmp & SKTEVENT_CCD_MASK) != 0) { //
// Yes they did..
// first clear the interrupt
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, SKTEVENT_CCD_MASK); retVal = TRUE; } return retVal; }
BOOLEAN CBDetectCardStatus( IN PSOCKET Socket ) /*++
Routine Description:
This routine will determine if socket's card insertion status has changed.
Arguments:
Socket -- Socket info.
Return Value:
TRUE if card insertion status has changed.
--*/ { BOOLEAN retVal = FALSE; ULONG tmp;
if (Is16BitCardInSocket(Socket)) { // NOTE: UNIMPLEMENTED: may need to do something for 16-bit cards
return FALSE; } //
// Read SOCKET Event register to see if CD's changed
//
tmp = CBReadSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG); if ((tmp & SKTEVENT_CSTSCHG) != 0) { //
// Yes they did..
// first clear the interrupt
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, SKTEVENT_CSTSCHG); retVal = TRUE; } return retVal; }
BOOLEAN CBDetectReadyChanged( IN PSOCKET Socket ) { return(PcicSupportFns.PCBDetectReadyChanged(Socket)); }
BOOLEAN CBProcessConfigureRequest( IN PSOCKET Socket, IN PCARD_REQUEST Request, IN PUCHAR Base ) { BOOLEAN bStatus = TRUE; USHORT word;
//
// Shouldn't this check for 16-bit cards?
//
switch (Request->RequestType) {
case IRQ_REQUEST:
if (CBEnableDeviceInterruptRouting(Socket)) { bStatus = PcicSupportFns.PCBProcessConfigureRequest(Socket, Request, Base); } break;
case DECONFIGURE_REQUEST:
bStatus = PcicSupportFns.PCBProcessConfigureRequest(Socket, Request, Base); GetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2); word |= BCTRL_IRQROUTING_ENABLE; SetPciConfigSpace(Socket->DeviceExtension, CFGSPACE_BRIDGE_CTRL, &word, 2); break;
default: bStatus = PcicSupportFns.PCBProcessConfigureRequest(Socket, Request, Base); } return bStatus; }
BOOLEAN CBEnableDisableCardDetectEvent( IN PSOCKET Socket, IN BOOLEAN Enable ) /*++
Routine Description:
Enable card detect/card ready interrupt.
Arguments:
Socket - socket information Enable - if TRUE, CSC interrupt is enabled, if FALSE, it is disabled Return Value:
TRUE if successful FALSE if not successful
--*/ {
switch (Enable) {
case TRUE: { UCHAR byte; //
// Only if TI 1130/1250?
// Route through PCI interrupts
byte = PcicReadSocket(Socket, PCIC_INTERRUPT); byte |= IGC_INTR_ENABLE; PcicWriteSocket(Socket, PCIC_INTERRUPT, byte);
//
// Clear the bits in Socket Event Register
//
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, 0xF);
//
// Enable card-detect interrupt in Socket Mask Register
//
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, SKTMSK_CCD); break; } case FALSE: { ULONG oldValue; //
// Clear the bits in Socket Event Register
//
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, 0xF);
//
// Disable card-detect interrupt in Socket Mask Register
//
oldValue = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG); oldValue &= ~SKTMSK_CCD; CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, oldValue); break; } }
return TRUE; }
VOID CBEnableDisableWakeupEvent( IN PSOCKET Socket, IN PPDO_EXTENSION PdoExtension, IN BOOLEAN Enable ) /*++
Routine Description:
Arguments:
Socket - socket information Enable - if TRUE, interrupt is enabled, if FALSE, it is disabled
Return Value:
none
--*/ { ULONG dwValue;
switch (Enable) {
case TRUE: {
//
// Enable card-status interrupt in Socket Mask Register
//
dwValue = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG); dwValue |= SKTMSK_CSTSCHG; CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwValue);
if (PdoExtension && IsCardBusCard(PdoExtension)) { UCHAR capptr; ULONG powercaps; //
// HACK ALERT - should be handled by PCI.SYS
// Have a look to see if PME_ENABLE has been turned on by PCI. If not then we do it.
//
GetPciConfigSpace(PdoExtension, CBCFG_CAPPTR, &capptr, sizeof(capptr)); if (capptr) { GetPciConfigSpace(PdoExtension, capptr, &powercaps, sizeof(powercaps)); if ((powercaps & 0xff) == 1) { GetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps)); if (!(powercaps & PME_EN)) { powercaps |= PME_EN; DebugPrint((PCMCIA_DEBUG_POWER, "pdo %08x setting PME_EN!\n", PdoExtension->DeviceObject)); SetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps)); } } } } break; } case FALSE: {
PFDO_EXTENSION fdoExtension = Socket->DeviceExtension; UCHAR capptr; ULONG powercaps, newPowercaps; //
// Check to see if PMESTAT is on... It shouldn't be. If it is, it probably means
// that the BIOS did not notify us that the device did the wake, and PCI didn't
// get a chance to clear the condition. This is really a BIOS bug.
//
if (PdoExtension && IsCardBusCard(PdoExtension)) {
GetPciConfigSpace(PdoExtension, CBCFG_CAPPTR, &capptr, sizeof(capptr)); if (capptr) { GetPciConfigSpace(PdoExtension, capptr, &powercaps, sizeof(powercaps)); if ((powercaps & 0xff) == 1) { GetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps)); if (powercaps & (PME_STAT | PME_EN)) {
DebugPrint((PCMCIA_DEBUG_POWER, "pdo %08x PME bits still set! stat=%x en=%x\n", PdoExtension->DeviceObject, ((powercaps&PME_STAT)!=0), ((powercaps&PME_EN)!=0)));
powercaps |= PME_STAT; powercaps &= ~PME_EN; SetPciConfigSpace(PdoExtension, capptr+4, &powercaps, sizeof(powercaps)); } } } }
GetPciConfigSpace(fdoExtension, CFGSPACE_CAPPTR, &capptr, sizeof(capptr)); if (capptr) { GetPciConfigSpace(fdoExtension, capptr, &powercaps, sizeof(powercaps)); if ((powercaps & 0xff) == 1) { //
// Clear PMESTAT, if on
//
GetPciConfigSpace(fdoExtension, capptr+4, &powercaps, sizeof(powercaps)); if (powercaps & PME_STAT) {
DebugPrint((PCMCIA_DEBUG_POWER, "fdo %08x PME_STAT still set!\n", fdoExtension->DeviceObject));
SetPciConfigSpace(fdoExtension, capptr+4, &powercaps, sizeof(powercaps)); } } } //
// Disable card-status interrupt in Socket Mask Register
//
dwValue = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG); dwValue &= ~SKTMSK_CSTSCHG; CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwValue); //
// Clear the event in Socket Event Register
//
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_EVENT_REG, SKTEVENT_CSTSCHG); break; } } }
ULONG CBGetIrqMask( IN PFDO_EXTENSION DeviceExtension ) { return(PcicSupportFns.PCBGetIrqMask(DeviceExtension)); }
ULONG CBReadCardMemory( IN PPDO_EXTENSION PdoExtension, IN MEMORY_SPACE MemorySpace, IN ULONG Offset, IN PUCHAR Buffer, IN ULONG Length ) { ULONG bytesCopied = 0;
if (!IsCardBusCard(PdoExtension)) { return(PcicSupportFns.PCBReadCardMemory(PdoExtension, MemorySpace, Offset, Buffer, Length)); }
switch(MemorySpace){
case PCCARD_PCI_CONFIGURATION_SPACE: bytesCopied = GetPciConfigSpace(PdoExtension, Offset, Buffer, Length); break; case PCCARD_CARDBUS_BAR0: case PCCARD_CARDBUS_BAR1: case PCCARD_CARDBUS_BAR2: case PCCARD_CARDBUS_BAR3: case PCCARD_CARDBUS_BAR4: case PCCARD_CARDBUS_BAR5: break; case PCCARD_CARDBUS_ROM: bytesCopied = PdoExtension->PciBusInterface.GetBusData( PdoExtension->PciBusInterface.Context, PCI_WHICHSPACE_ROM, Buffer, Offset, Length); break;
} return bytesCopied; }
ULONG CBWriteCardMemory( IN PPDO_EXTENSION PdoExtension, IN MEMORY_SPACE MemorySpace, IN ULONG Offset, IN PUCHAR Buffer, IN ULONG Length ) { if (IsCardBusCard(PdoExtension)) { return 0; } return(PcicSupportFns.PCBWriteCardMemory(PdoExtension, MemorySpace, Offset, Buffer, Length)); }
BOOLEAN CBModifyMemoryWindow( IN PDEVICE_OBJECT Pdo, IN ULONGLONG HostBase, IN ULONGLONG CardBase OPTIONAL, IN BOOLEAN Enable, IN ULONG WindowSize OPTIONAL, IN UCHAR AccessSpeed OPTIONAL, IN UCHAR BusWidth OPTIONAL, IN BOOLEAN IsAttributeMemory OPTIONAL ) { return(PcicSupportFns.PCBModifyMemoryWindow(Pdo, HostBase, CardBase, Enable, WindowSize, AccessSpeed, BusWidth, IsAttributeMemory)); }
BOOLEAN CBSetVpp( IN PDEVICE_OBJECT Pdo, IN UCHAR Vpp ) { return(PcicSupportFns.PCBSetVpp(Pdo, Vpp)); }
BOOLEAN CBIsWriteProtected( IN PDEVICE_OBJECT Pdo ) { return(PcicSupportFns.PCBIsWriteProtected(Pdo)); }
NTSTATUS CBGetPowerRequirements( IN PSOCKET Socket ) /*++
Routine Description:
Look at the hardware to see what it says the card needs, and update the socket structure accordingly.
Arguments:
Socket - the socket to examine
Return Value:
n/a
--*/ { ULONG state; UCHAR voltage; //
// Check what voltages are supported by this card
//
state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG); if (!(state & (SKTSTATE_5VCARD | SKTSTATE_3VCARD))) { ULONG dwSktMask; //
// neither 5v or 3v is set... try cvstest
// Disable interrupt temporarily because TI 12xx could cause spurious
// interrupt when playing with SktForce register.
//
dwSktMask = CBReadSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG); CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, 0); CBWriteSocketRegister(Socket, CARDBUS_SOCKET_FORCE_EVENT_REG, SKTFORCE_CVSTEST); state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG); CBWriteSocketRegister(Socket, CARDBUS_SOCKET_MASK_REG, dwSktMask); }
state &= (SKTSTATE_5VCARD | SKTSTATE_3VCARD);
if (state == 0) { return STATUS_UNSUCCESSFUL; }
if (state == (SKTSTATE_5VCARD | SKTSTATE_3VCARD)) { //
// both are specified. Check for preference
//
voltage = IsDeviceFlagSet(Socket->DeviceExtension, PCMCIA_FDO_PREFER_3V) ? 33 : 50; } else {
voltage = (state & SKTSTATE_5VCARD) ? 50 : 33; } Socket->Vcc = Socket->Vpp1 = Socket->Vpp2 = voltage; return STATUS_SUCCESS; }
NTSTATUS CBSetPower( IN PSOCKET Socket, IN BOOLEAN Enable, OUT PULONG pDelayTime ) /*++
Routine Description:
Set power to the specified socket.
Arguments:
Socket - 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; ULONG oldPower, state, newPower; ULONG vcc, vpp; UCHAR tmp; USHORT word;
switch(Socket->PowerPhase) { case 1: if (Enable) {
//
// Turn on the power
//
switch(Socket->Vcc) { case 50: vcc = SKTPOWER_VCC_050V; break; case 33: vcc = SKTPOWER_VCC_033V; break; default: vcc = SKTPOWER_VCC_OFF; }
switch(Socket->Vpp1) { case 120: vpp = SKTPOWER_VPP_120V; break; case 50: vpp = SKTPOWER_VPP_050V; break; case 33: vpp = SKTPOWER_VPP_033V; break; default: vpp = SKTPOWER_VPP_OFF; }
} else {
//
// Power off
//
vcc = SKTPOWER_VCC_OFF; vpp = SKTPOWER_VPP_OFF; //
// Disable output before powering down to avoid spurious signals
// from reaching the card
//
if (Is16BitCardInSocket(Socket)) { tmp = PcicReadSocket(Socket, PCIC_PWR_RST); if (tmp & PC_OUTPUT_ENABLE) { tmp &= ~PC_OUTPUT_ENABLE; PcicWriteSocket(Socket, PCIC_PWR_RST, tmp); } } } oldPower = CBReadSocketRegister(Socket, CARDBUS_SOCKET_CONTROL_REG); newPower = vcc | vpp; newPower|= oldPower & ~(SKTPOWER_VPP_CONTROL |SKTPOWER_VCC_CONTROL);
if (newPower != oldPower) { CBWriteSocketRegister(Socket, CARDBUS_SOCKET_CONTROL_REG, newPower); //
// When power is enabled always stall to give the PCCARD
// a chance to react.
//
*pDelayTime = PcicStallPower; Socket->PowerData = newPower; status = STATUS_MORE_PROCESSING_REQUIRED; } else { //
// Indicate that nothing was done
//
status = STATUS_INVALID_DEVICE_STATE; } break;
case 2: case 3: case 4:
newPower = Socket->PowerData; //
// Try to apply the required power setting a few times.
// We bail if it doesn't succeed after the given number of tries
//
state = CBReadSocketRegister(Socket, CARDBUS_SOCKET_PRESENT_STATE_REG); if (state & SKTSTATE_BADVCCREQ) { DebugPrint((PCMCIA_DEBUG_INFO, "skt %08 CBSetPower: Bad vcc request\n", Socket)); //
// Clear the status bits & try again
//
CBWriteSocketRegister(Socket, CARDBUS_SOCKET_FORCE_EVENT_REG, 0); CBWriteSocketRegister(Socket, CARDBUS_SOCKET_CONTROL_REG, newPower); *pDelayTime = PcicStallPower; status = STATUS_MORE_PROCESSING_REQUIRED; } else { status = STATUS_SUCCESS; if (Is16BitCardInSocket(Socket)) { tmp = PcicReadSocket(Socket, PCIC_PWR_RST); if (newPower & SKTPOWER_VCC_CONTROL) { //
// Vcc is on..
//
tmp |= PC_OUTPUT_ENABLE | PC_AUTOPWR_ENABLE; PcicWriteSocket(Socket, PCIC_PWR_RST, tmp); *pDelayTime = PcicStallPower; } else { //
// power off..
//
tmp &= ~(PC_OUTPUT_ENABLE | PC_AUTOPWR_ENABLE); PcicWriteSocket(Socket, PCIC_PWR_RST, tmp); } } } break; default: DebugPrint((PCMCIA_DEBUG_FAIL, "skt %08 CBSetPower: Final retry failed - bad vcc\n", Socket)); ASSERT(FALSE); status = STATUS_UNSUCCESSFUL; } return status; }
BOOLEAN CBSetWindowPage( IN PSOCKET Socket, USHORT Index, UCHAR Page ) { ASSERT(Index <= 4);
PcicWriteSocket(Socket, (UCHAR) (PCIC_PAGE_REG + Index), Page); return TRUE; }
ULONG CBReadSocketRegister( IN PSOCKET Socket, IN UCHAR Register ) /*++
Routine Description
Returns the contents of the specified Cardbus socket register for the given socket
Arguments
Socket - Pointer to the socket Register - Cardbus socket register
Return Value
Contents of the register
--*/ { ULONG data; ASSERT (CardBus(Socket)); ASSERT (Socket->DeviceExtension->CardBusSocketRegisterBase != NULL); ASSERT ((Register&3) == 0);
//
// Sanity check in case controller wasn't started
// or if the register is not dword aligned
//
if ((Socket->DeviceExtension->CardBusSocketRegisterBase) && ((Register&3) == 0)) { data = READ_REGISTER_ULONG((PULONG) (Socket->DeviceExtension->CardBusSocketRegisterBase+Register)); } else { data = 0xFFFFFFFF; } return data; }
VOID CBWriteSocketRegister( IN PSOCKET Socket, IN UCHAR Register, IN ULONG Data ) /*++
Routine Description
Writes the supplied value to the Cardbus socket register for the given socket
Arguments
Socket - Pointer to the socket Register - Cardbus socket register Data - Value to be written to the register
Return Value
--*/ { ASSERT (CardBus(Socket)); ASSERT (Socket->DeviceExtension->CardBusSocketRegisterBase != NULL); ASSERT ((Register&3) == 0); //
// Sanity check in case controller wasn't started
// or if the register is not dword aligned
//
if ((Socket->DeviceExtension->CardBusSocketRegisterBase) && ((Register&3) == 0)) { WRITE_REGISTER_ULONG((PULONG) (Socket->DeviceExtension->CardBusSocketRegisterBase+Register), Data); } }
|