OSDN Git Service

2.4: USB: fix DoS in pwc USB video driver
[linux-kernel-docs/linux-2.4.36.git] / drivers / scsi / cpqfcTSworker.c
1 /* Copyright(c) 2000, Compaq Computer Corporation 
2  * Fibre Channel Host Bus Adapter 
3  * 64-bit, 66MHz PCI 
4  * Originally developed and tested on:
5  * (front): [chip] Tachyon TS HPFC-5166A/1.2  L2C1090 ...
6  *          SP# P225CXCBFIEL6T, Rev XC
7  *          SP# 161290-001, Rev XD
8  * (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by the
12  * Free Software Foundation; either version 2, or (at your option) any
13  * later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  * Written by Don Zimmerman
20 */
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
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 //
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
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
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
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.
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
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
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
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
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
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
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
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
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
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)
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
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.
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
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
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)
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 // 
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
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
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
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
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.
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
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
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 //
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
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
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
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
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
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
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
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
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
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
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)
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
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 }