ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / scsi / cpqfcTScontrol.c
1 /* Copyright 2000, Compaq Computer Corporation 
2  * Fibre Channel Host Bus Adapter 
3  * 64-bit, 66MHz PCI 
4  * Originally developed and tested on:
5  * (front): [chip] Tachyon TS HPFC-5166A/1.2  L2C1090 ...
6  *          SP# P225CXCBFIEL6T, Rev XC
7  *          SP# 161290-001, Rev XD
8  * (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2, or (at your option) any
13  * later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  * Written by Don Zimmerman
20 */
21 /* These functions control the host bus adapter (HBA) hardware.  The main chip
22    control takes place in the interrupt handler where we process the IMQ 
23    (Inbound Message Queue).  The IMQ is Tachyon's way of communicating FC link
24    events and state information to the driver.  The Single Frame Queue (SFQ)
25    buffers incoming FC frames for processing by the driver.  References to 
26    "TL/TS UG" are for:
27    "HP HPFC-5100/5166 Tachyon TL/TS ICs User Guide", August 16, 1999, 1st Ed.
28    Hewlitt Packard Manual Part Number 5968-1083E.
29 */
30
31 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
32
33 #include <linux/blkdev.h>
34 #include <linux/kernel.h>
35 #include <linux/string.h>
36 #include <linux/ioport.h>  // request_region() prototype
37 #include <linux/sched.h>
38 #include <linux/slab.h>  // need "kfree" for ext. S/G pages
39 #include <linux/types.h>
40 #include <linux/pci.h>
41 #include <linux/delay.h>
42 #include <linux/unistd.h>
43 #include <asm/io.h>  // struct pt_regs for IRQ handler & Port I/O
44 #include <asm/irq.h>
45 #include <linux/spinlock.h>
46
47 #include "scsi.h"
48 #include "hosts.h"   // Scsi_Host definition for INT handler
49 #include "cpqfcTSchip.h"
50 #include "cpqfcTSstructs.h"
51
52 //#define IMQ_DEBUG 1
53
54 static void fcParseLinkStatusCounters(TACHYON * fcChip);
55 static void CpqTsGetSFQEntry(TACHYON * fcChip, 
56               USHORT pi, ULONG * buffr, BOOLEAN UpdateChip); 
57
58 static void 
59 cpqfc_free_dma_consistent(CPQFCHBA *cpqfcHBAdata)
60 {
61         // free up the primary EXCHANGES struct and Link Q
62         PTACHYON fcChip = &cpqfcHBAdata->fcChip;
63
64         if (fcChip->Exchanges != NULL)
65                 pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_EXCHANGES),
66                         fcChip->Exchanges, fcChip->exch_dma_handle);
67         fcChip->Exchanges = NULL;
68         if (cpqfcHBAdata->fcLQ != NULL)
69                 pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_LINK_QUE),
70                         cpqfcHBAdata->fcLQ, cpqfcHBAdata->fcLQ_dma_handle);
71         cpqfcHBAdata->fcLQ = NULL;
72 }
73
74 // Note special requirements for Q alignment!  (TL/TS UG pg. 190)
75 // We place critical index pointers at end of QUE elements to assist
76 // in non-symbolic (i.e. memory dump) debugging
77 // opcode defines placement of Queues (e.g. local/external RAM)
78
79 int CpqTsCreateTachLiteQues( void* pHBA, int opcode)
80 {
81   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;
82   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
83
84   int iStatus=0;
85   unsigned long ulAddr;
86   dma_addr_t ERQdma, IMQdma, SPQdma, SESTdma;
87   int i;
88
89   // NOTE! fcMemManager() will return system virtual addresses.
90   // System (kernel) virtual addresses, though non-paged, still
91   // aren't physical addresses.  Convert to PHYSICAL_ADDRESS for Tachyon's
92   // DMA use.
93   ENTER("CreateTachLiteQues");
94
95
96   // Allocate primary EXCHANGES array...
97   fcChip->Exchanges = NULL;
98   cpqfcHBAdata->fcLQ = NULL;
99   
100   /* printk("Allocating %u for %u Exchanges ", 
101           (ULONG)sizeof(FC_EXCHANGES), TACH_MAX_XID); */
102   fcChip->Exchanges = pci_alloc_consistent(cpqfcHBAdata->PciDev, 
103                         sizeof(FC_EXCHANGES), &fcChip->exch_dma_handle);
104   /* printk("@ %p\n", fcChip->Exchanges); */
105
106   if( fcChip->Exchanges == NULL ) // fatal error!!
107   {
108     printk("pci_alloc_consistent failure on Exchanges: fatal error\n");
109     return -1;
110   }
111   // zero out the entire EXCHANGE space
112   memset( fcChip->Exchanges, 0, sizeof( FC_EXCHANGES));  
113
114
115   /* printk("Allocating %u for LinkQ ", (ULONG)sizeof(FC_LINK_QUE)); */
116   cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev,
117                                  sizeof( FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle);
118   /* printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH); */
119   memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE));
120
121   if( cpqfcHBAdata->fcLQ == NULL ) // fatal error!!
122   {
123     cpqfc_free_dma_consistent(cpqfcHBAdata);
124     printk("pci_alloc_consistent() failure on fc Link Que: fatal error\n");
125     return -1;
126   }
127   // zero out the entire EXCHANGE space
128   memset( cpqfcHBAdata->fcLQ, 0, sizeof( FC_LINK_QUE));  
129   
130   // Verify that basic Tach I/O registers are not NULL  
131   if( !fcChip->Registers.ReMapMemBase )
132   {
133     cpqfc_free_dma_consistent(cpqfcHBAdata);
134     printk("HBA base address NULL: fatal error\n");
135     return -1;
136   }
137
138
139   // Initialize the fcMemManager memory pairs (stores allocated/aligned
140   // pairs for future freeing)
141   memset( cpqfcHBAdata->dynamic_mem, 0, sizeof(cpqfcHBAdata->dynamic_mem));
142   
143
144   // Allocate Tach's Exchange Request Queue (each ERQ entry 32 bytes)
145   
146   fcChip->ERQ = fcMemManager( cpqfcHBAdata->PciDev, 
147                         &cpqfcHBAdata->dynamic_mem[0], 
148                         sizeof( TachLiteERQ ), 32*(ERQ_LEN), 0L, &ERQdma);
149   if( !fcChip->ERQ )
150   {
151     cpqfc_free_dma_consistent(cpqfcHBAdata);
152     printk("pci_alloc_consistent/alignment failure on ERQ: fatal error\n");
153     return -1;
154   }
155   fcChip->ERQ->length = ERQ_LEN-1;
156   ulAddr = (ULONG) ERQdma; 
157 #if BITS_PER_LONG > 32
158   if( (ulAddr >> 32) )
159   {
160     cpqfc_free_dma_consistent(cpqfcHBAdata);
161     printk(" FATAL! ERQ ptr %p exceeds Tachyon's 32-bit register size\n",
162                     (void*)ulAddr);
163     return -1;  // failed
164   }
165 #endif
166   fcChip->ERQ->base = (ULONG)ulAddr;  // copy for quick reference
167
168
169   // Allocate Tach's Inbound Message Queue (32 bytes per entry)
170   
171   fcChip->IMQ = fcMemManager( cpqfcHBAdata->PciDev, 
172                   &cpqfcHBAdata->dynamic_mem[0],
173                   sizeof( TachyonIMQ ), 32*(IMQ_LEN), 0L, &IMQdma );
174   if( !fcChip->IMQ )
175   {
176     cpqfc_free_dma_consistent(cpqfcHBAdata);
177     printk("pci_alloc_consistent/alignment failure on IMQ: fatal error\n");
178     return -1;
179   }
180   fcChip->IMQ->length = IMQ_LEN-1;
181
182   ulAddr = IMQdma;
183 #if BITS_PER_LONG > 32
184   if( (ulAddr >> 32) )
185   {
186     cpqfc_free_dma_consistent(cpqfcHBAdata);
187     printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n",
188                     (void*)ulAddr);
189     return -1;  // failed
190   }
191 #endif
192   fcChip->IMQ->base = (ULONG)ulAddr;  // copy for quick reference
193
194
195   // Allocate Tach's  Single Frame Queue (64 bytes per entry)
196   fcChip->SFQ = fcMemManager( cpqfcHBAdata->PciDev, 
197                   &cpqfcHBAdata->dynamic_mem[0],
198                   sizeof( TachLiteSFQ ), 64*(SFQ_LEN),0L, &SPQdma );
199   if( !fcChip->SFQ )
200   {
201     cpqfc_free_dma_consistent(cpqfcHBAdata);
202     printk("pci_alloc_consistent/alignment failure on SFQ: fatal error\n");
203     return -1;
204   }
205   fcChip->SFQ->length = SFQ_LEN-1;      // i.e. Que length [# entries -
206                                        // min. 32; max.  4096 (0xffff)]
207   
208   ulAddr = SPQdma;
209 #if BITS_PER_LONG > 32
210   if( (ulAddr >> 32) )
211   {
212     cpqfc_free_dma_consistent(cpqfcHBAdata);
213     printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n",
214                     (void*)ulAddr);
215     return -1;  // failed
216   }
217 #endif
218   fcChip->SFQ->base = (ULONG)ulAddr;  // copy for quick reference
219
220
221   // Allocate SCSI Exchange State Table; aligned nearest @sizeof
222   // power-of-2 boundary
223   // LIVE DANGEROUSLY!  Assume the boundary for SEST mem will
224   // be on physical page (e.g. 4k) boundary.
225   /* printk("Allocating %u for TachSEST for %u Exchanges\n", 
226                  (ULONG)sizeof(TachSEST), TACH_SEST_LEN); */
227   fcChip->SEST = fcMemManager( cpqfcHBAdata->PciDev,
228                   &cpqfcHBAdata->dynamic_mem[0],
229                   sizeof(TachSEST),  4, 0L, &SESTdma );
230 //                sizeof(TachSEST),  64*TACH_SEST_LEN, 0L );
231   if( !fcChip->SEST )
232   {
233     cpqfc_free_dma_consistent(cpqfcHBAdata);
234     printk("pci_alloc_consistent/alignment failure on SEST: fatal error\n");
235     return -1;
236   }
237
238   for( i=0; i < TACH_SEST_LEN; i++)  // for each exchange
239       fcChip->SEST->sgPages[i] = NULL;
240
241   fcChip->SEST->length = TACH_SEST_LEN;  // e.g. DON'T subtract one 
242                                        // (TL/TS UG, pg 153)
243
244   ulAddr = SESTdma; 
245 #if BITS_PER_LONG > 32
246   if( (ulAddr >> 32) )
247   {
248     cpqfc_free_dma_consistent(cpqfcHBAdata);
249     printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n",
250                     (void*)ulAddr);
251     return -1;  // failed
252   }
253 #endif
254   fcChip->SEST->base = (ULONG)ulAddr;  // copy for quick reference
255
256
257                               // Now that structures are defined,
258                               // fill in Tachyon chip registers...
259
260                               // EEEEEEEE  EXCHANGE REQUEST QUEUE
261
262   writel( fcChip->ERQ->base, 
263     (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));
264       
265   writel( fcChip->ERQ->length,
266     (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_LENGTH));
267      
268
269   fcChip->ERQ->producerIndex = 0L;
270   writel( fcChip->ERQ->producerIndex,
271     (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_PRODUCER_INDEX));
272       
273
274                 // NOTE! write consumer index last, since the write
275                 // causes Tachyon to process the other registers
276
277   ulAddr = ((unsigned long)&fcChip->ERQ->consumerIndex - 
278                 (unsigned long)fcChip->ERQ) + (unsigned long) ERQdma;
279
280   // NOTE! Tachyon DMAs to the ERQ consumer Index host
281                 // address; must be correctly aligned
282   writel( (ULONG)ulAddr,
283     (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_CONSUMER_INDEX_ADR));
284
285
286
287                                  // IIIIIIIIIIIII  INBOUND MESSAGE QUEUE
288                                  // Tell Tachyon where the Que starts
289
290   // set the Host's pointer for Tachyon to access
291
292   /* printk("  cpqfcTS: writing IMQ BASE %Xh  ", fcChip->IMQ->base ); */
293   writel( fcChip->IMQ->base, 
294     (fcChip->Registers.ReMapMemBase + IMQ_BASE));
295
296   writel( fcChip->IMQ->length,
297     (fcChip->Registers.ReMapMemBase + IMQ_LENGTH));
298
299   writel( fcChip->IMQ->consumerIndex,
300     (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));
301
302
303                 // NOTE: TachLite DMAs to the producerIndex host address
304                 // must be correctly aligned with address bits 1-0 cleared
305     // Writing the BASE register clears the PI register, so write it last
306   ulAddr = ((unsigned long)&fcChip->IMQ->producerIndex - 
307                 (unsigned long)fcChip->IMQ) + (unsigned long) IMQdma;
308
309 #if BITS_PER_LONG > 32
310   if( (ulAddr >> 32) )
311   {
312     cpqfc_free_dma_consistent(cpqfcHBAdata);
313     printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n",
314                     (void*)ulAddr);
315     return -1;  // failed
316   }
317 #endif
318 #if DBG
319   printk("  PI %Xh\n", (ULONG)ulAddr );
320 #endif
321   writel( (ULONG)ulAddr, 
322     (fcChip->Registers.ReMapMemBase + IMQ_PRODUCER_INDEX));
323
324
325
326                                  // SSSSSSSSSSSSSSS SINGLE FRAME SEQUENCE
327                                  // Tell TachLite where the Que starts
328
329   writel( fcChip->SFQ->base, 
330     (fcChip->Registers.ReMapMemBase + TL_MEM_SFQ_BASE));
331
332   writel( fcChip->SFQ->length,
333     (fcChip->Registers.ReMapMemBase + TL_MEM_SFQ_LENGTH));
334
335
336          // tell TachLite where SEST table is & how long
337   writel( fcChip->SEST->base,
338     (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE));
339
340   /* printk("  cpqfcTS: SEST %p(virt): Wrote base %Xh @ %p\n",
341     fcChip->SEST, fcChip->SEST->base, 
342     fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE); */
343
344   writel( fcChip->SEST->length,
345     (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_LENGTH));
346       
347   writel( (TL_EXT_SG_PAGE_COUNT-1),
348     (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_SG_PAGE));
349
350
351   LEAVE("CreateTachLiteQues");
352
353   return iStatus;
354 }
355
356
357
358 // function to return TachLite to Power On state
359 // 1st - reset tachyon ('SOFT' reset)
360 // others - future
361
362 int CpqTsResetTachLite(void *pHBA, int type)
363 {
364   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;
365   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
366   ULONG ulBuff, i;
367   int ret_status=0; // def. success
368
369   ENTER("ResetTach");
370   
371   switch(type)
372   {
373
374     case CLEAR_FCPORTS:
375
376       // in case he was running previously, mask Tach's interrupt
377       writeb( 0, (fcChip->Registers.ReMapMemBase + IINTEN));
378       
379      // de-allocate mem for any Logged in ports
380       // (e.g., our module is unloading)
381       // search the forward linked list, de-allocating
382       // the memory we allocated when the port was initially logged in
383       {
384         PFC_LOGGEDIN_PORT pLoggedInPort = fcChip->fcPorts.pNextPort;
385         PFC_LOGGEDIN_PORT ptr;
386 //        printk("checking for allocated LoggedInPorts...\n");
387                         
388         while( pLoggedInPort )
389         {
390           ptr = pLoggedInPort;
391           pLoggedInPort = ptr->pNextPort;
392 //        printk("kfree(%p) on FC LoggedInPort port_id 0x%06lX\n",
393 //                        ptr, ptr->port_id);
394           kfree( ptr );
395         }
396       }
397       // (continue resetting hardware...)
398
399     case 1:                   // RESTART Tachyon (power-up state)
400
401       // in case he was running previously, mask Tach's interrupt
402       writeb( 0, (fcChip->Registers.ReMapMemBase + IINTEN));
403                               // turn OFF laser (NOTE: laser is turned
404                               // off during reset, because GPIO4 is cleared
405                               // to 0 by reset action - see TLUM, sec 7.22)
406                               // However, CPQ 64-bit HBAs have a "health
407                               // circuit" which keeps laser ON for a brief
408                               // period after it is turned off ( < 1s)
409       
410       fcChip->LaserControl( fcChip->Registers.ReMapMemBase, 0);
411   
412
413
414             // soft reset timing constraints require:
415             //   1. set RST to 1
416             //   2. read SOFTRST register 
417             //      (128 times per R. Callison code)
418             //   3. clear PCI ints
419             //   4. clear RST to 0
420       writel( 0xff000001L,
421         (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));
422         
423       for( i=0; i<128; i++)
424         ulBuff = readl( fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST);
425
426         // clear the soft reset
427       for( i=0; i<8; i++)
428         writel( 0, (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));
429
430                
431
432                                // clear out our copy of Tach regs,
433                                // because they must be invalid now,
434                                // since TachLite reset all his regs.
435       CpqTsDestroyTachLiteQues(cpqfcHBAdata,0); // remove Host-based Que structs
436       cpqfcTSClearLinkStatusCounters(fcChip);  // clear our s/w accumulators
437                                // lower bits give GBIC info
438       fcChip->Registers.TYstatus.value = 
439                       readl( fcChip->Registers.TYstatus.address );
440       break;
441
442 /*
443     case 2:                   // freeze SCSI
444     case 3:                   // reset Outbound command que (ERQ)
445     case 4:                   // unfreeze OSM (Outbound Seq. Man.) 'er'
446     case 5:                   // report status
447
448     break;
449 */
450     default:
451       ret_status = -1;  // invalid option passed to RESET function
452       break;
453   }
454   LEAVE("ResetTach");
455   return ret_status;
456 }
457
458
459
460
461
462
463 // 'addrBase' is IOBaseU for both TachLite and (older) Tachyon
464 int CpqTsLaserControl( void* addrBase, int opcode )
465 {
466   ULONG dwBuff;
467
468   dwBuff = readl((addrBase + TL_MEM_TACH_CONTROL) ); // read TL Control reg
469                                                     // (change only bit 4)
470   if( opcode == 1)
471     dwBuff |= ~0xffffffefL; // set - ON
472   else
473     dwBuff &= 0xffffffefL;  // clear - OFF
474   writel( dwBuff, (addrBase + TL_MEM_TACH_CONTROL)); // write TL Control reg
475   return 0;
476 }
477
478
479
480
481
482 // Use controller's "Options" field to determine loopback mode (if any)
483 //   internal loopback (silicon - no GBIC)
484 //   external loopback (GBIC - no FC loop)
485 //   no loopback: L_PORT, external cable from GBIC required
486
487 int CpqTsInitializeFrameManager( void *pChip, int opcode)
488 {
489   PTACHYON fcChip;
490   int iStatus;
491   ULONG wwnLo, wwnHi; // for readback verification
492
493   ENTER("InitializeFrameManager");
494   fcChip = (PTACHYON)pChip;
495   if( !fcChip->Registers.ReMapMemBase )   // undefined controller?
496     return -1;
497
498   // TL/TS UG, pg. 184
499   // 0x0065 = 100ms for RT_TOV
500   // 0x01f5 = 500ms for ED_TOV
501   // 0x07D1 = 2000ms 
502   fcChip->Registers.ed_tov.value = 0x006507D1; 
503   writel( fcChip->Registers.ed_tov.value,
504     (fcChip->Registers.ed_tov.address));
505       
506
507   // Set LP_TOV to the FC-AL2 specified 2 secs.
508   // TL/TS UG, pg. 185
509   writel( 0x07d00010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2);
510
511
512   // Now try to read the WWN from the adapter's NVRAM
513   iStatus = CpqTsReadWriteWWN( fcChip, 1); // '1' for READ
514
515   if( iStatus )   // NVRAM read failed?
516   {
517     printk(" WARNING! HBA NVRAM WWN read failed - make alias\n");
518     // make up a WWN.  If NULL or duplicated on loop, FC loop may hang!
519
520
521     fcChip->Registers.wwn_hi = (__u32)jiffies;
522     fcChip->Registers.wwn_hi |= 0x50000000L;
523     fcChip->Registers.wwn_lo = 0x44556677L;
524   }
525
526   
527   writel( fcChip->Registers.wwn_hi, 
528           fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI);
529   
530   writel( fcChip->Registers.wwn_lo, 
531           fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);
532           
533
534   // readback for verification:
535   wwnHi = readl( fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI ); 
536           
537   wwnLo = readl( fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);
538   // test for correct chip register WRITE/READ
539   DEBUG_PCI( printk("  WWN %08X%08X\n",
540     fcChip->Registers.wwn_hi, fcChip->Registers.wwn_lo ) );
541     
542   if( wwnHi != fcChip->Registers.wwn_hi ||
543       wwnLo != fcChip->Registers.wwn_lo )
544   {
545     printk( "cpqfcTS: WorldWideName register load failed\n");
546     return -1; // FAILED!
547   }
548
549
550
551                         // set Frame Manager Initialize command
552   fcChip->Registers.FMcontrol.value = 0x06;
553
554   // Note: for test/debug purposes, we may use "Hard" address,
555   // but we completely support "soft" addressing, including
556   // dynamically changing our address.
557   if( fcChip->Options.intLoopback == 1 )            // internal loopback
558     fcChip->Registers.FMconfig.value = 0x0f002080L;
559   else if( fcChip->Options.extLoopback == 1 )            // internal loopback
560     fcChip->Registers.FMconfig.value = 0x0f004080L;
561   else                  // L_Port
562     fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start)
563 //    fcChip->Registers.FMconfig.value = 0x01000080L; // soft address (can't pick)
564 //    fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start)
565                 
566   // write config to FM
567
568   if( !fcChip->Options.intLoopback && !fcChip->Options.extLoopback )
569                                // (also need LASER for real LOOP)
570     fcChip->LaserControl( fcChip->Registers.ReMapMemBase, 1); // turn on LASER
571
572   writel( fcChip->Registers.FMconfig.value,
573     fcChip->Registers.FMconfig.address);
574     
575
576                                // issue INITIALIZE command to FM - ACTION!
577   writel( fcChip->Registers.FMcontrol.value,
578     fcChip->Registers.FMcontrol.address);
579     
580   LEAVE("InitializeFrameManager");
581   
582   return 0;
583 }
584
585
586
587
588
589 // This "look ahead" function examines the IMQ for occurrence of
590 // "type".  Returns 1 if found, 0 if not.
591 static int PeekIMQEntry( PTACHYON fcChip, ULONG type)
592 {
593   ULONG CI = fcChip->IMQ->consumerIndex;
594   ULONG PI = fcChip->IMQ->producerIndex; // snapshot of IMQ indexes
595   
596   while( CI != PI )
597   {                             // proceed with search
598     if( (++CI) >= IMQ_LEN ) CI = 0; // rollover check
599     
600     switch( type )
601     {
602       case ELS_LILP_FRAME:
603       {
604       // first, we need to find an Inbound Completion message,
605       // If we find it, check the incoming frame payload (1st word)
606       // for LILP frame
607         if( (fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x104 )
608         { 
609           TachFCHDR_GCMND* fchs;
610           ULONG ulFibreFrame[2048/4];  // max DWORDS in incoming FC Frame
611           USHORT SFQpi = (USHORT)(fcChip->IMQ->QEntry[CI].word[0] & 0x0fffL);
612
613           CpqTsGetSFQEntry( fcChip,
614             SFQpi,        // SFQ producer ndx         
615             ulFibreFrame, // contiguous dest. buffer
616             FALSE);       // DON'T update chip--this is a "lookahead"
617           
618           fchs = (TachFCHDR_GCMND*)&ulFibreFrame;
619           if( fchs->pl[0] == ELS_LILP_FRAME)
620           {
621             return 1; // found the LILP frame!
622           }
623           else
624           {
625             // keep looking...
626           }
627         }  
628       }
629       break;
630
631       case OUTBOUND_COMPLETION:
632         if( (fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x00 )
633         {
634
635           // any OCM errors?
636           if( fcChip->IMQ->QEntry[CI].word[2] & 0x7a000000L )
637             return 1;               // found OCM error
638         }
639       break;
640
641
642       
643       default:
644       break;
645     }
646   }
647   return 0; // failed to find "type"
648 }
649
650                         
651 static void SetTachTOV( CPQFCHBA* cpqfcHBAdata)
652 {
653   PTACHYON fcChip = &cpqfcHBAdata->fcChip; 
654   
655   // TL/TS UG, pg. 184
656   // 0x0065 = 100ms for RT_TOV
657   // 0x01f5 = 500ms for ED_TOV
658   // 0x07d1 = 2000ms for ED_TOV
659
660   // SANMark Level 1 requires an "initialization backoff"
661   // (See "SANMark Test Suite Level 1":
662   // initialization_timeout.fcal.SANMark-1.fc)
663   // We have to use 2sec, 24sec, then 128sec when login/
664   // port discovery processes fail to complete.
665   
666   // when port discovery completes (logins done), we set
667   // ED_TOV to 500ms -- this is the normal operational case
668   // On the first Link Down, we'll move to 2 secs (7D1 ms)
669   if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x1f5)
670     fcChip->Registers.ed_tov.value = 0x006507D1; 
671   
672   // If we get another LST after we moved TOV to 2 sec,
673   // increase to 24 seconds (5DC1 ms) per SANMark!
674   else if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x7D1)
675     fcChip->Registers.ed_tov.value = 0x00655DC1; 
676
677   // If we get still another LST, set the max TOV (Tachyon
678   // has only 16 bits for ms timer, so the max is 65.5 sec)
679   else if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x5DC1)
680     fcChip->Registers.ed_tov.value = 0x0065FFFF; 
681
682   writel( fcChip->Registers.ed_tov.value,
683     (fcChip->Registers.ed_tov.address));
684   // keep the same 2sec LP_TOV 
685   writel( 0x07D00010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2);
686 }       
687
688
689 // The IMQ is an array with IMQ_LEN length, each element (QEntry)
690 // with eight 32-bit words.  Tachyon PRODUCES a QEntry with each
691 // message it wants to send to the host.  The host CONSUMES IMQ entries
692
693 // This function copies the current
694 // (or oldest not-yet-processed) QEntry to
695 // the caller, clears/ re-enables the interrupt, and updates the
696 // (Host) Consumer Index.
697 // Return value:
698 //  0   message processed, none remain (producer and consumer
699 //        indexes match)
700 //  1   message processed, more messages remain
701 // -1   no message processed - none were available to process
702 // Remarks:
703 //   TL/TS UG specifices that the following actions for
704 //   INTA_L handling:
705 //   1. read PCI Interrupt Status register (0xff)
706 //   2. all IMQ messages should be processed before writing the
707 //      IMQ consumer index.
708
709
710 int CpqTsProcessIMQEntry(void *host)
711 {
712   struct Scsi_Host *HostAdapter = (struct Scsi_Host *)host;
713   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
714   PTACHYON fcChip = &cpqfcHBAdata->fcChip; 
715   FC_EXCHANGES *Exchanges = fcChip->Exchanges;
716   int iStatus;
717   USHORT i, RPCset, DPCset;
718   ULONG x_ID;
719   ULONG ulBuff, dwStatus;
720   TachFCHDR_GCMND* fchs;
721   ULONG ulFibreFrame[2048/4];  // max number of DWORDS in incoming Fibre Frame
722   UCHAR ucInboundMessageType;  // Inbound CM, dword 3 "type" field
723
724   ENTER("ProcessIMQEntry");
725    
726
727                                 // check TachLite's IMQ producer index -
728                                 // is a new message waiting for us?
729                                 // equal indexes means empty que
730
731   if( fcChip->IMQ->producerIndex != fcChip->IMQ->consumerIndex )
732   {                             // need to process message
733
734
735 #ifdef IMQ_DEBUG
736     printk("PI %X, CI %X  type: %X\n", 
737       fcChip->IMQ->producerIndex,fcChip->IMQ->consumerIndex,
738       fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type);
739 #endif                                
740     // Examine Completion Messages in IMQ
741     // what CM_Type?
742     switch( (UCHAR)(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type
743                     & 0xffL) )
744     {
745     case OUTBOUND_COMPLETION:
746
747       // Remarks:
748       // x_IDs (OX_ID, RX_ID) are partitioned by SEST entries
749       // (starting at 0), and SFS entries (starting at
750       // SEST_LEN -- outside the SEST space).
751       // Psuedo code:
752       // x_ID (OX_ID or RX_ID) from message is Trans_ID or SEST index
753       // range check - x_ID
754       //   if x_ID outside 'Transactions' length, error - exit
755       // if any OCM error, copy error status to Exchange slot
756       // if FCP ASSIST transaction (x_ID within SEST),
757       //   call fcComplete (to App)
758       // ...
759
760
761       ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1];
762       x_ID = ulBuff & 0x7fffL;     // lower 14 bits SEST_Index/Trans_ID
763                                      // Range check CM OX/RX_ID value...
764       if( x_ID < TACH_MAX_XID )   // don't go beyond array space
765       {
766
767
768         if( ulBuff & 0x20000000L ) // RPC -Response Phase Complete?
769           RPCset = 1;              // (SEST transactions only)
770         else
771           RPCset = 0;
772
773         if( ulBuff & 0x40000000L ) // DPC -Data Phase Complete?
774           DPCset = 1;              // (SEST transactions only)
775         else
776           DPCset = 0;
777                 // set the status for this Outbound transaction's ID
778         dwStatus = 0L;
779         if( ulBuff & 0x10000000L ) // SPE? (SEST Programming Error)
780             dwStatus |= SESTPROG_ERR;
781
782         ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2];
783         if( ulBuff & 0x7a000000L ) // any other errs?
784         {
785           if( ulBuff & 0x40000000L )
786             dwStatus |= INV_ENTRY;
787           if( ulBuff & 0x20000000L )
788             dwStatus |= FRAME_TO;        // FTO
789           if( ulBuff & 0x10000000L )
790             dwStatus |= HOSTPROG_ERR;
791           if( ulBuff & 0x08000000L )
792             dwStatus |= LINKFAIL_TX;
793           if( ulBuff & 0x02000000L )
794             dwStatus |= ABORTSEQ_NOTIFY;  // ASN
795         }
796
797           
798         if( dwStatus )          // any errors?
799         {
800                   // set the Outbound Completion status
801           Exchanges->fcExchange[ x_ID ].status |= dwStatus;
802
803           // if this Outbound frame was for a SEST entry, automatically
804           // reque it in the case of LINKFAIL (it will restart on PDISC)
805           if( x_ID < TACH_SEST_LEN )
806           {
807
808             printk(" #OCM error %Xh x_ID %X# ", 
809                     dwStatus, x_ID);
810
811             Exchanges->fcExchange[x_ID].timeOut = 30000; // seconds default
812                                                  
813
814             // We Q ABTS for each exchange.
815             // NOTE: We can get FRAME_TO on bad alpa (device gone).  Since
816             // bad alpa is reported before FRAME_TO, examine the status
817             // flags to see if the device is removed.  If so, DON'T
818             // post an ABTS, since it will be terminated by the bad alpa
819             // message.
820             if( dwStatus & FRAME_TO ) // check for device removed...
821             {
822               if( !(Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED) )
823               { 
824                 // presumes device is still there: send ABTS.
825   
826                 cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);
827               }
828             }
829             else  // Abort all other errors
830             {
831               cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);
832             }
833
834             // if the HPE bit is set, we have to CLose the LOOP
835             // (see TL/TS UG, pg. 239)
836
837             if( dwStatus &= HOSTPROG_ERR )
838             // set CL bit (see TL/TS UG, pg. 172)
839               writel( 4, fcChip->Registers.FMcontrol.address);
840           }
841         }
842           // NOTE: we don't necessarily care about ALL completion messages...
843                                       // SCSI resp. complete OR
844         if( ((x_ID < TACH_SEST_LEN) && RPCset)|| 
845              (x_ID >= TACH_SEST_LEN) )  // non-SCSI command
846         {
847               // exchange done; complete to upper levels with status
848               // (if necessary) and free the exchange slot
849             
850
851           if( x_ID >= TACH_SEST_LEN ) // Link Service Outbound frame?
852                                     // A Request or Reply has been sent
853           {                         // signal waiting WorkerThread
854
855             up( cpqfcHBAdata->TYOBcomplete);   // frame is OUT of Tach
856
857                                     // WorkerThread will complete Xchng
858           }
859           else  // X_ID is for FCP assist (SEST)
860           {
861               // TBD (target mode)
862 //            fcCompleteExchange( fcChip, x_ID); // TRE completed
863           }
864         }
865       }
866       else  // ERROR CONDITION!  bogus x_ID in completion message
867       {
868
869         printk(" ProcessIMQ (OBCM) x_id out of range %Xh\n", x_ID);
870
871       }
872
873
874
875           // Load the Frame Manager's error counters.  We check them here
876           // because presumably the link is up and healthy enough for the
877           // counters to be meaningful (i.e., don't check them while loop
878           // is initializing).
879       fcChip->Registers.FMLinkStatus1.value =    // get TL's counter
880         readl(fcChip->Registers.FMLinkStatus1.address);
881                   
882       fcChip->Registers.FMLinkStatus2.value =    // get TL's counter
883         readl(fcChip->Registers.FMLinkStatus2.address);
884             
885
886       fcParseLinkStatusCounters( fcChip); // load into 6 s/w accumulators
887     break;
888
889
890
891     case ERROR_IDLE_COMPLETION:  // TachLite Error Idle...
892     
893     // We usually get this when the link goes down during heavy traffic.
894     // For now, presume that if SEST Exchanges are open, we will
895     // get this as our cue to INVALIDATE all SEST entries
896     // (and we OWN all the SEST entries).
897     // See TL/TS UG, pg. 53
898     
899       for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
900       {
901
902         // Does this VALid SEST entry need to be invalidated for Abort?
903         fcChip->SEST->u[ x_ID].IWE.Hdr_Len &= 0x7FFFFFFF; 
904       }
905       
906       CpqTsUnFreezeTachlite( fcChip, 2); // unfreeze Tachyon, if Link OK
907
908     break;
909
910
911     case INBOUND_SFS_COMPLETION:  //0x04
912           // NOTE! we must process this SFQ message to avoid SFQ filling
913           // up and stopping TachLite.  Incoming commands are placed here,
914           // as well as 'unknown' frames (e.g. LIP loop position data)
915           // write this CM's producer index to global...
916           // TL/TS UG, pg 234:
917           // Type: 0 - reserved
918           //       1 - Unassisted FCP
919           //       2 - BAD FCP
920           //       3 - Unkown Frame
921           //       4-F reserved
922
923
924       fcChip->SFQ->producerIndex = (USHORT)
925         (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] & 0x0fffL);
926
927
928       ucInboundMessageType = 0;  // default to useless frame
929
930         // we can only process two Types: 1, Unassisted FCP, and 3, Unknown
931         // Also, we aren't interested in processing frame fragments
932         // so don't Que anything with 'LKF' bit set
933       if( !(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] 
934         & 0x40000000) )  // 'LKF' link failure bit clear?
935       {
936         ucInboundMessageType = (UCHAR)  // ICM DWord3, "Type"
937         (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] & 0x0fL);
938       }
939       else
940       {
941         fcChip->fcStats.linkFailRX++;
942 //        printk("LKF (link failure) bit set on inbound message\n");
943       }
944
945           // clears SFQ entry from Tachyon buffer; copies to contiguous ulBuff
946       CpqTsGetSFQEntry(
947         fcChip,                  // i.e. this Device Object
948         (USHORT)fcChip->SFQ->producerIndex,  // SFQ producer ndx         
949         ulFibreFrame, TRUE);    // contiguous destination buffer, update chip
950                      
951         // analyze the incoming frame outside the INT handler...
952         // (i.e., Worker)
953
954       if( ucInboundMessageType == 1 )
955       {
956         fchs = (TachFCHDR_GCMND*)ulFibreFrame; // cast to examine IB frame
957         // don't fill up our Q with garbage - only accept FCP-CMND  
958         // or XRDY frames
959         if( (fchs->d_id & 0xFF000000) == 0x06000000 ) // CMND
960         {
961           // someone sent us a SCSI command
962           
963 //          fcPutScsiQue( cpqfcHBAdata, 
964 //                        SFQ_UNASSISTED_FCP, ulFibreFrame); 
965         }
966         else if( ((fchs->d_id & 0xFF000000) == 0x07000000) || // RSP (status)
967             (fchs->d_id & 0xFF000000) == 0x05000000 )  // XRDY  
968         {
969           ULONG x_ID;
970           // Unfortunately, ABTS requires a Freeze on the chip so
971           // we can modify the shared memory SEST.  When frozen,
972           // any received Exchange frames cannot be processed by
973           // Tachyon, so they will be dumped in here.  It is too
974           // complex to attempt the reconstruct these frames in
975           // the correct Exchange context, so we simply seek to
976           // find status or transfer ready frames, and cause the
977           // exchange to complete with errors before the timeout
978           // expires.  We use a Linux Scsi Cmnd result code that
979           // causes immediate retry.
980           
981
982           // Do we have an open exchange that matches this s_id
983           // and ox_id?
984           for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
985           {
986             if( (fchs->s_id & 0xFFFFFF) == 
987                  (Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF) 
988                        &&
989                 (fchs->ox_rx_id & 0xFFFF0000) == 
990                  (Exchanges->fcExchange[x_ID].fchs.ox_rx_id & 0xFFFF0000) )
991             {
992     //          printk(" #R/X frame x_ID %08X# ", fchs->ox_rx_id );
993               // simulate the anticipated error - since the
994               // SEST was frozen, frames were lost...
995               Exchanges->fcExchange[ x_ID ].status |= SFQ_FRAME;
996               
997               // presumes device is still there: send ABTS.
998               cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);
999               break;  // done
1000             }
1001           }
1002         }
1003           
1004       }
1005           
1006       else if( ucInboundMessageType == 3)
1007       {
1008         // FC Link Service frames (e.g. PLOGI, ACC) come in here.  
1009         cpqfcTSPutLinkQue( cpqfcHBAdata, SFQ_UNKNOWN, ulFibreFrame); 
1010                           
1011       }
1012
1013       else if( ucInboundMessageType == 2 ) // "bad FCP"?
1014       {
1015 #ifdef IMQ_DEBUG
1016         printk("Bad FCP incoming frame discarded\n");
1017 #endif
1018       }
1019
1020       else // don't know this type
1021       {
1022 #ifdef IMQ_DEBUG 
1023         printk("Incoming frame discarded, type: %Xh\n", ucInboundMessageType);
1024 #endif
1025       }
1026         
1027         // Check the Frame Manager's error counters.  We check them here
1028         // because presumably the link is up and healthy enough for the
1029         // counters to be meaningful (i.e., don't check them while loop
1030         // is initializing).
1031       fcChip->Registers.FMLinkStatus1.value =    // get TL's counter
1032         readl(fcChip->Registers.FMLinkStatus1.address);
1033                   
1034
1035       fcChip->Registers.FMLinkStatus2.value =    // get TL's counter
1036         readl(fcChip->Registers.FMLinkStatus2.address);
1037                 
1038
1039       break;
1040
1041
1042
1043
1044                     // We get this CM because we issued a freeze
1045                     // command to stop outbound frames.  We issue the
1046                     // freeze command at Link Up time; when this message
1047                     // is received, the ERQ base can be switched and PDISC
1048                     // frames can be sent.
1049
1050       
1051     case ERQ_FROZEN_COMPLETION:  // note: expect ERQ followed immediately
1052                                  // by FCP when freezing TL
1053       fcChip->Registers.TYstatus.value =         // read what's frozen
1054         readl(fcChip->Registers.TYstatus.address);
1055       // (do nothing; wait for FCP frozen message)
1056       break;
1057     case FCP_FROZEN_COMPLETION:
1058       
1059       fcChip->Registers.TYstatus.value =         // read what's frozen
1060         readl(fcChip->Registers.TYstatus.address);
1061       
1062       // Signal the kernel thread to proceed with SEST modification
1063       up( cpqfcHBAdata->TachFrozen);
1064
1065       break;
1066
1067
1068
1069     case INBOUND_C1_TIMEOUT:
1070     case MFS_BUF_WARN:
1071     case IMQ_BUF_WARN:
1072     break;
1073
1074
1075
1076
1077
1078         // In older Tachyons, we 'clear' the internal 'core' interrupt state
1079         // by reading the FMstatus register.  In newer TachLite (Tachyon),
1080         // we must WRITE the register
1081         // to clear the condition (TL/TS UG, pg 179)
1082     case FRAME_MGR_INTERRUPT:
1083     {
1084       PFC_LOGGEDIN_PORT pLoggedInPort; 
1085
1086       fcChip->Registers.FMstatus.value = 
1087         readl( fcChip->Registers.FMstatus.address );
1088                 
1089       // PROBLEM: It is possible, especially with "dumb" hubs that
1090       // don't automatically LIP on by-pass of ports that are going
1091       // away, for the hub by-pass process to destroy critical 
1092       // ordered sets of a frame.  The result of this is a hung LPSM
1093       // (Loop Port State Machine), which on Tachyon results in a
1094       // (default 2 sec) Loop State Timeout (LST) FM message.  We 
1095       // want to avoid this relatively huge timeout by detecting
1096       // likely scenarios which will result in LST.
1097       // To do this, we could examine FMstatus for Loss of Synchronization
1098       // and/or Elastic Store (ES) errors.  Of these, Elastic Store is better
1099       // because we get this indication more quickly than the LOS.
1100       // Not all ES errors are harmfull, so we don't want to LIP on every
1101       // ES.  Instead, on every ES, detect whether our LPSM in in one
1102       // of the LST states: ARBITRATING, OPEN, OPENED, XMITTED CLOSE,
1103       // or RECEIVED CLOSE.  (See TL/TS UG, pg. 181)
1104       // If any of these LPSM states are detected
1105       // in combination with the LIP while LDn is not set, 
1106       // send an FM init (LIP F7,F7 for loops)!
1107       // It is critical to the physical link stability NOT to reset (LIP)
1108       // more than absolutely necessary; this is a basic premise of the
1109       // SANMark level 1 spec.
1110       {
1111         ULONG Lpsm = (fcChip->Registers.FMstatus.value & 0xF0) >>4;
1112         
1113         if( (fcChip->Registers.FMstatus.value & 0x400)  // ElasticStore?
1114                       &&
1115             !(fcChip->Registers.FMstatus.value & 0x100) // NOT LDn
1116                       &&
1117             !(fcChip->Registers.FMstatus.value & 0x1000)) // NOT LF
1118         {
1119           if( (Lpsm != 0) || // not MONITORING? or
1120               !(Lpsm & 0x8) )// not already offline?
1121           {
1122           // now check the particular LST states...
1123             if( (Lpsm == ARBITRATING) || (Lpsm == OPEN) ||
1124               (Lpsm == OPENED)      || (Lpsm == XMITTD_CLOSE) ||
1125               (Lpsm == RCVD_CLOSE) )
1126             {
1127               // re-init the loop before it hangs itself!
1128               printk(" #req FMinit on E-S: LPSM %Xh# ",Lpsm);
1129
1130
1131               fcChip->fcStats.FMinits++;
1132               writel( 6, fcChip->Registers.FMcontrol.address); // LIP
1133             }
1134           }
1135         }
1136         else if( fcChip->Registers.FMstatus.value & 0x40000 ) // LST?
1137         {
1138           printk(" #req FMinit on LST, LPSM %Xh# ",Lpsm);
1139          
1140           fcChip->fcStats.FMinits++;
1141           writel( 6, fcChip->Registers.FMcontrol.address);  // LIP
1142         }  
1143       }
1144
1145
1146       // clear only the 'interrupting' type bits for this REG read
1147       writel( (fcChip->Registers.FMstatus.value & 0xff3fff00L),
1148         fcChip->Registers.FMstatus.address);
1149                           
1150
1151                // copy frame manager status to unused ULONG slot
1152       fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] =
1153           fcChip->Registers.FMstatus.value; // (for debugging)
1154
1155
1156           // Load the Frame Manager's error counters.  We check them here
1157           // because presumably the link is up and healthy enough for the
1158           // counters to be meaningful (i.e., don't check them while loop
1159           // is initializing).
1160       fcChip->Registers.FMLinkStatus1.value =   // get TL's counter
1161         readl(fcChip->Registers.FMLinkStatus1.address);
1162             
1163       fcChip->Registers.FMLinkStatus2.value =   // get TL's counter
1164         readl(fcChip->Registers.FMLinkStatus2.address);
1165           
1166           // Get FM BB_Credit Zero Reg - does not clear on READ
1167       fcChip->Registers.FMBB_CreditZero.value =   // get TL's counter
1168         readl(fcChip->Registers.FMBB_CreditZero.address);
1169             
1170
1171
1172       fcParseLinkStatusCounters( fcChip); // load into 6 s/w accumulators
1173
1174
1175                // LINK DOWN
1176
1177       if( fcChip->Registers.FMstatus.value & 0x100L ) // Link DOWN bit
1178       {                                 
1179         
1180 #ifdef IMQ_DEBUG
1181         printk("LinkDn\n");
1182 #endif
1183         printk(" #LDn# ");
1184         
1185         fcChip->fcStats.linkDown++;
1186         
1187         SetTachTOV( cpqfcHBAdata);  // must set according to SANMark
1188
1189         // Check the ERQ - force it to be "empty" to prevent Tach
1190         // from sending out frames before we do logins.
1191
1192
1193         if( fcChip->ERQ->producerIndex != fcChip->ERQ->consumerIndex)
1194         {
1195 //        printk("#ERQ PI != CI#");
1196           CpqTsFreezeTachlite( fcChip, 1); // freeze ERQ only     
1197           fcChip->ERQ->producerIndex = fcChip->ERQ->consumerIndex = 0;
1198           writel( fcChip->ERQ->base, 
1199             (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));
1200           // re-writing base forces ERQ PI to equal CI
1201   
1202         }
1203                 
1204         // link down transition occurred -- port_ids can change
1205         // on next LinkUp, so we must invalidate current logins
1206         // (and any I/O in progress) until PDISC or PLOGI/PRLI
1207         // completes
1208         {
1209           pLoggedInPort = &fcChip->fcPorts; 
1210           while( pLoggedInPort ) // for all ports which are expecting
1211                                  // PDISC after the next LIP, set the
1212                                  // logoutTimer
1213           {
1214
1215             if( pLoggedInPort->pdisc) // expecting PDISC within 2 sec?
1216             {
1217               pLoggedInPort->LOGO_timer = 3;  // we want 2 seconds
1218                                               // but Timer granularity
1219                                               // is 1 second
1220             }
1221                                 // suspend any I/O in progress until
1222                                 // PDISC received...
1223             pLoggedInPort->prli = FALSE;   // block FCP-SCSI commands
1224             
1225             pLoggedInPort = pLoggedInPort->pNextPort;
1226           }  // ... all Previously known ports checked
1227         }
1228         
1229         // since any hot plugging device may NOT support LILP frames
1230         // (such as early Tachyon chips), clear this flag indicating
1231         // we shouldn't use (our copy of) a LILP map.
1232         // If we receive an LILP frame, we'll set it again.
1233         fcChip->Options.LILPin = 0; // our LILPmap is invalid
1234         cpqfcHBAdata->PortDiscDone = 0; // must re-validate FC ports!
1235
1236           // also, we want to invalidate (i.e. INITIATOR_ABORT) any
1237           // open Login exchanges, in case the LinkDown happened in the
1238           // middle of logins.  It's possible that some ports already
1239           // ACCepted login commands which we have not processed before
1240           // another LinkDown occurred.  Any accepted Login exhanges are
1241           // invalidated by LinkDown, even before they are acknowledged.
1242           // It's also possible for a port to have a Queued Reply or Request
1243           // for login which was interrupted by LinkDown; it may come later,
1244           // but it will be unacceptable to us.
1245
1246           // we must scan the entire exchange space, find every Login type
1247           // originated by us, and abort it. This is NOT an abort due to
1248           // timeout, so we don't actually send abort to the other port -
1249           // we just complete it to free up the fcExchange slot.
1250
1251         for( i=TACH_SEST_LEN; i< TACH_MAX_XID; i++)
1252         {                     // looking for Extended Link Serv.Exchanges
1253           if( Exchanges->fcExchange[i].type == ELS_PDISC ||
1254               Exchanges->fcExchange[i].type == ELS_PLOGI ||
1255               Exchanges->fcExchange[i].type == ELS_PRLI ) 
1256           {
1257               // ABORT the exchange!
1258 #ifdef IMQ_DEBUG
1259             printk("Originator ABORT x_id %Xh, type %Xh, port_id %Xh on LDn\n",
1260               i, Exchanges->fcExchange[i].type,
1261             Exchanges->fcExchange[i].fchs.d_id);
1262 #endif
1263
1264             Exchanges->fcExchange[i].status |= INITIATOR_ABORT;
1265             cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, i); // abort on LDn
1266           }
1267         }
1268
1269       }
1270
1271              // ################   LINK UP   ##################
1272       if( fcChip->Registers.FMstatus.value & 0x200L ) // Link Up bit
1273       {                                 // AL_PA could have changed
1274
1275           // We need the following code, duplicated from LinkDn condition,
1276           // because it's possible for the Tachyon to re-initialize (hard
1277           // reset) without ever getting a LinkDn indication.
1278         pLoggedInPort = &fcChip->fcPorts; 
1279         while( pLoggedInPort )   // for all ports which are expecting
1280                                  // PDISC after the next LIP, set the
1281                                  // logoutTimer
1282         {
1283           if( pLoggedInPort->pdisc) // expecting PDISC within 2 sec?
1284           {
1285             pLoggedInPort->LOGO_timer = 3;  // we want 2 seconds
1286                                               // but Timer granularity
1287                                               // is 1 second
1288              
1289                                   // suspend any I/O in progress until
1290                                   // PDISC received...
1291
1292           }
1293           pLoggedInPort = pLoggedInPort->pNextPort;
1294         }  // ... all Previously known ports checked
1295  
1296           // CpqTs acquired AL_PA in register AL_PA (ACQ_ALPA)
1297         fcChip->Registers.rcv_al_pa.value = 
1298           readl(fcChip->Registers.rcv_al_pa.address);
1299  
1300         // Now, if our acquired address is DIFFERENT from our
1301         // previous one, we are not allow to do PDISC - we
1302         // must go back to PLOGI, which will terminate I/O in
1303         // progress for ALL logged in FC devices...
1304         // (This is highly unlikely).
1305
1306         if( (fcChip->Registers.my_al_pa & 0xFF) != 
1307             ((fcChip->Registers.rcv_al_pa.value >> 16) &0xFF) )
1308         {
1309
1310 //        printk(" #our HBA port_id changed!# "); // FC port_id changed!!       
1311
1312           pLoggedInPort = &fcChip->fcPorts; 
1313           while( pLoggedInPort ) // for all ports which are expecting
1314                                  // PDISC after the next LIP, set the
1315                                  // logoutTimer
1316           {
1317             pLoggedInPort->pdisc  = FALSE;
1318             pLoggedInPort->prli = FALSE;
1319             pLoggedInPort = pLoggedInPort->pNextPort;
1320           }  // ... all Previously known ports checked
1321
1322           // when the port_id changes, we must terminate
1323           // all open exchanges.
1324           cpqfcTSTerminateExchange( cpqfcHBAdata, NULL, PORTID_CHANGED);
1325
1326         }
1327                        
1328         // Replace the entire 24-bit port_id.  We only know the
1329         // lower 8 bits (alpa) from Tachyon; if a FLOGI is done,
1330         // we'll get the upper 16-bits from the FLOGI ACC frame.
1331         // If someone plugs into Fabric switch, we'll do FLOGI and
1332         // get full 24-bit port_id; someone could then remove and
1333         // hot-plug us into a dumb hub.  If we send a 24-bit PLOGI
1334         // to a "private" loop device, it might blow up.
1335         // Consequently, we force the upper 16-bits of port_id to
1336         // be re-set on every LinkUp transition
1337         fcChip->Registers.my_al_pa =
1338           (fcChip->Registers.rcv_al_pa.value >> 16) & 0xFF;
1339
1340               
1341               // copy frame manager status to unused ULONG slot
1342         fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] =
1343           fcChip->Registers.my_al_pa; // (for debugging)
1344
1345               // for TachLite, we need to write the acquired al_pa
1346               // back into the FMconfig register, because after
1347               // first initialization, the AQ (prev. acq.) bit gets
1348               // set, causing TL FM to use the AL_PA field in FMconfig.
1349               // (In Tachyon, FM writes the acquired AL_PA for us.)
1350         ulBuff = readl( fcChip->Registers.FMconfig.address);
1351         ulBuff &= 0x00ffffffL;  // mask out current al_pa
1352         ulBuff |= ( fcChip->Registers.my_al_pa << 24 ); // or in acq. al_pa
1353         fcChip->Registers.FMconfig.value = ulBuff; // copy it back
1354         writel( fcChip->Registers.FMconfig.value,  // put in TachLite
1355           fcChip->Registers.FMconfig.address);
1356             
1357
1358 #ifdef IMQ_DEBUG
1359         printk("#LUp %Xh, FMstat 0x%08X#", 
1360                 fcChip->Registers.my_al_pa, fcChip->Registers.FMstatus.value);
1361 #endif
1362
1363               // also set the WRITE-ONLY My_ID Register (for Fabric
1364               // initialization)
1365         writel( fcChip->Registers.my_al_pa,
1366           fcChip->Registers.ReMapMemBase +TL_MEM_TACH_My_ID);
1367           
1368
1369         fcChip->fcStats.linkUp++;
1370
1371                                      // reset TL statistics counters
1372                                      // (we ignore these error counters
1373                                      // while link is down)
1374         ulBuff =                     // just reset TL's counter
1375                  readl( fcChip->Registers.FMLinkStatus1.address);
1376           
1377         ulBuff =                     // just reset TL's counter
1378                  readl( fcChip->Registers.FMLinkStatus2.address);
1379
1380           // for initiator, need to start verifying ports (e.g. PDISC)
1381
1382
1383
1384          
1385       
1386       
1387         CpqTsUnFreezeTachlite( fcChip, 2); // unfreeze Tachlite, if Link OK
1388         
1389         // Tachyon creates an interesting problem for us on LILP frames.
1390         // Instead of writing the incoming LILP frame into the SFQ before
1391         // indicating LINK UP (the actual order of events), Tachyon tells
1392         // us LINK UP, and later us the LILP.  So we delay, then examine the
1393         // IMQ for an Inbound CM (x04); if found, we can set
1394         // LINKACTIVE after processing the LILP.  Otherwise, just proceed.
1395         // Since Tachyon imposes this time delay (and doesn't tell us
1396         // what it is), we have to impose a delay before "Peeking" the IMQ
1397         // for Tach hardware (DMA) delivery.
1398         // Processing LILP is required by SANMark
1399         udelay( 1000);  // microsec delay waiting for LILP (if it comes)
1400         if( PeekIMQEntry( fcChip, ELS_LILP_FRAME) )
1401         {  // found SFQ LILP, which will post LINKACTIVE          
1402 //        printk("skipping LINKACTIVE post\n");
1403
1404         }
1405         else
1406           cpqfcTSPutLinkQue( cpqfcHBAdata, LINKACTIVE, ulFibreFrame);  
1407       }
1408
1409
1410
1411       // ******* Set Fabric Login indication ********
1412       if( fcChip->Registers.FMstatus.value & 0x2000 )
1413       {
1414         printk(" #Fabric# ");
1415         fcChip->Options.fabric = 1;
1416       }
1417       else
1418         fcChip->Options.fabric = 0;
1419
1420       
1421       
1422                              // ******* LIP(F8,x) or BAD AL_PA? ********
1423       if( fcChip->Registers.FMstatus.value & 0x30000L )
1424       {
1425                         // copy the error AL_PAs
1426         fcChip->Registers.rcv_al_pa.value = 
1427           readl(fcChip->Registers.rcv_al_pa.address);
1428             
1429                         // Bad AL_PA?
1430         if( fcChip->Registers.FMstatus.value & 0x10000L )
1431         {
1432           PFC_LOGGEDIN_PORT pLoggedInPort;
1433         
1434                        // copy "BAD" al_pa field
1435           fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] =
1436               (fcChip->Registers.rcv_al_pa.value & 0xff00L) >> 8;
1437
1438           pLoggedInPort = fcFindLoggedInPort( fcChip,
1439             NULL,     // DON'T search Scsi Nexus
1440             fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1], // port id
1441             NULL,     // DON'T search linked list for FC WWN
1442             NULL);    // DON'T care about end of list
1443  
1444           if( pLoggedInPort )
1445           {
1446             // Just in case we got this BAD_ALPA because a device
1447             // quietly disappeared (can happen on non-managed hubs such 
1448             // as the Vixel Rapport 1000),
1449             // do an Implicit Logout.  We never expect this on a Logged
1450             // in port (but do expect it on port discovery).
1451             // (As a reasonable alternative, this could be changed to 
1452             // simply start the implicit logout timer, giving the device
1453             // several seconds to "come back".)
1454             // 
1455             printk(" #BAD alpa %Xh# ",
1456                    fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1]);
1457             cpqfcTSImplicitLogout( cpqfcHBAdata, pLoggedInPort);
1458           }
1459         }
1460                         // LIP(f8,x)?
1461         if( fcChip->Registers.FMstatus.value & 0x20000L )
1462         {
1463                         // for debugging, copy al_pa field
1464           fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] =
1465               (fcChip->Registers.rcv_al_pa.value & 0xffL);
1466                         // get the other port's al_pa
1467                         // (one that sent LIP(F8,?) )
1468         }
1469       }
1470
1471                              // Elastic store err
1472       if( fcChip->Registers.FMstatus.value & 0x400L )
1473       {
1474             // don't count e-s if loop is down!
1475         if( !(USHORT)(fcChip->Registers.FMstatus.value & 0x80) )
1476           fcChip->fcStats.e_stores++;
1477           
1478       }
1479     }
1480     break;
1481
1482
1483     case INBOUND_FCP_XCHG_COMPLETION:  // 0x0C
1484
1485     // Remarks:
1486     // On Tachlite TL/TS, we get this message when the data phase
1487     // of a SEST inbound transfer is complete.  For example, if a WRITE command
1488     // was received with OX_ID 0, we might respond with XFER_RDY with
1489     // RX_ID 8001.  This would start the SEST controlled data phases.  When
1490     // all data frames are received, we get this inbound completion. This means
1491     // we should send a status frame to complete the status phase of the 
1492     // FCP-SCSI exchange, using the same OX_ID,RX_ID that we used for data
1493     // frames.
1494     // See Outbound CM discussion of x_IDs
1495     // Psuedo Code
1496     //   Get SEST index (x_ID)
1497     //     x_ID out of range, return (err condition)
1498     //   set status bits from 2nd dword
1499     //   free transactionID & SEST entry
1500     //   call fcComplete with transactionID & status
1501
1502       ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0];
1503       x_ID = ulBuff & 0x7fffL;  // lower 14 bits SEST_Index/Trans_ID
1504                                 // (mask out MSB "direction" bit)
1505                                 // Range check CM OX/RX_ID value...
1506       if( x_ID < TACH_SEST_LEN )  // don't go beyond SEST array space
1507       {
1508
1509 //#define FCP_COMPLETION_DBG 1
1510 #ifdef FCP_COMPLETION_DBG
1511         printk(" FCP_CM x_ID %Xh, status %Xh, Cmnd %p\n", 
1512           x_ID, ulBuff, Exchanges->fcExchange[x_ID].Cmnd);
1513 #endif
1514         if( ulBuff & 0x08000000L ) // RPC -Response Phase Complete - or -
1515                                    // time to send response frame?
1516           RPCset = 1;             // (SEST transaction)
1517         else
1518           RPCset = 0;
1519                 // set the status for this Inbound SCSI transaction's ID
1520         dwStatus = 0L;
1521         if( ulBuff & 0x70000000L ) // any errs?
1522         {
1523           
1524           if( ulBuff & 0x40000000L )
1525             dwStatus |= LINKFAIL_RX;
1526           
1527           if( ulBuff & 0x20000000L )
1528             dwStatus |= COUNT_ERROR;
1529           
1530           if( ulBuff & 0x10000000L )
1531             dwStatus |= OVERFLOW;
1532         }
1533       
1534         
1535           // FCP transaction done - copy status
1536         Exchanges->fcExchange[ x_ID ].status = dwStatus;
1537
1538
1539         // Did the exchange get an FCP-RSP response frame?
1540         // (Note the little endian/big endian FC payload difference)
1541
1542         if( RPCset )             // SEST transaction Response frame rec'd
1543         {
1544           // complete the command in our driver...
1545           cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev,fcChip, x_ID);
1546
1547         }  // end "RPCset"
1548         
1549         else  // ("target" logic)
1550         {
1551             // Tachlite says all data frames have been received - now it's time
1552             // to analyze data transfer (successful?), then send a response 
1553             // frame for this exchange
1554
1555           ulFibreFrame[0] = x_ID; // copy for later reference
1556
1557           // if this was a TWE, we have to send satus response
1558           if( Exchanges->fcExchange[ x_ID].type == SCSI_TWE )
1559           {
1560 //            fcPutScsiQue( cpqfcHBAdata, 
1561 //                NEED_FCP_RSP, ulFibreFrame);  // (ulFibreFrame not used here)
1562           }
1563         }
1564       }
1565       else  // ERROR CONDITION!  bogus x_ID in completion message
1566       {
1567         printk("IN FCP_XCHG: bad x_ID: %Xh\n", x_ID);
1568       }
1569
1570     break;
1571
1572
1573
1574
1575     case INBOUND_SCSI_DATA_COMMAND:
1576     case BAD_SCSI_FRAME:
1577     case INB_SCSI_STATUS_COMPLETION:
1578     case BUFFER_PROCESSED_COMPLETION:
1579     break;
1580     }
1581
1582                                            // Tachyon is producing;
1583                                            // we are consuming
1584     fcChip->IMQ->consumerIndex++;             // increment OUR consumerIndex
1585     if( fcChip->IMQ->consumerIndex >= IMQ_LEN)// check for rollover
1586       fcChip->IMQ->consumerIndex = 0L;        // reset it
1587
1588
1589     if( fcChip->IMQ->producerIndex == fcChip->IMQ->consumerIndex )
1590     {                           // all Messages are processed -
1591       iStatus = 0;              // no more messages to process
1592
1593     }
1594     else
1595       iStatus = 1;              // more messages to process
1596
1597     // update TachLite's ConsumerIndex... (clears INTA_L)
1598     // NOTE: according to TL/TS UG, the 
1599     // "host must return completion messages in sequential order".
1600     // Does this mean one at a time, in the order received?  We
1601     // presume so.
1602
1603     writel( fcChip->IMQ->consumerIndex,
1604       (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));
1605                     
1606 #if IMQ_DEBUG
1607     printk("Process IMQ: writing consumer ndx %d\n ", 
1608       fcChip->IMQ->consumerIndex);
1609     printk("PI %X, CI %X\n", 
1610     fcChip->IMQ->producerIndex,fcChip->IMQ->consumerIndex );
1611 #endif
1612   
1613
1614
1615   }
1616   else
1617   {
1618    // hmmm... why did we get interrupted/called with no message?
1619     iStatus = -1;               // nothing to process
1620 #if IMQ_DEBUG
1621     printk("Process IMQ: no message PI %Xh  CI %Xh", 
1622       fcChip->IMQ->producerIndex,
1623       fcChip->IMQ->consumerIndex);
1624 #endif
1625   }
1626
1627   LEAVE("ProcessIMQEntry");
1628   
1629   return iStatus;
1630 }
1631
1632
1633
1634
1635
1636 // This routine initializes Tachyon according to the following
1637 // options (opcode1):
1638 // 1 - RESTART Tachyon, simulate power on condition by shutting
1639 //     down laser, resetting the hardware, de-allocating all buffers;
1640 //     continue
1641 // 2 - Config Tachyon / PCI registers;
1642 //     continue
1643 // 3 - Allocating memory and setting Tachyon queues (write Tachyon regs);
1644 //     continue
1645 // 4 - Config frame manager registers, initialize, turn on laser
1646 //
1647 // Returns:
1648 //  -1 on fatal error
1649 //   0 on success
1650
1651 int CpqTsInitializeTachLite( void *pHBA, int opcode1, int opcode2)
1652 {
1653   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;
1654   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1655   ULONG ulBuff;
1656   UCHAR bBuff;
1657   int iStatus=-1;  // assume failure
1658
1659   ENTER("InitializeTachLite");
1660
1661   // verify board's base address (sanity check)
1662
1663   if( !fcChip->Registers.ReMapMemBase)                // NULL address for card?
1664     return -1;                         // FATAL error!
1665
1666
1667
1668   switch( opcode1 )
1669   {
1670     case 1:       // restore hardware to power-on (hard) restart
1671
1672
1673       iStatus = fcChip->ResetTachyon( 
1674                   cpqfcHBAdata, opcode2); // laser off, reset hardware
1675                                       // de-allocate aligned buffers
1676
1677
1678 /* TBD      // reset FC link Q (producer and consumer = 0)
1679       fcLinkQReset(cpqfcHBAdata); 
1680
1681 */
1682
1683       if( iStatus )
1684         break;
1685
1686     case 2:       // Config PCI/Tachyon registers
1687       // NOTE: For Tach TL/TS, bit 31 must be set to 1.  For TS chips, a read
1688       // of bit 31 indicates state of M66EN signal; if 1, chip may run at 
1689       // 33-66MHz  (see TL/TS UG, pg 159)
1690
1691       ulBuff = 0x80000000;  // TachLite Configuration Register
1692
1693       writel( ulBuff, fcChip->Registers.TYconfig.address);
1694 //      ulBuff = 0x0147L;  // CpqTs PCI CFGCMD register
1695 //      WritePCIConfiguration( fcChip->Backplane.bus,
1696 //                           fcChip->Backplane.slot, TLCFGCMD, ulBuff, 4);
1697 //      ulBuff = 0x0L;  // test!
1698 //      ReadPCIConfiguration( fcChip->Backplane.bus,
1699 //                           fcChip->Backplane.slot, TLCFGCMD, &ulBuff, 4);
1700
1701       // read back for reference...
1702       fcChip->Registers.TYconfig.value = 
1703          readl( fcChip->Registers.TYconfig.address );
1704
1705       // what is the PCI bus width?
1706       pci_read_config_byte( cpqfcHBAdata->PciDev,
1707                                 0x43, // PCIMCTR offset
1708                                 &bBuff);
1709       
1710       fcChip->Registers.PCIMCTR = bBuff;
1711
1712       // set string identifying the chip on the circuit board
1713
1714       fcChip->Registers.TYstatus.value =
1715         readl( fcChip->Registers.TYstatus.address);
1716       
1717       {
1718 // Now that we are supporting multiple boards, we need to change
1719 // this logic to check for PCI vendor/device IDs...
1720 // for now, quick & dirty is simply checking Chip rev
1721         
1722         ULONG RevId = (fcChip->Registers.TYstatus.value &0x3E0)>>5;
1723         UCHAR Minor = (UCHAR)(RevId & 0x3);
1724         UCHAR Major = (UCHAR)((RevId & 0x1C) >>2);
1725   
1726         /* printk("  HBA Tachyon RevId %d.%d\n", Major, Minor); */
1727         if( (Major == 1) && (Minor == 2) )
1728         {
1729           sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE66_TS12);
1730
1731         }
1732         else if( (Major == 1) && (Minor == 3) )
1733         {
1734           sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE66_TS13);
1735         }
1736         else if( (Major == 2) && (Minor == 1) )
1737         {
1738           sprintf( cpqfcHBAdata->fcChip.Name, SAGILENT_XL2_21);
1739         }
1740         else
1741           sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE_UNKNOWN);
1742       }
1743
1744
1745
1746     case 3:       // allocate mem, set Tachyon Que registers
1747       iStatus = CpqTsCreateTachLiteQues( cpqfcHBAdata, opcode2);
1748
1749       if( iStatus )
1750         break;
1751
1752       // now that the Queues exist, Tach can DMA to them, so
1753       // we can begin processing INTs
1754       // INTEN register - enable INT (TachLite interrupt)
1755       writeb( 0x1F, fcChip->Registers.ReMapMemBase + IINTEN);
1756
1757         // Fall through
1758     case 4:       // Config Fame Manager, Init Loop Command, laser on
1759
1760                  // L_PORT or loopback
1761                  // depending on Options
1762       iStatus = CpqTsInitializeFrameManager( fcChip,0 );
1763       if( iStatus )
1764       {
1765            // failed to initialize Frame Manager
1766               break;
1767       }
1768
1769     default:
1770       break;
1771   }
1772   LEAVE("InitializeTachLite");
1773   
1774   return iStatus;
1775 }
1776
1777
1778
1779
1780 // Depending on the type of platform memory allocation (e.g. dynamic),
1781 // it's probably best to free memory in opposite order as it was allocated.
1782 // Order of allocation: see other function
1783
1784
1785 int CpqTsDestroyTachLiteQues( void *pHBA, int opcode)
1786 {
1787   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;
1788   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1789   USHORT i, iStatus=0;
1790   void* vPtr;  // mem Align manager sets this to the freed address on success
1791   unsigned long ulPtr;  // for 64-bit pointer cast (e.g. Alpa machine)
1792   FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1793   PSGPAGES j, next;
1794
1795   ENTER("DestroyTachLiteQues");
1796
1797   if( fcChip->SEST )
1798   {
1799                 // search out and free Pool for Extended S/G list pages
1800
1801     for( i=0; i < TACH_SEST_LEN; i++)  // for each exchange
1802     {
1803       // It's possible that extended S/G pages were allocated, mapped, and
1804       // not cleared due to error conditions or O/S driver termination.
1805       // Make sure they're all gone.
1806       if (Exchanges->fcExchange[i].Cmnd != NULL) 
1807         cpqfc_pci_unmap(cpqfcHBAdata->PciDev, Exchanges->fcExchange[i].Cmnd, 
1808                         fcChip, i); // undo DMA mappings.
1809
1810       for (j=fcChip->SEST->sgPages[i] ; j != NULL ; j = next) {
1811                 next = j->next;
1812                 kfree(j);
1813       }
1814       fcChip->SEST->sgPages[i] = NULL;
1815     }
1816     ulPtr = (unsigned long)fcChip->SEST;
1817     vPtr = fcMemManager( cpqfcHBAdata->PciDev, 
1818                     &cpqfcHBAdata->dynamic_mem[0],
1819                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1820     fcChip->SEST = 0L;  // null invalid ptr
1821     if( !vPtr )
1822     {
1823       printk("SEST mem not freed\n");
1824       iStatus = -1;
1825     }
1826   }
1827
1828   if( fcChip->SFQ )
1829   {
1830
1831     ulPtr = (unsigned long)fcChip->SFQ;
1832     vPtr = fcMemManager( cpqfcHBAdata->PciDev, 
1833                     &cpqfcHBAdata->dynamic_mem[0],
1834                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1835     fcChip->SFQ = 0L;  // null invalid ptr
1836     if( !vPtr )
1837     {
1838       printk("SFQ mem not freed\n");
1839       iStatus = -2;
1840     }
1841   }
1842
1843
1844   if( fcChip->IMQ )
1845   {
1846       // clear Indexes to show empty Queue
1847     fcChip->IMQ->producerIndex = 0;
1848     fcChip->IMQ->consumerIndex = 0;
1849
1850     ulPtr = (unsigned long)fcChip->IMQ;
1851     vPtr = fcMemManager( cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0],
1852                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1853     fcChip->IMQ = 0L;  // null invalid ptr
1854     if( !vPtr )
1855     {
1856       printk("IMQ mem not freed\n");
1857       iStatus = -3;
1858     }
1859   }
1860
1861   if( fcChip->ERQ )         // release memory blocks used by the queues
1862   {
1863     ulPtr = (unsigned long)fcChip->ERQ;
1864     vPtr = fcMemManager( cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0],
1865                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1866     fcChip->ERQ = 0L;  // null invalid ptr
1867     if( !vPtr )
1868     {
1869       printk("ERQ mem not freed\n");
1870       iStatus = -4;
1871     }
1872   }
1873     
1874   // free up the primary EXCHANGES struct and Link Q
1875   cpqfc_free_dma_consistent(cpqfcHBAdata);
1876   
1877   LEAVE("DestroyTachLiteQues");
1878   
1879   return iStatus;     // non-zero (failed) if any memory not freed
1880 }
1881
1882
1883
1884
1885
1886 // The SFQ is an array with SFQ_LEN length, each element (QEntry)
1887 // with eight 32-bit words.  TachLite places incoming FC frames (i.e.
1888 // a valid FC frame with our AL_PA ) in contiguous SFQ entries
1889 // and sends a completion message telling the host where the frame is
1890 // in the que.
1891 // This function copies the current (or oldest not-yet-processed) QEntry to
1892 // a caller's contiguous buffer and updates the Tachyon chip's consumer index
1893 //
1894 // NOTE:
1895 //   An FC frame may consume one or many SFQ entries.  We know the total
1896 //   length from the completion message.  The caller passes a buffer large
1897 //   enough for the complete message (max 2k).
1898
1899 static void CpqTsGetSFQEntry(
1900          PTACHYON fcChip,
1901          USHORT producerNdx,
1902          ULONG *ulDestPtr,            // contiguous destination buffer
1903          BOOLEAN UpdateChip)
1904 {
1905   ULONG total_bytes=0;
1906   ULONG consumerIndex = fcChip->SFQ->consumerIndex;
1907   
1908                                 // check passed copy of SFQ producer index -
1909                                 // is a new message waiting for us?
1910                                 // equal indexes means SFS is copied
1911
1912   while( producerNdx != consumerIndex )
1913   {                             // need to process message
1914     total_bytes += 64;   // maintain count to prevent writing past buffer
1915                    // don't allow copies over Fibre Channel defined length!
1916     if( total_bytes <= 2048 )
1917     {
1918       memcpy( ulDestPtr, 
1919               &fcChip->SFQ->QEntry[consumerIndex],
1920               64 );  // each SFQ entry is 64 bytes
1921       ulDestPtr += 16;   // advance pointer to next 64 byte block
1922     }
1923                          // Tachyon is producing,
1924                          // and we are consuming
1925
1926     if( ++consumerIndex >= SFQ_LEN)// check for rollover
1927       consumerIndex = 0L;        // reset it
1928   }
1929
1930   // if specified, update the Tachlite chip ConsumerIndex...
1931   if( UpdateChip )
1932   {
1933     fcChip->SFQ->consumerIndex = consumerIndex;
1934     writel( fcChip->SFQ->consumerIndex,
1935       fcChip->Registers.SFQconsumerIndex.address);
1936   }
1937 }
1938
1939
1940
1941 // TachLite routinely freezes it's core ques - Outbound FIFO, Inbound FIFO,
1942 // and Exchange Request Queue (ERQ) on error recover - 
1943 // (e.g. whenever a LIP occurs).  Here
1944 // we routinely RESUME by clearing these bits, but only if the loop is up
1945 // to avoid ERROR IDLE messages forever.
1946
1947 void CpqTsUnFreezeTachlite( void *pChip, int type )
1948 {
1949   PTACHYON fcChip = (PTACHYON)pChip;
1950   fcChip->Registers.TYcontrol.value = 
1951     readl(fcChip->Registers.TYcontrol.address);
1952             
1953   // (bit 4 of value is GBIC LASER)
1954   // if we 'unfreeze' the core machines before the loop is healthy
1955   // (i.e. FLT, OS, LS failure bits set in FMstatus)
1956   // we can get 'error idle' messages forever.  Verify that
1957   // FMstatus (Link Status) is OK before unfreezing.
1958
1959   if( !(fcChip->Registers.FMstatus.value & 0x07000000L) && // bits clear?
1960       !(fcChip->Registers.FMstatus.value & 0x80  ))  // Active LPSM?
1961   {
1962     fcChip->Registers.TYcontrol.value &=  ~0x300L; // clear FEQ, FFA
1963     if( type == 1 )  // unfreeze ERQ only
1964     {
1965 //      printk("Unfreezing ERQ\n");
1966       fcChip->Registers.TYcontrol.value |= 0x10000L; // set REQ
1967     }
1968     else             // unfreeze both ERQ and FCP-ASSIST (SEST)
1969     {
1970 //      printk("Unfreezing ERQ & FCP-ASSIST\n");
1971
1972                      // set ROF, RIF, REQ - resume Outbound FCP, Inbnd FCP, ERQ
1973       fcChip->Registers.TYcontrol.value |= 0x70000L; // set ROF, RIF, REQ
1974     }
1975
1976     writel( fcChip->Registers.TYcontrol.value,
1977       fcChip->Registers.TYcontrol.address);
1978               
1979   }
1980           // readback for verify (TachLite still frozen?)
1981   fcChip->Registers.TYstatus.value = 
1982     readl(fcChip->Registers.TYstatus.address);
1983 }
1984
1985
1986 // Whenever an FC Exchange Abort is required, we must manipulate the
1987 // Host/Tachyon shared memory SEST table.  Before doing this, we
1988 // must freeze Tachyon, which flushes certain buffers and ensure we
1989 // can manipulate the SEST without contention.
1990 // This freeze function will result in FCP & ERQ FROZEN completion
1991 // messages (per argument "type").
1992
1993 void CpqTsFreezeTachlite( void *pChip, int type )
1994 {
1995   PTACHYON fcChip = (PTACHYON)pChip;
1996   fcChip->Registers.TYcontrol.value = 
1997     readl(fcChip->Registers.TYcontrol.address);
1998     
1999                      //set FFA, FEQ - freezes SCSI assist and ERQ
2000   if( type == 1)    // freeze ERQ only
2001     fcChip->Registers.TYcontrol.value |= 0x100L; // (bit 4 is laser)
2002   else              // freeze both FCP assists (SEST) and ERQ
2003     fcChip->Registers.TYcontrol.value |= 0x300L; // (bit 4 is laser)
2004   
2005   writel( fcChip->Registers.TYcontrol.value,
2006     fcChip->Registers.TYcontrol.address);
2007               
2008 }
2009
2010
2011
2012
2013 // TL has two Frame Manager Link Status Registers, with three 8-bit
2014 // fields each. These eight bit counters are cleared after each read,
2015 // so we define six 32-bit accumulators for these TL counters. This
2016 // function breaks out each 8-bit field and adds the value to the existing
2017 // sum.  (s/w counters cleared independently)
2018
2019 void fcParseLinkStatusCounters(PTACHYON fcChip)
2020 {
2021   UCHAR bBuff;
2022   ULONG ulBuff;
2023
2024
2025 // The BB0 timer usually increments when TL is initialized, resulting
2026 // in an initially bogus count.  If our own counter is ZERO, it means we
2027 // are reading this thing for the first time, so we ignore the first count.
2028 // Also, reading the register does not clear it, so we have to keep an
2029 // additional static counter to detect rollover (yuk).
2030
2031   if( fcChip->fcStats.lastBB0timer == 0L)  // TL was reset? (ignore 1st values)
2032   {
2033                            // get TL's register counter - the "last" count
2034     fcChip->fcStats.lastBB0timer = 
2035       fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
2036   }
2037   else  // subsequent pass - check for rollover
2038   {
2039                               // "this" count
2040     ulBuff = fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
2041     if( fcChip->fcStats.lastBB0timer > ulBuff ) // rollover happened
2042     {
2043                                 // counter advanced to max...
2044       fcChip->fcStats.BB0_Timer += (0x00FFFFFFL - fcChip->fcStats.lastBB0timer);
2045       fcChip->fcStats.BB0_Timer += ulBuff;  // plus some more
2046
2047
2048     }
2049     else // no rollover -- more counts or no change
2050     {
2051       fcChip->fcStats.BB0_Timer +=  (ulBuff - fcChip->fcStats.lastBB0timer);
2052
2053     }
2054
2055     fcChip->fcStats.lastBB0timer = ulBuff;
2056   }
2057
2058
2059
2060   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus1.value >> 24);
2061   fcChip->fcStats.LossofSignal += bBuff;
2062
2063   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus1.value >> 16);
2064   fcChip->fcStats.BadRXChar += bBuff;
2065
2066   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus1.value >> 8);
2067   fcChip->fcStats.LossofSync += bBuff;
2068
2069
2070   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus2.value >> 24);
2071   fcChip->fcStats.Rx_EOFa += bBuff;
2072
2073   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus2.value >> 16);
2074   fcChip->fcStats.Dis_Frm += bBuff;
2075
2076   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus2.value >> 8);
2077   fcChip->fcStats.Bad_CRC += bBuff;
2078 }
2079
2080
2081 void cpqfcTSClearLinkStatusCounters(PTACHYON fcChip)
2082 {
2083   ENTER("ClearLinkStatusCounters");
2084   memset( &fcChip->fcStats, 0, sizeof( FCSTATS));
2085   LEAVE("ClearLinkStatusCounters");
2086
2087 }
2088
2089
2090
2091
2092 // The following function reads the I2C hardware to get the adapter's
2093 // World Wide Name (WWN).
2094 // If the WWN is "500805f1fadb43e8" (as printed on the card), the
2095 // Tachyon WWN_hi (32-bit) register is 500805f1, and WWN_lo register
2096 // is fadb43e8.
2097 // In the NVRAM, the bytes appear as:
2098 // [2d] ..
2099 // [2e] .. 
2100 // [2f] 50
2101 // [30] 08
2102 // [31] 05
2103 // [32] f1
2104 // [33] fa
2105 // [34] db
2106 // [35] 43
2107 // [36] e8
2108 //
2109 // In the Fibre Channel (Big Endian) format, the FC-AL LISM frame will
2110 // be correctly loaded by Tachyon silicon.  In the login payload, bytes
2111 // must be correctly swapped for Big Endian format.
2112
2113 int CpqTsReadWriteWWN( PVOID pChip, int Read)
2114 {
2115   PTACHYON fcChip = (PTACHYON)pChip;
2116 #define NVRAM_SIZE 512
2117   unsigned short i, count = NVRAM_SIZE;
2118   UCHAR nvRam[NVRAM_SIZE], WWNbuf[8];
2119   ULONG ulBuff;
2120   int iStatus=-1;  // assume failure
2121   int WWNoffset;
2122
2123   ENTER("ReadWriteWWN");
2124   // Now try to read the WWN from the adapter's NVRAM
2125
2126   if( Read )  // READing NVRAM WWN?
2127   {
2128     ulBuff = cpqfcTS_ReadNVRAM( fcChip->Registers.TYstatus.address,
2129                               fcChip->Registers.TYcontrol.address,
2130                               count, &nvRam[0] );
2131
2132     if( ulBuff )   // NVRAM read successful?
2133     {
2134       iStatus = 0; // success!
2135       
2136                    // for engineering/ prototype boards, the data may be
2137                    // invalid (GIGO, usually all "FF"); this prevents the
2138                    // parse routine from working correctly, which means
2139                    // nothing will be written to our passed buffer.
2140
2141       WWNoffset = cpqfcTS_GetNVRAM_data( WWNbuf, nvRam );
2142
2143       if( !WWNoffset ) // uninitialized NVRAM -- copy bytes directly
2144       {
2145         printk( "CAUTION: Copying NVRAM data on fcChip\n");
2146         for( i= 0; i < 8; i++)
2147           WWNbuf[i] = nvRam[i +0x2f]; // dangerous! some formats won't work
2148       }
2149       
2150       fcChip->Registers.wwn_hi = 0L;
2151       fcChip->Registers.wwn_lo = 0L;
2152       for( i=0; i<4; i++)  // WWN bytes are big endian in NVRAM
2153       {
2154         ulBuff = 0L;
2155         ulBuff = (ULONG)(WWNbuf[i]) << (8 * (3-i));
2156         fcChip->Registers.wwn_hi |= ulBuff;
2157       }
2158       for( i=0; i<4; i++)  // WWN bytes are big endian in NVRAM
2159       {
2160         ulBuff = 0L;
2161         ulBuff = (ULONG)(WWNbuf[i+4]) << (8 * (3-i));
2162         fcChip->Registers.wwn_lo |= ulBuff;
2163       }
2164     }  // done reading
2165     else
2166     {
2167
2168       printk( "cpqfcTS: NVRAM read failed\n");
2169
2170     }
2171   }
2172
2173   else  // WRITE
2174   {
2175
2176     // NOTE: WRITE not supported & not used in released driver.
2177
2178    
2179     printk("ReadWriteNRAM: can't write NVRAM; aborting write\n");
2180   }
2181   
2182   LEAVE("ReadWriteWWN");
2183   return iStatus;
2184 }
2185
2186
2187
2188
2189
2190 // The following function reads or writes the entire "NVRAM" contents of 
2191 // the I2C hardware (i.e. the NM24C03).  Note that HP's 5121A (TS 66Mhz)
2192 // adapter does not use the NM24C03 chip, so this function only works on
2193 // Compaq's adapters.
2194
2195 int CpqTsReadWriteNVRAM( PVOID pChip, PVOID buf, int Read)
2196 {
2197   PTACHYON fcChip = (PTACHYON)pChip;
2198 #define NVRAM_SIZE 512
2199   ULONG ulBuff;
2200   UCHAR *ucPtr = buf; // cast caller's void ptr to UCHAR array
2201   int iStatus=-1;  // assume failure
2202
2203      
2204   if( Read )  // READing NVRAM?
2205   {
2206     ulBuff = cpqfcTS_ReadNVRAM(   // TRUE on success
2207                 fcChip->Registers.TYstatus.address,
2208                 fcChip->Registers.TYcontrol.address,
2209                 256,            // bytes to write
2210                 ucPtr );        // source ptr
2211
2212
2213     if( ulBuff )
2214       iStatus = 0; // success
2215     else
2216     {
2217 #ifdef DBG
2218       printk( "CAUTION: NVRAM read failed\n");
2219 #endif
2220     }
2221   }  // done reading
2222
2223   else  // WRITING NVRAM 
2224   {
2225
2226     printk("cpqfcTS: WRITE of FC Controller's NVRAM disabled\n");
2227   }
2228     
2229   return iStatus;
2230 }