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