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#include <linux/blk.h>
32#include <linux/kernel.h>
33#include <linux/string.h>
34#include <linux/ioport.h>
35#include <linux/sched.h>
36#include <linux/slab.h>
37#include <linux/types.h>
38#include <linux/pci.h>
39#include <linux/delay.h>
40#include <linux/unistd.h>
41#include <asm/io.h>
42#include <asm/irq.h>
43#include <linux/spinlock.h>
44
45#include "sd.h"
46#include "hosts.h"
47#include "cpqfcTSchip.h"
48#include "cpqfcTSstructs.h"
49
50
51
52static void fcParseLinkStatusCounters(TACHYON * fcChip);
53static void CpqTsGetSFQEntry(TACHYON * fcChip, u16 pi, u32 * buffr, u8 UpdateChip);
54
55static void cpqfc_free_dma_consistent(CPQFCHBA * cpqfcHBAdata)
56{
57
58 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
59
60 if (fcChip->Exchanges != NULL)
61 pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_EXCHANGES), fcChip->Exchanges, fcChip->exch_dma_handle);
62 fcChip->Exchanges = NULL;
63 if (cpqfcHBAdata->fcLQ != NULL)
64 pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_LINK_QUE), cpqfcHBAdata->fcLQ, cpqfcHBAdata->fcLQ_dma_handle);
65 cpqfcHBAdata->fcLQ = NULL;
66}
67
68
69
70
71
72
73int CpqTsCreateTachLiteQues(void *pHBA, int opcode)
74{
75 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
76 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
77
78 int iStatus = 0;
79 unsigned long ulAddr;
80 dma_addr_t ERQdma, IMQdma, SPQdma, SESTdma;
81 int i;
82
83
84
85
86
87 ENTER("CreateTachLiteQues");
88
89
90
91 fcChip->Exchanges = NULL;
92 cpqfcHBAdata->fcLQ = NULL;
93
94 printk("Allocating %u for %u Exchanges ", (u32) sizeof(FC_EXCHANGES), TACH_MAX_XID);
95 fcChip->Exchanges = pci_alloc_consistent(cpqfcHBAdata->PciDev, sizeof(FC_EXCHANGES), &fcChip->exch_dma_handle);
96 printk("@ %p\n", fcChip->Exchanges);
97
98 if (fcChip->Exchanges == NULL)
99 {
100 printk("pci_alloc_consistent failure on Exchanges: fatal error\n");
101 return -1;
102 }
103
104 memset(fcChip->Exchanges, 0, sizeof(FC_EXCHANGES));
105
106
107 printk("Allocating %u for LinkQ ", (u32) sizeof(FC_LINK_QUE));
108 cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev, sizeof(FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle);
109 printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH);
110 memset(cpqfcHBAdata->fcLQ, 0, sizeof(FC_LINK_QUE));
111
112 if (cpqfcHBAdata->fcLQ == NULL)
113 {
114 cpqfc_free_dma_consistent(cpqfcHBAdata);
115 printk("pci_alloc_consistent() failure on fc Link Que: fatal error\n");
116 return -1;
117 }
118
119 memset(cpqfcHBAdata->fcLQ, 0, sizeof(FC_LINK_QUE));
120
121
122 if (!fcChip->Registers.ReMapMemBase) {
123 cpqfc_free_dma_consistent(cpqfcHBAdata);
124 printk("HBA base address NULL: fatal error\n");
125 return -1;
126 }
127
128
129
130 memset(cpqfcHBAdata->dynamic_mem, 0, sizeof(cpqfcHBAdata->dynamic_mem));
131
132
133
134
135 fcChip->ERQ = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachLiteERQ), 32 * (ERQ_LEN), 0L, &ERQdma);
136 if (!fcChip->ERQ) {
137 cpqfc_free_dma_consistent(cpqfcHBAdata);
138 printk("pci_alloc_consistent/alignment failure on ERQ: fatal error\n");
139 return -1;
140 }
141 fcChip->ERQ->length = ERQ_LEN - 1;
142 ulAddr = (u32) ERQdma;
143#if BITS_PER_LONG > 32
144 if ((ulAddr >> 32)) {
145 cpqfc_free_dma_consistent(cpqfcHBAdata);
146 printk(" FATAL! ERQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
147 return -1;
148 }
149#endif
150 fcChip->ERQ->base = (u32) ulAddr;
151
152
153
154
155 fcChip->IMQ = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachyonIMQ), 32 * (IMQ_LEN), 0L, &IMQdma);
156 if (!fcChip->IMQ) {
157 cpqfc_free_dma_consistent(cpqfcHBAdata);
158 printk("pci_alloc_consistent/alignment failure on IMQ: fatal error\n");
159 return -1;
160 }
161 fcChip->IMQ->length = IMQ_LEN - 1;
162
163 ulAddr = IMQdma;
164#if BITS_PER_LONG > 32
165 if ((ulAddr >> 32)) {
166 cpqfc_free_dma_consistent(cpqfcHBAdata);
167 printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
168 return -1;
169 }
170#endif
171 fcChip->IMQ->base = (u32) ulAddr;
172
173
174
175 fcChip->SFQ = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachLiteSFQ), 64 * (SFQ_LEN), 0L, &SPQdma);
176 if (!fcChip->SFQ) {
177 cpqfc_free_dma_consistent(cpqfcHBAdata);
178 printk("pci_alloc_consistent/alignment failure on SFQ: fatal error\n");
179 return -1;
180 }
181 fcChip->SFQ->length = SFQ_LEN - 1;
182
183
184 ulAddr = SPQdma;
185#if BITS_PER_LONG > 32
186 if ((ulAddr >> 32)) {
187 cpqfc_free_dma_consistent(cpqfcHBAdata);
188 printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
189 return -1;
190 }
191#endif
192 fcChip->SFQ->base = (u32) ulAddr;
193
194
195
196
197
198
199 printk("Allocating %u for TachSEST for %u Exchanges\n", (u32) sizeof(TachSEST), TACH_SEST_LEN);
200 fcChip->SEST = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachSEST), 4, 0L, &SESTdma);
201
202 if (!fcChip->SEST) {
203 cpqfc_free_dma_consistent(cpqfcHBAdata);
204 printk("pci_alloc_consistent/alignment failure on SEST: fatal error\n");
205 return -1;
206 }
207
208 for (i = 0; i < TACH_SEST_LEN; i++)
209 fcChip->SEST->sgPages[i] = NULL;
210
211 fcChip->SEST->length = TACH_SEST_LEN;
212
213
214 ulAddr = SESTdma;
215#if BITS_PER_LONG > 32
216 if ((ulAddr >> 32)) {
217 cpqfc_free_dma_consistent(cpqfcHBAdata);
218 printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
219 return -1;
220 }
221#endif
222 fcChip->SEST->base = (u32) ulAddr;
223
224
225
226
227
228
229
230 writel(fcChip->ERQ->base, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));
231
232 writel(fcChip->ERQ->length, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_LENGTH));
233
234
235 fcChip->ERQ->producerIndex = 0L;
236 writel(fcChip->ERQ->producerIndex, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_PRODUCER_INDEX));
237
238
239
240
241
242 ulAddr = ((unsigned long) &fcChip->ERQ->consumerIndex - (unsigned long) fcChip->ERQ) + (unsigned long) ERQdma;
243
244
245
246 writel((u32) ulAddr, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_CONSUMER_INDEX_ADR));
247
248
249
250
251
252
253
254
255 printk(" cpqfcTS: writing IMQ BASE %Xh ", fcChip->IMQ->base);
256 writel(fcChip->IMQ->base, (fcChip->Registers.ReMapMemBase + IMQ_BASE));
257
258 writel(fcChip->IMQ->length, (fcChip->Registers.ReMapMemBase + IMQ_LENGTH));
259
260 writel(fcChip->IMQ->consumerIndex, (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));
261
262
263
264
265
266 ulAddr = ((unsigned long) &fcChip->IMQ->producerIndex - (unsigned long) fcChip->IMQ) + (unsigned long) IMQdma;
267
268#if BITS_PER_LONG > 32
269 if ((ulAddr >> 32)) {
270 cpqfc_free_dma_consistent(cpqfcHBAdata);
271 printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
272 return -1;
273 }
274#endif
275
276 printk(" PI %Xh\n", (u32) ulAddr);
277
278 writel((u32) ulAddr, (fcChip->Registers.ReMapMemBase + IMQ_PRODUCER_INDEX));
279
280
281
282
283
284
285 writel(fcChip->SFQ->base, (fcChip->Registers.ReMapMemBase + TL_MEM_SFQ_BASE));
286
287 writel(fcChip->SFQ->length, (fcChip->Registers.ReMapMemBase + TL_MEM_SFQ_LENGTH));
288
289
290
291 writel(fcChip->SEST->base, (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE));
292
293 printk(" cpqfcTS: SEST %p(virt): Wrote base %Xh @ %p\n", fcChip->SEST, fcChip->SEST->base, fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE);
294
295 writel(fcChip->SEST->length, (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_LENGTH));
296
297 writel((TL_EXT_SG_PAGE_COUNT - 1), (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_SG_PAGE));
298
299
300 LEAVE("CreateTachLiteQues");
301
302 return iStatus;
303}
304
305
306
307
308
309
310
311int CpqTsResetTachLite(void *pHBA, int type)
312{
313 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
314 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
315 u32 ulBuff, i;
316 int ret_status = 0;
317
318 ENTER("ResetTach");
319
320 switch (type) {
321
322 case CLEAR_FCPORTS:
323
324
325 writeb(0, (fcChip->Registers.ReMapMemBase + IINTEN));
326
327
328
329
330
331 {
332 PFC_LOGGEDIN_PORT pLoggedInPort = fcChip->fcPorts.pNextPort;
333 PFC_LOGGEDIN_PORT ptr;
334
335
336 while (pLoggedInPort) {
337 ptr = pLoggedInPort;
338 pLoggedInPort = ptr->pNextPort;
339
340
341 kfree(ptr);
342 }
343 }
344
345
346 case 1:
347
348
349 writeb(0, (fcChip->Registers.ReMapMemBase + IINTEN));
350
351
352
353
354
355
356
357 fcChip->LaserControl(fcChip->Registers.ReMapMemBase, 0);
358
359
360
361
362
363
364
365
366
367 writel(0xff000001L, (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));
368
369 for (i = 0; i < 128; i++)
370 ulBuff = readl(fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST);
371
372
373 for (i = 0; i < 8; i++)
374 writel(0, (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));
375
376
377
378
379
380
381 CpqTsDestroyTachLiteQues(cpqfcHBAdata, 0);
382 cpqfcTSClearLinkStatusCounters(fcChip);
383
384 fcChip->Registers.TYstatus.value = readl(fcChip->Registers.TYstatus.address);
385 break;
386
387
388
389
390
391
392
393
394
395 default:
396 ret_status = -1;
397 break;
398 }
399 LEAVE("ResetTach");
400 return ret_status;
401}
402
403
404
405
406
407
408
409int CpqTsLaserControl(void *addrBase, int opcode)
410{
411 u32 dwBuff;
412
413 dwBuff = readl((addrBase + TL_MEM_TACH_CONTROL));
414
415 if (opcode == 1)
416 dwBuff |= ~0xffffffefL;
417 else
418 dwBuff &= 0xffffffefL;
419 writel(dwBuff, (addrBase + TL_MEM_TACH_CONTROL));
420 return 0;
421}
422
423
424
425
426
427
428
429
430
431
432int CpqTsInitializeFrameManager(void *pChip, int opcode)
433{
434 PTACHYON fcChip;
435 int iStatus;
436 u32 wwnLo, wwnHi;
437
438 ENTER("InitializeFrameManager");
439 fcChip = (PTACHYON) pChip;
440 if (!fcChip->Registers.ReMapMemBase)
441 return -1;
442
443
444
445
446
447 fcChip->Registers.ed_tov.value = 0x006507D1;
448 writel(fcChip->Registers.ed_tov.value, (fcChip->Registers.ed_tov.address));
449
450
451
452
453 writel(0x07d00010, fcChip->Registers.ReMapMemBase + TL_MEM_FM_TIMEOUT2);
454
455
456
457 iStatus = CpqTsReadWriteWWN(fcChip, 1);
458
459 if (iStatus)
460 {
461 printk(" WARNING! HBA NVRAM WWN read failed - make alias\n");
462
463
464
465 fcChip->Registers.wwn_hi = (__u32) jiffies;
466 fcChip->Registers.wwn_hi |= 0x50000000L;
467 fcChip->Registers.wwn_lo = 0x44556677L;
468 }
469
470
471 writel(fcChip->Registers.wwn_hi, fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI);
472
473 writel(fcChip->Registers.wwn_lo, fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);
474
475
476
477 wwnHi = readl(fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI);
478
479 wwnLo = readl(fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);
480
481 DEBUG_PCI(printk(" WWN %08X%08X\n", fcChip->Registers.wwn_hi, fcChip->Registers.wwn_lo));
482
483 if (wwnHi != fcChip->Registers.wwn_hi || wwnLo != fcChip->Registers.wwn_lo) {
484 printk("cpqfcTS: WorldWideName register load failed\n");
485 return -1;
486 }
487
488
489
490 fcChip->Registers.FMcontrol.value = 0x06;
491
492
493
494
495 if (fcChip->Options.intLoopback == 1)
496 fcChip->Registers.FMconfig.value = 0x0f002080L;
497 else if (fcChip->Options.extLoopback == 1)
498 fcChip->Registers.FMconfig.value = 0x0f004080L;
499 else
500 fcChip->Registers.FMconfig.value = 0x55000100L;
501
502
503
504
505
506 if (!fcChip->Options.intLoopback && !fcChip->Options.extLoopback)
507
508 fcChip->LaserControl(fcChip->Registers.ReMapMemBase, 1);
509
510 writel(fcChip->Registers.FMconfig.value, fcChip->Registers.FMconfig.address);
511
512
513
514 writel(fcChip->Registers.FMcontrol.value, fcChip->Registers.FMcontrol.address);
515
516 LEAVE("InitializeFrameManager");
517
518 return 0;
519}
520
521
522
523
524
525
526
527static int PeekIMQEntry(PTACHYON fcChip, u32 type)
528{
529 u32 CI = fcChip->IMQ->consumerIndex;
530 u32 PI = fcChip->IMQ->producerIndex;
531
532 while (CI != PI) {
533 if ((++CI) >= IMQ_LEN)
534 CI = 0;
535
536 switch (type) {
537 case ELS_LILP_FRAME:
538 {
539
540
541
542 if ((fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x104) {
543 TachFCHDR_GCMND *fchs;
544 u32 ulFibreFrame[2048 / 4];
545 u16 SFQpi = (u16) (fcChip->IMQ->QEntry[CI].word[0] & 0x0fffL);
546
547 CpqTsGetSFQEntry(fcChip, SFQpi,
548 ulFibreFrame,
549 FALSE);
550
551 fchs = (TachFCHDR_GCMND *) & ulFibreFrame;
552 if (fchs->pl[0] == ELS_LILP_FRAME) {
553 return 1;
554 } else {
555
556 }
557 }
558 }
559 break;
560
561 case OUTBOUND_COMPLETION:
562 if ((fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x00) {
563
564
565 if (fcChip->IMQ->QEntry[CI].word[2] & 0x7a000000L)
566 return 1;
567 }
568 break;
569
570
571
572 default:
573 break;
574 }
575 }
576 return 0;
577}
578
579
580static void SetTachTOV(CPQFCHBA * cpqfcHBAdata)
581{
582 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598 if ((fcChip->Registers.ed_tov.value & 0xFFFF) <= 0x1f5)
599 fcChip->Registers.ed_tov.value = 0x006507D1;
600
601
602
603 else if ((fcChip->Registers.ed_tov.value & 0xFFFF) <= 0x7D1)
604 fcChip->Registers.ed_tov.value = 0x00655DC1;
605
606
607
608 else if ((fcChip->Registers.ed_tov.value & 0xFFFF) <= 0x5DC1)
609 fcChip->Registers.ed_tov.value = 0x0065FFFF;
610
611 writel(fcChip->Registers.ed_tov.value, (fcChip->Registers.ed_tov.address));
612
613 writel(0x07D00010, fcChip->Registers.ReMapMemBase + TL_MEM_FM_TIMEOUT2);
614}
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638int CpqTsProcessIMQEntry(void *host)
639{
640 struct Scsi_Host *HostAdapter = (struct Scsi_Host *) host;
641 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
642 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
643 FC_EXCHANGES *Exchanges = fcChip->Exchanges;
644 int iStatus;
645 u16 i, RPCset, DPCset;
646 u32 x_ID;
647 u32 ulBuff, dwStatus;
648 TachFCHDR_GCMND *fchs;
649 u32 ulFibreFrame[2048 / 4];
650 u8 ucInboundMessageType;
651
652 ENTER("ProcessIMQEntry");
653
654
655
656
657
658
659 if (fcChip->IMQ->producerIndex != fcChip->IMQ->consumerIndex) {
660
661
662#ifdef IMQ_DEBUG
663 printk("PI %X, CI %X type: %X\n", fcChip->IMQ->producerIndex, fcChip->IMQ->consumerIndex, fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type);
664#endif
665
666
667 switch ((u8) (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type & 0xffL)) {
668 case OUTBOUND_COMPLETION:
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684 ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1];
685 x_ID = ulBuff & 0x7fffL;
686
687 if (x_ID < TACH_MAX_XID)
688 {
689
690
691 if (ulBuff & 0x20000000L)
692 RPCset = 1;
693 else
694 RPCset = 0;
695
696 if (ulBuff & 0x40000000L)
697 DPCset = 1;
698 else
699 DPCset = 0;
700
701 dwStatus = 0L;
702 if (ulBuff & 0x10000000L)
703 dwStatus |= SESTPROG_ERR;
704
705 ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2];
706 if (ulBuff & 0x7a000000L)
707 {
708 if (ulBuff & 0x40000000L)
709 dwStatus |= INV_ENTRY;
710 if (ulBuff & 0x20000000L)
711 dwStatus |= FRAME_TO;
712 if (ulBuff & 0x10000000L)
713 dwStatus |= HOSTPROG_ERR;
714 if (ulBuff & 0x08000000L)
715 dwStatus |= LINKFAIL_TX;
716 if (ulBuff & 0x02000000L)
717 dwStatus |= ABORTSEQ_NOTIFY;
718 }
719
720
721 if (dwStatus)
722 {
723
724 Exchanges->fcExchange[x_ID].status |= dwStatus;
725
726
727
728 if (x_ID < TACH_SEST_LEN) {
729
730 printk(" #OCM error %Xh x_ID %X# ", dwStatus, x_ID);
731
732 Exchanges->fcExchange[x_ID].timeOut = 30000;
733
734
735
736
737
738
739
740
741 if (dwStatus & FRAME_TO)
742 {
743 if (!(Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED)) {
744
745
746 cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, &x_ID);
747 }
748 } else
749 {
750 cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, &x_ID);
751 }
752
753
754
755
756 if (dwStatus &= HOSTPROG_ERR)
757
758 writel(4, fcChip->Registers.FMcontrol.address);
759 }
760 }
761
762
763 if (((x_ID < TACH_SEST_LEN) && RPCset) || (x_ID >= TACH_SEST_LEN))
764 {
765
766
767
768
769 if (x_ID >= TACH_SEST_LEN)
770
771 {
772
773 up(cpqfcHBAdata->TYOBcomplete);
774
775
776 } else
777 {
778
779
780 }
781 }
782 } else
783 {
784
785 printk(" ProcessIMQ (OBCM) x_id out of range %Xh\n", x_ID);
786
787 }
788
789
790
791
792
793
794
795 fcChip->Registers.FMLinkStatus1.value =
796 readl(fcChip->Registers.FMLinkStatus1.address);
797
798 fcChip->Registers.FMLinkStatus2.value =
799 readl(fcChip->Registers.FMLinkStatus2.address);
800
801
802 fcParseLinkStatusCounters(fcChip);
803 break;
804
805
806
807 case ERROR_IDLE_COMPLETION:
808
809
810
811
812
813
814
815 for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
816
817
818 fcChip->SEST->u[x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;
819 }
820
821 CpqTsUnFreezeTachlite(fcChip, 2);
822
823 break;
824
825
826 case INBOUND_SFS_COMPLETION:
827
828
829
830
831
832
833
834
835
836
837
838
839 fcChip->SFQ->producerIndex = (u16)
840 (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] & 0x0fffL);
841
842
843 ucInboundMessageType = 0;
844
845
846
847
848 if (!(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2]
849 & 0x40000000))
850 {
851 ucInboundMessageType = (u8)
852 (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] & 0x0fL);
853 } else {
854 fcChip->fcStats.linkFailRX++;
855
856 }
857
858
859 CpqTsGetSFQEntry(fcChip,
860 (u16) fcChip->SFQ->producerIndex,
861 ulFibreFrame, TRUE);
862
863
864
865
866 if (ucInboundMessageType == 1) {
867 fchs = (TachFCHDR_GCMND *) ulFibreFrame;
868
869
870 if ((fchs->d_id & 0xFF000000) == 0x06000000)
871 {
872
873
874
875
876 } else if (((fchs->d_id & 0xFF000000) == 0x07000000) ||
877 (fchs->d_id & 0xFF000000) == 0x05000000)
878 {
879 u32 x_ID;
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894 for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
895 if ((fchs->s_id & 0xFFFFFF) == (Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF)
896 && (fchs->ox_rx_id & 0xFFFF0000) == (Exchanges->fcExchange[x_ID].fchs.ox_rx_id & 0xFFFF0000)) {
897
898
899
900 Exchanges->fcExchange[x_ID].status |= SFQ_FRAME;
901
902
903 cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, &x_ID);
904 break;
905 }
906 }
907 }
908
909 }
910
911 else if (ucInboundMessageType == 3) {
912
913 cpqfcTSPutLinkQue(cpqfcHBAdata, SFQ_UNKNOWN, ulFibreFrame);
914
915 }
916
917 else if (ucInboundMessageType == 2)
918 {
919#ifdef IMQ_DEBUG
920 printk("Bad FCP incoming frame discarded\n");
921#endif
922 }
923
924 else
925 {
926#ifdef IMQ_DEBUG
927 printk("Incoming frame discarded, type: %Xh\n", ucInboundMessageType);
928#endif
929 }
930
931
932
933
934
935 fcChip->Registers.FMLinkStatus1.value =
936 readl(fcChip->Registers.FMLinkStatus1.address);
937
938
939 fcChip->Registers.FMLinkStatus2.value =
940 readl(fcChip->Registers.FMLinkStatus2.address);
941
942
943 break;
944
945
946
947
948
949
950
951
952
953
954
955 case ERQ_FROZEN_COMPLETION:
956
957 fcChip->Registers.TYstatus.value =
958 readl(fcChip->Registers.TYstatus.address);
959
960 break;
961 case FCP_FROZEN_COMPLETION:
962
963 fcChip->Registers.TYstatus.value =
964 readl(fcChip->Registers.TYstatus.address);
965
966
967 up(cpqfcHBAdata->TachFrozen);
968
969 break;
970
971
972
973 case INBOUND_C1_TIMEOUT:
974 case MFS_BUF_WARN:
975 case IMQ_BUF_WARN:
976 break;
977
978
979
980
981
982
983
984
985
986 case FRAME_MGR_INTERRUPT:
987 {
988 PFC_LOGGEDIN_PORT pLoggedInPort;
989
990 fcChip->Registers.FMstatus.value = readl(fcChip->Registers.FMstatus.address);
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013 {
1014 u32 Lpsm = (fcChip->Registers.FMstatus.value & 0xF0) >> 4;
1015
1016 if ((fcChip->Registers.FMstatus.value & 0x400)
1017 && !(fcChip->Registers.FMstatus.value & 0x100)
1018 && !(fcChip->Registers.FMstatus.value & 0x1000))
1019 {
1020 if ((Lpsm != 0) ||
1021 !(Lpsm & 0x8))
1022 {
1023
1024 if ((Lpsm == ARBITRATING) || (Lpsm == OPEN) || (Lpsm == OPENED) || (Lpsm == XMITTD_CLOSE) || (Lpsm == RCVD_CLOSE)) {
1025
1026 printk(" #req FMinit on E-S: LPSM %Xh# ", Lpsm);
1027
1028
1029 fcChip->fcStats.FMinits++;
1030 writel(6, fcChip->Registers.FMcontrol.address);
1031 }
1032 }
1033 } else if (fcChip->Registers.FMstatus.value & 0x40000)
1034 {
1035 printk(" #req FMinit on LST, LPSM %Xh# ", Lpsm);
1036
1037 fcChip->fcStats.FMinits++;
1038 writel(6, fcChip->Registers.FMcontrol.address);
1039 }
1040 }
1041
1042
1043
1044 writel((fcChip->Registers.FMstatus.value & 0xff3fff00L), fcChip->Registers.FMstatus.address);
1045
1046
1047
1048 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] = fcChip->Registers.FMstatus.value;
1049
1050
1051
1052
1053
1054
1055 fcChip->Registers.FMLinkStatus1.value =
1056 readl(fcChip->Registers.FMLinkStatus1.address);
1057
1058 fcChip->Registers.FMLinkStatus2.value =
1059 readl(fcChip->Registers.FMLinkStatus2.address);
1060
1061
1062 fcChip->Registers.FMBB_CreditZero.value =
1063 readl(fcChip->Registers.FMBB_CreditZero.address);
1064
1065
1066
1067 fcParseLinkStatusCounters(fcChip);
1068
1069
1070
1071
1072 if (fcChip->Registers.FMstatus.value & 0x100L)
1073 {
1074
1075#ifdef IMQ_DEBUG
1076 printk("LinkDn\n");
1077#endif
1078 printk(" #LDn# ");
1079
1080 fcChip->fcStats.linkDown++;
1081
1082 SetTachTOV(cpqfcHBAdata);
1083
1084
1085
1086
1087
1088 if (fcChip->ERQ->producerIndex != fcChip->ERQ->consumerIndex) {
1089
1090 CpqTsFreezeTachlite(fcChip, 1);
1091 fcChip->ERQ->producerIndex = fcChip->ERQ->consumerIndex = 0;
1092 writel(fcChip->ERQ->base, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));
1093
1094
1095 }
1096
1097
1098
1099
1100 {
1101 pLoggedInPort = &fcChip->fcPorts;
1102 while (pLoggedInPort)
1103
1104
1105 {
1106
1107 if (pLoggedInPort->pdisc)
1108 {
1109 pLoggedInPort->LOGO_timer = 3;
1110
1111
1112 }
1113
1114
1115 pLoggedInPort->prli = FALSE;
1116
1117 pLoggedInPort = pLoggedInPort->pNextPort;
1118 }
1119 }
1120
1121
1122
1123
1124
1125 fcChip->Options.LILPin = 0;
1126 cpqfcHBAdata->PortDiscDone = 0;
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143 for (i = TACH_SEST_LEN; i < TACH_MAX_XID; i++) {
1144 if (Exchanges->fcExchange[i].type == ELS_PDISC || Exchanges->fcExchange[i].type == ELS_PLOGI || Exchanges->fcExchange[i].type == ELS_PRLI) {
1145
1146#ifdef IMQ_DEBUG
1147 printk("Originator ABORT x_id %Xh, type %Xh, port_id %Xh on LDn\n", i, Exchanges->fcExchange[i].type, Exchanges->fcExchange[i].fchs.d_id);
1148#endif
1149
1150 Exchanges->fcExchange[i].status |= INITIATOR_ABORT;
1151 cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, i);
1152 }
1153 }
1154
1155 }
1156
1157 if (fcChip->Registers.FMstatus.value & 0x200L)
1158 {
1159
1160
1161
1162
1163 pLoggedInPort = &fcChip->fcPorts;
1164 while (pLoggedInPort)
1165
1166
1167 {
1168 if (pLoggedInPort->pdisc)
1169 {
1170 pLoggedInPort->LOGO_timer = 3;
1171
1172
1173
1174
1175
1176
1177 }
1178 pLoggedInPort = pLoggedInPort->pNextPort;
1179 }
1180
1181
1182 fcChip->Registers.rcv_al_pa.value = readl(fcChip->Registers.rcv_al_pa.address);
1183
1184
1185
1186
1187
1188
1189
1190 if ((fcChip->Registers.my_al_pa & 0xFF) != ((fcChip->Registers.rcv_al_pa.value >> 16) & 0xFF)) {
1191
1192
1193
1194 pLoggedInPort = &fcChip->fcPorts;
1195 while (pLoggedInPort)
1196
1197
1198 {
1199 pLoggedInPort->pdisc = FALSE;
1200 pLoggedInPort->prli = FALSE;
1201 pLoggedInPort = pLoggedInPort->pNextPort;
1202 }
1203
1204
1205
1206 cpqfcTSTerminateExchange(cpqfcHBAdata, NULL, PORTID_CHANGED);
1207
1208 }
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 fcChip->Registers.my_al_pa = (fcChip->Registers.rcv_al_pa.value >> 16) & 0xFF;
1219
1220
1221
1222 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] = fcChip->Registers.my_al_pa;
1223
1224
1225
1226
1227
1228
1229 ulBuff = readl(fcChip->Registers.FMconfig.address);
1230 ulBuff &= 0x00ffffffL;
1231 ulBuff |= (fcChip->Registers.my_al_pa << 24);
1232 fcChip->Registers.FMconfig.value = ulBuff;
1233 writel(fcChip->Registers.FMconfig.value,
1234 fcChip->Registers.FMconfig.address);
1235
1236
1237#ifdef IMQ_DEBUG
1238 printk("#LUp %Xh, FMstat 0x%08X#", fcChip->Registers.my_al_pa, fcChip->Registers.FMstatus.value);
1239#endif
1240
1241
1242
1243 writel(fcChip->Registers.my_al_pa, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
1244
1245
1246 fcChip->fcStats.linkUp++;
1247
1248
1249
1250
1251 ulBuff =
1252 readl(fcChip->Registers.FMLinkStatus1.address);
1253
1254 ulBuff =
1255 readl(fcChip->Registers.FMLinkStatus2.address);
1256
1257
1258
1259
1260
1261
1262
1263
1264 CpqTsUnFreezeTachlite(fcChip, 2);
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276 udelay(1000);
1277 if (PeekIMQEntry(fcChip, ELS_LILP_FRAME)) {
1278
1279
1280 } else
1281 cpqfcTSPutLinkQue(cpqfcHBAdata, LINKACTIVE, ulFibreFrame);
1282 }
1283
1284
1285
1286 if (fcChip->Registers.FMstatus.value & 0x2000) {
1287 printk(" #Fabric# ");
1288 fcChip->Options.fabric = 1;
1289 } else
1290 fcChip->Options.fabric = 0;
1291
1292
1293
1294
1295 if (fcChip->Registers.FMstatus.value & 0x30000L) {
1296
1297 fcChip->Registers.rcv_al_pa.value = readl(fcChip->Registers.rcv_al_pa.address);
1298
1299
1300 if (fcChip->Registers.FMstatus.value & 0x10000L) {
1301 PFC_LOGGEDIN_PORT pLoggedInPort;
1302
1303
1304 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] = (fcChip->Registers.rcv_al_pa.value & 0xff00L) >> 8;
1305
1306 pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,
1307 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1],
1308 NULL,
1309 NULL);
1310
1311 if (pLoggedInPort) {
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321 printk(" #BAD alpa %Xh# ", fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1]);
1322 cpqfcTSImplicitLogout(cpqfcHBAdata, pLoggedInPort);
1323 }
1324 }
1325
1326 if (fcChip->Registers.FMstatus.value & 0x20000L) {
1327
1328 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] = (fcChip->Registers.rcv_al_pa.value & 0xffL);
1329
1330
1331 }
1332 }
1333
1334 if (fcChip->Registers.FMstatus.value & 0x400L) {
1335
1336 if (!(u16) (fcChip->Registers.FMstatus.value & 0x80))
1337 fcChip->fcStats.e_stores++;
1338
1339 }
1340 }
1341 break;
1342
1343
1344 case INBOUND_FCP_XCHG_COMPLETION:
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363 ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0];
1364 x_ID = ulBuff & 0x7fffL;
1365
1366
1367 if (x_ID < TACH_SEST_LEN)
1368 {
1369
1370
1371#ifdef FCP_COMPLETION_DBG
1372 printk(" FCP_CM x_ID %Xh, status %Xh, Cmnd %p\n", x_ID, ulBuff, Exchanges->fcExchange[x_ID].Cmnd);
1373#endif
1374 if (ulBuff & 0x08000000L)
1375
1376 RPCset = 1;
1377 else
1378 RPCset = 0;
1379
1380 dwStatus = 0L;
1381 if (ulBuff & 0x70000000L)
1382 {
1383
1384 if (ulBuff & 0x40000000L)
1385 dwStatus |= LINKFAIL_RX;
1386
1387 if (ulBuff & 0x20000000L)
1388 dwStatus |= COUNT_ERROR;
1389
1390 if (ulBuff & 0x10000000L)
1391 dwStatus |= OVERFLOW;
1392 }
1393
1394
1395 Exchanges->fcExchange[x_ID].status = dwStatus;
1396
1397
1398
1399
1400
1401 if (RPCset)
1402 {
1403
1404 cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, x_ID);
1405
1406 }
1407
1408 else
1409 {
1410
1411
1412
1413
1414 ulFibreFrame[0] = x_ID;
1415
1416
1417 if (Exchanges->fcExchange[x_ID].type == SCSI_TWE) {
1418
1419
1420 }
1421 }
1422 } else
1423 {
1424 printk("IN FCP_XCHG: bad x_ID: %Xh\n", x_ID);
1425 }
1426
1427 break;
1428
1429
1430
1431
1432 case INBOUND_SCSI_DATA_COMMAND:
1433 case BAD_SCSI_FRAME:
1434 case INB_SCSI_STATUS_COMPLETION:
1435 case BUFFER_PROCESSED_COMPLETION:
1436 break;
1437 }
1438
1439
1440
1441 fcChip->IMQ->consumerIndex++;
1442 if (fcChip->IMQ->consumerIndex >= IMQ_LEN)
1443 fcChip->IMQ->consumerIndex = 0L;
1444
1445
1446 if (fcChip->IMQ->producerIndex == fcChip->IMQ->consumerIndex) {
1447 iStatus = 0;
1448
1449 } else
1450 iStatus = 1;
1451
1452
1453
1454
1455
1456
1457
1458 writel(fcChip->IMQ->consumerIndex, (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));
1459
1460#if IMQ_DEBUG
1461 printk("Process IMQ: writing consumer ndx %d\n ", fcChip->IMQ->consumerIndex);
1462 printk("PI %X, CI %X\n", fcChip->IMQ->producerIndex, fcChip->IMQ->consumerIndex);
1463#endif
1464
1465
1466
1467 } else {
1468
1469 iStatus = -1;
1470#if IMQ_DEBUG
1471 printk("Process IMQ: no message PI %Xh CI %Xh", fcChip->IMQ->producerIndex, fcChip->IMQ->consumerIndex);
1472#endif
1473 }
1474
1475 LEAVE("ProcessIMQEntry");
1476
1477 return iStatus;
1478}
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499int CpqTsInitializeTachLite(void *pHBA, int opcode1, int opcode2)
1500{
1501 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
1502 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1503 u32 ulBuff;
1504 u8 bBuff;
1505 int iStatus = -1;
1506
1507 ENTER("InitializeTachLite");
1508
1509
1510
1511 if (!fcChip->Registers.ReMapMemBase)
1512 return -1;
1513
1514
1515
1516 switch (opcode1) {
1517 case 1:
1518
1519
1520 iStatus = fcChip->ResetTachyon(cpqfcHBAdata, opcode2);
1521
1522
1523
1524
1525
1526
1527
1528
1529 if (iStatus)
1530 break;
1531
1532 case 2:
1533
1534
1535
1536
1537 ulBuff = 0x80000000;
1538
1539 writel(ulBuff, fcChip->Registers.TYconfig.address);
1540
1541
1542
1543
1544
1545
1546
1547
1548 fcChip->Registers.TYconfig.value = readl(fcChip->Registers.TYconfig.address);
1549
1550
1551 pci_read_config_byte(cpqfcHBAdata->PciDev, 0x43,
1552 &bBuff);
1553
1554 fcChip->Registers.PCIMCTR = bBuff;
1555
1556
1557
1558 fcChip->Registers.TYstatus.value = readl(fcChip->Registers.TYstatus.address);
1559
1560 {
1561
1562
1563
1564
1565 u32 RevId = (fcChip->Registers.TYstatus.value & 0x3E0) >> 5;
1566 u8 Minor = (u8) (RevId & 0x3);
1567 u8 Major = (u8) ((RevId & 0x1C) >> 2);
1568
1569 printk(" HBA Tachyon RevId %d.%d\n", Major, Minor);
1570 if ((Major == 1) && (Minor == 2)) {
1571 sprintf(cpqfcHBAdata->fcChip.Name, STACHLITE66_TS12);
1572
1573 } else if ((Major == 1) && (Minor == 3)) {
1574 sprintf(cpqfcHBAdata->fcChip.Name, STACHLITE66_TS13);
1575 } else if ((Major == 2) && (Minor == 1)) {
1576 sprintf(cpqfcHBAdata->fcChip.Name, SAGILENT_XL2_21);
1577 } else
1578 sprintf(cpqfcHBAdata->fcChip.Name, STACHLITE_UNKNOWN);
1579 }
1580
1581
1582
1583 case 3:
1584 iStatus = CpqTsCreateTachLiteQues(cpqfcHBAdata, opcode2);
1585
1586 if (iStatus)
1587 break;
1588
1589
1590
1591
1592 writeb(0x1F, fcChip->Registers.ReMapMemBase + IINTEN);
1593
1594
1595 case 4:
1596
1597
1598
1599 iStatus = CpqTsInitializeFrameManager(fcChip, 0);
1600 if (iStatus) {
1601
1602 break;
1603 }
1604
1605 default:
1606 break;
1607 }
1608 LEAVE("InitializeTachLite");
1609
1610 return iStatus;
1611}
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621int CpqTsDestroyTachLiteQues(void *pHBA, int opcode)
1622{
1623 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
1624 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1625 u16 i, iStatus = 0;
1626 void *vPtr;
1627 unsigned long ulPtr;
1628 FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1629 PSGPAGES j, next;
1630
1631 ENTER("DestroyTachLiteQues");
1632
1633 if (fcChip->SEST) {
1634
1635
1636 for (i = 0; i < TACH_SEST_LEN; i++)
1637 {
1638
1639
1640
1641 if (Exchanges->fcExchange[i].Cmnd != NULL)
1642 cpqfc_pci_unmap(cpqfcHBAdata->PciDev, Exchanges->fcExchange[i].Cmnd, fcChip, i);
1643
1644 for (j = fcChip->SEST->sgPages[i]; j != NULL; j = next) {
1645 next = j->next;
1646 kfree(j);
1647 }
1648 fcChip->SEST->sgPages[i] = NULL;
1649 }
1650 ulPtr = (unsigned long) fcChip->SEST;
1651 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL);
1652 fcChip->SEST = 0L;
1653 if (!vPtr) {
1654 printk("SEST mem not freed\n");
1655 iStatus = -1;
1656 }
1657 }
1658
1659 if (fcChip->SFQ) {
1660
1661 ulPtr = (unsigned long) fcChip->SFQ;
1662 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL);
1663 fcChip->SFQ = 0L;
1664 if (!vPtr) {
1665 printk("SFQ mem not freed\n");
1666 iStatus = -2;
1667 }
1668 }
1669
1670
1671 if (fcChip->IMQ) {
1672
1673 fcChip->IMQ->producerIndex = 0;
1674 fcChip->IMQ->consumerIndex = 0;
1675
1676 ulPtr = (unsigned long) fcChip->IMQ;
1677 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL);
1678 fcChip->IMQ = 0L;
1679 if (!vPtr) {
1680 printk("IMQ mem not freed\n");
1681 iStatus = -3;
1682 }
1683 }
1684
1685 if (fcChip->ERQ)
1686 {
1687 ulPtr = (unsigned long) fcChip->ERQ;
1688 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL);
1689 fcChip->ERQ = 0L;
1690 if (!vPtr) {
1691 printk("ERQ mem not freed\n");
1692 iStatus = -4;
1693 }
1694 }
1695
1696 cpqfc_free_dma_consistent(cpqfcHBAdata);
1697
1698 LEAVE("DestroyTachLiteQues");
1699
1700 return iStatus;
1701}
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720static void CpqTsGetSFQEntry(PTACHYON fcChip, u16 producerNdx, u32 * ulDestPtr,
1721 u8 UpdateChip)
1722{
1723 u32 total_bytes = 0;
1724 u32 consumerIndex = fcChip->SFQ->consumerIndex;
1725
1726
1727
1728
1729
1730 while (producerNdx != consumerIndex) {
1731 total_bytes += 64;
1732
1733 if (total_bytes <= 2048) {
1734 memcpy(ulDestPtr, &fcChip->SFQ->QEntry[consumerIndex], 64);
1735 ulDestPtr += 16;
1736 }
1737
1738
1739
1740 if (++consumerIndex >= SFQ_LEN)
1741 consumerIndex = 0L;
1742 }
1743
1744
1745 if (UpdateChip) {
1746 fcChip->SFQ->consumerIndex = consumerIndex;
1747 writel(fcChip->SFQ->consumerIndex, fcChip->Registers.SFQconsumerIndex.address);
1748 }
1749}
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759void CpqTsUnFreezeTachlite(void *pChip, int type)
1760{
1761 PTACHYON fcChip = (PTACHYON) pChip;
1762 fcChip->Registers.TYcontrol.value = readl(fcChip->Registers.TYcontrol.address);
1763
1764
1765
1766
1767
1768
1769
1770 if (!(fcChip->Registers.FMstatus.value & 0x07000000L) &&
1771 !(fcChip->Registers.FMstatus.value & 0x80))
1772 {
1773 fcChip->Registers.TYcontrol.value &= ~0x300L;
1774 if (type == 1)
1775 {
1776
1777 fcChip->Registers.TYcontrol.value |= 0x10000L;
1778 } else
1779 {
1780
1781
1782
1783 fcChip->Registers.TYcontrol.value |= 0x70000L;
1784 }
1785
1786 writel(fcChip->Registers.TYcontrol.value, fcChip->Registers.TYcontrol.address);
1787
1788 }
1789
1790 fcChip->Registers.TYstatus.value = readl(fcChip->Registers.TYstatus.address);
1791}
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801void CpqTsFreezeTachlite(void *pChip, int type)
1802{
1803 PTACHYON fcChip = (PTACHYON) pChip;
1804 fcChip->Registers.TYcontrol.value = readl(fcChip->Registers.TYcontrol.address);
1805
1806
1807 if (type == 1)
1808 fcChip->Registers.TYcontrol.value |= 0x100L;
1809 else
1810 fcChip->Registers.TYcontrol.value |= 0x300L;
1811
1812 writel(fcChip->Registers.TYcontrol.value, fcChip->Registers.TYcontrol.address);
1813
1814}
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825void fcParseLinkStatusCounters(PTACHYON fcChip)
1826{
1827 u8 bBuff;
1828 u32 ulBuff;
1829
1830
1831
1832
1833
1834
1835
1836
1837 if (fcChip->fcStats.lastBB0timer == 0L)
1838 {
1839
1840 fcChip->fcStats.lastBB0timer = fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
1841 } else
1842 {
1843
1844 ulBuff = fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
1845 if (fcChip->fcStats.lastBB0timer > ulBuff)
1846 {
1847
1848 fcChip->fcStats.BB0_Timer += (0x00FFFFFFL - fcChip->fcStats.lastBB0timer);
1849 fcChip->fcStats.BB0_Timer += ulBuff;
1850
1851
1852 } else
1853 {
1854 fcChip->fcStats.BB0_Timer += (ulBuff - fcChip->fcStats.lastBB0timer);
1855
1856 }
1857
1858 fcChip->fcStats.lastBB0timer = ulBuff;
1859 }
1860
1861
1862
1863 bBuff = (u8) (fcChip->Registers.FMLinkStatus1.value >> 24);
1864 fcChip->fcStats.LossofSignal += bBuff;
1865
1866 bBuff = (u8) (fcChip->Registers.FMLinkStatus1.value >> 16);
1867 fcChip->fcStats.BadRXChar += bBuff;
1868
1869 bBuff = (u8) (fcChip->Registers.FMLinkStatus1.value >> 8);
1870 fcChip->fcStats.LossofSync += bBuff;
1871
1872
1873 bBuff = (u8) (fcChip->Registers.FMLinkStatus2.value >> 24);
1874 fcChip->fcStats.Rx_EOFa += bBuff;
1875
1876 bBuff = (u8) (fcChip->Registers.FMLinkStatus2.value >> 16);
1877 fcChip->fcStats.Dis_Frm += bBuff;
1878
1879 bBuff = (u8) (fcChip->Registers.FMLinkStatus2.value >> 8);
1880 fcChip->fcStats.Bad_CRC += bBuff;
1881}
1882
1883
1884void cpqfcTSClearLinkStatusCounters(PTACHYON fcChip)
1885{
1886 ENTER("ClearLinkStatusCounters");
1887 memset(&fcChip->fcStats, 0, sizeof(FCSTATS));
1888 LEAVE("ClearLinkStatusCounters");
1889
1890}
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916int CpqTsReadWriteWWN(void * pChip, int Read)
1917{
1918 PTACHYON fcChip = (PTACHYON) pChip;
1919#define NVRAM_SIZE 512
1920 unsigned short i, count = NVRAM_SIZE;
1921 u8 nvRam[NVRAM_SIZE], WWNbuf[8];
1922 u32 ulBuff;
1923 int iStatus = -1;
1924 int WWNoffset;
1925
1926 ENTER("ReadWriteWWN");
1927
1928
1929 if (Read)
1930 {
1931 ulBuff = cpqfcTS_ReadNVRAM(fcChip->Registers.TYstatus.address, fcChip->Registers.TYcontrol.address, count, &nvRam[0]);
1932
1933 if (ulBuff)
1934 {
1935 iStatus = 0;
1936
1937
1938
1939
1940
1941
1942 WWNoffset = cpqfcTS_GetNVRAM_data(WWNbuf, nvRam);
1943
1944 if (!WWNoffset)
1945 {
1946 printk("CAUTION: Copying NVRAM data on fcChip\n");
1947 for (i = 0; i < 8; i++)
1948 WWNbuf[i] = nvRam[i + 0x2f];
1949 }
1950
1951 fcChip->Registers.wwn_hi = 0L;
1952 fcChip->Registers.wwn_lo = 0L;
1953 for (i = 0; i < 4; i++)
1954 {
1955 ulBuff = 0L;
1956 ulBuff = (u32) (WWNbuf[i]) << (8 * (3 - i));
1957 fcChip->Registers.wwn_hi |= ulBuff;
1958 }
1959 for (i = 0; i < 4; i++)
1960 {
1961 ulBuff = 0L;
1962 ulBuff = (u32) (WWNbuf[i + 4]) << (8 * (3 - i));
1963 fcChip->Registers.wwn_lo |= ulBuff;
1964 }
1965 }
1966 else {
1967
1968 printk("cpqfcTS: NVRAM read failed\n");
1969
1970 }
1971 }
1972
1973 else
1974 {
1975
1976
1977
1978
1979 printk("ReadWriteNRAM: can't write NVRAM; aborting write\n");
1980 }
1981
1982 LEAVE("ReadWriteWWN");
1983 return iStatus;
1984}
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995int CpqTsReadWriteNVRAM(void * pChip, void * buf, int Read)
1996{
1997 PTACHYON fcChip = (PTACHYON) pChip;
1998#define NVRAM_SIZE 512
1999 u32 ulBuff;
2000 u8 *ucPtr = buf;
2001 int iStatus = -1;
2002
2003
2004 if (Read)
2005 {
2006 ulBuff = cpqfcTS_ReadNVRAM(
2007 fcChip->Registers.TYstatus.address, fcChip->Registers.TYcontrol.address, 256,
2008 ucPtr);
2009
2010
2011 if (ulBuff)
2012 iStatus = 0;
2013 else {
2014#ifdef DBG
2015 printk("CAUTION: NVRAM read failed\n");
2016#endif
2017 }
2018 }
2019
2020 else
2021 {
2022
2023 printk("cpqfcTS: WRITE of FC Controller's NVRAM disabled\n");
2024 }
2025
2026 return iStatus;
2027}
2028