/*++ Copyright (c) 2002 Microsoft Corporation Module Name: activate.c Abstract: This module contains code to prepare an SD card in a given slot for use. This is done when the host is started, after device insertions, and after a power up transition. Authors: Neil Sandlin (neilsa) Jan 1, 2002 Environment: Kernel mode only Notes: Revision History: --*/ #include "pch.h" // // Internal References // VOID SdbusActivatePowerUpComplete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ); VOID SdbusActivateIdentifyPhase1Complete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ); VOID SdbusActivateIdentifyPhase2Complete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ); VOID SdbusActivateInitializeCardComplete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ); // // // VOID SdbusActivateSocket( IN PDEVICE_OBJECT Fdo, IN PSDBUS_ACTIVATE_COMPLETION_ROUTINE CompletionRoutine, IN PVOID Context ) /*++ Routine Description: Arguments: Fdo - Pointer to the device object for the host controller Return Value: --*/ { NTSTATUS status; PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension; PSD_WORK_PACKET workPacket1 = NULL, workPacket2 = NULL, workPacket3 = NULL, workPacket4 = NULL; BOOLEAN cardInSlot; BOOLEAN callCompletion; PSD_ACTIVATE_CONTEXT activateContext; DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x activate socket START\n", Fdo)); activateContext = ExAllocatePool(NonPagedPool, sizeof(SD_ACTIVATE_CONTEXT)); if (!activateContext) { ASSERT(activateContext != NULL); return; } activateContext->CompletionRoutine = CompletionRoutine; activateContext->Context = Context; try{ cardInSlot = (*(fdoExtension->FunctionBlock->DetectCardInSocket))(fdoExtension); if (!cardInSlot) { if (fdoExtension->SocketState != SOCKET_EMPTY) { IoInvalidateDeviceRelations(fdoExtension->Pdo, BusRelations); } //ISSUE: implement synchronization fdoExtension->SocketState = SOCKET_EMPTY; callCompletion = TRUE; status = STATUS_SUCCESS; leave; } fdoExtension->SocketState = CARD_DETECTED; status = SdbusBuildWorkPacket(fdoExtension, SDWP_POWER_ON, SdbusActivatePowerUpComplete, NULL, &workPacket1); if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } status = SdbusBuildWorkPacket(fdoExtension, SDWP_IDENTIFY_IO_DEVICE, SdbusActivateIdentifyPhase1Complete, NULL, &workPacket2); if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } status = SdbusBuildWorkPacket(fdoExtension, SDWP_IDENTIFY_MEMORY_DEVICE, SdbusActivateIdentifyPhase2Complete, NULL, &workPacket3); if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } status = SdbusBuildWorkPacket(fdoExtension, SDWP_INITIALIZE_CARD, SdbusActivateInitializeCardComplete, activateContext, &workPacket4); if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } workPacket1->NextWorkPacketInChain = workPacket2; workPacket2->NextWorkPacketInChain = workPacket3; workPacket3->NextWorkPacketInChain = workPacket4; SdbusQueueWorkPacket(fdoExtension, workPacket1, WP_TYPE_SYSTEM); callCompletion = FALSE; } finally { if (callCompletion) { if (activateContext->CompletionRoutine) { (*activateContext->CompletionRoutine)(Fdo, activateContext->Context, status); } if (workPacket1) { ExFreePool(workPacket1); } if (workPacket2) { ExFreePool(workPacket2); } if (workPacket3) { ExFreePool(workPacket3); } if (workPacket4) { ExFreePool(workPacket4); } ExFreePool(activateContext); } } } VOID SdbusActivatePowerUpComplete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ) /*++ Routine Description: Arguments: Return Value: --*/ { DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x activate PowerUp Complete\n", WorkPacket->FdoExtension->DeviceObject)); if (WorkPacket->NextWorkPacketInChain) { WorkPacket->NextWorkPacketInChain->ChainedStatus = status; } ExFreePool(WorkPacket); } VOID SdbusActivateIdentifyPhase1Complete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ) /*++ Routine Description: Arguments: Return Value: --*/ { DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x activate Identify Phase1 Complete\n", WorkPacket->FdoExtension->DeviceObject)); if (WorkPacket->NextWorkPacketInChain) { WorkPacket->NextWorkPacketInChain->ChainedStatus = status; } ExFreePool(WorkPacket); } VOID SdbusActivateIdentifyPhase2Complete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ) /*++ Routine Description: Arguments: Fdo - Pointer to the device object for the host controller Return Value: --*/ { PFDO_EXTENSION fdoExtension = WorkPacket->FdoExtension; PDEVICE_OBJECT Fdo = fdoExtension->DeviceObject; PSD_ACTIVATE_CONTEXT activateContext = WorkPacket->CompletionContext; BOOLEAN callCompletion; DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x activate Identify Phase2 Complete\n", WorkPacket->FdoExtension->DeviceObject)); ExFreePool(WorkPacket); #if 0 try{ if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } // // If we get this far, we expect that there is at least one function detected // if (!fdoExtension->numFunctions && !fdoExtension->memFunction) { callCompletion = TRUE; SdbusDumpDbgLog(); status = STATUS_UNSUCCESSFUL; leave; } // // The card should be in the Identification state. Send a CMD3 to get the relative address, // and to move the card to the standby state. // status = SdbusBuildWorkPacket(fdoExtension, SDWP_PASSTHRU, SdbusActivateTransitionToStandbyCompletion, activateContext, &WorkPacket); if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } WorkPacket->ExecutingSDCommand = TRUE; WorkPacket->Cmd = SDCMD_SEND_RELATIVE_ADDR; WorkPacket->ResponseType = SDCMD_RESP_6; SdbusQueueWorkPacket(fdoExtension, WorkPacket, WP_TYPE_SYSTEM_PRIORITY); callCompletion = FALSE; } finally { if (callCompletion) { if (activateContext->CompletionRoutine) { (*activateContext->CompletionRoutine)(Fdo, activateContext->Context, status); } ExFreePool(activateContext); } } #endif } #if 0 VOID SdbusActivateTransitionToStandbyCompletion( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ) /*++ Routine Description: Arguments: Fdo - Pointer to the device object for the host controller Return Value: --*/ { PFDO_EXTENSION fdoExtension = WorkPacket->FdoExtension; PDEVICE_OBJECT Fdo = fdoExtension->DeviceObject; PSD_ACTIVATE_CONTEXT activateContext = WorkPacket->CompletionContext; BOOLEAN callCompletion; DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x activate TransitionToStandby COMPLETE %08x\n", Fdo, status)); try{ if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } fdoExtension->RelativeAddr = WorkPacket->ResponseBuffer[0] & 0xFFFF0000; DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x relative addr %08x\n", Fdo, fdoExtension->RelativeAddr)); status = SdbusBuildWorkPacket(fdoExtension, SDWP_INITIALIZE_CARD, SdbusActivateInitializeCardComplete, activateContext, &workPacket); if (!NT_SUCCESS(status)) { callCompletion = TRUE; leave; } } else { if (activateContext->CompletionRoutine) { (*activateContext->CompletionRoutine)(Fdo, activateContext->Context, status); } ExFreePool(activateContext); } ExFreePool(WorkPacket); } #endif VOID SdbusActivateInitializeCardComplete( IN PSD_WORK_PACKET WorkPacket, IN NTSTATUS status ) /*++ Routine Description: Arguments: Fdo - Pointer to the device object for the host controller Return Value: --*/ { PFDO_EXTENSION fdoExtension = WorkPacket->FdoExtension; PDEVICE_OBJECT Fdo = fdoExtension->DeviceObject; PSD_ACTIVATE_CONTEXT activateContext = WorkPacket->CompletionContext; DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x activate socket COMPLETE %08x\n", Fdo, status)); if (NT_SUCCESS(status)) { fdoExtension->SocketState = CARD_NEEDS_ENUMERATION; IoInvalidateDeviceRelations(fdoExtension->Pdo, BusRelations); } else { DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x activate failure %08x\n", Fdo, status)); SdbusDumpDbgLog(); } ExFreePool(WorkPacket); if (activateContext->CompletionRoutine) { (*activateContext->CompletionRoutine)(Fdo, activateContext->Context, status); } ExFreePool(activateContext); }