cpqfcTSinit.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:60k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* Copyright(c) 2000, Compaq Computer Corporation 
  2.  * Fibre Channel Host Bus Adapter 
  3.  * 64-bit, 66MHz PCI 
  4.  * Originally developed and tested on:
  5.  * (front): [chip] Tachyon TS HPFC-5166A/1.2  L2C1090 ...
  6.  *          SP# P225CXCBFIEL6T, Rev XC
  7.  *          SP# 161290-001, Rev XD
  8.  * (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify it
  11.  * under the terms of the GNU General Public License as published by the
  12.  * Free Software Foundation; either version 2, or (at your option) any
  13.  * later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful, but
  16.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18.  * General Public License for more details.
  19.  * Written by Don Zimmerman
  20.  * IOCTL and procfs added by Jouke Numan
  21.  * SMP testing by Chel Van Gennip
  22.  *
  23.  * portions copied from:
  24.  * QLogic CPQFCTS SCSI-FCP
  25.  * Written by Erik H. Moe, ehm@cris.com
  26.  * Copyright 1995, Erik H. Moe
  27.  * Renamed and updated to 1.3.x by Michael Griffith <grif@cs.ucr.edu> 
  28.  * Chris Loveland <cwl@iol.unh.edu> to support the isp2100 and isp2200
  29. */
  30. #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
  31. #include <linux/blk.h>
  32. #include <linux/kernel.h>
  33. #include <linux/string.h>
  34. #include <linux/sched.h>
  35. #include <linux/types.h>
  36. #include <linux/pci.h>
  37. #include <linux/delay.h>
  38. #include <linux/timer.h>
  39. #include <linux/ioport.h>  // request_region() prototype
  40. #include <linux/vmalloc.h> // ioremap()
  41. #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
  42. #include <linux/completion.h>
  43. #endif
  44. #ifdef __alpha__
  45. #define __KERNEL_SYSCALLS__
  46. #endif
  47. #include <asm/unistd.h>
  48. #include <asm/io.h>
  49. #include <asm/uaccess.h>   // ioctl related
  50. #include <asm/irq.h>
  51. #include <linux/spinlock.h>
  52. #include "sd.h"
  53. #include <scsi/scsi_ioctl.h>
  54. #include "hosts.h"
  55. #include "cpqfcTSchip.h"
  56. #include "cpqfcTSstructs.h"
  57. #include "cpqfcTStrigger.h"
  58. #include "cpqfcTS.h"
  59. #include <linux/config.h>  
  60. #include <linux/module.h>
  61. #include <linux/version.h> 
  62. /* Embedded module documentation macros - see module.h */
  63. MODULE_AUTHOR("Compaq Computer Corporation");
  64. MODULE_DESCRIPTION("Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA v. 2.1.1");
  65. MODULE_LICENSE("GPL");
  66.   
  67. int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, unsigned int reset_flags);
  68. // This struct was originally defined in 
  69. // /usr/src/linux/include/linux/proc_fs.h
  70. // since it's only partially implemented, we only use first
  71. // few fields...
  72. // NOTE: proc_fs changes in 2.4 kernel
  73. #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
  74. static struct proc_dir_entry proc_scsi_cpqfcTS =
  75. {
  76.   PROC_SCSI_CPQFCTS,           // ushort low_ino (enumerated list)
  77.   7,                           // ushort namelen
  78.   DEV_NAME,                    // const char* name
  79.   S_IFDIR | S_IRUGO | S_IXUGO, // mode_t mode
  80.   2                            // nlink_t nlink
  81.                        // etc. ...
  82. };
  83. #endif
  84. #if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
  85. #  define CPQFC_DECLARE_COMPLETION(x) DECLARE_COMPLETION(x)
  86. #  define CPQFC_WAITING waiting
  87. #  define CPQFC_COMPLETE(x) complete(x)
  88. #  define CPQFC_WAIT_FOR_COMPLETION(x) wait_for_completion(x);
  89. #else
  90. #  define CPQFC_DECLARE_COMPLETION(x) DECLARE_MUTEX_LOCKED(x)
  91. #  define CPQFC_WAITING sem
  92. #  define CPQFC_COMPLETE(x) up(x)
  93. #  define CPQFC_WAIT_FOR_COMPLETION(x) down(x)
  94. #endif
  95. /* local function to load our per-HBA (local) data for chip
  96.    registers, FC link state, all FC exchanges, etc.
  97.    We allocate space and compute address offsets for the
  98.    most frequently accessed addresses; others (like World Wide
  99.    Name) are not necessary.
  100.    
  101. */
  102. static void Cpqfc_initHBAdata( CPQFCHBA *cpqfcHBAdata, struct pci_dev *PciDev )
  103. {
  104.              
  105.   cpqfcHBAdata->PciDev = PciDev; // copy PCI info ptr
  106.   // since x86 port space is 64k, we only need the lower 16 bits
  107.   cpqfcHBAdata->fcChip.Registers.IOBaseL = 
  108.     PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
  109.   
  110.   cpqfcHBAdata->fcChip.Registers.IOBaseU = 
  111.     PciDev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
  112.   
  113.   // 32-bit memory addresses
  114.   cpqfcHBAdata->fcChip.Registers.MemBase = 
  115.     PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK;
  116.   cpqfcHBAdata->fcChip.Registers.ReMapMemBase = 
  117.     ioremap( PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK,
  118.              0x200);
  119.   
  120.   cpqfcHBAdata->fcChip.Registers.RAMBase = 
  121.     PciDev->resource[4].start;
  122.   
  123.   cpqfcHBAdata->fcChip.Registers.SROMBase =  // NULL for HP TS adapter
  124.     PciDev->resource[5].start;
  125.   
  126.   // now the Tachlite chip registers
  127.   // the REGISTER struct holds both the physical address & last
  128.   // written value (some TL registers are WRITE ONLY)
  129.   cpqfcHBAdata->fcChip.Registers.SFQconsumerIndex.address = 
  130.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_SFQ_CONSUMER_INDEX;
  131.   cpqfcHBAdata->fcChip.Registers.ERQproducerIndex.address = 
  132.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_ERQ_PRODUCER_INDEX;
  133.       
  134.   // TL Frame Manager
  135.   cpqfcHBAdata->fcChip.Registers.FMconfig.address = 
  136.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_CONFIG;
  137.   cpqfcHBAdata->fcChip.Registers.FMcontrol.address = 
  138.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_CONTROL;
  139.   cpqfcHBAdata->fcChip.Registers.FMstatus.address = 
  140.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_STATUS;
  141.   cpqfcHBAdata->fcChip.Registers.FMLinkStatus1.address = 
  142.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_LINK_STAT1;
  143.   cpqfcHBAdata->fcChip.Registers.FMLinkStatus2.address = 
  144.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_LINK_STAT2;
  145.   cpqfcHBAdata->fcChip.Registers.FMBB_CreditZero.address = 
  146.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_BB_CREDIT0;
  147.       
  148.       // TL Control Regs
  149.   cpqfcHBAdata->fcChip.Registers.TYconfig.address = 
  150.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_CONFIG;
  151.   cpqfcHBAdata->fcChip.Registers.TYcontrol.address = 
  152.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_CONTROL;
  153.   cpqfcHBAdata->fcChip.Registers.TYstatus.address = 
  154.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_STATUS;
  155.   cpqfcHBAdata->fcChip.Registers.rcv_al_pa.address = 
  156.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_RCV_AL_PA;
  157.   cpqfcHBAdata->fcChip.Registers.ed_tov.address = 
  158.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_ED_TOV;
  159.   cpqfcHBAdata->fcChip.Registers.INTEN.address = 
  160.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTEN;
  161.   cpqfcHBAdata->fcChip.Registers.INTPEND.address = 
  162.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTPEND;
  163.   cpqfcHBAdata->fcChip.Registers.INTSTAT.address = 
  164.         cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTSTAT;
  165.   DEBUG_PCI(printk("  cpqfcHBAdata->fcChip.Registers. :n"));
  166.   DEBUG_PCI(printk("    IOBaseL = %xn", 
  167.     cpqfcHBAdata->fcChip.Registers.IOBaseL));
  168.   DEBUG_PCI(printk("    IOBaseU = %xn", 
  169.     cpqfcHBAdata->fcChip.Registers.IOBaseU));
  170.   
  171.   printk(" ioremap'd Membase: %pn", cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
  172.   
  173.   DEBUG_PCI(printk("    SFQconsumerIndex.address = %pn", 
  174.     cpqfcHBAdata->fcChip.Registers.SFQconsumerIndex.address));
  175.   DEBUG_PCI(printk("    ERQproducerIndex.address = %pn", 
  176.     cpqfcHBAdata->fcChip.Registers.ERQproducerIndex.address));
  177.   DEBUG_PCI(printk("    TYconfig.address = %pn", 
  178.     cpqfcHBAdata->fcChip.Registers.TYconfig.address));
  179.   DEBUG_PCI(printk("    FMconfig.address = %pn", 
  180.     cpqfcHBAdata->fcChip.Registers.FMconfig.address));
  181.   DEBUG_PCI(printk("    FMcontrol.address = %pn", 
  182.     cpqfcHBAdata->fcChip.Registers.FMcontrol.address));
  183.   // set default options for FC controller (chip)
  184.   cpqfcHBAdata->fcChip.Options.initiator = 1;  // default: SCSI initiator
  185.   cpqfcHBAdata->fcChip.Options.target = 0;     // default: SCSI target
  186.   cpqfcHBAdata->fcChip.Options.extLoopback = 0;// default: no loopback @GBIC
  187.   cpqfcHBAdata->fcChip.Options.intLoopback = 0;// default: no loopback inside chip
  188.   // set highest and lowest FC-PH version the adapter/driver supports
  189.   // (NOT strict compliance)
  190.   cpqfcHBAdata->fcChip.highest_FCPH_ver = FC_PH3;
  191.   cpqfcHBAdata->fcChip.lowest_FCPH_ver = FC_PH43;
  192.   // set function points for this controller / adapter
  193.   cpqfcHBAdata->fcChip.ResetTachyon = CpqTsResetTachLite;
  194.   cpqfcHBAdata->fcChip.FreezeTachyon = CpqTsFreezeTachlite;
  195.   cpqfcHBAdata->fcChip.UnFreezeTachyon = CpqTsUnFreezeTachlite;
  196.   cpqfcHBAdata->fcChip.CreateTachyonQues = CpqTsCreateTachLiteQues;
  197.   cpqfcHBAdata->fcChip.DestroyTachyonQues = CpqTsDestroyTachLiteQues;
  198.   cpqfcHBAdata->fcChip.InitializeTachyon = CpqTsInitializeTachLite;  
  199.   cpqfcHBAdata->fcChip.LaserControl = CpqTsLaserControl;  
  200.   cpqfcHBAdata->fcChip.ProcessIMQEntry = CpqTsProcessIMQEntry;
  201.   cpqfcHBAdata->fcChip.InitializeFrameManager = CpqTsInitializeFrameManager;;  
  202.   cpqfcHBAdata->fcChip.ReadWriteWWN = CpqTsReadWriteWWN;
  203.   cpqfcHBAdata->fcChip.ReadWriteNVRAM = CpqTsReadWriteNVRAM;
  204.  
  205. }
  206. /* (borrowed from linux/drivers/scsi/hosts.c) */
  207. static void launch_FCworker_thread(struct Scsi_Host *HostAdapter)
  208. {
  209.   DECLARE_MUTEX_LOCKED(sem);
  210.   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  211.   ENTER("launch_FC_worker_thread");
  212.              
  213.   cpqfcHBAdata->notify_wt = &sem;
  214.   /* must unlock before kernel_thread(), for it may cause a reschedule. */
  215.   spin_unlock_irq(&io_request_lock);
  216.   kernel_thread((int (*)(void *))cpqfcTSWorkerThread, 
  217.                           (void *) HostAdapter, 0);
  218.   /*
  219.    * Now wait for the kernel error thread to initialize itself
  220.    */
  221.   down (&sem);
  222.   spin_lock_irq(&io_request_lock);
  223.   cpqfcHBAdata->notify_wt = NULL;
  224.   LEAVE("launch_FC_worker_thread");
  225.  
  226. }
  227. /* "Entry" point to discover if any supported PCI 
  228.    bus adapter can be found
  229. */
  230. // We're supporting:
  231. // Compaq 64-bit, 66MHz HBA with Tachyon TS
  232. // Agilent XL2 
  233. #define HBA_TYPES 2
  234. int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
  235. {
  236.   int NumberOfAdapters=0; // how many of our PCI adapters are found?
  237.   struct pci_dev *PciDev = NULL;
  238.   struct Scsi_Host *HostAdapter = NULL;
  239.   CPQFCHBA *cpqfcHBAdata = NULL; 
  240.   struct timer_list *cpqfcTStimer = NULL;
  241.   SupportedPCIcards PCIids[HBA_TYPES];
  242.   int i;
  243.   
  244.   ENTER("cpqfcTS_detect");
  245.   
  246. #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
  247.   ScsiHostTemplate->proc_dir = &proc_scsi_cpqfcTS;
  248. #else
  249.   ScsiHostTemplate->proc_name = "cpqfcTS";
  250. #endif
  251.   
  252.   if( pci_present() == 0) // no PCI busses?
  253.   {
  254.     printk( "  no PCI bus?@#!n");
  255.     return NumberOfAdapters;
  256.   }
  257.   // what HBA adapters are we supporting?
  258.   PCIids[0].vendor_id = PCI_VENDOR_ID_COMPAQ;
  259.   PCIids[0].device_id = CPQ_DEVICE_ID;
  260.   PCIids[1].vendor_id = PCI_VENDOR_ID_HP; // i.e. 103Ch (Agilent == HP for now)
  261.   PCIids[1].device_id = AGILENT_XL2_ID;   // i.e. 1029h
  262.   for( i=0; i < HBA_TYPES; i++)
  263.   {
  264.     // look for all HBAs of each type
  265.     while( (PciDev =
  266.       pci_find_device( PCIids[i].vendor_id, PCIids[i].device_id, PciDev) ))
  267.     {
  268.       if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) {
  269. printk(KERN_WARNING 
  270. "cpqfc: HBA cannot support required DMA mask, skipping.n");
  271. continue;
  272.       }
  273.       // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes...
  274.       printk(" scsi_register allocating %d bytes for FC HBAn",
  275.       (ULONG)sizeof(CPQFCHBA));
  276.       HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) );
  277.       
  278.       if(HostAdapter == NULL)
  279.        continue;
  280.       DEBUG_PCI( printk("  HBA found!n"));
  281.       DEBUG_PCI( printk("  HostAdapter->PciDev->irq = %un", PciDev->irq) );
  282.       DEBUG_PCI(printk("  PciDev->baseaddress[0]= %lxn", 
  283. PciDev->resource[0].start));
  284.       DEBUG_PCI(printk("  PciDev->baseaddress[1]= %lxn", 
  285. PciDev->resource[1].start));
  286.       DEBUG_PCI(printk("  PciDev->baseaddress[2]= %lxn", 
  287. PciDev->resource[2].start));
  288.       DEBUG_PCI(printk("  PciDev->baseaddress[3]= %lxn", 
  289. PciDev->resource[3].start));
  290.       scsi_set_pci_device(HostAdapter, PciDev);      
  291.       HostAdapter->irq = PciDev->irq;  // copy for Scsi layers
  292.       
  293.       // HP Tachlite uses two (255-byte) ranges of Port I/O (lower & upper),
  294.       // for a total I/O port address space of 512 bytes.
  295.       // mask out the I/O port address (lower) & record
  296.       HostAdapter->io_port = (unsigned int)
  297.      PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
  298.       HostAdapter->n_io_port = 0xff;
  299.       
  300.       // i.e., expect 128 targets (arbitrary number), while the
  301.       //  RA-4000 supports 32 LUNs
  302.       HostAdapter->max_id =  0;   // incremented as devices log in    
  303.       HostAdapter->max_lun = CPQFCTS_MAX_LUN;         // LUNs per FC device
  304.       HostAdapter->max_channel = CPQFCTS_MAX_CHANNEL; // multiple busses?
  305.       
  306.       // get the pointer to our HBA specific data... (one for
  307.       // each HBA on the PCI bus(ses)).
  308.       cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  309.       
  310.       // make certain our data struct is clear
  311.       memset( cpqfcHBAdata, 0, sizeof( CPQFCHBA ) );
  312.       // initialize our HBA info
  313.       cpqfcHBAdata->HBAnum = NumberOfAdapters;
  314.       cpqfcHBAdata->HostAdapter = HostAdapter; // back ptr
  315.       Cpqfc_initHBAdata( cpqfcHBAdata, PciDev ); // fill MOST fields
  316.      
  317.       cpqfcHBAdata->HBAnum = NumberOfAdapters;
  318.       cpqfcHBAdata->hba_spinlock = SPIN_LOCK_UNLOCKED;
  319.       // request necessary resources and check for conflicts
  320.       if( request_irq( HostAdapter->irq,
  321.        cpqfcTS_intr_handler,
  322.                SA_INTERRUPT | SA_SHIRQ,
  323.                DEV_NAME,
  324.        HostAdapter) )
  325.       {
  326. printk(" IRQ %u already usedn", HostAdapter->irq);
  327.         scsi_unregister( HostAdapter);
  328. continue;
  329.       }
  330.       // Since we have two 256-byte I/O port ranges (upper
  331.       // and lower), check them both
  332.       if( check_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff) )
  333.       {
  334. printk("  cpqfcTS address in use: %xn", 
  335. cpqfcHBAdata->fcChip.Registers.IOBaseU);
  336. free_irq( HostAdapter->irq, HostAdapter);
  337.         scsi_unregister( HostAdapter);
  338. continue;
  339.       }
  340.       
  341.       if( check_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff) )
  342.       {
  343.    printk("  cpqfcTS address in use: %xn", 
  344.        cpqfcHBAdata->fcChip.Registers.IOBaseL);
  345. free_irq( HostAdapter->irq, HostAdapter);
  346.         scsi_unregister( HostAdapter);
  347. continue;
  348.       }
  349.       
  350.       // OK, we should be able to grab everything we need now.
  351.       request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME);
  352.       request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff, DEV_NAME);
  353.       DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %xn",
  354.         cpqfcHBAdata->fcChip.Registers.IOBaseL ));
  355.       DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %xn",
  356.         cpqfcHBAdata->fcChip.Registers.IOBaseU ));
  357.       
  358.       // start our kernel worker thread
  359.       launch_FCworker_thread(HostAdapter);
  360.       // start our TimerTask...
  361.       cpqfcTStimer = &cpqfcHBAdata->cpqfcTStimer;
  362.       init_timer( cpqfcTStimer); // Linux clears next/prev values
  363.       cpqfcTStimer->expires = jiffies + HZ; // one second
  364.       cpqfcTStimer->data = (unsigned long)cpqfcHBAdata; // this adapter
  365.       cpqfcTStimer->function = cpqfcTSheartbeat; // handles timeouts, housekeeping
  366.       add_timer( cpqfcTStimer);  // give it to Linux
  367.       // now initialize our hardware...
  368.       if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) {
  369. printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.n");
  370. // FIXME: might want to do something better than nothing here.
  371.       }
  372.       cpqfcHBAdata->fcStatsTime = jiffies;  // (for FC Statistics delta)
  373.       
  374.       // give our HBA time to initialize and login current devices...
  375.       {
  376. // The Brocade switch (e.g. 2400, 2010, etc.) as of March 2000,
  377. // has the following algorithm for FL_Port startup:
  378. // Time(sec) Action
  379. // 0:        Device Plugin and LIP(F7,F7) transmission
  380. // 1.0       LIP incoming
  381.         // 1.027     LISA incoming, no CLS! (link not up)
  382. // 1.028     NOS incoming (switch test for N_Port)
  383.         // 1.577     ED_TOV expired, transmit LIPs again
  384. // 3.0       LIP(F8,F7) incoming (switch passes Tach Prim.Sig)
  385. // 3.028     LILP received, link up, FLOGI starts
  386. // slowest(worst) case, measured on 1Gb Finisar GT analyzer
  387. unsigned long stop_time;
  388.         spin_unlock_irq(&io_request_lock);
  389. stop_time = jiffies + 4*HZ;
  390.         while ( time_before(jiffies, stop_time) ) 
  391.    schedule();  // (our worker task needs to run)
  392. spin_lock_irq(&io_request_lock);
  393.       }
  394.       
  395.       NumberOfAdapters++; 
  396.     } // end of while()
  397.   }
  398.   LEAVE("cpqfcTS_detect");
  399.  
  400.   return NumberOfAdapters;
  401. }
  402. static void my_ioctl_done (Scsi_Cmnd * SCpnt)
  403. {
  404.     struct request * req;
  405.     
  406.     req = &SCpnt->request;
  407.     req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
  408.   
  409.     if (req->CPQFC_WAITING != NULL)
  410. CPQFC_COMPLETE(req->CPQFC_WAITING);
  411. }   
  412. int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
  413. {
  414.   int result = 0;
  415.   struct Scsi_Host *HostAdapter = ScsiDev->host;
  416.   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  417.   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  418.   PFC_LOGGEDIN_PORT pLoggedInPort;
  419.   Scsi_Cmnd DumCmnd;
  420.   int i, j;
  421.   VENDOR_IOCTL_REQ ioc;
  422.   cpqfc_passthru_t *vendor_cmd;
  423.   Scsi_Device *SDpnt;
  424.   Scsi_Cmnd *ScsiPassThruCmnd;
  425.   ENTER("cpqfcTS_ioctl ");
  426.   
  427.   // can we find an FC device mapping to this SCSI target?
  428.   DumCmnd.channel = ScsiDev->channel; // For searching
  429.   DumCmnd.target  = ScsiDev->id;
  430.   pLoggedInPort = fcFindLoggedInPort( fcChip,
  431.     &DumCmnd, // search Scsi Nexus
  432.     0,        // DON'T search linked list for FC port id
  433.     NULL,     // DON'T search linked list for FC WWN
  434.     NULL);    // DON'T care about end of list
  435.  
  436.   if( pLoggedInPort == NULL )      // not found!
  437.   {
  438.     result = -ENXIO;
  439.   }
  440.  
  441.   else  // we know what FC device to operate on...
  442.   {
  443. // printk("ioctl CMND %d", Cmnd);
  444.     switch (Cmnd) 
  445.     {
  446.       // Passthrough provides a mechanism to bypass the RAID
  447.       // or other controller and talk directly to the devices
  448.       // (e.g. physical disk drive)
  449.       // Passthrough commands, unfortunately, tend to be vendor
  450.       // specific; this is tailored to COMPAQ's RAID (RA4x00)
  451.       case CPQFCTS_SCSI_PASSTHRU:
  452.       {
  453. void *buf = NULL; // for kernel space buffer for user data
  454. if( !arg)
  455.   return -EINVAL;
  456. // must be super user to send stuff directly to the
  457. // controller and/or physical drives...
  458. if( !suser() )
  459.   return -EPERM;
  460. // copy the caller's struct to our space.
  461.         if( copy_from_user( &ioc, arg, sizeof( VENDOR_IOCTL_REQ)))
  462. return( -EFAULT);
  463. vendor_cmd = ioc.argp;  // i.e., CPQ specific command struct
  464. // If necessary, grab a kernel/DMA buffer
  465. if( vendor_cmd->len)
  466. {
  467.      buf = kmalloc( vendor_cmd->len, GFP_KERNEL);
  468.   if( !buf)
  469.     return -ENOMEM;
  470. }
  471.         // Now build a SCSI_CMND to pass down...
  472. // This function allocates and sets Scsi_Cmnd ptrs such as
  473. //  ->channel, ->target, ->host
  474.         ScsiPassThruCmnd = scsi_allocate_device(ScsiDev, 1, 1);
  475.         // Need data from user?
  476. // make sure caller's buffer is in kernel space.
  477. if( (vendor_cmd->rw_flag == VENDOR_WRITE_OPCODE) &&
  478.     vendor_cmd->len)
  479.         if(  copy_from_user( buf, vendor_cmd->bufp, vendor_cmd->len))
  480. return( -EFAULT);
  481.     
  482. // copy the CDB (if/when MAX_COMMAND_SIZE is 16, remove copy below)
  483.         memcpy( &ScsiPassThruCmnd->cmnd[0], 
  484. &vendor_cmd->cdb[0], 
  485. MAX_COMMAND_SIZE);  
  486.         // we want to copy all 16 bytes into the FCP-SCSI CDB,
  487. // although the actual passthru only uses up to the
  488. // first 12.
  489. ScsiPassThruCmnd->cmd_len = 16; // sizeof FCP-SCSI CDB
  490. // Unfortunately, the SCSI command cmnd[] field has only
  491. // 12 bytes.  Ideally the MAX_COMMAND_SIZE should be increased
  492. // to 16 for newer Fibre Channel and SCSI-3 larger CDBs.
  493. // However, to avoid a mandatory kernel rebuild, we use the SCp
  494. // spare field to store the extra 4 bytes ( ugly :-(
  495. if( MAX_COMMAND_SIZE < 16)
  496. {
  497.           memcpy( &ScsiPassThruCmnd->SCp.buffers_residual,
  498.   &vendor_cmd->cdb[12], 4);
  499. }   
  500.                   
  501.         ScsiPassThruCmnd->SCp.sent_command = 1; // PASSTHRU!
  502.                                         // suppress LUN masking
  503.                                         // and VSA logic
  504. // Use spare fields to copy FCP-SCSI LUN address info...
  505.         ScsiPassThruCmnd->SCp.phase = vendor_cmd->bus;
  506. ScsiPassThruCmnd->SCp.have_data_in = vendor_cmd->pdrive;
  507.         // We copy the scheme used by scsi.c to submit commands
  508. // to our own HBA.  We do this in order to stall the
  509. // thread calling the IOCTL until it completes, and use
  510. // the same "_quecommand" function for synchronizing
  511. // FC Link events with our "worker thread".
  512.         {
  513.           CPQFC_DECLARE_COMPLETION(wait);
  514.           ScsiPassThruCmnd->request.CPQFC_WAITING = &wait;
  515.           // eventually gets us to our own _quecommand routine
  516.           scsi_do_cmd( ScsiPassThruCmnd, &vendor_cmd->cdb[0], 
  517.        buf, 
  518.        vendor_cmd->len, 
  519.        my_ioctl_done, 
  520.        10*HZ, 1);// timeout,retries
  521.           // Other I/Os can now resume; we wait for our ioctl
  522.   // command to complete
  523.   CPQFC_WAIT_FOR_COMPLETION(&wait);
  524.           ScsiPassThruCmnd->request.CPQFC_WAITING = NULL;
  525.         }
  526.         result = ScsiPassThruCmnd->result;
  527.         // copy any sense data back to caller
  528.         if( result != 0 )
  529. {
  530.   memcpy( vendor_cmd->sense_data, // see struct def - size=40
  531.   ScsiPassThruCmnd->sense_buffer, 
  532.   sizeof(ScsiPassThruCmnd->sense_buffer)); 
  533. }
  534.         SDpnt = ScsiPassThruCmnd->device;
  535.         scsi_release_command(ScsiPassThruCmnd); // "de-allocate"
  536.         ScsiPassThruCmnd = NULL;
  537.         // if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
  538.         //  (*SDpnt->scsi_request_fn)();
  539.         wake_up(&SDpnt->scpnt_wait);
  540. // need to pass data back to user (space)?
  541. if( (vendor_cmd->rw_flag == VENDOR_READ_OPCODE) &&
  542.      vendor_cmd->len )
  543.         if(  copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len))
  544. return( -EFAULT);
  545.         if( buf) 
  546.   kfree( buf);
  547.         return result;
  548.       }
  549.       
  550.       case CPQFCTS_GETPCIINFO:
  551.       {
  552. cpqfc_pci_info_struct pciinfo;
  553. if( !arg)
  554.   return -EINVAL;
  555.          
  556.         pciinfo.bus = cpqfcHBAdata->PciDev->bus->number;
  557.         pciinfo.dev_fn = cpqfcHBAdata->PciDev->devfn;  
  558. pciinfo.board_id = cpqfcHBAdata->PciDev->device |
  559.   (cpqfcHBAdata->PciDev->vendor <<16); 
  560.       
  561.         if(copy_to_user( arg, &pciinfo, sizeof(cpqfc_pci_info_struct)))
  562. return( -EFAULT);
  563.         return 0;
  564.       }
  565.       case CPQFCTS_GETDRIVVER:
  566.       {
  567. DriverVer_type DriverVer = 
  568. CPQFCTS_DRIVER_VER( VER_MAJOR,VER_MINOR,VER_SUBMINOR);
  569. if( !arg)
  570.   return -EINVAL;
  571.         if(copy_to_user( arg, &DriverVer, sizeof(DriverVer)))
  572. return( -EFAULT);
  573.         return 0;
  574.       }
  575.       case CPQFC_IOCTL_FC_TARGET_ADDRESS:
  576.       result = 
  577.         verify_area(VERIFY_WRITE, arg, sizeof(Scsi_FCTargAddress));
  578.       if (result) 
  579. break;
  580.  
  581.       put_user(pLoggedInPort->port_id,
  582. &((Scsi_FCTargAddress *) arg)->host_port_id);
  583.  
  584.       for( i=3,j=0; i>=0; i--)    // copy the LOGIN port's WWN
  585.         put_user(pLoggedInPort->u.ucWWN[i], 
  586. &((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
  587.       for( i=7; i>3; i--) // copy the LOGIN port's WWN
  588.         put_user(pLoggedInPort->u.ucWWN[i], 
  589. &((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
  590.         break;
  591.       case CPQFC_IOCTL_FC_TDR:
  592.           
  593.         result = cpqfcTS_TargetDeviceReset( ScsiDev, 0);
  594.         break;
  595.     default:
  596.       result = -EINVAL;
  597.       break;
  598.     }
  599.   }
  600.   LEAVE("cpqfcTS_ioctl");
  601.   return result;
  602. }
  603. /* "Release" the Host Bus Adapter...
  604.    disable interrupts, stop the HBA, release the interrupt,
  605.    and free all resources */
  606. int cpqfcTS_release(struct Scsi_Host *HostAdapter)
  607. {
  608.   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; 
  609.   ENTER("cpqfcTS_release");
  610.   DEBUG_PCI( printk(" cpqfcTS: delete timer...n"));
  611.   del_timer( &cpqfcHBAdata->cpqfcTStimer);  
  612.     
  613.   // disable the hardware...
  614.   DEBUG_PCI( printk(" disable hardware, destroy queues, free memn"));
  615.   cpqfcHBAdata->fcChip.ResetTachyon( cpqfcHBAdata, CLEAR_FCPORTS);
  616.   // kill kernel thread
  617.   if( cpqfcHBAdata->worker_thread ) // (only if exists)
  618.   {
  619.     DECLARE_MUTEX_LOCKED(sem);  // synchronize thread kill
  620.     cpqfcHBAdata->notify_wt = &sem;
  621.     DEBUG_PCI( printk(" killing kernel threadn"));
  622.     send_sig( SIGKILL, cpqfcHBAdata->worker_thread, 1);
  623.     down( &sem);
  624.     cpqfcHBAdata->notify_wt = NULL;
  625.     
  626.   }
  627.   // free Linux resources
  628.   DEBUG_PCI( printk(" cpqfcTS: freeing resources...n"));
  629.   free_irq( HostAdapter->irq, HostAdapter);
  630.   scsi_unregister( HostAdapter);
  631.   release_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff);
  632.   release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff);
  633.  /* we get "vfree: bad address" executing this - need to investigate... 
  634.   if( (void*)((unsigned long)cpqfcHBAdata->fcChip.Registers.MemBase) !=
  635.       cpqfcHBAdata->fcChip.Registers.ReMapMemBase)
  636.     vfree( cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
  637. */
  638.   LEAVE("cpqfcTS_release");
  639.   return 0;
  640. }
  641. const char * cpqfcTS_info(struct Scsi_Host *HostAdapter)
  642. {
  643.   static char buf[300];
  644.   CPQFCHBA *cpqfcHBA;
  645.   int BusSpeed, BusWidth;
  646.   
  647.   // get the pointer to our Scsi layer HBA buffer  
  648.   cpqfcHBA = (CPQFCHBA *)HostAdapter->hostdata;
  649.   BusWidth = (cpqfcHBA->fcChip.Registers.PCIMCTR &0x4) > 0 ?
  650.                64 : 32;
  651.   if( cpqfcHBA->fcChip.Registers.TYconfig.value & 0x80000000)
  652.     BusSpeed = 66;
  653.   else
  654.     BusSpeed = 33;
  655.   sprintf(buf, 
  656. "%s: WWN %08X%08Xn on PCI bus %d device 0x%02x irq %d IObaseL 0x%x, MEMBASE 0x%xnPCI bus width %d bits, bus speed %d MHznFCP-SCSI Driver v%d.%d.%d",
  657.       cpqfcHBA->fcChip.Name, 
  658.       cpqfcHBA->fcChip.Registers.wwn_hi,
  659.       cpqfcHBA->fcChip.Registers.wwn_lo,
  660.       cpqfcHBA->PciDev->bus->number,
  661.       cpqfcHBA->PciDev->device,  
  662.       HostAdapter->irq,
  663.       cpqfcHBA->fcChip.Registers.IOBaseL,
  664.       cpqfcHBA->fcChip.Registers.MemBase,
  665.       BusWidth,
  666.       BusSpeed,
  667.       VER_MAJOR, VER_MINOR, VER_SUBMINOR
  668. );
  669.   
  670.   cpqfcTSDecodeGBICtype( &cpqfcHBA->fcChip, &buf[ strlen(buf)]);
  671.   cpqfcTSGetLPSM( &cpqfcHBA->fcChip, &buf[ strlen(buf)]);
  672.   return buf;
  673. }
  674. //
  675. // /proc/scsi support. The following routines allow us to do 'normal'
  676. // sprintf like calls to return the currently requested piece (buflenght
  677. // chars, starting at bufoffset) of the file. Although procfs allows for
  678. // a 1 Kb bytes overflow after te supplied buffer, I consider it bad 
  679. // programming to use it to make programming a little simpler. This piece
  680. // of coding is borrowed from ncr53c8xx.c with some modifications 
  681. //
  682. struct info_str
  683. {
  684.         char *buffer; // Pointer to output buffer
  685.         int buflength; // It's length
  686.         int bufoffset; // File offset corresponding with buf[0]
  687. int buffillen; // Current filled length 
  688.         int filpos; // Current file offset
  689. };
  690. static void copy_mem_info(struct info_str *info, char *data, int datalen)
  691. {
  692.   if (info->filpos < info->bufoffset) { // Current offset before buffer offset
  693.     if (info->filpos + datalen <= info->bufoffset) {
  694.       info->filpos += datalen;  // Discard if completely before buffer
  695.       return;
  696.     } else { // Partial copy, set to begin
  697.       data += (info->bufoffset - info->filpos);
  698.       datalen  -= (info->bufoffset - info->filpos);
  699.       info->filpos = info->bufoffset;
  700.     }
  701.   }
  702.   info->filpos += datalen; // Update current offset
  703.   if (info->buffillen == info->buflength) // Buffer full, discard
  704.     return;
  705.   if (info->buflength - info->buffillen < datalen)  // Overflows buffer ?
  706.     datalen = info->buflength - info->buffillen;
  707.   memcpy(info->buffer + info->buffillen, data, datalen);
  708.   info->buffillen += datalen;
  709. }
  710. static int copy_info(struct info_str *info, char *fmt, ...)
  711. {
  712.         va_list args;
  713.         char buf[400];
  714.         int len;
  715.         va_start(args, fmt);
  716.         len = vsprintf(buf, fmt, args);
  717.         va_end(args);
  718.         copy_mem_info(info, buf, len);
  719.         return len;
  720. }
  721. // Routine to get data for /proc RAM filesystem
  722. //
  723. int cpqfcTS_proc_info (char *buffer, char **start, off_t offset, int length, 
  724.        int hostno, int inout)
  725. {
  726.   struct Scsi_Host *host;
  727.   Scsi_Cmnd DumCmnd;
  728.   int Chan, Targ, i;
  729.   struct info_str info;
  730.   CPQFCHBA *cpqfcHBA;
  731.   PTACHYON fcChip;
  732.   PFC_LOGGEDIN_PORT pLoggedInPort;
  733.   char buf[81];
  734.   // Search the Scsi host list for our controller
  735.   for (host=scsi_hostlist; host; host=host->next)
  736.     if (host->host_no == hostno)
  737.       break;
  738.   if (!host) return -ESRCH;
  739.   if (inout) return -EINVAL;
  740.   // get the pointer to our Scsi layer HBA buffer  
  741.   cpqfcHBA = (CPQFCHBA *)host->hostdata;
  742.   fcChip = &cpqfcHBA->fcChip;
  743.   
  744.   *start    = buffer;
  745.   info.buffer     = buffer;
  746.   info.buflength  = length;
  747.   info.bufoffset  = offset;
  748.   info.filpos     = 0;
  749.   info.buffillen  = 0;
  750.   copy_info(&info, "Driver version = %d.%d.%d", VER_MAJOR, VER_MINOR, VER_SUBMINOR); 
  751.   cpqfcTSDecodeGBICtype( &cpqfcHBA->fcChip, &buf[0]);
  752.   cpqfcTSGetLPSM( &cpqfcHBA->fcChip, &buf[ strlen(buf)]);
  753.   copy_info(&info, "%sn", buf); 
  754. #define DISPLAY_WWN_INFO
  755. #ifdef DISPLAY_WWN_INFO
  756.   copy_info(&info, "WWN database: ("port_id: 000000" means disconnected)n");
  757.   for ( Chan=0; Chan <= host->max_channel; Chan++) {
  758.     DumCmnd.channel = Chan;
  759.     for (Targ=0; Targ <= host->max_id; Targ++) {
  760.       DumCmnd.target = Targ;
  761.       if ((pLoggedInPort = fcFindLoggedInPort( fcChip,
  762.      &DumCmnd, // search Scsi Nexus
  763.      0,        // DON'T search list for FC port id
  764.      NULL,     // DON'T search list for FC WWN
  765.      NULL))){   // DON'T care about end of list
  766. copy_info(&info, "Host: scsi%d Channel: %02d TargetId: %02d -> WWN: ",
  767.    hostno, Chan, Targ);
  768.         for( i=3; i>=0; i--)        // copy the LOGIN port's WWN
  769.           copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]);
  770.         for( i=7; i>3; i--)             // copy the LOGIN port's WWN
  771.           copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]);
  772. copy_info(&info, " port_id: %06Xn", pLoggedInPort->port_id); 
  773.       }
  774.     }
  775.   }
  776. #endif
  777.   
  778.   
  779. // Unfortunately, the proc_info buffer isn't big enough
  780. // for everything we would like...
  781. // For FC stats, compile this and turn off WWN stuff above  
  782. //#define DISPLAY_FC_STATS
  783. #ifdef DISPLAY_FC_STATS
  784. // get the Fibre Channel statistics
  785.   {
  786.     int DeltaSecs = (jiffies - cpqfcHBA->fcStatsTime) / HZ;
  787.     int days,hours,minutes,secs;
  788.     
  789.     days = DeltaSecs / (3600*24); // days
  790.     hours = (DeltaSecs% (3600*24)) / 3600; // hours
  791.     minutes = (DeltaSecs%3600 /60); // minutes
  792.     secs =  DeltaSecs%60;  // secs
  793. copy_info( &info, "Fibre Channel Stats (time dd:hh:mm:ss %02u:%02u:%02u:%02un",
  794.       days, hours, minutes, secs);
  795.   }
  796.     
  797.   cpqfcHBA->fcStatsTime = jiffies;  // (for next delta)
  798.   copy_info( &info, "  LinkUp           %9u     LinkDown      %un",
  799.         fcChip->fcStats.linkUp, fcChip->fcStats.linkDown);
  800.         
  801.   copy_info( &info, "  Loss of Signal   %9u     Loss of Sync  %un",
  802.     fcChip->fcStats.LossofSignal, fcChip->fcStats.LossofSync);
  803.   
  804.   copy_info( &info, "  Discarded Frames %9u     Bad CRC Frame %un",
  805.     fcChip->fcStats.Dis_Frm, fcChip->fcStats.Bad_CRC);
  806.   copy_info( &info, "  TACH LinkFailTX  %9u     TACH LinkFailRX     %un",
  807.     fcChip->fcStats.linkFailTX, fcChip->fcStats.linkFailRX);
  808.   
  809.   copy_info( &info, "  TACH RxEOFa      %9u     TACH Elastic Store  %un",
  810.     fcChip->fcStats.Rx_EOFa, fcChip->fcStats.e_stores);
  811.   copy_info( &info, "  BufferCreditWait %9uus   TACH FM Inits %un",
  812.     fcChip->fcStats.BB0_Timer*10, fcChip->fcStats.FMinits );
  813.   copy_info( &info, "  FC-2 Timeouts    %9u     FC-2 Logouts  %un",
  814.     fcChip->fcStats.timeouts, fcChip->fcStats.logouts); 
  815.         
  816.   copy_info( &info, "  FC-2 Aborts      %9u     FC-4 Aborts   %un",
  817.     fcChip->fcStats.FC2aborted, fcChip->fcStats.FC4aborted);
  818.    
  819.   // clear the counters
  820.   cpqfcTSClearLinkStatusCounters( fcChip);
  821. #endif
  822.   return info.buffillen;
  823. }
  824. #if DEBUG_CMND
  825. UCHAR *ScsiToAscii( UCHAR ScsiCommand)
  826. {
  827. /*++
  828. Routine Description:
  829.    Converts a SCSI command to a text string for debugging purposes.
  830. Arguments:
  831.    ScsiCommand -- hex value SCSI Command
  832. Return Value:
  833.    An ASCII, null-terminated string if found, else returns NULL.
  834. Original code from M. McGowen, Compaq
  835. --*/
  836.    switch (ScsiCommand)
  837.    {
  838.       case 0x00:
  839.          return( "Test Unit Ready" );
  840.       case 0x01:
  841.          return( "Rezero Unit or Rewind" );
  842.       case 0x02:
  843.          return( "Request Block Address" );
  844.       case 0x03:
  845.          return( "Requese Sense" );
  846.       case 0x04:
  847.          return( "Format Unit" );
  848.       case 0x05:
  849.          return( "Read Block Limits" );
  850.       case 0x07:
  851.          return( "Reassign Blocks" );
  852.       case 0x08:
  853.          return( "Read (6)" );
  854.       case 0x0a:
  855.          return( "Write (6)" );
  856.       case 0x0b:
  857.          return( "Seek (6)" );
  858.       case 0x12:
  859.          return( "Inquiry" );
  860.       case 0x15:
  861.          return( "Mode Select (6)" );
  862.       case 0x16:
  863.          return( "Reserve" );
  864.       case 0x17:
  865.          return( "Release" );
  866.       case 0x1a:
  867.          return( "ModeSen(6)" );
  868.       case 0x1b:
  869.          return( "Start/Stop Unit" );
  870.       case 0x1c:
  871.          return( "Receive Diagnostic Results" );
  872.       case 0x1d:
  873.          return( "Send Diagnostic" );
  874.       case 0x25:
  875.          return( "Read Capacity" );
  876.       case 0x28:
  877.          return( "Read (10)" );
  878.       case 0x2a:
  879.          return( "Write (10)" );
  880.       case 0x2b:
  881.          return( "Seek (10)" );
  882.       case 0x2e:
  883.          return( "Write and Verify" );
  884.       case 0x2f:
  885.          return( "Verify" );
  886.       case 0x34:
  887.          return( "Pre-Fetch" );
  888.       case 0x35:
  889.          return( "Synchronize Cache" );
  890.       case 0x37:
  891.          return( "Read Defect Data (10)" );
  892.       case 0x3b:
  893.          return( "Write Buffer" );
  894.       case 0x3c:
  895.          return( "Read Buffer" );
  896.       case 0x3e:
  897.          return( "Read Long" );
  898.       case 0x3f:
  899.          return( "Write Long" );
  900.       case 0x41:
  901.          return( "Write Same" );
  902.       case 0x4c:
  903.          return( "Log Select" );
  904.       case 0x4d:
  905.          return( "Log Sense" );
  906.       case 0x56:
  907.          return( "Reserve (10)" );
  908.       case 0x57:
  909.          return( "Release (10)" );
  910.       case 0xa0:
  911.          return( "ReportLuns" );
  912.       case 0xb7:
  913.          return( "Read Defect Data (12)" );
  914.       case 0xca:
  915.          return( "Peripheral Device Addressing SCSI Passthrough" );
  916.       case 0xcb:
  917.          return( "Compaq Array Firmware Passthrough" );
  918.       default:
  919.          return( NULL );
  920.    }
  921. } // end ScsiToAscii()
  922. void cpqfcTS_print_scsi_cmd(Scsi_Cmnd * cmd)
  923. {
  924. printk("cpqfcTS: (%s) chnl 0x%02x, trgt = 0x%02x, lun = 0x%02x, cmd_len = 0x%02xn", 
  925.     ScsiToAscii( cmd->cmnd[0]), cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
  926. if( cmd->cmnd[0] == 0)   // Test Unit Ready?
  927. {
  928.   int i;
  929.   printk("Cmnd->request_bufflen = 0x%X, ->use_sg = %d, ->bufflen = %dn",
  930.     cmd->request_bufflen, cmd->use_sg, cmd->bufflen);
  931.   printk("Cmnd->request_buffer = %p, ->sglist_len = %d, ->buffer = %pn",
  932.     cmd->request_buffer, cmd->sglist_len, cmd->buffer);
  933.   for (i = 0; i < cmd->cmd_len; i++)
  934.     printk("0x%02x ", cmd->cmnd[i]);
  935.   printk("n");
  936. }
  937. }
  938. #endif /* DEBUG_CMND */
  939. static void QueCmndOnBoardLock( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd)
  940. {
  941.   int i;
  942.   for( i=0; i< CPQFCTS_REQ_QUEUE_LEN; i++)
  943.   {    // find spare slot
  944.     if( cpqfcHBAdata->BoardLockCmnd[i] == NULL )
  945.     {
  946.       cpqfcHBAdata->BoardLockCmnd[i] = Cmnd;
  947. //      printk(" BoardLockCmnd[%d] %p Queued, chnl/target/lun %d/%d/%dn",
  948. //        i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
  949.       break;
  950.     }
  951.   }
  952.   if( i >= CPQFCTS_REQ_QUEUE_LEN)
  953.   {
  954.     printk(" cpqfcTS WARNING: Lost Cmnd %p on BoardLock Q full!", Cmnd);
  955.   }
  956. }
  957. static void QueLinkDownCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd)
  958. {
  959.   int indx;
  960.   // Remember the command ptr so we can return; we'll complete when
  961.   // the device comes back, causing immediate retry
  962.   for( indx=0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++)//, SCptr++)
  963.   {
  964.     if( cpqfcHBAdata->LinkDnCmnd[indx] == NULL ) // available?
  965.     {
  966. #ifdef DUMMYCMND_DBG
  967.       printk(" @add Cmnd %p to LnkDnCmnd[%d]@ ", Cmnd,indx);
  968. #endif
  969.       cpqfcHBAdata->LinkDnCmnd[indx] = Cmnd;
  970.       break;
  971.     }
  972.   }
  973.   if( indx >= CPQFCTS_REQ_QUEUE_LEN ) // no space for Cmnd??
  974.   {
  975.     // this will result in an _abort call later (with possible trouble)
  976.     printk("no buffer for LinkDnCmnd!! %pn", Cmnd);
  977.   }
  978. }
  979. // The file "hosts.h" says not to call scsi_done from
  980. // inside _queuecommand, so we'll do it from the heartbeat timer
  981. // (clarification: Turns out it's ok to call scsi_done from queuecommand 
  982. // for cases that don't go to the hardware like scsi cmds destined
  983. // for LUNs we know don't exist, so this code might be simplified...)
  984. static void QueBadTargetCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd)
  985. {
  986.   int i;
  987.     //    printk(" can't find target %dn", Cmnd->target);
  988.   for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)
  989.   {    // find spare slot
  990.     if( cpqfcHBAdata->BadTargetCmnd[i] == NULL )
  991.     {
  992.       cpqfcHBAdata->BadTargetCmnd[i] = Cmnd;
  993. //      printk(" BadTargetCmnd[%d] %p Queued, chnl/target/lun %d/%d/%dn",
  994. //          i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
  995.       break;
  996.     }
  997.   }
  998. }
  999. // This is the "main" entry point for Linux Scsi commands --
  1000. // it all starts here.
  1001. int cpqfcTS_queuecommand(Scsi_Cmnd *Cmnd, void (* done)(Scsi_Cmnd *))
  1002. {
  1003.   struct Scsi_Host *HostAdapter = Cmnd->host;
  1004.   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  1005.   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  1006.   TachFCHDR_GCMND fchs;  // only use for FC destination id field  
  1007.   PFC_LOGGEDIN_PORT pLoggedInPort;
  1008.   ULONG ulStatus, SESTtype;
  1009.   LONG ExchangeID;
  1010.   ENTER("cpqfcTS_queuecommand");
  1011.       
  1012.   PCI_TRACEO( (ULONG)Cmnd, 0x98)
  1013.       
  1014.   
  1015.   Cmnd->scsi_done = done;
  1016. #ifdef DEBUG_CMND  
  1017.   cpqfcTS_print_scsi_cmd( Cmnd);
  1018. #endif
  1019.   // prevent board contention with kernel thread...  
  1020.   
  1021.    if( cpqfcHBAdata->BoardLock )
  1022.   {
  1023. //    printk(" @BrdLck Hld@ ");
  1024.     QueCmndOnBoardLock( cpqfcHBAdata, Cmnd);
  1025.   }
  1026.   
  1027.   else
  1028.   {
  1029.     // in the current system (2.2.12), this routine is called
  1030.     // after spin_lock_irqsave(), so INTs are disabled. However,
  1031.     // we might have something pending in the LinkQ, which
  1032.     // might cause the WorkerTask to run.  In case that
  1033.     // happens, make sure we lock it out.
  1034.     
  1035.     
  1036.     
  1037.     PCI_TRACE( 0x98) 
  1038.     CPQ_SPINLOCK_HBA( cpqfcHBAdata)
  1039.     PCI_TRACE( 0x98) 
  1040.     
  1041.   // can we find an FC device mapping to this SCSI target?
  1042.     pLoggedInPort = fcFindLoggedInPort( fcChip,
  1043.       Cmnd,     // search Scsi Nexus
  1044.       0,        // DON'T search linked list for FC port id
  1045.       NULL,     // DON'T search linked list for FC WWN
  1046.       NULL);    // DON'T care about end of list
  1047.  
  1048.     if( pLoggedInPort == NULL )      // not found!
  1049.     {
  1050. //    printk(" @Q bad targ cmnd %p@ ", Cmnd);
  1051.       QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
  1052.     }
  1053.     else if (Cmnd->lun >= CPQFCTS_MAX_LUN)
  1054.     {
  1055.       printk(KERN_WARNING "cpqfc: Invalid LUN: %dn", Cmnd->lun);
  1056.       QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
  1057.     } 
  1058.     else  // we know what FC device to send to...
  1059.     {
  1060.       // does this device support FCP target functions?
  1061.       // (determined by PRLI field)
  1062.       if( !(pLoggedInPort->fcp_info & TARGET_FUNCTION) )
  1063.       {
  1064.         printk(" Doesn't support TARGET functions port_id %Xhn",
  1065.           pLoggedInPort->port_id );
  1066.         QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
  1067.       }
  1068.     // In this case (previous login OK), the device is temporarily
  1069.     // unavailable waiting for re-login, in which case we expect it
  1070.     // to be back in between 25 - 500ms.  
  1071.     // If the FC port doesn't log back in within several seconds
  1072.     // (i.e. implicit "logout"), or we get an explicit logout,
  1073.     // we set "device_blocked" in Scsi_Device struct; in this
  1074.     // case 30 seconds will elapse before Linux/Scsi sends another
  1075.     // command to the device.
  1076.       else if( pLoggedInPort->prli != TRUE )
  1077.       {
  1078. //      printk("Device (Chnl/Target %d/%d) invalid PRLI, port_id %06lXhn",
  1079. //        Cmnd->channel, Cmnd->target, pLoggedInPort->port_id);
  1080.         QueLinkDownCmnd( cpqfcHBAdata, Cmnd);
  1081. //    Need to use "blocked" flag??   
  1082. // Cmnd->device->device_blocked = TRUE; // just let it timeout
  1083.       }
  1084.       else  // device supports TARGET functions, and is logged in...
  1085.       {
  1086.       // (context of fchs is to "reply" to...)
  1087.         fchs.s_id = pLoggedInPort->port_id; // destination FC address
  1088.       // what is the data direction?  For data TO the device,
  1089.       // we need IWE (Intiator Write Entry).  Otherwise, IRE.
  1090.         if( Cmnd->cmnd[0] == WRITE_10 ||
  1091.      Cmnd->cmnd[0] == WRITE_6 ||
  1092.   Cmnd->cmnd[0] == WRITE_BUFFER ||      
  1093.   Cmnd->cmnd[0] == VENDOR_WRITE_OPCODE ||  // CPQ specific 
  1094.   Cmnd->cmnd[0] == MODE_SELECT )
  1095.         {
  1096.           SESTtype = SCSI_IWE; // data from HBA to Device
  1097.         }
  1098.         else
  1099.           SESTtype = SCSI_IRE; // data from Device to HBA
  1100.        
  1101.         ulStatus = cpqfcTSBuildExchange(
  1102.           cpqfcHBAdata,
  1103.           SESTtype,     // e.g. Initiator Read Entry (IRE)
  1104.           &fchs,        // we are originator; only use d_id
  1105.           Cmnd,         // Linux SCSI command (with scatter/gather list)
  1106.           &ExchangeID );// fcController->fcExchanges index, -1 if failed
  1107.         if( !ulStatus ) // Exchange setup?
  1108.    
  1109.         {
  1110.           if( cpqfcHBAdata->BoardLock )
  1111.           {
  1112.     TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
  1113.     printk(" @bl! %d, xID %Xh@ ", current->pid, ExchangeID);
  1114.           }
  1115.   ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
  1116.   if( !ulStatus )
  1117.           {
  1118.             PCI_TRACEO( ExchangeID, 0xB8) 
  1119.           // submitted to Tach's Outbound Que (ERQ PI incremented)
  1120.           // waited for completion for ELS type (Login frames issued
  1121.           // synchronously)
  1122.   }
  1123.           else
  1124.             // check reason for Exchange not being started - we might
  1125.             // want to Queue and start later, or fail with error
  1126.           {
  1127.             printk("quecommand: cpqfcTSStartExchange failed: %Xhn", ulStatus );
  1128.           }
  1129.         }            // end good BuildExchange status
  1130.         
  1131.         else  // SEST table probably full  -- why? hardware hang?
  1132.         {
  1133.   printk("quecommand: cpqfcTSBuildExchange faild: %Xhn", ulStatus);
  1134.         }
  1135.       }  // end can't do FCP-SCSI target functions
  1136.     } // end can't find target (FC device)
  1137.     CPQ_SPINUNLOCK_HBA( cpqfcHBAdata)
  1138.   }
  1139.   PCI_TRACEO( (ULONG)Cmnd, 0x9C) 
  1140.   LEAVE("cpqfcTS_queuecommand");
  1141.   return 0;
  1142. }    
  1143. // Entry point for upper Scsi layer intiated abort.  Typically
  1144. // this is called if the command (for hard disk) fails to complete
  1145. // in 30 seconds.  This driver intends to complete all disk commands
  1146. // within Exchange ".timeOut" seconds (now 7) with target status, or
  1147. // in case of ".timeOut" expiration, a DID_SOFT_ERROR which causes
  1148. // immediate retry.
  1149. // If any disk commands get the _abort call, except for the case that
  1150. // the physical device was removed or unavailable due to hardware
  1151. // errors, it should be considered a driver error and reported to
  1152. // the author.
  1153. int cpqfcTS_abort(Scsi_Cmnd *Cmnd)
  1154. {
  1155. // printk(" cpqfcTS_abort called?? n");
  1156.   return 0;
  1157. }
  1158.  
  1159. int cpqfcTS_eh_abort(Scsi_Cmnd *Cmnd)
  1160. {
  1161.   struct Scsi_Host *HostAdapter = Cmnd->host;
  1162.   // get the pointer to our Scsi layer HBA buffer  
  1163.   CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
  1164.   PTACHYON fcChip = &cpqfcHBAdata->fcChip;
  1165.   FC_EXCHANGES *Exchanges = fcChip->Exchanges;
  1166.   int i;
  1167.   ENTER("cpqfcTS_eh_abort");
  1168.   Cmnd->result = DID_ABORT <<16;  // assume we'll find it
  1169.   printk(" @Linux _abort Scsi_Cmnd %p ", Cmnd);
  1170.   // See if we can find a Cmnd pointer that matches...
  1171.   // The most likely case is we accepted the command
  1172.   // from Linux Scsi (e.g. ceated a SEST entry) and it
  1173.   // got lost somehow.  If we can't find any reference
  1174.   // to the passed pointer, we can only presume it
  1175.   // got completed as far as our driver is concerned.
  1176.   // If we found it, we will try to abort it through
  1177.   // common mechanism.  If FC ABTS is successful (ACC)
  1178.   // or is rejected (RJT) by target, we will call
  1179.   // Scsi "done" quickly.  Otherwise, the ABTS will timeout
  1180.   // and we'll call "done" later.
  1181.   // Search the SEST exchanges for a matching Cmnd ptr.
  1182.   for( i=0; i< TACH_SEST_LEN; i++)
  1183.   {
  1184.     if( Exchanges->fcExchange[i].Cmnd == Cmnd )
  1185.     {
  1186.       
  1187.       // found it!
  1188.       printk(" x_ID %Xh, type %Xhn", i, Exchanges->fcExchange[i].type);
  1189.       Exchanges->fcExchange[i].status = INITIATOR_ABORT; // seconds default
  1190.       Exchanges->fcExchange[i].timeOut = 10; // seconds default (changed later)
  1191.       // Since we need to immediately return the aborted Cmnd to Scsi 
  1192.       // upper layers, we can't make future reference to any of it's 
  1193.       // fields (e.g the Nexus).
  1194.       cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &i);
  1195.       break;
  1196.     }
  1197.   }
  1198.   if( i >= TACH_SEST_LEN ) // didn't find Cmnd ptr in chip's SEST?
  1199.   {
  1200.     // now search our non-SEST buffers (i.e. Cmnd waiting to
  1201.     // start on the HBA or waiting to complete with error for retry).
  1202.     
  1203.     // first check BadTargetCmnd
  1204.     for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)
  1205.     { 
  1206.       if( cpqfcHBAdata->BadTargetCmnd[i] == Cmnd )
  1207.       {
  1208.         cpqfcHBAdata->BadTargetCmnd[i] = NULL;
  1209. printk("in BadTargetCmnd Qn");
  1210. goto Done; // exit
  1211.       }
  1212.     }
  1213.     // if not found above...
  1214.     for( i=0; i < CPQFCTS_REQ_QUEUE_LEN; i++)
  1215.     {
  1216.       if( cpqfcHBAdata->LinkDnCmnd[i] == Cmnd ) 
  1217.       {
  1218. cpqfcHBAdata->LinkDnCmnd[i] = NULL;
  1219. printk("in LinkDnCmnd Qn");
  1220. goto Done;
  1221.       }
  1222.     }
  1223.     for( i=0; i< CPQFCTS_REQ_QUEUE_LEN; i++)
  1224.     {    // find spare slot
  1225.       if( cpqfcHBAdata->BoardLockCmnd[i] == Cmnd )
  1226.       {
  1227.         cpqfcHBAdata->BoardLockCmnd[i] = NULL;
  1228. printk("in BoardLockCmnd Qn");
  1229. goto Done;
  1230.       }
  1231.     }
  1232.     
  1233.     Cmnd->result = DID_ERROR <<16;  // Hmmm...
  1234.     printk("Not found! ");
  1235. //    panic("_abort");
  1236.   }
  1237.   
  1238. Done:
  1239.   
  1240. //    panic("_abort");
  1241.   LEAVE("cpqfcTS_eh_abort");
  1242.   return 0;  // (see scsi.h)
  1243. }    
  1244. // FCP-SCSI Target Device Reset
  1245. // See dpANS Fibre Channel Protocol for SCSI
  1246. // X3.269-199X revision 12, pg 25
  1247. int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, 
  1248.                                unsigned int reset_flags)
  1249. {
  1250.   int timeout = 10*HZ;
  1251.   int retries = 1;
  1252.   char scsi_cdb[12];
  1253.   int result;
  1254.   Scsi_Cmnd * SCpnt;
  1255.   Scsi_Device * SDpnt;
  1256.   // printk("   ENTERING cpqfcTS_TargetDeviceReset() - flag=%d n",reset_flags);
  1257.   if (ScsiDev->host->eh_active) return FAILED;
  1258.   memset( scsi_cdb, 0, sizeof( scsi_cdb));
  1259.   scsi_cdb[0] = RELEASE;
  1260.   // allocate with wait = true, interruptible = false 
  1261.   SCpnt = scsi_allocate_device(ScsiDev, 1, 0);
  1262.   {
  1263.     CPQFC_DECLARE_COMPLETION(wait);
  1264.         
  1265.     SCpnt->SCp.buffers_residual = FCP_TARGET_RESET;
  1266. SCpnt->request.CPQFC_WAITING = &wait;
  1267. scsi_do_cmd(SCpnt,  scsi_cdb, NULL,  0, my_ioctl_done,  timeout, retries);
  1268. CPQFC_WAIT_FOR_COMPLETION(&wait);
  1269. SCpnt->request.CPQFC_WAITING = NULL;
  1270.   }
  1271.     
  1272. /*
  1273.       if(driver_byte(SCpnt->result) != 0)
  1274.   switch(SCpnt->sense_buffer[2] & 0xf) {
  1275. case ILLEGAL_REQUEST:
  1276.     if(cmd[0] == ALLOW_MEDIUM_REMOVAL) dev->lockable = 0;
  1277.     else printk("SCSI device (ioctl) reports ILLEGAL REQUEST.n");
  1278.     break;
  1279. case NOT_READY: // This happens if there is no disc in drive 
  1280.     if(dev->removable && (cmd[0] != TEST_UNIT_READY)){
  1281. printk(KERN_INFO "Device not ready.  Make sure there is a disc in the drive.n");
  1282. break;
  1283.     }
  1284. case UNIT_ATTENTION:
  1285.     if (dev->removable){
  1286. dev->changed = 1;
  1287. SCpnt->result = 0; // This is no longer considered an error
  1288. // gag this error, VFS will log it anyway /axboe 
  1289. // printk(KERN_INFO "Disc change detected.n"); 
  1290. break;
  1291.     };
  1292. default: // Fall through for non-removable media
  1293.     printk("SCSI error: host %d id %d lun %d return code = %xn",
  1294.    dev->host->host_no,
  1295.    dev->id,
  1296.    dev->lun,
  1297.    SCpnt->result);
  1298.     printk("tSense class %x, sense error %x, extended sense %xn",
  1299.    sense_class(SCpnt->sense_buffer[0]),
  1300.    sense_error(SCpnt->sense_buffer[0]),
  1301.    SCpnt->sense_buffer[2] & 0xf);
  1302.     
  1303.       };
  1304. */    
  1305.   result = SCpnt->result;
  1306.   SDpnt = SCpnt->device;
  1307.   scsi_release_command(SCpnt);
  1308.   SCpnt = NULL;
  1309.   // if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
  1310.   //  (*SDpnt->scsi_request_fn)();
  1311.   wake_up(&SDpnt->scpnt_wait);
  1312.   // printk("   LEAVING cpqfcTS_TargetDeviceReset() - return SUCCESS n");
  1313.   return SUCCESS;
  1314. }
  1315. int cpqfcTS_eh_device_reset(Scsi_Cmnd *Cmnd)
  1316. {
  1317.   int retval;
  1318.   Scsi_Device *SDpnt = Cmnd->device;
  1319.   // printk("   ENTERING cpqfcTS_eh_device_reset() n");
  1320.   spin_unlock_irq(&io_request_lock);
  1321.   retval = cpqfcTS_TargetDeviceReset( SDpnt, 0);
  1322.   spin_lock_irq(&io_request_lock);
  1323.   return retval;
  1324. }
  1325. int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
  1326. {
  1327.   ENTER("cpqfcTS_reset");
  1328.   LEAVE("cpqfcTS_reset");
  1329.   return SCSI_RESET_ERROR;      /* Bus Reset Not supported */
  1330. }
  1331. /* This function determines the bios parameters for a given
  1332.    harddisk. These tend to be numbers that are made up by the
  1333.    host adapter.  Parameters:
  1334.    size, device number, list (heads, sectors,cylinders).
  1335.    (from hosts.h)
  1336. */
  1337. int cpqfcTS_biosparam(Disk *disk, kdev_t n, int ip[])
  1338. {
  1339.   int size = disk->capacity;
  1340.   
  1341.   ENTER("cpqfcTS_biosparam");
  1342.   ip[0] = 64;
  1343.   ip[1] = 32;
  1344.   ip[2] = size >> 11;
  1345.   
  1346.   if( ip[2] > 1024 )
  1347.   {
  1348.     ip[0] = 255;
  1349.     ip[1] = 63;
  1350.     ip[2] = size / (ip[0] * ip[1]);
  1351.   }
  1352.   LEAVE("cpqfcTS_biosparam");
  1353.   return 0;
  1354. }    
  1355. void cpqfcTS_intr_handler( int irq, 
  1356. void *dev_id, 
  1357. struct pt_regs *regs)
  1358. {
  1359.   unsigned long flags, InfLoopBrk=0;
  1360.   struct Scsi_Host *HostAdapter = dev_id;
  1361.   CPQFCHBA *cpqfcHBA = (CPQFCHBA *)HostAdapter->hostdata;
  1362.   int MoreMessages = 1; // assume we have something to do
  1363.   UCHAR IntPending;
  1364.   
  1365.   ENTER("intr_handler");
  1366.   spin_lock_irqsave( &io_request_lock, flags);
  1367.   // is this our INT?
  1368.   IntPending = readb( cpqfcHBA->fcChip.Registers.INTPEND.address);
  1369.   // broken boards can generate messages forever, so
  1370.   // prevent the infinite loop
  1371. #define INFINITE_IMQ_BREAK 10000
  1372.   if( IntPending )
  1373.   {
  1374.     
  1375.     // mask our HBA interrupts until we handle it...
  1376.     writeb( 0, cpqfcHBA->fcChip.Registers.INTEN.address);
  1377.     if( IntPending & 0x4) // "INT" - Tach wrote to IMQ
  1378.     {
  1379.       while( (++InfLoopBrk < INFINITE_IMQ_BREAK) && (MoreMessages ==1) ) 
  1380.       {
  1381.         MoreMessages = CpqTsProcessIMQEntry( HostAdapter); // ret 0 when done
  1382.       }
  1383.       if( InfLoopBrk >= INFINITE_IMQ_BREAK )
  1384.       {
  1385.         printk("WARNING: Compaq FC adapter generating excessive INTs -REPLACEn");
  1386.         printk("or investigate alternate causes (e.g. physical FC layer)n");
  1387.       }
  1388.       else  // working normally - re-enable INTs and continue
  1389.         writeb( 0x1F, cpqfcHBA->fcChip.Registers.INTEN.address);
  1390.     
  1391.     }  // (...ProcessIMQEntry() clears INT by writing IMQ consumer)
  1392.     else  // indications of errors or problems...
  1393.           // these usually indicate critical system hardware problems.
  1394.     {
  1395.       if( IntPending & 0x10 )
  1396.    printk(" cpqfcTS adapter external memory parity error detectedn");
  1397.       if( IntPending & 0x8 )
  1398.    printk(" cpqfcTS adapter PCI master address crossed 45-bit boundaryn");
  1399.       if( IntPending & 0x2 )
  1400. printk(" cpqfcTS adapter DMA error detectedn");
  1401.       if( IntPending & 0x1 ) {
  1402.    UCHAR IntStat;
  1403.    printk(" cpqfcTS adapter PCI error detectedn");
  1404.    IntStat = readb( cpqfcHBA->fcChip.Registers.INTSTAT.address);
  1405. if (IntStat & 0x4) printk("(INT)n");
  1406. if (IntStat & 0x8) 
  1407. printk("CRS: PCI master address crossed 46 bit bouandaryn");
  1408. if (IntStat & 0x10) printk("MRE: external memory parity error.n");
  1409.       }
  1410.     }      
  1411.   }
  1412.   spin_unlock_irqrestore( &io_request_lock, flags);
  1413.   LEAVE("intr_handler");
  1414. }
  1415. int cpqfcTSDecodeGBICtype( PTACHYON fcChip, char cErrorString[])
  1416. {
  1417.         // Verify GBIC type (if any) and correct Tachyon Port State Machine
  1418.         // (GBIC) module definition is:
  1419.         // GPIO1, GPIO0, GPIO4 for MD2, MD1, MD0.  The input states appear
  1420.         // to be inverted -- i.e., a setting of 111 is read when there is NO
  1421.         // GBIC present.  The Module Def (MD) spec says 000 is "no GBIC"
  1422.         // Hard code the bit states to detect Copper, 
  1423.         // Long wave (single mode), Short wave (multi-mode), and absent GBIC
  1424.   ULONG ulBuff;
  1425.   sprintf( cErrorString, "nGBIC detected: ");
  1426.   ulBuff = fcChip->Registers.TYstatus.value & 0x13; 
  1427.   switch( ulBuff )
  1428.   {
  1429.   case 0x13:  // GPIO4, GPIO1, GPIO0 = 111; no GBIC!
  1430.     sprintf( &cErrorString[ strlen( cErrorString)],
  1431.             "NONE! ");
  1432.     return FALSE;          
  1433.           
  1434.        
  1435.   case 0x11:   // Copper GBIC detected
  1436.     sprintf( &cErrorString[ strlen( cErrorString)],
  1437.             "Copper. ");
  1438.     break;
  1439.   case 0x10:   // Long-wave (single mode) GBIC detected
  1440.     sprintf( &cErrorString[ strlen( cErrorString)],
  1441.         "Long-wave. ");
  1442.     break;
  1443.   case 0x1:    // Short-wave (multi mode) GBIC detected
  1444.     sprintf( &cErrorString[ strlen( cErrorString)],
  1445.         "Short-wave. ");
  1446.     break;
  1447.   default:     // unknown GBIC - presumably it will work (?)
  1448.     sprintf( &cErrorString[ strlen( cErrorString)],
  1449.             "Unknown. ");
  1450.           
  1451.     break;
  1452.   }  // end switch GBIC detection
  1453.   return TRUE;
  1454. }
  1455. int cpqfcTSGetLPSM( PTACHYON fcChip, char cErrorString[])
  1456. {
  1457.   // Tachyon's Frame Manager LPSM in LinkDown state?
  1458.   // (For non-loop port, check PSM instead.)
  1459.   // return string with state and FALSE is Link Down
  1460.   int LinkUp;
  1461.   if( fcChip->Registers.FMstatus.value & 0x80 ) 
  1462.     LinkUp = FALSE;
  1463.   else
  1464.     LinkUp = TRUE;
  1465.   sprintf( &cErrorString[ strlen( cErrorString)],
  1466.     " LPSM %Xh ", 
  1467.      (fcChip->Registers.FMstatus.value >>4) & 0xf );
  1468.   switch( fcChip->Registers.FMstatus.value & 0xF0)
  1469.   {
  1470.                     // bits set in LPSM
  1471.     case 0x10:
  1472.       sprintf( &cErrorString[ strlen( cErrorString)], "ARB");
  1473.       break;
  1474.     case 0x20:
  1475.       sprintf( &cErrorString[ strlen( cErrorString)], "ARBwon");
  1476.       break;
  1477.     case 0x30:
  1478.       sprintf( &cErrorString[ strlen( cErrorString)], "OPEN");
  1479.       break;
  1480.     case 0x40:
  1481.       sprintf( &cErrorString[ strlen( cErrorString)], "OPENed");
  1482.       break;
  1483.     case 0x50:
  1484.       sprintf( &cErrorString[ strlen( cErrorString)], "XmitCLS");
  1485.       break;
  1486.     case 0x60:
  1487.       sprintf( &cErrorString[ strlen( cErrorString)], "RxCLS");
  1488.       break;
  1489.     case 0x70:
  1490.       sprintf( &cErrorString[ strlen( cErrorString)], "Xfer");
  1491.       break;
  1492.     case 0x80:
  1493.       sprintf( &cErrorString[ strlen( cErrorString)], "Init");
  1494.       break;
  1495.     case 0x90:
  1496.       sprintf( &cErrorString[ strlen( cErrorString)], "O-IInitFin");
  1497.       break;
  1498.     case 0xa0:
  1499.       sprintf( &cErrorString[ strlen( cErrorString)], "O-IProtocol");
  1500.       break;
  1501.     case 0xb0:
  1502.       sprintf( &cErrorString[ strlen( cErrorString)], "O-ILipRcvd");
  1503.       break;
  1504.     case 0xc0:
  1505.       sprintf( &cErrorString[ strlen( cErrorString)], "HostControl");
  1506.       break;
  1507.     case 0xd0:
  1508.       sprintf( &cErrorString[ strlen( cErrorString)], "LoopFail");
  1509.       break;
  1510.     case 0xe0:
  1511.       sprintf( &cErrorString[ strlen( cErrorString)], "Offline");
  1512.       break;
  1513.     case 0xf0:
  1514.       sprintf( &cErrorString[ strlen( cErrorString)], "OldPort");
  1515.       break;
  1516.     case 0:
  1517.     default:
  1518.       sprintf( &cErrorString[ strlen( cErrorString)], "Monitor");
  1519.       break;
  1520.   }
  1521.   return LinkUp;
  1522. }
  1523. #include "linux/slab.h"
  1524. // Dynamic memory allocation alignment routines
  1525. // HP's Tachyon Fibre Channel Controller chips require
  1526. // certain memory queues and register pointers to be aligned
  1527. // on various boundaries, usually the size of the Queue in question.
  1528. // Alignment might be on 2, 4, 8, ... or even 512 byte boundaries.
  1529. // Since most O/Ss don't allow this (usually only Cache aligned -
  1530. // 32-byte boundary), these routines provide generic alignment (after
  1531. // O/S allocation) at any boundary, and store the original allocated
  1532. // pointer for deletion (O/S free function).  Typically, we expect
  1533. // these functions to only be called at HBA initialization and
  1534. // removal time (load and unload times)
  1535. // ALGORITHM notes:
  1536. // Memory allocation varies by compiler and platform.  In the worst case,
  1537. // we are only assured BYTE alignment, but in the best case, we can
  1538. // request allocation on any desired boundary.  Our strategy: pad the
  1539. // allocation request size (i.e. waste memory) so that we are assured
  1540. // of passing desired boundary near beginning of contiguous space, then
  1541. // mask out lower address bits.
  1542. // We define the following algorithm:
  1543. //   allocBoundary - compiler/platform specific address alignment
  1544. //                   in number of bytes (default is single byte; i.e. 1)
  1545. //   n_alloc       - number of bytes application wants @ aligned address
  1546. //   ab            - alignment boundary, in bytes (e.g. 4, 32, ...)
  1547. //   t_alloc       - total allocation needed to ensure desired boundary
  1548. //   mask          - to clear least significant address bits for boundary
  1549. //   Compute:
  1550. //   t_alloc = n_alloc + (ab - allocBoundary)
  1551. //   allocate t_alloc bytes @ alloc_address
  1552. //   mask =  NOT (ab - 1)
  1553. //       (e.g. if ab=32  _0001 1111  -> _1110 0000
  1554. //   aligned_address = alloc_address & mask
  1555. //   set n_alloc bytes to 0
  1556. //   return aligned_address (NULL if failed)
  1557. //
  1558. // If u32_AlignedAddress is non-zero, then search for BaseAddress (stored
  1559. // from previous allocation).  If found, invoke call to FREE the memory.
  1560. // Return NULL if BaseAddress not found
  1561. // we need about 8 allocations per HBA.  Figuring at most 10 HBAs per server
  1562. // size the dynamic_mem array at 80.
  1563. void* fcMemManager( struct pci_dev *pdev, ALIGNED_MEM *dynamic_mem, 
  1564.    ULONG n_alloc, ULONG ab, ULONG u32_AlignedAddress,
  1565. dma_addr_t *dma_handle)
  1566. {
  1567.   USHORT allocBoundary=1;   // compiler specific - worst case 1
  1568.                                   // best case - replace malloc() call
  1569.                                   // with function that allocates exactly
  1570.                                   // at desired boundary
  1571.   unsigned long ulAddress;
  1572.   ULONG t_alloc, i;
  1573.   void *alloc_address = 0;  // def. error code / address not found
  1574.   LONG mask;                // must be 32-bits wide!
  1575.   ENTER("fcMemManager");
  1576.   if( u32_AlignedAddress )          // are we freeing existing memory?
  1577.   {
  1578. //    printk(" freeing AlignedAddress %Xhn", u32_AlignedAddress);
  1579.     for( i=0; i<DYNAMIC_ALLOCATIONS; i++) // look for the base address
  1580.     {
  1581. //    printk("dynamic_mem[%u].AlignedAddress %lXn", i, dynamic_mem[i].AlignedAddress);
  1582.       if( dynamic_mem[i].AlignedAddress == u32_AlignedAddress )
  1583.       {
  1584.         alloc_address = dynamic_mem[i].BaseAllocated; // 'success' status
  1585. pci_free_consistent(pdev,dynamic_mem[i].size, 
  1586. alloc_address, 
  1587. dynamic_mem[i].dma_handle);
  1588.         dynamic_mem[i].BaseAllocated = 0;   // clear for next use
  1589.         dynamic_mem[i].AlignedAddress = 0;
  1590.         dynamic_mem[i].size = 0;
  1591.         break;                        // quit for loop; done
  1592.       }
  1593.     }
  1594.   }
  1595.   else if( n_alloc )                   // want new memory?
  1596.   {
  1597.     dma_addr_t handle;
  1598.     t_alloc = n_alloc + (ab - allocBoundary); // pad bytes for alignment
  1599. //    printk("pci_alloc_consistent() for Tach alignment: %ld bytesn", t_alloc);
  1600. // (would like to) allow thread block to free pages 
  1601.     alloc_address =                  // total bytes (NumberOfBytes)
  1602.       pci_alloc_consistent(pdev, t_alloc, &handle); 
  1603.                                   // now mask off least sig. bits of address
  1604.     if( alloc_address )           // (only if non-NULL)
  1605.     {
  1606.                                   // find place to store ptr, so we
  1607.                                   // can free it later...
  1608.       mask = (LONG)(ab - 1);            // mask all low-order bits
  1609.       mask = ~mask;                            // invert bits
  1610.       for( i=0; i<DYNAMIC_ALLOCATIONS; i++) // look for free slot
  1611.       {
  1612.         if( dynamic_mem[i].BaseAllocated == 0) // take 1st available
  1613.         {
  1614.           dynamic_mem[i].BaseAllocated = alloc_address;// address from O/S
  1615.           dynamic_mem[i].dma_handle = handle;
  1616.   if (dma_handle != NULL) 
  1617.   {
  1618. //             printk("handle = %p, ab=%d, boundary = %d, mask=0x%08xn", 
  1619. // handle, ab, allocBoundary, mask);
  1620.     *dma_handle = (dma_addr_t) 
  1621. ((((ULONG)handle) + (ab - allocBoundary)) & mask);
  1622.   }
  1623.           dynamic_mem[i].size = t_alloc;
  1624.           break;
  1625.         }
  1626.       }
  1627.       ulAddress = (unsigned long)alloc_address;
  1628.       
  1629.       ulAddress += (ab - allocBoundary);    // add the alignment bytes-
  1630.                                             // then truncate address...
  1631.       alloc_address = (void*)(ulAddress & mask);
  1632.       
  1633.       dynamic_mem[i].AlignedAddress = 
  1634. (ULONG)(ulAddress & mask); // 32bit Tach address
  1635.       memset( alloc_address, 0, n_alloc );  // clear new memory
  1636.     }
  1637.     else  // O/S dynamic mem alloc failed!
  1638.       alloc_address = 0;  // (for debugging breakpt)
  1639.   }
  1640.   LEAVE("fcMemManager");
  1641.   return alloc_address;  // good (or NULL) address
  1642. }
  1643. static Scsi_Host_Template driver_template = CPQFCTS;
  1644. #include "scsi_module.c"