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