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