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