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