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