OSDN Git Service

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