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