Make kernel complib static
[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         p_hob = (mlnx_hob_t *)(const void *)p_context;\r
1314 \r
1315         p_dev_obj = (DEVICE_OBJECT *)(const void *)p_hob->p_dev_obj;\r
1316         p_ci =  p_ci_op;\r
1317 \r
1318         if ( !p_ci )\r
1319                 return STATUS_INVALID_DEVICE_REQUEST;\r
1320         if ( !p_ci->buf_size )\r
1321                 return STATUS_INVALID_DEVICE_REQUEST;\r
1322 \r
1323         length = p_ci->buf_size;\r
1324         offset = p_ci->buf_info;\r
1325         p_data = p_ci->p_buf;\r
1326 \r
1327         switch ( p_ci->command )\r
1328         {\r
1329                 case    FW_READ: // read data from flash\r
1330                                 if ( if_ready )\r
1331                                 {\r
1332                                         status = fw_flash_read_data(&BusInterface, p_data, offset, length);\r
1333                                 }\r
1334                                 break;\r
1335                 case    FW_WRITE: // write data to flash\r
1336                                 if ( if_ready )\r
1337                                 {\r
1338 \r
1339                                         status = fw_flash_write_data(&BusInterface, p_data, offset, length);\r
1340                                 }\r
1341                                 break;\r
1342                 case    FW_READ_CMD:\r
1343                                 if ( if_ready )\r
1344                                 {\r
1345                                         status = fw_access_pciconf(&BusInterface, 0 , p_data, offset, 4);\r
1346                                 }\r
1347                                 break;\r
1348                 case    FW_WRITE_CMD:\r
1349                                 if ( if_ready )\r
1350                                 {\r
1351                                         status = fw_access_pciconf(&BusInterface, 1 , p_data, offset, 4);\r
1352                                 }\r
1353                                 break;\r
1354                 case    FW_CLOSE_IF: // close BusInterface\r
1355                                 if (if_ready )\r
1356                                 {\r
1357                                         if_ready = 0;\r
1358                                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1359                                 }\r
1360                                 return status;\r
1361                 case    FW_OPEN_IF: // open BusInterface\r
1362                                 if ( !if_ready )\r
1363                                 {\r
1364                                         status = fw_get_pci_bus_interface(p_dev_obj, &BusInterface);\r
1365                                 \r
1366                                         if ( NT_SUCCESS( status ) )\r
1367                                         {\r
1368                                                 if_ready = 1;\r
1369                                                 status = STATUS_SUCCESS;\r
1370                                         }\r
1371                                 }\r
1372                                 return status;\r
1373                 default:\r
1374                                 status = STATUS_NOT_SUPPORTED;\r
1375         }\r
1376 \r
1377         if ( status != STATUS_SUCCESS )\r
1378         {\r
1379                 if ( if_ready )\r
1380                 {\r
1381                         if_ready = 0;\r
1382                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1383                 }\r
1384                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
1385                         ("fw_access_ctrl failed returns %08x.\n", status) );\r
1386         }\r
1387         return status;\r
1388 }\r
1389 \r
1390 static NTSTATUS\r
1391 fw_flash_write_data (\r
1392                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1393                 IN              PVOID                                                   p_buffer,\r
1394                 IN              ULONG                                                   offset,\r
1395                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1396 {\r
1397         NTSTATUS                status;\r
1398         uint32_t                cnt = 0;\r
1399         uint32_t                lcl_data;\r
1400 \r
1401         lcl_data = (*((uint32_t*)p_buffer) << 24);\r
1402 \r
1403         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET+4, length );\r
1404         if ( status != STATUS_SUCCESS )\r
1405                 return status;\r
1406         lcl_data = ( WRITE_BIT | (offset & ADDR_MSK));\r
1407                 \r
1408         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET, 4 );\r
1409         if ( status != STATUS_SUCCESS )\r
1410         return status;\r
1411 \r
1412         lcl_data = 0;\r
1413         \r
1414         do\r
1415         {\r
1416                 if (++cnt > 5000)\r
1417                 {\r
1418                         return STATUS_DEVICE_NOT_READY;\r
1419                 }\r
1420 \r
1421                 status = fw_access_pciconf(p_BusInterface, FW_READ , &lcl_data, FLASH_OFFSET, 4 );\r
1422                 if ( status != STATUS_SUCCESS )\r
1423                 return status;\r
1424 \r
1425         } while(lcl_data & CMD_MASK);\r
1426 \r
1427         return status;\r
1428 }\r
1429 \r
1430 static NTSTATUS\r
1431 fw_flash_read_data (\r
1432                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1433                 IN              PVOID                                                   p_buffer,\r
1434                 IN              ULONG                                                   offset,\r
1435                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1436 {\r
1437         NTSTATUS        status = STATUS_SUCCESS;\r
1438         uint32_t        cnt = 0;\r
1439         uint32_t        lcl_data = ( READ_BIT | (offset & ADDR_MSK));\r
1440         \r
1441         status = fw_access_pciconf(p_BusInterface, FW_WRITE, &lcl_data, FLASH_OFFSET, 4 );\r
1442         if ( status != STATUS_SUCCESS )\r
1443                 return status;\r
1444 \r
1445         lcl_data = 0;\r
1446         do\r
1447         {\r
1448                 // Timeout checks\r
1449                 if (++cnt > 5000 )\r
1450                 {\r
1451                         return STATUS_DEVICE_NOT_READY;\r
1452         }\r
1453 \r
1454                 status = fw_access_pciconf(p_BusInterface, FW_READ, &lcl_data, FLASH_OFFSET, 4 );\r
1455         \r
1456                 if ( status != STATUS_SUCCESS )\r
1457                         return status;\r
1458 \r
1459         } while(lcl_data & CMD_MASK);\r
1460 \r
1461         status = fw_access_pciconf(p_BusInterface, FW_READ, p_buffer, FLASH_OFFSET+4, length );\r
1462         return status;\r
1463 }\r
1464 \r
1465 static NTSTATUS\r
1466 fw_flash_get_ca_guid(\r
1467                 IN              DEVICE_OBJECT           *p_dev_obj,\r
1468                 OUT             net64_t                 *ca_guid )\r
1469 {\r
1470         NTSTATUS                status = STATUS_SUCCESS;\r
1471         BUS_INTERFACE_STANDARD          BusInterface;\r
1472 \r
1473     uint32_t NODE_GUIDH, NODE_GUIDL;\r
1474         uint32_t prim_ptr = 0;\r
1475     uint32_t signature;\r
1476 \r
1477         primary_sector_t        ps;\r
1478         cl_memset( &ps, 0, sizeof(primary_sector_t));\r
1479 \r
1480         status = fw_get_pci_bus_interface(p_dev_obj, &BusInterface);\r
1481 \r
1482         if ( !NT_SUCCESS( status ) )\r
1483                 return status;\r
1484         \r
1485         status = fw_flash_init (&BusInterface);\r
1486         if (status != STATUS_SUCCESS )\r
1487                 return status;\r
1488     status = fw_flash_read_data(&BusInterface, &signature, 0x24, 4); \r
1489         if (status != STATUS_SUCCESS )\r
1490                 return status;\r
1491     //signature = cl_ntoh32(signature);\r
1492 \r
1493     if (signature == FW_SIGNATURE)\r
1494     {\r
1495        //Fail Safe image\r
1496         \r
1497         // Assume flash has been verified, and both images have the same guids, therefore,\r
1498         // we only need to read the primary image's guids\r
1499         status = fw_flash_readbuf(&BusInterface, FW_SECT_SIZE, &ps, sizeof(ps));\r
1500                 if ( status == STATUS_SUCCESS )\r
1501                 {\r
1502                         status = fw_flash_read_data(&BusInterface, &prim_ptr, ps.fi_addr+0x24, 4);\r
1503                         if (status == STATUS_SUCCESS )\r
1504                                 prim_ptr = prim_ptr + ps.fi_addr;\r
1505                 }\r
1506     }\r
1507     else\r
1508     {\r
1509         // Short image\r
1510         prim_ptr = signature;       \r
1511     }\r
1512 \r
1513     if ( signature == FW_SIGNATURE || prim_ptr < MAX_FLASH_SIZE )\r
1514     {\r
1515                 /* now we can read ca guid\r
1516                  * since we read it in host mode fw_flash_read4() \r
1517                  * swaps it back in BE - how it was stored in FW\r
1518                  */\r
1519         if (( status = fw_flash_read4(&BusInterface, prim_ptr, &NODE_GUIDL)) == STATUS_SUCCESS )\r
1520                         if (( status = fw_flash_read4(&BusInterface, prim_ptr+4, &NODE_GUIDH)) == STATUS_SUCCESS )\r
1521                         {\r
1522                                 *ca_guid = NODE_GUIDH;\r
1523                                 *ca_guid = (*ca_guid << 32) | NODE_GUIDL;\r
1524                         }\r
1525         }\r
1526         else \r
1527     {\r
1528         //invalid GUID pointer\r
1529         return STATUS_NO_SUCH_DEVICE;\r
1530     }\r
1531         fw_flash_deinit(&BusInterface);\r
1532         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1533     return status;\r
1534 }\r
1535 \r
1536 static NTSTATUS\r
1537 fw_flash_read4( \r
1538         IN                      BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1539         IN                      uint32_t                                addr, \r
1540         IN      OUT             uint32_t                                *p_data)\r
1541 {\r
1542         NTSTATUS        status = STATUS_SUCCESS;\r
1543         uint32_t lcl_data = 0;\r
1544         uint32_t bank;\r
1545         static uint32_t curr_bank =     0xffffffff;\r
1546 \r
1547         if (addr & 0x3)\r
1548                 return STATUS_INVALID_PARAMETER;\r
1549 \r
1550         bank = addr & BANK_MASK;\r
1551         if (bank !=  curr_bank)\r
1552         {\r
1553                 curr_bank = bank;\r
1554                 if ((status = fw_set_bank(p_BusInterface, bank)) != STATUS_SUCCESS )\r
1555                         return STATUS_INVALID_PARAMETER;\r
1556         }\r
1557         status = fw_flash_read_data(p_BusInterface, &lcl_data, addr, 4);\r
1558         *p_data = cl_ntoh32(lcl_data);\r
1559         return STATUS_SUCCESS;\r
1560 }\r
1561 \r
1562 static NTSTATUS\r
1563 fw_flash_readbuf(\r
1564                 IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1565                 IN              uint32_t                                offset,\r
1566                 IN OUT  void                                    *p_data,\r
1567                 IN              uint32_t                                len)\r
1568 {\r
1569         NTSTATUS        status = STATUS_SUCCESS;\r
1570         uint32_t *p_lcl_data;\r
1571         uint32_t        i;\r
1572 \r
1573     if (offset & 0x3)\r
1574     {\r
1575         //Address should be 4-bytes aligned\r
1576         return STATUS_INVALID_PARAMETER;\r
1577     }\r
1578     if (len & 0x3)\r
1579     {\r
1580         //Length should be 4-bytes aligned\r
1581         return STATUS_INVALID_PARAMETER;\r
1582     }\r
1583     p_lcl_data = (uint32_t *)p_data;\r
1584     \r
1585         for ( i=0; i < (len >> 2); i++)\r
1586     {                                   \r
1587         if ( (status = fw_flash_read_data( p_BusInterface, p_lcl_data, offset, sizeof(uint32_t) )) != STATUS_SUCCESS )\r
1588             return status;\r
1589         offset += 4;\r
1590                 p_lcl_data++;\r
1591     }\r
1592     return STATUS_SUCCESS;\r
1593 } // Flash::flash_read\r
1594 \r
1595 static NTSTATUS\r
1596 fw_flash_writebuf(\r
1597                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1598                 IN              PVOID                                                   p_buffer,\r
1599                 IN              ULONG                                                   offset,\r
1600                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1601 {\r
1602         NTSTATUS status = STATUS_SUCCESS;\r
1603         uint32_t        i;\r
1604         uint8_t *p_data = (uint8_t *)p_buffer;\r
1605 \r
1606         for ( i = 0; i < length;  i++ )\r
1607         {\r
1608                 status = fw_flash_write_data (p_BusInterface, p_data, offset, 1 );\r
1609                 if (status != STATUS_SUCCESS )\r
1610                         return status;\r
1611                 p_data++;\r
1612                 offset++;\r
1613         }\r
1614         return status;\r
1615 }\r
1616 static NTSTATUS\r
1617 fw_flash_init(\r
1618                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  )\r
1619 {\r
1620         uint32_t dir;\r
1621     uint32_t pol;\r
1622     uint32_t mod;\r
1623 \r
1624     uint32_t cnt=0;\r
1625     uint32_t data;\r
1626         NTSTATUS status = STATUS_SUCCESS;\r
1627         uint32_t        semaphore = 0;\r
1628     \r
1629         while ( !semaphore )\r
1630         {\r
1631                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, SEMAP63, 4);\r
1632                 if ( status != STATUS_SUCCESS )\r
1633                         break;\r
1634                 if( !data )\r
1635                 {\r
1636                         semaphore = 1;\r
1637                         break;\r
1638                 }\r
1639         if (++cnt > 5000 )\r
1640         {\r
1641             break;\r
1642         }\r
1643     } \r
1644 \r
1645         if ( !semaphore )\r
1646         {\r
1647                 return STATUS_NOT_SUPPORTED;\r
1648         }\r
1649 \r
1650     // Save old values\r
1651     \r
1652         status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dir,GPIO_DIR_L , 4);\r
1653         if ( status == STATUS_SUCCESS )\r
1654                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_pol,GPIO_POL_L , 4);\r
1655         if ( status == STATUS_SUCCESS )\r
1656                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_mod,GPIO_MOD_L , 4);\r
1657         if ( status == STATUS_SUCCESS )\r
1658                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dat,GPIO_DAT_L , 4);\r
1659 \r
1660    // Set Direction=1, Polarity=0, Mode=0 for 3 GPIO lower bits\r
1661     dir = old_dir | 0x70;\r
1662     pol = old_pol & ~0x70;\r
1663     mod = old_mod & ~0x70;\r
1664 \r
1665         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &dir,GPIO_DIR_L , 4);\r
1666         if ( status == STATUS_SUCCESS )\r
1667                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &pol,GPIO_POL_L , 4);\r
1668         if ( status == STATUS_SUCCESS )\r
1669                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &mod,GPIO_MOD_L , 4);\r
1670         if ( status == STATUS_SUCCESS )\r
1671                 // Set CPUMODE\r
1672                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, CPUMODE, 4);\r
1673     if ( status == STATUS_SUCCESS )\r
1674         {\r
1675                 data &= ~CPUMODE_MSK;\r
1676                 data |= 1 << CPUMODE_SHIFT;\r
1677                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, CPUMODE, 4);\r
1678         }\r
1679         if ( status == STATUS_SUCCESS )\r
1680         {\r
1681                 // Reset flash\r
1682                 data = 0xf0;\r
1683                 status = fw_flash_write_data(p_BusInterface, &data, 0x0, 4);\r
1684         }\r
1685         return status;\r
1686 }\r
1687 \r
1688 static NTSTATUS\r
1689 fw_flash_deinit(\r
1690         IN              BUS_INTERFACE_STANDARD  *p_BusInterface )\r
1691 {\r
1692         uint32_t data = 0;\r
1693         NTSTATUS status = STATUS_SUCCESS;\r
1694     \r
1695         status = fw_set_bank(p_BusInterface, 0);\r
1696         if ( status == STATUS_SUCCESS )\r
1697                 // Restore origin values\r
1698                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dir,GPIO_DIR_L , 4);\r
1699         if ( status == STATUS_SUCCESS )\r
1700                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_pol,GPIO_POL_L , 4);\r
1701         if ( status == STATUS_SUCCESS )\r
1702                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_mod,GPIO_MOD_L , 4);\r
1703         if ( status == STATUS_SUCCESS )\r
1704                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dat,GPIO_DAT_L , 4);\r
1705         if ( status == STATUS_SUCCESS )\r
1706                 // Free GPIO Semaphore\r
1707                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, SEMAP63, 4);\r
1708         return status;\r
1709 }\r
1710 \r
1711 static NTSTATUS\r
1712 fw_set_bank(\r
1713         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1714         IN               uint32_t bank )\r
1715 {\r
1716         NTSTATUS  status = STATUS_SUCCESS;\r
1717         uint32_t        data = ( (uint32_t)0x70 << 24 );\r
1718         uint32_t        mask = ((bank >> (BANK_SHIFT-4)) << 24 );\r
1719 \r
1720         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATACLEAR_L, 4);\r
1721         if (status == STATUS_SUCCESS)\r
1722         {\r
1723         // A1\r
1724                 data &= mask;\r
1725                 //data |= mask; // for A0\r
1726                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATASET_L, 4);\r
1727         }\r
1728         return status;\r
1729 }\r