[MT23108] Fix error reading CA guid from firmware image
[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 \r
918         HCA_ENTER( HCA_DBG_PNP );\r
919 \r
920         /* Handled on the way up. */\r
921         status = cl_do_sync_pnp( p_dev_obj, p_irp, p_action );\r
922         if( !NT_SUCCESS( status ) )\r
923         {\r
924                 HCA_TRACE_EXIT( HCA_DBG_ERROR, \r
925                         ("Lower drivers failed IRP_MN_START_DEVICE.\n") );\r
926                 return status;\r
927         }\r
928 \r
929         p_ext = p_dev_obj->DeviceExtension;\r
930 \r
931         /* Get the HH HCA handle for this instance. */\r
932         status = __get_hca_handle( p_ext );\r
933         if( !NT_SUCCESS( status ) )\r
934         {\r
935                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
936                         ("Failed to get HH HCA handle.\n") );\r
937                 return status;\r
938         }\r
939 \r
940         /* store HCA PDO */\r
941         p_ext->hca.p_dev_obj = p_ext->cl_ext.p_pdo;\r
942         status = fw_flash_get_ca_guid(p_ext->cl_ext.p_pdo, &ca_guid);\r
943         if ( !NT_SUCCESS( status ) )\r
944         {\r
945                 HCA_TRACE( HCA_DBG_ERROR, \r
946                         ("fw_flash_get_ca_guid failed status =%#x.\n", status) );\r
947                 return status;\r
948         }\r
949         p_ext->hca.guid = ca_guid;\r
950         mlnx_hca_insert( &p_ext->hca );\r
951 \r
952         /*\r
953          * Change the state since the PnP callback can happen\r
954          * before the callback returns.\r
955          */\r
956         p_ext->state = HCA_STARTED;\r
957         /* Register for interface arrival of the IB_AL device. */\r
958         status = IoRegisterPlugPlayNotification(\r
959                 EventCategoryDeviceInterfaceChange,\r
960                 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,\r
961                 (void*)&GUID_IB_CI_INTERFACE, p_dev_obj->DriverObject,\r
962                 __pnp_notify_ifc, p_dev_obj, &p_ext->pnp_ifc_entry );\r
963         if( !NT_SUCCESS( status ) )\r
964         {\r
965                 p_ext->state = HCA_ADDED;\r
966                 HCA_TRACE( HCA_DBG_ERROR, \r
967                         ("IoRegisterPlugPlayNotification returned %08x.\n", status) );\r
968         }\r
969 \r
970         HCA_EXIT( HCA_DBG_PNP );\r
971         return status;\r
972 }\r
973 \r
974 \r
975 static void\r
976 hca_release_resources(\r
977         IN                              DEVICE_OBJECT* const            p_dev_obj )\r
978 {\r
979         hca_dev_ext_t           *p_ext;\r
980 \r
981         HCA_ENTER( HCA_DBG_PNP );\r
982 \r
983         p_ext = p_dev_obj->DeviceExtension;\r
984 \r
985         if( p_ext->state == HCA_REGISTERED )\r
986         {\r
987                 CL_ASSERT( p_ext->ci_ifc.deregister_ca );\r
988                 CL_ASSERT( p_ext->p_al_dev );\r
989                 CL_ASSERT( p_ext->p_al_file_obj );\r
990                 /* Notify AL that the CA is being removed. */\r
991                 p_ext->ci_ifc.deregister_ca( p_ext->hca.guid );\r
992                 /* Release AL's CI interface. */\r
993                 p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
994         }\r
995 \r
996         if( p_ext->pnp_target_entry )\r
997         {\r
998                 ASSERT( p_ext->pnp_ifc_entry );\r
999                 IoUnregisterPlugPlayNotification( p_ext->pnp_target_entry );\r
1000         }\r
1001 \r
1002         if( p_ext->pnp_ifc_entry )\r
1003                 IoUnregisterPlugPlayNotification( p_ext->pnp_ifc_entry );\r
1004 \r
1005         if( p_ext->p_al_file_obj )\r
1006                 ObDereferenceObject( p_ext->p_al_file_obj );\r
1007 \r
1008         //cl_event_destroy( &p_ext->mutex );\r
1009 \r
1010         HCA_EXIT( HCA_DBG_PNP );\r
1011 }\r
1012 //\r
1013 //\r
1014 //static NTSTATUS\r
1015 //hca_disable(\r
1016 //      IN                                      DEVICE_OBJECT* const    p_dev_obj )\r
1017 //{\r
1018 //      hca_dev_ext_t   *p_ext;\r
1019 //\r
1020 //      HCA_ENTER( HCA_DBG_PNP );\r
1021 //\r
1022 //      p_ext = p_dev_obj->DeviceExtension;\r
1023 //\r
1024 //      ASSERT( p_ext->state == HCA_STARTED );\r
1025 //\r
1026 //      if( p_ext->state = HCA_REGISTERED )\r
1027 //      {\r
1028 //              /* Notify AL that the CA is being removed. */\r
1029 //              p_ext->ci_ifc.deregister_ca( p_ext->hca.guid );\r
1030 //              /* Release AL's CI interface. */\r
1031 //              p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
1032 //\r
1033 //              p_ext->state = HCA_STARTED;\r
1034 //      }\r
1035 //\r
1036 //      HCA_EXIT( HCA_DBG_PNP );\r
1037 //      return STATUS_SUCCESS;\r
1038 //}\r
1039 //\r
1040 //\r
1041 //static NTSTATUS\r
1042 //hca_deactivate(\r
1043 //      IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1044 //      IN                                      IRP* const                              p_irp, \r
1045 //              OUT                             cl_irp_action_t* const  p_action )\r
1046 //{\r
1047 //      NTSTATUS        status;\r
1048 //      hca_dev_ext_t   *p_ext;\r
1049 //\r
1050 //      HCA_ENTER( HCA_DBG_PNP );\r
1051 //\r
1052 //      UNUSED_PARAM( p_irp );\r
1053 //\r
1054 //      p_ext = p_dev_obj->DeviceExtension;\r
1055 //\r
1056 //      *p_action = IrpSkip;\r
1057 //\r
1058 //      status = hca_disable( p_dev_obj );\r
1059 //\r
1060 //      mlnx_hca_remove( &p_ext->hca );\r
1061 //\r
1062 //      p_ext->hca.hh_hndl = NULL;\r
1063 //\r
1064 //      p_ext->state = HCA_ADDED;\r
1065 //\r
1066 //      HCA_EXIT( HCA_DBG_PNP );\r
1067 //      return status;\r
1068 //}\r
1069 \r
1070 \r
1071 static NTSTATUS\r
1072 hca_query_bus_relations(\r
1073         IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
1074         IN                                      IRP* const                              p_irp, \r
1075                 OUT                             cl_irp_action_t* const  p_action )\r
1076 {\r
1077         NTSTATUS                        status;\r
1078         DEVICE_RELATIONS        *p_rel;\r
1079         hca_dev_ext_t           *p_ext;\r
1080 \r
1081         HCA_ENTER( HCA_DBG_PNP );\r
1082 \r
1083         p_ext = p_dev_obj->DeviceExtension;\r
1084 \r
1085         //cl_event_wait_on( &p_ext->mutex, EVENT_NO_TIMEOUT, FALSE );\r
1086         if( p_ext->state == HCA_REGISTERED )\r
1087         {\r
1088                 status = p_ext->ci_ifc.get_relations( p_ext->hca.guid, p_irp );\r
1089                 if( !NT_SUCCESS( status ) )\r
1090                 {\r
1091                         //cl_event_signal( &p_ext->mutex );\r
1092                         *p_action = IrpComplete;\r
1093                         HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
1094                                 ("AL get_relations returned %08x.\n", status) );\r
1095                         return status;\r
1096                 }\r
1097         }\r
1098         else\r
1099         {\r
1100                 status = cl_alloc_relations( p_irp, 1 );\r
1101                 if( !NT_SUCCESS( status ) )\r
1102                 {\r
1103                         HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
1104                                 ("cl_alloc_relations returned %08x.\n", status) );\r
1105                         return status;\r
1106                 }\r
1107 \r
1108                 p_rel = (DEVICE_RELATIONS*)p_irp->IoStatus.Information;\r
1109                 p_rel->Count = 0;\r
1110                 p_rel->Objects[0] = NULL;\r
1111         }\r
1112 \r
1113         //cl_event_signal( &p_ext->mutex );\r
1114 \r
1115         *p_action = IrpPassDown;\r
1116         HCA_EXIT( HCA_DBG_PNP );\r
1117         return STATUS_SUCCESS;\r
1118 }\r
1119 \r
1120 \r
1121 static NTSTATUS\r
1122 hca_set_power(\r
1123         IN                              DEVICE_OBJECT* const            p_dev_obj,\r
1124         IN                              IRP* const                                      p_irp, \r
1125                 OUT                     cl_irp_action_t* const          p_action )\r
1126 {\r
1127         NTSTATUS                        status;\r
1128         hca_dev_ext_t           *p_ext;\r
1129         IO_STACK_LOCATION       *p_io_stack;\r
1130 \r
1131         HCA_ENTER( HCA_DBG_PNP );\r
1132 \r
1133         p_ext = p_dev_obj->DeviceExtension;\r
1134 \r
1135         *p_action = IrpSkip;\r
1136 \r
1137         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
1138 \r
1139         if( p_io_stack->Parameters.Power.Type != DevicePowerState )\r
1140                 return STATUS_SUCCESS;\r
1141 \r
1142         switch( p_io_stack->Parameters.Power.State.DeviceState )\r
1143         {\r
1144         case PowerDeviceD0:\r
1145                 if( p_ext->p_al_dev )\r
1146                         status = __hca_register( p_dev_obj );\r
1147                 else\r
1148                         status = STATUS_SUCCESS;\r
1149                 break;\r
1150 \r
1151         default:\r
1152                 if( p_ext->state == HCA_REGISTERED )\r
1153                 {\r
1154                         /* Notify AL that the CA is being removed. */\r
1155                         p_ext->ci_ifc.deregister_ca( p_ext->hca.guid );\r
1156                         /* Release AL's CI interface. */\r
1157                         p_ext->ci_ifc.wdm.InterfaceDereference( p_ext->ci_ifc.wdm.Context );\r
1158 \r
1159                         p_ext->state = HCA_STARTED;\r
1160                 }\r
1161                 status = STATUS_SUCCESS;\r
1162                 break;\r
1163         }\r
1164 \r
1165         if( !NT_SUCCESS( status ) )\r
1166                 *p_action = IrpComplete;\r
1167 \r
1168         HCA_EXIT( HCA_DBG_PNP );\r
1169         return status;\r
1170 }\r
1171 \r
1172 typedef struct Primary_Sector{\r
1173         uint32_t fi_addr;\r
1174         uint32_t fi_size;\r
1175         uint32_t signature;\r
1176         uint32_t fw_reserved[5];\r
1177         uint32_t vsd[56];\r
1178         uint32_t branch_to;\r
1179         uint32_t crc016;\r
1180 } primary_sector_t;\r
1181 \r
1182 static uint32_t old_dir;\r
1183 static uint32_t old_pol;\r
1184 static uint32_t old_mod;\r
1185 static uint32_t old_dat;\r
1186 \r
1187 static NTSTATUS\r
1188 fw_access_pciconf (\r
1189                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1190                 IN              ULONG                                                   op_flag,\r
1191                 IN              PVOID                                                   p_buffer,\r
1192                 IN              ULONG                                                   offset,\r
1193                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1194 {\r
1195 \r
1196         ULONG                           bytes;  \r
1197         NTSTATUS                        status = STATUS_SUCCESS;\r
1198 \r
1199         PAGED_CODE();\r
1200 \r
1201         if (p_BusInterface)\r
1202         {\r
1203 \r
1204                 bytes = p_BusInterface->SetBusData(\r
1205                                                 p_BusInterface->Context,\r
1206                                                 PCI_WHICHSPACE_CONFIG,\r
1207                                                 (PVOID)&offset,\r
1208                                                 PCI_CONF_ADDR,\r
1209                                                 sizeof(ULONG) );\r
1210 \r
1211                 if( op_flag == 0 )\r
1212                 {\r
1213                         if ( bytes )\r
1214                                 bytes = p_BusInterface->GetBusData(\r
1215                                                         p_BusInterface->Context,\r
1216                                                         PCI_WHICHSPACE_CONFIG,\r
1217                                                         p_buffer,\r
1218                                                         PCI_CONF_DATA,\r
1219                                                         length );\r
1220                         if ( !bytes )\r
1221                                 status = STATUS_NOT_SUPPORTED;\r
1222                 }\r
1223 \r
1224                 else\r
1225                 {\r
1226                         if ( bytes )\r
1227                                 bytes = p_BusInterface->SetBusData(\r
1228                                                         p_BusInterface->Context,\r
1229                                                         PCI_WHICHSPACE_CONFIG,\r
1230                                                         p_buffer,\r
1231                                                         PCI_CONF_DATA,\r
1232                                                         length);\r
1233 \r
1234                         if ( !bytes )\r
1235                                 status = STATUS_NOT_SUPPORTED;\r
1236                 }\r
1237         }\r
1238         return status;\r
1239 }\r
1240 \r
1241 static NTSTATUS\r
1242 fw_get_pci_bus_interface(\r
1243         IN              DEVICE_OBJECT                           *p_dev_obj,\r
1244         OUT             BUS_INTERFACE_STANDARD          *p_BusInterface )\r
1245 {\r
1246         KEVENT event;\r
1247         NTSTATUS status;\r
1248         PIRP p_irp;\r
1249         IO_STATUS_BLOCK ioStatus;\r
1250         PIO_STACK_LOCATION p_irpStack;\r
1251         PDEVICE_OBJECT p_target_obj;\r
1252 \r
1253         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
1254 \r
1255         p_target_obj = IoGetAttachedDeviceReference( p_dev_obj );\r
1256 \r
1257         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,\r
1258                                                                                 p_target_obj,\r
1259                                                                                 NULL,\r
1260                                                                                 0,\r
1261                                                                                 NULL,\r
1262                                                                                 &event,\r
1263                                                                                 &ioStatus );\r
1264         if (p_irp == NULL)\r
1265         {\r
1266                 HCA_TRACE( HCA_DBG_ERROR,\r
1267                         ("IoBuildSynchronousFsdRequest failed.\n") );\r
1268                 status = STATUS_INSUFFICIENT_RESOURCES;\r
1269                 goto End;\r
1270         }\r
1271         p_irpStack = IoGetNextIrpStackLocation( p_irp );\r
1272         p_irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
1273         p_irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;\r
1274         p_irpStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);\r
1275         p_irpStack->Parameters.QueryInterface.Version = 1;\r
1276         p_irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) p_BusInterface;\r
1277         p_irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;\r
1278 \r
1279         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
1280         \r
1281         status = IoCallDriver( p_target_obj, p_irp );\r
1282 \r
1283         if ( status == STATUS_PENDING )\r
1284         {\r
1285                 KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );\r
1286                 status = ioStatus.Status;\r
1287         }\r
1288 End:\r
1289         // Done with reference\r
1290         ObDereferenceObject( p_target_obj );\r
1291         return status;\r
1292 }\r
1293 \r
1294 ib_api_status_t\r
1295 fw_access_ctrl(\r
1296         IN              const   void* __ptr64                           p_context,\r
1297         IN              const   void* __ptr64* const            handle_array    OPTIONAL,\r
1298         IN                              uint32_t                                        num_handles,\r
1299         IN                              ib_ci_op_t* const                       p_ci_op,\r
1300         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
1301 {\r
1302         DEVICE_OBJECT                           *p_dev_obj;\r
1303         static BUS_INTERFACE_STANDARD    BusInterface;\r
1304         static uint32_t                         if_ready;\r
1305         NTSTATUS                                        status;\r
1306         PVOID                                           p_data;\r
1307         ULONG                                           offset;\r
1308         ULONG POINTER_ALIGNMENT         length;\r
1309         ib_ci_op_t                                      *p_ci;\r
1310         mlnx_hob_t                                      *p_hob;\r
1311 \r
1312         UNREFERENCED_PARAMETER(handle_array);\r
1313         UNREFERENCED_PARAMETER(num_handles);\r
1314         UNREFERENCED_PARAMETER(p_umv_buf);\r
1315 \r
1316         status =  STATUS_SUCCESS;\r
1317         if( p_umv_buf )\r
1318                 p_hob = ((mlnx_um_ca_t* __ptr64)p_context)->hob_p;\r
1319         else\r
1320                 p_hob = (mlnx_hob_t *)(const void *)p_context;\r
1321 \r
1322         p_dev_obj = (DEVICE_OBJECT *)(const void *)p_hob->p_dev_obj;\r
1323         p_ci =  p_ci_op;\r
1324 \r
1325         if ( !p_ci )\r
1326                 return STATUS_INVALID_DEVICE_REQUEST;\r
1327         if ( !p_ci->buf_size )\r
1328                 return STATUS_INVALID_DEVICE_REQUEST;\r
1329 \r
1330         length = p_ci->buf_size;\r
1331         offset = p_ci->buf_info;\r
1332         p_data = p_ci->p_buf;\r
1333 \r
1334         switch ( p_ci->command )\r
1335         {\r
1336                 case    FW_READ: // read data from flash\r
1337                                 if ( if_ready )\r
1338                                 {\r
1339                                         status = fw_flash_read_data(&BusInterface, p_data, offset, length);\r
1340                                 }\r
1341                                 break;\r
1342                 case    FW_WRITE: // write data to flash\r
1343                                 if ( if_ready )\r
1344                                 {\r
1345 \r
1346                                         status = fw_flash_write_data(&BusInterface, p_data, offset, length);\r
1347                                 }\r
1348                                 break;\r
1349                 case    FW_READ_CMD:\r
1350                                 if ( if_ready )\r
1351                                 {\r
1352                                         status = fw_access_pciconf(&BusInterface, 0 , p_data, offset, 4);\r
1353                                 }\r
1354                                 break;\r
1355                 case    FW_WRITE_CMD:\r
1356                                 if ( if_ready )\r
1357                                 {\r
1358                                         status = fw_access_pciconf(&BusInterface, 1 , p_data, offset, 4);\r
1359                                 }\r
1360                                 break;\r
1361                 case    FW_CLOSE_IF: // close BusInterface\r
1362                                 if (if_ready )\r
1363                                 {\r
1364                                         if_ready = 0;\r
1365                                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1366                                 }\r
1367                                 return status;\r
1368                 case    FW_OPEN_IF: // open BusInterface\r
1369                                 if ( !if_ready )\r
1370                                 {\r
1371                                         status = fw_get_pci_bus_interface(p_dev_obj, &BusInterface);\r
1372                                 \r
1373                                         if ( NT_SUCCESS( status ) )\r
1374                                         {\r
1375                                                 if_ready = 1;\r
1376                                                 status = STATUS_SUCCESS;\r
1377                                         }\r
1378                                 }\r
1379                                 return status;\r
1380                 default:\r
1381                                 status = STATUS_NOT_SUPPORTED;\r
1382         }\r
1383 \r
1384         if ( status != STATUS_SUCCESS )\r
1385         {\r
1386                 if ( if_ready )\r
1387                 {\r
1388                         if_ready = 0;\r
1389                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1390                 }\r
1391                 HCA_TRACE_EXIT( HCA_DBG_ERROR,\r
1392                         ("fw_access_ctrl failed returns %08x.\n", status) );\r
1393         }\r
1394         return status;\r
1395 }\r
1396 \r
1397 static NTSTATUS\r
1398 fw_flash_write_data (\r
1399                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1400                 IN              PVOID                                                   p_buffer,\r
1401                 IN              ULONG                                                   offset,\r
1402                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1403 {\r
1404         NTSTATUS                status;\r
1405         uint32_t                cnt = 0;\r
1406         uint32_t                lcl_data;\r
1407 \r
1408         lcl_data = (*((uint32_t*)p_buffer) << 24);\r
1409 \r
1410         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET+4, length );\r
1411         if ( status != STATUS_SUCCESS )\r
1412                 return status;\r
1413         lcl_data = ( WRITE_BIT | (offset & ADDR_MSK));\r
1414                 \r
1415         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET, 4 );\r
1416         if ( status != STATUS_SUCCESS )\r
1417         return status;\r
1418 \r
1419         lcl_data = 0;\r
1420         \r
1421         do\r
1422         {\r
1423                 if (++cnt > 5000)\r
1424                 {\r
1425                         return STATUS_DEVICE_NOT_READY;\r
1426                 }\r
1427 \r
1428                 status = fw_access_pciconf(p_BusInterface, FW_READ , &lcl_data, FLASH_OFFSET, 4 );\r
1429                 if ( status != STATUS_SUCCESS )\r
1430                 return status;\r
1431 \r
1432         } while(lcl_data & CMD_MASK);\r
1433 \r
1434         return status;\r
1435 }\r
1436 \r
1437 static NTSTATUS\r
1438 fw_flash_read_data (\r
1439                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1440                 IN              PVOID                                                   p_buffer,\r
1441                 IN              ULONG                                                   offset,\r
1442                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1443 {\r
1444         NTSTATUS        status = STATUS_SUCCESS;\r
1445         uint32_t        cnt = 0;\r
1446         uint32_t        lcl_data = ( READ_BIT | (offset & ADDR_MSK));\r
1447         \r
1448         status = fw_access_pciconf(p_BusInterface, FW_WRITE, &lcl_data, FLASH_OFFSET, 4 );\r
1449         if ( status != STATUS_SUCCESS )\r
1450                 return status;\r
1451 \r
1452         lcl_data = 0;\r
1453         do\r
1454         {\r
1455                 // Timeout checks\r
1456                 if (++cnt > 5000 )\r
1457                 {\r
1458                         return STATUS_DEVICE_NOT_READY;\r
1459         }\r
1460 \r
1461                 status = fw_access_pciconf(p_BusInterface, FW_READ, &lcl_data, FLASH_OFFSET, 4 );\r
1462         \r
1463                 if ( status != STATUS_SUCCESS )\r
1464                         return status;\r
1465 \r
1466         } while(lcl_data & CMD_MASK);\r
1467 \r
1468         status = fw_access_pciconf(p_BusInterface, FW_READ, p_buffer, FLASH_OFFSET+4, length );\r
1469         return status;\r
1470 }\r
1471 \r
1472 static NTSTATUS\r
1473 fw_flash_get_ca_guid(\r
1474                 IN              DEVICE_OBJECT           *p_dev_obj,\r
1475                 OUT             net64_t                 *ca_guid )\r
1476 {\r
1477         NTSTATUS                status = STATUS_SUCCESS;\r
1478         BUS_INTERFACE_STANDARD          BusInterface;\r
1479 \r
1480         uint32_t NODE_GUIDH, NODE_GUIDL;\r
1481         uint32_t prim_ptr = 0;\r
1482         uint32_t signature, offset, sect_size;\r
1483 \r
1484         primary_sector_t        ps;\r
1485         cl_memset( &ps, 0, sizeof(primary_sector_t));\r
1486 \r
1487         status = fw_get_pci_bus_interface(p_dev_obj, &BusInterface);\r
1488 \r
1489         if ( !NT_SUCCESS( status ) )\r
1490                 return status;\r
1491         \r
1492         status = fw_flash_init (&BusInterface);\r
1493         if (status != STATUS_SUCCESS )\r
1494                 goto err1;\r
1495 \r
1496         status = fw_flash_read_data(&BusInterface, &signature, FW_SIG_OFFSET, 4);\r
1497         if (status != STATUS_SUCCESS )\r
1498                 goto err2;\r
1499 \r
1500         if (signature == FW_SIGNATURE)\r
1501         {\r
1502                 //Fail Safe image\r
1503 \r
1504                 /* Find the sector size offset. */\r
1505                 status = fw_flash_read_data(\r
1506                         &BusInterface, &offset, FW_SECT_PTR_OFFSET, 4 );\r
1507                 if( status != STATUS_SUCCESS )\r
1508                         goto err2;\r
1509 \r
1510                 offset &= 0x0000FFFF;\r
1511 \r
1512                 status = fw_flash_read_data(\r
1513                         &BusInterface, &sect_size, FW_SECT_OFFSET + offset, 4 );\r
1514                 if( status != STATUS_SUCCESS )\r
1515                         goto err2;\r
1516 \r
1517                 sect_size = 1 << (sect_size & 0x0000FFFF);\r
1518 \r
1519                 /* Try to read the GUIDs from the primary image. */\r
1520                 status = fw_flash_readbuf(&BusInterface, sect_size, &ps, sizeof(ps));\r
1521                 if ( status == STATUS_SUCCESS && ps.signature != FW_SIGNATURE )\r
1522                 {\r
1523                         /* Hmm, that didn't work.  Try the secondary image. */\r
1524                         status = fw_flash_readbuf(\r
1525                                 &BusInterface, sect_size * 2, &ps, sizeof(ps) );\r
1526                 }\r
1527                 if( status == STATUS_SUCCESS )\r
1528                 {\r
1529                         signature = ps.signature;\r
1530                         status = fw_flash_read_data(&BusInterface, &prim_ptr, ps.fi_addr+0x24, 4);\r
1531                         if (status == STATUS_SUCCESS )\r
1532                                 prim_ptr = prim_ptr + ps.fi_addr;\r
1533                 }\r
1534                 else\r
1535                 {\r
1536                         signature = 0;\r
1537                 }\r
1538         }\r
1539         else\r
1540         {\r
1541                 // Short image\r
1542                 HCA_TRACE( HCA_DBG_ERROR,\r
1543                         ("Invalid signature %08x, assuming short image.\n", signature) );\r
1544                 prim_ptr = signature;       \r
1545                 signature = FW_SIGNATURE;\r
1546         }\r
1547 \r
1548         if ( signature == FW_SIGNATURE && prim_ptr < MAX_FLASH_SIZE )\r
1549         {\r
1550                 /* now we can read ca guid\r
1551                  * since we read it in host mode fw_flash_read4() \r
1552                  * swaps it back in BE - how it was stored in FW\r
1553                  */\r
1554                 if (( status = fw_flash_read4(&BusInterface, prim_ptr, &NODE_GUIDL)) == STATUS_SUCCESS )\r
1555                         if (( status = fw_flash_read4(&BusInterface, prim_ptr+4, &NODE_GUIDH)) == STATUS_SUCCESS )\r
1556                         {\r
1557                                 *ca_guid = NODE_GUIDH;\r
1558                                 *ca_guid = (*ca_guid << 32) | NODE_GUIDL;\r
1559                         }\r
1560         }\r
1561         else \r
1562         {\r
1563                 //invalid GUID pointer\r
1564                 status = STATUS_NO_SUCH_DEVICE;\r
1565         }\r
1566 err2:\r
1567         fw_flash_deinit(&BusInterface);\r
1568 err1:\r
1569         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
1570         return status;\r
1571 }\r
1572 \r
1573 static NTSTATUS\r
1574 fw_flash_read4( \r
1575         IN                      BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1576         IN                      uint32_t                                addr, \r
1577         IN      OUT             uint32_t                                *p_data)\r
1578 {\r
1579         NTSTATUS        status = STATUS_SUCCESS;\r
1580         uint32_t lcl_data = 0;\r
1581         uint32_t bank;\r
1582         static uint32_t curr_bank =     0xffffffff;\r
1583 \r
1584         if (addr & 0x3)\r
1585         {\r
1586                 HCA_TRACE( HCA_DBG_ERROR, ("Invalid address %08x\n", addr) );\r
1587                 return STATUS_INVALID_PARAMETER;\r
1588         }\r
1589 \r
1590         bank = addr & BANK_MASK;\r
1591         if (bank !=  curr_bank)\r
1592         {\r
1593                 curr_bank = bank;\r
1594                 if ((status = fw_set_bank(p_BusInterface, bank)) != STATUS_SUCCESS )\r
1595                 {\r
1596                         HCA_TRACE( HCA_DBG_ERROR, ("fw_set_bank returned %08x\n", status) );\r
1597                         return STATUS_INVALID_PARAMETER;\r
1598                 }\r
1599         }\r
1600         status = fw_flash_read_data(p_BusInterface, &lcl_data, addr, 4);\r
1601         *p_data = cl_ntoh32(lcl_data);\r
1602         return STATUS_SUCCESS;\r
1603 }\r
1604 \r
1605 static NTSTATUS\r
1606 fw_flash_readbuf(\r
1607                 IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1608                 IN              uint32_t                                offset,\r
1609                 IN OUT  void                                    *p_data,\r
1610                 IN              uint32_t                                len)\r
1611 {\r
1612         NTSTATUS        status = STATUS_SUCCESS;\r
1613         uint32_t *p_lcl_data;\r
1614         uint32_t        i;\r
1615 \r
1616     if (offset & 0x3)\r
1617     {\r
1618         //Address should be 4-bytes aligned\r
1619                 HCA_TRACE( HCA_DBG_ERROR, ("Invalid address %08x\n", offset) );\r
1620         return STATUS_INVALID_PARAMETER;\r
1621     }\r
1622     if (len & 0x3)\r
1623     {\r
1624         //Length should be 4-bytes aligned\r
1625                 HCA_TRACE( HCA_DBG_ERROR, ("Invalid length %d\n", len) );\r
1626         return STATUS_INVALID_PARAMETER;\r
1627     }\r
1628     p_lcl_data = (uint32_t *)p_data;\r
1629     \r
1630         for ( i=0; i < (len >> 2); i++)\r
1631     {                                   \r
1632         if ( (status = fw_flash_read_data( p_BusInterface, p_lcl_data, offset, sizeof(uint32_t) )) != STATUS_SUCCESS )\r
1633             return status;\r
1634         offset += 4;\r
1635                 p_lcl_data++;\r
1636     }\r
1637     return STATUS_SUCCESS;\r
1638 } // Flash::flash_read\r
1639 \r
1640 static NTSTATUS\r
1641 fw_flash_writebuf(\r
1642                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
1643                 IN              PVOID                                                   p_buffer,\r
1644                 IN              ULONG                                                   offset,\r
1645                 IN              ULONG POINTER_ALIGNMENT                 length )\r
1646 {\r
1647         NTSTATUS status = STATUS_SUCCESS;\r
1648         uint32_t        i;\r
1649         uint8_t *p_data = (uint8_t *)p_buffer;\r
1650 \r
1651         for ( i = 0; i < length;  i++ )\r
1652         {\r
1653                 status = fw_flash_write_data (p_BusInterface, p_data, offset, 1 );\r
1654                 if (status != STATUS_SUCCESS )\r
1655                         return status;\r
1656                 p_data++;\r
1657                 offset++;\r
1658         }\r
1659         return status;\r
1660 }\r
1661 static NTSTATUS\r
1662 fw_flash_init(\r
1663                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  )\r
1664 {\r
1665         uint32_t dir;\r
1666     uint32_t pol;\r
1667     uint32_t mod;\r
1668 \r
1669     uint32_t cnt=0;\r
1670     uint32_t data;\r
1671         NTSTATUS status = STATUS_SUCCESS;\r
1672         uint32_t        semaphore = 0;\r
1673     \r
1674         while ( !semaphore )\r
1675         {\r
1676                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, SEMAP63, 4);\r
1677                 if ( status != STATUS_SUCCESS )\r
1678                         break;\r
1679                 if( !data )\r
1680                 {\r
1681                         semaphore = 1;\r
1682                         break;\r
1683                 }\r
1684         if (++cnt > 5000 )\r
1685         {\r
1686             break;\r
1687         }\r
1688     } \r
1689 \r
1690         if ( !semaphore )\r
1691         {\r
1692                 return STATUS_NOT_SUPPORTED;\r
1693         }\r
1694 \r
1695     // Save old values\r
1696     \r
1697         status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dir,GPIO_DIR_L , 4);\r
1698         if ( status == STATUS_SUCCESS )\r
1699                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_pol,GPIO_POL_L , 4);\r
1700         if ( status == STATUS_SUCCESS )\r
1701                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_mod,GPIO_MOD_L , 4);\r
1702         if ( status == STATUS_SUCCESS )\r
1703                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dat,GPIO_DAT_L , 4);\r
1704 \r
1705    // Set Direction=1, Polarity=0, Mode=0 for 3 GPIO lower bits\r
1706     dir = old_dir | 0x70;\r
1707     pol = old_pol & ~0x70;\r
1708     mod = old_mod & ~0x70;\r
1709 \r
1710         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &dir,GPIO_DIR_L , 4);\r
1711         if ( status == STATUS_SUCCESS )\r
1712                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &pol,GPIO_POL_L , 4);\r
1713         if ( status == STATUS_SUCCESS )\r
1714                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &mod,GPIO_MOD_L , 4);\r
1715         if ( status == STATUS_SUCCESS )\r
1716                 // Set CPUMODE\r
1717                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, CPUMODE, 4);\r
1718     if ( status == STATUS_SUCCESS )\r
1719         {\r
1720                 data &= ~CPUMODE_MSK;\r
1721                 data |= 1 << CPUMODE_SHIFT;\r
1722                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, CPUMODE, 4);\r
1723         }\r
1724         if ( status == STATUS_SUCCESS )\r
1725         {\r
1726                 // Reset flash\r
1727                 data = 0xf0;\r
1728                 status = fw_flash_write_data(p_BusInterface, &data, 0x0, 4);\r
1729         }\r
1730         return status;\r
1731 }\r
1732 \r
1733 static NTSTATUS\r
1734 fw_flash_deinit(\r
1735         IN              BUS_INTERFACE_STANDARD  *p_BusInterface )\r
1736 {\r
1737         uint32_t data = 0;\r
1738         NTSTATUS status = STATUS_SUCCESS;\r
1739     \r
1740         status = fw_set_bank(p_BusInterface, 0);\r
1741         if ( status == STATUS_SUCCESS )\r
1742                 // Restore origin values\r
1743                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dir,GPIO_DIR_L , 4);\r
1744         if ( status == STATUS_SUCCESS )\r
1745                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_pol,GPIO_POL_L , 4);\r
1746         if ( status == STATUS_SUCCESS )\r
1747                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_mod,GPIO_MOD_L , 4);\r
1748         if ( status == STATUS_SUCCESS )\r
1749                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dat,GPIO_DAT_L , 4);\r
1750         if ( status == STATUS_SUCCESS )\r
1751                 // Free GPIO Semaphore\r
1752                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, SEMAP63, 4);\r
1753         return status;\r
1754 }\r
1755 \r
1756 static NTSTATUS\r
1757 fw_set_bank(\r
1758         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1759         IN               uint32_t bank )\r
1760 {\r
1761         NTSTATUS  status = STATUS_SUCCESS;\r
1762         uint32_t        data = ( (uint32_t)0x70 << 24 );\r
1763         uint32_t        mask = ((bank >> (BANK_SHIFT-4)) << 24 );\r
1764 \r
1765         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATACLEAR_L, 4);\r
1766         if (status == STATUS_SUCCESS)\r
1767         {\r
1768         // A1\r
1769                 data &= mask;\r
1770                 //data |= mask; // for A0\r
1771                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATASET_L, 4);\r
1772         }\r
1773         return status;\r
1774 }\r