~ubuntu-branches/ubuntu/utopic/libhbalinux/utopic

« back to all changes in this revision

Viewing changes to lport.c

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2010-01-26 09:40:50 UTC
  • Revision ID: james.westby@ubuntu.com-20100126094050-owyzl1xibq4ebblh
Tags: upstream-1.0.8
ImportĀ upstreamĀ versionĀ 1.0.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2008, Intel Corporation.
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms and conditions of the GNU Lesser General Public License,
 
6
 * version 2.1, as published by the Free Software Foundation.
 
7
 *
 
8
 * This program is distributed in the hope it will be useful, but WITHOUT
 
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
10
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 
11
 * for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program; if not, write to the Free Software Foundation, Inc.,
 
15
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 
16
 *
 
17
 */
 
18
 
 
19
#include "utils.h"
 
20
#include "api_lib.h"
 
21
#include "adapt_impl.h"
 
22
 
 
23
#ifndef HBA_STATUS_ERROR_ILLEGAL_FCID
 
24
#define HBA_STATUS_ERROR_ILLEGAL_FCID 33        /* defined after HBA-API 2.2 */
 
25
#endif
 
26
#define SEND_CT_TIMEOUT         (3 * 1000)      /* timeout in milliseconds */
 
27
 
 
28
/*
 
29
 * The following are temporary settings until we can find a way to
 
30
 * collect these information.
 
31
 */
 
32
#define HBA_ROM_VERSION         ""
 
33
#define HBA_FW_VERSION          ""
 
34
#define HBA_VENDOR_SPECIFIC_ID  0
 
35
 
 
36
/*
 
37
 * Convert fc_port_type values to ascii string name.
 
38
 * (This table is copied from scsi_transport_fc.c).
 
39
 */
 
40
static struct {
 
41
        enum fc_port_type       value;
 
42
        char                    *name;
 
43
} port_types_table[] = {
 
44
    { FC_PORTTYPE_UNKNOWN,     "Unknown" },
 
45
    { FC_PORTTYPE_OTHER,       "Other" },
 
46
    { FC_PORTTYPE_NOTPRESENT,  "Not Present" },
 
47
    { FC_PORTTYPE_NPORT,       "NPort (fabric via point-to-point)" },
 
48
    { FC_PORTTYPE_NLPORT,      "NLPort (fabric via loop)" },
 
49
    { FC_PORTTYPE_LPORT,       "LPort (private loop)" },
 
50
    { FC_PORTTYPE_PTP,         "Point-To-Point (direct nport connection)" },
 
51
    { FC_PORTTYPE_NPIV,        "NPIV VPORT" },
 
52
};
 
53
fc_enum_name_search(port_type, fc_port_type, port_types_table)
 
54
#define FC_PORTTYPE_MAX_NAMELEN         50
 
55
 
 
56
/*
 
57
 * table of /sys port state strings to HBA-API values.
 
58
 */
 
59
struct sa_nameval port_states_table[] = {
 
60
        { "Not Present",    HBA_PORTSTATE_UNKNOWN },
 
61
        { "Online",         HBA_PORTSTATE_ONLINE },
 
62
        { "Offline",        HBA_PORTSTATE_OFFLINE },
 
63
        { "Blocked",        HBA_PORTSTATE_UNKNOWN },
 
64
        { "Bypassed",       HBA_PORTSTATE_BYPASSED },
 
65
        { "Diagnostics",    HBA_PORTSTATE_DIAGNOSTICS },
 
66
        { "Linkdown",       HBA_PORTSTATE_LINKDOWN },
 
67
        { "Error",          HBA_PORTSTATE_ERROR },
 
68
        { "Loopback",       HBA_PORTSTATE_LOOPBACK },
 
69
        { "Deleted",        HBA_PORTSTATE_UNKNOWN },
 
70
        { NULL, 0 }
 
71
};
 
72
 
 
73
/*
 
74
 * table of /sys port speed strings to HBA-API values.
 
75
 */
 
76
struct sa_nameval port_speeds_table[] = {
 
77
        { "10 Gbit",        HBA_PORTSPEED_10GBIT },
 
78
        { "2 Gbit",         HBA_PORTSPEED_2GBIT },
 
79
        { "1 Gbit",         HBA_PORTSPEED_1GBIT },
 
80
        { "Not Negotiated", HBA_PORTSPEED_NOT_NEGOTIATED },
 
81
        { "Unknown",        HBA_PORTSPEED_UNKNOWN },
 
82
        { NULL, 0 }
 
83
};
 
84
 
 
85
/*
 
86
 * Code for OpenFC-supported adapters.
 
87
 */
 
88
 
 
89
static int
 
90
counting_rports(struct dirent *dp, void *arg)
 
91
{
 
92
        int *count = (int *)arg;
 
93
 
 
94
        if (!strstr(dp->d_name, "rport-"))
 
95
                return HBA_STATUS_OK;
 
96
        (*count)++;
 
97
        return HBA_STATUS_OK;
 
98
}
 
99
 
 
100
static int
 
101
check_ifmac(struct dirent *dp, void *arg)
 
102
{
 
103
        char *address = (char *)arg;
 
104
        char hba_dir[256];
 
105
        char buf[256];
 
106
        int len, i, rc;
 
107
 
 
108
        snprintf(hba_dir, sizeof(hba_dir),
 
109
                 SYSFS_HBA_DIR "/%s", dp->d_name);
 
110
        i = readlink(hba_dir, buf, sizeof(buf) - 1);
 
111
        if (i < 0) {
 
112
                printf("readlink %s failed\n", hba_dir);
 
113
                return 0;
 
114
        }
 
115
        buf[i] = '\0';
 
116
        if (strstr(buf, "/virtual/net/"))
 
117
                return 0;       /* skip virtual devices */
 
118
 
 
119
        memset(buf, 0, sizeof(buf));
 
120
        rc = sa_sys_read_line(hba_dir, "address", buf, sizeof(buf));
 
121
        if (rc)
 
122
                return 0;
 
123
        len = strnlen(buf, sizeof(buf));
 
124
        if (!strncmp(address, buf, len)) {
 
125
                strncpy(address, dp->d_name, len);
 
126
                return 1;
 
127
        }
 
128
        return 0;
 
129
}
 
130
 
 
131
/*
 
132
 * find_phys_if - find the regular network interface name that
 
133
 *                has the same mac address as the VLAN interface.
 
134
 *                This ifname will be used to find the PCI info
 
135
 *                of a VLAN interface.
 
136
 * hba_dir: hba_dir of VLAN interface.
 
137
 * buf: returns ifname of regular network interface.
 
138
 */
 
139
static int
 
140
find_phys_if(char *hba_dir, char *buf, size_t len)
 
141
{
 
142
        int rc;
 
143
 
 
144
        /* Get the mac address of VLAN interface */
 
145
        rc = sa_sys_read_line(hba_dir, "address", buf, len);
 
146
        if (rc)
 
147
                return 1;
 
148
        /*
 
149
         * Search for the regular network interface and
 
150
         * return the interface name in the buf.
 
151
         */
 
152
        sa_dir_read(SYSFS_HBA_DIR, check_ifmac, buf);
 
153
        return 0;
 
154
}
 
155
 
 
156
static int
 
157
sysfs_scan(struct dirent *dp, void *arg)
 
158
{
 
159
        HBA_ADAPTERATTRIBUTES *atp;
 
160
        HBA_PORTATTRIBUTES *pap;
 
161
        HBA_WWN wwnn;
 
162
        struct hba_info hba_info;
 
163
        struct adapter_info *ap;
 
164
        struct port_info *pp;
 
165
        char host_dir[80], hba_dir[80], drv_dir[80];
 
166
        char ifname[20], buf[256];
 
167
        char *driverName;
 
168
        int data[32], rc, i;
 
169
        char *cp;
 
170
        char *saveptr;  /* for strtok_r */
 
171
 
 
172
        memset(&hba_info, 0, sizeof(hba_info));
 
173
 
 
174
        /*
 
175
         * Create a new HBA entry (ap) for the local port
 
176
         * We will create a new HBA entry for each local port.
 
177
         */
 
178
        ap = malloc(sizeof(*ap));
 
179
        if (!ap) {
 
180
                fprintf(stderr, "%s: malloc failed, errno=0x%x\n",
 
181
                        __func__, errno);
 
182
                return HBA_STATUS_ERROR;
 
183
        }
 
184
        memset(ap, 0, sizeof(*ap));
 
185
        ap->ad_kern_index = atoi(dp->d_name + sizeof("host") - 1);
 
186
        ap->ad_port_count = 1;
 
187
 
 
188
        /* atp points to the HBA attributes structure */
 
189
        atp = &ap->ad_attr;
 
190
 
 
191
        /*
 
192
         * Create a new local port entry
 
193
         */
 
194
        pp = malloc(sizeof(*pp));
 
195
        if (pp == NULL) {
 
196
                fprintf(stderr,
 
197
                        "%s: malloc for local port %d failed,"
 
198
                        " errno=0x%x\n", __func__,
 
199
                        ap->ad_port_count - 1, errno);
 
200
                free(ap);
 
201
                return 0;
 
202
        }
 
203
 
 
204
        memset(pp, 0, sizeof(*pp));
 
205
        pp->ap_adapt = ap;
 
206
        pp->ap_index = ap->ad_port_count - 1;
 
207
        pp->ap_kern_hba = atoi(dp->d_name + sizeof("host") - 1);
 
208
 
 
209
        /* pap points to the local port attributes structure */
 
210
        pap = &pp->ap_attr;
 
211
 
 
212
        /* Construct the host directory name from the input name */
 
213
        snprintf(host_dir, sizeof(host_dir),
 
214
                SYSFS_HOST_DIR "/%s", dp->d_name);
 
215
 
 
216
        rc = sa_sys_read_line(host_dir, "symbolic_name", buf, sizeof(buf));
 
217
 
 
218
        /* Get PortSymbolicName */
 
219
        sa_strncpy_safe(pap->PortSymbolicName, sizeof(pap->PortSymbolicName),
 
220
                        buf, sizeof(buf));
 
221
 
 
222
        /* Skip the HBA if it isn't OpenFC */
 
223
        cp = strstr(pap->PortSymbolicName, " over ");
 
224
        if (!cp)
 
225
                goto skip;
 
226
 
 
227
        /*
 
228
         * See if host_dir is a PCI device directory
 
229
         * If not, try it as a net device.
 
230
         */
 
231
        i = readlink(host_dir, buf, sizeof(buf) - 1);
 
232
        if (i < 0)
 
233
                goto skip;
 
234
        buf[i] = '\0';
 
235
 
 
236
        if (strstr(buf, "devices/pci") && !strstr(buf, "/net/")) {
 
237
                snprintf(hba_dir, sizeof(hba_dir), "%s/device/..", host_dir);
 
238
        } else {
 
239
                /* assume a net device */
 
240
                cp += 6;
 
241
                sa_strncpy_safe(ifname, sizeof(ifname), cp, strlen(cp));
 
242
                snprintf(hba_dir, sizeof(hba_dir),
 
243
                         SYSFS_HBA_DIR "/%s", ifname);
 
244
                i = readlink(hba_dir, buf, sizeof(buf) - 1);
 
245
                if (i < 0) {
 
246
                        printf("readlink %s failed\n", hba_dir);
 
247
                        goto skip;
 
248
                }
 
249
                buf[i] = '\0';
 
250
                if (strstr(buf, "/virtual/net/")) {
 
251
                        memset(buf, 0, sizeof(buf));
 
252
                        rc = find_phys_if(hba_dir, buf, sizeof(buf));
 
253
                        if (rc)
 
254
                                goto skip;
 
255
                        snprintf(hba_dir, sizeof(hba_dir),
 
256
                                 SYSFS_HBA_DIR "/%s", buf);
 
257
                        i = readlink(hba_dir, buf, sizeof(buf) - 1);
 
258
                        if (i < 0) {
 
259
                                printf("readlink %s failed\n", hba_dir);
 
260
                                goto skip;
 
261
                        }
 
262
                        buf[i] = '\0';
 
263
                }
 
264
                /*
 
265
                 * A sample link value here is like:
 
266
                 *      ../../devices/pci*.../0000:03:00.0/net/eth2
 
267
                 */
 
268
                cp = strstr(buf, "/net/");
 
269
                if (!cp)
 
270
                        goto skip;
 
271
                *cp = '\0';
 
272
                strcat(hba_dir, "/device");
 
273
        }
 
274
 
 
275
        /*
 
276
         * Assume a PCI symlink value is in buf.
 
277
         * Back up to the last path component that looks like a PCI element.
 
278
         * A sample link value is like:
 
279
         *      ../../devices/pci*.../0000:03:00.0
 
280
         */
 
281
        rc = 0;
 
282
        do {
 
283
                cp = strrchr(buf, '/');
 
284
                if (!cp)
 
285
                        break;
 
286
                rc = sscanf(cp + 1, "%x:%x:%x.%x",
 
287
                            &hba_info.domain, &hba_info.bus,
 
288
                            &hba_info.dev, &hba_info.func);
 
289
                if (rc == 4)
 
290
                        break;
 
291
                *cp = '\0';
 
292
        } while (cp && cp > buf);
 
293
 
 
294
        if (rc != 4)
 
295
                goto skip;
 
296
 
 
297
        /*
 
298
         * Save the host directory and the hba directory
 
299
         * in local port structure
 
300
         */
 
301
        sa_strncpy_safe(pp->host_dir, sizeof(pp->host_dir),
 
302
                        host_dir, sizeof(host_dir));
 
303
 
 
304
        /* Get NodeWWN */
 
305
        rc = sys_read_wwn(pp->host_dir, "node_name", &wwnn);
 
306
        memcpy(&pap->NodeWWN, &wwnn, sizeof(wwnn));
 
307
 
 
308
        /* Get PortWWN */
 
309
        rc = sys_read_wwn(pp->host_dir, "port_name", &pap->PortWWN);
 
310
 
 
311
        /* Get PortFcId */
 
312
        rc = sa_sys_read_u32(pp->host_dir, "port_id", &pap->PortFcId);
 
313
 
 
314
        /* Get PortType */
 
315
        rc = sa_sys_read_line(pp->host_dir, "port_type", buf, sizeof(buf));
 
316
        pap->PortType = get_fc_port_type_value(buf);
 
317
 
 
318
        /* Get PortState */
 
319
        rc = sa_sys_read_line(pp->host_dir, "port_state", buf, sizeof(buf));
 
320
        rc = sa_enum_encode(port_states_table, buf, &pap->PortState);
 
321
 
 
322
        /* Get PortSpeed */
 
323
        rc = sa_sys_read_line(pp->host_dir, "speed", buf, sizeof(buf));
 
324
        rc = sa_enum_encode(port_speeds_table, buf, &pap->PortSpeed);
 
325
 
 
326
        /* Get PortSupportedSpeed */
 
327
        rc = sa_sys_read_line(pp->host_dir, "supported_speed",
 
328
                                buf, sizeof(buf));
 
329
        rc = sa_enum_encode(port_speeds_table, buf, &pap->PortSupportedSpeed);
 
330
 
 
331
        /* Get PortMaxFrameSize */
 
332
        rc = sa_sys_read_line(pp->host_dir, "maxframe_size", buf, sizeof(buf));
 
333
        sscanf(buf, "%d", &pap->PortMaxFrameSize);
 
334
 
 
335
        /* Get PortSupportedFc4Types */
 
336
        rc = sa_sys_read_line(pp->host_dir, "supported_fc4s", buf, sizeof(buf));
 
337
        sscanf(buf, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
 
338
                    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
 
339
                    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
 
340
                    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
 
341
                &data[0], &data[1], &data[2], &data[3], &data[4], &data[5],
 
342
                &data[6], &data[7], &data[8], &data[9], &data[10], &data[11],
 
343
                &data[12], &data[13], &data[14], &data[15], &data[16],
 
344
                &data[17], &data[18], &data[19], &data[20], &data[21],
 
345
                &data[22], &data[23], &data[24], &data[25], &data[26],
 
346
                &data[27], &data[28], &data[29], &data[30], &data[31]);
 
347
        for (i = 0; i < 32; i++)
 
348
                pap->PortSupportedFc4Types.bits[i] = data[i];
 
349
 
 
350
        /* Get PortActiveFc4Types */
 
351
        rc = sa_sys_read_line(pp->host_dir, "active_fc4s", buf, sizeof(buf));
 
352
        sscanf(buf, "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
 
353
                    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
 
354
                    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x "
 
355
                    "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
 
356
                &data[0], &data[1], &data[2], &data[3], &data[4], &data[5],
 
357
                &data[6], &data[7], &data[8], &data[9], &data[10], &data[11],
 
358
                &data[12], &data[13], &data[14], &data[15], &data[16],
 
359
                &data[17], &data[18], &data[19], &data[20], &data[21],
 
360
                &data[22], &data[23], &data[24], &data[25], &data[26],
 
361
                &data[27], &data[28], &data[29], &data[30], &data[31]);
 
362
        for (i = 0; i < 32; i++)
 
363
                pap->PortActiveFc4Types.bits[i] = data[i];
 
364
 
 
365
        /* Get FabricName */
 
366
        rc = sys_read_wwn(pp->host_dir, "fabric_name", &pap->FabricName);
 
367
 
 
368
        /* Get PortSupportedClassofService */
 
369
        rc = sa_sys_read_line(pp->host_dir, "supported_classes",
 
370
                                buf, sizeof(buf));
 
371
        pap->PortSupportedClassofService = *(strstr(buf, "Class") + 6) - '0';
 
372
 
 
373
        /* Get OSDeviceName */
 
374
        sa_strncpy_safe(pap->OSDeviceName, sizeof(pap->OSDeviceName),
 
375
                        dp->d_name, sizeof(dp->d_name));
 
376
 
 
377
        /* Get NumberofDiscoveredPorts */
 
378
        snprintf(buf, sizeof(buf), "%s/device", pp->host_dir);
 
379
        sa_dir_read(buf, counting_rports, &pap->NumberofDiscoveredPorts);
 
380
 
 
381
        /*
 
382
         * Add the local port structure into local port table within
 
383
         * the HBA structure.
 
384
         */
 
385
        if (sa_table_insert(&ap->ad_ports, pp->ap_index, pp) < 0) {
 
386
                fprintf(stderr,
 
387
                        "%s: insert of HBA %d port %d failed\n",
 
388
                        __func__, ap->ad_kern_index, pp->ap_index);
 
389
                goto skip;
 
390
        }
 
391
 
 
392
        /* Create adapter name */
 
393
        snprintf(buf, sizeof(buf), "fcoe:%s", ifname);
 
394
        ap->ad_name = strdup(buf);
 
395
 
 
396
        /* Get vendor_id */
 
397
        rc = sa_sys_read_u32(hba_dir, "vendor", &hba_info.vendor_id);
 
398
 
 
399
        /* Get device_id */
 
400
        rc = sa_sys_read_u32(hba_dir, "device", &hba_info.device_id);
 
401
 
 
402
        /* Get subsystem_vendor_id */
 
403
        rc = sa_sys_read_u32(hba_dir, "subsystem_vendor",
 
404
                                &hba_info.subsystem_vendor_id);
 
405
 
 
406
        /* Get subsystem_device_id */
 
407
        rc = sa_sys_read_u32(hba_dir, "subsystem_device",
 
408
                                &hba_info.subsystem_device_id);
 
409
 
 
410
        /* Get device_class */
 
411
        rc = sa_sys_read_u32(hba_dir, "class", &hba_info.device_class);
 
412
        hba_info.device_class = hba_info.device_class>>8;
 
413
 
 
414
        /*
 
415
         * Get Hardware Information via PCI Library
 
416
         */
 
417
        (void) find_pci_device(&hba_info);
 
418
 
 
419
        /* Get Number of Ports */
 
420
        atp->NumberOfPorts = hba_info.NumberOfPorts;
 
421
 
 
422
        /* Get Manufacturer */
 
423
        sa_strncpy_safe(atp->Manufacturer, sizeof(atp->Manufacturer),
 
424
                        hba_info.Manufacturer, sizeof(hba_info.Manufacturer));
 
425
 
 
426
        /* Get SerialNumber */
 
427
        sa_strncpy_safe(atp->SerialNumber, sizeof(atp->SerialNumber),
 
428
                        hba_info.SerialNumber, sizeof(hba_info.SerialNumber));
 
429
 
 
430
 
 
431
        /* Get ModelDescription */
 
432
        sa_strncpy_safe(atp->ModelDescription, sizeof(atp->ModelDescription),
 
433
                        hba_info.ModelDescription,
 
434
                        sizeof(hba_info.ModelDescription));
 
435
        if (!strncmp(hba_info.ModelDescription, "Unknown",
 
436
                 sizeof(hba_info.ModelDescription))) {
 
437
                snprintf(atp->ModelDescription, sizeof(atp->ModelDescription),
 
438
                        "[%04x:%04x]-[%04x:%04x]-(%04x)",
 
439
                        hba_info.vendor_id, hba_info.device_id,
 
440
                        hba_info.subsystem_vendor_id,
 
441
                        hba_info.subsystem_device_id,
 
442
                        hba_info.device_class);
 
443
                /*
 
444
                 * Get Model
 
445
                 *
 
446
                 * If the device is a newly developed product, and
 
447
                 * the model description is not in pci.ids yet, use
 
448
                 * the model description constructed above as the
 
449
                 * model string.
 
450
                 */
 
451
                sa_strncpy_safe(atp->Model, sizeof(atp->Model),
 
452
                                atp->ModelDescription,
 
453
                                sizeof(atp->ModelDescription));
 
454
        }
 
455
 
 
456
        /*
 
457
         * Get Model
 
458
         *
 
459
         * If the device name has already been added into
 
460
         * the pci.ids file, use the first word of the model
 
461
         * description as the model. If the space after the
 
462
         * first word is not found (new product), use the
 
463
         * model description as the model.
 
464
         */
 
465
        sa_strncpy_safe(buf, sizeof(buf), atp->ModelDescription,
 
466
                        sizeof(atp->ModelDescription));
 
467
        if (strtok_r(buf, " ", &saveptr))
 
468
                sa_strncpy_safe(atp->Model, sizeof(atp->Model),
 
469
                                buf, strnlen(buf, sizeof(buf)));
 
470
        else
 
471
                sa_strncpy_safe(atp->Model, sizeof(atp->Model),
 
472
                                atp->ModelDescription,
 
473
                                sizeof(atp->ModelDescription));
 
474
 
 
475
        /* Get HardwareVersion */
 
476
        sa_strncpy_safe(atp->HardwareVersion, sizeof(atp->HardwareVersion),
 
477
                        hba_info.HardwareVersion,
 
478
                        sizeof(hba_info.HardwareVersion));
 
479
 
 
480
        /* Get OptionROMVersion (TODO) */
 
481
        sa_strncpy_safe(atp->OptionROMVersion, sizeof(atp->OptionROMVersion),
 
482
                        HBA_ROM_VERSION, sizeof(HBA_ROM_VERSION));
 
483
 
 
484
        /* Get FirmwareVersion (TODO) */
 
485
        sa_strncpy_safe(atp->FirmwareVersion, sizeof(atp->FirmwareVersion),
 
486
                        HBA_FW_VERSION, sizeof(HBA_FW_VERSION));
 
487
 
 
488
        /* Get VendorSpecificID (TODO) */
 
489
        atp->VendorSpecificID = HBA_VENDOR_SPECIFIC_ID;
 
490
 
 
491
        /* Get DriverVersion */
 
492
        rc = sa_sys_read_line(hba_dir, SYSFS_MODULE_VER,
 
493
                        atp->DriverVersion, sizeof(atp->DriverVersion));
 
494
 
 
495
        /* Get NodeSymbolicName */
 
496
        sa_strncpy_safe(atp->NodeSymbolicName, sizeof(atp->NodeSymbolicName),
 
497
                        ap->ad_name, sizeof(atp->NodeSymbolicName));
 
498
 
 
499
        /* Get NodeWWN - The NodeWWN is the same as
 
500
         *               the NodeWWN of the local port.
 
501
         */
 
502
        memcpy((char *)&atp->NodeWWN, (char *)&pap->NodeWWN,
 
503
                sizeof(pap->NodeWWN));
 
504
 
 
505
        /* Get DriverName */
 
506
        snprintf(drv_dir, sizeof(drv_dir), "%s" SYSFS_MODULE , hba_dir);
 
507
        i = readlink(drv_dir, buf, sizeof(buf));
 
508
        if (i < 0)
 
509
                i = 0;
 
510
        buf[i] = '\0';
 
511
        if (!strstr(buf, "module")) {
 
512
                /*
 
513
                 * Does not find "module" in the string.
 
514
                 * This should not happen. In this case, set
 
515
                 * the driver name to "Unknown".
 
516
                 */
 
517
                driverName = "Unknown";
 
518
        } else
 
519
                driverName = strstr(buf, "module") + 7;
 
520
        sa_strncpy_safe(atp->DriverName, sizeof(atp->DriverName),
 
521
                        driverName, sizeof(atp->DriverName));
 
522
 
 
523
        /*
 
524
         * Give HBA to library
 
525
         */
 
526
        rc = adapter_create(ap);
 
527
        if (rc != HBA_STATUS_OK) {
 
528
                fprintf(stderr, "%s: adapter_create failed, status=%d\n",
 
529
                        __func__, rc);
 
530
                adapter_destroy(ap);      /* free adapter and ports */
 
531
        }
 
532
 
 
533
        return 0;
 
534
 
 
535
skip:
 
536
        free(pp);
 
537
        free(ap);
 
538
        return 0;
 
539
}
 
540
 
 
541
void
 
542
copy_wwn(HBA_WWN *dest, fc_wwn_t src)
 
543
{
 
544
        dest->wwn[0] = (u_char) (src >> 56);
 
545
        dest->wwn[1] = (u_char) (src >> 48);
 
546
        dest->wwn[2] = (u_char) (src >> 40);
 
547
        dest->wwn[3] = (u_char) (src >> 32);
 
548
        dest->wwn[4] = (u_char) (src >> 24);
 
549
        dest->wwn[5] = (u_char) (src >> 16);
 
550
        dest->wwn[6] = (u_char) (src >> 8);
 
551
        dest->wwn[7] = (u_char) src;
 
552
}
 
553
 
 
554
/* Test for a non-zero WWN */
 
555
int
 
556
is_wwn_nonzero(HBA_WWN *wwn)
 
557
{
 
558
        return (wwn->wwn[0] | wwn->wwn[1] | wwn->wwn[2] | wwn->wwn[3] |
 
559
                wwn->wwn[4] | wwn->wwn[5] | wwn->wwn[6] | wwn->wwn[7]) != 0;
 
560
}
 
561
 
 
562
int
 
563
sys_read_wwn(const char *dir, const char *file, HBA_WWN *wwn)
 
564
{
 
565
        int rc;
 
566
        u_int64_t val;
 
567
 
 
568
        rc = sa_sys_read_u64(dir, file, &val);
 
569
        if (rc == 0)
 
570
                copy_wwn(wwn, val);
 
571
        return rc;
 
572
}
 
573
 
 
574
/* Port Statistics */
 
575
HBA_STATUS
 
576
sysfs_get_port_stats(char *dir, HBA_PORTSTATISTICS *sp)
 
577
{
 
578
        int rc;
 
579
 
 
580
        rc  = sa_sys_read_u64(dir, "seconds_since_last_reset",
 
581
                                (u_int64_t *)&sp->SecondsSinceLastReset);
 
582
        rc |= sa_sys_read_u64(dir, "tx_frames", (u_int64_t *)&sp->TxFrames);
 
583
        rc |= sa_sys_read_u64(dir, "tx_words", (u_int64_t *)&sp->TxWords);
 
584
        rc |= sa_sys_read_u64(dir, "rx_frames", (u_int64_t *)&sp->RxFrames);
 
585
        rc |= sa_sys_read_u64(dir, "rx_words", (u_int64_t *)&sp->RxWords);
 
586
        rc |= sa_sys_read_u64(dir, "lip_count", (u_int64_t *)&sp->LIPCount);
 
587
        rc |= sa_sys_read_u64(dir, "nos_count", (u_int64_t *)&sp->NOSCount);
 
588
        rc |= sa_sys_read_u64(dir, "error_frames",
 
589
                                (u_int64_t *)&sp->ErrorFrames);
 
590
        rc |= sa_sys_read_u64(dir, "dumped_frames",
 
591
                                (u_int64_t *)&sp->DumpedFrames);
 
592
        rc |= sa_sys_read_u64(dir, "link_failure_count",
 
593
                                (u_int64_t *)&sp->LinkFailureCount);
 
594
        rc |= sa_sys_read_u64(dir, "loss_of_sync_count",
 
595
                                (u_int64_t *)&sp->LossOfSyncCount);
 
596
        rc |= sa_sys_read_u64(dir, "loss_of_signal_count",
 
597
                                (u_int64_t *)&sp->LossOfSignalCount);
 
598
        rc |= sa_sys_read_u64(dir, "prim_seq_protocol_err_count",
 
599
                                (u_int64_t *)&sp->PrimitiveSeqProtocolErrCount);
 
600
        rc |= sa_sys_read_u64(dir, "invalid_tx_word_count",
 
601
                                (u_int64_t *)&sp->InvalidTxWordCount);
 
602
        rc |= sa_sys_read_u64(dir, "invalid_crc_count",
 
603
                                (u_int64_t *)&sp->InvalidCRCCount);
 
604
 
 
605
        return rc;
 
606
}
 
607
 
 
608
/* Port FC-4 Statistics */
 
609
HBA_STATUS
 
610
sysfs_get_port_fc4stats(char *dir, HBA_FC4STATISTICS *fc4sp)
 
611
{
 
612
        int rc;
 
613
 
 
614
        rc  = sa_sys_read_u64(dir, "fcp_input_requests",
 
615
                                (u_int64_t *)&fc4sp->InputRequests);
 
616
        rc |= sa_sys_read_u64(dir, "fcp_output_requests",
 
617
                                (u_int64_t *)&fc4sp->OutputRequests);
 
618
        rc |= sa_sys_read_u64(dir, "fcp_control_requests",
 
619
                                (u_int64_t *)&fc4sp->ControlRequests);
 
620
        rc |= sa_sys_read_u64(dir, "fcp_input_megabytes",
 
621
                                (u_int64_t *)&fc4sp->InputMegabytes);
 
622
        rc |= sa_sys_read_u64(dir, "fcp_output_megabytes",
 
623
                                (u_int64_t *)&fc4sp->OutputMegabytes);
 
624
 
 
625
        return rc;
 
626
}
 
627
/*
 
628
 * Open device and read adapter info if available.
 
629
 */
 
630
void
 
631
adapter_init(void)
 
632
{
 
633
        sa_dir_read(SYSFS_HOST_DIR, sysfs_scan, NULL);
 
634
}
 
635
 
 
636
void
 
637
adapter_shutdown(void)
 
638
{
 
639
}
 
640
 
 
641
HBA_STATUS
 
642
get_port_statistics(HBA_HANDLE handle, HBA_UINT32 port, HBA_PORTSTATISTICS *sp)
 
643
{
 
644
        struct port_info *pp;
 
645
        char dir[80];
 
646
        int rc;
 
647
 
 
648
        memset(sp, 0xff, sizeof(*sp)); /* unsupported statistics give -1 */
 
649
        pp = adapter_get_port(handle, port);
 
650
        if (pp == NULL) {
 
651
                fprintf(stderr, "%s: lookup failed. handle 0x%x port 0x%x\n",
 
652
                        __func__, handle, port);
 
653
                return HBA_STATUS_ERROR;
 
654
        }
 
655
 
 
656
        snprintf(dir, sizeof(dir), "%s/statistics", pp->host_dir);
 
657
        rc = sysfs_get_port_stats(dir, sp);
 
658
        if (rc != 0) {
 
659
                fprintf(stderr, "%s: sysfs_get_port_stats() failed,"
 
660
                        " hba index=%d port index=%d, -rc=0x%x\n",
 
661
                        __func__, pp->ap_adapt->ad_kern_index,
 
662
                        pp->ap_index, -rc);
 
663
                return HBA_STATUS_ERROR;
 
664
        }
 
665
        return HBA_STATUS_OK;
 
666
}
 
667
 
 
668
/*
 
669
 * Get FC4 statistics.
 
670
 */
 
671
HBA_STATUS
 
672
get_port_fc4_statistics(HBA_HANDLE handle, HBA_WWN wwn,
 
673
                       HBA_UINT8 fc4_type, HBA_FC4STATISTICS *sp)
 
674
{
 
675
        struct port_info *pp;
 
676
        char dir[80];
 
677
        int count;
 
678
        int rc;
 
679
 
 
680
        memset(sp, 0xff, sizeof(*sp)); /* unsupported statistics give -1 */
 
681
 
 
682
        pp = adapter_get_port_by_wwn(handle, wwn, &count);
 
683
        if (count > 1)
 
684
                return HBA_STATUS_ERROR_AMBIGUOUS_WWN;
 
685
        else if (pp == NULL)
 
686
                return HBA_STATUS_ERROR_ILLEGAL_WWN;
 
687
 
 
688
        snprintf(dir, sizeof(dir), "%s/statistics", pp->host_dir);
 
689
        rc = sysfs_get_port_fc4stats(dir, sp);
 
690
        if (rc != 0) {
 
691
                fprintf(stderr, "%s: sysfs_get_port_fc4stats() failed,"
 
692
                        " hba index=%d port index=%d, -rc=0x%x\n",
 
693
                        __func__, pp->ap_adapt->ad_kern_index,
 
694
                        pp->ap_index, -rc);
 
695
                return HBA_STATUS_ERROR;
 
696
        }
 
697
        return HBA_STATUS_OK;
 
698
}
 
699