/*++ Copyright (c) 2002 Microsoft Corporation Module Name: enum.c Abstract: This module contains the bus enum code for SDBUS driver Authors: Neil Sandlin (neilsa) 1-Jan-2002 Environment: Kernel mode only Notes: Revision History: --*/ #include "pch.h" // // Internal References // NTSTATUS SdbusCreatePdo( IN PDEVICE_OBJECT Fdo, OUT PDEVICE_OBJECT *PdoPtr ); #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, SdbusEnumerateDevices) #pragma alloc_text(PAGE, SdbusCreatePdo) #endif NTSTATUS SdbusEnumerateDevices( IN PDEVICE_OBJECT Fdo, IN PIRP Irp ) /*++ Routine Description: This enumerates the sd bus which is represented by Fdo (a pointer to the device object representing the sd controller. It creates new PDOs for any new PC-Cards which have been discovered since the last enumeration Notes: Arguments: Fdo - Pointer to the functional device object for the SD controller which needs to be enumerated Return value: None --*/ { PFDO_EXTENSION fdoExtension = Fdo->DeviceExtension; PPDO_EXTENSION pdoExtension = NULL; PDEVICE_OBJECT pdo; NTSTATUS status = STATUS_SUCCESS; ULONG i; PDEVICE_OBJECT nextPdo; PSD_CARD_DATA cardData; ULONG response; PAGED_CODE(); DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x enumerate devices - %s\n", Fdo, SOCKET_STATE_STRING(fdoExtension->SocketState))); switch(fdoExtension->SocketState) { case SOCKET_EMPTY: // mark pdo's removed for (pdo = fdoExtension->PdoList; pdo != NULL; pdo = pdoExtension->NextPdoInFdoChain) { pdoExtension = pdo->DeviceExtension; MarkDevicePhysicallyRemoved(pdoExtension); } //ISSUE: NEED TO IMPLEMENT SYNCHRONIZATION SdbusCleanupCardData(fdoExtension->CardData); fdoExtension->CardData = NULL; SdbusExecuteWorkSynchronous(SDWP_POWER_OFF, fdoExtension, NULL); (*(fdoExtension->FunctionBlock->SetFunctionType))(fdoExtension, SDBUS_FUNCTION_TYPE_MEMORY); break; case CARD_NEEDS_ENUMERATION: status = SdbusGetCardConfigData(fdoExtension, &cardData); //ISSUE: HACKHACK: UNIMPLEMENTED: temp code for test if (NT_SUCCESS(status) && fdoExtension->CardData) { // here we cheat, and just assume it is the same card // Normally we would want to compare the carddata we just // built with what was in the fdo extension. SdbusCleanupCardData(cardData); break; } if (!NT_SUCCESS(status)) { DebugPrint((SDBUS_DEBUG_FAIL, "fdo %08x error from GetCardConfig %08x\n", Fdo, status)); break; } if (NT_SUCCESS(status)) { UCHAR function; //ISSUE: would be better here to loop through the function data structures for (function=1; function <= fdoExtension->numFunctions; function++) { status = SdbusCreatePdo(fdoExtension->DeviceObject, &pdo); if (!NT_SUCCESS(status)) { return status; } DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x created PDO %08x\n", fdoExtension->DeviceObject, pdo)); // // initialize the pointers // pdoExtension = pdo->DeviceExtension; pdoExtension->NextPdoInFdoChain = fdoExtension->PdoList; fdoExtension->PdoList = pdo; pdoExtension->FdoExtension = fdoExtension; pdoExtension->Function = function; pdoExtension->FunctionType = SDBUS_FUNCTION_TYPE_IO; } if (fdoExtension->memFunction) { status = SdbusCreatePdo(fdoExtension->DeviceObject, &pdo); if (!NT_SUCCESS(status)) { return status; } DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x created PDO %08x\n", fdoExtension->DeviceObject, pdo)); // // initialize the pointers // pdoExtension = pdo->DeviceExtension; pdoExtension->NextPdoInFdoChain = fdoExtension->PdoList; fdoExtension->PdoList = pdo; pdoExtension->FdoExtension = fdoExtension; pdoExtension->Function = 8; pdoExtension->FunctionType = SDBUS_FUNCTION_TYPE_MEMORY; } fdoExtension->CardData = cardData; } break; case CARD_DETECTED: case CARD_ACTIVE: case CARD_LOGICALLY_REMOVED: DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x enum state %s not implemented\n", Fdo, SOCKET_STATE_STRING(fdoExtension->SocketState))); break; default: ASSERT(FALSE); } fdoExtension->LivePdoCount = 0; for (pdo = fdoExtension->PdoList; pdo != NULL; pdo = pdoExtension->NextPdoInFdoChain) { pdoExtension = pdo->DeviceExtension; if (!IsDevicePhysicallyRemoved(pdoExtension)) { fdoExtension->LivePdoCount++; } } DebugPrint((SDBUS_DEBUG_ENUM, "fdo %08x live pdo count = %d\n", Fdo, fdoExtension->LivePdoCount)); if (fdoExtension->LivePdoCount == 0) { // // ISSUE: active power management not implemented // Hint for the controller to check if it should turn itself off // // SdbusFdoCheckForIdle(fdoExtension); } return status; } NTSTATUS SdbusCreatePdo( IN PDEVICE_OBJECT Fdo, OUT PDEVICE_OBJECT *PdoPtr ) /*++ Routine Description: Creates and initializes a device object - which will be referred to as a Physical Device Object or PDO - for the PC-Card in the socket represented by Socket, hanging off the SDBUS controller represented by Fdo. Arguments: Fdo - Functional device object representing the SDBUS controller Socket - Socket in which the PC-Card for which we're creating a PDO resides PdoPtr - Pointer to an area of memory where the created PDO is returned Return value: STATUS_SUCCESS - Pdo creation/initialization successful, PdoPtr contains the pointer to the Pdo Any other status - creation/initialization unsuccessful --*/ { ULONG pdoNameIndex = 0; PPDO_EXTENSION pdoExtension; PFDO_EXTENSION fdoExtension=Fdo->DeviceExtension; char deviceName[128]; ANSI_STRING ansiName; UNICODE_STRING unicodeName; NTSTATUS status; PAGED_CODE(); // // Allocate space for the Unicode string:(handles upto 0xFFFF // devices for now :) // sprintf(deviceName, "%s-%d", "\\Device\\SdBus", 0xFFFF); RtlInitAnsiString(&ansiName, deviceName); status = RtlAnsiStringToUnicodeString(&unicodeName, &ansiName, TRUE); if (!NT_SUCCESS(status)) { return status; } // // Attempt to create the device with a unique name // do { sprintf(deviceName, "%s-%d", "\\Device\\SdBus", pdoNameIndex++); RtlInitAnsiString(&ansiName, deviceName); status = RtlAnsiStringToUnicodeString(&unicodeName, &ansiName, FALSE); if (!NT_SUCCESS(status)) { RtlFreeUnicodeString(&unicodeName); return status; } status = IoCreateDevice( Fdo->DriverObject, sizeof(PDO_EXTENSION), &unicodeName, FILE_DEVICE_UNKNOWN, 0, FALSE, PdoPtr ); } while ((status == STATUS_OBJECT_NAME_EXISTS) || (status == STATUS_OBJECT_NAME_COLLISION)); RtlFreeUnicodeString(&unicodeName); if (!NT_SUCCESS(status)) { return status; } // // Initialize the device extension for the PDO // pdoExtension = (*PdoPtr)->DeviceExtension; RtlZeroMemory(pdoExtension, sizeof(PDO_EXTENSION)); pdoExtension->Signature = SDBUS_PDO_EXTENSION_SIGNATURE; pdoExtension->DeviceObject = *PdoPtr; // // Initialize power states // pdoExtension->SystemPowerState = PowerSystemWorking; pdoExtension->DevicePowerState = PowerDeviceD0; // // ISSUE: Is this still relevant? // // PNP is going to mark the PDO as a DO_BUS_ENUMERATED_DEVICE, // but for CardBus cards- the PDO we return is owned by PCI. // Hence we need to mark this device object (in that case a // filter on top of PCI's PDO) as PDO explicitly. // // MARK_AS_PDO(*PdoPtr); return STATUS_SUCCESS; }