|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: chanpdo.c
//
//--------------------------------------------------------------------------
#include "pciidex.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, ChannelStartDevice)
#pragma alloc_text(PAGE, ChannelQueryStopRemoveDevice)
#pragma alloc_text(PAGE, ChannelRemoveDevice)
#pragma alloc_text(PAGE, ChannelStopDevice)
#pragma alloc_text(PAGE, ChannelStopChannel)
#pragma alloc_text(PAGE, ChannelQueryId)
#pragma alloc_text(PAGE, ChannelBuildDeviceId)
#pragma alloc_text(PAGE, ChannelBuildInstanceId)
#pragma alloc_text(PAGE, ChannelBuildCompatibleId)
#pragma alloc_text(PAGE, ChannelBuildHardwareId)
#pragma alloc_text(PAGE, ChannelQueryCapabitilies)
#pragma alloc_text(PAGE, ChannelQueryResources)
#pragma alloc_text(PAGE, ChannelQueryResourceRequirements)
#pragma alloc_text(PAGE, ChannelInternalDeviceIoControl)
#pragma alloc_text(PAGE, ChannelQueryText)
#pragma alloc_text(PAGE, PciIdeChannelQueryInterface)
#pragma alloc_text(PAGE, ChannelQueryDeviceRelations)
#pragma alloc_text(PAGE, ChannelUsageNotification)
#pragma alloc_text(PAGE, ChannelQueryPnPDeviceState)
#pragma alloc_text(NONPAGE, ChannelGetPdoExtension)
#pragma alloc_text(NONPAGE, ChannelUpdatePdoState)
#pragma alloc_text(NONPAGE, PciIdeChannelTransferModeSelect)
#pragma alloc_text(NONPAGE, PciIdeChannelTransferModeInterface)
#endif // ALLOC_PRAGMA
PCHANPDO_EXTENSION ChannelGetPdoExtension( PDEVICE_OBJECT DeviceObject ) { KIRQL currentIrql; PCHANPDO_EXTENSION pdoExtension = DeviceObject->DeviceExtension; PKSPIN_LOCK spinLock;
spinLock = &pdoExtension->SpinLock; KeAcquireSpinLock(spinLock, ¤tIrql);
if ((pdoExtension->PdoState & PDOS_DEADMEAT) && (pdoExtension->PdoState & PDOS_REMOVED)) {
pdoExtension = NULL; }
KeReleaseSpinLock(spinLock, currentIrql);
return pdoExtension; }
ULONG ChannelUpdatePdoState( PCHANPDO_EXTENSION PdoExtension, ULONG SetFlags, ULONG ClearFlags ) { ULONG pdoState; KIRQL currentIrql;
ASSERT (PdoExtension);
KeAcquireSpinLock(&PdoExtension->SpinLock, ¤tIrql);
SETMASK (PdoExtension->PdoState, SetFlags); CLRMASK (PdoExtension->PdoState, ClearFlags); pdoState = PdoExtension->PdoState;
KeReleaseSpinLock(&PdoExtension->SpinLock, currentIrql);
return pdoState; }
NTSTATUS ChannelStartDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PCHANPDO_EXTENSION pdoExtension; NTSTATUS status; IDE_CHANNEL_STATE channelState;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
status = STATUS_SUCCESS;
//
// always keep native mode started
//
if (pdoExtension->ParentDeviceExtension-> NativeMode[pdoExtension->ChannelNumber] == FALSE) {
channelState = PciIdeChannelEnabled ( pdoExtension->ParentDeviceExtension, pdoExtension->ChannelNumber ); //
// ISSUE: we should free the resources assigned.
//
//ASSERT(channelState != ChannelDisabled);
if (channelState == ChannelStateUnknown) {
//
// we don't really know if this channel
// is acutally enabled
//
// we will do our empty channel test
//
PIO_STACK_LOCATION thisIrpSp; IDE_RESOURCE ideResource; PCM_PARTIAL_RESOURCE_DESCRIPTOR irqPartialDescriptors; IDE_REGISTERS_1 baseIoAddress1; IDE_REGISTERS_2 baseIoAddress2; ULONG baseIoAddressLength1; ULONG baseIoAddressLength2; ULONG maxIdeDevice; PCM_RESOURCE_LIST resourceList;
thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
//
// legacy mode channel gets its the start device irp
//
resourceList = thisIrpSp->Parameters.StartDevice.AllocatedResourcesTranslated;
status = DigestResourceList ( &ideResource, resourceList, &irqPartialDescriptors );
if (NT_SUCCESS(status)) {
AtapiBuildIoAddress ( ideResource.TranslatedCommandBaseAddress, ideResource.TranslatedControlBaseAddress, &baseIoAddress1, &baseIoAddress2, &baseIoAddressLength1, &baseIoAddressLength2, &maxIdeDevice, NULL );
if (IdePortChannelEmpty ( &baseIoAddress1, &baseIoAddress2, maxIdeDevice)) {
//
// upgrade its state to "disabled"
//
channelState = ChannelDisabled;
} else {
channelState = ChannelEnabled; }
//
// don't need the io resource anymore
// unmap io space if nesscessary
//
if ((ideResource.CommandBaseAddressSpace == MEMORY_SPACE) && (ideResource.TranslatedCommandBaseAddress)) {
MmUnmapIoSpace ( ideResource.TranslatedCommandBaseAddress, baseIoAddressLength1 ); } if ((ideResource.ControlBaseAddressSpace == MEMORY_SPACE) && (ideResource.TranslatedControlBaseAddress)) {
MmUnmapIoSpace ( ideResource.TranslatedControlBaseAddress, baseIoAddressLength2 ); }
} if (channelState == ChannelDisabled) {
pdoExtension->EmptyChannel = TRUE;
//
// channel looks empty
// change our resource requirement to free our irq for other devices
//
if (irqPartialDescriptors) { SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED); IoInvalidateDeviceState (DeviceObject); } } else {
pdoExtension->EmptyChannel = FALSE; } } }
if (NT_SUCCESS(status)) {
//
// grab the DmaDetectionLevel from the registry
// default is DdlFirmwareOk
//
pdoExtension->DmaDetectionLevel = DdlFirmwareOk; status = PciIdeXGetDeviceParameter ( pdoExtension->DeviceObject, DMA_DETECTION_LEVEL_REG_KEY, (PULONG)&pdoExtension->DmaDetectionLevel );
status = BusMasterInitialize (pdoExtension); } }
if (NT_SUCCESS(status)) {
//
// get the firmware initialized DMA capable bits
//
if (pdoExtension->BmRegister) {
pdoExtension->BootBmStatus = READ_PORT_UCHAR (&pdoExtension->BmRegister->Status); }
ChannelUpdatePdoState ( pdoExtension, PDOS_STARTED, PDOS_DEADMEAT | PDOS_STOPPED | PDOS_REMOVED );
}
#if DBG
{ ULONG data; USHORT vendorId =0; USHORT deviceId = 0; PVOID deviceExtension;
data = 0; deviceExtension = pdoExtension->ParentDeviceExtension->VendorSpecificDeviceEntension;
PciIdeXGetBusData ( deviceExtension, &vendorId, FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID), sizeof(vendorId) );
PciIdeXGetBusData ( deviceExtension, &deviceId, FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceID), sizeof(deviceId) );
if (vendorId == 0x8086) {
data = 0; PciIdeXGetBusData ( deviceExtension, &data, 0x40, // IDETIM0
2 );
PciIdeXSaveDeviceParameter ( deviceExtension, L"Old IDETIM0", data );
data = 0; PciIdeXGetBusData ( deviceExtension, &data, 0x42, // IDETIM1
2 );
PciIdeXSaveDeviceParameter ( deviceExtension, L"Old IDETIM1", data );
if (deviceId != 0x1230) { // !PIIX
data = 0; PciIdeXGetBusData ( deviceExtension, &data, 0x44, 1 );
PciIdeXSaveDeviceParameter ( deviceExtension, L"Old SIDETIM", data ); }
if (deviceId == 0x7111) {
USHORT t;
data = 0; PciIdeXGetBusData ( deviceExtension, &data, 0x48, 1 );
PciIdeXSaveDeviceParameter ( deviceExtension, L"Old SDMACTL", data );
data = 0; PciIdeXGetBusData ( deviceExtension, &data, 0x4a, //SDMATIM0
1 );
PciIdeXSaveDeviceParameter ( deviceExtension, L"Old SDMATIM0", data );
data = 0; PciIdeXGetBusData ( deviceExtension, &data, 0x4b, //SDMATIM1
1 );
PciIdeXSaveDeviceParameter ( deviceExtension, L"Old SDMATIM1", data ); } } } #endif // DBG
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status; } // ChannelStartDevice
NTSTATUS ChannelQueryStopRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { NTSTATUS status; PCHANPDO_EXTENSION pdoExtension;
pdoExtension = ChannelGetPdoExtension(DeviceObject);
if (pdoExtension) {
//
// Check the paging path count for this device.
//
if (pdoExtension->PagingPathCount || pdoExtension->CrashDumpPathCount) { status = STATUS_UNSUCCESSFUL; } else { status = STATUS_SUCCESS; }
} else {
status = STATUS_NO_SUCH_DEVICE; }
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status;
} // ChannelQueryStopRemoveDevice
NTSTATUS ChannelRemoveDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PCHANPDO_EXTENSION pdoExtension; NTSTATUS status; PDEVICE_OBJECT AttacheePdo; BOOLEAN removeFromParent; BOOLEAN callIoDeleteDevice;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension) {
PIO_STACK_LOCATION thisIrpSp; ULONG actionFlag;
thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
status = ChannelStopChannel (pdoExtension); ASSERT (NT_SUCCESS(status));
if (thisIrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE) {
if (pdoExtension->PdoState & PDOS_DEADMEAT) {
actionFlag = PDOS_REMOVED; removeFromParent = TRUE; callIoDeleteDevice = TRUE;
} else { actionFlag = PDOS_DISABLED_BY_USER; removeFromParent = FALSE; callIoDeleteDevice = FALSE; }
} else {
actionFlag = PDOS_SURPRISE_REMOVED; removeFromParent = FALSE; callIoDeleteDevice = FALSE; }
ChannelUpdatePdoState ( pdoExtension, actionFlag, PDOS_STARTED | PDOS_STOPPED );
if (removeFromParent) {
PCTRLFDO_EXTENSION fdoExtension;
fdoExtension = pdoExtension->ParentDeviceExtension;
fdoExtension->ChildDeviceExtension[pdoExtension->ChannelNumber] = NULL;
if (callIoDeleteDevice) {
IoDeleteDevice (pdoExtension->DeviceObject); } }
if (pdoExtension->NeedToCallIoInvalidateDeviceRelations) {
pdoExtension->NeedToCallIoInvalidateDeviceRelations = FALSE; IoInvalidateDeviceRelations ( pdoExtension->ParentDeviceExtension->AttacheePdo, BusRelations ); }
status = STATUS_SUCCESS;
} else {
status = STATUS_NO_SUCH_DEVICE; }
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status; } // ChannelRemoveDevice
NTSTATUS ChannelStopDevice ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PCHANPDO_EXTENSION pdoExtension; NTSTATUS status;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
status = ChannelStopChannel (pdoExtension); ASSERT (NT_SUCCESS(status));
ChannelUpdatePdoState ( pdoExtension, PDOS_STOPPED, PDOS_STARTED );
status = STATUS_SUCCESS; }
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT );
return status; } // ChannelRemoveDevice
NTSTATUS ChannelStopChannel ( PCHANPDO_EXTENSION PdoExtension ) { NTSTATUS status;
PAGED_CODE();
status = BusMasterUninitialize (PdoExtension); ASSERT (NT_SUCCESS(status));
return STATUS_SUCCESS; } // ChannelStopChannel
NTSTATUS ChannelQueryId ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PCHANPDO_EXTENSION pdoExtension; NTSTATUS status = STATUS_UNSUCCESSFUL; PWSTR idString = NULL;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
thisIrpSp = IoGetCurrentIrpStackLocation( Irp ); switch (thisIrpSp->Parameters.QueryId.IdType) {
case BusQueryDeviceID:
//
// Caller wants the bus ID of this device.
//
idString = ChannelBuildDeviceId (pdoExtension); break;
case BusQueryInstanceID:
//
// Caller wants the unique id of the device
//
idString = ChannelBuildInstanceId (pdoExtension); break;
case BusQueryCompatibleIDs:
//
// Caller wants the unique id of the device
//
idString = ChannelBuildCompatibleId (pdoExtension); break;
case BusQueryHardwareIDs:
//
// Caller wants the unique id of the device
//
idString = ChannelBuildHardwareId (pdoExtension); break;
default: idString = NULL; DebugPrint ((1, "pciide: QueryID type %d not supported\n", thisIrpSp->Parameters.QueryId.IdType)); status = STATUS_NOT_SUPPORTED; break; } }
if( idString != NULL ){ Irp->IoStatus.Information = (ULONG_PTR) idString; status = STATUS_SUCCESS; }
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } // ChannelQueryId
PWSTR ChannelBuildDeviceId( IN PCHANPDO_EXTENSION pdoExtension ) { PWSTR idString; ULONG idStringBufLen; NTSTATUS status; WCHAR deviceIdFormat[] = L"PCIIDE\\IDEChannel";
PAGED_CODE();
idStringBufLen = ( wcslen( deviceIdFormat ) + 1 ) * sizeof( WCHAR ); idString = ExAllocatePool( PagedPool, idStringBufLen ); if( idString == NULL ){
return NULL; }
//
// Form the string and return it.
//
swprintf( idString, deviceIdFormat);
return idString; } // ChannelBuildDeviceId
PWSTR ChannelBuildInstanceId( IN PCHANPDO_EXTENSION pdoExtension ) { PWSTR idString; ULONG idStringBufLen; NTSTATUS status; WCHAR instanceIdFormat[] = L"%d";
PAGED_CODE();
idStringBufLen = 10 * sizeof( WCHAR ); idString = ExAllocatePool (PagedPool, idStringBufLen); if( idString == NULL ){
return NULL; }
//
// Form the string and return it.
//
swprintf( idString, instanceIdFormat, pdoExtension->ChannelNumber);
return idString; } // ChannelBuildInstanceId
//
// Multi-string Compatible IDs
//
WCHAR ChannelCompatibleId[] = { L"*PNP0600" }; //
// internal Compatible IDs
//
PWCHAR ChannelInternalCompatibleId[MAX_IDE_CHANNEL] = { L"Primary_IDE_Channel", L"Secondary_IDE_Channel" };
PWSTR ChannelBuildCompatibleId( IN PCHANPDO_EXTENSION pdoExtension ) { PWSTR idString; ULONG idStringBufLen; ULONG i;
PAGED_CODE();
idStringBufLen = sizeof(ChannelCompatibleId); idString = ExAllocatePool (PagedPool, idStringBufLen + sizeof (WCHAR) * 2); if( idString == NULL ){
return NULL; }
RtlCopyMemory ( idString, ChannelCompatibleId, idStringBufLen ); idString[idStringBufLen/2 + 0] = L'\0'; idString[idStringBufLen/2 + 1] = L'\0';
return idString; } // ChannelBuildCompatibleId
PWSTR ChannelBuildHardwareId( IN PCHANPDO_EXTENSION pdoExtension ) { NTSTATUS status;
struct { USHORT VendorId; USHORT DeviceId; } hwRawId;
PWSTR vendorIdString; PWSTR deviceIdString; WCHAR vendorId[10]; WCHAR deviceId[10];
PWSTR idString; ULONG idStringBufLen;
ULONG stringLen; ULONG internalIdLen;
PAGED_CODE();
status = PciIdeBusData ( pdoExtension->ParentDeviceExtension, &hwRawId, 0, sizeof (hwRawId), TRUE ); if (!NT_SUCCESS(status)) {
return NULL; }
vendorIdString = NULL; deviceIdString = NULL;
switch (hwRawId.VendorId) { case 0x8086: vendorIdString = L"Intel";
switch (hwRawId.DeviceId) {
case 0x1230: deviceIdString = L"PIIX"; break;
case 0x7010: deviceIdString = L"PIIX3"; break;
case 0x7111: deviceIdString = L"PIIX4"; break; } break;
case 0x1095: vendorIdString = L"CMD"; break;
case 0x10b9: vendorIdString = L"ALi"; break;
case 0x1039: vendorIdString = L"SiS"; break;
case 0x0e11: vendorIdString = L"Compaq"; break;
case 0x10ad: vendorIdString = L"WinBond"; break; }
if (vendorIdString == NULL) {
swprintf (vendorId, L"%04x", hwRawId.VendorId);
vendorIdString = vendorId; }
if (deviceIdString == NULL) {
swprintf (deviceId, L"%04x", hwRawId.DeviceId);
deviceIdString = deviceId; }
idStringBufLen = (256 * sizeof (WCHAR)); idStringBufLen += sizeof(ChannelCompatibleId); idString = ExAllocatePool( PagedPool, idStringBufLen); if( idString == NULL ){
return NULL; }
//
// Form the string and return it.
//
swprintf (idString, L"%ws-%ws", vendorIdString, deviceIdString ); stringLen = wcslen(idString); idString[stringLen] = L'\0'; stringLen++;
//
// internal HW id
//
internalIdLen = wcslen(ChannelInternalCompatibleId[pdoExtension->ChannelNumber]); RtlCopyMemory ( idString + stringLen, ChannelInternalCompatibleId[pdoExtension->ChannelNumber], internalIdLen * sizeof (WCHAR) ); stringLen += internalIdLen; idString[stringLen] = L'\0'; stringLen++;
//
// generic HW id
//
RtlCopyMemory ( idString + stringLen, ChannelCompatibleId, sizeof(ChannelCompatibleId) ); stringLen += sizeof(ChannelCompatibleId) / sizeof(WCHAR); idString[stringLen] = L'\0'; stringLen++; idString[stringLen] = L'\0'; stringLen++;
return idString; } // ChannelBuildHardwareId
NTSTATUS ChannelQueryCapabitilies ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PCHANPDO_EXTENSION pdoExtension; PDEVICE_CAPABILITIES capabilities; NTSTATUS status;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
DEVICE_CAPABILITIES parentDeviceCapabilities;
status = IdeGetDeviceCapabilities( pdoExtension->ParentDeviceExtension->AttacheePdo, &parentDeviceCapabilities);
if (NT_SUCCESS(status)) {
thisIrpSp = IoGetCurrentIrpStackLocation( Irp ); capabilities = thisIrpSp->Parameters.DeviceCapabilities.Capabilities;
*capabilities = parentDeviceCapabilities;
capabilities->UniqueID = FALSE; capabilities->Address = pdoExtension->ChannelNumber; } }
Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // ChannelQueryCapabitilies
NTSTATUS ChannelQueryResources( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PCHANPDO_EXTENSION pdoExtension; PCTRLFDO_EXTENSION fdoExtension; PIO_STACK_LOCATION thisIrpSp; NTSTATUS status; ULONG resourceListSize; PCM_RESOURCE_LIST resourceList; PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList; PCM_PARTIAL_RESOURCE_LIST partialResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors; IDE_CHANNEL_STATE channelState;
PAGED_CODE();
resourceList = NULL; pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
thisIrpSp = IoGetCurrentIrpStackLocation( Irp ); fdoExtension = pdoExtension->ParentDeviceExtension;
if (fdoExtension->NativeMode[pdoExtension->ChannelNumber]) {
//
// Don't make up resources for native mode controller
// PCI bus driver should find them all
//
resourceList = NULL; status = STATUS_SUCCESS; goto GetOut; }
//
// Don't claim resources if the channel is disabled
//
channelState = PciIdeChannelEnabled ( pdoExtension->ParentDeviceExtension, pdoExtension->ChannelNumber ); if (channelState == ChannelDisabled) {
resourceList = NULL; status = STATUS_SUCCESS; goto GetOut; }
//
// TEMP CODE for the time without a real PCI driver.
// Actually pciidex should do this
//
resourceListSize = sizeof (CM_RESOURCE_LIST) - sizeof (CM_FULL_RESOURCE_DESCRIPTOR) + FULL_RESOURCE_LIST_SIZE(3); // primary IO (2) + IRQ
resourceList = ExAllocatePool (PagedPool, resourceListSize); if (resourceList == NULL) { status = STATUS_NO_MEMORY; goto GetOut; }
RtlZeroMemory(resourceList, resourceListSize);
resourceList->Count = 1; fullResourceList = resourceList->List; partialResourceList = &(fullResourceList->PartialResourceList); partialResourceList->Count = 0; partialDescriptors = partialResourceList->PartialDescriptors;
fullResourceList->InterfaceType = Isa; fullResourceList->BusNumber = 0;
if (pdoExtension->ChannelNumber == 0) {
if (!fdoExtension->PdoCmdRegResourceFound[0]) {
partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort; partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x1f0; partialDescriptors[partialResourceList->Count].u.Port.Length = 8;
partialResourceList->Count++; }
if (!fdoExtension->PdoCtrlRegResourceFound[0]) {
partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort; partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x3f6; partialDescriptors[partialResourceList->Count].u.Port.Length = 1;
partialResourceList->Count++; }
if (!fdoExtension->PdoInterruptResourceFound[0]) {
partialDescriptors[partialResourceList->Count].Type = CmResourceTypeInterrupt; partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED; partialDescriptors[partialResourceList->Count].u.Interrupt.Level = 14; partialDescriptors[partialResourceList->Count].u.Interrupt.Vector = 14; partialDescriptors[partialResourceList->Count].u.Interrupt.Affinity = 0x1; // ISSUE: 08/28/2000: To be looked into.
partialResourceList->Count++; }
} else { // if (pdoExtension->ChannelNumber == 1)
if (!fdoExtension->PdoCmdRegResourceFound[1]) {
partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort; partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x170; partialDescriptors[partialResourceList->Count].u.Port.Length = 8;
partialResourceList->Count++; }
if (!fdoExtension->PdoCtrlRegResourceFound[1]) {
partialDescriptors[partialResourceList->Count].Type = CmResourceTypePort; partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; partialDescriptors[partialResourceList->Count].u.Port.Start.QuadPart = 0x376; partialDescriptors[partialResourceList->Count].u.Port.Length = 1;
partialResourceList->Count++; }
if (!fdoExtension->PdoInterruptResourceFound[1]) {
partialDescriptors[partialResourceList->Count].Type = CmResourceTypeInterrupt; partialDescriptors[partialResourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; partialDescriptors[partialResourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED; partialDescriptors[partialResourceList->Count].u.Interrupt.Level = 15; partialDescriptors[partialResourceList->Count].u.Interrupt.Vector = 15; partialDescriptors[partialResourceList->Count].u.Interrupt.Affinity = 0x1; // ISSUE: 08/28/2000: To be Looked into
partialResourceList->Count++; } }
if (!partialResourceList->Count) {
ExFreePool (resourceList); resourceList = NULL; }
status = STATUS_SUCCESS; }
GetOut:
Irp->IoStatus.Information = (ULONG_PTR) resourceList; Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } // ChannelQueryResources
NTSTATUS ChannelQueryResourceRequirements( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PCHANPDO_EXTENSION pdoExtension; PCTRLFDO_EXTENSION fdoExtension; NTSTATUS status;
PIO_RESOURCE_REQUIREMENTS_LIST requirementsList; PIO_RESOURCE_LIST resourceList; PIO_RESOURCE_DESCRIPTOR resourceDescriptor; ULONG requirementsListSize;
BOOLEAN reportIrq; IDE_CHANNEL_STATE channelState;
PAGED_CODE();
requirementsList = NULL; pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
thisIrpSp = IoGetCurrentIrpStackLocation( Irp ); fdoExtension = pdoExtension->ParentDeviceExtension;
if (fdoExtension->NativeMode[pdoExtension->ChannelNumber]) {
//
// Don't make up resources for native mode controller
// PCI bus driver should find them all
//
requirementsList = NULL; status = STATUS_SUCCESS; goto GetOut; }
//
// legacy controller
//
channelState = PciIdeChannelEnabled ( pdoExtension->ParentDeviceExtension, pdoExtension->ChannelNumber );
//
// Don't claim resources if the channel is disabled
//
if (channelState == ChannelStateUnknown ) {
if (pdoExtension->EmptyChannel) {
reportIrq = FALSE;
} else {
reportIrq = TRUE; } } else if (channelState == ChannelDisabled) {
requirementsList = NULL; status = STATUS_SUCCESS; goto GetOut; }
//
// TEMP CODE for the time without a real PCI driver.
// pciidex should do this.
//
requirementsListSize = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) + sizeof (IO_RESOURCE_DESCRIPTOR) * (3 - 1); requirementsList = ExAllocatePool (PagedPool, requirementsListSize); if( requirementsList == NULL ){ status = STATUS_NO_MEMORY; goto GetOut; }
RtlZeroMemory(requirementsList, requirementsListSize);
requirementsList->ListSize = requirementsListSize; requirementsList->InterfaceType = Isa; requirementsList->BusNumber = 0; // ISSUE: 08/30/2000
requirementsList->SlotNumber = 0; requirementsList->AlternativeLists = 1;
resourceList = requirementsList->List; resourceList->Version = 1; resourceList->Revision = 1; resourceList->Count = 0;
resourceDescriptor = resourceList->Descriptors;
if (pdoExtension->ChannelNumber == 0) {
if (!fdoExtension->PdoCmdRegResourceFound[0]) {
resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED; resourceDescriptor[resourceList->Count].Type = CmResourceTypePort; resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; resourceDescriptor[resourceList->Count].u.Port.Length = 8; resourceDescriptor[resourceList->Count].u.Port.Alignment = 1; resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x1f0; resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x1f7;
resourceList->Count++; }
if (!fdoExtension->PdoCtrlRegResourceFound[0]) {
resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED; resourceDescriptor[resourceList->Count].Type = CmResourceTypePort; resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; resourceDescriptor[resourceList->Count].u.Port.Length = 1; resourceDescriptor[resourceList->Count].u.Port.Alignment = 1; resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x3f6; resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x3f6;
resourceList->Count++; }
if (!fdoExtension->PdoInterruptResourceFound[0] && reportIrq) {
resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED; resourceDescriptor[resourceList->Count].Type = CmResourceTypeInterrupt; resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED; resourceDescriptor[resourceList->Count].u.Interrupt.MinimumVector = 0xe; resourceDescriptor[resourceList->Count].u.Interrupt.MaximumVector = 0xe;
resourceList->Count++; }
} else { // if (pdoExtension->ChannelNumber == 1)
if (!fdoExtension->PdoCmdRegResourceFound[1]) {
resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED; resourceDescriptor[resourceList->Count].Type = CmResourceTypePort; resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; resourceDescriptor[resourceList->Count].u.Port.Length = 8; resourceDescriptor[resourceList->Count].u.Port.Alignment = 1; resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x170; resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x177;
resourceList->Count++; }
if (!fdoExtension->PdoCtrlRegResourceFound[1]) {
resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED; resourceDescriptor[resourceList->Count].Type = CmResourceTypePort; resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_PORT_IO | CM_RESOURCE_PORT_16_BIT_DECODE; resourceDescriptor[resourceList->Count].u.Port.Length = 1; resourceDescriptor[resourceList->Count].u.Port.Alignment = 1; resourceDescriptor[resourceList->Count].u.Port.MinimumAddress.QuadPart = 0x376; resourceDescriptor[resourceList->Count].u.Port.MaximumAddress.QuadPart = 0x376;
resourceList->Count++; }
if (!fdoExtension->PdoInterruptResourceFound[1] && reportIrq) {
resourceDescriptor[resourceList->Count].Option = IO_RESOURCE_PREFERRED; resourceDescriptor[resourceList->Count].Type = CmResourceTypeInterrupt; resourceDescriptor[resourceList->Count].ShareDisposition = CmResourceShareDeviceExclusive; resourceDescriptor[resourceList->Count].Flags = CM_RESOURCE_INTERRUPT_LATCHED; resourceDescriptor[resourceList->Count].u.Interrupt.MinimumVector = 0xf; resourceDescriptor[resourceList->Count].u.Interrupt.MaximumVector = 0xf;
resourceList->Count++; } }
if (!resourceList->Count) {
ExFreePool (requirementsList); requirementsList = NULL; }
status = STATUS_SUCCESS; }
GetOut:
Irp->IoStatus.Information = (ULONG_PTR) requirementsList; Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } // ChannelQueryResourceRequirements
NTSTATUS ChannelInternalDeviceIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PCHANPDO_EXTENSION pdoExtension; NTSTATUS status;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
thisIrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (thisIrpSp->Parameters.DeviceIoControl.IoControlCode) {
//
// TEMP CODE for the time without a real PCI driver.
// pciidex knows about the resources.
//
case IOCTL_IDE_GET_RESOURCES_ALLOCATED: { PCTRLFDO_EXTENSION fdoExtension; ULONG resourceListSize; PCM_RESOURCE_LIST resourceList; PCM_FULL_RESOURCE_DESCRIPTOR fullResourceList; PCM_PARTIAL_RESOURCE_LIST partialResourceList; PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDescriptors; ULONG channel;
channel = pdoExtension->ChannelNumber; fdoExtension = pdoExtension->ParentDeviceExtension;
resourceListSize = fdoExtension->PdoResourceListSize[channel];
//
// have the callee allocate the buffer.
//
resourceList = (PCM_RESOURCE_LIST) Irp->AssociatedIrp.SystemBuffer; ASSERT(resourceList);
RtlCopyMemory ( resourceList, fdoExtension->PdoResourceList[channel], resourceListSize);
Irp->IoStatus.Information = resourceListSize; status = STATUS_SUCCESS; } break;
default: DebugPrint ((1, "PciIde, Channel PDO got Unknown IoControlCode 0x%x\n", thisIrpSp->Parameters.DeviceIoControl.IoControlCode)); status = STATUS_INVALID_PARAMETER; break; } }
Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status; } // ChannelInternalDeviceIoControl
NTSTATUS ChannelQueryText ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PCHANPDO_EXTENSION pdoExtension; PWCHAR returnString; ANSI_STRING ansiString; UNICODE_STRING unicodeString; ULONG stringLen; NTSTATUS status;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
thisIrpSp = IoGetCurrentIrpStackLocation (Irp);
returnString = NULL; Irp->IoStatus.Information = 0;
if (thisIrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
PMESSAGE_RESOURCE_ENTRY messageEntry;
status = RtlFindMessage(pdoExtension->DriverObject->DriverStart, 11, LANG_NEUTRAL, PCIIDEX_IDE_CHANNEL, &messageEntry);
if (!NT_SUCCESS(status)) {
returnString = NULL;
} else {
if (messageEntry->Flags & MESSAGE_RESOURCE_UNICODE) {
//
// Our caller wants a copy they can free, also we need to
// strip the trailing CR/LF. The Length field of the
// message structure includes both the header and the
// actual text.
//
// Note: The message resource entry length will always be a
// multiple of 4 bytes in length. The 2 byte null terminator
// could be in either the last or second last WCHAR position.
//
ULONG textLength;
textLength = messageEntry->Length - FIELD_OFFSET(MESSAGE_RESOURCE_ENTRY, Text) - 2 * sizeof(WCHAR);
returnString = (PWCHAR)(messageEntry->Text); if (returnString[textLength / sizeof(WCHAR)] == 0) { textLength -= sizeof(WCHAR); }
returnString = ExAllocatePool(PagedPool, textLength);
if (returnString) {
//
// Copy the text except for the CR/LF/NULL
//
textLength -= sizeof(WCHAR); RtlCopyMemory(returnString, messageEntry->Text, textLength);
//
// New NULL terminator.
//
returnString[textLength / sizeof(WCHAR)] = 0; }
} else {
//
// RtlFindMessage returns a string? Wierd.
//
ANSI_STRING ansiDescription; UNICODE_STRING unicodeDescription;
RtlInitAnsiString(&ansiDescription, messageEntry->Text);
//
// Strip CR/LF off the end of the string.
//
ansiDescription.Length -= 2;
//
// Turn it all into a unicode string so we can grab the buffer
// and return that to our caller.
//
status = RtlAnsiStringToUnicodeString( &unicodeDescription, &ansiDescription, TRUE );
returnString = unicodeDescription.Buffer; } } } else if (thisIrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextLocationInformation) {
stringLen = 100;
returnString = ExAllocatePool ( PagedPool, stringLen );
if (returnString) {
swprintf(returnString, L"%ws Channel", ((pdoExtension->ChannelNumber == 0) ? L"Primary" : L"Secondary"));
RtlInitUnicodeString (&unicodeString, returnString);
//
// null terminate it
//
unicodeString.Buffer[unicodeString.Length/sizeof(WCHAR) + 0] = L'\0'; } }
Irp->IoStatus.Information = (ULONG_PTR) returnString; if (Irp->IoStatus.Information) {
status = STATUS_SUCCESS; } else {
//
// return the original error code
//
status = Irp->IoStatus.Status; } }
Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status;
} // ChannelQueryText
NTSTATUS PciIdeChannelQueryInterface ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PCHANPDO_EXTENSION pdoExtension; NTSTATUS status;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
status = Irp->IoStatus.Status; thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
if (RtlEqualMemory(&GUID_PCIIDE_BUSMASTER_INTERFACE, thisIrpSp->Parameters.QueryInterface.InterfaceType, sizeof(GUID)) && (thisIrpSp->Parameters.QueryInterface.Size >= sizeof(PCIIDE_BUSMASTER_INTERFACE))) {
//
// The query is for an busmaster interface
//
status = BmQueryInterface ( pdoExtension, (PPCIIDE_BUSMASTER_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface );
} else if (RtlEqualMemory(&GUID_PCIIDE_SYNC_ACCESS_INTERFACE, thisIrpSp->Parameters.QueryInterface.InterfaceType, sizeof(GUID)) && (thisIrpSp->Parameters.QueryInterface.Size >= sizeof(PCIIDE_SYNC_ACCESS_INTERFACE))) {
//
// The query is for dual ide channel sync access interface
//
status = PciIdeQuerySyncAccessInterface ( pdoExtension, (PPCIIDE_SYNC_ACCESS_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface );
} else if (RtlEqualMemory(&GUID_PCIIDE_XFER_MODE_INTERFACE, thisIrpSp->Parameters.QueryInterface.InterfaceType, sizeof(GUID)) && (thisIrpSp->Parameters.QueryInterface.Size >= sizeof(PCIIDE_XFER_MODE_INTERFACE))) {
//
// The query is for dual ide channel sync access interface
//
status = PciIdeChannelTransferModeInterface ( pdoExtension, (PPCIIDE_XFER_MODE_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface );
#ifdef ENABLE_NATIVE_MODE
} else if (RtlEqualMemory(&GUID_PCIIDE_INTERRUPT_INTERFACE, thisIrpSp->Parameters.QueryInterface.InterfaceType, sizeof(GUID)) && (thisIrpSp->Parameters.QueryInterface.Size >= sizeof(PCIIDE_INTERRUPT_INTERFACE))) {
//
// The query is for the channel interrupt interface
//
status = PciIdeChannelInterruptInterface ( pdoExtension, (PPCIIDE_INTERRUPT_INTERFACE) thisIrpSp->Parameters.QueryInterface.Interface ); #endif
} else if (RtlEqualMemory(&GUID_PCIIDE_REQUEST_PROPER_RESOURCES, thisIrpSp->Parameters.QueryInterface.InterfaceType, sizeof(GUID)) && (thisIrpSp->Parameters.QueryInterface.Size >= sizeof(PCIIDE_REQUEST_PROPER_RESOURCES))) {
//
// The query is for dual ide channel sync access interface
//
*((PCIIDE_REQUEST_PROPER_RESOURCES *) thisIrpSp->Parameters.QueryInterface.Interface) = PciIdeChannelRequestProperResources; status = STATUS_SUCCESS; } }
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } // PciIdeChannelQueryInterface
#ifdef ENABLE_NATIVE_MODE
NTSTATUS PciIdeInterruptControl ( IN PVOID Context, IN ULONG DisConnect ) /*++
Description:
Connects or disconnects the controller ISR. This intermediate function provides a clean interface to atapi. Since this is not a very frequently used function we can afford the extra call Arguments : Context : Pdo extension Disconnect: 1 to disconnect and 0 to connect
Return Value:
STATUS_SUCCESS : if the operation succeeds. --*/ { PCHANPDO_EXTENSION pdoExtension = Context;
NTSTATUS status;
//
// Call the controller's interrupt control routine
//
status = ControllerInterruptControl(pdoExtension->ParentDeviceExtension, pdoExtension->ChannelNumber, DisConnect );
return status; }
NTSTATUS PciIdeChannelInterruptInterface ( IN PCHANPDO_EXTENSION PdoExtension, PPCIIDE_INTERRUPT_INTERFACE InterruptInterface ) { //
// Return an interface only if we are in native mode.
// Saves a few function calls on non native mode controllers
//
if (IsNativeMode(PdoExtension->ParentDeviceExtension)) {
InterruptInterface->Context = PdoExtension; InterruptInterface->PciIdeInterruptControl = PciIdeInterruptControl;
DebugPrint((1, "PciIdex: returing interrupt interface for channel %x\n", PdoExtension->ChannelNumber)); }
return STATUS_SUCCESS; } #endif
NTSTATUS PciIdeChannelTransferModeInterface ( IN PCHANPDO_EXTENSION PdoExtension, PPCIIDE_XFER_MODE_INTERFACE XferMode ) { XferMode->TransferModeSelect = PciIdeChannelTransferModeSelect; XferMode->TransferModeTimingTable = PdoExtension->ParentDeviceExtension-> TransferModeTimingTable; XferMode->TransferModeTableLength = PdoExtension->ParentDeviceExtension-> TransferModeTableLength; XferMode->Context = PdoExtension; XferMode->VendorSpecificDeviceExtension=PdoExtension-> ParentDeviceExtension->VendorSpecificDeviceEntension;
XferMode->UdmaModesSupported = PdoExtension-> ParentDeviceExtension-> ControllerProperties.PciIdeUdmaModesSupported; //
//NULL is ok. checked in the IdePortDispatchRoutine
//
XferMode->UseDma = PdoExtension-> ParentDeviceExtension-> ControllerProperties.PciIdeUseDma;
if (PdoExtension-> ParentDeviceExtension-> ControllerProperties.PciIdeTransferModeSelect) {
//
// Looks like the miniport fully support timing register programming
//
XferMode->SupportLevel = PciIdeFullXferModeSupport;
} else {
//
// Looks like the miniport doens't support timing register programming
//
XferMode->SupportLevel = PciIdeBasicXferModeSupport; }
//
// This function can't fail
//
return STATUS_SUCCESS; } // PciIdeChannelTransferModeInterface
NTSTATUS PciIdeChannelTransferModeSelect ( IN PCHANPDO_EXTENSION PdoExtension, PPCIIDE_TRANSFER_MODE_SELECT XferMode ) { ULONG i; NTSTATUS status; UCHAR bmRawStatus; struct { USHORT VendorID; USHORT DeviceID; } pciId;
//
// check the registry for bus master mode
// and overwrite the current if necessary
//
// if DMADetection = 0, clear current dma mode
// if DMADetection = 1, set current mode
// if DMADetection = 2, clear all current mode
if (PdoExtension->DmaDetectionLevel == DdlPioOnly) {
bmRawStatus = 0;
for (i=0; i<MAX_IDE_DEVICE * MAX_IDE_LINE; i++) {
XferMode->DeviceTransferModeSupported[i] &= PIO_SUPPORT; XferMode->DeviceTransferModeCurrent[i] &= PIO_SUPPORT; }
} else if (PdoExtension->DmaDetectionLevel == DdlFirmwareOk) {
if (PdoExtension->BmRegister) {
//
// get the firmware ok bits
// the current value seems to be 0??
//
bmRawStatus = PdoExtension->BootBmStatus;
} else {
bmRawStatus = 0; }
} else if (PdoExtension->DmaDetectionLevel == DdlAlways) {
if (PdoExtension->BmRegister) {
//
// fake the firmware ok bits
//
bmRawStatus = BUSMASTER_DEVICE0_DMA_OK | BUSMASTER_DEVICE1_DMA_OK;
} else {
bmRawStatus = 0; }
} else {
bmRawStatus = 0; }
//
// in case there is no miniport support
//
status = STATUS_UNSUCCESSFUL;
if (PdoExtension->DmaDetectionLevel != DdlPioOnly) {
//
// set up the channel number since the caller (atapi)
// doesn't know how.
//
XferMode->Channel = PdoExtension->ChannelNumber;
//
// This decides whether UDMA modes > 2 should be supported or not
// Currently impacts only the intel chipsets
//
XferMode->EnableUDMA66 = PdoExtension->ParentDeviceExtension->EnableUDMA66;
if (PdoExtension-> ParentDeviceExtension-> ControllerProperties.PciIdeTransferModeSelect) {
status = (*PdoExtension->ParentDeviceExtension->ControllerProperties.PciIdeTransferModeSelect) ( PdoExtension->ParentDeviceExtension->VendorSpecificDeviceEntension, XferMode ); } }
DebugPrint((1, "Select in PCIIDEX: RawStatus=%x, current[0]=%x, current[1]=%x\n", bmRawStatus, XferMode->DeviceTransferModeCurrent[0], XferMode->DeviceTransferModeCurrent[1]));
if (!NT_SUCCESS(status)) {
status = STATUS_SUCCESS;
if ((bmRawStatus & BUSMASTER_DEVICE0_DMA_OK) == 0) {
XferMode->DeviceTransferModeSelected[0] = XferMode->DeviceTransferModeCurrent[0] & PIO_SUPPORT; } else {
XferMode->DeviceTransferModeSelected[0] = XferMode->DeviceTransferModeCurrent[0]; }
if ((bmRawStatus & BUSMASTER_DEVICE1_DMA_OK) == 0) {
XferMode->DeviceTransferModeSelected[1] = XferMode->DeviceTransferModeCurrent[1] & PIO_SUPPORT; } else {
XferMode->DeviceTransferModeSelected[1] = XferMode->DeviceTransferModeCurrent[1]; }
for (i=0; i<MAX_IDE_DEVICE; i++) {
DebugPrint((1, "Select in PCIIDEX: xfermode[%d]=%x\n",i, PdoExtension->ParentDeviceExtension->ControllerProperties. SupportedTransferMode[PdoExtension->ChannelNumber][i]));
if ((PdoExtension->ParentDeviceExtension->ControllerProperties.DefaultPIO == 1) && (IS_DEFAULT(XferMode->UserChoiceTransferMode[i]))) { XferMode->DeviceTransferModeSelected[i] &= PIO_SUPPORT; } else { XferMode->DeviceTransferModeSelected[i] &= PdoExtension->ParentDeviceExtension->ControllerProperties. SupportedTransferMode[PdoExtension->ChannelNumber][i]; } } }
return status;
} // PciIdeChannelTransferModeSelect
NTSTATUS ChannelQueryDeviceRelations ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { PIO_STACK_LOCATION thisIrpSp; PDEVICE_RELATIONS deviceRelations; NTSTATUS status;
PAGED_CODE();
thisIrpSp = IoGetCurrentIrpStackLocation( Irp );
switch (thisIrpSp->Parameters.QueryDeviceRelations.Type) {
case TargetDeviceRelation:
deviceRelations = ExAllocatePool (NonPagedPool, sizeof(*deviceRelations));
if (deviceRelations != NULL) {
deviceRelations->Count = 1; deviceRelations->Objects[0] = DeviceObject;
ObReferenceObjectByPointer(DeviceObject, 0, 0, KernelMode);
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = (ULONG_PTR) deviceRelations; } else {
Irp->IoStatus.Status = STATUS_NO_MEMORY; Irp->IoStatus.Information = 0; } break; }
status = Irp->IoStatus.Status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } // ChannelQueryDeviceRelations
NTSTATUS ChannelUsageNotification ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { NTSTATUS status; PCHANPDO_EXTENSION pdoExtension; PIO_STACK_LOCATION irpSp; PDEVICE_OBJECT targetDeviceObject; IO_STATUS_BLOCK ioStatus; PULONG deviceUsageCount;
PAGED_CODE();
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension == NULL) {
status = STATUS_NO_SUCH_DEVICE;
} else {
irpSp = IoGetCurrentIrpStackLocation(Irp);
if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypePaging) {
//
// Adjust the paging path count for this device.
//
deviceUsageCount = &pdoExtension->PagingPathCount;
//
// changing device state
//
SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_NOT_DISABLEABLE); IoInvalidateDeviceState(pdoExtension->DeviceObject);
} else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation) {
//
// Adjust the paging path count for this device.
//
deviceUsageCount = &pdoExtension->HiberPathCount;
} else if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile) {
//
// Adjust the paging path count for this device.
//
deviceUsageCount = &pdoExtension->CrashDumpPathCount;
} else {
deviceUsageCount = NULL; DebugPrint ((0, "PCIIDEX: Unknown IRP_MN_DEVICE_USAGE_NOTIFICATION type: 0x%x\n", irpSp->Parameters.UsageNotification.Type)); }
//
// get the top of parent's device stack
//
targetDeviceObject = IoGetAttachedDeviceReference( pdoExtension-> ParentDeviceExtension-> DeviceObject);
ioStatus.Status = STATUS_NOT_SUPPORTED; status = PciIdeXSyncSendIrp (targetDeviceObject, irpSp, &ioStatus);
ObDereferenceObject (targetDeviceObject);
if (NT_SUCCESS(status)) {
if (deviceUsageCount) {
IoAdjustPagingPathCount ( deviceUsageCount, irpSp->Parameters.UsageNotification.InPath ); } } }
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status;
} // ChannelUsageNotification
NTSTATUS ChannelQueryPnPDeviceState ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { NTSTATUS status; PCHANPDO_EXTENSION pdoExtension;
pdoExtension = ChannelGetPdoExtension(DeviceObject);
if (pdoExtension) {
PPNP_DEVICE_STATE deviceState;
DebugPrint((2, "QUERY_DEVICE_STATE for PDOE 0x%x\n", pdoExtension));
deviceState = (PPNP_DEVICE_STATE) &Irp->IoStatus.Information; SETMASK((*deviceState), pdoExtension->PnPDeviceState);
CLRMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED);
status = STATUS_SUCCESS;
} else {
status = STATUS_DEVICE_DOES_NOT_EXIST; }
Irp->IoStatus.Status = status; IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } // ChannelQueryPnPDeviceState
VOID PciIdeChannelRequestProperResources( IN PDEVICE_OBJECT DeviceObject ) { PCHANPDO_EXTENSION pdoExtension;
//
// the FDO thinks the channel is not empty
// anymore
//
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (pdoExtension) { pdoExtension->EmptyChannel = FALSE; SETMASK (pdoExtension->PnPDeviceState, PNP_DEVICE_FAILED | PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED); IoInvalidateDeviceState (DeviceObject); } }
NTSTATUS ChannelFilterResourceRequirements ( IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp ) { NTSTATUS status; PCHANPDO_EXTENSION pdoExtension; PIO_STACK_LOCATION thisIrpSp; ULONG i, j;
PIO_RESOURCE_REQUIREMENTS_LIST requirementsListIn = NULL; PIO_RESOURCE_LIST resourceListIn; PIO_RESOURCE_DESCRIPTOR resourceDescriptorIn;
PIO_RESOURCE_LIST resourceListOut; PIO_RESOURCE_DESCRIPTOR resourceDescriptorOut;
ULONG newCount;
PAGED_CODE();
status = STATUS_NOT_SUPPORTED;
//
// the value will stay NULL if no filtering required
//
#ifdef IDE_FILTER_PROMISE_TECH_RESOURCES
if (NT_SUCCESS(ChannelFilterPromiseTechResourceRequirements (DeviceObject, Irp))) { goto getout; } #endif // IDE_FILTER_PROMISE_TECH_RESOURCES
pdoExtension = ChannelGetPdoExtension(DeviceObject); if (!pdoExtension) { goto getout; }
//
// filter out irq only if the channel is emtpy
//
if (!pdoExtension->EmptyChannel) {
goto getout; }
if (NT_SUCCESS(Irp->IoStatus.Status)) { //
// already filtered.
//
requirementsListIn = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information; } else { thisIrpSp = IoGetCurrentIrpStackLocation(Irp); requirementsListIn = thisIrpSp->Parameters.FilterResourceRequirements.IoResourceRequirementList; }
if (requirementsListIn == NULL) { goto getout; }
if (requirementsListIn->AlternativeLists == 0) { goto getout; }
resourceListIn = requirementsListIn->List; resourceListOut = resourceListIn; for (j=0; j<requirementsListIn->AlternativeLists; j++) {
ULONG resCount; resourceDescriptorIn = resourceListIn->Descriptors;
RtlMoveMemory ( resourceListOut, resourceListIn, FIELD_OFFSET(IO_RESOURCE_LIST, Descriptors)); resourceDescriptorOut = resourceListOut->Descriptors;
resCount = resourceListIn->Count; for (i=newCount=0; i<resCount; i++) {
if (resourceDescriptorIn[i].Type != CmResourceTypeInterrupt) { resourceDescriptorOut[newCount] = resourceDescriptorIn[i]; newCount++; } else { status = STATUS_SUCCESS; } } resourceListIn = (PIO_RESOURCE_LIST) (resourceDescriptorIn + resCount); resourceListOut->Count = newCount; resourceListOut = (PIO_RESOURCE_LIST) (resourceDescriptorOut + newCount); }
getout:
if (status != STATUS_NOT_SUPPORTED) { Irp->IoStatus.Status = status; Irp->IoStatus.Information = (ULONG_PTR) requirementsListIn; } else { status = Irp->IoStatus.Status; } IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; }
|