519251cc9cb384f4f7f70302b79489de36da2137
[mirror/winof/.git] / hw / mt23108 / kernel / hca_driver.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 \r
33 /*\r
34  * Provides the driver entry points for the Tavor VPD.\r
35  */\r
36 \r
37 \r
38 #include "hca_driver.h"\r
39 #include <wdmguid.h>\r
40 #include <initguid.h>\r
41 #pragma warning( push, 3 )\r
42 #include "MdCard.h"\r
43 #pragma warning( pop )\r
44 #include <iba/ib_ci_ifc.h>\r
45 #include <complib/cl_init.h>\r
46 \r
47 \r
48 /*\r
49  * UVP name does not include file extension.  For debug builds, UAL\r
50  * will append "d.dll".  For release builds, UAL will append ".dll"\r
51  */\r
52 char                    mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mt23108u"};\r
53 \r
54 \r
55 NTSTATUS\r
56 DriverEntry(\r
57         IN                              PDRIVER_OBJECT                          p_driver_obj,\r
58         IN                              PUNICODE_STRING                         p_registry_path );\r
59 \r
60 static NTSTATUS\r
61 __read_registry(\r
62         IN                              UNICODE_STRING* const           p_Param_Path );\r
63 \r
64 static void\r
65 hca_drv_unload(\r
66         IN                              PDRIVER_OBJECT                          p_driver_obj );\r
67 \r
68 static NTSTATUS\r
69 hca_sysctl(\r
70         IN                              PDEVICE_OBJECT                          p_dev_obj,\r
71         IN                              PIRP                                            p_irp );\r
72 \r
73 static NTSTATUS\r
74 hca_add_device(\r
75         IN                              PDRIVER_OBJECT                          p_driver_obj,\r
76         IN                              PDEVICE_OBJECT                          p_pdo );\r
77 //\r
78 //static NTSTATUS\r
79 //hca_enable(\r
80 //      IN                              DEVICE_OBJECT* const            p_dev_obj );\r
81 //\r
82 //static NTSTATUS\r
83 //hca_disable(\r
84 //      IN                              DEVICE_OBJECT* const            p_dev_obj );\r
85 \r
86 static NTSTATUS\r
87 hca_start(\r
88         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
89         IN                              IRP* const                                      p_irp, \r
90                 OUT                     cl_irp_action_t* const          p_action );\r
91 \r
92 static void\r
93 hca_release_resources(\r
94         IN                              DEVICE_OBJECT* const            p_dev_obj );\r
95 \r
96 //static NTSTATUS\r
97 //hca_deactivate(\r
98 //      IN                              DEVICE_OBJECT* const            p_dev_obj,\r
99 //      IN                              IRP* const                                      p_irp, \r
100 //              OUT                     cl_irp_action_t* const          p_action );\r
101 //\r
102 static NTSTATUS\r
103 hca_query_bus_relations(\r
104         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
105         IN                              IRP* const                                      p_irp, \r
106                 OUT                     cl_irp_action_t* const          p_action );\r
107 \r
108 static NTSTATUS\r
109 hca_set_power(\r
110         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
111         IN                              IRP* const                                      p_irp, \r
112                 OUT                     cl_irp_action_t* const          p_action );\r
113 \r
114 static ci_interface_t*\r
115 __alloc_hca_ifc(\r
116         IN                              hca_dev_ext_t* const            p_ext );\r
117 \r
118 static NTSTATUS\r
119 __get_ci_interface(\r
120         IN                                      DEVICE_OBJECT* const    p_dev_obj );\r
121 \r
122 static NTSTATUS\r
123 __get_hca_handle(\r
124         IN                                      hca_dev_ext_t* const    p_ext );\r
125 \r
126 static NTSTATUS\r
127 __hca_register(\r
128         IN                              DEVICE_OBJECT                           *p_dev_obj );\r
129 \r
130 //static void\r
131 //__work_item_pnp_cb(\r
132 //      IN                              DEVICE_OBJECT                           *p_dev_obj,\r
133 //      IN                              hca_work_item_context_t         *p_context );\r
134 \r
135 static NTSTATUS\r
136 __pnp_notify_target(\r
137         IN                              TARGET_DEVICE_REMOVAL_NOTIFICATION      *p_notify,\r
138         IN                              void                                            *context );\r
139 \r
140 static NTSTATUS\r
141 __pnp_notify_ifc(\r
142         IN                              DEVICE_INTERFACE_CHANGE_NOTIFICATION    *p_notify,\r
143         IN                              void                                            *context );\r
144 \r
145 static NTSTATUS\r
146 fw_access_pciconf (\r
147                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
148                 IN              ULONG                                                   op_flag,\r
149                 IN              PVOID                                                   p_buffer,\r
150                 IN              ULONG                                                   offset,\r
151                 IN              ULONG POINTER_ALIGNMENT                 length );\r
152 \r
153 static NTSTATUS\r
154 fw_get_pci_bus_interface(\r
155         IN              DEVICE_OBJECT                           *p_dev_obj,\r
156         OUT             BUS_INTERFACE_STANDARD          *p_BusInterface );\r
157 \r
158 static NTSTATUS\r
159 fw_flash_write_data (\r
160                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
161                 IN              PVOID                                                   p_buffer,\r
162                 IN              ULONG                                                   offset,\r
163                 IN              ULONG POINTER_ALIGNMENT                 length );\r
164 \r
165 static NTSTATUS\r
166 fw_flash_read_data (\r
167                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
168                 IN              PVOID                                                   p_buffer,\r
169                 IN              ULONG                                                   offset,\r
170                 IN              ULONG POINTER_ALIGNMENT                 length );\r
171 \r
172 static NTSTATUS\r
173 fw_flash_get_ca_guid(\r
174         IN              DEVICE_OBJECT           *p_dev_obj,\r
175         OUT             uint64_t                        *ca_guid );\r
176 \r
177 static NTSTATUS\r
178 fw_flash_read4( \r
179         IN                      BUS_INTERFACE_STANDARD  *p_BusInterface,\r
180         IN                      uint32_t                                addr, \r
181         IN      OUT             uint32_t                                *p_data);\r
182 \r
183 static NTSTATUS\r
184 fw_flash_readbuf(\r
185         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
186         IN              uint32_t                                offset,\r
187         IN OUT  void                                    *p_data,\r
188         IN              uint32_t                                len);\r
189 static NTSTATUS\r
190 fw_set_bank(\r
191         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
192         IN              uint32_t                                bank );\r
193 \r
194 static NTSTATUS\r
195 fw_flash_init(\r
196                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  );\r
197 \r
198 static NTSTATUS\r
199 fw_flash_deinit(\r
200                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  );\r
201 \r
202 #ifdef ALLOC_PRAGMA\r
203 #pragma alloc_text (INIT, DriverEntry)\r
204 #pragma alloc_text (INIT, __read_registry)\r
205 #pragma alloc_text (PAGE, hca_drv_unload)\r
206 #pragma alloc_text (PAGE, hca_sysctl)\r
207 #pragma alloc_text (PAGE, hca_add_device)\r
208 #pragma alloc_text (PAGE, hca_start)\r
209 //#pragma alloc_text (PAGE, hca_deactivate)\r
210 //#pragma alloc_text (PAGE, hca_enable)\r
211 //#pragma alloc_text (PAGE, hca_disable)\r
212 #pragma alloc_text (PAGE, hca_release_resources)\r
213 #pragma alloc_text (PAGE, hca_query_bus_relations)\r
214 #pragma alloc_text (PAGE, hca_set_power)\r
215 #pragma alloc_text (PAGE, __alloc_hca_ifc)\r
216 #pragma alloc_text (PAGE, __get_ci_interface)\r
217 #pragma alloc_text (PAGE, __get_hca_handle)\r
218 #pragma alloc_text (PAGE, __hca_register)\r
219 //#pragma alloc_text (PAGE, __work_item_pnp_cb)\r
220 #pragma alloc_text (PAGE, __pnp_notify_target)\r
221 #pragma alloc_text (PAGE, __pnp_notify_ifc)\r
222 #pragma alloc_text (PAGE, fw_flash_get_ca_guid)\r
223 #endif\r
224 \r
225 \r
226 static const cl_vfptr_pnp_po_t  hca_vfptr_pnp = {\r
227         "Tavor HCA VPD",\r
228         hca_start,                              /* StartDevice */\r
229         cl_irp_skip,\r
230         cl_irp_skip,\r
231         cl_do_sync_pnp,\r
232         cl_irp_skip,                    /* QueryRemove */\r
233         hca_release_resources,\r
234         cl_do_remove,                   /* Remove */\r
235         cl_irp_skip,                    /* CancelRemove */\r
236         cl_irp_skip,                    /* SurpriseRemove */\r
237         cl_irp_skip,            \r
238         cl_irp_skip,\r
239         cl_irp_skip,\r
240         cl_do_sync_pnp,\r
241         hca_query_bus_relations,\r
242         cl_irp_ignore,\r
243         cl_irp_skip,\r
244         cl_irp_ignore,\r
245         cl_irp_ignore,\r
246         cl_irp_ignore,\r
247         cl_irp_ignore,\r
248         cl_irp_ignore,\r
249         cl_irp_ignore,\r
250         cl_irp_ignore,\r
251         cl_irp_ignore,\r
252         cl_irp_ignore,\r
253         cl_irp_ignore,\r
254         cl_irp_ignore,                  /* QueryPower */\r
255         hca_set_power,                  /* SetPower */\r
256         cl_irp_ignore,                  /* PowerSequence */\r
257         cl_irp_ignore                   /* WaitWake */\r
258 };\r
259 \r
260 \r
261 NTSTATUS\r
262 DriverEntry(\r
263         IN                              PDRIVER_OBJECT                  p_driver_obj,\r
264         IN                              PUNICODE_STRING                 p_registry_path )\r
265 {\r
266         NTSTATUS                        status;\r
267         cl_status_t                     cl_status;\r
268 \r
269         HCA_ENTER( HCA_DBG_DEV );\r
270 \r
271         status = CL_INIT;\r
272         if( !NT_SUCCESS(status) )\r
273         {\r
274                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
275                         ("cl_init returned %08X.\n", status) );\r
276                 return status;\r
277         }\r
278 \r
279         status = __read_registry( p_registry_path );\r
280         if( !NT_SUCCESS( status ) )\r
281         {\r
282                 CL_DEINIT;\r
283                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
284                         ("__read_registry_path returned 0x%X.\n", status) );\r
285                 return status;\r
286         }\r
287 \r
288         /* Initializae Adapter DB */\r
289         cl_status = mlnx_hobs_init();\r
290         if( cl_status != CL_SUCCESS )\r
291         {\r
292                 CL_DEINIT;\r
293                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
294                         ("mlnx_hobs_init returned %s.\n", cl_status_text[cl_status]) );\r
295                 return cl_to_ntstatus( cl_status );\r
296         }\r
297 //      cl_memclr( mlnx_hca_array, MLNX_MAX_HCA * sizeof(ci_interface_t) );\r
298 \r
299         p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;\r
300         p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;\r
301         p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = hca_sysctl;\r
302         p_driver_obj->DriverUnload = hca_drv_unload;\r
303         p_driver_obj->DriverExtension->AddDevice = hca_add_device;\r
304 \r
305         HCA_EXIT( HCA_DBG_DEV );\r
306         return STATUS_SUCCESS;\r
307 }\r
308 \r
309 \r
310 static NTSTATUS\r
311 __read_registry(\r
312         IN                              UNICODE_STRING* const   p_registry_path )\r
313 {\r
314         NTSTATUS                                        status;\r
315         /* Remember the terminating entry in the table below. */\r
316         RTL_QUERY_REGISTRY_TABLE        table[2];\r
317         UNICODE_STRING                          param_path;\r
318 \r
319         HCA_ENTER( HCA_DBG_DEV );\r
320 \r
321         RtlInitUnicodeString( &param_path, NULL );\r
322         param_path.MaximumLength = p_registry_path->Length + \r
323                 sizeof(L"\\Parameters");\r
324         param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
325         if( !param_path.Buffer )\r
326         {\r
327                 HCA_TRACE_EXIT( HCA_DBG_ERROR, \r
328                         ("Failed to allocate parameters path buffer.\n") );\r
329                 return STATUS_INSUFFICIENT_RESOURCES;\r
330         }\r
331 \r
332         RtlAppendUnicodeStringToString( &param_path, p_registry_path );\r
333         RtlAppendUnicodeToString( &param_path, L"\\Parameters" );\r
334 \r
335         /*\r
336          * Clear the table.  This clears all the query callback pointers,\r
337          * and sets up the terminating table entry.\r
338          */\r
339         cl_memclr( table, sizeof(table) );\r
340 \r
341         /* Setup the table entries. */\r
342         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
343         table[0].Name = L"DebugFlags";\r
344         table[0].EntryContext = &g_mlnx_dbg_lvl;\r
345         table[0].DefaultType = REG_DWORD;\r
346         table[0].DefaultData = &g_mlnx_dbg_lvl;\r
347         table[0].DefaultLength = sizeof(ULONG);\r
348 \r
349         /* Have at it! */\r
350         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
351                 param_path.Buffer, table, NULL, NULL );\r
352 \r
353         cl_free( param_path.Buffer );\r
354         HCA_EXIT( HCA_DBG_DEV );\r
355         return status;\r
356 }\r
357 \r
358 \r
359 static void\r
360 hca_drv_unload(\r
361         IN                              PDRIVER_OBJECT                  p_driver_obj )\r
362 {\r
363         HCA_ENTER( HCA_DBG_DEV );\r
364 \r
365         UNUSED_PARAM( p_driver_obj );\r
366 \r
367         CL_DEINIT;\r
368 \r
369         HCA_EXIT( HCA_DBG_DEV );\r
370 }\r
371 \r
372 \r
373 static NTSTATUS\r
374 hca_sysctl(\r
375         IN                              PDEVICE_OBJECT                          p_dev_obj,\r
376         IN                              PIRP                                            p_irp )\r
377 {\r
378         NTSTATUS                status;\r
379         hca_dev_ext_t   *p_ext;\r
380 \r
381         HCA_ENTER( HCA_DBG_DEV );\r
382 \r
383         p_ext = p_dev_obj->DeviceExtension;\r
384 \r
385         IoSkipCurrentIrpStackLocation( p_irp );\r
386         status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
387 \r
388         HCA_EXIT( HCA_DBG_DEV );\r
389         return status;\r
390 }\r
391 \r
392 \r
393 static NTSTATUS\r
394 hca_add_device(\r
395         IN                              PDRIVER_OBJECT                          p_driver_obj,\r
396         IN                              PDEVICE_OBJECT                          p_pdo )\r
397 {\r
398         NTSTATUS                        status;\r
399         DEVICE_OBJECT           *p_dev_obj, *p_next_do;\r
400         hca_dev_ext_t           *p_ext;\r
401         //cl_status_t                   cl_status;\r
402 \r
403         HCA_ENTER( HCA_DBG_PNP );\r
404 \r
405         /*\r
406          * Create the device so that we have a device extension to store stuff in.\r
407          */\r
408         status = IoCreateDevice( p_driver_obj, sizeof(hca_dev_ext_t),\r
409                 NULL, FILE_DEVICE_INFINIBAND, FILE_DEVICE_SECURE_OPEN,\r
410                 FALSE, &p_dev_obj );\r
411         if( !NT_SUCCESS( status ) )\r
412         {\r
413                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
414                         ("IoCreateDevice returned 0x%08X.\n", status) );\r
415                 return status;\r
416         }\r
417 \r
418         p_ext = p_dev_obj->DeviceExtension;\r
419 \r
420         //cl_status = cl_event_init( &p_ext->mutex, FALSE );\r
421         //if( cl_status != CL_SUCCESS )\r
422         //{\r
423         //      IoDeleteDevice( p_dev_obj );\r
424         //      HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
425         //              ("cl_mutex_init returned %s.\n", cl_status_text[status]) );\r
426         //      return cl_to_ntstatus( status );\r
427         //}\r
428         //cl_event_signal( &p_ext->mutex );\r
429 \r
430         /* Attach to the device stack. */\r
431         p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
432         if( !p_next_do )\r
433         {\r
434                 //cl_event_destroy( &p_ext->mutex );\r
435                 IoDeleteDevice( p_dev_obj );\r
436                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
437                         ("IoAttachDeviceToDeviceStack failed.\n") );\r
438                 return STATUS_NO_SUCH_DEVICE;\r
439         }\r
440 \r
441         /* Inititalize the complib extension. */\r
442         cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, g_mlnx_dbg_lvl,\r
443                 &hca_vfptr_pnp, NULL );\r
444 \r
445         p_ext->state = HCA_ADDED;\r
446 \r
447         HCA_EXIT( HCA_DBG_PNP );\r
448         return status;\r
449 }\r
450 \r
451 \r
452 static NTSTATUS\r
453 __get_ci_interface(\r
454         IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
455 {\r
456         NTSTATUS                        status;\r
457         IRP                                     *p_irp;\r
458         hca_dev_ext_t           *p_ext;\r
459         IO_STATUS_BLOCK         io_status;\r
460         IO_STACK_LOCATION       *p_io_stack;\r
461         KEVENT                          event;\r
462 \r
463         HCA_ENTER( HCA_DBG_PNP );\r
464 \r
465         p_ext = p_dev_obj->DeviceExtension;\r
466 \r
467         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
468 \r
469         /* Query for the verbs interface. */\r
470         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_ext->p_al_dev,\r
471                 NULL, 0, NULL, &event, &io_status );\r
472         if( !p_irp )\r
473         {\r
474                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
475                         ("IoBuildSynchronousFsdRequest failed.\n") );\r
476                 return STATUS_INSUFFICIENT_RESOURCES;\r
477         }\r
478 \r
479         /* Format the IRP. */\r
480         p_io_stack = IoGetNextIrpStackLocation( p_irp );\r
481         p_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
482         p_io_stack->Parameters.QueryInterface.Version = IB_CI_INTERFACE_VERSION;\r
483         p_io_stack->Parameters.QueryInterface.Size = sizeof(ib_ci_ifc_t);\r
484         p_io_stack->Parameters.QueryInterface.Interface = \r
485                 (INTERFACE*)&p_ext->ci_ifc;\r
486         p_io_stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;\r
487         p_io_stack->Parameters.QueryInterface.InterfaceType = \r
488                 &GUID_IB_CI_INTERFACE;\r
489         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
490 \r
491         /* Send the IRP. */\r
492         status = IoCallDriver( p_ext->p_al_dev, p_irp );\r
493         if( status == STATUS_PENDING )\r
494         {\r
495                 KeWaitForSingleObject( &event, Executive, KernelMode, \r
496                         FALSE, NULL );\r
497 \r
498                 status = io_status.Status;\r
499         }\r
500 \r
501         if( !NT_SUCCESS( status ) )\r
502         {\r
503                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
504                         ("Query interface for verbs returned %08x.\n", status) );\r
505                 return status;\r
506         }\r
507 \r
508         HCA_EXIT( HCA_DBG_PNP );\r
509         return status;\r
510 }\r
511 \r
512 \r
513 static NTSTATUS\r
514 __get_hca_handle(\r
515         IN                                      hca_dev_ext_t* const    p_ext )\r
516 {\r
517         NTSTATUS                        status;\r
518         IRP                                     *p_irp;\r
519         IO_STATUS_BLOCK         io_status;\r
520         IO_STACK_LOCATION       *p_io_stack;\r
521         KEVENT                          event;\r
522 \r
523         HCA_ENTER( HCA_DBG_PNP );\r
524 \r
525         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
526 \r
527         /* Query for the verbs interface. */\r
528         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, p_ext->cl_ext.p_next_do,\r
529                 NULL, 0, NULL, &event, &io_status );\r
530         if( !p_irp )\r
531         {\r
532                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
533                         ("IoBuildSynchronousFsdRequest failed.\n") );\r
534                 return STATUS_INSUFFICIENT_RESOURCES;\r
535         }\r
536 \r
537         /* Format the IRP. */\r
538         p_io_stack = IoGetNextIrpStackLocation( p_irp );\r
539         p_io_stack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
540         p_io_stack->Parameters.QueryInterface.Version = 1;\r
541         p_io_stack->Parameters.QueryInterface.Size = 0;\r
542         p_io_stack->Parameters.QueryInterface.Interface = NULL;\r
543         p_io_stack->Parameters.QueryInterface.InterfaceSpecificData = \r
544                 &p_ext->hca.hh_hndl;\r
545         p_io_stack->Parameters.QueryInterface.InterfaceType = \r
546                 &GUID_MD_INTERFACE;\r
547         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
548 \r
549         /* Send the IRP. */\r
550         status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
551         if( status == STATUS_PENDING )\r
552         {\r
553                 KeWaitForSingleObject( &event, Executive, KernelMode, \r
554                         FALSE, NULL );\r
555 \r
556                 status = io_status.Status;\r
557         }\r
558 \r
559         if( !NT_SUCCESS( status ) )\r
560         {\r
561                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
562                         ("Query interface for HCA handle returned %08x.\n", status) );\r
563                 return status;\r
564         }\r
565 \r
566         HCA_EXIT( HCA_DBG_PNP );\r
567         return status;\r
568 }\r
569 \r
570 \r
571 static NTSTATUS\r
572 __pnp_notify_target(\r
573         IN                              TARGET_DEVICE_REMOVAL_NOTIFICATION      *p_notify,\r
574         IN                              void                                            *context )\r
575 {\r
576         NTSTATUS                                                        status = STATUS_SUCCESS;\r
577         DEVICE_OBJECT                                           *p_dev_obj;\r
578         hca_dev_ext_t                                           *p_ext;\r
579 \r
580         HCA_ENTER( HCA_DBG_PNP );\r
581 \r
582         p_dev_obj = context;\r
583         p_ext = p_dev_obj->DeviceExtension;\r
584 \r
585         if( IsEqualGUID( &p_notify->Event, &GUID_TARGET_DEVICE_QUERY_REMOVE ) )\r
586         {\r
587                 if( p_ext->state == HCA_REGISTERED )\r
588                 {\r
589                         /* Release AL's CI interface. */\r
590                         p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
591                         p_ext->state = HCA_STARTED;\r
592                 }\r
593 \r
594                 /* Release AL's file object so that it can unload. */\r
595                 CL_ASSERT( p_ext->p_al_file_obj );\r
596                 CL_ASSERT( p_ext->p_al_file_obj == p_notify->FileObject );\r
597                 ObDereferenceObject( p_ext->p_al_file_obj );\r
598                 p_ext->p_al_file_obj = NULL;\r
599                 p_ext->p_al_dev = NULL;\r
600         }\r
601         else if( IsEqualGUID( &p_notify->Event, \r
602                 &GUID_TARGET_DEVICE_REMOVE_COMPLETE ) )\r
603         {\r
604                 if( p_ext->state == HCA_REGISTERED )\r
605                 {\r
606                         /* Release AL's CI interface. */\r
607                         p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
608                         p_ext->state = HCA_STARTED;\r
609                 }\r
610 \r
611                 /* Release AL's file object so that it can unload. */\r
612                 if( p_ext->p_al_file_obj )\r
613                 {\r
614                         ObDereferenceObject( p_ext->p_al_file_obj );\r
615                         p_ext->p_al_file_obj = NULL;\r
616                         p_ext->p_al_dev = NULL;\r
617                 }\r
618 \r
619                 /* Cancel our target device change registration. */\r
620                 IoUnregisterPlugPlayNotification( p_ext->pnp_target_entry );\r
621                 p_ext->pnp_target_entry = NULL;\r
622         }\r
623         else if( IsEqualGUID( &p_notify->Event, \r
624                 &GUID_TARGET_DEVICE_REMOVE_CANCELLED ) )\r
625         {\r
626                 /* Cancel our target device change registration. */\r
627                 IoUnregisterPlugPlayNotification( p_ext->pnp_target_entry );\r
628                 p_ext->pnp_target_entry = NULL;\r
629 \r
630                 /* Get the device object pointer for the AL. */\r
631                 CL_ASSERT( !p_ext->p_al_file_obj );\r
632                 CL_ASSERT( !p_ext->p_al_dev );\r
633                 p_ext->p_al_file_obj = p_notify->FileObject;\r
634                 p_ext->p_al_dev = IoGetRelatedDeviceObject( p_ext->p_al_file_obj );\r
635 \r
636                 status = IoRegisterPlugPlayNotification( \r
637                         EventCategoryTargetDeviceChange, 0, p_ext->p_al_file_obj, \r
638                         p_dev_obj->DriverObject, __pnp_notify_target, p_dev_obj, \r
639                         &p_ext->pnp_target_entry );\r
640                 if( !NT_SUCCESS( status ) )\r
641                 {\r
642                         HCA_TRACE_EXIT( HCA_DBG_ERROR, \r
643                                 ("IoRegisterPlugPlayNotification returned %08x.\n") );\r
644                         return status;\r
645                 }\r
646 \r
647                 __hca_register( p_dev_obj );\r
648         }\r
649 \r
650         HCA_EXIT( HCA_DBG_PNP );\r
651         return status;\r
652 }\r
653 \r
654 \r
655 static ci_interface_t*\r
656 __alloc_hca_ifc(\r
657         IN                              hca_dev_ext_t* const            p_ext )\r
658 {\r
659         ci_interface_t  *p_ifc;\r
660 \r
661         HCA_ENTER( HCA_DBG_PNP );\r
662 \r
663         p_ifc = ExAllocatePool( PagedPool, sizeof(ci_interface_t) );\r
664         if( !p_ifc )\r
665         {\r
666                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
667                         ("Failed to allocate ci_interface_t (%d bytes).\n",\r
668                         sizeof(ci_interface_t)) );\r
669                 return NULL;\r
670         }\r
671 \r
672         setup_ci_interface( p_ext->hca.guid, p_ifc );\r
673 \r
674         p_ifc->p_hca_dev = p_ext->cl_ext.p_pdo;\r
675         p_ifc->vend_id = p_ext->hca.hh_hndl->vendor_id;\r
676         p_ifc->dev_id = (uint16_t)p_ext->hca.hh_hndl->dev_id;\r
677         p_ifc->dev_revision = (uint16_t)p_ext->hca.hh_hndl->hw_ver;\r
678 \r
679         HCA_EXIT( HCA_DBG_PNP );\r
680         return p_ifc;\r
681 }\r
682 \r
683 \r
684 static NTSTATUS\r
685 __hca_register(\r
686         IN                              DEVICE_OBJECT                           *p_dev_obj )\r
687 {\r
688         hca_dev_ext_t                   *p_ext;\r
689         NTSTATUS                                status;\r
690         ib_api_status_t                 ib_status;\r
691         ci_interface_t                  *p_hca_ifc;\r
692 \r
693         HCA_ENTER( HCA_DBG_PNP );\r
694         \r
695         p_ext = p_dev_obj->DeviceExtension;\r
696 \r
697         ASSERT( p_ext->state == HCA_STARTED );\r
698         ASSERT( p_ext->p_al_dev );\r
699 \r
700         /* Get the AL's lower interface. */\r
701         status = __get_ci_interface( p_dev_obj );\r
702         if( !NT_SUCCESS( status ) )\r
703         {\r
704                 HCA_TRACE( HCA_DBG_ERROR,\r
705                         ("__get_ci_interface returned %08x.\n", status) );\r
706                 return status;\r
707         }\r
708 \r
709         /* Allocate and populate our HCA interface structure. */\r
710         p_hca_ifc = __alloc_hca_ifc( p_ext );\r
711         if( !p_hca_ifc )\r
712         {\r
713                 HCA_TRACE( HCA_DBG_ERROR, ("__alloc_hca_ifc failed.\n") );\r
714                 return STATUS_NO_MEMORY;\r
715         }\r
716 \r
717         /* Notify AL that we're available... */\r
718         ib_status = p_ext->ci_ifc.register_ca( p_hca_ifc );\r
719         ExFreePool( p_hca_ifc );\r
720         if( ib_status != IB_SUCCESS )\r
721         {\r
722                 p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
723                 return STATUS_INSUFFICIENT_RESOURCES;\r
724         }\r
725 \r
726         p_ext->state = HCA_REGISTERED;\r
727         return STATUS_SUCCESS;\r
728 }\r
729 \r
730 \r
731 //static void\r
732 //__work_item_pnp_cb(\r
733 //      IN                              DEVICE_OBJECT                           *p_dev_obj,\r
734 //      IN                              hca_work_item_context_t         *p_context )\r
735 //{\r
736 //      hca_dev_ext_t                   *p_ext;\r
737 //      NTSTATUS                                status;\r
738 //\r
739 //      HCA_ENTER( HCA_DBG_PNP );\r
740 //      \r
741 //      p_ext = p_dev_obj->DeviceExtension;\r
742 //\r
743 //      cl_event_wait_on( &p_ext->mutex, EVENT_NO_TIMEOUT, FALSE );\r
744 //      do\r
745 //      {\r
746 //              /* Check the state under protection of the mutex. */\r
747 //              if( p_ext->state != HCA_ADDED &&\r
748 //                      p_ext->state != HCA_STARTED )\r
749 //              {\r
750 //                      HCA_TRACE( HCA_DBG_ERROR, ("Invalid state.\n") );\r
751 //                      break;\r
752 //              }\r
753 //\r
754 //              ASSERT( !p_ext->p_al_dev );\r
755 //\r
756 //              /* Get the AL device object. */\r
757 //              HCA_TRACE( HCA_DBG_PNP, ("Calling IoGetDeviceObjectPointer.\n") );\r
758 //              status = IoGetDeviceObjectPointer( &p_context->sym_link_name,\r
759 //                      FILE_ALL_ACCESS, &p_ext->p_al_file_obj, &p_ext->p_al_dev );\r
760 //              if( !NT_SUCCESS( status ) )\r
761 //              {\r
762 //                      HCA_TRACE( HCA_DBG_ERROR,\r
763 //                              ("IoGetDeviceObjectPointer returned %08x.\n", status) );\r
764 //                      break;\r
765 //              }\r
766 //\r
767 //              cl_event_signal( &p_ext->mutex );\r
768 //              /* Register for removal notification of the IB Fabric root device. */\r
769 //              HCA_TRACE( HCA_DBG_PNP, \r
770 //                      ("Registering for target notifications.\n") );\r
771 //              status = IoRegisterPlugPlayNotification( \r
772 //                      EventCategoryTargetDeviceChange, 0, p_ext->p_al_file_obj, \r
773 //                      p_dev_obj->DriverObject, __pnp_notify_target, p_dev_obj, \r
774 //                      &p_ext->pnp_target_entry );\r
775 //              cl_event_wait_on( &p_ext->mutex, EVENT_NO_TIMEOUT, FALSE );\r
776 //              if( !NT_SUCCESS( status ) )\r
777 //              {\r
778 //                      ObDereferenceObject( p_ext->p_al_file_obj );\r
779 //                      HCA_TRACE( HCA_DBG_ERROR, \r
780 //                              ("IoRegisterPlugPlayNotification returned %08x.\n", status) );\r
781 //                      break;\r
782 //              }\r
783 //\r
784 //              if( p_ext->state == HCA_STARTED )\r
785 //              {\r
786 //                      /* Queue the work item again to complete the registration. */\r
787 //                      IoQueueWorkItem( p_context->p_item, __work_item_started_cb, \r
788 //                              DelayedWorkQueue, p_context->p_item );\r
789 //              }\r
790 //              else\r
791 //              {\r
792 //                      /* Free the work item. */\r
793 //                      IoFreeWorkItem( p_context->p_item );\r
794 //              }\r
795 //      } while( !p_ext );\r
796 //\r
797 //      cl_event_signal( &p_ext->mutex );\r
798 //      cl_free( p_context );\r
799 //      return;\r
800 //}\r
801 \r
802 \r
803 static NTSTATUS\r
804 __pnp_notify_ifc(\r
805         IN                              DEVICE_INTERFACE_CHANGE_NOTIFICATION    *p_notify,\r
806         IN                              void                                            *context )\r
807 {\r
808         NTSTATUS                                status;\r
809         DEVICE_OBJECT                   *p_dev_obj;\r
810         hca_dev_ext_t                   *p_ext;\r
811 \r
812         HCA_ENTER( HCA_DBG_PNP );\r
813 \r
814         p_dev_obj = context;\r
815         p_ext = p_dev_obj->DeviceExtension;\r
816 \r
817         if( !IsEqualGUID( &p_notify->Event, &GUID_DEVICE_INTERFACE_ARRIVAL ) )\r
818         {\r
819                 HCA_EXIT( HCA_DBG_PNP );\r
820                 return STATUS_SUCCESS;\r
821         }\r
822 \r
823         /*\r
824          * Sanity check.  We should only be getting notifications of the \r
825          * CI interface exported by AL.\r
826          */\r
827         ASSERT( \r
828                 IsEqualGUID( &p_notify->InterfaceClassGuid, &GUID_IB_CI_INTERFACE ) );\r
829 \r
830         if( p_ext->state != HCA_STARTED )\r
831         {\r
832                 HCA_TRACE( HCA_DBG_ERROR, ("Invalid state: %d\n", p_ext->state) );\r
833                 return STATUS_SUCCESS;\r
834         }\r
835 \r
836         ASSERT( !p_ext->p_al_dev );\r
837         ASSERT( !p_ext->p_al_file_obj );\r
838 \r
839         /* Get the AL device object. */\r
840         HCA_TRACE( HCA_DBG_PNP, ("Calling IoGetDeviceObjectPointer.\n") );\r
841         status = IoGetDeviceObjectPointer( p_notify->SymbolicLinkName,\r
842                 FILE_ALL_ACCESS, &p_ext->p_al_file_obj, &p_ext->p_al_dev );\r
843         if( !NT_SUCCESS( status ) )\r
844         {\r
845                 HCA_TRACE( HCA_DBG_ERROR,\r
846                         ("IoGetDeviceObjectPointer returned %08x.\n", status) );\r
847                 return STATUS_SUCCESS;\r
848         }\r
849 \r
850         /* Register for removal notification of the IB Fabric root device. */\r
851         HCA_TRACE( HCA_DBG_PNP, \r
852                 ("Registering for target notifications.\n") );\r
853         status = IoRegisterPlugPlayNotification( \r
854                 EventCategoryTargetDeviceChange, 0, p_ext->p_al_file_obj, \r
855                 p_dev_obj->DriverObject, __pnp_notify_target, p_dev_obj, \r
856                 &p_ext->pnp_target_entry );\r
857         if( !NT_SUCCESS( status ) )\r
858         {\r
859                 ObDereferenceObject( p_ext->p_al_file_obj );\r
860                 p_ext->p_al_file_obj = NULL;\r
861                 p_ext->p_al_dev = NULL;\r
862                 HCA_TRACE( HCA_DBG_ERROR, \r
863                         ("IoRegisterPlugPlayNotification returned %08x.\n", status) );\r
864                 return STATUS_SUCCESS;\r
865         }\r
866 \r
867         status = __hca_register( p_dev_obj );\r
868         if( !NT_SUCCESS( status ) )\r
869         {\r
870                 IoUnregisterPlugPlayNotification( p_ext->pnp_target_entry );\r
871                 p_ext->pnp_target_entry = NULL;\r
872                 ObDereferenceObject( p_ext->p_al_file_obj );\r
873                 p_ext->p_al_file_obj = NULL;\r
874                 p_ext->p_al_dev = NULL;\r
875                 HCA_TRACE( HCA_DBG_ERROR,\r
876                         ("__get_ci_interface returned %08x.\n", status) );\r
877                 return STATUS_SUCCESS;\r
878         }\r
879 \r
880         HCA_EXIT( HCA_DBG_PNP );\r
881         return STATUS_SUCCESS;\r
882 }\r
883 //\r
884 //\r
885 //static NTSTATUS\r
886 //hca_enable(\r
887 //      IN                              DEVICE_OBJECT* const            p_dev_obj )\r
888 //{\r
889 //      PIO_WORKITEM    p_item;\r
890 //      hca_dev_ext_t   *p_ext;\r
891 //\r
892 //      HCA_ENTER( HCA_DBG_PNP );\r
893 //\r
894 //      p_ext = p_dev_obj->DeviceExtension;\r
895 //\r
896 //      /* Check for the AL device reference. */\r
897 //      if( p_ext->p_al_dev )\r
898 //      {\r
899 //              __hca_register( p_dev_obj );\r
900 //      }\r
901 //      p_ext->state = HCA_STARTED;\r
902 //\r
903 //      HCA_EXIT( HCA_DBG_PNP );\r
904 //      return STATUS_SUCCESS;\r
905 //}\r
906 \r
907 \r
908 static NTSTATUS\r
909 hca_start(\r
910         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
911         IN                              IRP* const                                      p_irp, \r
912                 OUT                     cl_irp_action_t* const          p_action )\r
913 {\r
914         NTSTATUS                        status;\r
915         hca_dev_ext_t           *p_ext;\r
916         net64_t                         ca_guid = 0;\r
917         HCA_ENTER( HCA_DBG_PNP );\r
918 \r
919         /* Handled on the way up. */\r
920         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
921         if( !NT_SUCCESS( status ) )\r
922         {\r
923                 HCA_TRACE_EXIT( HCA_DBG_ERROR, \r
924                         ("Lower drivers failed IRP_MN_START_DEVICE.\n") );\r
925                 return status;\r
926         }\r
927 \r
928         p_ext = p_dev_obj->DeviceExtension;\r
929 \r
930         /* Get the HH HCA handle for this instance. */\r
931         status = __get_hca_handle( p_ext );\r
932         if( !NT_SUCCESS( status ) )\r
933         {\r
934                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
935                         ("Failed to get HH HCA handle.\n") );\r
936                 return status;\r
937         }\r
938 \r
939         /* store HCA PDO */\r
940         p_ext->hca.p_dev_obj = p_ext->cl_ext.p_pdo;\r
941         status = fw_flash_get_ca_guid(p_ext->cl_ext.p_pdo, &ca_guid);\r
942         if ( !NT_SUCCESS( status ) )\r
943         {\r
944                 HCA_TRACE( HCA_DBG_ERROR, \r
945                         ("fw_flash_get_ca_guid failed status =%#x.\n", status) );\r
946                 return status;\r
947         }\r
948         p_ext->hca.guid = ca_guid;\r
949         mlnx_hca_insert( &p_ext->hca );\r
950 \r
951         /*\r
952          * Change the state since the PnP callback can happen\r
953          * before the callback returns.\r
954          */\r
955         p_ext->state = HCA_STARTED;\r
956         /* Register for interface arrival of the IB_AL device. */\r
957         status = IoRegisterPlugPlayNotification(\r
958                 EventCategoryDeviceInterfaceChange,\r
959                 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,\r
960                 (void*)&GUID_IB_CI_INTERFACE, p_dev_obj->DriverObject,\r
961                 __pnp_notify_ifc, p_dev_obj, &p_ext->pnp_ifc_entry );\r
962         if( !NT_SUCCESS( status ) )\r
963         {\r
964                 p_ext->state = HCA_ADDED;\r
965                 HCA_TRACE( HCA_DBG_ERROR, \r
966                         ("IoRegisterPlugPlayNotification returned %08x.\n", status) );\r
967         }\r
968 \r
969         HCA_EXIT( HCA_DBG_PNP );\r
970         return status;\r
971 }\r
972 \r
973 \r
974 static void\r
975 hca_release_resources(\r
976         IN                              DEVICE_OBJECT* const            p_dev_obj )\r
977 {\r
978         hca_dev_ext_t           *p_ext;\r
979 \r
980         HCA_ENTER( HCA_DBG_PNP );\r
981 \r
982         p_ext = p_dev_obj->DeviceExtension;\r
983 \r
984         if( p_ext->state == HCA_REGISTERED )\r
985         {\r
986                 CL_ASSERT( p_ext->ci_ifc.deregister_ca );\r
987                 CL_ASSERT( p_ext->p_al_dev );\r
988                 CL_ASSERT( p_ext->p_al_file_obj );\r
989                 /* Notify AL that the CA is being removed. */\r
990                 p_ext->ci_ifc.deregister_ca( p_ext->hca.guid );\r
991                 /* Release AL's CI interface. */\r
992                 p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
993         }\r
994 \r
995         if( p_ext->pnp_target_entry )\r
996         {\r
997                 ASSERT( p_ext->pnp_ifc_entry );\r
998                 IoUnregisterPlugPlayNotification( p_ext->pnp_target_entry );\r
999         }\r
1000 \r
1001         if( p_ext->pnp_ifc_entry )\r
1002                 IoUnregisterPlugPlayNotification( p_ext->pnp_ifc_entry );\r
1003 \r
1004         if( p_ext->p_al_file_obj )\r
1005                 ObDereferenceObject( p_ext->p_al_file_obj );\r
1006 \r
1007         //cl_event_destroy( &p_ext->mutex );\r
1008 \r
1009         HCA_EXIT( HCA_DBG_PNP );\r
1010 }\r
1011 //\r
1012 //\r
1013 //static NTSTATUS\r
1014 //hca_disable(\r
1015 //      IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
1016 //{\r
1017 //      hca_dev_ext_t   *p_ext;\r
1018 //\r
1019 //      HCA_ENTER( HCA_DBG_PNP );\r
1020 //\r
1021 //      p_ext = p_dev_obj->DeviceExtension;\r
1022 //\r
1023 //      ASSERT( p_ext->state == HCA_STARTED );\r
1024 //\r
1025 //      if( p_ext->state = HCA_REGISTERED )\r
1026 //      {\r
1027 //              /* Notify AL that the CA is being removed. */\r
1028 //              p_ext->ci_ifc.deregister_ca( p_ext->hca.guid );\r
1029 //              /* Release AL's CI interface. */\r
1030 //              p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
1031 //\r
1032 //              p_ext->state = HCA_STARTED;\r
1033 //      }\r
1034 //\r
1035 //      HCA_EXIT( HCA_DBG_PNP );\r
1036 //      return STATUS_SUCCESS;\r
1037 //}\r
1038 //\r
1039 //\r
1040 //static NTSTATUS\r
1041 //hca_deactivate(\r
1042 //      IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1043 //      IN                                      IRP* const                              p_irp, \r
1044 //              OUT                             cl_irp_action_t* const  p_action )\r
1045 //{\r
1046 //      NTSTATUS        status;\r
1047 //      hca_dev_ext_t   *p_ext;\r
1048 //\r
1049 //      HCA_ENTER( HCA_DBG_PNP );\r
1050 //\r
1051 //      UNUSED_PARAM( p_irp );\r
1052 //\r
1053 //      p_ext = p_dev_obj->DeviceExtension;\r
1054 //\r
1055 //      *p_action = IrpSkip;\r
1056 //\r
1057 //      status = hca_disable( p_dev_obj );\r
1058 //\r
1059 //      mlnx_hca_remove( &p_ext->hca );\r
1060 //\r
1061 //      p_ext->hca.hh_hndl = NULL;\r
1062 //\r
1063 //      p_ext->state = HCA_ADDED;\r
1064 //\r
1065 //      HCA_EXIT( HCA_DBG_PNP );\r
1066 //      return status;\r
1067 //}\r
1068 \r
1069 \r
1070 static NTSTATUS\r
1071 hca_query_bus_relations(\r
1072         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1073         IN                                      IRP* const                              p_irp, \r
1074                 OUT                             cl_irp_action_t* const  p_action )\r
1075 {\r
1076         NTSTATUS                        status;\r
1077         DEVICE_RELATIONS        *p_rel;\r
1078         hca_dev_ext_t           *p_ext;\r
1079 \r
1080         HCA_ENTER( HCA_DBG_PNP );\r
1081 \r
1082         p_ext = p_dev_obj->DeviceExtension;\r
1083 \r
1084         //cl_event_wait_on( &p_ext->mutex, EVENT_NO_TIMEOUT, FALSE );\r
1085         if( p_ext->state == HCA_REGISTERED )\r
1086         {\r
1087                 status = p_ext->ci_ifc.get_relations( p_ext->hca.guid, p_irp );\r
1088                 if( !NT_SUCCESS( status ) )\r
1089                 {\r
1090                         //cl_event_signal( &p_ext->mutex );\r
1091                         *p_action = IrpComplete;\r
1092                         HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
1093                                 ("AL get_relations returned %08x.\n", status) );\r
1094                         return status;\r
1095                 }\r
1096         }\r
1097         else\r
1098         {\r
1099                 status = cl_alloc_relations( p_irp, 1 );\r
1100                 if( !NT_SUCCESS( status ) )\r
1101                 {\r
1102                         HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
1103                                 ("cl_alloc_relations returned %08x.\n", status) );\r
1104                         return status;\r
1105                 }\r
1106 \r
1107                 p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
1108                 p_rel->Count = 0;\r
1109                 p_rel->Objects[0] = NULL;\r
1110         }\r
1111 \r
1112         //cl_event_signal( &p_ext->mutex );\r
1113 \r
1114         *p_action = IrpPassDown;\r
1115         HCA_EXIT( HCA_DBG_PNP );\r
1116         return STATUS_SUCCESS;\r
1117 }\r
1118 \r
1119 \r
1120 static NTSTATUS\r
1121 hca_set_power(\r
1122         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1123         IN                              IRP* const                                      p_irp, \r
1124                 OUT                     cl_irp_action_t* const          p_action )\r
1125 {\r
1126         NTSTATUS                        status;\r
1127         hca_dev_ext_t           *p_ext;\r
1128         IO_STACK_LOCATION       *p_io_stack;\r
1129 \r
1130         HCA_ENTER( HCA_DBG_PNP );\r
1131 \r
1132         p_ext = p_dev_obj->DeviceExtension;\r
1133 \r
1134         *p_action = IrpSkip;\r
1135 \r
1136         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1137 \r
1138         if( p_io_stack->Parameters.Power.Type != DevicePowerState )\r
1139                 return STATUS_SUCCESS;\r
1140 \r
1141         switch( p_io_stack->Parameters.Power.State.DeviceState )\r
1142         {\r
1143         case PowerDeviceD0:\r
1144                 if( p_ext->p_al_dev )\r
1145                         status = __hca_register( p_dev_obj );\r
1146                 else\r
1147                         status = STATUS_SUCCESS;\r
1148                 break;\r
1149 \r
1150         default:\r
1151                 if( p_ext->state == HCA_REGISTERED )\r
1152                 {\r
1153                         /* Notify AL that the CA is being removed. */\r
1154                         p_ext->ci_ifc.deregister_ca( p_ext->hca.guid );\r
1155                         /* Release AL's CI interface. */\r
1156                         p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
1157 \r
1158                         p_ext->state = HCA_STARTED;\r
1159                 }\r
1160                 status = STATUS_SUCCESS;\r
1161                 break;\r
1162         }\r
1163 \r
1164         if( !NT_SUCCESS( status ) )\r
1165                 *p_action = IrpComplete;\r
1166 \r
1167         HCA_EXIT( HCA_DBG_PNP );\r
1168         return status;\r
1169 }\r
1170 \r
1171 typedef struct Primary_Sector{\r
1172         uint32_t fi_addr;\r
1173         uint32_t fi_size;\r
1174         uint32_t signature;\r
1175         uint32_t fw_reserved[5];\r
1176         uint32_t vsd[56];\r
1177         uint32_t branch_to;\r
1178         uint32_t crc016;\r
1179 } primary_sector_t;\r
1180 \r
1181 static uint32_t old_dir;\r
1182 static uint32_t old_pol;\r
1183 static uint32_t old_mod;\r
1184 static uint32_t old_dat;\r
1185 \r
1186 static NTSTATUS\r
1187 fw_access_pciconf (\r
1188                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1189                 IN              ULONG                                                   op_flag,\r
1190                 IN              PVOID                                                   p_buffer,\r
1191                 IN              ULONG                                                   offset,\r
1192                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1193 {\r
1194 \r
1195         ULONG                           bytes;  \r
1196         NTSTATUS                        status = STATUS_SUCCESS;\r
1197 \r
1198         PAGED_CODE();\r
1199 \r
1200         if (p_BusInterface)\r
1201         {\r
1202 \r
1203                 bytes = p_BusInterface->SetBusData(\r
1204                                                 p_BusInterface->Context,\r
1205                                                 PCI_WHICHSPACE_CONFIG,\r
1206                                                 (PVOID)&offset,\r
1207                                                 PCI_CONF_ADDR,\r
1208                                                 sizeof(ULONG) );\r
1209 \r
1210                 if( op_flag == 0 )\r
1211                 {\r
1212                         if ( bytes )\r
1213                                 bytes = p_BusInterface->GetBusData(\r
1214                                                         p_BusInterface->Context,\r
1215                                                         PCI_WHICHSPACE_CONFIG,\r
1216                                                         p_buffer,\r
1217                                                         PCI_CONF_DATA,\r
1218                                                         length );\r
1219                         if ( !bytes )\r
1220                                 status = STATUS_NOT_SUPPORTED;\r
1221                 }\r
1222 \r
1223                 else\r
1224                 {\r
1225                         if ( bytes )\r
1226                                 bytes = p_BusInterface->SetBusData(\r
1227                                                         p_BusInterface->Context,\r
1228                                                         PCI_WHICHSPACE_CONFIG,\r
1229                                                         p_buffer,\r
1230                                                         PCI_CONF_DATA,\r
1231                                                         length);\r
1232 \r
1233                         if ( !bytes )\r
1234                                 status = STATUS_NOT_SUPPORTED;\r
1235                 }\r
1236         }\r
1237         return status;\r
1238 }\r
1239 \r
1240 static NTSTATUS\r
1241 fw_get_pci_bus_interface(\r
1242         IN              DEVICE_OBJECT                           *p_dev_obj,\r
1243         OUT             BUS_INTERFACE_STANDARD          *p_BusInterface )\r
1244 {\r
1245         KEVENT event;\r
1246         NTSTATUS status;\r
1247         PIRP p_irp;\r
1248         IO_STATUS_BLOCK ioStatus;\r
1249         PIO_STACK_LOCATION p_irpStack;\r
1250         PDEVICE_OBJECT p_target_obj;\r
1251 \r
1252         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
1253 \r
1254         p_target_obj = IoGetAttachedDeviceReference( p_dev_obj );\r
1255 \r
1256         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,\r
1257                                                                                 p_target_obj,\r
1258                                                                                 NULL,\r
1259                                                                                 0,\r
1260                                                                                 NULL,\r
1261                                                                                 &event,\r
1262                                                                                 &ioStatus );\r
1263         if (p_irp == NULL) {\r
1264                 status = STATUS_INSUFFICIENT_RESOURCES;\r
1265                 goto End;\r
1266         }\r
1267         p_irpStack = IoGetNextIrpStackLocation( p_irp );\r
1268         p_irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
1269         p_irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;\r
1270         p_irpStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);\r
1271         p_irpStack->Parameters.QueryInterface.Version = 1;\r
1272         p_irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) p_BusInterface;\r
1273         p_irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;\r
1274 \r
1275         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
1276         \r
1277         status = IoCallDriver( p_target_obj, p_irp );\r
1278 \r
1279         if ( status == STATUS_PENDING )\r
1280         {\r
1281                 KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );\r
1282                 status = ioStatus.Status;\r
1283         }\r
1284 End:\r
1285         // Done with reference\r
1286         ObDereferenceObject( p_target_obj );\r
1287         return status;\r
1288 }\r
1289 \r
1290 ib_api_status_t\r
1291 fw_access_ctrl(\r
1292         IN              const   void* __ptr64                           p_context,\r
1293         IN              const   void* __ptr64* const            handle_array    OPTIONAL,\r
1294         IN                              uint32_t                                        num_handles,\r
1295         IN                              ib_ci_op_t* const                       p_ci_op,\r
1296         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
1297 {\r
1298         DEVICE_OBJECT                           *p_dev_obj;\r
1299         static BUS_INTERFACE_STANDARD    BusInterface;\r
1300         static uint32_t                         if_ready;\r
1301         NTSTATUS                                        status;\r
1302         PVOID                                           p_data;\r
1303         ULONG                                           offset;\r
1304         ULONG POINTER_ALIGNMENT         length;\r
1305         ib_ci_op_t                                      *p_ci;\r
1306         mlnx_hob_t                                      *p_hob;\r
1307 \r
1308         UNREFERENCED_PARAMETER(handle_array);\r
1309         UNREFERENCED_PARAMETER(num_handles);\r
1310         UNREFERENCED_PARAMETER(p_umv_buf);\r
1311 \r
1312         status =  STATUS_SUCCESS;\r
1313         if( p_umv_buf )\r
1314                 p_hob = ((mlnx_um_ca_t* __ptr64)p_context)->hob_p;\r
1315         else\r
1316                 p_hob = (mlnx_hob_t *)(const void *)p_context;\r
1317 \r
1318         p_dev_obj = (DEVICE_OBJECT *)(const void *)p_hob->p_dev_obj;\r
1319         p_ci =  p_ci_op;\r
1320 \r
1321         if ( !p_ci )\r
1322                 return STATUS_INVALID_DEVICE_REQUEST;\r
1323         if ( !p_ci->buf_size )\r
1324                 return STATUS_INVALID_DEVICE_REQUEST;\r
1325 \r
1326         length = p_ci->buf_size;\r
1327         offset = p_ci->buf_info;\r
1328         p_data = p_ci->p_buf;\r
1329 \r
1330         switch ( p_ci->command )\r
1331         {\r
1332                 case    FW_READ: // read data from flash\r
1333                                 if ( if_ready )\r
1334                                 {\r
1335                                         status = fw_flash_read_data(&BusInterface, p_data, offset, length);\r
1336                                 }\r
1337                                 break;\r
1338                 case    FW_WRITE: // write data to flash\r
1339                                 if ( if_ready )\r
1340                                 {\r
1341 \r
1342                                         status = fw_flash_write_data(&BusInterface, p_data, offset, length);\r
1343                                 }\r
1344                                 break;\r
1345                 case    FW_READ_CMD:\r
1346                                 if ( if_ready )\r
1347                                 {\r
1348                                         status = fw_access_pciconf(&BusInterface, 0 , p_data, offset, 4);\r
1349                                 }\r
1350                                 break;\r
1351                 case    FW_WRITE_CMD:\r
1352                                 if ( if_ready )\r
1353                                 {\r
1354                                         status = fw_access_pciconf(&BusInterface, 1 , p_data, offset, 4);\r
1355                                 }\r
1356                                 break;\r
1357                 case    FW_CLOSE_IF: // close BusInterface\r
1358                                 if (if_ready )\r
1359                                 {\r
1360                                         if_ready = 0;\r
1361                                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1362                                 }\r
1363                                 return status;\r
1364                 case    FW_OPEN_IF: // open BusInterface\r
1365                                 if ( !if_ready )\r
1366                                 {\r
1367                                         status = fw_get_pci_bus_interface(p_dev_obj, &BusInterface);\r
1368                                 \r
1369                                         if ( NT_SUCCESS( status ) )\r
1370                                         {\r
1371                                                 if_ready = 1;\r
1372                                                 status = STATUS_SUCCESS;\r
1373                                         }\r
1374                                 }\r
1375                                 return status;\r
1376                 default:\r
1377                                 status = STATUS_NOT_SUPPORTED;\r
1378         }\r
1379 \r
1380         if ( status != STATUS_SUCCESS )\r
1381         {\r
1382                 if ( if_ready )\r
1383                 {\r
1384                         if_ready = 0;\r
1385                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1386                 }\r
1387                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
1388                         ("fw_access_ctrl failed returns %08x.\n", status) );\r
1389         }\r
1390         return status;\r
1391 }\r
1392 \r
1393 static NTSTATUS\r
1394 fw_flash_write_data (\r
1395                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1396                 IN              PVOID                                                   p_buffer,\r
1397                 IN              ULONG                                                   offset,\r
1398                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1399 {\r
1400         NTSTATUS                status;\r
1401         uint32_t                cnt = 0;\r
1402         uint32_t                lcl_data;\r
1403 \r
1404         lcl_data = (*((uint32_t*)p_buffer) << 24);\r
1405 \r
1406         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET+4, length );\r
1407         if ( status != STATUS_SUCCESS )\r
1408                 return status;\r
1409         lcl_data = ( WRITE_BIT | (offset & ADDR_MSK));\r
1410                 \r
1411         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET, 4 );\r
1412         if ( status != STATUS_SUCCESS )\r
1413         return status;\r
1414 \r
1415         lcl_data = 0;\r
1416         \r
1417         do\r
1418         {\r
1419                 if (++cnt > 5000)\r
1420                 {\r
1421                         return STATUS_DEVICE_NOT_READY;\r
1422                 }\r
1423 \r
1424                 status = fw_access_pciconf(p_BusInterface, FW_READ , &lcl_data, FLASH_OFFSET, 4 );\r
1425                 if ( status != STATUS_SUCCESS )\r
1426                 return status;\r
1427 \r
1428         } while(lcl_data & CMD_MASK);\r
1429 \r
1430         return status;\r
1431 }\r
1432 \r
1433 static NTSTATUS\r
1434 fw_flash_read_data (\r
1435                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1436                 IN              PVOID                                                   p_buffer,\r
1437                 IN              ULONG                                                   offset,\r
1438                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1439 {\r
1440         NTSTATUS        status = STATUS_SUCCESS;\r
1441         uint32_t        cnt = 0;\r
1442         uint32_t        lcl_data = ( READ_BIT | (offset & ADDR_MSK));\r
1443         \r
1444         status = fw_access_pciconf(p_BusInterface, FW_WRITE, &lcl_data, FLASH_OFFSET, 4 );\r
1445         if ( status != STATUS_SUCCESS )\r
1446                 return status;\r
1447 \r
1448         lcl_data = 0;\r
1449         do\r
1450         {\r
1451                 // Timeout checks\r
1452                 if (++cnt > 5000 )\r
1453                 {\r
1454                         return STATUS_DEVICE_NOT_READY;\r
1455         }\r
1456 \r
1457                 status = fw_access_pciconf(p_BusInterface, FW_READ, &lcl_data, FLASH_OFFSET, 4 );\r
1458         \r
1459                 if ( status != STATUS_SUCCESS )\r
1460                         return status;\r
1461 \r
1462         } while(lcl_data & CMD_MASK);\r
1463 \r
1464         status = fw_access_pciconf(p_BusInterface, FW_READ, p_buffer, FLASH_OFFSET+4, length );\r
1465         return status;\r
1466 }\r
1467 \r
1468 static NTSTATUS\r
1469 fw_flash_get_ca_guid(\r
1470                 IN              DEVICE_OBJECT           *p_dev_obj,\r
1471                 OUT             net64_t                 *ca_guid )\r
1472 {\r
1473         NTSTATUS                status = STATUS_SUCCESS;\r
1474         BUS_INTERFACE_STANDARD          BusInterface;\r
1475 \r
1476     uint32_t NODE_GUIDH, NODE_GUIDL;\r
1477         uint32_t prim_ptr = 0;\r
1478     uint32_t signature;\r
1479 \r
1480         primary_sector_t        ps;\r
1481         cl_memset( &ps, 0, sizeof(primary_sector_t));\r
1482 \r
1483         status = fw_get_pci_bus_interface(p_dev_obj, &BusInterface);\r
1484 \r
1485         if ( !NT_SUCCESS( status ) )\r
1486                 return status;\r
1487         \r
1488         status = fw_flash_init (&BusInterface);\r
1489         if (status != STATUS_SUCCESS )\r
1490                 return status;\r
1491     status = fw_flash_read_data(&BusInterface, &signature, 0x24, 4); \r
1492         if (status != STATUS_SUCCESS )\r
1493                 return status;\r
1494     //signature = cl_ntoh32(signature);\r
1495 \r
1496     if (signature == FW_SIGNATURE)\r
1497     {\r
1498        //Fail Safe image\r
1499         \r
1500         // Assume flash has been verified, and both images have the same guids, therefore,\r
1501         // we only need to read the primary image's guids\r
1502         status = fw_flash_readbuf(&BusInterface, FW_SECT_SIZE, &ps, sizeof(ps));\r
1503                 if ( status == STATUS_SUCCESS )\r
1504                 {\r
1505                         status = fw_flash_read_data(&BusInterface, &prim_ptr, ps.fi_addr+0x24, 4);\r
1506                         if (status == STATUS_SUCCESS )\r
1507                                 prim_ptr = prim_ptr + ps.fi_addr;\r
1508                 }\r
1509     }\r
1510     else\r
1511     {\r
1512         // Short image\r
1513         prim_ptr = signature;       \r
1514     }\r
1515 \r
1516     if ( signature == FW_SIGNATURE || prim_ptr < MAX_FLASH_SIZE )\r
1517     {\r
1518                 /* now we can read ca guid\r
1519                  * since we read it in host mode fw_flash_read4() \r
1520                  * swaps it back in BE - how it was stored in FW\r
1521                  */\r
1522         if (( status = fw_flash_read4(&BusInterface, prim_ptr, &NODE_GUIDL)) == STATUS_SUCCESS )\r
1523                         if (( status = fw_flash_read4(&BusInterface, prim_ptr+4, &NODE_GUIDH)) == STATUS_SUCCESS )\r
1524                         {\r
1525                                 *ca_guid = NODE_GUIDH;\r
1526                                 *ca_guid = (*ca_guid << 32) | NODE_GUIDL;\r
1527                         }\r
1528         }\r
1529         else \r
1530     {\r
1531         //invalid GUID pointer\r
1532         return STATUS_NO_SUCH_DEVICE;\r
1533     }\r
1534         fw_flash_deinit(&BusInterface);\r
1535         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1536     return status;\r
1537 }\r
1538 \r
1539 static NTSTATUS\r
1540 fw_flash_read4( \r
1541         IN                      BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1542         IN                      uint32_t                                addr, \r
1543         IN      OUT             uint32_t                                *p_data)\r
1544 {\r
1545         NTSTATUS        status = STATUS_SUCCESS;\r
1546         uint32_t lcl_data = 0;\r
1547         uint32_t bank;\r
1548         static uint32_t curr_bank =     0xffffffff;\r
1549 \r
1550         if (addr & 0x3)\r
1551                 return STATUS_INVALID_PARAMETER;\r
1552 \r
1553         bank = addr & BANK_MASK;\r
1554         if (bank !=  curr_bank)\r
1555         {\r
1556                 curr_bank = bank;\r
1557                 if ((status = fw_set_bank(p_BusInterface, bank)) != STATUS_SUCCESS )\r
1558                         return STATUS_INVALID_PARAMETER;\r
1559         }\r
1560         status = fw_flash_read_data(p_BusInterface, &lcl_data, addr, 4);\r
1561         *p_data = cl_ntoh32(lcl_data);\r
1562         return STATUS_SUCCESS;\r
1563 }\r
1564 \r
1565 static NTSTATUS\r
1566 fw_flash_readbuf(\r
1567                 IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1568                 IN              uint32_t                                offset,\r
1569                 IN OUT  void                                    *p_data,\r
1570                 IN              uint32_t                                len)\r
1571 {\r
1572         NTSTATUS        status = STATUS_SUCCESS;\r
1573         uint32_t *p_lcl_data;\r
1574         uint32_t        i;\r
1575 \r
1576     if (offset & 0x3)\r
1577     {\r
1578         //Address should be 4-bytes aligned\r
1579         return STATUS_INVALID_PARAMETER;\r
1580     }\r
1581     if (len & 0x3)\r
1582     {\r
1583         //Length should be 4-bytes aligned\r
1584         return STATUS_INVALID_PARAMETER;\r
1585     }\r
1586     p_lcl_data = (uint32_t *)p_data;\r
1587     \r
1588         for ( i=0; i < (len >> 2); i++)\r
1589     {                                   \r
1590         if ( (status = fw_flash_read_data( p_BusInterface, p_lcl_data, offset, sizeof(uint32_t) )) != STATUS_SUCCESS )\r
1591             return status;\r
1592         offset += 4;\r
1593                 p_lcl_data++;\r
1594     }\r
1595     return STATUS_SUCCESS;\r
1596 } // Flash::flash_read\r
1597 \r
1598 static NTSTATUS\r
1599 fw_flash_writebuf(\r
1600                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1601                 IN              PVOID                                                   p_buffer,\r
1602                 IN              ULONG                                                   offset,\r
1603                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1604 {\r
1605         NTSTATUS status = STATUS_SUCCESS;\r
1606         uint32_t        i;\r
1607         uint8_t *p_data = (uint8_t *)p_buffer;\r
1608 \r
1609         for ( i = 0; i < length;  i++ )\r
1610         {\r
1611                 status = fw_flash_write_data (p_BusInterface, p_data, offset, 1 );\r
1612                 if (status != STATUS_SUCCESS )\r
1613                         return status;\r
1614                 p_data++;\r
1615                 offset++;\r
1616         }\r
1617         return status;\r
1618 }\r
1619 static NTSTATUS\r
1620 fw_flash_init(\r
1621                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  )\r
1622 {\r
1623         uint32_t dir;\r
1624     uint32_t pol;\r
1625     uint32_t mod;\r
1626 \r
1627     uint32_t cnt=0;\r
1628     uint32_t data;\r
1629         NTSTATUS status = STATUS_SUCCESS;\r
1630         uint32_t        semaphore = 0;\r
1631     \r
1632         while ( !semaphore )\r
1633         {\r
1634                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, SEMAP63, 4);\r
1635                 if ( status != STATUS_SUCCESS )\r
1636                         break;\r
1637                 if( !data )\r
1638                 {\r
1639                         semaphore = 1;\r
1640                         break;\r
1641                 }\r
1642         if (++cnt > 5000 )\r
1643         {\r
1644             break;\r
1645         }\r
1646     } \r
1647 \r
1648         if ( !semaphore )\r
1649         {\r
1650                 return STATUS_NOT_SUPPORTED;\r
1651         }\r
1652 \r
1653     // Save old values\r
1654     \r
1655         status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dir,GPIO_DIR_L , 4);\r
1656         if ( status == STATUS_SUCCESS )\r
1657                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_pol,GPIO_POL_L , 4);\r
1658         if ( status == STATUS_SUCCESS )\r
1659                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_mod,GPIO_MOD_L , 4);\r
1660         if ( status == STATUS_SUCCESS )\r
1661                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dat,GPIO_DAT_L , 4);\r
1662 \r
1663    // Set Direction=1, Polarity=0, Mode=0 for 3 GPIO lower bits\r
1664     dir = old_dir | 0x70;\r
1665     pol = old_pol & ~0x70;\r
1666     mod = old_mod & ~0x70;\r
1667 \r
1668         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &dir,GPIO_DIR_L , 4);\r
1669         if ( status == STATUS_SUCCESS )\r
1670                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &pol,GPIO_POL_L , 4);\r
1671         if ( status == STATUS_SUCCESS )\r
1672                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &mod,GPIO_MOD_L , 4);\r
1673         if ( status == STATUS_SUCCESS )\r
1674                 // Set CPUMODE\r
1675                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, CPUMODE, 4);\r
1676     if ( status == STATUS_SUCCESS )\r
1677         {\r
1678                 data &= ~CPUMODE_MSK;\r
1679                 data |= 1 << CPUMODE_SHIFT;\r
1680                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, CPUMODE, 4);\r
1681         }\r
1682         if ( status == STATUS_SUCCESS )\r
1683         {\r
1684                 // Reset flash\r
1685                 data = 0xf0;\r
1686                 status = fw_flash_write_data(p_BusInterface, &data, 0x0, 4);\r
1687         }\r
1688         return status;\r
1689 }\r
1690 \r
1691 static NTSTATUS\r
1692 fw_flash_deinit(\r
1693         IN              BUS_INTERFACE_STANDARD  *p_BusInterface )\r
1694 {\r
1695         uint32_t data = 0;\r
1696         NTSTATUS status = STATUS_SUCCESS;\r
1697     \r
1698         status = fw_set_bank(p_BusInterface, 0);\r
1699         if ( status == STATUS_SUCCESS )\r
1700                 // Restore origin values\r
1701                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dir,GPIO_DIR_L , 4);\r
1702         if ( status == STATUS_SUCCESS )\r
1703                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_pol,GPIO_POL_L , 4);\r
1704         if ( status == STATUS_SUCCESS )\r
1705                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_mod,GPIO_MOD_L , 4);\r
1706         if ( status == STATUS_SUCCESS )\r
1707                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dat,GPIO_DAT_L , 4);\r
1708         if ( status == STATUS_SUCCESS )\r
1709                 // Free GPIO Semaphore\r
1710                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, SEMAP63, 4);\r
1711         return status;\r
1712 }\r
1713 \r
1714 static NTSTATUS\r
1715 fw_set_bank(\r
1716         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1717         IN               uint32_t bank )\r
1718 {\r
1719         NTSTATUS  status = STATUS_SUCCESS;\r
1720         uint32_t        data = ( (uint32_t)0x70 << 24 );\r
1721         uint32_t        mask = ((bank >> (BANK_SHIFT-4)) << 24 );\r
1722 \r
1723         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATACLEAR_L, 4);\r
1724         if (status == STATUS_SUCCESS)\r
1725         {\r
1726         // A1\r
1727                 data &= mask;\r
1728                 //data |= mask; // for A0\r
1729                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATASET_L, 4);\r
1730         }\r
1731         return status;\r
1732 }\r