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