patch-2_6_7-vs1_9_1_12
[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 #error This is too much stack
611           ULONG ulFibreFrame[2048/4];  // max DWORDS in incoming FC Frame
612           USHORT SFQpi = (USHORT)(fcChip->IMQ->QEntry[CI].word[0] & 0x0fffL);
613
614           CpqTsGetSFQEntry( fcChip,
615             SFQpi,        // SFQ producer ndx         
616             ulFibreFrame, // contiguous dest. buffer
617             FALSE);       // DON'T update chip--this is a "lookahead"
618           
619           fchs = (TachFCHDR_GCMND*)&ulFibreFrame;
620           if( fchs->pl[0] == ELS_LILP_FRAME)
621           {
622             return 1; // found the LILP frame!
623           }
624           else
625           {
626             // keep looking...
627           }
628         }  
629       }
630       break;
631
632       case OUTBOUND_COMPLETION:
633         if( (fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x00 )
634         {
635
636           // any OCM errors?
637           if( fcChip->IMQ->QEntry[CI].word[2] & 0x7a000000L )
638             return 1;               // found OCM error
639         }
640       break;
641
642
643       
644       default:
645       break;
646     }
647   }
648   return 0; // failed to find "type"
649 }
650
651                         
652 static void SetTachTOV( CPQFCHBA* cpqfcHBAdata)
653 {
654   PTACHYON fcChip = &cpqfcHBAdata->fcChip; 
655   
656   // TL/TS UG, pg. 184
657   // 0x0065 = 100ms for RT_TOV
658   // 0x01f5 = 500ms for ED_TOV
659   // 0x07d1 = 2000ms for ED_TOV
660
661   // SANMark Level 1 requires an "initialization backoff"
662   // (See "SANMark Test Suite Level 1":
663   // initialization_timeout.fcal.SANMark-1.fc)
664   // We have to use 2sec, 24sec, then 128sec when login/
665   // port discovery processes fail to complete.
666   
667   // when port discovery completes (logins done), we set
668   // ED_TOV to 500ms -- this is the normal operational case
669   // On the first Link Down, we'll move to 2 secs (7D1 ms)
670   if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x1f5)
671     fcChip->Registers.ed_tov.value = 0x006507D1; 
672   
673   // If we get another LST after we moved TOV to 2 sec,
674   // increase to 24 seconds (5DC1 ms) per SANMark!
675   else if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x7D1)
676     fcChip->Registers.ed_tov.value = 0x00655DC1; 
677
678   // If we get still another LST, set the max TOV (Tachyon
679   // has only 16 bits for ms timer, so the max is 65.5 sec)
680   else if( (fcChip->Registers.ed_tov.value &0xFFFF) <= 0x5DC1)
681     fcChip->Registers.ed_tov.value = 0x0065FFFF; 
682
683   writel( fcChip->Registers.ed_tov.value,
684     (fcChip->Registers.ed_tov.address));
685   // keep the same 2sec LP_TOV 
686   writel( 0x07D00010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2);
687 }       
688
689
690 // The IMQ is an array with IMQ_LEN length, each element (QEntry)
691 // with eight 32-bit words.  Tachyon PRODUCES a QEntry with each
692 // message it wants to send to the host.  The host CONSUMES IMQ entries
693
694 // This function copies the current
695 // (or oldest not-yet-processed) QEntry to
696 // the caller, clears/ re-enables the interrupt, and updates the
697 // (Host) Consumer Index.
698 // Return value:
699 //  0   message processed, none remain (producer and consumer
700 //        indexes match)
701 //  1   message processed, more messages remain
702 // -1   no message processed - none were available to process
703 // Remarks:
704 //   TL/TS UG specifices that the following actions for
705 //   INTA_L handling:
706 //   1. read PCI Interrupt Status register (0xff)
707 //   2. all IMQ messages should be processed before writing the
708 //      IMQ consumer index.
709
710
711 int CpqTsProcessIMQEntry(void *host)
712 {
713   struct Scsi_Host *HostAdapter = (struct Scsi_Host *)host;
714   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
715   PTACHYON fcChip = &cpqfcHBAdata->fcChip; 
716   FC_EXCHANGES *Exchanges = fcChip->Exchanges;
717   int iStatus;
718   USHORT i, RPCset, DPCset;
719   ULONG x_ID;
720   ULONG ulBuff, dwStatus;
721   TachFCHDR_GCMND* fchs;
722 #error This is too much stack
723   ULONG ulFibreFrame[2048/4];  // max number of DWORDS in incoming Fibre Frame
724   UCHAR ucInboundMessageType;  // Inbound CM, dword 3 "type" field
725
726   ENTER("ProcessIMQEntry");
727    
728
729                                 // check TachLite's IMQ producer index -
730                                 // is a new message waiting for us?
731                                 // equal indexes means empty que
732
733   if( fcChip->IMQ->producerIndex != fcChip->IMQ->consumerIndex )
734   {                             // need to process message
735
736
737 #ifdef IMQ_DEBUG
738     printk("PI %X, CI %X  type: %X\n", 
739       fcChip->IMQ->producerIndex,fcChip->IMQ->consumerIndex,
740       fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type);
741 #endif                                
742     // Examine Completion Messages in IMQ
743     // what CM_Type?
744     switch( (UCHAR)(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type
745                     & 0xffL) )
746     {
747     case OUTBOUND_COMPLETION:
748
749       // Remarks:
750       // x_IDs (OX_ID, RX_ID) are partitioned by SEST entries
751       // (starting at 0), and SFS entries (starting at
752       // SEST_LEN -- outside the SEST space).
753       // Psuedo code:
754       // x_ID (OX_ID or RX_ID) from message is Trans_ID or SEST index
755       // range check - x_ID
756       //   if x_ID outside 'Transactions' length, error - exit
757       // if any OCM error, copy error status to Exchange slot
758       // if FCP ASSIST transaction (x_ID within SEST),
759       //   call fcComplete (to App)
760       // ...
761
762
763       ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1];
764       x_ID = ulBuff & 0x7fffL;     // lower 14 bits SEST_Index/Trans_ID
765                                      // Range check CM OX/RX_ID value...
766       if( x_ID < TACH_MAX_XID )   // don't go beyond array space
767       {
768
769
770         if( ulBuff & 0x20000000L ) // RPC -Response Phase Complete?
771           RPCset = 1;              // (SEST transactions only)
772         else
773           RPCset = 0;
774
775         if( ulBuff & 0x40000000L ) // DPC -Data Phase Complete?
776           DPCset = 1;              // (SEST transactions only)
777         else
778           DPCset = 0;
779                 // set the status for this Outbound transaction's ID
780         dwStatus = 0L;
781         if( ulBuff & 0x10000000L ) // SPE? (SEST Programming Error)
782             dwStatus |= SESTPROG_ERR;
783
784         ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2];
785         if( ulBuff & 0x7a000000L ) // any other errs?
786         {
787           if( ulBuff & 0x40000000L )
788             dwStatus |= INV_ENTRY;
789           if( ulBuff & 0x20000000L )
790             dwStatus |= FRAME_TO;        // FTO
791           if( ulBuff & 0x10000000L )
792             dwStatus |= HOSTPROG_ERR;
793           if( ulBuff & 0x08000000L )
794             dwStatus |= LINKFAIL_TX;
795           if( ulBuff & 0x02000000L )
796             dwStatus |= ABORTSEQ_NOTIFY;  // ASN
797         }
798
799           
800         if( dwStatus )          // any errors?
801         {
802                   // set the Outbound Completion status
803           Exchanges->fcExchange[ x_ID ].status |= dwStatus;
804
805           // if this Outbound frame was for a SEST entry, automatically
806           // reque it in the case of LINKFAIL (it will restart on PDISC)
807           if( x_ID < TACH_SEST_LEN )
808           {
809
810             printk(" #OCM error %Xh x_ID %X# ", 
811                     dwStatus, x_ID);
812
813             Exchanges->fcExchange[x_ID].timeOut = 30000; // seconds default
814                                                  
815
816             // We Q ABTS for each exchange.
817             // NOTE: We can get FRAME_TO on bad alpa (device gone).  Since
818             // bad alpa is reported before FRAME_TO, examine the status
819             // flags to see if the device is removed.  If so, DON'T
820             // post an ABTS, since it will be terminated by the bad alpa
821             // message.
822             if( dwStatus & FRAME_TO ) // check for device removed...
823             {
824               if( !(Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED) )
825               { 
826                 // presumes device is still there: send ABTS.
827   
828                 cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);
829               }
830             }
831             else  // Abort all other errors
832             {
833               cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);
834             }
835
836             // if the HPE bit is set, we have to CLose the LOOP
837             // (see TL/TS UG, pg. 239)
838
839             if( dwStatus &= HOSTPROG_ERR )
840             // set CL bit (see TL/TS UG, pg. 172)
841               writel( 4, fcChip->Registers.FMcontrol.address);
842           }
843         }
844           // NOTE: we don't necessarily care about ALL completion messages...
845                                       // SCSI resp. complete OR
846         if( ((x_ID < TACH_SEST_LEN) && RPCset)|| 
847              (x_ID >= TACH_SEST_LEN) )  // non-SCSI command
848         {
849               // exchange done; complete to upper levels with status
850               // (if necessary) and free the exchange slot
851             
852
853           if( x_ID >= TACH_SEST_LEN ) // Link Service Outbound frame?
854                                     // A Request or Reply has been sent
855           {                         // signal waiting WorkerThread
856
857             up( cpqfcHBAdata->TYOBcomplete);   // frame is OUT of Tach
858
859                                     // WorkerThread will complete Xchng
860           }
861           else  // X_ID is for FCP assist (SEST)
862           {
863               // TBD (target mode)
864 //            fcCompleteExchange( fcChip, x_ID); // TRE completed
865           }
866         }
867       }
868       else  // ERROR CONDITION!  bogus x_ID in completion message
869       {
870
871         printk(" ProcessIMQ (OBCM) x_id out of range %Xh\n", x_ID);
872
873       }
874
875
876
877           // Load the Frame Manager's error counters.  We check them here
878           // because presumably the link is up and healthy enough for the
879           // counters to be meaningful (i.e., don't check them while loop
880           // is initializing).
881       fcChip->Registers.FMLinkStatus1.value =    // get TL's counter
882         readl(fcChip->Registers.FMLinkStatus1.address);
883                   
884       fcChip->Registers.FMLinkStatus2.value =    // get TL's counter
885         readl(fcChip->Registers.FMLinkStatus2.address);
886             
887
888       fcParseLinkStatusCounters( fcChip); // load into 6 s/w accumulators
889     break;
890
891
892
893     case ERROR_IDLE_COMPLETION:  // TachLite Error Idle...
894     
895     // We usually get this when the link goes down during heavy traffic.
896     // For now, presume that if SEST Exchanges are open, we will
897     // get this as our cue to INVALIDATE all SEST entries
898     // (and we OWN all the SEST entries).
899     // See TL/TS UG, pg. 53
900     
901       for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
902       {
903
904         // Does this VALid SEST entry need to be invalidated for Abort?
905         fcChip->SEST->u[ x_ID].IWE.Hdr_Len &= 0x7FFFFFFF; 
906       }
907       
908       CpqTsUnFreezeTachlite( fcChip, 2); // unfreeze Tachyon, if Link OK
909
910     break;
911
912
913     case INBOUND_SFS_COMPLETION:  //0x04
914           // NOTE! we must process this SFQ message to avoid SFQ filling
915           // up and stopping TachLite.  Incoming commands are placed here,
916           // as well as 'unknown' frames (e.g. LIP loop position data)
917           // write this CM's producer index to global...
918           // TL/TS UG, pg 234:
919           // Type: 0 - reserved
920           //       1 - Unassisted FCP
921           //       2 - BAD FCP
922           //       3 - Unkown Frame
923           //       4-F reserved
924
925
926       fcChip->SFQ->producerIndex = (USHORT)
927         (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] & 0x0fffL);
928
929
930       ucInboundMessageType = 0;  // default to useless frame
931
932         // we can only process two Types: 1, Unassisted FCP, and 3, Unknown
933         // Also, we aren't interested in processing frame fragments
934         // so don't Que anything with 'LKF' bit set
935       if( !(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] 
936         & 0x40000000) )  // 'LKF' link failure bit clear?
937       {
938         ucInboundMessageType = (UCHAR)  // ICM DWord3, "Type"
939         (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] & 0x0fL);
940       }
941       else
942       {
943         fcChip->fcStats.linkFailRX++;
944 //        printk("LKF (link failure) bit set on inbound message\n");
945       }
946
947           // clears SFQ entry from Tachyon buffer; copies to contiguous ulBuff
948       CpqTsGetSFQEntry(
949         fcChip,                  // i.e. this Device Object
950         (USHORT)fcChip->SFQ->producerIndex,  // SFQ producer ndx         
951         ulFibreFrame, TRUE);    // contiguous destination buffer, update chip
952                      
953         // analyze the incoming frame outside the INT handler...
954         // (i.e., Worker)
955
956       if( ucInboundMessageType == 1 )
957       {
958         fchs = (TachFCHDR_GCMND*)ulFibreFrame; // cast to examine IB frame
959         // don't fill up our Q with garbage - only accept FCP-CMND  
960         // or XRDY frames
961         if( (fchs->d_id & 0xFF000000) == 0x06000000 ) // CMND
962         {
963           // someone sent us a SCSI command
964           
965 //          fcPutScsiQue( cpqfcHBAdata, 
966 //                        SFQ_UNASSISTED_FCP, ulFibreFrame); 
967         }
968         else if( ((fchs->d_id & 0xFF000000) == 0x07000000) || // RSP (status)
969             (fchs->d_id & 0xFF000000) == 0x05000000 )  // XRDY  
970         {
971           ULONG x_ID;
972           // Unfortunately, ABTS requires a Freeze on the chip so
973           // we can modify the shared memory SEST.  When frozen,
974           // any received Exchange frames cannot be processed by
975           // Tachyon, so they will be dumped in here.  It is too
976           // complex to attempt the reconstruct these frames in
977           // the correct Exchange context, so we simply seek to
978           // find status or transfer ready frames, and cause the
979           // exchange to complete with errors before the timeout
980           // expires.  We use a Linux Scsi Cmnd result code that
981           // causes immediate retry.
982           
983
984           // Do we have an open exchange that matches this s_id
985           // and ox_id?
986           for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
987           {
988             if( (fchs->s_id & 0xFFFFFF) == 
989                  (Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF) 
990                        &&
991                 (fchs->ox_rx_id & 0xFFFF0000) == 
992                  (Exchanges->fcExchange[x_ID].fchs.ox_rx_id & 0xFFFF0000) )
993             {
994     //          printk(" #R/X frame x_ID %08X# ", fchs->ox_rx_id );
995               // simulate the anticipated error - since the
996               // SEST was frozen, frames were lost...
997               Exchanges->fcExchange[ x_ID ].status |= SFQ_FRAME;
998               
999               // presumes device is still there: send ABTS.
1000               cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID);
1001               break;  // done
1002             }
1003           }
1004         }
1005           
1006       }
1007           
1008       else if( ucInboundMessageType == 3)
1009       {
1010         // FC Link Service frames (e.g. PLOGI, ACC) come in here.  
1011         cpqfcTSPutLinkQue( cpqfcHBAdata, SFQ_UNKNOWN, ulFibreFrame); 
1012                           
1013       }
1014
1015       else if( ucInboundMessageType == 2 ) // "bad FCP"?
1016       {
1017 #ifdef IMQ_DEBUG
1018         printk("Bad FCP incoming frame discarded\n");
1019 #endif
1020       }
1021
1022       else // don't know this type
1023       {
1024 #ifdef IMQ_DEBUG 
1025         printk("Incoming frame discarded, type: %Xh\n", ucInboundMessageType);
1026 #endif
1027       }
1028         
1029         // Check the Frame Manager's error counters.  We check them here
1030         // because presumably the link is up and healthy enough for the
1031         // counters to be meaningful (i.e., don't check them while loop
1032         // is initializing).
1033       fcChip->Registers.FMLinkStatus1.value =    // get TL's counter
1034         readl(fcChip->Registers.FMLinkStatus1.address);
1035                   
1036
1037       fcChip->Registers.FMLinkStatus2.value =    // get TL's counter
1038         readl(fcChip->Registers.FMLinkStatus2.address);
1039                 
1040
1041       break;
1042
1043
1044
1045
1046                     // We get this CM because we issued a freeze
1047                     // command to stop outbound frames.  We issue the
1048                     // freeze command at Link Up time; when this message
1049                     // is received, the ERQ base can be switched and PDISC
1050                     // frames can be sent.
1051
1052       
1053     case ERQ_FROZEN_COMPLETION:  // note: expect ERQ followed immediately
1054                                  // by FCP when freezing TL
1055       fcChip->Registers.TYstatus.value =         // read what's frozen
1056         readl(fcChip->Registers.TYstatus.address);
1057       // (do nothing; wait for FCP frozen message)
1058       break;
1059     case FCP_FROZEN_COMPLETION:
1060       
1061       fcChip->Registers.TYstatus.value =         // read what's frozen
1062         readl(fcChip->Registers.TYstatus.address);
1063       
1064       // Signal the kernel thread to proceed with SEST modification
1065       up( cpqfcHBAdata->TachFrozen);
1066
1067       break;
1068
1069
1070
1071     case INBOUND_C1_TIMEOUT:
1072     case MFS_BUF_WARN:
1073     case IMQ_BUF_WARN:
1074     break;
1075
1076
1077
1078
1079
1080         // In older Tachyons, we 'clear' the internal 'core' interrupt state
1081         // by reading the FMstatus register.  In newer TachLite (Tachyon),
1082         // we must WRITE the register
1083         // to clear the condition (TL/TS UG, pg 179)
1084     case FRAME_MGR_INTERRUPT:
1085     {
1086       PFC_LOGGEDIN_PORT pLoggedInPort; 
1087
1088       fcChip->Registers.FMstatus.value = 
1089         readl( fcChip->Registers.FMstatus.address );
1090                 
1091       // PROBLEM: It is possible, especially with "dumb" hubs that
1092       // don't automatically LIP on by-pass of ports that are going
1093       // away, for the hub by-pass process to destroy critical 
1094       // ordered sets of a frame.  The result of this is a hung LPSM
1095       // (Loop Port State Machine), which on Tachyon results in a
1096       // (default 2 sec) Loop State Timeout (LST) FM message.  We 
1097       // want to avoid this relatively huge timeout by detecting
1098       // likely scenarios which will result in LST.
1099       // To do this, we could examine FMstatus for Loss of Synchronization
1100       // and/or Elastic Store (ES) errors.  Of these, Elastic Store is better
1101       // because we get this indication more quickly than the LOS.
1102       // Not all ES errors are harmfull, so we don't want to LIP on every
1103       // ES.  Instead, on every ES, detect whether our LPSM in in one
1104       // of the LST states: ARBITRATING, OPEN, OPENED, XMITTED CLOSE,
1105       // or RECEIVED CLOSE.  (See TL/TS UG, pg. 181)
1106       // If any of these LPSM states are detected
1107       // in combination with the LIP while LDn is not set, 
1108       // send an FM init (LIP F7,F7 for loops)!
1109       // It is critical to the physical link stability NOT to reset (LIP)
1110       // more than absolutely necessary; this is a basic premise of the
1111       // SANMark level 1 spec.
1112       {
1113         ULONG Lpsm = (fcChip->Registers.FMstatus.value & 0xF0) >>4;
1114         
1115         if( (fcChip->Registers.FMstatus.value & 0x400)  // ElasticStore?
1116                       &&
1117             !(fcChip->Registers.FMstatus.value & 0x100) // NOT LDn
1118                       &&
1119             !(fcChip->Registers.FMstatus.value & 0x1000)) // NOT LF
1120         {
1121           if( (Lpsm != 0) || // not MONITORING? or
1122               !(Lpsm & 0x8) )// not already offline?
1123           {
1124           // now check the particular LST states...
1125             if( (Lpsm == ARBITRATING) || (Lpsm == OPEN) ||
1126               (Lpsm == OPENED)      || (Lpsm == XMITTD_CLOSE) ||
1127               (Lpsm == RCVD_CLOSE) )
1128             {
1129               // re-init the loop before it hangs itself!
1130               printk(" #req FMinit on E-S: LPSM %Xh# ",Lpsm);
1131
1132
1133               fcChip->fcStats.FMinits++;
1134               writel( 6, fcChip->Registers.FMcontrol.address); // LIP
1135             }
1136           }
1137         }
1138         else if( fcChip->Registers.FMstatus.value & 0x40000 ) // LST?
1139         {
1140           printk(" #req FMinit on LST, LPSM %Xh# ",Lpsm);
1141          
1142           fcChip->fcStats.FMinits++;
1143           writel( 6, fcChip->Registers.FMcontrol.address);  // LIP
1144         }  
1145       }
1146
1147
1148       // clear only the 'interrupting' type bits for this REG read
1149       writel( (fcChip->Registers.FMstatus.value & 0xff3fff00L),
1150         fcChip->Registers.FMstatus.address);
1151                           
1152
1153                // copy frame manager status to unused ULONG slot
1154       fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] =
1155           fcChip->Registers.FMstatus.value; // (for debugging)
1156
1157
1158           // Load the Frame Manager's error counters.  We check them here
1159           // because presumably the link is up and healthy enough for the
1160           // counters to be meaningful (i.e., don't check them while loop
1161           // is initializing).
1162       fcChip->Registers.FMLinkStatus1.value =   // get TL's counter
1163         readl(fcChip->Registers.FMLinkStatus1.address);
1164             
1165       fcChip->Registers.FMLinkStatus2.value =   // get TL's counter
1166         readl(fcChip->Registers.FMLinkStatus2.address);
1167           
1168           // Get FM BB_Credit Zero Reg - does not clear on READ
1169       fcChip->Registers.FMBB_CreditZero.value =   // get TL's counter
1170         readl(fcChip->Registers.FMBB_CreditZero.address);
1171             
1172
1173
1174       fcParseLinkStatusCounters( fcChip); // load into 6 s/w accumulators
1175
1176
1177                // LINK DOWN
1178
1179       if( fcChip->Registers.FMstatus.value & 0x100L ) // Link DOWN bit
1180       {                                 
1181         
1182 #ifdef IMQ_DEBUG
1183         printk("LinkDn\n");
1184 #endif
1185         printk(" #LDn# ");
1186         
1187         fcChip->fcStats.linkDown++;
1188         
1189         SetTachTOV( cpqfcHBAdata);  // must set according to SANMark
1190
1191         // Check the ERQ - force it to be "empty" to prevent Tach
1192         // from sending out frames before we do logins.
1193
1194
1195         if( fcChip->ERQ->producerIndex != fcChip->ERQ->consumerIndex)
1196         {
1197 //        printk("#ERQ PI != CI#");
1198           CpqTsFreezeTachlite( fcChip, 1); // freeze ERQ only     
1199           fcChip->ERQ->producerIndex = fcChip->ERQ->consumerIndex = 0;
1200           writel( fcChip->ERQ->base, 
1201             (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));
1202           // re-writing base forces ERQ PI to equal CI
1203   
1204         }
1205                 
1206         // link down transition occurred -- port_ids can change
1207         // on next LinkUp, so we must invalidate current logins
1208         // (and any I/O in progress) until PDISC or PLOGI/PRLI
1209         // completes
1210         {
1211           pLoggedInPort = &fcChip->fcPorts; 
1212           while( pLoggedInPort ) // for all ports which are expecting
1213                                  // PDISC after the next LIP, set the
1214                                  // logoutTimer
1215           {
1216
1217             if( pLoggedInPort->pdisc) // expecting PDISC within 2 sec?
1218             {
1219               pLoggedInPort->LOGO_timer = 3;  // we want 2 seconds
1220                                               // but Timer granularity
1221                                               // is 1 second
1222             }
1223                                 // suspend any I/O in progress until
1224                                 // PDISC received...
1225             pLoggedInPort->prli = FALSE;   // block FCP-SCSI commands
1226             
1227             pLoggedInPort = pLoggedInPort->pNextPort;
1228           }  // ... all Previously known ports checked
1229         }
1230         
1231         // since any hot plugging device may NOT support LILP frames
1232         // (such as early Tachyon chips), clear this flag indicating
1233         // we shouldn't use (our copy of) a LILP map.
1234         // If we receive an LILP frame, we'll set it again.
1235         fcChip->Options.LILPin = 0; // our LILPmap is invalid
1236         cpqfcHBAdata->PortDiscDone = 0; // must re-validate FC ports!
1237
1238           // also, we want to invalidate (i.e. INITIATOR_ABORT) any
1239           // open Login exchanges, in case the LinkDown happened in the
1240           // middle of logins.  It's possible that some ports already
1241           // ACCepted login commands which we have not processed before
1242           // another LinkDown occurred.  Any accepted Login exhanges are
1243           // invalidated by LinkDown, even before they are acknowledged.
1244           // It's also possible for a port to have a Queued Reply or Request
1245           // for login which was interrupted by LinkDown; it may come later,
1246           // but it will be unacceptable to us.
1247
1248           // we must scan the entire exchange space, find every Login type
1249           // originated by us, and abort it. This is NOT an abort due to
1250           // timeout, so we don't actually send abort to the other port -
1251           // we just complete it to free up the fcExchange slot.
1252
1253         for( i=TACH_SEST_LEN; i< TACH_MAX_XID; i++)
1254         {                     // looking for Extended Link Serv.Exchanges
1255           if( Exchanges->fcExchange[i].type == ELS_PDISC ||
1256               Exchanges->fcExchange[i].type == ELS_PLOGI ||
1257               Exchanges->fcExchange[i].type == ELS_PRLI ) 
1258           {
1259               // ABORT the exchange!
1260 #ifdef IMQ_DEBUG
1261             printk("Originator ABORT x_id %Xh, type %Xh, port_id %Xh on LDn\n",
1262               i, Exchanges->fcExchange[i].type,
1263             Exchanges->fcExchange[i].fchs.d_id);
1264 #endif
1265
1266             Exchanges->fcExchange[i].status |= INITIATOR_ABORT;
1267             cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, i); // abort on LDn
1268           }
1269         }
1270
1271       }
1272
1273              // ################   LINK UP   ##################
1274       if( fcChip->Registers.FMstatus.value & 0x200L ) // Link Up bit
1275       {                                 // AL_PA could have changed
1276
1277           // We need the following code, duplicated from LinkDn condition,
1278           // because it's possible for the Tachyon to re-initialize (hard
1279           // reset) without ever getting a LinkDn indication.
1280         pLoggedInPort = &fcChip->fcPorts; 
1281         while( pLoggedInPort )   // for all ports which are expecting
1282                                  // PDISC after the next LIP, set the
1283                                  // logoutTimer
1284         {
1285           if( pLoggedInPort->pdisc) // expecting PDISC within 2 sec?
1286           {
1287             pLoggedInPort->LOGO_timer = 3;  // we want 2 seconds
1288                                               // but Timer granularity
1289                                               // is 1 second
1290              
1291                                   // suspend any I/O in progress until
1292                                   // PDISC received...
1293
1294           }
1295           pLoggedInPort = pLoggedInPort->pNextPort;
1296         }  // ... all Previously known ports checked
1297  
1298           // CpqTs acquired AL_PA in register AL_PA (ACQ_ALPA)
1299         fcChip->Registers.rcv_al_pa.value = 
1300           readl(fcChip->Registers.rcv_al_pa.address);
1301  
1302         // Now, if our acquired address is DIFFERENT from our
1303         // previous one, we are not allow to do PDISC - we
1304         // must go back to PLOGI, which will terminate I/O in
1305         // progress for ALL logged in FC devices...
1306         // (This is highly unlikely).
1307
1308         if( (fcChip->Registers.my_al_pa & 0xFF) != 
1309             ((fcChip->Registers.rcv_al_pa.value >> 16) &0xFF) )
1310         {
1311
1312 //        printk(" #our HBA port_id changed!# "); // FC port_id changed!!       
1313
1314           pLoggedInPort = &fcChip->fcPorts; 
1315           while( pLoggedInPort ) // for all ports which are expecting
1316                                  // PDISC after the next LIP, set the
1317                                  // logoutTimer
1318           {
1319             pLoggedInPort->pdisc  = FALSE;
1320             pLoggedInPort->prli = FALSE;
1321             pLoggedInPort = pLoggedInPort->pNextPort;
1322           }  // ... all Previously known ports checked
1323
1324           // when the port_id changes, we must terminate
1325           // all open exchanges.
1326           cpqfcTSTerminateExchange( cpqfcHBAdata, NULL, PORTID_CHANGED);
1327
1328         }
1329                        
1330         // Replace the entire 24-bit port_id.  We only know the
1331         // lower 8 bits (alpa) from Tachyon; if a FLOGI is done,
1332         // we'll get the upper 16-bits from the FLOGI ACC frame.
1333         // If someone plugs into Fabric switch, we'll do FLOGI and
1334         // get full 24-bit port_id; someone could then remove and
1335         // hot-plug us into a dumb hub.  If we send a 24-bit PLOGI
1336         // to a "private" loop device, it might blow up.
1337         // Consequently, we force the upper 16-bits of port_id to
1338         // be re-set on every LinkUp transition
1339         fcChip->Registers.my_al_pa =
1340           (fcChip->Registers.rcv_al_pa.value >> 16) & 0xFF;
1341
1342               
1343               // copy frame manager status to unused ULONG slot
1344         fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] =
1345           fcChip->Registers.my_al_pa; // (for debugging)
1346
1347               // for TachLite, we need to write the acquired al_pa
1348               // back into the FMconfig register, because after
1349               // first initialization, the AQ (prev. acq.) bit gets
1350               // set, causing TL FM to use the AL_PA field in FMconfig.
1351               // (In Tachyon, FM writes the acquired AL_PA for us.)
1352         ulBuff = readl( fcChip->Registers.FMconfig.address);
1353         ulBuff &= 0x00ffffffL;  // mask out current al_pa
1354         ulBuff |= ( fcChip->Registers.my_al_pa << 24 ); // or in acq. al_pa
1355         fcChip->Registers.FMconfig.value = ulBuff; // copy it back
1356         writel( fcChip->Registers.FMconfig.value,  // put in TachLite
1357           fcChip->Registers.FMconfig.address);
1358             
1359
1360 #ifdef IMQ_DEBUG
1361         printk("#LUp %Xh, FMstat 0x%08X#", 
1362                 fcChip->Registers.my_al_pa, fcChip->Registers.FMstatus.value);
1363 #endif
1364
1365               // also set the WRITE-ONLY My_ID Register (for Fabric
1366               // initialization)
1367         writel( fcChip->Registers.my_al_pa,
1368           fcChip->Registers.ReMapMemBase +TL_MEM_TACH_My_ID);
1369           
1370
1371         fcChip->fcStats.linkUp++;
1372
1373                                      // reset TL statistics counters
1374                                      // (we ignore these error counters
1375                                      // while link is down)
1376         ulBuff =                     // just reset TL's counter
1377                  readl( fcChip->Registers.FMLinkStatus1.address);
1378           
1379         ulBuff =                     // just reset TL's counter
1380                  readl( fcChip->Registers.FMLinkStatus2.address);
1381
1382           // for initiator, need to start verifying ports (e.g. PDISC)
1383
1384
1385
1386          
1387       
1388       
1389         CpqTsUnFreezeTachlite( fcChip, 2); // unfreeze Tachlite, if Link OK
1390         
1391         // Tachyon creates an interesting problem for us on LILP frames.
1392         // Instead of writing the incoming LILP frame into the SFQ before
1393         // indicating LINK UP (the actual order of events), Tachyon tells
1394         // us LINK UP, and later us the LILP.  So we delay, then examine the
1395         // IMQ for an Inbound CM (x04); if found, we can set
1396         // LINKACTIVE after processing the LILP.  Otherwise, just proceed.
1397         // Since Tachyon imposes this time delay (and doesn't tell us
1398         // what it is), we have to impose a delay before "Peeking" the IMQ
1399         // for Tach hardware (DMA) delivery.
1400         // Processing LILP is required by SANMark
1401         udelay( 1000);  // microsec delay waiting for LILP (if it comes)
1402         if( PeekIMQEntry( fcChip, ELS_LILP_FRAME) )
1403         {  // found SFQ LILP, which will post LINKACTIVE          
1404 //        printk("skipping LINKACTIVE post\n");
1405
1406         }
1407         else
1408           cpqfcTSPutLinkQue( cpqfcHBAdata, LINKACTIVE, ulFibreFrame);  
1409       }
1410
1411
1412
1413       // ******* Set Fabric Login indication ********
1414       if( fcChip->Registers.FMstatus.value & 0x2000 )
1415       {
1416         printk(" #Fabric# ");
1417         fcChip->Options.fabric = 1;
1418       }
1419       else
1420         fcChip->Options.fabric = 0;
1421
1422       
1423       
1424                              // ******* LIP(F8,x) or BAD AL_PA? ********
1425       if( fcChip->Registers.FMstatus.value & 0x30000L )
1426       {
1427                         // copy the error AL_PAs
1428         fcChip->Registers.rcv_al_pa.value = 
1429           readl(fcChip->Registers.rcv_al_pa.address);
1430             
1431                         // Bad AL_PA?
1432         if( fcChip->Registers.FMstatus.value & 0x10000L )
1433         {
1434           PFC_LOGGEDIN_PORT pLoggedInPort;
1435         
1436                        // copy "BAD" al_pa field
1437           fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] =
1438               (fcChip->Registers.rcv_al_pa.value & 0xff00L) >> 8;
1439
1440           pLoggedInPort = fcFindLoggedInPort( fcChip,
1441             NULL,     // DON'T search Scsi Nexus
1442             fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1], // port id
1443             NULL,     // DON'T search linked list for FC WWN
1444             NULL);    // DON'T care about end of list
1445  
1446           if( pLoggedInPort )
1447           {
1448             // Just in case we got this BAD_ALPA because a device
1449             // quietly disappeared (can happen on non-managed hubs such 
1450             // as the Vixel Rapport 1000),
1451             // do an Implicit Logout.  We never expect this on a Logged
1452             // in port (but do expect it on port discovery).
1453             // (As a reasonable alternative, this could be changed to 
1454             // simply start the implicit logout timer, giving the device
1455             // several seconds to "come back".)
1456             // 
1457             printk(" #BAD alpa %Xh# ",
1458                    fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1]);
1459             cpqfcTSImplicitLogout( cpqfcHBAdata, pLoggedInPort);
1460           }
1461         }
1462                         // LIP(f8,x)?
1463         if( fcChip->Registers.FMstatus.value & 0x20000L )
1464         {
1465                         // for debugging, copy al_pa field
1466           fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] =
1467               (fcChip->Registers.rcv_al_pa.value & 0xffL);
1468                         // get the other port's al_pa
1469                         // (one that sent LIP(F8,?) )
1470         }
1471       }
1472
1473                              // Elastic store err
1474       if( fcChip->Registers.FMstatus.value & 0x400L )
1475       {
1476             // don't count e-s if loop is down!
1477         if( !(USHORT)(fcChip->Registers.FMstatus.value & 0x80) )
1478           fcChip->fcStats.e_stores++;
1479           
1480       }
1481     }
1482     break;
1483
1484
1485     case INBOUND_FCP_XCHG_COMPLETION:  // 0x0C
1486
1487     // Remarks:
1488     // On Tachlite TL/TS, we get this message when the data phase
1489     // of a SEST inbound transfer is complete.  For example, if a WRITE command
1490     // was received with OX_ID 0, we might respond with XFER_RDY with
1491     // RX_ID 8001.  This would start the SEST controlled data phases.  When
1492     // all data frames are received, we get this inbound completion. This means
1493     // we should send a status frame to complete the status phase of the 
1494     // FCP-SCSI exchange, using the same OX_ID,RX_ID that we used for data
1495     // frames.
1496     // See Outbound CM discussion of x_IDs
1497     // Psuedo Code
1498     //   Get SEST index (x_ID)
1499     //     x_ID out of range, return (err condition)
1500     //   set status bits from 2nd dword
1501     //   free transactionID & SEST entry
1502     //   call fcComplete with transactionID & status
1503
1504       ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0];
1505       x_ID = ulBuff & 0x7fffL;  // lower 14 bits SEST_Index/Trans_ID
1506                                 // (mask out MSB "direction" bit)
1507                                 // Range check CM OX/RX_ID value...
1508       if( x_ID < TACH_SEST_LEN )  // don't go beyond SEST array space
1509       {
1510
1511 //#define FCP_COMPLETION_DBG 1
1512 #ifdef FCP_COMPLETION_DBG
1513         printk(" FCP_CM x_ID %Xh, status %Xh, Cmnd %p\n", 
1514           x_ID, ulBuff, Exchanges->fcExchange[x_ID].Cmnd);
1515 #endif
1516         if( ulBuff & 0x08000000L ) // RPC -Response Phase Complete - or -
1517                                    // time to send response frame?
1518           RPCset = 1;             // (SEST transaction)
1519         else
1520           RPCset = 0;
1521                 // set the status for this Inbound SCSI transaction's ID
1522         dwStatus = 0L;
1523         if( ulBuff & 0x70000000L ) // any errs?
1524         {
1525           
1526           if( ulBuff & 0x40000000L )
1527             dwStatus |= LINKFAIL_RX;
1528           
1529           if( ulBuff & 0x20000000L )
1530             dwStatus |= COUNT_ERROR;
1531           
1532           if( ulBuff & 0x10000000L )
1533             dwStatus |= OVERFLOW;
1534         }
1535       
1536         
1537           // FCP transaction done - copy status
1538         Exchanges->fcExchange[ x_ID ].status = dwStatus;
1539
1540
1541         // Did the exchange get an FCP-RSP response frame?
1542         // (Note the little endian/big endian FC payload difference)
1543
1544         if( RPCset )             // SEST transaction Response frame rec'd
1545         {
1546           // complete the command in our driver...
1547           cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev,fcChip, x_ID);
1548
1549         }  // end "RPCset"
1550         
1551         else  // ("target" logic)
1552         {
1553             // Tachlite says all data frames have been received - now it's time
1554             // to analyze data transfer (successful?), then send a response 
1555             // frame for this exchange
1556
1557           ulFibreFrame[0] = x_ID; // copy for later reference
1558
1559           // if this was a TWE, we have to send satus response
1560           if( Exchanges->fcExchange[ x_ID].type == SCSI_TWE )
1561           {
1562 //            fcPutScsiQue( cpqfcHBAdata, 
1563 //                NEED_FCP_RSP, ulFibreFrame);  // (ulFibreFrame not used here)
1564           }
1565         }
1566       }
1567       else  // ERROR CONDITION!  bogus x_ID in completion message
1568       {
1569         printk("IN FCP_XCHG: bad x_ID: %Xh\n", x_ID);
1570       }
1571
1572     break;
1573
1574
1575
1576
1577     case INBOUND_SCSI_DATA_COMMAND:
1578     case BAD_SCSI_FRAME:
1579     case INB_SCSI_STATUS_COMPLETION:
1580     case BUFFER_PROCESSED_COMPLETION:
1581     break;
1582     }
1583
1584                                            // Tachyon is producing;
1585                                            // we are consuming
1586     fcChip->IMQ->consumerIndex++;             // increment OUR consumerIndex
1587     if( fcChip->IMQ->consumerIndex >= IMQ_LEN)// check for rollover
1588       fcChip->IMQ->consumerIndex = 0L;        // reset it
1589
1590
1591     if( fcChip->IMQ->producerIndex == fcChip->IMQ->consumerIndex )
1592     {                           // all Messages are processed -
1593       iStatus = 0;              // no more messages to process
1594
1595     }
1596     else
1597       iStatus = 1;              // more messages to process
1598
1599     // update TachLite's ConsumerIndex... (clears INTA_L)
1600     // NOTE: according to TL/TS UG, the 
1601     // "host must return completion messages in sequential order".
1602     // Does this mean one at a time, in the order received?  We
1603     // presume so.
1604
1605     writel( fcChip->IMQ->consumerIndex,
1606       (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));
1607                     
1608 #if IMQ_DEBUG
1609     printk("Process IMQ: writing consumer ndx %d\n ", 
1610       fcChip->IMQ->consumerIndex);
1611     printk("PI %X, CI %X\n", 
1612     fcChip->IMQ->producerIndex,fcChip->IMQ->consumerIndex );
1613 #endif
1614   
1615
1616
1617   }
1618   else
1619   {
1620    // hmmm... why did we get interrupted/called with no message?
1621     iStatus = -1;               // nothing to process
1622 #if IMQ_DEBUG
1623     printk("Process IMQ: no message PI %Xh  CI %Xh", 
1624       fcChip->IMQ->producerIndex,
1625       fcChip->IMQ->consumerIndex);
1626 #endif
1627   }
1628
1629   LEAVE("ProcessIMQEntry");
1630   
1631   return iStatus;
1632 }
1633
1634
1635
1636
1637
1638 // This routine initializes Tachyon according to the following
1639 // options (opcode1):
1640 // 1 - RESTART Tachyon, simulate power on condition by shutting
1641 //     down laser, resetting the hardware, de-allocating all buffers;
1642 //     continue
1643 // 2 - Config Tachyon / PCI registers;
1644 //     continue
1645 // 3 - Allocating memory and setting Tachyon queues (write Tachyon regs);
1646 //     continue
1647 // 4 - Config frame manager registers, initialize, turn on laser
1648 //
1649 // Returns:
1650 //  -1 on fatal error
1651 //   0 on success
1652
1653 int CpqTsInitializeTachLite( void *pHBA, int opcode1, int opcode2)
1654 {
1655   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;
1656   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1657   ULONG ulBuff;
1658   UCHAR bBuff;
1659   int iStatus=-1;  // assume failure
1660
1661   ENTER("InitializeTachLite");
1662
1663   // verify board's base address (sanity check)
1664
1665   if( !fcChip->Registers.ReMapMemBase)                // NULL address for card?
1666     return -1;                         // FATAL error!
1667
1668
1669
1670   switch( opcode1 )
1671   {
1672     case 1:       // restore hardware to power-on (hard) restart
1673
1674
1675       iStatus = fcChip->ResetTachyon( 
1676                   cpqfcHBAdata, opcode2); // laser off, reset hardware
1677                                       // de-allocate aligned buffers
1678
1679
1680 /* TBD      // reset FC link Q (producer and consumer = 0)
1681       fcLinkQReset(cpqfcHBAdata); 
1682
1683 */
1684
1685       if( iStatus )
1686         break;
1687
1688     case 2:       // Config PCI/Tachyon registers
1689       // NOTE: For Tach TL/TS, bit 31 must be set to 1.  For TS chips, a read
1690       // of bit 31 indicates state of M66EN signal; if 1, chip may run at 
1691       // 33-66MHz  (see TL/TS UG, pg 159)
1692
1693       ulBuff = 0x80000000;  // TachLite Configuration Register
1694
1695       writel( ulBuff, fcChip->Registers.TYconfig.address);
1696 //      ulBuff = 0x0147L;  // CpqTs PCI CFGCMD register
1697 //      WritePCIConfiguration( fcChip->Backplane.bus,
1698 //                           fcChip->Backplane.slot, TLCFGCMD, ulBuff, 4);
1699 //      ulBuff = 0x0L;  // test!
1700 //      ReadPCIConfiguration( fcChip->Backplane.bus,
1701 //                           fcChip->Backplane.slot, TLCFGCMD, &ulBuff, 4);
1702
1703       // read back for reference...
1704       fcChip->Registers.TYconfig.value = 
1705          readl( fcChip->Registers.TYconfig.address );
1706
1707       // what is the PCI bus width?
1708       pci_read_config_byte( cpqfcHBAdata->PciDev,
1709                                 0x43, // PCIMCTR offset
1710                                 &bBuff);
1711       
1712       fcChip->Registers.PCIMCTR = bBuff;
1713
1714       // set string identifying the chip on the circuit board
1715
1716       fcChip->Registers.TYstatus.value =
1717         readl( fcChip->Registers.TYstatus.address);
1718       
1719       {
1720 // Now that we are supporting multiple boards, we need to change
1721 // this logic to check for PCI vendor/device IDs...
1722 // for now, quick & dirty is simply checking Chip rev
1723         
1724         ULONG RevId = (fcChip->Registers.TYstatus.value &0x3E0)>>5;
1725         UCHAR Minor = (UCHAR)(RevId & 0x3);
1726         UCHAR Major = (UCHAR)((RevId & 0x1C) >>2);
1727   
1728         /* printk("  HBA Tachyon RevId %d.%d\n", Major, Minor); */
1729         if( (Major == 1) && (Minor == 2) )
1730         {
1731           sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE66_TS12);
1732
1733         }
1734         else if( (Major == 1) && (Minor == 3) )
1735         {
1736           sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE66_TS13);
1737         }
1738         else if( (Major == 2) && (Minor == 1) )
1739         {
1740           sprintf( cpqfcHBAdata->fcChip.Name, SAGILENT_XL2_21);
1741         }
1742         else
1743           sprintf( cpqfcHBAdata->fcChip.Name, STACHLITE_UNKNOWN);
1744       }
1745
1746
1747
1748     case 3:       // allocate mem, set Tachyon Que registers
1749       iStatus = CpqTsCreateTachLiteQues( cpqfcHBAdata, opcode2);
1750
1751       if( iStatus )
1752         break;
1753
1754       // now that the Queues exist, Tach can DMA to them, so
1755       // we can begin processing INTs
1756       // INTEN register - enable INT (TachLite interrupt)
1757       writeb( 0x1F, fcChip->Registers.ReMapMemBase + IINTEN);
1758
1759         // Fall through
1760     case 4:       // Config Fame Manager, Init Loop Command, laser on
1761
1762                  // L_PORT or loopback
1763                  // depending on Options
1764       iStatus = CpqTsInitializeFrameManager( fcChip,0 );
1765       if( iStatus )
1766       {
1767            // failed to initialize Frame Manager
1768               break;
1769       }
1770
1771     default:
1772       break;
1773   }
1774   LEAVE("InitializeTachLite");
1775   
1776   return iStatus;
1777 }
1778
1779
1780
1781
1782 // Depending on the type of platform memory allocation (e.g. dynamic),
1783 // it's probably best to free memory in opposite order as it was allocated.
1784 // Order of allocation: see other function
1785
1786
1787 int CpqTsDestroyTachLiteQues( void *pHBA, int opcode)
1788 {
1789   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA*)pHBA;
1790   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1791   USHORT i, iStatus=0;
1792   void* vPtr;  // mem Align manager sets this to the freed address on success
1793   unsigned long ulPtr;  // for 64-bit pointer cast (e.g. Alpa machine)
1794   FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1795   PSGPAGES j, next;
1796
1797   ENTER("DestroyTachLiteQues");
1798
1799   if( fcChip->SEST )
1800   {
1801                 // search out and free Pool for Extended S/G list pages
1802
1803     for( i=0; i < TACH_SEST_LEN; i++)  // for each exchange
1804     {
1805       // It's possible that extended S/G pages were allocated, mapped, and
1806       // not cleared due to error conditions or O/S driver termination.
1807       // Make sure they're all gone.
1808       if (Exchanges->fcExchange[i].Cmnd != NULL) 
1809         cpqfc_pci_unmap(cpqfcHBAdata->PciDev, Exchanges->fcExchange[i].Cmnd, 
1810                         fcChip, i); // undo DMA mappings.
1811
1812       for (j=fcChip->SEST->sgPages[i] ; j != NULL ; j = next) {
1813                 next = j->next;
1814                 kfree(j);
1815       }
1816       fcChip->SEST->sgPages[i] = NULL;
1817     }
1818     ulPtr = (unsigned long)fcChip->SEST;
1819     vPtr = fcMemManager( cpqfcHBAdata->PciDev, 
1820                     &cpqfcHBAdata->dynamic_mem[0],
1821                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1822     fcChip->SEST = 0L;  // null invalid ptr
1823     if( !vPtr )
1824     {
1825       printk("SEST mem not freed\n");
1826       iStatus = -1;
1827     }
1828   }
1829
1830   if( fcChip->SFQ )
1831   {
1832
1833     ulPtr = (unsigned long)fcChip->SFQ;
1834     vPtr = fcMemManager( cpqfcHBAdata->PciDev, 
1835                     &cpqfcHBAdata->dynamic_mem[0],
1836                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1837     fcChip->SFQ = 0L;  // null invalid ptr
1838     if( !vPtr )
1839     {
1840       printk("SFQ mem not freed\n");
1841       iStatus = -2;
1842     }
1843   }
1844
1845
1846   if( fcChip->IMQ )
1847   {
1848       // clear Indexes to show empty Queue
1849     fcChip->IMQ->producerIndex = 0;
1850     fcChip->IMQ->consumerIndex = 0;
1851
1852     ulPtr = (unsigned long)fcChip->IMQ;
1853     vPtr = fcMemManager( cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0],
1854                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1855     fcChip->IMQ = 0L;  // null invalid ptr
1856     if( !vPtr )
1857     {
1858       printk("IMQ mem not freed\n");
1859       iStatus = -3;
1860     }
1861   }
1862
1863   if( fcChip->ERQ )         // release memory blocks used by the queues
1864   {
1865     ulPtr = (unsigned long)fcChip->ERQ;
1866     vPtr = fcMemManager( cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0],
1867                     0,0, (ULONG)ulPtr, NULL ); // 'free' mem
1868     fcChip->ERQ = 0L;  // null invalid ptr
1869     if( !vPtr )
1870     {
1871       printk("ERQ mem not freed\n");
1872       iStatus = -4;
1873     }
1874   }
1875     
1876   // free up the primary EXCHANGES struct and Link Q
1877   cpqfc_free_dma_consistent(cpqfcHBAdata);
1878   
1879   LEAVE("DestroyTachLiteQues");
1880   
1881   return iStatus;     // non-zero (failed) if any memory not freed
1882 }
1883
1884
1885
1886
1887
1888 // The SFQ is an array with SFQ_LEN length, each element (QEntry)
1889 // with eight 32-bit words.  TachLite places incoming FC frames (i.e.
1890 // a valid FC frame with our AL_PA ) in contiguous SFQ entries
1891 // and sends a completion message telling the host where the frame is
1892 // in the que.
1893 // This function copies the current (or oldest not-yet-processed) QEntry to
1894 // a caller's contiguous buffer and updates the Tachyon chip's consumer index
1895 //
1896 // NOTE:
1897 //   An FC frame may consume one or many SFQ entries.  We know the total
1898 //   length from the completion message.  The caller passes a buffer large
1899 //   enough for the complete message (max 2k).
1900
1901 static void CpqTsGetSFQEntry(
1902          PTACHYON fcChip,
1903          USHORT producerNdx,
1904          ULONG *ulDestPtr,            // contiguous destination buffer
1905          BOOLEAN UpdateChip)
1906 {
1907   ULONG total_bytes=0;
1908   ULONG consumerIndex = fcChip->SFQ->consumerIndex;
1909   
1910                                 // check passed copy of SFQ producer index -
1911                                 // is a new message waiting for us?
1912                                 // equal indexes means SFS is copied
1913
1914   while( producerNdx != consumerIndex )
1915   {                             // need to process message
1916     total_bytes += 64;   // maintain count to prevent writing past buffer
1917                    // don't allow copies over Fibre Channel defined length!
1918     if( total_bytes <= 2048 )
1919     {
1920       memcpy( ulDestPtr, 
1921               &fcChip->SFQ->QEntry[consumerIndex],
1922               64 );  // each SFQ entry is 64 bytes
1923       ulDestPtr += 16;   // advance pointer to next 64 byte block
1924     }
1925                          // Tachyon is producing,
1926                          // and we are consuming
1927
1928     if( ++consumerIndex >= SFQ_LEN)// check for rollover
1929       consumerIndex = 0L;        // reset it
1930   }
1931
1932   // if specified, update the Tachlite chip ConsumerIndex...
1933   if( UpdateChip )
1934   {
1935     fcChip->SFQ->consumerIndex = consumerIndex;
1936     writel( fcChip->SFQ->consumerIndex,
1937       fcChip->Registers.SFQconsumerIndex.address);
1938   }
1939 }
1940
1941
1942
1943 // TachLite routinely freezes it's core ques - Outbound FIFO, Inbound FIFO,
1944 // and Exchange Request Queue (ERQ) on error recover - 
1945 // (e.g. whenever a LIP occurs).  Here
1946 // we routinely RESUME by clearing these bits, but only if the loop is up
1947 // to avoid ERROR IDLE messages forever.
1948
1949 void CpqTsUnFreezeTachlite( void *pChip, int type )
1950 {
1951   PTACHYON fcChip = (PTACHYON)pChip;
1952   fcChip->Registers.TYcontrol.value = 
1953     readl(fcChip->Registers.TYcontrol.address);
1954             
1955   // (bit 4 of value is GBIC LASER)
1956   // if we 'unfreeze' the core machines before the loop is healthy
1957   // (i.e. FLT, OS, LS failure bits set in FMstatus)
1958   // we can get 'error idle' messages forever.  Verify that
1959   // FMstatus (Link Status) is OK before unfreezing.
1960
1961   if( !(fcChip->Registers.FMstatus.value & 0x07000000L) && // bits clear?
1962       !(fcChip->Registers.FMstatus.value & 0x80  ))  // Active LPSM?
1963   {
1964     fcChip->Registers.TYcontrol.value &=  ~0x300L; // clear FEQ, FFA
1965     if( type == 1 )  // unfreeze ERQ only
1966     {
1967 //      printk("Unfreezing ERQ\n");
1968       fcChip->Registers.TYcontrol.value |= 0x10000L; // set REQ
1969     }
1970     else             // unfreeze both ERQ and FCP-ASSIST (SEST)
1971     {
1972 //      printk("Unfreezing ERQ & FCP-ASSIST\n");
1973
1974                      // set ROF, RIF, REQ - resume Outbound FCP, Inbnd FCP, ERQ
1975       fcChip->Registers.TYcontrol.value |= 0x70000L; // set ROF, RIF, REQ
1976     }
1977
1978     writel( fcChip->Registers.TYcontrol.value,
1979       fcChip->Registers.TYcontrol.address);
1980               
1981   }
1982           // readback for verify (TachLite still frozen?)
1983   fcChip->Registers.TYstatus.value = 
1984     readl(fcChip->Registers.TYstatus.address);
1985 }
1986
1987
1988 // Whenever an FC Exchange Abort is required, we must manipulate the
1989 // Host/Tachyon shared memory SEST table.  Before doing this, we
1990 // must freeze Tachyon, which flushes certain buffers and ensure we
1991 // can manipulate the SEST without contention.
1992 // This freeze function will result in FCP & ERQ FROZEN completion
1993 // messages (per argument "type").
1994
1995 void CpqTsFreezeTachlite( void *pChip, int type )
1996 {
1997   PTACHYON fcChip = (PTACHYON)pChip;
1998   fcChip->Registers.TYcontrol.value = 
1999     readl(fcChip->Registers.TYcontrol.address);
2000     
2001                      //set FFA, FEQ - freezes SCSI assist and ERQ
2002   if( type == 1)    // freeze ERQ only
2003     fcChip->Registers.TYcontrol.value |= 0x100L; // (bit 4 is laser)
2004   else              // freeze both FCP assists (SEST) and ERQ
2005     fcChip->Registers.TYcontrol.value |= 0x300L; // (bit 4 is laser)
2006   
2007   writel( fcChip->Registers.TYcontrol.value,
2008     fcChip->Registers.TYcontrol.address);
2009               
2010 }
2011
2012
2013
2014
2015 // TL has two Frame Manager Link Status Registers, with three 8-bit
2016 // fields each. These eight bit counters are cleared after each read,
2017 // so we define six 32-bit accumulators for these TL counters. This
2018 // function breaks out each 8-bit field and adds the value to the existing
2019 // sum.  (s/w counters cleared independently)
2020
2021 void fcParseLinkStatusCounters(PTACHYON fcChip)
2022 {
2023   UCHAR bBuff;
2024   ULONG ulBuff;
2025
2026
2027 // The BB0 timer usually increments when TL is initialized, resulting
2028 // in an initially bogus count.  If our own counter is ZERO, it means we
2029 // are reading this thing for the first time, so we ignore the first count.
2030 // Also, reading the register does not clear it, so we have to keep an
2031 // additional static counter to detect rollover (yuk).
2032
2033   if( fcChip->fcStats.lastBB0timer == 0L)  // TL was reset? (ignore 1st values)
2034   {
2035                            // get TL's register counter - the "last" count
2036     fcChip->fcStats.lastBB0timer = 
2037       fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
2038   }
2039   else  // subsequent pass - check for rollover
2040   {
2041                               // "this" count
2042     ulBuff = fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
2043     if( fcChip->fcStats.lastBB0timer > ulBuff ) // rollover happened
2044     {
2045                                 // counter advanced to max...
2046       fcChip->fcStats.BB0_Timer += (0x00FFFFFFL - fcChip->fcStats.lastBB0timer);
2047       fcChip->fcStats.BB0_Timer += ulBuff;  // plus some more
2048
2049
2050     }
2051     else // no rollover -- more counts or no change
2052     {
2053       fcChip->fcStats.BB0_Timer +=  (ulBuff - fcChip->fcStats.lastBB0timer);
2054
2055     }
2056
2057     fcChip->fcStats.lastBB0timer = ulBuff;
2058   }
2059
2060
2061
2062   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus1.value >> 24);
2063   fcChip->fcStats.LossofSignal += bBuff;
2064
2065   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus1.value >> 16);
2066   fcChip->fcStats.BadRXChar += bBuff;
2067
2068   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus1.value >> 8);
2069   fcChip->fcStats.LossofSync += bBuff;
2070
2071
2072   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus2.value >> 24);
2073   fcChip->fcStats.Rx_EOFa += bBuff;
2074
2075   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus2.value >> 16);
2076   fcChip->fcStats.Dis_Frm += bBuff;
2077
2078   bBuff = (UCHAR)(fcChip->Registers.FMLinkStatus2.value >> 8);
2079   fcChip->fcStats.Bad_CRC += bBuff;
2080 }
2081
2082
2083 void cpqfcTSClearLinkStatusCounters(PTACHYON fcChip)
2084 {
2085   ENTER("ClearLinkStatusCounters");
2086   memset( &fcChip->fcStats, 0, sizeof( FCSTATS));
2087   LEAVE("ClearLinkStatusCounters");
2088
2089 }
2090
2091
2092
2093
2094 // The following function reads the I2C hardware to get the adapter's
2095 // World Wide Name (WWN).
2096 // If the WWN is "500805f1fadb43e8" (as printed on the card), the
2097 // Tachyon WWN_hi (32-bit) register is 500805f1, and WWN_lo register
2098 // is fadb43e8.
2099 // In the NVRAM, the bytes appear as:
2100 // [2d] ..
2101 // [2e] .. 
2102 // [2f] 50
2103 // [30] 08
2104 // [31] 05
2105 // [32] f1
2106 // [33] fa
2107 // [34] db
2108 // [35] 43
2109 // [36] e8
2110 //
2111 // In the Fibre Channel (Big Endian) format, the FC-AL LISM frame will
2112 // be correctly loaded by Tachyon silicon.  In the login payload, bytes
2113 // must be correctly swapped for Big Endian format.
2114
2115 int CpqTsReadWriteWWN( PVOID pChip, int Read)
2116 {
2117   PTACHYON fcChip = (PTACHYON)pChip;
2118 #define NVRAM_SIZE 512
2119   unsigned short i, count = NVRAM_SIZE;
2120   UCHAR nvRam[NVRAM_SIZE], WWNbuf[8];
2121   ULONG ulBuff;
2122   int iStatus=-1;  // assume failure
2123   int WWNoffset;
2124
2125   ENTER("ReadWriteWWN");
2126   // Now try to read the WWN from the adapter's NVRAM
2127
2128   if( Read )  // READing NVRAM WWN?
2129   {
2130     ulBuff = cpqfcTS_ReadNVRAM( fcChip->Registers.TYstatus.address,
2131                               fcChip->Registers.TYcontrol.address,
2132                               count, &nvRam[0] );
2133
2134     if( ulBuff )   // NVRAM read successful?
2135     {
2136       iStatus = 0; // success!
2137       
2138                    // for engineering/ prototype boards, the data may be
2139                    // invalid (GIGO, usually all "FF"); this prevents the
2140                    // parse routine from working correctly, which means
2141                    // nothing will be written to our passed buffer.
2142
2143       WWNoffset = cpqfcTS_GetNVRAM_data( WWNbuf, nvRam );
2144
2145       if( !WWNoffset ) // uninitialized NVRAM -- copy bytes directly
2146       {
2147         printk( "CAUTION: Copying NVRAM data on fcChip\n");
2148         for( i= 0; i < 8; i++)
2149           WWNbuf[i] = nvRam[i +0x2f]; // dangerous! some formats won't work
2150       }
2151       
2152       fcChip->Registers.wwn_hi = 0L;
2153       fcChip->Registers.wwn_lo = 0L;
2154       for( i=0; i<4; i++)  // WWN bytes are big endian in NVRAM
2155       {
2156         ulBuff = 0L;
2157         ulBuff = (ULONG)(WWNbuf[i]) << (8 * (3-i));
2158         fcChip->Registers.wwn_hi |= ulBuff;
2159       }
2160       for( i=0; i<4; i++)  // WWN bytes are big endian in NVRAM
2161       {
2162         ulBuff = 0L;
2163         ulBuff = (ULONG)(WWNbuf[i+4]) << (8 * (3-i));
2164         fcChip->Registers.wwn_lo |= ulBuff;
2165       }
2166     }  // done reading
2167     else
2168     {
2169
2170       printk( "cpqfcTS: NVRAM read failed\n");
2171
2172     }
2173   }
2174
2175   else  // WRITE
2176   {
2177
2178     // NOTE: WRITE not supported & not used in released driver.
2179
2180    
2181     printk("ReadWriteNRAM: can't write NVRAM; aborting write\n");
2182   }
2183   
2184   LEAVE("ReadWriteWWN");
2185   return iStatus;
2186 }
2187
2188
2189
2190
2191
2192 // The following function reads or writes the entire "NVRAM" contents of 
2193 // the I2C hardware (i.e. the NM24C03).  Note that HP's 5121A (TS 66Mhz)
2194 // adapter does not use the NM24C03 chip, so this function only works on
2195 // Compaq's adapters.
2196
2197 int CpqTsReadWriteNVRAM( PVOID pChip, PVOID buf, int Read)
2198 {
2199   PTACHYON fcChip = (PTACHYON)pChip;
2200 #define NVRAM_SIZE 512
2201   ULONG ulBuff;
2202   UCHAR *ucPtr = buf; // cast caller's void ptr to UCHAR array
2203   int iStatus=-1;  // assume failure
2204
2205      
2206   if( Read )  // READing NVRAM?
2207   {
2208     ulBuff = cpqfcTS_ReadNVRAM(   // TRUE on success
2209                 fcChip->Registers.TYstatus.address,
2210                 fcChip->Registers.TYcontrol.address,
2211                 256,            // bytes to write
2212                 ucPtr );        // source ptr
2213
2214
2215     if( ulBuff )
2216       iStatus = 0; // success
2217     else
2218     {
2219 #ifdef DBG
2220       printk( "CAUTION: NVRAM read failed\n");
2221 #endif
2222     }
2223   }  // done reading
2224
2225   else  // WRITING NVRAM 
2226   {
2227
2228     printk("cpqfcTS: WRITE of FC Controller's NVRAM disabled\n");
2229   }
2230     
2231   return iStatus;
2232 }