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