forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 1
/
cpqfcTSstructs.h
1530 lines (1247 loc) · 46.2 KB
/
cpqfcTSstructs.h
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
/* 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);