Training courses

Kernel and Embedded Linux

Bootlin training courses

Embedded Linux, kernel,
Yocto Project, Buildroot, real-time,
graphics, boot time, debugging...

Bootlin logo

Elixir Cross Referencer

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
/*-
 * Copyright (c) 2017 Broadcom. All rights reserved.
 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * $FreeBSD$
 */

/**
 * @file
 * Defines the Hardware Abstraction Layer (HW) interface functions.
 */

#ifndef _OCS_HW_H
#define _OCS_HW_H

#include "sli4.h"
#include "ocs_hw.h"
#include "ocs_stats.h"
#include "ocs_utils.h"

typedef struct ocs_hw_io_s ocs_hw_io_t;

#if defined(OCS_INCLUDE_DEBUG)
#else
#define ocs_queue_history_wq(...)
#define ocs_queue_history_cqe(...)
#define ocs_queue_history_init(...)
#define ocs_queue_history_free(...)
#endif

/**
 * @brief HW queue forward declarations
 */
typedef struct hw_eq_s hw_eq_t;
typedef struct hw_cq_s hw_cq_t;
typedef struct hw_mq_s hw_mq_t;
typedef struct hw_wq_s hw_wq_t;
typedef struct hw_rq_s hw_rq_t;
typedef struct hw_rq_grp_s hw_rq_grp_t;

/* HW asserts/verify
 *
 */

extern void _ocs_hw_assert(const char *cond, const char *filename, int linenum);
extern void _ocs_hw_verify(const char *cond, const char *filename, int linenum);

#if defined(HW_NDEBUG)
#define ocs_hw_assert(cond)
#define ocs_hw_verify(cond, ...)
#else
#define ocs_hw_assert(cond) \
	do { \
		if ((!(cond))) { \
			_ocs_hw_assert(#cond, __FILE__, __LINE__); \
		} \
	} while (0)

#define ocs_hw_verify(cond, ...) \
	do { \
		if ((!(cond))) { \
			_ocs_hw_verify(#cond, __FILE__, __LINE__); \
			return __VA_ARGS__; \
		} \
	} while (0)
#endif
#define ocs_hw_verify_arg(cond)	ocs_hw_verify(cond, OCS_HW_RTN_INVALID_ARG)

/*
 * HW completion loop control parameters.
 *
 * The HW completion loop must terminate periodically to keep the OS happy.  The
 * loop terminates when a predefined time has elapsed, but to keep the overhead of
 * computing time down, the time is only checked after a number of loop iterations
 * has completed.
 *
 * OCS_HW_TIMECHECK_ITERATIONS		number of loop iterations between time checks
 *
 */

#define OCS_HW_TIMECHECK_ITERATIONS	100
#define OCS_HW_MAX_NUM_MQ 1
#define OCS_HW_MAX_NUM_RQ 32
#define OCS_HW_MAX_NUM_EQ 16
#define OCS_HW_MAX_NUM_WQ 32

#define OCE_HW_MAX_NUM_MRQ_PAIRS 16

#define OCS_HW_MAX_WQ_CLASS	4
#define OCS_HW_MAX_WQ_CPU	128

/*
 * A CQ will be assinged to each WQ (CQ must have 2X entries of the WQ for abort
 * processing), plus a separate one for each RQ PAIR and one for MQ
 */
#define OCS_HW_MAX_NUM_CQ ((OCS_HW_MAX_NUM_WQ*2) + 1 + (OCE_HW_MAX_NUM_MRQ_PAIRS * 2))

/*
 * Q hash - size is the maximum of all the queue sizes, rounded up to the next
 * power of 2
 */
#define OCS_HW_Q_HASH_SIZE	B32_NEXT_POWER_OF_2(OCS_MAX(OCS_HW_MAX_NUM_MQ, OCS_MAX(OCS_HW_MAX_NUM_RQ, \
				OCS_MAX(OCS_HW_MAX_NUM_EQ, OCS_MAX(OCS_HW_MAX_NUM_WQ, \
				OCS_HW_MAX_NUM_CQ)))))

#define OCS_HW_RQ_HEADER_SIZE	128
#define OCS_HW_RQ_HEADER_INDEX	0

/**
 * @brief Options for ocs_hw_command().
 */
enum {
	OCS_CMD_POLL,	/**< command executes synchronously and busy-waits for completion */
	OCS_CMD_NOWAIT,	/**< command executes asynchronously. Uses callback */
};

typedef enum {
	OCS_HW_RTN_SUCCESS = 0,
	OCS_HW_RTN_SUCCESS_SYNC = 1,
	OCS_HW_RTN_ERROR = -1,
	OCS_HW_RTN_NO_RESOURCES = -2,
	OCS_HW_RTN_NO_MEMORY = -3,
	OCS_HW_RTN_IO_NOT_ACTIVE = -4,
	OCS_HW_RTN_IO_ABORT_IN_PROGRESS = -5,
	OCS_HW_RTN_IO_PORT_OWNED_ALREADY_ABORTED = -6,
	OCS_HW_RTN_INVALID_ARG = -7,
} ocs_hw_rtn_e;
#define OCS_HW_RTN_IS_ERROR(e)	((e) < 0)

typedef enum {
	OCS_HW_RESET_FUNCTION,
	OCS_HW_RESET_FIRMWARE,
	OCS_HW_RESET_MAX
} ocs_hw_reset_e;

typedef enum {
	OCS_HW_N_IO,
	OCS_HW_N_SGL,
	OCS_HW_MAX_IO,
	OCS_HW_MAX_SGE,
	OCS_HW_MAX_SGL,
	OCS_HW_MAX_NODES,
	OCS_HW_MAX_RQ_ENTRIES,
	OCS_HW_TOPOLOGY,	/**< auto, nport, loop */
	OCS_HW_WWN_NODE,
	OCS_HW_WWN_PORT,
	OCS_HW_FW_REV,
	OCS_HW_FW_REV2,
	OCS_HW_IPL,
	OCS_HW_VPD,
	OCS_HW_VPD_LEN,
	OCS_HW_MODE,		/**< initiator, target, both */
	OCS_HW_LINK_SPEED,
	OCS_HW_IF_TYPE,
	OCS_HW_SLI_REV,
	OCS_HW_SLI_FAMILY,
	OCS_HW_RQ_PROCESS_LIMIT,
	OCS_HW_RQ_DEFAULT_BUFFER_SIZE,
	OCS_HW_AUTO_XFER_RDY_CAPABLE,
	OCS_HW_AUTO_XFER_RDY_XRI_CNT,
	OCS_HW_AUTO_XFER_RDY_SIZE,
	OCS_HW_AUTO_XFER_RDY_BLK_SIZE,
	OCS_HW_AUTO_XFER_RDY_T10_ENABLE,
	OCS_HW_AUTO_XFER_RDY_P_TYPE,
	OCS_HW_AUTO_XFER_RDY_REF_TAG_IS_LBA,
	OCS_HW_AUTO_XFER_RDY_APP_TAG_VALID,
	OCS_HW_AUTO_XFER_RDY_APP_TAG_VALUE,
	OCS_HW_DIF_CAPABLE,
	OCS_HW_DIF_SEED,
	OCS_HW_DIF_MODE,
	OCS_HW_DIF_MULTI_SEPARATE,
	OCS_HW_DUMP_MAX_SIZE,
	OCS_HW_DUMP_READY,
	OCS_HW_DUMP_PRESENT,
	OCS_HW_RESET_REQUIRED,
	OCS_HW_FW_ERROR,
	OCS_HW_FW_READY,
	OCS_HW_HIGH_LOGIN_MODE,
	OCS_HW_PREREGISTER_SGL,
	OCS_HW_HW_REV1,
	OCS_HW_HW_REV2,
	OCS_HW_HW_REV3,
	OCS_HW_LINKCFG,
	OCS_HW_ETH_LICENSE,
	OCS_HW_LINK_MODULE_TYPE,
	OCS_HW_NUM_CHUTES,
	OCS_HW_WAR_VERSION,
	OCS_HW_DISABLE_AR_TGT_DIF,
	OCS_HW_EMULATE_I_ONLY_AAB, /**< emulate IAAB=0 for initiator-commands only */
	OCS_HW_EMULATE_TARGET_WQE_TIMEOUT, /**< enable driver timeouts for target WQEs */
	OCS_HW_LINK_CONFIG_SPEED,
	OCS_HW_CONFIG_TOPOLOGY,
	OCS_HW_BOUNCE,
	OCS_HW_PORTNUM,
	OCS_HW_BIOS_VERSION_STRING,
	OCS_HW_RQ_SELECT_POLICY,
	OCS_HW_SGL_CHAINING_CAPABLE,
	OCS_HW_SGL_CHAINING_ALLOWED,
	OCS_HW_SGL_CHAINING_HOST_ALLOCATED,
	OCS_HW_SEND_FRAME_CAPABLE,
	OCS_HW_RQ_SELECTION_POLICY,
	OCS_HW_RR_QUANTA,
	OCS_HW_FILTER_DEF,
	OCS_HW_MAX_VPORTS,
	OCS_ESOC,
	OCS_HW_FW_TIMED_OUT,
} ocs_hw_property_e;

enum {
	OCS_HW_TOPOLOGY_AUTO,
	OCS_HW_TOPOLOGY_NPORT,
	OCS_HW_TOPOLOGY_LOOP,
	OCS_HW_TOPOLOGY_NONE,
	OCS_HW_TOPOLOGY_MAX
};

enum {
	OCS_HW_MODE_INITIATOR,
	OCS_HW_MODE_TARGET,
	OCS_HW_MODE_BOTH,
	OCS_HW_MODE_MAX
};

/**
 * @brief Port protocols
 */

typedef enum {
	OCS_HW_PORT_PROTOCOL_ISCSI,
	OCS_HW_PORT_PROTOCOL_FCOE,
	OCS_HW_PORT_PROTOCOL_FC,
	OCS_HW_PORT_PROTOCOL_OTHER,
} ocs_hw_port_protocol_e;

#define OCS_HW_MAX_PROFILES	40
/**
 * @brief A Profile Descriptor
 */
typedef struct {
	uint32_t	profile_index;
	uint32_t	profile_id;
	char		profile_description[512];
} ocs_hw_profile_descriptor_t;

/**
 * @brief A Profile List
 */
typedef struct {
	uint32_t			num_descriptors;
	ocs_hw_profile_descriptor_t	descriptors[OCS_HW_MAX_PROFILES];
} ocs_hw_profile_list_t;

/**
 * @brief Defines DIF operation modes
 */
enum {
	OCS_HW_DIF_MODE_INLINE,
	OCS_HW_DIF_MODE_SEPARATE,
};

/**
 * @brief Defines the type of RQ buffer
 */
typedef enum {
	OCS_HW_RQ_BUFFER_TYPE_HDR,
	OCS_HW_RQ_BUFFER_TYPE_PAYLOAD,
	OCS_HW_RQ_BUFFER_TYPE_MAX,
} ocs_hw_rq_buffer_type_e;

/**
 * @brief Defines a wrapper for the RQ payload buffers so that we can place it
 *        back on the proper queue.
 */
typedef struct {
	uint16_t rqindex;
	ocs_dma_t dma;
} ocs_hw_rq_buffer_t;

/**
 * @brief T10 DIF operations.
 */
typedef enum {
	OCS_HW_DIF_OPER_DISABLED,
	OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC,
	OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF,
	OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CHKSUM,
	OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_NODIF,
	OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC,
	OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CHKSUM,
	OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CHKSUM,
	OCS_HW_SGE_DIF_OP_IN_CHKSUM_OUT_CRC,
	OCS_HW_SGE_DIF_OP_IN_RAW_OUT_RAW,
} ocs_hw_dif_oper_e;

#define OCS_HW_DIF_OPER_PASS_THRU	OCS_HW_SGE_DIF_OP_IN_CRC_OUT_CRC
#define OCS_HW_DIF_OPER_STRIP		OCS_HW_SGE_DIF_OP_IN_CRC_OUT_NODIF
#define OCS_HW_DIF_OPER_INSERT		OCS_HW_SGE_DIF_OP_IN_NODIF_OUT_CRC

/**
 * @brief T10 DIF block sizes.
 */
typedef enum {
	OCS_HW_DIF_BK_SIZE_512,
	OCS_HW_DIF_BK_SIZE_1024,
	OCS_HW_DIF_BK_SIZE_2048,
	OCS_HW_DIF_BK_SIZE_4096,
	OCS_HW_DIF_BK_SIZE_520,
	OCS_HW_DIF_BK_SIZE_4104,
	OCS_HW_DIF_BK_SIZE_NA = 0
} ocs_hw_dif_blk_size_e;

/**
 * @brief Link configurations.
 */
typedef enum {
	OCS_HW_LINKCFG_4X10G = 0,
	OCS_HW_LINKCFG_1X40G,
	OCS_HW_LINKCFG_2X16G,
	OCS_HW_LINKCFG_4X8G,
	OCS_HW_LINKCFG_4X1G,
	OCS_HW_LINKCFG_2X10G,
	OCS_HW_LINKCFG_2X10G_2X8G,

	/* must be last */
	OCS_HW_LINKCFG_NA,
} ocs_hw_linkcfg_e;

/**
 * @brief link module types
 *
 * (note: these just happen to match SLI4 values)
 */

enum {
	OCS_HW_LINK_MODULE_TYPE_1GB = 0x0004,
	OCS_HW_LINK_MODULE_TYPE_2GB = 0x0008,
	OCS_HW_LINK_MODULE_TYPE_4GB = 0x0040,
	OCS_HW_LINK_MODULE_TYPE_8GB = 0x0080,
	OCS_HW_LINK_MODULE_TYPE_10GB = 0x0100,
	OCS_HW_LINK_MODULE_TYPE_16GB = 0x0200,
	OCS_HW_LINK_MODULE_TYPE_32GB = 0x0400,
};

/**
 * @brief T10 DIF information passed to the transport.
 */
typedef struct ocs_hw_dif_info_s {
	ocs_hw_dif_oper_e dif_oper;
	ocs_hw_dif_blk_size_e blk_size;
	uint32_t ref_tag_cmp;
	uint32_t ref_tag_repl;
	uint32_t app_tag_cmp:16,
		app_tag_repl:16;
	uint32_t check_ref_tag:1,
		check_app_tag:1,
		check_guard:1,
		auto_incr_ref_tag:1,
		repl_app_tag:1,
		repl_ref_tag:1,
		dif:2,
		dif_separate:1,

		/* If the APP TAG is 0xFFFF, disable checking the REF TAG and CRC fields */
		disable_app_ffff:1,

		/* if the APP TAG is 0xFFFF and REF TAG is 0xFFFF_FFFF, disable checking the received CRC field. */
		disable_app_ref_ffff:1,

		:21;
	uint16_t dif_seed;
} ocs_hw_dif_info_t;
typedef enum {
	OCS_HW_ELS_REQ,	/**< ELS request */
	OCS_HW_ELS_RSP,	/**< ELS response */
	OCS_HW_ELS_RSP_SID,	/**< ELS response, override the S_ID */
	OCS_HW_FC_CT,		/**< FC Common Transport */
	OCS_HW_FC_CT_RSP,	/**< FC Common Transport Response */
	OCS_HW_BLS_ACC,	/**< BLS accept (BA_ACC) */
	OCS_HW_BLS_ACC_SID,	/**< BLS accept (BA_ACC), override the S_ID */
	OCS_HW_BLS_RJT,	/**< BLS reject (BA_RJT) */
	OCS_HW_BCAST,		/**< Class 3 broadcast sequence */
	OCS_HW_IO_TARGET_READ,
	OCS_HW_IO_TARGET_WRITE,
	OCS_HW_IO_TARGET_RSP,
	OCS_HW_IO_INITIATOR_READ,
	OCS_HW_IO_INITIATOR_WRITE,
	OCS_HW_IO_INITIATOR_NODATA,
	OCS_HW_IO_DNRX_REQUEUE,
	OCS_HW_IO_MAX,
} ocs_hw_io_type_e;

typedef enum {
	OCS_HW_IO_STATE_FREE,
	OCS_HW_IO_STATE_INUSE,
	OCS_HW_IO_STATE_WAIT_FREE,
	OCS_HW_IO_STATE_WAIT_SEC_HIO,
} ocs_hw_io_state_e;

/* Descriptive strings for the HW IO request types (note: these must always
 * match up with the ocs_hw_io_type_e declaration) */
#define OCS_HW_IO_TYPE_STRINGS \
	"ELS request", \
	"ELS response", \
	"ELS response(set SID)", \
	"FC CT request", \
	"BLS accept", \
	"BLS accept(set SID)", \
	"BLS reject", \
	"target read", \
	"target write", \
	"target response", \
	"initiator read", \
	"initiator write", \
	"initiator nodata",

/**
 * @brief HW command context.
 *
 * Stores the state for the asynchronous commands sent to the hardware.
 */
typedef struct ocs_command_ctx_s {
	ocs_list_t	link;
	/**< Callback function */
	int32_t		(*cb)(struct ocs_hw_s *, int32_t, uint8_t *, void *);
	void		*arg;	/**< Argument for callback */
	uint8_t		*buf;	/**< buffer holding command / results */
	void		*ctx;	/**< upper layer context */
} ocs_command_ctx_t;

typedef struct ocs_hw_sgl_s {
	uintptr_t	addr;
	size_t		len;
} ocs_hw_sgl_t;

/**
 * @brief HW callback type
 *
 * Typedef for HW "done" callback.
 */
typedef int32_t	(*ocs_hw_done_t)(struct ocs_hw_io_s *, ocs_remote_node_t *, uint32_t len, int32_t status, uint32_t ext, void *ul_arg);

typedef union ocs_hw_io_param_u {
	struct {
		uint16_t ox_id;
		uint16_t rx_id;
		uint8_t  payload[12];	/**< big enough for ABTS BA_ACC */
	} bls;
	struct {
		uint32_t s_id;
		uint16_t ox_id;
		uint16_t rx_id;
		uint8_t  payload[12];	/**< big enough for ABTS BA_ACC */
	} bls_sid;
	struct {
		uint8_t	r_ctl;
		uint8_t	type;
		uint8_t	df_ctl;
		uint8_t timeout;
	} bcast;
	struct {
		uint16_t ox_id;
		uint8_t timeout;
	} els;
	struct {
		uint32_t s_id;
		uint16_t ox_id;
		uint8_t timeout;
	} els_sid;
	struct {
		uint8_t	r_ctl;
		uint8_t	type;
		uint8_t	df_ctl;
		uint8_t timeout;
	} fc_ct;
	struct {
		uint8_t	r_ctl;
		uint8_t	type;
		uint8_t	df_ctl;
		uint8_t timeout;
		uint16_t ox_id;
	} fc_ct_rsp;
	struct {
		uint32_t offset;
		uint16_t ox_id;
		uint16_t flags;
		uint8_t	cs_ctl;
		ocs_hw_dif_oper_e dif_oper;
		ocs_hw_dif_blk_size_e blk_size;
		uint8_t	timeout;
		uint32_t app_id;
	} fcp_tgt;
	struct {
		ocs_dma_t	*cmnd;
		ocs_dma_t	*rsp;
		ocs_hw_dif_oper_e dif_oper;
		ocs_hw_dif_blk_size_e blk_size;
		uint32_t	cmnd_size;
		uint16_t	flags;
		uint8_t		timeout;
		uint32_t	first_burst;
	} fcp_ini;
} ocs_hw_io_param_t;

/**
 * @brief WQ steering mode
 */
typedef enum {
	OCS_HW_WQ_STEERING_CLASS,
	OCS_HW_WQ_STEERING_REQUEST,
	OCS_HW_WQ_STEERING_CPU,
} ocs_hw_wq_steering_e;

/**
 * @brief HW wqe object
 */
typedef struct {
	uint32_t	abort_wqe_submit_needed:1,	/**< set if abort wqe needs to be submitted */
			send_abts:1,			/**< set to 1 to have hardware to automatically send ABTS */
			auto_xfer_rdy_dnrx:1,		/**< TRUE if DNRX was set on this IO */
			:29;
	uint32_t	id;
	uint32_t	abort_reqtag;
	ocs_list_link_t link;
	uint8_t 	*wqebuf;			/**< work queue entry buffer */
} ocs_hw_wqe_t;

/**
 * @brief HW IO object.
 *
 * Stores the per-IO information necessary for both the lower (SLI) and upper
 * layers (ocs).
 */
struct ocs_hw_io_s {
	/* Owned by HW */
	ocs_list_link_t	link;		/**< used for busy, wait_free, free lists */
	ocs_list_link_t	wqe_link;	/**< used for timed_wqe list */
	ocs_list_link_t	dnrx_link;	/**< used for io posted dnrx list */
	ocs_hw_io_state_e state;	/**< state of IO: free, busy, wait_free */
	ocs_hw_wqe_t	wqe;		/**< Work queue object, with link for pending */
	ocs_lock_t	axr_lock;	/**< Lock to synchronize TRSP and AXT Data/Cmd Cqes */
	ocs_hw_t	*hw;		/**< pointer back to hardware context */
	ocs_remote_node_t	*rnode;
	struct ocs_hw_auto_xfer_rdy_buffer_s *axr_buf;
	ocs_dma_t	xfer_rdy;
	uint16_t	type;
	uint32_t	port_owned_abort_count; /**< IO abort count */
	hw_wq_t	*wq;		/**< WQ assigned to the exchange */
	uint32_t	xbusy;		/**< Exchange is active in FW */
	ocs_hw_done_t  done;		/**< Function called on IO completion */
	void		*arg;		/**< argument passed to "IO done" callback */
	ocs_hw_done_t  abort_done;	/**< Function called on abort completion */
	void		*abort_arg;	/**< argument passed to "abort done" callback */
	ocs_ref_t	ref;		/**< refcount object */
	size_t		length;		/**< needed for bug O127585: length of IO */
	uint8_t		tgt_wqe_timeout; /**< timeout value for target WQEs */
	uint64_t	submit_ticks;	/**< timestamp when current WQE was submitted */

	uint32_t	status_saved:1, /**< if TRUE, latched status should be returned */
			abort_in_progress:1, /**< if TRUE, abort is in progress */
			quarantine:1,	/**< set if IO to be quarantined */
			quarantine_first_phase:1,	/**< set if first phase of IO */
			is_port_owned:1,	/**< set if POST_XRI was used to send XRI to th chip */
			auto_xfer_rdy_dnrx:1,	/**< TRUE if DNRX was set on this IO */
			:26;
	uint32_t	saved_status;	/**< latched status */
	uint32_t	saved_len;	/**< latched length */
	uint32_t	saved_ext;	/**< latched extended status */

	hw_eq_t	*eq;		/**< EQ that this HIO came up on */
	ocs_hw_wq_steering_e	wq_steering;	/**< WQ steering mode request */
	uint8_t		wq_class;	/**< WQ class if steering mode is Class */

	/* Owned by SLI layer */
	uint16_t	reqtag;		/**< request tag for this HW IO */
	uint32_t	abort_reqtag;	/**< request tag for an abort of this HW IO (note: this is a 32 bit value
					     to allow us to use UINT32_MAX as an uninitialized value) */
	uint32_t	indicator;	/**< XRI */
	ocs_dma_t	def_sgl;	/**< default scatter gather list */
	uint32_t	def_sgl_count;	/**< count of SGEs in default SGL */
	ocs_dma_t	*sgl;		/**< pointer to current active SGL */
	uint32_t	sgl_count;	/**< count of SGEs in io->sgl */
	uint32_t	first_data_sge;	/**< index of first data SGE */
	ocs_dma_t	*ovfl_sgl;	/**< overflow SGL */
	uint32_t	ovfl_sgl_count;	/**< count of SGEs in default SGL */
	sli4_lsp_sge_t	*ovfl_lsp;	/**< pointer to overflow segment length */
	ocs_hw_io_t	*ovfl_io;	/**< Used for SGL chaining on skyhawk */
	uint32_t	n_sge;		/**< number of active SGEs */
	uint32_t	sge_offset;

	/* BZ 161832 Workaround: */
	struct ocs_hw_io_s	*sec_hio; /**< Secondary HW IO context */
	ocs_hw_io_param_t sec_iparam;	/**< Secondary HW IO context saved iparam */
	uint32_t	sec_len;	/**< Secondary HW IO context saved len */

	/* Owned by upper layer */
	void		*ul_io;		/**< where upper layer can store reference to its IO */
};

typedef enum {
	OCS_HW_PORT_INIT,
	OCS_HW_PORT_SHUTDOWN,
	OCS_HW_PORT_SET_LINK_CONFIG,
} ocs_hw_port_e;

/**
 * @brief Fabric/Domain events
 */
typedef enum {
	OCS_HW_DOMAIN_ALLOC_OK,	/**< domain successfully allocated */
	OCS_HW_DOMAIN_ALLOC_FAIL,	/**< domain allocation failed */
	OCS_HW_DOMAIN_ATTACH_OK,	/**< successfully attached to domain */
	OCS_HW_DOMAIN_ATTACH_FAIL,	/**< domain attach failed */
	OCS_HW_DOMAIN_FREE_OK,		/**< successfully freed domain */
	OCS_HW_DOMAIN_FREE_FAIL,	/**< domain free failed */
	OCS_HW_DOMAIN_LOST,		/**< previously discovered domain no longer available */
	OCS_HW_DOMAIN_FOUND,		/**< new domain discovered */
	OCS_HW_DOMAIN_CHANGED,		/**< previously discovered domain properties have changed */
} ocs_hw_domain_event_e;

typedef enum {
	OCS_HW_PORT_ALLOC_OK,		/**< port successfully allocated */
	OCS_HW_PORT_ALLOC_FAIL,	/**< port allocation failed */
	OCS_HW_PORT_ATTACH_OK,		/**< successfully attached to port */
	OCS_HW_PORT_ATTACH_FAIL,	/**< port attach failed */
	OCS_HW_PORT_FREE_OK,		/**< successfully freed port */
	OCS_HW_PORT_FREE_FAIL,		/**< port free failed */
} ocs_hw_port_event_e;

typedef enum {
	OCS_HW_NODE_ATTACH_OK,
	OCS_HW_NODE_ATTACH_FAIL,
	OCS_HW_NODE_FREE_OK,
	OCS_HW_NODE_FREE_FAIL,
	OCS_HW_NODE_FREE_ALL_OK,
	OCS_HW_NODE_FREE_ALL_FAIL,
} ocs_hw_remote_node_event_e;

typedef enum {
	OCS_HW_CB_DOMAIN,
	OCS_HW_CB_PORT,
	OCS_HW_CB_REMOTE_NODE,
	OCS_HW_CB_UNSOLICITED,
	OCS_HW_CB_BOUNCE,
	OCS_HW_CB_MAX,			/**< must be last */
} ocs_hw_callback_e;

/**
 * @brief HW unsolicited callback status
 */
typedef enum {
	OCS_HW_UNSOL_SUCCESS,
	OCS_HW_UNSOL_ERROR,
	OCS_HW_UNSOL_ABTS_RCVD,
	OCS_HW_UNSOL_MAX,		/**< must be last */
} ocs_hw_unsol_status_e;

/**
 * @brief Node group rpi reference
 */
typedef struct {
	ocs_atomic_t rpi_count;
	ocs_atomic_t rpi_attached;
} ocs_hw_rpi_ref_t;

/**
 * @brief HW link stat types
 */
typedef enum {
	OCS_HW_LINK_STAT_LINK_FAILURE_COUNT,
	OCS_HW_LINK_STAT_LOSS_OF_SYNC_COUNT,
	OCS_HW_LINK_STAT_LOSS_OF_SIGNAL_COUNT,
	OCS_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT,
	OCS_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT,
	OCS_HW_LINK_STAT_CRC_COUNT,
	OCS_HW_LINK_STAT_PRIMITIVE_SEQ_TIMEOUT_COUNT,
	OCS_HW_LINK_STAT_ELASTIC_BUFFER_OVERRUN_COUNT,
	OCS_HW_LINK_STAT_ARB_TIMEOUT_COUNT,
	OCS_HW_LINK_STAT_ADVERTISED_RCV_B2B_CREDIT,
	OCS_HW_LINK_STAT_CURR_RCV_B2B_CREDIT,
	OCS_HW_LINK_STAT_ADVERTISED_XMIT_B2B_CREDIT,
	OCS_HW_LINK_STAT_CURR_XMIT_B2B_CREDIT,
	OCS_HW_LINK_STAT_RCV_EOFA_COUNT,
	OCS_HW_LINK_STAT_RCV_EOFDTI_COUNT,
	OCS_HW_LINK_STAT_RCV_EOFNI_COUNT,
	OCS_HW_LINK_STAT_RCV_SOFF_COUNT,
	OCS_HW_LINK_STAT_RCV_DROPPED_NO_AER_COUNT,
	OCS_HW_LINK_STAT_RCV_DROPPED_NO_RPI_COUNT,
	OCS_HW_LINK_STAT_RCV_DROPPED_NO_XRI_COUNT,
	OCS_HW_LINK_STAT_MAX,		/**< must be last */
} ocs_hw_link_stat_e;

typedef enum {
	OCS_HW_HOST_STAT_TX_KBYTE_COUNT,
	OCS_HW_HOST_STAT_RX_KBYTE_COUNT,
	OCS_HW_HOST_STAT_TX_FRAME_COUNT,
	OCS_HW_HOST_STAT_RX_FRAME_COUNT,
	OCS_HW_HOST_STAT_TX_SEQ_COUNT,
	OCS_HW_HOST_STAT_RX_SEQ_COUNT,
	OCS_HW_HOST_STAT_TOTAL_EXCH_ORIG,
	OCS_HW_HOST_STAT_TOTAL_EXCH_RESP,
	OCS_HW_HOSY_STAT_RX_P_BSY_COUNT,
	OCS_HW_HOST_STAT_RX_F_BSY_COUNT,
	OCS_HW_HOST_STAT_DROP_FRM_DUE_TO_NO_RQ_BUF_COUNT,
	OCS_HW_HOST_STAT_EMPTY_RQ_TIMEOUT_COUNT,
	OCS_HW_HOST_STAT_DROP_FRM_DUE_TO_NO_XRI_COUNT,
	OCS_HW_HOST_STAT_EMPTY_XRI_POOL_COUNT,
	OCS_HW_HOST_STAT_MAX /* MUST BE LAST */
} ocs_hw_host_stat_e;

typedef enum {
	OCS_HW_STATE_UNINITIALIZED,		/* power-on, no allocations, no initializations */
	OCS_HW_STATE_QUEUES_ALLOCATED,		/* chip is reset, allocations are complete (queues not registered) */
	OCS_HW_STATE_ACTIVE,			/* chip is up an running */
	OCS_HW_STATE_RESET_IN_PROGRESS,	/* chip is being reset */
	OCS_HW_STATE_TEARDOWN_IN_PROGRESS,	/* teardown has been started */
} ocs_hw_state_e;

/**
 * @brief Defines a general FC sequence object, consisting of a header, payload buffers
 *	  and a HW IO in the case of port owned XRI
 */
typedef struct {
	ocs_hw_t *hw;			/**< HW that owns this sequence */
	/* sequence information */
	uint8_t fcfi;		/**< FCFI associated with sequence */
	uint8_t auto_xrdy;	/**< If auto XFER_RDY was generated */
	uint8_t out_of_xris;	/**< If IO would have been assisted if XRIs were available */
	ocs_hw_rq_buffer_t *header;
	ocs_hw_rq_buffer_t *payload;	/**< received frame payload buffer */

	/* other "state" information from the SRB (sequence coalescing) */
	ocs_hw_unsol_status_e status;
	uint32_t xri;		/**< XRI associated with sequence; sequence coalescing only */
	ocs_hw_io_t *hio;	/**< HW IO */

	ocs_list_link_t link;
	void *hw_priv;		/**< HW private context */
} ocs_hw_sequence_t;

/**
 * @brief Structure to track optimized write buffers posted to chip owned XRIs.
 *
 * Note: The rqindex will be set the following "fake" indexes. This will be used
 *       when the buffer is returned via ocs_seq_free() to make the buffer available
 *       for re-use on another XRI.
 *
 *       The dma->alloc pointer on the dummy header will be used to get back to this structure when the buffer is freed.
 *
 *       More of these object may be allocated on the fly if more XRIs are pushed to the chip.
 */
#define OCS_HW_RQ_INDEX_DUMMY_HDR	0xFF00
#define OCS_HW_RQ_INDEX_DUMMY_DATA	0xFF01
typedef struct ocs_hw_auto_xfer_rdy_buffer_s {
	fc_header_t hdr;		/**< used to build a dummy data header for unsolicited processing */
	ocs_hw_rq_buffer_t header;	/**< Points to the dummy data header */
	ocs_hw_rq_buffer_t payload;	/**< received frame payload buffer */
	ocs_hw_sequence_t seq;         /**< sequence for passing the buffers */
	uint8_t data_cqe;
	uint8_t cmd_cqe;

	/* fields saved from the command header that are needed when the data arrives */
	uint8_t fcfi;

	/* To handle outof order completions save AXR cmd and data cqes */
	uint8_t call_axr_cmd;
	uint8_t call_axr_data;
	ocs_hw_sequence_t *cmd_seq;
} ocs_hw_auto_xfer_rdy_buffer_t;

/**
 * @brief Node group rpi reference
 */
typedef struct {
	uint8_t overflow;
	uint32_t counter;
} ocs_hw_link_stat_counts_t;

/**
 * @brief HW object describing fc host stats
 */
typedef struct {
	uint32_t counter;
} ocs_hw_host_stat_counts_t;

#define TID_HASH_BITS	8
#define TID_HASH_LEN	(1U << TID_HASH_BITS)

typedef struct ocs_hw_iopt_s {
	char		name[32];
	uint32_t	instance_index;
	ocs_thread_t	iopt_thread;
	ocs_cbuf_t	*iopt_free_queue;	/* multiple reader, multiple writer */
	ocs_cbuf_t	*iopt_work_queue;
	ocs_array_t	*iopt_cmd_array;
} ocs_hw_iopt_t;

typedef enum {
	HW_CQ_HANDLER_LOCAL,
	HW_CQ_HANDLER_THREAD,
} hw_cq_handler_e;

#include "ocs_hw_queues.h"

/**
 * @brief Stucture used for the hash lookup of queue IDs
 */
typedef struct {
	uint32_t id:16,
		in_use:1,
		index:15;
} ocs_queue_hash_t;

/**
 * @brief Define the fields required to implement the skyhawk DIF quarantine.
 */
#define OCS_HW_QUARANTINE_QUEUE_DEPTH	4

typedef struct {
	uint32_t	quarantine_index;
	ocs_hw_io_t	*quarantine_ios[OCS_HW_QUARANTINE_QUEUE_DEPTH];
} ocs_quarantine_info_t;

/**
 * @brief Define the WQ callback object
 */
typedef struct {
	uint16_t instance_index;	/**< use for request tag */
	void (*callback)(void *arg, uint8_t *cqe, int32_t status);
	void *arg;
} hw_wq_callback_t;

typedef struct {
	uint64_t fwrev;

	/* Control Declarations here ...*/

	uint8_t retain_tsend_io_length;

	/* Use unregistered RPI */
	uint8_t use_unregistered_rpi;
	uint32_t unregistered_rid;
	uint32_t unregistered_index;

	uint8_t disable_ar_tgt_dif;	/* Disable auto response if target DIF */
	uint8_t disable_dump_loc;
	uint8_t use_dif_quarantine;
	uint8_t use_dif_sec_xri;

	uint8_t override_fcfi;

	uint8_t fw_version_too_low;

	uint8_t sglc_misreported;

	uint8_t ignore_send_frame;

} ocs_hw_workaround_t;

/**
 * @brief HW object
 */
struct ocs_hw_s {
	ocs_os_handle_t	os;
	sli4_t		sli;
	uint16_t	ulp_start;
	uint16_t	ulp_max;
	uint32_t	dump_size;
	ocs_hw_state_e state;
	uint8_t		hw_setup_called;
	uint8_t		sliport_healthcheck;
	uint16_t        watchdog_timeout;
	ocs_lock_t	watchdog_lock;

	/** HW configuration, subject to ocs_hw_set()  */
	struct {
		uint32_t	n_eq; /**< number of event queues */
		uint32_t	n_cq; /**< number of completion queues */
		uint32_t	n_mq; /**< number of mailbox queues */
		uint32_t	n_rq; /**< number of receive queues */
		uint32_t	n_wq; /**< number of work queues */
		uint32_t	n_io; /**< total number of IO objects */
		uint32_t	n_sgl;/**< length of SGL */
		uint32_t	speed;	/** requested link speed in Mbps */
		uint32_t	topology;  /** requested link topology */
		uint32_t	rq_default_buffer_size;	/** size of the buffers for first burst */
		uint32_t	auto_xfer_rdy_xri_cnt;	/** Initial XRIs to post to chip at initialization */
		uint32_t	auto_xfer_rdy_size;	/** max size IO to use with this feature */
		uint8_t		auto_xfer_rdy_blk_size_chip;	/** block size to use with this feature */
		uint8_t         esoc;
		uint16_t	dif_seed; /** The seed for the DIF CRC calculation */
		uint16_t	auto_xfer_rdy_app_tag_value;
		uint8_t		dif_mode; /**< DIF mode to use */
		uint8_t		i_only_aab; /** Enable initiator-only auto-abort */
		uint8_t		emulate_tgt_wqe_timeout; /** Enable driver target wqe timeouts */
		uint32_t	bounce:1;
		const char	*queue_topology;		/**< Queue topology string */
		uint8_t		auto_xfer_rdy_t10_enable;	/** Enable t10 PI for auto xfer ready */
		uint8_t		auto_xfer_rdy_p_type;	/** p_type for auto xfer ready */
		uint8_t		auto_xfer_rdy_ref_tag_is_lba;
		uint8_t		auto_xfer_rdy_app_tag_valid;
		uint8_t		rq_selection_policy;		/** MRQ RQ selection policy */
		uint8_t		rr_quanta;			/** RQ quanta if rq_selection_policy == 2 */
		uint32_t	filter_def[SLI4_CMD_REG_FCFI_NUM_RQ_CFG];
	} config;

	/* calculated queue sizes for each type */
	uint32_t	num_qentries[SLI_QTYPE_MAX];

	/* Storage for SLI queue objects */
	sli4_queue_t	wq[OCS_HW_MAX_NUM_WQ];
	sli4_queue_t	rq[OCS_HW_MAX_NUM_RQ];
	uint16_t	hw_rq_lookup[OCS_HW_MAX_NUM_RQ];
	sli4_queue_t	mq[OCS_HW_MAX_NUM_MQ];
	sli4_queue_t	cq[OCS_HW_MAX_NUM_CQ];
	sli4_queue_t	eq[OCS_HW_MAX_NUM_EQ];

	/* HW queue */
	uint32_t	eq_count;
	uint32_t	cq_count;
	uint32_t	mq_count;
	uint32_t	wq_count;
	uint32_t	rq_count;			/**< count of SLI RQs */
	ocs_list_t	eq_list;

	ocs_queue_hash_t cq_hash[OCS_HW_Q_HASH_SIZE];
	ocs_queue_hash_t rq_hash[OCS_HW_Q_HASH_SIZE];
	ocs_queue_hash_t wq_hash[OCS_HW_Q_HASH_SIZE];

	/* Storage for HW queue objects */
	hw_wq_t	*hw_wq[OCS_HW_MAX_NUM_WQ];
	hw_rq_t	*hw_rq[OCS_HW_MAX_NUM_RQ];
	hw_mq_t	*hw_mq[OCS_HW_MAX_NUM_MQ];
	hw_cq_t	*hw_cq[OCS_HW_MAX_NUM_CQ];
	hw_eq_t	*hw_eq[OCS_HW_MAX_NUM_EQ];
	uint32_t	hw_rq_count;			/**< count of hw_rq[] entries */
	uint32_t	hw_mrq_count;			/**< count of multirq RQs */

	ocs_varray_t	*wq_class_array[OCS_HW_MAX_WQ_CLASS];	/**< pool per class WQs */
	ocs_varray_t	*wq_cpu_array[OCS_HW_MAX_WQ_CPU];	/**< pool per CPU WQs */

	/* Sequence objects used in incoming frame processing */
	ocs_array_t	*seq_pool;

	/* Auto XFER RDY Buffers - protect with io_lock */
	uint32_t	auto_xfer_rdy_enabled:1,	/**< TRUE if auto xfer rdy is enabled */
			:31;
	ocs_pool_t	*auto_xfer_rdy_buf_pool;	/**< pool of ocs_hw_auto_xfer_rdy_buffer_t objects */

	/** Maintain an ordered, linked list of outstanding HW commands. */
	ocs_lock_t	cmd_lock;
	ocs_list_t	cmd_head;
	ocs_list_t	cmd_pending;
	uint32_t	cmd_head_count;

	sli4_link_event_t link;
	ocs_hw_linkcfg_e linkcfg; /**< link configuration setting */
	uint32_t eth_license;	   /**< Ethernet license; to enable FCoE on Lancer */

	struct {
		/**
		 * Function + argument used to notify upper layer of domain events.
		 *
		 * The final argument to the callback is a generic data pointer:
		 *  - ocs_domain_record_t on OCS_HW_DOMAIN_FOUND
		 *  - ocs_domain_t on OCS_HW_DOMAIN_ALLOC_FAIL, OCS_HW_DOMAIN_ALLOC_OK,
		 * OCS_HW_DOMAIN_FREE_FAIL, OCS_HW_DOMAIN_FREE_OK,
		 * OCS_HW_DOMAIN_ATTACH_FAIL, OCS_HW_DOMAIN_ATTACH_OK, and
		 * OCS_HW_DOMAIN_LOST.
		 */
		int32_t	(*domain)(void *, ocs_hw_domain_event_e, void *);
		/**
		 * Function + argument used to notify upper layers of port events.
		 *
		 * The final argument to the callback is a pointer to the effected
		 * SLI port for all events.
		 */
		int32_t (*port)(void *, ocs_hw_port_event_e, void *);
		/** Function + argument used to announce arrival of unsolicited frames */
		int32_t (*unsolicited)(void *, ocs_hw_sequence_t *);
		int32_t (*rnode)(void *, ocs_hw_remote_node_event_e, void *);
		int32_t (*bounce)(void (*)(void *arg), void *arg, uint32_t s_id, uint32_t d_id, uint32_t ox_id);
	} callback;
	struct {
		void *domain;
		void *port;
		void *unsolicited;
		void *rnode;
		void *bounce;
	} args;

	/* OCS domain objects index by FCFI */
	int32_t		first_domain_idx;		/* Workaround for srb->fcfi == 0 */
	ocs_domain_t	*domains[SLI4_MAX_FCFI];

	/* Table of FCFI values index by FCF_index */
	uint16_t	fcf_index_fcfi[SLI4_MAX_FCF_INDEX];

	uint16_t	fcf_indicator;

	ocs_hw_io_t	**io;		/**< pointer array of IO objects */
	uint8_t		*wqe_buffs;	/**< array of WQE buffs mapped to IO objects */	

	ocs_lock_t	io_lock;		/**< IO lock to synchronize list access */
	ocs_lock_t	io_abort_lock;		/**< IO lock to synchronize IO aborting */
	ocs_list_t	io_inuse;		/**< List of IO objects in use */
	ocs_list_t	io_timed_wqe;		/**< List of IO objects with a timed target WQE */
	ocs_list_t	io_wait_free;		/**< List of IO objects waiting to be freed */
	ocs_list_t	io_free;		/**< List of IO objects available for allocation */
	ocs_list_t	io_port_owned;		/**< List of IO objects posted for chip use */
	ocs_list_t	io_port_dnrx;		/**< List of IO objects needing auto xfer rdy buffers */

	ocs_dma_t	loop_map;

	ocs_dma_t	xfer_rdy;

	ocs_dma_t	dump_sges;

	ocs_dma_t	rnode_mem;

	ocs_dma_t	domain_dmem; 	/*domain dma mem for service params */
	ocs_dma_t	fcf_dmem; 	/*dma men for fcf */

	ocs_hw_rpi_ref_t *rpi_ref;

	char		*hw_war_version;
	ocs_hw_workaround_t workaround;

	ocs_atomic_t io_alloc_failed_count;

#if defined(OCS_DEBUG_QUEUE_HISTORY)
	ocs_hw_q_hist_t q_hist;
#endif

	ocs_list_t	sec_hio_wait_list;	/**< BZ 161832 Workaround: Secondary HW IO context wait list */
	uint32_t	sec_hio_wait_count;	/**< BZ 161832 Workaround: Count of IOs that were put on the
						 * Secondary HW IO wait list
						 */

#define HW_MAX_TCMD_THREADS		16
	ocs_hw_qtop_t	*qtop;					/**< pointer to queue topology */

	uint32_t	tcmd_wq_submit[OCS_HW_MAX_NUM_WQ];	/**< stat: wq sumbit count */
	uint32_t	tcmd_wq_complete[OCS_HW_MAX_NUM_WQ];	/**< stat: wq complete count */

	ocs_timer_t	wqe_timer;		/**< Timer to periodically check for WQE timeouts */
	ocs_timer_t	watchdog_timer;		/**< Timer for heartbeat */
	bool            expiration_logged;
	uint32_t	in_active_wqe_timer:1,	/**< TRUE if currently in active wqe timer handler */
			active_wqe_timer_shutdown:1, /** TRUE if wqe timer is to be shutdown */
			:30;

	ocs_list_t	iopc_list;		/**< list of IO processing contexts */
	ocs_lock_t	iopc_list_lock;		/**< lock for iopc_list */

	ocs_pool_t	*wq_reqtag_pool;	/**< pool of hw_wq_callback_t objects */

	ocs_atomic_t	send_frame_seq_id;	/**< send frame sequence ID */
};

typedef enum {
	OCS_HW_IO_INUSE_COUNT,
	OCS_HW_IO_FREE_COUNT,
	OCS_HW_IO_WAIT_FREE_COUNT,
	OCS_HW_IO_PORT_OWNED_COUNT,
	OCS_HW_IO_N_TOTAL_IO_COUNT,
} ocs_hw_io_count_type_e;

typedef void (*tcmd_cq_handler)(ocs_hw_t *hw, uint32_t cq_idx, void *cq_handler_arg);

/*
 * HW queue data structures
 */

struct hw_eq_s {
	ocs_list_link_t link;		/**< must be first */
	sli4_qtype_e type;		/**< must be second */
	uint32_t instance;
	uint32_t entry_count;
	uint32_t entry_size;
	ocs_hw_t *hw;
	sli4_queue_t *queue;
	ocs_list_t cq_list;
#if OCS_STAT_ENABLE
	uint32_t use_count;
#endif
	ocs_varray_t *wq_array;		/*<< array of WQs */
};

struct hw_cq_s {
	ocs_list_link_t link;		/*<< must be first */
	sli4_qtype_e type;		/**< must be second */
	uint32_t instance;		/*<< CQ instance (cq_idx) */
	uint32_t entry_count;		/*<< Number of entries */
	uint32_t entry_size;		/*<< entry size */
	hw_eq_t *eq;			/*<< parent EQ */
	sli4_queue_t *queue;		/**< pointer to SLI4 queue */
	ocs_list_t q_list;		/**< list of children queues */

#if OCS_STAT_ENABLE
	uint32_t use_count;
#endif
};

typedef struct {
	ocs_list_link_t link;		/*<< must be first */
	sli4_qtype_e type;		/*<< must be second */
} hw_q_t;

struct hw_mq_s {
	ocs_list_link_t link;		/*<< must be first */
	sli4_qtype_e type;		/*<< must be second */
	uint32_t instance;

	uint32_t entry_count;
	uint32_t entry_size;
	hw_cq_t *cq;
	sli4_queue_t *queue;

#if OCS_STAT_ENABLE
	uint32_t use_count;
#endif
};

struct hw_wq_s {
	ocs_list_link_t link;		/*<< must be first */
	sli4_qtype_e type;		/*<< must be second */
	uint32_t instance;
	ocs_hw_t *hw;

	uint32_t entry_count;
	uint32_t entry_size;
	hw_cq_t *cq;
	sli4_queue_t *queue;
	uint32_t class;
	uint8_t ulp;

	/* WQ consumed */
	uint32_t wqec_set_count;		/*<< how often IOs are submitted with wqce set */
	uint32_t wqec_count;			/*<< current wqce counter */
	uint32_t free_count;			/*<< free count */
	uint32_t total_submit_count;		/*<< total submit count */
	ocs_list_t pending_list;		/*<< list of IOs pending for this WQ */

	/*
	 * ---Skyhawk only ---
	 * BZ 160124 - Driver must quarantine XRIs for target writes and
	 * initiator read when using DIF separates. Throw them on a
	 * queue until another 4 similar requests are completed to ensure they
	 * are flushed from the internal chip cache before being re-used.
	 * The must be a separate queue per CQ because the actual chip completion
	 * order cannot be determined. Since each WQ has a separate CQ, use the wq
	 * associated with the IO.
	 *
	 * Note: Protected by queue->lock
	 */
	ocs_quarantine_info_t quarantine_info;

	/*
	 * HW IO allocated for use with Send Frame
	 */
	ocs_hw_io_t *send_frame_io;

	/* Stats */
#if OCS_STAT_ENABLE
	uint32_t use_count;			/*<< use count */
	uint32_t wq_pending_count;		/*<< count of HW IOs that were queued on the WQ pending list */
#endif
};

struct hw_rq_s {
	ocs_list_link_t link;			/*<< must be first */
	sli4_qtype_e type;			/*<< must be second */
	uint32_t instance;

	uint32_t entry_count;
	uint32_t hdr_entry_size;
	uint32_t first_burst_entry_size;
	uint32_t data_entry_size;
	uint8_t ulp;
	bool is_mrq;
	uint32_t base_mrq_id;

	hw_cq_t *cq;

	uint8_t filter_mask;			/* Filter mask value */
	sli4_queue_t *hdr;
	sli4_queue_t *first_burst;
	sli4_queue_t *data;

	ocs_hw_rq_buffer_t *hdr_buf;
	ocs_hw_rq_buffer_t *fb_buf;
	ocs_hw_rq_buffer_t *payload_buf;

	ocs_hw_sequence_t **rq_tracker;	/* RQ tracker for this RQ */
#if OCS_STAT_ENABLE
	uint32_t use_count;
	uint32_t hdr_use_count;
	uint32_t fb_use_count;
	uint32_t payload_use_count;
#endif
};

typedef struct ocs_hw_global_s {
	const char	*queue_topology_string;			/**< queue topology string */
} ocs_hw_global_t;
extern ocs_hw_global_t hw_global;

extern hw_eq_t *hw_new_eq(ocs_hw_t *hw, uint32_t entry_count);
extern hw_cq_t *hw_new_cq(hw_eq_t *eq, uint32_t entry_count);
extern uint32_t hw_new_cq_set(hw_eq_t *eqs[], hw_cq_t *cqs[], uint32_t num_cqs, uint32_t entry_count);
extern hw_mq_t *hw_new_mq(hw_cq_t *cq, uint32_t entry_count);
extern hw_wq_t *hw_new_wq(hw_cq_t *cq, uint32_t entry_count, uint32_t class, uint32_t ulp);
extern hw_rq_t *hw_new_rq(hw_cq_t *cq, uint32_t entry_count, uint32_t ulp);
extern uint32_t hw_new_rq_set(hw_cq_t *cqs[], hw_rq_t *rqs[], uint32_t num_rq_pairs, uint32_t entry_count, uint32_t ulp);
extern void hw_del_eq(hw_eq_t *eq);
extern void hw_del_cq(hw_cq_t *cq);
extern void hw_del_mq(hw_mq_t *mq);
extern void hw_del_wq(hw_wq_t *wq);
extern void hw_del_rq(hw_rq_t *rq);
extern void hw_queue_dump(ocs_hw_t *hw);
extern void hw_queue_teardown(ocs_hw_t *hw);
extern int32_t hw_route_rqe(ocs_hw_t *hw, ocs_hw_sequence_t *seq);
extern int32_t ocs_hw_queue_hash_find(ocs_queue_hash_t *, uint16_t);
extern ocs_hw_rtn_e ocs_hw_setup(ocs_hw_t *, ocs_os_handle_t, sli4_port_type_e);
extern ocs_hw_rtn_e ocs_hw_init(ocs_hw_t *);
extern ocs_hw_rtn_e ocs_hw_teardown(ocs_hw_t *);
extern ocs_hw_rtn_e ocs_hw_reset(ocs_hw_t *, ocs_hw_reset_e);
extern int32_t ocs_hw_get_num_eq(ocs_hw_t *);
extern ocs_hw_rtn_e ocs_hw_get(ocs_hw_t *, ocs_hw_property_e, uint32_t *);
extern void *ocs_hw_get_ptr(ocs_hw_t *, ocs_hw_property_e);
extern ocs_hw_rtn_e ocs_hw_set(ocs_hw_t *, ocs_hw_property_e, uint32_t);
extern ocs_hw_rtn_e ocs_hw_set_ptr(ocs_hw_t *, ocs_hw_property_e, void*);
extern int32_t ocs_hw_event_check(ocs_hw_t *, uint32_t);
extern int32_t ocs_hw_process(ocs_hw_t *, uint32_t, uint32_t);
extern ocs_hw_rtn_e ocs_hw_command(ocs_hw_t *, uint8_t *, uint32_t, void *, void *);
extern ocs_hw_rtn_e ocs_hw_callback(ocs_hw_t *, ocs_hw_callback_e, void *, void *);
extern ocs_hw_rtn_e ocs_hw_port_alloc(ocs_hw_t *, ocs_sli_port_t *, ocs_domain_t *, uint8_t *);
extern ocs_hw_rtn_e ocs_hw_port_attach(ocs_hw_t *, ocs_sli_port_t *, uint32_t);
typedef void (*ocs_hw_port_control_cb_t)(int32_t status, uintptr_t value, void *arg);
extern ocs_hw_rtn_e ocs_hw_port_control(ocs_hw_t *, ocs_hw_port_e, uintptr_t, ocs_hw_port_control_cb_t, void *);
extern ocs_hw_rtn_e ocs_hw_port_free(ocs_hw_t *, ocs_sli_port_t *);
extern ocs_hw_rtn_e ocs_hw_domain_alloc(ocs_hw_t *, ocs_domain_t *, uint32_t, uint32_t);
extern ocs_hw_rtn_e ocs_hw_domain_attach(ocs_hw_t *, ocs_domain_t *, uint32_t);
extern ocs_hw_rtn_e ocs_hw_domain_free(ocs_hw_t *, ocs_domain_t *);
extern ocs_hw_rtn_e ocs_hw_domain_force_free(ocs_hw_t *, ocs_domain_t *);
extern ocs_domain_t * ocs_hw_domain_get(ocs_hw_t *, uint16_t);
extern ocs_hw_rtn_e ocs_hw_node_alloc(ocs_hw_t *, ocs_remote_node_t *, uint32_t, ocs_sli_port_t *);
extern ocs_hw_rtn_e ocs_hw_node_free_all(ocs_hw_t *);
extern ocs_hw_rtn_e ocs_hw_node_attach(ocs_hw_t *, ocs_remote_node_t *, ocs_dma_t *);
extern ocs_hw_rtn_e ocs_hw_node_detach(ocs_hw_t *, ocs_remote_node_t *);
extern ocs_hw_rtn_e ocs_hw_node_free_resources(ocs_hw_t *, ocs_remote_node_t *);
extern ocs_hw_rtn_e ocs_hw_node_group_alloc(ocs_hw_t *, ocs_remote_node_group_t *);
extern ocs_hw_rtn_e ocs_hw_node_group_attach(ocs_hw_t *, ocs_remote_node_group_t *, ocs_remote_node_t *);
extern ocs_hw_rtn_e ocs_hw_node_group_free(ocs_hw_t *, ocs_remote_node_group_t *);
extern ocs_hw_io_t *ocs_hw_io_alloc(ocs_hw_t *);
extern ocs_hw_io_t *ocs_hw_io_activate_port_owned(ocs_hw_t *, ocs_hw_io_t *);
extern int32_t ocs_hw_io_free(ocs_hw_t *, ocs_hw_io_t *);
extern uint8_t ocs_hw_io_inuse(ocs_hw_t *hw, ocs_hw_io_t *io);
typedef int32_t (*ocs_hw_srrs_cb_t)(ocs_hw_io_t *io, ocs_remote_node_t *rnode, uint32_t length, int32_t status, uint32_t ext_status, void *arg);
extern ocs_hw_rtn_e ocs_hw_srrs_send(ocs_hw_t *, ocs_hw_io_type_e, ocs_hw_io_t *, ocs_dma_t *, uint32_t, ocs_dma_t *, ocs_remote_node_t *, ocs_hw_io_param_t *, ocs_hw_srrs_cb_t, void *);
extern ocs_hw_rtn_e ocs_hw_io_send(ocs_hw_t *, ocs_hw_io_type_e, ocs_hw_io_t *, uint32_t, ocs_hw_io_param_t *, ocs_remote_node_t *, void *, void *);
extern ocs_hw_rtn_e _ocs_hw_io_send(ocs_hw_t *hw, ocs_hw_io_type_e type, ocs_hw_io_t *io,
				      uint32_t len, ocs_hw_io_param_t *iparam, ocs_remote_node_t *rnode,
				      void *cb, void *arg);
extern ocs_hw_rtn_e ocs_hw_io_register_sgl(ocs_hw_t *, ocs_hw_io_t *, ocs_dma_t *, uint32_t);
extern ocs_hw_rtn_e ocs_hw_io_init_sges(ocs_hw_t *hw, ocs_hw_io_t *io, ocs_hw_io_type_e type);
extern ocs_hw_rtn_e ocs_hw_io_add_seed_sge(ocs_hw_t *hw, ocs_hw_io_t *io, ocs_hw_dif_info_t *dif_info);
extern ocs_hw_rtn_e ocs_hw_io_add_sge(ocs_hw_t *, ocs_hw_io_t *, uintptr_t, uint32_t);
extern ocs_hw_rtn_e ocs_hw_io_add_dif_sge(ocs_hw_t *hw, ocs_hw_io_t *io, uintptr_t addr);
extern ocs_hw_rtn_e ocs_hw_io_abort(ocs_hw_t *, ocs_hw_io_t *, uint32_t, void *, void *);
extern int32_t ocs_hw_io_get_xid(ocs_hw_t *, ocs_hw_io_t *);
extern uint32_t ocs_hw_io_get_count(ocs_hw_t *, ocs_hw_io_count_type_e);
extern uint32_t ocs_hw_get_rqes_produced_count(ocs_hw_t *hw);

typedef void (*ocs_hw_fw_cb_t)(int32_t status, uint32_t bytes_written, uint32_t change_status, void *arg);
extern ocs_hw_rtn_e ocs_hw_firmware_write(ocs_hw_t *, ocs_dma_t *, uint32_t, uint32_t, int, ocs_hw_fw_cb_t, void*);

/* Function for retrieving SFP data */
typedef void (*ocs_hw_sfp_cb_t)(void *, int32_t, uint32_t, uint32_t *, void *);
extern ocs_hw_rtn_e ocs_hw_get_sfp(ocs_hw_t *, uint16_t, ocs_hw_sfp_cb_t, void *);

/* Function for retrieving temperature data */
typedef void (*ocs_hw_temp_cb_t)(int32_t status,
				  uint32_t curr_temp,
				  uint32_t crit_temp_thrshld,
				  uint32_t warn_temp_thrshld,
				  uint32_t norm_temp_thrshld,
				  uint32_t fan_off_thrshld,
				  uint32_t fan_on_thrshld,
				  void *arg);
extern ocs_hw_rtn_e ocs_hw_get_temperature(ocs_hw_t *, ocs_hw_temp_cb_t, void*);

/* Function for retrieving link statistics */
typedef void (*ocs_hw_link_stat_cb_t)(int32_t status,
				       uint32_t num_counters,
				       ocs_hw_link_stat_counts_t *counters,
				       void *arg);
extern ocs_hw_rtn_e ocs_hw_get_link_stats(ocs_hw_t *,
					    uint8_t req_ext_counters,
					    uint8_t clear_overflow_flags,
					    uint8_t clear_all_counters,
					    ocs_hw_link_stat_cb_t, void*);
/* Function for retrieving host statistics */
typedef void (*ocs_hw_host_stat_cb_t)(int32_t status,
				       uint32_t num_counters,
				       ocs_hw_host_stat_counts_t *counters,
				       void *arg);
extern ocs_hw_rtn_e ocs_hw_get_host_stats(ocs_hw_t *hw, uint8_t cc, ocs_hw_host_stat_cb_t, void *arg);

extern ocs_hw_rtn_e ocs_hw_raise_ue(ocs_hw_t *, uint8_t);
typedef void (*ocs_hw_dump_get_cb_t)(int32_t status, uint32_t bytes_read, uint8_t eof, void *arg);
extern ocs_hw_rtn_e ocs_hw_dump_get(ocs_hw_t *, ocs_dma_t *, uint32_t, uint32_t, ocs_hw_dump_get_cb_t, void *);
extern ocs_hw_rtn_e ocs_hw_set_dump_location(ocs_hw_t *, uint32_t, ocs_dma_t *, uint8_t);

typedef void (*ocs_get_port_protocol_cb_t)(int32_t status, ocs_hw_port_protocol_e port_protocol, void *arg);
extern ocs_hw_rtn_e ocs_hw_get_port_protocol(ocs_hw_t *hw, uint32_t pci_func, ocs_get_port_protocol_cb_t mgmt_cb, void* ul_arg);
typedef void (*ocs_set_port_protocol_cb_t)(int32_t status,  void *arg);
extern ocs_hw_rtn_e ocs_hw_set_port_protocol(ocs_hw_t *hw, ocs_hw_port_protocol_e profile,
					       uint32_t pci_func, ocs_set_port_protocol_cb_t mgmt_cb,
					       void* ul_arg);

typedef void (*ocs_get_profile_list_cb_t)(int32_t status,  ocs_hw_profile_list_t*, void *arg);
extern ocs_hw_rtn_e ocs_hw_get_profile_list(ocs_hw_t *hw, ocs_get_profile_list_cb_t mgmt_cb, void *arg);
typedef void (*ocs_get_active_profile_cb_t)(int32_t status,  uint32_t active_profile, void *arg);
extern ocs_hw_rtn_e ocs_hw_get_active_profile(ocs_hw_t *hw, ocs_get_active_profile_cb_t mgmt_cb, void *arg);
typedef void (*ocs_set_active_profile_cb_t)(int32_t status, void *arg);
extern ocs_hw_rtn_e ocs_hw_set_active_profile(ocs_hw_t *hw, ocs_set_active_profile_cb_t mgmt_cb,
		uint32_t profile_id, void *arg);
typedef void (*ocs_get_nvparms_cb_t)(int32_t status, uint8_t *wwpn, uint8_t *wwnn, uint8_t hard_alpa,
		uint32_t preferred_d_id, void *arg);
extern ocs_hw_rtn_e ocs_hw_get_nvparms(ocs_hw_t *hw, ocs_get_nvparms_cb_t mgmt_cb, void *arg);
typedef void (*ocs_set_nvparms_cb_t)(int32_t status, void *arg);
extern ocs_hw_rtn_e ocs_hw_set_nvparms(ocs_hw_t *hw, ocs_set_nvparms_cb_t mgmt_cb, uint8_t *wwpn,
		uint8_t *wwnn, uint8_t hard_alpa, uint32_t preferred_d_id, void *arg);
extern int32_t ocs_hw_eq_process(ocs_hw_t *hw, hw_eq_t *eq, uint32_t max_isr_time_msec);
extern void ocs_hw_cq_process(ocs_hw_t *hw, hw_cq_t *cq);
extern void ocs_hw_wq_process(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe, int32_t status, uint16_t rid);
extern void ocs_hw_xabt_process(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe, uint16_t rid);
extern int32_t hw_wq_write(hw_wq_t *wq, ocs_hw_wqe_t *wqe);

typedef void (*ocs_hw_dump_clear_cb_t)(int32_t status, void *arg);
extern ocs_hw_rtn_e ocs_hw_dump_clear(ocs_hw_t *, ocs_hw_dump_clear_cb_t, void *);

extern uint8_t ocs_hw_is_io_port_owned(ocs_hw_t *hw, ocs_hw_io_t *io);

extern uint8_t ocs_hw_is_xri_port_owned(ocs_hw_t *hw, uint32_t xri);
extern ocs_hw_io_t * ocs_hw_io_lookup(ocs_hw_t *hw, uint32_t indicator);
extern uint32_t ocs_hw_xri_move_to_port_owned(ocs_hw_t *hw, uint32_t num_xri);
extern ocs_hw_rtn_e ocs_hw_xri_move_to_host_owned(ocs_hw_t *hw, uint8_t num_xri);
extern int32_t ocs_hw_reque_xri(ocs_hw_t *hw, ocs_hw_io_t *io);

typedef struct {
	/* structure elements used by HW */
	ocs_hw_t *hw;			/**> pointer to HW */
	hw_wq_callback_t *wqcb;	/**> WQ callback object, request tag */
	ocs_hw_wqe_t wqe;		/**> WQE buffer object (may be queued on WQ pending list) */
	void (*callback)(int32_t status, void *arg);	/**> final callback function */
	void *arg;			/**> final callback argument */

	/* General purpose elements */
	ocs_hw_sequence_t *seq;
	ocs_dma_t payload;		/**> a payload DMA buffer */
} ocs_hw_send_frame_context_t;

#define OCS_HW_OBJECT_G5              0xfeaa0001
#define OCS_HW_OBJECT_G6              0xfeaa0003
#define OCS_FILE_TYPE_GROUP            0xf7
#define OCS_FILE_ID_GROUP              0xa2
struct ocs_hw_grp_hdr {
	uint32_t size;          
	uint32_t magic_number;  
	uint32_t word2;         
	uint8_t rev_name[128];
        uint8_t date[12];
        uint8_t revision[32];
};                              

ocs_hw_rtn_e
ocs_hw_send_frame(ocs_hw_t *hw, fc_header_le_t *hdr, uint8_t sof, uint8_t eof, ocs_dma_t *payload,
		   ocs_hw_send_frame_context_t *ctx,
		   void (*callback)(void *arg, uint8_t *cqe, int32_t status), void *arg);

/* RQ completion handlers for RQ pair mode */
extern int32_t ocs_hw_rqpair_process_rq(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe);
extern ocs_hw_rtn_e ocs_hw_rqpair_sequence_free(ocs_hw_t *hw, ocs_hw_sequence_t *seq);
extern int32_t ocs_hw_rqpair_process_auto_xfr_rdy_cmd(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe);
extern int32_t ocs_hw_rqpair_process_auto_xfr_rdy_data(ocs_hw_t *hw, hw_cq_t *cq, uint8_t *cqe);
extern ocs_hw_rtn_e ocs_hw_rqpair_init(ocs_hw_t *hw);
extern ocs_hw_rtn_e ocs_hw_rqpair_auto_xfer_rdy_buffer_alloc(ocs_hw_t *hw, uint32_t num_buffers);
extern uint8_t ocs_hw_rqpair_auto_xfer_rdy_buffer_post(ocs_hw_t *hw, ocs_hw_io_t *io, int reuse_buf);
extern ocs_hw_rtn_e ocs_hw_rqpair_auto_xfer_rdy_move_to_port(ocs_hw_t *hw, ocs_hw_io_t *io);
extern void ocs_hw_rqpair_auto_xfer_rdy_move_to_host(ocs_hw_t *hw, ocs_hw_io_t *io);
extern void ocs_hw_rqpair_teardown(ocs_hw_t *hw);

extern ocs_hw_rtn_e ocs_hw_rx_allocate(ocs_hw_t *hw);
extern ocs_hw_rtn_e ocs_hw_rx_post(ocs_hw_t *hw);
extern void ocs_hw_rx_free(ocs_hw_t *hw);

extern void ocs_hw_unsol_process_bounce(void *arg);

typedef int32_t (*ocs_hw_async_cb_t)(ocs_hw_t *hw, int32_t status, uint8_t *mqe, void *arg);
extern int32_t ocs_hw_async_call(ocs_hw_t *hw, ocs_hw_async_cb_t callback, void *arg);

static inline void
ocs_hw_sequence_copy(ocs_hw_sequence_t *dst, ocs_hw_sequence_t *src)
{
	/* Copy the src to dst, then zero out the linked list link */
	*dst = *src;
	ocs_memset(&dst->link, 0, sizeof(dst->link));
}

static inline ocs_hw_rtn_e
ocs_hw_sequence_free(ocs_hw_t *hw, ocs_hw_sequence_t *seq)
{
	/* Only RQ pair mode is supported */
	return ocs_hw_rqpair_sequence_free(hw, seq);
}

/* HW WQ request tag API */
extern ocs_hw_rtn_e ocs_hw_reqtag_init(ocs_hw_t *hw);
extern hw_wq_callback_t *ocs_hw_reqtag_alloc(ocs_hw_t *hw,
					       void (*callback)(void *arg, uint8_t *cqe, int32_t status), void *arg);
extern void ocs_hw_reqtag_free(ocs_hw_t *hw, hw_wq_callback_t *wqcb);
extern hw_wq_callback_t *ocs_hw_reqtag_get_instance(ocs_hw_t *hw, uint32_t instance_index);
extern void ocs_hw_reqtag_reset(ocs_hw_t *hw);

extern uint32_t ocs_hw_dif_blocksize(ocs_hw_dif_info_t *dif_info);
extern int32_t ocs_hw_dif_mem_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem);
extern int32_t ocs_hw_dif_wire_blocksize(ocs_hw_dif_info_t *dif_info, int wiretomem);
extern uint32_t ocs_hw_get_def_wwn(ocs_t *ocs, uint32_t chan, uint64_t *wwpn, uint64_t *wwnn);

/* Uncomment to enable CPUTRACE */
//#define ENABLE_CPUTRACE
#ifdef ENABLE_CPUTRACE
#define CPUTRACE(t) ocs_printf("trace: %-20s %2s %-16s cpu %2d\n", __func__, t, \
	({ocs_thread_t *self = ocs_thread_self(); self != NULL ? self->name : "unknown";}), ocs_thread_getcpu());
#else
#define CPUTRACE(...)
#endif

/* Two levels of macro needed due to expansion */
#define HW_FWREV(a,b,c,d) (((uint64_t)(a) << 48) | ((uint64_t)(b) << 32) | ((uint64_t)(c) << 16) | ((uint64_t)(d)))
#define HW_FWREV_1(x) HW_FWREV(x)

#define OCS_FW_VER_STR2(a,b,c,d) #a "." #b "." #c "." #d
#define OCS_FW_VER_STR(x) OCS_FW_VER_STR2(x)

#define OCS_MIN_FW_VER_LANCER 10,4,255,0
#define OCS_MIN_FW_VER_SKYHAWK 10,4,255,0

extern void ocs_hw_workaround_setup(struct ocs_hw_s *hw);

/**
 * @brief Defines the number of the RQ buffers for each RQ
 */

#ifndef OCS_HW_RQ_NUM_HDR
#define OCS_HW_RQ_NUM_HDR		1024
#endif

#ifndef OCS_HW_RQ_NUM_PAYLOAD
#define OCS_HW_RQ_NUM_PAYLOAD			1024
#endif

/**
 * @brief Defines the size of the RQ buffers used for each RQ
 */
#ifndef OCS_HW_RQ_SIZE_HDR
#define OCS_HW_RQ_SIZE_HDR		128
#endif

#ifndef OCS_HW_RQ_SIZE_PAYLOAD
#define OCS_HW_RQ_SIZE_PAYLOAD		1024
#endif

/*
 * @brief Define the maximum number of multi-receive queues
 */
#ifndef OCS_HW_MAX_MRQS
#define OCS_HW_MAX_MRQS			8
#endif

/*
 * @brief Define count of when to set the WQEC bit in a submitted
 * WQE, causing a consummed/released completion to be posted.
 */
#ifndef OCS_HW_WQEC_SET_COUNT
#define OCS_HW_WQEC_SET_COUNT			32
#endif

/*
 * @brief Send frame timeout in seconds
 */
#ifndef OCS_HW_SEND_FRAME_TIMEOUT
#define OCS_HW_SEND_FRAME_TIMEOUT		10
#endif

/*
 * @brief FDT Transfer Hint value, reads greater than this value
 * will be segmented to implement fairness.   A value of zero disables
 * the feature.
 */
#ifndef OCS_HW_FDT_XFER_HINT
#define OCS_HW_FDT_XFER_HINT			8192
#endif

#endif /* !_OCS_HW_H */