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