aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/cpqfcTSstructs.h
blob: 0bae3298c44b7615a777d775c45bdec83416de71 (plain) (blame)
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
/* Copyright(c) 2000, Compaq Computer Corporation
 * Fibre Channel Host Bus Adapter 64-bit, 66MHz PCI 
 * Originally developed and tested on:
 * (front): [chip] Tachyon TS HPFC-5166A/1.2  L2C1090 ...
 *          SP# P225CXCBFIEL6T, Rev XC
 *          SP# 161290-001, Rev XD
 * (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
 *  
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * Written by Don Zimmerman
*/
#ifndef CPQFCTSSTRUCTS_H
#define CPQFCTSSTRUCTS_H

#include <linux/timer.h>  // timer declaration in our host data
#include <linux/interrupt.h>
#include <asm/atomic.h>
#include "cpqfcTSioctl.h"

#define DbgDelay(secs) { int wait_time; printk( " DbgDelay %ds ", secs); \
                         for( wait_time=jiffies + (secs*HZ); \
		         time_before(jiffies, wait_time) ;) ; }

#define CPQFCTS_DRIVER_VER(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
// don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
#define VER_MAJOR 2
#define VER_MINOR 5
#define VER_SUBMINOR 4

// Macros for kernel (esp. SMP) tracing using a PCI analyzer
// (e.g. x86).
//#define PCI_KERNEL_TRACE
#ifdef PCI_KERNEL_TRACE
#define PCI_TRACE(x) inl( fcChip->Registers.IOBaseL +x);
#define PCI_TRACEO(x,y) outl( x, (fcChip->Registers.IOBaseL +y));
#else

#define PCI_TRACE(x) 
#define PCI_TRACEO(x,y)
#endif

			 
//#define DEBUG_CMND 1   // debug output for Linux Scsi CDBs
//#define DUMMYCMND_DBG 1

//#define DEBUG_CPQFCTS 1
//#undef DEBUG_CPQFCTS 
#ifdef DEBUG_CPQFCTS
#define ENTER(x)	printk("cpqfcts : entering %s()\n", x);
#define LEAVE(x)	printk("cpqfcts : leaving %s()\n", x);
#define DEBUG(x)	x
#else
#define ENTER(x)
#define LEAVE(x)
#define DEBUG(x)
#endif				/* DEBUG_CPQFCTS */

//#define DEBUG_CPQFCTS_PCI 1
//#undef DEBUG_CPQFCTS_PCI
#if DEBUG_CPQFCTS_PCI
#define DEBUG_PCI(x)	x
#else
#define DEBUG_PCI(x)
#endif				/* DEBUG_CPQFCTS_PCI */

#define STACHLITE66_TS12  "Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2"
#define STACHLITE66_TS13  "Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.3"
#define STACHLITE_UNKNOWN "Compaq FibreChannel HBA Tachyon Chip/Board Ver??"
#define SAGILENT_XL2_21   "Agilent FC HBA, Tachyon XL2 HPFC-5200B/2.1"

// PDA is Peripheral Device Address, VSA is Volume Set Addressing
// Linux SCSI parameters
#define CPQFCTS_MAX_TARGET_ID 64

// Note, changing CPQFCTS_MAX_LUN to less than 32 (e.g, 8) will result in
// strange behavior if a box with more than, e.g. 8, is on the loop.
#define CPQFCTS_MAX_LUN 32    // The RA-4x00 supports 32 (Linux SCSI supports 8)
#define CPQFCTS_MAX_CHANNEL 0 // One FC port on cpqfcTS HBA

#define CPQFCTS_CMD_PER_LUN 15 // power of 2 -1, must be >0 
#define CPQFCTS_REQ_QUEUE_LEN (TACH_SEST_LEN/2) // must be < TACH_SEST_LEN

#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
#ifndef DECLARE_MUTEX_LOCKED
#define DECLARE_MUTEX_LOCKED(sem) struct semaphore sem = MUTEX_LOCKED
#endif

#define DEV_NAME "cpqfcTS"

struct SupportedPCIcards
{
  __u16 vendor_id;
  __u16 device_id;
};
			 
// nn:nn denotes bit field
                            // TachyonHeader struct def.
                            // the fields shared with ODB
                            // need to have same value




#ifndef BYTE
//typedef UCHAR BYTE;
typedef __u8 BYTE;
#endif
#ifndef UCHAR
typedef __u8 UCHAR;
#endif
#ifndef LONG
typedef __s32 LONG;
#endif
#ifndef ULONG
typedef __u32 ULONG;
#endif
#ifndef PVOID
typedef void * PVOID;
#endif
#ifndef USHORT
typedef __u16 USHORT;
#endif
#ifndef BOOLEAN
typedef __u8 BOOLEAN;
#endif


// macro for FC-PH reject codes
// payload format for LS_RJT (FC payloads are big endian):
//     byte  0         1         2         3  (MSB)
// DWORD 0   01        00        00        00
// DWORD 1   resvd     code      expl.     vendor

#define LS_RJT_REASON( code, expl) (( code<<8) | (expl <<16))


#define TachLiteSTATUS 0x12

// Fibre Channel EXCHANGE status codes for Tachyon chips/ driver software
// 32-bit ERROR word defines
#define INVALID_ARGS 0x1
#define LNKDWN_OSLS  0x2
#define LNKDWN_LASER 0x4
#define OUTQUE_FULL  0x8
#define DRIVERQ_FULL 0x10
#define SEST_FULL    0x20
#define BAD_ALPA     0x40
#define OVERFLOW     0x80  // inbound CM
#define COUNT_ERROR     0x100  // inbound CM
#define LINKFAIL_RX     0x200  // inbound CM
#define ABORTSEQ_NOTIFY 0x400  // outbound CM
#define LINKFAIL_TX     0x800  // outbound CM
#define HOSTPROG_ERR     0x1000  // outbound CM
#define FRAME_TO         0x2000  // outbound CM
#define INV_ENTRY        0x4000  // outbound CM
#define SESTPROG_ERR     0x8000  // outbound CM
#define OUTBOUND_TIMEOUT 0x10000L // timeout waiting for Tachyon outbound CM
#define INITIATOR_ABORT  0x20000L // initiator exchange timeout or O/S ABORT
#define MEMPOOL_FAIL     0x40000L // O/S memory pool allocation failed
#define FC2_TIMEOUT      0x80000L // driver timeout for lost frames
#define TARGET_ABORT     0x100000L // ABTS received from FC port
#define EXCHANGE_QUEUED  0x200000L // e.g. Link State was LDn on fcStart
#define PORTID_CHANGED   0x400000L // fc Port address changed
#define DEVICE_REMOVED   0x800000L // fc Port address changed
// Several error scenarios result in SEST Exchange frames 
// unexpectedly arriving in the SFQ
#define SFQ_FRAME        0x1000000L // SFQ frames from open Exchange

// Maximum number of Host Bus Adapters (HBA) / controllers supported
// only important for mem allocation dimensions - increase as necessary

#define MAX_ADAPTERS 8
#define MAX_RX_PAYLOAD 1024  // hardware dependent max frame payload
// Tach header struc defines
#define SOFi3 0x7
#define SOFf  0x8
#define SOFn3 0xB
#define EOFn  0x5
#define EOFt  0x6

// FCP R_CTL defines
#define FCP_CMND 0x6
#define FCP_XFER_RDY 0x5
#define FCP_RSP 0x7
#define FCP_RESPONSE 0x777 // (arbitrary #)
#define NEED_FCP_RSP 0x77  // (arbitrary #)
#define FCP_DATA 0x1

#define RESET_TACH 0x100 // Reset Tachyon/TachLite
#define SCSI_IWE 0x2000  // initiator write entry (for SEST)
#define SCSI_IRE 0x3000  // initiator read entry (for SEST)
#define SCSI_TRE 0x400  // target read entry (for SEST)
#define SCSI_TWE 0x500  // target write entry (for SEST)
#define TOGGLE_LASER 0x800
#define LIP 0x900
#define CLEAR_FCPORTS 99 // (arbitrary #) free mem for Logged in ports
#define FMINIT 0x707     // (arbitrary) for Frame Manager Init command

// BLS == Basic Link Service
// ELS == Extended Link Service
#define BLS_NOP 4
#define BLS_ABTS 0x10   // FC-PH Basic Link Service Abort Sequence
#define BLS_ABTS_ACC 0x100  // FC-PH Basic Link Service Abort Sequence Accept
#define BLS_ABTS_RJT 0x101  // FC-PH Basic Link Service Abort Sequence Reject
#define ELS_PLOGI 0x03  // FC-PH Port Login (arbitrary assign)
#define ELS_SCR   0x70  // (arb assign) State Change Registration (Fabric)
#define FCS_NSR   0x72  // (arb assign) Name Service Request (Fabric)
#define ELS_FLOGI 0x44  // (arb assign) Fabric Login
#define ELS_FDISC 0x41  // (arb assign) Fabric Discovery (Login)
#define ELS_PDISC 0x50  // FC-PH2 Port Discovery
#define ELS_ABTX  0x06  // FC-PH Abort Exchange 
#define ELS_LOGO 0x05   // FC-PH Port Logout
#define ELS_PRLI 0x20   // FCP-SCSI Process Login
#define ELS_PRLO 0x21   // FCP-SCSI Process Logout
#define ELS_LOGO_ACC 0x07   // {FC-PH} Port Logout Accept
#define ELS_PLOGI_ACC 0x08  // {FC-PH} Port Login Accept
#define ELS_ACC 0x18        // {FC-PH} (generic) ACCept
#define ELS_PRLI_ACC 0x22  // {FCP-SCSI} Process Login Accept
#define ELS_RJT 0x1000000
#define SCSI_REPORT_LUNS 0x0A0
#define FCP_TARGET_RESET 0x200

#define ELS_LILP_FRAME 0x00000711 // 1st payload word of LILP frame

#define SFQ_UNASSISTED_FCP  1  // ICM, DWord3, "Type" unassisted FCP
#define SFQ_UNKNOWN         0x31 // (arbitrary) ICM, DWord3, "Type" unknown

// these "LINK" bits refer to loop or non-loop
#define LINKACTIVE 0x2    // fcLinkQ type - LINK UP Tachyon FM 'Lup' bit set
#define LINKDOWN 0xf2     // fcLinkQ type - LINK DOWN Tachyon FM 'Ldn' bit set

//#define VOLUME_SET_ADDRESSING 1 // "channel" or "bus" 1

typedef struct      // 32 bytes hdr ONLY (e.g. FCP_DATA buffer for SEST)
{
  ULONG reserved;   // dword 0 (don't use)
  ULONG sof_eof;
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;         // dword 7 - relative offset
} TachFCHDR;

                    // NOTE!! the following struct MUST be 64 bytes.
typedef struct      // 32 bytes hdr + 32 bytes payload
{
  ULONG reserved;   // dword 0 (don't use - must clear to 0)
  ULONG sof_eof;    // dword 1 - 31:24 SOF:EOF, UAM,CLS, LCr, TFV, TimeStamp
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;  // dword 7 - relative offset
//---------
  __u32 pl[8];              // dwords 8-15 frame data payload
} TachFCHDR_CMND;


typedef struct      // 32 bytes hdr + 120 bytes payload
{
  ULONG reserved;   // dword 0 (don't use - must clear to 0)
  ULONG sof_eof;    // dword 1 - 31:24 SOF:EOF, UAM,CLS, LCr, TFV, TimeStamp
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;  // dword 7 - relative offset
//---------
  __u32 pl[30];              // largest necessary payload (for LOGIN cmnds)
} TachFCHDR_GCMND;

typedef struct      // 32 bytes hdr + 64 bytes payload
{
  ULONG reserved;   // dword 0 (don't use)
  ULONG sof_eof;
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;  // dword 7 - relative offset
//---------
  __u32 pl[18]; // payload for FCP-RSP (response buffer) RA-4x00 is 72bytes
} TachFCHDR_RSP;






// Inbound Message Queue structures...
typedef struct              // each entry 8 words (32 bytes)
{
  ULONG type;               // IMQ completion message types
  ULONG word[7];            // remainder of structure
                            // interpreted by IMQ type
} TachyonIMQE;


// Queues for TachLite not in original Tachyon
// ERQ       - Exchange Request Queue (for outbound commands)
// SFQ       - Single Frame Queue (for incoming frames)

                            // Define Tachyon Outbound Command Que
                            // (Since many Tachyon registers are Read
                            // only, maintain copies for debugging)
                            // most Tach ques need power-of-2 sizes,
                            // where registers are loaded with po2 -1
#define TACH_SEST_LEN 512   // TachLite SEST

#define ELS_EXCHANGES 64    // e.g. PLOGI, RSCN, ...
// define the total number of outstanding (simultaneous) exchanges
#define TACH_MAX_XID (TACH_SEST_LEN + ELS_EXCHANGES)  // ELS exchanges

#define ERQ_LEN 128         // power of 2, max 4096

// Inbound Message Queue structures...
#define IMQ_LEN 512              // minimum 4 entries [(power of 2) - 1]
typedef struct                   // 8 words - 32 bytes
{
  TachyonIMQE QEntry[IMQ_LEN];
  ULONG producerIndex;   // IMQ Producer Index register
                                 // @32 byte align
  ULONG consumerIndex;   // Consumer Index register (in Tachyon)
  ULONG length;          // Length register
  ULONG base;
} TachyonIMQ;                    // @ 32 * IMQ_LEN align



typedef struct           // inbound completion message
{
  ULONG Type;
  ULONG Index;
  ULONG TransferLength;
} TachyonInbCM;



// arbitrary numeric tags for TL structures
#define TL_FCHS 1  // TachLite Fibre Channel Header Structure
#define TL_IWE 2  // initiator write entry (for SEST)
#define TL_TWE 3  // target write entry (for SEST)
#define TL_IRE 4  // initiator read entry (for SEST)
#define TL_TRE 5  // target read entry (for SEST)
#define TL_IRB 6  // I/O request block

                                // for INCOMING frames
#define SFQ_LEN 32              // minimum 32 entries, max 4096

typedef struct                  // Single Frame Que
{
  TachFCHDR_CMND QEntry[SFQ_LEN]; // must be 64 bytes!!
  ULONG producerIndex;   // IMQ Producer Index register
                                 // @32 byte align
  ULONG consumerIndex;   // Consumer Index register (in Tachyon)
  ULONG length;          // Length register
  ULONG base;
} TachLiteSFQ;


typedef struct                 // I/O Request Block flags
{
  UCHAR  BRD : 1;
  UCHAR      : 1; // reserved
  UCHAR  SFA : 1;
  UCHAR  DNC : 1;
  UCHAR  DIN : 1;
  UCHAR  DCM : 1;
  UCHAR  CTS : 1;
  UCHAR  SBV : 1;  // IRB entry valid - IRB'B' only
} IRBflags;

typedef struct                  // I/O Request Block
{                          // Request 'A'
  ULONG Req_A_SFS_Len;     // total frame len (hdr + payload), min 32
  ULONG Req_A_SFS_Addr;    // 32-bit pointer to FCHS struct (to be sent)
  ULONG Req_A_SFS_D_ID;    // 24-bit FC destination (i.e. 8 bit al_pa)
  ULONG Req_A_Trans_ID;    // X_ID (OX_ID or RX_ID) and/or Index in SEST
                           // Request 'B'
  ULONG Req_B_SFS_Len;     // total frame len (hdr + payload), min 32
  ULONG Req_B_SFS_Addr;    // 32-bit pointer to FCHS struct (to be sent)
  ULONG Req_B_SFS_D_ID;    // 24-bit FC destination (i.e. 8 bit al_pa)
  ULONG Req_B_Trans_ID;    // X_ID (OX_ID or RX_ID) and/or Index in SEST
} TachLiteIRB;


typedef struct           // TachLite placeholder for IRBs
{                        // aligned @sizeof(ERQ) for TachLite
                         // MAX commands is sum of SEST len and ERQ
                         // we know that each SEST entry requires an
                         // IRB (ERQ) entry; in addition, we provide
                         // ERQ_LEN
  TachLiteIRB QEntry[ERQ_LEN]; // Base register; entries 32 bytes ea.
  ULONG consumerIndex;   // Consumer Index register
  ULONG producerIndex;   // ERQ Producer Index register
  ULONG length;          // Length register
  ULONG base;            // copy of base ptr for debug
                         // struct is sized for largest expected cmnd (LOGIN)
} TachLiteERQ;

// for now, just 32 bit DMA, eventually 40something, with code changes
#define CPQFCTS_DMA_MASK ((unsigned long) (0x00000000FFFFFFFF))

#define TL_MAX_SG_ELEM_LEN 0x7ffff  // Max buffer length a single S/G entry
				// may represent (a hardware limitation).  The
				// only reason to ever change this is if you
				// want to exercise very-hard-to-reach code in
				// cpqfcTSworker.c:build_SEST_sglist().

#define TL_DANGER_SGPAGES 7  // arbitrary high water mark for # of S/G pages
				// we must exceed to elicit a warning indicative
				// of EXTREMELY large data transfers or 
				// EXTREME memory fragmentation.
				// (means we just used up 2048 S/G elements,
				// Never seen this is real life, only in 
				// testing with tricked up driver.)

#define TL_EXT_SG_PAGE_COUNT 256  // Number of Extended Scatter/Gather a/l PAIRS
                                  // Tachyon register (IOBaseU 0x68)
                                  // power-of-2 value ONLY!  4 min, 256 max

                          // byte len is #Pairs * 2 ULONG/Pair * 4 bytes/ULONG
#define TL_EXT_SG_PAGE_BYTELEN (TL_EXT_SG_PAGE_COUNT *2 *4)



// SEST entry types: IWE, IRE, TWE, TRE
typedef struct 
{
  ULONG Hdr_Len;
  ULONG Hdr_Addr;
  ULONG RSP_Len;
  ULONG RSP_Addr;
  ULONG Buff_Off;
#define USES_EXTENDED_SGLIST(this_sest, x_ID) \
	(!((this_sest)->u[ x_ID ].IWE.Buff_Off & 0x80000000))
  ULONG Link;
  ULONG RX_ID;
  ULONG Data_Len;
  ULONG Exp_RO;
  ULONG Exp_Byte_Cnt;
   // --- extended/local Gather Len/Address pairs
  ULONG GLen1;
  ULONG GAddr1;
  ULONG GLen2;
  ULONG GAddr2;
  ULONG GLen3;
  ULONG GAddr3;
} TachLiteIWE;


typedef struct 
{
  ULONG Seq_Accum;
  ULONG reserved;       // must clear to 0
  ULONG RSP_Len;
  ULONG RSP_Addr;
  ULONG Buff_Off;
  ULONG Buff_Index;           // ULONG 5
  ULONG Exp_RO;
  ULONG Byte_Count;
  ULONG reserved_;      // ULONG 8
  ULONG Exp_Byte_Cnt;
   // --- extended/local Scatter Len/Address pairs
  ULONG SLen1;
  ULONG SAddr1;
  ULONG SLen2;
  ULONG SAddr2;
  ULONG SLen3;
  ULONG SAddr3;
} TachLiteIRE;


typedef struct          // Target Write Entry
{
  ULONG Seq_Accum;      // dword 0
  ULONG reserved;       // dword 1  must clear to 0
  ULONG Remote_Node_ID;
  ULONG reserved1;      // dword 3  must clear to 0
  ULONG Buff_Off;
  ULONG Buff_Index;     // ULONG 5
  ULONG Exp_RO;
  ULONG Byte_Count;
  ULONG reserved_;      // ULONG 8
  ULONG Exp_Byte_Cnt;
   // --- extended/local Scatter Len/Address pairs
  ULONG SLen1;
  ULONG SAddr1;
  ULONG SLen2;
  ULONG SAddr2;
  ULONG SLen3;
  ULONG SAddr3;
} TachLiteTWE;

typedef struct      
{
  ULONG Hdr_Len;
  ULONG Hdr_Addr;
  ULONG RSP_Len;        // DWord 2
  ULONG RSP_Addr;
  ULONG Buff_Off;
  ULONG Buff_Index;     // DWord 5
  ULONG reserved;
  ULONG Data_Len;
  ULONG reserved_;
  ULONG reserved__;
   // --- extended/local Gather Len/Address pairs
  ULONG GLen1;          // DWord A
  ULONG GAddr1;
  ULONG GLen2;
  ULONG GAddr2;
  ULONG GLen3;
  ULONG GAddr3;
} TachLiteTRE;

typedef struct ext_sg_page_ptr_t *PSGPAGES;
typedef struct ext_sg_page_ptr_t 
{
  unsigned char page[TL_EXT_SG_PAGE_BYTELEN * 2]; // 2x for alignment
  dma_addr_t busaddr; 	// need the bus addresses and
  unsigned int maplen;  // lengths for later pci unmapping.
  PSGPAGES next;
} SGPAGES; // linked list of S/G pairs, by Exchange

typedef struct                  // SCSI Exchange State Table
{
  union                         // Entry can be IWE, IRE, TWE, TRE
  {                             // 64 bytes per entry
    TachLiteIWE IWE;
    TachLiteIRE IRE;
    TachLiteTWE TWE;
    TachLiteTRE TRE;
  } u[TACH_SEST_LEN];

  TachFCHDR DataHDR[TACH_SEST_LEN]; // for SEST FCP_DATA frame hdr (no pl)
  TachFCHDR_RSP RspHDR[TACH_SEST_LEN]; // space for SEST FCP_RSP frame
  PSGPAGES sgPages[TACH_SEST_LEN]; // head of linked list of Pool-allocations
  ULONG length;          // Length register
  ULONG base;            // copy of base ptr for debug
} TachSEST;



typedef struct                  // each register has it's own address
                                // and value (used for write-only regs)
{
  void* address;
  volatile ULONG value;
} FCREGISTER;

typedef struct         // Host copy - TachLite Registers
{
  ULONG IOBaseL, IOBaseU;  // I/O port lower and upper TL register addresses
  ULONG MemBase;           // memory mapped register addresses
  void* ReMapMemBase;      // O/S VM reference for MemBase
  ULONG wwn_hi;            // WWN is set once at startup
  ULONG wwn_lo;
  ULONG my_al_pa;          // al_pa received after LIP()
  ULONG ROMCTR;            // flags for on-board RAM/ROM
  ULONG RAMBase;           // on-board RAM (i.e. some Tachlites)
  ULONG SROMBase;          // on-board EEPROM (some Tachlites)
  ULONG PCIMCTR;           // PCI Master Control Reg (has bus width)

  FCREGISTER INTEN;        // copy of interrupt enable mask
  FCREGISTER INTPEND;      // interrupt pending
  FCREGISTER INTSTAT;      // interrupt status
  FCREGISTER SFQconsumerIndex; 
  FCREGISTER ERQproducerIndex; 
  FCREGISTER TYconfig;   // TachYon (chip level)
  FCREGISTER TYcontrol;
  FCREGISTER TYstatus;
  FCREGISTER FMconfig;   // Frame Manager (FC loop level)
  FCREGISTER FMcontrol;
  FCREGISTER FMstatus;
  FCREGISTER FMLinkStatus1;
  FCREGISTER FMLinkStatus2;
  FCREGISTER FMBB_CreditZero;
  FCREGISTER status;
  FCREGISTER ed_tov;     // error detect time-out value
  FCREGISTER rcv_al_pa;  // received arb. loop physical address
  FCREGISTER primitive;  // e.g. LIP(), OPN(), ...
} TL_REGISTERS;



typedef struct 
{
  ULONG ok;
  ULONG invalidArgs;
  ULONG linkDown;
  ULONG linkUp;
  ULONG outQueFull;
  ULONG SESTFull;
  ULONG hpe;    // host programming err (from Tach)
  ULONG FC4aborted; // aborts from Application or upper driver layer
  ULONG FC2aborted; // aborts from our driver's timeouts
  ULONG timeouts;   // our driver timeout (on individual exchanges)
  ULONG logouts;    // explicit - sent LOGO; implicit - device removed
  ULONG retries;
  ULONG linkFailTX;
  ULONG linkFailRX;
  ULONG CntErrors;  // byte count expected != count received (typ. SEST)
  ULONG e_stores;   // elastic store errs
  ULONG resets;     // hard or soft controller resets
  ULONG FMinits;    // TACH Frame Manager Init (e.g. LIPs)
  ULONG lnkQueFull;  // too many LOGIN, loop commands
  ULONG ScsiQueFull; // too many FCP-SCSI inbound frames
  ULONG LossofSignal;   // FM link status 1 regs
  ULONG BadRXChar;   // FM link status 1 regs
  ULONG LossofSync;   // FM link status 1 regs
  ULONG Rx_EOFa;   // FM link status 2 regs (received EOFa)
  ULONG Dis_Frm;   // FM link status 2 regs (discarded frames)
  ULONG Bad_CRC;   // FM link status 2 regs
  ULONG BB0_Timer; //  FM BB_Credit Zero Timer Reg
  ULONG loopBreaks; // infinite loop exits
  ULONG lastBB0timer;  // static accum. buffer needed by Tachlite
} FCSTATS;


typedef struct               // Config Options
{                            // LS Bit first
  USHORT        : 1;           // bit0:
  USHORT  flogi : 1;           // bit1: We sent FLOGI - wait for Fabric logins
  USHORT  fabric: 1;           // bit2: Tachyon detected Fabric (FM stat LG)
  USHORT  LILPin: 1;           // bit3: We can use an FC-AL LILP frame
  USHORT  target: 1;           // bit4: this Port has SCSI target capability
  USHORT  initiator:    1;     // bit5: this Port has SCSI initiator capability
  USHORT  extLoopback:  1;     // bit6: loopback at GBIC
  USHORT  intLoopback:  1;     // bit7: loopback in HP silicon
  USHORT        : 1;           // bit8:
  USHORT        : 1;           // bit9:
  USHORT        : 1;           // bit10:
  USHORT        : 1;           // bit11:
  USHORT        : 1;           // bit12:
  USHORT        : 1;           // bit13:
  USHORT        : 1;           // bit14:
  USHORT        : 1;           // bit15:
} FC_OPTIONS;



typedef struct dyn_mem_pair
{
  void *BaseAllocated;  // address as allocated from O/S;
  unsigned long AlignedAddress; // aligned address (used by Tachyon DMA)
  dma_addr_t dma_handle;
  size_t size;
} ALIGNED_MEM;




// these structs contain only CRUCIAL (stuff we actually use) parameters
// from FC-PH(n) logins.  (Don't save entire LOGIN payload to save mem.)

// Implicit logout happens when the loop goes down - we require PDISC
// to restore.  Explicit logout is when WE decide never to talk to someone,
// or when a target refuses to talk to us, i.e. sends us a LOGO frame or
// LS_RJT reject in response to our PLOGI request.

#define IMPLICIT_LOGOUT 1
#define EXPLICIT_LOGOUT 2

typedef struct 
{
  UCHAR channel; // SCSI "bus"
  UCHAR target;
  UCHAR InqDeviceType;  // byte 0 from SCSI Inquiry response
  UCHAR VolumeSetAddressing;  // FCP-SCSI LUN coding (40h for VSA)
  UCHAR LunMasking;     // True if selective presentation supported
  UCHAR lun[CPQFCTS_MAX_LUN];
} SCSI_NEXUS;


typedef struct        
{
  union 
  {
    UCHAR ucWWN[8];  // a FC 64-bit World Wide Name/ PortID of target
                     // addressing of single target on single loop...
    u64 liWWN;
  } u;

  ULONG port_id;     // a FC 24-bit address of port (lower 8 bits = al_pa)

#define REPORT_LUNS_PL 256  
  UCHAR ReportLunsPayload[REPORT_LUNS_PL];
  
  SCSI_NEXUS ScsiNexus; // LUNs per FC device

  ULONG LOGO_counter; // might try several times before logging out for good
  ULONG LOGO_timer;   // after LIP, ports expecting PDISC must time-out and
                      // LOGOut if successful PDISC not completed in 2 secs

  ULONG concurrent_seq;  // must be 1 or greater
  ULONG rx_data_size;    // e.g. 128, 256, 1024, 2048 per FC-PH spec
  ULONG BB_credit;
  ULONG EE_credit;

  ULONG fcp_info;        // from PRLI (i.e. INITIATOR/ TARGET flags)
                         // flags for login process
  BOOLEAN Originator;    // Login sequence Originated (if false, we
                         // responded to another port's login sequence)
  BOOLEAN plogi;         // PLOGI frame ACCepted (originated or responded)
  BOOLEAN pdisc;         // PDISC frame was ORIGINATED (self-login logic)
  BOOLEAN prli;          // PRLI frame ACCepted (originated or responded)
  BOOLEAN flogi;         // FLOGI frame ACCepted (originated or responded)
  BOOLEAN logo;          // port permanently logged out (invalid login param)
  BOOLEAN flogiReq;      // Fabric login required (set in LIP process)
  UCHAR highest_ver;
  UCHAR lowest_ver;

  
  // when the "target" (actually FC Port) is waiting for login
  // (e.g. after Link reset), set the device_blocked bit;
  // after Port completes login, un-block target.
  UCHAR device_blocked; // see Scsi_Device struct

                    // define singly-linked list of logged-in ports
                    // once a port_id is identified, it is remembered,
                    // even if the port is removed indefinitely
  PVOID pNextPort;  // actually, type PFC_LOGGEDIN_PORT; void for Compiler

} FC_LOGGEDIN_PORT, *PFC_LOGGEDIN_PORT;



// This serves as the ESB (Exchange Status Block),
// and has timeout counter; used for ABORTs
typedef struct                
{                                  // FC-1 X_IDs
  ULONG type;            // ELS_PLOGI, SCSI_IWE, ... (0 if free)
  PFC_LOGGEDIN_PORT pLoggedInPort; // FC device on other end of Exchange
  Scsi_Cmnd *Cmnd;       // Linux SCSI command packet includes S/G list
  ULONG timeOut;         // units of ??, DEC by driver, Abort when 0
  ULONG reTries;         // need one or more retries?
  ULONG status;          // flags indicating errors (0 if none)
  TachLiteIRB IRB;       // I/O Request Block, gets copied to ERQ
  TachFCHDR_GCMND fchs;  // location of IRB's Req_A_SFS_Addr
} FC_EXCHANGE, *PFC_EXCHANGE;

// Unfortunately, Linux limits our kmalloc() allocations to 128k.
// Because of this and the fact that our ScsiRegister allocation
// is also constrained, we move this large structure out for
// allocation after Scsi Register.
// (In other words, this cumbersome indirection is necessary
// because of kernel memory allocation constraints!)

typedef struct // we will allocate this dynamically
{
  FC_EXCHANGE fcExchange[ TACH_MAX_XID ];
} FC_EXCHANGES;











typedef struct
{
  char Name[64]; // name of controller ("HP Tachlite TL Rev2.0, 33MHz, 64bit bus")
  //PVOID  pAdapterDevExt; // back pointer to device object/extension
  ULONG ChipType;        // local numeric key for Tachyon Type / Rev.
  ULONG status;              // our Driver - logical status
  
  TL_REGISTERS Registers;    // reg addresses & host memory copies
                             // FC-4 mapping of 'transaction' to X_IDs
  UCHAR LILPmap[32*4];       // Loop Position Map of ALPAs (late FC-AL only)
  FC_OPTIONS Options;        // e.g. Target, Initiator, loopback...
  UCHAR highest_FCPH_ver;    // FC-PH version limits
  UCHAR lowest_FCPH_ver;     // FC-PH version limits

  FC_EXCHANGES *Exchanges;  
  ULONG fcLsExchangeLRU;       // Least Recently Used counter (Link Service)
  ULONG fcSestExchangeLRU;       // Least Recently Used counter (FCP-SCSI)
  FC_LOGGEDIN_PORT fcPorts;  // linked list of every FC port ever seen
  FCSTATS fcStats;           // FC comm err counters

                             // Host memory QUEUE pointers
  TachLiteERQ *ERQ;          // Exchange Request Que 
  TachyonIMQ *IMQ;           // Inbound Message Que 
  TachLiteSFQ *SFQ;          // Single Frame Queue
  TachSEST *SEST;            // SCSI Exchange State Table

  dma_addr_t exch_dma_handle;

  // these function pointers are for "generic" functions, which are
  // replaced with Host Bus Adapter types at
  // runtime.
  int (*CreateTachyonQues)( void* , int);
  int (*DestroyTachyonQues)( void* , int);
  int (*LaserControl)(void*, int );   // e.g. On/Off
  int (*ResetTachyon)(void*, int );
  void (*FreezeTachyon)(void*, int );
  void (*UnFreezeTachyon)(void*, int );
  int (*InitializeTachyon)(void*, int, int );
  int (*InitializeFrameManager)(void*, int );
  int (*ProcessIMQEntry)(void*);
  int (*ReadWriteWWN)(void*, int ReadWrite);
  int (*ReadWriteNVRAM)(void*, void*, int ReadWrite);

} TACHYON, *PTACHYON;


void cpqfcTSClearLinkStatusCounters(TACHYON * fcChip);

int CpqTsCreateTachLiteQues( void* pHBA, int opcode);
int CpqTsDestroyTachLiteQues( void* , int);
int CpqTsInitializeTachLite( void *pHBA, int opcode1, int opcode2);

int CpqTsProcessIMQEntry(void* pHBA);
int CpqTsResetTachLite(void *pHBA, int type);
void CpqTsFreezeTachlite(void *pHBA, int type);
void CpqTsUnFreezeTachlite(void *pHBA, int type);
int CpqTsInitializeFrameManager(void *pHBA, int);
int CpqTsLaserControl( void* addrBase, int opcode );
int CpqTsReadWriteWWN(void*, int ReadWrite);
int CpqTsReadWriteNVRAM(void*, void* data, int ReadWrite);

void cpqfcTS_WorkTask( struct Scsi_Host *HostAdapter);
void cpqfcTSWorkerThread( void *host);

int cpqfcTS_GetNVRAM_data( UCHAR *wwnbuf, UCHAR *buf );
ULONG cpqfcTS_ReadNVRAM( void* GPIOin, void* GPIOout , USHORT count,
	UCHAR *buf );

BOOLEAN tl_write_i2c_nvram( void* GPIOin, void* GPIOout,
  USHORT startOffset,  // e.g. 0x2f for WWN start
  USHORT count,
  UCHAR *buf );


// define misc functions 
int cpqfcTSGetLPSM( PTACHYON fcChip, char cErrorString[]);
int cpqfcTSDecodeGBICtype( PTACHYON fcChip, char cErrorString[]);
void* fcMemManager( struct pci_dev *pdev,
		ALIGNED_MEM *dyn_mem_pair, ULONG n_alloc, ULONG ab,
                   ULONG ulAlignedAddress, dma_addr_t *dma_handle);

void BigEndianSwap(  UCHAR *source, UCHAR *dest,  USHORT cnt);

//ULONG virt_to_phys( PVOID virtaddr );
                  

// Linux interrupt handler
irqreturn_t cpqfcTS_intr_handler( int irq,void *dev_id,struct pt_regs *regs);
void cpqfcTSheartbeat( unsigned long ptr );



// The biggest Q element we deal with is Aborts - we
// need 4 bytes for x_ID, and a Scsi_Cmnd (~284 bytes)
//#define LINKQ_ITEM_SIZE ((4+sizeof(Scsi_Cmnd)+3)/4)
#define LINKQ_ITEM_SIZE (3*16)
typedef struct
{
  ULONG Type;              // e.g. LINKUP, SFQENTRY, PDISC, BLS_ABTS, ...
  ULONG ulBuff[ LINKQ_ITEM_SIZE ];
} LINKQ_ITEM;

#define FC_LINKQ_DEPTH TACH_MAX_XID
typedef struct
{
  ULONG producer;
  ULONG consumer;  // when producer equals consumer, Q empty

  LINKQ_ITEM Qitem[ FC_LINKQ_DEPTH ];

} FC_LINK_QUE, *PFC_LINK_QUE;


     // DPC routines post to here on Inbound SCSI frames
     // User thread processes
#define FC_SCSIQ_DEPTH 32

typedef struct
{
  int Type;              // e.g. SCSI
  ULONG ulBuff[ 3*16 ];
} SCSIQ_ITEM;

typedef struct
{
  ULONG producer;
  ULONG consumer;  // when producer equals consumer, Q empty

  SCSIQ_ITEM Qitem[ FC_SCSIQ_DEPTH ];

} FC_SCSI_QUE, *PFC_SCSI_QUE;

typedef struct {
	/* This is tacked on to a Scsi_Request in upper_private_data 
	   for pasthrough ioctls, as a place to hold data that can't 
	   be stashed anywhere else in the Scsi_Request.  We differentiate
	   this from _real_ upper_private_data by checking if the virt addr
	   is within our special pool.  */
	ushort bus;
	ushort pdrive;
} cpqfc_passthru_private_t;

#define CPQFC_MAX_PASSTHRU_CMDS 100

#define DYNAMIC_ALLOCATIONS 4  // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST

// Linux space allocated per HBA (chip state, etc.)
typedef struct 
{
  struct Scsi_Host *HostAdapter; // back pointer to Linux Scsi struct

  TACHYON fcChip;    // All Tachyon registers, Queues, functions
  ALIGNED_MEM dynamic_mem[DYNAMIC_ALLOCATIONS];

  struct pci_dev *PciDev;
  dma_addr_t fcLQ_dma_handle;

  Scsi_Cmnd *LinkDnCmnd[CPQFCTS_REQ_QUEUE_LEN]; // collects Cmnds during LDn
                                                // (for Acceptable targets)
  Scsi_Cmnd *BoardLockCmnd[CPQFCTS_REQ_QUEUE_LEN]; // SEST was full
  
  Scsi_Cmnd *BadTargetCmnd[CPQFCTS_MAX_TARGET_ID]; // missing targets

  u_char HBAnum;     // 0-based host number


  struct timer_list cpqfcTStimer; // FC utility timer for implicit
                                  // logouts, FC protocol timeouts, etc.
  int fcStatsTime;  // Statistics delta reporting time

  struct task_struct *worker_thread; // our kernel thread
  int PortDiscDone;    // set by SendLogins(), cleared by LDn
  
  struct semaphore *TachFrozen;
  struct semaphore *TYOBcomplete;    // handshake for Tach outbound frames
  struct semaphore *fcQueReady;      // FibreChannel work for our kernel thread
  struct semaphore *notify_wt;       // synchronizes kernel thread kill
  struct semaphore *BoardLock;
  
  PFC_LINK_QUE fcLQ;             // the WorkerThread operates on this

  spinlock_t hba_spinlock;           // held/released by WorkerThread
  cpqfc_passthru_private_t *private_data_pool;
  unsigned long *private_data_bits;

} CPQFCHBA;

#define	CPQ_SPINLOCK_HBA( x )   spin_lock(&x->hba_spinlock);
#define CPQ_SPINUNLOCK_HBA(x)   spin_unlock(&x->hba_spinlock);



void cpqfcTSImplicitLogout( CPQFCHBA* cpqfcHBAdata,
		PFC_LOGGEDIN_PORT pFcPort);


void cpqfcTSTerminateExchange( CPQFCHBA*, SCSI_NEXUS *target, int );

PFC_LOGGEDIN_PORT fcPortLoggedIn( 
   CPQFCHBA *cpqfcHBAdata, 
   TachFCHDR_GCMND* fchs, 
   BOOLEAN, 
   BOOLEAN);
void fcProcessLoggedIn( 
   CPQFCHBA *cpqfcHBAdata, TachFCHDR_GCMND* fchs);


ULONG cpqfcTSBuildExchange( 
  CPQFCHBA *cpqfcHBAdata,
  ULONG type, // e.g. PLOGI
  TachFCHDR_GCMND* InFCHS,  // incoming FCHS
  void *Data,               // the CDB, scatter/gather, etc.  
  LONG *ExchangeID );       // allocated exchange ID

ULONG cpqfcTSStartExchange( 
  CPQFCHBA *cpqfcHBAdata,
  LONG ExchangeID );

void cpqfcTSCompleteExchange( 
       struct pci_dev *pcidev,
       PTACHYON fcChip, 
       ULONG exchange_ID);


PFC_LOGGEDIN_PORT  fcFindLoggedInPort( 
  PTACHYON fcChip, 
  Scsi_Cmnd *Cmnd,  // (We want the channel/target/lun Nexus from Cmnd)
  ULONG port_id,  // search linked list for al_pa, or
  UCHAR wwn[8],    // search linked list for WWN, or...
  PFC_LOGGEDIN_PORT *pLastLoggedInPort
);

void cpqfcTSPutLinkQue( 
  CPQFCHBA *cpqfcHBAdata, 
  int Type, 
  void *QueContent);

void fcPutScsiQue( 
  CPQFCHBA *cpqfcHBAdata, 
  int Type, 
  void *QueContent);

void fcLinkQReset(
   CPQFCHBA *);
void fcScsiQReset(
   CPQFCHBA *);
void fcSestReset(
   CPQFCHBA *);

void cpqfc_pci_unmap(struct pci_dev *pcidev, 
	Scsi_Cmnd *cmd, 
	PTACHYON fcChip, 
	ULONG x_ID);

extern const UCHAR valid_al_pa[];
extern const int number_of_al_pa;

#define FCP_RESID_UNDER   0x80000
#define FCP_RESID_OVER    0x40000
#define FCP_SNS_LEN_VALID 0x20000
#define FCP_RSP_LEN_VALID 0x10000

// RSP_CODE definitions (dpANS Fibre Channel Protocol for SCSI, pg 34)
#define FCP_DATA_LEN_NOT_BURST_LEN 0x1000000
#define FCP_CMND_FIELD_INVALID     0x2000000
#define FCP_DATA_RO_NOT_XRDY_RO    0x3000000
#define FCP_TASKFUNCTION_NS        0x4000000
#define FCP_TASKFUNCTION_FAIL      0x5000000

// FCP-SCSI response status struct
typedef struct  // see "TachFCHDR_RSP" definition - 64 bytes
{
  __u32 reserved;
  __u32 reserved1;
  __u32 fcp_status;    // field validity and SCSI status
  __u32 fcp_resid;
  __u32 fcp_sns_len;   // length of FCP_SNS_INFO field
  __u32 fcp_rsp_len;   // length of FCP_RSP_INFO field (expect 8)
  __u32 fcp_rsp_info;  // 4 bytes of FCP protocol response information
  __u32 fcp_rsp_info2; // (4 more bytes, since most implementations use 8)
  __u8  fcp_sns_info[36]; // bytes for SCSI sense (ASC, ASCQ)

} FCP_STATUS_RESPONSE, *PFCP_STATUS_RESPONSE;


// Fabric State Change Registration
typedef struct scrpl
{
  __u32 command;
  __u32 function;
} SCR_PL;

// Fabric Name Service Request
typedef struct nsrpl
{
  __u32 CT_Rev;  // (& IN_ID)   WORD 0
  __u32 FCS_Type;            // WORD 1
  __u32 Command_code;        // WORD 2
  __u32 reason_code;         // WORD 3
  __u32 FCP;                 // WORD 4 (lower byte)
  
} NSR_PL;



// "FC.H"
#define MAX_RX_SIZE		0x800	// Max Receive Buffer Size is 2048
#define MIN_RX_SIZE		0x100	// Min Size is 256, per FC-PLDA Spec
#define	MAX_TARGET_RXIDS	SEST_DEPTH
#define TARGET_RX_SIZE		SEST_BUFFER_LENGTH

#define CLASS_1			0x01
#define CLASS_2			0x02
#define CLASS_3			0x03

#define FC_PH42			0x08
#define FC_PH43			0x09
#define FC_PH3			0x20

#define RR_TOV			2	// Minimum Time for target to wait for
					// PDISC after a LIP.
#define E_D_TOV			2	// Minimum Time to wait for Sequence
					// Completion.
#define R_A_TOV			0	// Minimum Time for Target to wait 
					// before reclaiming resources.
//
//	R_CTL Field
//
//	Routing Bits (31-28)
//
#define FC4_DEVICE_DATA		0x00000000
#define EXT_LINK_DATA		0x20000000
#define FC4_LINK_DATA		0x30000000
#define VIDEO_DATA		0x40000000
#define BASIC_LINK_DATA		0x80000000
#define LINK_CONTROL		0xC0000000
#define ROUTING_MASK		0xF0000000

//
//	Information Bits (27-24)
//
#define UNCAT_INFORMATION	0x00000000
#define SOLICITED_DATA		0x01000000
#define UNSOLICITED_CONTROL	0x02000000
#define SOLICITED_CONTROL	0x03000000
#define UNSOLICITED_DATA	0x04000000
#define DATA_DESCRIPTOR		0x05000000
#define UNSOLICITED_COMMAND	0x06000000
#define COMMAND_STATUS		0x07000000
#define INFO_MASK		0x0F000000
//
//	(Link Control Codes)
//
#define ACK_1			0x00000000
#define ACK_0_OR_N		0x01000000
#define P_RJT			0x02000000 
#define F_RJT			0x03000000 
#define P_BSY			0x04000000
#define FABRIC_BUSY_TO_DF	0x05000000	// Fabric Busy to Data Frame
#define FABRIC_BUSY_TO_LC	0x06000000	// Fabric Busy to Link Ctl Frame
#define LINK_CREDIT_RESET	0x07000000
//
//	(Link Service Command Codes)
//
//#define LS_RJT			0x01000000	// LS Reject

#define LS_ACC			0x02000000	// LS Accept
#define LS_PLOGI		0x03000000	// N_PORT Login
#define LS_FLOGI		0x04000000	// F_PORT Login
#define LS_LOGO			0x05000000	// Logout
#define LS_ABTX			0x06000000	// Abort Exchange
#define LS_RCS			0x07000000	// Read Connection Status
#define LS_RES			0x08000000	// Read Exchange Status
#define LS_RSS			0x09000000	// Read Sequence Status
#define LS_RSI			0x0A000000	// Request Seq Initiative
#define LS_ESTS			0x0B000000	// Establish Steaming
#define LS_ESTC			0x0C000000	// Estimate Credit
#define LS_ADVC			0x0D000000	// Advice Credit
#define LS_RTV			0x0E000000	// Read Timeout Value
#define LS_RLS			0x0F000000	// Read Link Status
#define LS_ECHO			0x10000000	// Echo
#define LS_TEST			0x11000000	// Test
#define LS_RRQ			0x12000000	// Reinstate Rec. Qual.
#define LS_PRLI			0x20000000	// Process Login
#define LS_PRLO			0x21000000	// Process Logout
#define LS_TPRLO		0x24000000	// 3rd Party Process Logout
#define LS_PDISC		0x50000000	// Process Discovery
#define LS_FDISC		0x51000000	// Fabric Discovery
#define LS_ADISC		0x52000000	// Discover Address
#define LS_RNC			0x53000000	// Report Node Capability
#define LS_SCR                  0x62000000      // State Change Registration
#define LS_MASK			0xFF000000	

//
// 	TYPE Bit Masks
//
#define BASIC_LINK_SERVICE	0x00000000
#define EXT_LINK_SERVICE	0x01000000

#define LLC			0x04000000
#define LLC_SNAP		0x05000000
#define SCSI_FCP		0x08000000
#define SCSI_GPP		0x09000000
#define IPI3_MASTER		0x11000000
#define IPI3_SLAVE		0x12000000
#define IPI3_PEER		0x13000000
#define CP_IPI3_MASTER		0x15000000
#define CP_IPI3_SLAVE		0x16000000
#define CP_IPI3_PEER		0x17000000
#define SBCCS_CHANNEL		0x19000000
#define SBCCS_CONTROL		0x1A000000
#define FIBRE_SERVICES		0x20000000
#define FC_FG			0x21000000
#define FC_XS			0x22000000
#define FC_AL			0x23000000
#define SNMP			0x24000000
#define HIPPI_FP		0x40000000
#define TYPE_MASK		0xFF000000

typedef struct {
	UCHAR seq_id_valid;
	UCHAR seq_id;
	USHORT reserved;  // 2 bytes reserved
	ULONG ox_rx_id;
	USHORT low_seq_cnt;
	USHORT high_seq_cnt;
} BA_ACC_PAYLOAD;

typedef struct {
	UCHAR reserved;
	UCHAR reason_code;
	UCHAR reason_explain;
	UCHAR vendor_unique;
} BA_RJT_PAYLOAD;


typedef struct {
	ULONG 	command_code;
	ULONG 	sid;
	USHORT	ox_id;
	USHORT	rx_id;
} RRQ_MESSAGE;

typedef struct {
	ULONG command_code;
	UCHAR vendor;
	UCHAR explain;
	UCHAR reason;
	UCHAR reserved;
} REJECT_MESSAGE;


#define	N_OR_F_PORT		0x1000
#define RANDOM_RELATIVE_OFFSET	0x4000
#define CONTINUOSLY_INCREASING	0x8000

#define CLASS_VALID		0x8000
#define INTERMIX_MODE		0x4000
#define TRANSPARENT_STACKED	0x2000
#define LOCKDOWN_STACKED	0x1000
#define SEQ_DELIVERY		0x800

#define XID_NOT_SUPPORTED	0x00
#define XID_SUPPORTED		0x4000
#define XID_REQUIRED		0xC000

#define ASSOCIATOR_NOT_SUPPORTED	0x00
#define ASSOCIATOR_SUPPORTED	0x1000
#define ASSOCIATOR_REQUIRED	0x3000

#define	INIT_ACK0_SUPPORT	0x800
#define INIT_ACKN_SUPPORT	0x400

#define	RECIP_ACK0_SUPPORT	0x8000
#define RECIP_ACKN_SUPPORT	0x4000

#define X_ID_INTERLOCK		0x2000

#define ERROR_POLICY		0x1800		// Error Policy Supported
#define ERROR_DISCARD		0x00		// Only Discard Supported
#define ERROR_DISC_PROCESS	0x02		// Discard and process supported

#define NODE_ID			0x01
#define IEEE_EXT		0x20

//
// Categories Supported Per Sequence
//
#define	CATEGORIES_PER_SEQUENCE	0x300
#define ONE_CATEGORY_SEQUENCE	0x00		// 1 Category per Sequence
#define TWO_CATEGORY_SEQUENCE	0x01		// 2 Categories per Sequence
#define MANY_CATEGORY_SEQUENCE	0x03		// > 2 Categories/Sequence

typedef struct {

	USHORT initiator_control;
	USHORT service_options;

	USHORT rx_data_size;
	USHORT recipient_control;

	USHORT ee_credit;
	USHORT concurrent_sequences;

	USHORT reserved;
	USHORT open_sequences;

} CLASS_PARAMETERS;

typedef struct {
	ULONG	login_cmd;
	//
	// Common Service Parameters
	//
	struct {

		USHORT bb_credit;
		UCHAR lowest_ver;
		UCHAR highest_ver;

		USHORT bb_rx_size;
		USHORT common_features;

		USHORT rel_offset;
		USHORT concurrent_seq;


		ULONG e_d_tov;
	} cmn_services;

	//
	// Port Name
	//
	UCHAR port_name[8];

	//
	// Node/Fabric Name
	//
	UCHAR node_name[8];

	//
	// Class 1, 2 and 3 Service Parameters
	//
	CLASS_PARAMETERS	class1;
	CLASS_PARAMETERS	class2;
	CLASS_PARAMETERS	class3;

	ULONG reserved[4];

	//
	// Vendor Version Level
	//
	UCHAR		vendor_id[2];
	UCHAR		vendor_version[6];
	ULONG		buffer_size;
	USHORT		rxid_start;
	USHORT		total_rxids;
} LOGIN_PAYLOAD;


typedef struct
{
  ULONG cmd;  // 4 bytes
  UCHAR n_port_identifier[3];
  UCHAR reserved;
  UCHAR port_name[8];
} LOGOUT_PAYLOAD;


//
//	PRLI Request Service Parameter Defines
//
#define PRLI_ACC			0x01
#define PRLI_REQ			0x02
#define ORIG_PROCESS_ASSOC_VALID	0x8000
#define RESP_PROCESS_ASSOC_VALID	0x4000
#define ESTABLISH_PAIR			0x2000
#define DATA_OVERLAY_ALLOWED		0x40
#define	INITIATOR_FUNCTION		0x20
#define	TARGET_FUNCTION			0x10
#define CMD_DATA_MIXED			0x08
#define DATA_RESP_MIXED			0x04
#define READ_XFER_RDY			0x02
#define WRITE_XFER_RDY			0x01

#define RESPONSE_CODE_MASK	0xF00
#define REQUEST_EXECUTED	0x100
#define NO_RESOURCES		0x200
#define INIT_NOT_COMPLETE	0x300
#define IMAGE_DOES_NOT_EXIST	0x400
#define BAD_PREDEFINED_COND	0x500
#define REQ_EXEC_COND		0x600
#define NO_MULTI_PAGE		0x700

typedef struct {
	USHORT	payload_length;
	UCHAR	page_length;
	UCHAR	cmd;


	ULONG	valid;

	ULONG	orig_process_associator;

	ULONG	resp_process_associator;
	
	ULONG	fcp_info;
} PRLI_REQUEST;

typedef struct {

	USHORT	payload_length;
	UCHAR	page_length;
	UCHAR	cmd;

	ULONG	valid;
	ULONG	orig_process_associator;

	ULONG	resp_process_associator;
	ULONG	reserved;
} PRLO_REQUEST;

typedef struct {
	ULONG	cmd;

	ULONG	hard_address;
	
	UCHAR	port_name[8];

	UCHAR	node_name[8];

	ULONG	s_id;
} ADISC_PAYLOAD;

struct ext_sg_entry_t {
	__u32 len:18;		/* buffer length, bits 0-17 */
	__u32 uba:13;		/* upper bus address bits 18-31 */
	__u32 lba;		/* lower bus address bits 0-31 */
}; 


// J. McCarty's LINK.H
//
//	LS_RJT Reason Codes
//

#define INVALID_COMMAND_CODE	0x01
#define LOGICAL_ERROR		0x03
#define LOGICAL_BUSY		0x05
#define PROTOCOL_ERROR		0x07
#define UNABLE_TO_PERFORM	0x09
#define COMMAND_NOT_SUPPORTED	0x0B
#define LS_VENDOR_UNIQUE	0xFF

//
// 	LS_RJT Reason Codes Explanations
//
#define NO_REASON		0x00
#define OPTIONS_ERROR		0x01
#define INITIATOR_CTL_ERROR	0x03
#define RECIPIENT_CTL_ERROR	0x05
#define DATA_FIELD_SIZE_ERROR	0x07
#define CONCURRENT_SEQ_ERROR	0x09
#define CREDIT_ERROR		0x0B
#define INVALID_PORT_NAME	0x0D
#define INVALID_NODE_NAME	0x0E
#define INVALID_CSP		0x0F	// Invalid Service Parameters
#define INVALID_ASSOC_HDR	0x11	// Invalid Association Header
#define ASSOC_HDR_REQUIRED	0x13	// Association Header Required
#define LS_INVALID_S_ID		0x15
#define INVALID_OX_RX_ID	0x17	// Invalid OX_ID RX_ID Combination
#define CMD_IN_PROCESS		0x19
#define INVALID_IDENTIFIER	0x1F	// Invalid N_PORT Identifier
#define INVALID_SEQ_ID		0x21
#define ABT_INVALID_XCHNG	0x23 	// Attempt to Abort an invalid Exchange
#define ABT_INACTIVE_XCHNG	0x25 	// Attempt to Abort an inactive Exchange
#define NEED_REC_QUAL		0x27	// Recovery Qualifier required
#define NO_LOGIN_RESOURCES	0x29	// No resources to support login
#define NO_DATA			0x2A	// Unable to supply requested data
#define	REQUEST_NOT_SUPPORTED	0x2C	// Request Not Supported

//
//	Link Control Codes
//

//
//	P_BSY Action Codes
//
#define SEQUENCE_TERMINATED	0x01000000
#define SEQUENCE_ACTIVE		0x02000000

//
//	P_BSY Reason Codes
//
#define PHYS_NPORT_BUSY		0x010000
#define NPORT_RESOURCE_BUSY	0x020000

//
// 	P_RJT, F_RJT Action Codes
//

#define RETRYABLE_ERROR		0x01000000
#define NON_RETRYABLE_ERROR	0x02000000

//
// 	P_RJT, F_RJT Reason Codes
//
#define INVALID_D_ID		0x010000
#define INVALID_S_ID		0x020000
#define NPORT_NOT_AVAIL_TMP	0x030000
#define NPORT_NOT_AVAIL_PERM	0x040000
#define CLASS_NOT_SUPPORTED	0x050000
#define USAGE_ERROR		0x060000
#define TYPE_NOT_SUPPORTED	0x070000
#define INVAL_LINK_CONTROL	0x080000
#define INVAL_R_CTL		0x090000
#define INVAL_F_CTL		0x0A0000
#define INVAL_OX_ID		0x0B0000
#define INVAL_RX_ID		0x0C0000
#define INVAL_SEQ_ID		0x0D0000
#define INVAL_DF_CTL		0x0E0000
#define INVAL_SEQ_CNT		0x0F0000
#define INVAL_PARAMS		0x100000
#define EXCHANGE_ERROR		0x110000
#define LS_PROTOCOL_ERROR	0x120000
#define INCORRECT_LENGTH	0x130000
#define UNEXPECTED_ACK		0x140000
#define LOGIN_REQ		0x160000
#define EXCESSIVE_SEQ		0x170000
#define NO_EXCHANGE		0x180000
#define SEC_HDR_NOT_SUPPORTED	0x190000
#define NO_FABRIC		0x1A0000
#define P_VENDOR_UNIQUE		0xFF0000

//
// 	BA_RJT Reason Codes
//
#define BA_INVALID_COMMAND	0x00010000
#define BA_LOGICAL_ERROR	0x00030000
#define BA_LOGICAL_BUSY		0x00050000
#define BA_PROTOCOL_ERROR	0x00070000
#define BA_UNABLE_TO_PERFORM	0x00090000

//
// 	BA_RJT Reason Explanation Codes
//
#define BA_NO_REASON		0x00000000
#define BA_INVALID_OX_RX	0x00000300
#define BA_SEQUENCE_ABORTED	0x00000500



#endif /* CPQFCTSSTRUCTS_H	*/