1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte /* 22*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*fcf3ce44SJohn Forte * Use is subject to license terms. 24*fcf3ce44SJohn Forte */ 25*fcf3ce44SJohn Forte 26*fcf3ce44SJohn Forte 27*fcf3ce44SJohn Forte 28*fcf3ce44SJohn Forte 29*fcf3ce44SJohn Forte #include <stdlib.h> 30*fcf3ce44SJohn Forte #include <stdio.h> 31*fcf3ce44SJohn Forte #include <unistd.h> 32*fcf3ce44SJohn Forte #include <sys/types.h> 33*fcf3ce44SJohn Forte #include <sys/stat.h> 34*fcf3ce44SJohn Forte #include <fcntl.h> 35*fcf3ce44SJohn Forte #include <errno.h> 36*fcf3ce44SJohn Forte #include <string.h> 37*fcf3ce44SJohn Forte #include <stdarg.h> 38*fcf3ce44SJohn Forte #include <syslog.h> 39*fcf3ce44SJohn Forte #include <libdevice.h> 40*fcf3ce44SJohn Forte #include <sys/fibre-channel/fcio.h> 41*fcf3ce44SJohn Forte #include "common.h" 42*fcf3ce44SJohn Forte 43*fcf3ce44SJohn Forte static int parse_line(char *line, char *path, char *wwn, char *filename); 44*fcf3ce44SJohn Forte static int create_ap_instance(char *ap_id, char *wwn_string, 45*fcf3ce44SJohn Forte char *filename, char *line); 46*fcf3ce44SJohn Forte static void log_error(char *msg_id, char *input_tmplt, ...); 47*fcf3ce44SJohn Forte static char ctoi(char c); 48*fcf3ce44SJohn Forte 49*fcf3ce44SJohn Forte /* 50*fcf3ce44SJohn Forte * Simple wrapper for syslog error messages. 51*fcf3ce44SJohn Forte * Allows easy addition of syserr output if desired. 52*fcf3ce44SJohn Forte */ 53*fcf3ce44SJohn Forte static void 54*fcf3ce44SJohn Forte log_error(char *msg_id, char *input_tmplt, ...) 55*fcf3ce44SJohn Forte { 56*fcf3ce44SJohn Forte va_list ap; 57*fcf3ce44SJohn Forte char input_merged_msg[200]; 58*fcf3ce44SJohn Forte char *msg_template = "ID[luxadm.create_fabric_device.%s] %s"; 59*fcf3ce44SJohn Forte /* 60*fcf3ce44SJohn Forte * First %s for msg_id in merged msg. 61*fcf3ce44SJohn Forte * Second %s is for input merged_msg 62*fcf3ce44SJohn Forte */ 63*fcf3ce44SJohn Forte char *merged_msg; 64*fcf3ce44SJohn Forte 65*fcf3ce44SJohn Forte va_start(ap, input_tmplt); 66*fcf3ce44SJohn Forte /* insert caller's args */ 67*fcf3ce44SJohn Forte (void) vsprintf(input_merged_msg, input_tmplt, ap); 68*fcf3ce44SJohn Forte va_end(ap); 69*fcf3ce44SJohn Forte 70*fcf3ce44SJohn Forte merged_msg = (char *)malloc(strlen(msg_template) + 71*fcf3ce44SJohn Forte strlen(input_merged_msg) + 72*fcf3ce44SJohn Forte strlen(msg_id) + 1); 73*fcf3ce44SJohn Forte if (merged_msg == NULL) { 74*fcf3ce44SJohn Forte syslog(LOG_ERR, 75*fcf3ce44SJohn Forte "ID[luxadm.create_fabric_device.2317] " 76*fcf3ce44SJohn Forte "malloc failure, %s", strerror(errno)); 77*fcf3ce44SJohn Forte } else { 78*fcf3ce44SJohn Forte sprintf(merged_msg, msg_template, msg_id, input_merged_msg); 79*fcf3ce44SJohn Forte /* first insert msg_id */ 80*fcf3ce44SJohn Forte syslog(LOG_ERR, merged_msg, ""); 81*fcf3ce44SJohn Forte (void) puts(merged_msg); /* also print message */ 82*fcf3ce44SJohn Forte free(merged_msg); 83*fcf3ce44SJohn Forte } 84*fcf3ce44SJohn Forte } 85*fcf3ce44SJohn Forte 86*fcf3ce44SJohn Forte /* 87*fcf3ce44SJohn Forte * Routines for reading tapestry repository file 88*fcf3ce44SJohn Forte */ 89*fcf3ce44SJohn Forte 90*fcf3ce44SJohn Forte #define COMMENT_CHAR '#' 91*fcf3ce44SJohn Forte int 92*fcf3ce44SJohn Forte read_repos_file(char *repos_filename) 93*fcf3ce44SJohn Forte { 94*fcf3ce44SJohn Forte int fd; 95*fcf3ce44SJohn Forte char *line; 96*fcf3ce44SJohn Forte char *tmp_ptr, *mmap_ptr; 97*fcf3ce44SJohn Forte char path[MAXPATHLEN]; 98*fcf3ce44SJohn Forte int ret; 99*fcf3ce44SJohn Forte char wwn[FC_WWN_SIZE*2+1]; 100*fcf3ce44SJohn Forte struct stat stbuf; 101*fcf3ce44SJohn Forte unsigned int filesize; 102*fcf3ce44SJohn Forte unsigned int bytes_read; 103*fcf3ce44SJohn Forte 104*fcf3ce44SJohn Forte if (repos_filename == NULL || *repos_filename == NULL) { 105*fcf3ce44SJohn Forte log_error("2310", 106*fcf3ce44SJohn Forte "filename missing for -f option of " 107*fcf3ce44SJohn Forte "luxadm -e create_fabric_device"); 108*fcf3ce44SJohn Forte return (-1); 109*fcf3ce44SJohn Forte } 110*fcf3ce44SJohn Forte 111*fcf3ce44SJohn Forte fd = open(repos_filename, O_RDONLY); 112*fcf3ce44SJohn Forte 113*fcf3ce44SJohn Forte if (fd == -1) { 114*fcf3ce44SJohn Forte log_error("2311", 115*fcf3ce44SJohn Forte "fopen failed: cannot open repository file %s. %d", 116*fcf3ce44SJohn Forte repos_filename, strerror(errno)); 117*fcf3ce44SJohn Forte return (-1); 118*fcf3ce44SJohn Forte } 119*fcf3ce44SJohn Forte 120*fcf3ce44SJohn Forte if (fstat(fd, &stbuf) == -1) { 121*fcf3ce44SJohn Forte close(fd); 122*fcf3ce44SJohn Forte log_error("2312", 123*fcf3ce44SJohn Forte "stat failed on file %s. %s", 124*fcf3ce44SJohn Forte repos_filename, strerror(errno)); 125*fcf3ce44SJohn Forte return (-1); 126*fcf3ce44SJohn Forte } 127*fcf3ce44SJohn Forte filesize = stbuf.st_size; 128*fcf3ce44SJohn Forte tmp_ptr = mmap_ptr = mmap((caddr_t)0, filesize, 129*fcf3ce44SJohn Forte (PROT_READ | PROT_WRITE), MAP_PRIVATE, fd, 0); 130*fcf3ce44SJohn Forte 131*fcf3ce44SJohn Forte if (mmap_ptr == MAP_FAILED) { 132*fcf3ce44SJohn Forte log_error("2315", 133*fcf3ce44SJohn Forte "Failed to mmap file %s. %s", 134*fcf3ce44SJohn Forte repos_filename, strerror(errno)); 135*fcf3ce44SJohn Forte return (-1); 136*fcf3ce44SJohn Forte } 137*fcf3ce44SJohn Forte 138*fcf3ce44SJohn Forte bytes_read = 0; 139*fcf3ce44SJohn Forte while (bytes_read < filesize) { 140*fcf3ce44SJohn Forte line = tmp_ptr; 141*fcf3ce44SJohn Forte while (bytes_read < filesize && *tmp_ptr != '\n') { 142*fcf3ce44SJohn Forte bytes_read++; 143*fcf3ce44SJohn Forte tmp_ptr++; 144*fcf3ce44SJohn Forte } 145*fcf3ce44SJohn Forte if (*tmp_ptr == '\n') { 146*fcf3ce44SJohn Forte *tmp_ptr = NULL; 147*fcf3ce44SJohn Forte tmp_ptr++; 148*fcf3ce44SJohn Forte bytes_read++; 149*fcf3ce44SJohn Forte } 150*fcf3ce44SJohn Forte 151*fcf3ce44SJohn Forte /* If the line is a comment, read another line */ 152*fcf3ce44SJohn Forte if (*line == COMMENT_CHAR) { 153*fcf3ce44SJohn Forte continue; 154*fcf3ce44SJohn Forte } 155*fcf3ce44SJohn Forte ret = parse_line(line, path, wwn, repos_filename); 156*fcf3ce44SJohn Forte if (ret == 0) { 157*fcf3ce44SJohn Forte ret = create_ap_instance(path, 158*fcf3ce44SJohn Forte wwn, repos_filename, line); 159*fcf3ce44SJohn Forte } 160*fcf3ce44SJohn Forte } 161*fcf3ce44SJohn Forte 162*fcf3ce44SJohn Forte ret = close(fd); 163*fcf3ce44SJohn Forte ret = munmap(mmap_ptr, filesize); 164*fcf3ce44SJohn Forte return (ret); 165*fcf3ce44SJohn Forte } 166*fcf3ce44SJohn Forte 167*fcf3ce44SJohn Forte /* 168*fcf3ce44SJohn Forte * Input is paramater 1 - a line from repository 169*fcf3ce44SJohn Forte * Output is other parameters, the path to the attachment point, 170*fcf3ce44SJohn Forte * and the port wwn are parsed from the repository 171*fcf3ce44SJohn Forte * Format is 172*fcf3ce44SJohn Forte * "/devices/pci..../fp@1,0:fc::wwn" 173*fcf3ce44SJohn Forte * If controller name is missing, that's okay. Other fields 174*fcf3ce44SJohn Forte * must be present 175*fcf3ce44SJohn Forte * 176*fcf3ce44SJohn Forte * Return 0 on success or -1 on failure; all failures logged to syslog. 177*fcf3ce44SJohn Forte */ 178*fcf3ce44SJohn Forte #define WWN_DELIM "::" 179*fcf3ce44SJohn Forte static int 180*fcf3ce44SJohn Forte parse_line(char *line, char *path, char *wwn, char *filename) 181*fcf3ce44SJohn Forte { 182*fcf3ce44SJohn Forte char *p_path, *p_wwn, *p_delim; 183*fcf3ce44SJohn Forte char *line_copy; 184*fcf3ce44SJohn Forte 185*fcf3ce44SJohn Forte line_copy = strdup(line); 186*fcf3ce44SJohn Forte if (line_copy == NULL) { 187*fcf3ce44SJohn Forte log_error("2317", 188*fcf3ce44SJohn Forte "malloc failure, %s", strerror(errno)); 189*fcf3ce44SJohn Forte } 190*fcf3ce44SJohn Forte p_path = line_copy; 191*fcf3ce44SJohn Forte p_delim = strstr(p_path, WWN_DELIM); 192*fcf3ce44SJohn Forte if (p_delim == NULL) { 193*fcf3ce44SJohn Forte log_error("2313", 194*fcf3ce44SJohn Forte "Invalid line (%s) in file %s.", line, filename); 195*fcf3ce44SJohn Forte free(line_copy); 196*fcf3ce44SJohn Forte return (-1); 197*fcf3ce44SJohn Forte } 198*fcf3ce44SJohn Forte *p_delim = NULL; /* NULL terminate path */ 199*fcf3ce44SJohn Forte 200*fcf3ce44SJohn Forte if (strlcpy(path, p_path, MAXPATHLEN) >= MAXPATHLEN) { 201*fcf3ce44SJohn Forte log_error("2318", 202*fcf3ce44SJohn Forte "Path too long (%s) in file %s.", p_path, filename); 203*fcf3ce44SJohn Forte free(line_copy); 204*fcf3ce44SJohn Forte return (-1); 205*fcf3ce44SJohn Forte } 206*fcf3ce44SJohn Forte 207*fcf3ce44SJohn Forte p_wwn = p_delim + strlen(WWN_DELIM); 208*fcf3ce44SJohn Forte /* 209*fcf3ce44SJohn Forte * Now look for the blank delimiter before the controller 210*fcf3ce44SJohn Forte * 211*fcf3ce44SJohn Forte * This is just the case when there may be a controller # 212*fcf3ce44SJohn Forte * after the attachment point and WWN. For example - 213*fcf3ce44SJohn Forte * /devices/pci@b,2000/pci@2/SUNW,qlc@4/fp@0,0:fc::220000203707f4f1 c4 214*fcf3ce44SJohn Forte */ 215*fcf3ce44SJohn Forte p_delim = strchr(p_wwn, ' '); 216*fcf3ce44SJohn Forte if (p_delim != NULL) { 217*fcf3ce44SJohn Forte /* now p_delim points to blank */ 218*fcf3ce44SJohn Forte *p_delim = NULL; /* terminate wwn at delim */ 219*fcf3ce44SJohn Forte } else { 220*fcf3ce44SJohn Forte char *p_last_char; 221*fcf3ce44SJohn Forte p_last_char = p_wwn+strlen(p_wwn)-1; 222*fcf3ce44SJohn Forte if (*p_last_char == '\n') { 223*fcf3ce44SJohn Forte *p_last_char = NULL; 224*fcf3ce44SJohn Forte } 225*fcf3ce44SJohn Forte } 226*fcf3ce44SJohn Forte strcpy(wwn, p_wwn); 227*fcf3ce44SJohn Forte free(line_copy); 228*fcf3ce44SJohn Forte return (0); 229*fcf3ce44SJohn Forte } 230*fcf3ce44SJohn Forte 231*fcf3ce44SJohn Forte static char 232*fcf3ce44SJohn Forte ctoi(char c) 233*fcf3ce44SJohn Forte { 234*fcf3ce44SJohn Forte if ((c >= '0') && (c <= '9')) 235*fcf3ce44SJohn Forte c -= '0'; 236*fcf3ce44SJohn Forte else if ((c >= 'A') && (c <= 'F')) 237*fcf3ce44SJohn Forte c = c - 'A' + 10; 238*fcf3ce44SJohn Forte else if ((c >= 'a') && (c <= 'f')) 239*fcf3ce44SJohn Forte c = c - 'a' + 10; 240*fcf3ce44SJohn Forte else 241*fcf3ce44SJohn Forte c = -1; 242*fcf3ce44SJohn Forte return (c); 243*fcf3ce44SJohn Forte } 244*fcf3ce44SJohn Forte 245*fcf3ce44SJohn Forte /* 246*fcf3ce44SJohn Forte * "string" is Input and "port_wwn" has the output 247*fcf3ce44SJohn Forte * 248*fcf3ce44SJohn Forte * This function converts a string to WWN. 249*fcf3ce44SJohn Forte * For example a string like 250*fcf3ce44SJohn Forte * "220000203707F4F1" gets converted to 0x220000203707F4F1 ... 251*fcf3ce44SJohn Forte * where 252*fcf3ce44SJohn Forte * port_wwn[0] = 0x22, 253*fcf3ce44SJohn Forte * port_wwn[1] = 0x00, 254*fcf3ce44SJohn Forte * port_wwn[2] = 0x00, 255*fcf3ce44SJohn Forte * port_wwn[3] = 0x20, 256*fcf3ce44SJohn Forte * port_wwn[4] = 0x37, 257*fcf3ce44SJohn Forte * port_wwn[5] = 0x07, 258*fcf3ce44SJohn Forte * port_wwn[6] = 0xF4, and 259*fcf3ce44SJohn Forte * port_wwn[7] = 0xF1 260*fcf3ce44SJohn Forte */ 261*fcf3ce44SJohn Forte static int 262*fcf3ce44SJohn Forte string_to_wwn(const uchar_t *string, uchar_t *port_wwn) 263*fcf3ce44SJohn Forte { 264*fcf3ce44SJohn Forte int i; 265*fcf3ce44SJohn Forte char c, c1; 266*fcf3ce44SJohn Forte uchar_t *wwnp; 267*fcf3ce44SJohn Forte 268*fcf3ce44SJohn Forte wwnp = port_wwn; 269*fcf3ce44SJohn Forte for (i = 0; i < WWN_SIZE; i++, wwnp++) { 270*fcf3ce44SJohn Forte 271*fcf3ce44SJohn Forte c = ctoi(*string++); 272*fcf3ce44SJohn Forte c1 = ctoi(*string++); 273*fcf3ce44SJohn Forte if (c == -1 || c1 == -1) 274*fcf3ce44SJohn Forte return (-1); 275*fcf3ce44SJohn Forte *wwnp = ((c << 4) + c1); 276*fcf3ce44SJohn Forte } 277*fcf3ce44SJohn Forte 278*fcf3ce44SJohn Forte return (0); 279*fcf3ce44SJohn Forte } 280*fcf3ce44SJohn Forte 281*fcf3ce44SJohn Forte static int 282*fcf3ce44SJohn Forte create_ap_instance(char *ap_id, char *wwn_string, 283*fcf3ce44SJohn Forte char *filename, char *line) 284*fcf3ce44SJohn Forte { 285*fcf3ce44SJohn Forte devctl_hdl_t bus_handle, dev_handle; 286*fcf3ce44SJohn Forte devctl_ddef_t ddef_handle; 287*fcf3ce44SJohn Forte int ret; 288*fcf3ce44SJohn Forte uchar_t wwn_array[FC_WWN_SIZE]; 289*fcf3ce44SJohn Forte 290*fcf3ce44SJohn Forte ddef_handle = devctl_ddef_alloc("dummy", 0); 291*fcf3ce44SJohn Forte if (ddef_handle == NULL) { 292*fcf3ce44SJohn Forte log_error("2314", 293*fcf3ce44SJohn Forte "Internal error to process line (%s) " 294*fcf3ce44SJohn Forte "in file: %s. %s", 295*fcf3ce44SJohn Forte line, filename, strerror(errno)); 296*fcf3ce44SJohn Forte return (-1); 297*fcf3ce44SJohn Forte } 298*fcf3ce44SJohn Forte /* 299*fcf3ce44SJohn Forte * g_string_to_wwn() has not been used here because it 300*fcf3ce44SJohn Forte * prepends 2 NULLs. 301*fcf3ce44SJohn Forte */ 302*fcf3ce44SJohn Forte if (string_to_wwn((uchar_t *)wwn_string, wwn_array) != 0) { 303*fcf3ce44SJohn Forte log_error("2314", 304*fcf3ce44SJohn Forte "Internal error to process line (%s) " 305*fcf3ce44SJohn Forte "in file: %s. %s", 306*fcf3ce44SJohn Forte line, filename, strerror(errno)); 307*fcf3ce44SJohn Forte devctl_ddef_free(ddef_handle); 308*fcf3ce44SJohn Forte return (-1); 309*fcf3ce44SJohn Forte } 310*fcf3ce44SJohn Forte (void) devctl_ddef_byte_array(ddef_handle, 311*fcf3ce44SJohn Forte "port-wwn", FC_WWN_SIZE, wwn_array); 312*fcf3ce44SJohn Forte 313*fcf3ce44SJohn Forte if ((bus_handle = devctl_bus_acquire(ap_id, 0)) == NULL) { 314*fcf3ce44SJohn Forte devctl_ddef_free(ddef_handle); 315*fcf3ce44SJohn Forte log_error("2314", 316*fcf3ce44SJohn Forte "Internal error to process line (%s) " 317*fcf3ce44SJohn Forte "in file: %s. %s", 318*fcf3ce44SJohn Forte line, filename, strerror(errno)); 319*fcf3ce44SJohn Forte return (-1); 320*fcf3ce44SJohn Forte } 321*fcf3ce44SJohn Forte if (ret = 322*fcf3ce44SJohn Forte devctl_bus_dev_create(bus_handle, ddef_handle, 0, &dev_handle)) { 323*fcf3ce44SJohn Forte devctl_ddef_free(ddef_handle); 324*fcf3ce44SJohn Forte devctl_release(bus_handle); 325*fcf3ce44SJohn Forte log_error("2316", 326*fcf3ce44SJohn Forte "configuration failed for line (%s) " 327*fcf3ce44SJohn Forte "in file: %s. %s", 328*fcf3ce44SJohn Forte line, filename, strerror(errno)); 329*fcf3ce44SJohn Forte return (-1); 330*fcf3ce44SJohn Forte } 331*fcf3ce44SJohn Forte devctl_release(dev_handle); 332*fcf3ce44SJohn Forte devctl_ddef_free(ddef_handle); 333*fcf3ce44SJohn Forte devctl_release(bus_handle); 334*fcf3ce44SJohn Forte return (ret); 335*fcf3ce44SJohn Forte } 336