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 */
21 
22 #include <linux/sched.h>
23 #include <linux/timer.h>
24 #include <linux/string.h>
25 #include <linux/slab.h>
26 #include <linux/ioport.h>
27 #include <linux/kernel.h>
28 #include <linux/stat.h>
29 #include <linux/blk.h>
30 #include <linux/interrupt.h>
31 #include <linux/delay.h>
32 #include <linux/smp_lock.h>
33 
34 #define __KERNEL_SYSCALLS__
35 
36 #define SHUTDOWN_SIGS	(sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM))
37 
38 #include <linux/unistd.h>
39 
40 #include <asm/system.h>
41 #include <asm/irq.h>
42 #include <asm/dma.h>
43 
44 
45 
46 #include "sd.h"
47 #include "hosts.h"		// struct Scsi_Host definition for T handler
48 #include "cpqfcTSchip.h"
49 #include "cpqfcTSstructs.h"
50 #include "cpqfcTStrigger.h"
51 static const __u8 valid_al_pa[];
52 
53 //#define LOGIN_DBG 1
54 
55 // REMARKS:
56 // Since Tachyon chips may be permitted to wait from 500ms up to 2 sec
57 // to empty an outgoing frame from its FIFO to the Fibre Channel stream,
58 // we cannot do everything we need to in the interrupt handler.  Specifically,
59 // every time a link re-init (e.g. LIP) takes place, all SCSI I/O has to be
60 // suspended until the login sequences have been completed.  Login commands
61 // are frames just like SCSI commands are frames; they are subject to the same
62 // timeout issues and delays.  Also, various specs provide up to 2 seconds for
63 // devices to log back in (i.e. respond with ACC to a login frame), so I/O to
64 // that device has to be suspended.
65 // A serious problem here occurs on highly loaded FC-AL systems.  If our FC port
66 // has a low priority (e.g. high arbitrated loop physical address, alpa), and
67 // some other device is hogging bandwidth (permissible under FC-AL), we might
68 // time out thinking the link is hung, when it's simply busy.  Many such
69 // considerations complicate the design.  Although Tachyon assumes control
70 // (in silicon) for many link-specific issues, the Linux driver is left with the
71 // rest, which turns out to be a difficult, time critical chore.
72 
73 // These "worker" functions will handle things like FC Logins; all
74 // processes with I/O to our device must wait for the Login to complete
75 // and (if successful) I/O to resume.  In the event of a malfunctioning or
76 // very busy loop, it may take hundreds of millisecs or even seconds to complete
77 // a frame send.  We don't want to hang up the entire server (and all
78 // processes which don't depend on Fibre) during this wait.
79 
80 // The Tachyon chip can have around 30,000 I/O operations ("exchanges")
81 // open at one time.  However, each exchange must be initiated
82 // synchronously (i.e. each of the 30k I/O had to be started one at a
83 // time by sending a starting frame via Tachyon's outbound que).
84 
85 // To accomodate kernel "module" build, this driver limits the exchanges
86 // to 256, because of the contiguous physical memory limitation of 128M.
87 
88 // Typical FC Exchanges are opened presuming the FC frames start without errors,
89 // while Exchange completion is handled in the interrupt handler.  This
90 // optimizes performance for the "everything's working" case.
91 // However, when we have FC related errors or hot plugging of FC ports, we pause
92 // I/O and handle FC-specific tasks in the worker thread.  These FC-specific
93 // functions will handle things like FC Logins and Aborts.  As the Login sequence
94 // completes to each and every target, I/O can resume to that target.
95 
96 // Our kernel "worker thread" must share the HBA with threads calling
97 // "queuecommand".  We define a "BoardLock" semaphore which indicates
98 // to "queuecommand" that the HBA is unavailable, and Cmnds are added to a
99 // board lock Q.  When the worker thread finishes with the board, the board
100 // lock Q commands are completed with status causing immediate retry.
101 // Typically, the board is locked while Logins are in progress after an
102 // FC Link Down condition.  When Cmnds are re-queued after board lock, the
103 // particular Scsi channel/target may or may not have logged back in.  When
104 // the device is waiting for login, the "prli" flag is clear, in which case
105 // commands are passed to a Link Down Q.  Whenever the login finally completes,
106 // the LinkDown Q is completed, again with status causing immediate retry.
107 // When FC devices are logged in, we build and start FC commands to the
108 // devices.
109 
110 // NOTE!! As of May 2000, kernel 2.2.14, the error recovery logic for devices
111 // that never log back in (e.g. physically removed) is NOT completely
112 // understood.  I've still seen instances of system hangs on failed Write
113 // commands (possibly from the ext2 layer?) on device removal.  Such special
114 // cases need to be evaluated from a system/application view - e.g., how
115 // exactly does the system want me to complete commands when the device is
116 // physically removed??
117 
118 // local functions
119 
120 static void SetLoginFields(PFC_LOGGEDIN_PORT pLoggedInPort, TachFCHDR_GCMND * fchs, u8 PDisc, u8 Originator);
121 
122 static void AnalyzeIncomingFrame(CPQFCHBA * dev, u32 QNdx);
123 
124 static void SendLogins(CPQFCHBA * dev, __u32 * FabricPortIds);
125 
126 static int verify_PLOGI(PTACHYON fcChip, TachFCHDR_GCMND * fchs, u32 * reject_explain);
127 static int verify_PRLI(TachFCHDR_GCMND * fchs, u32 * reject_explain);
128 
129 static void LoadWWN(PTACHYON fcChip, u8 * dest, u8 type);
130 static void BuildLinkServicePayload(PTACHYON fcChip, u32 type, void *payload);
131 
132 static void UnblockScsiDevice(struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort);
133 
134 static void cpqfcTSCheckandSnoopFCP(PTACHYON fcChip, u32 x_ID);
135 
136 static void CompleteBoardLockCmnd(CPQFCHBA * dev);
137 
138 static void RevalidateSEST(struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort);
139 
140 static void IssueReportLunsCommand(CPQFCHBA * dev, TachFCHDR_GCMND * fchs);
141 
142 // (see scsi_error.c comments on kernel task creation)
143 
cpqfcTSWorkerThread(void * host)144 void cpqfcTSWorkerThread(void *host)
145 {
146 	struct Scsi_Host *shpnt = (struct Scsi_Host *) host;
147 	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
148 #ifdef PCI_KERNEL_TRACE
149 	PTACHYON fcChip = &dev->fcChip;
150 #endif
151 	struct fs_struct *fs;
152 	DECLARE_MUTEX_LOCKED(fcQueReady);
153 	DECLARE_MUTEX_LOCKED(fcTYOBcomplete);
154 	DECLARE_MUTEX_LOCKED(TachFrozen);
155 	DECLARE_MUTEX_LOCKED(BoardLock);
156 
157 	ENTER("WorkerThread");
158 
159 	lock_kernel();
160 	/*
161 	 * If we were started as result of loading a module, close all of the
162 	 * user space pages.  We don't need them, and if we didn't close them
163 	 * they would be locked into memory.
164 	 *
165 	 * FIXME: should use daemonize!
166 	 */
167 	exit_mm(current);
168 
169 	current->session = 1;
170 	current->pgrp = 1;
171 
172 	/* Become as one with the init task */
173 
174 	exit_fs(current);	/* current->fs->count--; */
175 	fs = init_task.fs;
176 	current->fs = fs;
177 	atomic_inc(&fs->count);
178 
179 	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
180 
181 
182 	/*
183 	 * Set the name of this process.
184 	 */
185 	sprintf(current->comm, "cpqfcTS_wt_%d", shpnt->host_no);
186 
187 	dev->fcQueReady = &fcQueReady;	// primary wait point
188 	dev->TYOBcomplete = &fcTYOBcomplete;
189 	dev->TachFrozen = &TachFrozen;
190 
191 
192 	dev->worker_thread = current;
193 
194 	unlock_kernel();
195 
196 	if (dev->notify_wt != NULL)
197 		up(dev->notify_wt);	// OK to continue
198 
199 	while (1) {
200 		unsigned long flags;
201 
202 		down_interruptible(&fcQueReady);	// wait for something to do
203 
204 		if (signal_pending(current))
205 			break;
206 
207 		PCI_TRACE(0x90)
208 		// first, take the IO lock so the SCSI upper layers can't call
209 		// into our _quecommand function (this also disables INTs)
210 		spin_lock_irqsave(&io_request_lock, flags);	// STOP _que function
211 		PCI_TRACE(0x90)
212 
213 		CPQ_SPINLOCK_HBA(dev)
214 		// next, set this pointer to indicate to the _quecommand function
215 		// that the board is in use, so it should que the command and
216 		// immediately return (we don't actually require the semaphore function
217 		// in this driver rev)
218 		dev->BoardLock = &BoardLock;
219 
220 		PCI_TRACE(0x90)
221 		// release the IO lock (and re-enable interrupts)
222 		spin_unlock_irqrestore(&io_request_lock, flags);
223 
224 		// disable OUR HBA interrupt (keep them off as much as possible
225 		// during error recovery)
226 		disable_irq(dev->HostAdapter->irq);
227 
228 		// OK, let's process the Fibre Channel Link Q and do the work
229 		cpqfcTS_WorkTask(shpnt);
230 
231 		// hopefully, no more "work" to do;
232 		// re-enable our INTs for "normal" completion processing
233 		enable_irq(dev->HostAdapter->irq);
234 
235 
236 		dev->BoardLock = NULL;	// allow commands to be queued
237 		CPQ_SPINUNLOCK_HBA(dev)
238 
239 		// Now, complete any Cmnd we Q'd up while BoardLock was held
240 		CompleteBoardLockCmnd(dev);
241 
242 
243 	}
244 	// hopefully, the signal was for our module exit...
245 	if (dev->notify_wt != NULL)
246 		up(dev->notify_wt);	// yep, we're outta here
247 }
248 
249 
250 // Freeze Tachyon routine.
251 // If Tachyon is already frozen, return 0
252 // If Tachyon is not frozen, call freeze function, return 1
253 //
FreezeTach(CPQFCHBA * dev)254 static u8 FreezeTach(CPQFCHBA * dev)
255 {
256 	PTACHYON fcChip = &dev->fcChip;
257 	u8 FrozeTach = 0;
258 	// It's possible that the chip is already frozen; if so,
259 	// "Freezing" again will NOT! generate another Freeze
260 	// Completion Message.
261 
262 	if ((fcChip->Registers.TYstatus.value & 0x70000) != 0x70000) {	// (need to freeze...)
263 		fcChip->FreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
264 		// 2. Get Tach freeze confirmation
265 		// (synchronize SEST manipulation with Freeze Completion Message)
266 		// we need INTs on so semaphore can be set.
267 		enable_irq(dev->HostAdapter->irq);	// only way to get Semaphore
268 		down_interruptible(dev->TachFrozen);	// wait for INT handler sem.
269 		// can we TIMEOUT semaphore wait?? TBD
270 		disable_irq(dev->HostAdapter->irq);
271 		FrozeTach = 1;
272 	}			// (else, already frozen)
273 	return FrozeTach;
274 }
275 
276 // This is the kernel worker thread task, which processes FC
277 // tasks which were queued by the Interrupt handler or by
278 // other WorkTask functions.
279 
280 #define DBG 1
281 
282 //#undef DBG
cpqfcTS_WorkTask(struct Scsi_Host * shpnt)283 void cpqfcTS_WorkTask(struct Scsi_Host *shpnt)
284 {
285 	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
286 	PTACHYON fcChip = &dev->fcChip;
287 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
288 	u32 QconsumerNdx;
289 	s32 ExchangeID;
290 	u32 ulStatus = 0;
291 	TachFCHDR_GCMND fchs;
292 	PFC_LINK_QUE fcLQ = dev->fcLQ;
293 
294 	ENTER("WorkTask");
295 
296 	// copy current index to work on
297 	QconsumerNdx = fcLQ->consumer;
298 
299 	PCI_TRACEO(fcLQ->Qitem[QconsumerNdx].Type, 0x90)
300 
301 	// NOTE: when this switch completes, we will "consume" the Que item
302 	//  printk("Que type %Xh\n", fcLQ->Qitem[QconsumerNdx].Type);
303 	switch (fcLQ->Qitem[QconsumerNdx].Type)
304 	{
305 		// incoming frame - link service (ACC, UNSOL REQ, etc.)
306 		// or FCP-SCSI command
307 	case SFQ_UNKNOWN:
308 		AnalyzeIncomingFrame(dev, QconsumerNdx);
309 		break;
310 
311 	case EXCHANGE_QUEUED:
312 		// an Exchange (i.e. FCP-SCSI) was previously
313 		// Queued because the link was down.  The
314 		// heartbeat timer detected it and Queued it here.
315 		// We attempt to start it again, and if
316 		// successful we clear the EXCHANGE_Q flag.
317 		// If the link doesn't come up, the Exchange
318 		// will eventually time-out.
319 
320 		ExchangeID = (s32) fcLQ->Qitem[QconsumerNdx].ulBuff[0]; // x_ID copied from DPC timeout function
321 
322 		// It's possible that a Q'd exchange could have already
323 		// been started by other logic (e.g. ABTS process)
324 		// Don't start if already started (Q'd flag clear)
325 
326 		if (Exchanges->fcExchange[ExchangeID].status & EXCHANGE_QUEUED) {
327 //      		printk(" *Start Q'd x_ID %Xh: type %Xh ",
328 //				ExchangeID, Exchanges->fcExchange[ExchangeID].type);
329 
330 			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
331 			if (!ulStatus) {
332 //				printk("success* ");
333 			} else {
334 #ifdef DBG
335 				if (ulStatus == EXCHANGE_QUEUED)
336 					printk("Queued* ");
337 				else
338 					printk("failed* ");
339 #endif
340 			}
341 		}
342 		break;
343 
344 	case LINKDOWN:
345 		// (lots of things already done in INT handler) future here?
346 		break;
347 
348 	case LINKACTIVE:	// Tachyon set the Lup bit in FM status
349 		// NOTE: some misbehaving FC ports (like Tach2.1)
350 		// can re-LIP immediately after a LIP completes.
351 		// if "initiator", need to verify LOGs with ports
352 //		printk("\n*LNKUP* ");
353 
354 		if (fcChip->Options.initiator)
355 			SendLogins(dev, NULL);	// PLOGI or PDISC, based on fcPort data
356 		// if SendLogins successfully completes, PortDiscDone
357 		// will be set.
358 		// If SendLogins was successful, then we expect to get incoming
359 		// ACCepts or REJECTs, which are handled below.
360 		break;
361 
362 		// LinkService and Fabric request/reply processing
363 	case ELS_FDISC:	// need to send Fabric Discovery (Login)
364 	case ELS_FLOGI:	// need to send Fabric Login
365 	case ELS_SCR:		// need to send State Change Registration
366 	case FCS_NSR:		// need to send Name Service Request
367 	case ELS_PLOGI:	// need to send PLOGI
368 	case ELS_ACC:		// send generic ACCept
369 	case ELS_PLOGI_ACC:	// need to send ELS ACCept frame to recv'd PLOGI
370 	case ELS_PRLI_ACC:	// need to send ELS ACCept frame to recv'd PRLI
371 	case ELS_LOGO:		// need to send ELS LOGO (logout)
372 	case ELS_LOGO_ACC:	// need to send ELS ACCept frame to recv'd PLOGI
373 	case ELS_RJT:		// ReJecT reply
374 	case ELS_PRLI:		// need to send ELS PRLI
375 
376 
377 //		printk(" *ELS %Xh* ", fcLQ->Qitem[QconsumerNdx].Type);
378 		// if PortDiscDone is not set, it means the SendLogins routine
379 		// failed to complete -- assume that LDn occurred, so login frames
380 		// are invalid
381 		if (!dev->PortDiscDone)	// cleared by LDn
382 		{
383 			printk("Discard Q'd ELS login frame\n");
384 			break;
385 		}
386 
387 		ulStatus = cpqfcTSBuildExchange(dev, fcLQ->Qitem[QconsumerNdx].Type,	// e.g. PLOGI
388 						(TachFCHDR_GCMND *)
389 						fcLQ->Qitem[QconsumerNdx].ulBuff,	// incoming fchs
390 						NULL,	// no data (no scatter/gather list)
391 						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
392 
393 		if (!ulStatus)	// Exchange setup?
394 		{
395 			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
396 			if (!ulStatus) {
397 				// submitted to Tach's Outbound Que (ERQ PI incremented)
398 				// waited for completion for ELS type (Login frames issued
399 				// synchronously)
400 			} else
401 				// check reason for Exchange not being started - we might
402 				// want to Queue and start later, or fail with error
403 			{
404 
405 			}
406 		}
407 
408 		else		// Xchange setup failed...
409 			printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus);
410 
411 		break;
412 
413 	case SCSI_REPORT_LUNS:
414 		// pass the incoming frame (actually, it's a PRLI frame)
415 		// so we can send REPORT_LUNS, in order to determine VSA/PDU
416 		// FCP-SCSI Lun address mode
417 		IssueReportLunsCommand(dev, (TachFCHDR_GCMND *)
418 				       fcLQ->Qitem[QconsumerNdx].ulBuff);
419 
420 		break;
421 
422 	case BLS_ABTS:		// need to ABORT one or more exchanges
423 		{
424 			s32 x_ID = fcLQ->Qitem[QconsumerNdx].ulBuff[0];
425 			u8 FrozeTach = 0;
426 
427 			if (x_ID > TACH_SEST_LEN)	// (in)sanity check
428 			{
429 //				printk( " cpqfcTS ERROR! BOGUS x_ID %Xh", x_ID);
430 				break;
431 			}
432 			if (Exchanges->fcExchange[x_ID].Cmnd == NULL)	// should be RARE
433 			{
434 //				printk(" ABTS %Xh Scsi Cmnd null! ", x_ID);
435 				break;	// nothing to abort!
436 			}
437 //#define ABTS_DBG
438 #ifdef ABTS_DBG
439 			printk("INV SEST[%X] ", x_ID);
440 			if (Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT) {
441 				printk("FC2TO");
442 			}
443 			if (Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT) {
444 				printk("IA");
445 			}
446 			if (Exchanges->fcExchange[x_ID].status & PORTID_CHANGED) {
447 				printk("PORTID");
448 			}
449 			if (Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED) {
450 				printk("DEVRM");
451 			}
452 			if (Exchanges->fcExchange[x_ID].status & LINKFAIL_TX) {
453 				printk("LKF");
454 			}
455 			if (Exchanges->fcExchange[x_ID].status & FRAME_TO) {
456 				printk("FRMTO");
457 			}
458 			if (Exchanges->fcExchange[x_ID].status & ABORTSEQ_NOTIFY) {
459 				printk("ABSQ");
460 			}
461 			if (Exchanges->fcExchange[x_ID].status & SFQ_FRAME) {
462 				printk("SFQFR");
463 			}
464 
465 			if (Exchanges->fcExchange[x_ID].type == 0x2000)
466 				printk(" WR");
467 			else if (Exchanges->fcExchange[x_ID].type == 0x3000)
468 				printk(" RD");
469 			else if (Exchanges->fcExchange[x_ID].type == 0x10)
470 				printk(" ABTS");
471 			else
472 				printk(" %Xh", Exchanges->fcExchange[x_ID].type);
473 
474 			if (!(Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)) {
475 				printk(" Cmd %p, ", Exchanges->fcExchange[x_ID].Cmnd);
476 
477 				printk(" brd/chn/trg/lun %d/%d/%d/%d port_id %06X\n",
478 				       dev->HBAnum, Exchanges->fcExchange[x_ID].Cmnd->channel, Exchanges->fcExchange[x_ID].Cmnd->target, Exchanges->fcExchange[x_ID].Cmnd->lun, Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF);
479 			} else	// assume that Cmnd ptr is invalid on _abort()
480 			{
481 				printk(" Cmd ptr invalid\n");
482 			}
483 #endif
484 			// Steps to ABORT a SEST exchange:
485 			// 1. Freeze TL SCSI assists & ERQ (everything)
486 			// 2. Receive FROZEN inbound CM (must succeed!)
487 			// 3. Invalidate x_ID SEST entry
488 			// 4. Resume TL SCSI assists & ERQ (everything)
489 			// 5. Build/start on exchange - change "type" to BLS_ABTS,
490 			//    timeout to X sec (RA_TOV from PLDA is actually 0)
491 			// 6. Set Exchange Q'd status if ABTS cannot be started,
492 			//    or simply complete Exchange in "Terminate" condition
493 
494 			PCI_TRACEO(x_ID, 0xB4)
495 			    // 1 & 2 . Freeze Tach & get confirmation of freeze
496 			    FrozeTach = FreezeTach(dev);
497 
498 			// 3. OK, Tachyon is frozen, so we can invalidate SEST exchange.
499 			// FC2_TIMEOUT means we are originating the abort, while
500 			// TARGET_ABORT means we are ACCepting an abort.
501 			// LINKFAIL_TX, ABORTSEQ_NOFITY, INV_ENTRY or FRAME_TO are
502 			// all from Tachyon:
503 			// Exchange was corrupted by LDn or other FC physical failure
504 			// INITIATOR_ABORT means the upper layer driver/application
505 			// requested the abort.
506 
507 			// clear bit 31 (VALid), to invalidate & take control from TL
508 			fcChip->SEST->u[x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;
509 
510 			// examine and Tach's "Linked List" for IWEs that
511 			// received (nearly) simultaneous transfer ready (XRDY)
512 			// repair linked list if necessary (TBD!)
513 			// (If we ignore the "Linked List", we will time out
514 			// WRITE commands where we received the FCP-SCSI XFRDY
515 			// frame (because Tachyon didn't processes it).  Linked List
516 			// management should be done as an optimization.
517 
518 //			readl( fcChip->Registers.ReMapMemBase+TL_MEM_SEST_LINKED_LIST ));
519 
520 			// 4. Resume all Tachlite functions (for other open Exchanges)
521 			// as quickly as possible to allow other exchanges to other ports
522 			// to resume.  Freezing Tachyon may cause cascading errors, because
523 			// any received SEST frame cannot be processed by the SEST.
524 			// Don't "unfreeze" unless Link is operational
525 			if (FrozeTach)	// did we just freeze it (above)?
526 				fcChip->UnFreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
527 
528 			PCI_TRACEO(x_ID, 0xB4)
529 			    // Note there is no confirmation that the chip is "unfrozen".  Also,
530 			    // if the Link is down when unfreeze is called, it has no effect.
531 			    // Chip will unfreeze when the Link is back up.
532 			    // 5. Now send out Abort commands if possible
533 			    // Some Aborts can't be "sent" (Port_id changed or gone);
534 			    // if the device is gone, there is no port_id to send the ABTS to.
535 			if (!(Exchanges->fcExchange[x_ID].status & PORTID_CHANGED)
536 				&& !(Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED)) {
537 				Exchanges->fcExchange[x_ID].type = BLS_ABTS;
538 				fchs.s_id = Exchanges->fcExchange[x_ID].fchs.d_id;
539 				ulStatus = cpqfcTSBuildExchange(dev, BLS_ABTS, &fchs,	// (uses only s_id)
540 								NULL,	// (no scatter/gather list for ABTS)
541 								&x_ID);	// ABTS on this Exchange ID
542 
543 				if (!ulStatus)	// Exchange setup build OK?
544 				{
545 
546 					// ABTS may be needed because an Exchange was corrupted
547 					// by a Link disruption.  If the Link is UP, we can
548 					// presume that this ABTS can start immediately; otherwise,
549 					// set Que'd status so the Login functions
550 					// can restart it when the FC physical Link is restored
551 					if (((fcChip->Registers.FMstatus.value & 0xF0) & 0x80))	// loop init?
552 					{
553 //						printk(" *set Q status x_ID %Xh on LDn* ", x_ID);
554 						Exchanges->fcExchange[x_ID].status |= EXCHANGE_QUEUED;
555 					}
556 
557 					else	// what FC device (port_id) does the Cmd belong to?
558 					{
559 						PFC_LOGGEDIN_PORT pLoggedInPort = Exchanges->fcExchange[x_ID].pLoggedInPort;
560 
561 						// if Port is logged in, we might start the abort.
562 
563 						if ((pLoggedInPort != NULL)
564 						    && (pLoggedInPort->prli == 1)) {
565 							// it's possible that an Exchange has already been Queued
566 							// to start after Login completes.  Check and don't
567 							// start it (again) here if Q'd status set
568 //							printk(" ABTS xchg %Xh ", x_ID);
569 							if (Exchanges->fcExchange[x_ID].status & EXCHANGE_QUEUED) {
570 //								printk("already Q'd ");
571 							} else {
572 //								printk("starting ");
573 								fcChip->fcStats.FC2aborted++;
574 								ulStatus = cpqfcTSStartExchange(dev, x_ID);
575 								if (!ulStatus) {
576 									// OK
577 									// submitted to Tach's Outbound Que (ERQ PI incremented)
578 								} else {
579 //									printk("ABTS exchange start failed -status %Xh, x_ID %Xh ", ulStatus, x_ID);
580 								}
581 							}
582 						}
583 					}
584 				} else	// what the #@!
585 				{	// how do we fail to build an Exchange for ABTS??
586 					printk("ABTS exchange build failed -status %Xh, x_ID %Xh\n", ulStatus, x_ID);
587 				}
588 			} else	// abort without ABTS -- just complete exchange/Cmnd to Linux
589 			{
590 //				printk(" *Terminating x_ID %Xh on %Xh* ",
591 //					x_ID, Exchanges->fcExchange[x_ID].status);
592 				cpqfcTSCompleteExchange(dev->PciDev, fcChip, x_ID);
593 
594 			}
595 		}		// end of ABTS case
596 		break;
597 
598 	case BLS_ABTS_ACC:	// need to ACCept one ABTS
599 		// (NOTE! this code not updated for Linux yet..)
600 		printk(" *ABTS_ACC* ");
601 		// 1. Freeze TL
602 
603 		fcChip->FreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
604 		memcpy(		// copy the incoming ABTS frame
605 			      &fchs, fcLQ->Qitem[QconsumerNdx].ulBuff,	// incoming fchs
606 			      sizeof(fchs));
607 
608 		// 3. OK, Tachyon is frozen so we can invalidate SEST entry
609 		// (if necessary)
610 		// Status FC2_TIMEOUT means we are originating the abort, while
611 		// TARGET_ABORT means we are ACCepting an abort
612 
613 		ExchangeID = fchs.ox_rx_id & 0x7FFF;	// RX_ID for exchange
614 //		printk("ABTS ACC for Target ExchangeID %Xh\n", ExchangeID);
615 
616 		// sanity check on received ExchangeID
617 		if (Exchanges->fcExchange[ExchangeID].status == TARGET_ABORT) {
618 			// clear bit 31 (VALid), to invalidate & take control from TL
619 //			printk("Invalidating SEST exchange %Xh\n", ExchangeID);
620 			fcChip->SEST->u[ExchangeID].IWE.Hdr_Len &= 0x7FFFFFFF;
621 		}
622 
623 		// 4. Resume all Tachlite functions (for other open Exchanges)
624 		// as quickly as possible to allow other exchanges to other ports
625 		// to resume.  Freezing Tachyon for too long may royally screw
626 		// up everything!
627 		fcChip->UnFreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
628 
629 		// Note there is no confirmation that the chip is "unfrozen".  Also,
630 		// if the Link is down when unfreeze is called, it has no effect.
631 		// Chip will unfreeze when the Link is back up.
632 
633 		// 5. Now send out Abort ACC reply for this exchange
634 		Exchanges->fcExchange[ExchangeID].type = BLS_ABTS_ACC;
635 
636 		fchs.s_id = Exchanges->fcExchange[ExchangeID].fchs.d_id;
637 		ulStatus = cpqfcTSBuildExchange(dev, BLS_ABTS_ACC, &fchs, NULL,	// no data (no scatter/gather list)
638 						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
639 
640 		if (!ulStatus)	// Exchange setup?
641 		{
642 			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
643 			if (!ulStatus) {
644 				// submitted to Tach's Outbound Que (ERQ PI incremented)
645 				// waited for completion for ELS type (Login frames issued
646 				// synchronously)
647 			} else
648 				// check reason for Exchange not being started - we might
649 				// want to Queue and start later, or fail with error
650 			{
651 
652 			}
653 		}
654 		break;
655 
656 	case BLS_ABTS_RJT:	// need to ReJecT one ABTS; reject implies the
657 		// exchange doesn't exist in the TARGET context.
658 		// ExchangeID has to come from LinkService space.
659 
660 		printk(" *ABTS_RJT* ");
661 		ulStatus = cpqfcTSBuildExchange(dev, BLS_ABTS_RJT, (TachFCHDR_GCMND *)
662 						fcLQ->Qitem[QconsumerNdx].ulBuff,	// incoming fchs
663 						NULL,	// no data (no scatter/gather list)
664 						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
665 
666 		if (!ulStatus)	// Exchange setup OK?
667 		{
668 			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
669 			// If it fails, we aren't required to retry.
670 		}
671 		if (ulStatus) {
672 			printk("Failed to send BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
673 		} else {
674 			printk("Sent BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
675 
676 		}
677 		break;
678 
679 	default:
680 		break;
681 	}			// end switch
682 	// done with this item - now set the NEXT index
683 
684 	if (QconsumerNdx + 1 >= FC_LINKQ_DEPTH)	// rollover test
685 		fcLQ->consumer = 0;
686 	else
687 		fcLQ->consumer++;
688 
689 	PCI_TRACEO(fcLQ->Qitem[QconsumerNdx].Type, 0x94)
690 
691 	LEAVE("WorkTask");
692 	return;
693 }
694 
695 
696 
697 
698 // When Tachyon reports link down, bad al_pa, or Link Service (e.g. Login)
699 // commands come in, post to the LinkQ so that action can be taken outside the
700 // interrupt handler.
701 // This circular Q works like Tachyon's que - the producer points to the next
702 // (unused) entry.  Called by Interrupt handler, WorkerThread, Timer
703 // sputlinkq
cpqfcTSPutLinkQue(CPQFCHBA * dev,int Type,void * QueContent)704 void cpqfcTSPutLinkQue(CPQFCHBA * dev, int Type, void *QueContent)
705 {
706 	PTACHYON fcChip = &dev->fcChip;
707 //	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
708 	PFC_LINK_QUE fcLQ = dev->fcLQ;
709 	u32 ndx;
710 
711 	ENTER("cpqfcTSPutLinkQ");
712 
713 	ndx = fcLQ->producer;
714 
715 	ndx += 1;		// test for Que full
716 
717 
718 
719 	if (ndx >= FC_LINKQ_DEPTH)	// rollover test
720 		ndx = 0;
721 
722 	if (ndx == fcLQ->consumer)	// QUE full test
723 	{
724 		// QUE was full! lost LK command (fatal to logic)
725 		fcChip->fcStats.lnkQueFull++;
726 
727 		printk("*LinkQ Full!*");
728 		TriggerHBA(fcChip->Registers.ReMapMemBase, 1);
729 /*
730 		{
731 			int i;
732 			printk("LinkQ PI %d, CI %d\n", fcLQ->producer, fcLQ->consumer);
733 
734 			for( i=0; i< FC_LINKQ_DEPTH; )
735 			{
736 				printk(" [%d]%Xh ", i, fcLQ->Qitem[i].Type);
737 				if( (++i %8) == 0)
738 					printk("\n");
739 			}
740 		}
741 */
742 		printk("cpqfcTS: WARNING!! PutLinkQue - FULL!\n");	// we're hung
743 	}
744 	else			// QUE next element
745 	{
746 		// Prevent certain multiple (back-to-back) requests.
747 		// This is important in that we don't want to issue multiple
748 		// ABTS for the same Exchange, or do multiple FM inits, etc.
749 		// We can never be sure of the timing of events reported to
750 		// us by Tach's IMQ, which can depend on system/bus speeds,
751 		// FC physical link circumstances, etc.
752 
753 		if ((fcLQ->producer != fcLQ->consumer)
754 		    && (Type == FMINIT)) {
755 			s32 lastNdx;	// compute previous producer index
756 			if (fcLQ->producer)
757 				lastNdx = fcLQ->producer - 1;
758 			else
759 				lastNdx = FC_LINKQ_DEPTH - 1;
760 
761 
762 			if (fcLQ->Qitem[lastNdx].Type == FMINIT) {
763 //      			printk(" *skip FMINIT Q post* ");
764 //        			goto DoneWithPutQ;
765 			}
766 
767 		}
768 		// OK, add the Q'd item...
769 		fcLQ->Qitem[fcLQ->producer].Type = Type;
770 		memcpy(fcLQ->Qitem[fcLQ->producer].ulBuff, QueContent, sizeof(fcLQ->Qitem[fcLQ->producer].ulBuff));
771 		fcLQ->producer = ndx;	// increment Que producer
772 		// set semaphore to wake up Kernel (worker) thread
773 		up(dev->fcQueReady);
774 	}
775 //DoneWithPutQ:
776 	LEAVE("cpqfcTSPutLinkQ");
777 }
778 
779 // reset device ext FC link Q
cpqfcTSLinkQReset(CPQFCHBA * dev)780 void cpqfcTSLinkQReset(CPQFCHBA * dev)
781 {
782 	PFC_LINK_QUE fcLQ = dev->fcLQ;
783 	fcLQ->producer = 0;
784 	fcLQ->consumer = 0;
785 }
786 
787 // When Tachyon gets an unassisted FCP-SCSI frame, post here so
788 // an arbitrary context thread (e.g. IOCTL loopback test function)
789 // can process it.
790 
791 // (NOTE: Not revised for Linux)
792 // This Q works like Tachyon's que - the producer points to the next
793 // (unused) entry.
cpqfcTSPutScsiQue(CPQFCHBA * dev,int Type,void * QueContent)794 void cpqfcTSPutScsiQue(CPQFCHBA * dev, int Type, void *QueContent)
795 {
796 //  CPQFCHBA *dev = (CPQFCHBA *)shpnt->hostdata;
797 //  PTACHYON fcChip = &dev->fcChip;
798 
799 //  u32 ndx;
800 
801 //  u32 *pExchangeID;
802 //  s32 ExchangeID;
803 
804 /*
805   KeAcquireSpinLockAtDpcLevel( &pDevExt->fcScsiQueLock);
806   ndx = pDevExt->fcScsiQue.producer + 1;  // test for Que full
807 
808   if( ndx >= FC_SCSIQ_DEPTH ) // rollover test
809     ndx = 0;
810 
811   if( ndx == pDevExt->fcScsiQue.consumer )   // QUE full test
812   {
813                        // QUE was full! lost LK command (fatal to logic)
814     fcChip->fcStats.ScsiQueFull++;
815 #ifdef DBG
816     printk( "fcPutScsiQue - FULL!\n");
817 #endif
818 
819   }
820   else                        // QUE next element
821   {
822     pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].Type = Type;
823 
824     if( Type == FCP_RSP )
825     {
826       // this TL inbound message type means that a TL SEST exchange has
827       // copied an FCP response frame into a buffer pointed to by the SEST
828       // entry.  That buffer is allocated in the SEST structure at ->RspHDR.
829       // Copy the RspHDR for use by the Que handler.
830       pExchangeID = (u32 *)QueContent;
831 
832       memcpy(
833 	      pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff,
834         &fcChip->SEST->RspHDR[ *pExchangeID ],
835 	      sizeof(pDevExt->fcScsiQue.Qitem[0].ulBuff)); // (any element for size)
836 
837     }
838     else
839     {
840       memcpy(
841 	      pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff,
842         QueContent,
843 	      sizeof(pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff));
844     }
845 
846     pDevExt->fcScsiQue.producer = ndx;  // increment Que
847 
848 
849     KeSetEvent( &pDevExt->TYIBscsi,  // signal any waiting thread
850        0,                    // no priority boost
851 		   0 );              // no waiting later for this event
852   }
853   KeReleaseSpinLockFromDpcLevel( &pDevExt->fcScsiQueLock);
854 */
855 }
856 
857 static void ProcessELS_Request(CPQFCHBA *, TachFCHDR_GCMND *);
858 static void ProcessELS_Reply(CPQFCHBA *, TachFCHDR_GCMND *);
859 static void ProcessFCS_Reply(CPQFCHBA *, TachFCHDR_GCMND *);
860 
cpqfcTSImplicitLogout(CPQFCHBA * dev,PFC_LOGGEDIN_PORT pFcPort)861 void cpqfcTSImplicitLogout(CPQFCHBA * dev, PFC_LOGGEDIN_PORT pFcPort)
862 {
863 	PTACHYON fcChip = &dev->fcChip;
864 
865 	if (pFcPort->port_id != 0xFFFC01)	// don't care about Fabric
866 	{
867 		fcChip->fcStats.logouts++;
868 		printk("cpqfcTS: Implicit logout of WWN %08X%08X, port_id %06X\n", (u32) pFcPort->u.liWWN, (u32) (pFcPort->u.liWWN >> 32), pFcPort->port_id);
869 
870 		// Terminate I/O with this (Linux) Scsi target
871 		cpqfcTSTerminateExchange(dev, &pFcPort->ScsiNexus, DEVICE_REMOVED);
872 	}
873 	// Do an "implicit logout" - we can't really Logout the device
874 	// (i.e. with LOGOut Request) because of port_id confusion
875 	// (i.e. the Other port has no port_id).
876 	// A new login for that WWN will have to re-write port_id (0 invalid)
877 	pFcPort->port_id = 0;	// invalid!
878 	pFcPort->pdisc = 0;
879 	pFcPort->prli = 0;
880 	pFcPort->plogi = 0;
881 	pFcPort->flogi = 0;
882 	pFcPort->LOGO_timer = 0;
883 	pFcPort->device_blocked = 1;	// block Scsi Requests
884 	pFcPort->ScsiNexus.VolumeSetAddressing = 0;
885 }
886 
887 
888 // On FC-AL, there is a chance that a previously known device can
889 // be quietly removed (e.g. with non-managed hub),
890 // while a NEW device (with different WWN) took the same alpa or
891 // even 24-bit port_id.  This chance is unlikely but we must always
892 // check for it.
893 
TestDuplicatePortId(CPQFCHBA * dev,PFC_LOGGEDIN_PORT pLoggedInPort)894 static void TestDuplicatePortId(CPQFCHBA * dev, PFC_LOGGEDIN_PORT pLoggedInPort)
895 {
896 	PTACHYON fcChip = &dev->fcChip;
897 	// set "other port" at beginning of fcPorts list
898 	PFC_LOGGEDIN_PORT pOtherPortWithPortId = fcChip->fcPorts.pNextPort;
899 	while (pOtherPortWithPortId) {
900 		if ((pOtherPortWithPortId->port_id == pLoggedInPort->port_id)
901 		    && (pOtherPortWithPortId != pLoggedInPort)) {
902 			// trouble!  (Implicitly) Log the other guy out
903 			printk(" *port_id %Xh is duplicated!* ", pOtherPortWithPortId->port_id);
904 			cpqfcTSImplicitLogout(dev, pOtherPortWithPortId);
905 		}
906 		pOtherPortWithPortId = pOtherPortWithPortId->pNextPort;
907 	}
908 }
909 
910 // Dynamic Memory Allocation for newly discovered FC Ports.
911 // For simplicity, maintain fcPorts structs for ALL
912 // for discovered devices, including those we never do I/O with
913 // (e.g. Fabric addresses)
914 
CreateFcPort(CPQFCHBA * dev,PFC_LOGGEDIN_PORT pLastLoggedInPort,TachFCHDR_GCMND * fchs,LOGIN_PAYLOAD * plogi)915 static PFC_LOGGEDIN_PORT CreateFcPort(CPQFCHBA * dev, PFC_LOGGEDIN_PORT pLastLoggedInPort, TachFCHDR_GCMND * fchs, LOGIN_PAYLOAD * plogi)
916 {
917 	PTACHYON fcChip = &dev->fcChip;
918 	PFC_LOGGEDIN_PORT pNextLoggedInPort = NULL;
919 	int i;
920 
921 	printk("cpqfcTS: New FC port %06Xh WWN: ", fchs->s_id);
922 	for (i = 3; i >= 0; i--)	// copy the LOGIN port's WWN
923 		printk("%02X", plogi->port_name[i]);
924 	for (i = 7; i > 3; i--)	// copy the LOGIN port's WWN
925 		printk("%02X", plogi->port_name[i]);
926 
927 	// allocate mem for new port
928 	// (these are small and rare allocations...)
929 	pNextLoggedInPort = kmalloc(sizeof(FC_LOGGEDIN_PORT), GFP_ATOMIC);
930 
931 	// allocation succeeded?  Fill out NEW PORT
932 	if (pNextLoggedInPort) {
933 		// clear out any garbage (sometimes exists)
934 		memset(pNextLoggedInPort, 0, sizeof(FC_LOGGEDIN_PORT));
935 		// If we login to a Fabric, we don't want to treat it
936 		// as a SCSI device...
937 		if ((fchs->s_id & 0xFFF000) != 0xFFF000) {
938 			int i;
939 
940 			// create a unique "virtual" SCSI Nexus (for now, just a
941 			// new target ID) -- we will update channel/target on REPORT_LUNS
942 			// special case for very first SCSI target...
943 			if (dev->HostAdapter->max_id == 0) {
944 				pNextLoggedInPort->ScsiNexus.target = 0;
945 				fcChip->fcPorts.ScsiNexus.target = -1;	// don't use "stub"
946 			} else {
947 				pNextLoggedInPort->ScsiNexus.target = dev->HostAdapter->max_id;
948 			}
949 
950 			// initialize the lun[] Nexus struct for lun masking
951 			for (i = 0; i < CPQFCTS_MAX_LUN; i++)
952 				pNextLoggedInPort->ScsiNexus.lun[i] = 0xFF;	// init to NOT USED
953 
954 			pNextLoggedInPort->ScsiNexus.channel = 0;	// cpqfcTS has 1 FC port
955 			printk(" SCSI Chan/Trgt %d/%d", pNextLoggedInPort->ScsiNexus.channel, pNextLoggedInPort->ScsiNexus.target);
956 			// tell Scsi layers about the new target...
957 			dev->HostAdapter->max_id++;
958 //			printk("HostAdapter->max_id = %d\n",
959 //				dev->HostAdapter->max_id);
960 		} else {
961 			// device is NOT SCSI (in case of Fabric)
962 			pNextLoggedInPort->ScsiNexus.target = -1;	// invalid
963 		}
964 
965 		// create forward link to new port
966 		pLastLoggedInPort->pNextPort = pNextLoggedInPort;
967 		printk("\n");
968 
969 	}
970 	return pNextLoggedInPort;	// NULL on allocation failure
971 }				// end NEW PORT (WWN) logic
972 
973 // For certain cases, we want to terminate exchanges without
974 // sending ABTS to the device.  Examples include when an FC
975 // device changed it's port_id after Loop re-init, or when
976 // the device sent us a logout.  In the case of changed port_id,
977 // we want to complete the command and return SOFT_ERROR to
978 // force a re-try.  In the case of LOGOut, we might return
979 // BAD_TARGET if the device is really gone.
980 // Since we must ensure that Tachyon is not operating on the
981 // exchange, we have to freeze the chip
982 // sterminateex
983 
cpqfcTSTerminateExchange(CPQFCHBA * dev,SCSI_NEXUS * ScsiNexus,int TerminateStatus)984 void cpqfcTSTerminateExchange(CPQFCHBA * dev, SCSI_NEXUS * ScsiNexus, int TerminateStatus)
985 {
986 	PTACHYON fcChip = &dev->fcChip;
987 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
988 	u32 x_ID;
989 
990 	if (ScsiNexus) {
991 //		printk("TerminateExchange: ScsiNexus chan/target %d/%d\n",
992 //			ScsiNexus->channel, ScsiNexus->target);
993 	}
994 	for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
995 		if (Exchanges->fcExchange[x_ID].type)	// in use?
996 		{
997 			if (ScsiNexus == NULL)	// our HBA changed - term. all
998 			{
999 				Exchanges->fcExchange[x_ID].status = TerminateStatus;
1000 				cpqfcTSPutLinkQue(dev, BLS_ABTS, &x_ID);
1001 			} else {
1002 				// If a device, according to WWN, has been removed, it's
1003 				// port_id may be used by another working device, so we
1004 				// have to terminate by SCSI target, NOT port_id.
1005 				if (Exchanges->fcExchange[x_ID].Cmnd)	// Cmnd in progress?
1006 				{
1007 					if ((Exchanges->fcExchange[x_ID].Cmnd->target == ScsiNexus->target)
1008 					    && (Exchanges->fcExchange[x_ID].Cmnd->channel == ScsiNexus->channel)) {
1009 						Exchanges->fcExchange[x_ID].status = TerminateStatus;
1010 						cpqfcTSPutLinkQue(dev, BLS_ABTS, &x_ID);	// timed-out
1011 					}
1012 				}
1013 				// (in case we ever need it...)
1014 				// all SEST structures have a remote node ID at SEST DWORD 2
1015 				//          if( (fcChip->SEST->u[ x_ID ].TWE.Remote_Node_ID >> 8)
1016 				//                ==  port_id)
1017 			}
1018 		}
1019 	}
1020 }
1021 
ProcessELS_Request(CPQFCHBA * dev,TachFCHDR_GCMND * fchs)1022 static void ProcessELS_Request(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
1023 {
1024 	PTACHYON fcChip = &dev->fcChip;
1025 //	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1026 //	u32 ox_id = (fchs->ox_rx_id >>16);
1027 	PFC_LOGGEDIN_PORT pLoggedInPort = NULL, pLastLoggedInPort;
1028 	u8 NeedReject = 0;
1029 	u32 ls_reject_code = 0;	// default don'n know??
1030 
1031 
1032 	// Check the incoming frame for a supported ELS type
1033 	switch (fchs->pl[0] & 0xFFFF)
1034 	{
1035 	case 0x0050:
1036 		//  PDISC?
1037 		// Payload for PLOGI and PDISC is identical (request & reply)
1038 		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code))	// valid payload?
1039 		{
1040 			LOGIN_PAYLOAD logi;	// FC-PH Port Login
1041 
1042 			// PDISC payload OK. If critical login fields
1043 			// (e.g. WWN) matches last login for this port_id,
1044 			// we may resume any prior exchanges
1045 			// with the other port
1046 
1047 			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
1048 
1049 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
1050 							   0,	// don't search linked list for port_id
1051 							   &logi.port_name[0],	// search linked list for WWN
1052 							   &pLastLoggedInPort);	// must return non-NULL; when a port_id
1053 			// is not found, this pointer marks the
1054 			// end of the singly linked list
1055 
1056 			if (pLoggedInPort != NULL)	// WWN found (prior login OK)
1057 			{
1058 				if ((fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id) {
1059 					// Yes.  We were expecting PDISC?
1060 					if (pLoggedInPort->pdisc) {
1061 						// Yes; set fields accordingly.     (PDISC, not Originator)
1062 						SetLoginFields(pLoggedInPort, fchs, 1, 0);
1063 						// send 'ACC' reply
1064 						cpqfcTSPutLinkQue(dev, ELS_PLOGI_ACC,	// (PDISC same as PLOGI ACC)
1065 								  fchs);
1066 						// OK to resume I/O...
1067 					} else {
1068 						printk("Not expecting PDISC (pdisc=0)\n");
1069 						NeedReject = 1;
1070 						// set reject reason code
1071 						ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
1072 					}
1073 				} else {
1074 					if (pLoggedInPort->port_id != 0) {
1075 						printk("PDISC PortID change: old %Xh, new %Xh\n", pLoggedInPort->port_id, fchs->s_id & 0xFFFFFF);
1076 					}
1077 					NeedReject = 1;
1078 					// set reject reason code
1079 					ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
1080 				}
1081 			} else {
1082 				printk("PDISC Request from unknown WWN\n");
1083 				NeedReject = 1;
1084 				// set reject reason code
1085 				ls_reject_code = LS_RJT_REASON(LOGICAL_ERROR, INVALID_PORT_NAME);
1086 			}
1087 
1088 		}
1089 		else		// Payload unacceptable
1090 		{
1091 			printk("payload unacceptable\n");
1092 			NeedReject = 1;	// reject code already set
1093 
1094 		}
1095 		if (NeedReject) {
1096 			u32 port_id;
1097 			// The PDISC failed.  Set login struct flags accordingly,
1098 			// terminate any I/O to this port, and Q a PLOGI
1099 			if (pLoggedInPort) {
1100 				pLoggedInPort->pdisc = 0;
1101 				pLoggedInPort->prli = 0;
1102 				pLoggedInPort->plogi = 0;
1103 
1104 				cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
1105 				port_id = pLoggedInPort->port_id;
1106 			} else {
1107 				port_id = fchs->s_id & 0xFFFFFF;
1108 			}
1109 			fchs->reserved = ls_reject_code;	// borrow this (unused) field
1110 			cpqfcTSPutLinkQue(dev, ELS_RJT, fchs);
1111 		}
1112 		break;
1113 
1114 	case 0x0003:
1115 		//  PLOGI?
1116 		// Payload for PLOGI and PDISC is identical (request & reply)
1117 		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code))	// valid payload?
1118 		{
1119 			LOGIN_PAYLOAD logi;	// FC-PH Port Login
1120 			u8 NeedReject = 0;
1121 
1122 			// PDISC payload OK. If critical login fields
1123 			// (e.g. WWN) matches last login for this port_id,
1124 			// we may resume any prior exchanges
1125 			// with the other port
1126 
1127 			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
1128 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
1129 							   0,	// don't search linked list for port_id
1130 							   &logi.port_name[0],	// search linked list for WWN
1131 							   &pLastLoggedInPort);	// must return non-NULL; when a port_id
1132 			// is not found, this pointer marks the
1133 			// end of the singly linked list
1134 			if (pLoggedInPort == NULL)	// WWN not found -New Port
1135 			{
1136 				pLoggedInPort = CreateFcPort(dev, pLastLoggedInPort, fchs, &logi);
1137 				if (pLoggedInPort == NULL) {
1138 					printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
1139 					// Now Q a LOGOut Request, since we won't be talking to that device
1140 					NeedReject = 1;
1141 					// set reject reason code
1142 					ls_reject_code = LS_RJT_REASON(LOGICAL_ERROR, NO_LOGIN_RESOURCES);
1143 				}
1144 			}
1145 			if (!NeedReject) {
1146 				// OK - we have valid fcPort ptr; set fields accordingly.
1147 				//                         (not PDISC, not Originator)
1148 				SetLoginFields(pLoggedInPort, fchs, 0, 0);
1149 				// send 'ACC' reply
1150 				cpqfcTSPutLinkQue(dev, ELS_PLOGI_ACC,	// (PDISC same as PLOGI ACC)
1151 						  fchs);
1152 			}
1153 		}
1154 		else		// Payload unacceptable
1155 		{
1156 			printk("payload unacceptable\n");
1157 			NeedReject = 1;	// reject code already set
1158 		}
1159 		if (NeedReject) {
1160 			// The PDISC failed.  Set login struct flags accordingly,
1161 			// terminate any I/O to this port, and Q a PLOGI
1162 			pLoggedInPort->pdisc = 0;
1163 			pLoggedInPort->prli = 0;
1164 			pLoggedInPort->plogi = 0;
1165 
1166 			fchs->reserved = ls_reject_code;	// borrow this (unused) field
1167 
1168 			// send 'RJT' reply
1169 			cpqfcTSPutLinkQue(dev, ELS_RJT, fchs);
1170 		}
1171 		// terminate any exchanges with this device...
1172 		if (pLoggedInPort) {
1173 			cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
1174 		}
1175 		break;
1176 
1177 	case 0x1020:		// PRLI?
1178 		{
1179 			u8 NeedReject = 1;
1180 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
1181 							   (fchs->s_id & 0xFFFFFF),	// search linked list for port_id
1182 							   NULL,	// DON'T search linked list for WWN
1183 							   NULL);	// don't care
1184 
1185 			if (pLoggedInPort == NULL) {
1186 				// huh?
1187 				printk(" Unexpected PRLI Request -not logged in!\n");
1188 				// set reject reason code
1189 				ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
1190 				// Q a LOGOut here?
1191 			} else {
1192 				// verify the PRLI ACC payload
1193 				if (!verify_PRLI(fchs, &ls_reject_code)) {
1194 					// PRLI Reply is acceptable; were we expecting it?
1195 					if (pLoggedInPort->plogi) {
1196 						// yes, we expected the PRLI ACC  (not PDISC; not Originator)
1197 						SetLoginFields(pLoggedInPort, fchs, 0, 0);
1198 						// Q an ACCept Reply
1199 						cpqfcTSPutLinkQue(dev, ELS_PRLI_ACC, fchs);
1200 						NeedReject = 0;
1201 					} else {
1202 						// huh?
1203 						printk(" (unexpected) PRLI REQEST with plogi 0\n");
1204 						// set reject reason code
1205 						ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
1206 						// Q a LOGOut here?
1207 					}
1208 				} else {
1209 					printk(" PRLI REQUEST payload failed verify\n");
1210 					// (reject code set by "verify")
1211 					// Q a LOGOut here?
1212 				}
1213 			}
1214 
1215 			if (NeedReject) {
1216 				// Q a ReJecT Reply with reason code
1217 				fchs->reserved = ls_reject_code;
1218 				cpqfcTSPutLinkQue(dev, ELS_RJT,	// Q Type
1219 						  fchs);
1220 			}
1221 		}
1222 		break;
1223 
1224 	case 0x0005:		// LOGOut?
1225 		{
1226 			// was this LOGOUT because we sent a ELS_PDISC to an FC device
1227 			// with changed (or new) port_id, or does the port refuse
1228 			// to communicate to us?
1229 			// We maintain a logout counter - if we get 3 consecutive LOGOuts,
1230 			// give up!
1231 			LOGOUT_PAYLOAD logo;
1232 			u8 GiveUpOnDevice = 0;
1233 			u32 ls_reject_code = 0;
1234 
1235 			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logo, sizeof(logo));
1236 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
1237 							   0,	// don't search linked list for port_id
1238 							   &logo.port_name[0],	// search linked list for WWN
1239 							   NULL);	// don't care about end of list
1240 
1241 			if (pLoggedInPort)	// found the device?
1242 			{
1243 				// Q an ACC reply
1244 				cpqfcTSPutLinkQue(dev, ELS_LOGO_ACC,	// Q Type
1245 						  fchs);	// device to respond to
1246 				// set login struct fields (LOGO_counter increment)
1247 				SetLoginFields(pLoggedInPort, fchs, 0, 0);
1248 				// are we an Initiator?
1249 				if (fcChip->Options.initiator) {
1250 					// we're an Initiator, so check if we should
1251 					// try (another?) login
1252 					// Fabrics routinely log out from us after
1253 					// getting device info - don't try to log them
1254 					// back in.
1255 					if ((fchs->s_id & 0xFFF000) == 0xFFF000) {
1256 						;	// do nothing
1257 					} else if (pLoggedInPort->LOGO_counter <= 3) {
1258 						// try (another) login (PLOGI request)
1259 						cpqfcTSPutLinkQue(dev, ELS_PLOGI,	// Q Type
1260 								  fchs);
1261 						// Terminate I/O with "retry" potential
1262 						cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
1263 					} else {
1264 						printk(" Got 3 LOGOuts - terminating comm. with port_id %Xh\n", fchs->s_id & 0xFFFFFF);
1265 						GiveUpOnDevice = 1;
1266 					}
1267 				} else {
1268 					GiveUpOnDevice = 1;
1269 				}
1270 
1271 				if (GiveUpOnDevice == 1) {
1272 					cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, DEVICE_REMOVED);
1273 				}
1274 			} else	// we don't know this WWN!
1275 			{
1276 				// Q a ReJecT Reply with reason code
1277 				fchs->reserved = ls_reject_code;
1278 				cpqfcTSPutLinkQue(dev, ELS_RJT,	// Q Type
1279 						  fchs);
1280 			}
1281 		}
1282 		break;
1283 
1284 			// FABRIC only case
1285 	case 0x0461:	// ELS RSCN (Registered State Change Notification)?
1286 		{
1287 			int Ports;
1288 			int i;
1289 			__u32 Buff;
1290 			// Typically, one or more devices have been added to or dropped
1291 			// from the Fabric.
1292 			// The format of this frame is defined in FC-FLA (Rev 2.7, Aug 1997)
1293 			// The first 32-bit word has a 2-byte Payload Length, which
1294 			// includes the 4 bytes of the first word.  Consequently,
1295 			// this PL len must never be less than 4, must be a multiple of 4,
1296 			// and has a specified max value 256.
1297 			// (Endianess!)
1298 			Ports = ((fchs->pl[0] >> 24) - 4) / 4;
1299 			Ports = Ports > 63 ? 63 : Ports;
1300 
1301 			printk(" RSCN ports: %d\n", Ports);
1302 			if (Ports <= 0)	// huh?
1303 			{
1304 				// ReJecT the command
1305 				fchs->reserved = LS_RJT_REASON(UNABLE_TO_PERFORM, 0);
1306 
1307 				cpqfcTSPutLinkQue(dev, ELS_RJT,	// Q Type
1308 						  fchs);
1309 
1310 				break;
1311 			} else	// Accept the command
1312 			{
1313 				cpqfcTSPutLinkQue(dev, ELS_ACC,	// Q Type
1314 						  fchs);
1315 			}
1316 
1317 			// Check the "address format" to determine action.
1318 			// We have 3 cases:
1319 			// 0 = Port Address; 24-bit address of affected device
1320 			// 1 = Area Address; MS 16 bits valid
1321 			// 2 = Domain Address; MS 8 bits valid
1322 			for (i = 0; i < Ports; i++) {
1323 				BigEndianSwap((u8 *) & fchs->pl[i + 1], (u8 *) & Buff, 4);
1324 				switch (Buff & 0xFF000000) {
1325 				case 0:	// Port Address?
1326 				case 0x01000000:	// Area Domain?
1327 				case 0x02000000:	// Domain Address
1328 					// For example, "port_id" 0x201300
1329 					// OK, let's try a Name Service Request (Query)
1330 					fchs->s_id = 0xFFFFFC;	// Name Server Address
1331 					cpqfcTSPutLinkQue(dev, FCS_NSR, fchs);
1332 					break;
1333 				default:	// huh? new value on version change?
1334 					break;
1335 				}
1336 			}
1337 		}
1338 		break;
1339 	default:
1340 		// don't support this request (yet)
1341 		// set reject reason code
1342 		fchs->reserved = LS_RJT_REASON(UNABLE_TO_PERFORM, REQUEST_NOT_SUPPORTED);
1343 		cpqfcTSPutLinkQue(dev, ELS_RJT,	fchs);	// Q Type
1344 		break;
1345 	}
1346 }
1347 
1348 
ProcessELS_Reply(CPQFCHBA * dev,TachFCHDR_GCMND * fchs)1349 static void ProcessELS_Reply(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
1350 {
1351 	PTACHYON fcChip = &dev->fcChip;
1352 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1353 	u32 ox_id = (fchs->ox_rx_id >> 16);
1354 	u32 ls_reject_code;
1355 	PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
1356 
1357 	// If this is a valid reply, then we MUST have sent a request.
1358 	// Verify that we can find a valid request OX_ID corresponding to
1359 	// this reply
1360 
1361 	if (Exchanges->fcExchange[(fchs->ox_rx_id >> 16)].type == 0) {
1362 		printk(" *Discarding ACC/RJT frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff);
1363 		goto Quit;	// exit this routine
1364 	}
1365 
1366 	// Is the reply a RJT (reject)?
1367 	if ((fchs->pl[0] & 0xFFFFL) == 0x01)	// Reject reply?
1368 	{
1369 		//  ******  REJECT REPLY  ********
1370 		switch (Exchanges->fcExchange[ox_id].type) {
1371 		case ELS_FDISC:	// we sent out Fabric Discovery
1372 		case ELS_FLOGI:	// we sent out FLOGI
1373 			printk("RJT received on Fabric Login from %Xh, reason %Xh\n", fchs->s_id, fchs->pl[1]);
1374 			break;
1375 		default:
1376 			break;
1377 		}
1378 		goto Done;
1379 	}
1380 	// OK, we have an ACCept...
1381 	// What's the ACC type? (according to what we sent)
1382 	switch (Exchanges->fcExchange[ox_id].type) {
1383 	case ELS_PLOGI:	// we sent out PLOGI
1384 		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code)) {
1385 			LOGIN_PAYLOAD logi;	// FC-PH Port Login
1386 			// login ACC payload acceptable; search for WWN in our list
1387 			// of fcPorts
1388 			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
1389 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
1390 						   0,	// don't search linked list for port_id
1391 						   &logi.port_name[0],	// search linked list for WWN
1392 						   &pLastLoggedInPort);	// must return non-NULL; when a port_id
1393 			// is not found, this pointer marks the
1394 			// end of the singly linked list
1395 			if (pLoggedInPort == NULL)	// WWN not found - new port
1396 			{
1397 				pLoggedInPort = CreateFcPort(dev, pLastLoggedInPort, fchs, &logi);
1398 				if (pLoggedInPort == NULL) {
1399 					printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
1400 					// Now Q a LOGOut Request, since we won't be talking to that device
1401 					goto Done;	// exit with error! dropped login frame
1402 				}
1403 			} else	// WWN was already known.  Ensure that any open
1404 				// exchanges for this WWN are terminated.
1405 				// NOTE: It's possible that a device can change its
1406 				// 24-bit port_id after a Link init or Fabric change
1407 				// (e.g. LIP or Fabric RSCN).  In that case, the old
1408 				// 24-bit port_id may be duplicated, or no longer exist.
1409 			{
1410 				cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
1411 			}
1412 
1413 			// We have an fcPort struct - set fields accordingly
1414 			// not PDISC, originator
1415 			SetLoginFields(pLoggedInPort, fchs, 0, 1);
1416 			// We just set a "port_id"; is it duplicated?
1417 			TestDuplicatePortId(dev, pLoggedInPort);
1418 			// For Fabric operation, we issued PLOGI to 0xFFFFFC
1419 			// so we can send SCR (State Change Registration)
1420 			// Check for this special case...
1421 			if (fchs->s_id == 0xFFFFFC) {
1422 				// PLOGI ACC was a Fabric response... issue SCR
1423 				fchs->s_id = 0xFFFFFD;	// address for SCR
1424 				cpqfcTSPutLinkQue(dev, ELS_SCR, fchs);
1425 			}
1426 			else {
1427 				// Now we need a PRLI to enable FCP-SCSI operation
1428 				// set flags and Q up a ELS_PRLI
1429 				cpqfcTSPutLinkQue(dev, ELS_PRLI, fchs);
1430 			}
1431 		} else {
1432 			// login payload unacceptable - reason in ls_reject_code
1433 			// Q up a Logout Request
1434 			printk("Login Payload unacceptable\n");
1435 		}
1436 		break;
1437 
1438 		// PDISC logic very similar to PLOGI, except we never want
1439 		// to allocate mem for "new" port, and we set flags differently
1440 		// (might combine later with PLOGI logic for efficiency)
1441 	case ELS_PDISC:	// we sent out PDISC
1442 		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code)) {
1443 			LOGIN_PAYLOAD logi;	// FC-PH Port Login
1444 			u8 NeedLogin = 0;
1445 
1446 			// login payload acceptable; search for WWN in our list
1447 			// of (previously seen) fcPorts
1448 			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
1449 
1450 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
1451 							   0,	// don't search linked list for port_id
1452 							   &logi.port_name[0],	// search linked list for WWN
1453 							   &pLastLoggedInPort);	// must return non-NULL; when a port_id
1454 			// is not found, this pointer marks the
1455 			// end of the singly linked list
1456 			if (pLoggedInPort != NULL)	// WWN found?
1457 			{
1458 				// WWN has same port_id as last login?  (Of course, a properly
1459 				// working FC device should NEVER ACCept a PDISC if it's
1460 				// port_id changed, but check just in case...)
1461 				if ((fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id) {
1462 					// Yes.  We were expecting PDISC?
1463 					if (pLoggedInPort->pdisc) {
1464 						int i;
1465 
1466 
1467 						// PDISC expected -- set fields.  (PDISC, Originator)
1468 						SetLoginFields(pLoggedInPort, fchs, 1, 1);
1469 
1470 						// We are ready to resume FCP-SCSI to this device...
1471 						// Do we need to start anything that was Queued?
1472 
1473 						for (i = 0; i < TACH_SEST_LEN; i++) {
1474 							// see if any exchange for this PDISC'd port was queued
1475 							if (((fchs->s_id & 0xFFFFFF) == (Exchanges->fcExchange[i].fchs.d_id & 0xFFFFFF))
1476 							    && (Exchanges->fcExchange[i].status & EXCHANGE_QUEUED)) {
1477 								fchs->reserved = i;	// copy ExchangeID
1478 //						                printk(" *Q x_ID %Xh after PDISC* ",i);
1479 
1480 								cpqfcTSPutLinkQue(dev, EXCHANGE_QUEUED, fchs);
1481 							}
1482 						}
1483 						// Complete commands Q'd while we were waiting for Login
1484 						UnblockScsiDevice(dev->HostAdapter, pLoggedInPort);
1485 					} else {
1486 						printk("Not expecting PDISC (pdisc=0)\n");
1487 						NeedLogin = 1;
1488 					}
1489 				} else {
1490 					printk("PDISC PortID change: old %Xh, new %Xh\n", pLoggedInPort->port_id, fchs->s_id & 0xFFFFFF);
1491 					NeedLogin = 1;
1492 				}
1493 			} else {
1494 				printk("PDISC ACC from unknown WWN\n");
1495 				NeedLogin = 1;
1496 			}
1497 
1498 			if (NeedLogin) {
1499 				// The PDISC failed.  Set login struct flags accordingly,
1500 				// terminate any I/O to this port, and Q a PLOGI
1501 				if (pLoggedInPort)	// FC device previously known?
1502 				{
1503 					cpqfcTSPutLinkQue(dev, ELS_LOGO, fchs);	// Qtype has port_id to send to
1504 					// There are a variety of error scenarios which can result
1505 					// in PDISC failure, so as a catchall, add the check for
1506 					// duplicate port_id.
1507 					TestDuplicatePortId(dev, pLoggedInPort);
1508 
1509 					// TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
1510 					pLoggedInPort->pdisc = 0;
1511 					pLoggedInPort->prli = 0;
1512 					pLoggedInPort->plogi = 0;
1513 
1514 					cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
1515 				}
1516 				cpqfcTSPutLinkQue(dev, ELS_PLOGI, fchs);
1517 			}
1518 		} else {
1519 			// login payload unacceptable - reason in ls_reject_code
1520 			// Q up a Logout Request
1521 			printk("ERROR: Login Payload unacceptable!\n");
1522 
1523 		}
1524 		break;
1525 
1526 	case ELS_PRLI:		// we sent out PRLI
1527 		pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
1528 						   (fchs->s_id & 0xFFFFFF),	// search linked list for port_id
1529 						   NULL,	// DON'T search linked list for WWN
1530 						   NULL);	// don't care
1531 
1532 		if (pLoggedInPort == NULL) {
1533 			// huh?
1534 			printk(" Unexpected PRLI ACCept frame!\n");
1535 			// Q a LOGOut here?
1536 			goto Done;
1537 		}
1538 		// verify the PRLI ACC payload
1539 		if (!verify_PRLI(fchs, &ls_reject_code)) {
1540 			// PRLI Reply is acceptable; were we expecting it?
1541 			if (pLoggedInPort->plogi) {
1542 				// yes, we expected the PRLI ACC  (not PDISC; Originator)
1543 				SetLoginFields(pLoggedInPort, fchs, 0, 1);
1544 				// OK, let's send a REPORT_LUNS command to determine
1545 				// whether VSA or PDA FCP-LUN addressing is used.
1546 				cpqfcTSPutLinkQue(dev, SCSI_REPORT_LUNS, fchs);
1547 				// It's possible that a device we were talking to changed
1548 				// port_id, and has logged back in.  This function ensures
1549 				// that I/O will resume.
1550 				UnblockScsiDevice(dev->HostAdapter, pLoggedInPort);
1551 			} else {
1552 				// huh?
1553 				printk(" (unexpected) PRLI ACCept with plogi 0\n");
1554 				// Q a LOGOut here?
1555 				goto Done;
1556 			}
1557 		} else {
1558 			printk(" PRLI ACCept payload failed verify\n");
1559 			// Q a LOGOut here?
1560 		}
1561 		break;
1562 
1563 	case ELS_FLOGI:	// we sent out FLOGI (Fabric Login)
1564 		// update the upper 16 bits of our port_id in Tachyon
1565 		// the switch adds those upper 16 bits when responding
1566 		// to us (i.e. we are the destination_id)
1567 		fcChip->Registers.my_al_pa = (fchs->d_id & 0xFFFFFF);
1568 		writel(fcChip->Registers.my_al_pa, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
1569 
1570 		// now send out a PLOGI to the well known port_id 0xFFFFFC
1571 		fchs->s_id = 0xFFFFFC;
1572 		cpqfcTSPutLinkQue(dev, ELS_PLOGI, fchs);
1573 		break;
1574 
1575 
1576 	case ELS_FDISC:	// we sent out FDISC (Fabric Discovery (Login))
1577 		printk(" ELS_FDISC success ");
1578 		break;
1579 
1580 	case ELS_SCR:		// we sent out State Change Registration
1581 		// now we can issue Name Service Request to find any
1582 		// Fabric-connected devices we might want to login to.
1583 		fchs->s_id = 0xFFFFFC;	// Name Server Address
1584 		cpqfcTSPutLinkQue(dev, FCS_NSR, fchs);
1585 		break;
1586 
1587 	default:
1588 		printk(" *Discarding unknown ACC frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff);
1589 		break;
1590 	}
1591 Done:
1592 	// Regardless of whether the Reply is valid or not, the
1593 	// the exchange is done - complete
1594 	cpqfcTSCompleteExchange(dev->PciDev, fcChip, (fchs->ox_rx_id >> 16));
1595 Quit:
1596 	return;
1597 }
1598 
1599 
1600 
1601 
1602 
1603 
1604 // ****************  Fibre Channel Services  **************
1605 // This is where we process the Directory (Name) Service Reply
1606 // to know which devices are on the Fabric
1607 
ProcessFCS_Reply(CPQFCHBA * dev,TachFCHDR_GCMND * fchs)1608 static void ProcessFCS_Reply(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
1609 {
1610 	PTACHYON fcChip = &dev->fcChip;
1611 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1612 	u32 ox_id = (fchs->ox_rx_id >> 16);
1613 //	u32 ls_reject_code;
1614 //	PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
1615 
1616 	// If this is a valid reply, then we MUST have sent a request.
1617 	// Verify that we can find a valid request OX_ID corresponding to
1618 	// this reply
1619 
1620 	if (Exchanges->fcExchange[(fchs->ox_rx_id >> 16)].type == 0) {
1621 		printk(" *Discarding Reply frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff);
1622 		goto Quit;	// exit this routine
1623 	}
1624 
1625 	// OK, we were expecting it.  Now check to see if it's a
1626 	// "Name Service" Reply, and if so force a re-validation of
1627 	// Fabric device logins (i.e. Start the login timeout and
1628 	// send PDISC or PLOGI)
1629 	// (Endianess Byte Swap?)
1630 	if (fchs->pl[1] == 0x02FC)	// Name Service
1631 	{
1632 		// got a new (or NULL) list of Fabric attach devices...
1633 		// Invalidate current logins
1634 
1635 		PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
1636 		while (pLoggedInPort)	// for all ports which are expecting
1637 			// PDISC after the next LIP, set the
1638 			// logoutTimer
1639 		{
1640 
1641 			if ((pLoggedInPort->port_id & 0xFFFF00)	// Fabric device?
1642 			    && (pLoggedInPort->port_id != 0xFFFFFC))	// NOT the F_Port
1643 			{
1644 				pLoggedInPort->LOGO_timer = 6;	// what's the Fabric timeout??
1645 				// suspend any I/O in progress until
1646 				// PDISC received...
1647 				pLoggedInPort->prli = 0;	// block FCP-SCSI commands
1648 			}
1649 
1650 			pLoggedInPort = pLoggedInPort->pNextPort;
1651 		}
1652 
1653 		if (fchs->pl[2] == 0x0280)	// ACCept?
1654 		{
1655 			// Send PLOGI or PDISC to these Fabric devices
1656 			SendLogins(dev, &fchs->pl[4]);
1657 		}
1658 		// As of this writing, the only reason to reject is because NO
1659 		// devices are left on the Fabric.  We already started
1660 		// "logged out" timers; if the device(s) don't come
1661 		// back, we'll do the implicit logout in the heart beat
1662 		// timer routine
1663 		else		// ReJecT
1664 		{
1665 			// this just means no Fabric device is visible at this instant
1666 		}
1667 	}
1668 	// Regardless of whether the Reply is valid or not, the
1669 	// the exchange is done - complete
1670 	cpqfcTSCompleteExchange(dev->PciDev, fcChip, (fchs->ox_rx_id >> 16));
1671 
1672 Quit:
1673 	return;
1674 }
1675 
AnalyzeIncomingFrame(CPQFCHBA * dev,u32 QNdx)1676 static void AnalyzeIncomingFrame(CPQFCHBA * dev, u32 QNdx)
1677 {
1678 	PTACHYON fcChip = &dev->fcChip;
1679 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1680 	PFC_LINK_QUE fcLQ = dev->fcLQ;
1681 	TachFCHDR_GCMND *fchs = (TachFCHDR_GCMND *) fcLQ->Qitem[QNdx].ulBuff;
1682 //	u32 ls_reject_code;  // reason for rejecting login
1683 	s32 ExchangeID;
1684 //	FC_LOGGEDIN_PORT *pLoggedInPort;
1685 	u8 AbortAccept;
1686 
1687 	ENTER("AnalyzeIncomingFrame");
1688 
1689 	switch (fcLQ->Qitem[QNdx].Type)	// FCP or Unknown
1690 	{
1691 	case SFQ_UNKNOWN:	// unknown frame (e.g. LIP position frame, NOP, etc.)
1692 		// *********  FC-4 Device Data/ Fibre Channel Service *************
1693 		if (((fchs->d_id & 0xF0000000) == 0)	// R_CTL (upper nibble) 0x0?
1694 		    && (fchs->f_ctl & 0x20000000))	// TYPE 20h is Fibre Channel Service
1695 		{
1696 			// ************** FCS Reply **********************
1697 			if ((fchs->d_id & 0xff000000L) == 0x03000000L)	// (31:23 R_CTL)
1698 			{
1699 				ProcessFCS_Reply(dev, fchs);
1700 			}	// end of  FCS logic
1701 		}
1702 		// ***********  Extended Link Service **************
1703 		else if (fchs->d_id & 0x20000000	// R_CTL 0x2?
1704 			 && (fchs->f_ctl & 0x01000000))	// TYPE = 1
1705 		{
1706 			// these frames are either a response to
1707 			// something we sent (0x23) or "unsolicited"
1708 			// frames (0x22).
1709 			// **************Extended Link REPLY **********************
1710 			// R_CTL Solicited Control Reply
1711 			if ((fchs->d_id & 0xff000000L) == 0x23000000L)	// (31:23 R_CTL)
1712 			{
1713 				ProcessELS_Reply(dev, fchs);
1714 			}	// end of  "R_CTL Solicited Control Reply"
1715 			// **************Extended Link REQUEST **********************
1716 			// (unsolicited commands from another port or task...)
1717 			// R_CTL Ext Link REQUEST
1718 			else if ((fchs->d_id & 0xff000000L) == 0x22000000L && (fchs->ox_rx_id != 0xFFFFFFFFL))	// (ignore LIP frame)
1719 			{
1720 				ProcessELS_Request(dev, fchs);
1721 			}
1722 			// ************** LILP **********************
1723 			else if ((fchs->d_id & 0xff000000L) == 0x22000000L && (fchs->ox_rx_id == 0xFFFFFFFFL))	// (e.g., LIP frames)
1724 			{
1725 				// SANMark specifies that when available, we must use
1726 				// the LILP frame to determine which ALPAs to send Port Discovery
1727 				// to...
1728 				if (fchs->pl[0] == 0x0711L)	//  ELS_PLOGI?
1729 				{
1730 //					u8 *ptr = (u8*)&fchs->pl[1];
1731 //					printk(" %d ALPAs found\n", *ptr);
1732 					memcpy(fcChip->LILPmap, &fchs->pl[1], 32 * 4);	// 32 DWORDs
1733 					fcChip->Options.LILPin = 1;	// our LILPmap is valid!
1734 					// now post to make Port Discovery happen...
1735 					cpqfcTSPutLinkQue(dev, LINKACTIVE, fchs);
1736 				}
1737 			}
1738 		}
1739 		// *****************  BASIC LINK SERVICE *****************
1740 		else if (fchs->d_id & 0x80000000	// R_CTL:
1741 			 &&	// Basic Link Service Request
1742 			 !(fchs->f_ctl & 0xFF000000))	// type=0 for BLS
1743 		{
1744 			// Check for ABTS (Abort Sequence)
1745 			if ((fchs->d_id & 0x8F000000) == 0x81000000) {
1746 				// look for OX_ID, S_ID pair that matches in our
1747 				// fcExchanges table; if found, reply with ACCept and complete
1748 				// the exchange
1749 
1750 				// Per PLDA, an ABTS is sent by an initiator; therefore
1751 				// assume that if we have an exhange open to the port who
1752 				// sent ABTS, it will be the d_id of what we sent.
1753 				for (ExchangeID = 0, AbortAccept = 0; ExchangeID < TACH_SEST_LEN; ExchangeID++) {
1754 					// Valid "target" exchange 24-bit port_id matches?
1755 					// NOTE: For the case of handling Intiator AND Target
1756 					// functions on the same chip, we can have TWO Exchanges
1757 					// with the same OX_ID -- OX_ID/FFFF for the CMND, and
1758 					// OX_ID/RX_ID for the XRDY or DATA frame(s).  Ideally,
1759 					// we would like to support ABTS from Initiators or Targets,
1760 					// but it's not clear that can be supported on Tachyon for
1761 					// all cases (requires more investigation).
1762 
1763 					if ((Exchanges->fcExchange[ExchangeID].type == SCSI_TWE || Exchanges->fcExchange[ExchangeID].type == SCSI_TRE)
1764 					    && ((Exchanges->fcExchange[ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF))) {
1765 
1766 						// target xchnge port_id matches -- how about OX_ID?
1767 						if ((Exchanges->fcExchange[ExchangeID].fchs.ox_rx_id & 0xFFFF0000)
1768 						    == (fchs->ox_rx_id & 0xFFFF0000))
1769 							// yes! post ACCept response; will be completed by fcStart
1770 						{
1771 							Exchanges->fcExchange[ExchangeID].status = TARGET_ABORT;
1772 
1773 							// copy (add) rx_id field for simplified ACCept reply
1774 							fchs->ox_rx_id = Exchanges->fcExchange[ExchangeID].fchs.ox_rx_id;
1775 
1776 							cpqfcTSPutLinkQue(dev, BLS_ABTS_ACC,	// Q Type
1777 									  fchs);	// void QueContent
1778 							AbortAccept = 1;
1779 							printk("ACCepting ABTS for x_ID %8.8Xh, SEST pair %8.8Xh\n", fchs->ox_rx_id, Exchanges->fcExchange[ExchangeID].fchs.ox_rx_id);
1780 							break;	// ABTS can affect only ONE exchange -exit loop
1781 						}
1782 					}
1783 				}	// end of FOR loop
1784 				if (!AbortAccept)	// can't ACCept ABTS - send Reject
1785 				{
1786 					printk("ReJecTing: can't find ExchangeID %8.8Xh for ABTS command\n", fchs->ox_rx_id);
1787 					if (Exchanges->fcExchange[ExchangeID].type && !(fcChip->SEST->u[ExchangeID].IWE.Hdr_Len & 0x80000000)) {
1788 						cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
1789 					} else {
1790 						printk("Unexpected ABTS ReJecT! SEST[%X] Dword 0: %Xh\n", ExchangeID, fcChip->SEST->u[ExchangeID].IWE.Hdr_Len);
1791 					}
1792 				}
1793 			}
1794 			// Check for BLS {ABTS? (Abort Sequence)} ACCept
1795 			else if ((fchs->d_id & 0x8F000000) == 0x84000000) {
1796 				// target has responded with ACC for our ABTS;
1797 				// complete the indicated exchange with ABORTED status
1798 				// Make no checks for correct RX_ID, since
1799 				// all we need to conform ABTS ACC is the OX_ID.
1800 				// Verify that the d_id matches!
1801 
1802 				ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF;	// x_id from ACC
1803 //      printk("ABTS ACC x_ID 0x%04X 0x%04X, status %Xh\n",
1804 //          fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff,
1805 //          Exchanges->fcExchange[ExchangeID].status);
1806 				if (ExchangeID < TACH_SEST_LEN)	// x_ID makes sense
1807 				{
1808 					// Does "target" exchange 24-bit port_id match?
1809 					// (See "NOTE" above for handling Intiator AND Target in
1810 					// the same device driver)
1811 					// First, if this is a target response, then we originated
1812 					// (initiated) it with BLS_ABTS:
1813 
1814 					if ((Exchanges->fcExchange[ExchangeID].type == BLS_ABTS) &&
1815 					    // Second, does the source of this ACC match the destination
1816 					    // of who we originally sent it to?
1817 					    ((Exchanges->fcExchange[ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF))) {
1818 						cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
1819 					}
1820 				}
1821 			}
1822 			// Check for BLS {ABTS? (Abort Sequence)} ReJecT
1823 			else if ((fchs->d_id & 0x8F000000) == 0x85000000) {
1824 				// target has responded with RJT for our ABTS;
1825 				// complete the indicated exchange with ABORTED status
1826 				// Make no checks for correct RX_ID, since
1827 				// all we need to conform ABTS ACC is the OX_ID.
1828 				// Verify that the d_id matches!
1829 
1830 				ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF;	// x_id from ACC
1831 //				printk("BLS_ABTS RJT on Exchange 0x%04X 0x%04X\n",
1832 //					fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff);
1833 
1834 				if (ExchangeID < TACH_SEST_LEN)	// x_ID makes sense
1835 				{
1836 					// Does "target" exchange 24-bit port_id match?
1837 					// (See "NOTE" above for handling Intiator AND Target in
1838 					// the same device driver)
1839 					// First, if this is a target response, then we originated
1840 					// (initiated) it with BLS_ABTS:
1841 
1842 					if ((Exchanges->fcExchange[ExchangeID].type == BLS_ABTS)
1843 
1844 					    &&
1845 					    // Second, does the source of this ACC match the destination
1846 					    // of who we originally sent it to?
1847 					    ((Exchanges->fcExchange[ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF))) {
1848 						// YES! NOTE: There is a bug in CPQ's RA-4000 box
1849 						// where the "reason code" isn't returned in the payload
1850 						// For now, simply presume the reject is because the target
1851 						// already completed the exchange...
1852 
1853 //						printk("complete x_ID %Xh on ABTS RJT\n", ExchangeID);
1854 						cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
1855 					}
1856 				}
1857 			}	// end of ABTS check
1858 		}		// end of Basic Link Service Request
1859 		break;
1860 
1861 	default:
1862 		printk("AnalyzeIncomingFrame: unknown type: %Xh(%d)\n", fcLQ->Qitem[QNdx].Type, fcLQ->Qitem[QNdx].Type);
1863 		break;
1864 	}
1865 }
1866 
1867 
1868 // Function for Port Discovery necessary after every FC
1869 // initialization (e.g. LIP).
1870 // Also may be called if from Fabric Name Service logic.
1871 
SendLogins(CPQFCHBA * dev,__u32 * FabricPortIds)1872 static void SendLogins(CPQFCHBA * dev, __u32 * FabricPortIds)
1873 {
1874 	PTACHYON fcChip = &dev->fcChip;
1875 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1876 	u32 ulStatus = 0;
1877 	TachFCHDR_GCMND fchs;	// copy fields for transmission
1878 	int i;
1879 	u32 loginType;
1880 	s32 ExchangeID;
1881 	PFC_LOGGEDIN_PORT pLoggedInPort;
1882 	__u32 PortIds[number_of_al_pa];
1883 	int NumberOfPorts = 0;
1884 
1885 	// We're going to presume (for now) that our limit of Fabric devices
1886 	// is the same as the number of alpa on a private loop (126 devices).
1887 	// (Of course this could be changed to support however many we have
1888 	// memory for).
1889 	memset(&PortIds[0], 0, sizeof(PortIds));
1890 
1891 	// First, check if this login is for our own Link Initialization
1892 	// (e.g. LIP on FC-AL), or if we have knowledge of Fabric devices
1893 	// from a switch.  If we are logging into Fabric devices, we'll
1894 	// have a non-NULL FabricPortId pointer
1895 
1896 	if (FabricPortIds != NULL)	// may need logins
1897 	{
1898 		int LastPort = 0;
1899 		i = 0;
1900 		while (!LastPort) {
1901 			// port IDs From NSR payload; byte swap needed?
1902 			BigEndianSwap((u8 *) FabricPortIds, (u8 *) & PortIds[i], 4);
1903 
1904 //			printk("FPortId[%d] %Xh ", i, PortIds[i]);
1905 			if (PortIds[i] & 0x80000000)
1906 				LastPort = 1;
1907 
1908 			PortIds[i] &= 0xFFFFFF;	// get 24-bit port_id
1909 			// some non-Fabric devices (like the Crossroads Fibre/Scsi bridge)
1910 			// erroneously use ALPA 0.
1911 			if (PortIds[i])	// need non-zero port_id...
1912 				i++;
1913 
1914 			if (i >= number_of_al_pa)	// (in)sanity check
1915 				break;
1916 			FabricPortIds++;	// next...
1917 		}
1918 
1919 		NumberOfPorts = i;
1920 //    printk("NumberOf Fabric ports %d", NumberOfPorts);
1921 	}
1922 	else			// need to send logins on our "local" link
1923 	{
1924 		// are we a loop port?  If so, check for reception of LILP frame,
1925 		// and if received use it (SANMark requirement)
1926 		if (fcChip->Options.LILPin) {
1927 			int j = 0;
1928 			// sanity check on number of ALPAs from LILP frame...
1929 			// For format of LILP frame, see FC-AL specs or
1930 			// "Fibre Channel Bench Reference", J. Stai, 1995 (ISBN 1-879936-17-8)
1931 			// First byte is number of ALPAs
1932 			i = fcChip->LILPmap[0] >= (32 * 4) ? 32 * 4 : fcChip->LILPmap[0];
1933 			NumberOfPorts = i;
1934 //			printk(" LILP alpa count %d ", i);
1935 			while (i > 0) {
1936 				PortIds[j] = fcChip->LILPmap[1 + j];
1937 				j++;
1938 				i--;
1939 			}
1940 		}
1941 		else		// have to send login to everybody
1942 		{
1943 			int j = 0;
1944 			i = number_of_al_pa;
1945 			NumberOfPorts = i;
1946 			while (i > 0) {
1947 				PortIds[j] = valid_al_pa[j];	// all legal ALPAs
1948 				j++;
1949 				i--;
1950 			}
1951 		}
1952 	}
1953 
1954 	// Now we have a copy of the port_ids (and how many)...
1955 	for (i = 0; i < NumberOfPorts; i++) {
1956 		// 24-bit FC Port ID
1957 		fchs.s_id = PortIds[i];	// note: only 8-bits used for ALPA
1958 		// don't log into ourselves (Linux Scsi disk scan will stop on
1959 		// no TARGET support error on us, and quit trying for rest of devices)
1960 		if ((fchs.s_id & 0xFF) == (fcChip->Registers.my_al_pa & 0xFF))
1961 			continue;
1962 		// fabric login needed?
1963 		if ((fchs.s_id == 0) || (fcChip->Options.fabric == 1)) {
1964 			fcChip->Options.flogi = 1;	// fabric needs longer for login
1965 			// Do we need FLOGI or FDISC?
1966 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search SCSI Nexus
1967 							   0xFFFFFC,	// search linked list for Fabric port_id
1968 							   NULL,	// don't search WWN
1969 							   NULL);	// (don't care about end of list)
1970 
1971 			if (pLoggedInPort)	// If found, we have prior experience with
1972 				// this port -- check whether PDISC is needed
1973 			{
1974 				if (pLoggedInPort->flogi) {
1975 					// does the switch support FDISC?? (FLOGI for now...)
1976 					loginType = ELS_FLOGI;	// prior FLOGI still valid
1977 				} else
1978 					loginType = ELS_FLOGI;	// expired FLOGI
1979 			} else	// first FLOGI?
1980 				loginType = ELS_FLOGI;
1981 
1982 			fchs.s_id = 0xFFFFFE;	// well known F_Port address
1983 
1984 			// Fabrics are not required to support FDISC, and
1985 			// it's not clear if that helps us anyway, since
1986 			// we'll want a Name Service Request to re-verify
1987 			// visible devices...
1988 			// Consequently, we always want our upper 16 bit
1989 			// port_id to be zero (we'll be rejected if we
1990 			// use our prior port_id if we've been plugged into
1991 			// a different switch port).
1992 			// Trick Tachyon to send to ALPA 0 (see TL/TS UG, pg 87)
1993 			// If our ALPA is 55h for instance, we want the FC frame
1994 			// s_id to be 0x000055, while Tach's my_al_pa register
1995 			// must be 0x000155, to force an OPN at ALPA 0
1996 			// (the Fabric port)
1997 			fcChip->Registers.my_al_pa &= 0xFF;	// only use ALPA for FLOGI
1998 			writel(fcChip->Registers.my_al_pa | 0x0100, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
1999 		}
2000 		else		// not FLOGI...
2001 		{
2002 			// should we send PLOGI or PDISC?  Check if any prior port_id
2003 			// (e.g. alpa) completed a PLOGI/PRLI exchange by checking
2004 			// the pdisc flag.
2005 
2006 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search SCSI Nexus
2007 							   fchs.s_id,	// search linked list for al_pa
2008 							   NULL,	// don't search WWN
2009 							   NULL);	// (don't care about end of list)
2010 
2011 			if (pLoggedInPort)	// If found, we have prior experience with
2012 				// this port -- check whether PDISC is needed
2013 			{
2014 				if (pLoggedInPort->pdisc) {
2015 					loginType = ELS_PDISC;	// prior PLOGI and PRLI maybe still valid
2016 				} else
2017 					loginType = ELS_PLOGI;	// prior knowledge, but can't use PDISC
2018 			} else	// never talked to this port_id before
2019 				loginType = ELS_PLOGI;	// prior knowledge, but can't use PDISC
2020 		}
2021 
2022 		ulStatus = cpqfcTSBuildExchange(dev, loginType,	// e.g. PLOGI
2023 						&fchs,	// no incoming frame (we are originator)
2024 						NULL,	// no data (no scatter/gather list)
2025 						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
2026 
2027 		if (!ulStatus)	// Exchange setup OK?
2028 		{
2029 			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
2030 			if (!ulStatus) {
2031 				// submitted to Tach's Outbound Que (ERQ PI incremented)
2032 				// waited for completion for ELS type (Login frames issued
2033 				// synchronously)
2034 
2035 				if (loginType == ELS_PDISC) {
2036 					// now, we really shouldn't Revalidate SEST exchanges until
2037 					// we get an ACC reply from our target and verify that
2038 					// the target address/WWN is unchanged.  However, when a fast
2039 					// target gets the PDISC, they can send SEST Exchange data
2040 					// before we even get around to processing the PDISC ACC.
2041 					// Consequently, we lose the I/O.
2042 					// To avoid this, go ahead and Revalidate when the PDISC goes
2043 					// out, anticipating that the ACC will be truly acceptable
2044 					// (this happens 99.9999....% of the time).
2045 					// If we revalidate a SEST write, and write data goes to a
2046 					// target that is NOT the one we originated the WRITE to,
2047 					// that target is required (FCP-SCSI specs, etc) to discard
2048 					// our WRITE data.
2049 
2050 					// Re-validate SEST entries (Tachyon hardware assists)
2051 					RevalidateSEST(dev->HostAdapter, pLoggedInPort);
2052 					//TriggerHBA( fcChip->Registers.ReMapMemBase, 1);
2053 				}
2054 			} else	// give up immediately on error
2055 			{
2056 #ifdef LOGIN_DBG
2057 				printk("SendLogins: fcStartExchange failed: %Xh\n", ulStatus);
2058 #endif
2059 				break;
2060 			}
2061 
2062 
2063 			if (fcChip->Registers.FMstatus.value & 0x080)	// LDn during Port Disc.
2064 			{
2065 				ulStatus = LNKDWN_OSLS;
2066 #ifdef LOGIN_DBG
2067 				printk("SendLogins: PortDisc aborted (LDn) @alpa %Xh\n", fchs.s_id);
2068 #endif
2069 				break;
2070 			}
2071 			// Check the exchange for bad status (i.e. FrameTimeOut),
2072 			// and complete on bad status (most likely due to BAD_ALPA)
2073 			// on LDn, DPC function may already complete (ABORT) a started
2074 			// exchange, so check type first (type = 0 on complete).
2075 			if (Exchanges->fcExchange[ExchangeID].status) {
2076 #ifdef LOGIN_DBG
2077 				printk("completing x_ID %X on status %Xh\n", ExchangeID, Exchanges->fcExchange[ExchangeID].status);
2078 #endif
2079 				cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
2080 			}
2081 		} else		// Xchange setup failed...
2082 		{
2083 #ifdef LOGIN_DBG
2084 			printk("FC: cpqfcTSBuildExchange failed: %Xh\n", ulStatus);
2085 #endif
2086 			break;
2087 		}
2088 	}
2089 	if (!ulStatus) {
2090 		// set the event signifying that all ALPAs were sent out.
2091 #ifdef LOGIN_DBG
2092 		printk("SendLogins: PortDiscDone\n");
2093 #endif
2094 		dev->PortDiscDone = 1;
2095 		// TL/TS UG, pg. 184
2096 		// 0x0065 = 100ms for RT_TOV
2097 		// 0x01f5 = 500ms for ED_TOV
2098 		fcChip->Registers.ed_tov.value = 0x006501f5L;
2099 		writel(fcChip->Registers.ed_tov.value, (fcChip->Registers.ed_tov.address));
2100 
2101 		// set the LP_TOV back to ED_TOV (i.e. 500 ms)
2102 		writel(0x00000010, fcChip->Registers.ReMapMemBase + TL_MEM_FM_TIMEOUT2);
2103 	} else {
2104 		printk("SendLogins: failed at xchng %Xh, alpa %Xh, status %Xh\n", ExchangeID, fchs.s_id, ulStatus);
2105 	}
2106 	LEAVE("SendLogins");
2107 
2108 }
2109 
2110 // for REPORT_LUNS documentation, see "In-Depth Exploration of Scsi",
2111 // D. Deming, 1994, pg 7-19 (ISBN 1-879936-08-9)
ScsiReportLunsDone(Scsi_Cmnd * Cmnd)2112 static void ScsiReportLunsDone(Scsi_Cmnd * Cmnd)
2113 {
2114 	struct Scsi_Host *shpnt = Cmnd->host;
2115 	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
2116 	PTACHYON fcChip = &dev->fcChip;
2117 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
2118 	PFC_LOGGEDIN_PORT pLoggedInPort;
2119 	int LunListLen = 0;
2120 	int i;
2121 	u32 x_ID = 0xFFFFFFFF;
2122 	u8 *ucBuff = Cmnd->request_buffer;
2123 
2124 	//  printk("cpqfcTS: ReportLunsDone \n");
2125 	// first, we need to find the Exchange for this command,
2126 	// so we can find the fcPort struct to make the indicated
2127 	// changes.
2128 	for (i = 0; i < TACH_SEST_LEN; i++) {
2129 		if (Exchanges->fcExchange[i].type	// exchange defined?
2130 		    && (Exchanges->fcExchange[i].Cmnd == Cmnd))	// matches?
2131 
2132 		{
2133 			x_ID = i;	// found exchange!
2134 			break;
2135 		}
2136 	}
2137 	if (x_ID == 0xFFFFFFFF) {
2138 //		printk("cpqfcTS: ReportLuns failed - no FC Exchange\n");
2139 		goto Done;	// Report Luns FC Exchange gone;
2140 		// exchange probably Terminated by Implicit logout
2141 	}
2142 
2143 	// search linked list for the port_id we sent INQUIRY to
2144 	pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// DON'T search Scsi Nexus (we will set it)
2145 					   Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF, NULL,	// DON'T search linked list for FC WWN
2146 					   NULL);	// DON'T care about end of list
2147 
2148 	if (!pLoggedInPort) {
2149 //		printk("cpqfcTS: ReportLuns failed - device gone\n");
2150 		goto Done;	// error! can't find logged in Port
2151 	}
2152 	LunListLen = ucBuff[3];
2153 	LunListLen += ucBuff[2] >> 8;
2154 
2155 	if (!LunListLen)	// failed
2156 	{
2157 		// generically speaking, a soft error means we should retry...
2158 		if ((Cmnd->result >> 16) == DID_SOFT_ERROR) {
2159 			if (((Cmnd->sense_buffer[2] & 0xF) == 0x6) && (Cmnd->sense_buffer[12] == 0x29))	// Sense Code "reset"
2160 			{
2161 				TachFCHDR_GCMND *fchs = &Exchanges->fcExchange[x_ID].fchs;
2162 				// did we fail because of "check condition, device reset?"
2163 				// e.g. the device was reset (i.e., at every power up)
2164 				// retry the Report Luns
2165 
2166 				// who are we sending it to?
2167 				// we know this because we have a copy of the command
2168 				// frame from the original Report Lun command -
2169 				// switch the d_id/s_id fields, because the Exchange Build
2170 				// context is "reply to source".
2171 
2172 				fchs->s_id = fchs->d_id;	// (temporarily re-use the struct)
2173 				cpqfcTSPutLinkQue(dev, SCSI_REPORT_LUNS, fchs);
2174 			}
2175 		} else		// probably, the device doesn't support Report Luns
2176 			pLoggedInPort->ScsiNexus.VolumeSetAddressing = 0;
2177 	} else			// we have LUN info - check VSA mode
2178 	{
2179 		// for now, assume all LUNs will have same addr mode
2180 		// for VSA, payload byte 8 will be 0x40; otherwise, 0
2181 		pLoggedInPort->ScsiNexus.VolumeSetAddressing = ucBuff[8];
2182 
2183 		// Since we got a Report Luns answer, set lun masking flag
2184 		pLoggedInPort->ScsiNexus.LunMasking = 1;
2185 
2186 		if (LunListLen > 8 * CPQFCTS_MAX_LUN)	// We expect CPQFCTS_MAX_LUN max
2187 			LunListLen = 8 * CPQFCTS_MAX_LUN;
2188 
2189 /*
2190 		printk("Device WWN %08X%08X Reports Luns @: ",
2191 			(u32)(pLoggedInPort->u.liWWN &0xFFFFFFFF),
2192 			(u32)(pLoggedInPort->u.liWWN>>32));
2193 
2194 		for( i=8; i<LunListLen+8; i+=8)
2195 		{
2196 			printk("%02X%02X ", ucBuff[i], ucBuff[i+1] );
2197 		}
2198 		printk("\n");
2199 */
2200 
2201 		// Since the device was kind enough to tell us where the
2202 		// LUNs are, lets ensure they are contiguous for Linux's
2203 		// SCSI driver scan, which expects them to start at 0.
2204 		// Since Linux only supports 8 LUNs, only copy the first
2205 		// eight from the report luns command
2206 
2207 		// e.g., the Compaq RA4x00 f/w Rev 2.54 and above may report
2208 		// LUNs 4001, 4004, etc., because other LUNs are masked from
2209 		// this HBA (owned by someone else).  We'll make those appear as
2210 		// LUN 0, 1... to Linux
2211 		{
2212 			int j;
2213 			int AppendLunList = 0;
2214 			// Walk through the LUN list.  The 'j' array number is
2215 			// Linux's lun #, while the value of .lun[j] is the target's
2216 			// lun #.
2217 			// Once we build a LUN list, it's possible for a known device
2218 			// to go offline while volumes (LUNs) are added.  Later,
2219 			// the device will do another PLOGI ... Report Luns command,
2220 			// and we must not alter the existing Linux Lun map.
2221 			// (This will be very rare).
2222 			for (j = 0; j < CPQFCTS_MAX_LUN; j++) {
2223 				if (pLoggedInPort->ScsiNexus.lun[j] != 0xFF) {
2224 					AppendLunList = 1;
2225 					break;
2226 				}
2227 			}
2228 			if (AppendLunList) {
2229 				int k;
2230 				int FreeLunIndex;
2231 //				printk("cpqfcTS: AppendLunList\n");
2232 
2233 				// If we get a new Report Luns, we cannot change
2234 				// any existing LUN mapping! (Only additive entry)
2235 				// For all LUNs in ReportLun list
2236 				// if RL lun != ScsiNexus lun
2237 				//   if RL lun present in ScsiNexus lun[], continue
2238 				//   else find ScsiNexus lun[]==FF and add, continue
2239 
2240 				for (i = 8, j = 0; i < LunListLen + 8 && j < CPQFCTS_MAX_LUN; i += 8, j++) {
2241 					if (pLoggedInPort->ScsiNexus.lun[j] != ucBuff[i + 1]) {
2242 						// something changed from the last Report Luns
2243 						printk(" cpqfcTS: Report Lun change!\n");
2244 						for (k = 0, FreeLunIndex = CPQFCTS_MAX_LUN; k < CPQFCTS_MAX_LUN; k++) {
2245 							if (pLoggedInPort->ScsiNexus.lun[k] == 0xFF) {
2246 								FreeLunIndex = k;
2247 								break;
2248 							}
2249 							if (pLoggedInPort->ScsiNexus.lun[k] == ucBuff[i + 1])
2250 								break;	// we already masked this lun
2251 						}
2252 						if (k >= CPQFCTS_MAX_LUN) {
2253 							printk(" no room for new LUN %d\n", ucBuff[i + 1]);
2254 						} else if (k == FreeLunIndex)	// need to add LUN
2255 						{
2256 							pLoggedInPort->ScsiNexus.lun[k] = ucBuff[i + 1];
2257 //							printk("add [%d]->%02d\n", k, pLoggedInPort->ScsiNexus.lun[k]);
2258 
2259 						} else {
2260 							// lun already known
2261 						}
2262 						break;
2263 					}
2264 				}
2265 				// print out the new list...
2266 				for (j = 0; j < CPQFCTS_MAX_LUN; j++) {
2267 					if (pLoggedInPort->ScsiNexus.lun[j] == 0xFF)
2268 						break;	// done
2269 //					printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
2270 				}
2271 			} else {
2272 //				printk("Linux SCSI LUNs[] -> Device LUNs: ");
2273 				// first time - this is easy
2274 				for (i = 8, j = 0; i < LunListLen + 8 && j < CPQFCTS_MAX_LUN; i += 8, j++) {
2275 					pLoggedInPort->ScsiNexus.lun[j] = ucBuff[i + 1];
2276 //					printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
2277 				}
2278 //				printk("\n");
2279 			}
2280 		}
2281 	}
2282 
2283       Done:;
2284 }
2285 
call_scsi_done(Scsi_Cmnd * Cmnd)2286 static void call_scsi_done(Scsi_Cmnd * Cmnd)
2287 {
2288 	// We have to reinitialize sent_command here, so the scsi-mid
2289 	// layer won't re-use the scsi command leaving it set incorrectly.
2290 	// (incorrectly for our purposes...it's normally unused.)
2291 
2292 	if (Cmnd->SCp.sent_command != 0) {	// was it a passthru?
2293 		Cmnd->SCp.sent_command = 0;
2294 		Cmnd->result &= 0xff00ffff;
2295 		Cmnd->result |= (DID_PASSTHROUGH << 16);	// prevents retry
2296 	}
2297 	if (Cmnd->scsi_done != NULL)
2298 		(*Cmnd->scsi_done) (Cmnd);
2299 }
2300 
2301 // After successfully getting a "Process Login" (PRLI) from an
2302 // FC port, we want to Discover the LUNs so that we know the
2303 // addressing type (e.g., FCP-SCSI Volume Set Address, Peripheral
2304 // Unit Device), and whether SSP (Selective Storage Presentation or
2305 // Lun Masking) has made the LUN numbers non-zero based or
2306 // non-contiguous.  To remain backward compatible with the SCSI-2
2307 // driver model, which expects a contiguous LUNs starting at 0,
2308 // will use the ReportLuns info to map from "device" to "Linux"
2309 // LUNs.
IssueReportLunsCommand(CPQFCHBA * dev,TachFCHDR_GCMND * fchs)2310 static void IssueReportLunsCommand(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
2311 {
2312 	PTACHYON fcChip = &dev->fcChip;
2313 	PFC_LOGGEDIN_PORT pLoggedInPort;
2314 	Scsi_Cmnd *Cmnd;
2315 	s32 x_ID;
2316 	u32 ulStatus;
2317 	u8 *ucBuff;
2318 
2319 	if (!dev->PortDiscDone)	// cleared by LDn
2320 	{
2321 		printk("Discard Q'd ReportLun command\n");
2322 		goto Done;
2323 	}
2324 	// find the device (from port_id) we're talking to
2325 	pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// DON'T search Scsi Nexus
2326 					   fchs->s_id & 0xFFFFFF, NULL,	// DON'T search linked list for FC WWN
2327 					   NULL);	// DON'T care about end of list
2328 	if (pLoggedInPort)	// we'd BETTER find it!
2329 	{
2330 
2331 
2332 		if (!(pLoggedInPort->fcp_info & TARGET_FUNCTION))
2333 			goto Done;	// forget it - FC device not a "target"
2334 
2335 		// now use the port's Scsi Command buffer for the
2336 		// Report Luns Command
2337 
2338 		Cmnd = &pLoggedInPort->ScsiCmnd;
2339 		ucBuff = pLoggedInPort->ReportLunsPayload;
2340 
2341 		memset(Cmnd, 0, sizeof(Scsi_Cmnd));
2342 		memset(ucBuff, 0, REPORT_LUNS_PL);
2343 
2344 		Cmnd->scsi_done = ScsiReportLunsDone;
2345 		Cmnd->host = dev->HostAdapter;
2346 
2347 		Cmnd->request_buffer = pLoggedInPort->ReportLunsPayload;
2348 		Cmnd->request_bufflen = REPORT_LUNS_PL;
2349 
2350 		Cmnd->cmnd[0] = 0xA0;
2351 		Cmnd->cmnd[8] = REPORT_LUNS_PL >> 8;
2352 		Cmnd->cmnd[9] = (u8) REPORT_LUNS_PL;
2353 		Cmnd->cmd_len = 12;
2354 
2355 		Cmnd->channel = pLoggedInPort->ScsiNexus.channel;
2356 		Cmnd->target = pLoggedInPort->ScsiNexus.target;
2357 
2358 
2359 		ulStatus = cpqfcTSBuildExchange(dev, SCSI_IRE, fchs, Cmnd,	// buffer for Report Lun data
2360 						&x_ID);	// fcController->fcExchanges index, -1 if failed
2361 
2362 		if (!ulStatus)	// Exchange setup?
2363 		{
2364 			ulStatus = cpqfcTSStartExchange(dev, x_ID);
2365 			if (!ulStatus) {
2366 				// submitted to Tach's Outbound Que (ERQ PI incremented)
2367 				// waited for completion for ELS type (Login frames issued
2368 				// synchronously)
2369 			} else
2370 				// check reason for Exchange not being started - we might
2371 				// want to Queue and start later, or fail with error
2372 			{
2373 			}
2374 		}
2375 
2376 		else		// Xchange setup failed...
2377 			printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus);
2378 	} else			// like, we just got a PRLI ACC, and now the port is gone?
2379 	{
2380 		printk(" can't send ReportLuns - no login for port_id %Xh\n", fchs->s_id & 0xFFFFFF);
2381 	}
2382 Done:;
2383 }
2384 
CompleteBoardLockCmnd(CPQFCHBA * dev)2385 static void CompleteBoardLockCmnd(CPQFCHBA * dev)
2386 {
2387 	int i;
2388 	for (i = CPQFCTS_REQ_QUEUE_LEN - 1; i >= 0; i--) {
2389 		if (dev->BoardLockCmnd[i] != NULL) {
2390 			Scsi_Cmnd *Cmnd = dev->BoardLockCmnd[i];
2391 			dev->BoardLockCmnd[i] = NULL;
2392 			Cmnd->result = (DID_SOFT_ERROR << 16);	// ask for retry
2393 //			printk(" BoardLockCmnd[%d] %p Complete, chnl/target/lun %d/%d/%d\n",
2394 //				i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
2395 			call_scsi_done(Cmnd);
2396 		}
2397 	}
2398 }
2399 
2400 // runs every 1 second for FC exchange timeouts and implicit FC device logouts
2401 
cpqfcTSheartbeat(unsigned long ptr)2402 void cpqfcTSheartbeat(unsigned long ptr)
2403 {
2404 	CPQFCHBA *dev = (CPQFCHBA *) ptr;
2405 	PTACHYON fcChip = &dev->fcChip;
2406 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
2407 	PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
2408 	u32 i;
2409 	unsigned long flags;
2410 	DECLARE_MUTEX_LOCKED(BoardLock);
2411 
2412 	PCI_TRACE(0xA8)
2413 
2414 	if (dev->BoardLock)	// Worker Task Running?
2415 		goto Skip;
2416 
2417 	spin_lock_irqsave(&io_request_lock, flags);	// STOP _que function
2418 
2419 	PCI_TRACE(0xA8)
2420 
2421 	dev->BoardLock = &BoardLock;	// stop Linux SCSI command queuing
2422 
2423 	// release the IO lock (and re-enable interrupts)
2424 	spin_unlock_irqrestore(&io_request_lock, flags);
2425 
2426 	// Ensure no contention from  _quecommand or Worker process
2427 	CPQ_SPINLOCK_HBA(dev)
2428 
2429 	PCI_TRACE(0xA8)
2430 
2431 	disable_irq(dev->HostAdapter->irq);	// our IRQ
2432 
2433 	// Complete the "bad target" commands (normally only used during
2434 	// initialization, since we aren't supposed to call "scsi_done"
2435 	// inside the queuecommand() function).  (this is overly contorted,
2436 	// scsi_done can be safely called from queuecommand for
2437 	// this bad target case.  May want to simplify this later)
2438 
2439 	for (i = 0; i < CPQFCTS_MAX_TARGET_ID; i++) {
2440 		if (dev->BadTargetCmnd[i]) {
2441 			Scsi_Cmnd *Cmnd = dev->BadTargetCmnd[i];
2442 			dev->BadTargetCmnd[i] = NULL;
2443 			Cmnd->result = (DID_BAD_TARGET << 16);
2444 			call_scsi_done(Cmnd);
2445 		} else
2446 			break;
2447 	}
2448 
2449 
2450 	// logged in ports -- re-login check (ports required to verify login with
2451 	// PDISC after LIP within 2 secs)
2452 
2453 	// prevent contention
2454 	while (pLoggedInPort)	// for all ports which are expecting
2455 				// PDISC after the next LIP, check to see if
2456 				// time is up!
2457 	{
2458 		// Important: we only detect "timeout" condition on TRANSITION
2459 		// from non-zero to zero
2460 		if (pLoggedInPort->LOGO_timer)	// time-out "armed"?
2461 		{
2462 			if (!(--pLoggedInPort->LOGO_timer))	// DEC from 1 to 0?
2463 			{
2464 				// LOGOUT time!  Per PLDA, PDISC hasn't complete in 2 secs, so
2465 				// issue LOGO request and destroy all I/O with other FC port(s).
2466 
2467 /*
2468 			        printk(" ~cpqfcTS heartbeat: LOGOut!~ ");
2469         			printk("Linux SCSI Chanl/Target %d/%d (port_id %06Xh) WWN %08X%08X\n",
2470 				        pLoggedInPort->ScsiNexus.channel,
2471 				        pLoggedInPort->ScsiNexus.target,
2472 					pLoggedInPort->port_id,
2473 				        (u32)(pLoggedInPort->u.liWWN &0xFFFFFFFF),
2474 				        (u32)(pLoggedInPort->u.liWWN>>32));
2475 */
2476 				cpqfcTSImplicitLogout(dev, pLoggedInPort);
2477 
2478 			}
2479 			// else simply decremented - maybe next time...
2480 		}
2481 		pLoggedInPort = pLoggedInPort->pNextPort;
2482 	}
2483 
2484 	// ************  FC EXCHANGE TIMEOUT CHECK **************
2485 
2486 	for (i = 0; i < TACH_MAX_XID; i++) {
2487 		if (Exchanges->fcExchange[i].type)	// exchange defined?
2488 		{
2489 
2490 			if (!Exchanges->fcExchange[i].timeOut)	// time expired
2491 			{
2492 				// Set Exchange timeout status
2493 				Exchanges->fcExchange[i].status |= FC2_TIMEOUT;
2494 
2495 				if (i >= TACH_SEST_LEN)	// Link Service Exchange
2496 				{
2497 					cpqfcTSCompleteExchange(dev->PciDev, fcChip, i);	// Don't "abort" LinkService
2498 				}
2499 				else	// SEST Exchange TO -- may post ABTS to Worker Thread Que
2500 				{
2501 					// (Make sure we don't keep timing it out; let other functions
2502 					// complete it or set the timeOut as needed)
2503 					Exchanges->fcExchange[i].timeOut = 30000;	// seconds default
2504 
2505 					if (Exchanges->fcExchange[i].type & (BLS_ABTS | BLS_ABTS_ACC)) {
2506 						// For BLS_ABTS*, an upper level might still have
2507 						// an outstanding command waiting for low-level completion.
2508 						// Also, in the case of a WRITE, we MUST get confirmation
2509 						// of either ABTS ACC or RJT before re-using the Exchange.
2510 						// It's possible that the RAID cache algorithm can hang
2511 						// if we fail to complete a WRITE to a LBA, when a READ
2512 						// comes later to that same LBA.  Therefore, we must
2513 						// ensure that the target verifies receipt of ABTS for
2514 						// the exchange
2515 
2516 						printk("~TO Q'd ABTS (x_ID %Xh)~ ", i);
2517 //						TriggerHBA( fcChip->Registers.ReMapMemBase);
2518 
2519 						// On timeout of a ABTS exchange, check to
2520 						// see if the FC device has a current valid login.
2521 						// If so, restart it.
2522 						pLoggedInPort = fcFindLoggedInPort(fcChip, Exchanges->fcExchange[i].Cmnd,	// find Scsi Nexus
2523 										   0,	// DON'T search linked list for FC port id
2524 										   NULL,	// DON'T search linked list for FC WWN
2525 										   NULL);	// DON'T care about end of list
2526 						// device exists?
2527 						if (pLoggedInPort)	// device exists?
2528 						{
2529 							if (pLoggedInPort->prli)	// logged in for FCP-SCSI?
2530 							{
2531 								// attempt to restart the ABTS
2532 								printk(" ~restarting ABTS~ ");
2533 								cpqfcTSStartExchange(dev, i);
2534 
2535 							}
2536 						}
2537 					} else	// not an ABTS
2538 					{
2539 
2540 						// We expect the WorkerThread to change the xchng type to
2541 						// abort and set appropriate timeout.
2542 						cpqfcTSPutLinkQue(dev, BLS_ABTS, &i);	// timed-out
2543 					}
2544 				}
2545 			} else	// time not expired...
2546 			{
2547 				// decrement timeout: 1 or more seconds left
2548 				--Exchanges->fcExchange[i].timeOut;
2549 			}
2550 		}
2551 	}
2552 
2553 	enable_irq(dev->HostAdapter->irq);
2554 	CPQ_SPINUNLOCK_HBA(dev)
2555 	dev->BoardLock = NULL;	// Linux SCSI commands may be queued
2556 	// Now, complete any Cmnd we Q'd up while BoardLock was held
2557 	CompleteBoardLockCmnd(dev);
2558 	// restart the timer to run again (1 sec later)
2559 Skip:
2560 	mod_timer(&dev->cpqfcTStimer, jiffies + HZ);
2561 	PCI_TRACEO(i, 0xA8)
2562 	return;
2563 }
2564 
2565 
2566 // put valid FC-AL physical address in spec order
2567 static const u8 valid_al_pa[] = {
2568 	0xef, 0xe8, 0xe4, 0xe2,
2569 	0xe1, 0xE0, 0xDC, 0xDA,
2570 	0xD9, 0xD6, 0xD5, 0xD4,
2571 	0xD3, 0xD2, 0xD1, 0xCe,
2572 	0xCd, 0xCc, 0xCb, 0xCa,
2573 	0xC9, 0xC7, 0xC6, 0xC5,
2574 	0xC3, 0xBc, 0xBa, 0xB9,
2575 	0xB6, 0xB5, 0xB4, 0xB3,
2576 	0xB2, 0xB1, 0xae, 0xad,
2577 	0xAc, 0xAb, 0xAa, 0xA9,
2578 
2579 	0xA7, 0xA6, 0xA5, 0xA3,
2580 	0x9f, 0x9e, 0x9d, 0x9b,
2581 	0x98, 0x97, 0x90, 0x8f,
2582 	0x88, 0x84, 0x82, 0x81,
2583 	0x80, 0x7c, 0x7a, 0x79,
2584 	0x76, 0x75, 0x74, 0x73,
2585 	0x72, 0x71, 0x6e, 0x6d,
2586 	0x6c, 0x6b, 0x6a, 0x69,
2587 	0x67, 0x66, 0x65, 0x63,
2588 	0x5c, 0x5a, 0x59, 0x56,
2589 
2590 	0x55, 0x54, 0x53, 0x52,
2591 	0x51, 0x4e, 0x4d, 0x4c,
2592 	0x4b, 0x4a, 0x49, 0x47,
2593 	0x46, 0x45, 0x43, 0x3c,
2594 	0x3a, 0x39, 0x36, 0x35,
2595 	0x34, 0x33, 0x32, 0x31,
2596 	0x2e, 0x2d, 0x2c, 0x2b,
2597 	0x2a, 0x29, 0x27, 0x26,
2598 	0x25, 0x23, 0x1f, 0x1E,
2599 	0x1d, 0x1b, 0x18, 0x17,
2600 
2601 	0x10, 0x0f, 8, 4, 2, 1
2602 };				// ALPA 0 (Fabric) is special case
2603 
2604 const int number_of_al_pa = (sizeof(valid_al_pa));
2605 
2606 // this function looks up an al_pa from the table of valid al_pa's
2607 // we decrement from the last decimal loop ID, because soft al_pa
2608 // (our typical case) are assigned with highest priority (and high al_pa)
2609 // first.  See "In-Depth FC-AL", R. Kembel pg. 38
2610 // INPUTS:
2611 //   al_pa - 24 bit port identifier (8 bit al_pa on private loop)
2612 // RETURN:
2613 //  Loop ID - serves are index to array of logged in ports
2614 //  -1      - invalid al_pa (not all 8 bit values are legal)
2615 
2616 #if (0)
GetLoopID(u32 al_pa)2617 static int GetLoopID(u32 al_pa)
2618 {
2619 	int i;
2620 
2621 	for (i = number_of_al_pa - 1; i >= 0; i--)	// dec.
2622 	{
2623 		if (valid_al_pa[i] == (u8) al_pa)	// take lowest 8 bits
2624 			return i;	// success - found valid al_pa; return decimal LoopID
2625 	}
2626 	return -1;		// failed - not found
2627 }
2628 #endif
2629 
2630 
2631 // Search the singly (forward) linked list "fcPorts" looking for
2632 // either the SCSI target (if != -1), port_id (if not NULL),
2633 // or WWN (if not null), in that specific order.
2634 // If we find a SCSI nexus (from Cmnd arg), set the SCp.phase
2635 // field according to VSA or PDU
2636 // RETURNS:
2637 //   Ptr to logged in port struct if found
2638 //     (NULL if not found)
2639 //   pLastLoggedInPort - ptr to last struct (for adding new ones)
2640 //
fcFindLoggedInPort(PTACHYON fcChip,Scsi_Cmnd * Cmnd,u32 port_id,u8 wwn[8],PFC_LOGGEDIN_PORT * pLastLoggedInPort)2641 PFC_LOGGEDIN_PORT fcFindLoggedInPort(PTACHYON fcChip, Scsi_Cmnd * Cmnd,	// search linked list for Scsi Nexus (channel/target/lun)
2642 				     u32 port_id,	// search linked list for al_pa, or
2643 				     u8 wwn[8],	// search linked list for WWN, or...
2644 				     PFC_LOGGEDIN_PORT * pLastLoggedInPort)
2645 {
2646 	PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
2647 	u8 target_id_valid = 0;
2648 	u8 port_id_valid = 0;
2649 	u8 wwn_valid = 0;
2650 	int i;
2651 
2652 
2653 	if (Cmnd != NULL)
2654 		target_id_valid = 1;
2655 
2656 	else if (port_id)	// note! 24-bit NULL address is illegal
2657 		port_id_valid = 1;
2658 
2659 	else {
2660 		if (wwn)	// non-null arg? (OK to pass NULL when not searching WWN)
2661 		{
2662 			for (i = 0; i < 8; i++)	// valid WWN passed?  NULL WWN invalid
2663 			{
2664 				if (wwn[i] != 0)
2665 					wwn_valid = 1;	// any non-zero byte makes (presumably) valid
2666 			}
2667 		}
2668 	}
2669 	// check other options ...
2670 
2671 
2672 	// In case multiple search options are given, we use a priority
2673 	// scheme:
2674 	// While valid pLoggedIn Ptr
2675 	//   If port_id is valid
2676 	//     if port_id matches, return Ptr
2677 	//   If wwn is valid
2678 	//     if wwn matches, return Ptr
2679 	//   Next Ptr in list
2680 	//
2681 	// Return NULL (not found)
2682 
2683 
2684 	while (pLoggedInPort)	// NULL marks end of list (1st ptr always valid)
2685 	{
2686 		if (pLastLoggedInPort)	// caller's pointer valid?
2687 			*pLastLoggedInPort = pLoggedInPort;	// end of linked list
2688 
2689 		if (target_id_valid) {
2690 			// check Linux Scsi Cmnd for channel/target Nexus match
2691 			// (all luns are accessed through matching "pLoggedInPort")
2692 			if ((pLoggedInPort->ScsiNexus.target == Cmnd->target)
2693 			    && (pLoggedInPort->ScsiNexus.channel == Cmnd->channel)) {
2694 				// For "passthru" modes, the IOCTL caller is responsible
2695 				// for setting the FCP-LUN addressing
2696 				if (!Cmnd->SCp.sent_command)	// NOT passthru?
2697 				{
2698 
2699 					// set the FCP-LUN addressing type
2700 					Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing;
2701 
2702 					// set the Device Type we got from the snooped INQUIRY string
2703 					Cmnd->SCp.Message = pLoggedInPort->ScsiNexus.InqDeviceType;
2704 
2705 					// handle LUN masking; if not "default" (illegal) lun value,
2706 					// the use it.  These lun values are set by a successful
2707 					// Report Luns command
2708 					if (pLoggedInPort->ScsiNexus.LunMasking == 1) {
2709 						// we KNOW all the valid LUNs... 0xFF is invalid!
2710 						if (Cmnd->lun > sizeof(pLoggedInPort->ScsiNexus.lun)){
2711 							// printk("cpqfcTS FATAL: Invalid LUN index !!!!\n ");
2712 							return NULL;
2713 						}
2714 						Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->lun];
2715 						if (pLoggedInPort->ScsiNexus.lun[Cmnd->lun] == 0xFF)
2716 							return NULL;
2717 						// printk("xlating lun %d to 0x%02x\n", Cmnd->lun,
2718 						//  pLoggedInPort->ScsiNexus.lun[Cmnd->lun]);
2719 					} else
2720 						Cmnd->SCp.have_data_in = Cmnd->lun;	// Linux & target luns match
2721 				}
2722 				break;	// found it!
2723 			}
2724 		}
2725 
2726 		if (port_id_valid)	// look for alpa first
2727 		{
2728 			if (pLoggedInPort->port_id == port_id)
2729 				break;	// found it!
2730 		}
2731 		if (wwn_valid)	// look for wwn second
2732 		{
2733 
2734 			if (!memcmp(&pLoggedInPort->u.ucWWN[0], &wwn[0], 8)) {
2735 				// all 8 bytes of WWN match
2736 				break;	// found it!
2737 			}
2738 		}
2739 
2740 		pLoggedInPort = pLoggedInPort->pNextPort;	// try next port
2741 	}
2742 
2743 	return pLoggedInPort;
2744 }
2745 
2746 //
2747 // We need to examine the SEST table and re-validate
2748 // any open Exchanges for this LoggedInPort
2749 // To make Tachyon pay attention, Freeze FCP assists,
2750 // set VAL bits, Unfreeze FCP assists
RevalidateSEST(struct Scsi_Host * shpnt,PFC_LOGGEDIN_PORT pLoggedInPort)2751 static void RevalidateSEST(struct Scsi_Host *shpnt, PFC_LOGGEDIN_PORT pLoggedInPort)
2752 {
2753 	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
2754 	PTACHYON fcChip = &dev->fcChip;
2755 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
2756 	u32 x_ID;
2757 	u8 TachFroze = 0;
2758 
2759 
2760 	// re-validate any SEST exchanges that are permitted
2761 	// to survive the link down (e.g., good PDISC performed)
2762 	for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
2763 
2764 		// If the SEST entry port_id matches the pLoggedInPort,
2765 		// we need to re-validate
2766 		if ((Exchanges->fcExchange[x_ID].type == SCSI_IRE)
2767 		    || (Exchanges->fcExchange[x_ID].type == SCSI_IWE)) {
2768 			if ((Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF) == pLoggedInPort->port_id) 	// (24-bit port ID)
2769 			{
2770 //				printk(" re-val xID %Xh ", x_ID);
2771 				if (!TachFroze)	// freeze if not already frozen
2772 					TachFroze |= FreezeTach(dev);
2773 				fcChip->SEST->u[x_ID].IWE.Hdr_Len |= 0x80000000;	// set VAL bit
2774 			}
2775 		}
2776 	}
2777 	if (TachFroze) {
2778 		fcChip->UnFreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
2779 	}
2780 }
2781 
2782 
2783 // Complete an Linux Cmnds that we Queued because
2784 // our FC link was down (cause immediate retry)
2785 
UnblockScsiDevice(struct Scsi_Host * shpnt,PFC_LOGGEDIN_PORT pLoggedInPort)2786 static void UnblockScsiDevice(struct Scsi_Host *shpnt, PFC_LOGGEDIN_PORT pLoggedInPort)
2787 {
2788 //  Scsi_Device *sdev = shpnt->host_queue;
2789 	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
2790 	Scsi_Cmnd **SCptr = &dev->LinkDnCmnd[0];
2791 	Scsi_Cmnd *Cmnd;
2792 	int indx;
2793 
2794 	// if the device was previously "blocked", make sure
2795 	// we unblock it so Linux SCSI will resume
2796 
2797 	pLoggedInPort->device_blocked = 0;	// clear our flag
2798 
2799 	// check the Link Down command ptr buffer;
2800 	// we can complete now causing immediate retry
2801 	for (indx = 0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++, SCptr++) {
2802 		if (*SCptr != NULL)	// scsi command to complete?
2803 		{
2804 #ifdef DUMMYCMND_DBG
2805 			printk("complete Cmnd %p in LinkDnCmnd[%d]\n", *SCptr, indx);
2806 #endif
2807 			Cmnd = *SCptr;
2808 
2809 			// Are there any Q'd commands for this target?
2810 			if ((Cmnd->target == pLoggedInPort->ScsiNexus.target)
2811 			    && (Cmnd->channel == pLoggedInPort->ScsiNexus.channel)) {
2812 				Cmnd->result = (DID_SOFT_ERROR << 16);	// force retry
2813 				if (Cmnd->scsi_done == NULL) {
2814 					printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n", pLoggedInPort->port_id);
2815 					Cmnd->SCp.sent_command = 0;
2816 				} else
2817 					call_scsi_done(Cmnd);
2818 				*SCptr = NULL;	// free this slot for next use
2819 			}
2820 		}
2821 	}
2822 }
2823 
2824 
2825 //#define WWN_DBG 1
2826 
SetLoginFields(PFC_LOGGEDIN_PORT pLoggedInPort,TachFCHDR_GCMND * fchs,u8 PDisc,u8 Originator)2827 static void SetLoginFields(PFC_LOGGEDIN_PORT pLoggedInPort, TachFCHDR_GCMND * fchs, u8 PDisc, u8 Originator)
2828 {
2829 	LOGIN_PAYLOAD logi;	// FC-PH Port Login
2830 	PRLI_REQUEST prli;	// copy for BIG ENDIAN switch
2831 	int i;
2832 #ifdef WWN_DBG
2833 	u32 ulBuff;
2834 #endif
2835 
2836 	BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
2837 
2838 	pLoggedInPort->Originator = Originator;
2839 	pLoggedInPort->port_id = fchs->s_id & 0xFFFFFF;
2840 
2841 	switch (fchs->pl[0] & 0xffff) {
2842 	case 0x00000002:	//  PLOGI or PDISC ACCept?
2843 		if (PDisc)	// PDISC accept
2844 			goto PDISC_case;
2845 
2846 	case 0x00000003:	//  ELS_PLOGI or ELS_PLOGI_ACC
2847 
2848 		// Login BB_credit typically 0 for Tachyons
2849 		pLoggedInPort->BB_credit = logi.cmn_services.bb_credit;
2850 
2851 		// e.g. 128, 256, 1024, 2048 per FC-PH spec
2852 		// We have to use this when setting up SEST Writes,
2853 		// since that determines frame size we send.
2854 		pLoggedInPort->rx_data_size = logi.class3.rx_data_size;
2855 		pLoggedInPort->plogi = 1;
2856 		pLoggedInPort->pdisc = 0;
2857 		pLoggedInPort->prli = 0;	// ELS_PLOGI resets
2858 		pLoggedInPort->flogi = 0;	// ELS_PLOGI resets
2859 		pLoggedInPort->logo = 0;	// ELS_PLOGI resets
2860 		pLoggedInPort->LOGO_counter = 0;	// ELS_PLOGI resets
2861 		pLoggedInPort->LOGO_timer = 0;	// ELS_PLOGI resets
2862 
2863 		// was this PLOGI to a Fabric?
2864 		if (pLoggedInPort->port_id == 0xFFFFFC)	// well know address
2865 			pLoggedInPort->flogi = 1;
2866 
2867 
2868 		for (i = 0; i < 8; i++)	// copy the LOGIN port's WWN
2869 			pLoggedInPort->u.ucWWN[i] = logi.port_name[i];
2870 
2871 #ifdef WWN_DBG
2872 		ulBuff = (u32) pLoggedInPort->u.liWWN;
2873 		if (pLoggedInPort->Originator)
2874 			printk("o");
2875 		else
2876 			printk("r");
2877 		printk("PLOGI port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
2878 
2879 		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
2880 		printk("%08Xh fcPort %p\n", ulBuff, pLoggedInPort);
2881 #endif
2882 		break;
2883 
2884 	case 0x00000005:	//  ELS_LOGO (logout)
2885 		pLoggedInPort->plogi = 0;
2886 		pLoggedInPort->pdisc = 0;
2887 		pLoggedInPort->prli = 0;	// ELS_PLOGI resets
2888 		pLoggedInPort->flogi = 0;	// ELS_PLOGI resets
2889 		pLoggedInPort->logo = 1;	// ELS_PLOGI resets
2890 		pLoggedInPort->LOGO_counter++;	// ELS_PLOGI resets
2891 		pLoggedInPort->LOGO_timer = 0;
2892 #ifdef WWN_DBG
2893 		ulBuff = (u32) pLoggedInPort->u.liWWN;
2894 		if (pLoggedInPort->Originator)
2895 			printk("o");
2896 		else
2897 			printk("r");
2898 		printk("LOGO port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
2899 
2900 		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
2901 		printk("%08Xh\n", ulBuff);
2902 #endif
2903 		break;
2904 
2905 	PDISC_case:
2906 	case 0x00000050:	//  ELS_PDISC or ELS_PDISC_ACC
2907 		pLoggedInPort->LOGO_timer = 0;	// stop the time-out
2908 
2909 		pLoggedInPort->prli = 1;	// ready to accept FCP-SCSI I/O
2910 #ifdef WWN_DBG
2911 		ulBuff = (u32) pLoggedInPort->u.liWWN;
2912 		if (pLoggedInPort->Originator)
2913 			printk("o");
2914 		else
2915 			printk("r");
2916 		printk("PDISC port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
2917 
2918 		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
2919 		printk("%08Xh\n", ulBuff);
2920 #endif
2921 		break;
2922 
2923 	case 0x1020L:		//  PRLI?
2924 	case 0x1002L:		//  PRLI ACCept?
2925 		BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & prli, sizeof(prli));
2926 
2927 		pLoggedInPort->fcp_info = prli.fcp_info;	// target/initiator flags
2928 		pLoggedInPort->prli = 1;	// PLOGI resets, PDISC doesn't
2929 
2930 		pLoggedInPort->pdisc = 1;	// expect to send (or receive) PDISC
2931 		// next time
2932 		pLoggedInPort->LOGO_timer = 0;	// will be set next LinkDown
2933 #ifdef WWN_DBG
2934 		ulBuff = (u32) pLoggedInPort->u.liWWN;
2935 		if (pLoggedInPort->Originator)
2936 			printk("o");
2937 		else
2938 			printk("r");
2939 		printk("PRLI port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
2940 
2941 		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
2942 		printk("%08Xh\n", ulBuff);
2943 #endif
2944 		break;
2945 	}
2946 	return;
2947 }
2948 
BuildLinkServicePayload(PTACHYON fcChip,u32 type,void * payload)2949 static void BuildLinkServicePayload(PTACHYON fcChip, u32 type, void *payload)
2950 {
2951 	LOGIN_PAYLOAD *plogi;	// FC-PH Port Login
2952 	LOGIN_PAYLOAD PlogiPayload;	// copy for BIG ENDIAN switch
2953 	PRLI_REQUEST *prli;	// FCP-SCSI Process Login
2954 	PRLI_REQUEST PrliPayload;	// copy for BIG ENDIAN switch
2955 	LOGOUT_PAYLOAD *logo;
2956 	LOGOUT_PAYLOAD LogoutPayload;
2957 //	PRLO_REQUEST  *prlo;
2958 //	PRLO_REQUEST  PrloPayload;
2959 	REJECT_MESSAGE rjt, *prjt;
2960 
2961 	memset(&PlogiPayload, 0, sizeof(PlogiPayload));
2962 	plogi = &PlogiPayload;	// load into stack buffer,
2963 	// then BIG-ENDIAN switch a copy to caller
2964 
2965 	switch (type)		// payload type can be ELS_PLOGI, ELS_PRLI, ADISC, ...
2966 	{
2967 	case ELS_FDISC:
2968 	case ELS_FLOGI:
2969 	case ELS_PLOGI_ACC:	// FC-PH PORT Login Accept
2970 	case ELS_PLOGI:	// FC-PH PORT Login
2971 	case ELS_PDISC:	// FC-PH2 Port Discovery - same payload as ELS_PLOGI
2972 		plogi->login_cmd = LS_PLOGI;
2973 		if (type == ELS_PDISC)
2974 			plogi->login_cmd = LS_PDISC;
2975 		else if (type == ELS_PLOGI_ACC)
2976 			plogi->login_cmd = LS_ACC;
2977 
2978 		plogi->cmn_services.bb_credit = 0x00;
2979 		plogi->cmn_services.lowest_ver = fcChip->lowest_FCPH_ver;
2980 		plogi->cmn_services.highest_ver = fcChip->highest_FCPH_ver;
2981 		plogi->cmn_services.bb_rx_size = TACHLITE_TS_RX_SIZE;
2982 		plogi->cmn_services.common_features = CONTINUOSLY_INCREASING | RANDOM_RELATIVE_OFFSET;
2983 
2984 		// fill in with World Wide Name based Port Name - 8 u8s
2985 		// get from Tach registers WWN hi & lo
2986 		LoadWWN(fcChip, plogi->port_name, 0);
2987 		// fill in with World Wide Name based Node/Fabric Name - 8 u8s
2988 		// get from Tach registers WWN hi & lo
2989 		LoadWWN(fcChip, plogi->node_name, 1);
2990 
2991 		// For Seagate Drives.
2992 		//
2993 		plogi->cmn_services.common_features |= 0x800;
2994 		plogi->cmn_services.rel_offset = 0xFE;
2995 		plogi->cmn_services.concurrent_seq = 1;
2996 		plogi->class1.service_options = 0x00;
2997 		plogi->class2.service_options = 0x00;
2998 		plogi->class3.service_options = CLASS_VALID;
2999 		plogi->class3.initiator_control = 0x00;
3000 		plogi->class3.rx_data_size = MAX_RX_PAYLOAD;
3001 		plogi->class3.recipient_control = ERROR_DISCARD | ONE_CATEGORY_SEQUENCE;
3002 		plogi->class3.concurrent_sequences = 1;
3003 		plogi->class3.open_sequences = 1;
3004 		plogi->vendor_id[0] = 'C';
3005 		plogi->vendor_id[1] = 'Q';
3006 		plogi->vendor_version[0] = 'C';
3007 		plogi->vendor_version[1] = 'Q';
3008 		plogi->vendor_version[2] = ' ';
3009 		plogi->vendor_version[3] = '0';
3010 		plogi->vendor_version[4] = '0';
3011 		plogi->vendor_version[5] = '0';
3012 
3013 		// FLOGI specific fields... (see FC-FLA, Rev 2.7, Aug 1999, sec 5.1)
3014 		if ((type == ELS_FLOGI) || (type == ELS_FDISC)) {
3015 			if (type == ELS_FLOGI)
3016 				plogi->login_cmd = LS_FLOGI;
3017 			else
3018 				plogi->login_cmd = LS_FDISC;
3019 
3020 			plogi->cmn_services.lowest_ver = 0x20;
3021 			plogi->cmn_services.common_features = 0x0800;
3022 			plogi->cmn_services.rel_offset = 0;
3023 			plogi->cmn_services.concurrent_seq = 0;
3024 
3025 			plogi->class3.service_options = 0x8800;
3026 			plogi->class3.rx_data_size = 0;
3027 			plogi->class3.recipient_control = 0;
3028 			plogi->class3.concurrent_sequences = 0;
3029 			plogi->class3.open_sequences = 0;
3030 		}
3031 		// copy back to caller's buff, w/ BIG ENDIAN swap
3032 		BigEndianSwap((u8 *) & PlogiPayload, payload, sizeof(PlogiPayload));
3033 		break;
3034 
3035 	case ELS_ACC:		// generic Extended Link Service ACCept
3036 		plogi->login_cmd = LS_ACC;
3037 		// copy back to caller's buff, w/ BIG ENDIAN swap
3038 		BigEndianSwap((u8 *) & PlogiPayload, payload, 4);
3039 		break;
3040 
3041 	case ELS_SCR:		// Fabric State Change Registration
3042 		{
3043 			SCR_PL scr;	// state change registration
3044 
3045 			memset(&scr, 0, sizeof(scr));
3046 
3047 			scr.command = LS_SCR;	// 0x62000000
3048 			// see FC-FLA, Rev 2.7, Table A.22 (pg 82)
3049 			scr.function = 3;	// 1 = Events detected by Fabric
3050 			// 2 = N_Port detected registration
3051 			// 3 = Full registration
3052 
3053 			// copy back to caller's buff, w/ BIG ENDIAN swap
3054 			BigEndianSwap((u8 *) & scr, payload, sizeof(SCR_PL));
3055 		}
3056 		break;
3057 
3058 	case FCS_NSR:		// Fabric Name Service Request
3059 		{
3060 			NSR_PL nsr;	// Name Server Req. payload
3061 
3062 			memset(&nsr, 0, sizeof(NSR_PL));
3063 
3064 			// see Brocade Fabric Programming Guide,
3065 			// Rev 1.3, pg 4-44
3066 			nsr.CT_Rev = 0x01000000;
3067 			nsr.FCS_Type = 0xFC020000;
3068 			nsr.Command_code = 0x01710000;
3069 			nsr.FCP = 8;
3070 
3071 			// copy back to caller's buff, w/ BIG ENDIAN swap
3072 			BigEndianSwap((u8 *) & nsr, payload, sizeof(NSR_PL));
3073 		}
3074 		break;
3075 
3076 	case ELS_LOGO:		// FC-PH PORT LogOut
3077 		logo = &LogoutPayload;	// load into stack buffer,
3078 		// then BIG-ENDIAN switch a copy to caller
3079 		logo->cmd = LS_LOGO;
3080 		// load the 3 u8s of the node name
3081 		// (if private loop, upper two u8s 0)
3082 		logo->reserved = 0;
3083 
3084 		logo->n_port_identifier[0] = (u8) (fcChip->Registers.my_al_pa);
3085 		logo->n_port_identifier[1] = (u8) (fcChip->Registers.my_al_pa >> 8);
3086 		logo->n_port_identifier[2] = (u8) (fcChip->Registers.my_al_pa >> 16);
3087 		// fill in with World Wide Name based Port Name - 8 u8s
3088 		// get from Tach registers WWN hi & lo
3089 		LoadWWN(fcChip, logo->port_name, 0);
3090 
3091 		BigEndianSwap((u8 *) & LogoutPayload, payload, sizeof(LogoutPayload));	// 16 u8 struct
3092 		break;
3093 
3094 	case ELS_LOGO_ACC:	// Logout Accept (FH-PH pg 149, table 74)
3095 		logo = &LogoutPayload;	// load into stack buffer,
3096 		// then BIG-ENDIAN switch a copy to caller
3097 		logo->cmd = LS_ACC;
3098 		BigEndianSwap((u8 *) & LogoutPayload, payload, 4);	// 4 u8 cmnd
3099 		break;
3100 
3101 	case ELS_RJT:		// ELS_RJT link service reject (FH-PH pg 155)
3102 		prjt = (REJECT_MESSAGE *) payload;	// pick up passed data
3103 		rjt.command_code = ELS_RJT;
3104 		// reverse fields, because of Swap that follows...
3105 		rjt.vendor = prjt->reserved;	// vendor specific
3106 		rjt.explain = prjt->reason;	//
3107 		rjt.reason = prjt->explain;	//
3108 		rjt.reserved = prjt->vendor;	//
3109 		// BIG-ENDIAN switch a copy to caller
3110 		BigEndianSwap((u8 *) & rjt, payload, 8);	// 8 u8 cmnd
3111 		break;
3112 
3113 	case ELS_PRLI_ACC:	// Process Login ACCept
3114 	case ELS_PRLI:		// Process Login
3115 	case ELS_PRLO:		// Process Logout
3116 		memset(&PrliPayload, 0, sizeof(PrliPayload));
3117 		prli = &PrliPayload;	// load into stack buffer,
3118 
3119 		if (type == ELS_PRLI)
3120 			prli->cmd = 0x20;	// Login
3121 		else if (type == ELS_PRLO)
3122 			prli->cmd = 0x21;	// Logout
3123 		else if (type == ELS_PRLI_ACC) {
3124 			prli->cmd = 0x02;	// Login ACCept
3125 			prli->valid = REQUEST_EXECUTED;
3126 		}
3127 		prli->valid |= SCSI_FCP | ESTABLISH_PAIR;
3128 		prli->fcp_info = READ_XFER_RDY;
3129 		prli->page_length = 0x10;
3130 		prli->payload_length = 20;
3131 		// Can be initiator AND target
3132 
3133 		if (fcChip->Options.initiator)
3134 			prli->fcp_info |= INITIATOR_FUNCTION;
3135 		if (fcChip->Options.target)
3136 			prli->fcp_info |= TARGET_FUNCTION;
3137 
3138 		BigEndianSwap((u8 *) & PrliPayload, payload, prli->payload_length);
3139 		break;
3140 
3141 	default:		// no can do - programming error
3142 		printk(" BuildLinkServicePayload unknown!\n");
3143 		break;
3144 	}
3145 }
3146 
3147 // loads 8 u8s for PORT name or NODE name base on
3148 // controller's WWN.
LoadWWN(PTACHYON fcChip,u8 * dest,u8 type)3149 void LoadWWN(PTACHYON fcChip, u8 * dest, u8 type)
3150 {
3151 	u8 *bPtr, i;
3152 
3153 	switch (type) {
3154 	case 0:		// Port_Name
3155 		bPtr = (u8 *) & fcChip->Registers.wwn_hi;
3156 		for (i = 0; i < 4; i++)
3157 			dest[i] = *bPtr++;
3158 		bPtr = (u8 *) & fcChip->Registers.wwn_lo;
3159 		for (i = 4; i < 8; i++)
3160 			dest[i] = *bPtr++;
3161 		break;
3162 	case 1:		// Node/Fabric _Name
3163 		bPtr = (u8 *) & fcChip->Registers.wwn_hi;
3164 		for (i = 0; i < 4; i++)
3165 			dest[i] = *bPtr++;
3166 		bPtr = (u8 *) & fcChip->Registers.wwn_lo;
3167 		for (i = 4; i < 8; i++)
3168 			dest[i] = *bPtr++;
3169 		break;
3170 	}
3171 
3172 }
3173 
3174 // We check the Port Login payload for required values.  Note that
3175 // ELS_PLOGI and ELS_PDISC (Port DISCover) use the same payload.
3176 
verify_PLOGI(PTACHYON fcChip,TachFCHDR_GCMND * fchs,u32 * reject_explain)3177 int verify_PLOGI(PTACHYON fcChip, TachFCHDR_GCMND * fchs, u32 * reject_explain)
3178 {
3179 	LOGIN_PAYLOAD login;
3180 
3181 	// source, dest, len (should be mult. of 4)
3182 	BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & login, sizeof(login));
3183 
3184 	// check FC version
3185 	// if other port's highest supported version
3186 	// is less than our lowest, and
3187 	// if other port's lowest
3188 	if (login.cmn_services.highest_ver < fcChip->lowest_FCPH_ver || login.cmn_services.lowest_ver > fcChip->highest_FCPH_ver) {
3189 		*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, OPTIONS_ERROR);
3190 		return LOGICAL_ERROR;
3191 	}
3192 	// Receive Data Field Size must be >=128
3193 	// per FC-PH
3194 	if (login.cmn_services.bb_rx_size < 128) {
3195 		*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, DATA_FIELD_SIZE_ERROR);
3196 		return LOGICAL_ERROR;
3197 	}
3198 	// Only check Class 3 params
3199 	if (login.class3.service_options & CLASS_VALID) {
3200 		if (login.class3.rx_data_size < 128) {
3201 			*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, INVALID_CSP);
3202 			return LOGICAL_ERROR;
3203 		}
3204 		if (login.class3.initiator_control & XID_REQUIRED) {
3205 			*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, INITIATOR_CTL_ERROR);
3206 			return LOGICAL_ERROR;
3207 		}
3208 	}
3209 	return 0;		// success
3210 }
3211 
verify_PRLI(TachFCHDR_GCMND * fchs,u32 * reject_explain)3212 int verify_PRLI(TachFCHDR_GCMND * fchs, u32 * reject_explain)
3213 {
3214 	PRLI_REQUEST prli;	// buffer for BIG ENDIAN
3215 
3216 	// source, dest, len (should be mult. of 4)
3217 	BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & prli, sizeof(prli));
3218 
3219 	if (prli.fcp_info == 0)	// i.e., not target or initiator?
3220 	{
3221 		*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, OPTIONS_ERROR);
3222 		return LOGICAL_ERROR;
3223 	}
3224 
3225 	return 0;		// success
3226 }
3227 
3228 // SWAP u8s as required by Fibre Channel (i.e. BIG ENDIAN)
3229 // INPUTS:
3230 //   source   - ptr to LITTLE ENDIAN u32S
3231 //   cnt      - number of u8s to switch (should be mult. of u32)
3232 // OUTPUTS:
3233 //   dest     - ptr to BIG ENDIAN copy
3234 // RETURN:
3235 //   none
3236 //
BigEndianSwap(u8 * source,u8 * dest,u16 cnt)3237 void BigEndianSwap(u8 * source, u8 * dest, u16 cnt)
3238 {
3239 	int i, j;
3240 
3241 	source += 3;		// start at MSB of 1st u32
3242 	for (j = 0; j < cnt; j += 4, source += 4, dest += 4)	// every u32
3243 	{
3244 		for (i = 0; i < 4; i++)	// every u8 in u32
3245 			*(dest + i) = *(source - i);
3246 	}
3247 }
3248 
3249 // Build FC Exchanges............
3250 
3251 static void buildFCPstatus(PTACHYON fcChip, u32 ExchangeID);
3252 static s32 FindFreeExchange(PTACHYON fcChip, u32 type);
3253 static u32 build_SEST_sgList(struct pci_dev *pcidev, u32 * SESTalPairStart, Scsi_Cmnd * Cmnd, u32 * sgPairs, PSGPAGES * sgPages_head);	// link list of TL Ext. S/G pages from O/S Pool
3254 static int build_FCP_payload(Scsi_Cmnd * Cmnd, u8 * payload, u32 type, u32 fcp_dl);
3255 
3256 /*
3257                              IRB
3258       ERQ           __________________
3259   |          |   / | Req_A_SFS_Len    |        ____________________
3260   |----------|  /  | Req_A_SFS_Addr   |------->|  Reserved         |
3261   |   IRB    | /   | Req_A_D_ID       |        | SOF EOF TimeStamp |
3262   |-----------/    | Req_A_SEST_Index |-+      | R_CTL |   D_ID    |
3263   |   IRB    |     | Req_B...         | |      | CS_CTL|   S_ID    |
3264   |-----------\    |                  | |      | TYPE  |   F_CTL   |
3265   |   IRB    | \   |                  | |      | SEQ_ID  | SEQ_CNT |
3266   |-----------  \  |                  | +-->+--| OX_ID   | RX_ID   |
3267   |          |   \ |__________________|     |  |       RO          |
3268                                             |  | pl (payload/cmnd) |
3269                                             |  |        .....      |
3270                                             |  |___________________|
3271                                             |
3272                                             |
3273 +-------------------------------------------+
3274 |
3275 |
3276 |                        e.g. IWE
3277 |    SEST           __________________             for FCP_DATA
3278 | |          |   / |       | Hdr_Len  |        ____________________
3279 | |----------|  /  |  Hdr_Addr_Addr   |------->|  Reserved         |
3280 | |   [0]    | /   |Remote_ID| RSP_Len|        | SOF EOF TimeStamp |
3281 | |-----------/    |   RSP_Addr       |---+    | R_CTL |   D_ID    |
3282 +->   [1]    |     |       | Buff_Off |   |    | CS_CTL|   S_ID    |
3283   |-----------\    |BuffIndex| Link   |   |    | TYPE  |   F_CTL   |
3284   |   [2]    | \   | Rsvd  |   RX_ID  |   |    | SEQ_ID  | SEQ_CNT |
3285   |-----------  \  |    Data_Len      |   |    | OX_ID   | RX_ID   |
3286   |    ...   |   \ |     Exp_RO       |   |    |       RO          |
3287   |----------|     |   Exp_Byte_Cnt   |   |    |___________________|
3288   | SEST_LEN |  +--|    Len           |   |
3289   |__________|  |  |   Address        |   |
3290                 |  |    ...           |   |         for FCP_RSP
3291                 |  |__________________|   |    ____________________
3292                 |                         +----|  Reserved         |
3293                 |                              | SOF EOF TimeStamp |
3294                 |                              | R_CTL |   D_ID    |
3295                 |                              | CS_CTL|   S_ID    |
3296                 +--- local or extended         |     ....          |
3297                      scatter/gather lists
3298                      defining upper-layer
3299                      data (e.g. from user's App)
3300 
3301 
3302 */
3303 // All TachLite commands must start with a SFS (Single Frame Sequence)
3304 // command.  In the simplest case (a NOP Basic Link command),
3305 // only one frame header and ERQ entry is required.  The most complex
3306 // case is the SCSI assisted command, which requires an ERQ entry,
3307 // SEST entry, and several frame headers and data buffers all
3308 // logically linked together.
3309 // Inputs:
3310 //   dev  - controller struct
3311 //   type          - PLOGI, SCSI_IWE, etc.
3312 //   InFCHS        - Incoming Tachlite FCHS which prompted this exchange
3313 //                   (only s_id set if we are originating)
3314 //   Data          - PVOID to data struct consistent with "type"
3315 //   fcExchangeIndex - pointer to OX/RD ID value of built exchange
3316 // Return:
3317 //   fcExchangeIndex - OX/RD ID value if successful
3318 //   0    - success
3319 //  INVALID_ARGS    - NULL/ invalid passed args
3320 //  BAD_ALPA        - Bad source al_pa address
3321 //  LNKDWN_OSLS     - Link Down (according to this controller)
3322 //  OUTQUE_FULL     - Outbound Que full
3323 //  DRIVERQ_FULL    - controller's Exchange array full
3324 //  SEST_FULL       - SEST table full
3325 //
3326 // Remarks:
3327 // Psuedo code:
3328 // Check for NULL pointers / bad args
3329 // Build outgoing FCHS - the header/payload struct
3330 // Build IRB (for ERQ entry)
3331 // if SCSI command, build SEST entry (e.g. IWE, TRE,...)
3332 // return success
3333 
3334 //sbuildex
cpqfcTSBuildExchange(CPQFCHBA * dev,u32 type,TachFCHDR_GCMND * InFCHS,void * Data,s32 * fcExchangeIndex)3335 u32 cpqfcTSBuildExchange(CPQFCHBA * dev, u32 type,	// e.g. PLOGI
3336 			   TachFCHDR_GCMND * InFCHS,	// incoming FCHS
3337 			   void *Data,	// the CDB, scatter/gather, etc.
3338 			   s32 * fcExchangeIndex)	// points to allocated exchange,
3339 {
3340 	PTACHYON fcChip = &dev->fcChip;
3341 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
3342 	u32 ulStatus = 0;	// assume OK
3343 	u16 ox_ID, rx_ID = 0xFFFF;
3344 	u32 SfsLen = 0L;
3345 	TachLiteIRB *pIRB;
3346 	IRBflags IRB_flags;
3347 	u8 *pIRB_flags = (u8 *) & IRB_flags;
3348 	TachFCHDR_GCMND *CMDfchs;
3349 	TachFCHDR *dataHDR;	// 32 byte HEADER ONLY FCP-DATA buffer
3350 	TachFCHDR_RSP *rspHDR;	// 32 byte header + RSP payload
3351 	Scsi_Cmnd *Cmnd = (Scsi_Cmnd *) Data;	// Linux Scsi CDB, S/G, ...
3352 	TachLiteIWE *pIWE;
3353 	TachLiteIRE *pIRE;
3354 	TachLiteTWE *pTWE;
3355 	TachLiteTRE *pTRE;
3356 	u32 fcp_dl;		// total byte length of DATA transferred
3357 	u32 fl;		// frame length (FC frame size, 128, 256, 512, 1024)
3358 	u32 sgPairs;		// number of valid scatter/gather pairs
3359 	int FCP_SCSI_command;
3360 	BA_ACC_PAYLOAD *ba_acc;
3361 	BA_RJT_PAYLOAD *ba_rjt;
3362 
3363 	// check passed ARGS
3364 	if (!fcChip->ERQ)	// NULL ptr means uninitialized Tachlite chip
3365 		return INVALID_ARGS;
3366 
3367 	if (type == SCSI_IRE || type == SCSI_TRE || type == SCSI_IWE || type == SCSI_TWE)
3368 		FCP_SCSI_command = 1;
3369 	else
3370 		FCP_SCSI_command = 0;
3371 
3372 	// for commands that pass payload data (e.g. SCSI write)
3373 	// examine command struct - verify that the
3374 	// length of s/g buffers is adequate for total payload
3375 	// length (end of list is NULL address)
3376 
3377 	if (FCP_SCSI_command) {
3378 		if (Data)	// must have data descriptor (S/G list -- at least
3379 			// one address with at least 1 byte of data)
3380 		{
3381 			// something to do (later)?
3382 		}
3383 		else
3384 			return INVALID_ARGS;	// invalid DATA ptr
3385 	}
3386 
3387 	// we can build an Exchange for later Queuing (on the TL chip)
3388 	// if an empty slot is available in the DevExt for this controller
3389 	// look for available Exchange slot...
3390 
3391 	if (type != FCP_RESPONSE && type != BLS_ABTS && type != BLS_ABTS_ACC)	// already have Exchange slot!
3392 		*fcExchangeIndex = FindFreeExchange(fcChip, type);
3393 
3394 	if (*fcExchangeIndex != -1)	// Exchange is available?
3395 	{
3396 		// assign tmp ptr (shorthand)
3397 		CMDfchs = &Exchanges->fcExchange[*fcExchangeIndex].fchs;
3398 
3399 		if (Cmnd != NULL)	// (necessary for ABTS cases)
3400 		{
3401 			Exchanges->fcExchange[*fcExchangeIndex].Cmnd = Cmnd;	// Linux Scsi
3402 			Exchanges->fcExchange[*fcExchangeIndex].pLoggedInPort = fcFindLoggedInPort(fcChip, Exchanges->fcExchange[*fcExchangeIndex].Cmnd,	// find Scsi Nexus
3403 												   0,	// DON'T search linked list for FC port id
3404 												   NULL,	// DON'T search linked list for FC WWN
3405 												   NULL);	// DON'T care about end of list
3406 		}
3407 
3408 		// Build the command frame header (& data) according
3409 		// to command type
3410 
3411 		// fields common for all SFS frame types
3412 		CMDfchs->reserved = 0L;	// must clear
3413 		CMDfchs->sof_eof = 0x75000000L;	// SOFi3:EOFn  no UAM; LCr=0, no TS
3414 
3415 		// get the destination port_id from incoming FCHS
3416 		// (initialized before calling if we're Originator)
3417 		// Frame goes to port it was from - the source_id
3418 
3419 		CMDfchs->d_id = InFCHS->s_id & 0xFFFFFF;	// destination (add R_CTL later)
3420 		CMDfchs->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
3421 
3422 		// now enter command-specific fields
3423 		switch (type) {
3424 		case BLS_NOP:	// FC defined basic link service command NO-OP
3425 			// ensure unique X_IDs! (use tracking function)
3426 			*pIRB_flags = 0;	// clear IRB flags
3427 			IRB_flags.SFA = 1;	// send SFS (not SEST index)
3428 			SfsLen = *pIRB_flags;
3429 
3430 			SfsLen <<= 24;	// shift flags to MSB
3431 			SfsLen += 32L;	// add len to LSB (header only - no payload)
3432 
3433 			// TYPE[31-24] 00 Basic Link Service
3434 			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
3435 			CMDfchs->d_id |= 0x80000000L;	// R_CTL = 80 for NOP (Basic Link Ser.)
3436 			CMDfchs->f_ctl = 0x00310000L;	// xchng originator, 1st seq,....
3437 			CMDfchs->seq_cnt = 0x0L;
3438 			CMDfchs->ox_rx_id = 0xFFFF;	// RX_ID for now; OX_ID on start
3439 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3440 			CMDfchs->pl[0] = 0xaabbccddL;	// words 8-15 frame data payload (n/a)
3441 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 1;	// seconds
3442 			// (NOP should complete ~instantly)
3443 			break;
3444 
3445 		case BLS_ABTS_ACC:	// Abort Sequence ACCept
3446 			*pIRB_flags = 0;	// clear IRB flags
3447 			IRB_flags.SFA = 1;	// send SFS (not SEST index)
3448 			SfsLen = *pIRB_flags;
3449 
3450 			SfsLen <<= 24;	// shift flags to MSB
3451 			SfsLen += 32 + 12;	// add len to LSB (header + 3 DWORD payload)
3452 
3453 			CMDfchs->d_id |= 0x84000000L;	// R_CTL = 84 for BASIC ACCept
3454 			// TYPE[31-24] 00 Basic Link Service
3455 			// f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
3456 			CMDfchs->f_ctl = 0x00910000L;	// xchnge responder, last seq, xfer SI
3457 			// CMDfchs->seq_id & count might be set from DataHdr?
3458 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3459 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 5;	// seconds
3460 			// (Timeout in case of weird error)
3461 
3462 			// now set the ACCept payload...
3463 			ba_acc = (BA_ACC_PAYLOAD *) & CMDfchs->pl[0];
3464 			memset(ba_acc, 0, sizeof(BA_ACC_PAYLOAD));
3465 			// Since PLDA requires (only) entire Exchange aborts, we don't need
3466 			// to worry about what the last sequence was.
3467 
3468 			// We expect that a "target" task is accepting the abort, so we
3469 			// can use the OX/RX ID pair
3470 			ba_acc->ox_rx_id = CMDfchs->ox_rx_id;
3471 
3472 			// source, dest, #bytes
3473 			BigEndianSwap((u8 *) & CMDfchs->ox_rx_id, (u8 *) & ba_acc->ox_rx_id, 4);
3474 
3475 			ba_acc->low_seq_cnt = 0;
3476 			ba_acc->high_seq_cnt = 0xFFFF;
3477 			break;
3478 
3479 		case BLS_ABTS_RJT:	// Abort Sequence ACCept
3480 			*pIRB_flags = 0;	// clear IRB flags
3481 			IRB_flags.SFA = 1;	// send SFS (not SEST index)
3482 			SfsLen = *pIRB_flags;
3483 
3484 			SfsLen <<= 24;	// shift flags to MSB
3485 			SfsLen += 32 + 12;	// add len to LSB (header + 3 DWORD payload)
3486 
3487 			CMDfchs->d_id |= 0x85000000L;	// R_CTL = 85 for BASIC ReJecT
3488 			// f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
3489 			// TYPE[31-24] 00 Basic Link Service
3490 			CMDfchs->f_ctl = 0x00910000L;	// xchnge responder, last seq, xfer SI
3491 			// CMDfchs->seq_id & count might be set from DataHdr?
3492 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3493 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 5;	// seconds
3494 			// (Timeout in case of weird error)
3495 
3496 			CMDfchs->ox_rx_id = InFCHS->ox_rx_id;	// copy from sender!
3497 
3498 			// now set the ReJecT payload...
3499 			ba_rjt = (BA_RJT_PAYLOAD *) & CMDfchs->pl[0];
3500 			memset(ba_rjt, 0, sizeof(BA_RJT_PAYLOAD));
3501 
3502 			// We expect that a "target" task couldn't find the Exhange in the
3503 			// array of active exchanges, so we use a new LinkService X_ID.
3504 			// See Reject payload description in FC-PH (Rev 4.3), pg. 140
3505 			ba_rjt->reason_code = 0x09;	// "unable to perform command request"
3506 			ba_rjt->reason_explain = 0x03;	// invalid OX/RX ID pair
3507 			break;
3508 
3509 		case BLS_ABTS:	// FC defined basic link service command ABTS
3510 			// Abort Sequence
3511 			*pIRB_flags = 0;	// clear IRB flags
3512 			IRB_flags.SFA = 1;	// send SFS (not SEST index)
3513 			SfsLen = *pIRB_flags;
3514 
3515 			SfsLen <<= 24;	// shift flags to MSB
3516 			SfsLen += 32L;	// add len to LSB (header only - no payload)
3517 
3518 			// TYPE[31-24] 00 Basic Link Service
3519 			// f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
3520 			CMDfchs->d_id |= 0x81000000L;	// R_CTL = 81 for ABTS
3521 			CMDfchs->f_ctl = 0x00110000L;	// xchnge originator, last seq, xfer SI
3522 			// CMDfchs->seq_id & count might be set from DataHdr?
3523 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3524 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 2;	// seconds
3525 			// (ABTS must timeout when responder is gone)
3526 			break;
3527 
3528 		case FCS_NSR:	// Fabric Name Service Request
3529 			Exchanges->fcExchange[*fcExchangeIndex].reTries = 2;
3530 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 2;	// seconds
3531 			// OX_ID, linked to Driver Transaction ID
3532 			// (fix-up at Queing time)
3533 			CMDfchs->ox_rx_id = 0xFFFF;	// RX_ID - Responder (target) to modify
3534 			// OX_ID set at ERQueing time
3535 			*pIRB_flags = 0;	// clear IRB flags
3536 			IRB_flags.SFA = 1;	// send SFS (not SEST index)
3537 			SfsLen = *pIRB_flags;
3538 			SfsLen <<= 24;	// shift flags to MSB
3539 			SfsLen += (32L + sizeof(NSR_PL));	// add len (header & NSR payload)
3540 			CMDfchs->d_id |= 0x02000000L;	// R_CTL = 02 for -
3541 			// Name Service Request: Unsolicited
3542 			// TYPE[31-24] 01 Extended Link Service
3543 			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
3544 			CMDfchs->f_ctl = 0x20210000L;
3545 			// OX_ID will be fixed-up at Tachyon enqueing time
3546 			CMDfchs->seq_cnt = 0;	// seq ID, DF_ctl, seq cnt
3547 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3548 			BuildLinkServicePayload(fcChip, type, &CMDfchs->pl[0]);
3549 			break;
3550 
3551 		case ELS_PLOGI:	// FC-PH extended link service command Port Login
3552 			// (May, 2000)
3553 			// NOTE! This special case facilitates SANMark testing.  The SANMark
3554 			// test script for initialization-timeout.fcal.SANMark-1.fc
3555 			// "eats" the OPN() primitive without issuing an R_RDY, causing
3556 			// Tachyon to report LST (loop state timeout), which causes a
3557 			// LIP.  To avoid this, simply send out the frame (i.e. assuming a
3558 			// buffer credit of 1) without waiting for R_RDY.  Many FC devices
3559 			// (other than Tachyon) have been doing this for years.  We don't
3560 			// ever want to do this for non-Link Service frames unless the
3561 			// other device really did report non-zero login BB credit (i.e.
3562 			// in the PLOGI ACCept frame).
3563 //			CMDfchs->sof_eof |= 0x00000400L;  // LCr=1
3564 
3565 		case ELS_FDISC:	// Fabric Discovery (Login)
3566 		case ELS_FLOGI:	// Fabric Login
3567 		case ELS_SCR:	// Fabric State Change Registration
3568 		case ELS_LOGO:	// FC-PH extended link service command Port Logout
3569 		case ELS_PDISC:	// FC-PH extended link service cmnd Port Discovery
3570 		case ELS_PRLI:	// FC-PH extended link service cmnd Process Login
3571 			Exchanges->fcExchange[*fcExchangeIndex].reTries = 2;
3572 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 2;	// seconds
3573 			// OX_ID, linked to Driver Transaction ID
3574 			// (fix-up at Queing time)
3575 			CMDfchs->ox_rx_id = 0xFFFF;	// RX_ID - Responder (target) to modify
3576 			// OX_ID set at ERQueing time
3577 			*pIRB_flags = 0;	// clear IRB flags
3578 			IRB_flags.SFA = 1;	// send SFS (not SEST index)
3579 			SfsLen = *pIRB_flags;
3580 			SfsLen <<= 24;	// shift flags to MSB
3581 			if (type == ELS_LOGO)
3582 				SfsLen += (32L + 16L);	//  add len (header & PLOGI payload)
3583 			else if (type == ELS_PRLI)
3584 				SfsLen += (32L + 20L);	//  add len (header & PRLI payload)
3585 			else if (type == ELS_SCR)
3586 				SfsLen += (32L + sizeof(SCR_PL));	//  add len (header & SCR payload)
3587 			else
3588 				SfsLen += (32L + 116L);	//  add len (header & PLOGI payload)
3589 
3590 			CMDfchs->d_id |= 0x22000000L;	// R_CTL = 22 for -
3591 			// Extended Link_Data: Unsolicited Control
3592 			// TYPE[31-24] 01 Extended Link Service
3593 			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
3594 			CMDfchs->f_ctl = 0x01210000L;
3595 			// OX_ID will be fixed-up at Tachyon enqueing time
3596 			CMDfchs->seq_cnt = 0;	// seq ID, DF_ctl, seq cnt
3597 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3598 
3599 			BuildLinkServicePayload(fcChip, type, &CMDfchs->pl[0]);
3600 			break;
3601 
3602 		case ELS_LOGO_ACC:	// FC-PH extended link service logout accept
3603 		case ELS_RJT:	// extended link service reject (add reason)
3604 		case ELS_ACC:	// ext. link service generic accept
3605 		case ELS_PLOGI_ACC:	// ext. link service login accept (PLOGI or PDISC)
3606 		case ELS_PRLI_ACC:	// ext. link service process login accept
3607 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 1;	// assume done
3608 			// ensure unique X_IDs! (use tracking function)
3609 			// OX_ID from initiator cmd
3610 			ox_ID = (u16) (InFCHS->ox_rx_id >> 16);
3611 			rx_ID = 0xFFFF;	// RX_ID, linked to Driver Exchange ID
3612 
3613 			*pIRB_flags = 0;	// clear IRB flags
3614 			IRB_flags.SFA = 1;	// send SFS (not SEST index)
3615 			SfsLen = *pIRB_flags;
3616 
3617 			SfsLen <<= 24;	// shift flags to MSB
3618 			if (type == ELS_RJT) {
3619 				SfsLen += (32L + 8L);	//  add len (header + payload)
3620 
3621 				// ELS_RJT reason codes (utilize unused "reserved" field)
3622 				CMDfchs->pl[0] = 1;
3623 				CMDfchs->pl[1] = InFCHS->reserved;
3624 
3625 			} else if ((type == ELS_LOGO_ACC) || (type == ELS_ACC))
3626 				SfsLen += (32L + 4L);	//  add len (header + payload)
3627 			else if (type == ELS_PLOGI_ACC)
3628 				SfsLen += (32L + 116L);	//  add len (header + payload)
3629 			else if (type == ELS_PRLI_ACC)
3630 				SfsLen += (32L + 20L);	//  add len (header + payload)
3631 
3632 			CMDfchs->d_id |= 0x23000000L;	// R_CTL = 23 for -
3633 			// Extended Link_Data: Control Reply
3634 			// TYPE[31-24] 01 Extended Link Service
3635 			// f_ctl[23:0] exchg responder, last seq, e_s, tsi
3636 			CMDfchs->f_ctl = 0x01990000L;
3637 			CMDfchs->seq_cnt = 0x0L;
3638 			CMDfchs->ox_rx_id = 0L;	// clear
3639 			CMDfchs->ox_rx_id = ox_ID;	// load upper 16 bits
3640 			CMDfchs->ox_rx_id <<= 16;	// shift them
3641 
3642 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3643 
3644 			BuildLinkServicePayload(fcChip, type, &CMDfchs->pl[0]);
3645 			break;
3646 
3647 			// Fibre Channel SCSI 'originator' sequences...
3648 			// (originator means 'initiator' in FCP-SCSI)
3649 		case SCSI_IWE:	// TachLite Initiator Write Entry
3650 			{
3651 				PFC_LOGGEDIN_PORT pLoggedInPort = Exchanges->fcExchange[*fcExchangeIndex].pLoggedInPort;
3652 
3653 				Exchanges->fcExchange[*fcExchangeIndex].reTries = 1;
3654 				Exchanges->fcExchange[*fcExchangeIndex].timeOut = 7;	// FC2 timeout
3655 
3656 				// first, build FCP_CMND
3657 				// unique X_ID fix-ups in StartExchange
3658 
3659 				*pIRB_flags = 0;	// clear IRB flags
3660 				IRB_flags.SFA = 1;	// send SFS FCP-CMND (not SEST index)
3661 
3662 				// NOTE: unlike FC LinkService login frames, normal
3663 				// SCSI commands are sent without outgoing verification
3664 				IRB_flags.DCM = 1;	// Disable completion message for Cmnd frame
3665 				SfsLen = *pIRB_flags;
3666 
3667 				SfsLen <<= 24;	// shift flags to MSB
3668 				SfsLen += 64L;	// add len to LSB (header & CMND payload)
3669 
3670 				CMDfchs->d_id |= (0x06000000L);	// R_CTL = 6 for command
3671 
3672 				// TYPE[31-24] 8 for FCP SCSI
3673 				// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
3674 				//             valid RO
3675 				CMDfchs->f_ctl = 0x08210008L;
3676 				CMDfchs->seq_cnt = 0x0L;
3677 				CMDfchs->ox_rx_id = 0L;	// clear for now (-or- in later)
3678 				CMDfchs->ro = 0x0L;	// relative offset (n/a)
3679 
3680 				// now, fill out FCP-DATA header
3681 				// (use buffer inside SEST object)
3682 				dataHDR = &fcChip->SEST->DataHDR[*fcExchangeIndex];
3683 				dataHDR->reserved = 0L;	// must clear
3684 				dataHDR->sof_eof = 0x75002000L;	// SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
3685 				dataHDR->d_id = (InFCHS->s_id | 0x01000000L);	// R_CTL= FCP_DATA
3686 				dataHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
3687 				// TYPE[31-24] 8 for FCP SCSI
3688 				// f_ctl[23:0] xfer S.I.| valid RO
3689 				dataHDR->f_ctl = 0x08010008L;
3690 				dataHDR->seq_cnt = 0x02000000L;	// sequence ID: df_ctl : seqence count
3691 				dataHDR->ox_rx_id = 0L;	// clear; fix-up dataHDR fields later
3692 				dataHDR->ro = 0x0L;	// relative offset (n/a)
3693 
3694 				// Now setup the SEST entry
3695 				pIWE = &fcChip->SEST->u[*fcExchangeIndex].IWE;
3696 
3697 				// fill out the IWE:
3698 
3699 				// VALid entry:Dir outbound:DCM:enable CM:enal INT: FC frame len
3700 				pIWE->Hdr_Len = 0x8e000020L;	// data frame Len always 32 bytes
3701 
3702 
3703 				// from login parameters with other port, what's the largest frame
3704 				// we can send?
3705 				if (pLoggedInPort == NULL) {
3706 					ulStatus = INVALID_ARGS;	// failed! give up
3707 					break;
3708 				}
3709 				if (pLoggedInPort->rx_data_size >= 2048)
3710 					fl = 0x00020000;	// 2048 code (only support 1024!)
3711 				else if (pLoggedInPort->rx_data_size >= 1024)
3712 					fl = 0x00020000;	// 1024 code
3713 				else if (pLoggedInPort->rx_data_size >= 512)
3714 					fl = 0x00010000;	// 512 code
3715 				else
3716 					fl = 0;	// 128 bytes -- should never happen
3717 
3718 
3719 				pIWE->Hdr_Len |= fl;	// add xmit FC frame len for data phase
3720 				pIWE->Hdr_Addr = fcChip->SEST->base + ((unsigned long) &fcChip->SEST->DataHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
3721 
3722 				pIWE->RSP_Len = sizeof(TachFCHDR_RSP);	// hdr+data (recv'd RSP frame)
3723 				pIWE->RSP_Len |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
3724 
3725 				memset(&fcChip->SEST->RspHDR[*fcExchangeIndex].pl, 0, sizeof(FCP_STATUS_RESPONSE));	// clear out previous status
3726 
3727 				pIWE->RSP_Addr = fcChip->SEST->base + ((unsigned long) &fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
3728 
3729 				// Do we need local or extended gather list?
3730 				// depends on size - we can handle 3 len/addr pairs
3731 				// locally.
3732 
3733 				fcp_dl = build_SEST_sgList(dev->PciDev, &pIWE->GLen1, Cmnd,	// S/G list
3734 							   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
3735 							   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
3736 
3737 				if (!fcp_dl)	// error building S/G list?
3738 				{
3739 					ulStatus = MEMPOOL_FAIL;
3740 					break;	// give up
3741 				}
3742 				// Now that we know total data length in
3743 				// the passed S/G buffer, set FCP CMND frame
3744 				build_FCP_payload(Cmnd, (u8 *) & CMDfchs->pl[0], type, fcp_dl);
3745 
3746 
3747 
3748 				if (sgPairs > 3)	// need extended s/g list
3749 					pIWE->Buff_Off = 0x78000000L;	// extended data | (no offset)
3750 				else	// local data pointers (in SEST)
3751 					pIWE->Buff_Off = 0xf8000000L;	// local data | (no offset)
3752 
3753 				// u32 5
3754 				pIWE->Link = 0x0000ffffL;	// Buff_Index | Link
3755 
3756 				pIWE->RX_ID = 0x0L;	// DWord 6: RX_ID set by target XFER_RDY
3757 
3758 				// DWord 7
3759 				pIWE->Data_Len = 0L;	// TL enters rcv'd XFER_RDY BURST_LEN
3760 				pIWE->Exp_RO = 0L;	// DWord 8
3761 				// DWord 9
3762 				pIWE->Exp_Byte_Cnt = fcp_dl;	// sum of gather buffers
3763 			}
3764 			break;
3765 
3766 		case SCSI_IRE:	// TachLite Initiator Read Entry
3767 			if (Cmnd->timeout != 0) {
3768 //      printk("Cmnd->timeout %d\n", Cmnd->timeout);
3769 				// per Linux Scsi
3770 				Exchanges->fcExchange[*fcExchangeIndex].timeOut = Cmnd->timeout;
3771 			} else	// use our best guess, based on FC & device
3772 			{
3773 
3774 				if (Cmnd->SCp.Message == 1)	// Tape device? (from INQUIRY)
3775 				{
3776 					// turn off our timeouts (for now...)
3777 					Exchanges->fcExchange[*fcExchangeIndex].timeOut = 0xFFFFFFFF;
3778 				} else {
3779 					Exchanges->fcExchange[*fcExchangeIndex].reTries = 1;
3780 					Exchanges->fcExchange[*fcExchangeIndex].timeOut = 7;	// per SCSI req.
3781 				}
3782 			}
3783 			// first, build FCP_CMND
3784 			*pIRB_flags = 0;	// clear IRB flags
3785 			IRB_flags.SFA = 1;	// send SFS FCP-CMND (not SEST index)
3786 			// NOTE: unlike FC LinkService login frames,
3787 			// normal SCSI commands are sent "open loop"
3788 			IRB_flags.DCM = 1;	// Disable completion message for Cmnd frame
3789 			SfsLen = *pIRB_flags;
3790 
3791 			SfsLen <<= 24;	// shift flags to MSB
3792 			SfsLen += 64L;	// add len to LSB (header & CMND payload)
3793 
3794 			CMDfchs->d_id |= (0x06000000L);	// R_CTL = 6 for command
3795 
3796 			// TYPE[31-24] 8 for FCP SCSI
3797 			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
3798 			//             valid RO
3799 			CMDfchs->f_ctl = 0x08210008L;
3800 			CMDfchs->seq_cnt = 0x0L;
3801 			// x_ID & data direction bit set later
3802 			CMDfchs->ox_rx_id = 0xFFFF;	// clear
3803 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3804 			// Now setup the SEST entry
3805 			pIRE = &fcChip->SEST->u[*fcExchangeIndex].IRE;
3806 			// fill out the IRE:
3807 			// VALid entry:Dir outbound:enable CM:enal INT:
3808 			pIRE->Seq_Accum = 0xCE000000L;	// VAL,DIR inbound,DCM| INI,DAT,RSP
3809 
3810 			pIRE->reserved = 0L;
3811 			pIRE->RSP_Len = sizeof(TachFCHDR_RSP);	// hdr+data (recv'd RSP frame)
3812 			pIRE->RSP_Len |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
3813 
3814 			pIRE->RSP_Addr = fcChip->SEST->base + ((unsigned long) &fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
3815 
3816 			// Do we need local or extended gather list?
3817 			// depends on size - we can handle 3 len/addr pairs
3818 			// locally.
3819 
3820 			fcp_dl = build_SEST_sgList(dev->PciDev, &pIRE->SLen1, Cmnd,	// SCSI command Data desc. with S/G list
3821 						   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
3822 						   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
3823 
3824 
3825 			if (!fcp_dl)	// error building S/G list?
3826 			{
3827 				// It is permissible to have a ZERO LENGTH Read command.
3828 				// If there is the case, simply set fcp_dl (and Exp_Byte_Cnt)
3829 				// to 0 and continue.
3830 				if (Cmnd->request_bufflen == 0) {
3831 					fcp_dl = 0;	// no FC DATA frames expected
3832 
3833 				} else {
3834 					ulStatus = MEMPOOL_FAIL;
3835 					break;	// give up
3836 				}
3837 			}
3838 			// now that we know the S/G length, build CMND payload
3839 			build_FCP_payload(Cmnd, (u8 *) & CMDfchs->pl[0], type, fcp_dl);
3840 
3841 
3842 			if (sgPairs > 3)	// need extended s/g list
3843 				pIRE->Buff_Off = 0x00000000;	// DWord 4: extended s/g list, no offset
3844 			else
3845 				pIRE->Buff_Off = 0x80000000;	// local data, no offset
3846 
3847 			pIRE->Buff_Index = 0x0L;	// DWord 5: Buff_Index | Reserved
3848 
3849 			pIRE->Exp_RO = 0x0L;	// DWord 6: Expected Rel. Offset
3850 
3851 			pIRE->Byte_Count = 0;	// DWord 7: filled in by TL on err
3852 			pIRE->reserved_ = 0;	// DWord 8: reserved
3853 			// NOTE: 0 length READ is OK.
3854 			pIRE->Exp_Byte_Cnt = fcp_dl;	// DWord 9: sum of scatter buffers
3855 			break;
3856 
3857 			// Fibre Channel SCSI 'responder' sequences...
3858 			// (originator means 'target' in FCP-SCSI)
3859 		case SCSI_TWE:	// TachLite Target Write Entry
3860 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 10;	// per SCSI req.
3861 			// first, build FCP_CMND
3862 			*pIRB_flags = 0;	// clear IRB flags
3863 			IRB_flags.SFA = 1;	// send SFS (XFER_RDY)
3864 			SfsLen = *pIRB_flags;
3865 			SfsLen <<= 24;	// shift flags to MSB
3866 			SfsLen += (32L + 12L);	// add SFS len (header & XFER_RDY payload)
3867 
3868 			CMDfchs->d_id |= (0x05000000L);	// R_CTL = 5 for XFER_RDY
3869 
3870 			// TYPE[31-24] 8 for FCP SCSI
3871 			// f_ctl[23:0] exchg responder, 1st seq, xfer S.I.
3872 			//             valid RO
3873 			CMDfchs->f_ctl = 0x08810008L;
3874 			CMDfchs->seq_cnt = 0x01000000;	// sequence ID: df_ctl: sequence count
3875 			// use originator (other port's) OX_ID
3876 			CMDfchs->ox_rx_id = InFCHS->ox_rx_id;	// we want upper 16 bits
3877 			CMDfchs->ro = 0x0L;	// relative offset (n/a)
3878 
3879 			// now, fill out FCP-RSP header
3880 			// (use buffer inside SEST object)
3881 
3882 			rspHDR = &fcChip->SEST->RspHDR[*fcExchangeIndex];
3883 			rspHDR->reserved = 0L;	// must clear
3884 			rspHDR->sof_eof = 0x75000000L;	// SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
3885 			rspHDR->d_id = (InFCHS->s_id | 0x07000000L);	// R_CTL= FCP_RSP
3886 			rspHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
3887 			// TYPE[31-24] 8 for FCP SCSI
3888 			// f_ctl[23:0] responder|last seq| xfer S.I.
3889 			rspHDR->f_ctl = 0x08910000L;
3890 			rspHDR->seq_cnt = 0x03000000;	// sequence ID
3891 			rspHDR->ox_rx_id = InFCHS->ox_rx_id;	// gives us OX_ID
3892 			rspHDR->ro = 0x0L;	// relative offset (n/a)
3893 			// Now setup the SEST entry
3894 
3895 			pTWE = &fcChip->SEST->u[*fcExchangeIndex].TWE;
3896 			// fill out the TWE:
3897 
3898 			// VALid entry:Dir outbound:enable CM:enal INT:
3899 			pTWE->Seq_Accum = 0xC4000000L;	// upper word flags
3900 			pTWE->reserved = 0L;
3901 			pTWE->Remote_Node_ID = 0L;	// no more auto RSP frame! (TL/TS change)
3902 			pTWE->Remote_Node_ID |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
3903 
3904 			// Do we need local or extended gather list?
3905 			// depends on size - we can handle 3 len/addr pairs
3906 			// locally.
3907 
3908 			fcp_dl = build_SEST_sgList(dev->PciDev, &pTWE->SLen1, Cmnd,	// S/G list
3909 						   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
3910 						   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
3911 
3912 			if (!fcp_dl)	// error building S/G list?
3913 			{
3914 				ulStatus = MEMPOOL_FAIL;
3915 				break;	// give up
3916 			}
3917 			// now that we know the S/G length, build CMND payload
3918 			build_FCP_payload(Cmnd, (u8 *) & CMDfchs->pl[0], type, fcp_dl);
3919 
3920 			if (sgPairs > 3)	// need extended s/g list
3921 				pTWE->Buff_Off = 0x00000000;	// extended s/g list, no offset
3922 			else
3923 				pTWE->Buff_Off = 0x80000000;	// local data, no offset
3924 
3925 			pTWE->Buff_Index = 0;	// Buff_Index | Link
3926 			pTWE->Exp_RO = 0;
3927 			pTWE->Byte_Count = 0;	// filled in by TL on err
3928 			pTWE->reserved_ = 0;
3929 			pTWE->Exp_Byte_Cnt = fcp_dl;	// sum of scatter buffers
3930 			break;
3931 
3932 		case SCSI_TRE:	// TachLite Target Read Entry
3933 			// It doesn't make much sense for us to "time-out" a READ,
3934 			// but we'll use it for design consistency and internal error recovery.
3935 			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 10;	// per SCSI req.
3936 			// I/O request block settings...
3937 			*pIRB_flags = 0;	// clear IRB flags
3938 			// check PRLI (process login) info
3939 			// to see if Initiator Requires XFER_RDY
3940 			// if not, don't send one!
3941 			// { PRLI check...}
3942 			IRB_flags.SFA = 0;	// don't send XFER_RDY - start data
3943 			SfsLen = *pIRB_flags;
3944 			SfsLen <<= 24;	// shift flags to MSB
3945 			SfsLen += (32L + 12L);	// add SFS len (header & XFER_RDY payload)
3946 
3947 			// now, fill out FCP-DATA header
3948 			// (use buffer inside SEST object)
3949 			dataHDR = &fcChip->SEST->DataHDR[*fcExchangeIndex];
3950 
3951 			dataHDR->reserved = 0L;	// must clear
3952 			dataHDR->sof_eof = 0x75000000L;	// SOFi3:EOFn no UAM; no CLS,noLCr,no TS
3953 			dataHDR->d_id = (InFCHS->s_id | 0x01000000L);	// R_CTL= FCP_DATA
3954 			dataHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
3955 
3956 			// TYPE[31-24] 8 for FCP SCSI
3957 			// f_ctl[23:0] exchg responder, not 1st seq, xfer S.I.
3958 			//             valid RO
3959 			dataHDR->f_ctl = 0x08810008L;
3960 			dataHDR->seq_cnt = 0x01000000;	// sequence ID (no XRDY)
3961 			dataHDR->ox_rx_id = InFCHS->ox_rx_id & 0xFFFF0000;	// we want upper 16 bits
3962 			dataHDR->ro = 0x0L;	// relative offset (n/a)
3963 
3964 			// now, fill out FCP-RSP header
3965 			// (use buffer inside SEST object)
3966 			rspHDR = &fcChip->SEST->RspHDR[*fcExchangeIndex];
3967 
3968 			rspHDR->reserved = 0L;	// must clear
3969 			rspHDR->sof_eof = 0x75000000L;	// SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
3970 			rspHDR->d_id = (InFCHS->s_id | 0x07000000L);	// R_CTL= FCP_RSP
3971 			rspHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
3972 			// TYPE[31-24] 8 for FCP SCSI
3973 			// f_ctl[23:0] responder|last seq| xfer S.I.
3974 			rspHDR->f_ctl = 0x08910000L;
3975 			rspHDR->seq_cnt = 0x02000000;	// sequence ID: df_ctl: sequence count
3976 			rspHDR->ro = 0x0L;	// relative offset (n/a)
3977 
3978 			// Now setup the SEST entry
3979 			pTRE = &fcChip->SEST->u[*fcExchangeIndex].TRE;
3980 
3981 			// VALid entry:Dir outbound:enable CM:enal INT:
3982 			pTRE->Hdr_Len = 0x86010020L;	// data frame Len always 32 bytes
3983 			pTRE->Hdr_Addr =	// bus address of dataHDR;
3984 			    fcChip->SEST->base + ((unsigned long) &fcChip->SEST->DataHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
3985 
3986 			pTRE->RSP_Len = 64L;	// hdr+data (TL assisted RSP frame)
3987 			pTRE->RSP_Len |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
3988 			pTRE->RSP_Addr =	// bus address of rspHDR
3989 			    fcChip->SEST->base + ((unsigned long) &fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
3990 
3991 			// Do we need local or extended gather list?
3992 			// depends on size - we can handle 3 len/addr pairs
3993 			// locally.
3994 
3995 			fcp_dl = build_SEST_sgList(dev->PciDev, &pTRE->GLen1, Cmnd,	// S/G list
3996 						   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
3997 						   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
3998 
3999 			if (!fcp_dl)	// error building S/G list?
4000 			{
4001 				ulStatus = MEMPOOL_FAIL;
4002 				break;	// give up
4003 			}
4004 			// no payload or command to build -- READ doesn't need XRDY
4005 			if (sgPairs > 3)	// need extended s/g list
4006 				pTRE->Buff_Off = 0x78000000L;	// extended data | (no offset)
4007 			else	// local data pointers (in SEST)
4008 				pTRE->Buff_Off = 0xf8000000L;	// local data | (no offset)
4009 
4010 			// u32 5
4011 			pTRE->Buff_Index = 0L;	// Buff_Index | reserved
4012 			pTRE->reserved = 0x0L;	// DWord 6
4013 
4014 			// DWord 7: NOTE: zero length will
4015 			// hang TachLite!
4016 			pTRE->Data_Len = fcp_dl;	// e.g. sum of scatter buffers
4017 
4018 			pTRE->reserved_ = 0L;	// DWord 8
4019 			pTRE->reserved__ = 0L;	// DWord 9
4020 
4021 			break;
4022 
4023 		case FCP_RESPONSE:
4024 			// Target response frame: this sequence uses an OX/RX ID
4025 			// pair from a completed SEST exchange.  We built most
4026 			// of the response frame when we created the TWE/TRE.
4027 
4028 			*pIRB_flags = 0;	// clear IRB flags
4029 			IRB_flags.SFA = 1;	// send SFS (RSP)
4030 			SfsLen = *pIRB_flags;
4031 
4032 			SfsLen <<= 24;	// shift flags to MSB
4033 			SfsLen += sizeof(TachFCHDR_RSP);	// add SFS len (header & RSP payload)
4034 			Exchanges->fcExchange[*fcExchangeIndex].type = FCP_RESPONSE;	// change Exchange type to "response" phase
4035 
4036 			// take advantage of prior knowledge of OX/RX_ID pair from
4037 			// previous XFER outbound frame (still in fchs of exchange)
4038 			fcChip->SEST->RspHDR[*fcExchangeIndex].ox_rx_id = CMDfchs->ox_rx_id;
4039 
4040 			// Check the status of the DATA phase of the exchange so we can report
4041 			// status to the initiator
4042 			buildFCPstatus(fcChip, *fcExchangeIndex);	// set RSP payload fields
4043 
4044 			memcpy(CMDfchs,	// re-use same XFER fchs for Response frame
4045 			       &fcChip->SEST->RspHDR[*fcExchangeIndex], sizeof(TachFCHDR_RSP));
4046 			break;
4047 
4048 		default:
4049 			printk("cpqfcTS: don't know how to build FC type: %Xh(%d)\n", type, type);
4050 			break;
4051 		}
4052 		if (!ulStatus)	// no errors above?
4053 		{
4054 			// FCHS is built; now build IRB
4055 
4056 			// link the just built FCHS (the "command") to the IRB entry
4057 			// for this Exchange.
4058 			pIRB = &Exchanges->fcExchange[*fcExchangeIndex].IRB;
4059 
4060 			// len & flags according to command type above
4061 			pIRB->Req_A_SFS_Len = SfsLen;	// includes IRB flags & len
4062 			pIRB->Req_A_SFS_Addr =	// TL needs physical addr of frame to send
4063 			    fcChip->exch_dma_handle + (unsigned long) CMDfchs - (unsigned long) Exchanges;
4064 
4065 			pIRB->Req_A_SFS_D_ID = CMDfchs->d_id << 8;	// Dest_ID must be consistent!
4066 
4067 			// Exchange is complete except for "fix-up" fields to be set
4068 			// at Tachyon Queuing time:
4069 			//    IRB->Req_A_Trans_ID (OX_ID/ RX_ID):
4070 			//        for SEST entry, lower bits correspond to actual FC Exchange ID
4071 			//    fchs->OX_ID or RX_ID
4072 		} else {
4073 #ifdef DBG
4074 			printk("FC Error: SEST build Pool Allocation failed\n");
4075 #endif
4076 			// return resources...
4077 			cpqfcTSCompleteExchange(dev->PciDev, fcChip, *fcExchangeIndex);	// SEST build failed
4078 		}
4079 	} else			// no Exchanges available
4080 	{
4081 		ulStatus = SEST_FULL;
4082 		printk("FC Error: no fcExchanges available\n");
4083 	}
4084 	return ulStatus;
4085 }
4086 
4087 // set RSP payload fields
buildFCPstatus(PTACHYON fcChip,u32 ExchangeID)4088 static void buildFCPstatus(PTACHYON fcChip, u32 ExchangeID)
4089 {
4090 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
4091 	FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ExchangeID];	// shorthand
4092 	PFCP_STATUS_RESPONSE pFcpStatus;
4093 
4094 	memset(&fcChip->SEST->RspHDR[ExchangeID].pl, 0, sizeof(FCP_STATUS_RESPONSE));
4095 	if (pExchange->status)	// something wrong?
4096 	{
4097 		pFcpStatus = (PFCP_STATUS_RESPONSE)	// cast RSP buffer for this xchng
4098 		    & fcChip->SEST->RspHDR[ExchangeID].pl;
4099 		if (pExchange->status & COUNT_ERROR) {
4100 
4101 			// set FCP response len valid (so we can report count error)
4102 			pFcpStatus->fcp_status |= FCP_RSP_LEN_VALID;
4103 			pFcpStatus->fcp_rsp_len = 0x04000000;	// 4 byte len (BIG Endian)
4104 
4105 			pFcpStatus->fcp_rsp_info = FCP_DATA_LEN_NOT_BURST_LEN;	// RSP_CODE
4106 		}
4107 	}
4108 }
4109 
4110 
cpqfc_pci_map_sg_page(struct pci_dev * pcidev,u32 * hw_paddr,void * sgp_vaddr,dma_addr_t * umap_paddr,unsigned int * maplen,int PairCount)4111 static dma_addr_t cpqfc_pci_map_sg_page(struct pci_dev *pcidev, u32 * hw_paddr,	// where to put phys addr for HW use
4112 					void *sgp_vaddr,	// the virtual address of the sg page
4113 					dma_addr_t * umap_paddr,	// where to put phys addr for unmap
4114 					unsigned int *maplen,	// where to store sg entry length
4115 					int PairCount)	// number of sg pairs used in the page.
4116 {
4117 	unsigned long aligned_addr = (unsigned long) sgp_vaddr;
4118 
4119 	*maplen = PairCount * 8;
4120 	aligned_addr += TL_EXT_SG_PAGE_BYTELEN;
4121 	aligned_addr &= ~(TL_EXT_SG_PAGE_BYTELEN - 1);
4122 
4123 	*umap_paddr = pci_map_single(pcidev, (void *) aligned_addr, *maplen, PCI_DMA_TODEVICE);
4124 	*hw_paddr = (u32) * umap_paddr;
4125 
4126 #       if BITS_PER_LONG > 32
4127 	if (*umap_paddr >> 32) {
4128 		printk("cqpfcTS:Tach SG DMA addr %p>32 bits\n", (void *) umap_paddr);
4129 		return 0;
4130 	}
4131 #       endif
4132 	return *umap_paddr;
4133 }
4134 
cpqfc_undo_SEST_mappings(struct pci_dev * pcidev,unsigned long contigaddr,int len,int dir,struct scatterlist * sgl,int use_sg,PSGPAGES * sgPages_head,int allocated_pages)4135 static void cpqfc_undo_SEST_mappings(struct pci_dev *pcidev, unsigned long contigaddr, int len, int dir, struct scatterlist *sgl, int use_sg, PSGPAGES * sgPages_head, int allocated_pages)
4136 {
4137 	PSGPAGES i, next;
4138 
4139 	if (contigaddr != (unsigned long) NULL)
4140 		pci_unmap_single(pcidev, contigaddr, len, dir);
4141 
4142 	if (sgl != NULL)
4143 		pci_unmap_sg(pcidev, sgl, use_sg, dir);
4144 
4145 	for (i = *sgPages_head; i != NULL; i = next) {
4146 		pci_unmap_single(pcidev, i->busaddr, i->maplen, scsi_to_pci_dma_dir(PCI_DMA_TODEVICE));
4147 		i->busaddr = (dma_addr_t) NULL;
4148 		i->maplen = 0L;
4149 		next = i->next;
4150 		kfree(i);
4151 	}
4152 	*sgPages_head = NULL;
4153 }
4154 
4155 // This routine builds scatter/gather lists into SEST entries
4156 // INPUTS:
4157 //   SESTalPair - SEST address @DWordA "Local Buffer Length"
4158 //   sgList     - Scatter/Gather linked list of Len/Address data buffers
4159 // OUTPUT:
4160 //   sgPairs - number of valid address/length pairs
4161 // Remarks:
4162 //   The SEST data buffer pointers only depend on number of
4163 //   length/ address pairs, NOT on the type (IWE, TRE,...)
4164 //   Up to 3 pairs can be referenced in the SEST - more than 3
4165 //   require this Extended S/G list page.  The page holds 4, 8, 16...
4166 //   len/addr pairs, per Scatter/Gather List Page Length Reg.
4167 //   TachLite allows pages to be linked to any depth.
4168 
4169 //#define DBG_SEST_SGLIST 1 // for printing out S/G pairs with Ext. pages
4170 
4171 static int ap_hi_water = TL_DANGER_SGPAGES;
4172 
build_SEST_sgList(struct pci_dev * pcidev,u32 * SESTalPairStart,Scsi_Cmnd * Cmnd,u32 * sgPairs,PSGPAGES * sgPages_head)4173 static u32 build_SEST_sgList(struct pci_dev *pcidev, u32 * SESTalPairStart,	// the 3 len/address buffers in SEST
4174 			       Scsi_Cmnd * Cmnd, u32 * sgPairs, PSGPAGES * sgPages_head)	// link list of TL Ext. S/G pages from O/S Pool
4175 {
4176 	u32 i, AllocatedPages = 0;	// Tach Ext. S/G page allocations
4177 	u32 *alPair = SESTalPairStart;
4178 	u32 *ext_sg_page_phys_addr_place = NULL;
4179 	int PairCount;
4180 	unsigned long ulBuff, contigaddr;
4181 	u32 total_data_len = 0;	// (in bytes)
4182 	u32 bytes_to_go = Cmnd->request_bufflen;	// total xfer (S/G sum)
4183 	u32 thisMappingLen;
4184 	struct scatterlist *sgl = NULL;	// S/G list (Linux format)
4185 	int sg_count, totalsgs;
4186 	dma_addr_t busaddr;
4187 	unsigned long thislen, offset;
4188 	PSGPAGES *sgpage = sgPages_head;
4189 	PSGPAGES prev_page = NULL;
4190 
4191 # define WE_HAVE_SG_LIST (sgl != (unsigned long) NULL)
4192 	contigaddr = (unsigned long) NULL;
4193 
4194 	if (!Cmnd->use_sg)	// no S/G list?
4195 	{
4196 		if (bytes_to_go <= TL_MAX_SG_ELEM_LEN) {
4197 			*sgPairs = 1;	// use "local" S/G pair in SEST entry
4198 			// (for now, ignore address bits above #31)
4199 
4200 			*alPair++ = bytes_to_go;	// bits 18-0, length
4201 
4202 			if (bytes_to_go != 0) {
4203 				contigaddr = ulBuff = pci_map_single(pcidev, Cmnd->request_buffer, Cmnd->request_bufflen, scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
4204 				// printk("ms %p ", ulBuff);
4205 			} else {
4206 				// No data transfer, (e.g.: Test Unit Ready)
4207 				// printk("btg=0 ");
4208 				*sgPairs = 0;
4209 				memset(alPair, 0, sizeof(*alPair));
4210 				return 0;
4211 			}
4212 
4213 #		if BITS_PER_LONG > 32
4214 			if (ulBuff >> 32) {
4215 				printk("FATAL! Tachyon DMA address %p " "exceeds 32 bits\n", (void *) ulBuff);
4216 				return 0;
4217 			}
4218 #		endif
4219 			*alPair = (u32) ulBuff;
4220 			return bytes_to_go;
4221 		} else		// We have a single large (too big) contiguous buffer.
4222 		{		// We will have to break it up.  We'll use the scatter
4223 			// gather code way below, but use contigaddr instead
4224 			// of sg_dma_addr(). (this is a very rare case).
4225 
4226 			unsigned long btg;
4227 			contigaddr = pci_map_single(pcidev, Cmnd->request_buffer, Cmnd->request_bufflen, scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
4228 
4229 			// printk("contigaddr = %p, len = %d\n",
4230 			//      (void *) contigaddr, bytes_to_go);
4231 			totalsgs = 0;
4232 			for (btg = bytes_to_go; btg > 0;) {
4233 				btg -= (btg > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : btg);
4234 				totalsgs++;
4235 			}
4236 			sgl = NULL;
4237 			*sgPairs = totalsgs;
4238 		}
4239 	} else			// we do have a scatter gather list
4240 	{
4241 		// [TBD - update for Linux to support > 32 bits addressing]
4242 		// since the format for local & extended S/G lists is different,
4243 		// check if S/G pairs exceeds 3.
4244 		// *sgPairs = Cmnd->use_sg; Nope, that's wrong.
4245 
4246 		sgl = (struct scatterlist *) Cmnd->request_buffer;
4247 		sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg, scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
4248 		// printk("sgl = %p, sg_count = %d\n", (void *) sgl, sg_count);
4249 		if (sg_count <= 3) {
4250 
4251 			// we need to be careful here that no individual mapping
4252 			// is too large, and if any is, that breaking it up
4253 			// doesn't push us over 3 sgs, or, if it does, that we
4254 			// handle that case.  Tachyon can take 0x7FFFF bits for length,
4255 			// but sg structure uses "unsigned int", on the face of it,
4256 			// up to 0xFFFFFFFF or even more.
4257 
4258 			int i;
4259 			unsigned long thislen;
4260 
4261 			totalsgs = 0;
4262 			for (i = 0; i < sg_count; i++) {
4263 				thislen = sg_dma_len(&sgl[i]);
4264 				while (thislen >= TL_MAX_SG_ELEM_LEN) {
4265 					totalsgs++;
4266 					thislen -= TL_MAX_SG_ELEM_LEN;
4267 				}
4268 				if (thislen > 0)
4269 					totalsgs++;
4270 			}
4271 			*sgPairs = totalsgs;
4272 		} else
4273 			totalsgs = 999;	// as a first estimate, definitely >3,
4274 
4275 		// if (totalsgs != sg_count)
4276 		//      printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
4277 	}
4278 
4279 	// printk("totalsgs = %d, sgcount=%d\n", totalsgs, sg_count);
4280 	if (totalsgs <= 3)	// can (must) use "local" SEST list
4281 	{
4282 		while (bytes_to_go) {
4283 			offset = 0L;
4284 
4285 			if (WE_HAVE_SG_LIST)
4286 				thisMappingLen = sg_dma_len(sgl);
4287 			else	// or contiguous buffer?
4288 				thisMappingLen = bytes_to_go;
4289 
4290 			while (thisMappingLen > 0) {
4291 				thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : thisMappingLen;
4292 				bytes_to_go = bytes_to_go - thislen;
4293 
4294 				// we have L/A pair; L = thislen, A = physicalAddress
4295 				// load into SEST...
4296 
4297 				total_data_len += thislen;
4298 				*alPair = thislen;	// bits 18-0, length
4299 
4300 				alPair++;
4301 
4302 				if (WE_HAVE_SG_LIST)
4303 					ulBuff = sg_dma_address(sgl) + offset;
4304 				else
4305 					ulBuff = contigaddr + offset;
4306 
4307 				offset += thislen;
4308 
4309 #	if BITS_PER_LONG > 32
4310 				if (ulBuff >> 32) {
4311 					printk("cqpfcTS: 2Tach DMA address %p > 32 bits\n", (void *) ulBuff);
4312 					printk("%s = %p, offset = %ld\n", WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr", WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr, offset);
4313 					return 0;
4314 				}
4315 #	endif
4316 				*alPair++ = (u32) ulBuff;	// lower 32 bits (31-0)
4317 				thisMappingLen -= thislen;
4318 			}
4319 
4320 			if (WE_HAVE_SG_LIST)
4321 				++sgl;	// next S/G pair
4322 			else if (bytes_to_go != 0)
4323 				printk("BTG not zero!\n");
4324 
4325 #     ifdef DBG_SEST_SGLIST
4326 			printk("L=%d ", thisMappingLen);
4327 			printk("btg=%d ", bytes_to_go);
4328 #     endif
4329 
4330 		}
4331 		// printk("i:%d\n", *sgPairs);
4332 	} else			// more than 3 pairs requires Extended S/G page (Pool Allocation)
4333 	{
4334 		// clear out SEST DWORDs (local S/G addr) C-F (A-B set in following logic)
4335 		for (i = 2; i < 6; i++)
4336 			alPair[i] = 0;
4337 
4338 		PairCount = TL_EXT_SG_PAGE_COUNT;	// forces initial page allocation
4339 		totalsgs = 0;
4340 		while (bytes_to_go) {
4341 			// Per SEST format, we can support 524287 byte lengths per
4342 			// S/G pair.  Typical user buffers are 4k, and very rarely
4343 			// exceed 12k due to fragmentation of physical memory pages.
4344 			// However, on certain O/S system (not "user") buffers (on platforms
4345 			// with huge memories), it's possible to exceed this
4346 			// length in a single S/G address/len mapping, so we have to handle
4347 			// that.
4348 
4349 			offset = 0L;
4350 			if (WE_HAVE_SG_LIST)
4351 				thisMappingLen = sg_dma_len(sgl);
4352 			else
4353 				thisMappingLen = bytes_to_go;
4354 
4355 			while (thisMappingLen > 0) {
4356 				thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : thisMappingLen;
4357 				// printk("%d/%d/%d\n", thislen, thisMappingLen, bytes_to_go);
4358 
4359 				// should we load into "this" extended S/G page, or allocate
4360 				// new page?
4361 
4362 				if (PairCount >= TL_EXT_SG_PAGE_COUNT) {
4363 					// Now, we have to map the previous page, (triggering buffer bounce)
4364 					// The first time thru the loop, there won't be a previous page.
4365 					if (prev_page != NULL)	// is there a prev page?
4366 					{
4367 						// this code is normally kind of hard to trigger,
4368 						// you have to use up more than 256 scatter gather
4369 						// elements to get here.  Cranking down TL_MAX_SG_ELEM_LEN
4370 						// to an absurdly low value (128 bytes or so) to artificially
4371 						// break i/o's into a zillion pieces is how I tested it.
4372 						busaddr = cpqfc_pci_map_sg_page(pcidev, ext_sg_page_phys_addr_place, prev_page->page, &prev_page->busaddr, &prev_page->maplen, PairCount);
4373 					}
4374 					// Allocate the TL Extended S/G list page.  We have
4375 					// to allocate twice what we want to ensure required TL alignment
4376 					// (Tachlite TL/TS User Man. Rev 6.0, p 168)
4377 					// We store the original allocated PVOID so we can free later
4378 					*sgpage = kmalloc(sizeof(SGPAGES), GFP_ATOMIC);
4379 					if (!*sgpage) {
4380 						printk("cpqfc: Allocation failed @ %d S/G page allocations\n", AllocatedPages);
4381 						total_data_len = 0;	// failure!! Ext. S/G is All-or-none affair
4382 
4383 						// unmap the previous mappings, if any.
4384 
4385 						cpqfc_undo_SEST_mappings(pcidev, contigaddr, Cmnd->request_bufflen, scsi_to_pci_dma_dir(Cmnd->sc_data_direction), sgl, Cmnd->use_sg, sgPages_head, AllocatedPages + 1);
4386 
4387 						// FIXME: testing shows that if we get here,
4388 						// it's bad news.  (this has been this way for a long
4389 						// time though, AFAIK.  Not that that excuses it.)
4390 
4391 						return 0;	// give up (and probably hang the system)
4392 					}
4393 					// clear out memory we just allocated
4394 					memset((*sgpage)->page, 0, TL_EXT_SG_PAGE_BYTELEN * 2);
4395 					(*sgpage)->next = NULL;
4396 					(*sgpage)->busaddr = (dma_addr_t) NULL;
4397 					(*sgpage)->maplen = 0L;
4398 
4399 					// align the memory - TL requires sizeof() Ext. S/G page alignment.
4400 					// We doubled the actual required size so we could mask off LSBs
4401 					// to get desired offset
4402 
4403 					ulBuff = (unsigned long) (*sgpage)->page;
4404 					ulBuff += TL_EXT_SG_PAGE_BYTELEN;
4405 					ulBuff &= ~(TL_EXT_SG_PAGE_BYTELEN - 1);
4406 
4407 					// set pointer, in SEST if first Ext. S/G page, or in last pair
4408 					// of linked Ext. S/G pages... (Only 32-bit PVOIDs, so just
4409 					// load lower 32 bits)
4410 					// NOTE: the Len field must be '0' if this is the first Ext. S/G
4411 					// pointer in SEST, and not 0 otherwise (we know thislen != 0).
4412 
4413 					*alPair = (alPair != SESTalPairStart) ? thislen : 0;
4414 
4415 #	  ifdef DBG_SEST_SGLIST
4416 					printk("PairCount %d @%p even %Xh, ", PairCount, alPair, *alPair);
4417 #	  endif
4418 
4419 					// Save the place where we need to store the physical
4420 					// address of this scatter gather page which we get when we map it
4421 					// (and mapping we can do only after we fill it in.)
4422 					alPair++;	// next DWORD, will contain phys addr of the ext page
4423 					ext_sg_page_phys_addr_place = alPair;
4424 
4425 					// Now, set alPair = the virtual addr of the (Extended) S/G page
4426 					// which will accept the Len/ PhysicalAddress pairs
4427 					alPair = (u32 *) ulBuff;
4428 
4429 					AllocatedPages++;
4430 					if (AllocatedPages >= ap_hi_water) {
4431 						// This message should rarely, if ever, come out.
4432 						// Previously (cpqfc version <= 2.0.5) the driver would
4433 						// just puke if more than 4 SG pages were used, and nobody
4434 						// ever complained about that.  This only comes out if
4435 						// more than 8 pages are used.
4436 
4437 						printk(KERN_WARNING "cpqfc: Possible danger.  %d scatter gather pages used.\n" "cpqfc: detected seemingly extreme memory " "fragmentation or huge data transfers.\n", AllocatedPages);
4438 						ap_hi_water = AllocatedPages + 1;
4439 					}
4440 
4441 					PairCount = 1;	// starting new Ext. S/G page
4442 					prev_page = (*sgpage);	// remember this page, for next time thru
4443 					sgpage = &((*sgpage)->next);
4444 				}	// end of new TL Ext. S/G page allocation
4445 
4446 				*alPair = thislen;	// bits 18-0, length (range check above)
4447 
4448 #	ifdef DBG_SEST_SGLIST
4449 				printk("PairCount %d @%p, even %Xh, ", PairCount, alPair, *alPair);
4450 #	endif
4451 
4452 				alPair++;	// next DWORD, physical address
4453 
4454 				if (WE_HAVE_SG_LIST)
4455 					ulBuff = sg_dma_address(sgl) + offset;
4456 				else
4457 					ulBuff = contigaddr + offset;
4458 				offset += thislen;
4459 
4460 #	if BITS_PER_LONG > 32
4461 				if (ulBuff >> 32) {
4462 					printk("cqpfcTS: 1Tach DMA address %p > 32 bits\n", (void *) ulBuff);
4463 					printk("%s = %p, offset = %ld\n", WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr", WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr, offset);
4464 					return 0;
4465 				}
4466 #	endif
4467 
4468 				*alPair = (u32) ulBuff;	// lower 32 bits (31-0)
4469 
4470 #       ifdef DBG_SEST_SGLIST
4471 				printk("odd %Xh\n", *alPair);
4472 #       endif
4473 				alPair++;	// next DWORD, next address/length pair
4474 
4475 				PairCount++;	// next Length/Address pair
4476 
4477 				// if (PairCount > pc_hi_water)
4478 				// {
4479 				// printk("pc hi = %d ", PairCount);
4480 				// pc_hi_water = PairCount;
4481 				// }
4482 				bytes_to_go -= thislen;
4483 				total_data_len += thislen;
4484 				thisMappingLen -= thislen;
4485 				totalsgs++;
4486 			}	// while (thisMappingLen > 0)
4487 			if (WE_HAVE_SG_LIST)
4488 				sgl++;	// next S/G pair
4489 		}		// while (bytes_to_go)
4490 
4491 		// printk("Totalsgs=%d\n", totalsgs);
4492 		*sgPairs = totalsgs;
4493 
4494 		// PCI map (and bounce) the last (and usually only) extended SG page
4495 		busaddr = cpqfc_pci_map_sg_page(pcidev, ext_sg_page_phys_addr_place, prev_page->page, &prev_page->busaddr, &prev_page->maplen, PairCount);
4496 	}
4497 	return total_data_len;
4498 }
4499 
4500 
4501 
4502 // The Tachlite SEST table is referenced to OX_ID (or RX_ID).  To optimize
4503 // performance and debuggability, we index the Exchange structure to FC X_ID
4504 // This enables us to build exchanges for later en-queing to Tachyon,
4505 // provided we have an open X_ID slot. At Tachyon queing time, we only
4506 // need an ERQ slot; then "fix-up" references in the
4507 // IRB, FCHS, etc. as needed.
4508 // RETURNS:
4509 // 0 if successful
4510 // non-zero on error
4511 //sstartex
4512 
cpqfcTSStartExchange(CPQFCHBA * dev,s32 ExchangeID)4513 u32 cpqfcTSStartExchange(CPQFCHBA * dev, s32 ExchangeID)
4514 {
4515 	PTACHYON fcChip = &dev->fcChip;
4516 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
4517 	FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ExchangeID];	// shorthand
4518 	u16 producer, consumer;
4519 	u32 ulStatus = 0;
4520 	short int ErqIndex;
4521 	u8 CompleteExchange = 0;	// e.g. ACC replies are complete
4522 	u8 SestType = 0;
4523 	u32 InboundData = 0;
4524 
4525 	// We will manipulate Tachlite chip registers here to successfully
4526 	// start exchanges.
4527 
4528 	// Check that link is not down -- we can't start an exchange on a
4529 	// down link!
4530 
4531 	if (fcChip->Registers.FMstatus.value & 0x80)	// LPSM offline?
4532 	{
4533 		printk("fcStartExchange: PSM offline (%Xh), x_ID %Xh, type %Xh, port_id %Xh\n", fcChip->Registers.FMstatus.value & 0xFF, ExchangeID, pExchange->type, pExchange->fchs.d_id);
4534 
4535 		if (ExchangeID >= TACH_SEST_LEN)	// Link Service Outbound frame?
4536 		{
4537 			// Our most popular LinkService commands are port discovery types
4538 			// (PLOGI/ PDISC...), which are implicitly nullified by Link Down
4539 			// events, so it makes no sense to Que them.  However, ABTS should
4540 			// be queued, since exchange sequences are likely destroyed by
4541 			// Link Down events, and we want to notify other ports of broken
4542 			// sequences by aborting the corresponding exchanges.
4543 			if (pExchange->type != BLS_ABTS) {
4544 				ulStatus = LNKDWN_OSLS;
4545 				goto Done;
4546 				// don't Que most LinkServ exchanges on LINK DOWN
4547 			}
4548 		}
4549 
4550 		printk("fcStartExchange: Que x_ID %Xh, type %Xh\n", ExchangeID, pExchange->type);
4551 		pExchange->status |= EXCHANGE_QUEUED;
4552 		ulStatus = EXCHANGE_QUEUED;
4553 		goto Done;
4554 	}
4555 	// Make sure ERQ has available space.
4556 
4557 	producer = (u16) fcChip->ERQ->producerIndex;	// copies for logical arith.
4558 	consumer = (u16) fcChip->ERQ->consumerIndex;
4559 	producer++;		// We are testing for full que by incrementing
4560 
4561 	if (producer >= ERQ_LEN)	// rollover condition?
4562 		producer = 0;
4563 	if (consumer != producer)	// ERQ not full?
4564 	{
4565 		// ****************** Need Atomic access to chip registers!!********
4566 
4567 		// remember ERQ PI for copying IRB
4568 		ErqIndex = (u16) fcChip->ERQ->producerIndex;
4569 		fcChip->ERQ->producerIndex = producer;	// this is written to Tachyon
4570 		// we have an ERQ slot! If SCSI command, need SEST slot
4571 		// otherwise we are done.
4572 
4573 		// Note that Tachyon requires that bit 15 of the OX_ID or RX_ID be
4574 		// set according to direction of data to/from Tachyon for SEST assists.
4575 		// For consistency, enforce this rule for Link Service (non-SEST)
4576 		// exchanges as well.
4577 
4578 		// fix-up the X_ID field in IRB
4579 		pExchange->IRB.Req_A_Trans_ID = ExchangeID & 0x7FFF;	// 15-bit field
4580 
4581 		// fix-up the X_ID field in fchs -- depends on Originator or Responder,
4582 		// outgoing or incoming data?
4583 		switch (pExchange->type) {
4584 			// ORIGINATOR types...  we're setting our OX_ID and
4585 			// defaulting the responder's RX_ID to 0xFFFF
4586 
4587 		case SCSI_IRE:
4588 			// Requirement: set MSB of x_ID for Incoming TL data
4589 			// (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
4590 			InboundData = 0x8000;
4591 
4592 		case SCSI_IWE:
4593 			SestType = 1;
4594 			pExchange->fchs.ox_rx_id = (ExchangeID | InboundData);
4595 			pExchange->fchs.ox_rx_id <<= 16;	// MSW shift
4596 			pExchange->fchs.ox_rx_id |= 0xffff;	// add default RX_ID
4597 
4598 			// now fix-up the Data HDR OX_ID (TL automatically does rx_id)
4599 			// (not necessary for IRE -- data buffer unused)
4600 			if (pExchange->type == SCSI_IWE) {
4601 				fcChip->SEST->DataHDR[ExchangeID].ox_rx_id = pExchange->fchs.ox_rx_id;
4602 
4603 			}
4604 
4605 			break;
4606 
4607 
4608 		case FCS_NSR:	// ext. link service Name Service Request
4609 		case ELS_SCR:	// ext. link service State Change Registration
4610 		case ELS_FDISC:	// ext. link service login
4611 		case ELS_FLOGI:	// ext. link service login
4612 		case ELS_LOGO:	// FC-PH extended link service logout
4613 		case BLS_NOP:	// Basic link service No OPeration
4614 		case ELS_PLOGI:	// ext. link service login (PLOGI)
4615 		case ELS_PDISC:	// ext. link service login (PDISC)
4616 		case ELS_PRLI:	// ext. link service process login
4617 
4618 			pExchange->fchs.ox_rx_id = ExchangeID;
4619 			pExchange->fchs.ox_rx_id <<= 16;	// MSW shift
4620 			pExchange->fchs.ox_rx_id |= 0xffff;	// and RX_ID
4621 
4622 			break;
4623 
4624 
4625 
4626 
4627 			// RESPONDER types... we must set our RX_ID while preserving
4628 			// sender's OX_ID
4629 			// outgoing (or no) data
4630 		case ELS_RJT:	// extended link service reject
4631 		case ELS_LOGO_ACC:	// FC-PH extended link service logout accept
4632 		case ELS_ACC:	// ext. generic link service accept
4633 		case ELS_PLOGI_ACC:	// ext. link service login accept (PLOGI or PDISC)
4634 		case ELS_PRLI_ACC:	// ext. link service process login accept
4635 
4636 			CompleteExchange = 1;	// Reply (ACC or RJT) is end of exchange
4637 			pExchange->fchs.ox_rx_id |= (ExchangeID & 0xFFFF);
4638 
4639 			break;
4640 
4641 
4642 			// since we are a Responder, OX_ID should already be set by
4643 			// cpqfcTSBuildExchange().  We need to -OR- in RX_ID
4644 		case SCSI_TWE:
4645 			SestType = 1;
4646 			// Requirement: set MSB of x_ID for Incoming TL data
4647 			// (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
4648 
4649 			pExchange->fchs.ox_rx_id &= 0xFFFF0000;	// clear RX_ID
4650 			// Requirement: set MSB of RX_ID for Incoming TL data
4651 			// (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
4652 			pExchange->fchs.ox_rx_id |= (ExchangeID | 0x8000);
4653 			break;
4654 
4655 
4656 		case SCSI_TRE:
4657 			SestType = 1;
4658 
4659 			// there is no XRDY for SEST target read; the data
4660 			// header needs to be updated. Also update the RSP
4661 			// exchange IDs for the status frame, in case it is sent automatically
4662 			fcChip->SEST->DataHDR[ExchangeID].ox_rx_id |= ExchangeID;
4663 			fcChip->SEST->RspHDR[ExchangeID].ox_rx_id = fcChip->SEST->DataHDR[ExchangeID].ox_rx_id;
4664 
4665 			// for easier FCP response logic (works for TWE and TRE),
4666 			// copy exchange IDs.  (Not needed if TRE 'RSP' bit set)
4667 			pExchange->fchs.ox_rx_id = fcChip->SEST->DataHDR[ExchangeID].ox_rx_id;
4668 
4669 			break;
4670 
4671 
4672 		case FCP_RESPONSE:	// using existing OX_ID/ RX_ID pair,
4673 			// start SFS FCP-RESPONSE frame
4674 			// OX/RX_ID should already be set! (See "fcBuild" above)
4675 			CompleteExchange = 1;	// RSP is end of FCP-SCSI exchange
4676 
4677 
4678 			break;
4679 
4680 
4681 		case BLS_ABTS_RJT:	// uses new RX_ID, since SEST x_ID non-existent
4682 		case BLS_ABTS_ACC:	// using existing OX_ID/ RX_ID pair from SEST entry
4683 			CompleteExchange = 1;	// ACC or RJT marks end of FCP-SCSI exchange
4684 		case BLS_ABTS:	// using existing OX_ID/ RX_ID pair from SEST entry
4685 
4686 
4687 			break;
4688 
4689 
4690 		default:
4691 			printk("Error on fcStartExchange: undefined type %Xh(%d)\n", pExchange->type, pExchange->type);
4692 			return INVALID_ARGS;
4693 		}
4694 
4695 
4696 		// X_ID fields are entered -- copy IRB to Tachyon's ERQ
4697 
4698 
4699 		memcpy(&fcChip->ERQ->QEntry[ErqIndex],	// dest.
4700 		       &pExchange->IRB, 32);	// fixed (hardware) length!
4701 
4702 		PCI_TRACEO(ExchangeID, 0xA0)
4703 		    // ACTION!  May generate INT and IMQ entry
4704 		    writel(fcChip->ERQ->producerIndex, fcChip->Registers.ERQproducerIndex.address);
4705 
4706 
4707 		if (ExchangeID >= TACH_SEST_LEN)	// Link Service Outbound frame?
4708 		{
4709 
4710 			// wait for completion! (TDB -- timeout and chip reset)
4711 
4712 
4713 			PCI_TRACEO(ExchangeID, 0xA4)
4714 
4715 			    enable_irq(dev->HostAdapter->irq);	// only way to get Sem.
4716 
4717 			down_interruptible(dev->TYOBcomplete);
4718 
4719 			disable_irq(dev->HostAdapter->irq);
4720 			PCI_TRACE(0xA4)
4721 			    // On login exchanges, BAD_ALPA (non-existent port_id) results in
4722 			    // FTO (Frame Time Out) on the Outbound Completion message.
4723 			    // If we got an FTO status, complete the exchange (free up slot)
4724 			    if (CompleteExchange ||	// flag from Reply frames
4725 				pExchange->status)	// typically, can get FRAME_TO
4726 			{
4727 				cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
4728 			}
4729 		}
4730 
4731 		else		// SEST Exchange
4732 		{
4733 			ulStatus = 0;	// ship & pray success (e.g. FCP-SCSI)
4734 
4735 			if (CompleteExchange)	// by Type of exchange (e.g. end-of-xchng)
4736 			{
4737 				cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
4738 			}
4739 
4740 			else
4741 				pExchange->status &= ~EXCHANGE_QUEUED;	// clear ExchangeQueued flag
4742 
4743 		}
4744 	}
4745 
4746 
4747 	else			// ERQ 'producer' = 'consumer' and QUE is full
4748 	{
4749 		ulStatus = OUTQUE_FULL;	// Outbound (ERQ) Que full
4750 	}
4751 
4752       Done:
4753 	PCI_TRACE(0xA0)
4754 	    return ulStatus;
4755 }
4756 
4757 
4758 
4759 
4760 
4761 // Scan fcController->fcExchanges array for a usuable index (a "free"
4762 // exchange).
4763 // Inputs:
4764 //   fcChip - pointer to TachLite chip structure
4765 // Return:
4766 //  index - exchange array element where exchange can be built
4767 //  -1    - exchange array is full
4768 // REMARKS:
4769 // Although this is a (yuk!) linear search, we presume
4770 // that the system will complete exchanges about as quickly as
4771 // they are submitted.  A full Exchange array (and hence, max linear
4772 // search time for free exchange slot) almost guarantees a Fibre problem
4773 // of some sort.
4774 // In the interest of making exchanges easier to debug, we want a LRU
4775 // (Least Recently Used) scheme.
4776 
4777 
FindFreeExchange(PTACHYON fcChip,u32 type)4778 static s32 FindFreeExchange(PTACHYON fcChip, u32 type)
4779 {
4780 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
4781 	u32 i;
4782 	u32 ulStatus = -1;	// assume failure
4783 
4784 
4785 	if (type == SCSI_IRE || type == SCSI_TRE || type == SCSI_IWE || type == SCSI_TWE) {
4786 		// SCSI type - X_IDs should be from 0 to TACH_SEST_LEN-1
4787 		if (fcChip->fcSestExchangeLRU >= TACH_SEST_LEN)	// rollover?
4788 			fcChip->fcSestExchangeLRU = 0;
4789 		i = fcChip->fcSestExchangeLRU;	// typically it's already free!
4790 
4791 		if (Exchanges->fcExchange[i].type == 0)	// check for "free" element
4792 		{
4793 			ulStatus = 0;	// success!
4794 		}
4795 
4796 		else {		// YUK! we need to do a linear search for free element.
4797 			// Fragmentation of the fcExchange array is due to excessively
4798 			// long completions or timeouts.
4799 
4800 			while (1) {
4801 				if (++i >= TACH_SEST_LEN)	// rollover check
4802 					i = 0;	// beginning of SEST X_IDs
4803 
4804 //					printk( "looping for SCSI xchng ID: i=%d, type=%Xh\n",
4805 //						i, Exchanges->fcExchange[i].type);
4806 
4807 				if (Exchanges->fcExchange[i].type == 0)	// "free"?
4808 				{
4809 					ulStatus = 0;	// success!
4810 					break;
4811 				}
4812 				if (i == fcChip->fcSestExchangeLRU)	// wrapped-around array?
4813 				{
4814 					printk("SEST X_ID space full\n");
4815 					break;	// failed - prevent inf. loop
4816 				}
4817 			}
4818 		}
4819 		fcChip->fcSestExchangeLRU = i + 1;	// next! (rollover check next pass)
4820 	}
4821 	else			// Link Service type - X_IDs should be from TACH_SEST_LEN
4822 				// to TACH_MAX_XID
4823 	{
4824 		if (fcChip->fcLsExchangeLRU >= TACH_MAX_XID ||	// range check
4825 		    fcChip->fcLsExchangeLRU < TACH_SEST_LEN)	// (e.g. startup)
4826 			fcChip->fcLsExchangeLRU = TACH_SEST_LEN;
4827 
4828 		i = fcChip->fcLsExchangeLRU;	// typically it's already free!
4829 		if (Exchanges->fcExchange[i].type == 0)	// check for "free" element
4830 		{
4831 			ulStatus = 0;	// success!
4832 		}
4833 
4834 		else {		// YUK! we need to do a linear search for free element
4835 			// Fragmentation of the fcExchange array is due to excessively
4836 			// long completions or timeouts.
4837 
4838 			while (1) {
4839 				if (++i >= TACH_MAX_XID)	// rollover check
4840 					i = TACH_SEST_LEN;	// beginning of Link Service X_IDs
4841 
4842 //				printk( "looping for xchng ID: i=%d, type=%Xh\n",
4843 //					i, Exchanges->fcExchange[i].type);
4844 
4845 				if (Exchanges->fcExchange[i].type == 0)	// "free"?
4846 				{
4847 					ulStatus = 0;	// success!
4848 					break;
4849 				}
4850 				if (i == fcChip->fcLsExchangeLRU)	// wrapped-around array?
4851 				{
4852 					printk("LinkService X_ID space full\n");
4853 					break;	// failed - prevent inf. loop
4854 				}
4855 			}
4856 		}
4857 		fcChip->fcLsExchangeLRU = i + 1;	// next! (rollover check next pass)
4858 
4859 	}
4860 
4861 	if (!ulStatus)		// success?
4862 		Exchanges->fcExchange[i].type = type;	// allocate it.
4863 
4864 	else
4865 		i = -1;		// error - all exchanges "open"
4866 
4867 	return i;
4868 }
4869 
cpqfc_pci_unmap_extended_sg(struct pci_dev * pcidev,PTACHYON fcChip,u32 x_ID)4870 static void cpqfc_pci_unmap_extended_sg(struct pci_dev *pcidev, PTACHYON fcChip, u32 x_ID)
4871 {
4872 	// Unmaps the memory regions used to hold the scatter gather lists
4873 
4874 	PSGPAGES i;
4875 
4876 	// Were there any such regions needing unmapping?
4877 	if (!USES_EXTENDED_SGLIST(fcChip->SEST, x_ID))
4878 		return;		// No such regions, we're outta here.
4879 
4880 	// for each extended scatter gather region needing unmapping...
4881 	for (i = fcChip->SEST->sgPages[x_ID]; i != NULL; i = i->next)
4882 		pci_unmap_single(pcidev, i->busaddr, i->maplen, scsi_to_pci_dma_dir(PCI_DMA_TODEVICE));
4883 }
4884 
4885 // Called also from cpqfcTScontrol.o, so can't be static
cpqfc_pci_unmap(struct pci_dev * pcidev,Scsi_Cmnd * cmd,PTACHYON fcChip,u32 x_ID)4886 void cpqfc_pci_unmap(struct pci_dev *pcidev, Scsi_Cmnd * cmd, PTACHYON fcChip, u32 x_ID)
4887 {
4888 	// Undo the DMA mappings
4889 	if (cmd->use_sg) {	// Used scatter gather list for data buffer?
4890 		cpqfc_pci_unmap_extended_sg(pcidev, fcChip, x_ID);
4891 		pci_unmap_sg(pcidev, cmd->buffer, cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction));
4892 		// printk("umsg %d\n", cmd->use_sg);
4893 	} else if (cmd->request_bufflen) {
4894 		// printk("ums %p ", fcChip->SEST->u[ x_ID ].IWE.GAddr1);
4895 		pci_unmap_single(pcidev, fcChip->SEST->u[x_ID].IWE.GAddr1, cmd->request_bufflen, scsi_to_pci_dma_dir(cmd->sc_data_direction));
4896 	}
4897 }
4898 
4899 // We call this routine to free an Exchange for any reason:
4900 // completed successfully, completed with error, aborted, etc.
4901 
4902 // returns 0 if Exchange failed and "retry" is acceptable
4903 // returns 1 if Exchange was successful, or retry is impossible
4904 // (e.g. port/device gone).
4905 //scompleteexchange
4906 
cpqfcTSCompleteExchange(struct pci_dev * pcidev,PTACHYON fcChip,u32 x_ID)4907 void cpqfcTSCompleteExchange(struct pci_dev *pcidev, PTACHYON fcChip, u32 x_ID)
4908 {
4909 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
4910 	int already_unmapped = 0;
4911 
4912 	if (x_ID < TACH_SEST_LEN)	// SEST-based (or LinkServ for FCP exchange)
4913 	{
4914 		if (Exchanges->fcExchange[x_ID].Cmnd == NULL)	// what#@!
4915 		{
4916 //			TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
4917 			printk(" x_ID %Xh, type %Xh, NULL ptr!\n", x_ID, Exchanges->fcExchange[x_ID].type);
4918 
4919 			goto CleanUpSestResources;	// this path should be very rare.
4920 		}
4921 		// we have Linux Scsi Cmnd ptr..., now check our Exchange status
4922 		// to decide how to complete this SEST FCP exchange
4923 
4924 		if (Exchanges->fcExchange[x_ID].status)	// perhaps a Tach indicated problem,
4925 			// or abnormal exchange completion
4926 		{
4927 			// set FCP Link statistics
4928 
4929 			if (Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT)
4930 				fcChip->fcStats.timeouts++;
4931 			if (Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)
4932 				fcChip->fcStats.FC4aborted++;
4933 			if (Exchanges->fcExchange[x_ID].status & COUNT_ERROR)
4934 				fcChip->fcStats.CntErrors++;
4935 			if (Exchanges->fcExchange[x_ID].status & LINKFAIL_TX)
4936 				fcChip->fcStats.linkFailTX++;
4937 			if (Exchanges->fcExchange[x_ID].status & LINKFAIL_RX)
4938 				fcChip->fcStats.linkFailRX++;
4939 			if (Exchanges->fcExchange[x_ID].status & OVERFLOW)
4940 				fcChip->fcStats.CntErrors++;
4941 
4942 			// First, see if the Scsi upper level initiated an ABORT on this
4943 			// exchange...
4944 			if (Exchanges->fcExchange[x_ID].status == INITIATOR_ABORT) {
4945 				printk(" DID_ABORT, x_ID %Xh, Cmnd %p ", x_ID, Exchanges->fcExchange[x_ID].Cmnd);
4946 				goto CleanUpSestResources;	// (we don't expect Linux _aborts)
4947 			}
4948 			// Did our driver timeout the Exchange, or did Tachyon indicate
4949 			// a failure during transmission?  Ask for retry with "SOFT_ERROR"
4950 			else if (Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT) {
4951 //				printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n",
4952 //					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
4953 				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
4954 			}
4955 			// Did frame(s) for an open exchange arrive in the SFQ,
4956 			// meaning the SEST was unable to process them?
4957 			else if (Exchanges->fcExchange[x_ID].status & SFQ_FRAME) {
4958 //				printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n",
4959 //					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
4960 				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
4961 			}
4962 			// Did our driver timeout the Exchange, or did Tachyon indicate
4963 			// a failure during transmission?  Ask for retry with "SOFT_ERROR"
4964 			else if ((Exchanges->fcExchange[x_ID].status & LINKFAIL_TX) ||
4965 				 (Exchanges->fcExchange[x_ID].status & PORTID_CHANGED) || (Exchanges->fcExchange[x_ID].status & FRAME_TO) || (Exchanges->fcExchange[x_ID].status & INV_ENTRY) || (Exchanges->fcExchange[x_ID].status & ABORTSEQ_NOTIFY))
4966 
4967 			{
4968 //				printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n",
4969 //					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
4970 				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
4971 
4972 
4973 			}
4974 			// e.g., a LOGOut happened, or device never logged back in.
4975 			else if (Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED) {
4976 //				printk(" *LOGOut or timeout on login!* ");
4977 //				trigger?
4978 //				TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
4979 				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_BAD_TARGET << 16);
4980 			}
4981 
4982 			// Did Tachyon indicate a CNT error?  We need further analysis
4983 			// to determine if the exchange is acceptable
4984 			else if (Exchanges->fcExchange[x_ID].status == COUNT_ERROR) {
4985 				u8 ScsiStatus;
4986 				FCP_STATUS_RESPONSE *pFcpStatus = (PFCP_STATUS_RESPONSE) & fcChip->SEST->RspHDR[x_ID].pl;
4987 
4988 				ScsiStatus = pFcpStatus->fcp_status >> 24;
4989 
4990 				// If the command is a SCSI Read/Write type, we don't tolerate
4991 				// count errors of any kind; assume the count error is due to
4992 				// a dropped frame and ask for retry...
4993 
4994 				if (((Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0x8) || (Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0x28) || (Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0xA) || (Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0x2A))
4995 				    && ScsiStatus == 0) {
4996 					// ask for retry
4997 //					printk("COUNT_ERROR retry, x_ID %Xh, status %Xh, Cmnd %p\n",
4998 //						x_ID, Exchanges->fcExchange[ x_ID ].status,
4999 //						Exchanges->fcExchange[ x_ID ].Cmnd);
5000 					Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
5001 				}
5002 
5003 				else	// need more analysis
5004 				{
5005 					cpqfcTSCheckandSnoopFCP(fcChip, x_ID);	// (will set ->result)
5006 				}
5007 			}
5008 			// default: NOTE! We don't ever want to get here.  Getting here
5009 			// implies something new is happening that we've never had a test
5010 			// case for.  Need code maintenance!  Return "ERROR"
5011 			else {
5012 				unsigned int stat = Exchanges->fcExchange[x_ID].status;
5013 				printk("DEFAULT result %Xh, x_ID %Xh, Cmnd %p", Exchanges->fcExchange[x_ID].status, x_ID, Exchanges->fcExchange[x_ID].Cmnd);
5014 
5015 				if (stat & INVALID_ARGS)
5016 					printk(" INVALID_ARGS ");
5017 				if (stat & LNKDWN_OSLS)
5018 					printk(" LNKDWN_OSLS ");
5019 				if (stat & LNKDWN_LASER)
5020 					printk(" LNKDWN_LASER ");
5021 				if (stat & OUTQUE_FULL)
5022 					printk(" OUTQUE_FULL ");
5023 				if (stat & DRIVERQ_FULL)
5024 					printk(" DRIVERQ_FULL ");
5025 				if (stat & SEST_FULL)
5026 					printk(" SEST_FULL ");
5027 				if (stat & BAD_ALPA)
5028 					printk(" BAD_ALPA ");
5029 				if (stat & OVERFLOW)
5030 					printk(" OVERFLOW ");
5031 				if (stat & COUNT_ERROR)
5032 					printk(" COUNT_ERROR ");
5033 				if (stat & LINKFAIL_RX)
5034 					printk(" LINKFAIL_RX ");
5035 				if (stat & ABORTSEQ_NOTIFY)
5036 					printk(" ABORTSEQ_NOTIFY ");
5037 				if (stat & LINKFAIL_TX)
5038 					printk(" LINKFAIL_TX ");
5039 				if (stat & HOSTPROG_ERR)
5040 					printk(" HOSTPROG_ERR ");
5041 				if (stat & FRAME_TO)
5042 					printk(" FRAME_TO ");
5043 				if (stat & INV_ENTRY)
5044 					printk(" INV_ENTRY ");
5045 				if (stat & SESTPROG_ERR)
5046 					printk(" SESTPROG_ERR ");
5047 				if (stat & OUTBOUND_TIMEOUT)
5048 					printk(" OUTBOUND_TIMEOUT ");
5049 				if (stat & INITIATOR_ABORT)
5050 					printk(" INITIATOR_ABORT ");
5051 				if (stat & MEMPOOL_FAIL)
5052 					printk(" MEMPOOL_FAIL ");
5053 				if (stat & FC2_TIMEOUT)
5054 					printk(" FC2_TIMEOUT ");
5055 				if (stat & TARGET_ABORT)
5056 					printk(" TARGET_ABORT ");
5057 				if (stat & EXCHANGE_QUEUED)
5058 					printk(" EXCHANGE_QUEUED ");
5059 				if (stat & PORTID_CHANGED)
5060 					printk(" PORTID_CHANGED ");
5061 				if (stat & DEVICE_REMOVED)
5062 					printk(" DEVICE_REMOVED ");
5063 				if (stat & SFQ_FRAME)
5064 					printk(" SFQ_FRAME ");
5065 				printk("\n");
5066 
5067 				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_ERROR << 16);
5068 			}
5069 		} else		// definitely no Tach problem, but perhaps an FCP problem
5070 		{
5071 			// set FCP Link statistic
5072 			fcChip->fcStats.ok++;
5073 			cpqfcTSCheckandSnoopFCP(fcChip, x_ID);	// (will set ->result)
5074 		}
5075 
5076 		cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, fcChip, x_ID);	// undo DMA mappings.
5077 		already_unmapped = 1;
5078 
5079 		// OK, we've set the Scsi "->result" field, so proceed with calling
5080 		// Linux Scsi "done" (if not NULL), and free any kernel memory we
5081 		// may have allocated for the exchange.
5082 
5083 		PCI_TRACEO((u32) Exchanges->fcExchange[x_ID].Cmnd, 0xAC);
5084 		// complete the command back to upper Scsi drivers
5085 		if (Exchanges->fcExchange[x_ID].Cmnd->scsi_done != NULL) {
5086 			// Calling "done" on an Linux _abort() aborted
5087 			// Cmnd causes a kernel panic trying to re-free mem.
5088 			// Actually, we shouldn't do anything with an _abort CMND
5089 			if (Exchanges->fcExchange[x_ID].Cmnd->result != (DID_ABORT << 16)) {
5090 				PCI_TRACE(0xAC)
5091 				    call_scsi_done(Exchanges->fcExchange[x_ID].Cmnd);
5092 			} else {
5093 				Exchanges->fcExchange[x_ID].Cmnd->SCp.sent_command = 0;
5094 //				printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
5095 //					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
5096 			}
5097 		} else {
5098 			Exchanges->fcExchange[x_ID].Cmnd->SCp.sent_command = 0;
5099 			printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID, Exchanges->fcExchange[x_ID].type, Exchanges->fcExchange[x_ID].Cmnd->cmnd[0]);
5100 			printk(" cpqfcTS: Null scsi_done function pointer!\n");
5101 		}
5102 
5103 
5104 		// Now, clean up non-Scsi_Cmnd items...
5105 CleanUpSestResources:
5106 
5107 		if (!already_unmapped)
5108 			cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, fcChip, x_ID);	// undo DMA mappings.
5109 
5110 		// Was an Extended Scatter/Gather page allocated?  We know
5111 		// this by checking DWORD 4, bit 31 ("LOC") of SEST entry
5112 		if (!(fcChip->SEST->u[x_ID].IWE.Buff_Off & 0x80000000)) {
5113 			PSGPAGES p, next;
5114 
5115 			// extended S/G list was used -- Free the allocated ext. S/G pages
5116 			for (p = fcChip->SEST->sgPages[x_ID]; p != NULL; p = next) {
5117 				next = p->next;
5118 				kfree(p);
5119 			}
5120 			fcChip->SEST->sgPages[x_ID] = NULL;
5121 		}
5122 
5123 		Exchanges->fcExchange[x_ID].Cmnd = NULL;
5124 	}			// Done with FCP (SEST) exchanges
5125 
5126 
5127 	// the remaining logic is common to ALL Exchanges:
5128 	// FCP(SEST) and LinkServ.
5129 
5130 	Exchanges->fcExchange[x_ID].type = 0;	// there -- FREE!
5131 	Exchanges->fcExchange[x_ID].status = 0;
5132 
5133 	PCI_TRACEO(x_ID, 0xAC)
5134 }				// (END of CompleteExchange function)
5135 
5136 
5137 
5138 
5139 // Unfortunately, we must snoop all command completions in
5140 // order to manipulate certain return fields, and take note of
5141 // device types, etc., to facilitate the Fibre-Channel to SCSI
5142 // "mapping".
5143 // (Watch for BIG Endian confusion on some payload fields)
cpqfcTSCheckandSnoopFCP(PTACHYON fcChip,u32 x_ID)5144 void cpqfcTSCheckandSnoopFCP(PTACHYON fcChip, u32 x_ID)
5145 {
5146 	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
5147 	Scsi_Cmnd *Cmnd = Exchanges->fcExchange[x_ID].Cmnd;
5148 	FCP_STATUS_RESPONSE *pFcpStatus = (PFCP_STATUS_RESPONSE) & fcChip->SEST->RspHDR[x_ID].pl;
5149 	u8 ScsiStatus;
5150 
5151 	ScsiStatus = pFcpStatus->fcp_status >> 24;
5152 
5153 #ifdef FCP_COMPLETION_DBG
5154 	printk("ScsiStatus = 0x%X\n", ScsiStatus);
5155 #endif
5156 
5157 	// First, check FCP status
5158 	if (pFcpStatus->fcp_status & FCP_RSP_LEN_VALID) {
5159 		// check response code (RSP_CODE) -- most popular is bad len
5160 		// 1st 4 bytes of rsp info -- only byte 3 interesting
5161 		if (pFcpStatus->fcp_rsp_info & FCP_DATA_LEN_NOT_BURST_LEN) {
5162 
5163 			// do we EVER get here?
5164 			printk("cpqfcTS: FCP data len not burst len, x_ID %Xh\n", x_ID);
5165 		}
5166 	}
5167 	// for now, go by the ScsiStatus, and manipulate certain
5168 	// commands when necessary...
5169 	if (ScsiStatus == 0)	// SCSI status byte "good"?
5170 	{
5171 		Cmnd->result = 0;	// everything's OK
5172 
5173 		if ((Cmnd->cmnd[0] == INQUIRY)) {
5174 			u8 *InquiryData = Cmnd->request_buffer;
5175 			PFC_LOGGEDIN_PORT pLoggedInPort;
5176 
5177 			// We need to manipulate INQUIRY
5178 			// strings for COMPAQ RAID controllers to force
5179 			// Linux to scan additional LUNs.  Namely, set
5180 			// the Inquiry string byte 2 (ANSI-approved version)
5181 			// to 2.
5182 
5183 			if (!memcmp(&InquiryData[8], "COMPAQ", 6)) {
5184 				InquiryData[2] = 0x2;	// claim SCSI-2 compliance,
5185 				// so multiple LUNs may be scanned.
5186 				// (no SCSI-2 problems known in CPQ)
5187 			}
5188 			// snoop the Inquiry to detect Disk, Tape, etc. type
5189 			// (search linked list for the port_id we sent INQUIRY to)
5190 			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// DON'T search Scsi Nexus (we will set it)
5191 							   Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF, NULL,	// DON'T search linked list for FC WWN
5192 							   NULL);	// DON'T care about end of list
5193 
5194 			if (pLoggedInPort) {
5195 				pLoggedInPort->ScsiNexus.InqDeviceType = InquiryData[0];
5196 			} else {
5197 				printk("cpqfcTS: can't find LoggedIn FC port %06X for INQUIRY\n", Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF);
5198 			}
5199 		}
5200 	}
5201 
5202 	// Scsi Status not good -- pass it back to caller
5203 
5204 	else {
5205 		Cmnd->result = ScsiStatus;	// SCSI status byte is 1st
5206 
5207 		// check for valid "sense" data
5208 
5209 		if (pFcpStatus->fcp_status & FCP_SNS_LEN_VALID) {	// limit Scsi Sense field length!
5210 			int SenseLen = pFcpStatus->fcp_sns_len >> 24;	// (BigEndian) lower byte
5211 
5212 			SenseLen = SenseLen > sizeof(Cmnd->sense_buffer) ? sizeof(Cmnd->sense_buffer) : SenseLen;
5213 
5214 
5215 #ifdef FCP_COMPLETION_DBG
5216 			printk("copy sense_buffer %p, len %d, result %Xh\n", Cmnd->sense_buffer, SenseLen, Cmnd->result);
5217 #endif
5218 
5219 			// NOTE: There is some dispute over the FCP response
5220 			// format.  Most FC devices assume that FCP_RSP_INFO
5221 			// is 8 bytes long, in spite of the fact that FCP_RSP_LEN
5222 			// is (virtually) always 0 and the field is "invalid".
5223 			// Some other devices assume that
5224 			// the FCP_SNS_INFO begins after FCP_RSP_LEN bytes (i.e. 0)
5225 			// when the FCP_RSP is invalid (this almost appears to be
5226 			// one of those "religious" issues).
5227 			// Consequently, we test the usual position of FCP_SNS_INFO
5228 			// for 7Xh, since the SCSI sense format says the first
5229 			// byte ("error code") should be 0x70 or 0x71.  In practice,
5230 			// we find that every device does in fact have 0x70 or 0x71
5231 			// in the first byte position, so this test works for all
5232 			// FC devices.
5233 			// (This logic is especially effective for the CPQ/DEC HSG80
5234 			// & HSG60 controllers).
5235 
5236 			if ((pFcpStatus->fcp_sns_info[0] & 0x70) == 0x70)
5237 				memcpy(Cmnd->sense_buffer, &pFcpStatus->fcp_sns_info[0], SenseLen);
5238 			else {
5239 				unsigned char *sbPtr = (unsigned char *) &pFcpStatus->fcp_sns_info[0];
5240 				sbPtr -= 8;	// back up 8 bytes hoping to find the
5241 				// start of the sense buffer
5242 				memcpy(Cmnd->sense_buffer, sbPtr, SenseLen);
5243 			}
5244 
5245 			// in the special case of Device Reset, tell upper layer
5246 			// to immediately retry (with SOFT_ERROR status)
5247 			// look for Sense Key Unit Attention (0x6) with ASC Device
5248 			// Reset (0x29)
5249 			//            printk("SenseLen %d, Key = 0x%X, ASC = 0x%X\n",
5250 			//                    SenseLen, Cmnd->sense_buffer[2],
5251 			//                   Cmnd->sense_buffer[12]);
5252 			if (((Cmnd->sense_buffer[2] & 0xF) == 0x6) && (Cmnd->sense_buffer[12] == 0x29))	// Sense Code "reset"
5253 			{
5254 				Cmnd->result |= (DID_SOFT_ERROR << 16);	// "Host" status byte 3rd
5255 			}
5256 			// check for SenseKey "HARDWARE ERROR", ASC InternalTargetFailure
5257 			else if (((Cmnd->sense_buffer[2] & 0xF) == 0x4) &&	// "hardware error"
5258 				 (Cmnd->sense_buffer[12] == 0x44))	// Addtl. Sense Code
5259 			{
5260 //        printk("HARDWARE_ERROR, Channel/Target/Lun %d/%d/%d\n",
5261 //              Cmnd->channel, Cmnd->target, Cmnd->lun);
5262 				Cmnd->result |= (DID_ERROR << 16);	// "Host" status byte 3rd
5263 			}
5264 
5265 		}		// (end of sense len valid)
5266 
5267 		// there is no sense data to help out Linux's Scsi layers...
5268 		// We'll just return the Scsi status and hope he will "do the
5269 		// right thing"
5270 		else {
5271 			// as far as we know, the Scsi status is sufficient
5272 			Cmnd->result |= (DID_OK << 16);	// "Host" status byte 3rd
5273 		}
5274 	}
5275 }
5276 
5277 
5278 
5279 //PPPPPPPPPPPPPPPPPPPPPPPPP  PAYLOAD  PPPPPPPPP
5280 // build data PAYLOAD; SCSI FCP_CMND I.U.
5281 // remember BIG ENDIAN payload - DWord values must be byte-reversed
5282 // (hence the affinity for byte pointer building).
5283 
build_FCP_payload(Scsi_Cmnd * Cmnd,u8 * payload,u32 type,u32 fcp_dl)5284 static int build_FCP_payload(Scsi_Cmnd * Cmnd, u8 * payload, u32 type, u32 fcp_dl)
5285 {
5286 	int i;
5287 
5288 
5289 	switch (type) {
5290 
5291 	case SCSI_IWE:
5292 	case SCSI_IRE:
5293 		// 8 bytes FCP_LUN
5294 		// Peripheral Device or Volume Set addressing, and LUN mapping
5295 		// When the FC port was looked up, we copied address mode
5296 		// and any LUN mask to the scratch pad SCp.phase & .mode
5297 
5298 		*payload++ = (u8) Cmnd->SCp.phase;
5299 
5300 		// Now, because of "lun masking"
5301 		// (aka selective storage presentation),
5302 		// the contiguous Linux Scsi lun number may not match the
5303 		// device's lun number, so we may have to "map".
5304 
5305 		*payload++ = (u8) Cmnd->SCp.have_data_in;
5306 
5307 		// We don't know of anyone in the FC business using these
5308 		// extra "levels" of addressing.  In fact, confusion still exists
5309 		// just using the FIRST level... ;-)
5310 
5311 		*payload++ = 0;	// 2nd level addressing
5312 		*payload++ = 0;
5313 		*payload++ = 0;	// 3rd level addressing
5314 		*payload++ = 0;
5315 		*payload++ = 0;	// 4th level addressing
5316 		*payload++ = 0;
5317 
5318 		// 4 bytes Control Field FCP_CNTL
5319 		*payload++ = 0;	// byte 0: (MSB) reserved
5320 		*payload++ = 0;	// byte 1: task codes
5321 
5322 		// byte 2: task management flags
5323 		// another "use" of the spare field to accomplish TDR
5324 		// note combination needed
5325 		if ((Cmnd->cmnd[0] == RELEASE) && (Cmnd->SCp.buffers_residual == FCP_TARGET_RESET)) {
5326 			Cmnd->cmnd[0] = 0;	// issue "Test Unit Ready" for TDR
5327 			*payload++ = 0x20;	// target device reset bit
5328 		} else
5329 			*payload++ = 0;	// no TDR
5330 		// byte 3: (LSB) execution management codes
5331 		// bit 0 write, bit 1 read (don't set together)
5332 
5333 		if (fcp_dl != 0) {
5334 			if (type == SCSI_IWE)	// WRITE
5335 				*payload++ = 1;
5336 			else	// READ
5337 				*payload++ = 2;
5338 		} else {
5339 			// On some devices, if RD or WR bits are set,
5340 			// and fcp_dl is 0, they will generate an error on the command.
5341 			// (i.e., if direction is specified, they insist on a length).
5342 			*payload++ = 0;	// no data (necessary for CPQ)
5343 		}
5344 
5345 
5346 		// NOTE: clean this up if/when MAX_COMMAND_SIZE is increased to 16
5347 		// FCP_CDB allows 16 byte SCSI command descriptor blk;
5348 		// Linux SCSI CDB array is MAX_COMMAND_SIZE (12 at this time...)
5349 		for (i = 0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++)
5350 			*payload++ = Cmnd->cmnd[i];
5351 
5352 		if (Cmnd->cmd_len == 16) {
5353 			memcpy(payload, &Cmnd->SCp.buffers_residual, 4);
5354 		}
5355 		payload += (16 - i);
5356 
5357 		// FCP_DL is largest number of expected data bytes
5358 		// per CDB (i.e. read/write command)
5359 		*payload++ = (u8) (fcp_dl >> 24);	// (MSB) 8 bytes data len FCP_DL
5360 		*payload++ = (u8) (fcp_dl >> 16);
5361 		*payload++ = (u8) (fcp_dl >> 8);
5362 		*payload++ = (u8) fcp_dl;	// (LSB)
5363 		break;
5364 
5365 	case SCSI_TWE:		// need FCP_XFER_RDY
5366 		*payload++ = 0;	// (4 bytes) DATA_RO (MSB byte 0)
5367 		*payload++ = 0;
5368 		*payload++ = 0;
5369 		*payload++ = 0;	// LSB (byte 3)
5370 		// (4 bytes) BURST_LEN
5371 		// size of following FCP_DATA payload
5372 		*payload++ = (u8) (fcp_dl >> 24);	// (MSB) 8 bytes data len FCP_DL
5373 		*payload++ = (u8) (fcp_dl >> 16);
5374 		*payload++ = (u8) (fcp_dl >> 8);
5375 		*payload++ = (u8) fcp_dl;	// (LSB)
5376 		// 4 bytes RESERVED
5377 		*payload++ = 0;
5378 		*payload++ = 0;
5379 		*payload++ = 0;
5380 		*payload++ = 0;
5381 		break;
5382 
5383 	default:
5384 		break;
5385 	}
5386 
5387 	return 0;
5388 }
5389