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