Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2118 lines
61 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
1394f.C
Abstract:
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include <wdm.h>
#include "stdarg.h"
#include "stdio.h"
#include "dbci.h"
#include "dbclass.h" //private data strutures
#include "dbfilter.h"
#include "1394.h"
#if DBG
VOID
DBCLASS_PrintTopologyMap(
PTOPOLOGY_MAP TopologyMap
)
/* ++
*
* Routine Description:
*
* Passes a IRB to the 1394 stack, and waits for return.
*
* Arguments:
*
* DeviceObject - Device object of the to of the port driver
* stack
*
* Return Value:
*
* STATUS_SUCCESS if successful
*
* -- */
{
USHORT nodeCount, selfIdCount;
ULONG i;
DBCLASS_KdPrint((2, "'***********************\n"));
DBCLASS_KdPrint((2, "'TopologyMap = (%08X)\n", TopologyMap));
DBCLASS_KdPrint((2, "'TOP_Length = (%08X)\n", TopologyMap->TOP_Length));
DBCLASS_KdPrint((2, "'TOP_CRC = (%08X)\n", TopologyMap->TOP_CRC));
DBCLASS_KdPrint((2, "'TOP_Generation = (%08X)\n", TopologyMap->TOP_Generation));
DBCLASS_KdPrint((2, "'TOP_Node_Count = (%08X)\n", TopologyMap->TOP_Node_Count));
DBCLASS_KdPrint((2, "'TOP_Self_ID_Count = (%08X)\n", TopologyMap->TOP_Self_ID_Count));
nodeCount = TopologyMap->TOP_Node_Count;
selfIdCount = TopologyMap->TOP_Self_ID_Count;
DBCLASS_KdPrint((2, "'nodeCount = (%08X) selfIdCount = (%08X)\n",
nodeCount, selfIdCount));
for (i=0; i< selfIdCount; i++) {
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
selfId = TopologyMap->TOP_Self_ID_Array[i];
DBCLASS_KdPrint((2, "'TOP_Self_ID = (%08X)\n",
selfId));
DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
selfId.SID_Phys_ID));
DBCLASS_KdPrint((2, "'SID_Port1 = (%08X)\n", (ULONG)
selfId.SID_Port1));
DBCLASS_KdPrint((2, "'SID_Port2 = (%08X)\n", (ULONG)
selfId.SID_Port2));
DBCLASS_KdPrint((2, "'SID_Port3 = (%08X)\n", (ULONG)
selfId.SID_Port3));
DBCLASS_KdPrint((2, "'SID_More_Packets = (%08X)\n", (ULONG)
selfId.SID_More_Packets));
if (selfId.SID_More_Packets)
{
do
{
i++;
RtlCopyMemory(&selfIdMore,
&TopologyMap->TOP_Self_ID_Array[i],
sizeof(ULONG));
DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
selfIdMore.SID_Phys_ID));
DBCLASS_KdPrint((2, "'SID_PortA = (%08X)\n", (ULONG)
selfIdMore.SID_PortA));
DBCLASS_KdPrint((2, "'SID_PortB = (%08X)\n", (ULONG)
selfIdMore.SID_PortB));
DBCLASS_KdPrint((2, "'SID_PortC = (%08X)\n", (ULONG)
selfIdMore.SID_PortC));
DBCLASS_KdPrint((2, "'SID_PortD = (%08X)\n", (ULONG)
selfIdMore.SID_PortD));
DBCLASS_KdPrint((2, "'SID_PortE = (%08X)\n", (ULONG)
selfIdMore.SID_PortE));
DBCLASS_KdPrint((2, "'SID_PortF = (%08X)\n", (ULONG)
selfIdMore.SID_PortF));
DBCLASS_KdPrint((2, "'SID_PortG = (%08X)\n", (ULONG)
selfIdMore.SID_PortG));
DBCLASS_KdPrint((2, "'SID_PortH = (%08X)\n", (ULONG)
selfIdMore.SID_PortH));
} while (selfIdMore.SID_More_Packets);
}
} /* for */
DBCLASS_KdPrint((2, "'***********************\n"));
}
#else
#define DBCLASS_PrintTopologyMap(x) x
#endif /* DBG */
NTSTATUS
DBCLASS_SyncSubmitIrb(
IN PDEVICE_OBJECT DeviceObject,
IN PIRB Irb
)
/* ++
*
* Routine Description:
*
* Passes a IRB to the 1394 stack, and waits for return.
*
* Arguments:
*
* DeviceObject - Device object of the to of the port driver
* stack
*
* Return Value:
*
* STATUS_SUCCESS if successful
*
* -- */
{
NTSTATUS ntStatus, status;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
#ifdef DEADMAN_TIMER
BOOLEAN haveTimer = FALSE;
KDPC timeoutDpc;
KTIMER timeoutTimer;
#endif
PAGED_CODE();
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(IOCTL_1394_CLASS,
DeviceObject,
NULL,
0,
NULL,
0,
TRUE, // INTERNAL
&event,
&ioStatus);
if (NULL == irp) {
DBCLASS_KdPrint((0, "'could not allocate an irp!\n"));
TRAP();
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Call the port driver to perform the operation. If the returned
// status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
//
// pass the DRB
//
nextStack->Parameters.Others.Argument1 = Irb;
ntStatus = IoCallDriver(DeviceObject, irp);
if (ntStatus == STATUS_PENDING)
{
#ifdef DEADMAN_TIMER
LARGE_INTEGER dueTime;
KeInitializeTimer(&timeoutTimer);
KeInitializeDpc(&timeoutDpc,
UsbhTimeoutDPC,
irp);
dueTime.QuadPart = -10000 * DEADMAN_TIMEOUT;
KeSetTimer(&timeoutTimer,
dueTime,
&timeoutDpc);
haveTimer = TRUE;
#endif
status = KeWaitForSingleObject(&event,
Suspended,
KernelMode,
FALSE,
NULL);
} else {
ioStatus.Status = ntStatus;
}
#ifdef DEADMAN_TIMER
//
// remove our timeoutDPC from the queue
//
if (haveTimer)
{
KeCancelTimer(&timeoutTimer);
}
#endif /* DEADMAN_TIMER */
ntStatus = ioStatus.Status;
DBCLASS_KdPrint((2,"'DBCLASS_SyncSubmitIrb (%x)\n", ntStatus));
return ntStatus;
}
#define DBCLASS_COUNT_PORT(s, d) (d)->NumberOf1394Ports++;
USHORT
DBCLASS_GetNodeId(
PTOPOLOGY_MAP TopologyMap,
USHORT Index,
USHORT Connect
)
/*++
Routine Description:
Given an index walk the map and return the NodeId
Arguments:
Return Value:
zero if not a device bay PDO.
--*/
{
USHORT i;
USHORT nodeCount;
USHORT nodeId = 0xffff;
USHORT idCount = 0;
USHORT selfIdCount;
nodeCount = TopologyMap->TOP_Node_Count;
selfIdCount = TopologyMap->TOP_Self_ID_Count;
DBCLASS_KdPrint((2, "'>GetNodeId Index = %d\n", Index));
for (i=0; i< selfIdCount; i++)
{
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
selfId = TopologyMap->TOP_Self_ID_Array[i];
if (idCount == Index &&
((USHORT)selfId.SID_Port1 == Connect ||
(USHORT)selfId.SID_Port2 == Connect ||
(USHORT)selfId.SID_Port3 == Connect))
{
nodeId = (USHORT) selfId.SID_Phys_ID;
break;
}
if (selfId.SID_More_Packets)
{
do
{
i++;
RtlCopyMemory(&selfIdMore,
&TopologyMap->TOP_Self_ID_Array[i],
sizeof(ULONG));
if (idCount == Index &&
((USHORT)selfIdMore.SID_PortA == Connect ||
(USHORT)selfIdMore.SID_PortB == Connect ||
(USHORT)selfIdMore.SID_PortC == Connect ||
(USHORT)selfIdMore.SID_PortD == Connect ||
(USHORT)selfIdMore.SID_PortE == Connect ||
(USHORT)selfIdMore.SID_PortF == Connect ||
(USHORT)selfIdMore.SID_PortG == Connect ||
(USHORT)selfIdMore.SID_PortH == Connect)) {
nodeId = (USHORT) selfId.SID_Phys_ID;
goto DBCLASS_GetNodeId_Done;
}
} while (selfIdMore.SID_More_Packets);
}
idCount++;
}
DBCLASS_KdPrint((2, "'>nodeId = (%08X)\n", nodeId));
DBCLASS_GetNodeId_Done:
return nodeId;
}
PBUS1394_PORT_INFO
DBCLASS_SetNodeId(
PTOPOLOGY_MAP TopologyMap,
SELF_ID HcSelfId,
USHORT SelfIdPortX,
PUSHORT ChildIdx,
PUSHORT ParentIdx,
PBUS1394_PORT_INFO Bus1394PortInfo
)
/*++
Routine Description:
Arguments:
Return Value:
zero if not a device bay PDO.
--*/
{
ULONG flags = 0;
USHORT nodeId = 0xffff, idCount;
idCount = TopologyMap->TOP_Self_ID_Count;
DBCLASS_KdPrint((2, "'ParentIdx = %d ChildIdx = %d count = %d\n",
*ParentIdx, *ChildIdx, idCount));
//Scan forward through the map looking for potential children
if (SelfIdPortX == SELF_ID_CONNECTED_TO_CHILD)
{
DBCLASS_KdPrint((2, "'find child\n"));
do
{
(*ChildIdx)++;
// are we out of children?
if (*ChildIdx > idCount)
{
// yes, check the root
*ChildIdx = 0;
}
flags = DBCLASS_PORTFLAG_DEVICE_CONNECTED;
// find the child node id
nodeId = DBCLASS_GetNodeId(TopologyMap, *ChildIdx, SELF_ID_CONNECTED_TO_PARENT);
} while (nodeId == 0xffff);
DBCLASS_KdPrint((2, "'Found ChildIdx = %d nodeId = %d\n", *ChildIdx, nodeId));
}
else if (SelfIdPortX == SELF_ID_CONNECTED_TO_PARENT)
{
do
{
(*ParentIdx)++;
// are we out of parents?
if (*ParentIdx > idCount)
{
// yes, check the root
*ParentIdx = 0;
}
flags = DBCLASS_PORTFLAG_DEVICE_CONNECTED;
nodeId = DBCLASS_GetNodeId(TopologyMap, *ParentIdx, SELF_ID_CONNECTED_TO_CHILD);
} while (nodeId == 0xffff);
DBCLASS_KdPrint((2, "'Found ParentIdx = %d nodeId = %d\n", *ParentIdx, nodeId));
}
Bus1394PortInfo->Flags = flags;
Bus1394PortInfo->NodeId = nodeId;
Bus1394PortInfo->BayNumber = 0;
Bus1394PortInfo++;
return Bus1394PortInfo;
}
#if DBG
VOID
DBCLASS_KdPrintGuid(
ULONG Level,
PUCHAR P
)
{
DBCLASS_KdPrint((Level, "'>>>>GUID1 = [%02.2x] [%02.2x] [%02.2x] [%02.2x]\n",
*P, *(P+1), *(P+2), *(P+3)));
DBCLASS_KdPrint((Level, "'>>>>GUID2 = [%02.2x] [%02.2x] [%02.2x] [%02.2x]\n",
*(P+4), *(P+5), *(P+6), *(P+7)));
}
#endif
BOOLEAN
DBCLASS_IsLinkDeviceObject(
PDBC_CONTEXT DbcContext,
PDEVICE_OBJECT Pdo1394
)
/*++
Routine Description:
check the link guid in dbcContext against the link guid for a
1394 device,
Arguments:
Return Value:
true if link guid matches
--*/
{
PNODE_DEVICE_EXTENSION nodeExtension;
nodeExtension = Pdo1394->DeviceExtension;
DBCLASS_KdPrint((2, "'>NodeExt (%08X) ConfigRom (%08X)\n", nodeExtension, nodeExtension->ConfigRom));
DBCLASS_KdPrint((2, "'>1394 PDO GUID\n"));
if(nodeExtension->ConfigRom)
{
#if DBG
DBCLASS_KdPrintGuid(2, (PUCHAR)&nodeExtension->ConfigRom->CR_Node_UniqueID[0]);
#endif
DBCLASS_KdPrint((2, "'>DBC Link GUID\n"));
#if DBG
DBCLASS_KdPrintGuid(2, &DbcContext->SubsystemDescriptor.guid1394Link[0]);
#endif
return RtlCompareMemory(&DbcContext->SubsystemDescriptor.guid1394Link[0],
&nodeExtension->ConfigRom->CR_Node_UniqueID[0],
8) == 8;
}
else
return FALSE;
}
NTSTATUS
DBCLASS_GetSpeedAndTopologyMaps(
PTOPOLOGY_MAP *TopologyMap,
PDEVICE_OBJECT BusFilterMdo
)
/*++
Routine Description:
Arguments:
Return Value:
topology map or NULL
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
IRB irb;
PDEVICE_EXTENSION deviceExtension;
GET_LOCAL_HOST_INFO6 info6;
PUCHAR buffer = NULL;
if(BusFilterMdo == NULL)
return STATUS_UNSUCCESSFUL;
deviceExtension = BusFilterMdo->DeviceExtension;
DBCLASS_KdPrint((2, "'>Get 1394 Speed & Topology Maps MDO (%08X)\n", BusFilterMdo));
BRK_ON_TRAP();
irb.FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
irb.u.GetLocalHostInformation.nLevel = GET_HOST_CSR_CONTENTS;
info6.CsrBaseAddress.Off_High = 0xffff;
info6.CsrBaseAddress.Off_Low = TOPOLOGY_MAP_LOCATION;
info6.CsrDataLength = 0;
info6.CsrDataBuffer = buffer;
irb.u.GetLocalHostInformation.Information = &info6;
ntStatus = DBCLASS_SyncSubmitIrb(
deviceExtension->TopOfStackDeviceObject,
&irb);
DBCLASS_KdPrint((2, "'GetLocalHostInfo(), first call = (%08X)\n", ntStatus));
if (ntStatus == STATUS_INVALID_BUFFER_SIZE)
{
// try again with correct size
buffer = DbcExAllocatePool(NonPagedPool,
info6.CsrDataLength);
if (buffer)
{
info6.CsrDataBuffer = buffer;
ntStatus = DBCLASS_SyncSubmitIrb(
deviceExtension->TopOfStackDeviceObject,
&irb);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
DBCLASS_KdPrint((2, "'GetLocalHostInfo(), second call = (%08X) buffer = %x\n",
ntStatus, buffer));
}
if (NT_SUCCESS(ntStatus))
{
*TopologyMap = (PTOPOLOGY_MAP) buffer;
DBCLASS_PrintTopologyMap(*TopologyMap);
}
return ntStatus;
}
NTSTATUS
DBCLASS_Get1394BayPortMapping(
PDEVICE_OBJECT BusFilterMdo,
PDBC_CONTEXT DbcContext
)
/*++
Routine Description:
Arguments:
Return Value:
zero if not a device bay PDO.
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
IRB irb;
PDEVICE_EXTENSION deviceExtension;
PTOPOLOGY_MAP topologyMap = NULL;
USHORT i, nodeCount, selfIdCount, linkNodeId;
USHORT linkSelfId_Index = 0;
PDEVICE_OBJECT linkDeviceObject;
DBCLASS_KdPrint((1, "'>Get 1394 Port Mapping\n"));
DBCLASS_ASSERT(DbcContext);
BRK_ON_TRAP();
//
// get the topology map & local node id from the 1394 port driver
//
// our mission her is to find the parent nodeid
//
// if the DBC controller is ACPI then this will be the 1394 host controller
// if it is USB based it will be the PHY for DBC
if (DbcContext->ControllerSig == DBC_ACPI_CONTROLLER_SIG)
{
//
// link device object is the PDO for the 1394 HC
//
DBCLASS_KdPrint((2, "'DBC is ACPI \n"));
deviceExtension = DbcContext->BusFilterMdo1394->DeviceExtension;
DBCLASS_ASSERT(DbcContext->BusFilterMdo1394 == BusFilterMdo);
DBCLASS_ASSERT(DbcContext->LinkDeviceObject == NULL);
linkDeviceObject = deviceExtension->TopOfStackDeviceObject;
}
else
{
//
// for USBDBC the link is stored in the dbcContext
//
DBCLASS_KdPrint((2, "'DBC is USB \n"));
linkDeviceObject = DbcContext->LinkDeviceObject;
BRK_ON_TRAP();
}
DBCLASS_KdPrint((2, "'DbcContext (%08X) LinkDeviceObject (%08X)\n", DbcContext, linkDeviceObject));
// check for invalid device object
if(((linkDeviceObject) == (PDEVICE_OBJECT)(-1)) || (linkDeviceObject == NULL))
{
ntStatus = STATUS_UNSUCCESSFUL;
goto BayPort_End;
}
// should only get here if the db controller
// has been found
DBCLASS_ASSERT(linkDeviceObject != NULL);
irb.u.Get1394AddressFromDeviceObject.fulFlags = 0;
irb.FunctionNumber = REQUEST_GET_ADDR_FROM_DEVICE_OBJECT;
ntStatus = DBCLASS_SyncSubmitIrb(linkDeviceObject,
&irb);
DBCLASS_KdPrint((2, "'GetLocalNodeId() = (%08X)\n", ntStatus));
if (NT_SUCCESS(ntStatus))
{
linkNodeId = irb.u.Get1394AddressFromDeviceObject.NodeAddress.NA_Node_Number;
DBCLASS_KdPrint((2, "'link node id (%08X)\n", linkNodeId));
ntStatus = DBCLASS_GetSpeedAndTopologyMaps(
&topologyMap,
DbcContext->BusFilterMdo1394);
DBCLASS_KdPrint((2, "'GetTopologyMap() = (%08X)\n", ntStatus));
}
if(NT_SUCCESS(ntStatus))
{
DBCLASS_ASSERT(topologyMap != NULL);
DbcContext->NumberOf1394Ports = 0;
// free the old information
if (DbcContext->Bus1394PortInfo)
{
DbcExFreePool(DbcContext->Bus1394PortInfo);
DbcContext->Bus1394PortInfo = NULL;
}
//
// parse the map
//
if(topologyMap)
{
nodeCount = topologyMap->TOP_Node_Count;
selfIdCount = topologyMap->TOP_Self_ID_Count;
// walk the topology map and find the node for the
// for the link
//
// first pass we just count up the ports
// we count all SID entries for ports if if
// not present.
//
for (i=0; i< selfIdCount; i++)
{
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
selfId = topologyMap->TOP_Self_ID_Array[i];
if (selfId.SID_Phys_ID == linkNodeId)
{
// this is the host, count the ports
linkSelfId_Index = i;
DBCLASS_COUNT_PORT(selfId.SID_Port1, DbcContext);
DBCLASS_COUNT_PORT(selfId.SID_Port2, DbcContext);
DBCLASS_COUNT_PORT(selfId.SID_Port3, DbcContext);
}
if (selfId.SID_More_Packets)
{
do
{
i++;
RtlCopyMemory(&selfIdMore,
&topologyMap->TOP_Self_ID_Array[i],
sizeof(ULONG));
if (selfIdMore.SID_Phys_ID == linkNodeId)
{
// this is the link, count the ports
DBCLASS_COUNT_PORT(selfIdMore.SID_PortA, DbcContext);
DBCLASS_COUNT_PORT(selfIdMore.SID_PortB, DbcContext);
DBCLASS_COUNT_PORT(selfIdMore.SID_PortC, DbcContext);
DBCLASS_COUNT_PORT(selfIdMore.SID_PortD, DbcContext);
DBCLASS_COUNT_PORT(selfIdMore.SID_PortE, DbcContext);
DBCLASS_COUNT_PORT(selfIdMore.SID_PortF, DbcContext);
DBCLASS_COUNT_PORT(selfIdMore.SID_PortG, DbcContext);
DBCLASS_COUNT_PORT(selfIdMore.SID_PortH, DbcContext);
}
} while(selfIdMore.SID_More_Packets);
}
}
}
// now set up the port map
DbcContext->Bus1394PortInfo =
DbcExAllocatePool(NonPagedPool, sizeof(BUS1394_PORT_INFO) *
DbcContext->NumberOf1394Ports);
DBCLASS_KdPrint((2, "'link index = %d\n", linkSelfId_Index));
DBCLASS_KdPrint((2, "'link id = %d\n", linkNodeId));
if(DbcContext->Bus1394PortInfo && topologyMap)
{
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
USHORT parentIdx, childIdx;
PBUS1394_PORT_INFO bus1394PortInfo = DbcContext->Bus1394PortInfo;
// scan children and parents
// now parse the self id for the link and fill in the port map
// fill in the phys ids for all child devices
selfId = topologyMap->TOP_Self_ID_Array[linkSelfId_Index];
parentIdx = childIdx = linkNodeId;
DBCLASS_ASSERT(selfId.SID_Phys_ID == linkNodeId);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfId.SID_Port1,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfId.SID_Port2,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfId.SID_Port3,
&parentIdx, &childIdx, bus1394PortInfo);
if (selfId.SID_More_Packets)
{
do
{
linkSelfId_Index++;
RtlCopyMemory(&selfIdMore,
&topologyMap->TOP_Self_ID_Array[linkSelfId_Index],
sizeof(ULONG));
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortA,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortB,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortC,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortD,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortE,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortF,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortG,
&parentIdx, &childIdx, bus1394PortInfo);
bus1394PortInfo =
DBCLASS_SetNodeId(topologyMap, selfId, (USHORT)selfIdMore.SID_PortH,
&parentIdx, &childIdx, bus1394PortInfo);
} while (selfIdMore.SID_More_Packets);
}
// now update the bay/port map
for (i=0; i< DbcContext->NumberOf1394Ports; i++)
{
USHORT bay;
// find the bay for this port
// note: phy port index start at 1
for (bay=1; bay <=NUMBER_OF_BAYS(DbcContext); bay++)
{
if (DbcContext->BayInformation[bay].BayDescriptor.bPHYPortNumber
== i+1)
{
DbcContext->Bus1394PortInfo[i].BayNumber = bay;
break;
}
}
}
#if DBG
for (i=0; i<DbcContext->NumberOf1394Ports; i++)
{
DBCLASS_KdPrint((2, "'Port [%d] = nodeId (%08X) bay (%08X) flg = (%08X)\n",
i+1,
DbcContext->Bus1394PortInfo[i].NodeId,
DbcContext->Bus1394PortInfo[i].BayNumber,
DbcContext->Bus1394PortInfo[i].Flags));
}
for (i=1; i<= NUMBER_OF_BAYS(DbcContext); i++)
{
DBCLASS_KdPrint((2, "'Port [%d] = bay (%08X)\n",
DbcContext->BayInformation[i].BayDescriptor.bPHYPortNumber,
DbcContext->BayInformation[i].BayDescriptor.bBayNumber
));
}
#endif
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
DBCLASS_KdPrint((0, "No memory for Port Info'\n"));
TRAP();
}
}
if (topologyMap)
{
DbcExFreePool(topologyMap);
}
BayPort_End:
return ntStatus;
}
USHORT
DBCLASS_GetBayFor1394Pdo(
PDEVICE_OBJECT BusFilterMdo,
PDBC_CONTEXT DbcContext,
PDEVICE_OBJECT Pdo1394
)
/*++
Routine Description:
given a 1394 PDO figure out wich bay it is associated with
Arguments:
Return Value:
zero if not a device bay PDO.
--*/
{
PNODE_DEVICE_EXTENSION nodeExtension;
USHORT nodeId;
ULONG i;
NTSTATUS ntStatus;
PBUS1394_PORT_INFO bus1394PortInfo;
PAGED_CODE();
ntStatus = DBCLASS_Get1394BayPortMapping(BusFilterMdo,
DbcContext);
if (NT_SUCCESS(ntStatus))
{
nodeExtension = Pdo1394->DeviceExtension;
// check the node id against the bay port mapping
nodeId = nodeExtension->NodeAddress.NA_Node_Number;
DBCLASS_KdPrint((1, "'>1394 PDO (%08X) has NodeID = (%08X)\n",
Pdo1394, nodeId));
bus1394PortInfo = DbcContext->Bus1394PortInfo;
for (i=0; i< DbcContext->NumberOf1394Ports; i++)
{
if (bus1394PortInfo->NodeId == nodeId)
{
DBCLASS_KdPrint((1, "'>1394 PDO is in bay = %d\n",
bus1394PortInfo->BayNumber));
return bus1394PortInfo->BayNumber;
}
bus1394PortInfo++;
}
}
#if DBG
else
{
DBCLASS_KdPrint((1, "'failed to get 1394 bay->port mapping!\n"));
}
#endif
return 0;
}
NTSTATUS
DBCLASS_DeferIrpCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
This routine is called when the port driver completes an IRP.
Arguments:
DeviceObject - Pointer to the device object for the class device.
Irp - Irp completed.
Context - Driver defined context.
Return Value:
The function value is the final status from the operation.
--*/
{
PKEVENT event = Context;
KeSetEvent(event,
1,
FALSE);
DBCLASS_KdPrint((2, "'defer irp %x\n", Irp));
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
DBCLASS_CreateDeviceFilterObject(
IN PDRIVER_OBJECT DriverObject,
IN OUT PDEVICE_OBJECT *DeviceObject,
IN PDEVICE_OBJECT DevicePdo,
IN PDBC_CONTEXT DbcContext,
IN ULONG BusTypeSig
)
/*++
Routine Description:
This routine is called to create a new instance of the DBC
bus filter.
Arguments:
DriverObject - pointer to the driver object for USBD.
*DeviceObject - ptr to DeviceObject ptr to be filled
in with the device object we create.
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
PAGED_CODE();
ntStatus = IoCreateDevice(DriverObject,
sizeof (DEVICE_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
0,
FALSE, //NOT Exclusive
DeviceObject);
if (!NT_SUCCESS(ntStatus) && *DeviceObject)
{
IoDeleteDevice(*DeviceObject);
}
if (NT_SUCCESS(ntStatus))
{
PDEVICE_OBJECT deviceObject = *DeviceObject, stackTopDO;
PDEVICE_EXTENSION deviceExtension;
// initialize the FDO
// and attach it to the PDO
//
// clone some charateristics of the PDO.
//
deviceExtension = deviceObject->DeviceExtension;
deviceExtension->PhysicalDeviceObject = DevicePdo;
stackTopDO =
deviceExtension->TopOfStackDeviceObject =
IoAttachDeviceToDeviceStack(deviceObject, DevicePdo);
//
// Preserve flags in lower device object
//
deviceObject->Flags |= (DevicePdo->Flags &
(DO_POWER_INRUSH | DO_POWER_PAGABLE));
deviceObject->Flags |= (DevicePdo->Flags &
(DO_BUFFERED_IO | DO_DIRECT_IO));
deviceExtension->DbcContext = DbcContext;
deviceExtension->FdoType = BusTypeSig;
// object is ready
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
return ntStatus;
}
NTSTATUS
DBCLASS_1394QBusRelationsComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
Arguments:
DeviceObject - a pointer to the device object
Irp - a pointer to the irp
Context - NULL ptr
Return Value:
STATUS_SUCCESS
--*/
{
PDEVICE_RELATIONS deviceRelations;
ULONG i;
PDEVICE_OBJECT busFilterMdo = Context;
PDEVICE_EXTENSION deviceExtension;
PDEVICE_OBJECT mdo1394;
deviceExtension = busFilterMdo->DeviceExtension;
deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
LOGENTRY(LOG_MISC, '3QBR', busFilterMdo, 0, deviceRelations);
if ((!NT_SUCCESS(Irp->IoStatus.Status)) || deviceRelations == NULL)
{
LOGENTRY(LOG_MISC, '3QBn', busFilterMdo, 0, deviceRelations);
DBCLASS_KdPrint((0, "'>QBR 1394 Failed\n"));
deviceExtension->QBusRelations1394Success = FALSE;
goto DBCLASS_1394QBR_Done;
}
else
{
DBCLASS_KdPrint((0, "'>QBR 1394 Passed\n"));
deviceExtension->QBusRelations1394Success = TRUE;
}
for (i=0; i< deviceRelations->Count; i++)
{
DBCLASS_KdPrint((1, "'>QBR 1394 PDO[%d] %x \n", i,
deviceRelations->Objects[i]));
LOGENTRY(LOG_MISC, 'QBRd', deviceRelations->Objects[i], i, 0);
// 1394 is returning a PDO, see if we know
// about it
// if this is the PHY/LINK for a DBC link it to the
// DBC context
DBCLASS_CheckPhyLink(deviceRelations->Objects[i]);
mdo1394 = DBCLASS_FindDevicePdo(deviceRelations->Objects[i]);
if (mdo1394)
{
// we know about this one,
PDEVICE_EXTENSION mdo1394DeviceExtension;
PDBC_CONTEXT dbcContext;
mdo1394DeviceExtension = mdo1394->DeviceExtension;
dbcContext = mdo1394DeviceExtension->DbcContext;
}
else
{
PDEVICE_OBJECT deviceFilterObject;
NTSTATUS ntStatus;
PDBC_CONTEXT dbcContext;
PDEVICE_OBJECT devObj;
PNODE_DEVICE_EXTENSION nodeExtension;
devObj = deviceRelations->Objects[i];
nodeExtension = devObj->DeviceExtension;
// if this is a "virtual" device, just skip it
if(nodeExtension->Tag == VIRTUAL_DEVICE_EXTENSION_TAG)
{
DBCLASS_KdPrint((1, "'****> Virtual 1394 Device\n"));
continue;
}
// don't know about it,
// create an MDO for this device
dbcContext = NULL;
ntStatus = DBCLASS_CreateDeviceFilterObject(
deviceExtension->DriverObject,
&deviceFilterObject,
devObj,
dbcContext,
DB_FDO_1394_DEVICE);
if (NT_SUCCESS(ntStatus))
{
DBCLASS_AddDevicePDOToList(deviceFilterObject,
deviceRelations->Objects[i]);
}
DBCLASS_KdPrint((1,
"'(dbfilter)(bus)(1394) Create DO %x for 1394 PDO\n",
deviceFilterObject));
}
}
DBCLASS_1394QBR_Done:
KeSetEvent(&deviceExtension->QBusRelations1394Event,
1,
FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
ULONG
DBCLASS_CountConnectedPorts(
PTOPOLOGY_MAP TopologyMap,
ULONG Index,
ULONG Connection
)
/*++
Routine Description:
Arguments:
Return Value:
NTSTATUS
--*/
{
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
ULONG count = 0;
selfId = TopologyMap->TOP_Self_ID_Array[Index];
DBCLASS_KdPrint((2, "'TOP_Self_ID = (%08X)\n",
selfId));
DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
selfId.SID_Phys_ID));
DBCLASS_KdPrint((2, "'SID_Port1 = (%08X)\n", (ULONG)
selfId.SID_Port1));
DBCLASS_KdPrint((2, "'SID_Port2 = (%08X)\n", (ULONG)
selfId.SID_Port2));
DBCLASS_KdPrint((2, "'SID_Port3 = (%08X)\n", (ULONG)
selfId.SID_Port3));
DBCLASS_KdPrint((2, "'SID_More_Packets = (%08X)\n", (ULONG)
selfId.SID_More_Packets));
#define COUNT_PORT(s) if ((s) == Connection) { count++;}
COUNT_PORT(selfId.SID_Port1);
COUNT_PORT(selfId.SID_Port2);
COUNT_PORT(selfId.SID_Port3);
if (selfId.SID_More_Packets)
{
do
{
Index++;
RtlCopyMemory(&selfIdMore,
&TopologyMap->TOP_Self_ID_Array[Index],
sizeof(ULONG));
DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
selfIdMore.SID_Phys_ID));
DBCLASS_KdPrint((2, "'SID_PortA = (%08X)\n", (ULONG)
selfIdMore.SID_PortA));
DBCLASS_KdPrint((2, "'SID_PortB = (%08X)\n", (ULONG)
selfIdMore.SID_PortB));
DBCLASS_KdPrint((2, "'SID_PortC = (%08X)\n", (ULONG)
selfIdMore.SID_PortC));
DBCLASS_KdPrint((2, "'SID_PortD = (%08X)\n", (ULONG)
selfIdMore.SID_PortD));
DBCLASS_KdPrint((2, "'SID_PortE = (%08X)\n", (ULONG)
selfIdMore.SID_PortE));
DBCLASS_KdPrint((2, "'SID_PortF = (%08X)\n", (ULONG)
selfIdMore.SID_PortF));
DBCLASS_KdPrint((2, "'SID_PortG = (%08X)\n", (ULONG)
selfIdMore.SID_PortG));
DBCLASS_KdPrint((2, "'SID_PortH = (%08X)\n", (ULONG)
selfIdMore.SID_PortH));
COUNT_PORT(selfIdMore.SID_PortA);
COUNT_PORT(selfIdMore.SID_PortB);
COUNT_PORT(selfIdMore.SID_PortC);
COUNT_PORT(selfIdMore.SID_PortD);
COUNT_PORT(selfIdMore.SID_PortE);
COUNT_PORT(selfIdMore.SID_PortF);
COUNT_PORT(selfIdMore.SID_PortG);
COUNT_PORT(selfIdMore.SID_PortH);
} while (selfIdMore.SID_More_Packets);
}
#undef COUNT_PORT
return count;
}
BOOLEAN
DBCLASS_IsParent(
PTOPOLOGY_MAP TopologyMap,
ULONG SelfIdIndex
)
/*++
Routine Description:
returns true if the node is 'connetected to parent' (2)
Arguments:
Return Value:
NTSTATUS
--*/
{
return TRUE;
}
BOOLEAN
DBCLASS_IsChild(
PTOPOLOGY_MAP TopologyMap,
ULONG SelfIdIndex
)
/*++
Routine Description:
returns true if the node is 'connetected to child' (3)
Arguments:
Return Value:
NTSTATUS
--*/
{
ULONG i = SelfIdIndex;
BOOLEAN isChild = FALSE;
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
selfId = TopologyMap->TOP_Self_ID_Array[i];
if (selfId.SID_Port1 == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfId.SID_Port2 == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfId.SID_Port3 == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfId.SID_More_Packets)
{
do
{
i++;
RtlCopyMemory(&selfIdMore,
&TopologyMap->TOP_Self_ID_Array[i],
sizeof(ULONG));
if (selfIdMore.SID_PortA == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfIdMore.SID_PortB == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfIdMore.SID_PortC == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfIdMore.SID_PortD == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfIdMore.SID_PortE == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfIdMore.SID_PortF == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfIdMore.SID_PortG == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
if (selfIdMore.SID_PortH == SELF_ID_CONNECTED_TO_CHILD)
{
isChild = TRUE;
}
} while (selfIdMore.SID_More_Packets);
}
DBCLASS_KdPrint((2, "'IsChild %d\n", isChild));
return isChild;
}
BOOLEAN
DBCLASS_IsNodeConnectedToLink(
PDBC_CONTEXT DbcContext,
PTOPOLOGY_MAP TopologyMap,
USHORT CurrentNodeId,
USHORT LinkNodeId
)
/*++
Routine Description:
Given the nodeId for a Device and the node Id for the link
figure out if the node is connected to the link
return true if it is
Arguments:
Return Value:
NTSTATUS
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
USHORT nodeCount, selfIdCount;
BOOLEAN connected = FALSE;
LONG device_Index = -1;
ULONG connectCount, i, childCount, parentCount;
DBCLASS_KdPrint((2, "'TopologyMap = (%08X)\n", TopologyMap));
DBCLASS_KdPrint((2, "'TOP_Length = (%08X)\n", TopologyMap->TOP_Length));
DBCLASS_KdPrint((2, "'TOP_CRC = (%08X)\n", TopologyMap->TOP_CRC));
DBCLASS_KdPrint((2, "'TOP_Generation = (%08X)\n", TopologyMap->TOP_Generation));
DBCLASS_KdPrint((2, "'TOP_Node_Count = (%08X)\n", TopologyMap->TOP_Node_Count));
DBCLASS_KdPrint((2, "'TOP_Self_ID_Count = (%08X)\n", TopologyMap->TOP_Self_ID_Count));
nodeCount = TopologyMap->TOP_Node_Count;
selfIdCount = TopologyMap->TOP_Self_ID_Count;
DBCLASS_KdPrint((2, "'nodeCount = (%08X) selfIdCount = (%08X)\n",
nodeCount, selfIdCount));
//
// walk the topology map and find the index of the node for the
// device
//
DBCLASS_KdPrint((2, "'Find Node Index\n"));
for (i=0; i< nodeCount; i++)
{
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
selfId = TopologyMap->TOP_Self_ID_Array[i];
DBCLASS_KdPrint((2, "'[%d] SID_Phys_ID = (%08X)\n", i, (ULONG)
selfId.SID_Phys_ID));
if (selfId.SID_Phys_ID == CurrentNodeId)
{
// this is the host, count the ports
device_Index = i;
}
if (selfId.SID_More_Packets)
{
do
{
i++;
RtlCopyMemory(&selfIdMore,
&TopologyMap->TOP_Self_ID_Array[i],
sizeof(ULONG));
DBCLASS_KdPrint((2, "'[%d].more SID_Phys_ID = (%08X)\n", i, (ULONG)
selfIdMore.SID_Phys_ID));
} while (selfIdMore.SID_More_Packets);
}
} /* for */
// did we find the device?
if (device_Index != -1)
{
// yes
DBCLASS_KdPrint((2, "'-->device_Index found = (%08X)\n",
device_Index));
// OK if this is a device bay device then it can
// have only one connected port
childCount = DBCLASS_CountConnectedPorts(
TopologyMap,
device_Index,
SELF_ID_CONNECTED_TO_CHILD);
parentCount = DBCLASS_CountConnectedPorts(
TopologyMap,
device_Index,
SELF_ID_CONNECTED_TO_PARENT);
connectCount = childCount + parentCount;
DBCLASS_KdPrint((2, "'parent = %d child %d\n",
parentCount, childCount));
DBCLASS_KdPrint((2, "'connectCount = %d \n",
connectCount));
if (parentCount == 1)
{
// OK possible device bay device
SELF_ID selfId;
SELF_ID_MORE selfIdMore;
i = device_Index;
// port is 'connected to parent' see if it is
// the link
// if it is not the link then this cannot be a DB
// device
i++;
if (i == selfIdCount)
{
DBCLASS_KdPrint((2, "'NXT ENTRY wraps\n"));
i=0;
}
while (!DBCLASS_IsChild(TopologyMap, i))
{
// advance to the next selfId until we find one
// that is connected to child(3)
selfId = TopologyMap->TOP_Self_ID_Array[i];
// skip 'more packets'
if (selfId.SID_More_Packets)
{
do
{
i++;
RtlCopyMemory(&selfIdMore,
&TopologyMap->TOP_Self_ID_Array[i],
sizeof(ULONG));
DBCLASS_KdPrint((2, "'SID_Phys_ID = (%08X)\n", (ULONG)
selfIdMore.SID_Phys_ID));
} while (selfIdMore.SID_More_Packets);
}
i++;
if (i == selfIdCount)
{
DBCLASS_KdPrint((2, "'NXT ENTRY wraps\n"));
i=0;
}
}
// now check the next entry
selfId = TopologyMap->TOP_Self_ID_Array[i];
DBCLASS_KdPrint((2, "'NXT ENTRY - SID_Phys_ID = (%08X)\n", (ULONG)
selfId.SID_Phys_ID));
if (selfId.SID_Phys_ID == LinkNodeId)
{
connected = TRUE;
}
}
else if (childCount == 1)
{
// possible DB device
SELF_ID selfId;
ULONG physIdPrev, top;
i = device_Index;
do
{
if (i==0)
{
i = nodeCount-1;
}
else
{
i--;
}
selfId = TopologyMap->TOP_Self_ID_Array[i];
physIdPrev = selfId.SID_Phys_ID;
do
{
top = i;
if (i==0)
{
i = nodeCount-1;
}
else
{
i--;
}
selfId = TopologyMap->TOP_Self_ID_Array[i];
} while (physIdPrev == selfId.SID_Phys_ID);
i = top;
DBCLASS_KdPrint((2, "'PREV - idx = %d\n", i));
// stop when we find a parent
} while (!DBCLASS_IsParent(TopologyMap, i)); // entry !=2
// port is 'connected to parent' see if it is
// the link
// advance to the next selfId
selfId = TopologyMap->TOP_Self_ID_Array[i];
// note that PhysID is the same even if this is a 'more packets'
// SID
DBCLASS_KdPrint((2, "'NXT ENTRY - SID_Phys_ID = (%08X)\n", (ULONG)
selfId.SID_Phys_ID));
if (selfId.SID_Phys_ID == LinkNodeId)
{
connected = TRUE;
}
}
}
DBCLASS_KdPrint((2, "'>CurrentNodeId %d, LinkNodeId = %d CONNECTED(%d)\n",
CurrentNodeId, LinkNodeId, connected));
BRK_ON_TRAP();
return connected;
}
NTSTATUS
DBCLASS_Check1394DevicePDO(
PDEVICE_OBJECT FilterDeviceObject,
PDBC_CONTEXT DbcContext,
PDEVICE_OBJECT DevicePDO
)
/*++
Routine Description:
Arguments:
Return Value:
NTSTATUS
--*/
{
NTSTATUS ntStatus;
PTOPOLOGY_MAP topologyMap = NULL;
PNODE_DEVICE_EXTENSION nodeExtension;
PDEVICE_EXTENSION deviceExtension;
USHORT nodeId, linkNodeId;
IRB irb;
// get the node id for the device
deviceExtension = FilterDeviceObject->DeviceExtension;
nodeExtension = DevicePDO->DeviceExtension;
nodeId = nodeExtension->NodeAddress.NA_Node_Number;
DBCLASS_KdPrint((2, "'1394 PDO (%08X) has NodeID = (%08X)\n",
DevicePDO, nodeId));
// get the topology map from the local host
ntStatus = DBCLASS_GetSpeedAndTopologyMaps(&topologyMap,
FilterDeviceObject);
if (DbcContext->ControllerSig == DBC_ACPI_CONTROLLER_SIG && topologyMap)
{
// ACPI dbc
// PDO must be a child or parent of the controller
irb.u.Get1394AddressFromDeviceObject.fulFlags = 0;
irb.FunctionNumber = REQUEST_GET_ADDR_FROM_DEVICE_OBJECT;
ntStatus = DBCLASS_SyncSubmitIrb(deviceExtension->TopOfStackDeviceObject,
&irb);
DBCLASS_KdPrint((2, "'GetLocalNodeId() = (%08X)\n", ntStatus));
linkNodeId =
irb.u.Get1394AddressFromDeviceObject.NodeAddress.NA_Node_Number;
if (DBCLASS_IsNodeConnectedToLink(DbcContext,
topologyMap,
nodeId,
linkNodeId))
{
ntStatus = STATUS_SUCCESS;
}
else
{
ntStatus = STATUS_DEVICE_NOT_CONNECTED;
}
}
else
{
// USB dbc
PNODE_DEVICE_EXTENSION linkExtension;
// USB dbc
// PDO must be a child or parent of the link
DBCLASS_ASSERT(DbcContext->LinkDeviceObject);
linkExtension = DbcContext->LinkDeviceObject->DeviceExtension;
linkNodeId = linkExtension->NodeAddress.NA_Node_Number;
DBCLASS_ASSERT(RtlCompareMemory(&DbcContext->SubsystemDescriptor.guid1394Link[0],
&linkExtension->ConfigRom->CR_Node_UniqueID[0],
8) == 8);
if(topologyMap)
{
if (DBCLASS_IsNodeConnectedToLink(DbcContext,
topologyMap,
nodeId,
linkNodeId))
{
ntStatus = STATUS_SUCCESS;
}
else
{
ntStatus = STATUS_DEVICE_NOT_CONNECTED;
}
}
}
return ntStatus;
}
NTSTATUS
DBCLASS_1394GetBusGuid(
PDEVICE_OBJECT DeviceObject,
PUCHAR BusGuid
)
/*++
Routine Description:
Arguments:
Return Value:
NTSTATUS
--*/
{
NTSTATUS ntStatus;
BOOLEAN waitForIt = FALSE;
IRB irb;
irb.u.GetLocalHostInformation.nLevel = GET_HOST_UNIQUE_ID;
irb.FunctionNumber = REQUEST_GET_LOCAL_HOST_INFO;
irb.u.GetLocalHostInformation.Information = BusGuid;
ntStatus = DBCLASS_SyncSubmitIrb(DeviceObject,
&irb);
DBCLASS_KdPrint((2, "'GetBusGuid() = (%08X)\n", ntStatus));
#if DBG
DBCLASS_KdPrint((1, "'>Local Host GUID\n"));
DBCLASS_KdPrintGuid(1, BusGuid);
#endif
return ntStatus;
}
NTSTATUS
DBCLASS_1394BusFilterDispatch(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PBOOLEAN Handled
)
/*++
Routine Description:
Arguments:
Return Value:
NTSTATUS
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
BOOLEAN waitForIt = FALSE;
UCHAR busGuid1394[8];
deviceExtension = DeviceObject->DeviceExtension;
ntStatus = Irp->IoStatus.Status;
*Handled = FALSE;
LOGENTRY(LOG_MISC, '13b>', 0, DeviceObject, Irp);
ntStatus = Irp->IoStatus.Status;
irpStack = IoGetCurrentIrpStackLocation (Irp);
DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MJ_ (%08X) IRP_MN_ (%08X)\n",
irpStack->MajorFunction, irpStack->MinorFunction));
switch (irpStack->MajorFunction)
{
case IRP_MJ_PNP:
switch (irpStack->MinorFunction)
{
case IRP_MN_START_DEVICE:
DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_START_DEVICE\n"));
break;
case IRP_MN_STOP_DEVICE:
DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_STOP_DEVICE\n"));
break;
case IRP_MN_REMOVE_DEVICE:
DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_REMOVE_DEVICE\n"));
DBCLASS_RemoveBusFilterMDOFromList(DeviceObject);
IoDetachDevice(deviceExtension->TopOfStackDeviceObject);
IoDeleteDevice (DeviceObject);
DBCLASS_KdPrint((1, "'REMOVE DB Filter on 1394 BUS\n"));
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
DBCLASS_KdPrint((1, "'(dbfilter)(bus)(1394)IRP_MN_QUERY_DEVICE_RELATIONS\n"));
*Handled = TRUE;
if (irpStack->Parameters.QueryDeviceRelations.Type == BusRelations)
{
DBCLASS_KdPrint((1,"'>>QBR 1394 BUS\n"));
IoCopyCurrentIrpStackLocationToNext(Irp);
KeInitializeEvent(&deviceExtension->QBusRelations1394Event,
NotificationEvent,
FALSE);
// Set up a completion routine to handle marking the IRP.
IoSetCompletionRoutine(Irp,
DBCLASS_1394QBusRelationsComplete,
DeviceObject,
TRUE,
TRUE,
TRUE);
waitForIt = TRUE;
}
else
{
IoSkipCurrentIrpStackLocation(Irp);
}
// Now Pass down the IRP
deviceExtension->QBusRelations1394Success = FALSE;
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, Irp);
if (waitForIt)
{
NTSTATUS status;
status = KeWaitForSingleObject(&deviceExtension->QBusRelations1394Event,
Suspended,
KernelMode,
FALSE,
NULL);
// let's see if the call down the stack failed
if(!deviceExtension->QBusRelations1394Success)
{
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
DBCLASS_KdPrint((1, "'**** Searching for Device Bay PDOs \n"));
//
// get the bus guid
//
if (NT_SUCCESS(DBCLASS_1394GetBusGuid(
deviceExtension->TopOfStackDeviceObject,
&busGuid1394[0])))
{
PDEVICE_RELATIONS deviceRelations;
ULONG i;
deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
// loop thru DOs finding a DBC links
for (i=0; i< deviceRelations->Count; i++)
{
PDEVICE_EXTENSION mdo1394DeviceExtension;
PDEVICE_OBJECT mdo1394;
// should always be found
mdo1394 = DBCLASS_FindDevicePdo(deviceRelations->Objects[i]);
if(!mdo1394)
continue;
mdo1394DeviceExtension = mdo1394->DeviceExtension;
DBCLASS_Find1394DbcLinks(
mdo1394DeviceExtension->PhysicalDeviceObject);
}
// loop through PDO list
// and try to find the controllers
DBCLASS_KdPrint((1, "'**>> DevRel Count (%08X)\n", deviceRelations->Count));
for (i=0; i< deviceRelations->Count; i++)
{
PDEVICE_EXTENSION mdo1394DeviceExtension;
PDEVICE_OBJECT mdo1394;
PDEVICE_OBJECT DevicePDO;
PNODE_DEVICE_EXTENSION nodeExtension;
LOGENTRY(LOG_MISC, 'FCQB', deviceRelations->Objects[i], i, 0);
// should always be found
mdo1394 = DBCLASS_FindDevicePdo(deviceRelations->Objects[i]);
if(!mdo1394)
continue;
mdo1394DeviceExtension = mdo1394->DeviceExtension;
DevicePDO = mdo1394DeviceExtension->PhysicalDeviceObject;
nodeExtension = DevicePDO->DeviceExtension;
DBCLASS_KdPrint((1, "'****>> MDO (%08X) DbcContext (%08X) DrvObj (%08X) DevObj (%08X) PhysDevObj (%08X)\n",
mdo1394, mdo1394DeviceExtension->DbcContext,
deviceExtension->DriverObject, DeviceObject, mdo1394DeviceExtension->PhysicalDeviceObject));
// if this is a "virtual" device, just skip it
if(nodeExtension->Tag == VIRTUAL_DEVICE_EXTENSION_TAG)
{
DBCLASS_KdPrint((1, "'****> Virtual 1394 Device\n"));
continue;
}
DBCLASS_KdPrint((1, "'****>> NodeNumber (%08X) BusNumber (%08X) DevObj (%08X) PortDevObj (%08X)\n",
nodeExtension->NodeAddress.NA_Node_Number,
nodeExtension->NodeAddress.NA_Bus_Number,
nodeExtension->DeviceObject,
nodeExtension->PortDeviceObject));
if (mdo1394DeviceExtension->DbcContext == NULL)
{
mdo1394DeviceExtension->DbcContext =
DBCLASS_FindController1394DevicePdo(
deviceExtension->DriverObject,
DeviceObject,
mdo1394DeviceExtension->PhysicalDeviceObject,
&busGuid1394[0]);
}
// this PDO is associated with a controller
// see if is really a device bay device
DBCLASS_KdPrint((1, "'****> Check 1394 Device\n"));
if (mdo1394DeviceExtension->DbcContext)
{
PDBC_CONTEXT dbcContext;
USHORT bay = 0;
DBCLASS_KdPrint((1, "'****>> DBC detected on bus\n"));
DBCLASS_KdPrint((2, "'DbcContext (%08X) PhyDevObj (%08X)\n", mdo1394DeviceExtension->DbcContext,
mdo1394DeviceExtension->PhysicalDeviceObject));
dbcContext = mdo1394DeviceExtension->DbcContext;
bay = DBCLASS_GetBayFor1394Pdo(
DeviceObject,
mdo1394DeviceExtension->DbcContext,
mdo1394DeviceExtension->PhysicalDeviceObject);
if (bay)
{
// This is device bay device
dbcContext->BayInformation[bay].DeviceFilterObject =
mdo1394;
mdo1394DeviceExtension->Bay = bay;
DBCLASS_KdPrint((1,
"'****>>> 1394 PDO(%x) is in BAY[%d]\n",
mdo1394DeviceExtension->PhysicalDeviceObject,
bay));
// Notify PNP that this Device object
// is tied to the controller PDO
//TEST_TRAP();
IoInvalidateDeviceRelations(dbcContext->ControllerPdo,
RemovalRelations);
}
else
{
// not a device bay device
mdo1394DeviceExtension->Bay = 0;
DBCLASS_KdPrint((1,
"'****>>> 1394 PDO(%x) is not a DB device\n",
mdo1394DeviceExtension->PhysicalDeviceObject));
}
}
else
{
// no DBC phy link on this bus therefore this is
// not a device bay device
DBCLASS_KdPrint(
(1, "'****>> No DBC detected on bus\n"));
mdo1394DeviceExtension->Bay = 0;
DBCLASS_KdPrint((1,
"'****>>> 1394 PDO(%x) is not a DB device\n",
mdo1394DeviceExtension->PhysicalDeviceObject));
}
#if DBG
// dump the guid for this PDO
{
PNODE_DEVICE_EXTENSION nodeExtension;
nodeExtension =
mdo1394DeviceExtension->PhysicalDeviceObject->DeviceExtension;
DBCLASS_KdPrint((2, "'****>>>> 1394 PDO GUID\n"));
DBCLASS_KdPrintGuid(2, (PUCHAR)&nodeExtension->ConfigRom->CR_Node_UniqueID[0]);
}
#endif
DBCLASS_KdPrint((2, "'****>>>>> FC-QBR 1394 PDO[%d] %x DbcContext %x\n", i,
deviceRelations->Objects[i], mdo1394DeviceExtension->DbcContext));
}
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
break;
} /* irpStack->MinorFunction */
break;
} /* irpStack->MajorFunction */
LOGENTRY(LOG_MISC, '13b<', 0, DeviceObject, 0);
return ntStatus;
}