[MTHCA] cleaup: remove unused global variable
[mirror/winof/.git] / hw / mthca / 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: hca_driver.c 46 2005-05-30 17:55:53Z sleybo $\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 #include "hca_driver.h"\r
38 #include "hca_debug.h"\r
39 \r
40 #include "mthca_log.h"\r
41 #if defined(EVENT_TRACING)\r
42 #ifdef offsetof\r
43 #undef offsetof\r
44 #endif\r
45 #include "hca_driver.tmh"\r
46 #endif\r
47 #include "mthca_dev.h"\r
48 #include <wdmguid.h>\r
49 #include <initguid.h>\r
50 #pragma warning( push, 3 )\r
51 //#include "MdCard.h"\r
52 #pragma warning( pop )\r
53 #include <iba/ib_ci_ifc.h>\r
54 #include "mthca/mthca_vc.h"\r
55 \r
56 /* from \inc\platform\evntrace.h\r
57 #define TRACE_LEVEL_NONE        0   // Tracing is not on\r
58 #define TRACE_LEVEL_FATAL       1   // Abnormal exit or termination\r
59 #define TRACE_LEVEL_ERROR       2   // Severe errors that need logging\r
60 #define TRACE_LEVEL_WARNING     3   // Warnings such as allocation failure\r
61 #define TRACE_LEVEL_INFORMATION 4   // Includes non-error cases(e.g.,Entry-Exit)\r
62 #define TRACE_LEVEL_VERBOSE     5   // Detailed traces from intermediate steps\r
63 */\r
64 uint32_t g_mthca_dbg_level = TRACE_LEVEL_INFORMATION;\r
65 uint32_t g_mthca_dbg_flags= 0xffff;\r
66 WCHAR g_wlog_buf[ MAX_LOG_BUF_LEN ]; \r
67 UCHAR g_slog_buf[ MAX_LOG_BUF_LEN ];  \r
68 \r
69 /*\r
70  * UVP name does not include file extension.  For debug builds, UAL\r
71  * will append "d.dll".  For release builds, UAL will append ".dll"\r
72  */\r
73 char                    mlnx_uvp_lib_name[MAX_LIB_NAME] = {"mthcau"};\r
74 \r
75 \r
76 NTSTATUS\r
77 DriverEntry(\r
78         IN                              PDRIVER_OBJECT                          p_driver_obj,\r
79         IN                              PUNICODE_STRING                         p_registry_path );\r
80 \r
81 static NTSTATUS\r
82 __read_registry(\r
83         IN                              UNICODE_STRING* const           p_Param_Path );\r
84 \r
85 static void\r
86 hca_drv_unload(\r
87         IN                              PDRIVER_OBJECT                          p_driver_obj );\r
88 \r
89 static NTSTATUS\r
90 hca_sysctl(\r
91         IN                              PDEVICE_OBJECT                          p_dev_obj,\r
92         IN                              PIRP                                            p_irp );\r
93 \r
94 static NTSTATUS\r
95 __pnp_notify_target(\r
96         IN                              TARGET_DEVICE_REMOVAL_NOTIFICATION      *p_notify,\r
97         IN                              void                                            *context );\r
98 \r
99 static NTSTATUS\r
100 __pnp_notify_ifc(\r
101         IN                              DEVICE_INTERFACE_CHANGE_NOTIFICATION    *p_notify,\r
102         IN                              void                                            *context );\r
103 \r
104 static NTSTATUS\r
105 fw_access_pciconf (\r
106                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
107                 IN              ULONG                                                   op_flag,\r
108                 IN              PVOID                                                   p_buffer,\r
109                 IN              ULONG                                                   offset,\r
110                 IN              ULONG POINTER_ALIGNMENT                 length );\r
111 \r
112 static NTSTATUS\r
113 fw_get_pci_bus_interface(\r
114         IN              DEVICE_OBJECT                           *p_dev_obj,\r
115         OUT             BUS_INTERFACE_STANDARD          *p_BusInterface );\r
116 \r
117 static NTSTATUS\r
118 fw_flash_write_data (\r
119                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
120                 IN              PVOID                                                   p_buffer,\r
121                 IN              ULONG                                                   offset,\r
122                 IN              ULONG POINTER_ALIGNMENT                 length );\r
123 \r
124 static NTSTATUS\r
125 fw_flash_read_data (\r
126                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
127                 IN              PVOID                                                   p_buffer,\r
128                 IN              ULONG                                                   offset,\r
129                 IN              ULONG POINTER_ALIGNMENT                 length );\r
130 \r
131 static NTSTATUS\r
132 fw_flash_read4( \r
133         IN                      BUS_INTERFACE_STANDARD  *p_BusInterface,\r
134         IN                      uint32_t                                addr, \r
135         IN      OUT             uint32_t                                *p_data);\r
136 \r
137 static NTSTATUS\r
138 fw_flash_readbuf(\r
139         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
140         IN              uint32_t                                offset,\r
141         IN OUT  void                                    *p_data,\r
142         IN              uint32_t                                len);\r
143 static NTSTATUS\r
144 fw_set_bank(\r
145         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
146         IN              uint32_t                                bank );\r
147 \r
148 static NTSTATUS\r
149 fw_flash_init(\r
150                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  );\r
151 \r
152 static NTSTATUS\r
153 fw_flash_deinit(\r
154                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  );\r
155 \r
156 #ifdef ALLOC_PRAGMA\r
157 #pragma alloc_text (INIT, DriverEntry)\r
158 #pragma alloc_text (INIT, __read_registry)\r
159 #pragma alloc_text (PAGE, hca_drv_unload)\r
160 #pragma alloc_text (PAGE, hca_sysctl)\r
161 #endif\r
162 \r
163 NTSTATUS\r
164 DriverEntry(\r
165         IN                              PDRIVER_OBJECT                  p_driver_obj,\r
166         IN                              PUNICODE_STRING                 p_registry_path )\r
167 {\r
168         NTSTATUS                        status;\r
169         cl_status_t                     cl_status;\r
170 #if defined(EVENT_TRACING)\r
171         WPP_INIT_TRACING(p_driver_obj ,p_registry_path);\r
172 #endif\r
173         HCA_ENTER( HCA_DBG_DEV );\r
174 \r
175         status = __read_registry( p_registry_path );\r
176         if( !NT_SUCCESS( status ) )\r
177         {\r
178                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_INIT, \r
179                         ("__read_registry_path returned 0x%X.\n", status));\r
180                 return status;\r
181         }\r
182 \r
183         /* Initialize Adapter DB */\r
184         cl_status = mlnx_hcas_init();\r
185         if( cl_status != CL_SUCCESS )\r
186         {\r
187                 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_INIT ,\r
188                         ("mlnx_hcas_init returned %s.\n", cl_status_text[cl_status]));\r
189                 return cl_to_ntstatus( cl_status );\r
190         }\r
191 //      cl_memclr( mlnx_hca_array, MLNX_MAX_HCA * sizeof(ci_interface_t) );\r
192 \r
193         /*leo:  init function table */\r
194         hca_init_vfptr();\r
195         \r
196         p_driver_obj->MajorFunction[IRP_MJ_PNP] = cl_pnp;\r
197         p_driver_obj->MajorFunction[IRP_MJ_POWER] = cl_power;\r
198         p_driver_obj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = hca_sysctl;\r
199         p_driver_obj->DriverUnload = hca_drv_unload;\r
200         p_driver_obj->DriverExtension->AddDevice = hca_add_device;\r
201 \r
202         /* init core */\r
203         if (ib_core_init()) {\r
204                 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_INIT ,("Failed to init core, aborting.\n"));\r
205                 return STATUS_UNSUCCESSFUL;\r
206         }\r
207 \r
208         /* init uverbs module */\r
209         if (ib_uverbs_init()) {\r
210                 HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_INIT ,("Failed ib_uverbs_init, aborting.\n"));\r
211                 return STATUS_UNSUCCESSFUL;\r
212         }\r
213         HCA_EXIT( HCA_DBG_DEV );\r
214         return STATUS_SUCCESS;\r
215 }\r
216 \r
217 \r
218 static NTSTATUS\r
219 __read_registry(\r
220         IN                              UNICODE_STRING* const   p_registry_path )\r
221 {\r
222         NTSTATUS                                        status;\r
223         /* Remember the terminating entry in the table below. */\r
224         RTL_QUERY_REGISTRY_TABLE        table[3];\r
225         UNICODE_STRING                          param_path;\r
226 \r
227         HCA_ENTER( HCA_DBG_DEV );\r
228 \r
229         RtlInitUnicodeString( &param_path, NULL );\r
230         param_path.MaximumLength = p_registry_path->Length + \r
231                 sizeof(L"\\Parameters");\r
232         param_path.Buffer = cl_zalloc( param_path.MaximumLength );\r
233         if( !param_path.Buffer )\r
234         {\r
235                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_DEV, \r
236                         ("Failed to allocate parameters path buffer.\n"));\r
237                 return STATUS_INSUFFICIENT_RESOURCES;\r
238         }\r
239 \r
240         RtlAppendUnicodeStringToString( &param_path, p_registry_path );\r
241         RtlAppendUnicodeToString( &param_path, L"\\Parameters" );\r
242 \r
243         /*\r
244          * Clear the table.  This clears all the query callback pointers,\r
245          * and sets up the terminating table entry.\r
246          */\r
247         cl_memclr( table, sizeof(table) );\r
248 \r
249         /* Setup the table entries. */\r
250         table[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
251         table[0].Name = L"DebugLevel";\r
252         table[0].EntryContext = &g_mthca_dbg_level;\r
253         table[0].DefaultType = REG_DWORD;\r
254         table[0].DefaultData = &g_mthca_dbg_level;\r
255         table[0].DefaultLength = sizeof(ULONG);\r
256 \r
257         \r
258         table[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
259         table[1].Name = L"DebugFlags";\r
260         table[1].EntryContext = &g_mthca_dbg_flags;\r
261         table[1].DefaultType = REG_DWORD;\r
262         table[1].DefaultData = &g_mthca_dbg_flags;\r
263         table[1].DefaultLength = sizeof(ULONG);\r
264 \r
265         /* Have at it! */\r
266         status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE, \r
267                 param_path.Buffer, table, NULL, NULL );\r
268 \r
269         HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_INIT, \r
270                         ("debug level  %d debug flags  0x%.8x\n",\r
271                         g_mthca_dbg_level ,\r
272                         g_mthca_dbg_flags));\r
273 \r
274 \r
275         cl_free( param_path.Buffer );\r
276         HCA_EXIT( HCA_DBG_DEV );\r
277         return status;\r
278 }\r
279 \r
280 \r
281 static void\r
282 hca_drv_unload(\r
283         IN                              PDRIVER_OBJECT                  p_driver_obj )\r
284 {\r
285         HCA_ENTER( HCA_DBG_DEV );\r
286 \r
287         UNUSED_PARAM( p_driver_obj );\r
288 \r
289         ib_uverbs_cleanup();\r
290         ib_core_cleanup();\r
291         \r
292         HCA_EXIT( HCA_DBG_DEV );\r
293 #if defined(EVENT_TRACING)\r
294         WPP_CLEANUP(p_driver_obj);\r
295 #endif\r
296 \r
297 }\r
298 \r
299 \r
300 static NTSTATUS\r
301 hca_sysctl(\r
302         IN                              PDEVICE_OBJECT                          p_dev_obj,\r
303         IN                              PIRP                                            p_irp )\r
304 {\r
305         NTSTATUS                status;\r
306         hca_dev_ext_t   *p_ext;\r
307 \r
308         HCA_ENTER( HCA_DBG_DEV );\r
309 \r
310         p_ext = p_dev_obj->DeviceExtension;\r
311 \r
312         IoSkipCurrentIrpStackLocation( p_irp );\r
313         status = IoCallDriver( p_ext->cl_ext.p_next_do, p_irp );\r
314 \r
315         HCA_EXIT( HCA_DBG_DEV );\r
316         return status;\r
317 }\r
318 \r
319 typedef struct Primary_Sector{\r
320         uint32_t fi_addr;\r
321         uint32_t fi_size;\r
322         uint32_t signature;\r
323         uint32_t fw_reserved[5];\r
324         uint32_t vsd[56];\r
325         uint32_t branch_to;\r
326         uint32_t crc016;\r
327 } primary_sector_t;\r
328 \r
329 static uint32_t old_dir;\r
330 static uint32_t old_pol;\r
331 static uint32_t old_mod;\r
332 static uint32_t old_dat;\r
333 \r
334 static NTSTATUS\r
335 fw_access_pciconf (\r
336                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
337                 IN              ULONG                                                   op_flag,\r
338                 IN              PVOID                                                   p_buffer,\r
339                 IN              ULONG                                                   offset,\r
340                 IN              ULONG POINTER_ALIGNMENT                 length )\r
341 {\r
342 \r
343         ULONG                           bytes;  \r
344         NTSTATUS                        status = STATUS_SUCCESS;\r
345 \r
346         PAGED_CODE();\r
347 \r
348         if (p_BusInterface)\r
349         {\r
350 \r
351                 bytes = p_BusInterface->SetBusData(\r
352                                                 p_BusInterface->Context,\r
353                                                 PCI_WHICHSPACE_CONFIG,\r
354                                                 (PVOID)&offset,\r
355                                                 PCI_CONF_ADDR,\r
356                                                 sizeof(ULONG) );\r
357 \r
358                 if( op_flag == 0 )\r
359                 {\r
360                         if ( bytes )\r
361                                 bytes = p_BusInterface->GetBusData(\r
362                                                         p_BusInterface->Context,\r
363                                                         PCI_WHICHSPACE_CONFIG,\r
364                                                         p_buffer,\r
365                                                         PCI_CONF_DATA,\r
366                                                         length );\r
367                         if ( !bytes )\r
368                                 status = STATUS_NOT_SUPPORTED;\r
369                 }\r
370 \r
371                 else\r
372                 {\r
373                         if ( bytes )\r
374                                 bytes = p_BusInterface->SetBusData(\r
375                                                         p_BusInterface->Context,\r
376                                                         PCI_WHICHSPACE_CONFIG,\r
377                                                         p_buffer,\r
378                                                         PCI_CONF_DATA,\r
379                                                         length);\r
380 \r
381                         if ( !bytes )\r
382                                 status = STATUS_NOT_SUPPORTED;\r
383                 }\r
384         }\r
385         return status;\r
386 }\r
387 \r
388 static NTSTATUS\r
389 fw_get_pci_bus_interface(\r
390         IN              DEVICE_OBJECT                           *p_dev_obj,\r
391         OUT             BUS_INTERFACE_STANDARD          *p_BusInterface )\r
392 {\r
393         KEVENT event;\r
394         NTSTATUS status;\r
395         PIRP p_irp;\r
396         IO_STATUS_BLOCK ioStatus;\r
397         PIO_STACK_LOCATION p_irpStack;\r
398         PDEVICE_OBJECT p_target_obj;\r
399 \r
400         KeInitializeEvent( &event, NotificationEvent, FALSE );\r
401 \r
402         p_target_obj = IoGetAttachedDeviceReference( p_dev_obj );\r
403 \r
404         p_irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,\r
405                                                                                 p_target_obj,\r
406                                                                                 NULL,\r
407                                                                                 0,\r
408                                                                                 NULL,\r
409                                                                                 &event,\r
410                                                                                 &ioStatus );\r
411         if (p_irp == NULL) {\r
412                 status = STATUS_INSUFFICIENT_RESOURCES;\r
413                 goto End;\r
414         }\r
415         p_irpStack = IoGetNextIrpStackLocation( p_irp );\r
416         p_irpStack->MinorFunction = IRP_MN_QUERY_INTERFACE;\r
417         p_irpStack->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;\r
418         p_irpStack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);\r
419         p_irpStack->Parameters.QueryInterface.Version = 1;\r
420         p_irpStack->Parameters.QueryInterface.Interface = (PINTERFACE) p_BusInterface;\r
421         p_irpStack->Parameters.QueryInterface.InterfaceSpecificData = NULL;\r
422 \r
423         p_irp->IoStatus.Status = STATUS_NOT_SUPPORTED;\r
424         \r
425         status = IoCallDriver( p_target_obj, p_irp );\r
426 \r
427         if ( status == STATUS_PENDING )\r
428         {\r
429                 KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );\r
430                 status = ioStatus.Status;\r
431         }\r
432 End:\r
433         // Done with reference\r
434         ObDereferenceObject( p_target_obj );\r
435         return status;\r
436 }\r
437 \r
438 typedef struct _mthca_map_space {\r
439         struct list_head list;\r
440         PMDL    p_mdl;\r
441         PVOID   va;\r
442         PEPROCESS p_pcs;\r
443 } mthca_map_space;\r
444 \r
445 static NTSTATUS\r
446 __map_crspace(\r
447         IN                              struct ib_ucontext *                    p_context,\r
448         IN                              mlnx_hob_t                      *       p_hob,\r
449         IN                              PVOID                                           p_buf,\r
450         IN                              ULONG                                           buf_size\r
451         )\r
452 {\r
453         NTSTATUS status;\r
454         PMDL p_mdl;\r
455         PVOID ua, ka;\r
456         ULONG sz;\r
457         mthca_map_space *p_map;\r
458         hca_dev_ext_t *p_ext = EXT_FROM_HOB(p_hob);\r
459         map_crspace *p_res = (map_crspace *)p_buf;\r
460 \r
461         HCA_ENTER( HCA_DBG_PNP );\r
462 \r
463         // sanity checks\r
464         if ( buf_size < sizeof *p_res ) {\r
465                 status = STATUS_INVALID_PARAMETER;\r
466                 goto err_invalid_params;\r
467         }\r
468 \r
469         // allocate a structure\r
470         p_map = (mthca_map_space *)kmalloc(sizeof *p_map, GFP_KERNEL);\r
471         if (p_map == NULL) {\r
472                 status = STATUS_INSUFFICIENT_RESOURCES;\r
473                 goto err_no_memory;\r
474         }\r
475 \r
476         // support several sim clients \r
477         down( &p_context->mutex );\r
478         \r
479         // map memory\r
480         sz =(ULONG)p_ext->bar[HCA_BAR_TYPE_HCR].size;\r
481         if (!p_ext->bar[HCA_BAR_TYPE_HCR].virt) {\r
482                 PHYSICAL_ADDRESS pa;\r
483                 pa.QuadPart = p_ext->bar[HCA_BAR_TYPE_HCR].phys;\r
484                 ka = MmMapIoSpace( pa, sz, MmNonCached ); \r
485                 if ( ka == NULL) {\r
486                         HCA_PRINT(TRACE_LEVEL_ERROR  , HCA_DBG_SHIM,\r
487                                 ("No kernel mapping of CR space.\n") );\r
488                         status = STATUS_UNSUCCESSFUL;\r
489                         goto err_map_to_kernel;\r
490                 }\r
491                 p_ext->bar[HCA_BAR_TYPE_HCR].virt = ka;\r
492         }\r
493         ka = p_ext->bar[HCA_BAR_TYPE_HCR].virt;\r
494 \r
495         // prepare for mapping to user space \r
496         p_mdl = IoAllocateMdl( ka, sz, FALSE,FALSE,NULL);\r
497         if (p_mdl == NULL) {\r
498                 HCA_PRINT(TRACE_LEVEL_ERROR  , HCA_DBG_SHIM, \r
499                         ("IoAllocateMdl failed.\n") );\r
500                 status = STATUS_INSUFFICIENT_RESOURCES;\r
501                 goto err_alloc_mdl;\r
502         }\r
503 \r
504         // fill MDL\r
505         MmBuildMdlForNonPagedPool(p_mdl);\r
506         \r
507         // map the buffer into user space \r
508         ua = MmMapLockedPagesSpecifyCache( p_mdl, UserMode, MmNonCached, \r
509                 NULL, FALSE, NormalPagePriority );\r
510         if (ua == NULL) {\r
511                 HCA_PRINT(TRACE_LEVEL_ERROR  , HCA_DBG_SHIM, \r
512                         ("MmMapLockedPagesSpecifyCache failed.\n") );\r
513                 status =  STATUS_UNSUCCESSFUL;\r
514                 goto err_map_to_user;\r
515         }\r
516         \r
517         // fill the results\r
518         p_res->va = ua;\r
519         p_res->size = sz;\r
520 \r
521         // resource tracking\r
522         p_map->p_mdl = p_mdl;\r
523         p_map->va = ua;\r
524         p_map->p_pcs = PsGetCurrentProcess();\r
525         list_add_tail(&p_map->list, &p_context->map_list);\r
526         \r
527         up( &p_context->mutex );\r
528         status = STATUS_SUCCESS;\r
529         goto out;\r
530 \r
531 err_map_to_user:\r
532         IoFreeMdl( p_mdl );\r
533 err_alloc_mdl:\r
534 err_map_to_kernel:\r
535         up( &p_context->mutex );\r
536         kfree( p_map );\r
537 err_no_memory:\r
538 err_invalid_params:     \r
539 out:    \r
540         HCA_EXIT( HCA_DBG_PNP );\r
541         return status;\r
542 }\r
543 \r
544 \r
545 static NTSTATUS\r
546 __unmap_crspace(\r
547         IN                              struct ib_ucontext *                    p_context,\r
548         IN                              PVOID                                           p_buf,\r
549         IN                              ULONG                                           buf_size\r
550         )\r
551 {\r
552         NTSTATUS status;\r
553         unmap_crspace *parm = (unmap_crspace *)p_buf;\r
554         mthca_map_space *p_map, *p_tmp;\r
555         int found = FALSE;\r
556         PEPROCESS  p_pcs = PsGetCurrentProcess();\r
557 \r
558         HCA_ENTER( HCA_DBG_PNP );\r
559 \r
560         // sanity checks\r
561         if ( buf_size < sizeof *parm ) {\r
562                 status = STATUS_INVALID_PARAMETER;\r
563                 goto err_invalid_params;\r
564         }\r
565 \r
566         // support several sim clients \r
567         down( &p_context->mutex );\r
568 \r
569         // look for the mapping info\r
570         list_for_each_entry_safe(p_map, p_tmp, &p_context->map_list, list, \r
571                 mthca_map_space, mthca_map_space) {\r
572                 if (p_map->va == parm->va && p_map->p_pcs == p_pcs) {\r
573                         found = TRUE;\r
574                         break;\r
575                 }\r
576         }\r
577 \r
578         if (!found) {\r
579                 HCA_PRINT(TRACE_LEVEL_ERROR  , HCA_DBG_SHIM, \r
580                         ("Not found internal info for unmappipng.%p for PID %d.\n" , \r
581                         parm->va, (int)(INT_PTR)PsGetCurrentProcessId()));\r
582                 status =  STATUS_UNSUCCESSFUL;\r
583                 goto err_not_found;\r
584         }\r
585 \r
586         // release the resources\r
587         list_del( &p_map->list );\r
588         MmUnmapLockedPages(p_map->va, p_map->p_mdl);\r
589         IoFreeMdl( p_map->p_mdl );\r
590         kfree( p_map );\r
591 \r
592         up( &p_context->mutex );\r
593         status = STATUS_SUCCESS;\r
594         goto out;\r
595 \r
596 err_not_found:\r
597         up( &p_context->mutex );\r
598 err_invalid_params:     \r
599 out:    \r
600         HCA_EXIT( HCA_DBG_PNP );\r
601         return status;\r
602 }\r
603 \r
604 void\r
605 unmap_crspace_for_all( struct ib_ucontext *p_context )\r
606 {\r
607         mthca_map_space *p_map, *p_tmp;\r
608 \r
609         HCA_ENTER( HCA_DBG_PNP );\r
610 \r
611         down( &p_context->mutex );\r
612 \r
613         list_for_each_entry_safe(p_map, p_tmp, &p_context->map_list, list, \r
614                 mthca_map_space, mthca_map_space) {\r
615                 list_del( &p_map->list );\r
616                 MmUnmapLockedPages(p_map->va, p_map->p_mdl);\r
617                 IoFreeMdl( p_map->p_mdl );\r
618                 kfree( p_map );\r
619         }\r
620 \r
621         up( &p_context->mutex );\r
622 \r
623         HCA_EXIT( HCA_DBG_PNP );\r
624 }\r
625 \r
626 ib_api_status_t\r
627 fw_access_ctrl(\r
628         IN              const   ib_ca_handle_t                          h_ca,\r
629         IN              const   void* __ptr64* const            handle_array    OPTIONAL,\r
630         IN                              uint32_t                                        num_handles,\r
631         IN                              ib_ci_op_t* const                       p_ci_op,\r
632         IN      OUT                     ci_umv_buf_t                            *p_umv_buf )\r
633 {\r
634         DEVICE_OBJECT                           *p_dev_obj;\r
635         static BUS_INTERFACE_STANDARD    BusInterface;\r
636         static uint32_t                         if_ready;\r
637         NTSTATUS                                        status;\r
638         PVOID                                           p_data;\r
639         ULONG                                           offset;\r
640         ULONG POINTER_ALIGNMENT         length;\r
641         ib_ci_op_t                                      *p_ci;\r
642         mlnx_hob_t                                      *p_hob;\r
643         struct ib_ucontext *                    p_context;\r
644 \r
645         UNREFERENCED_PARAMETER(handle_array);\r
646         UNREFERENCED_PARAMETER(num_handles);\r
647         UNREFERENCED_PARAMETER(p_umv_buf);\r
648 \r
649         status =  STATUS_SUCCESS;\r
650 \r
651         if( p_umv_buf ) {\r
652                 p_context = (struct ib_ucontext *)h_ca;\r
653                 p_hob = HOB_FROM_IBDEV( ((struct ib_ucontext*)h_ca)->device );\r
654         }\r
655         else {\r
656                 p_context = NULL;\r
657                 p_hob = (mlnx_hob_t *)(const void *)h_ca;\r
658         }\r
659 \r
660         p_dev_obj = (DEVICE_OBJECT *)EXT_FROM_HOB(p_hob)->cl_ext.p_self_do;\r
661         p_ci =  p_ci_op;\r
662 \r
663         if ( !p_ci ||  !p_ci->buf_size )\r
664                 return STATUS_INVALID_DEVICE_REQUEST;\r
665 \r
666         length = p_ci->buf_size;\r
667         offset = p_ci->buf_info;\r
668         p_data = p_ci->p_buf;\r
669 \r
670         switch ( p_ci->command )\r
671         {\r
672         case FW_MAP_CRSPACE:\r
673                 status = __map_crspace(p_context, p_hob, p_data, length);\r
674                 break;\r
675                 \r
676         case FW_UNMAP_CRSPACE:\r
677                 status = __unmap_crspace(p_context, p_data, length);\r
678                 break;\r
679                                 \r
680         case FW_READ: // read data from flash\r
681                 if ( if_ready )\r
682                         status = fw_flash_read_data(&BusInterface, p_data, offset, length);\r
683                 break;\r
684 \r
685         case FW_WRITE: // write data to flash\r
686                 if ( if_ready )\r
687                         status = fw_flash_write_data(&BusInterface, p_data, offset, length);\r
688                 break;\r
689 \r
690         case FW_READ_CMD:\r
691                 if ( if_ready )\r
692                         status = fw_access_pciconf(&BusInterface, 0 , p_data, offset, 4);\r
693                 break;\r
694 \r
695         case FW_WRITE_CMD:\r
696                 if ( if_ready )\r
697                         status = fw_access_pciconf(&BusInterface, 1 , p_data, offset, 4);\r
698                 break;\r
699 \r
700         case FW_CLOSE_IF: // close BusInterface\r
701                 if (if_ready )\r
702                 {\r
703                         if_ready = 0;\r
704                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
705                 }\r
706                 return status;\r
707 \r
708         case FW_OPEN_IF: // open BusInterface\r
709                 if ( !if_ready )\r
710                 {\r
711                         status = fw_get_pci_bus_interface(p_dev_obj, &BusInterface);\r
712 \r
713                         if ( NT_SUCCESS( status ) )\r
714                         {\r
715                                 if_ready = 1;\r
716                                 status = STATUS_SUCCESS;\r
717                         }\r
718                 }\r
719                 return status;\r
720 \r
721         default:\r
722                 status = STATUS_NOT_SUPPORTED;\r
723         }\r
724 \r
725         if ( status != STATUS_SUCCESS )\r
726         {\r
727                 if ( if_ready )\r
728                 {\r
729                         if_ready = 0;\r
730                         BusInterface.InterfaceDereference((PVOID)BusInterface.Context);\r
731                 }\r
732                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_INIT, \r
733                         ("fw_access_ctrl failed returns %08x.\n", status));\r
734         }\r
735         return status;\r
736 }\r
737 \r
738 static NTSTATUS\r
739 fw_flash_write_data (\r
740                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
741                 IN              PVOID                                                   p_buffer,\r
742                 IN              ULONG                                                   offset,\r
743                 IN              ULONG POINTER_ALIGNMENT                 length )\r
744 {\r
745         NTSTATUS                status;\r
746         uint32_t                cnt = 0;\r
747         uint32_t                lcl_data;\r
748 \r
749         lcl_data = (*((uint32_t*)p_buffer) << 24);\r
750 \r
751         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET+4, length );\r
752         if ( status != STATUS_SUCCESS )\r
753                 return status;\r
754         lcl_data = ( WRITE_BIT | (offset & ADDR_MSK));\r
755                 \r
756         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &lcl_data, FLASH_OFFSET, 4 );\r
757         if ( status != STATUS_SUCCESS )\r
758         return status;\r
759 \r
760         lcl_data = 0;\r
761         \r
762         do\r
763         {\r
764                 if (++cnt > 5000)\r
765                 {\r
766                         return STATUS_DEVICE_NOT_READY;\r
767                 }\r
768 \r
769                 status = fw_access_pciconf(p_BusInterface, FW_READ , &lcl_data, FLASH_OFFSET, 4 );\r
770                 if ( status != STATUS_SUCCESS )\r
771                 return status;\r
772 \r
773         } while(lcl_data & CMD_MASK);\r
774 \r
775         return status;\r
776 }\r
777 \r
778 static NTSTATUS\r
779 fw_flash_read_data (\r
780                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
781                 IN              PVOID                                                   p_buffer,\r
782                 IN              ULONG                                                   offset,\r
783                 IN              ULONG POINTER_ALIGNMENT                 length )\r
784 {\r
785         NTSTATUS        status = STATUS_SUCCESS;\r
786         uint32_t        cnt = 0;\r
787         uint32_t        lcl_data = ( READ_BIT | (offset & ADDR_MSK));\r
788         \r
789         status = fw_access_pciconf(p_BusInterface, FW_WRITE, &lcl_data, FLASH_OFFSET, 4 );\r
790         if ( status != STATUS_SUCCESS )\r
791                 return status;\r
792 \r
793         lcl_data = 0;\r
794         do\r
795         {\r
796                 // Timeout checks\r
797                 if (++cnt > 5000 )\r
798                 {\r
799                         return STATUS_DEVICE_NOT_READY;\r
800         }\r
801 \r
802                 status = fw_access_pciconf(p_BusInterface, FW_READ, &lcl_data, FLASH_OFFSET, 4 );\r
803         \r
804                 if ( status != STATUS_SUCCESS )\r
805                         return status;\r
806 \r
807         } while(lcl_data & CMD_MASK);\r
808 \r
809         status = fw_access_pciconf(p_BusInterface, FW_READ, p_buffer, FLASH_OFFSET+4, length );\r
810         return status;\r
811 }\r
812 \r
813 static NTSTATUS\r
814 fw_flash_read4( \r
815         IN                      BUS_INTERFACE_STANDARD  *p_BusInterface,\r
816         IN                      uint32_t                                addr, \r
817         IN      OUT             uint32_t                                *p_data)\r
818 {\r
819         NTSTATUS        status = STATUS_SUCCESS;\r
820         uint32_t lcl_data = 0;\r
821         uint32_t bank;\r
822         static uint32_t curr_bank =     0xffffffff;\r
823 \r
824         if (addr & 0x3)\r
825         {\r
826                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_INIT,\r
827                         ("Invalid address %08x\n", addr) );\r
828                 return STATUS_INVALID_PARAMETER;\r
829         }\r
830 \r
831         bank = addr & BANK_MASK;\r
832         if (bank !=  curr_bank)\r
833         {\r
834                 curr_bank = bank;\r
835                 if ((status = fw_set_bank(p_BusInterface, bank)) != STATUS_SUCCESS )\r
836                 {\r
837                         HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_INIT,\r
838                                 ("fw_set_bank returned %08x\n", status) );\r
839                         return STATUS_INVALID_PARAMETER;\r
840                 }\r
841         }\r
842         status = fw_flash_read_data(p_BusInterface, &lcl_data, addr, 4);\r
843         *p_data = cl_ntoh32(lcl_data);\r
844         return STATUS_SUCCESS;\r
845 }\r
846 \r
847 static NTSTATUS\r
848 fw_flash_readbuf(\r
849                 IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
850                 IN              uint32_t                                offset,\r
851                 IN OUT  void                                    *p_data,\r
852                 IN              uint32_t                                len)\r
853 {\r
854         NTSTATUS        status = STATUS_SUCCESS;\r
855         uint32_t *p_lcl_data;\r
856         uint32_t        i;\r
857 \r
858     if (offset & 0x3)\r
859     {\r
860         //Address should be 4-bytes aligned\r
861                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_INIT,\r
862                         ("Invalid address %08x\n", offset) );\r
863         return STATUS_INVALID_PARAMETER;\r
864     }\r
865     if (len & 0x3)\r
866     {\r
867         //Length should be 4-bytes aligned\r
868                 HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_INIT,\r
869                         ("Invalid length %d\n", len) );\r
870         return STATUS_INVALID_PARAMETER;\r
871     }\r
872     p_lcl_data = (uint32_t *)p_data;\r
873     \r
874         for ( i=0; i < (len >> 2); i++)\r
875     {                                   \r
876         if ( (status = fw_flash_read_data( p_BusInterface, p_lcl_data, offset, sizeof(uint32_t) )) != STATUS_SUCCESS )\r
877             return status;\r
878         offset += 4;\r
879                 p_lcl_data++;\r
880     }\r
881     return STATUS_SUCCESS;\r
882 } // Flash::flash_read\r
883 \r
884 static NTSTATUS\r
885 fw_flash_writebuf(\r
886                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface,\r
887                 IN              PVOID                                                   p_buffer,\r
888                 IN              ULONG                                                   offset,\r
889                 IN              ULONG POINTER_ALIGNMENT                 length )\r
890 {\r
891         NTSTATUS status = STATUS_SUCCESS;\r
892         uint32_t        i;\r
893         uint8_t *p_data = (uint8_t *)p_buffer;\r
894 \r
895         for ( i = 0; i < length;  i++ )\r
896         {\r
897                 status = fw_flash_write_data (p_BusInterface, p_data, offset, 1 );\r
898                 if (status != STATUS_SUCCESS )\r
899                         return status;\r
900                 p_data++;\r
901                 offset++;\r
902         }\r
903         return status;\r
904 }\r
905 static NTSTATUS\r
906 fw_flash_init(\r
907                 IN              BUS_INTERFACE_STANDARD                  *p_BusInterface  )\r
908 {\r
909         uint32_t dir;\r
910     uint32_t pol;\r
911     uint32_t mod;\r
912 \r
913     uint32_t cnt=0;\r
914     uint32_t data;\r
915         NTSTATUS status = STATUS_SUCCESS;\r
916         uint32_t        semaphore = 0;\r
917     \r
918         while ( !semaphore )\r
919         {\r
920                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, SEMAP63, 4);\r
921                 if ( status != STATUS_SUCCESS )\r
922                         break;\r
923                 if( !data )\r
924                 {\r
925                         semaphore = 1;\r
926                         break;\r
927                 }\r
928         if (++cnt > 5000 )\r
929         {\r
930             break;\r
931         }\r
932     } \r
933 \r
934         if ( !semaphore )\r
935         {\r
936                 return STATUS_NOT_SUPPORTED;\r
937         }\r
938 \r
939     // Save old values\r
940     \r
941         status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dir,GPIO_DIR_L , 4);\r
942         if ( status == STATUS_SUCCESS )\r
943                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_pol,GPIO_POL_L , 4);\r
944         if ( status == STATUS_SUCCESS )\r
945                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_mod,GPIO_MOD_L , 4);\r
946         if ( status == STATUS_SUCCESS )\r
947                 status = fw_access_pciconf(p_BusInterface, FW_READ , &old_dat,GPIO_DAT_L , 4);\r
948 \r
949    // Set Direction=1, Polarity=0, Mode=0 for 3 GPIO lower bits\r
950     dir = old_dir | 0x70;\r
951     pol = old_pol & ~0x70;\r
952     mod = old_mod & ~0x70;\r
953 \r
954         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &dir,GPIO_DIR_L , 4);\r
955         if ( status == STATUS_SUCCESS )\r
956                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &pol,GPIO_POL_L , 4);\r
957         if ( status == STATUS_SUCCESS )\r
958                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &mod,GPIO_MOD_L , 4);\r
959         if ( status == STATUS_SUCCESS )\r
960                 // Set CPUMODE\r
961                 status = fw_access_pciconf(p_BusInterface, FW_READ , &data, CPUMODE, 4);\r
962     if ( status == STATUS_SUCCESS )\r
963         {\r
964                 data &= ~CPUMODE_MSK;\r
965                 data |= 1 << CPUMODE_SHIFT;\r
966                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, CPUMODE, 4);\r
967         }\r
968         if ( status == STATUS_SUCCESS )\r
969         {\r
970                 // Reset flash\r
971                 data = 0xf0;\r
972                 status = fw_flash_write_data(p_BusInterface, &data, 0x0, 4);\r
973         }\r
974         return status;\r
975 }\r
976 \r
977 static NTSTATUS\r
978 fw_flash_deinit(\r
979         IN              BUS_INTERFACE_STANDARD  *p_BusInterface )\r
980 {\r
981         uint32_t data = 0;\r
982         NTSTATUS status = STATUS_SUCCESS;\r
983     \r
984         status = fw_set_bank(p_BusInterface, 0);\r
985         if ( status == STATUS_SUCCESS )\r
986                 // Restore origin values\r
987                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dir,GPIO_DIR_L , 4);\r
988         if ( status == STATUS_SUCCESS )\r
989                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_pol,GPIO_POL_L , 4);\r
990         if ( status == STATUS_SUCCESS )\r
991                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_mod,GPIO_MOD_L , 4);\r
992         if ( status == STATUS_SUCCESS )\r
993                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &old_dat,GPIO_DAT_L , 4);\r
994         if ( status == STATUS_SUCCESS )\r
995                 // Free GPIO Semaphore\r
996                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, SEMAP63, 4);\r
997         return status;\r
998 }\r
999 \r
1000 static NTSTATUS\r
1001 fw_set_bank(\r
1002         IN              BUS_INTERFACE_STANDARD  *p_BusInterface,\r
1003         IN               uint32_t bank )\r
1004 {\r
1005         NTSTATUS  status = STATUS_SUCCESS;\r
1006         uint32_t        data = ( (uint32_t)0x70 << 24 );\r
1007         uint32_t        mask = ((bank >> (BANK_SHIFT-4)) << 24 );\r
1008 \r
1009         status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATACLEAR_L, 4);\r
1010         if (status == STATUS_SUCCESS)\r
1011         {\r
1012         // A1\r
1013                 data &= mask;\r
1014                 //data |= mask; // for A0\r
1015                 status = fw_access_pciconf(p_BusInterface, FW_WRITE , &data, GPIO_DATASET_L, 4);\r
1016         }\r
1017         return status;\r
1018 }\r