Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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