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