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/blk.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 "sd.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
54static void fcParseLinkStatusCounters(TACHYON * fcChip);
55static void CpqTsGetSFQEntry(TACHYON * fcChip,
56	      USHORT pi, ULONG * buffr, BOOLEAN UpdateChip);
57
58static void
59cpqfc_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
79int 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
362int 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
464int 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
487int 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 occurence of
590// "type".  Returns 1 if found, 0 if not.
591static 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
651static 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
710int 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
1651int 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
1785int 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
1899static 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
1947void 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
1993void 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
2019void 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
2081void 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
2113int 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
2195int 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}
2231