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