--- /dev/null
+#include <stdio.h>\r
+#include <string.h>\r
+#include <wchar.h>\r
+#include <windows.h>\r
+#include <al_dev.h>\r
+#include <complib/cl_byteswap.h>\r
+#include <complib/cl_memory.h>\r
+\r
+#define MAX_DEVICE_ID_LEN 200\r
+#define MAX_DEVICE_STRING_LEN MAX_DEVICE_ID_LEN + 2 /* add extra 4 bytes in case we need double NULL ending */\r
+\r
+#pragma pack(push, 1)\r
+typedef struct _ca_ioc_info {\r
+ net64_t ca_guid;\r
+ ib_ioc_info_t info;\r
+ ib_svc_entry_t svc_entry_array[1];\r
+} ca_ioc_info_t;\r
+\r
+typedef struct _child_device_info {\r
+ wchar_t device_id[MAX_DEVICE_STRING_LEN]; \r
+ uint32_t device_id_size;\r
+ wchar_t compatible_id[MAX_DEVICE_STRING_LEN];\r
+ uint32_t compatible_id_size;\r
+ wchar_t hardware_id[MAX_DEVICE_STRING_LEN];\r
+ uint32_t hardware_id_size;\r
+ wchar_t description[MAX_DEVICE_STRING_LEN];\r
+ uint32_t description_size;\r
+ ca_ioc_info_t ca_ioc_path;\r
+ uint32_t uniqueinstanceid;\r
+} child_device_info_t;\r
+\r
+#pragma pack(pop)\r
+\r
+int usage()\r
+{\r
+ printf( "Correct usage to create VNIC child devices is:-\n" );\r
+ printf( "qlgcvnic_config -c <CAGUID> <IOCGUID> "\r
+ "<InstanceID> <Interface Description>\n" );\r
+ printf( "Executing qlgcvnic_config without any option or with -l "\r
+ "option will list the IOCs reachable from the host\n" );\r
+ return -1;\r
+}\r
+\r
+DWORD send_device_ioctl( DWORD ioctlcode, PVOID input_buf, DWORD in_size, PVOID *output_buf, PDWORD out_size )\r
+{\r
+ DWORD dwRet = 0, dwMemSize, dwBytesRet = 0;\r
+ BOOL bRet;\r
+ PVOID pBuf;\r
+ HANDLE hDevice = INVALID_HANDLE_VALUE;\r
+\r
+ hDevice = CreateFileW ( L"\\\\.\\VNICCONFIG",\r
+ GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share mode none */\r
+ NULL, /* no security */\r
+ OPEN_EXISTING,\r
+ FILE_ATTRIBUTE_NORMAL,\r
+ NULL ); /* no template; */\r
+\r
+ if ( hDevice == INVALID_HANDLE_VALUE ) \r
+ {\r
+ printf( "Error opening VNICCONFIG device file\n" );\r
+ return ERROR_FILE_NOT_FOUND;\r
+ }\r
+\r
+ switch( ioctlcode ) \r
+ {\r
+ case UAL_IOC_DEVICE_CREATE:\r
+ bRet = DeviceIoControl( hDevice, ioctlcode, input_buf, in_size, NULL, 0, &dwBytesRet, NULL );\r
+\r
+ if ( !bRet ) \r
+ {\r
+ dwRet = GetLastError();\r
+ printf( "GetLastError after UAL_IOC_DEVICE_CREATE gives %d\n", dwRet );\r
+ }\r
+ break;\r
+\r
+ case UAL_IOC_LIST:\r
+ dwMemSize = sizeof(ca_ioc_info_t ) * 2;\r
+ pBuf = NULL;\r
+\r
+ do \r
+ {\r
+ if ( pBuf ) \r
+ {\r
+ cl_free( pBuf );\r
+ dwMemSize *= 2; \r
+ pBuf = NULL;\r
+ }\r
+\r
+ pBuf = cl_malloc( dwMemSize );\r
+\r
+ if ( !pBuf ) \r
+ {\r
+ printf( "Insufficient memory\n" );\r
+ dwRet = ERROR_NOT_ENOUGH_MEMORY;\r
+ break;\r
+ }\r
+\r
+ bRet = DeviceIoControl( hDevice, ioctlcode, NULL, 0, pBuf, dwMemSize, &dwBytesRet, NULL );\r
+ dwRet = GetLastError();\r
+\r
+ if ( bRet ) \r
+ {\r
+ dwRet = 0;\r
+ break;\r
+ }\r
+ \r
+ }while( dwRet == ERROR_INSUFFICIENT_BUFFER );\r
+\r
+ *output_buf = pBuf;\r
+ *out_size = dwBytesRet;\r
+\r
+ break;\r
+ }\r
+\r
+ CloseHandle( hDevice );\r
+ return dwRet;\r
+}\r
+\r
+ca_ioc_info_t *find_ca_ioc_path ( ca_ioc_info_t *pList, DWORD nListSize,\r
+ uint64_t ca_guid, uint64_t ioc_guid )\r
+{\r
+ while ( nListSize ) \r
+ {\r
+\r
+ if ( pList->ca_guid == ca_guid && pList->info.profile.ioc_guid == ioc_guid ) \r
+ {\r
+ return pList;\r
+ }\r
+ nListSize--;\r
+ pList++;\r
+ }\r
+\r
+ return NULL;\r
+}\r
+\r
+#define IBIOU_SERVICE_PARAM_KEY "SYSTEM\\CurrentControlSet\\Services\\ibiou"\r
+#define IBIOU_PARAM_KEY_DEVICE_VALUE "StaticChild"\r
+#define IBIOU_PARAMETER_NAME "Parameters"\r
+#define MAX_VALUE_LENGTH 2048\r
+\r
+DWORD write_device_name( char *device_name )\r
+{\r
+\r
+ DWORD dwRet = 0, dwBytesRet = 0, n_size = 100, dwType;\r
+ HKEY hKey = INVALID_HANDLE_VALUE;\r
+ LONG lRet = -1;\r
+ PVOID pOldValue, pNewValue, pBuf;\r
+ char szKeyName[200];\r
+\r
+ sprintf( szKeyName, "%s\\%s", IBIOU_SERVICE_PARAM_KEY, IBIOU_PARAMETER_NAME );\r
+ lRet = RegOpenKeyExA( HKEY_LOCAL_MACHINE, szKeyName, 0, KEY_ALL_ACCESS, \r
+ &hKey );\r
+\r
+\r
+ if ( lRet != ERROR_SUCCESS ) \r
+ {\r
+ printf( "Opening services key of ibiou failed\n" );\r
+ dwRet = -1;\r
+ } \r
+ else \r
+ {\r
+ do \r
+ {\r
+ pOldValue = cl_malloc( n_size );\r
+\r
+ if ( !pOldValue ) \r
+ {\r
+ printf( "Not enough memory on system\n" );\r
+ break;\r
+ }\r
+ dwType = REG_MULTI_SZ;\r
+\r
+ lRet = RegQueryValueExA( hKey, IBIOU_PARAM_KEY_DEVICE_VALUE, 0, &dwType, pOldValue, &dwBytesRet );\r
+\r
+\r
+ if ( lRet == ERROR_MORE_DATA ) \r
+ {\r
+ cl_free( pOldValue );\r
+ pOldValue = NULL;\r
+ n_size = n_size*2;\r
+ }\r
+\r
+ } while( lRet == ERROR_MORE_DATA && n_size < MAX_VALUE_LENGTH );\r
+\r
+ if ( lRet != ERROR_SUCCESS ) \r
+ {\r
+ cl_free( pOldValue );\r
+ pOldValue = NULL;\r
+ }\r
+\r
+\r
+ n_size = dwBytesRet + strlen( device_name )*sizeof( char ) + 2*sizeof( char ); /* more for NULLs */\r
+ pNewValue = cl_malloc( n_size );\r
+ pBuf = pNewValue;\r
+ cl_memset( pNewValue, 0x00, n_size );\r
+ if ( !pNewValue ) \r
+ {\r
+ printf( "Not enough memory on system\n" );\r
+ } \r
+ else \r
+ {\r
+ if ( pOldValue ) \r
+ { /* Come here only when "StaticChild" key was there already*/\r
+ cl_memcpy( pBuf, pOldValue, dwBytesRet );\r
+\r
+ while ( *( ( PBYTE )pBuf ) != 0 || *( ( PBYTE ) pBuf + 1 ) != 0 )\r
+ pBuf = ( PBYTE ) pBuf + 1;\r
+\r
+ pBuf = ( PBYTE ) pBuf + 1;\r
+ cl_free( pOldValue );\r
+ pOldValue = NULL;\r
+ }\r
+\r
+ cl_memcpy( pBuf, device_name, strlen( device_name ) );\r
+ lRet = RegSetValueExA( hKey, IBIOU_PARAM_KEY_DEVICE_VALUE, 0, REG_MULTI_SZ, \r
+ pNewValue, ( strlen( device_name ) + dwBytesRet + 2 ) ); /* Two bytes for extra NULLs*/\r
+ cl_free( pNewValue );\r
+ RegCloseKey( hKey );\r
+ if ( lRet != ERROR_SUCCESS ) \r
+ {\r
+ printf( "Error setting device name in value of services key of ibiou\n" );\r
+ dwRet = -1;\r
+ }\r
+ }\r
+\r
+ }\r
+ return dwRet; \r
+}\r
+\r
+static const char *value_names[] = {\r
+ "CAGUID",\r
+#define CAGUID_INDEX 0\r
+ "IOCGUID",\r
+#define IOCGUID_INDEX 1\r
+ "CompatibleId",\r
+#define COMPATIBLEID_INDEX 2\r
+ "Description",\r
+#define DESCRIPTION_INDEX 3\r
+ "DeviceId",\r
+#define DEVICEID_INDEX 4\r
+ "HardwareId",\r
+#define HARDWAREID_INDEX 5\r
+ "InstanceId"\r
+#define INSTANCEID_INDEX 6\r
+#define MAXVALUE_INDEX 7\r
+};\r
+\r
+DWORD write_deviceinfo_to_registry( uint64_t ca_guid, uint64_t ioc_guid, \r
+ uint32_t instance_id, char *device_name )\r
+{\r
+ DWORD dwRet = 0, dwDisposition, dwType, dwSize;\r
+ HKEY hKey = INVALID_HANDLE_VALUE;\r
+ char szKeyName[250];\r
+ LONG lRet;\r
+ DWORD dwIndex;\r
+ PVOID pBuf;\r
+\r
+ dwRet = write_device_name( device_name );\r
+\r
+ if ( dwRet == 0 ) \r
+ {\r
+ sprintf( szKeyName, "%s\\%s\\%s", \r
+ IBIOU_SERVICE_PARAM_KEY, IBIOU_PARAMETER_NAME, device_name );\r
+ lRet = RegCreateKeyExA( HKEY_LOCAL_MACHINE, szKeyName, 0,\r
+ NULL, REG_OPTION_NON_VOLATILE, \r
+ KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition );\r
+\r
+ if ( dwDisposition == REG_CREATED_NEW_KEY ) \r
+ {\r
+ dwIndex = CAGUID_INDEX;\r
+ \r
+ while ( dwIndex < MAXVALUE_INDEX ) \r
+ {\r
+\r
+ switch( dwIndex ) \r
+ {\r
+ case CAGUID_INDEX:\r
+ pBuf = &ca_guid;\r
+ dwType = REG_BINARY;\r
+ dwSize = sizeof( uint64_t );\r
+ break;\r
+\r
+ case IOCGUID_INDEX:\r
+ pBuf = &ioc_guid;\r
+ dwType = REG_BINARY;\r
+ dwSize = sizeof( uint64_t ); \r
+ break;\r
+\r
+ case DEVICEID_INDEX:\r
+ pBuf = "IBA\\qlgcvnic";\r
+ dwType = REG_SZ;\r
+ dwSize = strlen( pBuf ) + 1;\r
+ break;\r
+\r
+ case COMPATIBLEID_INDEX: /* Currently all id's used are same. */\r
+ case HARDWAREID_INDEX:\r
+ pBuf = "IBA\\qlgcvnic";\r
+ dwType = REG_MULTI_SZ;\r
+ dwSize = strlen( pBuf ) + 1; \r
+ break;\r
+\r
+ case DESCRIPTION_INDEX: \r
+ pBuf = device_name;\r
+ dwType = REG_SZ;\r
+ dwSize = strlen( pBuf ) + 1; \r
+ break;\r
+\r
+ case INSTANCEID_INDEX:\r
+ pBuf = &instance_id;\r
+ dwType = REG_DWORD;\r
+ dwSize = sizeof( instance_id );\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ lRet = RegSetValueExA( hKey, value_names[dwIndex], 0,\r
+ dwType, pBuf, dwSize );\r
+\r
+ if ( lRet != ERROR_SUCCESS ) \r
+ {\r
+ printf( "Failed in setting device information as Parameters of ibiou driver\n" );\r
+ dwRet = -1;\r
+ break;\r
+ }\r
+\r
+ dwIndex++;\r
+ }\r
+ }\r
+\r
+ if ( hKey != INVALID_HANDLE_VALUE ) \r
+ {\r
+ RegCloseKey( hKey );\r
+ }\r
+ }\r
+\r
+ return dwRet;\r
+}\r
+\r
+DWORD create_child_device( uint64_t ca_guid, uint64_t ioc_guid, uint32_t instance_id, char *device_name )\r
+{\r
+ ca_ioc_info_t *pList = NULL, *p_ca_ioc_entry = NULL;\r
+ DWORD dwRet = 0, dwBytesRet;\r
+ child_device_info_t *child_dev = NULL;\r
+ WCHAR szDevName[200];\r
+\r
+\r
+ dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );\r
+\r
+ if ( dwRet ) \r
+ {\r
+ printf( "Obtaining IOC LIST from ibiou failed\n" );\r
+ } \r
+ else \r
+ {\r
+ p_ca_ioc_entry = find_ca_ioc_path( pList, dwBytesRet/sizeof( ca_ioc_info_t ),\r
+ ca_guid, ioc_guid );\r
+\r
+ if ( p_ca_ioc_entry ) \r
+ {\r
+ child_dev = cl_malloc( sizeof( child_device_info_t ) );\r
+ cl_memset( child_dev, 0x00, sizeof( child_device_info_t ) );\r
+\r
+ if ( !child_dev ) \r
+ {\r
+ printf( "Allocating memory for child device failed\n" );\r
+ } \r
+ else \r
+ {\r
+ child_dev->ca_ioc_path = *p_ca_ioc_entry;\r
+ wcscpy( child_dev->device_id, L"IBA\\qlgcvnic" );\r
+ child_dev->device_id_size = ( wcslen( child_dev->device_id ) + 1 )*sizeof( WCHAR );\r
+ wcscpy( child_dev->hardware_id, L"IBA\\qlgcvnic" );\r
+ child_dev->hardware_id_size = ( wcslen( child_dev->hardware_id ) + 2 )*sizeof( WCHAR );\r
+ wcscpy( child_dev->compatible_id, L"IBA\\qlgcvnic" );\r
+ child_dev->compatible_id_size = ( wcslen( child_dev->compatible_id ) + 2 )*sizeof( WCHAR );\r
+ swprintf( szDevName, L"%S", device_name );\r
+ wcscpy( child_dev->description, szDevName );\r
+ child_dev->description_size = ( wcslen( child_dev->description ) + 1 )*sizeof( WCHAR );\r
+ child_dev->uniqueinstanceid = instance_id;\r
+\r
+ dwRet = send_device_ioctl( UAL_IOC_DEVICE_CREATE, child_dev, sizeof( *child_dev ), NULL, NULL );\r
+\r
+ if ( !dwRet ) \r
+ {\r
+ printf( "Child device creation for CA = %I64X and IOC = %I64X was successful\n", \r
+ cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
+ dwRet = write_deviceinfo_to_registry( ca_guid, ioc_guid, instance_id, device_name );\r
+ }\r
+ }\r
+ } \r
+ else \r
+ {\r
+ dwRet = -1;\r
+ printf( "No path CA=%I64X to IOC=%I64X found\n",\r
+ cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
+ }\r
+ }\r
+\r
+ if ( dwRet ) \r
+ {\r
+ printf( "Child device creation for CA = %I64X and IOC = %I64X failed\n", \r
+ cl_ntoh64( ca_guid ), cl_ntoh64( ioc_guid ) );\r
+ }\r
+\r
+\r
+ if ( pList ) \r
+ {\r
+ cl_free( pList );\r
+ }\r
+\r
+ return dwRet;\r
+}\r
+\r
+DWORD list_ca_ioc_paths()\r
+{\r
+ DWORD dwBytesRet = 0, dwRet, n_ca_ioc_path = 0;\r
+ ca_ioc_info_t *pList = NULL;\r
+ PVOID pBuf = NULL;\r
+\r
+ dwRet = send_device_ioctl( UAL_IOC_LIST, NULL, 0, &pList, &dwBytesRet );\r
+\r
+ if ( dwRet ) \r
+ {\r
+ printf( "Obtaining IOC list from ibiou failed\n" );\r
+ } \r
+ else if ( dwBytesRet )\r
+ {\r
+ pBuf = pList;\r
+ n_ca_ioc_path = dwBytesRet/sizeof( ca_ioc_info_t );\r
+\r
+ while ( n_ca_ioc_path ) \r
+ {\r
+ printf( "Channel Adapter %I64X reaches to IOC %I64X\n", \r
+ cl_ntoh64( pList->ca_guid ), cl_ntoh64( pList->info.profile.ioc_guid ) );\r
+ pList++; n_ca_ioc_path--;\r
+ }\r
+ }\r
+ else \r
+ {\r
+ printf( "No IOCs are reachable from the host\nPlease check the connections of host\n" );\r
+ }\r
+\r
+ if ( pBuf ) \r
+ {\r
+ cl_free( pBuf );\r
+ }\r
+\r
+ return dwRet;\r
+}\r
+\r
+int _cdecl main ( int argc, char *argv[] )\r
+{\r
+ char device_name[200];\r
+ int i = 1;\r
+ BOOLEAN b_list_ioc_paths = FALSE;\r
+ BOOLEAN b_create_device = FALSE;\r
+ uint64_t ca_guid, ioc_guid;\r
+ uint32_t unique_id;\r
+ DWORD ret = 0;\r
+\r
+ while ( i < argc ) \r
+ {\r
+ if ( !strcmp( argv[i], "-l" ) ) \r
+ {\r
+ b_list_ioc_paths = TRUE;\r
+ } \r
+ else if ( !strcmp( argv[i], "-c" ) ) \r
+ {\r
+ b_create_device = TRUE;\r
+\r
+ if ( argv[++i] ) \r
+ {\r
+ ca_guid = _strtoui64( argv[i], NULL, 16 );\r
+ } \r
+ else \r
+ {\r
+ return usage();\r
+ }\r
+ if ( argv[++i] ) \r
+ {\r
+ ioc_guid = _strtoui64( argv[i], NULL, 16 ); \r
+ } \r
+ else \r
+ {\r
+ return usage();\r
+ }\r
+ if ( argv[++i] ) \r
+ {\r
+ unique_id = strtoul( argv[i], NULL, 10 );\r
+ }\r
+ else \r
+ {\r
+ return usage();\r
+ }\r
+ if ( argv[++i] ) \r
+ {\r
+ strcpy( device_name, argv[i] );\r
+ } \r
+ else \r
+ {\r
+ return usage();\r
+ }\r
+\r
+ } \r
+ else \r
+ {\r
+ return usage();\r
+ }\r
+ i++;\r
+ }\r
+\r
+ if ( b_list_ioc_paths && b_create_device ) \r
+ {\r
+ return usage();\r
+ }\r
+\r
+ else if ( b_create_device ) \r
+ {\r
+ ret = create_child_device( cl_hton64( ca_guid ), cl_hton64( ioc_guid ), unique_id, device_name );\r
+ } \r
+ else \r
+ {\r
+ ret = list_ca_ioc_paths();\r
+ }\r
+\r
+ return 0;\r
+}\r