1e04bd198de8f8814688836ef4d8cf750ac93e91
[mirror/winof/.git] / hw / mt23108 / vapi / mlxsys / os_dep / win / tdriver / MdPnp.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 2004-2005 Mellanox Technologies Ltd.  All rights reserved.\r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 \r
34 #include "MdGen.h"\r
35 #include <initguid.h>\r
36 #include "MdCard.h"\r
37 #include "mosal_util.h"\r
38 \r
39 static int IB_MGT_started = 0;\r
40 extern NTSTATUS MdMosalHelper( \r
41     IN PMD_DEV_CONTEXT_T        pi_pMdDevContext,\r
42     IN int cmd\r
43 );\r
44 \r
45 int IsIbMgtOn() { return (IB_MGT_started>0) ? 1 : 0; }\r
46 /*------------------------------------------------------------------------------------------------------*/\r
47 \r
48 NTSTATUS\r
49 MdProcessPnPIrp(\r
50     IN PDEVICE_OBJECT pi_pFdo,\r
51     IN PIRP           pi_pIrp\r
52     )\r
53 /*++\r
54 \r
55 Routine Description:\r
56 \r
57     Dispatch table routine for IRP_MJ_PNP.\r
58     Process the Plug and Play IRPs sent to this device.\r
59 \r
60 Arguments:\r
61 \r
62     pi_pFdo - pointer to our FDO (Functional Device Object)\r
63 \r
64     pi_pIrp          - pointer to an I/O Request Packet\r
65 \r
66 Return Value:\r
67 \r
68     NT status code\r
69 \r
70 --*/\r
71 {\r
72 \r
73     PIO_STACK_LOCATION          l_pIrpStack;\r
74     PMD_DEV_CONTEXT_T           l_pMdDevContext;\r
75     NTSTATUS                            l_Status = STATUS_SUCCESS;\r
76     NTSTATUS                            l_WaitStatus;\r
77     PDEVICE_OBJECT                      l_pLdo;\r
78     KEVENT                                      startDeviceEvent;\r
79 \r
80 \r
81     //\r
82     // Get a pointer to the current location in the Irp. This is where\r
83     //     the function codes and parameters are located.\r
84     //\r
85     l_pIrpStack = IoGetCurrentIrpStackLocation (pi_pIrp);\r
86 \r
87     //\r
88     // Get a pointer to the device extension\r
89     //\r
90 \r
91     l_pMdDevContext                     = (PMD_DEV_CONTEXT_T)pi_pFdo->DeviceExtension;\r
92     l_pLdo      = l_pMdDevContext->m_pLdo;\r
93 \r
94     MdKdPrint( DBGLVL_MEDIUM, ( "enter MdProcessPnPIrp() IRP_MJ_PNP, minor %s\n",\r
95         MdStringForPnpMnFunc( l_pIrpStack->MinorFunction ) ));\r
96 \r
97         // inc the FDO device extension's pending IO count for this Irp\r
98     MdIncrementIoCount(l_pMdDevContext);\r
99 \r
100     MDASSERT( IRP_MJ_PNP == l_pIrpStack->MajorFunction );\r
101 \r
102     switch (l_pIrpStack->MinorFunction) {\r
103     case IRP_MN_START_DEVICE:\r
104 \r
105         // The PnP Manager sends this IRP after it has assigned resources,\r
106         // if any, to the device. The device may have been recently enumerated\r
107         // and is being started for the first time, or the device may be\r
108         // restarting after being stopped for resource reconfiguration.\r
109 \r
110         // Initialize an event we can wait on for the PDO to be done with this irp\r
111         KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);\r
112         IoCopyCurrentIrpStackLocationToNext(pi_pIrp);\r
113 \r
114         // Set a completion routine so it can signal our event when\r
115         //  the PDO is done with the Irp\r
116         IoSetCompletionRoutine(pi_pIrp,\r
117                         MdIrpCompletionRoutine,\r
118                         &startDeviceEvent,  // pass the event to the completion routine as the Context\r
119                         TRUE,    // invoke on success\r
120                         TRUE,    // invoke on error\r
121                         TRUE);   // invoke on cancellation\r
122 \r
123         // let the PDO process the IRP\r
124         l_Status = IoCallDriver(l_pLdo,\r
125                                 pi_pIrp);\r
126 \r
127         // if PDO is not done yet, wait for the event to be set in our completion routine\r
128         if (l_Status == STATUS_PENDING) {\r
129              // wait for irp to complete\r
130 \r
131             l_WaitStatus = KeWaitForSingleObject(\r
132                 &startDeviceEvent,\r
133                 Suspended,\r
134                 KernelMode,\r
135                 FALSE,\r
136                 NULL);\r
137 \r
138             l_Status = pi_pIrp->IoStatus.Status;\r
139         }\r
140 \r
141         if (NT_SUCCESS(l_Status)) {\r
142 \r
143             // Now we're ready to do our own startup processing.\r
144             // USB client drivers such as us set up URBs (USB Request Packets) to send requests\r
145             // to the host controller driver (HCD). The URB structure defines a format for all\r
146             // possible commands that can be sent to a USB device.\r
147             // Here, we request the device descriptor and store it,\r
148             // and configure the device.\r
149             l_Status = MdStartDevice(pi_pFdo, pi_pIrp);\r
150             pi_pIrp->IoStatus.Status = l_Status;\r
151         }\r
152 \r
153         IoCompleteRequest (pi_pIrp,\r
154                            IO_NO_INCREMENT\r
155                            );\r
156 \r
157         MdDecrementIoCount(l_pMdDevContext);\r
158         return l_Status;  // end, case IRP_MN_START_DEVICE\r
159 \r
160     case IRP_MN_QUERY_STOP_DEVICE:\r
161 \r
162         // The IRP_MN_QUERY_STOP_DEVICE/IRP_MN_STOP_DEVICE sequence only occurs\r
163         // during "polite" shutdowns, such as the user explicitily requesting the\r
164         // service be stopped in, or requesting unplug from the Pnp tray icon.\r
165         // This sequence is NOT received during "impolite" shutdowns,\r
166         // such as someone suddenly yanking the USB cord or otherwise\r
167         // unexpectedly disabling/resetting the device.\r
168 \r
169         // If a driver sets STATUS_SUCCESS for this IRP,\r
170         // the driver must not start any operations on the device that\r
171         // would prevent that driver from successfully completing an IRP_MN_STOP_DEVICE\r
172         // for the device.\r
173         // For mass storage devices such as disk drives, while the device is in the\r
174         // stop-pending state,the driver holds IRPs that require access to the device,\r
175         // but for most USB devices, there is no 'persistent storage', so we will just\r
176         // refuse any more IO until restarted or the stop is cancelled\r
177 \r
178         // If a driver in the device stack determines that the device cannot be\r
179         // stopped for resource reconfiguration, the driver is not required to pass\r
180         // the IRP down the device stack. If a query-stop IRP fails,\r
181         // the PnP Manager sends an IRP_MN_CANCEL_STOP_DEVICE to the device stack,\r
182         // notifying the drivers for the device that the query has been cancelled\r
183         // and that the device will not be stopped.\r
184 \r
185 \r
186         // It is possible to receive this irp when the device has not been started\r
187         //  ( as on a boot device )\r
188         if (!l_pMdDevContext->m_DeviceStarted) { // if get when never started, just pass on\r
189             MdKdPrint( DBGLVL_MEDIUM,("MdProcessPnPIrp() IRP_MN_QUERY_STOP_DEVICE when device not started\n"));\r
190             IoSkipCurrentIrpStackLocation (pi_pIrp);\r
191             l_Status = IoCallDriver (l_pMdDevContext->m_pLdo, pi_pIrp);\r
192             MdDecrementIoCount(l_pMdDevContext);\r
193 \r
194             return l_Status;\r
195         }\r
196 \r
197 \r
198         // fail the request if we have any IRPS in progress\r
199         if( g_pDrvContext->m_pCtlDevContext->m_nPendingIoCnt > 1) {\r
200             l_Status = STATUS_UNSUCCESSFUL;\r
201         }\r
202         else {\r
203                         // We'll not veto it; pass it on and flag that stop was requested.\r
204                         // Once m_StopDeviceRequested is set no new IOCTL or read/write irps will be passed\r
205                         // down the stack to lower drivers; all will be quickly failed\r
206              l_pMdDevContext->m_StopDeviceRequested = TRUE;\r
207              pi_pIrp->IoStatus.Status = STATUS_SUCCESS;\r
208         }\r
209 \r
210         break; // end, case IRP_MN_QUERY_STOP_DEVICE\r
211 \r
212     case IRP_MN_CANCEL_STOP_DEVICE:\r
213 \r
214                 // The PnP Manager uses this IRP to inform the drivers for a device\r
215                 // that the device will not be stopped for resource reconfiguration.\r
216                 // This should only be received after a successful IRP_MN_QUERY_STOP_DEVICE.\r
217 \r
218 \r
219         // It is possible to receive this irp when the device has not been started\r
220         if (!l_pMdDevContext->m_DeviceStarted) { // if get when never started, just pass on\r
221             MdKdPrint( DBGLVL_MEDIUM,("MdProcessPnPIrp() IRP_MN_CANCEL_STOP_DEVICE when device not started\n"));\r
222             IoSkipCurrentIrpStackLocation (pi_pIrp);\r
223             l_Status = IoCallDriver (l_pMdDevContext->m_pLdo, pi_pIrp);\r
224             MdDecrementIoCount(l_pMdDevContext);\r
225             return l_Status;\r
226         }\r
227 \r
228                 // Reset this flag so new IOCTL and IO Irp processing will be re-enabled\r
229         l_pMdDevContext->m_StopDeviceRequested = FALSE;\r
230         pi_pIrp->IoStatus.Status = STATUS_SUCCESS;\r
231         break; // end, case IRP_MN_CANCEL_STOP_DEVICE\r
232 \r
233     case IRP_MN_STOP_DEVICE:\r
234 \r
235         // The PnP Manager sends this IRP to stop a device so it can reconfigure\r
236         // its hardware resources. The PnP Manager only sends this IRP if a prior\r
237         // IRP_MN_QUERY_STOP_DEVICE completed successfully.\r
238 \r
239 \r
240         // Cancel any pending io requests.  (there shouldn't be any)\r
241         MdCancelPendingIo( pi_pFdo );\r
242         //\r
243         // stop the device\r
244         //\r
245         l_Status = MdStopDevice(pi_pFdo);\r
246         pi_pIrp->IoStatus.Status = l_Status;\r
247 \r
248         break; // end, case IRP_MN_STOP_DEVICE\r
249 \r
250 \r
251 \r
252     case IRP_MN_QUERY_REMOVE_DEVICE:\r
253 \r
254         //  In response to this IRP, drivers indicate whether the device can be\r
255         //  removed without disrupting the system.\r
256         //  If a driver determines it is safe to remove the device,\r
257         //  the driver completes any outstanding I/O requests, arranges to hold any subsequent\r
258         //  read/write requests, and sets pi_pIrp->IoStatus.Status to STATUS_SUCCESS. Function\r
259         //  and filter drivers then pass the IRP to the next-lower driver in the device stack.\r
260         //  The underlying bus driver calls IoCompleteRequest.\r
261 \r
262         //  If a driver sets STATUS_SUCCESS for this IRP, the driver must not start any\r
263         //  operations on the device that would prevent that driver from successfully completing\r
264         //  an IRP_MN_REMOVE_DEVICE for the device. If a driver in the device stack determines\r
265         //  that the device cannot be removed, the driver is not required to pass the\r
266         //  query-remove IRP down the device stack. If a query-remove IRP fails, the PnP Manager\r
267         //  sends an IRP_MN_CANCEL_REMOVE_DEVICE to the device stack, notifying the drivers for\r
268         //  the device that the query has been cancelled and that the device will not be removed.\r
269 \r
270         // It is possible to receive this irp when the device has not been started\r
271         if (!l_pMdDevContext->m_DeviceStarted) { // if get when never started, just pass on\r
272             MdKdPrint( DBGLVL_MEDIUM,("MdProcessPnPIrp() IRP_MN_QUERY_STOP_DEVICE when device not started\n"));\r
273             IoSkipCurrentIrpStackLocation (pi_pIrp);\r
274             l_Status = IoCallDriver (l_pMdDevContext->m_pLdo, pi_pIrp);\r
275             MdDecrementIoCount(l_pMdDevContext);\r
276 \r
277             return l_Status;\r
278         }\r
279 \r
280         // Once m_RemoveDeviceRequested is set no new IOCTL or read/write irps will be passed\r
281         // down the stack to lower drivers; all will be quickly failed\r
282        l_pMdDevContext->m_RemoveDeviceRequested = TRUE;\r
283 \r
284         // Wait for any io request pending in our driver to\r
285         // complete before returning success.\r
286         // This  event is set when l_pMdDevContext->PendingIoCount goes to 1\r
287 #if 0\r
288         l_WaitStatus = KeWaitForSingleObject(\r
289                     &l_pMdDevContext->m_NoPendingIoEvent,\r
290                     Suspended,\r
291                     KernelMode,\r
292                     FALSE,\r
293                     NULL);\r
294 \r
295 #else\r
296                 { // wait for all applications IRPs to all cards and all PnP and Power IRPs to this card to be finished \r
297                         PVOID   l_Objects[] = { &g_pDrvContext->m_pCtlDevContext->m_NoPendingIoEvent, &l_pMdDevContext->m_NoPendingIoEvent };\r
298 \r
299                         // Leo: match the inc at the begining of the dispatch routine to get signal from MdDecrementIoCount()\r
300             MdDecrementIoCount(l_pMdDevContext);\r
301 \r
302                         // wait\r
303                         l_WaitStatus = KeWaitForMultipleObjects( 2, l_Objects, WaitAll, Executive, KernelMode, FALSE, NULL, NULL );\r
304 \r
305                         // Leo: return the inc at the begining of the dispatch routine\r
306             MdIncrementIoCount(l_pMdDevContext);\r
307                 }\r
308 #endif\r
309 \r
310         pi_pIrp->IoStatus.Status = STATUS_SUCCESS;\r
311         break; // end, case IRP_MN_QUERY_REMOVE_DEVICE\r
312 \r
313     case IRP_MN_CANCEL_REMOVE_DEVICE:\r
314 \r
315                 // The PnP Manager uses this IRP to inform the drivers\r
316                 // for a device that the device will not be removed.\r
317                 // It is sent only after a successful IRP_MN_QUERY_REMOVE_DEVICE.\r
318 \r
319         if (!l_pMdDevContext->m_DeviceStarted) { // if get when never started, just pass on\r
320             MdKdPrint( DBGLVL_MEDIUM,("MdProcessPnPIrp() IRP_MN_CANCEL_REMOVE_DEVICE when device not started\n"));\r
321             IoSkipCurrentIrpStackLocation (pi_pIrp);\r
322             l_Status = IoCallDriver (l_pMdDevContext->m_pLdo, pi_pIrp);\r
323             MdDecrementIoCount(l_pMdDevContext);\r
324             return l_Status;\r
325         }\r
326 \r
327                 // Reset this flag so new IOCTL and IO Irp processing will be re-enabled\r
328         l_pMdDevContext->m_RemoveDeviceRequested = FALSE;\r
329         pi_pIrp->IoStatus.Status = STATUS_SUCCESS;\r
330 \r
331         break; // end, case IRP_MN_CANCEL_REMOVE_DEVICE\r
332 \r
333     case IRP_MN_SURPRISE_REMOVAL:\r
334         MdKdPrint( DBGLVL_MEDIUM,("MdProcessPnPIrp() IRP_MN_SURPRISE_REMOVAL\n"));\r
335 \r
336         // For a surprise-style device removal ( i.e. sudden cord yank ),\r
337         // the physical device has already been removed so the PnP Manager sends\r
338         // the remove IRP without a prior query-remove. A device can be in any state\r
339         // when it receives a remove IRP as a result of a surprise-style removal.\r
340 \r
341         // match the inc at the begining of the dispatch routine\r
342         MdDecrementIoCount(l_pMdDevContext);\r
343 \r
344         //\r
345         // Once m_DeviceRemoved is set no new IOCTL or read/write irps will be passed\r
346         // down the stack to lower drivers; all will be quickly failed\r
347         //\r
348         l_pMdDevContext->m_DeviceRemoved = TRUE;\r
349 \r
350         // Cancel any pending io requests; we may not have gotten a query first!\r
351         MdCancelPendingIo( pi_pFdo );\r
352 \r
353         // Cancels all in progress requests.\r
354         MdAbortInPgsReqs( pi_pFdo );\r
355 \r
356         //\r
357         // Mark this handled\r
358         //\r
359         pi_pIrp->IoStatus.Status = STATUS_SUCCESS;\r
360 \r
361         // We don't explicitly wait for the below driver to complete, but just make\r
362         // the call and go on, finishing cleanup\r
363         IoCopyCurrentIrpStackLocationToNext(pi_pIrp);\r
364 \r
365         l_Status = IoCallDriver(l_pLdo,\r
366                                 pi_pIrp);\r
367 \r
368         return l_Status;\r
369 \r
370     case IRP_MN_REMOVE_DEVICE:\r
371 \r
372 \r
373         // The PnP Manager uses this IRP to direct drivers to remove a device.\r
374         // For a "polite" device removal, the PnP Manager sends an\r
375         // IRP_MN_QUERY_REMOVE_DEVICE prior to the remove IRP. In this case,\r
376         // the device is in the remove-pending state when the remove IRP arrives.\r
377         // For a surprise-style device removal ( i.e. sudden cord yank ),\r
378         // the physical device has already been removed and the PnP Manager may not\r
379         //  have sent IRP_MN_SURPRISE_REMOVAL. A device can be in any state\r
380         // when it receives a remove IRP as a result of a surprise-style removal.\r
381 \r
382         // match the inc at the begining of the dispatch routine\r
383         MdDecrementIoCount(l_pMdDevContext);\r
384 \r
385         //\r
386         // Once m_DeviceRemoved is set no new IOCTL or read/write irps will be passed\r
387         // down the stack to lower drivers; all will be quickly failed\r
388         //\r
389         l_pMdDevContext->m_DeviceRemoved = TRUE;\r
390 \r
391         // Cancel any pending io requests; we may not have gotten a query first!\r
392         MdCancelPendingIo( pi_pFdo );\r
393 \r
394         // Cancels all in progress requests.\r
395         MdAbortInPgsReqs( pi_pFdo );\r
396 \r
397         //\r
398         // Delete MDDK device\r
399         //\r
400         MdStopDevice(pi_pFdo);\r
401 \r
402         // We don't explicitly wait for the below driver to complete, but just make\r
403         // the call and go on, finishing cleanup\r
404         IoCopyCurrentIrpStackLocationToNext(pi_pIrp);\r
405 \r
406         l_Status = IoCallDriver(l_pLdo,\r
407                                 pi_pIrp);\r
408         //\r
409         // The final decrement to device extension PendingIoCount == 0\r
410                 // will set l_pMdDevContext->m_RemoveEvent, enabling device removal.\r
411                 // If there is no pending IO at this point, the below decrement will be it.\r
412         //\r
413         MdDecrementIoCount(l_pMdDevContext);\r
414 \r
415         // wait for any io request pending in our driver to\r
416         // complete for finishing the remove\r
417 \r
418 #if 0\r
419         KeWaitForSingleObject(\r
420                     &l_pMdDevContext->m_RemoveEvent,\r
421                     Suspended,\r
422                     KernelMode,\r
423                     FALSE,\r
424                     NULL);\r
425 \r
426 #else\r
427                 { // wait for all applications IRPs to all cards and all PnP and Power IRPs to this card to be finished \r
428                         PVOID   l_Objects[] = { &g_pDrvContext->m_pCtlDevContext->m_NoPendingIoEvent, &l_pMdDevContext->m_RemoveEvent };\r
429 \r
430                         KeWaitForMultipleObjects( 2, l_Objects, WaitAll, Executive, KernelMode, FALSE, NULL, NULL );\r
431                 }\r
432 #endif\r
433 \r
434         //\r
435         // Detach the device\r
436         //\r
437         MdKdPrint( DBGLVL_DEFAULT,("MdProcessPnPIrp() Detaching from %08X\n",\r
438                          l_pMdDevContext->m_pLdo));\r
439 \r
440         IoDetachDevice(l_pMdDevContext->m_pLdo);\r
441 \r
442         //\r
443         // Delete the link and FDO we created\r
444         //\r
445         MdRemoveDevice(pi_pFdo);\r
446 \r
447                 //\r
448                 // if it was the last device - remove also the control device\r
449                 //\r
450                 if (g_pDrvContext->m_uDevNo == 1 )\r
451                 { /* it was the last IB device */\r
452                         \r
453                         PMD_DEV_CONTEXT_T l_pCtlDevContext = g_pDrvContext->m_pCtlDevContext;\r
454 \r
455            KMUTEX_ACQ(&l_pCtlDevContext->m_Mutex);\r
456                         if (l_pCtlDevContext->m_nOpenCount > 0)\r
457                         { /* there is open handles - postpone removing */\r
458 \r
459                                 // mark delete pending\r
460                                 l_pCtlDevContext->m_fDeletePending = TRUE;\r
461               KMUTEX_REL(&l_pCtlDevContext->m_Mutex);\r
462 \r
463                                 // wait for handles to be closed\r
464                                 KeWaitForSingleObject(\r
465                                                         &l_pCtlDevContext->m_RemoveEvent,\r
466                                                         Suspended,\r
467                                                         KernelMode,\r
468                                                         FALSE,\r
469                                                         NULL);\r
470 \r
471                         } /* there is open handles - postpone removing */\r
472                         else\r
473               KMUTEX_REL(&l_pCtlDevContext->m_Mutex);\r
474 \r
475                         // remove control device\r
476                         if (l_pCtlDevContext != NULL)\r
477                                 MdDevDeInit( l_pCtlDevContext );\r
478                         g_pDrvContext->m_pCtlDevContext = NULL;\r
479 \r
480 \r
481                 } /* it was the last IB device */\r
482 \r
483         return l_Status; // end, case IRP_MN_REMOVE_DEVICE\r
484 \r
485         case IRP_MN_QUERY_INTERFACE:\r
486                 // Handle the query interface call to retrieve the HH handle for\r
487                 // our HCA instance.\r
488                 if( IsEqualGUID( l_pIrpStack->Parameters.QueryInterface.InterfaceType,\r
489                         &GUID_MD_INTERFACE ) )\r
490                 {\r
491                         if( l_pIrpStack->Parameters.QueryInterface.InterfaceSpecificData )\r
492                         {\r
493                                 // Our interface.  Return the HH HCA handle in \r
494                                 // the "InterfaceSpecificData" member.\r
495                                 *(HH_hca_hndl_t*)l_pIrpStack->Parameters.QueryInterface.\r
496                                         InterfaceSpecificData = l_pMdDevContext->m_hHhHca;\r
497                     pi_pIrp->IoStatus.Status = STATUS_SUCCESS;\r
498                                 l_Status = STATUS_SUCCESS;\r
499                                 break;\r
500                         }\r
501                 }\r
502                 // Fall through.\r
503                 \r
504     default:\r
505 \r
506         //\r
507         // In this case we must not touch the status. As l_Status is\r
508         // STATUS_SUCCESS, we will skip the failure case and pass down the IRP\r
509         // untouched.\r
510         //\r
511         MdKdPrint( DBGLVL_MEDIUM,("MdProcessPnPIrp() Minor PnP IOCTL 0x%x not handled\n", l_pIrpStack->MinorFunction));\r
512     } /* case MinorFunction  */\r
513 \r
514 \r
515     if (!NT_SUCCESS(l_Status)) {\r
516 \r
517         // if anything went wrong, return failure  without passing Irp down\r
518         pi_pIrp->IoStatus.Status = l_Status;\r
519         IoCompleteRequest (pi_pIrp,\r
520                                            IO_NO_INCREMENT\r
521                                            );\r
522 \r
523         MdDecrementIoCount(l_pMdDevContext);\r
524 \r
525         MdKdPrint( DBGLVL_MINIMUM,("MdProcessPnPIrp() Exit MdProcessPnPIrp FAILURE %x\n", l_Status));\r
526         return l_Status;\r
527     }\r
528 \r
529     IoCopyCurrentIrpStackLocationToNext(pi_pIrp);\r
530 \r
531     //\r
532     // All PNP_POWER messages get passed to the m_pLdo\r
533     // we were given in PnPAddDevice\r
534     //\r
535 \r
536     MdKdPrint( DBGLVL_MAXIMUM,("MdProcessPnPIrp() Passing PnP Irp down, status = %x\n", l_Status));\r
537 \r
538     l_Status = IoCallDriver(l_pLdo,\r
539                             pi_pIrp);\r
540 \r
541     MdDecrementIoCount(l_pMdDevContext);\r
542 \r
543     MdKdPrint( DBGLVL_MAXIMUM,("MdProcessPnPIrp() Exit MdProcessPnPIrp %x\n", l_Status));\r
544 \r
545     return l_Status;\r
546 }\r
547 \r
548 /*------------------------------------------------------------------------------------------------------*/\r
549 \r
550 NTSTATUS\r
551 MdPnPAddDevice(\r
552     IN PDRIVER_OBJECT pi_pDrvObject,\r
553     IN PDEVICE_OBJECT pi_pPdo\r
554     )\r
555 /*++\r
556 \r
557 Routine Description:\r
558 \r
559     This routine is called to create and initialize our Functional Device Object (FDO).\r
560 \r
561 Arguments:\r
562 \r
563     pi_pDrvObject       - pointer to the driver object for this instance of BulkUsb\r
564     pi_pPdo                     - pointer to a device object created by the bus\r
565 \r
566 Return Value:\r
567 \r
568     STATUS_SUCCESS if successful,\r
569     STATUS_UNSUCCESSFUL otherwise\r
570 \r
571 --*/\r
572 {\r
573         /* status */\r
574     NTSTATUS                l_Status                    = STATUS_SUCCESS;\r
575         /* device object we create for the added device */\r
576     PDEVICE_OBJECT          l_pFdo                              = NULL;\r
577         /* our context to this device */\r
578     PMD_DEV_CONTEXT_T       l_pMdDevContext;\r
579         /* index */\r
580     ULONG                                       l_nIx;\r
581         /* The device Win32 name as unicode string */\r
582         UNICODE_STRING                  l_usNtDeviceName = { 0 , 0 , NULL };\r
583         /* The Dos device name as unicde string */\r
584         UNICODE_STRING                  l_usDosDeviceName = { 0 , 0 , NULL };\r
585         // size of the returned DevId string\r
586         ULONG                                   l_DevIdWstrSize;\r
587         // size of the returned DevId string\r
588         ULONG                                   l_DevIdWstrSizeReqd;\r
589         /* buffer for DevId string */\r
590         WCHAR                                   l_DevIdWstr[5];\r
591         /* pointer to buffer for all Hardware ID strings */\r
592         WCHAR   *                               l_pDevIdWstr;\r
593         /* Device BD id */\r
594         int                                             l_DevIx;\r
595         /* Logging */\r
596         char *                                  l_pReason = "Unknown";\r
597         char                                    l_Buf[120];\r
598         \r
599         /* debug print */\r
600     MdKdPrint( DBGLVL_DEFAULT,("(MdPnPAddDevice) enter \n"));\r
601 \r
602         do\r
603         { /* find out the type of the device */\r
604 \r
605 \r
606                 //\r
607                 // get the Device ID \r
608                 //\r
609                 l_DevIdWstrSize = 512;\r
610                 while (1)\r
611                 { /* get device ID */ \r
612                 \r
613                         /* allocate buffer */\r
614                         l_pDevIdWstr = (WCHAR   *)MdExAllocatePool( PagedPool , l_DevIdWstrSize);\r
615                         if (l_pDevIdWstr == NULL)\r
616                         { /* error */\r
617                         MdKdPrint( DBGLVL_LOW,("(MdPnPAddDevice) MdExAllocatePool failed req-d size %d \n", \r
618                                 l_DevIdWstrSize  ));\r
619                                 sprintf( l_Buf, "MdExAllocatePool failed req-d size %d \n", l_DevIdWstrSize);\r
620                         l_pReason = l_Buf;\r
621                             l_Status = STATUS_INSUFFICIENT_RESOURCES;\r
622                             goto err;\r
623                         } /* error */\r
624                         \r
625                         /* Get the device Hardware ID */\r
626                         l_Status = IoGetDeviceProperty(pi_pPdo, DevicePropertyHardwareID , \r
627                                 l_DevIdWstrSize, (void*)l_pDevIdWstr, &l_DevIdWstrSizeReqd);\r
628 \r
629                         if (NT_SUCCESS(l_Status))  \r
630                         { /* suceeded - get Device ID */\r
631 \r
632                                 /* print the first string */\r
633                             MdKdPrint( DBGLVL_LOW,("(MdPnPAddDevice) first Device HW ID %ws, total size %d \n",\r
634                                 l_pDevIdWstr, l_DevIdWstrSizeReqd));\r
635                             \r
636                                 /* extract DevId */\r
637                                 memcpy( l_DevIdWstr, l_pDevIdWstr + 17, 8 );\r
638                                 l_DevIdWstr[4] = 0;\r
639 \r
640                                 /* free all the buffer */\r
641                                 MdExFreePool(l_pDevIdWstr);\r
642                                 break;\r
643                                 \r
644                         } /* suceeded - get Device ID */\r
645                         else\r
646                         if (l_Status == STATUS_BUFFER_TOO_SMALL)\r
647                         { /* prepare for reallocate */\r
648 \r
649                                 MdExFreePool(l_pDevIdWstr);\r
650                                 l_DevIdWstrSize = l_DevIdWstrSizeReqd;\r
651                                 continue;\r
652                                 \r
653                         } /* prepare for reallocate */\r
654                         else\r
655                         { /* error */\r
656                         \r
657                             MdKdPrint( DBGLVL_LOW,("(MdPnPAddDevice) getting of DevicePropertyHardwareID failed (0x%x): ID %ws, size %d, req-d size %d \n", \r
658                                     l_Status, sizeof(l_DevIdWstr), l_DevIdWstrSize  ));\r
659                                 sprintf( l_Buf, "Getting of DevicePropertyHardwareID failed (0x%x): ID %ws, size %d, req-d size %d \n", \r
660                                     l_Status, l_pDevIdWstr, sizeof(l_DevIdWstr), l_DevIdWstrSize);\r
661                         l_pReason = l_Buf;\r
662                             goto err;\r
663                             \r
664                         } /* error */\r
665                         \r
666                 } /* get device ID */ \r
667 \r
668                 /* find TAVOR device */\r
669                 for (l_DevIx=0; l_DevIx<(int)MD_DEV_IX_LAST; l_DevIx++) {\r
670                 \r
671                         if (NULL != wcsstr( l_DevIdWstr, g_DevParams[l_DevIx].m_DevIdWstr ))\r
672                         { \r
673                             MdKdPrint( DBGLVL_LOW,("(MdPnPAddDevice) Found device with ID %ws ! \n", \r
674                                 g_DevParams[l_DevIx].m_DevIdWstr));\r
675                             break;\r
676                         }\r
677                 }                   \r
678 \r
679                 /* get at the device */\r
680                 if (l_DevIx >= MD_DEV_IX_LAST) {\r
681                     MdKdPrint( DBGLVL_LOW,("(MdPnPAddDevice) Failed to identify device with ID %ws ! \n", l_DevIdWstr));\r
682                         sprintf( l_Buf, "Failed to identify device with ID %ws ! \n", l_DevIdWstr);\r
683                 l_pReason = l_Buf;\r
684                     l_Status = STATUS_NOT_SUPPORTED;\r
685                     goto err;\r
686                 }\r
687                 \r
688         } /* find out the type of the device */\r
689         while (0);\r
690 \r
691         l_Status = CreateOneDevice( l_DevIx, &l_usNtDeviceName, &l_usDosDeviceName, &l_pMdDevContext); \r
692     if (!NT_SUCCESS(l_Status)) {\r
693                         sprintf( l_Buf, "Failed to create device '%s' ! \n", g_DevParams[l_DevIx].m_Format);\r
694                 l_pReason = l_Buf;\r
695                     goto err;\r
696         }\r
697 \r
698         // store card number\r
699         l_pMdDevContext->m_uCardNo = g_pDrvContext->m_uCardNo;\r
700         \r
701     //\r
702     // remember the Physical device Object\r
703     //\r
704     l_pMdDevContext->m_pPdo = pi_pPdo;\r
705 \r
706     //\r
707     // Attach to the PDO\r
708     //\r
709     l_pFdo = l_pMdDevContext->m_pFdo;\r
710     l_pMdDevContext->m_pLdo = IoAttachDeviceToDeviceStack(l_pFdo, pi_pPdo);\r
711 \r
712         /* open direct PCI interface */\r
713         PciIfOpen( l_pMdDevContext->m_pFdo, l_pMdDevContext->m_pLdo, &l_pMdDevContext->m_Interface );\r
714 \r
715         /* fix command register of HCA */\r
716         PciFixCmdReg( l_pMdDevContext );\r
717         \r
718         /* set PCI master bit: no need for aux drivers */\r
719         //SetPciMasterBit( l_pMdDevContext );\r
720         \r
721     // Get a copy of the physical device's capabilities into a\r
722     // DEVICE_CAPABILITIES struct in our device extension;\r
723     // We are most interested in learning which system power states\r
724     // are to be mapped to which device power states for handling\r
725     // IRP_MJ_SET_POWER Irps.\r
726     MdQueryCapabilities(l_pMdDevContext->m_pLdo, &l_pMdDevContext->m_DeviceCapabilities);\r
727 \r
728 \r
729     // We want to determine what level to auto-powerdown to; This is the lowest\r
730     //  sleeping level that is LESS than D3;\r
731     // If all are set to D3, auto powerdown/powerup will be disabled.\r
732 \r
733     l_pMdDevContext->m_PowerDownLevel = PowerDeviceUnspecified; // init to disabled\r
734 \r
735     for (l_nIx=PowerSystemSleeping1; l_nIx<= PowerSystemSleeping3; l_nIx++) \r
736         {\r
737         if ( l_pMdDevContext->m_DeviceCapabilities.DeviceState[l_nIx] < PowerDeviceD3 )\r
738                         l_pMdDevContext->m_PowerDownLevel = l_pMdDevContext->m_DeviceCapabilities.DeviceState[l_nIx];\r
739     }\r
740 \r
741 #if DBG\r
742         {\r
743                 PDEVICE_CAPABILITIES    l_pCap = &l_pMdDevContext->m_DeviceCapabilities;\r
744                 //\r
745                 // display the device  caps\r
746                 //\r
747 \r
748                 MdKdPrint( DBGLVL_MEDIUM,(" >>>>>> ---------- DeviceCaps -----------\n"));\r
749                 MdKdPrint( DBGLVL_MEDIUM,(" Version %d, Address 0x%x, UINum 0x%x, D1Lat %d, D2Lat %d, D3Lat %d\n",\r
750                         l_pCap->Version, l_pCap->Address, l_pCap->UINumber, l_pCap->D1Latency, l_pCap->D2Latency, l_pCap->D3Latency ));\r
751                 MdKdPrint( DBGLVL_MEDIUM,(" DevD1 %d, DevD2 %d, Lock %d, Eject %d, Removable %d, Dock %d\n",\r
752                         l_pCap->DeviceD1, l_pCap->DeviceD2, l_pCap->LockSupported, \r
753                         l_pCap->EjectSupported, l_pCap->Removable, l_pCap->DockDevice ));\r
754                 MdKdPrint( DBGLVL_MEDIUM,(" UniqueId %d, Silent %d, RawDevOK %d, SurpriseRmvOK %d, HwDis %d, NonDyn %d\n",\r
755                         l_pCap->UniqueID, l_pCap->SilentInstall, l_pCap->RawDeviceOK, \r
756                         l_pCap->SurpriseRemovalOK, l_pCap->HardwareDisabled, l_pCap->NonDynamic ));\r
757                 MdKdPrint( DBGLVL_MEDIUM,(" WakeD0 %d, WakeD1 %d, WakeD2 %d, WakeD3 %d WarmEject %d\n",\r
758                         l_pCap->WakeFromD0, l_pCap->WakeFromD1, l_pCap->WakeFromD2, \r
759                         l_pCap->WakeFromD3, l_pCap->WarmEjectSupported ));\r
760                 MdKdPrint( DBGLVL_MEDIUM,(" SystemWake = %s\n", MdStringForSysState( l_pCap->SystemWake ) ));\r
761                 MdKdPrint( DBGLVL_MEDIUM,(" DeviceWake = %s\n", MdStringForDevState( l_pCap->DeviceWake) ));\r
762 \r
763                 for (l_nIx=PowerSystemUnspecified; l_nIx< PowerSystemMaximum; l_nIx++) \r
764                 {\r
765 \r
766                         MdKdPrint( DBGLVL_MEDIUM,(" Device State Map: sysstate %s = devstate %s\n",\r
767                                 MdStringForSysState( l_nIx ),\r
768                                 MdStringForDevState( l_pCap->DeviceState[l_nIx] ) ));\r
769 \r
770                 }\r
771                 MdKdPrint( DBGLVL_MEDIUM,(" <<<<<<<< ---------- DeviceCaps -----------\n"));\r
772 \r
773         }\r
774 \r
775 #endif\r
776     // We keep a pending IO count ( extension->PendingIoCount )  in the device extension.\r
777     // The first increment of this count is done on adding the device.\r
778     // Subsequently, the count is incremented for each new IRP received and\r
779     // decremented when each IRP is completed or passed on.\r
780 \r
781     // Transition to 'one' therefore indicates no IO is pending and signals\r
782     // l_pMdDevContext->NoPendingIoEvent. This is needed for processing\r
783     // IRP_MN_QUERY_REMOVE_DEVICE\r
784 \r
785     // Transition to 'zero' signals an event ( l_pMdDevContext->m_RemoveEvent )\r
786     // to enable device removal. This is used in processing for IRP_MN_REMOVE_DEVICE\r
787     //\r
788     MdIncrementIoCount(l_pMdDevContext);\r
789 \r
790     if( NT_SUCCESS( l_Status ) )\r
791     {\r
792         NTSTATUS        l_ActStat;\r
793 \r
794         // try to power down device until IO actually requested\r
795         l_ActStat = MdSelfSuspendOrActivate( l_pFdo, TRUE );\r
796     }\r
797 \r
798         // init DPC object\r
799         //IoInitializeDpcRequest(l_pFdo, MdDpcForIsr); \r
800 \r
801         // unmark delete pending\r
802         if ( g_pDrvContext->m_pCtlDevContext ) \r
803         {\r
804       KMUTEX_ACQ(&g_pDrvContext->m_pCtlDevContext->m_Mutex);\r
805       g_pDrvContext->m_pCtlDevContext->m_fDeletePending = FALSE;\r
806       KMUTEX_REL(&g_pDrvContext->m_pCtlDevContext->m_Mutex);\r
807         }       \r
808 \r
809         // mark the end of device init\r
810     l_pFdo->Flags &= ~DO_DEVICE_INITIALIZING;\r
811 \r
812     MdKdPrint( DBGLVL_DEFAULT,("(MdPnPAddDevice) exit: (%x)\n", l_Status));\r
813     return l_Status;\r
814 \r
815 err:\r
816 #pragma warning( push )\r
817 #pragma warning( disable:4296 )\r
818         MdKdPrint( DBGLVL_ALWAYS ,("(MdDeviceInit) Device failed to initialize \n"));\r
819 #pragma warning( pop )\r
820 \r
821         /* Write to event log */\r
822         WriteEventLogEntry(     g_pDrvContext->m_pDrvObject, MD_EVENT_LOG_LOAD_ERROR,\r
823                         0, l_Status, 1, l_Status );\r
824         return STATUS_UNSUCCESSFUL;\r
825 }\r
826 \r
827 /*------------------------------------------------------------------------------------------------------*/\r
828 \r
829 NTSTATUS\r
830 MdStartDevice(\r
831     IN  PDEVICE_OBJECT          pi_pFdo,\r
832         IN      PIRP                            pi_pIrp\r
833     )\r
834 /*++\r
835 \r
836 Routine Description:\r
837 \r
838         Called from MdProcessPnPIrp(), the dispatch routine for IRP_MJ_PNP.\r
839         Performs:\r
840                 - re-read cards PCI configuration data and stores on the device context;\r
841                 - add device to MDDK\r
842 \r
843 Arguments:\r
844 \r
845     pi_pFdo                     - pointer to FDO\r
846         pi_pIrp                 - pointer to IRP\r
847 \r
848 Return Value:\r
849 \r
850     NT status code\r
851 \r
852 --*/\r
853 {\r
854     PMD_DEV_CONTEXT_T                   l_pMdDevContext = (PMD_DEV_CONTEXT_T)pi_pFdo->DeviceExtension;\r
855     NTSTATUS                                    l_Status;\r
856     PIO_STACK_LOCATION                  l_pIrpStack             = IoGetCurrentIrpStackLocation (pi_pIrp);\r
857         int                                                     l_nDevIx;\r
858         call_result_t                           l_MddkStatus;\r
859         MOSAL_dev_t                                     l_MosalDevParams;\r
860         /* Logging */\r
861         char *                                          l_pReason = "Unknown";\r
862         char                                            l_Buf[120];\r
863         ULONG                                   l_EventCode = MD_EVENT_LOG_LOAD_ERROR;\r
864         card_hw_props_t                         l_HwProps;\r
865 \r
866     MdKdPrint( DBGLVL_DEFAULT,("(MdStartDevice) enter \n"));\r
867 \r
868         // init PCI card resources\r
869         l_Status = MdInitPciCfgCard( l_pMdDevContext, \r
870                 l_pIrpStack->Parameters.StartDevice.AllocatedResources,\r
871                 l_pIrpStack->Parameters.StartDevice.AllocatedResourcesTranslated );\r
872 \r
873         // check the results\r
874     if (!NT_SUCCESS(l_Status)) {\r
875         l_pReason = "Read Pci Card Configuration failed";\r
876         goto err;\r
877     }\r
878 \r
879 #ifdef __i386__\r
880         /* save PCI header */\r
881         PciHdrSave( l_pMdDevContext );\r
882 \r
883         /* Reset the card */ \r
884          if (l_pMdDevContext->m_PerformReset == 1 && l_pMdDevContext->m_fMayReset) \r
885                 PciReset( l_pMdDevContext );\r
886 #endif   \r
887 \r
888         /*\r
889          * add device to MOSAL\r
890          */ \r
891 \r
892         /* fill specific params */\r
893         memset( &l_MosalDevParams, 0, sizeof(MOSAL_dev_t) );\r
894         l_MosalDevParams.irq_num        = (MOSAL_IRQ_ID_t)l_pMdDevContext->m_ulIntVector;\r
895         l_MosalDevParams.irql           = l_pMdDevContext->m_ulIntLevel;\r
896         l_MosalDevParams.affinity       = l_pMdDevContext->m_Affinity;\r
897         l_MosalDevParams.int_shared     = l_pMdDevContext->m_fIntShared;\r
898         l_MosalDevParams.int_mode       = l_pMdDevContext->m_IntMode;\r
899         l_MosalDevParams.fdo_p          = l_pMdDevContext->m_pFdo;\r
900         l_MosalDevParams.ldo_p          = l_pMdDevContext->m_pLdo;\r
901         l_MosalDevParams.bus            = (u_int8_t)l_pMdDevContext->m_BusNumber;\r
902         l_MosalDevParams.dev_func       = (u_int8_t)((l_pMdDevContext->m_DevNumber << 3) | l_pMdDevContext->m_Function);\r
903         strcpy( l_MosalDevParams.name, l_pMdDevContext->m_AsciiDevName );\r
904         memcpy( (PVOID)&l_MosalDevParams.m_Cr, (PVOID)&l_pMdDevContext->m_Cr, sizeof(MD_BAR_T));\r
905         memcpy( (PVOID)&l_MosalDevParams.m_Uar, (PVOID)&l_pMdDevContext->m_Uar, sizeof(MD_BAR_T));\r
906         memcpy( (PVOID)&l_MosalDevParams.m_Ddr, (PVOID)&l_pMdDevContext->m_Ddr, sizeof(MD_BAR_T));\r
907         l_MosalDevParams.drv_helper = (void*)MdMosalHelper;\r
908         l_MosalDevParams.drv_helper_ctx = (void*)l_pMdDevContext;\r
909 \r
910         /* add specific parameters to MOSAL */\r
911         l_MddkStatus = MOSAL_add_device( &l_pMdDevContext->m_hMosal, &l_MosalDevParams );\r
912 \r
913         /* find the device parameters table by PCI configuration Device ID */\r
914         l_pMdDevContext->m_pMdhalParams = NULL;\r
915         for (l_nDevIx=0; l_nDevIx < MD_DEV_IX_LAST; l_nDevIx++)\r
916         { /* find the type */\r
917 \r
918                 if (g_DevParams[l_nDevIx].m_DevIx == l_pMdDevContext->m_eDevType)\r
919                 { /* found the device type */\r
920                         l_pMdDevContext->m_pMdhalParams = &g_DevParams[l_nDevIx];\r
921                         break;\r
922                 } /* found the device type */\r
923 \r
924         } /* find the type */\r
925 \r
926         if ( l_pMdDevContext->m_pMdhalParams == NULL ) {\r
927                 l_Status = STATUS_NOT_SUPPORTED;\r
928         goto err;\r
929     }\r
930                 \r
931         /*\r
932          * add device to TAVOR\r
933          */ \r
934 \r
935         if (l_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR      && g_pDrvContext->m_fSupportTavor)\r
936         { /* add HCA to Tavor functional DLLs */\r
937         \r
938                 unsigned char                           l_RevId = 0;\r
939                 char                                            l_IntPin = 1;\r
940                 HH_ret_t                                        l_HhRet;\r
941                 VAPI_ret_t                                      l_VapiRet;\r
942                 VAPI_hca_hndl_t                         l_hVapiHca;\r
943                 HH_hca_hndl_t                   l_hHhHca;\r
944                 \r
945                 /* get hw revision id */\r
946                 DrvReadWritePciConfig( l_pMdDevContext, \r
947                         &l_RevId, FIELD_OFFSET( PCI_COMMON_CONFIG, RevisionID ), \r
948                         sizeof(l_RevId), IRP_MN_READ_CONFIG );\r
949 \r
950                 /* get interrupt pin (Who, the hell, needs it ?) */\r
951                 DrvReadWritePciConfig( l_pMdDevContext, \r
952                         &l_IntPin, \r
953                         FIELD_OFFSET( PCI_COMMON_CONFIG, u ) + \r
954                         FIELD_OFFSET( struct _PCI_HEADER_TYPE_0, InterruptPin ), \r
955                         sizeof(l_IntPin), IRP_MN_READ_CONFIG );\r
956 \r
957                 /* add HCA */\r
958                 l_pMdDevContext->m_hHca = VAPI_INVAL_HNDL;\r
959                 l_pMdDevContext->m_hHhHca = (HH_hca_hndl_t)NULL;\r
960                 l_HwProps.bus                                                   = (u_int8_t)l_pMdDevContext->m_BusNumber;\r
961                 l_HwProps.dev_func                                      = (u_int8_t)((l_pMdDevContext->m_DevNumber << 3) | l_pMdDevContext->m_Function);\r
962                 l_HwProps.device_id                                     = g_DevParams[l_pMdDevContext->m_eDevType].m_DevId;\r
963                 l_HwProps.pci_vendor_id                         = MLX_VENDOR_ID;\r
964                 l_HwProps.hw_ver                                                = l_RevId;\r
965                 l_HwProps.cr_base                                               = (MT_phys_addr_t)l_pMdDevContext->m_Cr.m_MemPhysAddr.QuadPart & 0xFFF00000;\r
966                 l_HwProps.uar_base                                      = (MT_phys_addr_t)l_pMdDevContext->m_Uar.m_MemPhysAddr.QuadPart & 0xFFF00000;\r
967                 l_HwProps.ddr_base                                      = (MT_phys_addr_t)l_pMdDevContext->m_Ddr.m_MemPhysAddr.QuadPart & 0xFFF00000;\r
968                 l_HwProps.interrupt_props.irq                   = (MOSAL_IRQ_ID_t)l_pMdDevContext->m_ulIntVector;\r
969                 l_HwProps.interrupt_props.intr_pin              = l_IntPin;\r
970 \r
971                 l_HhRet = THH_add_hca( l_pMdDevContext->m_uCardNo-1, &l_HwProps, &l_hHhHca );\r
972                 if (l_HhRet != MT_OK) {\r
973                         l_Status = l_HhRet;\r
974                 l_pReason = "THH_add_hca failed. Check FW";\r
975                 l_EventCode = MD_EVENT_LOG_LOAD_ERROR_FW;\r
976                 goto err;\r
977         }\r
978 \r
979                 /* open HCA */\r
980   //            l_VapiRet = VAPI_open_hca(l_pMdDevContext->m_AsciiDevName, &l_hVapiHca); \r
981   //            if (l_VapiRet == VAPI_EBUSY) {\r
982   //            MdKdPrint( DBGLVL_LOW,("HCA [%s] is already open.\n",l_pMdDevContext->m_AsciiDevName));\r
983                 //      l_Status = l_VapiRet;\r
984                 //      sprintf( l_Buf, "HCA [%s] is already open.\n",l_pMdDevContext->m_AsciiDevName);\r
985   //            l_pReason = l_Buf;\r
986   //            goto err;\r
987   //            } \r
988   //            else \r
989   //            if (l_VapiRet != VAPI_OK) {\r
990   //            MdKdPrint( DBGLVL_LOW,("Failed opening HCA [%s] - %s\n",\r
991   //                    l_pMdDevContext->m_AsciiDevName, VAPI_strerror_sym(l_VapiRet) ));\r
992                 //      l_Status = l_VapiRet;\r
993                 //      sprintf( l_Buf, "Failed opening HCA [%s] - %s\n",\r
994   //                    l_pMdDevContext->m_AsciiDevName, VAPI_strerror_sym(l_VapiRet) );\r
995   //            l_pReason = l_Buf;\r
996   //            } else {\r
997   //            MdKdPrint( DBGLVL_LOW,("HCA [%s] is open \n", l_pMdDevContext->m_AsciiDevName));\r
998   //            } \r
999                 //\r
1000                 ///* save HCA handles */\r
1001                 //l_pMdDevContext->m_hHca = l_hVapiHca;\r
1002                 l_pMdDevContext->m_hHhHca = l_hHhHca;\r
1003                 \r
1004 \r
1005                 /* init IB_MGT */\r
1006                 //if (g_pDrvContext->m_fSupportIbMgt) {\r
1007                 //    if (IB_MGT_started) {\r
1008                 //      l_MddkStatus = IB_MGT_reattach_hca( l_pMdDevContext->m_AsciiDevName );\r
1009   //                if (l_MddkStatus != MT_OK)                          \r
1010   //                    {                                                                               \r
1011   //                    MdKdPrint( DBGLVL_LOW,("IB_MGT_reattach_hca failed (%d)\n",l_MddkStatus));\r
1012   //                            sprintf( l_Buf, "IB_MT init failed (%d)\n",l_MddkStatus );\r
1013   //                            l_pReason = l_Buf;\r
1014   //                    }\r
1015   //                else {\r
1016   //                    MdKdPrint( DBGLVL_LOW,("'%s' attached to IB_MGT\n",l_pMdDevContext->m_AsciiDevName));\r
1017   //                          IB_MGT_started++;\r
1018          //   }\r
1019                 //    }\r
1020                 //    else {\r
1021   //              l_MddkStatus = IB_MGT_init_module(g_pDrvContext->m_IbMgtQp0Only);\r
1022   //                if (l_MddkStatus != MT_OK)                          \r
1023   //                    {                                                                               \r
1024   //                    MdKdPrint( DBGLVL_LOW,("IB_MGT_init_module failed (%d)\n",l_MddkStatus));\r
1025   //                            sprintf( l_Buf, "IB_MGT_init_module failed (%d)\n",l_MddkStatus );\r
1026   //                            l_pReason = l_Buf;\r
1027   //                    }\r
1028   //                else {\r
1029   //                  IB_MGT_started++;\r
1030   //                    MdKdPrint( DBGLVL_LOW,("IB_MGT started over '%s'\n",l_pMdDevContext->m_AsciiDevName));\r
1031   //                }\r
1032                 //    }\r
1033                 //}\r
1034                 \r
1035         } /* add HCA to Tavor functional DLLs */\r
1036         \r
1037         // mark device started\r
1038     l_pMdDevContext->m_DeviceStarted = TRUE;\r
1039 \r
1040         // exit\r
1041         /* Write to event log */\r
1042         WriteEventLogEntry( g_pDrvContext->m_pDrvObject, MD_EVENT_LOG_LOAD_OK, 0, 0, 0  );\r
1043         MdKdPrint( DBGLVL_DEFAULT, ("(MdStartDevice) exit (%x)\n", l_Status));\r
1044     return l_Status;\r
1045     \r
1046 err:\r
1047 #pragma warning( push )\r
1048 #pragma warning( disable:4296 )\r
1049         MdKdPrint( DBGLVL_ALWAYS ,("(MdStartDevice) Device failed to initialize \n"));\r
1050 #pragma warning( pop )\r
1051 \r
1052         /* Write to event log */\r
1053         WriteEventLogEntry(     g_pDrvContext->m_pDrvObject, l_EventCode,\r
1054                         0, l_Status, 1, l_Status );\r
1055         return STATUS_UNSUCCESSFUL;\r
1056 }\r
1057 \r
1058 /*------------------------------------------------------------------------------------------------------*/\r
1059 \r
1060 NTSTATUS\r
1061 MdRemoveDevice(\r
1062     IN  PDEVICE_OBJECT pi_pFdo\r
1063     )\r
1064 /*++\r
1065 \r
1066 Routine Description:\r
1067 \r
1068     Called from MdProcessPnPIrp() to\r
1069     clean up our device instance's allocated buffers; free symbolic links\r
1070 \r
1071 Arguments:\r
1072 \r
1073     pi_pFdo - pointer to the FDO\r
1074 \r
1075 Return Value:\r
1076 \r
1077     NT status code from free symbolic link operation\r
1078 \r
1079 --*/\r
1080 {\r
1081     PMD_DEV_CONTEXT_T   l_pMdDevContext = (PMD_DEV_CONTEXT_T)pi_pFdo->DeviceExtension;\r
1082     NTSTATUS                    l_Status = STATUS_SUCCESS;\r
1083 \r
1084     MdKdPrint( DBGLVL_DEFAULT,("enter MdRemoveDevice\n"));\r
1085 \r
1086         /* remove functional device object (FDO) */\r
1087         MdDevDeInit( l_pMdDevContext ); \r
1088         \r
1089     MdKdPrint( DBGLVL_DEFAULT,("exit MdRemoveDevice() status = 0x%x\n", l_Status ));\r
1090 \r
1091     return l_Status;\r
1092 }\r
1093 \r
1094 \r
1095 /*------------------------------------------------------------------------------------------------------*/\r
1096 \r
1097 NTSTATUS\r
1098 MdStopDevice(\r
1099     IN  PDEVICE_OBJECT pi_pFdo\r
1100     )\r
1101 /*++\r
1102 \r
1103 Routine Description:\r
1104 \r
1105     Stops a given instance of a 82930 device on the USB.\r
1106     We basically just tell USB this device is now 'unconfigured'\r
1107 \r
1108 Arguments:\r
1109 \r
1110     pi_pFdo - pointer to the device object for this instance of a 82930\r
1111 \r
1112 Return Value:\r
1113 \r
1114     NT status code\r
1115 \r
1116 --*/\r
1117 {\r
1118     PMD_DEV_CONTEXT_T   l_pMdDevContext = pi_pFdo->DeviceExtension;\r
1119     NTSTATUS l_Status = STATUS_SUCCESS;\r
1120     HH_hca_hndl_t       l_hHhHca =  l_pMdDevContext->m_hHhHca;\r
1121 \r
1122     MdKdPrint( DBGLVL_DEFAULT,("enter MdStopDevice\n"));\r
1123 \r
1124         // mark device stopping\r
1125     l_pMdDevContext->m_StopDeviceRequested = TRUE;\r
1126 \r
1127         // TBD\r
1128         // stop the card by sending some commands to it or suspend all new requests and wait for the end of in-progress ones\r
1129         //\r
1130 \r
1131         if (l_pMdDevContext->m_eDevType == MD_DEV_IX_TAVOR      && g_pDrvContext->m_fSupportTavor)\r
1132         { /* remove HCA from Tavor functional DLLs */\r
1133         \r
1134                 HH_ret_t                                        l_HhRet;\r
1135                 //VAPI_ret_t                                    l_VapiRet;\r
1136 \r
1137                 /* de-init IB_MGT */\r
1138                 //if (g_pDrvContext->m_fSupportIbMgt) {\r
1139                 //    if (--IB_MGT_started > 0) {\r
1140 //                              if (l_pMdDevContext->m_hHca != VAPI_INVAL_HNDL)\r
1141                 //                      IB_MGT_fatal_delete_hca( l_pMdDevContext->m_hHca );\r
1142          //                     MdKdPrint( DBGLVL_LOW,("'%s' detached from IB_MGT\n",l_pMdDevContext->m_AsciiDevName));\r
1143                 //      }\r
1144                 //    else {\r
1145   //                    IB_MGT_cleanup_module();\r
1146          //                     MdKdPrint( DBGLVL_LOW,("The last HCA '%s' detached from IB_MGT\n",l_pMdDevContext->m_AsciiDevName));\r
1147                 //      }\r
1148                 //}\r
1149                                 \r
1150                 /* close HCA handle */\r
1151                 //if (l_pMdDevContext->m_hHca != VAPI_INVAL_HNDL)\r
1152                       //        l_VapiRet = VAPI_close_hca( l_pMdDevContext->m_hHca ); \r
1153                 //if (l_VapiRet) {\r
1154                 //      DbgPrint("MdStopDevice: error 0x%x on VAPI_close_hca\n", l_VapiRet);\r
1155                 //}\r
1156                 \r
1157                 /* remove HCA */\r
1158                 //l_HhRet = THH_rmv_hca( l_pMdDevContext->m_uCardNo-1 );\r
1159                 l_pMdDevContext->m_hHhHca = (HH_hca_hndl_t)NULL;\r
1160                 if ( l_hHhHca != (HH_hca_hndl_t)NULL)\r
1161                         l_HhRet = THH_hob_destroy( l_hHhHca );\r
1162                 if (l_HhRet) {\r
1163                         DbgPrint("MdStopDevice: error 0x%x on THH_rmv_hca\n", l_HhRet);\r
1164                 }\r
1165                 \r
1166                 /* save HCA handle */\r
1167                 l_pMdDevContext->m_hHca = VAPI_INVAL_HNDL;\r
1168                 \r
1169         } /* remove HCA from Tavor functional DLLs */\r
1170         \r
1171         // remove device from MOSAL\r
1172         MOSAL_remove_device( l_pMdDevContext->m_hMosal );\r
1173 \r
1174         // release PCI card resources\r
1175         MdDeInitPciCfgCard( l_pMdDevContext );\r
1176 \r
1177         // mark device stopping\r
1178     l_pMdDevContext->m_DeviceStarted = FALSE;\r
1179     l_pMdDevContext->m_StopDeviceRequested = FALSE;\r
1180 \r
1181     MdKdPrint( DBGLVL_DEFAULT,("exit MdStopDevice() (%x)\n", l_Status));\r
1182 \r
1183     return l_Status;\r
1184 }\r
1185 \r
1186 \r
1187 /*------------------------------------------------------------------------------------------------------*/\r
1188 \r
1189 NTSTATUS\r
1190 MdIrpCompletionRoutine(\r
1191     IN PDEVICE_OBJECT pi_pFdo,\r
1192     IN PIRP pi_pIrp,\r
1193     IN PVOID Context\r
1194     )\r
1195 /*++\r
1196 \r
1197 Routine Description:\r
1198 \r
1199     Used as a  general purpose completion routine so it can signal an event,\r
1200     passed as the Context, when the next lower driver is done with the input Irp.\r
1201         This routine is used by both PnP and Power Management logic.\r
1202 \r
1203     Even though this routine does nothing but set an event, it must be defined and\r
1204     prototyped as a completetion routine for use as such\r
1205 \r
1206 \r
1207 Arguments:\r
1208 \r
1209     pi_pFdo - Pointer to the device object for the class device.\r
1210 \r
1211     pi_pIrp - Irp completed.\r
1212 \r
1213     Context - Driver defined context, in this case a pointer to an event.\r
1214 \r
1215 Return Value:\r
1216 \r
1217     The function value is the final status from the operation.\r
1218 \r
1219 --*/\r
1220 {\r
1221     PKEVENT event = Context;\r
1222 \r
1223     // Set the input event\r
1224     KeSetEvent(event,\r
1225                1,       // Priority increment  for waiting thread.\r
1226                FALSE);  // Flag this call is not immediately followed by wait.\r
1227 \r
1228     // This routine must return STATUS_MORE_PROCESSING_REQUIRED because we have not yet called\r
1229     // IoFreeIrp() on this IRP.\r
1230     return STATUS_MORE_PROCESSING_REQUIRED;\r
1231 \r
1232 }\r
1233 \r
1234 \r