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