23dbea53763bdbab30e37e2e157f7d543143586c
[mirror/winof/.git] / hw / mthca / kernel / mt_reset_tavor.c
1 #include <initguid.h>
2 #include <wdmguid.h>
3 #include "hca_driver.h"
4 #include "mthca.h"
5 #include "hca_debug.h"
6 #include "Mt_l2w.h"
7 #if defined(EVENT_TRACING)
8 #ifdef offsetof
9 #undef offsetof
10 #endif
11 #include "mt_reset_tavor.tmh"
12 #endif
13
14
15 #pragma warning(disable : 4996)
16
17 /* limitations */
18 #define N_BUSES                         16              /* max number of PCI buses */
19 #define N_DEVICES                       32              /* max number of devices on one bus */
20 #define N_FUNCTIONS             8                       /* max number of functions on one device */
21 #define N_CARDS                         8                       /* max number of HCA cards */
22
23 /*----------------------------------------------------------------*/
24
25 PWCHAR 
26 WcharFindChar(
27         IN      PWCHAR          pi_BufStart,
28         IN      PWCHAR          pi_BufEnd,
29         IN      WCHAR           pi_FromPattern,
30         IN      WCHAR           pi_ToPattern
31         )
32 /*++
33
34 Routine Description:
35     Converts wide-character string into ASCII
36
37 Arguments:
38
39         pi_BufStart.......... start of the source string
40         pi_BufEnd............ end of the source string
41         pi_FromPattern....... start of pattern range to find
42         pi_ToPattern......... end of pattern range to find
43
44 Return Value:
45
46         pointer to the first pattern found or NULL (when reached the end)
47
48 --*/
49 { /* WcharFindChar */
50
51         PWCHAR  l_pResult       = pi_BufStart;
52
53         while (l_pResult < pi_BufEnd )
54         {
55                 if (*l_pResult >= pi_FromPattern && *l_pResult <= pi_ToPattern)
56                         return l_pResult;
57                 l_pResult++;
58         }
59
60         return NULL;
61
62 } /* WcharFindChar */
63
64 /*----------------------------------------------------------------*/
65
66 /*
67  * Function: PciFindDeviceByBusAndId
68  *
69  * Parameters:
70  *              IN                      pi_Bus                          - a bus, to start the scan
71  *              IN                      pi_DevId                        - Device Id to search
72  *              INOUT   po_pDevFunc     - pointer to dev/func, from which to start the search
73  * 
74  * Returns:
75  *              FALSE   - device not found
76  *      TRUE    - a device was found;  *po_pDevFunc contains its location
77  *
78  * Description:
79  *      The function is intended for iterative search on one bus.
80  *              It looks for the device of pi_DevId id, starting from device with  
81  *              *po_pDevFunc location. When it finds the next device of that id, it updates  
82  *              *po_pDevFunc with the found device' location
83  *
84  */
85 BOOLEAN PciFindDeviceByBusAndId( 
86         IN      ULONG           pi_Bus, 
87         IN      ULONG           pi_DevId, 
88         IN OUT PULONG   po_pDevFunc )
89 {
90         ULONG   l_DevId;
91         ULONG   l_Bytes;
92         ULONG   l_Device;
93         ULONG l_Function; 
94
95         // calculate, where to start the search
96         l_Device = *po_pDevFunc & 0x01f;
97         l_Function = (*po_pDevFunc >> 5) & 7;
98         for (; l_Device < N_DEVICES; l_Device++, l_Function = 0 ) {
99                 for (; l_Function < N_FUNCTIONS; l_Function++ ) {
100                 l_Bytes = HalGetBusDataByOffset(
101                         PCIConfiguration,
102                         pi_Bus,
103                                 l_Device |(l_Function<<5),
104                         (PVOID)&l_DevId,
105                         0,
106                         sizeof(ULONG)
107                         );
108                 if (l_Bytes != sizeof(ULONG)) 
109                                 continue;       /* as if - "not found" */
110                         if (l_DevId == pi_DevId)
111                                 goto ExitFound;
112                 }
113         }
114         return FALSE;
115         
116 ExitFound:              
117         *po_pDevFunc = l_Device |(l_Function<<5);
118         return TRUE;
119 }
120
121 /*----------------------------------------------------------------*/
122
123 /*
124  * Function: PciFindDeviceById
125  *
126  * Parameters:
127  *              IN                      pi_DevId                        - Device Id to search
128  *              INOUT   po_pBus                 - pointer to bus number, from which to start the search
129  *              INOUT   po_pDevFunc     - pointer to dev/func, from which to start the search
130  * 
131  * Returns:
132  *              FALSE   - device was not found
133  *      TRUE    - a device was found;  *po_pBus/*po_pDevFunc contain its location
134  *
135  * Description:
136  *      The function is intended for an iterative search.
137  *              It looks for the device of pi_DevId id, starting from device with *po_pBus and 
138  *              *po_pDevFunc location. When it finds the next device of that id, updates *po_pBus 
139  *              and *po_pDevFunc with the found device' location
140  *
141  */
142 static 
143 BOOLEAN PciFindDeviceById( 
144         IN      ULONG           pi_DevId, 
145         IN OUT PULONG           po_pBus, 
146         IN OUT PULONG           po_pDevFunc )
147 {
148         ULONG l_Bus;
149         ULONG l_DevFunc = *po_pDevFunc;
150         
151         for (l_Bus= *po_pBus; l_Bus < N_BUSES; l_Bus++, l_DevFunc=0) {
152                 if (PciFindDeviceByBusAndId(l_Bus, pi_DevId, &l_DevFunc))
153                         break;
154         }
155         if (l_Bus >= N_BUSES)
156                 return FALSE;
157         
158         // found
159         *po_pBus = l_Bus;
160         *po_pDevFunc = l_DevFunc;
161         return TRUE;
162 }
163
164 /*----------------------------------------------------------------*/
165
166 /*
167  * Function: PciFindBridgeByBus
168  *
169  * Parameters:
170  *              IN              pi_SecBus               - bus number of an HCA in question
171  *              OUT     po_pBus                 - pointer to bus number of the bridge of the HCA, if found
172  *              OUT     po_pDevFunc     - pointer to dev/func of the bridge of the HCA, if found
173  * 
174  * Returns:
175  *              FALSE   - the bridge not found
176  *      TRUE    - a device was found;  *po_pBus/*po_pDevFunc contain its location
177  *
178  * Description:
179  *              The function scans all the buses to find the Bridge of an HCA device, found on bus pi_SecBus. 
180  *              The appropiate bridge must have its PrimaryBus field in PCI cfg header equal to pi_SecBus.
181  *                      
182  */
183 static BOOLEAN PciFindBridgeByBus( 
184         IN ULONG                pi_SecBus, 
185         OUT PULONG              po_pBus, 
186         OUT PULONG              po_pDevFunc )
187 {
188         ULONG   l_DevFunc=0, l_Bus=0;
189         ULONG l_DevId = ((int)(23110) << 16) | PCI_VENDOR_ID_MELLANOX;  
190         ULONG l_SecBus, l_tmp, l_Bytes;
191         ULONG   l_Device;
192         ULONG l_Function; 
193         int searching =1;
194
195         while (searching) {
196                 /* look for a bridge */
197                 if (!PciFindDeviceById(l_DevId, &l_Bus, &l_DevFunc)) 
198                         return FALSE;   /* bridge not found */
199                 
200                 /* found a bridge  -check, whether it is ours */
201        l_Bytes = HalGetBusDataByOffset(
202                 PCIConfiguration,
203                 l_Bus,
204                 l_DevFunc,
205                 (PVOID)&l_tmp,
206                 24,     /* 24 - PrimaryBus, 25 - SecondaryBus, 26 - SubordinateBus */
207                 sizeof(ULONG)
208                 );
209        if (l_Bytes != sizeof(ULONG)) 
210                         goto NextDevice;        /* as if - "not found" */
211                          
212                 l_SecBus = (l_tmp >> 16) & 255;
213                 if ( l_SecBus == pi_SecBus )
214                         break; /* found !!! */
215                 
216 NextDevice:             
217                 // calculate, where to continue the search
218                 l_Device = l_DevFunc & 0x01f;
219                 l_Function = (l_DevFunc >> 5) & 7;
220                 l_Function++;
221                 if (l_Function >= N_FUNCTIONS) {
222                         l_Function = 0;
223                         l_Device++;
224                         if (l_Device >= N_DEVICES) {
225                                 l_Device = 0;
226                                 l_Bus++;
227                         }
228                         if (l_Bus >= N_BUSES)
229                                 return FALSE;
230                 }
231                 l_DevFunc = l_Device |(l_Function<<5);;
232         }
233         
234         *po_pBus = l_Bus;
235         *po_pDevFunc = l_DevFunc;
236         return TRUE;
237 }
238
239 /*----------------------------------------------------------------*/
240
241 /*
242  * Function: MdGetDevLocation
243  *
244  * Parameters:
245  *              IN              pi_pPdo                 - PDO of a device in question
246  *              OUT     po_pBus                 - pointer to the bus number of the device in question
247  *              OUT     po_pDevFunc     - pointer to dev/func of the device, if found
248  * 
249  * Returns:
250  *              not STATUS_SUCCESS      - the device location was not found
251  *      STATUS_SUCCESS          - the device location was found and returned in OUT parameters
252  *
253  * Description:
254  *              The function uses IoGetDeviceProperty to get the location of a device with given PDO
255  *                      
256  */
257 static NTSTATUS 
258 MdGetDevLocation(
259         IN      PDEVICE_OBJECT  pi_pPdo,
260         OUT     ULONG *                 po_pBus,
261         OUT ULONG        *                      po_pDevFunc 
262         )
263 {
264         ULONG   l_BusNumber, l_DevNumber, l_Function, l_ResultLength = 0;
265         WCHAR   l_Buffer[40], *l_pEnd, *l_pBuf = l_Buffer, *l_pBufEnd = l_Buffer + sizeof(l_Buffer);
266         NTSTATUS        l_Status;
267         UNICODE_STRING  l_UnicodeNumber;
268
269         /* prepare */
270         l_ResultLength = 0;
271         RtlZeroMemory( l_Buffer, sizeof(l_Buffer) );
272
273         /* Get the device number  */
274         l_Status = IoGetDeviceProperty(pi_pPdo,
275                 DevicePropertyLocationInformation, sizeof(l_Buffer), l_Buffer, &l_ResultLength);
276
277         /* Verify if the function was successful */
278         if ( !NT_SUCCESS(l_Status) || !l_ResultLength ) {
279                 HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM  ,("(MdGetDevLocation) Unable to get device number: Status 0x%x, ResultSize %d \n", 
280                         l_Status, l_ResultLength  ));
281                 goto exit;      
282         }
283
284         // ALL THE BELOW CRAP WE DO INSTEAD OF 
285         // sscanf(l_Buffer, "PCI bus %d, device %d, function %d", &l_BusNumber, &l_DevNumber, &l_Function );
286
287         /* take bus number */
288         l_pBuf  = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );
289         if (l_pBuf == NULL) goto err;
290         l_pEnd  = WcharFindChar( l_pBuf, l_pBufEnd, L',', L',' );
291         if (l_pEnd == NULL) goto err;
292         l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);
293         l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;
294         RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_BusNumber);
295
296         /* take slot number */
297         l_pBuf  = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );
298         if (l_pBuf == NULL) goto err;
299         l_pEnd  = WcharFindChar( l_pBuf, l_pBufEnd, L',', L',' );
300         if (l_pEnd == NULL) goto err;
301         l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);
302         l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;
303         RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_DevNumber);
304
305         /* take function number */
306         *(l_Buffer + (l_ResultLength>>1)) = 0;  /* set end of string */
307         l_pBuf  = WcharFindChar( l_pBuf, l_pBufEnd, L'0', L'9' );
308         if (l_pBuf == NULL) goto err;
309         l_pEnd  = WcharFindChar( l_pBuf, l_pBufEnd, 0, 0 );
310         if (l_pEnd == NULL) goto err;
311         l_UnicodeNumber.Length = l_UnicodeNumber.MaximumLength = (USHORT)((PCHAR)l_pEnd - (PCHAR)l_pBuf);
312         l_UnicodeNumber.Buffer = l_pBuf; l_pBuf = l_pEnd;
313         RtlUnicodeStringToInteger( &l_UnicodeNumber, 10, &l_Function);
314
315         /* return the results */
316         *po_pBus                = l_BusNumber;
317         *po_pDevFunc = (l_DevNumber & 0x01f) | ((l_Function & 7) << 5);
318
319         goto exit;
320
321 err:
322         l_Status = STATUS_UNSUCCESSFUL;
323 exit:
324         return l_Status;
325 }
326
327
328 /*------------------------------------------------------------------------------------------------------*/
329
330 /*
331  * Function: PciFindPdoByPdoAndLocation
332  *
333  * Parameters:
334  *              IN              pi_pPdo                 - PDO of HCA's bus device
335  *              IN      pi_Bus, pi_DevFunc      - bridge location
336  *              OUT     po_pPdo                 - pointer to PDO of the bridge, when found
337  * 
338  * Returns:
339  *              FALSE   - the bridge was not found
340  *      TRUE    - a device was found;  *po_pPdo contains its PDO
341  *
342  * Description:
343  *              The function finds PDO of a Tavor bridge device by scanning through all the 
344  *              devices of the PCI.SYS driver   
345  *
346  *      Note:
347  *              It is a "hack" algorithm. It uses some fields of system structures and some
348  *              optimistic assumptions - see more below
349  */
350 static BOOLEAN PciFindPdoByPdoAndLocation( 
351         IN PDEVICE_OBJECT pi_pPdo,
352         IN ULONG                pi_Bus, 
353         IN ULONG                pi_DevFunc,
354         OUT PDEVICE_OBJECT * po_pPdo )
355 {
356         PDRIVER_OBJECT l_pDrv;
357         PDEVICE_OBJECT l_pPdo;
358         NTSTATUS l_Status;
359         ULONG   l_Bus, l_DevFunc;
360         // suppose that there is no more than N_PCI_DEVICES, belonging to PCI.SYS
361         #define N_PCI_DEVICES   256
362         // suppose that the PDO objects, once created, never get moved
363         PDEVICE_OBJECT *pdo;
364         int i, n_pdos = 0;
365         KIRQL irql;
366
367         
368         pdo = (PDEVICE_OBJECT *)ExAllocatePoolWithTag(
369                 NonPagedPool,
370                 N_PCI_DEVICES * sizeof(PDEVICE_OBJECT),
371                 MT_TAG_KERNEL );
372         if (!pdo)
373                 return FALSE;
374         
375         // suppose, that PDOs are added only at PASSIVE_LEVEL
376         irql = KeRaiseIrqlToDpcLevel();
377                 
378         // get to the PCI.SYS driver
379         l_pDrv = pi_pPdo->DriverObject;
380
381         // find and store all bus PDO   s (because the bridge is a bus enumerated device)
382         for ( l_pPdo = l_pDrv->DeviceObject; l_pPdo; l_pPdo = l_pPdo->NextDevice ) {
383                 if ( l_pPdo->Flags & DO_BUS_ENUMERATED_DEVICE ) {
384                         pdo[n_pdos] = l_pPdo;
385                         if (++n_pdos >= N_PCI_DEVICES)
386                                 break;
387                 }
388         }
389
390         // return to previous level
391         KeLowerIrql(irql);
392         
393         //  loop over all the PCI driver devices
394         l_pPdo = NULL;  /* mark, that we didn't find PDO */
395         for ( i = 0; i < n_pdos; ++i ) {
396                 // get the location of the device of that PDO
397                 l_Status = MdGetDevLocation( pdo[i], &l_Bus, &l_DevFunc );
398                 if (l_Status != STATUS_SUCCESS)
399                         continue;
400                 // check, whether it's our device
401                 if (l_Bus == pi_Bus && l_DevFunc == pi_DevFunc) {
402                         l_pPdo = pdo[i];
403                         break;
404                 }
405         }
406
407         *po_pPdo = l_pPdo;
408         ExFreePool(pdo);
409         return (BOOLEAN)!!*po_pPdo;     
410 }
411
412 /*----------------------------------------------------------------*/
413
414 /* Function: SendAwaitIrpCompletion
415  *              
416  *  Parameters:
417  *
418  *  Description:
419  *              IRP completion routine 
420  *
421  *  Returns:
422  *              pointer to the entry on SUCCESS
423  *              NULL - otherwise
424  *
425 */ 
426 static
427 NTSTATUS
428 SendAwaitIrpCompletion (
429     IN PDEVICE_OBJECT   DeviceObject,
430     IN PIRP             Irp,
431     IN PVOID            Context
432     )
433 {
434     UNREFERENCED_PARAMETER (DeviceObject);    
435     UNREFERENCED_PARAMETER (Irp);    
436     KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
437     return STATUS_MORE_PROCESSING_REQUIRED; // Keep this IRP
438 }
439
440 /*------------------------------------------------------------------------------------------------------*/
441
442 /*
443  *  Function: SendAwaitIrp
444  *
445  *  Description:
446  *              Create and send IRP stack down the stack and wait for the response (Blocking Mode)
447  *
448  *  Parameters:
449  *              pi_pDeviceExt.......... ointer to USB device extension
450  *              pi_MajorCode........... IRP major code
451  *              pi_MinorCode........... IRP minor code
452  *              pi_pBuffer............. parameter buffer
453  *              pi_nSize............... size of the buffer
454  *    po_pInfo.............. returned field Information from IoStatus block
455  *
456  *  Returns:
457  *              pointer to the entry on SUCCESS
458  *              NULL - otherwise
459  *
460 */
461 static 
462 NTSTATUS 
463 SendAwaitIrp(
464         IN  PDEVICE_OBJECT              pi_pFdo,
465         IN  PDEVICE_OBJECT              pi_pLdo,
466         IN  ULONG                               pi_MajorCode,
467         IN  ULONG                               pi_MinorCode,
468         IN      PVOID                           pi_pBuffer,
469         IN      int                                     pi_nSize,
470         OUT     PVOID           *               po_pInfo
471    )
472 /*++
473
474  Routine Description: 
475
476         Create and send IRP stack down the stack and wait for the response (
477 Blocking Mode)
478
479  Arguments: 
480  
481         pi_pFdo................ our device
482         pi_pLdo................ lower device
483         pi_MajorCode........... IRP major code
484         pi_MinorCode........... IRP minor code
485         pi_pBuffer............. parameter buffer
486         pi_nSize............... size of the buffer
487
488  Returns: 
489  
490         standard NTSTATUS return codes.
491
492  Notes:
493
494 --*/
495 { /* SendAwaitIrp */
496         // Event
497         KEVENT                          l_hEvent;
498         // Pointer to IRP
499         PIRP                            l_pIrp;
500         // Stack location
501         PIO_STACK_LOCATION      l_pStackLocation;
502         // Returned status
503         NTSTATUS                        l_Status;
504         // when to invoke
505         BOOLEAN InvokeAlways = TRUE;
506
507         // call validation
508         if(KeGetCurrentIrql() != PASSIVE_LEVEL)
509                 return STATUS_SUCCESS;
510
511         // create event
512         KeInitializeEvent(&l_hEvent, NotificationEvent, FALSE);
513
514         // build IRP request to USBD driver
515         l_pIrp = IoAllocateIrp( pi_pFdo->StackSize, FALSE );
516
517         // validate request
518         if (!l_pIrp)
519         {
520             //MdKdPrint( DBGLVL_MAXIMUM, ("(SendAwaitIrp) Unable to allocate IRP !\n"));
521                 return STATUS_INSUFFICIENT_RESOURCES;
522         }
523
524         // fill IRP
525         l_pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
526
527         // set completion routine
528     IoSetCompletionRoutine(l_pIrp,SendAwaitIrpCompletion, &l_hEvent, InvokeAlways, InvokeAlways, InvokeAlways);
529
530         // fill stack location
531     l_pStackLocation = IoGetNextIrpStackLocation(l_pIrp);
532     l_pStackLocation->MajorFunction= (UCHAR)pi_MajorCode;
533     l_pStackLocation->MinorFunction= (UCHAR)pi_MinorCode;
534         RtlCopyMemory( &l_pStackLocation->Parameters, pi_pBuffer, pi_nSize );
535
536         // Call lower driver perform request
537         l_Status = IoCallDriver( pi_pLdo, l_pIrp ); 
538
539         // if the request not performed --> wait
540         if (l_Status == STATUS_PENDING)
541         {
542                 // Wait until the IRP  will be complete
543                 KeWaitForSingleObject(
544                         &l_hEvent,                                                              // event to wait for
545                         Executive,                                                              // thread type (to wait into its context)
546                         KernelMode,                                                     // mode of work
547                         FALSE,                                                                  // alertable
548                         NULL                                                                    // timeout
549                 );
550                 l_Status = l_pIrp->IoStatus.Status;
551         }
552
553         if (po_pInfo)
554                 *po_pInfo = (PVOID)l_pIrp->IoStatus.Information;
555
556     IoFreeIrp(l_pIrp);
557         return l_Status;
558
559 } /* SendAwaitIrp */
560
561 /*------------------------------------------------------------------------------------------------------*/
562
563 /*
564  * Function: FindBridgeIf
565  *
566  * Parameters:
567  *              IN              pi_ext                          - device extension
568  *              OUT     pi_pInterface   - bus interface to work with the bridge
569  * 
570  * Returns:
571  *              FALSE   - the bridge was not found
572  *      TRUE    - a device was found;  *po_pPdo contains its PDO
573  *
574  * Description:
575  *              The function finds PDO of the bridge by HCA's bus number
576  *                      
577  */
578 int
579 FindBridgeIf(
580         IN hca_dev_ext_t                *pi_ext,
581         IN      PBUS_INTERFACE_STANDARD pi_pInterface
582         )
583 {
584         NTSTATUS rc;
585         IO_STACK_LOCATION l_Iosl;
586         PDEVICE_RELATIONS l_pDr;
587         PDEVICE_OBJECT                  l_pPdo;
588         ULONG l_DevFunc, l_Bus;
589         // parameter buffer for the request
590         IO_STACK_LOCATION l_Stack;
591
592         // find bridge location
593         if (!PciFindBridgeByBus( pi_ext->bus_number,  &l_Bus, &l_DevFunc ))
594                 return FALSE;
595         
596         // find PDO of our bus driver (bypassing possible low filter drivers)
597         RtlZeroMemory( &l_Iosl, sizeof(l_Iosl) );
598         l_Iosl.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
599         rc = SendAwaitIrp(
600                 pi_ext->cl_ext.p_self_do,
601                 pi_ext->cl_ext.p_next_do,
602                 IRP_MJ_PNP,
603                 IRP_MN_QUERY_DEVICE_RELATIONS,
604                 &l_Iosl.Parameters,
605                 sizeof(l_Iosl.Parameters.QueryDeviceRelations),
606                 &l_pDr
607                  );
608         
609         if (!NT_SUCCESS (rc)) {
610                 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_SHIM ,("IRP_MN_QUERY_DEVICE_RELATIONS failed (%#x);: Fdo %p, Ldo %p \n",
611                         rc, pi_ext->cl_ext.p_self_do, pi_ext->cl_ext.p_next_do ));
612                 return FALSE;
613         }
614                 
615         HCA_PRINT(TRACE_LEVEL_INFORMATION ,HCA_DBG_SHIM ,("IRP_MN_QUERY_DEVICE_RELATIONS for Fdo %p, Ldo %p: num_of_PDOs %d, PDO %p \n",
616                 pi_ext->cl_ext.p_self_do, pi_ext->cl_ext.p_next_do, l_pDr->Count, l_pDr->Objects[0] ));
617         
618         /* get the PDO of Bridge */
619         if (!PciFindPdoByPdoAndLocation( l_pDr->Objects[0], 
620                 l_Bus, l_DevFunc, &l_pPdo )) {
621                 HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM  ,("Not found bridge's (bus %d, dev/func %x. pdo %p) PDO - can't restore the PCI header \n",
622                                 l_Bus, l_DevFunc, l_pDr->Objects[0] ));
623                 return FALSE;
624         } 
625         HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_SHIM ,("Found bridge's PDO %p (bus %d, dev/func %x. pdo %p) \n",
626                 l_pPdo, l_Bus, l_DevFunc, l_pDr->Objects[0] ));
627                 
628         // clean interface data
629         RtlZeroMemory( (PCHAR)pi_pInterface, sizeof(BUS_INTERFACE_STANDARD) );
630         
631         // fill request parameters
632         l_Stack.Parameters.QueryInterface.InterfaceType                 = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;
633         l_Stack.Parameters.QueryInterface.Size                                  = sizeof(BUS_INTERFACE_STANDARD);
634         l_Stack.Parameters.QueryInterface.Version                               = 1;
635         l_Stack.Parameters.QueryInterface.Interface                     = (PINTERFACE)pi_pInterface;
636         l_Stack.Parameters.QueryInterface.InterfaceSpecificData = NULL;
637         
638         rc =SendAwaitIrp( pi_ext->cl_ext.p_self_do, l_pPdo, IRP_MJ_PNP, 
639                 IRP_MN_QUERY_INTERFACE, &l_Stack.Parameters, sizeof(l_Stack.Parameters), NULL);
640         if (!NT_SUCCESS (rc)) 
641                 return FALSE;
642
643         return TRUE;
644 }
645
646
647 /*----------------------------------------------------------------*/
648
649