2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. 2N/A * I18N message number ranges 2N/A * This file: 12000 - 12499 2N/A * Shared common messages: 1 - 1999 2N/A * This module is part of the Fibre Channel Interface library. 2N/A/* #define _POSIX_SOURCE 1 */ 2N/A/* Some forward declarations of static functions */ 2N/A * becomes extern interface for Tapestry. 2N/A * static int g_get_inq_dtype(char *, la_wwn_t, uchar_t *); 2N/A * static int g_get_dev_list(char *, fc_port_dev_t **, int *, int); 2N/A/* type for g_dev_map_init related routines */ 2N/A/* static for g_dev_map_init related routines */ 2N/A 0xef,
0xe8,
0xe4,
0xe2,
0xe1,
0xe0,
0xdc,
0xda,
0xd9,
0xd6,
2N/A 0xd5,
0xd4,
0xd3,
0xd2,
0xd1,
0xce,
0xcd,
0xcc,
0xcb,
0xca,
2N/A 0xc9,
0xc7,
0xc6,
0xc5,
0xc3,
0xbc,
0xba,
0xb9,
0xb6,
0xb5,
2N/A 0xb4,
0xb3,
0xb2,
0xb1,
0xae,
0xad,
0xac,
0xab,
0xaa,
0xa9,
2N/A 0xa7,
0xa6,
0xa5,
0xa3,
0x9f,
0x9e,
0x9d,
0x9b,
0x98,
0x97,
2N/A 0x90,
0x8f,
0x88,
0x84,
0x82,
0x81,
0x80,
0x7c,
0x7a,
0x79,
2N/A 0x76,
0x75,
0x74,
0x73,
0x72,
0x71,
0x6e,
0x6d,
0x6c,
0x6b,
2N/A 0x6a,
0x69,
0x67,
0x66,
0x65,
0x63,
0x5c,
0x5a,
0x59,
0x56,
2N/A 0x55,
0x54,
0x53,
0x52,
0x51,
0x4e,
0x4d,
0x4c,
0x4b,
0x4a,
2N/A 0x49,
0x47,
0x46,
0x45,
0x43,
0x3c,
0x3a,
0x39,
0x36,
0x35,
2N/A 0x34,
0x33,
0x32,
0x31,
0x2e,
0x2d,
0x2c,
0x2b,
0x2a,
0x29,
2N/A 0x27,
0x26,
0x25,
0x23,
0x1f,
0x1e,
0x1d,
0x1b,
0x18,
0x17,
2N/A 0x10,
0x0f,
0x08,
0x04,
0x02,
0x01 2N/A 0x00,
0x7d,
0x7c,
0x00,
0x7b,
0x00,
0x00,
0x00,
0x7a,
0x00,
2N/A 0x00,
0x00,
0x00,
0x00,
0x00,
0x79,
0x78,
0x00,
0x00,
0x00,
2N/A 0x00,
0x00,
0x00,
0x77,
0x76,
0x00,
0x00,
0x75,
0x00,
0x74,
2N/A 0x73,
0x72,
0x00,
0x00,
0x00,
0x71,
0x00,
0x70,
0x6f,
0x6e,
2N/A 0x00,
0x6d,
0x6c,
0x6b,
0x6a,
0x69,
0x68,
0x00,
0x00,
0x67,
2N/A 0x66,
0x65,
0x64,
0x63,
0x62,
0x00,
0x00,
0x61,
0x60,
0x00,
2N/A 0x5f,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x5e,
0x00,
0x5d,
2N/A 0x5c,
0x5b,
0x00,
0x5a,
0x59,
0x58,
0x57,
0x56,
0x55,
0x00,
2N/A 0x00,
0x54,
0x53,
0x52,
0x51,
0x50,
0x4f,
0x00,
0x00,
0x4e,
2N/A 0x4d,
0x00,
0x4c,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x4b,
2N/A 0x00,
0x4a,
0x49,
0x48,
0x00,
0x47,
0x46,
0x45,
0x44,
0x43,
2N/A 0x42,
0x00,
0x00,
0x41,
0x40,
0x3f,
0x3e,
0x3d,
0x3c,
0x00,
2N/A 0x00,
0x3b,
0x3a,
0x00,
0x39,
0x00,
0x00,
0x00,
0x38,
0x37,
2N/A 0x36,
0x00,
0x35,
0x00,
0x00,
0x00,
0x34,
0x00,
0x00,
0x00,
2N/A 0x00,
0x00,
0x00,
0x33,
0x32,
0x00,
0x00,
0x00,
0x00,
0x00,
2N/A 0x00,
0x31,
0x30,
0x00,
0x00,
0x2f,
0x00,
0x2e,
0x2d,
0x2c,
2N/A 0x00,
0x00,
0x00,
0x2b,
0x00,
0x2a,
0x29,
0x28,
0x00,
0x27,
2N/A 0x26,
0x25,
0x24,
0x23,
0x22,
0x00,
0x00,
0x21,
0x20,
0x1f,
2N/A 0x1e,
0x1d,
0x1c,
0x00,
0x00,
0x1b,
0x1a,
0x00,
0x19,
0x00,
2N/A 0x00,
0x00,
0x00,
0x00,
0x00,
0x18,
0x00,
0x17,
0x16,
0x15,
2N/A 0x00,
0x14,
0x13,
0x12,
0x11,
0x10,
0x0f,
0x00,
0x00,
0x0e,
2N/A 0x0d,
0x0c,
0x0b,
0x0a,
0x09,
0x00,
0x00,
0x08,
0x07,
0x00,
2N/A 0x06,
0x00,
0x00,
0x00,
0x05,
0x04,
0x03,
0x00,
0x02,
0x00,
2N/A 0x00,
0x00,
0x01,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00 2N/A * Check if device is in the map. 2N/A * map - loop map returned from fc port 2N/A * tid - device ID for private map or 24-bit alpa for fabric map 2N/A * 1 if device present in the map. 2N/A /* Does not count if WWN == 0 */ 2N/A /* Does not count if WWN == 0 */ 2N/A * Inserts any missing port wwns for mpxio device paths 2N/A * which are in ONLINE or STANDBY state. 2N/A * Now check each scsi_vhci device path to find any missed 2N/A * port wwns and insert a new wwn list entry for the missed 2N/A /* Free memory for pathlist before return */ 2N/A * Just search for ONLINE and STANDBY paths as 2N/A * those should be the only missing wwn entries. 2N/A * There is a very small window for an offline 2N/A * to have occurred between the time we retrieved 2N/A * the device list and a call to this function. 2N/A * If that happens, we just won't add it to 2N/A * the list which is probably a good thing. 2N/A * Now search through wwn list for matching 2N/A * device path AND pwwn 2N/A * If it's found, continue to next path. 2N/A * If it's not found, add it the wwn list. 2N/A * didn't find a match but the mpxio 2N/A * device is in the list. Retrieve 2N/A * the info from the wwn_list_found 2N/A * and add it to the list. 2N/A * Insert new_wwn at the beginning of the list. 2N/A /* set new starting ptr */ 2N/A * Copy found node wwn data to this new entry 2N/A * Node wwn is required for the wwn_list 2N/A * however for mpxio devices it is not 2N/A * relevant as it may apply to multiple 2N/A * target controllers, so just use what 2N/A * we already have in wwn_list_found. 2N/A * gets the port wwn for a scsi_vhci device using ONLINE path priority 2N/A * Look for an ONLINE path first. 2N/A * If that fails, get the STANDBY path port WWN 2N/A * If that fails, give up 2N/A * searches wwn_list_found for the pwwn passed in 2N/A * and sets the corresponding nwwn on return. 2N/A * If no match is found, -1 is returned and nwwn is not set. 2N/A * adds a nwwn, pwwn entry to the next entry in wwn_list_found list 2N/A /* Got wwns, load data in list */ 2N/A * Insert new_wwn in the list 2N/A * Create a linked list of all the WWN's for all FC_AL disks and 2N/A * tapes that are attached to this host. 2N/A * RETURN VALUES: 0 O.K. 2N/A * NULL: No devices found. 2N/A * !NULL: Devices found 2N/A * wwn_list points to a linked list of wwn's. 2N/A /* return L_NULL_WWN_LIST if wwn_list_ptr is NULL */ 2N/A * retain backward compatibility with g_get_wwn_list 2N/A * and retrieve the WWN for scsi_vhci devices in the 2N/A * Note that for scsi_vhci devices, the wwn fields are 2N/A * not relevant but in the previous versions 2N/A * we loaded the wwns so... 2N/A /* get port wwn of first ONLINE, STANDBY */ 2N/A /* Use g_get_wwn as a last resort */ 2N/A * this is a bad WWN. 2N/A * remove it from the wwn_list. 2N/A * After removing the bad WWN, 2N/A * wwn_list_p should point to the next 2N/A * Now go through the list one more time to add entries for 2N/A * any missing port wwns. 2N/A * This allows a search on port wwn for any paths which are 2N/A * ONLINE or STANDBY. We don't care about OFFLINE as those won't 2N/A * and should not show up in the list 2N/A "\t\tTime = %lld millisec\n",
2N/A * Try to prime di_drv_first_node() 2N/A * If there are no nodes bound, di_drv_first_node() 2N/A * will return nothing. 2N/A "\t\tTime = %lld millisec\n",
2N/A "\t\tTime = %lld millisec\n",
2N/A * if *wwn_list_ptr == NULL 2N/A * we have disks but no tapes 2N/A "\t\tTime = %lld millisec\n",
2N/A /* Now link the two together */ 2N/A /* Walk to the end of it */ 2N/A /* else we have no disks */ 2N/A /* return if wwn_list_found is NULL */ 2N/A /* return if wwn_list is NULL */ 2N/A * Count the number of wwn_list in the list 2N/A * Allocate a simple wwn_list array and fill it in 2N/A * Sort the wwn_list array 2N/A * Rebuild the linked list wwn_list structure 2N/A for (i = 0; i < n -
1; i++) {
2N/A * Get the limited map for FC4 devices. 2N/A * This function is specific to FC4 2N/A * devices and doesn't work for FC (leadville) devices. 2N/A * non-zero otherwise 2N/A * NULL: No devices found 2N/A * !NULL: if devices found 2N/A /* initialize map */ 2N/A * Get the path to the :devctl driver 2N/A * This assumes the path looks something like this: 2N/A * a 1 level PCI type driver 2N/A /* append a port. Just try 0 since they did not give us one */ 2N/A /* open controller */ 2N/A * Check for reasonableness. 2N/A * For leadville specific HBA's ONLY. 2N/A * Get the host specific parameters, 2N/A * fc_port_dev_t structure. 2N/A * non-zero in case of error. 2N/A /* return invalid path if host_path is NULL */ 2N/A /* return invalid arg if host_val is NULL */ 2N/A /* initialize structure */ 2N/A /* get the inquiry information for the leadville HBA. */ 2N/A * Issue FCIO ioctls to the port(fp) driver. 2N/A * FCIO ioctl needs to be retried when it 2N/A * is returned with an EINVAL error, wait 2N/A * time between retries should be atleast 2N/A * WAIT_FCIO_IOCTL (too much of a time to wait!!) 2N/A * non-zero otherwise. 2N/A /* wait WAIT_FCIO_IOCTL */ 2N/A "Error: %s. fc_error = %d (0x%x)\n",
2N/A * When port is offlined, qlc 2N/A * returns the FC_OFFLINE error and errno 2N/A * We do want to ignore this error, 2N/A * especially when an enclosure is 2N/A * removed from the loop. 2N/A * This function issues the FCP_TGT_INQUIRY ioctl to 2N/A * fcp_ioctl structure in fcp_data is filled in by fcp 2N/A * Non-zero otherwise 2N/A * Issue the ioctl to FCP 2N/A * The retries are required because the driver may 2N/A * need some time to respond at times. 2N/A /* if ioctl fails it is an error from Solaris operation. */ 2N/A * Get the number of devices and also 2N/A * a list of devices accessible through 2N/A * the device's port as specified by path. 2N/A * The calling function * is responsible for freeing the dev_list. 2N/A * Acquires inq_dtype from g_get_inq_dtype() and 2N/A * stores into dev_dtype field of fc_port_dev. 2N/A * For fabric devices call FCIO_DEV_LOGIN (if necessary) to execute port login 2N/A * and get inq dtype. 2N/A * NULL: No devices found, in case of an error 2N/A * Non-NULL: Devices found. 2N/A * set to the number of devices 2N/A * accessible through the port. 2N/A * non-zero otherwise 2N/A * Get the path to the :devctl driver 2N/A * This assumes the path looks something like this: 2N/A * a 1 level PCI type driver but still :devctl 2N/A /* append controller */ 2N/A /* append controller */ 2N/A * Get the device list from port driver 2N/A /* Get the device list */ 2N/A /* Information read operation */ 2N/A /* new device count */ 2N/A * original buffer was small so allocate buffer 2N/A * with a new count and retry. 2N/A /* Information read operation */ 2N/A /* new device count */ 2N/A * No more retry. There may be severe 2N/A * hardware problem so return error 2N/A " should have been %d\n",
2N/A " FCIO_GET_DEV_LIST ioctl failed.");
2N/A * if new count is smaller than the original number from 2N/A * FCIO_GET_NUM_DEVS, adjust new count and buffer size 2N/A /* close here since fcapath will be passed to other routines. */ 2N/A /* Get the inq_dtype for each device on dev list. */ 2N/A /* Get the inq_dtype for each device. */ 2N/A * if g_get_inq_dtype failed on g_dev_login 2N/A * or g_issue_fcp_ioctl, continue to the next 2N/A * L_GET_DEV_LIST_ULP_FAILURE is returned 2N/A * after processing the whole dlist. 2N/A/* Constant used by g_get_inq_dtype() */ 2N/A * Gets the inq_dtype for devices on the fabric FC driver 2N/A * through an ioctl to the FCP module. 2N/A * inq_dtype is set to the dtype on success 2N/A * if there is an error on getting port state we will 2N/A * continue to login. 2N/A * state can be either of 2N/A * PORT_DEVICE_INVALID, PORT_DEVICE_VALID, 2N/A * PORT_DEVICE_LOGGED_IN. Trying port login 2N/A * unless already logged in. 2N/A * It will be examined if there is an adverse 2N/A * effect on invalid state device. 2N/A /* do port login to fabric device. */ 2N/A /* Get the minor number for an fp instance */ 2N/A * Gets the inq_dtype for devices on the fabric FC driver 2N/A * through an ioctl to the FCP module. 2N/A * This is exactly same as g_get_inq_dtype except that it does not do 2N/A * g_dev_login(). That is for the case when the FCA tries to get its own 2N/A * inq_dtype and in such a case, it cannot PLOGI into itself. 2N/A * inq_dtype is set to the dtype on success 2N/A /* Get the minor number for an fp instance */ 2N/A * This function returns the traditional g_get_dev_map. Device list 2N/A * and local hba separate. 2N/A * This function returns the device map with local hba in physical 2N/A * order. Note: Physical order is only returned properly for 2N/A * private loop. local hba is also included separate 2N/A * Gets device map from nexus driver 2N/A * path - must be the physical path to a device 2N/A * map - loop map returned from fc port. 2N/A * verbose - options. 2N/A * 1. check the validity of path via g_get_path_type. 2N/A * 2. If FC path, get the topology of the path via 2N/A * g_get_fca_port_topology. 2N/A * 3. If FC type(Leadville statck) 2N/A * g_get_dev_list to get the device node list of fc_port_dev_t. 2N/A * g_get_host_params to get the fca port node of fc_port_dev_t. 2N/A * Case of fabric or public loop topology 2N/A * Check if the port id > 0xffff. 2N/A * Move device node and fca port node to 2N/A * gfc_map structure via gfc_port_dev_info_t 2N/A * Issue g_get_inq_dtype to get FCP inquiry data 2N/A * and store it into gfc_port_dev_info_t. 2N/A * Case of private loop topology 2N/A * Check if the port id < 0xff. 2N/A * Move device node and fca port node to 2N/A * gfc_map structure via gfc_port_dev_info_t 2N/A * Issue g_get_inq_dtype to get FCP inquiry data 2N/A * and store it into gfc_port_dev_info_t. 2N/A * SFIOCGMAP ioctl to get the device and hba nodes of 2N/A * non-zero: otherwise 2N/A /* return invalid path if path is NULL */ 2N/A /* return invalid arg if map_ptr is NULL */ 2N/A * Get the path to the :devctl driver 2N/A * This assumes the path looks something like this: 2N/A * a 1 level PCI type driver but still :devctl 2N/A /* standby or path0 */ 2N/A /* append controller */ 2N/A /* append controller */ 2N/A /* get fiber topology */ 2N/A /* for FC devices. */ 2N/A * if g_get_dev_list fails with L_NO_DEVICES_FOUND 2N/A * we still want to call g_get_host_params to try to find the 2N/A * HBA. If we do not see any HBAs on the loop, the 2N/A * g_get_host_params will fail when it trys to issue the target 2N/A * inquiry ioctl. In this case, we would still like to return 2N/A * L_NO_DEVICES_FOUND. 2N/A * If g_get_dev_list fails with L_NO_DEVICES_FOUND and 2N/A * g_get_host_params fails, the function returns 2N/A * L_NO_DEVICES_FOUND 2N/A * g_get_dev_map doesn't allow ulp failure 2N/A * to continue thus we need to free dev_list 2N/A /* Get local HBA information */ 2N/A /* If devices, other than local HBA are found */ 2N/A /* allocate space for them in the gfc_map. */ 2N/A /* If map type is on MAP_FORMAT_LILP we need */ 2N/A /* to add space for the local HBA */ 2N/A /* If we want the lilp map then we need to do a little */ 2N/A /* work here. The lilp map contains the local hba in */ 2N/A /* the dev_addr. Once this has been added qsort the */ 2N/A /* dev_addr array so it's in physical order. */ 2N/A /* The lilp map will contain the local hba in the */ 2N/A /* dev_addr array only when num_devices > 0 */ 2N/A /* First we need to allocate one additional */ 2N/A /* device to the dev_addr structure, for the */ 2N/A /* Next, copy the local hba into this new loc. */ 2N/A /* Now sort by physical location */ 2N/A * Map the (new->old) structures here. 2N/A * Checking (i < SF_NUM_ENTRIES_IN_MAP) just to 2N/A * make sure that we don't overrun the map structure 2N/A * since it can hold data for upto 126 devices. 2N/A * Out of 24 bits of port_id, copy only 2N/A * 8 bits to al_pa. This works okay for 2N/A * devices that're on a private loop. 2N/A /* Code refactorization is needed for C style */ 2N/A }
/* End of switch on port_topology */ 2N/A /* initialize map */ 2N/A /* Check for reasonableness. */ 2N/A * This function consturct FC proerty list using map_dev_fc_prop_list. 2N/A * port WWN, node WWN, port addr and hard addr properties is constructed. 2N/A * otherwise returns error code. 2N/A /* consrtruct port addr property. */ 2N/A /* consrtruct port WWN property. */ 2N/A /* consrtruct node WWN property. */ 2N/A /* consrtruct hard addr property. */ 2N/A * This function consturct FCP inq dtype propery. 2N/A * if inq_dtype is null the property is constrcted with err info. 2N/A * L_MALLOC_FAILED is the only possible error. 2N/A * This function calls FCP_TGT_INQUIRY via g_issue_fcp_ioctl() 2N/A * to get the inq_dtype of input device and calls update_map_dev_FCP_prop(). 2N/A * inq_dtype is set to NULL and pass error code if inq_dtype data is not 2N/A * return error from update_map_dev_FCP_prop(). 2N/A /* Get the minor number for an fp instance */ 2N/A /* Get FCP prop for the hba first. */ 2N/A /* if ioctl error then set the prop_error. */ 2N/A * Construct device map tree from nexus driver 2N/A * path - must be the physical path to a device 2N/A * l_err - ptr to an error code. Set when NULL is returned. 2N/A * flag - device map fomat and property type. 2N/A * 1. check the validity of path via g_get_path_type. 2N/A * 2. If FC path, get the topology of the path via 2N/A * g_get_fca_port_topology. 2N/A * 3. If FC type(Leadville statck) 2N/A * FCIO_GET_DEV_LIST to get the device node list of fc_port_dev_t. 2N/A * FCIO_GET_HOST_PARAMS to get the fca port node of fc_port_dev_t. 2N/A * root of tree is set with host_params info 2N/A * FC propery is set. 2N/A * FCP property is set if reqyested through flag. 2N/A * Issue g_issue_fcp_ioctl to get FCP inquiry data 2N/A * consruruct list of children via dev_list. 2N/A * FC property is set. 2N/A * FCP property is set if reqyested through flag. 2N/A * Issue FCIO_DEV_LOGIN if it is fabric device. 2N/A * Issue g_issue_fcp_ioctl to get FCP inquiry data. 2N/A * SFIOCGMAP ioctl to get the device and hba nodes of 2N/A * FCIO_GETMAP ioctl to get hba port info. 2N/A * consturct map and child tree list and 2N/A * set the properties as private loop devices. 2N/A * ptr to map is returned if OK. 2N/A * NULL and l_err is set otherwise. 2N/A * Get the path to the :devctl driver 2N/A * This assumes the path looks something like this: 2N/A * a 1 level PCI type driver but still :devctl 2N/A /* standby or path0 */ 2N/A /* append controller */ 2N/A /* append controller */ 2N/A /* get fiber topology */ 2N/A /* for FC devices. */ 2N/A /* get the number of device first. */ 2N/A /* Get the device list */ 2N/A /* Information read operation */ 2N/A /* new device count */ 2N/A * original buffer was small so allocate 2N/A * buffer with a new count and retry. 2N/A /* Information read operation */ 2N/A /* new device count */ 2N/A * No more retry. There 2N/A * hardware problem so 2N/A * return error here. 2N/A /* Code refactorization is needed for C style */ 2N/A * if new count is smaller than the original number from 2N/A * FCIO_GET_NUM_DEVS, adjust new count and buffer size 2N/A /* get the host param info */ 2N/A /* If we want the lilp map then we need to do a little */ 2N/A /* work here. The lilp map contains the local hba in */ 2N/A /* the dev_addr. Once this has been added qsort the */ 2N/A /* dev_addr array so it's in physical order. */ 2N/A /* First we need to allocate one additional */ 2N/A /* device to the dev_addr structure, for the */ 2N/A * In case dev_list is not null free 2N/A * Next, copy the local hba into this new 2N/A /* Now sort by physical location */ 2N/A /* We have dev list info and host param info. */ 2N/A /* Now constructs map tree with these info. */ 2N/A /* First consturct the root of the map tree */ 2N/A /* with host param. */ 2N/A /* consturct hba property list. */ 2N/A /* consturct child for each device and */ 2N/A /* set device property list. */ 2N/A /* set the map as parent */ 2N/A " FCIO_GET_STATE ioctl failed.\n");
2N/A /* Code refactorization is needed for C style */ 2N/A * plogi failed continue 2N/A /* sbuf should be set from hba_port handling. */ 2N/A /* connect the children to to map. */ 2N/A /* initialize map */ 2N/A /* Check for reasonableness. */ 2N/A /* get limited map to get hba param info */ 2N/A /* We have dev list info and host param info. */ 2N/A /* Now constructs map tree with these info. */ 2N/A /* First consturct the root of the map tree */ 2N/A /* with host param. */ 2N/A /* consturct hba property list. */ 2N/A /* set the map as parent */ 2N/A }
/* end of for loop */ 2N/A * This function deallocates memory for propery list. 2N/A * This function deallocates memory for children list. 2N/A * This function deallocates memory for the whole map. 2N/A * This function passes back topology of the input map. 2N/A * input should be a handle form g_dev_map_init(). 2N/A * return error code otherwise. 2N/A * This function returns the first device handle of the input map. 2N/A * map input should be a handle form g_dev_map_init(). 2N/A * l_err set to 0 if OK. 2N/A * l_err set to error code otherwise. 2N/A * This function returns the next device handle of the input map. 2N/A * map_dev input should be a handle for device. 2N/A * l_err set to 0 if OK. 2N/A * l_err set to error code otherwise. 2N/A * This function passes back uchar_t type property and its count. 2N/A * map_dev input should be a handle for device. 2N/A * return error code otherwise. 2N/A * This function passes back int type property. 2N/A * map_dev input should be a handle for device. 2N/A * return error code otherwise. 2N/A * This function passes back int type property. 2N/A * map_dev input should be a handle for device. 2N/A * return error code otherwise. 2N/A * This function returns the handle for the first property of the input device. 2N/A * map_dev input should be a handle form a device. 2N/A * l_err set to 0 if OK. 2N/A * l_err set to error code otherwise. 2N/A * This function returns the handle for next property handle of the input prop. 2N/A * map_prop input should be a handle for property. 2N/A * l_err set to 0 if OK. 2N/A * l_err set to error code otherwise. 2N/A * This function returns the name of the property of the input prop. 2N/A * map_prop input should be a handle for property. 2N/A * return name string if OK. 2N/A * returns NULL and l_err set to error code otherwise. 2N/A * This function returns the type of the property of the input prop. 2N/A * map_prop input should be a handle for property. 2N/A * return type if OK. 2N/A * returns GFC_PROP_TYPE_UNKNOWN and l_err set to error code otherwise. 2N/A * This function passes back uchar_t type property and its count. 2N/A * map_prop input should be a handle for property. 2N/A * return error code otherwise. 2N/A * This function passes back int type property. 2N/A * map_prop input should be a handle for property. 2N/A * return error code otherwise. 2N/A * This function passes back string type property. 2N/A * map_prop input should be a handle for property. 2N/A * return error code otherwise. 2N/A * Free the linked list allocated by g_rdls() 2N/A * Read the extended link error status block 2N/A * from the specified device and Host Adapter. 2N/A * path_phys - physical path to an FC device 2N/A * rls_ptr - pointer to read link state structure 2N/A * non-zero: otherwise 2N/A /* return invalid path if path_phys is NULL */ 2N/A /* return invalid arg if rls_ptr is NULL */ 2N/A /* standby or path0 */ 2N/A /* Get map of devices on this loop. */ 2N/A /* append devctl to the path */ 2N/A /* append devctl to the path */ 2N/A }
else {
/* FC4_FCA_MASK type path */ 2N/A * First try using the socal version of the map. 2N/A * If that fails get the expanded vesion. 2N/A /* Check for reasonableness. */ 2N/A " FCIO_GETMAP ioctl returned %d entries.\n",
2N/A /* Check for reasonableness. */ 2N/A (
uint_t)
0xff000000;
/* get LESB for this port */ 2N/A * The ifp driver will return ENXIO when rls 2N/A * is issued for same initiator on loop when 2N/A * there is more than one on the loop. 2N/A * Rather than completely fail, continue on. 2N/A * Set values in the payload struct to -1 as 2N/A * this is what socal is currently doing for 2N/A * the case of same initiator rls. 2N/A /* Now we need to take care of FC_FCA_MASK case. */ 2N/A /* we have map created already via g_dev_map_init. */ 2N/A /* Set the al_ha here */ 2N/A * rls. Load the values returned for the fp ioctl 2N/A * into the structure passed back to the caller 2N/A * Note: There is no reason for the path 2N/A }
/* if g_get_dev_port_state fails proceed. */ 2N/A * Load the values into the struct passed 2N/A * back to the caller 2N/A /* for Leadville issue a final call for the initiator */ 2N/A * Load the values into the struct passed 2N/A * back to the caller 2N/A * Get device World Wide Name (port and node) for device at path 2N/A * and add all WWNs to the wwn_list_found list. 2N/A * - path_phys must be of a device, either an IB or disk. 2N/A " and al_pa for device: %s\n",
2N/A * Get the loop identifier (switch setting) from the path. 2N/A * This assumes the path looks something like this: 2N/A * /devices/.../SUNW,socal@3,0/SUNW,sf@0,0/SUNW,ssd@x,0 2N/A * /devices/.../SUNW,qlc@5/SUNW,fp@0,0/SUNW,ssd@x,0 2N/A /* This function allocs mem for map.dev_addr on success */ 2N/A /* standby or path0 */ 2N/A * ssd@w2200002037000f96,0:a,raw 2N/A "\t\tTime = %lld millisec\n",
2N/A * Get device World Wide Name and AL_PA for device at path 2N/A * - path_phys must be of a device, either an IB or disk. 2N/A /* return invalid path if the argument is NULL */ 2N/A /* return invalid arg if the argument is NULL */ 2N/A /* return invalid path if path is NULL */ 2N/A /* return invalid arg if serial_number is NULL */ 2N/A * Call the inquiry cmd on page 0x80 only if the vendor 2N/A * supports page 0x80. 2N/A * Let's retrieve the serial number from page 0x80 2N/A * and store it in the inquiry structure 2N/A * page 0x80 is not supported, so print the 2N/A * appropriate message. 2N/A /* return invalid path if path is NULL */ 2N/A /* return invalid arg if l_inquiry is NULL */ 2N/A * Function to retrieve inquiry page 0x80 from the device 2N/A * Function to determine if the given page is supported by vendor. 2N/A P_DPRINTF(
" g_get_perf_statistics: Get Performance Statistics:" 2N/A /* initialize tables */ 2N/A /* open controller */ 2N/A /* update parameters in the performance table */ 2N/A /* get the period in seconds */ 2N/A if ((c >=
'0') && (c <=
'9'))
2N/A else if ((c >=
'A') && (c <=
'F'))
2N/A else if ((c >=
'a') && (c <=
'f'))
2N/A * Converts a string of WWN ASCII characters to a 2N/A * binary representation. 2N/A * Input: string - pointer to uchar_t array 2N/A * Output: wwn - pointer to uchar_t array 2N/A * containing WWN result 2N/A * Get multiple paths to a given device port. 2N/A /* Initialize list structures. */ 2N/A H_DPRINTF(
" g_get_port_multipath: Looking for multiple paths for" 2N/A " device with\n port WWW:" 2N/A " Found multipath:\n %s\n",
2N/A * The arg: devpath should be the physical path to device. 2N/A * multipath_list points to a list of multiple paths to the device. 2N/A * NOTE: The caller must free the allocated list (dlist). 2N/A * non-zero otherwise 2N/A H_DPRINTF(
" g_get_multipath: Looking for multiple paths for" 2N/A /* return invalid path if devpath is NULL */ 2N/A /* return invalid arg if argument is NULL */ 2N/A * Returns multipath information for a ssd device. 2N/A * devpath: device path to for requested multipath info 2N/A * wwn_list: returned from g_get_wwn_list or devices_get_all 2N/A * multipath_list: dlist list of paths 2N/A * non-zero on failure 2N/A * When a path is found from the list, load the logical 2N/A * and physical dev path 2N/A /* Load multipath list */ 2N/A " g_get_multipath: Found multipath=%s\n",
2N/A /* Strip partition information. */ 2N/A * Free a multipath list 2N/A * Get the path to the nexus (HBA) driver. 2N/A * This assumes the path looks something like this: 2N/A * (or "qlc" instead of "socal" and "fp" for "sf") 2N/A * Which should resolve to a path like this: 2N/A * which should resolve to 2N/A /* return invalid path if the path_phys is NULL */ 2N/A /* standby or path0 */ 2N/A /* sf driver in path so capture the port # */ 2N/A " sf driver in path so use port #%d.\n",
2N/A * check to see if it 3rd party vendor FCA. 2N/A * if it is return error for this operation since 2N/A * we don't know how they creates FCA port related minor node. 2N/A * As of now there is no supported operation on FCA node so 2N/A * this should be okay. 2N/A * For current Sun FCA driver, appending 2N/A * port # doesn't work. Just remove transport layer from 2N/A * Found a directory. 2N/A * Now append a port number or devctl to the path. 2N/A /* Try adding port 0 and see if node exists. */ 2N/A * Path we guessed at does not 2N/A * exist so it may be a driver 2N/A * that ends in :devctl. 2N/A * The path that was entered 2N/A * did not include a port number 2N/A * so the port was set to zero, and 2N/A * then checked. The default path 2N/A " was not supplied " 2N/A "a default path is being" 2N/A * Get the FC topology for the input device or nexus(HBA) path. 2N/A * The routine calls g_get_path_type to determine the stack of 2N/A * If it a socal path 2N/A * it returns FC_TOP_PRIVATE_LOOP 2N/A * calls fc_get_topology ioctl to 2N/A * get the fp topolgy from the driver. 2N/A * path - a string of device path, transport path. 2N/A * NOTE: "path" SHOULD NOT BE OPEN BEFORE CALLING 2N/A * THIS FUNCTION BECAUSE THIS FUNCTION DOES 2N/A * port_top - a pointer to the toplogy type. 2N/A * 0 if there is no error. 2N/A * The input path is expected to be something like below: 2N/A * (or "qlc" instead of "socal" and "fp" for "sf") 2N/A * Which should resolve to a path like this: 2N/A * which should resolve to 2N/A * 3) The nexus(hba or nexus) path will get an error only for qlc 2N/A * since the routine need to open fp :devctl node for fcio ioctl. 2N/A /* return invalid path if the path is NULL */ 2N/A /* return invalid arg if the argument is NULL */ 2N/A /* standby or path0 */ 2N/A * Get the path to the :devctl driver 2N/A * This assumes the path looks something like this: 2N/A * a 1 level PCI type driver but still :devctl 2N/A * (or "qlc" in the place of "socal" and "fp" for "sf") 2N/A * The dir below doesn't have corresponding :devctl node. 2N/A /* append controller */ 2N/A /* append controller */ 2N/A /* To contiue the path type should be fp :devctl node */ 2N/A * This functions enables or disables a FCA port depending on the 2N/A * argument, cmd, passed to it. If cmd is PORT_OFFLINE, the function 2N/A * tries to disable the port specified by the argument 'phys_path'. If 2N/A * cmd is PORT_ONLINE, the function tries to enable the port specified 2N/A * by the argument 'phys_path'. 2N/A * nexus_port_ptr - Pointer to the nexus path of the FCA port to 2N/A * cmd - PORT_OFFLINE or PORT_ONLINE 2N/A * 0 on success and non-zero otherwise 2N/A * The socal driver currently returns EFAULT 2N/A * even if the ioctl has completed successfully. 2N/A * Can't do much here since the driver currently 2N/A * doesn't support this feature. We'll just fail 2N/A * for now. Support can be added when the driver 2N/A * is enabled with the feature at a later date. 2N/A * The socal driver currently returns EFAULT 2N/A * even if the ioctl has completed successfully. 2N/A * Can't do much here since the driver currently 2N/A * doesn't support this feature. We'll just fail 2N/A * for now. Support can be added when the driver 2N/A * is enabled with the feature at a later date. 2N/A * The interfaces defined below (g_port_offline() and g_port_online()) 2N/A * are what will be exposed to applications. We will hide g_set_port_state(). 2N/A * They have to be functions (as against macros) because making them 2N/A * macros will mean exposing g_set_port_state() and we dont want to do that 2N/A * This function sets the loopback mode for a port on a HBA 2N/A * portpath - Pointer to the path of the FCA port on which to 2N/A * set the loopback mode 2N/A * 0 on success and non-zero otherwise 2N/A * The loopback calls are currently not fully supported 2N/A * A fp based general solution is required to support Leadville FCAs 2N/A * including Qlgc and 3rd party FCA. As of now qlgc provides 2N/A * some diag functions like echo through qlc private ioctl 2N/A * which is not supproted by luxadm and libraries. 2N/A /* Check for previous mode set */ 2N/A * Well, it wasn't one of the above cards so.. 2N/A * Well, it wasn't one of the above cards so.. 2N/A /* Check for previous mode set */ 2N/A * Well, it wasn't one of the above cards so.. 2N/A * g_get_port_state(char *portpath, int port_state) 2N/A * Purpose: Get port state for a path 2N/A * set to path of port 2N/A * Output: port_state 2N/A * Set to one of the following: 2N/A * Returns: 0 on success 2N/A * non-zero on failure 2N/A /* return invalid path if portpath is NULL */ 2N/A /* return invalid arg if argument is NULL */ 2N/A * FCIO_GETMAP returns error when there are * no devices attached. 2N/A * ENOMEM is returned when no devices are attached. 2N/A * g_get_first_dev returns NULL without error when there is no 2N/A * devices are attached. 2N/A /* no device is found if err == 0 */ 2N/A /* Device found okay */ 2N/A /* open controller */ 2N/A * Note: There is only one error returned by this ioctl. ENOMEM. 2N/A * Hence the lack of return on error. 2N/A /* Non-Leadville stacks report the FCA in the count */ 2N/A * g_dev_login(char *port_path, la_wwn_t port_wwn) 2N/A * Purpose: port login via g_dev_log_in_out() 2N/A * port wwn of device node to login 2N/A * Returns: return code from g_dev_log_in_out() 2N/A * g_dev_logout(char *port_path, la_wwn_t port_wwn) 2N/A * Purpose: port login via g_dev_log_in_out() 2N/A * port wwn of device node to logout 2N/A * Returns: return code from g_dev_log_in_out() 2N/A * g_dev_log_in_out(char *port_path, la_wwn_t port_wwn, uint16_t cmd) 2N/A * Purpose: port login via FCIO_DEV_LOGOUT and port logout via FCIO_DEV_LOGOUT 2N/A * IOCTL requires EXCLUSIVE open. 2N/A * port wwn of device node to logout 2N/A * FCIO_DEV_LOGON or FCIO_DEV_LOGOUT 2N/A * Returns: 0 on success 2N/A * non-zero on failure 2N/A /* open controller */ 2N/A * stores port_wwn to la_wwn_t raw_wwn field 2N/A * and construct fcio structures for FCIO_DEV_LOGIN. 2N/A " FCIO_DEV_LOGIN ioctl failed.\n" 2N/A :
" FCIO_DEV_LOGOUT ioctl failed.\n");
2N/A * This function will verify if a FC device (represented by input WWN 2N/A * is connected on a FCA port by searching the device list from 2N/A * g_get_dev_list() for a WWN match. 2N/A * fca_path: pointer to the physical path string, path to a fp node. 2N/A * possible forms are 2N/A * dev_wwn: WWN string 2N/A * flag: indicate that the input WWN is node or port 2N/A * 0: if a match is found. 2N/A * L_WWN_NOT_FOUND_IN_DEV_LIST: if no match found 2N/A * L_UNEXPECTED_FC_TOPOLOGY: existing error code for an error 2N/A * from the topology checking of the input fca path. 2N/A * L_MALLOC_FAILED: existing error code for allocation eror from the 2N/A * L_FCIO_GETMAP_IOCTL_FAIL: existing error code for an error from the 2N/A * FCIO ioctl called by the g_get_dev_list() 2N/A /* consider a new error code for not found. */ 2N/A /* consider a new error code for not found. */ 2N/A * g_get_dev_port_state(char *fca_path, la_wwn_t port_wwn, uint32_t *state) 2N/A * Purpose: get the state of device port login via FCIO_GET_STATE ioctl. 2N/A * port wwn of device node to logout 2N/A * Returns: 0 on success 2N/A * non-zero on failure 2N/A /* open controller */ 2N/A * stores port_wwn to la_wwn_t raw_wwn field 2N/A * and construct fcio structures for FCIO_DEV_LOGIN. 2N/A * Name: lilp_map_cmp 2N/A * Description: This function is used to compare the physical location 2N/A * of to fc devices in a gfc_map_t.dev_addr arrary. 2N/A * First device to compare 2N/A * Second device to compare 2N/A * 0 = Devices at equal phyiscal location, How did this happen? 2N/A * >0 = First device have a higher physical location than second 2N/A * <0 = Second device have a higher physical location than first 2N/A * Retrieves multiple paths to a device based on devid 2N/A * Caller must use mplist_free to free mplist structure 2N/A * This currently only supports ssd devices. 2N/A * The st driver does not register a device id. 2N/A * devid: ptr to valid ddi_devid_t struct 2N/A * root: root handle to device tree snapshot 2N/A * drvr_name: driver name to start the node tree search 2N/A * non-zero on failure 2N/A /* point to first node which matches portdrvr */ 2N/A /* Load multipath list */ 2N/A * Frees a previously allocated mplist_struct 2N/A * Retrieves all device nodes based on drvr_name 2N/A * Currently supports SSD_DRVR_NAME, ST_DRVR_NAME 2N/A * There will be a device node in the libdevinfo 2N/A * snapshot only if there is at least one node bound. 2N/A * root valid snapshot handle from di_init(3DEVINFO) 2N/A * drvr_name name of driver to start node search 2N/A * wwn_list_ptr ptr to ptr to WWN_list struct 2N/A * An unsupported driver name was passed in 2N/A /* point to first node which matches portdrvr */ 2N/A * Check for offline state 2N/A * Only support st, ssd nodes 2N/A * Clear values for SCSI VHCI devices. 2N/A * node wwn, port wwn are irrevelant at 2N/A * the SCSI VHCI level 2N/A /* Got wwns, load data in list */ 2N/A * Now load the /dev/ paths 2N/A * Access the properties for the node to get the node-wwn, port-wwn property 2N/A * On error, contents of nwwn, pwwn are unspecified. 2N/A * On successful return nwwn and pwwn are WWN_SIZE bytes. 2N/A /* If we didn't get back the right count, return error */ 2N/A /* If we didn't get back the right count, return error */ 2N/A * retrieves the /dev logical path for a WWN_list of devices. 2N/A * wwn_list_ptr ptr to list returned by devices_get_all 2N/A * dir_name /dev/ directory to search 2N/A * Ignore current directory and parent directory 2N/A * Add information to the list. 2N/A * Did we load all of the paths? 2N/A * Note: if there is a missing entry in /dev then 2N/A * the user probably did a cleanup of /dev. 2N/A * Whatever the case, remove the entry as it 2N/A * No previous entries 2N/A " get_dev_path %s: " 2N/A "\t\tTime = %lld millisec\n",
2N/A * This functions calls di_devfs_path and gets the path associated with a 2N/A * given devinfo node. If the path returned does not have a '@' in it, it 2N/A * checks if the driver is detached and creates a path after looking at the 2N/A * driver properties. 2N/A * di_devfs_path_free is called internally. 2N/A * The argument 'path' points to the final value upon return. 2N/A * Caller must use my_devfs_path_free on returned char * 2N/A * for FC check for initiator-interconnect-type prop 2N/A /* Now go get the path for this node */ 2N/A /* Prepend "/devices" to libdevinfo-returned paths */ 2N/A * Is this a FC device? 2N/A * Check initiator-interconnect-type property 2N/A /* Check for INTERCONNECT_FABRIC_STR & INTERCONNECT_FIBRE_STR */ 2N/A /* Not a FC device. Free path and return */ 2N/A * No '@' in path. This can happen when driver is detached. 2N/A * We'll check if the state is detached and if it is, we'll construct 2N/A * the path by looking at the properties. 2N/A * Driver is not detached and no '@' in path. 2N/A /* Something unexpected happened. */ 2N/A * from_ptr: ptr to uchar_t array of size WWN_SIZE 2N/A * to_ptr: char ptr to string of size WWN_SIZE*2+1 2N/A * Open the requested directory and get one valid open. 2N/A * If a device is busy, return. 2N/A * Only need to open one device since 2N/A * that implies there will be a node returned from 2N/A * di_drv_first_node() 2N/A * dir_name: logical device name directory 2N/A * (DEV_TAPE_DIR, DEV_RDIR) 2N/A * pattern_match: used by fnmatch on directory entry 2N/A * (DIR_MATCH_SSD, DIR_MATCH_ST) 2N/A * drvr_path: path type to verify ("/ssd@", "/st@") 2N/A * (SLSH_DRV_NAME_ST, SLSH_DRV_NAME_SSD) 2N/A * Ignore current directory and parent directory