diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTSchip.h linux-2.6.13-eike/drivers/scsi/cpqfcTSchip.h --- linux-2.6.13-eike/drivers/SCSI/cpqfcTSchip.h 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTSchip.h 2005-09-07 10:21:06.000000000 +0200 @@ -1,6 +1,6 @@ -/* Copyright(c) 2000, Compaq Computer Corporation - * Fibre Channel Host Bus Adapter - * 64-bit, 66MHz PCI +/* Copyright(c) 2000, Compaq Computer Corporation + * Fibre Channel Host Bus Adapter + * 64-bit, 66MHz PCI * Originally developed and tested on: * (front): [chip] Tachyon TS HPFC-5166A/1.2 L2C1090 ... * SP# P225CXCBFIEL6T, Rev XC @@ -92,7 +92,7 @@ #define FRAME_MANAGER_RCV_AL_PA 0xE8 // (R) #define FRAME_MANAGER_PRIMITIVE 0xEC // {K28.5} byte1 byte2 byte3 */ - + #define TL_MEM_ERQ_BASE 0x0 //ERQ Base #define TL_IO_ERQ_BASE 0x0 //ERQ base @@ -105,8 +105,8 @@ #define TL_MEM_ERQ_CONSUMER_INDEX_ADR 0xC //ERQ Consumer Index address register #define TL_IO_ERQ_CONSUMER_INDEX_ADR 0xC //ERQ Consumer Index address register -#define TL_MEM_ERQ_CONSUMER_INDEX 0xC //ERQ Consumer Index -#define TL_IO_ERQ_CONSUMER_INDEX 0xC //ERQ Consumer Index +#define TL_MEM_ERQ_CONSUMER_INDEX 0xC //ERQ Consumer Index +#define TL_IO_ERQ_CONSUMER_INDEX 0xC //ERQ Consumer Index #define TL_MEM_SFQ_BASE 0x50 //SFQ Base #define TL_IO_SFQ_BASE 0x50 //SFQ base diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTScontrol.c linux-2.6.13-eike/drivers/scsi/cpqfcTScontrol.c --- linux-2.6.13-eike/drivers/SCSI/cpqfcTScontrol.c 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTScontrol.c 2005-09-07 10:21:07.000000000 +0200 @@ -358,7 +358,7 @@ int CpqTsResetTachLite(void *pHBA, int t PFC_LOGGEDIN_PORT pLoggedInPort = fcChip->fcPorts.pNextPort; PFC_LOGGEDIN_PORT ptr; // printk("checking for allocated LoggedInPorts...\n"); - + while( pLoggedInPort ) { ptr = pLoggedInPort; @@ -517,7 +517,7 @@ int CpqTsInitializeFrameManager( void *p fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start) // fcChip->Registers.FMconfig.value = 0x01000080L; // soft address (can't pick) // fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start) - + // write config to FM if( !fcChip->Options.intLoopback && !fcChip->Options.extLoopback ) @@ -625,7 +625,7 @@ static void SetTachTOV( CPQFCHBA* cpqfcH (fcChip->Registers.ed_tov.address)); // keep the same 2sec LP_TOV writel( 0x07D00010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2); -} +} // The IMQ is an array with IMQ_LEN length, each element (QEntry) @@ -728,7 +728,7 @@ int CpqTsProcessIMQEntry(void *host) if( ulBuff & 0x02000000L ) dwStatus |= ABORTSEQ_NOTIFY; // ASN } - + if( dwStatus ) // any errors? { // set the Outbound Completion status @@ -875,7 +875,7 @@ int CpqTsProcessIMQEntry(void *host) // or XRDY frames if ((fchs.d_id & 0xFF000000) == 0x06000000) { /* CMND */ // someone sent us a SCSI command - + // fcPutScsiQue(cpqfcHBAdata, // SFQ_UNASSISTED_FCP, ulFibreFrame); } else if (((fchs.d_id & 0xFF000000) == 0x07000000) || /* RSP (status) */ @@ -913,7 +913,7 @@ int CpqTsProcessIMQEntry(void *host) } } } - + } else if (ucInboundMessageType == 3) { // FC Link Service frames (e.g. PLOGI, ACC) come in here. cpqfcTSPutLinkQue(cpqfcHBAdata, SFQ_UNKNOWN, &fchs, 0); @@ -1002,7 +1002,7 @@ int CpqTsProcessIMQEntry(void *host) // SANMark level 1 spec. { ULONG Lpsm = (fcChip->Registers.FMstatus.value & 0xF0) >>4; - + if( (fcChip->Registers.FMstatus.value & 0x400) // ElasticStore? && !(fcChip->Registers.FMstatus.value & 0x100) // NOT LDn @@ -1028,7 +1028,7 @@ int CpqTsProcessIMQEntry(void *host) else if( fcChip->Registers.FMstatus.value & 0x40000 ) // LST? { printk(" #req FMinit on LST, LPSM %Xh# ",Lpsm); - + fcChip->fcStats.FMinits++; writel( 6, fcChip->Registers.FMcontrol.address); // LIP } @@ -1062,7 +1062,7 @@ int CpqTsProcessIMQEntry(void *host) if( fcChip->Registers.FMstatus.value & 0x100L ) // Link DOWN bit { - + #ifdef IMQ_DEBUG printk("LinkDn\n"); #endif @@ -1078,13 +1078,13 @@ int CpqTsProcessIMQEntry(void *host) if( fcChip->ERQ->producerIndex != fcChip->ERQ->consumerIndex) { // printk("#ERQ PI != CI#"); - CpqTsFreezeTachlite(fcChip, 1); // freeze ERQ only + CpqTsFreezeTachlite(fcChip, 1); // freeze ERQ only fcChip->ERQ->producerIndex = fcChip->ERQ->consumerIndex = 0; writel(fcChip->ERQ->base, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE)); // re-writing base forces ERQ PI to equal CI } - + // link down transition occurred -- port_ids can change // on next LinkUp, so we must invalidate current logins // (and any I/O in progress) until PDISC or PLOGI/PRLI @@ -1104,7 +1104,7 @@ int CpqTsProcessIMQEntry(void *host) // suspend any I/O in progress until // PDISC received... pLoggedInPort->prli = FALSE; // block FCP-SCSI commands - + pLoggedInPort = pLoggedInPort->pNextPort; } // ... all Previously known ports checked } @@ -1187,7 +1187,7 @@ int CpqTsProcessIMQEntry(void *host) if( (fcChip->Registers.my_al_pa & 0xFF) != ((fcChip->Registers.rcv_al_pa.value >> 16) &0xFF) ) { -// printk(" #our HBA port_id changed!# "); // FC port_id changed!! +// printk(" #our HBA port_id changed!# "); // FC port_id changed!! pLoggedInPort = &fcChip->fcPorts; while( pLoggedInPort ) // for all ports which are expecting @@ -1203,7 +1203,7 @@ int CpqTsProcessIMQEntry(void *host) // all open exchanges. cpqfcTSTerminateExchange( cpqfcHBAdata, NULL, PORTID_CHANGED); } - + // Replace the entire 24-bit port_id. We only know the // lower 8 bits (alpa) from Tachyon; if a FLOGI is done, // we'll get the upper 16-bits from the FLOGI ACC frame. @@ -1256,7 +1256,7 @@ int CpqTsProcessIMQEntry(void *host) // for initiator, need to start verifying ports (e.g. PDISC) CpqTsUnFreezeTachlite( fcChip, 2); // unfreeze Tachlite, if Link OK - + // Tachyon creates an interesting problem for us on LILP frames. // Instead of writing the incoming LILP frame into the SFQ before // indicating LINK UP (the actual order of events), Tachyon tells @@ -1269,7 +1269,7 @@ int CpqTsProcessIMQEntry(void *host) // Processing LILP is required by SANMark udelay( 1000); // microsec delay waiting for LILP (if it comes) if( PeekIMQEntry( fcChip, ELS_LILP_FRAME) ) - { // found SFQ LILP, which will post LINKACTIVE + { // found SFQ LILP, which will post LINKACTIVE // printk("skipping LINKACTIVE post\n"); } else @@ -1393,7 +1393,7 @@ int CpqTsProcessIMQEntry(void *host) if( ulBuff & 0x10000000L ) dwStatus |= OVERFLOW; } - + // FCP transaction done - copy status Exchanges->fcExchange[ x_ID ].status = dwStatus; @@ -1459,7 +1459,7 @@ int CpqTsProcessIMQEntry(void *host) writel( fcChip->IMQ->consumerIndex, (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX)); - + #if IMQ_DEBUG printk("Process IMQ: writing consumer ndx %d\n", fcChip->IMQ->consumerIndex); @@ -1566,7 +1566,7 @@ int CpqTsInitializeTachLite( void *pHBA, // Now that we are supporting multiple boards, we need to change // this logic to check for PCI vendor/device IDs... // for now, quick & dirty is simply checking Chip rev - + ULONG RevId = (fcChip->Registers.TYstatus.value &0x3E0)>>5; UCHAR Minor = (UCHAR)(RevId & 0x3); UCHAR Major = (UCHAR)((RevId & 0x1C) >>2); diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTSi2c.c linux-2.6.13-eike/drivers/scsi/cpqfcTSi2c.c --- linux-2.6.13-eike/drivers/SCSI/cpqfcTSi2c.c 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTSi2c.c 2005-09-07 12:28:57.000000000 +0200 @@ -81,7 +81,6 @@ static void i2c_delay(ULONG mstime); static void tl_i2c_clock_pulse( UCHAR , void* GPIOout); static UCHAR tl_read_i2c_data( void* ); - //----------------------------------------------------------------------------- // // Name: I2C_RX_ACK @@ -387,7 +386,7 @@ int cpqfcTS_GetNVRAM_data( UCHAR *wwnbuf UCHAR sub_name; UCHAR done; int iReturn=0; // def. 0 offset is failure to find WWN field - + data_ptr = (UCHAR *)buf; done = FALSE; @@ -396,8 +395,7 @@ int cpqfcTS_GetNVRAM_data( UCHAR *wwnbuf while ( (i < 128) && (!done) ) { z = data_ptr[i];\ - if ( !(z & 0x80) ) - { + if ( !(z & 0x80) ) { len = 1 + (z & 0x07); name = (z & 0x78) >> 3; @@ -464,7 +462,7 @@ static void i2c_delay(ULONG mstime) // delay technique for( i=0; i < mstime; i++) udelay(1000); // 1ms per loop - + } else // 5 micro sec delay diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTSinit.c linux-2.6.13-eike/drivers/scsi/cpqfcTSinit.c --- linux-2.6.13-eike/drivers/SCSI/cpqfcTSinit.c 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTSinit.c 2005-09-07 12:33:58.000000000 +0200 @@ -28,7 +28,6 @@ * Chris Loveland to support the isp2100 and isp2200 */ - #include #include #include @@ -276,7 +275,7 @@ int cpqfcTS_detect(Scsi_Host_Template *S /* printk(" scsi_register allocating %d bytes for FC HBA\n", (ULONG)sizeof(CPQFCHBA)); */ - HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) ); + HostAdapter = scsi_register(ScsiHostTemplate, sizeof(CPQFCHBA)); if(HostAdapter == NULL) { printk(KERN_WARNING @@ -344,7 +343,7 @@ int cpqfcTS_detect(Scsi_Host_Template *S printk(KERN_WARNING "cpqfc: address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseU); goto err_free_irq; - } + } if( !request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME ) ) @@ -352,7 +351,7 @@ int cpqfcTS_detect(Scsi_Host_Template *S printk(KERN_WARNING "cpqfc: address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseL); goto err_release_region_U; - } + } // OK, we have grabbed everything we need now. DEBUG_PCI(printk(" Reserved 255 I/O addresses @ %x\n", @@ -397,11 +396,11 @@ int cpqfcTS_detect(Scsi_Host_Template *S // 1.0 LIP incoming // 1.027 LISA incoming, no CLS! (link not up) // 1.028 NOS incoming (switch test for N_Port) - // 1.577 ED_TOV expired, transmit LIPs again + // 1.577 ED_TOV expired, transmit LIPs again // 3.0 LIP(F8,F7) incoming (switch passes Tach Prim.Sig) // 3.028 LILP received, link up, FLOGI starts // slowest(worst) case, measured on 1Gb Finisar GT analyzer - + unsigned long stop_time; spin_unlock_irq(HostAdapter->host_lock); @@ -551,7 +550,7 @@ int cpqfcTS_ioctl( struct scsi_device *S /* Check that our pool got allocated ok. */ if (cpqfcHBAdata->private_data_pool == NULL) return -ENOMEM; - + if( !arg) return -EINVAL; @@ -561,7 +560,7 @@ int cpqfcTS_ioctl( struct scsi_device *S return -EPERM; // copy the caller's struct to our space. - if( copy_from_user( &ioc, arg, sizeof( VENDOR_IOCTL_REQ))) + if (copy_from_user(&ioc, arg, sizeof(VENDOR_IOCTL_REQ))) return( -EFAULT); vendor_cmd = ioc.argp; // i.e., CPQ specific command struct @@ -604,7 +603,7 @@ int cpqfcTS_ioctl( struct scsi_device *S } else // maybe this means a bug in the user app ScsiPassThruReq->sr_data_direction = DMA_BIDIRECTIONAL; - + ScsiPassThruReq->sr_cmd_len = 0; // set correctly by scsi_do_req() ScsiPassThruReq->sr_sense_buffer[0] = 0; ScsiPassThruReq->sr_sense_buffer[2] = 0; @@ -618,7 +617,7 @@ int cpqfcTS_ioctl( struct scsi_device *S privatedata = ScsiPassThruReq->upper_private_data; privatedata->bus = vendor_cmd->bus; privatedata->pdrive = vendor_cmd->pdrive; - + // eventually gets us to our own _quecommand routine scsi_wait_req(ScsiPassThruReq, &vendor_cmd->cdb[0], buf, vendor_cmd->len, @@ -663,7 +662,7 @@ int cpqfcTS_ioctl( struct scsi_device *S DumCmnd = scsi_get_command (ScsiDev, GFP_KERNEL); if (!DumCmnd) return -ENOMEM; - + pLoggedInPort = fcFindLoggedInPort( fcChip, DumCmnd, // search Scsi Nexus 0, // DON'T search linked list for FC port id @@ -695,9 +694,6 @@ int cpqfcTS_ioctl( struct scsi_device *S break; - - - default: result = -EINVAL; break; @@ -707,7 +703,6 @@ int cpqfcTS_ioctl( struct scsi_device *S return result; } - /* "Release" the Host Bus Adapter... disable interrupts, stop the HBA, release the interrupt, and free all resources */ @@ -941,7 +936,7 @@ copy_info( &info, "Fibre Channel Stats ( copy_info( &info, " Loss of Signal %9u Loss of Sync %u\n", fcChip->fcStats.LossofSignal, fcChip->fcStats.LossofSync); - + copy_info( &info, " Discarded Frames %9u Bad CRC Frame %u\n", fcChip->fcStats.Dis_Frm, fcChip->fcStats.Bad_CRC); @@ -953,7 +948,7 @@ copy_info( &info, "Fibre Channel Stats ( copy_info( &info, " BufferCreditWait %9uus TACH FM Inits %u\n", fcChip->fcStats.BB0_Timer*10, fcChip->fcStats.FMinits ); - + copy_info( &info, " FC-2 Timeouts %9u FC-2 Logouts %u\n", fcChip->fcStats.timeouts, fcChip->fcStats.logouts); @@ -963,7 +958,7 @@ copy_info( &info, "Fibre Channel Stats ( // clear the counters cpqfcTSClearLinkStatusCounters( fcChip); #endif - + return info.buffillen; } @@ -1270,7 +1265,7 @@ int cpqfcTS_queuecommand(Scsi_Cmnd *Cmnd PCI_TRACE( 0x98) CPQ_SPINLOCK_HBA( cpqfcHBAdata) PCI_TRACE( 0x98) - + // can we find an FC device mapping to this SCSI target? pLoggedInPort = fcFindLoggedInPort( fcChip, Cmnd, // search Scsi Nexus @@ -1315,7 +1310,7 @@ int cpqfcTS_queuecommand(Scsi_Cmnd *Cmnd // printk("Device (Chnl/Target %d/%d) invalid PRLI, port_id %06lXh\n", // Cmnd->channel, Cmnd->target, pLoggedInPort->port_id); QueLinkDownCmnd( cpqfcHBAdata, Cmnd); -// Need to use "blocked" flag?? +// Need to use "blocked" flag?? // Cmnd->device->device_blocked = TRUE; // just let it timeout } else // device supports TARGET functions, and is logged in... @@ -1336,7 +1331,7 @@ int cpqfcTS_queuecommand(Scsi_Cmnd *Cmnd } else SESTtype = SCSI_IRE; // data from Device to HBA - + ulStatus = cpqfcTSBuildExchange( cpqfcHBAdata, SESTtype, // e.g. Initiator Read Entry (IRE) @@ -1378,7 +1373,7 @@ int cpqfcTS_queuecommand(Scsi_Cmnd *Cmnd CPQ_SPINUNLOCK_HBA( cpqfcHBAdata) } - + PCI_TRACEO( (ULONG)Cmnd, 0x9C) LEAVE("cpqfcTS_queuecommand"); return 0; @@ -1528,7 +1523,7 @@ int cpqfcTS_TargetDeviceReset( Scsi_Devi if (ScsiDev->host->eh_active) return FAILED; - memset( scsi_cdb, 0, sizeof( scsi_cdb)); + memset(scsi_cdb, 0, sizeof(scsi_cdb)); scsi_cdb[0] = RELEASE; @@ -1575,7 +1570,7 @@ int cpqfcTS_TargetDeviceReset( Scsi_Devi sense_class(SCpnt->sense_buffer[0]), sense_error(SCpnt->sense_buffer[0]), SCpnt->sense_buffer[2] & 0xf); - + }; result = SCpnt->result; @@ -1642,7 +1637,7 @@ cpqfc_tasklet_func(unsigned long data) struct Scsi_Host *scsihost = cpqfcHBA->HostAdapter; unsigned long flags; int i = 0, r = 1; - + ENTER(__FUNCTION__); spin_lock_irqsave(scsihost->host_lock, flags); /* broken boards can generate messages forever, so @@ -1976,7 +1971,7 @@ void* fcMemManager( struct pci_dev *pdev dynamic_mem[i].AlignedAddress = (ULONG)(ulAddress & mask); // 32bit Tach address - memset( alloc_address, 0, n_alloc ); // clear new memory + memset(alloc_address, 0, n_alloc); // clear new memory } else // O/S dynamic mem alloc failed! alloc_address = 0; // (for debugging breakpt) diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTSioctl.h linux-2.6.13-eike/drivers/scsi/cpqfcTSioctl.h --- linux-2.6.13-eike/drivers/SCSI/cpqfcTSioctl.h 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTSioctl.h 2005-09-07 10:21:07.000000000 +0200 @@ -1,5 +1,5 @@ // for user apps, make sure data size types are defined -// with +// with #define CCPQFCTS_IOC_MAGIC 'Z' @@ -34,11 +34,11 @@ typedef struct { #define CPQFCTS_SCSI_PASSTHRU _IOWR( CCPQFCTS_IOC_MAGIC,11, VENDOR_IOCTL_REQ) -/* We would rather have equivalent generic, low-level driver agnostic -ioctls that do what CPQFC_IOCTL_FC_TARGET_ADDRESS and -CPQFC_IOCTL_FC_TDR 0x5388 do, but currently, we do not have them, +/* We would rather have equivalent generic, low-level driver agnostic +ioctls that do what CPQFC_IOCTL_FC_TARGET_ADDRESS and +CPQFC_IOCTL_FC_TDR 0x5388 do, but currently, we do not have them, consequently applications would have to know they are talking to cpqfc. */ - + /* Used to get Fibre Channel WWN and port_id from device */ // #define CPQFC_IOCTL_FC_TARGET_ADDRESS 0x5387 #define CPQFC_IOCTL_FC_TARGET_ADDRESS \ diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTSstructs.h linux-2.6.13-eike/drivers/scsi/cpqfcTSstructs.h --- linux-2.6.13-eike/drivers/SCSI/cpqfcTSstructs.h 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTSstructs.h 2005-09-07 12:39:50.000000000 +0200 @@ -1,11 +1,11 @@ /* Copyright(c) 2000, Compaq Computer Corporation - * Fibre Channel Host Bus Adapter 64-bit, 66MHz PCI + * Fibre Channel Host Bus Adapter 64-bit, 66MHz PCI * Originally developed and tested on: * (front): [chip] Tachyon TS HPFC-5166A/1.2 L2C1090 ... * SP# P225CXCBFIEL6T, Rev XC * SP# 161290-001, Rev XD * (back): Board No. 010008-001 A/W Rev X5, FAB REV X5 - * + * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any @@ -43,16 +43,15 @@ #define PCI_TRACEO(x,y) outl( x, (fcChip->Registers.IOBaseL +y)); #else -#define PCI_TRACE(x) +#define PCI_TRACE(x) #define PCI_TRACEO(x,y) #endif - //#define DEBUG_CMND 1 // debug output for Linux Scsi CDBs //#define DUMMYCMND_DBG 1 //#define DEBUG_CPQFCTS 1 -//#undef DEBUG_CPQFCTS +//#undef DEBUG_CPQFCTS #ifdef DEBUG_CPQFCTS #define ENTER(x) printk("cpqfcts : entering %s()\n", x); #define LEAVE(x) printk("cpqfcts : leaving %s()\n", x); @@ -85,7 +84,7 @@ #define CPQFCTS_MAX_LUN 32 // The RA-4x00 supports 32 (Linux SCSI supports 8) #define CPQFCTS_MAX_CHANNEL 0 // One FC port on cpqfcTS HBA -#define CPQFCTS_CMD_PER_LUN 15 // power of 2 -1, must be >0 +#define CPQFCTS_CMD_PER_LUN 15 // power of 2 -1, must be >0 #define CPQFCTS_REQ_QUEUE_LEN (TACH_SEST_LEN/2) // must be < TACH_SEST_LEN #ifndef DECLARE_MUTEX_LOCKED @@ -99,9 +98,6 @@ // the fields shared with ODB // need to have same value - - - #ifndef BYTE //typedef UCHAR BYTE; typedef __u8 BYTE; @@ -125,7 +121,6 @@ typedef __u16 USHORT; typedef __u8 BOOLEAN; #endif - // macro for FC-PH reject codes // payload format for LS_RJT (FC payloads are big endian): // byte 0 1 2 3 (MSB) @@ -134,7 +129,6 @@ typedef __u8 BOOLEAN; #define LS_RJT_REASON( code, expl) (( code<<8) | (expl <<16)) - #define TachLiteSTATUS 0x12 // Fibre Channel EXCHANGE status codes for Tachyon chips/ driver software @@ -163,7 +157,7 @@ typedef __u8 BOOLEAN; #define EXCHANGE_QUEUED 0x200000L // e.g. Link State was LDn on fcStart #define PORTID_CHANGED 0x400000L // fc Port address changed #define DEVICE_REMOVED 0x800000L // fc Port address changed -// Several error scenarios result in SEST Exchange frames +// Several error scenarios result in SEST Exchange frames // unexpectedly arriving in the SFQ #define SFQ_FRAME 0x1000000L // SFQ frames from open Exchange @@ -209,7 +203,7 @@ typedef __u8 BOOLEAN; #define ELS_FLOGI 0x44 // (arb assign) Fabric Login #define ELS_FDISC 0x41 // (arb assign) Fabric Discovery (Login) #define ELS_PDISC 0x50 // FC-PH2 Port Discovery -#define ELS_ABTX 0x06 // FC-PH Abort Exchange +#define ELS_ABTX 0x06 // FC-PH Abort Exchange #define ELS_LOGO 0x05 // FC-PH Port Logout #define ELS_PRLI 0x20 // FCP-SCSI Process Login #define ELS_PRLO 0x21 // FCP-SCSI Process Logout @@ -288,11 +282,6 @@ typedef struct // 32 bytes hdr + 64 __u32 pl[18]; // payload for FCP-RSP (response buffer) RA-4x00 is 72bytes } TachFCHDR_RSP; - - - - - // Inbound Message Queue structures... typedef struct // each entry 8 words (32 bytes) { @@ -301,7 +290,6 @@ typedef struct // each entr // interpreted by IMQ type } TachyonIMQE; - // Queues for TachLite not in original Tachyon // ERQ - Exchange Request Queue (for outbound commands) // SFQ - Single Frame Queue (for incoming frames) @@ -331,8 +319,6 @@ typedef struct // 8 wo ULONG base; } TachyonIMQ; // @ 32 * IMQ_LEN align - - typedef struct // inbound completion message { ULONG Type; @@ -340,8 +326,6 @@ typedef struct // inbound comp ULONG TransferLength; } TachyonInbCM; - - // arbitrary numeric tags for TL structures #define TL_FCHS 1 // TachLite Fibre Channel Header Structure #define TL_IWE 2 // initiator write entry (for SEST) @@ -363,7 +347,6 @@ typedef struct // Singl ULONG base; } TachLiteSFQ; - typedef struct // I/O Request Block flags { UCHAR BRD : 1; @@ -389,7 +372,6 @@ typedef struct // I/O R ULONG Req_B_Trans_ID; // X_ID (OX_ID or RX_ID) and/or Index in SEST } TachLiteIRB; - typedef struct // TachLite placeholder for IRBs { // aligned @sizeof(ERQ) for TachLite // MAX commands is sum of SEST len and ERQ @@ -415,10 +397,10 @@ typedef struct // TachLite pla #define TL_DANGER_SGPAGES 7 // arbitrary high water mark for # of S/G pages // we must exceed to elicit a warning indicative - // of EXTREMELY large data transfers or + // of EXTREMELY large data transfers or // EXTREME memory fragmentation. // (means we just used up 2048 S/G elements, - // Never seen this is real life, only in + // Never seen this is real life, only in // testing with tricked up driver.) #define TL_EXT_SG_PAGE_COUNT 256 // Number of Extended Scatter/Gather a/l PAIRS @@ -428,10 +410,8 @@ typedef struct // TachLite pla // byte len is #Pairs * 2 ULONG/Pair * 4 bytes/ULONG #define TL_EXT_SG_PAGE_BYTELEN (TL_EXT_SG_PAGE_COUNT *2 *4) - - // SEST entry types: IWE, IRE, TWE, TRE -typedef struct +typedef struct { ULONG Hdr_Len; ULONG Hdr_Addr; @@ -454,8 +434,7 @@ typedef struct ULONG GAddr3; } TachLiteIWE; - -typedef struct +typedef struct { ULONG Seq_Accum; ULONG reserved; // must clear to 0 @@ -476,7 +455,6 @@ typedef struct ULONG SAddr3; } TachLiteIRE; - typedef struct // Target Write Entry { ULONG Seq_Accum; // dword 0 @@ -498,7 +476,7 @@ typedef struct // Target Write ULONG SAddr3; } TachLiteTWE; -typedef struct +typedef struct { ULONG Hdr_Len; ULONG Hdr_Addr; @@ -520,7 +498,7 @@ typedef struct } TachLiteTRE; typedef struct ext_sg_page_ptr_t *PSGPAGES; -typedef struct ext_sg_page_ptr_t +typedef struct ext_sg_page_ptr_t { unsigned char page[TL_EXT_SG_PAGE_BYTELEN * 2]; // 2x for alignment dma_addr_t busaddr; // need the bus addresses and @@ -545,8 +523,6 @@ typedef struct // SCSI ULONG base; // copy of base ptr for debug } TachSEST; - - typedef struct // each register has it's own address // and value (used for write-only regs) { @@ -570,8 +546,8 @@ typedef struct // Host copy - Ta FCREGISTER INTEN; // copy of interrupt enable mask FCREGISTER INTPEND; // interrupt pending FCREGISTER INTSTAT; // interrupt status - FCREGISTER SFQconsumerIndex; - FCREGISTER ERQproducerIndex; + FCREGISTER SFQconsumerIndex; + FCREGISTER ERQproducerIndex; FCREGISTER TYconfig; // TachYon (chip level) FCREGISTER TYcontrol; FCREGISTER TYstatus; @@ -587,9 +563,7 @@ typedef struct // Host copy - Ta FCREGISTER primitive; // e.g. LIP(), OPN(), ... } TL_REGISTERS; - - -typedef struct +typedef struct { ULONG ok; ULONG invalidArgs; @@ -622,7 +596,6 @@ typedef struct ULONG lastBB0timer; // static accum. buffer needed by Tachlite } FCSTATS; - typedef struct // Config Options { // LS Bit first USHORT : 1; // bit0: @@ -643,8 +616,6 @@ typedef struct // Config O USHORT : 1; // bit15: } FC_OPTIONS; - - typedef struct dyn_mem_pair { void *BaseAllocated; // address as allocated from O/S; @@ -653,9 +624,6 @@ typedef struct dyn_mem_pair size_t size; } ALIGNED_MEM; - - - // these structs contain only CRUCIAL (stuff we actually use) parameters // from FC-PH(n) logins. (Don't save entire LOGIN payload to save mem.) @@ -667,7 +635,7 @@ typedef struct dyn_mem_pair #define IMPLICIT_LOGOUT 1 #define EXPLICIT_LOGOUT 2 -typedef struct +typedef struct { UCHAR channel; // SCSI "bus" UCHAR target; @@ -677,10 +645,9 @@ typedef struct UCHAR lun[CPQFCTS_MAX_LUN]; } SCSI_NEXUS; - -typedef struct +typedef struct { - union + union { UCHAR ucWWN[8]; // a FC 64-bit World Wide Name/ PortID of target // addressing of single target on single loop... @@ -689,9 +656,9 @@ typedef struct ULONG port_id; // a FC 24-bit address of port (lower 8 bits = al_pa) -#define REPORT_LUNS_PL 256 +#define REPORT_LUNS_PL 256 UCHAR ReportLunsPayload[REPORT_LUNS_PL]; - + SCSI_NEXUS ScsiNexus; // LUNs per FC device ULONG LOGO_counter; // might try several times before logging out for good @@ -716,7 +683,6 @@ typedef struct UCHAR highest_ver; UCHAR lowest_ver; - // when the "target" (actually FC Port) is waiting for login // (e.g. after Link reset), set the device_blocked bit; // after Port completes login, un-block target. @@ -729,11 +695,9 @@ typedef struct } FC_LOGGEDIN_PORT, *PFC_LOGGEDIN_PORT; - - // This serves as the ESB (Exchange Status Block), // and has timeout counter; used for ABORTs -typedef struct +typedef struct { // FC-1 X_IDs ULONG type; // ELS_PLOGI, SCSI_IWE, ... (0 if free) PFC_LOGGEDIN_PORT pLoggedInPort; // FC device on other end of Exchange @@ -757,23 +721,13 @@ typedef struct // we will allocate this FC_EXCHANGE fcExchange[ TACH_MAX_XID ]; } FC_EXCHANGES; - - - - - - - - - - typedef struct { char Name[64]; // name of controller ("HP Tachlite TL Rev2.0, 33MHz, 64bit bus") //PVOID pAdapterDevExt; // back pointer to device object/extension ULONG ChipType; // local numeric key for Tachyon Type / Rev. ULONG status; // our Driver - logical status - + TL_REGISTERS Registers; // reg addresses & host memory copies // FC-4 mapping of 'transaction' to X_IDs UCHAR LILPmap[32*4]; // Loop Position Map of ALPAs (late FC-AL only) @@ -781,15 +735,15 @@ typedef struct UCHAR highest_FCPH_ver; // FC-PH version limits UCHAR lowest_FCPH_ver; // FC-PH version limits - FC_EXCHANGES *Exchanges; + FC_EXCHANGES *Exchanges; ULONG fcLsExchangeLRU; // Least Recently Used counter (Link Service) ULONG fcSestExchangeLRU; // Least Recently Used counter (FCP-SCSI) FC_LOGGEDIN_PORT fcPorts; // linked list of every FC port ever seen FCSTATS fcStats; // FC comm err counters // Host memory QUEUE pointers - TachLiteERQ *ERQ; // Exchange Request Que - TachyonIMQ *IMQ; // Inbound Message Que + TachLiteERQ *ERQ; // Exchange Request Que + TachyonIMQ *IMQ; // Inbound Message Que TachLiteSFQ *SFQ; // Single Frame Queue TachSEST *SEST; // SCSI Exchange State Table @@ -812,7 +766,6 @@ typedef struct } TACHYON, *PTACHYON; - void cpqfcTSClearLinkStatusCounters(TACHYON * fcChip); int CpqTsCreateTachLiteQues( void* pHBA, int opcode); @@ -840,8 +793,7 @@ BOOLEAN tl_write_i2c_nvram( void* GPIOin USHORT count, UCHAR *buf ); - -// define misc functions +// define misc functions int cpqfcTSGetLPSM( PTACHYON fcChip, char cErrorString[]); int cpqfcTSDecodeGBICtype( PTACHYON fcChip, char cErrorString[]); void* fcMemManager( struct pci_dev *pdev, @@ -851,14 +803,11 @@ void* fcMemManager( struct pci_dev *pdev void BigEndianSwap( UCHAR *source, UCHAR *dest, USHORT cnt); //ULONG virt_to_phys( PVOID virtaddr ); - // Linux interrupt handler irqreturn_t cpqfcTS_intr_handler( int irq,void *dev_id,struct pt_regs *regs); void cpqfcTSheartbeat( unsigned long ptr ); - - // The biggest Q element we deal with is Aborts - we // need 4 bytes for x_ID, and a Scsi_Cmnd (~284 bytes) //#define LINKQ_ITEM_SIZE ((4+sizeof(Scsi_Cmnd)+3)/4) @@ -879,7 +828,6 @@ typedef struct } FC_LINK_QUE, *PFC_LINK_QUE; - // DPC routines post to here on Inbound SCSI frames // User thread processes #define FC_SCSIQ_DEPTH 32 @@ -900,8 +848,8 @@ typedef struct } FC_SCSI_QUE, *PFC_SCSI_QUE; typedef struct { - /* This is tacked on to a Scsi_Request in upper_private_data - for pasthrough ioctls, as a place to hold data that can't + /* This is tacked on to a Scsi_Request in upper_private_data + for pasthrough ioctls, as a place to hold data that can't be stashed anywhere else in the Scsi_Request. We differentiate this from _real_ upper_private_data by checking if the virt addr is within our special pool. */ @@ -914,7 +862,7 @@ typedef struct { #define DYNAMIC_ALLOCATIONS 4 // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST // Linux space allocated per HBA (chip state, etc.) -typedef struct +typedef struct { struct Scsi_Host *HostAdapter; // back pointer to Linux Scsi struct @@ -927,25 +875,24 @@ typedef struct Scsi_Cmnd *LinkDnCmnd[CPQFCTS_REQ_QUEUE_LEN]; // collects Cmnds during LDn // (for Acceptable targets) Scsi_Cmnd *BoardLockCmnd[CPQFCTS_REQ_QUEUE_LEN]; // SEST was full - + Scsi_Cmnd *BadTargetCmnd[CPQFCTS_MAX_TARGET_ID]; // missing targets u_char HBAnum; // 0-based host number - struct timer_list cpqfcTStimer; // FC utility timer for implicit // logouts, FC protocol timeouts, etc. int fcStatsTime; // Statistics delta reporting time struct task_struct *worker_thread; // our kernel thread int PortDiscDone; // set by SendLogins(), cleared by LDn - + struct semaphore *TachFrozen; struct semaphore *TYOBcomplete; // handshake for Tach outbound frames struct semaphore *fcQueReady; // FibreChannel work for our kernel thread struct semaphore *notify_wt; // synchronizes kernel thread kill struct semaphore *BoardLock; - + PFC_LINK_QUE fcLQ; // the WorkerThread operates on this spinlock_t hba_spinlock; // held/released by WorkerThread @@ -958,42 +905,32 @@ typedef struct #define CPQ_SPINLOCK_HBA( x ) spin_lock(&x->hba_spinlock); #define CPQ_SPINUNLOCK_HBA(x) spin_unlock(&x->hba_spinlock); - - void cpqfcTSImplicitLogout( CPQFCHBA* cpqfcHBAdata, PFC_LOGGEDIN_PORT pFcPort); - void cpqfcTSTerminateExchange( CPQFCHBA*, SCSI_NEXUS *target, int ); -PFC_LOGGEDIN_PORT fcPortLoggedIn( - CPQFCHBA *cpqfcHBAdata, - TachFCHDR_GCMND* fchs, - BOOLEAN, - BOOLEAN); -void fcProcessLoggedIn( - CPQFCHBA *cpqfcHBAdata, TachFCHDR_GCMND* fchs); - +PFC_LOGGEDIN_PORT fcPortLoggedIn(CPQFCHBA*, TachFCHDR_GCMND*, BOOLEAN, BOOLEAN); +void fcProcessLoggedIn(CPQFCHBA *, TachFCHDR_GCMND*); -ULONG cpqfcTSBuildExchange( +ULONG cpqfcTSBuildExchange( CPQFCHBA *cpqfcHBAdata, ULONG type, // e.g. PLOGI TachFCHDR_GCMND* InFCHS, // incoming FCHS - void *Data, // the CDB, scatter/gather, etc. + void *Data, // the CDB, scatter/gather, etc. LONG *ExchangeID ); // allocated exchange ID -ULONG cpqfcTSStartExchange( +ULONG cpqfcTSStartExchange( CPQFCHBA *cpqfcHBAdata, LONG ExchangeID ); -void cpqfcTSCompleteExchange( +void cpqfcTSCompleteExchange( struct pci_dev *pcidev, - PTACHYON fcChip, + PTACHYON fcChip, ULONG exchange_ID); - -PFC_LOGGEDIN_PORT fcFindLoggedInPort( - PTACHYON fcChip, +PFC_LOGGEDIN_PORT fcFindLoggedInPort( + PTACHYON fcChip, Scsi_Cmnd *Cmnd, // (We want the channel/target/lun Nexus from Cmnd) ULONG port_id, // search linked list for al_pa, or UCHAR wwn[8], // search linked list for WWN, or... @@ -1002,9 +939,9 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( void cpqfcTSPutLinkQue(CPQFCHBA *, int, TachFCHDR_GCMND*, ULONG); -void fcPutScsiQue( - CPQFCHBA *cpqfcHBAdata, - int Type, +void fcPutScsiQue( + CPQFCHBA *cpqfcHBAdata, + int Type, void *QueContent); void fcLinkQReset( @@ -1014,9 +951,9 @@ void fcScsiQReset( void fcSestReset( CPQFCHBA *); -void cpqfc_pci_unmap(struct pci_dev *pcidev, - Scsi_Cmnd *cmd, - PTACHYON fcChip, +void cpqfc_pci_unmap(struct pci_dev *pcidev, + Scsi_Cmnd *cmd, + PTACHYON fcChip, ULONG x_ID); extern const UCHAR valid_al_pa[]; @@ -1049,7 +986,6 @@ typedef struct // see "TachFCHDR_RSP" d } FCP_STATUS_RESPONSE, *PFCP_STATUS_RESPONSE; - // Fabric State Change Registration typedef struct scrpl { @@ -1065,11 +1001,8 @@ typedef struct nsrpl __u32 Command_code; // WORD 2 __u32 reason_code; // WORD 3 __u32 FCP; // WORD 4 (lower byte) - } NSR_PL; - - // "FC.H" #define MAX_RX_SIZE 0x800 // Max Receive Buffer Size is 2048 #define MIN_RX_SIZE 0x100 // Min Size is 256, per FC-PLDA Spec @@ -1088,7 +1021,7 @@ typedef struct nsrpl // PDISC after a LIP. #define E_D_TOV 2 // Minimum Time to wait for Sequence // Completion. -#define R_A_TOV 0 // Minimum Time for Target to wait +#define R_A_TOV 0 // Minimum Time for Target to wait // before reclaiming resources. // // R_CTL Field @@ -1120,8 +1053,8 @@ typedef struct nsrpl // #define ACK_1 0x00000000 #define ACK_0_OR_N 0x01000000 -#define P_RJT 0x02000000 -#define F_RJT 0x03000000 +#define P_RJT 0x02000000 +#define F_RJT 0x03000000 #define P_BSY 0x04000000 #define FABRIC_BUSY_TO_DF 0x05000000 // Fabric Busy to Data Frame #define FABRIC_BUSY_TO_LC 0x06000000 // Fabric Busy to Link Ctl Frame @@ -1156,7 +1089,7 @@ typedef struct nsrpl #define LS_ADISC 0x52000000 // Discover Address #define LS_RNC 0x53000000 // Report Node Capability #define LS_SCR 0x62000000 // State Change Registration -#define LS_MASK 0xFF000000 +#define LS_MASK 0xFF000000 // // TYPE Bit Masks @@ -1200,7 +1133,6 @@ typedef struct { UCHAR vendor_unique; } BA_RJT_PAYLOAD; - typedef struct { ULONG command_code; ULONG sid; @@ -1216,7 +1148,6 @@ typedef struct { UCHAR reserved; } REJECT_MESSAGE; - #define N_OR_F_PORT 0x1000 #define RANDOM_RELATIVE_OFFSET 0x4000 #define CONTINUOSLY_INCREASING 0x8000 @@ -1324,7 +1255,6 @@ typedef struct { USHORT total_rxids; } LOGIN_PAYLOAD; - typedef struct { ULONG cmd; // 4 bytes @@ -1333,7 +1263,6 @@ typedef struct UCHAR port_name[8]; } LOGOUT_PAYLOAD; - // // PRLI Request Service Parameter Defines // @@ -1370,7 +1299,7 @@ typedef struct { ULONG orig_process_associator; ULONG resp_process_associator; - + ULONG fcp_info; } PRLI_REQUEST; @@ -1391,7 +1320,7 @@ typedef struct { ULONG cmd; ULONG hard_address; - + UCHAR port_name[8]; UCHAR node_name[8]; @@ -1403,8 +1332,7 @@ struct ext_sg_entry_t { __u32 len:18; /* buffer length, bits 0-17 */ __u32 uba:13; /* upper bus address bits 18-31 */ __u32 lba; /* lower bus address bits 0-31 */ -}; - +}; // J. McCarty's LINK.H // @@ -1515,7 +1443,4 @@ struct ext_sg_entry_t { #define BA_INVALID_OX_RX 0x00000300 #define BA_SEQUENCE_ABORTED 0x00000500 - - #endif /* CPQFCTSSTRUCTS_H */ - diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTStrigger.c linux-2.6.13-eike/drivers/scsi/cpqfcTStrigger.c --- linux-2.6.13-eike/drivers/SCSI/cpqfcTStrigger.c 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTStrigger.c 2005-09-07 10:21:07.000000000 +0200 @@ -18,7 +18,7 @@ void TriggerHBA( void* IOBaseUpper, int // get initial value in hopes of not modifying any other GPIO line IOBaseUpper += 0x188; // TachTL/TS Control reg - + value = readl( IOBaseUpper); // set HIGH to trigger external analyzer (tested on Dolche Finisar 1Gb GTA) // The Finisar anaylzer triggers on low-to-high TTL transition diff -aurp linux-2.6.13-eike/drivers/SCSI/cpqfcTSworker.c linux-2.6.13-eike/drivers/scsi/cpqfcTSworker.c --- linux-2.6.13-eike/drivers/SCSI/cpqfcTSworker.c 2005-09-07 10:15:14.000000000 +0200 +++ linux-2.6.13-eike/drivers/scsi/cpqfcTSworker.c 2005-09-07 12:41:40.000000000 +0200 @@ -1,6 +1,6 @@ -/* Copyright(c) 2000, Compaq Computer Corporation - * Fibre Channel Host Bus Adapter - * 64-bit, 66MHz PCI +/* Copyright(c) 2000, Compaq Computer Corporation + * Fibre Channel Host Bus Adapter + * 64-bit, 66MHz PCI * Originally developed and tested on: * (front): [chip] Tachyon TS HPFC-5166A/1.2 L2C1090 ... * SP# P225CXCBFIEL6T, Rev XC @@ -65,15 +65,15 @@ // These "worker" functions will handle things like FC Logins; all // processes with I/O to our device must wait for the Login to complete -// and (if successful) I/O to resume. In the event of a malfunctioning or +// and (if successful) I/O to resume. In the event of a malfunctioning or // very busy loop, it may take hundreds of millisecs or even seconds to complete // a frame send. We don't want to hang up the entire server (and all // processes which don't depend on Fibre) during this wait. // The Tachyon chip can have around 30,000 I/O operations ("exchanges") -// open at one time. However, each exchange must be initiated +// open at one time. However, each exchange must be initiated // synchronously (i.e. each of the 30k I/O had to be started one at a -// time by sending a starting frame via Tachyon's outbound que). +// time by sending a starting frame via Tachyon's outbound que). // To accommodate kernel "module" build, this driver limits the exchanges // to 256, because of the contiguous physical memory limitation of 128M. @@ -84,9 +84,9 @@ // However, when we have FC related errors or hot plugging of FC ports, we pause // I/O and handle FC-specific tasks in the worker thread. These FC-specific // functions will handle things like FC Logins and Aborts. As the Login sequence -// completes to each and every target, I/O can resume to that target. +// completes to each and every target, I/O can resume to that target. -// Our kernel "worker thread" must share the HBA with threads calling +// Our kernel "worker thread" must share the HBA with threads calling // "queuecommand". We define a "BoardLock" semaphore which indicates // to "queuecommand" that the HBA is unavailable, and Cmnds are added to a // board lock Q. When the worker thread finishes with the board, the board @@ -100,9 +100,9 @@ // When FC devices are logged in, we build and start FC commands to the // devices. -// NOTE!! As of May 2000, kernel 2.2.14, the error recovery logic for devices +// NOTE!! As of May 2000, kernel 2.2.14, the error recovery logic for devices // that never log back in (e.g. physically removed) is NOT completely -// understood. I've still seen instances of system hangs on failed Write +// understood. I've still seen instances of system hangs on failed Write // commands (possibly from the ext2 layer?) on device removal. Such special // cases need to be evaluated from a system/application view - e.g., how // exactly does the system want me to complete commands when the device is @@ -116,7 +116,7 @@ static void SetLoginFields( BOOLEAN PDisc, BOOLEAN Originator); -static void AnalyzeIncomingFrame( +static void AnalyzeIncomingFrame( CPQFCHBA *cpqfcHBAdata, ULONG QNdx ); @@ -127,35 +127,35 @@ static int verify_PLOGI( PTACHYON fcChip static int verify_PRLI( TachFCHDR_GCMND* fchs, ULONG* reject_explain); static void LoadWWN( PTACHYON fcChip, UCHAR* dest, UCHAR type); -static void BuildLinkServicePayload( +static void BuildLinkServicePayload( PTACHYON fcChip, ULONG type, void* payload); -static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, +static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort); static void cpqfcTSCheckandSnoopFCP( PTACHYON fcChip, ULONG x_ID); static void CompleteBoardLockCmnd( CPQFCHBA *cpqfcHBAdata); -static void RevalidateSEST( struct Scsi_Host *HostAdapter, +static void RevalidateSEST( struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort); -static void IssueReportLunsCommand( - CPQFCHBA* cpqfcHBAdata, +static void IssueReportLunsCommand( + CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs); int cpqfcTSWorkerThread(void *host) { struct Scsi_Host *HostAdapter = (struct Scsi_Host*)host; - CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; + CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; #ifdef PCI_KERNEL_TRACE PTACHYON fcChip = &cpqfcHBAdata->fcChip; #endif DECLARE_MUTEX_LOCKED(fcQueReady); - DECLARE_MUTEX_LOCKED(fcTYOBcomplete); - DECLARE_MUTEX_LOCKED(TachFrozen); - DECLARE_MUTEX_LOCKED(BoardLock); + DECLARE_MUTEX_LOCKED(fcTYOBcomplete); + DECLARE_MUTEX_LOCKED(TachFrozen); + DECLARE_MUTEX_LOCKED(BoardLock); ENTER(__FUNCTION__); @@ -177,10 +177,10 @@ cpqfcTSWorkerThread(void *host) // into our _quecommand function (this also disables INTs) spin_lock_irqsave( HostAdapter->host_lock, flags); // STOP _que function PCI_TRACE( 0x90) - + CPQ_SPINLOCK_HBA( cpqfcHBAdata) // next, set this pointer to indicate to the _quecommand function - // that the board is in use, so it should que the command and + // that the board is in use, so it should que the command and // immediately return (we don't actually require the semaphore function // in this driver rev) @@ -201,7 +201,7 @@ cpqfcTSWorkerThread(void *host) // hopefully, no more "work" to do; // re-enable our INTs for "normal" completion processing enable_irq( cpqfcHBAdata->HostAdapter->irq); - + cpqfcHBAdata->BoardLock = NULL; // allow commands to be queued CPQ_SPINUNLOCK_HBA( cpqfcHBAdata) @@ -232,20 +232,17 @@ static BOOLEAN FreezeTach( CPQFCHBA *cpq // 2. Get Tach freeze confirmation // (synchronize SEST manipulation with Freeze Completion Message) - // we need INTs on so semaphore can be set. + // we need INTs on so semaphore can be set. enable_irq( cpqfcHBAdata->HostAdapter->irq); // only way to get Semaphore down_interruptible( cpqfcHBAdata->TachFrozen); // wait for INT handler sem. // can we TIMEOUT semaphore wait?? TBD - disable_irq( cpqfcHBAdata->HostAdapter->irq); + disable_irq( cpqfcHBAdata->HostAdapter->irq); FrozeTach = TRUE; } // (else, already frozen) - - return FrozeTach; -} - - + return FrozeTach; +} // This is the kernel worker thread task, which processes FC // tasks which were queued by the Interrupt handler or by @@ -270,7 +267,6 @@ void cpqfcTS_WorkTask( struct Scsi_Host QconsumerNdx = fcLQ->consumer; PCI_TRACEO( fcLQ->Qitem[QconsumerNdx].Type, 0x90) - // NOTE: when this switch completes, we will "consume" the Que item // printk("Que type %Xh\n", fcLQ->Qitem[QconsumerNdx].Type); @@ -278,15 +274,13 @@ void cpqfcTS_WorkTask( struct Scsi_Host { // incoming frame - link service (ACC, UNSOL REQ, etc.) // or FCP-SCSI command - case SFQ_UNKNOWN: + case SFQ_UNKNOWN: AnalyzeIncomingFrame( cpqfcHBAdata, QconsumerNdx ); break; - - - + case EXCHANGE_QUEUED: // an Exchange (i.e. FCP-SCSI) was previously - // Queued because the link was down. The + // Queued because the link was down. The // heartbeat timer detected it and Queued it here. // We attempt to start it again, and if // successful we clear the EXCHANGE_Q flag. @@ -302,38 +296,36 @@ void cpqfcTS_WorkTask( struct Scsi_Host if( Exchanges->fcExchange[ExchangeID].status & EXCHANGE_QUEUED ) { -// printk(" *Start Q'd x_ID %Xh: type %Xh ", +// printk(" *Start Q'd x_ID %Xh: type %Xh ", // ExchangeID, Exchanges->fcExchange[ExchangeID].type); - + ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID); if( !ulStatus ) { // printk("success* "); - } + } else { #ifdef DBG - + if( ulStatus == EXCHANGE_QUEUED) printk("Queued* "); else printk("failed* "); - + #endif - } + } } break; - - case LINKDOWN: + case LINKDOWN: // (lots of things already done in INT handler) future here? break; - - + case LINKACTIVE: // Tachyon set the Lup bit in FM status // NOTE: some misbehaving FC ports (like Tach2.1) // can re-LIP immediately after a LIP completes. - + // if "initiator", need to verify LOGs with ports // printk("\n*LNKUP* "); @@ -341,8 +333,8 @@ void cpqfcTS_WorkTask( struct Scsi_Host SendLogins( cpqfcHBAdata, NULL ); // PLOGI or PDISC, based on fcPort data // if SendLogins successfully completes, PortDiscDone // will be set. - - + + // If SendLogins was successful, then we expect to get incoming // ACCepts or REJECTs, which are handled below. @@ -361,8 +353,7 @@ void cpqfcTS_WorkTask( struct Scsi_Host case ELS_LOGO_ACC: // need to send ELS ACCept frame to recv'd PLOGI case ELS_RJT: // ReJecT reply case ELS_PRLI: // need to send ELS PRLI - - + // printk(" *ELS %Xh* ", fcLQ->Qitem[QconsumerNdx].Type); // if PortDiscDone is not set, it means the SendLogins routine // failed to complete -- assume that LDn occurred, so login frames @@ -370,7 +361,7 @@ void cpqfcTS_WorkTask( struct Scsi_Host if( !cpqfcHBAdata->PortDiscDone) // cleared by LDn { printk("Discard Q'd ELS login frame\n"); - break; + break; } ulStatus = cpqfcTSBuildExchange( @@ -408,18 +399,15 @@ void cpqfcTS_WorkTask( struct Scsi_Host // so we can send REPORT_LUNS, in order to determine VSA/PDU // FCP-SCSI Lun address mode IssueReportLunsCommand( cpqfcHBAdata, (TachFCHDR_GCMND*) - fcLQ->Qitem[QconsumerNdx].ulBuff); + fcLQ->Qitem[QconsumerNdx].ulBuff); break; - - - case BLS_ABTS: // need to ABORT one or more exchanges { LONG x_ID = fcLQ->Qitem[QconsumerNdx].ulBuff[0]; - BOOLEAN FrozeTach = FALSE; - + BOOLEAN FrozeTach = FALSE; + if ( x_ID >= TACH_SEST_LEN ) // (in)sanity check { // printk( " cpqfcTS ERROR! BOGUS x_ID %Xh", x_ID); @@ -430,13 +418,13 @@ void cpqfcTS_WorkTask( struct Scsi_Host if( Exchanges->fcExchange[ x_ID].Cmnd == NULL ) // should be RARE { // printk(" ABTS %Xh Scsi Cmnd null! ", x_ID); - + break; // nothing to abort! } //#define ABTS_DBG #ifdef ABTS_DBG - printk("INV SEST[%X] ", x_ID); + printk("INV SEST[%X] ", x_ID); if( Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT) { printk("FC2TO"); @@ -477,14 +465,14 @@ void cpqfcTS_WorkTask( struct Scsi_Host else if( Exchanges->fcExchange[ x_ID].type == 0x10) printk(" ABTS"); else - printk(" %Xh", Exchanges->fcExchange[ x_ID].type); + printk(" %Xh", Exchanges->fcExchange[ x_ID].type); if( !(Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)) { - printk(" Cmd %p, ", + printk(" Cmd %p, ", Exchanges->fcExchange[ x_ID].Cmnd); - printk(" brd/chn/trg/lun %d/%d/%d/%d port_id %06X\n", + printk(" brd/chn/trg/lun %d/%d/%d/%d port_id %06X\n", cpqfcHBAdata->HBAnum, Exchanges->fcExchange[ x_ID].Cmnd->channel, Exchanges->fcExchange[ x_ID].Cmnd->target, @@ -495,14 +483,13 @@ void cpqfcTS_WorkTask( struct Scsi_Host { printk(" Cmd ptr invalid\n"); } - -#endif - +#endif + // Steps to ABORT a SEST exchange: // 1. Freeze TL SCSI assists & ERQ (everything) // 2. Receive FROZEN inbound CM (must succeed!) - // 3. Invalidate x_ID SEST entry + // 3. Invalidate x_ID SEST entry // 4. Resume TL SCSI assists & ERQ (everything) // 5. Build/start on exchange - change "type" to BLS_ABTS, // timeout to X sec (RA_TOV from PLDA is actually 0) @@ -510,27 +497,24 @@ void cpqfcTS_WorkTask( struct Scsi_Host // or simply complete Exchange in "Terminate" condition PCI_TRACEO( x_ID, 0xB4) - + // 1 & 2 . Freeze Tach & get confirmation of freeze FrozeTach = FreezeTach( cpqfcHBAdata); // 3. OK, Tachyon is frozen, so we can invalidate SEST exchange. // FC2_TIMEOUT means we are originating the abort, while // TARGET_ABORT means we are ACCepting an abort. - // LINKFAIL_TX, ABORTSEQ_NOFITY, INV_ENTRY or FRAME_TO are + // LINKFAIL_TX, ABORTSEQ_NOFITY, INV_ENTRY or FRAME_TO are // all from Tachyon: // Exchange was corrupted by LDn or other FC physical failure // INITIATOR_ABORT means the upper layer driver/application // requested the abort. - - // clear bit 31 (VALid), to invalidate & take control from TL fcChip->SEST->u[ x_ID].IWE.Hdr_Len &= 0x7FFFFFFF; - - // examine and Tach's "Linked List" for IWEs that - // received (nearly) simultaneous transfer ready (XRDY) + // examine and Tach's "Linked List" for IWEs that + // received (nearly) simultaneous transfer ready (XRDY) // repair linked list if necessary (TBD!) // (If we ignore the "Linked List", we will time out // WRITE commands where we received the FCP-SCSI XFRDY @@ -539,9 +523,6 @@ void cpqfcTS_WorkTask( struct Scsi_Host // readl( fcChip->Registers.ReMapMemBase+TL_MEM_SEST_LINKED_LIST )); - - - // 4. Resume all Tachlite functions (for other open Exchanges) // as quickly as possible to allow other exchanges to other ports // to resume. Freezing Tachyon may cause cascading errors, because @@ -549,7 +530,6 @@ void cpqfcTS_WorkTask( struct Scsi_Host // Don't "unfreeze" unless Link is operational if( FrozeTach ) // did we just freeze it (above)? fcChip->UnFreezeTachyon( fcChip, 2); // both ERQ and FCP assists - PCI_TRACEO( x_ID, 0xB4) @@ -576,33 +556,31 @@ void cpqfcTS_WorkTask( struct Scsi_Host if( !ulStatus ) // Exchange setup build OK? { - // ABTS may be needed because an Exchange was corrupted // by a Link disruption. If the Link is UP, we can // presume that this ABTS can start immediately; otherwise, // set Que'd status so the Login functions // can restart it when the FC physical Link is restored if( ((fcChip->Registers.FMstatus.value &0xF0) &0x80)) // loop init? - { + { // printk(" *set Q status x_ID %Xh on LDn* ", x_ID); Exchanges->fcExchange[ x_ID].status |= EXCHANGE_QUEUED; } - else // what FC device (port_id) does the Cmd belong to? { - PFC_LOGGEDIN_PORT pLoggedInPort = + PFC_LOGGEDIN_PORT pLoggedInPort = Exchanges->fcExchange[ x_ID].pLoggedInPort; - + // if Port is logged in, we might start the abort. - - if( (pLoggedInPort != NULL) + + if( (pLoggedInPort != NULL) && - (pLoggedInPort->prli == TRUE) ) + (pLoggedInPort->prli == TRUE) ) { // it's possible that an Exchange has already been Queued // to start after Login completes. Check and don't // start it (again) here if Q'd status set -// printk(" ABTS xchg %Xh ", x_ID); +// printk(" ABTS xchg %Xh ", x_ID); if( Exchanges->fcExchange[x_ID].status & EXCHANGE_QUEUED) { // printk("already Q'd "); @@ -610,8 +588,8 @@ void cpqfcTS_WorkTask( struct Scsi_Host else { // printk("starting "); - - fcChip->fcStats.FC2aborted++; + + fcChip->fcStats.FC2aborted++; ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, x_ID ); if( !ulStatus ) { @@ -623,7 +601,7 @@ void cpqfcTS_WorkTask( struct Scsi_Host /* printk("ABTS exchange start failed -status %Xh, x_ID %Xh ", ulStatus, x_ID); */ - } + } } } else @@ -633,7 +611,7 @@ void cpqfcTS_WorkTask( struct Scsi_Host if( pLoggedInPort ) printk("prli %d ", pLoggedInPort->prli); */ - } + } } } else // what the #@! @@ -644,7 +622,7 @@ void cpqfcTS_WorkTask( struct Scsi_Host } else // abort without ABTS -- just complete exchange/Cmnd to Linux { -// printk(" *Terminating x_ID %Xh on %Xh* ", +// printk(" *Terminating x_ID %Xh on %Xh* ", // x_ID, Exchanges->fcExchange[x_ID].status); cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, x_ID); @@ -652,11 +630,8 @@ void cpqfcTS_WorkTask( struct Scsi_Host } // end of ABTS case break; - - case BLS_ABTS_ACC: // need to ACCept one ABTS // (NOTE! this code not updated for Linux yet..) - printk(" *ABTS_ACC* "); // 1. Freeze TL @@ -666,17 +641,16 @@ void cpqfcTS_WorkTask( struct Scsi_Host memcpy( // copy the incoming ABTS frame &fchs, fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs - sizeof( fchs)); + sizeof(fchs)); - // 3. OK, Tachyon is frozen so we can invalidate SEST entry + // 3. OK, Tachyon is frozen so we can invalidate SEST entry // (if necessary) // Status FC2_TIMEOUT means we are originating the abort, while // TARGET_ABORT means we are ACCepting an abort - + ExchangeID = fchs.ox_rx_id & 0x7FFF; // RX_ID for exchange // printk("ABTS ACC for Target ExchangeID %Xh\n", ExchangeID); - // sanity check on received ExchangeID if( Exchanges->fcExchange[ ExchangeID].status == TARGET_ABORT ) { @@ -685,20 +659,19 @@ void cpqfcTS_WorkTask( struct Scsi_Host fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len &= 0x7FFFFFFF; } - // 4. Resume all Tachlite functions (for other open Exchanges) // as quickly as possible to allow other exchanges to other ports // to resume. Freezing Tachyon for too long may royally screw // up everything! fcChip->UnFreezeTachyon( fcChip, 2); // both ERQ and FCP assists - + // Note there is no confirmation that the chip is "unfrozen". Also, // if the Link is down when unfreeze is called, it has no effect. // Chip will unfreeze when the Link is back up. // 5. Now send out Abort ACC reply for this exchange Exchanges->fcExchange[ ExchangeID].type = BLS_ABTS_ACC; - + fchs.s_id = Exchanges->fcExchange[ ExchangeID].fchs.d_id; ulStatus = cpqfcTSBuildExchange( cpqfcHBAdata, @@ -721,11 +694,10 @@ void cpqfcTS_WorkTask( struct Scsi_Host // want to Queue and start later, or fail with error { - } + } } break; - case BLS_ABTS_RJT: // need to ReJecT one ABTS; reject implies the // exchange doesn't exist in the TARGET context. // ExchangeID has to come from LinkService space. @@ -751,13 +723,11 @@ void cpqfcTS_WorkTask( struct Scsi_Host else { printk("Sent BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID); - + } break; - - default: break; } // end switch @@ -769,7 +739,7 @@ void cpqfcTS_WorkTask( struct Scsi_Host fcLQ->consumer = 0; } else - { + { fcLQ->consumer++; } @@ -779,12 +749,9 @@ void cpqfcTS_WorkTask( struct Scsi_Host return; } - - - // When Tachyon reports link down, bad al_pa, or Link Service (e.g. Login) // commands come in, post to the LinkQ so that action can be taken outside the -// interrupt handler. +// interrupt handler. // This circular Q works like Tachyon's que - the producer points to the next // (unused) entry. Called by Interrupt handler, WorkerThread, Timer // sputlinkq @@ -796,7 +763,7 @@ cpqfcTSPutLinkQue(CPQFCHBA *cpqfcHBAdata // FC_EXCHANGES *Exchanges = fcChip->Exchanges; PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ; ULONG ndx; - + ENTER("cpqfcTSPutLinkQ"); ndx = fcLQ->producer + 1; /* test for Que full */ @@ -816,15 +783,15 @@ cpqfcTSPutLinkQue(CPQFCHBA *cpqfcHBAdata int i; printk("LinkQ PI %d, CI %d\n", fcLQ->producer, fcLQ->consumer); - + for( i=0; i< FC_LINKQ_DEPTH; ) { printk(" [%d]%Xh ", i, fcLQ->Qitem[i].Type); if( (++i %8) == 0) printk("\n"); } - + } -*/ +*/ printk( "cpqfcTS: WARNING!! PutLinkQue - FULL!\n"); // we're hung } else // QUE next element @@ -835,9 +802,9 @@ cpqfcTSPutLinkQue(CPQFCHBA *cpqfcHBAdata // We can never be sure of the timing of events reported to // us by Tach's IMQ, which can depend on system/bus speeds, // FC physical link circumstances, etc. - + if( (fcLQ->producer != fcLQ->consumer) - && + && (Type == FMINIT) ) { LONG lastNdx; // compute previous producer index @@ -856,7 +823,7 @@ cpqfcTSPutLinkQue(CPQFCHBA *cpqfcHBAdata } // OK, add the Q'd item... - + fcLQ->Qitem[fcLQ->producer].Type = Type; if (content) { @@ -869,7 +836,7 @@ cpqfcTSPutLinkQue(CPQFCHBA *cpqfcHBAdata fcLQ->producer = ndx; // increment Que producer // set semaphore to wake up Kernel (worker) thread - // + // up( cpqfcHBAdata->fcQueReady ); } @@ -878,23 +845,15 @@ cpqfcTSPutLinkQue(CPQFCHBA *cpqfcHBAdata LEAVE("cpqfcTSPutLinkQ"); } - - - // reset device ext FC link Q void cpqfcTSLinkQReset( CPQFCHBA *cpqfcHBAdata) - + { PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ; fcLQ->producer = 0; fcLQ->consumer = 0; - } - - - - // When Tachyon gets an unassisted FCP-SCSI frame, post here so // an arbitrary context thread (e.g. IOCTL loopback test function) // can process it. @@ -903,7 +862,7 @@ void cpqfcTSLinkQReset( CPQFCHBA *cpqfcH // This Q works like Tachyon's que - the producer points to the next // (unused) entry. void cpqfcTSPutScsiQue( CPQFCHBA *cpqfcHBAdata, - int Type, + int Type, void *QueContent) { // CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; @@ -933,7 +892,7 @@ void cpqfcTSPutScsiQue( CPQFCHBA *cpqfcH else // QUE next element { pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].Type = Type; - + if( Type == FCP_RSP ) { // this TL inbound message type means that a TL SEST exchange has @@ -941,21 +900,21 @@ void cpqfcTSPutScsiQue( CPQFCHBA *cpqfcH // entry. That buffer is allocated in the SEST structure at ->RspHDR. // Copy the RspHDR for use by the Que handler. pExchangeID = (ULONG *)QueContent; - + memcpy( pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff, &fcChip->SEST->RspHDR[ *pExchangeID ], sizeof(pDevExt->fcScsiQue.Qitem[0].ulBuff)); // (any element for size) - + } else { memcpy( pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff, - QueContent, + QueContent, sizeof(pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff)); } - + pDevExt->fcScsiQue.producer = ndx; // increment Que @@ -967,16 +926,8 @@ void cpqfcTSPutScsiQue( CPQFCHBA *cpqfcH */ } - - - - - - static void ProcessELS_Request( CPQFCHBA*,TachFCHDR_GCMND*); - static void ProcessELS_Reply( CPQFCHBA*,TachFCHDR_GCMND*); - static void ProcessFCS_Reply( CPQFCHBA*,TachFCHDR_GCMND*); void cpqfcTSImplicitLogout( CPQFCHBA* cpqfcHBAdata, @@ -987,17 +938,17 @@ void cpqfcTSImplicitLogout( CPQFCHBA* cp if( pFcPort->port_id != 0xFFFC01 ) // don't care about Fabric { fcChip->fcStats.logouts++; - printk("cpqfcTS: Implicit logout of WWN %08X%08X, port_id %06X\n", + printk("cpqfcTS: Implicit logout of WWN %08X%08X, port_id %06X\n", (ULONG)pFcPort->u.liWWN, (ULONG)(pFcPort->u.liWWN >>32), pFcPort->port_id); // Terminate I/O with this (Linux) Scsi target - cpqfcTSTerminateExchange( cpqfcHBAdata, + cpqfcTSTerminateExchange( cpqfcHBAdata, &pFcPort->ScsiNexus, DEVICE_REMOVED); } - + // Do an "implicit logout" - we can't really Logout the device // (i.e. with LOGOut Request) because of port_id confusion // (i.e. the Other port has no port_id). @@ -1009,12 +960,11 @@ void cpqfcTSImplicitLogout( CPQFCHBA* cp pFcPort->flogi = FALSE; pFcPort->LOGO_timer = 0; pFcPort->device_blocked = TRUE; // block Scsi Requests - pFcPort->ScsiNexus.VolumeSetAddressing=0; + pFcPort->ScsiNexus.VolumeSetAddressing=0; } - // On FC-AL, there is a chance that a previously known device can -// be quietly removed (e.g. with non-managed hub), +// be quietly removed (e.g. with non-managed hub), // while a NEW device (with different WWN) took the same alpa or // even 24-bit port_id. This chance is unlikely but we must always // check for it. @@ -1024,35 +974,30 @@ static void TestDuplicatePortId( CPQFCHB PTACHYON fcChip = &cpqfcHBAdata->fcChip; // set "other port" at beginning of fcPorts list PFC_LOGGEDIN_PORT pOtherPortWithPortId = fcChip->fcPorts.pNextPort; - while( pOtherPortWithPortId ) + while( pOtherPortWithPortId ) { - if( (pOtherPortWithPortId->port_id == - pLoggedInPort->port_id) + if( (pOtherPortWithPortId->port_id == + pLoggedInPort->port_id) && (pOtherPortWithPortId != pLoggedInPort) ) { // trouble! (Implicitly) Log the other guy out - printk(" *port_id %Xh is duplicated!* ", + printk(" *port_id %Xh is duplicated!* ", pOtherPortWithPortId->port_id); - cpqfcTSImplicitLogout( cpqfcHBAdata, pOtherPortWithPortId); + cpqfcTSImplicitLogout( cpqfcHBAdata, pOtherPortWithPortId); } pOtherPortWithPortId = pOtherPortWithPortId->pNextPort; } } - - - - - // Dynamic Memory Allocation for newly discovered FC Ports. // For simplicity, maintain fcPorts structs for ALL // for discovered devices, including those we never do I/O with // (e.g. Fabric addresses) -static PFC_LOGGEDIN_PORT CreateFcPort( - CPQFCHBA* cpqfcHBAdata, - PFC_LOGGEDIN_PORT pLastLoggedInPort, +static PFC_LOGGEDIN_PORT CreateFcPort( + CPQFCHBA* cpqfcHBAdata, + PFC_LOGGEDIN_PORT pLastLoggedInPort, TachFCHDR_GCMND* fchs, LOGIN_PAYLOAD* plogi) { @@ -1060,32 +1005,28 @@ static PFC_LOGGEDIN_PORT CreateFcPort( PFC_LOGGEDIN_PORT pNextLoggedInPort = NULL; int i; - printk("cpqfcTS: New FC port %06Xh WWN: ", fchs->s_id); for( i=3; i>=0; i--) // copy the LOGIN port's WWN printk("%02X", plogi->port_name[i]); for( i=7; i>3; i--) // copy the LOGIN port's WWN printk("%02X", plogi->port_name[i]); - // allocate mem for new port // (these are small and rare allocations...) - pNextLoggedInPort = kmalloc( sizeof( FC_LOGGEDIN_PORT), GFP_ATOMIC ); + pNextLoggedInPort = kmalloc( sizeof(FC_LOGGEDIN_PORT), GFP_ATOMIC ); - // allocation succeeded? Fill out NEW PORT if( pNextLoggedInPort ) - { + { // clear out any garbage (sometimes exists) - memset( pNextLoggedInPort, 0, sizeof( FC_LOGGEDIN_PORT)); - + memset(pNextLoggedInPort, 0, sizeof(FC_LOGGEDIN_PORT)); // If we login to a Fabric, we don't want to treat it // as a SCSI device... if( (fchs->s_id & 0xFFF000) != 0xFFF000) { int i; - + // create a unique "virtual" SCSI Nexus (for now, just a // new target ID) -- we will update channel/target on REPORT_LUNS // special case for very first SCSI target... @@ -1100,21 +1041,21 @@ static PFC_LOGGEDIN_PORT CreateFcPort( cpqfcHBAdata->HostAdapter->max_id; } - // initialize the lun[] Nexus struct for lun masking + // initialize the lun[] Nexus struct for lun masking for( i=0; i< CPQFCTS_MAX_LUN; i++) pNextLoggedInPort->ScsiNexus.lun[i] = 0xFF; // init to NOT USED - + pNextLoggedInPort->ScsiNexus.channel = 0; // cpqfcTS has 1 FC port - - printk(" SCSI Chan/Trgt %d/%d", + + printk(" SCSI Chan/Trgt %d/%d", pNextLoggedInPort->ScsiNexus.channel, pNextLoggedInPort->ScsiNexus.target); - + // tell Scsi layers about the new target... - cpqfcHBAdata->HostAdapter->max_id++; + cpqfcHBAdata->HostAdapter->max_id++; // printk("HostAdapter->max_id = %d\n", -// cpqfcHBAdata->HostAdapter->max_id); - } +// cpqfcHBAdata->HostAdapter->max_id); + } else { // device is NOT SCSI (in case of Fabric) @@ -1125,12 +1066,10 @@ static PFC_LOGGEDIN_PORT CreateFcPort( pLastLoggedInPort->pNextPort = pNextLoggedInPort; printk("\n"); - } + } return pNextLoggedInPort; // NULL on allocation failure } // end NEW PORT (WWN) logic - - // For certain cases, we want to terminate exchanges without // sending ABTS to the device. Examples include when an FC // device changed it's port_id after Loop re-init, or when @@ -1141,7 +1080,7 @@ static PFC_LOGGEDIN_PORT CreateFcPort( // Since we must ensure that Tachyon is not operating on the // exchange, we have to freeze the chip // sterminateex -void cpqfcTSTerminateExchange( +void cpqfcTSTerminateExchange( CPQFCHBA* cpqfcHBAdata, SCSI_NEXUS *ScsiNexus, int TerminateStatus) { PTACHYON fcChip = &cpqfcHBAdata->fcChip; @@ -1152,9 +1091,8 @@ void cpqfcTSTerminateExchange( { // printk("TerminateExchange: ScsiNexus chan/target %d/%d\n", // ScsiNexus->channel, ScsiNexus->target); + } - } - for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) { if( Exchanges->fcExchange[x_ID].type ) // in use? @@ -1162,16 +1100,16 @@ void cpqfcTSTerminateExchange( if( ScsiNexus == NULL ) // our HBA changed - term. all { Exchanges->fcExchange[x_ID].status = TerminateStatus; - cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, NULL, x_ID); + cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, NULL, x_ID); } else { // If a device, according to WWN, has been removed, it's // port_id may be used by another working device, so we // have to terminate by SCSI target, NOT port_id. if( Exchanges->fcExchange[x_ID].Cmnd) // Cmnd in progress? - { + { if( (Exchanges->fcExchange[x_ID].Cmnd->device->id == ScsiNexus->target) && - (Exchanges->fcExchange[x_ID].Cmnd->device->channel == ScsiNexus->channel)) + (Exchanges->fcExchange[x_ID].Cmnd->device->channel == ScsiNexus->channel)) { Exchanges->fcExchange[x_ID].status = TerminateStatus; cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, NULL, x_ID); /* timed-out */ @@ -1182,13 +1120,12 @@ void cpqfcTSTerminateExchange( // all SEST structures have a remote node ID at SEST DWORD 2 // if( (fcChip->SEST->u[ x_ID ].TWE.Remote_Node_ID >> 8) // == port_id) - } + } } } } - -static void ProcessELS_Request( +static void ProcessELS_Request( CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs) { PTACHYON fcChip = &cpqfcHBAdata->fcChip; @@ -1198,7 +1135,6 @@ static void ProcessELS_Request( BOOLEAN NeedReject = FALSE; ULONG ls_reject_code = 0; // default don'n know?? - // Check the incoming frame for a supported ELS type switch( fchs->pl[0] & 0xFFFF) { @@ -1208,27 +1144,26 @@ static void ProcessELS_Request( if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) // valid payload? { LOGIN_PAYLOAD logi; // FC-PH Port Login - + // PDISC payload OK. If critical login fields // (e.g. WWN) matches last login for this port_id, // we may resume any prior exchanges // with the other port - BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi)); - - pLoggedInPort = fcFindLoggedInPort( - fcChip, + + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search Scsi Nexus 0, // don't search linked list for port_id &logi.port_name[0], // search linked list for WWN &pLastLoggedInPort); // must return non-NULL; when a port_id // is not found, this pointer marks the // end of the singly linked list - + if( pLoggedInPort != NULL) // WWN found (prior login OK) - { - + { + if( (fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id) { // Yes. We were expecting PDISC? @@ -1236,9 +1171,9 @@ static void ProcessELS_Request( { // Yes; set fields accordingly. (PDISC, not Originator) SetLoginFields( pLoggedInPort, fchs, TRUE, FALSE); - - // send 'ACC' reply - cpqfcTSPutLinkQue( cpqfcHBAdata, + + // send 'ACC' reply + cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC) fchs, 0); @@ -1248,8 +1183,8 @@ static void ProcessELS_Request( { printk("Not expecting PDISC (pdisc=FALSE)\n"); NeedReject = TRUE; - // set reject reason code - ls_reject_code = + // set reject reason code + ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR); } } @@ -1261,19 +1196,18 @@ static void ProcessELS_Request( pLoggedInPort->port_id, fchs->s_id &0xFFFFFF); } NeedReject = TRUE; - // set reject reason code - ls_reject_code = + // set reject reason code + ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR); - } } else { printk("PDISC Request from unknown WWN\n"); NeedReject = TRUE; - - // set reject reason code - ls_reject_code = + + // set reject reason code + ls_reject_code = LS_RJT_REASON( LOGICAL_ERROR, INVALID_PORT_NAME); } @@ -1282,7 +1216,6 @@ static void ProcessELS_Request( { printk("payload unacceptable\n"); NeedReject = TRUE; // reject code already set - } if( NeedReject) @@ -1295,8 +1228,8 @@ static void ProcessELS_Request( pLoggedInPort->pdisc = FALSE; pLoggedInPort->prli = FALSE; pLoggedInPort->plogi = FALSE; - - cpqfcTSTerminateExchange( cpqfcHBAdata, + + cpqfcTSTerminateExchange( cpqfcHBAdata, &pLoggedInPort->ScsiNexus, PORTID_CHANGED); port_id = pLoggedInPort->port_id; } @@ -1307,10 +1240,8 @@ static void ProcessELS_Request( fchs->reserved = ls_reject_code; // borrow this (unused) field cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_RJT, fchs, 0); } - - break; - + break; case 0x0003: // PLOGI? @@ -1319,53 +1250,51 @@ static void ProcessELS_Request( { LOGIN_PAYLOAD logi; // FC-PH Port Login BOOLEAN NeedReject = FALSE; - + // PDISC payload OK. If critical login fields // (e.g. WWN) matches last login for this port_id, // we may resume any prior exchanges // with the other port - BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi)); - - pLoggedInPort = fcFindLoggedInPort( - fcChip, + + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search Scsi Nexus 0, // don't search linked list for port_id &logi.port_name[0], // search linked list for WWN &pLastLoggedInPort); // must return non-NULL; when a port_id // is not found, this pointer marks the // end of the singly linked list - + if( pLoggedInPort == NULL) // WWN not found -New Port - { - pLoggedInPort = CreateFcPort( - cpqfcHBAdata, - pLastLoggedInPort, + { + pLoggedInPort = CreateFcPort( + cpqfcHBAdata, + pLastLoggedInPort, fchs, &logi); if( pLoggedInPort == NULL ) { printk(" cpqfcTS: New port allocation failed - lost FC device!\n"); // Now Q a LOGOut Request, since we won't be talking to that device - - NeedReject = TRUE; - - // set reject reason code - ls_reject_code = + + NeedReject = TRUE; + + // set reject reason code + ls_reject_code = LS_RJT_REASON( LOGICAL_ERROR, NO_LOGIN_RESOURCES); - + } } if( !NeedReject ) { - - // OK - we have valid fcPort ptr; set fields accordingly. + // OK - we have valid fcPort ptr; set fields accordingly. // (not PDISC, not Originator) - SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE); + SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE); - // send 'ACC' reply - cpqfcTSPutLinkQue( cpqfcHBAdata, + // send 'ACC' reply + cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC) fchs, 0); } @@ -1383,41 +1312,39 @@ static void ProcessELS_Request( pLoggedInPort->pdisc = FALSE; pLoggedInPort->prli = FALSE; pLoggedInPort->plogi = FALSE; - + fchs->reserved = ls_reject_code; // borrow this (unused) field - // send 'RJT' reply + // send 'RJT' reply cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_RJT, fchs, 0); } - + // terminate any exchanges with this device... if( pLoggedInPort ) { - cpqfcTSTerminateExchange( cpqfcHBAdata, + cpqfcTSTerminateExchange( cpqfcHBAdata, &pLoggedInPort->ScsiNexus, PORTID_CHANGED); } break; - - case 0x1020: // PRLI? { BOOLEAN NeedReject = TRUE; - pLoggedInPort = fcFindLoggedInPort( - fcChip, + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search Scsi Nexus (fchs->s_id & 0xFFFFFF), // search linked list for port_id NULL, // DON'T search linked list for WWN NULL); // don't care - - if( pLoggedInPort == NULL ) + + if( pLoggedInPort == NULL ) { // huh? printk(" Unexpected PRLI Request -not logged in!\n"); - // set reject reason code + // set reject reason code ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR); - + // Q a LOGOut here? } else @@ -1426,8 +1353,8 @@ static void ProcessELS_Request( if( !verify_PRLI( fchs, &ls_reject_code) ) { // PRLI Reply is acceptable; were we expecting it? - if( pLoggedInPort->plogi ) - { + if( pLoggedInPort->plogi ) + { // yes, we expected the PRLI ACC (not PDISC; not Originator) SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE); @@ -1438,11 +1365,11 @@ static void ProcessELS_Request( // huh? printk(" (unexpected) PRLI REQEST with plogi FALSE\n"); - // set reject reason code + // set reject reason code ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR); - + // Q a LOGOut here? - + } } else @@ -1462,42 +1389,39 @@ static void ProcessELS_Request( } } break; - - - case 0x0005: // LOGOut? { // was this LOGOUT because we sent a ELS_PDISC to an FC device - // with changed (or new) port_id, or does the port refuse + // with changed (or new) port_id, or does the port refuse // to communicate to us? // We maintain a logout counter - if we get 3 consecutive LOGOuts, // give up! LOGOUT_PAYLOAD logo; BOOLEAN GiveUpOnDevice = FALSE; ULONG ls_reject_code = 0; - + BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logo, sizeof(logo)); - pLoggedInPort = fcFindLoggedInPort( - fcChip, + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search Scsi Nexus 0, // don't search linked list for port_id &logo.port_name[0], // search linked list for WWN NULL); // don't care about end of list - + if( pLoggedInPort ) // found the device? { - // Q an ACC reply + // Q an ACC reply cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_LOGO_ACC, fchs, 0); // set login struct fields (LOGO_counter increment) SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE); - + // are we an Initiator? - if( fcChip->Options.initiator) + if( fcChip->Options.initiator) { - // we're an Initiator, so check if we should + // we're an Initiator, so check if we should // try (another?) login // Fabrics routinely log out from us after @@ -1513,7 +1437,7 @@ static void ProcessELS_Request( cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_PLOGI, fchs, 0); // Terminate I/O with "retry" potential - cpqfcTSTerminateExchange( cpqfcHBAdata, + cpqfcTSTerminateExchange( cpqfcHBAdata, &pLoggedInPort->ScsiNexus, PORTID_CHANGED); } @@ -1532,11 +1456,11 @@ static void ProcessELS_Request( if( GiveUpOnDevice == TRUE ) { - cpqfcTSTerminateExchange( cpqfcHBAdata, + cpqfcTSTerminateExchange( cpqfcHBAdata, &pLoggedInPort->ScsiNexus, DEVICE_REMOVED); } - } + } else // we don't know this WWN! { // Q a ReJecT Reply with reason code @@ -1546,9 +1470,6 @@ static void ProcessELS_Request( } break; - - - // FABRIC only case case 0x0461: // ELS RSCN (Registered State Change Notification)? { @@ -1565,7 +1486,7 @@ static void ProcessELS_Request( // (Endianess!) Ports = ((fchs->pl[0] >>24) - 4) / 4; Ports = Ports > 63 ? 63 : Ports; - + printk(" RSCN ports: %d\n", Ports); if( Ports <= 0 ) // huh? { @@ -1577,52 +1498,48 @@ static void ProcessELS_Request( } else { /* Accept the command */ cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_ACC, fchs, 0); } - + // Check the "address format" to determine action. // We have 3 cases: // 0 = Port Address; 24-bit address of affected device // 1 = Area Address; MS 16 bits valid // 2 = Domain Address; MS 8 bits valid for( i=0; ipl[i+1],(UCHAR*)&Buff, 4); switch( Buff & 0xFF000000) { case 0: // Port Address? - + case 0x01000000: // Area Domain? case 0x02000000: // Domain Address - // For example, "port_id" 0x201300 + // For example, "port_id" 0x201300 // OK, let's try a Name Service Request (Query) fchs->s_id = 0xFFFFFC; // Name Server Address cpqfcTSPutLinkQue(cpqfcHBAdata, FCS_NSR, fchs, 0); break; - - + + default: // huh? new value on version change? break; } } - } - break; - - + } + break; - default: // don't support this request (yet) - // set reject reason code - fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM, + // set reject reason code + fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM, REQUEST_NOT_SUPPORTED); cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_RJT, fchs, 0); - break; + break; } } - -static void ProcessELS_Reply( +static void ProcessELS_Reply( CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs) { PTACHYON fcChip = &cpqfcHBAdata->fcChip; @@ -1630,39 +1547,37 @@ static void ProcessELS_Reply( ULONG ox_id = (fchs->ox_rx_id >>16); ULONG ls_reject_code; PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort; - + // If this is a valid reply, then we MUST have sent a request. // Verify that we can find a valid request OX_ID corresponding to // this reply - if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0) { - printk(" *Discarding ACC/RJT frame, xID %04X/%04X* ", + printk(" *Discarding ACC/RJT frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff); goto Quit; // exit this routine } - // Is the reply a RJT (reject)? if( (fchs->pl[0] & 0xFFFFL) == 0x01) // Reject reply? { // ****** REJECT REPLY ******** switch( Exchanges->fcExchange[ox_id].type ) { - + case ELS_FDISC: // we sent out Fabric Discovery case ELS_FLOGI: // we sent out FLOGI - printk("RJT received on Fabric Login from %Xh, reason %Xh\n", - fchs->s_id, fchs->pl[1]); + printk("RJT received on Fabric Login from %Xh, reason %Xh\n", + fchs->s_id, fchs->pl[1]); break; default: break; } - + goto Done; } @@ -1670,32 +1585,32 @@ static void ProcessELS_Reply( // What's the ACC type? (according to what we sent) switch( Exchanges->fcExchange[ox_id].type ) { - + case ELS_PLOGI: // we sent out PLOGI if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) { LOGIN_PAYLOAD logi; // FC-PH Port Login - + // login ACC payload acceptable; search for WWN in our list // of fcPorts - + BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi)); - - pLoggedInPort = fcFindLoggedInPort( - fcChip, + + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search Scsi Nexus 0, // don't search linked list for port_id &logi.port_name[0], // search linked list for WWN &pLastLoggedInPort); // must return non-NULL; when a port_id // is not found, this pointer marks the // end of the singly linked list - + if( pLoggedInPort == NULL) // WWN not found - new port { - pLoggedInPort = CreateFcPort( - cpqfcHBAdata, - pLastLoggedInPort, + pLoggedInPort = CreateFcPort( + cpqfcHBAdata, + pLastLoggedInPort, fchs, &logi); @@ -1703,33 +1618,33 @@ static void ProcessELS_Reply( { printk(" cpqfcTS: New port allocation failed - lost FC device!\n"); // Now Q a LOGOut Request, since we won't be talking to that device - + goto Done; // exit with error! dropped login frame } } else // WWN was already known. Ensure that any open // exchanges for this WWN are terminated. - // NOTE: It's possible that a device can change its - // 24-bit port_id after a Link init or Fabric change + // NOTE: It's possible that a device can change its + // 24-bit port_id after a Link init or Fabric change // (e.g. LIP or Fabric RSCN). In that case, the old // 24-bit port_id may be duplicated, or no longer exist. { - cpqfcTSTerminateExchange( cpqfcHBAdata, + cpqfcTSTerminateExchange( cpqfcHBAdata, &pLoggedInPort->ScsiNexus, PORTID_CHANGED); } // We have an fcPort struct - set fields accordingly - // not PDISC, originator + // not PDISC, originator SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE); - + // We just set a "port_id"; is it duplicated? TestDuplicatePortId( cpqfcHBAdata, pLoggedInPort); // For Fabric operation, we issued PLOGI to 0xFFFFFC - // so we can send SCR (State Change Registration) + // so we can send SCR (State Change Registration) // Check for this special case... - if( fchs->s_id == 0xFFFFFC ) + if( fchs->s_id == 0xFFFFFC ) { // PLOGI ACC was a Fabric response... issue SCR fchs->s_id = 0xFFFFFD; // address for SCR @@ -1749,30 +1664,29 @@ static void ProcessELS_Reply( } break; - // PDISC logic very similar to PLOGI, except we never want // to allocate mem for "new" port, and we set flags differently - // (might combine later with PLOGI logic for efficiency) + // (might combine later with PLOGI logic for efficiency) case ELS_PDISC: // we sent out PDISC if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) { LOGIN_PAYLOAD logi; // FC-PH Port Login BOOLEAN NeedLogin = FALSE; - + // login payload acceptable; search for WWN in our list // of (previously seen) fcPorts - + BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi)); - - pLoggedInPort = fcFindLoggedInPort( - fcChip, + + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search Scsi Nexus 0, // don't search linked list for port_id &logi.port_name[0], // search linked list for WWN &pLastLoggedInPort); // must return non-NULL; when a port_id // is not found, this pointer marks the // end of the singly linked list - + if( pLoggedInPort != NULL) // WWN found? { // WWN has same port_id as last login? (Of course, a properly @@ -1784,8 +1698,7 @@ static void ProcessELS_Reply( if( pLoggedInPort->pdisc ) { int i; - - + // PDISC expected -- set fields. (PDISC, Originator) SetLoginFields( pLoggedInPort, fchs, TRUE, TRUE); @@ -1795,7 +1708,7 @@ static void ProcessELS_Reply( for( i=0; i< TACH_SEST_LEN; i++) { // see if any exchange for this PDISC'd port was queued - if( ((fchs->s_id &0xFFFFFF) == + if( ((fchs->s_id &0xFFFFFF) == (Exchanges->fcExchange[i].fchs.d_id & 0xFFFFFF)) && (Exchanges->fcExchange[i].status & EXCHANGE_QUEUED)) @@ -1822,7 +1735,7 @@ static void ProcessELS_Reply( printk("PDISC PortID change: old %Xh, new %Xh\n", pLoggedInPort->port_id, fchs->s_id &0xFFFFFF); NeedLogin = TRUE; - + } } else @@ -1833,7 +1746,6 @@ static void ProcessELS_Reply( if( NeedLogin) { - // The PDISC failed. Set login struct flags accordingly, // terminate any I/O to this port, and Q a PLOGI if( pLoggedInPort ) // FC device previously known? @@ -1849,8 +1761,8 @@ static void ProcessELS_Reply( pLoggedInPort->pdisc = FALSE; pLoggedInPort->prli = FALSE; pLoggedInPort->plogi = FALSE; - - cpqfcTSTerminateExchange( cpqfcHBAdata, + + cpqfcTSTerminateExchange( cpqfcHBAdata, &pLoggedInPort->ScsiNexus, PORTID_CHANGED); } cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_PLOGI, fchs, 0); @@ -1861,24 +1773,20 @@ static void ProcessELS_Reply( // login payload unacceptable - reason in ls_reject_code // Q up a Logout Request printk("ERROR: Login Payload unacceptable!\n"); - } - - break; - + break; case ELS_PRLI: // we sent out PRLI - - pLoggedInPort = fcFindLoggedInPort( - fcChip, + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search Scsi Nexus (fchs->s_id & 0xFFFFFF), // search linked list for port_id NULL, // DON'T search linked list for WWN NULL); // don't care - - if( pLoggedInPort == NULL ) + + if( pLoggedInPort == NULL ) { // huh? printk(" Unexpected PRLI ACCept frame!\n"); @@ -1892,17 +1800,17 @@ static void ProcessELS_Reply( if( !verify_PRLI( fchs, &ls_reject_code) ) { // PRLI Reply is acceptable; were we expecting it? - if( pLoggedInPort->plogi ) - { + if( pLoggedInPort->plogi ) + { // yes, we expected the PRLI ACC (not PDISC; Originator) SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE); // OK, let's send a REPORT_LUNS command to determine // whether VSA or PDA FCP-LUN addressing is used. - + cpqfcTSPutLinkQue(cpqfcHBAdata, SCSI_REPORT_LUNS, fchs, 0); - - // It's possible that a device we were talking to changed + + // It's possible that a device we were talking to changed // port_id, and has logged back in. This function ensures // that I/O will resume. UnblockScsiDevice( cpqfcHBAdata->HostAdapter, pLoggedInPort); @@ -1925,64 +1833,54 @@ static void ProcessELS_Reply( } break; - + case ELS_FLOGI: // we sent out FLOGI (Fabric Login) // update the upper 16 bits of our port_id in Tachyon // the switch adds those upper 16 bits when responding // to us (i.e. we are the destination_id) fcChip->Registers.my_al_pa = (fchs->d_id & 0xFFFFFF); - writel( fcChip->Registers.my_al_pa, + writel( fcChip->Registers.my_al_pa, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID); // now send out a PLOGI to the well known port_id 0xFFFFFC fchs->s_id = 0xFFFFFC; cpqfcTSPutLinkQue(cpqfcHBAdata, ELS_PLOGI, fchs, 0); - break; - + break; case ELS_FDISC: // we sent out FDISC (Fabric Discovery (Login)) printk( " ELS_FDISC success "); break; - case ELS_SCR: // we sent out State Change Registration // now we can issue Name Service Request to find any // Fabric-connected devices we might want to login to. - - + fchs->s_id = 0xFFFFFC; // Name Server Address cpqfcTSPutLinkQue(cpqfcHBAdata, FCS_NSR, fchs, 0); break; - default: - printk(" *Discarding unknown ACC frame, xID %04X/%04X* ", + printk(" *Discarding unknown ACC frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff); break; } - Done: // Regardless of whether the Reply is valid or not, the // the exchange is done - complete - cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, (fchs->ox_rx_id >>16)); - -Quit: + cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, (fchs->ox_rx_id >>16)); + +Quit: return; } - - - - - // **************** Fibre Channel Services ************** // This is where we process the Directory (Name) Service Reply // to know which devices are on the Fabric -static void ProcessFCS_Reply( +static void ProcessFCS_Reply( CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs) { PTACHYON fcChip = &cpqfcHBAdata->fcChip; @@ -1990,14 +1888,14 @@ static void ProcessFCS_Reply( ULONG ox_id = (fchs->ox_rx_id >>16); // ULONG ls_reject_code; // PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort; - + // If this is a valid reply, then we MUST have sent a request. // Verify that we can find a valid request OX_ID corresponding to // this reply if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0) { - printk(" *Discarding Reply frame, xID %04X/%04X* ", + printk(" *Discarding Reply frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff); goto Quit; // exit this routine } @@ -2010,9 +1908,9 @@ static void ProcessFCS_Reply( // (Endianess Byte Swap?) if( fchs->pl[1] == 0x02FC ) // Name Service { - // got a new (or NULL) list of Fabric attach devices... + // got a new (or NULL) list of Fabric attach devices... // Invalidate current logins - + PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts; while( pLoggedInPort ) // for all ports which are expecting // PDISC after the next LIP, set the @@ -2028,95 +1926,77 @@ static void ProcessFCS_Reply( // PDISC received... pLoggedInPort->prli = FALSE; // block FCP-SCSI commands } - + pLoggedInPort = pLoggedInPort->pNextPort; } - + if( fchs->pl[2] == 0x0280) // ACCept? { // Send PLOGI or PDISC to these Fabric devices - SendLogins( cpqfcHBAdata, &fchs->pl[4] ); + SendLogins( cpqfcHBAdata, &fchs->pl[4] ); } - // As of this writing, the only reason to reject is because NO // devices are left on the Fabric. We already started // "logged out" timers; if the device(s) don't come - // back, we'll do the implicit logout in the heart beat + // back, we'll do the implicit logout in the heart beat // timer routine else // ReJecT { // this just means no Fabric device is visible at this instant - } + } } // Regardless of whether the Reply is valid or not, the // the exchange is done - complete cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, (fchs->ox_rx_id >>16)); - -Quit: + +Quit: return; } - - - - - - -static void AnalyzeIncomingFrame( +static void AnalyzeIncomingFrame( CPQFCHBA *cpqfcHBAdata, ULONG QNdx ) { PTACHYON fcChip = &cpqfcHBAdata->fcChip; FC_EXCHANGES *Exchanges = fcChip->Exchanges; PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ; - TachFCHDR_GCMND* fchs = + TachFCHDR_GCMND* fchs = (TachFCHDR_GCMND*)fcLQ->Qitem[QNdx].ulBuff; // ULONG ls_reject_code; // reason for rejecting login LONG ExchangeID; // FC_LOGGEDIN_PORT *pLoggedInPort; - BOOLEAN AbortAccept; + BOOLEAN AbortAccept; ENTER("AnalyzeIncomingFrame"); - - switch( fcLQ->Qitem[QNdx].Type) // FCP or Unknown { case SFQ_UNKNOWN: // unknown frame (e.g. LIP position frame, NOP, etc.) - // ********* FC-4 Device Data/ Fibre Channel Service ************* if( ((fchs->d_id &0xF0000000) == 0) // R_CTL (upper nibble) 0x0? - && + && (fchs->f_ctl & 0x20000000) ) // TYPE 20h is Fibre Channel Service { - // ************** FCS Reply ********************** if( (fchs->d_id & 0xff000000L) == 0x03000000L) // (31:23 R_CTL) { ProcessFCS_Reply( cpqfcHBAdata, fchs ); - } // end of FCS logic - } - - // *********** Extended Link Service ************** - else if( fchs->d_id & 0x20000000 // R_CTL 0x2? - && + && (fchs->f_ctl & 0x01000000) ) // TYPE = 1 { - // these frames are either a response to // something we sent (0x23) or "unsolicited" // frames (0x22). - // **************Extended Link REPLY ********************** // R_CTL Solicited Control Reply @@ -2127,9 +2007,6 @@ static void AnalyzeIncomingFrame( } // end of "R_CTL Solicited Control Reply" - - - // **************Extended Link REQUEST ********************** // (unsolicited commands from another port or task...) @@ -2137,19 +2014,11 @@ static void AnalyzeIncomingFrame( else if( (fchs->d_id & 0xff000000L) == 0x22000000L && (fchs->ox_rx_id != 0xFFFFFFFFL) ) // (ignore LIP frame) { - - - ProcessELS_Request( cpqfcHBAdata, fchs ); - } - - - // ************** LILP ********************** else if( (fchs->d_id & 0xff000000L) == 0x22000000L && (fchs->ox_rx_id == 0xFFFFFFFFL)) // (e.g., LIP frames) - { // SANMark specifies that when available, we must use // the LILP frame to determine which ALPAs to send Port Discovery @@ -2166,15 +2035,11 @@ static void AnalyzeIncomingFrame( } } } - - // ***************** BASIC LINK SERVICE ***************** - else if( fchs->d_id & 0x80000000 // R_CTL: && // Basic Link Service Request !(fchs->f_ctl & 0xFF000000) ) // type=0 for BLS { - // Check for ABTS (Abort Sequence) if( (fchs->d_id & 0x8F000000) == 0x81000000) { @@ -2184,11 +2049,11 @@ static void AnalyzeIncomingFrame( // Per PLDA, an ABTS is sent by an initiator; therefore // assume that if we have an exhange open to the port who - // sent ABTS, it will be the d_id of what we sent. + // sent ABTS, it will be the d_id of what we sent. for( ExchangeID = 0, AbortAccept=FALSE; ExchangeID < TACH_SEST_LEN; ExchangeID++) { - // Valid "target" exchange 24-bit port_id matches? + // Valid "target" exchange 24-bit port_id matches? // NOTE: For the case of handling Intiator AND Target // functions on the same chip, we can have TWO Exchanges // with the same OX_ID -- OX_ID/FFFF for the CMND, and @@ -2196,28 +2061,28 @@ static void AnalyzeIncomingFrame( // we would like to support ABTS from Initiators or Targets, // but it's not clear that can be supported on Tachyon for // all cases (requires more investigation). - + if( (Exchanges->fcExchange[ ExchangeID].type == SCSI_TWE || Exchanges->fcExchange[ ExchangeID].type == SCSI_TRE) && ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF)) ) { - + // target xchnge port_id matches -- how about OX_ID? if( (Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id &0xFFFF0000) == (fchs->ox_rx_id & 0xFFFF0000) ) // yes! post ACCept response; will be completed by fcStart { Exchanges->fcExchange[ ExchangeID].status = TARGET_ABORT; - + // copy (add) rx_id field for simplified ACCept reply - fchs->ox_rx_id = + fchs->ox_rx_id = Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id; - + cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS_ACC, fchs, 0); AbortAccept = TRUE; - printk("ACCepting ABTS for x_ID %8.8Xh, SEST pair %8.8Xh\n", + printk("ACCepting ABTS for x_ID %8.8Xh, SEST pair %8.8Xh\n", fchs->ox_rx_id, Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id); break; // ABTS can affect only ONE exchange -exit loop } @@ -2225,9 +2090,9 @@ static void AnalyzeIncomingFrame( } // end of FOR loop if( !AbortAccept ) // can't ACCept ABTS - send Reject { - printk("ReJecTing: can't find ExchangeID %8.8Xh for ABTS command\n", + printk("ReJecTing: can't find ExchangeID %8.8Xh for ABTS command\n", fchs->ox_rx_id); - if( Exchanges->fcExchange[ ExchangeID].type + if( Exchanges->fcExchange[ ExchangeID].type && !(fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len & 0x80000000)) @@ -2236,38 +2101,34 @@ static void AnalyzeIncomingFrame( } else { - printk("Unexpected ABTS ReJecT! SEST[%X] Dword 0: %Xh\n", + printk("Unexpected ABTS ReJecT! SEST[%X] Dword 0: %Xh\n", ExchangeID, fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len); } } } - // Check for BLS {ABTS? (Abort Sequence)} ACCept else if( (fchs->d_id & 0x8F000000) == 0x84000000) { // target has responded with ACC for our ABTS; - // complete the indicated exchange with ABORTED status + // complete the indicated exchange with ABORTED status // Make no checks for correct RX_ID, since // all we need to conform ABTS ACC is the OX_ID. // Verify that the d_id matches! - + ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF; // x_id from ACC -// printk("ABTS ACC x_ID 0x%04X 0x%04X, status %Xh\n", +// printk("ABTS ACC x_ID 0x%04X 0x%04X, status %Xh\n", // fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff, // Exchanges->fcExchange[ExchangeID].status); - - if( ExchangeID < TACH_SEST_LEN ) // x_ID makes sense { - // Does "target" exchange 24-bit port_id match? + // Does "target" exchange 24-bit port_id match? // (See "NOTE" above for handling Intiator AND Target in // the same device driver) // First, if this is a target response, then we originated // (initiated) it with BLS_ABTS: - - if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS) + if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS) && // Second, does the source of this ACC match the destination // of who we originally sent it to? @@ -2276,50 +2137,49 @@ static void AnalyzeIncomingFrame( { cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID ); } - } + } } // Check for BLS {ABTS? (Abort Sequence)} ReJecT else if( (fchs->d_id & 0x8F000000) == 0x85000000) { // target has responded with RJT for our ABTS; - // complete the indicated exchange with ABORTED status + // complete the indicated exchange with ABORTED status // Make no checks for correct RX_ID, since // all we need to conform ABTS ACC is the OX_ID. // Verify that the d_id matches! - + ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF; // x_id from ACC -// printk("BLS_ABTS RJT on Exchange 0x%04X 0x%04X\n", +// printk("BLS_ABTS RJT on Exchange 0x%04X 0x%04X\n", // fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff); if( ExchangeID < TACH_SEST_LEN ) // x_ID makes sense - { - // Does "target" exchange 24-bit port_id match? + { + // Does "target" exchange 24-bit port_id match? // (See "NOTE" above for handling Intiator AND Target in // the same device driver) // First, if this is a target response, then we originated // (initiated) it with BLS_ABTS: - - if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS) + if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS) && // Second, does the source of this ACC match the destination // of who we originally sent it to? ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF)) ) { - // YES! NOTE: There is a bug in CPQ's RA-4000 box + // YES! NOTE: There is a bug in CPQ's RA-4000 box // where the "reason code" isn't returned in the payload // For now, simply presume the reject is because the target // already completed the exchange... - + // printk("complete x_ID %Xh on ABTS RJT\n", ExchangeID); cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID ); } - } + } } // end of ABTS check } // end of Basic Link Service Request break; - + default: printk("AnalyzeIncomingFrame: unknown type: %Xh(%d)\n", fcLQ->Qitem[QNdx].Type, @@ -2328,8 +2188,7 @@ static void AnalyzeIncomingFrame( } } - -// Function for Port Discovery necessary after every FC +// Function for Port Discovery necessary after every FC // initialization (e.g. LIP). // Also may be called if from Fabric Name Service logic. @@ -2350,13 +2209,13 @@ static void SendLogins( CPQFCHBA *cpqfcH // is the same as the number of alpa on a private loop (126 devices). // (Of course this could be changed to support however many we have // memory for). - memset( &PortIds[0], 0, sizeof(PortIds)); - + memset(&PortIds[0], 0, sizeof(PortIds)); + // First, check if this login is for our own Link Initialization // (e.g. LIP on FC-AL), or if we have knowledge of Fabric devices // from a switch. If we are logging into Fabric devices, we'll // have a non-NULL FabricPortId pointer - + if( FabricPortIds != NULL) // may need logins { int LastPort=FALSE; @@ -2365,17 +2224,17 @@ static void SendLogins( CPQFCHBA *cpqfcH { // port IDs From NSR payload; byte swap needed? BigEndianSwap( (UCHAR*)FabricPortIds, (UCHAR*)&PortIds[i], 4); - + // printk("FPortId[%d] %Xh ", i, PortIds[i]); if( PortIds[i] & 0x80000000) LastPort = TRUE; - + PortIds[i] &= 0xFFFFFF; // get 24-bit port_id // some non-Fabric devices (like the Crossroads Fibre/Scsi bridge) // erroneously use ALPA 0. if( PortIds[i] ) // need non-zero port_id... i++; - + if( i >= number_of_al_pa ) // (in)sanity check break; FabricPortIds++; // next... @@ -2384,17 +2243,16 @@ static void SendLogins( CPQFCHBA *cpqfcH NumberOfPorts = i; // printk("NumberOf Fabric ports %d", NumberOfPorts); } - else // need to send logins on our "local" link { - + // are we a loop port? If so, check for reception of LILP frame, // and if received use it (SANMark requirement) if( fcChip->Options.LILPin ) { int j=0; // sanity check on number of ALPAs from LILP frame... - // For format of LILP frame, see FC-AL specs or + // For format of LILP frame, see FC-AL specs or // "Fibre Channel Bench Reference", J. Stai, 1995 (ISBN 1-879936-17-8) // First byte is number of ALPAs i = fcChip->LILPmap[0] >= (32*4) ? 32*4 : fcChip->LILPmap[0]; @@ -2419,27 +2277,25 @@ static void SendLogins( CPQFCHBA *cpqfcH } } - // Now we have a copy of the port_ids (and how many)... for( i = 0; i < NumberOfPorts; i++) { // 24-bit FC Port ID fchs.s_id = PortIds[i]; // note: only 8-bits used for ALPA - // don't log into ourselves (Linux Scsi disk scan will stop on // no TARGET support error on us, and quit trying for rest of devices) if( (fchs.s_id & 0xFF ) == (fcChip->Registers.my_al_pa & 0xFF) ) continue; // fabric login needed? - if( (fchs.s_id == 0) || + if( (fchs.s_id == 0) || (fcChip->Options.fabric == 1) ) { fcChip->Options.flogi = 1; // fabric needs longer for login // Do we need FLOGI or FDISC? - pLoggedInPort = fcFindLoggedInPort( - fcChip, + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search SCSI Nexus 0xFFFFFC, // search linked list for Fabric port_id NULL, // don't search WWN @@ -2457,8 +2313,7 @@ static void SendLogins( CPQFCHBA *cpqfcH loginType = ELS_FLOGI; // expired FLOGI } else // first FLOGI? - loginType = ELS_FLOGI; - + loginType = ELS_FLOGI; fchs.s_id = 0xFFFFFE; // well known F_Port address @@ -2473,35 +2328,32 @@ static void SendLogins( CPQFCHBA *cpqfcH // Trick Tachyon to send to ALPA 0 (see TL/TS UG, pg 87) // If our ALPA is 55h for instance, we want the FC frame // s_id to be 0x000055, while Tach's my_al_pa register - // must be 0x000155, to force an OPN at ALPA 0 + // must be 0x000155, to force an OPN at ALPA 0 // (the Fabric port) fcChip->Registers.my_al_pa &= 0xFF; // only use ALPA for FLOGI - writel( fcChip->Registers.my_al_pa | 0x0100, + writel( fcChip->Registers.my_al_pa | 0x0100, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID); } - else // not FLOGI... { // should we send PLOGI or PDISC? Check if any prior port_id - // (e.g. alpa) completed a PLOGI/PRLI exchange by checking + // (e.g. alpa) completed a PLOGI/PRLI exchange by checking // the pdisc flag. - pLoggedInPort = fcFindLoggedInPort( - fcChip, + pLoggedInPort = fcFindLoggedInPort( + fcChip, NULL, // don't search SCSI Nexus fchs.s_id, // search linked list for al_pa NULL, // don't search WWN NULL); // (don't care about end of list) - - if( pLoggedInPort ) // If found, we have prior experience with // this port -- check whether PDISC is needed { if( pLoggedInPort->pdisc ) { loginType = ELS_PDISC; // prior PLOGI and PRLI maybe still valid - + } else loginType = ELS_PLOGI; // prior knowledge, but can't use PDISC @@ -2510,8 +2362,6 @@ static void SendLogins( CPQFCHBA *cpqfcH loginType = ELS_PLOGI; // prior knowledge, but can't use PDISC } - - ulStatus = cpqfcTSBuildExchange( cpqfcHBAdata, loginType, // e.g. PLOGI @@ -2541,11 +2391,11 @@ static void SendLogins( CPQFCHBA *cpqfcH // (this happens 99.9999....% of the time). // If we revalidate a SEST write, and write data goes to a // target that is NOT the one we originated the WRITE to, - // that target is required (FCP-SCSI specs, etc) to discard + // that target is required (FCP-SCSI specs, etc) to discard // our WRITE data. // Re-validate SEST entries (Tachyon hardware assists) - RevalidateSEST( cpqfcHBAdata->HostAdapter, pLoggedInPort); + RevalidateSEST( cpqfcHBAdata->HostAdapter, pLoggedInPort); //TriggerHBA( fcChip->Registers.ReMapMemBase, 1); } } @@ -2557,7 +2407,6 @@ static void SendLogins( CPQFCHBA *cpqfcH break; } - if( fcChip->Registers.FMstatus.value & 0x080 ) // LDn during Port Disc. { ulStatus = LNKDWN_OSLS; @@ -2572,8 +2421,8 @@ static void SendLogins( CPQFCHBA *cpqfcH // exchange, so check type first (type = 0 on complete). if( Exchanges->fcExchange[ExchangeID].status ) { -#ifdef LOGIN_DBG - printk("completing x_ID %X on status %Xh\n", +#ifdef LOGIN_DBG + printk("completing x_ID %X on status %Xh\n", ExchangeID, Exchanges->fcExchange[ExchangeID].status); #endif cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID); @@ -2595,11 +2444,10 @@ static void SendLogins( CPQFCHBA *cpqfcH #endif cpqfcHBAdata->PortDiscDone = 1; - // TL/TS UG, pg. 184 // 0x0065 = 100ms for RT_TOV // 0x01f5 = 500ms for ED_TOV - fcChip->Registers.ed_tov.value = 0x006501f5L; + fcChip->Registers.ed_tov.value = 0x006501f5L; writel( fcChip->Registers.ed_tov.value, (fcChip->Registers.ed_tov.address)); @@ -2608,14 +2456,12 @@ static void SendLogins( CPQFCHBA *cpqfcH } else { - printk("SendLogins: failed at xchng %Xh, alpa %Xh, status %Xh\n", + printk("SendLogins: failed at xchng %Xh, alpa %Xh, status %Xh\n", ExchangeID, fchs.s_id, ulStatus); } LEAVE("SendLogins"); - } - // for REPORT_LUNS documentation, see "In-Depth Exploration of Scsi", // D. Deming, 1994, pg 7-19 (ISBN 1-879936-08-9) static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd) @@ -2624,7 +2470,7 @@ static void ScsiReportLunsDone(Scsi_Cmnd CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; PTACHYON fcChip = &cpqfcHBAdata->fcChip; FC_EXCHANGES *Exchanges = fcChip->Exchanges; - PFC_LOGGEDIN_PORT pLoggedInPort; + PFC_LOGGEDIN_PORT pLoggedInPort; int LunListLen=0; int i; ULONG x_ID = 0xFFFFFFFF; @@ -2639,7 +2485,6 @@ static void ScsiReportLunsDone(Scsi_Cmnd if( Exchanges->fcExchange[i].type // exchange defined? && (Exchanges->fcExchange[i].Cmnd == Cmnd) ) // matches? - { x_ID = i; // found exchange! break; @@ -2648,23 +2493,22 @@ static void ScsiReportLunsDone(Scsi_Cmnd if( x_ID == 0xFFFFFFFF) { // printk("cpqfcTS: ReportLuns failed - no FC Exchange\n"); - goto Done; // Report Luns FC Exchange gone; + goto Done; // Report Luns FC Exchange gone; // exchange probably Terminated by Implicit logout } - // search linked list for the port_id we sent INQUIRY to pLoggedInPort = fcFindLoggedInPort( fcChip, NULL, // DON'T search Scsi Nexus (we will set it) - Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF, + Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF, NULL, // DON'T search linked list for FC WWN NULL); // DON'T care about end of list - + if( !pLoggedInPort ) { // printk("cpqfcTS: ReportLuns failed - device gone\n"); goto Done; // error! can't find logged in Port - } + } LunListLen = ucBuff[3]; LunListLen += ucBuff[2]>>8; @@ -2680,44 +2524,44 @@ static void ScsiReportLunsDone(Scsi_Cmnd // did we fail because of "check condition, device reset?" // e.g. the device was reset (i.e., at every power up) // retry the Report Luns - + // who are we sending it to? // we know this because we have a copy of the command // frame from the original Report Lun command - // switch the d_id/s_id fields, because the Exchange Build // context is "reply to source". - + fchs->s_id = fchs->d_id; // (temporarily re-use the struct) cpqfcTSPutLinkQue(cpqfcHBAdata, SCSI_REPORT_LUNS, fchs, 0); } } else // probably, the device doesn't support Report Luns - pLoggedInPort->ScsiNexus.VolumeSetAddressing = 0; + pLoggedInPort->ScsiNexus.VolumeSetAddressing = 0; } else // we have LUN info - check VSA mode { // for now, assume all LUNs will have same addr mode // for VSA, payload byte 8 will be 0x40; otherwise, 0 - pLoggedInPort->ScsiNexus.VolumeSetAddressing = ucBuff[8]; - + pLoggedInPort->ScsiNexus.VolumeSetAddressing = ucBuff[8]; + // Since we got a Report Luns answer, set lun masking flag pLoggedInPort->ScsiNexus.LunMasking = 1; if( LunListLen > 8*CPQFCTS_MAX_LUN) // We expect CPQFCTS_MAX_LUN max LunListLen = 8*CPQFCTS_MAX_LUN; -/* - printk("Device WWN %08X%08X Reports Luns @: ", - (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF), +/* + printk("Device WWN %08X%08X Reports Luns @: ", + (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF), (ULONG)(pLoggedInPort->u.liWWN>>32)); - + for( i=8; iScsiNexus.lun[j] != ucBuff[i+1] ) { // something changed from the last Report Luns printk(" cpqfcTS: Report Lun change!\n"); - for( k=0, FreeLunIndex=CPQFCTS_MAX_LUN; + for( k=0, FreeLunIndex=CPQFCTS_MAX_LUN; k < CPQFCTS_MAX_LUN; k++) { if( pLoggedInPort->ScsiNexus.lun[k] == 0xFF) @@ -2785,7 +2629,6 @@ static void ScsiReportLunsDone(Scsi_Cmnd { pLoggedInPort->ScsiNexus.lun[k] = ucBuff[i+1]; // printk("add [%d]->%02d\n", k, pLoggedInPort->ScsiNexus.lun[k]); - } else { @@ -2822,18 +2665,18 @@ Done: ; extern int is_private_data_of_cpqfc(CPQFCHBA *hba, void * pointer); extern void cpqfc_free_private_data(CPQFCHBA *hba, cpqfc_passthru_private_t *data); -static void +static void call_scsi_done(Scsi_Cmnd *Cmnd) { CPQFCHBA *hba; hba = (CPQFCHBA *) Cmnd->device->host->hostdata; // Was this command a cpqfc passthru ioctl ? - if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL && + if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL && Cmnd->device->host->hostdata != NULL && is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->device->host->hostdata, Cmnd->sc_request->upper_private_data)) { - cpqfc_free_private_data(hba, - Cmnd->sc_request->upper_private_data); + cpqfc_free_private_data(hba, + Cmnd->sc_request->upper_private_data); Cmnd->sc_request->upper_private_data = NULL; Cmnd->result &= 0xff00ffff; Cmnd->result |= (DID_PASSTHROUGH << 16); // prevents retry @@ -2846,17 +2689,17 @@ call_scsi_done(Scsi_Cmnd *Cmnd) // FC port, we want to Discover the LUNs so that we know the // addressing type (e.g., FCP-SCSI Volume Set Address, Peripheral // Unit Device), and whether SSP (Selective Storage Presentation or -// Lun Masking) has made the LUN numbers non-zero based or +// Lun Masking) has made the LUN numbers non-zero based or // non-contiguous. To remain backward compatible with the SCSI-2 // driver model, which expects a contiguous LUNs starting at 0, -// will use the ReportLuns info to map from "device" to "Linux" +// will use the ReportLuns info to map from "device" to "Linux" // LUNs. -static void IssueReportLunsCommand( - CPQFCHBA* cpqfcHBAdata, +static void IssueReportLunsCommand( + CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs) { PTACHYON fcChip = &cpqfcHBAdata->fcChip; - PFC_LOGGEDIN_PORT pLoggedInPort; + PFC_LOGGEDIN_PORT pLoggedInPort; struct scsi_cmnd *Cmnd = NULL; struct scsi_device *ScsiDev = NULL; LONG x_ID; @@ -2871,35 +2714,32 @@ static void IssueReportLunsCommand( // find the device (from port_id) we're talking to pLoggedInPort = fcFindLoggedInPort( fcChip, - NULL, // DON'T search Scsi Nexus - fchs->s_id & 0xFFFFFF, + NULL, // DON'T search Scsi Nexus + fchs->s_id & 0xFFFFFF, NULL, // DON'T search linked list for FC WWN NULL); // DON'T care about end of list if( pLoggedInPort ) // we'd BETTER find it! { - - if( !(pLoggedInPort->fcp_info & TARGET_FUNCTION) ) goto Done; // forget it - FC device not a "target" - ScsiDev = scsi_get_host_dev (cpqfcHBAdata->HostAdapter); if (!ScsiDev) goto Done; - + Cmnd = scsi_get_command (ScsiDev, GFP_KERNEL); - if (!Cmnd) + if (!Cmnd) goto Done; ucBuff = pLoggedInPort->ReportLunsPayload; - - memset( ucBuff, 0, REPORT_LUNS_PL); - + + memset(ucBuff, 0, REPORT_LUNS_PL); + Cmnd->scsi_done = ScsiReportLunsDone; - Cmnd->request_buffer = pLoggedInPort->ReportLunsPayload; - Cmnd->request_bufflen = REPORT_LUNS_PL; - + Cmnd->request_buffer = pLoggedInPort->ReportLunsPayload; + Cmnd->request_bufflen = REPORT_LUNS_PL; + Cmnd->cmnd[0] = 0xA0; Cmnd->cmnd[8] = REPORT_LUNS_PL >> 8; Cmnd->cmnd[9] = (UCHAR)REPORT_LUNS_PL; @@ -2908,10 +2748,9 @@ static void IssueReportLunsCommand( Cmnd->device->channel = pLoggedInPort->ScsiNexus.channel; Cmnd->device->id = pLoggedInPort->ScsiNexus.target; - ulStatus = cpqfcTSBuildExchange( cpqfcHBAdata, - SCSI_IRE, + SCSI_IRE, fchs, Cmnd, // buffer for Report Lun data &x_ID );// fcController->fcExchanges index, -1 if failed @@ -2929,10 +2768,9 @@ static void IssueReportLunsCommand( // check reason for Exchange not being started - we might // want to Queue and start later, or fail with error { - + } } - else // Xchange setup failed... printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus ); } @@ -2942,22 +2780,14 @@ static void IssueReportLunsCommand( fchs->s_id & 0xFFFFFF); } - - Done: if (Cmnd) scsi_put_command (Cmnd); - if (ScsiDev) + if (ScsiDev) scsi_free_host_dev (ScsiDev); } - - - - - - static void CompleteBoardLockCmnd( CPQFCHBA *cpqfcHBAdata) { int i; @@ -2975,11 +2805,6 @@ static void CompleteBoardLockCmnd( CPQFC } } - - - - - // runs every 1 second for FC exchange timeouts and implicit FC device logouts void cpqfcTSheartbeat( unsigned long ptr ) @@ -2987,32 +2812,30 @@ void cpqfcTSheartbeat( unsigned long ptr CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)ptr; PTACHYON fcChip = &cpqfcHBAdata->fcChip; FC_EXCHANGES *Exchanges = fcChip->Exchanges; - PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts; + PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts; ULONG i; unsigned long flags; DECLARE_MUTEX_LOCKED(BoardLock); - + PCI_TRACE( 0xA8) if( cpqfcHBAdata->BoardLock) // Worker Task Running? goto Skip; // STOP _que function - spin_lock_irqsave( cpqfcHBAdata->HostAdapter->host_lock, flags); + spin_lock_irqsave( cpqfcHBAdata->HostAdapter->host_lock, flags); PCI_TRACE( 0xA8) - cpqfcHBAdata->BoardLock = &BoardLock; // stop Linux SCSI command queuing - + // release the IO lock (and re-enable interrupts) spin_unlock_irqrestore( cpqfcHBAdata->HostAdapter->host_lock, flags); - - // Ensure no contention from _quecommand or Worker process + + // Ensure no contention from _quecommand or Worker process CPQ_SPINLOCK_HBA( cpqfcHBAdata) - + PCI_TRACE( 0xA8) - disable_irq( cpqfcHBAdata->HostAdapter->irq); // our IRQ @@ -3035,7 +2858,6 @@ void cpqfcTSheartbeat( unsigned long ptr break; } - // logged in ports -- re-login check (ports required to verify login with // PDISC after LIP within 2 secs) @@ -3052,14 +2874,14 @@ void cpqfcTSheartbeat( unsigned long ptr { // LOGOUT time! Per PLDA, PDISC hasn't complete in 2 secs, so // issue LOGO request and destroy all I/O with other FC port(s). - -/* + +/* printk(" ~cpqfcTS heartbeat: LOGOut!~ "); - printk("Linux SCSI Chanl/Target %d/%d (port_id %06Xh) WWN %08X%08X\n", - pLoggedInPort->ScsiNexus.channel, - pLoggedInPort->ScsiNexus.target, + printk("Linux SCSI Chanl/Target %d/%d (port_id %06Xh) WWN %08X%08X\n", + pLoggedInPort->ScsiNexus.channel, + pLoggedInPort->ScsiNexus.target, pLoggedInPort->port_id, - (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF), + (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF), (ULONG)(pLoggedInPort->u.liWWN>>32)); */ @@ -3071,12 +2893,8 @@ void cpqfcTSheartbeat( unsigned long ptr pLoggedInPort = pLoggedInPort->pNextPort; } - - - - // ************ FC EXCHANGE TIMEOUT CHECK ************** - + for( i=0; i< TACH_MAX_XID; i++) { if( Exchanges->fcExchange[i].type ) // exchange defined? @@ -3091,15 +2909,14 @@ void cpqfcTSheartbeat( unsigned long ptr { cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, i); // Don't "abort" LinkService } - else // SEST Exchange TO -- may post ABTS to Worker Thread Que { // (Make sure we don't keep timing it out; let other functions // complete it or set the timeOut as needed) Exchanges->fcExchange[i].timeOut = 30000; // seconds default - if( Exchanges->fcExchange[i].type - & + if( Exchanges->fcExchange[i].type + & (BLS_ABTS | BLS_ABTS_ACC ) ) { // For BLS_ABTS*, an upper level might still have @@ -3111,8 +2928,8 @@ void cpqfcTSheartbeat( unsigned long ptr // comes later to that same LBA. Therefore, we must // ensure that the target verifies receipt of ABTS for // the exchange - - printk("~TO Q'd ABTS (x_ID %Xh)~ ", i); + + printk("~TO Q'd ABTS (x_ID %Xh)~ ", i); // TriggerHBA( fcChip->Registers.ReMapMemBase); // On timeout of a ABTS exchange, check to @@ -3137,8 +2954,8 @@ void cpqfcTSheartbeat( unsigned long ptr } } else // not an ABTS - { - + { + // We expect the WorkerThread to change the xchng type to // abort and set appropriate timeout. cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, NULL, i); /* timed-out */ @@ -3153,9 +2970,7 @@ void cpqfcTSheartbeat( unsigned long ptr } } - enable_irq( cpqfcHBAdata->HostAdapter->irq); - CPQ_SPINUNLOCK_HBA( cpqfcHBAdata) @@ -3164,58 +2979,54 @@ void cpqfcTSheartbeat( unsigned long ptr // Now, complete any Cmnd we Q'd up while BoardLock was held CompleteBoardLockCmnd( cpqfcHBAdata); - // restart the timer to run again (1 sec later) Skip: mod_timer( &cpqfcHBAdata->cpqfcTStimer, jiffies + HZ); - + PCI_TRACEO( i, 0xA8) return; } - // put valid FC-AL physical address in spec order static const UCHAR valid_al_pa[]={ - 0xef, 0xe8, 0xe4, 0xe2, - 0xe1, 0xE0, 0xDC, 0xDA, - 0xD9, 0xD6, 0xD5, 0xD4, - 0xD3, 0xD2, 0xD1, 0xCe, - 0xCd, 0xCc, 0xCb, 0xCa, - 0xC9, 0xC7, 0xC6, 0xC5, + 0xef, 0xe8, 0xe4, 0xe2, + 0xe1, 0xE0, 0xDC, 0xDA, + 0xD9, 0xD6, 0xD5, 0xD4, + 0xD3, 0xD2, 0xD1, 0xCe, + 0xCd, 0xCc, 0xCb, 0xCa, + 0xC9, 0xC7, 0xC6, 0xC5, 0xC3, 0xBc, 0xBa, 0xB9, - 0xB6, 0xB5, 0xB4, 0xB3, + 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xae, 0xad, - 0xAc, 0xAb, 0xAa, 0xA9, + 0xAc, 0xAb, 0xAa, 0xA9, - 0xA7, 0xA6, 0xA5, 0xA3, - 0x9f, 0x9e, 0x9d, 0x9b, - 0x98, 0x97, 0x90, 0x8f, - 0x88, 0x84, 0x82, 0x81, - 0x80, 0x7c, 0x7a, 0x79, - 0x76, 0x75, 0x74, 0x73, - 0x72, 0x71, 0x6e, 0x6d, - 0x6c, 0x6b, 0x6a, 0x69, - 0x67, 0x66, 0x65, 0x63, - 0x5c, 0x5a, 0x59, 0x56, - - 0x55, 0x54, 0x53, 0x52, - 0x51, 0x4e, 0x4d, 0x4c, - 0x4b, 0x4a, 0x49, 0x47, + 0xA7, 0xA6, 0xA5, 0xA3, + 0x9f, 0x9e, 0x9d, 0x9b, + 0x98, 0x97, 0x90, 0x8f, + 0x88, 0x84, 0x82, 0x81, + 0x80, 0x7c, 0x7a, 0x79, + 0x76, 0x75, 0x74, 0x73, + 0x72, 0x71, 0x6e, 0x6d, + 0x6c, 0x6b, 0x6a, 0x69, + 0x67, 0x66, 0x65, 0x63, + 0x5c, 0x5a, 0x59, 0x56, + + 0x55, 0x54, 0x53, 0x52, + 0x51, 0x4e, 0x4d, 0x4c, + 0x4b, 0x4a, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3c, - 0x3a, 0x39, 0x36, 0x35, - 0x34, 0x33, 0x32, 0x31, - 0x2e, 0x2d, 0x2c, 0x2b, - 0x2a, 0x29, 0x27, 0x26, + 0x3a, 0x39, 0x36, 0x35, + 0x34, 0x33, 0x32, 0x31, + 0x2e, 0x2d, 0x2c, 0x2b, + 0x2a, 0x29, 0x27, 0x26, 0x25, 0x23, 0x1f, 0x1E, - 0x1d, 0x1b, 0x18, 0x17, + 0x1d, 0x1b, 0x18, 0x17, 0x10, 0x0f, 8, 4, 2, 1 }; // ALPA 0 (Fabric) is special case const int number_of_al_pa = (sizeof(valid_al_pa) ); - - // this function looks up an al_pa from the table of valid al_pa's // we decrement from the last decimal loop ID, because soft al_pa // (our typical case) are assigned with highest priority (and high al_pa) @@ -3242,8 +3053,8 @@ static int GetLoopID( ULONG al_pa ) extern cpqfc_passthru_private_t *cpqfc_private(Scsi_Request *sr); -// Search the singly (forward) linked list "fcPorts" looking for -// either the SCSI target (if != -1), port_id (if not NULL), +// Search the singly (forward) linked list "fcPorts" looking for +// either the SCSI target (if != -1), port_id (if not NULL), // or WWN (if not null), in that specific order. // If we find a SCSI nexus (from Cmnd arg), set the SCp.phase // field according to VSA or PDU @@ -3251,25 +3062,24 @@ extern cpqfc_passthru_private_t *cpqfc_p // Ptr to logged in port struct if found // (NULL if not found) // pLastLoggedInPort - ptr to last struct (for adding new ones) -// -PFC_LOGGEDIN_PORT fcFindLoggedInPort( - PTACHYON fcChip, +// +PFC_LOGGEDIN_PORT fcFindLoggedInPort( + PTACHYON fcChip, Scsi_Cmnd *Cmnd, // search linked list for Scsi Nexus (channel/target/lun) ULONG port_id, // search linked list for al_pa, or UCHAR wwn[8], // search linked list for WWN, or... PFC_LOGGEDIN_PORT *pLastLoggedInPort ) - + { - PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts; + PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts; BOOLEAN target_id_valid=FALSE; BOOLEAN port_id_valid=FALSE; BOOLEAN wwn_valid=FALSE; int i; - if( Cmnd != NULL ) target_id_valid = TRUE; - + else if( port_id ) // note! 24-bit NULL address is illegal port_id_valid = TRUE; @@ -3286,7 +3096,6 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( } // check other options ... - // In case multiple search options are given, we use a priority // scheme: // While valid pLoggedIn Ptr @@ -3297,13 +3106,12 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( // Next Ptr in list // // Return NULL (not found) - - + while( pLoggedInPort ) // NULL marks end of list (1st ptr always valid) { if( pLastLoggedInPort ) // caller's pointer valid? *pLastLoggedInPort = pLoggedInPort; // end of linked list - + if( target_id_valid ) { // check Linux Scsi Cmnd for channel/target Nexus match @@ -3314,10 +3122,10 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( { // For "passthru" modes, the IOCTL caller is responsible // for setting the FCP-LUN addressing - if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL && + if (Cmnd->sc_request != NULL && Cmnd->device->host != NULL && Cmnd->device->host->hostdata != NULL && is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->device->host->hostdata, - Cmnd->sc_request->upper_private_data)) { + Cmnd->sc_request->upper_private_data)) { /* This is a passthru... */ cpqfc_passthru_private_t *pd; pd = Cmnd->sc_request->upper_private_data; @@ -3326,9 +3134,9 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( Cmnd->SCp.have_data_in = Cmnd->device->lun; } else { /* This is not a passthru... */ - + // set the FCP-LUN addressing type - Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing; + Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing; // set the Device Type we got from the snooped INQUIRY string Cmnd->SCp.Message = pLoggedInPort->ScsiNexus.InqDeviceType; @@ -3336,7 +3144,7 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( // handle LUN masking; if not "default" (illegal) lun value, // the use it. These lun values are set by a successful // Report Luns command - if( pLoggedInPort->ScsiNexus.LunMasking == 1) + if( pLoggedInPort->ScsiNexus.LunMasking == 1) { if (Cmnd->device->lun > sizeof(pLoggedInPort->ScsiNexus.lun)) return NULL; @@ -3344,7 +3152,7 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->device->lun]; if (pLoggedInPort->ScsiNexus.lun[Cmnd->device->lun] == 0xFF) return NULL; - // printk("xlating lun %d to 0x%02x\n", Cmnd->lun, + // printk("xlating lun %d to 0x%02x\n", Cmnd->lun, // pLoggedInPort->ScsiNexus.lun[Cmnd->lun]); } else @@ -3353,7 +3161,7 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( break; // found it! } } - + if( port_id_valid ) // look for alpa first { if( pLoggedInPort->port_id == port_id ) @@ -3363,27 +3171,24 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort( { if( !memcmp( &pLoggedInPort->u.ucWWN[0], &wwn[0], 8)) - { + { // all 8 bytes of WWN match break; // found it! } } - + pLoggedInPort = pLoggedInPort->pNextPort; // try next port } return pLoggedInPort; } - - - -// +// // We need to examine the SEST table and re-validate // any open Exchanges for this LoggedInPort // To make Tachyon pay attention, Freeze FCP assists, // set VAL bits, Unfreeze FCP assists -static void RevalidateSEST( struct Scsi_Host *HostAdapter, +static void RevalidateSEST( struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort) { CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; @@ -3391,8 +3196,7 @@ static void RevalidateSEST( struct Scsi_ FC_EXCHANGES *Exchanges = fcChip->Exchanges; ULONG x_ID; BOOLEAN TachFroze = FALSE; - - + // re-validate any SEST exchanges that are permitted // to survive the link down (e.g., good PDISC performed) for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) @@ -3401,32 +3205,31 @@ static void RevalidateSEST( struct Scsi_ // If the SEST entry port_id matches the pLoggedInPort, // we need to re-validate if( (Exchanges->fcExchange[ x_ID].type == SCSI_IRE) - || + || (Exchanges->fcExchange[ x_ID].type == SCSI_IWE)) { - + if( (Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF) // (24-bit port ID) - == pLoggedInPort->port_id) + == pLoggedInPort->port_id) { // printk(" re-val xID %Xh ", x_ID); if( !TachFroze ) // freeze if not already frozen TachFroze |= FreezeTach( cpqfcHBAdata); fcChip->SEST->u[ x_ID].IWE.Hdr_Len |= 0x80000000; // set VAL bit } - } + } } - if( TachFroze) - { + if( TachFroze) + { fcChip->UnFreezeTachyon( fcChip, 2); // both ERQ and FCP assists } -} - +} // Complete an Linux Cmnds that we Queued because // our FC link was down (cause immediate retry) -static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, +static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort) { CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; @@ -3434,8 +3237,6 @@ static void UnblockScsiDevice( struct Sc Scsi_Cmnd *Cmnd; int indx; - - // if the device was previously "blocked", make sure // we unblock it so Linux SCSI will resume @@ -3452,14 +3253,13 @@ static void UnblockScsiDevice( struct Sc #endif Cmnd = *SCptr; - // Are there any Q'd commands for this target? if( (Cmnd->device->id == pLoggedInPort->ScsiNexus.target) && (Cmnd->device->channel == pLoggedInPort->ScsiNexus.channel) ) { Cmnd->result = (DID_SOFT_ERROR <<16); // force retry - if( Cmnd->scsi_done == NULL) + if( Cmnd->scsi_done == NULL) { printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n", pLoggedInPort->port_id); @@ -3472,7 +3272,6 @@ static void UnblockScsiDevice( struct Sc } } - //#define WWN_DBG 1 static void SetLoginFields( @@ -3492,7 +3291,7 @@ static void SetLoginFields( pLoggedInPort->Originator = Originator; pLoggedInPort->port_id = fchs->s_id & 0xFFFFFF; - + switch( fchs->pl[0] & 0xffff ) { case 0x00000002: // PLOGI or PDISC ACCept? @@ -3520,9 +3319,8 @@ static void SetLoginFields( if( pLoggedInPort->port_id == 0xFFFFFC ) // well know address pLoggedInPort->flogi = TRUE; - for( i=0; i<8; i++) // copy the LOGIN port's WWN - pLoggedInPort->u.ucWWN[i] = logi.port_name[i]; + pLoggedInPort->u.ucWWN[i] = logi.port_name[i]; #ifdef WWN_DBG ulBuff = (ULONG)pLoggedInPort->u.liWWN; @@ -3538,12 +3336,8 @@ static void SetLoginFields( #endif break; - - - case 0x00000005: // ELS_LOGO (logout) - pLoggedInPort->plogi = FALSE; pLoggedInPort->pdisc = FALSE; pLoggedInPort->prli = FALSE; // ELS_PLOGI resets @@ -3565,16 +3359,12 @@ static void SetLoginFields( #endif break; - - PDISC_case: case 0x00000050: // ELS_PDISC or ELS_PDISC_ACC pLoggedInPort->LOGO_timer = 0; // stop the time-out - + pLoggedInPort->prli = TRUE; // ready to accept FCP-SCSI I/O - - #ifdef WWN_DBG ulBuff = (ULONG)pLoggedInPort->u.liWWN; if( pLoggedInPort->Originator) @@ -3588,12 +3378,8 @@ PDISC_case: printk("%08Xh\n", ulBuff); #endif - - break; - - case 0x1020L: // PRLI? case 0x1002L: // PRLI ACCept? BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&prli, sizeof(prli)); @@ -3618,17 +3404,9 @@ PDISC_case: #endif break; - } - - return; } - - - - - static void BuildLinkServicePayload( PTACHYON fcChip, ULONG type, void* payload) { LOGIN_PAYLOAD *plogi; // FC-PH Port Login @@ -3641,11 +3419,10 @@ static void BuildLinkServicePayload( PTA // PRLO_REQUEST PrloPayload; REJECT_MESSAGE rjt, *prjt; - memset( &PlogiPayload, 0, sizeof( PlogiPayload)); + memset(&PlogiPayload, 0, sizeof(PlogiPayload)); plogi = &PlogiPayload; // load into stack buffer, // then BIG-ENDIAN switch a copy to caller - switch( type ) // payload type can be ELS_PLOGI, ELS_PRLI, ADISC, ... { case ELS_FDISC: @@ -3692,14 +3469,13 @@ static void BuildLinkServicePayload( PTA plogi->vendor_version[2] = ' '; plogi->vendor_version[3] = '0'; plogi->vendor_version[4] = '0'; plogi->vendor_version[5] = '0'; - // FLOGI specific fields... (see FC-FLA, Rev 2.7, Aug 1999, sec 5.1) if( (type == ELS_FLOGI) || (type == ELS_FDISC) ) { if( type == ELS_FLOGI ) - plogi->login_cmd = LS_FLOGI; + plogi->login_cmd = LS_FLOGI; else - plogi->login_cmd = LS_FDISC; + plogi->login_cmd = LS_FDISC; plogi->cmn_services.lowest_ver = 0x20; plogi->cmn_services.common_features = 0x0800; @@ -3712,44 +3488,40 @@ static void BuildLinkServicePayload( PTA plogi->class3.concurrent_sequences = 0; plogi->class3.open_sequences = 0; } - + // copy back to caller's buff, w/ BIG ENDIAN swap BigEndianSwap( (UCHAR*)&PlogiPayload, payload, sizeof(PlogiPayload)); break; - - case ELS_ACC: // generic Extended Link Service ACCept + case ELS_ACC: // generic Extended Link Service ACCept plogi->login_cmd = LS_ACC; // copy back to caller's buff, w/ BIG ENDIAN swap BigEndianSwap( (UCHAR*)&PlogiPayload, payload, 4); break; - - case ELS_SCR: // Fabric State Change Registration { SCR_PL scr; // state change registration - memset( &scr, 0, sizeof(scr)); + memset(&scr, 0, sizeof(scr)); scr.command = LS_SCR; // 0x62000000 // see FC-FLA, Rev 2.7, Table A.22 (pg 82) scr.function = 3; // 1 = Events detected by Fabric // 2 = N_Port detected registration // 3 = Full registration - + // copy back to caller's buff, w/ BIG ENDIAN swap BigEndianSwap( (UCHAR*)&scr, payload, sizeof(SCR_PL)); } - + break; - case FCS_NSR: // Fabric Name Service Request { NSR_PL nsr; // Name Server Req. payload - memset( &nsr, 0, sizeof(NSR_PL)); + memset(&nsr, 0, sizeof(NSR_PL)); // see Brocade Fabric Programming Guide, // Rev 1.3, pg 4-44 @@ -3757,16 +3529,13 @@ static void BuildLinkServicePayload( PTA nsr.FCS_Type = 0xFC020000; nsr.Command_code = 0x01710000; nsr.FCP = 8; - + // copy back to caller's buff, w/ BIG ENDIAN swap BigEndianSwap( (UCHAR*)&nsr, payload, sizeof(NSR_PL)); } - - break; - + break; - case ELS_LOGO: // FC-PH PORT LogOut logo = &LogoutPayload; // load into stack buffer, // then BIG-ENDIAN switch a copy to caller @@ -3788,14 +3557,12 @@ static void BuildLinkServicePayload( PTA payload, sizeof(LogoutPayload) ); // 16 UCHAR struct break; - case ELS_LOGO_ACC: // Logout Accept (FH-PH pg 149, table 74) logo = &LogoutPayload; // load into stack buffer, // then BIG-ENDIAN switch a copy to caller logo->cmd = LS_ACC; BigEndianSwap( (UCHAR*)&LogoutPayload, payload, 4 ); // 4 UCHAR cmnd break; - case ELS_RJT: // ELS_RJT link service reject (FH-PH pg 155) @@ -3810,14 +3577,10 @@ static void BuildLinkServicePayload( PTA BigEndianSwap( (UCHAR*)&rjt, payload, 8 ); // 8 UCHAR cmnd break; - - - - case ELS_PRLI_ACC: // Process Login ACCept case ELS_PRLI: // Process Login case ELS_PRLO: // Process Logout - memset( &PrliPayload, 0, sizeof( PrliPayload)); + memset(&PrliPayload, 0, sizeof(PrliPayload)); prli = &PrliPayload; // load into stack buffer, if( type == ELS_PRLI ) @@ -3830,7 +3593,6 @@ static void BuildLinkServicePayload( PTA prli->valid = REQUEST_EXECUTED; } - prli->valid |= SCSI_FCP | ESTABLISH_PAIR; prli->fcp_info = READ_XFER_RDY; prli->page_length = 0x10; @@ -3845,8 +3607,6 @@ static void BuildLinkServicePayload( PTA BigEndianSwap( (UCHAR*)&PrliPayload, payload, prli->payload_length); break; - - default: // no can do - programming error printk(" BuildLinkServicePayload unknown!\n"); break; @@ -3878,17 +3638,14 @@ void LoadWWN( PTACHYON fcChip, UCHAR* de dest[i] = *bPtr++; break; } - -} - +} // We check the Port Login payload for required values. Note that // ELS_PLOGI and ELS_PDISC (Port DISCover) use the same payload. - int verify_PLOGI( PTACHYON fcChip, - TachFCHDR_GCMND* fchs, + TachFCHDR_GCMND* fchs, ULONG* reject_explain) { LOGIN_PAYLOAD login; @@ -3898,7 +3655,7 @@ int verify_PLOGI( PTACHYON fcChip, // check FC version // if other port's highest supported version - // is less than our lowest, and + // is less than our lowest, and // if other port's lowest if( login.cmn_services.highest_ver < fcChip->lowest_FCPH_ver || login.cmn_services.lowest_ver > fcChip->highest_FCPH_ver ) @@ -3932,9 +3689,6 @@ int verify_PLOGI( PTACHYON fcChip, return 0; // success } - - - int verify_PRLI( TachFCHDR_GCMND* fchs, ULONG* reject_explain) { PRLI_REQUEST prli; // buffer for BIG ENDIAN @@ -3951,7 +3705,6 @@ int verify_PRLI( TachFCHDR_GCMND* fchs, return 0; // success } - // SWAP UCHARs as required by Fibre Channel (i.e. BIG ENDIAN) // INPUTS: // source - ptr to LITTLE ENDIAN ULONGS @@ -3973,18 +3726,15 @@ void BigEndianSwap( UCHAR *source, UCHAR } } - - - // Build FC Exchanges............ -static void buildFCPstatus( - PTACHYON fcChip, +static void buildFCPstatus( + PTACHYON fcChip, ULONG ExchangeID); static LONG FindFreeExchange( PTACHYON fcChip, ULONG type ); -static ULONG build_SEST_sgList( +static ULONG build_SEST_sgList( struct pci_dev *pcidev, ULONG *SESTalPairStart, Scsi_Cmnd *Cmnd, @@ -3992,7 +3742,7 @@ static ULONG build_SEST_sgList( PSGPAGES *sgPages_head // link list of TL Ext. S/G pages from O/S Pool ); -static int build_FCP_payload( Scsi_Cmnd *Cmnd, +static int build_FCP_payload( Scsi_Cmnd *Cmnd, UCHAR* payload, ULONG type, ULONG fcp_dl ); @@ -4003,7 +3753,7 @@ static int build_FCP_payload( Scsi_Cmnd |----------| / | Req_A_SFS_Addr |------->| Reserved | | IRB | / | Req_A_D_ID | | SOF EOF TimeStamp | |-----------/ | Req_A_SEST_Index |-+ | R_CTL | D_ID | - | IRB | | Req_B... | | | CS_CTL| S_ID | + | IRB | | Req_B... | | | CS_CTL| S_ID | |-----------\ | | | | TYPE | F_CTL | | IRB | \ | | | | SEQ_ID | SEQ_CNT | |----------- \ | | +-->+--| OX_ID | RX_ID | @@ -4016,26 +3766,26 @@ static int build_FCP_payload( Scsi_Cmnd +-------------------------------------------+ | | -| e.g. IWE +| e.g. IWE | SEST __________________ for FCP_DATA | | | / | | Hdr_Len | ____________________ | |----------| / | Hdr_Addr_Addr |------->| Reserved | | | [0] | / |Remote_ID| RSP_Len| | SOF EOF TimeStamp | | |-----------/ | RSP_Addr |---+ | R_CTL | D_ID | -+-> [1] | | | Buff_Off | | | CS_CTL| S_ID | ++-> [1] | | | Buff_Off | | | CS_CTL| S_ID | |-----------\ |BuffIndex| Link | | | TYPE | F_CTL | | [2] | \ | Rsvd | RX_ID | | | SEQ_ID | SEQ_CNT | |----------- \ | Data_Len | | | OX_ID | RX_ID | | ... | \ | Exp_RO | | | RO | |----------| | Exp_Byte_Cnt | | |___________________| - | SEST_LEN | +--| Len | | - |__________| | | Address | | - | | ... | | for FCP_RSP + | SEST_LEN | +--| Len | | + |__________| | | Address | | + | | ... | | for FCP_RSP | |__________________| | ____________________ - | +----| Reserved | + | +----| Reserved | | | SOF EOF TimeStamp | | | R_CTL | D_ID | - | | CS_CTL| S_ID | + | | CS_CTL| S_ID | +--- local or extended | .... | scatter/gather lists defining upper-layer @@ -4079,8 +3829,8 @@ ULONG cpqfcTSBuildExchange( CPQFCHBA *cpqfcHBAdata, ULONG type, // e.g. PLOGI TachFCHDR_GCMND* InFCHS, // incoming FCHS - void *Data, // the CDB, scatter/gather, etc. - LONG *fcExchangeIndex ) // points to allocated exchange, + void *Data, // the CDB, scatter/gather, etc. + LONG *fcExchangeIndex ) // points to allocated exchange, { PTACHYON fcChip = &cpqfcHBAdata->fcChip; FC_EXCHANGES *Exchanges = fcChip->Exchanges; @@ -4109,7 +3859,6 @@ ULONG cpqfcTSBuildExchange( if( !fcChip->ERQ ) // NULL ptr means uninitialized Tachlite chip return INVALID_ARGS; - if( type == SCSI_IRE || type == SCSI_TRE || type == SCSI_IWE || @@ -4119,7 +3868,6 @@ ULONG cpqfcTSBuildExchange( else FCP_SCSI_command = 0; - // for commands that pass payload data (e.g. SCSI write) // examine command struct - verify that the // length of s/g buffers is adequate for total payload @@ -4132,13 +3880,10 @@ ULONG cpqfcTSBuildExchange( { // something to do (later)? } - else return INVALID_ARGS; // invalid DATA ptr } - - // we can build an Exchange for later Queuing (on the TL chip) // if an empty slot is available in the DevExt for this controller // look for available Exchange slot... @@ -4151,12 +3896,12 @@ ULONG cpqfcTSBuildExchange( if( *fcExchangeIndex != -1 ) // Exchange is available? { // assign tmp ptr (shorthand) - CMDfchs = &Exchanges->fcExchange[ *fcExchangeIndex].fchs; + CMDfchs = &Exchanges->fcExchange[ *fcExchangeIndex].fchs; if( Cmnd != NULL ) // (necessary for ABTS cases) { Exchanges->fcExchange[ *fcExchangeIndex].Cmnd = Cmnd; // Linux Scsi - Exchanges->fcExchange[ *fcExchangeIndex].pLoggedInPort = + Exchanges->fcExchange[ *fcExchangeIndex].pLoggedInPort = fcFindLoggedInPort( fcChip, Exchanges->fcExchange[ *fcExchangeIndex].Cmnd, // find Scsi Nexus 0, // DON'T search linked list for FC port id @@ -4165,18 +3910,17 @@ ULONG cpqfcTSBuildExchange( } - // Build the command frame header (& data) according // to command type // fields common for all SFS frame types CMDfchs->reserved = 0L; // must clear CMDfchs->sof_eof = 0x75000000L; // SOFi3:EOFn no UAM; LCr=0, no TS - + // get the destination port_id from incoming FCHS // (initialized before calling if we're Originator) // Frame goes to port it was from - the source_id - + CMDfchs->d_id = InFCHS->s_id &0xFFFFFF; // destination (add R_CTL later) CMDfchs->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0 @@ -4207,9 +3951,6 @@ ULONG cpqfcTSBuildExchange( // (NOP should complete ~instantly) break; - - - case BLS_ABTS_ACC: // Abort Sequence ACCept *pIRB_flags = 0; // clear IRB flags IRB_flags.SFA = 1; // send SFS (not SEST index) @@ -4226,26 +3967,24 @@ ULONG cpqfcTSBuildExchange( CMDfchs->ro = 0x0L; // relative offset (n/a) Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 5; // seconds // (Timeout in case of weird error) - + // now set the ACCept payload... ba_acc = (BA_ACC_PAYLOAD*)&CMDfchs->pl[0]; - memset( ba_acc, 0, sizeof( BA_ACC_PAYLOAD)); + memset(ba_acc, 0, sizeof(BA_ACC_PAYLOAD)); // Since PLDA requires (only) entire Exchange aborts, we don't need // to worry about what the last sequence was. // We expect that a "target" task is accepting the abort, so we - // can use the OX/RX ID pair + // can use the OX/RX ID pair ba_acc->ox_rx_id = CMDfchs->ox_rx_id; - + // source, dest, #bytes BigEndianSwap((UCHAR *)&CMDfchs->ox_rx_id, (UCHAR *)&ba_acc->ox_rx_id, 4); ba_acc->low_seq_cnt = 0; ba_acc->high_seq_cnt = 0xFFFF; - break; - case BLS_ABTS_RJT: // Abort Sequence ACCept *pIRB_flags = 0; // clear IRB flags @@ -4263,12 +4002,12 @@ ULONG cpqfcTSBuildExchange( CMDfchs->ro = 0x0L; // relative offset (n/a) Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 5; // seconds // (Timeout in case of weird error) - + CMDfchs->ox_rx_id = InFCHS->ox_rx_id; // copy from sender! - + // now set the ReJecT payload... ba_rjt = (BA_RJT_PAYLOAD*)&CMDfchs->pl[0]; - memset( ba_rjt, 0, sizeof( BA_RJT_PAYLOAD)); + memset(ba_rjt, 0, sizeof(BA_RJT_PAYLOAD)); // We expect that a "target" task couldn't find the Exhange in the // array of active exchanges, so we use a new LinkService X_ID. @@ -4276,13 +4015,10 @@ ULONG cpqfcTSBuildExchange( ba_rjt->reason_code = 0x09; // "unable to perform command request" ba_rjt->reason_explain = 0x03; // invalid OX/RX ID pair - break; - - - case BLS_ABTS: // FC defined basic link service command ABTS + + case BLS_ABTS: // FC defined basic link service command ABTS // Abort Sequence - *pIRB_flags = 0; // clear IRB flags IRB_flags.SFA = 1; // send SFS (not SEST index) @@ -4301,8 +4037,6 @@ ULONG cpqfcTSBuildExchange( // (ABTS must timeout when responder is gone) break; - - case FCS_NSR: // Fabric Name Service Request Exchanges->fcExchange[ *fcExchangeIndex].reTries = 2; @@ -4320,7 +4054,7 @@ ULONG cpqfcTSBuildExchange( SfsLen += (32L + sizeof(NSR_PL)); // add len (header & NSR payload) CMDfchs->d_id |= 0x02000000L; // R_CTL = 02 for - - // Name Service Request: Unsolicited + // Name Service Request: Unsolicited // TYPE[31-24] 01 Extended Link Service // f_ctl[23:0] exchg originator, 1st seq, xfer S.I. CMDfchs->f_ctl = 0x20210000L; @@ -4330,16 +4064,8 @@ ULONG cpqfcTSBuildExchange( BuildLinkServicePayload( fcChip, type, &CMDfchs->pl[0]); - - - - - - break; - - - - + break; + case ELS_PLOGI: // FC-PH extended link service command Port Login // (May, 2000) // NOTE! This special case facilitates SANMark testing. The SANMark @@ -4353,7 +4079,7 @@ ULONG cpqfcTSBuildExchange( // other device really did report non-zero login BB credit (i.e. // in the PLOGI ACCept frame). // CMDfchs->sof_eof |= 0x00000400L; // LCr=1 - + case ELS_FDISC: // Fabric Discovery (Login) case ELS_FLOGI: // Fabric Login case ELS_SCR: // Fabric State Change Registration @@ -4363,7 +4089,6 @@ ULONG cpqfcTSBuildExchange( Exchanges->fcExchange[ *fcExchangeIndex].reTries = 2; - Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 2; // seconds // OX_ID, linked to Driver Transaction ID // (fix-up at Queing time) @@ -4396,19 +4121,16 @@ ULONG cpqfcTSBuildExchange( break; - - case ELS_LOGO_ACC: // FC-PH extended link service logout accept case ELS_RJT: // extended link service reject (add reason) case ELS_ACC: // ext. link service generic accept case ELS_PLOGI_ACC:// ext. link service login accept (PLOGI or PDISC) case ELS_PRLI_ACC: // ext. link service process login accept - Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 1; // assume done // ensure unique X_IDs! (use tracking function) // OX_ID from initiator cmd - ox_ID = (USHORT)(InFCHS->ox_rx_id >> 16); + ox_ID = (USHORT)(InFCHS->ox_rx_id >> 16); rx_ID = 0xFFFF; // RX_ID, linked to Driver Exchange ID *pIRB_flags = 0; // clear IRB flags @@ -4422,8 +4144,7 @@ ULONG cpqfcTSBuildExchange( // ELS_RJT reason codes (utilize unused "reserved" field) CMDfchs->pl[0] = 1; - CMDfchs->pl[1] = InFCHS->reserved; - + CMDfchs->pl[1] = InFCHS->reserved; } else if( (type == ELS_LOGO_ACC) || (type == ELS_ACC) ) SfsLen += (32L + 4L); // add len (header + payload) @@ -4448,20 +4169,19 @@ ULONG cpqfcTSBuildExchange( break; - // Fibre Channel SCSI 'originator' sequences... // (originator means 'initiator' in FCP-SCSI) case SCSI_IWE: // TachLite Initiator Write Entry { - PFC_LOGGEDIN_PORT pLoggedInPort = + PFC_LOGGEDIN_PORT pLoggedInPort = Exchanges->fcExchange[ *fcExchangeIndex].pLoggedInPort; Exchanges->fcExchange[ *fcExchangeIndex].reTries = 1; Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 7; // FC2 timeout - + // first, build FCP_CMND - // unique X_ID fix-ups in StartExchange + // unique X_ID fix-ups in StartExchange *pIRB_flags = 0; // clear IRB flags IRB_flags.SFA = 1; // send SFS FCP-CMND (not SEST index) @@ -4500,16 +4220,16 @@ ULONG cpqfcTSBuildExchange( // Now setup the SEST entry pIWE = &fcChip->SEST->u[ *fcExchangeIndex ].IWE; - + // fill out the IWE: // VALid entry:Dir outbound:DCM:enable CM:enal INT: FC frame len pIWE->Hdr_Len = 0x8e000020L; // data frame Len always 32 bytes - - + + // from login parameters with other port, what's the largest frame - // we can send? - if( pLoggedInPort == NULL) + // we can send? + if( pLoggedInPort == NULL) { ulStatus = INVALID_ARGS; // failed! give up break; @@ -4522,30 +4242,29 @@ ULONG cpqfcTSBuildExchange( fl = 0x00010000; // 512 code else fl = 0; // 128 bytes -- should never happen - - + pIWE->Hdr_Len |= fl; // add xmit FC frame len for data phase - pIWE->Hdr_Addr = fcChip->SEST->base + - ((unsigned long)&fcChip->SEST->DataHDR[*fcExchangeIndex] - + pIWE->Hdr_Addr = fcChip->SEST->base + + ((unsigned long)&fcChip->SEST->DataHDR[*fcExchangeIndex] - (unsigned long)fcChip->SEST); pIWE->RSP_Len = sizeof(TachFCHDR_RSP) ; // hdr+data (recv'd RSP frame) pIWE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID - - memset( &fcChip->SEST->RspHDR[ *fcExchangeIndex].pl, 0, - sizeof( FCP_STATUS_RESPONSE) ); // clear out previous status - - pIWE->RSP_Addr = fcChip->SEST->base + - ((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] - + + memset(&fcChip->SEST->RspHDR[ *fcExchangeIndex].pl, 0, + sizeof(FCP_STATUS_RESPONSE) ); // clear out previous status + + pIWE->RSP_Addr = fcChip->SEST->base + + ((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long)fcChip->SEST); // Do we need local or extended gather list? // depends on size - we can handle 3 len/addr pairs // locally. - fcp_dl = build_SEST_sgList( + fcp_dl = build_SEST_sgList( cpqfcHBAdata->PciDev, - &pIWE->GLen1, + &pIWE->GLen1, Cmnd, // S/G list &sgPairs, // return # of pairs in S/G list (from "Data" descriptor) &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later) @@ -4560,8 +4279,6 @@ ULONG cpqfcTSBuildExchange( // the passed S/G buffer, set FCP CMND frame build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl ); - - if( sgPairs > 3 ) // need extended s/g list pIWE->Buff_Off = 0x78000000L; // extended data | (no offset) else // local data pointers (in SEST) @@ -4580,10 +4297,6 @@ ULONG cpqfcTSBuildExchange( } break; - - - - case SCSI_IRE: // TachLite Initiator Read Entry if( Cmnd->timeout != 0) @@ -4595,10 +4308,10 @@ ULONG cpqfcTSBuildExchange( else // use our best guess, based on FC & device { - if( Cmnd->SCp.Message == 1 ) // Tape device? (from INQUIRY) + if( Cmnd->SCp.Message == 1 ) // Tape device? (from INQUIRY) { // turn off our timeouts (for now...) - Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 0xFFFFFFFF; + Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 0xFFFFFFFF; } else { @@ -4607,10 +4320,8 @@ ULONG cpqfcTSBuildExchange( } } - // first, build FCP_CMND - *pIRB_flags = 0; // clear IRB flags IRB_flags.SFA = 1; // send SFS FCP-CMND (not SEST index) // NOTE: unlike FC LinkService login frames, @@ -4632,8 +4343,6 @@ ULONG cpqfcTSBuildExchange( CMDfchs->ox_rx_id = 0xFFFF; // clear CMDfchs->ro = 0x0L; // relative offset (n/a) - - // Now setup the SEST entry pIRE = &fcChip->SEST->u[ *fcExchangeIndex ].IRE; @@ -4645,22 +4354,21 @@ ULONG cpqfcTSBuildExchange( pIRE->RSP_Len = sizeof(TachFCHDR_RSP) ; // hdr+data (recv'd RSP frame) pIRE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID - pIRE->RSP_Addr = fcChip->SEST->base + - ((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] - + pIRE->RSP_Addr = fcChip->SEST->base + + ((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long)fcChip->SEST); - + // Do we need local or extended gather list? // depends on size - we can handle 3 len/addr pairs // locally. - fcp_dl = build_SEST_sgList( + fcp_dl = build_SEST_sgList( cpqfcHBAdata->PciDev, - &pIRE->SLen1, + &pIRE->SLen1, Cmnd, // SCSI command Data desc. with S/G list &sgPairs, // return # of pairs in S/G list (from "Data" descriptor) &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later) - - + if( !fcp_dl ) // error building S/G list? { // It is permissible to have a ZERO LENGTH Read command. @@ -4669,7 +4377,6 @@ ULONG cpqfcTSBuildExchange( if( Cmnd->request_bufflen == 0 ) { fcp_dl = 0; // no FC DATA frames expected - } else { @@ -4681,12 +4388,11 @@ ULONG cpqfcTSBuildExchange( // now that we know the S/G length, build CMND payload build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl ); - if( sgPairs > 3 ) // need extended s/g list pIRE->Buff_Off = 0x00000000; // DWord 4: extended s/g list, no offset else pIRE->Buff_Off = 0x80000000; // local data, no offset - + pIRE->Buff_Index = 0x0L; // DWord 5: Buff_Index | Reserved pIRE->Exp_RO = 0x0L; // DWord 6: Expected Rel. Offset @@ -4695,11 +4401,8 @@ ULONG cpqfcTSBuildExchange( pIRE->reserved_ = 0; // DWord 8: reserved // NOTE: 0 length READ is OK. pIRE->Exp_Byte_Cnt = fcp_dl;// DWord 9: sum of scatter buffers - - break; - - + break; // Fibre Channel SCSI 'responder' sequences... // (originator means 'target' in FCP-SCSI) @@ -4742,9 +4445,8 @@ ULONG cpqfcTSBuildExchange( rspHDR->ox_rx_id = InFCHS->ox_rx_id; // gives us OX_ID rspHDR->ro = 0x0L; // relative offset (n/a) - // Now setup the SEST entry - + pTWE = &fcChip->SEST->u[ *fcExchangeIndex ].TWE; // fill out the TWE: @@ -4754,20 +4456,18 @@ ULONG cpqfcTSBuildExchange( pTWE->reserved = 0L; pTWE->Remote_Node_ID = 0L; // no more auto RSP frame! (TL/TS change) pTWE->Remote_Node_ID |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID - // Do we need local or extended gather list? // depends on size - we can handle 3 len/addr pairs // locally. - fcp_dl = build_SEST_sgList( + fcp_dl = build_SEST_sgList( cpqfcHBAdata->PciDev, - &pTWE->SLen1, + &pTWE->SLen1, Cmnd, // S/G list &sgPairs, // return # of pairs in S/G list (from "Data" descriptor) &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later) - - + if( !fcp_dl ) // error building S/G list? { ulStatus = MEMPOOL_FAIL; @@ -4777,24 +4477,19 @@ ULONG cpqfcTSBuildExchange( // now that we know the S/G length, build CMND payload build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl ); - + if( sgPairs > 3 ) // need extended s/g list pTWE->Buff_Off = 0x00000000; // extended s/g list, no offset else pTWE->Buff_Off = 0x80000000; // local data, no offset - + pTWE->Buff_Index = 0; // Buff_Index | Link pTWE->Exp_RO = 0; pTWE->Byte_Count = 0; // filled in by TL on err pTWE->reserved_ = 0; pTWE->Exp_Byte_Cnt = fcp_dl;// sum of scatter buffers - - break; - - - - + break; case SCSI_TRE: // TachLite Target Read Entry @@ -4814,8 +4509,6 @@ ULONG cpqfcTSBuildExchange( SfsLen <<= 24; // shift flags to MSB SfsLen += (32L + 12L);// add SFS len (header & XFER_RDY payload) - - // now, fill out FCP-DATA header // (use buffer inside SEST object) dataHDR = &fcChip->SEST->DataHDR[ *fcExchangeIndex ]; @@ -4825,7 +4518,6 @@ ULONG cpqfcTSBuildExchange( dataHDR->d_id = (InFCHS->s_id | 0x01000000L); // R_CTL= FCP_DATA dataHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0 - // TYPE[31-24] 8 for FCP SCSI // f_ctl[23:0] exchg responder, not 1st seq, xfer S.I. // valid RO @@ -4849,22 +4541,20 @@ ULONG cpqfcTSBuildExchange( rspHDR->ro = 0x0L; // relative offset (n/a) - // Now setup the SEST entry pTRE = &fcChip->SEST->u[ *fcExchangeIndex ].TRE; - // VALid entry:Dir outbound:enable CM:enal INT: pTRE->Hdr_Len = 0x86010020L; // data frame Len always 32 bytes pTRE->Hdr_Addr = // bus address of dataHDR; - fcChip->SEST->base + + fcChip->SEST->base + ((unsigned long)&fcChip->SEST->DataHDR[ *fcExchangeIndex ] - (unsigned long)fcChip->SEST); - + pTRE->RSP_Len = 64L; // hdr+data (TL assisted RSP frame) pTRE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID pTRE->RSP_Addr = // bus address of rspHDR - fcChip->SEST->base + + fcChip->SEST->base + ((unsigned long)&fcChip->SEST->RspHDR[ *fcExchangeIndex ] - (unsigned long)fcChip->SEST); @@ -4872,14 +4562,13 @@ ULONG cpqfcTSBuildExchange( // depends on size - we can handle 3 len/addr pairs // locally. - fcp_dl = build_SEST_sgList( + fcp_dl = build_SEST_sgList( cpqfcHBAdata->PciDev, - &pTRE->GLen1, + &pTRE->GLen1, Cmnd, // S/G list &sgPairs, // return # of pairs in S/G list (from "Data" descriptor) &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later) - - + if( !fcp_dl ) // error building S/G list? { ulStatus = MEMPOOL_FAIL; @@ -4888,7 +4577,6 @@ ULONG cpqfcTSBuildExchange( // no payload or command to build -- READ doesn't need XRDY - if( sgPairs > 3 ) // need extended s/g list pTRE->Buff_Off = 0x78000000L; // extended data | (no offset) else // local data pointers (in SEST) @@ -4907,13 +4595,7 @@ ULONG cpqfcTSBuildExchange( break; - - - - - - - case FCP_RESPONSE: + case FCP_RESPONSE: // Target response frame: this sequence uses an OX/RX ID // pair from a completed SEST exchange. We built most // of the response frame when we created the TWE/TRE. @@ -4924,14 +4606,13 @@ ULONG cpqfcTSBuildExchange( SfsLen <<= 24; // shift flags to MSB SfsLen += sizeof(TachFCHDR_RSP);// add SFS len (header & RSP payload) - - Exchanges->fcExchange[ *fcExchangeIndex].type = + Exchanges->fcExchange[ *fcExchangeIndex].type = FCP_RESPONSE; // change Exchange type to "response" phase // take advantage of prior knowledge of OX/RX_ID pair from // previous XFER outbound frame (still in fchs of exchange) - fcChip->SEST->RspHDR[ *fcExchangeIndex ].ox_rx_id = + fcChip->SEST->RspHDR[ *fcExchangeIndex ].ox_rx_id = CMDfchs->ox_rx_id; // Check the status of the DATA phase of the exchange so we can report @@ -4941,9 +4622,8 @@ ULONG cpqfcTSBuildExchange( memcpy( CMDfchs, // re-use same XFER fchs for Response frame &fcChip->SEST->RspHDR[ *fcExchangeIndex ], - sizeof( TachFCHDR_RSP )); - - + sizeof(TachFCHDR_RSP )); + break; default: @@ -4952,33 +4632,31 @@ ULONG cpqfcTSBuildExchange( } - - if( !ulStatus) // no errors above? { // FCHS is built; now build IRB - // link the just built FCHS (the "command") to the IRB entry + // link the just built FCHS (the "command") to the IRB entry // for this Exchange. - pIRB = &Exchanges->fcExchange[ *fcExchangeIndex].IRB; - + pIRB = &Exchanges->fcExchange[ *fcExchangeIndex].IRB; + // len & flags according to command type above pIRB->Req_A_SFS_Len = SfsLen; // includes IRB flags & len pIRB->Req_A_SFS_Addr = // TL needs physical addr of frame to send - fcChip->exch_dma_handle + (unsigned long)CMDfchs - + fcChip->exch_dma_handle + (unsigned long)CMDfchs - (unsigned long)Exchanges; pIRB->Req_A_SFS_D_ID = CMDfchs->d_id << 8; // Dest_ID must be consistent! // Exchange is complete except for "fix-up" fields to be set // at Tachyon Queuing time: - // IRB->Req_A_Trans_ID (OX_ID/ RX_ID): + // IRB->Req_A_Trans_ID (OX_ID/ RX_ID): // for SEST entry, lower bits correspond to actual FC Exchange ID // fchs->OX_ID or RX_ID } else { -#ifdef DBG +#ifdef DBG printk( "FC Error: SEST build Pool Allocation failed\n"); #endif // return resources... @@ -4993,27 +4671,21 @@ ULONG cpqfcTSBuildExchange( return ulStatus; } - - - - - // set RSP payload fields -static void buildFCPstatus( PTACHYON fcChip, ULONG ExchangeID) +static void buildFCPstatus( PTACHYON fcChip, ULONG ExchangeID) { FC_EXCHANGES *Exchanges = fcChip->Exchanges; FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ExchangeID]; // shorthand PFCP_STATUS_RESPONSE pFcpStatus; - - memset( &fcChip->SEST->RspHDR[ ExchangeID ].pl, 0, - sizeof( FCP_STATUS_RESPONSE) ); + + memset(&fcChip->SEST->RspHDR[ ExchangeID ].pl, 0, + sizeof(FCP_STATUS_RESPONSE) ); if( pExchange->status ) // something wrong? { pFcpStatus = (PFCP_STATUS_RESPONSE) // cast RSP buffer for this xchng &fcChip->SEST->RspHDR[ ExchangeID ].pl; if( pExchange->status & COUNT_ERROR ) { - // set FCP response len valid (so we can report count error) pFcpStatus->fcp_status |= FCP_RSP_LEN_VALID; pFcpStatus->fcp_rsp_len = 0x04000000; // 4 byte len (BIG Endian) @@ -5023,29 +4695,28 @@ static void buildFCPstatus( PTACHYON fc } } - -static dma_addr_t +static dma_addr_t cpqfc_pci_map_sg_page( struct pci_dev *pcidev, ULONG *hw_paddr, // where to put phys addr for HW use - void *sgp_vaddr, // the virtual address of the sg page + void *sgp_vaddr, // the virtual address of the sg page dma_addr_t *umap_paddr, // where to put phys addr for unmap unsigned int *maplen, // where to store sg entry length - int PairCount) // number of sg pairs used in the page. + int PairCount) // number of sg pairs used in the page. { unsigned long aligned_addr = (unsigned long) sgp_vaddr; *maplen = PairCount * 8; aligned_addr += TL_EXT_SG_PAGE_BYTELEN; aligned_addr &= ~(TL_EXT_SG_PAGE_BYTELEN -1); - - *umap_paddr = pci_map_single(pcidev, (void *) aligned_addr, + + *umap_paddr = pci_map_single(pcidev, (void *) aligned_addr, *maplen, PCI_DMA_TODEVICE); *hw_paddr = (ULONG) *umap_paddr; # if BITS_PER_LONG > 32 if( *umap_paddr >>32 ) { - printk("cqpfcTS:Tach SG DMA addr %p>32 bits\n", + printk("cqpfcTS:Tach SG DMA addr %p>32 bits\n", (void*)umap_paddr); return 0; } @@ -5070,12 +4741,12 @@ cpqfc_undo_SEST_mappings(struct pci_dev for (i=*sgPages_head; i != NULL ;i = next) { - pci_unmap_single(pcidev, i->busaddr, i->maplen, + pci_unmap_single(pcidev, i->busaddr, i->maplen, PCI_DMA_TODEVICE); - i->busaddr = (dma_addr_t) NULL; - i->maplen = 0L; + i->busaddr = (dma_addr_t) NULL; + i->maplen = 0L; next = i->next; - kfree(i); + kfree(i); } *sgPages_head = NULL; } @@ -5098,13 +4769,13 @@ cpqfc_undo_SEST_mappings(struct pci_dev static int ap_hi_water = TL_DANGER_SGPAGES; -static ULONG build_SEST_sgList( +static ULONG build_SEST_sgList( struct pci_dev *pcidev, ULONG *SESTalPairStart, // the 3 len/address buffers in SEST Scsi_Cmnd *Cmnd, - ULONG *sgPairs, + ULONG *sgPairs, PSGPAGES *sgPages_head) // link list of TL Ext. S/G pages from O/S Pool - + { ULONG i, AllocatedPages=0; // Tach Ext. S/G page allocations ULONG* alPair = SESTalPairStart; @@ -5115,7 +4786,7 @@ static ULONG build_SEST_sgList( ULONG bytes_to_go = Cmnd->request_bufflen; // total xfer (S/G sum) ULONG thisMappingLen; struct scatterlist *sgl = NULL; // S/G list (Linux format) - int sg_count, totalsgs; + int sg_count, totalsgs; dma_addr_t busaddr; unsigned long thislen, offset; PSGPAGES *sgpage = sgPages_head; @@ -5134,8 +4805,8 @@ static ULONG build_SEST_sgList( *alPair++ = bytes_to_go; // bits 18-0, length if (bytes_to_go != 0) { - contigaddr = ulBuff = pci_map_single(pcidev, - Cmnd->request_buffer, + contigaddr = ulBuff = pci_map_single(pcidev, + Cmnd->request_buffer, Cmnd->request_bufflen, Cmnd->sc_data_direction); // printk("ms %p ", ulBuff); @@ -5155,24 +4826,24 @@ static ULONG build_SEST_sgList( return 0; } # endif - *alPair = (ULONG)ulBuff; + *alPair = (ULONG)ulBuff; return bytes_to_go; - } + } else // We have a single large (too big) contiguous buffer. { // We will have to break it up. We'll use the scatter // gather code way below, but use contigaddr instead // of sg_dma_addr(). (this is a very rare case). unsigned long btg; - contigaddr = pci_map_single(pcidev, Cmnd->request_buffer, + contigaddr = pci_map_single(pcidev, Cmnd->request_buffer, Cmnd->request_bufflen, Cmnd->sc_data_direction); - // printk("contigaddr = %p, len = %d\n", + // printk("contigaddr = %p, len = %d\n", // (void *) contigaddr, bytes_to_go); totalsgs = 0; for (btg = bytes_to_go; btg > 0; ) { - btg -= ( btg > TL_MAX_SG_ELEM_LEN ? + btg -= ( btg > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : btg ); totalsgs++; } @@ -5186,9 +4857,9 @@ static ULONG build_SEST_sgList( // since the format for local & extended S/G lists is different, // check if S/G pairs exceeds 3. // *sgPairs = Cmnd->use_sg; Nope, that's wrong. - - sgl = (struct scatterlist*)Cmnd->request_buffer; - sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg, + + sgl = (struct scatterlist*)Cmnd->request_buffer; + sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg, Cmnd->sc_data_direction); if( sg_count <= 3 ) { @@ -5196,7 +4867,7 @@ static ULONG build_SEST_sgList( // is too large, and if any is, that breaking it up // doesn't push us over 3 sgs, or, if it does, that we // handle that case. Tachyon can take 0x7FFFF bits for length, - // but sg structure uses "unsigned int", on the face of it, + // but sg structure uses "unsigned int", on the face of it, // up to 0xFFFFFFFF or even more. int i; @@ -5212,9 +4883,9 @@ static ULONG build_SEST_sgList( if (thislen > 0) totalsgs++; } *sgPairs = totalsgs; - } else totalsgs = 999; // as a first estimate, definitely >3, - - // if (totalsgs != sg_count) + } else totalsgs = 999; // as a first estimate, definitely >3, + + // if (totalsgs != sg_count) // printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count); } @@ -5224,14 +4895,14 @@ static ULONG build_SEST_sgList( { offset = 0L; - if ( WE_HAVE_SG_LIST ) + if ( WE_HAVE_SG_LIST ) thisMappingLen = sg_dma_len(sgl); else // or contiguous buffer? thisMappingLen = bytes_to_go; while (thisMappingLen > 0) - { - thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? + { + thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : thisMappingLen; bytes_to_go = bytes_to_go - thislen; @@ -5243,7 +4914,7 @@ static ULONG build_SEST_sgList( alPair++; - if ( WE_HAVE_SG_LIST ) + if ( WE_HAVE_SG_LIST ) ulBuff = sg_dma_address(sgl) + offset; else ulBuff = contigaddr + offset; @@ -5252,9 +4923,9 @@ static ULONG build_SEST_sgList( # if BITS_PER_LONG > 32 if( ulBuff >>32 ) { - printk("cqpfcTS: 2Tach DMA address %p > 32 bits\n", + printk("cqpfcTS: 2Tach DMA address %p > 32 bits\n", (void*)ulBuff ); - printk("%s = %p, offset = %ld\n", + printk("%s = %p, offset = %ld\n", WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr", WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr, offset); @@ -5289,23 +4960,23 @@ static ULONG build_SEST_sgList( // Per SEST format, we can support 524287 byte lengths per // S/G pair. Typical user buffers are 4k, and very rarely // exceed 12k due to fragmentation of physical memory pages. - // However, on certain O/S system (not "user") buffers (on platforms + // However, on certain O/S system (not "user") buffers (on platforms // with huge memories), it's possible to exceed this // length in a single S/G address/len mapping, so we have to handle // that. offset = 0L; - if ( WE_HAVE_SG_LIST ) + if ( WE_HAVE_SG_LIST ) thisMappingLen = sg_dma_len(sgl); else thisMappingLen = bytes_to_go; while (thisMappingLen > 0) { - thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? + thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : thisMappingLen; // printk("%d/%d/%d\n", thislen, thisMappingLen, bytes_to_go); - + // should we load into "this" extended S/G page, or allocate // new page? @@ -5313,20 +4984,20 @@ static ULONG build_SEST_sgList( { // Now, we have to map the previous page, (triggering buffer bounce) // The first time thru the loop, there won't be a previous page. - if (prev_page != NULL) // is there a prev page? + if (prev_page != NULL) // is there a prev page? { - // this code is normally kind of hard to trigger, - // you have to use up more than 256 scatter gather + // this code is normally kind of hard to trigger, + // you have to use up more than 256 scatter gather // elements to get here. Cranking down TL_MAX_SG_ELEM_LEN // to an absurdly low value (128 bytes or so) to artificially - // break i/o's into a zillion pieces is how I tested it. + // break i/o's into a zillion pieces is how I tested it. busaddr = cpqfc_pci_map_sg_page(pcidev, ext_sg_page_phys_addr_place, prev_page->page, &prev_page->busaddr, &prev_page->maplen, PairCount); - } + } // Allocate the TL Extended S/G list page. We have // to allocate twice what we want to ensure required TL alignment // (Tachlite TL/TS User Man. Rev 6.0, p 168) @@ -5340,33 +5011,33 @@ static ULONG build_SEST_sgList( // unmap the previous mappings, if any. - cpqfc_undo_SEST_mappings(pcidev, contigaddr, + cpqfc_undo_SEST_mappings(pcidev, contigaddr, Cmnd->request_bufflen, Cmnd->sc_data_direction, sgl, Cmnd->use_sg, sgPages_head, AllocatedPages+1); - // FIXME: testing shows that if we get here, - // it's bad news. (this has been this way for a long + // FIXME: testing shows that if we get here, + // it's bad news. (this has been this way for a long // time though, AFAIK. Not that that excuses it.) return 0; // give up (and probably hang the system) } // clear out memory we just allocated - memset( (*sgpage)->page,0,TL_EXT_SG_PAGE_BYTELEN*2); + memset((*sgpage)->page,0,TL_EXT_SG_PAGE_BYTELEN*2); (*sgpage)->next = NULL; (*sgpage)->busaddr = (dma_addr_t) NULL; (*sgpage)->maplen = 0L; - + // align the memory - TL requires sizeof() Ext. S/G page alignment. - // We doubled the actual required size so we could mask off LSBs - // to get desired offset + // We doubled the actual required size so we could mask off LSBs + // to get desired offset ulBuff = (unsigned long) (*sgpage)->page; ulBuff += TL_EXT_SG_PAGE_BYTELEN; ulBuff &= ~(TL_EXT_SG_PAGE_BYTELEN -1); // set pointer, in SEST if first Ext. S/G page, or in last pair - // of linked Ext. S/G pages... (Only 32-bit PVOIDs, so just + // of linked Ext. S/G pages... (Only 32-bit PVOIDs, so just // load lower 32 bits) // NOTE: the Len field must be '0' if this is the first Ext. S/G // pointer in SEST, and not 0 otherwise (we know thislen != 0). @@ -5374,7 +5045,7 @@ static ULONG build_SEST_sgList( *alPair = (alPair != SESTalPairStart) ? thislen : 0; # ifdef DBG_SEST_SGLIST - printk("PairCount %d @%p even %Xh, ", + printk("PairCount %d @%p even %Xh, ", PairCount, alPair, *alPair); # endif @@ -5394,31 +5065,31 @@ static ULONG build_SEST_sgList( // This message should rarely, if ever, come out. // Previously (cpqfc version <= 2.0.5) the driver would // just puke if more than 4 SG pages were used, and nobody - // ever complained about that. This only comes out if + // ever complained about that. This only comes out if // more than 8 pages are used. printk(KERN_WARNING "cpqfc: Possible danger. %d scatter gather pages used.\n" "cpqfc: detected seemingly extreme memory " - "fragmentation or huge data transfers.\n", + "fragmentation or huge data transfers.\n", AllocatedPages); ap_hi_water = AllocatedPages+1; } - + PairCount = 1; // starting new Ext. S/G page prev_page = (*sgpage); // remember this page, for next time thru sgpage = &((*sgpage)->next); } // end of new TL Ext. S/G page allocation *alPair = thislen; // bits 18-0, length (range check above) - + # ifdef DBG_SEST_SGLIST printk("PairCount %d @%p, even %Xh, ", PairCount, alPair, *alPair); # endif - alPair++; // next DWORD, physical address + alPair++; // next DWORD, physical address - if ( WE_HAVE_SG_LIST ) + if ( WE_HAVE_SG_LIST ) ulBuff = sg_dma_address(sgl) + offset; else ulBuff = contigaddr + offset; @@ -5428,7 +5099,7 @@ static ULONG build_SEST_sgList( if( ulBuff >>32 ) { printk("cqpfcTS: 1Tach DMA address %p > 32 bits\n", (void*)ulBuff ); - printk("%s = %p, offset = %ld\n", + printk("%s = %p, offset = %ld\n", WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr", WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr, offset); @@ -5442,7 +5113,7 @@ static ULONG build_SEST_sgList( printk("odd %Xh\n", *alPair); # endif alPair++; // next DWORD, next address/length pair - + PairCount++; // next Length/Address pair // if (PairCount > pc_hi_water) @@ -5451,7 +5122,7 @@ static ULONG build_SEST_sgList( // pc_hi_water = PairCount; // } bytes_to_go -= thislen; - total_data_len += thislen; + total_data_len += thislen; thisMappingLen -= thislen; totalsgs++; } // while (thisMappingLen > 0) @@ -5464,28 +5135,26 @@ static ULONG build_SEST_sgList( // PCI map (and bounce) the last (and usually only) extended SG page busaddr = cpqfc_pci_map_sg_page(pcidev, ext_sg_page_phys_addr_place, - prev_page->page, - &prev_page->busaddr, + prev_page->page, + &prev_page->busaddr, &prev_page->maplen, PairCount); } return total_data_len; } - - // The Tachlite SEST table is referenced to OX_ID (or RX_ID). To optimize // performance and debuggability, we index the Exchange structure to FC X_ID // This enables us to build exchanges for later en-queing to Tachyon, -// provided we have an open X_ID slot. At Tachyon queing time, we only -// need an ERQ slot; then "fix-up" references in the +// provided we have an open X_ID slot. At Tachyon queing time, we only +// need an ERQ slot; then "fix-up" references in the // IRB, FCHS, etc. as needed. // RETURNS: // 0 if successful // non-zero on error //sstartex -ULONG cpqfcTSStartExchange( - CPQFCHBA *cpqfcHBAdata, +ULONG cpqfcTSStartExchange( + CPQFCHBA *cpqfcHBAdata, LONG ExchangeID ) { PTACHYON fcChip = &cpqfcHBAdata->fcChip; @@ -5499,7 +5168,7 @@ ULONG cpqfcTSStartExchange( ULONG InboundData=0; // We will manipulate Tachlite chip registers here to successfully - // start exchanges. + // start exchanges. // Check that link is not down -- we can't start an exchange on a // down link! @@ -5528,7 +5197,7 @@ printk("fcStartExchange: PSM offline (%X } } - printk("fcStartExchange: Que x_ID %Xh, type %Xh\n", + printk("fcStartExchange: Que x_ID %Xh, type %Xh\n", ExchangeID, pExchange->type); pExchange->status |= EXCHANGE_QUEUED; ulStatus = EXCHANGE_QUEUED; @@ -5536,19 +5205,19 @@ printk("fcStartExchange: PSM offline (%X } // Make sure ERQ has available space. - + producer = (USHORT)fcChip->ERQ->producerIndex; // copies for logical arith. consumer = (USHORT)fcChip->ERQ->consumerIndex; producer++; // We are testing for full que by incrementing - + if( producer >= ERQ_LEN ) // rollover condition? producer = 0; if( consumer != producer ) // ERQ not full? { // ****************** Need Atomic access to chip registers!!******** - + // remember ERQ PI for copying IRB - ErqIndex = (USHORT)fcChip->ERQ->producerIndex; + ErqIndex = (USHORT)fcChip->ERQ->producerIndex; fcChip->ERQ->producerIndex = producer; // this is written to Tachyon // we have an ERQ slot! If SCSI command, need SEST slot // otherwise we are done. @@ -5567,30 +5236,29 @@ printk("fcStartExchange: PSM offline (%X { // ORIGINATOR types... we're setting our OX_ID and // defaulting the responder's RX_ID to 0xFFFF - + case SCSI_IRE: // Requirement: set MSB of x_ID for Incoming TL data // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50) InboundData = 0x8000; - case SCSI_IWE: + case SCSI_IWE: SestType = TRUE; pExchange->fchs.ox_rx_id = (ExchangeID | InboundData); pExchange->fchs.ox_rx_id <<= 16; // MSW shift pExchange->fchs.ox_rx_id |= 0xffff; // add default RX_ID - + // now fix-up the Data HDR OX_ID (TL automatically does rx_id) // (not necessary for IRE -- data buffer unused) if( pExchange->type == SCSI_IWE) { - fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id = + fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id = pExchange->fchs.ox_rx_id; } break; - case FCS_NSR: // ext. link service Name Service Request case ELS_SCR: // ext. link service State Change Registration case ELS_FDISC:// ext. link service login @@ -5606,14 +5274,11 @@ printk("fcStartExchange: PSM offline (%X pExchange->fchs.ox_rx_id |= 0xffff; // and RX_ID break; - - - // RESPONDER types... we must set our RX_ID while preserving // sender's OX_ID // outgoing (or no) data - case ELS_RJT: // extended link service reject + case ELS_RJT: // extended link service reject case ELS_LOGO_ACC: // FC-PH extended link service logout accept case ELS_ACC: // ext. generic link service accept case ELS_PLOGI_ACC:// ext. link service login accept (PLOGI or PDISC) @@ -5624,7 +5289,6 @@ printk("fcStartExchange: PSM offline (%X break; - // since we are a Responder, OX_ID should already be set by // cpqfcTSBuildExchange(). We need to -OR- in RX_ID case SCSI_TWE: @@ -5637,53 +5301,46 @@ printk("fcStartExchange: PSM offline (%X // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50) pExchange->fchs.ox_rx_id |= (ExchangeID | 0x8000); break; - - + case SCSI_TRE: SestType = TRUE; - + // there is no XRDY for SEST target read; the data // header needs to be updated. Also update the RSP // exchange IDs for the status frame, in case it is sent automatically fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id |= ExchangeID; - fcChip->SEST->RspHDR[ ExchangeID ].ox_rx_id = + fcChip->SEST->RspHDR[ ExchangeID ].ox_rx_id = fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id; - - // for easier FCP response logic (works for TWE and TRE), + + // for easier FCP response logic (works for TWE and TRE), // copy exchange IDs. (Not needed if TRE 'RSP' bit set) pExchange->fchs.ox_rx_id = fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id; break; - case FCP_RESPONSE: // using existing OX_ID/ RX_ID pair, // start SFS FCP-RESPONSE frame // OX/RX_ID should already be set! (See "fcBuild" above) CompleteExchange = TRUE; // RSP is end of FCP-SCSI exchange - - break; + break; case BLS_ABTS_RJT: // uses new RX_ID, since SEST x_ID non-existent case BLS_ABTS_ACC: // using existing OX_ID/ RX_ID pair from SEST entry CompleteExchange = TRUE; // ACC or RJT marks end of FCP-SCSI exchange case BLS_ABTS: // using existing OX_ID/ RX_ID pair from SEST entry - break; - default: printk("Error on fcStartExchange: undefined type %Xh(%d)\n", pExchange->type, pExchange->type); return INVALID_ARGS; } - - + // X_ID fields are entered -- copy IRB to Tachyon's ERQ - memcpy( &fcChip->ERQ->QEntry[ ErqIndex ], // dest. @@ -5696,62 +5353,52 @@ printk("fcStartExchange: PSM offline (%X writel( fcChip->ERQ->producerIndex, fcChip->Registers.ERQproducerIndex.address); - if( ExchangeID >= TACH_SEST_LEN ) // Link Service Outbound frame? { - + // wait for completion! (TDB -- timeout and chip reset) - PCI_TRACEO( ExchangeID, 0xA4) - + enable_irq( cpqfcHBAdata->HostAdapter->irq); // only way to get Sem. - - down_interruptible( cpqfcHBAdata->TYOBcomplete); - + + down_interruptible( cpqfcHBAdata->TYOBcomplete); + disable_irq( cpqfcHBAdata->HostAdapter->irq); PCI_TRACE( 0xA4) - // On login exchanges, BAD_ALPA (non-existent port_id) results in + // On login exchanges, BAD_ALPA (non-existent port_id) results in // FTO (Frame Time Out) on the Outbound Completion message. // If we got an FTO status, complete the exchange (free up slot) if( CompleteExchange || // flag from Reply frames pExchange->status ) // typically, can get FRAME_TO { - cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID); + cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID); } } - else // SEST Exchange { ulStatus = 0; // ship & pray success (e.g. FCP-SCSI) - + if( CompleteExchange ) // by Type of exchange (e.g. end-of-xchng) { - cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID); + cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID); } - - else - pExchange->status &= ~EXCHANGE_QUEUED; // clear ExchangeQueued flag + else + pExchange->status &= ~EXCHANGE_QUEUED; // clear ExchangeQueued flag } } - - else // ERQ 'producer' = 'consumer' and QUE is full { ulStatus = OUTQUE_FULL; // Outbound (ERQ) Que full } - -Done: + +Done: PCI_TRACE( 0xA0) - return ulStatus; + return ulStatus; } - - - - // Scan fcController->fcExchanges array for a usuable index (a "free" // exchange). // Inputs: @@ -5763,19 +5410,17 @@ Done: // Although this is a (yuk!) linear search, we presume // that the system will complete exchanges about as quickly as // they are submitted. A full Exchange array (and hence, max linear -// search time for free exchange slot) almost guarantees a Fibre problem +// search time for free exchange slot) almost guarantees a Fibre problem // of some sort. // In the interest of making exchanges easier to debug, we want a LRU // (Least Recently Used) scheme. - static LONG FindFreeExchange( PTACHYON fcChip, ULONG type ) { FC_EXCHANGES *Exchanges = fcChip->Exchanges; ULONG i; ULONG ulStatus=-1; // assume failure - if( type == SCSI_IRE || type == SCSI_TRE || type == SCSI_IWE || @@ -5790,18 +5435,17 @@ static LONG FindFreeExchange( PTACHYON f { ulStatus = 0; // success! } - else { // YUK! we need to do a linear search for free element. // Fragmentation of the fcExchange array is due to excessively // long completions or timeouts. - + while( TRUE ) { if( ++i >= TACH_SEST_LEN ) // rollover check i = 0; // beginning of SEST X_IDs -// printk( "looping for SCSI xchng ID: i=%d, type=%Xh\n", +// printk( "looping for SCSI xchng ID: i=%d, type=%Xh\n", // i, Exchanges->fcExchange[i].type); if( Exchanges->fcExchange[i].type == 0 ) // "free"? @@ -5818,10 +5462,7 @@ static LONG FindFreeExchange( PTACHYON f } fcChip->fcSestExchangeLRU = i + 1; // next! (rollover check next pass) } - - - - else // Link Service type - X_IDs should be from TACH_SEST_LEN + else // Link Service type - X_IDs should be from TACH_SEST_LEN // to TACH_MAX_XID { if( fcChip->fcLsExchangeLRU >= TACH_MAX_XID || // range check @@ -5833,18 +5474,17 @@ static LONG FindFreeExchange( PTACHYON f { ulStatus = 0; // success! } - else { // YUK! we need to do a linear search for free element // Fragmentation of the fcExchange array is due to excessively // long completions or timeouts. - + while( TRUE ) { if( ++i >= TACH_MAX_XID ) // rollover check i = TACH_SEST_LEN;// beginning of Link Service X_IDs -// printk( "looping for xchng ID: i=%d, type=%Xh\n", +// printk( "looping for xchng ID: i=%d, type=%Xh\n", // i, Exchanges->fcExchange[i].type); if( Exchanges->fcExchange[i].type == 0 ) // "free"? @@ -5865,11 +5505,11 @@ static LONG FindFreeExchange( PTACHYON f if( !ulStatus ) // success? Exchanges->fcExchange[i].type = type; // allocate it. - + else i = -1; // error - all exchanges "open" - return i; + return i; } static void @@ -5885,7 +5525,7 @@ cpqfc_pci_unmap_extended_sg(struct pci_d if (! USES_EXTENDED_SGLIST(fcChip->SEST, x_ID)) return; // No such regions, we're outta here. - // for each extended scatter gather region needing unmapping... + // for each extended scatter gather region needing unmapping... for (i=fcChip->SEST->sgPages[x_ID] ; i != NULL ; i = i->next) pci_unmap_single(pcidev, i->busaddr, i->maplen, PCI_DMA_TODEVICE); @@ -5893,9 +5533,9 @@ cpqfc_pci_unmap_extended_sg(struct pci_d // Called also from cpqfcTScontrol.o, so can't be static void -cpqfc_pci_unmap(struct pci_dev *pcidev, - Scsi_Cmnd *cmd, - PTACHYON fcChip, +cpqfc_pci_unmap(struct pci_dev *pcidev, + Scsi_Cmnd *cmd, + PTACHYON fcChip, ULONG x_ID) { // Undo the DMA mappings @@ -5910,7 +5550,7 @@ cpqfc_pci_unmap(struct pci_dev *pcidev, pci_unmap_single(pcidev, fcChip->SEST->u[ x_ID ].IWE.GAddr1, cmd->request_bufflen, cmd->sc_data_direction); - } + } } // We call this routine to free an Exchange for any reason: @@ -5921,14 +5561,14 @@ cpqfc_pci_unmap(struct pci_dev *pcidev, // (e.g. port/device gone). //scompleteexchange -void cpqfcTSCompleteExchange( +void cpqfcTSCompleteExchange( struct pci_dev *pcidev, - PTACHYON fcChip, + PTACHYON fcChip, ULONG x_ID) { FC_EXCHANGES *Exchanges = fcChip->Exchanges; int already_unmapped = 0; - + if( x_ID < TACH_SEST_LEN ) // SEST-based (or LinkServ for FCP exchange) { if( Exchanges->fcExchange[ x_ID ].Cmnd == NULL ) // what#@! @@ -5947,7 +5587,7 @@ void cpqfcTSCompleteExchange( // or abnormal exchange completion { // set FCP Link statistics - + if( Exchanges->fcExchange[ x_ID ].status & FC2_TIMEOUT) fcChip->fcStats.timeouts++; if( Exchanges->fcExchange[ x_ID ].status & INITIATOR_ABORT) @@ -5965,100 +5605,94 @@ void cpqfcTSCompleteExchange( // exchange... if( Exchanges->fcExchange[ x_ID ].status == INITIATOR_ABORT ) { - printk(" DID_ABORT, x_ID %Xh, Cmnd %p ", + printk(" DID_ABORT, x_ID %Xh, Cmnd %p ", x_ID, Exchanges->fcExchange[ x_ID ].Cmnd); goto CleanUpSestResources; // (we don't expect Linux _aborts) } // Did our driver timeout the Exchange, or did Tachyon indicate // a failure during transmission? Ask for retry with "SOFT_ERROR" - else if( Exchanges->fcExchange[ x_ID ].status & FC2_TIMEOUT) + else if( Exchanges->fcExchange[ x_ID ].status & FC2_TIMEOUT) { -// printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", +// printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd); Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16); } - + // Did frame(s) for an open exchange arrive in the SFQ, // meaning the SEST was unable to process them? - else if( Exchanges->fcExchange[ x_ID ].status & SFQ_FRAME) + else if( Exchanges->fcExchange[ x_ID ].status & SFQ_FRAME) { -// printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", +// printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd); Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16); } - + // Did our driver timeout the Exchange, or did Tachyon indicate // a failure during transmission? Ask for retry with "SOFT_ERROR" - else if( + else if( (Exchanges->fcExchange[ x_ID ].status & LINKFAIL_TX) || (Exchanges->fcExchange[ x_ID ].status & PORTID_CHANGED) || (Exchanges->fcExchange[ x_ID ].status & FRAME_TO) || (Exchanges->fcExchange[ x_ID ].status & INV_ENTRY) || (Exchanges->fcExchange[ x_ID ].status & ABORTSEQ_NOTIFY) ) - - { -// printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", +// printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", // x_ID, Exchanges->fcExchange[ x_ID ].Cmnd); Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16); - - } // e.g., a LOGOut happened, or device never logged back in. - else if( Exchanges->fcExchange[ x_ID ].status & DEVICE_REMOVED) + else if( Exchanges->fcExchange[ x_ID ].status & DEVICE_REMOVED) { // printk(" *LOGOut or timeout on login!* "); // trigger? // TriggerHBA( fcChip->Registers.ReMapMemBase, 0); Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_BAD_TARGET <<16); - } - - + } + // Did Tachyon indicate a CNT error? We need further analysis // to determine if the exchange is acceptable else if( Exchanges->fcExchange[ x_ID ].status == COUNT_ERROR) { UCHAR ScsiStatus; - FCP_STATUS_RESPONSE *pFcpStatus = + FCP_STATUS_RESPONSE *pFcpStatus = (PFCP_STATUS_RESPONSE)&fcChip->SEST->RspHDR[ x_ID ].pl; ScsiStatus = pFcpStatus->fcp_status >>24; - + // If the command is a SCSI Read/Write type, we don't tolerate // count errors of any kind; assume the count error is due to // a dropped frame and ask for retry... - + if(( (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x8) || - (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x28) || + (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x28) || (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0xA) || (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x2A) ) && ScsiStatus == 0 ) { // ask for retry -/* printk("COUNT_ERROR retry, x_ID %Xh, status %Xh, Cmnd %p\n", +/* printk("COUNT_ERROR retry, x_ID %Xh, status %Xh, Cmnd %p\n", x_ID, Exchanges->fcExchange[ x_ID ].status, Exchanges->fcExchange[ x_ID ].Cmnd);*/ Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16); } - else // need more analysis { cpqfcTSCheckandSnoopFCP(fcChip, x_ID); // (will set ->result) } } - + // default: NOTE! We don't ever want to get here. Getting here // implies something new is happening that we've never had a test // case for. Need code maintenance! Return "ERROR" else { unsigned int stat = Exchanges->fcExchange[ x_ID ].status; - printk("DEFAULT result %Xh, x_ID %Xh, Cmnd %p", - Exchanges->fcExchange[ x_ID ].status, x_ID, + printk("DEFAULT result %Xh, x_ID %Xh, Cmnd %p", + Exchanges->fcExchange[ x_ID ].status, x_ID, Exchanges->fcExchange[ x_ID ].Cmnd); if (stat & INVALID_ARGS) printk(" INVALID_ARGS "); @@ -6095,10 +5729,10 @@ void cpqfcTSCompleteExchange( { // set FCP Link statistic fcChip->fcStats.ok++; - cpqfcTSCheckandSnoopFCP( fcChip, x_ID); // (will set ->result) + cpqfcTSCheckandSnoopFCP( fcChip, x_ID); // (will set ->result) } - cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, + cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, fcChip, x_ID); // undo DMA mappings. already_unmapped = 1; @@ -6126,17 +5760,16 @@ void cpqfcTSCompleteExchange( } else{ printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID, - Exchanges->fcExchange[ x_ID ].type, - Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]); + Exchanges->fcExchange[ x_ID ].type, + Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]); printk(" cpqfcTS: Null scsi_done function pointer!\n"); } - // Now, clean up non-Scsi_Cmnd items... CleanUpSestResources: - - if (!already_unmapped) - cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, + + if (!already_unmapped) + cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, fcChip, x_ID); // undo DMA mappings. // Was an Extended Scatter/Gather page allocated? We know @@ -6152,36 +5785,29 @@ CleanUpSestResources: } fcChip->SEST->sgPages[x_ID] = NULL; } - - Exchanges->fcExchange[ x_ID ].Cmnd = NULL; - } // Done with FCP (SEST) exchanges + Exchanges->fcExchange[ x_ID ].Cmnd = NULL; + } // Done with FCP (SEST) exchanges - // the remaining logic is common to ALL Exchanges: + // the remaining logic is common to ALL Exchanges: // FCP(SEST) and LinkServ. - Exchanges->fcExchange[ x_ID ].type = 0; // there -- FREE! - Exchanges->fcExchange[ x_ID ].status = 0; + Exchanges->fcExchange[ x_ID ].type = 0; // there -- FREE! + Exchanges->fcExchange[ x_ID ].status = 0; PCI_TRACEO( x_ID, 0xAC) - - - return; } // (END of CompleteExchange function) - - - // Unfortunately, we must snoop all command completions in // order to manipulate certain return fields, and take note of // device types, etc., to facilitate the Fibre-Channel to SCSI -// "mapping". +// "mapping". // (Watch for BIG Endian confusion on some payload fields) void cpqfcTSCheckandSnoopFCP( PTACHYON fcChip, ULONG x_ID) { FC_EXCHANGES *Exchanges = fcChip->Exchanges; Scsi_Cmnd *Cmnd = Exchanges->fcExchange[ x_ID].Cmnd; - FCP_STATUS_RESPONSE *pFcpStatus = + FCP_STATUS_RESPONSE *pFcpStatus = (PFCP_STATUS_RESPONSE)&fcChip->SEST->RspHDR[ x_ID ].pl; UCHAR ScsiStatus; @@ -6189,7 +5815,7 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f #ifdef FCP_COMPLETION_DBG printk("ScsiStatus = 0x%X\n", ScsiStatus); -#endif +#endif // First, check FCP status if( pFcpStatus->fcp_status & FCP_RSP_LEN_VALID ) @@ -6197,7 +5823,7 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f // check response code (RSP_CODE) -- most popular is bad len // 1st 4 bytes of rsp info -- only byte 3 interesting if( pFcpStatus->fcp_rsp_info & FCP_DATA_LEN_NOT_BURST_LEN ) - { + { // do we EVER get here? printk("cpqfcTS: FCP data len not burst len, x_ID %Xh\n", x_ID); @@ -6210,7 +5836,7 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f { Cmnd->result = 0; // everything's OK - if( (Cmnd->cmnd[0] == INQUIRY)) + if( (Cmnd->cmnd[0] == INQUIRY)) { UCHAR *InquiryData = Cmnd->request_buffer; PFC_LOGGEDIN_PORT pLoggedInPort; @@ -6227,15 +5853,15 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f // so multiple LUNs may be scanned. // (no SCSI-2 problems known in CPQ) } - + // snoop the Inquiry to detect Disk, Tape, etc. type // (search linked list for the port_id we sent INQUIRY to) pLoggedInPort = fcFindLoggedInPort( fcChip, NULL, // DON'T search Scsi Nexus (we will set it) - Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF, + Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF, NULL, // DON'T search linked list for FC WWN NULL); // DON'T care about end of list - + if( pLoggedInPort ) { pLoggedInPort->ScsiNexus.InqDeviceType = InquiryData[0]; @@ -6247,33 +5873,29 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f } } } - - - // Scsi Status not good -- pass it back to caller - + // Scsi Status not good -- pass it back to caller else { Cmnd->result = ScsiStatus; // SCSI status byte is 1st - + // check for valid "sense" data - if( pFcpStatus->fcp_status & FCP_SNS_LEN_VALID ) + if( pFcpStatus->fcp_status & FCP_SNS_LEN_VALID ) { // limit Scsi Sense field length! int SenseLen = pFcpStatus->fcp_sns_len >>24; // (BigEndian) lower byte - - SenseLen = SenseLen > sizeof( Cmnd->sense_buffer) ? - sizeof( Cmnd->sense_buffer) : SenseLen; - -#ifdef FCP_COMPLETION_DBG + SenseLen = SenseLen > sizeof(Cmnd->sense_buffer) ? + sizeof(Cmnd->sense_buffer) : SenseLen; + +#ifdef FCP_COMPLETION_DBG printk("copy sense_buffer %p, len %d, result %Xh\n", Cmnd->sense_buffer, SenseLen, Cmnd->result); -#endif +#endif // NOTE: There is some dispute over the FCP response // format. Most FC devices assume that FCP_RSP_INFO // is 8 bytes long, in spite of the fact that FCP_RSP_LEN - // is (virtually) always 0 and the field is "invalid". + // is (virtually) always 0 and the field is "invalid". // Some other devices assume that // the FCP_SNS_INFO begins after FCP_RSP_LEN bytes (i.e. 0) // when the FCP_RSP is invalid (this almost appears to be @@ -6283,16 +5905,16 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f // byte ("error code") should be 0x70 or 0x71. In practice, // we find that every device does in fact have 0x70 or 0x71 // in the first byte position, so this test works for all - // FC devices. + // FC devices. // (This logic is especially effective for the CPQ/DEC HSG80 // & HSG60 controllers). if( (pFcpStatus->fcp_sns_info[0] & 0x70) == 0x70 ) - memcpy( Cmnd->sense_buffer, + memcpy( Cmnd->sense_buffer, &pFcpStatus->fcp_sns_info[0], SenseLen); else { - unsigned char *sbPtr = + unsigned char *sbPtr = (unsigned char *)&pFcpStatus->fcp_sns_info[0]; sbPtr -= 8; // back up 8 bytes hoping to find the // start of the sense buffer @@ -6304,27 +5926,26 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f // look for Sense Key Unit Attention (0x6) with ASC Device // Reset (0x29) // printk("SenseLen %d, Key = 0x%X, ASC = 0x%X\n", - // SenseLen, Cmnd->sense_buffer[2], + // SenseLen, Cmnd->sense_buffer[2], // Cmnd->sense_buffer[12]); if( ((Cmnd->sense_buffer[2] & 0xF) == 0x6) && (Cmnd->sense_buffer[12] == 0x29) ) // Sense Code "reset" { Cmnd->result |= (DID_SOFT_ERROR << 16); // "Host" status byte 3rd } - + // check for SenseKey "HARDWARE ERROR", ASC InternalTargetFailure else if( ((Cmnd->sense_buffer[2] & 0xF) == 0x4) && // "hardware error" - (Cmnd->sense_buffer[12] == 0x44) ) // Addtl. Sense Code + (Cmnd->sense_buffer[12] == 0x44) ) // Addtl. Sense Code { // printk("HARDWARE_ERROR, Channel/Target/Lun %d/%d/%d\n", // Cmnd->channel, Cmnd->target, Cmnd->lun); Cmnd->result |= (DID_ERROR << 16); // "Host" status byte 3rd } - } // (end of sense len valid) // there is no sense data to help out Linux's Scsi layers... - // We'll just return the Scsi status and hope he will "do the + // We'll just return the Scsi status and hope he will "do the // right thing" else { @@ -6334,24 +5955,21 @@ void cpqfcTSCheckandSnoopFCP( PTACHYON f } } - - //PPPPPPPPPPPPPPPPPPPPPPPPP PAYLOAD PPPPPPPPP // build data PAYLOAD; SCSI FCP_CMND I.U. // remember BIG ENDIAN payload - DWord values must be byte-reversed // (hence the affinity for byte pointer building). -static int build_FCP_payload( Scsi_Cmnd *Cmnd, +static int build_FCP_payload( Scsi_Cmnd *Cmnd, UCHAR* payload, ULONG type, ULONG fcp_dl ) { int i; - switch( type) { - - case SCSI_IWE: - case SCSI_IRE: + + case SCSI_IWE: + case SCSI_IRE: // 8 bytes FCP_LUN // Peripheral Device or Volume Set addressing, and LUN mapping // When the FC port was looked up, we copied address mode @@ -6359,17 +5977,17 @@ static int build_FCP_payload( Scsi_Cmnd *payload++ = (UCHAR)Cmnd->SCp.phase; - // Now, because of "lun masking" + // Now, because of "lun masking" // (aka selective storage presentation), // the contiguous Linux Scsi lun number may not match the - // device's lun number, so we may have to "map". - + // device's lun number, so we may have to "map". + *payload++ = (UCHAR)Cmnd->SCp.have_data_in; - - // We don't know of anyone in the FC business using these + + // We don't know of anyone in the FC business using these // extra "levels" of addressing. In fact, confusion still exists // just using the FIRST level... ;-) - + *payload++ = 0; // 2nd level addressing *payload++ = 0; *payload++ = 0; // 3rd level addressing @@ -6394,7 +6012,7 @@ static int build_FCP_payload( Scsi_Cmnd *payload++ = 0; // no TDR // byte 3: (LSB) execution management codes // bit 0 write, bit 1 read (don't set together) - + if( fcp_dl != 0 ) { if( type == SCSI_IWE ) // WRITE @@ -6410,7 +6028,6 @@ static int build_FCP_payload( Scsi_Cmnd *payload++ = 0; // no data (necessary for CPQ) } - // NOTE: clean this up if/when MAX_COMMAND_SIZE is increased to 16 // FCP_CDB allows 16 byte SCSI command descriptor blk; // Linux SCSI CDB array is MAX_COMMAND_SIZE (12 at this time...) @@ -6421,7 +6038,7 @@ static int build_FCP_payload( Scsi_Cmnd // { // memcpy( payload, &Cmnd->SCp.buffers_residual, 4); // } - payload+= (16 - i); + payload += (16 - i); // FCP_DL is largest number of expected data bytes // per CDB (i.e. read/write command) @@ -6455,4 +6072,3 @@ static int build_FCP_payload( Scsi_Cmnd return 0; } -