2 * Copyright (c) 2009 QLogic Corporation. All rights reserved.
\r
4 * This software is available to you under the OpenFabrics.org BSD license
\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
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\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
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
35 #include <windows.h>
\r
37 #include <complib/cl_byteswap.h>
\r
38 #include <complib/cl_memory.h>
\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
43 #pragma pack(push, 1)
\r
44 typedef struct _ca_ioc_info {
\r
47 ib_svc_entry_t svc_entry_array[1];
\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
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
75 DWORD send_device_ioctl( DWORD ioctlcode, PVOID input_buf, DWORD in_size, PVOID *output_buf, PDWORD out_size )
\r
77 DWORD dwRet = 0, dwMemSize, dwBytesRet = 0;
\r
80 HANDLE hDevice = INVALID_HANDLE_VALUE;
\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
87 FILE_ATTRIBUTE_NORMAL,
\r
88 NULL ); /* no template; */
\r
90 if ( hDevice == INVALID_HANDLE_VALUE )
\r
92 printf( "Error opening VNICCONFIG device file\n" );
\r
93 return ERROR_FILE_NOT_FOUND;
\r
96 switch( ioctlcode )
\r
98 case UAL_IOC_DEVICE_CREATE:
\r
99 bRet = DeviceIoControl( hDevice, ioctlcode, input_buf, in_size, NULL, 0, &dwBytesRet, NULL );
\r
103 dwRet = GetLastError();
\r
104 printf( "GetLastError after UAL_IOC_DEVICE_CREATE gives %d\n", dwRet );
\r
109 dwMemSize = sizeof(ca_ioc_info_t ) * 2;
\r
121 pBuf = cl_malloc( dwMemSize );
\r
125 printf( "Insufficient memory\n" );
\r
126 dwRet = ERROR_NOT_ENOUGH_MEMORY;
\r
130 bRet = DeviceIoControl( hDevice, ioctlcode, NULL, 0, pBuf, dwMemSize, &dwBytesRet, NULL );
\r
131 dwRet = GetLastError();
\r
139 }while( dwRet == ERROR_INSUFFICIENT_BUFFER );
\r
141 *output_buf = pBuf;
\r
142 *out_size = dwBytesRet;
\r
147 CloseHandle( hDevice );
\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
154 while ( nListSize )
\r
157 if ( pList->ca_guid == ca_guid && pList->info.profile.ioc_guid == ioc_guid )
\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
173 DWORD write_device_name( char *device_name )
\r
176 DWORD dwRet = 0, dwBytesRet = 0, n_size = 100, dwType;
\r
177 HKEY hKey = INVALID_HANDLE_VALUE;
\r
179 PVOID pOldValue, pNewValue, pBuf;
\r
180 char szKeyName[200];
\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
187 if ( lRet != ERROR_SUCCESS )
\r
189 printf( "Opening services key of ibiou failed\n" );
\r
196 pOldValue = cl_malloc( n_size );
\r
200 printf( "Not enough memory on system\n" );
\r
203 dwType = REG_MULTI_SZ;
\r
205 lRet = RegQueryValueExA( hKey, IBIOU_PARAM_KEY_DEVICE_VALUE, 0, &dwType, pOldValue, &dwBytesRet );
\r
208 if ( lRet == ERROR_MORE_DATA )
\r
210 cl_free( pOldValue );
\r
215 } while( lRet == ERROR_MORE_DATA && n_size < MAX_VALUE_LENGTH );
\r
217 if ( lRet != ERROR_SUCCESS )
\r
219 cl_free( pOldValue );
\r
224 n_size = dwBytesRet + strlen( device_name )*sizeof( char ) + 2*sizeof( char ); /* more for NULLs */
\r
225 pNewValue = cl_malloc( n_size );
\r
227 cl_memset( pNewValue, 0x00, n_size );
\r
230 printf( "Not enough memory on system\n" );
\r
235 { /* Come here only when "StaticChild" key was there already*/
\r
236 cl_memcpy( pBuf, pOldValue, dwBytesRet );
\r
238 while ( *( ( PBYTE )pBuf ) != 0 || *( ( PBYTE ) pBuf + 1 ) != 0 )
\r
239 pBuf = ( PBYTE ) pBuf + 1;
\r
241 pBuf = ( PBYTE ) pBuf + 1;
\r
242 cl_free( pOldValue );
\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
253 printf( "Error setting device name in value of services key of ibiou\n" );
\r
262 static const char *value_names[] = {
\r
264 #define CAGUID_INDEX 0
\r
266 #define IOCGUID_INDEX 1
\r
268 #define COMPATIBLEID_INDEX 2
\r
270 #define DESCRIPTION_INDEX 3
\r
272 #define DEVICEID_INDEX 4
\r
274 #define HARDWAREID_INDEX 5
\r
276 #define INSTANCEID_INDEX 6
\r
277 #define MAXVALUE_INDEX 7
\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
283 DWORD dwRet = 0, dwDisposition, dwType, dwSize;
\r
284 HKEY hKey = INVALID_HANDLE_VALUE;
\r
285 char szKeyName[250];
\r
290 dwRet = write_device_name( device_name );
\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
300 if ( dwDisposition == REG_CREATED_NEW_KEY )
\r
302 dwIndex = CAGUID_INDEX;
\r
304 while ( dwIndex < MAXVALUE_INDEX )
\r
311 dwType = REG_BINARY;
\r
312 dwSize = sizeof( uint64_t );
\r
315 case IOCGUID_INDEX:
\r
317 dwType = REG_BINARY;
\r
318 dwSize = sizeof( uint64_t );
\r
321 case DEVICEID_INDEX:
\r
322 pBuf = "IBA\\qlgcvnic";
\r
324 dwSize = strlen( pBuf ) + 1;
\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
334 case DESCRIPTION_INDEX:
\r
335 pBuf = device_name;
\r
337 dwSize = strlen( pBuf ) + 1;
\r
340 case INSTANCEID_INDEX:
\r
341 pBuf = &instance_id;
\r
342 dwType = REG_DWORD;
\r
343 dwSize = sizeof( instance_id );
\r
349 lRet = RegSetValueExA( hKey, value_names[dwIndex], 0,
\r
350 dwType, pBuf, dwSize );
\r
352 if ( lRet != ERROR_SUCCESS )
\r
354 printf( "Failed in setting device information as Parameters of ibiou driver\n" );
\r
363 if ( hKey != INVALID_HANDLE_VALUE )
\r
365 RegCloseKey( hKey );
\r
372 DWORD create_child_device( uint64_t ca_guid, uint64_t ioc_guid, uint32_t instance_id, char *device_name )
\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
380 dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );
\r
384 printf( "Obtaining IOC LIST from ibiou failed\n" );
\r
388 p_ca_ioc_entry = find_ca_ioc_path( pList, dwBytesRet/sizeof( ca_ioc_info_t ),
\r
389 ca_guid, ioc_guid );
\r
391 if ( p_ca_ioc_entry )
\r
393 child_dev = cl_malloc( sizeof( child_device_info_t ) );
\r
394 cl_memset( child_dev, 0x00, sizeof( child_device_info_t ) );
\r
398 printf( "Allocating memory for child device failed\n" );
\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
414 dwRet = send_device_ioctl( UAL_IOC_DEVICE_CREATE, child_dev, sizeof( *child_dev ), NULL, NULL );
\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
427 printf( "No path CA=%I64X to IOC=%I64X found\n",
\r
428 cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );
\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
447 DWORD list_ca_ioc_paths()
\r
449 DWORD dwBytesRet = 0, dwRet, n_ca_ioc_path = 0;
\r
450 ca_ioc_info_t *pList = NULL;
\r
453 dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );
\r
457 printf( "Obtaining IOC list from ibiou failed\n" );
\r
459 else if ( dwBytesRet )
\r
462 n_ca_ioc_path = dwBytesRet/sizeof( ca_ioc_info_t );
\r
464 while ( n_ca_ioc_path )
\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
473 printf( "No IOCs are reachable from the host\nPlease check the connections of host\n" );
\r
484 int _cdecl main ( int argc, char *argv[] )
\r
486 char device_name[200];
\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
494 while ( i < argc )
\r
496 if ( !strcmp( argv[i], "-l" ) )
\r
498 b_list_ioc_paths = TRUE;
\r
500 else if ( !strcmp( argv[i], "-c" ) )
\r
502 b_create_device = TRUE;
\r
506 ca_guid = _strtoui64( argv[i], NULL, 16 );
\r
514 ioc_guid = _strtoui64( argv[i], NULL, 16 );
\r
522 unique_id = strtoul( argv[i], NULL, 10 );
\r
530 strcpy( device_name, argv[i] );
\r
545 if ( b_list_ioc_paths && b_create_device )
\r
550 else if ( b_create_device )
\r
552 ret = create_child_device( cl_hton64( ca_guid ), cl_hton64( ioc_guid ), unique_id, device_name );
\r
556 ret = list_ca_ioc_paths();
\r