PageRenderTime 46ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/scsi/cpqfcTSworker.c

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