1*d6b92ffaSHans Petter Selasky /* 2*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. 3*d6b92ffaSHans Petter Selasky * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved. 4*d6b92ffaSHans Petter Selasky * 5*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two 6*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU 7*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file 8*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the 9*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below: 10*d6b92ffaSHans Petter Selasky * 11*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or 12*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following 13*d6b92ffaSHans Petter Selasky * conditions are met: 14*d6b92ffaSHans Petter Selasky * 15*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above 16*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 17*d6b92ffaSHans Petter Selasky * disclaimer. 18*d6b92ffaSHans Petter Selasky * 19*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above 20*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 21*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials 22*d6b92ffaSHans Petter Selasky * provided with the distribution. 23*d6b92ffaSHans Petter Selasky * 24*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31*d6b92ffaSHans Petter Selasky * SOFTWARE. 32*d6b92ffaSHans Petter Selasky * 33*d6b92ffaSHans Petter Selasky */ 34*d6b92ffaSHans Petter Selasky 35*d6b92ffaSHans Petter Selasky #define _GNU_SOURCE 36*d6b92ffaSHans Petter Selasky 37*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H 38*d6b92ffaSHans Petter Selasky # include <config.h> 39*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */ 40*d6b92ffaSHans Petter Selasky 41*d6b92ffaSHans Petter Selasky #include <inttypes.h> 42*d6b92ffaSHans Petter Selasky #include <string.h> 43*d6b92ffaSHans Petter Selasky #include <stdio.h> 44*d6b92ffaSHans Petter Selasky #include <stdlib.h> 45*d6b92ffaSHans Petter Selasky #include <getopt.h> 46*d6b92ffaSHans Petter Selasky #include <netinet/in.h> 47*d6b92ffaSHans Petter Selasky #include <sys/types.h> 48*d6b92ffaSHans Petter Selasky #include <sys/stat.h> 49*d6b92ffaSHans Petter Selasky #include <fcntl.h> 50*d6b92ffaSHans Petter Selasky #include <errno.h> 51*d6b92ffaSHans Petter Selasky 52*d6b92ffaSHans Petter Selasky #include <infiniband/umad.h> 53*d6b92ffaSHans Petter Selasky 54*d6b92ffaSHans Petter Selasky #include <ibdiag_common.h> 55*d6b92ffaSHans Petter Selasky 56*d6b92ffaSHans Petter Selasky static char *node_type_str[] = { 57*d6b92ffaSHans Petter Selasky "???", 58*d6b92ffaSHans Petter Selasky "CA", 59*d6b92ffaSHans Petter Selasky "Switch", 60*d6b92ffaSHans Petter Selasky "Router", 61*d6b92ffaSHans Petter Selasky "iWARP RNIC" 62*d6b92ffaSHans Petter Selasky }; 63*d6b92ffaSHans Petter Selasky 64*d6b92ffaSHans Petter Selasky static void ca_dump(umad_ca_t * ca) 65*d6b92ffaSHans Petter Selasky { 66*d6b92ffaSHans Petter Selasky if (!ca->node_type) 67*d6b92ffaSHans Petter Selasky return; 68*d6b92ffaSHans Petter Selasky printf("%s '%s'\n", 69*d6b92ffaSHans Petter Selasky ((unsigned)ca->node_type <= 70*d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca->node_type] : "???"), 71*d6b92ffaSHans Petter Selasky ca->ca_name); 72*d6b92ffaSHans Petter Selasky printf("\t%s type: %s\n", 73*d6b92ffaSHans Petter Selasky ((unsigned)ca->node_type <= 74*d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca->node_type] : "???"), 75*d6b92ffaSHans Petter Selasky ca->ca_type); 76*d6b92ffaSHans Petter Selasky printf("\tNumber of ports: %d\n", ca->numports); 77*d6b92ffaSHans Petter Selasky printf("\tFirmware version: %s\n", ca->fw_ver); 78*d6b92ffaSHans Petter Selasky printf("\tHardware version: %s\n", ca->hw_ver); 79*d6b92ffaSHans Petter Selasky printf("\tNode GUID: 0x%016" PRIx64 "\n", ntohll(ca->node_guid)); 80*d6b92ffaSHans Petter Selasky printf("\tSystem image GUID: 0x%016" PRIx64 "\n", 81*d6b92ffaSHans Petter Selasky ntohll(ca->system_guid)); 82*d6b92ffaSHans Petter Selasky } 83*d6b92ffaSHans Petter Selasky 84*d6b92ffaSHans Petter Selasky static char *port_state_str[] = { 85*d6b92ffaSHans Petter Selasky "???", 86*d6b92ffaSHans Petter Selasky "Down", 87*d6b92ffaSHans Petter Selasky "Initializing", 88*d6b92ffaSHans Petter Selasky "Armed", 89*d6b92ffaSHans Petter Selasky "Active" 90*d6b92ffaSHans Petter Selasky }; 91*d6b92ffaSHans Petter Selasky 92*d6b92ffaSHans Petter Selasky static char *port_phy_state_str[] = { 93*d6b92ffaSHans Petter Selasky "No state change", 94*d6b92ffaSHans Petter Selasky "Sleep", 95*d6b92ffaSHans Petter Selasky "Polling", 96*d6b92ffaSHans Petter Selasky "Disabled", 97*d6b92ffaSHans Petter Selasky "PortConfigurationTraining", 98*d6b92ffaSHans Petter Selasky "LinkUp", 99*d6b92ffaSHans Petter Selasky "LinkErrorRecovery", 100*d6b92ffaSHans Petter Selasky "PhyTest" 101*d6b92ffaSHans Petter Selasky }; 102*d6b92ffaSHans Petter Selasky 103*d6b92ffaSHans Petter Selasky static int ret_code(void) 104*d6b92ffaSHans Petter Selasky { 105*d6b92ffaSHans Petter Selasky int e = errno; 106*d6b92ffaSHans Petter Selasky 107*d6b92ffaSHans Petter Selasky if (e > 0) 108*d6b92ffaSHans Petter Selasky return -e; 109*d6b92ffaSHans Petter Selasky return e; 110*d6b92ffaSHans Petter Selasky } 111*d6b92ffaSHans Petter Selasky 112*d6b92ffaSHans Petter Selasky int sys_read_string(const char *dir_name, const char *file_name, char *str, int max_len) 113*d6b92ffaSHans Petter Selasky { 114*d6b92ffaSHans Petter Selasky char path[256], *s; 115*d6b92ffaSHans Petter Selasky size_t len; 116*d6b92ffaSHans Petter Selasky 117*d6b92ffaSHans Petter Selasky snprintf(path, sizeof(path), "%s/%s", dir_name, file_name); 118*d6b92ffaSHans Petter Selasky 119*d6b92ffaSHans Petter Selasky for (s = &path[0]; *s != '\0'; s++) 120*d6b92ffaSHans Petter Selasky if (*s == '/') 121*d6b92ffaSHans Petter Selasky *s = '.'; 122*d6b92ffaSHans Petter Selasky 123*d6b92ffaSHans Petter Selasky len = max_len; 124*d6b92ffaSHans Petter Selasky if (sysctlbyname(&path[1], str, &len, NULL, 0) == -1) 125*d6b92ffaSHans Petter Selasky return ret_code(); 126*d6b92ffaSHans Petter Selasky 127*d6b92ffaSHans Petter Selasky str[(len < max_len) ? len : max_len - 1] = 0; 128*d6b92ffaSHans Petter Selasky 129*d6b92ffaSHans Petter Selasky if ((s = strrchr(str, '\n'))) 130*d6b92ffaSHans Petter Selasky *s = 0; 131*d6b92ffaSHans Petter Selasky 132*d6b92ffaSHans Petter Selasky return 0; 133*d6b92ffaSHans Petter Selasky } 134*d6b92ffaSHans Petter Selasky 135*d6b92ffaSHans Petter Selasky static int is_fdr10(umad_port_t *port) 136*d6b92ffaSHans Petter Selasky { 137*d6b92ffaSHans Petter Selasky char port_dir[256]; 138*d6b92ffaSHans Petter Selasky char rate[32]; 139*d6b92ffaSHans Petter Selasky int len, fdr10 = 0; 140*d6b92ffaSHans Petter Selasky char *p; 141*d6b92ffaSHans Petter Selasky 142*d6b92ffaSHans Petter Selasky len = snprintf(port_dir, sizeof(port_dir), "%s/%s/%s/%d", 143*d6b92ffaSHans Petter Selasky SYS_INFINIBAND, port->ca_name, SYS_CA_PORTS_DIR, 144*d6b92ffaSHans Petter Selasky port->portnum); 145*d6b92ffaSHans Petter Selasky if (len < 0 || len > sizeof(port_dir)) 146*d6b92ffaSHans Petter Selasky goto done; 147*d6b92ffaSHans Petter Selasky 148*d6b92ffaSHans Petter Selasky if (sys_read_string(port_dir, SYS_PORT_RATE, rate, sizeof(rate)) == 0) { 149*d6b92ffaSHans Petter Selasky if ((p = strchr(rate, ')'))) { 150*d6b92ffaSHans Petter Selasky if (!strncasecmp(p - 5, "fdr10", 5)) 151*d6b92ffaSHans Petter Selasky fdr10 = 1; 152*d6b92ffaSHans Petter Selasky } 153*d6b92ffaSHans Petter Selasky } 154*d6b92ffaSHans Petter Selasky 155*d6b92ffaSHans Petter Selasky done: 156*d6b92ffaSHans Petter Selasky return fdr10; 157*d6b92ffaSHans Petter Selasky } 158*d6b92ffaSHans Petter Selasky 159*d6b92ffaSHans Petter Selasky static int port_dump(umad_port_t * port, int alone) 160*d6b92ffaSHans Petter Selasky { 161*d6b92ffaSHans Petter Selasky char *pre = ""; 162*d6b92ffaSHans Petter Selasky char *hdrpre = ""; 163*d6b92ffaSHans Petter Selasky 164*d6b92ffaSHans Petter Selasky if (!port) 165*d6b92ffaSHans Petter Selasky return -1; 166*d6b92ffaSHans Petter Selasky 167*d6b92ffaSHans Petter Selasky if (!alone) { 168*d6b92ffaSHans Petter Selasky pre = " "; 169*d6b92ffaSHans Petter Selasky hdrpre = " "; 170*d6b92ffaSHans Petter Selasky } 171*d6b92ffaSHans Petter Selasky 172*d6b92ffaSHans Petter Selasky printf("%sPort %d:\n", hdrpre, port->portnum); 173*d6b92ffaSHans Petter Selasky printf("%sState: %s\n", pre, 174*d6b92ffaSHans Petter Selasky (unsigned)port->state <= 175*d6b92ffaSHans Petter Selasky 4 ? port_state_str[port->state] : "???"); 176*d6b92ffaSHans Petter Selasky printf("%sPhysical state: %s\n", pre, 177*d6b92ffaSHans Petter Selasky (unsigned)port->phys_state <= 178*d6b92ffaSHans Petter Selasky 7 ? port_phy_state_str[port->phys_state] : "???"); 179*d6b92ffaSHans Petter Selasky if (is_fdr10(port)) 180*d6b92ffaSHans Petter Selasky printf("%sRate: %d (FDR10)\n", pre, port->rate); 181*d6b92ffaSHans Petter Selasky else 182*d6b92ffaSHans Petter Selasky if (port->rate != 2) 183*d6b92ffaSHans Petter Selasky printf("%sRate: %d\n", pre, port->rate); 184*d6b92ffaSHans Petter Selasky else 185*d6b92ffaSHans Petter Selasky printf("%sRate: 2.5\n", pre); 186*d6b92ffaSHans Petter Selasky printf("%sBase lid: %d\n", pre, port->base_lid); 187*d6b92ffaSHans Petter Selasky printf("%sLMC: %d\n", pre, port->lmc); 188*d6b92ffaSHans Petter Selasky printf("%sSM lid: %d\n", pre, port->sm_lid); 189*d6b92ffaSHans Petter Selasky printf("%sCapability mask: 0x%08x\n", pre, ntohl(port->capmask)); 190*d6b92ffaSHans Petter Selasky printf("%sPort GUID: 0x%016" PRIx64 "\n", pre, ntohll(port->port_guid)); 191*d6b92ffaSHans Petter Selasky #ifdef HAVE_UMAD_PORT_LINK_LAYER 192*d6b92ffaSHans Petter Selasky printf("%sLink layer: %s\n", pre, port->link_layer); 193*d6b92ffaSHans Petter Selasky #endif 194*d6b92ffaSHans Petter Selasky return 0; 195*d6b92ffaSHans Petter Selasky } 196*d6b92ffaSHans Petter Selasky 197*d6b92ffaSHans Petter Selasky static int ca_stat(char *ca_name, int portnum, int no_ports) 198*d6b92ffaSHans Petter Selasky { 199*d6b92ffaSHans Petter Selasky umad_ca_t ca; 200*d6b92ffaSHans Petter Selasky int r; 201*d6b92ffaSHans Petter Selasky 202*d6b92ffaSHans Petter Selasky if ((r = umad_get_ca(ca_name, &ca)) < 0) 203*d6b92ffaSHans Petter Selasky return r; 204*d6b92ffaSHans Petter Selasky 205*d6b92ffaSHans Petter Selasky if (!ca.node_type) 206*d6b92ffaSHans Petter Selasky return 0; 207*d6b92ffaSHans Petter Selasky 208*d6b92ffaSHans Petter Selasky if (!no_ports && portnum >= 0) { 209*d6b92ffaSHans Petter Selasky if (portnum > ca.numports || !ca.ports[portnum]) { 210*d6b92ffaSHans Petter Selasky IBWARN("%s: '%s' has no port number %d - max (%d)", 211*d6b92ffaSHans Petter Selasky ((unsigned)ca.node_type <= 212*d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca.node_type] : 213*d6b92ffaSHans Petter Selasky "???"), ca_name, portnum, ca.numports); 214*d6b92ffaSHans Petter Selasky return -1; 215*d6b92ffaSHans Petter Selasky } 216*d6b92ffaSHans Petter Selasky printf("%s: '%s'\n", 217*d6b92ffaSHans Petter Selasky ((unsigned)ca.node_type <= 218*d6b92ffaSHans Petter Selasky IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), 219*d6b92ffaSHans Petter Selasky ca.ca_name); 220*d6b92ffaSHans Petter Selasky port_dump(ca.ports[portnum], 1); 221*d6b92ffaSHans Petter Selasky return 0; 222*d6b92ffaSHans Petter Selasky } 223*d6b92ffaSHans Petter Selasky 224*d6b92ffaSHans Petter Selasky /* print ca header */ 225*d6b92ffaSHans Petter Selasky ca_dump(&ca); 226*d6b92ffaSHans Petter Selasky 227*d6b92ffaSHans Petter Selasky if (no_ports) 228*d6b92ffaSHans Petter Selasky return 0; 229*d6b92ffaSHans Petter Selasky 230*d6b92ffaSHans Petter Selasky for (portnum = 0; portnum <= ca.numports; portnum++) 231*d6b92ffaSHans Petter Selasky port_dump(ca.ports[portnum], 0); 232*d6b92ffaSHans Petter Selasky 233*d6b92ffaSHans Petter Selasky return 0; 234*d6b92ffaSHans Petter Selasky } 235*d6b92ffaSHans Petter Selasky 236*d6b92ffaSHans Petter Selasky static int ports_list(char names[][UMAD_CA_NAME_LEN], int n) 237*d6b92ffaSHans Petter Selasky { 238*d6b92ffaSHans Petter Selasky uint64_t guids[64]; 239*d6b92ffaSHans Petter Selasky int found, ports, i; 240*d6b92ffaSHans Petter Selasky 241*d6b92ffaSHans Petter Selasky for (i = 0, found = 0; i < n && found < 64; i++) { 242*d6b92ffaSHans Petter Selasky if ((ports = 243*d6b92ffaSHans Petter Selasky umad_get_ca_portguids(names[i], guids + found, 244*d6b92ffaSHans Petter Selasky 64 - found)) < 0) 245*d6b92ffaSHans Petter Selasky return -1; 246*d6b92ffaSHans Petter Selasky found += ports; 247*d6b92ffaSHans Petter Selasky } 248*d6b92ffaSHans Petter Selasky 249*d6b92ffaSHans Petter Selasky for (i = 0; i < found; i++) 250*d6b92ffaSHans Petter Selasky if (guids[i]) 251*d6b92ffaSHans Petter Selasky printf("0x%016" PRIx64 "\n", ntohll(guids[i])); 252*d6b92ffaSHans Petter Selasky return found; 253*d6b92ffaSHans Petter Selasky } 254*d6b92ffaSHans Petter Selasky 255*d6b92ffaSHans Petter Selasky static int list_only, short_format, list_ports; 256*d6b92ffaSHans Petter Selasky 257*d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg) 258*d6b92ffaSHans Petter Selasky { 259*d6b92ffaSHans Petter Selasky switch (ch) { 260*d6b92ffaSHans Petter Selasky case 'l': 261*d6b92ffaSHans Petter Selasky list_only++; 262*d6b92ffaSHans Petter Selasky break; 263*d6b92ffaSHans Petter Selasky case 's': 264*d6b92ffaSHans Petter Selasky short_format++; 265*d6b92ffaSHans Petter Selasky break; 266*d6b92ffaSHans Petter Selasky case 'p': 267*d6b92ffaSHans Petter Selasky list_ports++; 268*d6b92ffaSHans Petter Selasky break; 269*d6b92ffaSHans Petter Selasky default: 270*d6b92ffaSHans Petter Selasky return -1; 271*d6b92ffaSHans Petter Selasky } 272*d6b92ffaSHans Petter Selasky return 0; 273*d6b92ffaSHans Petter Selasky } 274*d6b92ffaSHans Petter Selasky 275*d6b92ffaSHans Petter Selasky int main(int argc, char *argv[]) 276*d6b92ffaSHans Petter Selasky { 277*d6b92ffaSHans Petter Selasky char names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN]; 278*d6b92ffaSHans Petter Selasky int dev_port = -1; 279*d6b92ffaSHans Petter Selasky int n, i; 280*d6b92ffaSHans Petter Selasky 281*d6b92ffaSHans Petter Selasky const struct ibdiag_opt opts[] = { 282*d6b92ffaSHans Petter Selasky {"list_of_cas", 'l', 0, NULL, "list all IB devices"}, 283*d6b92ffaSHans Petter Selasky {"short", 's', 0, NULL, "short output"}, 284*d6b92ffaSHans Petter Selasky {"port_list", 'p', 0, NULL, "show port list"}, 285*d6b92ffaSHans Petter Selasky {0} 286*d6b92ffaSHans Petter Selasky }; 287*d6b92ffaSHans Petter Selasky char usage_args[] = "<ca_name> [portnum]"; 288*d6b92ffaSHans Petter Selasky const char *usage_examples[] = { 289*d6b92ffaSHans Petter Selasky "-l # list all IB devices", 290*d6b92ffaSHans Petter Selasky "mthca0 2 # stat port 2 of 'mthca0'", 291*d6b92ffaSHans Petter Selasky NULL 292*d6b92ffaSHans Petter Selasky }; 293*d6b92ffaSHans Petter Selasky 294*d6b92ffaSHans Petter Selasky ibdiag_process_opts(argc, argv, NULL, "CDeGKLPsty", opts, process_opt, 295*d6b92ffaSHans Petter Selasky usage_args, usage_examples); 296*d6b92ffaSHans Petter Selasky 297*d6b92ffaSHans Petter Selasky argc -= optind; 298*d6b92ffaSHans Petter Selasky argv += optind; 299*d6b92ffaSHans Petter Selasky 300*d6b92ffaSHans Petter Selasky if (argc > 1) 301*d6b92ffaSHans Petter Selasky dev_port = strtol(argv[1], 0, 0); 302*d6b92ffaSHans Petter Selasky 303*d6b92ffaSHans Petter Selasky if (umad_init() < 0) 304*d6b92ffaSHans Petter Selasky IBPANIC("can't init UMAD library"); 305*d6b92ffaSHans Petter Selasky 306*d6b92ffaSHans Petter Selasky if ((n = umad_get_cas_names(names, UMAD_MAX_DEVICES)) < 0) 307*d6b92ffaSHans Petter Selasky IBPANIC("can't list IB device names"); 308*d6b92ffaSHans Petter Selasky 309*d6b92ffaSHans Petter Selasky if (argc) { 310*d6b92ffaSHans Petter Selasky for (i = 0; i < n; i++) 311*d6b92ffaSHans Petter Selasky if (!strncmp(names[i], argv[0], sizeof names[i])) 312*d6b92ffaSHans Petter Selasky break; 313*d6b92ffaSHans Petter Selasky if (i >= n) 314*d6b92ffaSHans Petter Selasky IBPANIC("'%s' IB device can't be found", argv[0]); 315*d6b92ffaSHans Petter Selasky 316*d6b92ffaSHans Petter Selasky strncpy(names[0], argv[0], sizeof(names[0])-1); 317*d6b92ffaSHans Petter Selasky names[0][sizeof(names[0])-1] = '\0'; 318*d6b92ffaSHans Petter Selasky n = 1; 319*d6b92ffaSHans Petter Selasky } 320*d6b92ffaSHans Petter Selasky 321*d6b92ffaSHans Petter Selasky if (list_ports) { 322*d6b92ffaSHans Petter Selasky if (ports_list(names, n) < 0) 323*d6b92ffaSHans Petter Selasky IBPANIC("can't list ports"); 324*d6b92ffaSHans Petter Selasky return 0; 325*d6b92ffaSHans Petter Selasky } 326*d6b92ffaSHans Petter Selasky 327*d6b92ffaSHans Petter Selasky for (i = 0; i < n; i++) { 328*d6b92ffaSHans Petter Selasky if (list_only) 329*d6b92ffaSHans Petter Selasky printf("%s\n", names[i]); 330*d6b92ffaSHans Petter Selasky else if (ca_stat(names[i], dev_port, short_format) < 0) 331*d6b92ffaSHans Petter Selasky IBPANIC("stat of IB device '%s' failed", names[i]); 332*d6b92ffaSHans Petter Selasky } 333*d6b92ffaSHans Petter Selasky 334*d6b92ffaSHans Petter Selasky return 0; 335*d6b92ffaSHans Petter Selasky } 336