[IBBUS,HW] add standby/hibernation support to IBBUS. [mlnx: 4750]
[mirror/winof/.git] / tools / qlgcvnic_config / vnic_child_config.c
1 /*\r
2  * Copyright (c) 2009 QLogic Corporation.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenFabrics.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 #include <stdio.h>\r
33 #include <string.h>\r
34 #include <wchar.h>\r
35 #include <windows.h>\r
36 #include <al_dev.h>\r
37 #include <complib/cl_byteswap.h>\r
38 #include <complib/cl_memory.h>\r
39 \r
40 #define MAX_DEVICE_ID_LEN     200\r
41 #define MAX_DEVICE_STRING_LEN           MAX_DEVICE_ID_LEN + 2   /* add extra 4 bytes in case we need double NULL ending */\r
42 \r
43 #pragma pack(push, 1)\r
44 typedef struct _ca_ioc_info {\r
45         net64_t                                 ca_guid;\r
46         ib_ioc_info_t                           info;\r
47         ib_svc_entry_t                          svc_entry_array[1];\r
48 } ca_ioc_info_t;\r
49 \r
50 typedef struct _child_device_info {\r
51         wchar_t         device_id[MAX_DEVICE_STRING_LEN];  \r
52         uint32_t        device_id_size;\r
53         wchar_t         compatible_id[MAX_DEVICE_STRING_LEN];\r
54         uint32_t        compatible_id_size;\r
55         wchar_t         hardware_id[MAX_DEVICE_STRING_LEN];\r
56         uint32_t        hardware_id_size;\r
57         wchar_t         description[MAX_DEVICE_STRING_LEN];\r
58         uint32_t        description_size;\r
59         ca_ioc_info_t   ca_ioc_path;\r
60         uint32_t        uniqueinstanceid;\r
61 }  child_device_info_t;\r
62 \r
63 #pragma pack(pop)\r
64 \r
65 int usage()\r
66 {\r
67         printf( "Correct usage to create VNIC child devices is:-\n" );\r
68         printf( "qlgcvnic_config -c <CAGUID> <IOCGUID> "\r
69                 "<InstanceID> <Interface Description>\n" );\r
70         printf( "Executing qlgcvnic_config without any option or with -l "\r
71                 "option will list the IOCs reachable from the host\n" );\r
72         return -1;\r
73 }\r
74 \r
75 DWORD   send_device_ioctl( DWORD ioctlcode, PVOID input_buf, DWORD in_size, PVOID *output_buf, PDWORD out_size )\r
76 {\r
77         DWORD   dwRet = 0, dwMemSize, dwBytesRet = 0;\r
78         BOOL    bRet;\r
79         PVOID   pBuf;\r
80         HANDLE  hDevice = INVALID_HANDLE_VALUE;\r
81 \r
82         hDevice = CreateFileW ( L"\\\\.\\VNICCONFIG",\r
83                                 GENERIC_READ | GENERIC_WRITE,\r
84                                 FILE_SHARE_READ | FILE_SHARE_WRITE,     /* share mode none */\r
85                                 NULL,                                   /* no security */\r
86                                 OPEN_EXISTING,\r
87                                 FILE_ATTRIBUTE_NORMAL,\r
88                                 NULL );                                 /* no template; */\r
89 \r
90         if ( hDevice == INVALID_HANDLE_VALUE ) \r
91         {\r
92                 printf( "Error opening VNICCONFIG device file\n" );\r
93                 return ERROR_FILE_NOT_FOUND;\r
94         }\r
95 \r
96         switch( ioctlcode ) \r
97         {\r
98                 case    UAL_IOC_DEVICE_CREATE:\r
99                         bRet = DeviceIoControl( hDevice, ioctlcode, input_buf, in_size, NULL, 0, &dwBytesRet, NULL );\r
100 \r
101                         if ( !bRet ) \r
102                         {\r
103                                 dwRet = GetLastError();\r
104                                 printf( "GetLastError after UAL_IOC_DEVICE_CREATE gives %d\n", dwRet );\r
105                         }\r
106                         break;\r
107 \r
108                 case    UAL_IOC_LIST:\r
109                         dwMemSize = sizeof(ca_ioc_info_t ) * 2;\r
110                         pBuf = NULL;\r
111 \r
112                         do \r
113                         {\r
114                                 if ( pBuf ) \r
115                                 {\r
116                                         cl_free( pBuf );\r
117                                         dwMemSize *= 2;                                 \r
118                                         pBuf = NULL;\r
119                                 }\r
120 \r
121                                 pBuf = cl_malloc( dwMemSize );\r
122 \r
123                                 if ( !pBuf ) \r
124                                 {\r
125                                         printf( "Insufficient memory\n" );\r
126                                         dwRet = ERROR_NOT_ENOUGH_MEMORY;\r
127                                         break;\r
128                                 }\r
129 \r
130                                 bRet = DeviceIoControl( hDevice, ioctlcode, NULL, 0, pBuf, dwMemSize, &dwBytesRet, NULL );\r
131                                 dwRet = GetLastError();\r
132 \r
133                                 if ( bRet ) \r
134                                 {\r
135                                         dwRet = 0;\r
136                                         break;\r
137                                 }\r
138                                 \r
139                         }while( dwRet == ERROR_INSUFFICIENT_BUFFER );\r
140 \r
141                         *output_buf = pBuf;\r
142                         *out_size = dwBytesRet;\r
143 \r
144                         break;\r
145         }\r
146 \r
147         CloseHandle( hDevice );\r
148         return dwRet;\r
149 }\r
150 \r
151 ca_ioc_info_t   *find_ca_ioc_path ( ca_ioc_info_t       *pList, DWORD   nListSize,\r
152                         uint64_t        ca_guid, uint64_t       ioc_guid )\r
153 {\r
154         while ( nListSize ) \r
155         {\r
156 \r
157                 if ( pList->ca_guid == ca_guid && pList->info.profile.ioc_guid == ioc_guid ) \r
158                 {\r
159                         return pList;\r
160                 }\r
161                 nListSize--;\r
162                 pList++;\r
163         }\r
164 \r
165         return NULL;\r
166 }\r
167 \r
168 #define IBIOU_SERVICE_PARAM_KEY         "SYSTEM\\CurrentControlSet\\Services\\ibiou"\r
169 #define IBIOU_PARAM_KEY_DEVICE_VALUE    "StaticChild"\r
170 #define IBIOU_PARAMETER_NAME            "Parameters"\r
171 #define MAX_VALUE_LENGTH                2048\r
172 \r
173 DWORD   write_device_name( char *device_name )\r
174 {\r
175 \r
176         DWORD   dwRet = 0, dwBytesRet = 0, n_size = 100, dwType;\r
177         HKEY    hKey = INVALID_HANDLE_VALUE;\r
178         LONG    lRet = -1;\r
179         PVOID   pOldValue, pNewValue, pBuf;\r
180         char    szKeyName[200];\r
181 \r
182         sprintf( szKeyName, "%s\\%s", IBIOU_SERVICE_PARAM_KEY, IBIOU_PARAMETER_NAME );\r
183         lRet = RegOpenKeyExA( HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_ALL_ACCESS, \r
184                                 &hKey );\r
185 \r
186 \r
187         if ( lRet != ERROR_SUCCESS ) \r
188         {\r
189                 printf( "Opening services key of ibiou failed\n" );\r
190                 dwRet = -1;\r
191         } \r
192         else \r
193         {\r
194                 do \r
195                 {\r
196                         pOldValue = cl_malloc( n_size );\r
197 \r
198                         if ( !pOldValue ) \r
199                         {\r
200                                 printf( "Not enough memory on system\n" );\r
201                                 break;\r
202                         }\r
203                         dwType = REG_MULTI_SZ;\r
204 \r
205                         lRet = RegQueryValueExA( hKey, IBIOU_PARAM_KEY_DEVICE_VALUE, 0, &dwType, pOldValue, &dwBytesRet );\r
206 \r
207 \r
208                         if ( lRet == ERROR_MORE_DATA ) \r
209                         {\r
210                                 cl_free( pOldValue );\r
211                                 pOldValue = NULL;\r
212                                 n_size = n_size*2;\r
213                         }\r
214 \r
215                 } while( lRet == ERROR_MORE_DATA && n_size < MAX_VALUE_LENGTH );\r
216 \r
217                 if ( lRet != ERROR_SUCCESS ) \r
218                 {\r
219                         cl_free( pOldValue );\r
220                         pOldValue = NULL;\r
221                 }\r
222 \r
223 \r
224                 n_size = dwBytesRet + strlen( device_name )*sizeof( char ) + 2*sizeof( char ); /*  more for NULLs */\r
225                 pNewValue = cl_malloc( n_size );\r
226                 pBuf = pNewValue;\r
227                 cl_memset( pNewValue, 0x00, n_size );\r
228                 if ( !pNewValue ) \r
229                 {\r
230                         printf( "Not enough memory on system\n" );\r
231                 } \r
232                 else \r
233                 {\r
234                         if ( pOldValue ) \r
235                         {       /* Come here only when "StaticChild" key was there already*/\r
236                                 cl_memcpy( pBuf, pOldValue, dwBytesRet );\r
237 \r
238                                 while ( *( ( PBYTE )pBuf ) != 0 || *( ( PBYTE ) pBuf + 1 ) != 0 )\r
239                                         pBuf = ( PBYTE ) pBuf + 1;\r
240 \r
241                                 pBuf = ( PBYTE ) pBuf + 1;\r
242                                 cl_free( pOldValue );\r
243                                 pOldValue = NULL;\r
244                         }\r
245 \r
246                         cl_memcpy( pBuf, device_name, strlen( device_name ) );\r
247                         lRet = RegSetValueExA( hKey, IBIOU_PARAM_KEY_DEVICE_VALUE, 0, REG_MULTI_SZ, \r
248                                                 pNewValue, ( strlen( device_name ) + dwBytesRet + 2 ) ); /* Two bytes for extra NULLs*/\r
249                         cl_free( pNewValue );\r
250                         RegCloseKey( hKey );\r
251                         if ( lRet != ERROR_SUCCESS ) \r
252                         {\r
253                                 printf( "Error setting device name in value of services key of ibiou\n" );\r
254                                 dwRet = -1;\r
255                         }\r
256                 }\r
257 \r
258         }\r
259         return dwRet;   \r
260 }\r
261 \r
262 static const    char    *value_names[] = {\r
263                 "CAGUID",\r
264 #define         CAGUID_INDEX            0\r
265                 "IOCGUID",\r
266 #define         IOCGUID_INDEX           1\r
267                 "CompatibleId",\r
268 #define         COMPATIBLEID_INDEX      2\r
269                 "Description",\r
270 #define         DESCRIPTION_INDEX       3\r
271                 "DeviceId",\r
272 #define         DEVICEID_INDEX          4\r
273                 "HardwareId",\r
274 #define         HARDWAREID_INDEX        5\r
275                 "InstanceId"\r
276 #define         INSTANCEID_INDEX        6\r
277 #define         MAXVALUE_INDEX          7\r
278 };\r
279 \r
280 DWORD   write_deviceinfo_to_registry( uint64_t  ca_guid, uint64_t       ioc_guid, \r
281                                         uint32_t        instance_id, char *device_name )\r
282 {\r
283         DWORD   dwRet = 0, dwDisposition, dwType, dwSize;\r
284         HKEY    hKey = INVALID_HANDLE_VALUE;\r
285         char    szKeyName[250];\r
286         LONG    lRet;\r
287         DWORD   dwIndex;\r
288         PVOID   pBuf;\r
289 \r
290         dwRet = write_device_name( device_name );\r
291 \r
292         if ( dwRet == 0 ) \r
293         {\r
294                 sprintf( szKeyName, "%s\\%s\\%s", \r
295                         IBIOU_SERVICE_PARAM_KEY, IBIOU_PARAMETER_NAME, device_name );\r
296                 lRet = RegCreateKeyExA( HKEY_LOCAL_MACHINE, szKeyName, 0,\r
297                                         NULL, REG_OPTION_NON_VOLATILE, \r
298                                         KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition  );\r
299 \r
300                 if ( dwDisposition == REG_CREATED_NEW_KEY ) \r
301                 {\r
302                         dwIndex = CAGUID_INDEX;\r
303                         \r
304                         while ( dwIndex < MAXVALUE_INDEX ) \r
305                         {\r
306 \r
307                                 switch( dwIndex ) \r
308                                 {\r
309                                         case    CAGUID_INDEX:\r
310                                                 pBuf = &ca_guid;\r
311                                                 dwType = REG_BINARY;\r
312                                                 dwSize = sizeof( uint64_t );\r
313                                                 break;\r
314 \r
315                                         case    IOCGUID_INDEX:\r
316                                                 pBuf = &ioc_guid;\r
317                                                 dwType = REG_BINARY;\r
318                                                 dwSize = sizeof( uint64_t );                                            \r
319                                                 break;\r
320 \r
321                                         case    DEVICEID_INDEX:\r
322                                                 pBuf = "IBA\\qlgcvnic";\r
323                                                 dwType = REG_SZ;\r
324                                                 dwSize = strlen( pBuf ) + 1;\r
325                                                 break;\r
326 \r
327                                         case    COMPATIBLEID_INDEX:             /* Currently all id's used are same. */\r
328                                         case    HARDWAREID_INDEX:\r
329                                                 pBuf = "IBA\\qlgcvnic";\r
330                                                 dwType = REG_MULTI_SZ;\r
331                                                 dwSize = strlen( pBuf ) + 1;                                            \r
332                                                 break;\r
333 \r
334                                         case    DESCRIPTION_INDEX:      \r
335                                                 pBuf = device_name;\r
336                                                 dwType = REG_SZ;\r
337                                                 dwSize = strlen( pBuf ) + 1;                                            \r
338                                                 break;\r
339 \r
340                                         case    INSTANCEID_INDEX:\r
341                                                 pBuf = &instance_id;\r
342                                                 dwType = REG_DWORD;\r
343                                                 dwSize = sizeof( instance_id );\r
344                                                 break;\r
345 \r
346                                         default:\r
347                                                 break;\r
348                                 }\r
349                                 lRet = RegSetValueExA( hKey, value_names[dwIndex], 0,\r
350                                                         dwType, pBuf, dwSize );\r
351 \r
352                                 if ( lRet != ERROR_SUCCESS ) \r
353                                 {\r
354                                         printf( "Failed in setting device information as Parameters of ibiou driver\n" );\r
355                                         dwRet = -1;\r
356                                         break;\r
357                                 }\r
358 \r
359                                 dwIndex++;\r
360                         }\r
361                 }\r
362 \r
363                 if ( hKey != INVALID_HANDLE_VALUE ) \r
364                 {\r
365                         RegCloseKey( hKey );\r
366                 }\r
367         }\r
368 \r
369         return dwRet;\r
370 }\r
371 \r
372 DWORD   create_child_device( uint64_t   ca_guid, uint64_t       ioc_guid, uint32_t instance_id, char *device_name )\r
373 {\r
374         ca_ioc_info_t           *pList = NULL, *p_ca_ioc_entry = NULL;\r
375         DWORD                   dwRet = 0, dwBytesRet;\r
376         child_device_info_t     *child_dev = NULL;\r
377         WCHAR                   szDevName[200];\r
378 \r
379 \r
380         dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );\r
381 \r
382         if ( dwRet ) \r
383         {\r
384                 printf( "Obtaining IOC LIST from ibiou failed\n" );\r
385         } \r
386         else \r
387         {\r
388                 p_ca_ioc_entry = find_ca_ioc_path( pList, dwBytesRet/sizeof( ca_ioc_info_t ),\r
389                                         ca_guid, ioc_guid );\r
390 \r
391                 if ( p_ca_ioc_entry ) \r
392                 {\r
393                         child_dev = cl_malloc( sizeof( child_device_info_t ) );\r
394                         cl_memset( child_dev, 0x00, sizeof( child_device_info_t ) );\r
395 \r
396                         if ( !child_dev ) \r
397                         {\r
398                                 printf( "Allocating memory for child device failed\n" );\r
399                         } \r
400                         else \r
401                         {\r
402                                 child_dev->ca_ioc_path = *p_ca_ioc_entry;\r
403                                 wcscpy( child_dev->device_id, L"IBA\\qlgcvnic" );\r
404                                 child_dev->device_id_size = ( wcslen( child_dev->device_id ) + 1 )*sizeof( WCHAR );\r
405                                 wcscpy( child_dev->hardware_id, L"IBA\\qlgcvnic" );\r
406                                 child_dev->hardware_id_size = ( wcslen( child_dev->hardware_id ) + 2 )*sizeof( WCHAR );\r
407                                 wcscpy( child_dev->compatible_id, L"IBA\\qlgcvnic" );\r
408                                 child_dev->compatible_id_size = ( wcslen( child_dev->compatible_id ) + 2 )*sizeof( WCHAR );\r
409                                 swprintf( szDevName, L"%S", device_name );\r
410                                 wcscpy( child_dev->description, szDevName );\r
411                                 child_dev->description_size = ( wcslen( child_dev->description ) + 1 )*sizeof( WCHAR );\r
412                                 child_dev->uniqueinstanceid = instance_id;\r
413 \r
414                                 dwRet = send_device_ioctl( UAL_IOC_DEVICE_CREATE, child_dev, sizeof( *child_dev ), NULL, NULL );\r
415 \r
416                                 if ( !dwRet ) \r
417                                 {\r
418                                         printf( "Child device creation for CA = %I64X and IOC = %I64X was successful\n", \r
419                                                 cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
420                                         dwRet = write_deviceinfo_to_registry( ca_guid, ioc_guid, instance_id, device_name );\r
421                                 }\r
422                         }\r
423                 } \r
424                 else \r
425                 {\r
426                         dwRet = -1;\r
427                         printf( "No path CA=%I64X to IOC=%I64X found\n",\r
428                                 cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
429                 }\r
430         }\r
431 \r
432         if ( dwRet ) \r
433         {\r
434                 printf( "Child device creation for CA = %I64X and IOC = %I64X failed\n", \r
435                         cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
436         }\r
437 \r
438 \r
439         if ( pList ) \r
440         {\r
441                 cl_free( pList );\r
442         }\r
443 \r
444         return dwRet;\r
445 }\r
446 \r
447 DWORD   list_ca_ioc_paths()\r
448 {\r
449         DWORD           dwBytesRet = 0, dwRet, n_ca_ioc_path = 0;\r
450         ca_ioc_info_t   *pList = NULL;\r
451         PVOID           pBuf = NULL;\r
452 \r
453         dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );\r
454 \r
455         if ( dwRet ) \r
456         {\r
457                 printf( "Obtaining IOC list from ibiou failed\n" );\r
458         } \r
459         else if ( dwBytesRet )\r
460         {\r
461                 pBuf = pList;\r
462                 n_ca_ioc_path = dwBytesRet/sizeof( ca_ioc_info_t );\r
463 \r
464                 while ( n_ca_ioc_path ) \r
465                 {\r
466                         printf( "Channel Adapter %I64X reaches to IOC %I64X\n", \r
467                                 cl_ntoh64( pList->ca_guid ), cl_ntoh64( pList->info.profile.ioc_guid ) );\r
468                         pList++; n_ca_ioc_path--;\r
469                 }\r
470         }\r
471         else \r
472         {\r
473                 printf( "No IOCs are reachable from the host\nPlease check the connections of host\n" );\r
474         }\r
475 \r
476         if ( pBuf ) \r
477         {\r
478                 cl_free( pBuf );\r
479         }\r
480 \r
481         return dwRet;\r
482 }\r
483 \r
484 int _cdecl main ( int argc, char *argv[] )\r
485 {\r
486         char            device_name[200];\r
487         int             i = 1;\r
488         BOOLEAN         b_list_ioc_paths = FALSE;\r
489         BOOLEAN         b_create_device = FALSE;\r
490         uint64_t        ca_guid, ioc_guid;\r
491         uint32_t        unique_id;\r
492         DWORD           ret = 0;\r
493 \r
494         while ( i < argc  ) \r
495         {\r
496                 if ( !strcmp( argv[i], "-l" ) ) \r
497                 {\r
498                         b_list_ioc_paths = TRUE;\r
499                 } \r
500                 else if ( !strcmp( argv[i], "-c" ) ) \r
501                 {\r
502                         b_create_device = TRUE;\r
503 \r
504                         if ( argv[++i] ) \r
505                         {\r
506                                 ca_guid = _strtoui64( argv[i], NULL, 16 );\r
507                         } \r
508                         else \r
509                         {\r
510                                 return usage();\r
511                         }\r
512                         if ( argv[++i] ) \r
513                         {\r
514                                 ioc_guid = _strtoui64( argv[i],  NULL, 16 );                            \r
515                         } \r
516                         else \r
517                         {\r
518                                 return usage();\r
519                         }\r
520                         if ( argv[++i] ) \r
521                         {\r
522                                 unique_id = strtoul( argv[i], NULL, 10 );\r
523                         }\r
524                         else \r
525                         {\r
526                                 return usage();\r
527                         }\r
528                         if ( argv[++i] ) \r
529                         {\r
530                                 strcpy( device_name, argv[i] );\r
531                         } \r
532                         else \r
533                         {\r
534                                 return usage();\r
535                         }\r
536 \r
537                 } \r
538                 else \r
539                 {\r
540                         return usage();\r
541                 }\r
542                 i++;\r
543         }\r
544 \r
545         if ( b_list_ioc_paths && b_create_device ) \r
546         {\r
547                 return usage();\r
548         }\r
549 \r
550         else if ( b_create_device ) \r
551         {\r
552                 ret = create_child_device( cl_hton64( ca_guid ), cl_hton64( ioc_guid ), unique_id, device_name );\r
553         } \r
554         else \r
555         {\r
556                 ret = list_ca_ioc_paths();\r
557         }\r
558 \r
559         return 0;\r
560 }\r