1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <string.h> 31*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 32*7c478bd9Sstevel@tonic-gate #include <unistd.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 34*7c478bd9Sstevel@tonic-gate #include <errno.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 36*7c478bd9Sstevel@tonic-gate #include <dirent.h> 37*7c478bd9Sstevel@tonic-gate #include <libdevinfo.h> 38*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/pci.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/biosdisk.h> 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate /* 46*7c478bd9Sstevel@tonic-gate * structure used for searching device tree for a node matching 47*7c478bd9Sstevel@tonic-gate * pci bus/dev/fn 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate typedef struct pcibdf { 50*7c478bd9Sstevel@tonic-gate int busnum; 51*7c478bd9Sstevel@tonic-gate int devnum; 52*7c478bd9Sstevel@tonic-gate int funcnum; 53*7c478bd9Sstevel@tonic-gate di_node_t di_node; 54*7c478bd9Sstevel@tonic-gate } pcibdf_t; 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * structure used for searching device tree for a node matching 58*7c478bd9Sstevel@tonic-gate * USB serial number. 59*7c478bd9Sstevel@tonic-gate */ 60*7c478bd9Sstevel@tonic-gate typedef struct { 61*7c478bd9Sstevel@tonic-gate uint64_t serialno; 62*7c478bd9Sstevel@tonic-gate di_node_t node; 63*7c478bd9Sstevel@tonic-gate } usbser_t; 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * structure for holding the mapping info 67*7c478bd9Sstevel@tonic-gate */ 68*7c478bd9Sstevel@tonic-gate typedef struct { 69*7c478bd9Sstevel@tonic-gate int disklist_index; /* index to disk_list of the mapped path */ 70*7c478bd9Sstevel@tonic-gate int matchcount; /* number of matches per this device number */ 71*7c478bd9Sstevel@tonic-gate } mapinfo_t; 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #define DEVFS_PREFIX "/devices" 74*7c478bd9Sstevel@tonic-gate #define DISKS_LIST_INCR 20 /* increment for resizing disk_list */ 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate #define BIOSPROPNAME_TMPL "biosdev-0x%x" 77*7c478bd9Sstevel@tonic-gate #define BIOSPROPNAME_TMPL_LEN 13 78*7c478bd9Sstevel@tonic-gate #define BIOSDEV_NUM 8 79*7c478bd9Sstevel@tonic-gate #define STARTING_DRVNUM 0x80 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* 82*7c478bd9Sstevel@tonic-gate * array to hold mappings. Element at index X corresponds to BIOS device 83*7c478bd9Sstevel@tonic-gate * number 0x80 + X 84*7c478bd9Sstevel@tonic-gate */ 85*7c478bd9Sstevel@tonic-gate static mapinfo_t mapinfo[BIOSDEV_NUM]; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate /* 88*7c478bd9Sstevel@tonic-gate * Cache copy of kernel device tree snapshot root handle, includes devices 89*7c478bd9Sstevel@tonic-gate * that are detached 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate static di_node_t root_node = DI_NODE_NIL; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * kernel device tree snapshot with currently attached devices. Detached 95*7c478bd9Sstevel@tonic-gate * devices are not included. 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate static di_node_t root_allnode = DI_NODE_NIL; 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* 100*7c478bd9Sstevel@tonic-gate * handle to retrieve prom properties 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate static di_prom_handle_t prom_hdl = DI_PROM_HANDLE_NIL; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate static char **disk_list = NULL; /* array of physical device pathnames */ 106*7c478bd9Sstevel@tonic-gate static int disk_list_len = 0; /* length of disk_list */ 107*7c478bd9Sstevel@tonic-gate static int disk_list_valid = 0; /* number of valid entries in disk_list */ 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate static int debug = 0; /* used for enabling debug output */ 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate /* Local function prototypes */ 113*7c478bd9Sstevel@tonic-gate static void new_disk_list_entry(di_node_t node); 114*7c478bd9Sstevel@tonic-gate static int find_disks_callback(di_node_t node, di_minor_t minor, void *arg); 115*7c478bd9Sstevel@tonic-gate static void build_disk_list(); 116*7c478bd9Sstevel@tonic-gate static void free_disks(); 117*7c478bd9Sstevel@tonic-gate static int matchpcibdf(di_node_t node, void *arg); 118*7c478bd9Sstevel@tonic-gate static int matchusbserial(di_node_t node, void *arg); 119*7c478bd9Sstevel@tonic-gate static di_node_t search_tree_forpcibdf(int bus, int dev, int fn); 120*7c478bd9Sstevel@tonic-gate static int match_edd(biosdev_data_t *bd); 121*7c478bd9Sstevel@tonic-gate static int match_first_block(biosdev_data_t *bd); 122*7c478bd9Sstevel@tonic-gate static void cleanup_and_exit(int); 123*7c478bd9Sstevel@tonic-gate static int find_path_index_in_disk_list(char *path); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate static void 127*7c478bd9Sstevel@tonic-gate new_disk_list_entry(di_node_t node) 128*7c478bd9Sstevel@tonic-gate { 129*7c478bd9Sstevel@tonic-gate size_t newsize; 130*7c478bd9Sstevel@tonic-gate char **newlist; 131*7c478bd9Sstevel@tonic-gate int newlen; 132*7c478bd9Sstevel@tonic-gate char *devfspath; 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate if (disk_list_valid >= disk_list_len) { 135*7c478bd9Sstevel@tonic-gate /* valid should never really be larger than len */ 136*7c478bd9Sstevel@tonic-gate /* if they are equal we need to init or realloc */ 137*7c478bd9Sstevel@tonic-gate newlen = disk_list_len + DISKS_LIST_INCR; 138*7c478bd9Sstevel@tonic-gate newsize = newlen * sizeof (*disk_list); 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate newlist = (char **)realloc(disk_list, newsize); 141*7c478bd9Sstevel@tonic-gate if (newlist == NULL) { 142*7c478bd9Sstevel@tonic-gate (void) printf("realloc failed to resize disk table\n"); 143*7c478bd9Sstevel@tonic-gate cleanup_and_exit(1); 144*7c478bd9Sstevel@tonic-gate } 145*7c478bd9Sstevel@tonic-gate disk_list = newlist; 146*7c478bd9Sstevel@tonic-gate disk_list_len = newlen; 147*7c478bd9Sstevel@tonic-gate } 148*7c478bd9Sstevel@tonic-gate 149*7c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 150*7c478bd9Sstevel@tonic-gate disk_list[disk_list_valid] = devfspath; 151*7c478bd9Sstevel@tonic-gate if (debug) 152*7c478bd9Sstevel@tonic-gate (void) printf("adding %s\n", devfspath); 153*7c478bd9Sstevel@tonic-gate disk_list_valid++; 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 157*7c478bd9Sstevel@tonic-gate static int 158*7c478bd9Sstevel@tonic-gate find_disks_callback(di_node_t node, di_minor_t minor, void *arg) 159*7c478bd9Sstevel@tonic-gate { 160*7c478bd9Sstevel@tonic-gate char *minortype; 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate if (di_minor_spectype(minor) == S_IFCHR) { 163*7c478bd9Sstevel@tonic-gate minortype = di_minor_nodetype(minor); 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* exclude CD's */ 166*7c478bd9Sstevel@tonic-gate if (strncmp(minortype, DDI_NT_CD, sizeof (DDI_NT_CD) - 1) != 0) 167*7c478bd9Sstevel@tonic-gate /* only take p0 raw device */ 168*7c478bd9Sstevel@tonic-gate if (strcmp(di_minor_name(minor), "q,raw") == 0) 169*7c478bd9Sstevel@tonic-gate new_disk_list_entry(node); 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 172*7c478bd9Sstevel@tonic-gate } 173*7c478bd9Sstevel@tonic-gate 174*7c478bd9Sstevel@tonic-gate static void 175*7c478bd9Sstevel@tonic-gate build_disk_list() 176*7c478bd9Sstevel@tonic-gate { 177*7c478bd9Sstevel@tonic-gate int ret; 178*7c478bd9Sstevel@tonic-gate ret = di_walk_minor(root_node, DDI_NT_BLOCK, 0, NULL, 179*7c478bd9Sstevel@tonic-gate find_disks_callback); 180*7c478bd9Sstevel@tonic-gate if (ret != 0) { 181*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "di_walk_minor failed errno %d\n", 182*7c478bd9Sstevel@tonic-gate errno); 183*7c478bd9Sstevel@tonic-gate cleanup_and_exit(1); 184*7c478bd9Sstevel@tonic-gate } 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate static void 188*7c478bd9Sstevel@tonic-gate free_disks() 189*7c478bd9Sstevel@tonic-gate { 190*7c478bd9Sstevel@tonic-gate int i; 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate if (disk_list) { 193*7c478bd9Sstevel@tonic-gate for (i = 0; i < disk_list_valid; i++) 194*7c478bd9Sstevel@tonic-gate di_devfs_path_free(disk_list[i]); 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate free(disk_list); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate } 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate static int 201*7c478bd9Sstevel@tonic-gate matchpcibdf(di_node_t node, void *arg) 202*7c478bd9Sstevel@tonic-gate { 203*7c478bd9Sstevel@tonic-gate pcibdf_t *pbp; 204*7c478bd9Sstevel@tonic-gate int len; 205*7c478bd9Sstevel@tonic-gate uint32_t regval; 206*7c478bd9Sstevel@tonic-gate uint32_t busnum, funcnum, devicenum; 207*7c478bd9Sstevel@tonic-gate char *devtype; 208*7c478bd9Sstevel@tonic-gate uint32_t *regbuf = NULL; 209*7c478bd9Sstevel@tonic-gate di_node_t parentnode; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate pbp = (pcibdf_t *)arg; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate parentnode = di_parent_node(node); 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate len = di_prop_lookup_strings(DDI_DEV_T_ANY, parentnode, 216*7c478bd9Sstevel@tonic-gate "device_type", (char **)&devtype); 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if ((len <= 0) || (strcmp(devtype, "pci") != 0)) 219*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate len = di_prop_lookup_ints(DDI_DEV_T_ANY, node, "reg", 222*7c478bd9Sstevel@tonic-gate (int **)®buf); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate if (len <= 0) { 225*7c478bd9Sstevel@tonic-gate /* Try PROM property */ 226*7c478bd9Sstevel@tonic-gate len = di_prom_prop_lookup_ints(prom_hdl, node, "reg", 227*7c478bd9Sstevel@tonic-gate (int **)®buf); 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if (len > 0) { 232*7c478bd9Sstevel@tonic-gate regval = regbuf[0]; 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate busnum = PCI_REG_BUS_G(regval); 235*7c478bd9Sstevel@tonic-gate devicenum = PCI_REG_DEV_G(regval); 236*7c478bd9Sstevel@tonic-gate funcnum = PCI_REG_FUNC_G(regval); 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate if ((busnum == pbp->busnum) && 239*7c478bd9Sstevel@tonic-gate (devicenum == pbp->devnum) && 240*7c478bd9Sstevel@tonic-gate (funcnum == pbp->funcnum)) { 241*7c478bd9Sstevel@tonic-gate /* found it */ 242*7c478bd9Sstevel@tonic-gate pbp->di_node = node; 243*7c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate } 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate static di_node_t 251*7c478bd9Sstevel@tonic-gate search_tree_forpcibdf(int bus, int dev, int fn) 252*7c478bd9Sstevel@tonic-gate { 253*7c478bd9Sstevel@tonic-gate pcibdf_t pb; 254*7c478bd9Sstevel@tonic-gate pb.busnum = bus; 255*7c478bd9Sstevel@tonic-gate pb.devnum = dev; 256*7c478bd9Sstevel@tonic-gate pb.funcnum = fn; 257*7c478bd9Sstevel@tonic-gate pb.di_node = DI_NODE_NIL; 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate (void) di_walk_node(root_node, DI_WALK_CLDFIRST, &pb, matchpcibdf); 260*7c478bd9Sstevel@tonic-gate return (pb.di_node); 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate static int 265*7c478bd9Sstevel@tonic-gate matchusbserial(di_node_t node, void *arg) 266*7c478bd9Sstevel@tonic-gate { 267*7c478bd9Sstevel@tonic-gate int len; 268*7c478bd9Sstevel@tonic-gate char *serialp; 269*7c478bd9Sstevel@tonic-gate usbser_t *usbsp; 270*7c478bd9Sstevel@tonic-gate 271*7c478bd9Sstevel@tonic-gate usbsp = (usbser_t *)arg; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate len = di_prop_lookup_bytes(DDI_DEV_T_ANY, node, "usb-serialno", 274*7c478bd9Sstevel@tonic-gate (uchar_t **)&serialp); 275*7c478bd9Sstevel@tonic-gate 276*7c478bd9Sstevel@tonic-gate if ((len > 0) && (strcmp((char *)&usbsp->serialno, serialp) == 0)) { 277*7c478bd9Sstevel@tonic-gate usbsp->node = node; 278*7c478bd9Sstevel@tonic-gate return (DI_WALK_TERMINATE); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate return (DI_WALK_CONTINUE); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate static di_node_t 284*7c478bd9Sstevel@tonic-gate match_usb(di_node_t node, uint64_t serialno) 285*7c478bd9Sstevel@tonic-gate { 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate usbser_t usbs; 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate usbs.serialno = serialno; 290*7c478bd9Sstevel@tonic-gate usbs.node = DI_NODE_NIL; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate (void) di_walk_node(node, DI_WALK_CLDFIRST, &usbs, matchusbserial); 293*7c478bd9Sstevel@tonic-gate return (usbs.node); 294*7c478bd9Sstevel@tonic-gate } 295*7c478bd9Sstevel@tonic-gate 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate static int 298*7c478bd9Sstevel@tonic-gate find_path_index_in_disk_list(char *path) 299*7c478bd9Sstevel@tonic-gate { 300*7c478bd9Sstevel@tonic-gate int i; 301*7c478bd9Sstevel@tonic-gate for (i = 0; i < disk_list_valid; i++) 302*7c478bd9Sstevel@tonic-gate if (strcmp(disk_list[i], path) == 0) { 303*7c478bd9Sstevel@tonic-gate return (i); 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate return (-1); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate /* 310*7c478bd9Sstevel@tonic-gate * Construct a physical device pathname from EDD and verify the 311*7c478bd9Sstevel@tonic-gate * path exists. Return the index of in disk_list for the mapped 312*7c478bd9Sstevel@tonic-gate * path on success, -1 on failure. 313*7c478bd9Sstevel@tonic-gate */ 314*7c478bd9Sstevel@tonic-gate static int 315*7c478bd9Sstevel@tonic-gate match_edd(biosdev_data_t *bdata) 316*7c478bd9Sstevel@tonic-gate { 317*7c478bd9Sstevel@tonic-gate di_node_t node; 318*7c478bd9Sstevel@tonic-gate char *devfspath; 319*7c478bd9Sstevel@tonic-gate fn48_t *bd; 320*7c478bd9Sstevel@tonic-gate int index; 321*7c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate if (!bdata->edd_valid) { 324*7c478bd9Sstevel@tonic-gate if (debug) 325*7c478bd9Sstevel@tonic-gate (void) printf("edd not valid\n"); 326*7c478bd9Sstevel@tonic-gate return (-1); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate bd = &bdata->fn48_dev_params; 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate if (bd->magic != 0xBEDD || bd->pathinfo_len == 0) { 332*7c478bd9Sstevel@tonic-gate /* EDD extensions for devicepath not present */ 333*7c478bd9Sstevel@tonic-gate if (debug) 334*7c478bd9Sstevel@tonic-gate (void) printf("magic not valid %x pathinfolen %d\n", 335*7c478bd9Sstevel@tonic-gate bd->magic, bd->pathinfo_len); 336*7c478bd9Sstevel@tonic-gate return (-1); 337*7c478bd9Sstevel@tonic-gate } 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate /* we handle only PCI scsi, ata or sata for now */ 340*7c478bd9Sstevel@tonic-gate if (strncmp(bd->bustype, "PCI", 3) != 0) { 341*7c478bd9Sstevel@tonic-gate if (debug) 342*7c478bd9Sstevel@tonic-gate (void) printf("was not pci %s\n", bd->bustype); 343*7c478bd9Sstevel@tonic-gate return (-1); 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate if (debug) 346*7c478bd9Sstevel@tonic-gate (void) printf("match_edd bdf %d %d %d\n", 347*7c478bd9Sstevel@tonic-gate bd->interfacepath.pci.bus, 348*7c478bd9Sstevel@tonic-gate bd->interfacepath.pci.device, 349*7c478bd9Sstevel@tonic-gate bd->interfacepath.pci.function); 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /* look into devinfo tree and find a node with matching pci b/d/f */ 352*7c478bd9Sstevel@tonic-gate node = search_tree_forpcibdf(bd->interfacepath.pci.bus, 353*7c478bd9Sstevel@tonic-gate bd->interfacepath.pci.device, 354*7c478bd9Sstevel@tonic-gate bd->interfacepath.pci.function); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 357*7c478bd9Sstevel@tonic-gate if (debug) 358*7c478bd9Sstevel@tonic-gate (void) printf(" could not find a node in tree " 359*7c478bd9Sstevel@tonic-gate "matching bdf\n"); 360*7c478bd9Sstevel@tonic-gate return (-1); 361*7c478bd9Sstevel@tonic-gate } 362*7c478bd9Sstevel@tonic-gate 363*7c478bd9Sstevel@tonic-gate /* construct a path */ 364*7c478bd9Sstevel@tonic-gate devfspath = di_devfs_path(node); 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate if (debug) 367*7c478bd9Sstevel@tonic-gate (void) printf("interface type %s\n", bd->interface_type); 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate if (strncmp(bd->interface_type, "SCSI", 4) == 0) { 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate /* at this time sd doesnot support luns greater than uchar_t */ 372*7c478bd9Sstevel@tonic-gate (void) snprintf(path, MAXPATHLEN, "%s/sd@%d,%d", devfspath, 373*7c478bd9Sstevel@tonic-gate bd->devicepath.scsi.target, bd->devicepath.scsi.lun_lo); 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate } else if (strncmp(bd->interface_type, "ATAPI", 5) == 0) { 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate (void) snprintf(path, MAXPATHLEN, "%s/ide@%d/sd@%d,0", 378*7c478bd9Sstevel@tonic-gate devfspath, bd->interfacepath.pci.channel, 379*7c478bd9Sstevel@tonic-gate bd->devicepath.ata.chan); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate } else if (strncmp(bd->interface_type, "ATA", 3) == 0) { 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate (void) snprintf(path, MAXPATHLEN, "%s/ide@%d/cmdk@%d,0", 384*7c478bd9Sstevel@tonic-gate devfspath, bd->interfacepath.pci.channel, 385*7c478bd9Sstevel@tonic-gate bd->devicepath.ata.chan); 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate } else if (strncmp(bd->interface_type, "SATA", 4) == 0) { 388*7c478bd9Sstevel@tonic-gate 389*7c478bd9Sstevel@tonic-gate (void) snprintf(path, MAXPATHLEN, "%s/ide@%d/cmdk@%d,0", 390*7c478bd9Sstevel@tonic-gate devfspath, bd->interfacepath.pci.channel, 391*7c478bd9Sstevel@tonic-gate bd->devicepath.ata.chan); 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate } else if (strncmp(bd->interface_type, "USB", 3) == 0) { 394*7c478bd9Sstevel@tonic-gate (void) printf("USB\n"); 395*7c478bd9Sstevel@tonic-gate node = match_usb(node, bd->devicepath.usb.usb_serial_id); 396*7c478bd9Sstevel@tonic-gate if (node != DI_NODE_NIL) { 397*7c478bd9Sstevel@tonic-gate if (debug) 398*7c478bd9Sstevel@tonic-gate (void) printf("usb path %s\n", 399*7c478bd9Sstevel@tonic-gate di_devfs_path(node)); 400*7c478bd9Sstevel@tonic-gate (void) snprintf(path, MAXPATHLEN, "%s", devfspath); 401*7c478bd9Sstevel@tonic-gate } else 402*7c478bd9Sstevel@tonic-gate return (-1); 403*7c478bd9Sstevel@tonic-gate } else { 404*7c478bd9Sstevel@tonic-gate if (debug) 405*7c478bd9Sstevel@tonic-gate (void) printf("sorry not supported interface %s\n", 406*7c478bd9Sstevel@tonic-gate bd->interface_type); 407*7c478bd9Sstevel@tonic-gate return (-1); 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate index = find_path_index_in_disk_list(path); 411*7c478bd9Sstevel@tonic-gate if (index >= 0) { 412*7c478bd9Sstevel@tonic-gate return (index); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate return (-1); 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate /* 419*7c478bd9Sstevel@tonic-gate * For each disk in list of disks, compare the first block with the 420*7c478bd9Sstevel@tonic-gate * one from bdd. On the first match, return the index of path in 421*7c478bd9Sstevel@tonic-gate * disk_list. If none matched return -1. 422*7c478bd9Sstevel@tonic-gate */ 423*7c478bd9Sstevel@tonic-gate static int 424*7c478bd9Sstevel@tonic-gate match_first_block(biosdev_data_t *bd) 425*7c478bd9Sstevel@tonic-gate { 426*7c478bd9Sstevel@tonic-gate 427*7c478bd9Sstevel@tonic-gate char diskpath[MAXPATHLEN]; 428*7c478bd9Sstevel@tonic-gate int fd; 429*7c478bd9Sstevel@tonic-gate char buf[512]; 430*7c478bd9Sstevel@tonic-gate ssize_t num_read; 431*7c478bd9Sstevel@tonic-gate int i; 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate if (!bd->first_block_valid) 434*7c478bd9Sstevel@tonic-gate return (-1); 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate for (i = 0; i < disk_list_valid; i++) { 437*7c478bd9Sstevel@tonic-gate (void) snprintf(diskpath, MAXPATHLEN, "%s/%s:q,raw", 438*7c478bd9Sstevel@tonic-gate DEVFS_PREFIX, disk_list[i]); 439*7c478bd9Sstevel@tonic-gate fd = open(diskpath, O_RDONLY); 440*7c478bd9Sstevel@tonic-gate if (fd < 0) { 441*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "opening %s failed errno %d\n", 442*7c478bd9Sstevel@tonic-gate diskpath, errno); 443*7c478bd9Sstevel@tonic-gate continue; 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate num_read = read(fd, buf, 512); 446*7c478bd9Sstevel@tonic-gate if (num_read != 512) { 447*7c478bd9Sstevel@tonic-gate (void) printf("read only %d bytes from %s\n", num_read, 448*7c478bd9Sstevel@tonic-gate diskpath); 449*7c478bd9Sstevel@tonic-gate continue; 450*7c478bd9Sstevel@tonic-gate } 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate if (memcmp(buf, bd->first_block, 512) == 0) { 453*7c478bd9Sstevel@tonic-gate /* found it */ 454*7c478bd9Sstevel@tonic-gate return (i); 455*7c478bd9Sstevel@tonic-gate } 456*7c478bd9Sstevel@tonic-gate } 457*7c478bd9Sstevel@tonic-gate return (-1); 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate static void 462*7c478bd9Sstevel@tonic-gate cleanup_and_exit(int exitcode) 463*7c478bd9Sstevel@tonic-gate { 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate free_disks(); 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate if (root_node != DI_NODE_NIL) 468*7c478bd9Sstevel@tonic-gate di_fini(root_node); 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate if (root_allnode != DI_NODE_NIL) 471*7c478bd9Sstevel@tonic-gate di_fini(root_allnode); 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate if (prom_hdl != DI_PROM_HANDLE_NIL) 474*7c478bd9Sstevel@tonic-gate di_prom_fini(prom_hdl); 475*7c478bd9Sstevel@tonic-gate exit(exitcode); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate int 481*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 482*7c478bd9Sstevel@tonic-gate { 483*7c478bd9Sstevel@tonic-gate biosdev_data_t *biosdata; 484*7c478bd9Sstevel@tonic-gate int len, i, c, j; 485*7c478bd9Sstevel@tonic-gate int matchedindex = -1; 486*7c478bd9Sstevel@tonic-gate char biospropname[BIOSPROPNAME_TMPL_LEN]; 487*7c478bd9Sstevel@tonic-gate int totalmatches = 0; 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "d")) != -1) { 491*7c478bd9Sstevel@tonic-gate switch (c) { 492*7c478bd9Sstevel@tonic-gate case 'd': 493*7c478bd9Sstevel@tonic-gate debug = 1; 494*7c478bd9Sstevel@tonic-gate break; 495*7c478bd9Sstevel@tonic-gate default: 496*7c478bd9Sstevel@tonic-gate (void) printf("unknown option %c\n", c); 497*7c478bd9Sstevel@tonic-gate exit(1); 498*7c478bd9Sstevel@tonic-gate } 499*7c478bd9Sstevel@tonic-gate } 500*7c478bd9Sstevel@tonic-gate 501*7c478bd9Sstevel@tonic-gate if ((prom_hdl = di_prom_init()) == DI_PROM_HANDLE_NIL) { 502*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "di_prom_init failed\n"); 503*7c478bd9Sstevel@tonic-gate cleanup_and_exit(1); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate 506*7c478bd9Sstevel@tonic-gate if ((root_node = di_init("/", DINFOCACHE)) == DI_NODE_NIL) { 507*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "di_init failed\n"); 508*7c478bd9Sstevel@tonic-gate cleanup_and_exit(1); 509*7c478bd9Sstevel@tonic-gate } 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate if ((root_allnode = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 512*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "di_init failed\n"); 513*7c478bd9Sstevel@tonic-gate cleanup_and_exit(1); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate (void) memset(mapinfo, 0, sizeof (mapinfo)); 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate /* get a list of all disks in the system */ 519*7c478bd9Sstevel@tonic-gate build_disk_list(); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate /* for each property try to match with a disk */ 522*7c478bd9Sstevel@tonic-gate for (i = 0; i < BIOSDEV_NUM; i++) { 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate (void) snprintf((char *)biospropname, BIOSPROPNAME_TMPL_LEN, 525*7c478bd9Sstevel@tonic-gate BIOSPROPNAME_TMPL, i + STARTING_DRVNUM); 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate len = di_prop_lookup_bytes(DDI_DEV_T_ANY, root_allnode, 528*7c478bd9Sstevel@tonic-gate biospropname, (uchar_t **)&biosdata); 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate if (len <= 0) { 531*7c478bd9Sstevel@tonic-gate continue; 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate if (debug) 535*7c478bd9Sstevel@tonic-gate (void) printf("matching %s\n", biospropname); 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate matchedindex = match_edd(biosdata); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate if (matchedindex == -1) { 540*7c478bd9Sstevel@tonic-gate matchedindex = match_first_block(biosdata); 541*7c478bd9Sstevel@tonic-gate if (debug && matchedindex != -1) 542*7c478bd9Sstevel@tonic-gate (void) printf("matched first block\n"); 543*7c478bd9Sstevel@tonic-gate } else if (debug) 544*7c478bd9Sstevel@tonic-gate (void) printf("matched thru edd\n"); 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate if (matchedindex != -1) { 547*7c478bd9Sstevel@tonic-gate mapinfo[i].disklist_index = matchedindex; 548*7c478bd9Sstevel@tonic-gate mapinfo[i].matchcount++; 549*7c478bd9Sstevel@tonic-gate if (debug) 550*7c478bd9Sstevel@tonic-gate (void) printf("0x%x %s\n", i + STARTING_DRVNUM, 551*7c478bd9Sstevel@tonic-gate disk_list[matchedindex]); 552*7c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) { 553*7c478bd9Sstevel@tonic-gate if (mapinfo[j].matchcount > 0 && 554*7c478bd9Sstevel@tonic-gate mapinfo[j].disklist_index == matchedindex) { 555*7c478bd9Sstevel@tonic-gate mapinfo[j].matchcount++; 556*7c478bd9Sstevel@tonic-gate mapinfo[i].matchcount++; 557*7c478bd9Sstevel@tonic-gate } 558*7c478bd9Sstevel@tonic-gate } 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate } else if (debug) 561*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Could not match %s\n", 562*7c478bd9Sstevel@tonic-gate biospropname); 563*7c478bd9Sstevel@tonic-gate } 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate for (i = 0; i < BIOSDEV_NUM; i++) { 566*7c478bd9Sstevel@tonic-gate if (mapinfo[i].matchcount == 1) { 567*7c478bd9Sstevel@tonic-gate (void) printf("0x%x %s\n", i + STARTING_DRVNUM, 568*7c478bd9Sstevel@tonic-gate disk_list[mapinfo[i].disklist_index]); 569*7c478bd9Sstevel@tonic-gate totalmatches++; 570*7c478bd9Sstevel@tonic-gate } else if (debug && mapinfo[i].matchcount > 1) { 571*7c478bd9Sstevel@tonic-gate (void) printf("0x%x %s matchcount %d\n", 572*7c478bd9Sstevel@tonic-gate i + STARTING_DRVNUM, 573*7c478bd9Sstevel@tonic-gate disk_list[mapinfo[i].disklist_index], 574*7c478bd9Sstevel@tonic-gate mapinfo[i].matchcount); 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate if (totalmatches == 0) { 579*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "biosdev: Could not match any!!\n"); 580*7c478bd9Sstevel@tonic-gate cleanup_and_exit(1); 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate 583*7c478bd9Sstevel@tonic-gate cleanup_and_exit(0); 584*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 585*7c478bd9Sstevel@tonic-gate return (0); 586*7c478bd9Sstevel@tonic-gate } 587