1 /* Copyright 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 /* These functions control the host bus adapter (HBA) hardware. The main chip
22 control takes place in the interrupt handler where we process the IMQ
23 (Inbound Message Queue). The IMQ is Tachyon's way of communicating FC link
24 events and state information to the driver. The Single Frame Queue (SFQ)
25 buffers incoming FC frames for processing by the driver. References to
26 "TL/TS UG" are for:
27 "HP HPFC-5100/5166 Tachyon TL/TS ICs User Guide", August 16, 1999, 1st Ed.
28 Hewlitt Packard Manual Part Number 5968-1083E.
29 */
30
31 #include <linux/blk.h>
32 #include <linux/kernel.h>
33 #include <linux/string.h>
34 #include <linux/ioport.h> // request_region() prototype
35 #include <linux/sched.h>
36 #include <linux/slab.h> // need "kfree" for ext. S/G pages
37 #include <linux/types.h>
38 #include <linux/pci.h>
39 #include <linux/delay.h>
40 #include <linux/unistd.h>
41 #include <asm/io.h> // struct pt_regs for IRQ handler & Port I/O
42 #include <asm/irq.h>
43 #include <linux/spinlock.h>
44
45 #include "sd.h"
46 #include "hosts.h" // Scsi_Host definition for INT handler
47 #include "cpqfcTSchip.h"
48 #include "cpqfcTSstructs.h"
49
50 //#define IMQ_DEBUG 1
51
52 static void fcParseLinkStatusCounters(TACHYON * fcChip);
53 static void CpqTsGetSFQEntry(TACHYON * fcChip, u16 pi, u32 * buffr, u8 UpdateChip);
54
cpqfc_free_dma_consistent(CPQFCHBA * cpqfcHBAdata)55 static void cpqfc_free_dma_consistent(CPQFCHBA * cpqfcHBAdata)
56 {
57 // free up the primary EXCHANGES struct and Link Q
58 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
59
60 if (fcChip->Exchanges != NULL)
61 pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_EXCHANGES), fcChip->Exchanges, fcChip->exch_dma_handle);
62 fcChip->Exchanges = NULL;
63 if (cpqfcHBAdata->fcLQ != NULL)
64 pci_free_consistent(cpqfcHBAdata->PciDev, sizeof(FC_LINK_QUE), cpqfcHBAdata->fcLQ, cpqfcHBAdata->fcLQ_dma_handle);
65 cpqfcHBAdata->fcLQ = NULL;
66 }
67
68 // Note special requirements for Q alignment! (TL/TS UG pg. 190)
69 // We place critical index pointers at end of QUE elements to assist
70 // in non-symbolic (i.e. memory dump) debugging
71 // opcode defines placement of Queues (e.g. local/external RAM)
72
CpqTsCreateTachLiteQues(void * pHBA,int opcode)73 int CpqTsCreateTachLiteQues(void *pHBA, int opcode)
74 {
75 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
76 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
77
78 int iStatus = 0;
79 unsigned long ulAddr;
80 dma_addr_t ERQdma, IMQdma, SPQdma, SESTdma;
81 int i;
82
83 // NOTE! fcMemManager() will return system virtual addresses.
84 // System (kernel) virtual addresses, though non-paged, still
85 // aren't physical addresses. Convert to PHYSICAL_ADDRESS for Tachyon's
86 // DMA use.
87 ENTER("CreateTachLiteQues");
88
89
90 // Allocate primary EXCHANGES array...
91 fcChip->Exchanges = NULL;
92 cpqfcHBAdata->fcLQ = NULL;
93
94 printk("Allocating %u for %u Exchanges ", (u32) sizeof(FC_EXCHANGES), TACH_MAX_XID);
95 fcChip->Exchanges = pci_alloc_consistent(cpqfcHBAdata->PciDev, sizeof(FC_EXCHANGES), &fcChip->exch_dma_handle);
96 printk("@ %p\n", fcChip->Exchanges);
97
98 if (fcChip->Exchanges == NULL) // fatal error!!
99 {
100 printk("pci_alloc_consistent failure on Exchanges: fatal error\n");
101 return -1;
102 }
103 // zero out the entire EXCHANGE space
104 memset(fcChip->Exchanges, 0, sizeof(FC_EXCHANGES));
105
106
107 printk("Allocating %u for LinkQ ", (u32) sizeof(FC_LINK_QUE));
108 cpqfcHBAdata->fcLQ = pci_alloc_consistent(cpqfcHBAdata->PciDev, sizeof(FC_LINK_QUE), &cpqfcHBAdata->fcLQ_dma_handle);
109 printk("@ %p (%u elements)\n", cpqfcHBAdata->fcLQ, FC_LINKQ_DEPTH);
110 memset(cpqfcHBAdata->fcLQ, 0, sizeof(FC_LINK_QUE));
111
112 if (cpqfcHBAdata->fcLQ == NULL) // fatal error!!
113 {
114 cpqfc_free_dma_consistent(cpqfcHBAdata);
115 printk("pci_alloc_consistent() failure on fc Link Que: fatal error\n");
116 return -1;
117 }
118 // zero out the entire EXCHANGE space
119 memset(cpqfcHBAdata->fcLQ, 0, sizeof(FC_LINK_QUE));
120
121 // Verify that basic Tach I/O registers are not NULL
122 if (!fcChip->Registers.ReMapMemBase) {
123 cpqfc_free_dma_consistent(cpqfcHBAdata);
124 printk("HBA base address NULL: fatal error\n");
125 return -1;
126 }
127
128 // Initialize the fcMemManager memory pairs (stores allocated/aligned
129 // pairs for future freeing)
130 memset(cpqfcHBAdata->dynamic_mem, 0, sizeof(cpqfcHBAdata->dynamic_mem));
131
132
133 // Allocate Tach's Exchange Request Queue (each ERQ entry 32 bytes)
134
135 fcChip->ERQ = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachLiteERQ), 32 * (ERQ_LEN), 0L, &ERQdma);
136 if (!fcChip->ERQ) {
137 cpqfc_free_dma_consistent(cpqfcHBAdata);
138 printk("pci_alloc_consistent/alignment failure on ERQ: fatal error\n");
139 return -1;
140 }
141 fcChip->ERQ->length = ERQ_LEN - 1;
142 ulAddr = (u32) ERQdma;
143 #if BITS_PER_LONG > 32
144 if ((ulAddr >> 32)) {
145 cpqfc_free_dma_consistent(cpqfcHBAdata);
146 printk(" FATAL! ERQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
147 return -1; // failed
148 }
149 #endif
150 fcChip->ERQ->base = (u32) ulAddr; // copy for quick reference
151
152
153 // Allocate Tach's Inbound Message Queue (32 bytes per entry)
154
155 fcChip->IMQ = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachyonIMQ), 32 * (IMQ_LEN), 0L, &IMQdma);
156 if (!fcChip->IMQ) {
157 cpqfc_free_dma_consistent(cpqfcHBAdata);
158 printk("pci_alloc_consistent/alignment failure on IMQ: fatal error\n");
159 return -1;
160 }
161 fcChip->IMQ->length = IMQ_LEN - 1;
162
163 ulAddr = IMQdma;
164 #if BITS_PER_LONG > 32
165 if ((ulAddr >> 32)) {
166 cpqfc_free_dma_consistent(cpqfcHBAdata);
167 printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
168 return -1; // failed
169 }
170 #endif
171 fcChip->IMQ->base = (u32) ulAddr; // copy for quick reference
172
173
174 // Allocate Tach's Single Frame Queue (64 bytes per entry)
175 fcChip->SFQ = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachLiteSFQ), 64 * (SFQ_LEN), 0L, &SPQdma);
176 if (!fcChip->SFQ) {
177 cpqfc_free_dma_consistent(cpqfcHBAdata);
178 printk("pci_alloc_consistent/alignment failure on SFQ: fatal error\n");
179 return -1;
180 }
181 fcChip->SFQ->length = SFQ_LEN - 1; // i.e. Que length [# entries -
182 // min. 32; max. 4096 (0xffff)]
183
184 ulAddr = SPQdma;
185 #if BITS_PER_LONG > 32
186 if ((ulAddr >> 32)) {
187 cpqfc_free_dma_consistent(cpqfcHBAdata);
188 printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
189 return -1; // failed
190 }
191 #endif
192 fcChip->SFQ->base = (u32) ulAddr; // copy for quick reference
193
194
195 // Allocate SCSI Exchange State Table; aligned nearest @sizeof
196 // power-of-2 boundary
197 // LIVE DANGEROUSLY! Assume the boundary for SEST mem will
198 // be on physical page (e.g. 4k) boundary.
199 printk("Allocating %u for TachSEST for %u Exchanges\n", (u32) sizeof(TachSEST), TACH_SEST_LEN);
200 fcChip->SEST = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], sizeof(TachSEST), 4, 0L, &SESTdma);
201 // sizeof(TachSEST), 64*TACH_SEST_LEN, 0L );
202 if (!fcChip->SEST) {
203 cpqfc_free_dma_consistent(cpqfcHBAdata);
204 printk("pci_alloc_consistent/alignment failure on SEST: fatal error\n");
205 return -1;
206 }
207
208 for (i = 0; i < TACH_SEST_LEN; i++) // for each exchange
209 fcChip->SEST->sgPages[i] = NULL;
210
211 fcChip->SEST->length = TACH_SEST_LEN; // e.g. DON'T subtract one
212 // (TL/TS UG, pg 153)
213
214 ulAddr = SESTdma;
215 #if BITS_PER_LONG > 32
216 if ((ulAddr >> 32)) {
217 cpqfc_free_dma_consistent(cpqfcHBAdata);
218 printk(" FATAL! SFQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
219 return -1; // failed
220 }
221 #endif
222 fcChip->SEST->base = (u32) ulAddr; // copy for quick reference
223
224
225 // Now that structures are defined,
226 // fill in Tachyon chip registers...
227
228 // EEEEEEEE EXCHANGE REQUEST QUEUE
229
230 writel(fcChip->ERQ->base, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));
231
232 writel(fcChip->ERQ->length, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_LENGTH));
233
234
235 fcChip->ERQ->producerIndex = 0L;
236 writel(fcChip->ERQ->producerIndex, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_PRODUCER_INDEX));
237
238
239 // NOTE! write consumer index last, since the write
240 // causes Tachyon to process the other registers
241
242 ulAddr = ((unsigned long) &fcChip->ERQ->consumerIndex - (unsigned long) fcChip->ERQ) + (unsigned long) ERQdma;
243
244 // NOTE! Tachyon DMAs to the ERQ consumer Index host
245 // address; must be correctly aligned
246 writel((u32) ulAddr, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_CONSUMER_INDEX_ADR));
247
248
249
250 // IIIIIIIIIIIII INBOUND MESSAGE QUEUE
251 // Tell Tachyon where the Que starts
252
253 // set the Host's pointer for Tachyon to access
254
255 printk(" cpqfcTS: writing IMQ BASE %Xh ", fcChip->IMQ->base);
256 writel(fcChip->IMQ->base, (fcChip->Registers.ReMapMemBase + IMQ_BASE));
257
258 writel(fcChip->IMQ->length, (fcChip->Registers.ReMapMemBase + IMQ_LENGTH));
259
260 writel(fcChip->IMQ->consumerIndex, (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));
261
262
263 // NOTE: TachLite DMAs to the producerIndex host address
264 // must be correctly aligned with address bits 1-0 cleared
265 // Writing the BASE register clears the PI register, so write it last
266 ulAddr = ((unsigned long) &fcChip->IMQ->producerIndex - (unsigned long) fcChip->IMQ) + (unsigned long) IMQdma;
267
268 #if BITS_PER_LONG > 32
269 if ((ulAddr >> 32)) {
270 cpqfc_free_dma_consistent(cpqfcHBAdata);
271 printk(" FATAL! IMQ ptr %p exceeds Tachyon's 32-bit register size\n", (void *) ulAddr);
272 return -1; // failed
273 }
274 #endif
275 //#if DBG
276 printk(" PI %Xh\n", (u32) ulAddr);
277 //#endif
278 writel((u32) ulAddr, (fcChip->Registers.ReMapMemBase + IMQ_PRODUCER_INDEX));
279
280
281
282 // SSSSSSSSSSSSSSS SINGLE FRAME SEQUENCE
283 // Tell TachLite where the Que starts
284
285 writel(fcChip->SFQ->base, (fcChip->Registers.ReMapMemBase + TL_MEM_SFQ_BASE));
286
287 writel(fcChip->SFQ->length, (fcChip->Registers.ReMapMemBase + TL_MEM_SFQ_LENGTH));
288
289
290 // tell TachLite where SEST table is & how long
291 writel(fcChip->SEST->base, (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE));
292
293 printk(" cpqfcTS: SEST %p(virt): Wrote base %Xh @ %p\n", fcChip->SEST, fcChip->SEST->base, fcChip->Registers.ReMapMemBase + TL_MEM_SEST_BASE);
294
295 writel(fcChip->SEST->length, (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_LENGTH));
296
297 writel((TL_EXT_SG_PAGE_COUNT - 1), (fcChip->Registers.ReMapMemBase + TL_MEM_SEST_SG_PAGE));
298
299
300 LEAVE("CreateTachLiteQues");
301
302 return iStatus;
303 }
304
305
306
307 // function to return TachLite to Power On state
308 // 1st - reset tachyon ('SOFT' reset)
309 // others - future
310
CpqTsResetTachLite(void * pHBA,int type)311 int CpqTsResetTachLite(void *pHBA, int type)
312 {
313 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
314 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
315 u32 ulBuff, i;
316 int ret_status = 0; // def. success
317
318 ENTER("ResetTach");
319
320 switch (type) {
321
322 case CLEAR_FCPORTS:
323
324 // in case he was running previously, mask Tach's interrupt
325 writeb(0, (fcChip->Registers.ReMapMemBase + IINTEN));
326
327 // de-allocate mem for any Logged in ports
328 // (e.g., our module is unloading)
329 // search the forward linked list, de-allocating
330 // the memory we allocated when the port was initially logged in
331 {
332 PFC_LOGGEDIN_PORT pLoggedInPort = fcChip->fcPorts.pNextPort;
333 PFC_LOGGEDIN_PORT ptr;
334 // printk("checking for allocated LoggedInPorts...\n");
335
336 while (pLoggedInPort) {
337 ptr = pLoggedInPort;
338 pLoggedInPort = ptr->pNextPort;
339 // printk("kfree(%p) on FC LoggedInPort port_id 0x%06lX\n",
340 // ptr, ptr->port_id);
341 kfree(ptr);
342 }
343 }
344 // (continue resetting hardware...)
345
346 case 1: // RESTART Tachyon (power-up state)
347
348 // in case he was running previously, mask Tach's interrupt
349 writeb(0, (fcChip->Registers.ReMapMemBase + IINTEN));
350 // turn OFF laser (NOTE: laser is turned
351 // off during reset, because GPIO4 is cleared
352 // to 0 by reset action - see TLUM, sec 7.22)
353 // However, CPQ 64-bit HBAs have a "health
354 // circuit" which keeps laser ON for a brief
355 // period after it is turned off ( < 1s)
356
357 fcChip->LaserControl(fcChip->Registers.ReMapMemBase, 0);
358
359
360
361 // soft reset timing constraints require:
362 // 1. set RST to 1
363 // 2. read SOFTRST register
364 // (128 times per R. Callison code)
365 // 3. clear PCI ints
366 // 4. clear RST to 0
367 writel(0xff000001L, (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));
368
369 for (i = 0; i < 128; i++)
370 ulBuff = readl(fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST);
371
372 // clear the soft reset
373 for (i = 0; i < 8; i++)
374 writel(0, (fcChip->Registers.ReMapMemBase + TL_MEM_SOFTRST));
375
376
377
378 // clear out our copy of Tach regs,
379 // because they must be invalid now,
380 // since TachLite reset all his regs.
381 CpqTsDestroyTachLiteQues(cpqfcHBAdata, 0); // remove Host-based Que structs
382 cpqfcTSClearLinkStatusCounters(fcChip); // clear our s/w accumulators
383 // lower bits give GBIC info
384 fcChip->Registers.TYstatus.value = readl(fcChip->Registers.TYstatus.address);
385 break;
386
387 /*
388 case 2: // freeze SCSI
389 case 3: // reset Outbound command que (ERQ)
390 case 4: // unfreeze OSM (Outbound Seq. Man.) 'er'
391 case 5: // report status
392
393 break;
394 */
395 default:
396 ret_status = -1; // invalid option passed to RESET function
397 break;
398 }
399 LEAVE("ResetTach");
400 return ret_status;
401 }
402
403
404
405
406
407
408 // 'addrBase' is IOBaseU for both TachLite and (older) Tachyon
CpqTsLaserControl(void * addrBase,int opcode)409 int CpqTsLaserControl(void *addrBase, int opcode)
410 {
411 u32 dwBuff;
412
413 dwBuff = readl((addrBase + TL_MEM_TACH_CONTROL)); // read TL Control reg
414 // (change only bit 4)
415 if (opcode == 1)
416 dwBuff |= ~0xffffffefL; // set - ON
417 else
418 dwBuff &= 0xffffffefL; // clear - OFF
419 writel(dwBuff, (addrBase + TL_MEM_TACH_CONTROL)); // write TL Control reg
420 return 0;
421 }
422
423
424
425
426
427 // Use controller's "Options" field to determine loopback mode (if any)
428 // internal loopback (silicon - no GBIC)
429 // external loopback (GBIC - no FC loop)
430 // no loopback: L_PORT, external cable from GBIC required
431
CpqTsInitializeFrameManager(void * pChip,int opcode)432 int CpqTsInitializeFrameManager(void *pChip, int opcode)
433 {
434 PTACHYON fcChip;
435 int iStatus;
436 u32 wwnLo, wwnHi; // for readback verification
437
438 ENTER("InitializeFrameManager");
439 fcChip = (PTACHYON) pChip;
440 if (!fcChip->Registers.ReMapMemBase) // undefined controller?
441 return -1;
442
443 // TL/TS UG, pg. 184
444 // 0x0065 = 100ms for RT_TOV
445 // 0x01f5 = 500ms for ED_TOV
446 // 0x07D1 = 2000ms
447 fcChip->Registers.ed_tov.value = 0x006507D1;
448 writel(fcChip->Registers.ed_tov.value, (fcChip->Registers.ed_tov.address));
449
450
451 // Set LP_TOV to the FC-AL2 specified 2 secs.
452 // TL/TS UG, pg. 185
453 writel(0x07d00010, fcChip->Registers.ReMapMemBase + TL_MEM_FM_TIMEOUT2);
454
455
456 // Now try to read the WWN from the adapter's NVRAM
457 iStatus = CpqTsReadWriteWWN(fcChip, 1); // '1' for READ
458
459 if (iStatus) // NVRAM read failed?
460 {
461 printk(" WARNING! HBA NVRAM WWN read failed - make alias\n");
462 // make up a WWN. If NULL or duplicated on loop, FC loop may hang!
463
464
465 fcChip->Registers.wwn_hi = (__u32) jiffies;
466 fcChip->Registers.wwn_hi |= 0x50000000L;
467 fcChip->Registers.wwn_lo = 0x44556677L;
468 }
469
470
471 writel(fcChip->Registers.wwn_hi, fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI);
472
473 writel(fcChip->Registers.wwn_lo, fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);
474
475
476 // readback for verification:
477 wwnHi = readl(fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_HI);
478
479 wwnLo = readl(fcChip->Registers.ReMapMemBase + TL_MEM_FM_WWN_LO);
480 // test for correct chip register WRITE/READ
481 DEBUG_PCI(printk(" WWN %08X%08X\n", fcChip->Registers.wwn_hi, fcChip->Registers.wwn_lo));
482
483 if (wwnHi != fcChip->Registers.wwn_hi || wwnLo != fcChip->Registers.wwn_lo) {
484 printk("cpqfcTS: WorldWideName register load failed\n");
485 return -1; // FAILED!
486 }
487
488
489 // set Frame Manager Initialize command
490 fcChip->Registers.FMcontrol.value = 0x06;
491
492 // Note: for test/debug purposes, we may use "Hard" address,
493 // but we completely support "soft" addressing, including
494 // dynamically changing our address.
495 if (fcChip->Options.intLoopback == 1) // internal loopback
496 fcChip->Registers.FMconfig.value = 0x0f002080L;
497 else if (fcChip->Options.extLoopback == 1) // internal loopback
498 fcChip->Registers.FMconfig.value = 0x0f004080L;
499 else // L_Port
500 fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start)
501 // fcChip->Registers.FMconfig.value = 0x01000080L; // soft address (can't pick)
502 // fcChip->Registers.FMconfig.value = 0x55000100L; // hard address (55h start)
503
504 // write config to FM
505
506 if (!fcChip->Options.intLoopback && !fcChip->Options.extLoopback)
507 // (also need LASER for real LOOP)
508 fcChip->LaserControl(fcChip->Registers.ReMapMemBase, 1); // turn on LASER
509
510 writel(fcChip->Registers.FMconfig.value, fcChip->Registers.FMconfig.address);
511
512
513 // issue INITIALIZE command to FM - ACTION!
514 writel(fcChip->Registers.FMcontrol.value, fcChip->Registers.FMcontrol.address);
515
516 LEAVE("InitializeFrameManager");
517
518 return 0;
519 }
520
521
522
523
524
525 // This "look ahead" function examines the IMQ for occurence of
526 // "type". Returns 1 if found, 0 if not.
PeekIMQEntry(PTACHYON fcChip,u32 type)527 static int PeekIMQEntry(PTACHYON fcChip, u32 type)
528 {
529 u32 CI = fcChip->IMQ->consumerIndex;
530 u32 PI = fcChip->IMQ->producerIndex; // snapshot of IMQ indexes
531
532 while (CI != PI) { // proceed with search
533 if ((++CI) >= IMQ_LEN)
534 CI = 0; // rollover check
535
536 switch (type) {
537 case ELS_LILP_FRAME:
538 {
539 // first, we need to find an Inbound Completion message,
540 // If we find it, check the incoming frame payload (1st word)
541 // for LILP frame
542 if ((fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x104) {
543 TachFCHDR_GCMND *fchs;
544 u32 ulFibreFrame[2048 / 4]; // max DWORDS in incoming FC Frame
545 u16 SFQpi = (u16) (fcChip->IMQ->QEntry[CI].word[0] & 0x0fffL);
546
547 CpqTsGetSFQEntry(fcChip, SFQpi, // SFQ producer ndx
548 ulFibreFrame, // contiguous dest. buffer
549 FALSE); // DON'T update chip--this is a "lookahead"
550
551 fchs = (TachFCHDR_GCMND *) & ulFibreFrame;
552 if (fchs->pl[0] == ELS_LILP_FRAME) {
553 return 1; // found the LILP frame!
554 } else {
555 // keep looking...
556 }
557 }
558 }
559 break;
560
561 case OUTBOUND_COMPLETION:
562 if ((fcChip->IMQ->QEntry[CI].type & 0x1FF) == 0x00) {
563
564 // any OCM errors?
565 if (fcChip->IMQ->QEntry[CI].word[2] & 0x7a000000L)
566 return 1; // found OCM error
567 }
568 break;
569
570
571
572 default:
573 break;
574 }
575 }
576 return 0; // failed to find "type"
577 }
578
579
SetTachTOV(CPQFCHBA * cpqfcHBAdata)580 static void SetTachTOV(CPQFCHBA * cpqfcHBAdata)
581 {
582 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
583
584 // TL/TS UG, pg. 184
585 // 0x0065 = 100ms for RT_TOV
586 // 0x01f5 = 500ms for ED_TOV
587 // 0x07d1 = 2000ms for ED_TOV
588
589 // SANMark Level 1 requires an "initialization backoff"
590 // (See "SANMark Test Suite Level 1":
591 // initialization_timeout.fcal.SANMark-1.fc)
592 // We have to use 2sec, 24sec, then 128sec when login/
593 // port discovery processes fail to complete.
594
595 // when port discovery completes (logins done), we set
596 // ED_TOV to 500ms -- this is the normal operational case
597 // On the first Link Down, we'll move to 2 secs (7D1 ms)
598 if ((fcChip->Registers.ed_tov.value & 0xFFFF) <= 0x1f5)
599 fcChip->Registers.ed_tov.value = 0x006507D1;
600
601 // If we get another LST after we moved TOV to 2 sec,
602 // increase to 24 seconds (5DC1 ms) per SANMark!
603 else if ((fcChip->Registers.ed_tov.value & 0xFFFF) <= 0x7D1)
604 fcChip->Registers.ed_tov.value = 0x00655DC1;
605
606 // If we get still another LST, set the max TOV (Tachyon
607 // has only 16 bits for ms timer, so the max is 65.5 sec)
608 else if ((fcChip->Registers.ed_tov.value & 0xFFFF) <= 0x5DC1)
609 fcChip->Registers.ed_tov.value = 0x0065FFFF;
610
611 writel(fcChip->Registers.ed_tov.value, (fcChip->Registers.ed_tov.address));
612 // keep the same 2sec LP_TOV
613 writel(0x07D00010, fcChip->Registers.ReMapMemBase + TL_MEM_FM_TIMEOUT2);
614 }
615
616
617 // The IMQ is an array with IMQ_LEN length, each element (QEntry)
618 // with eight 32-bit words. Tachyon PRODUCES a QEntry with each
619 // message it wants to send to the host. The host CONSUMES IMQ entries
620
621 // This function copies the current
622 // (or oldest not-yet-processed) QEntry to
623 // the caller, clears/ re-enables the interrupt, and updates the
624 // (Host) Consumer Index.
625 // Return value:
626 // 0 message processed, none remain (producer and consumer
627 // indexes match)
628 // 1 message processed, more messages remain
629 // -1 no message processed - none were available to process
630 // Remarks:
631 // TL/TS UG specifices that the following actions for
632 // INTA_L handling:
633 // 1. read PCI Interrupt Status register (0xff)
634 // 2. all IMQ messages should be processed before writing the
635 // IMQ consumer index.
636
637
CpqTsProcessIMQEntry(void * host)638 int CpqTsProcessIMQEntry(void *host)
639 {
640 struct Scsi_Host *HostAdapter = (struct Scsi_Host *) host;
641 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
642 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
643 FC_EXCHANGES *Exchanges = fcChip->Exchanges;
644 int iStatus;
645 u16 i, RPCset, DPCset;
646 u32 x_ID;
647 u32 ulBuff, dwStatus;
648 TachFCHDR_GCMND *fchs;
649 u32 ulFibreFrame[2048 / 4]; // max number of DWORDS in incoming Fibre Frame
650 u8 ucInboundMessageType; // Inbound CM, dword 3 "type" field
651
652 ENTER("ProcessIMQEntry");
653
654
655 // check TachLite's IMQ producer index -
656 // is a new message waiting for us?
657 // equal indexes means empty que
658
659 if (fcChip->IMQ->producerIndex != fcChip->IMQ->consumerIndex) { // need to process message
660
661
662 #ifdef IMQ_DEBUG
663 printk("PI %X, CI %X type: %X\n", fcChip->IMQ->producerIndex, fcChip->IMQ->consumerIndex, fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type);
664 #endif
665 // Examine Completion Messages in IMQ
666 // what CM_Type?
667 switch ((u8) (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].type & 0xffL)) {
668 case OUTBOUND_COMPLETION:
669
670 // Remarks:
671 // x_IDs (OX_ID, RX_ID) are partitioned by SEST entries
672 // (starting at 0), and SFS entries (starting at
673 // SEST_LEN -- outside the SEST space).
674 // Psuedo code:
675 // x_ID (OX_ID or RX_ID) from message is Trans_ID or SEST index
676 // range check - x_ID
677 // if x_ID outside 'Transactions' length, error - exit
678 // if any OCM error, copy error status to Exchange slot
679 // if FCP ASSIST transaction (x_ID within SEST),
680 // call fcComplete (to App)
681 // ...
682
683
684 ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1];
685 x_ID = ulBuff & 0x7fffL; // lower 14 bits SEST_Index/Trans_ID
686 // Range check CM OX/RX_ID value...
687 if (x_ID < TACH_MAX_XID) // don't go beyond array space
688 {
689
690
691 if (ulBuff & 0x20000000L) // RPC -Response Phase Complete?
692 RPCset = 1; // (SEST transactions only)
693 else
694 RPCset = 0;
695
696 if (ulBuff & 0x40000000L) // DPC -Data Phase Complete?
697 DPCset = 1; // (SEST transactions only)
698 else
699 DPCset = 0;
700 // set the status for this Outbound transaction's ID
701 dwStatus = 0L;
702 if (ulBuff & 0x10000000L) // SPE? (SEST Programming Error)
703 dwStatus |= SESTPROG_ERR;
704
705 ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2];
706 if (ulBuff & 0x7a000000L) // any other errs?
707 {
708 if (ulBuff & 0x40000000L)
709 dwStatus |= INV_ENTRY;
710 if (ulBuff & 0x20000000L)
711 dwStatus |= FRAME_TO; // FTO
712 if (ulBuff & 0x10000000L)
713 dwStatus |= HOSTPROG_ERR;
714 if (ulBuff & 0x08000000L)
715 dwStatus |= LINKFAIL_TX;
716 if (ulBuff & 0x02000000L)
717 dwStatus |= ABORTSEQ_NOTIFY; // ASN
718 }
719
720
721 if (dwStatus) // any errors?
722 {
723 // set the Outbound Completion status
724 Exchanges->fcExchange[x_ID].status |= dwStatus;
725
726 // if this Outbound frame was for a SEST entry, automatically
727 // reque it in the case of LINKFAIL (it will restart on PDISC)
728 if (x_ID < TACH_SEST_LEN) {
729
730 printk(" #OCM error %Xh x_ID %X# ", dwStatus, x_ID);
731
732 Exchanges->fcExchange[x_ID].timeOut = 30000; // seconds default
733
734
735 // We Q ABTS for each exchange.
736 // NOTE: We can get FRAME_TO on bad alpa (device gone). Since
737 // bad alpa is reported before FRAME_TO, examine the status
738 // flags to see if the device is removed. If so, DON'T
739 // post an ABTS, since it will be terminated by the bad alpa
740 // message.
741 if (dwStatus & FRAME_TO) // check for device removed...
742 {
743 if (!(Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED)) {
744 // presumes device is still there: send ABTS.
745
746 cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, &x_ID);
747 }
748 } else // Abort all other errors
749 {
750 cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, &x_ID);
751 }
752
753 // if the HPE bit is set, we have to CLose the LOOP
754 // (see TL/TS UG, pg. 239)
755
756 if (dwStatus &= HOSTPROG_ERR)
757 // set CL bit (see TL/TS UG, pg. 172)
758 writel(4, fcChip->Registers.FMcontrol.address);
759 }
760 }
761 // NOTE: we don't necessarily care about ALL completion messages...
762 // SCSI resp. complete OR
763 if (((x_ID < TACH_SEST_LEN) && RPCset) || (x_ID >= TACH_SEST_LEN)) // non-SCSI command
764 {
765 // exchange done; complete to upper levels with status
766 // (if necessary) and free the exchange slot
767
768
769 if (x_ID >= TACH_SEST_LEN) // Link Service Outbound frame?
770 // A Request or Reply has been sent
771 { // signal waiting WorkerThread
772
773 up(cpqfcHBAdata->TYOBcomplete); // frame is OUT of Tach
774
775 // WorkerThread will complete Xchng
776 } else // X_ID is for FCP assist (SEST)
777 {
778 // TBD (target mode)
779 // fcCompleteExchange( fcChip, x_ID); // TRE completed
780 }
781 }
782 } else // ERROR CONDITION! bogus x_ID in completion message
783 {
784
785 printk(" ProcessIMQ (OBCM) x_id out of range %Xh\n", x_ID);
786
787 }
788
789
790
791 // Load the Frame Manager's error counters. We check them here
792 // because presumably the link is up and healthy enough for the
793 // counters to be meaningful (i.e., don't check them while loop
794 // is initializing).
795 fcChip->Registers.FMLinkStatus1.value = // get TL's counter
796 readl(fcChip->Registers.FMLinkStatus1.address);
797
798 fcChip->Registers.FMLinkStatus2.value = // get TL's counter
799 readl(fcChip->Registers.FMLinkStatus2.address);
800
801
802 fcParseLinkStatusCounters(fcChip); // load into 6 s/w accumulators
803 break;
804
805
806
807 case ERROR_IDLE_COMPLETION: // TachLite Error Idle...
808
809 // We usually get this when the link goes down during heavy traffic.
810 // For now, presume that if SEST Exchanges are open, we will
811 // get this as our cue to INVALIDATE all SEST entries
812 // (and we OWN all the SEST entries).
813 // See TL/TS UG, pg. 53
814
815 for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
816
817 // Does this VALid SEST entry need to be invalidated for Abort?
818 fcChip->SEST->u[x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;
819 }
820
821 CpqTsUnFreezeTachlite(fcChip, 2); // unfreeze Tachyon, if Link OK
822
823 break;
824
825
826 case INBOUND_SFS_COMPLETION: //0x04
827 // NOTE! we must process this SFQ message to avoid SFQ filling
828 // up and stopping TachLite. Incoming commands are placed here,
829 // as well as 'unknown' frames (e.g. LIP loop position data)
830 // write this CM's producer index to global...
831 // TL/TS UG, pg 234:
832 // Type: 0 - reserved
833 // 1 - Unassisted FCP
834 // 2 - BAD FCP
835 // 3 - Unkown Frame
836 // 4-F reserved
837
838
839 fcChip->SFQ->producerIndex = (u16)
840 (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] & 0x0fffL);
841
842
843 ucInboundMessageType = 0; // default to useless frame
844
845 // we can only process two Types: 1, Unassisted FCP, and 3, Unknown
846 // Also, we aren't interested in processing frame fragments
847 // so don't Que anything with 'LKF' bit set
848 if (!(fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2]
849 & 0x40000000)) // 'LKF' link failure bit clear?
850 {
851 ucInboundMessageType = (u8) // ICM DWord3, "Type"
852 (fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] & 0x0fL);
853 } else {
854 fcChip->fcStats.linkFailRX++;
855 // printk("LKF (link failure) bit set on inbound message\n");
856 }
857
858 // clears SFQ entry from Tachyon buffer; copies to contiguous ulBuff
859 CpqTsGetSFQEntry(fcChip, // i.e. this Device Object
860 (u16) fcChip->SFQ->producerIndex, // SFQ producer ndx
861 ulFibreFrame, TRUE); // contiguous destination buffer, update chip
862
863 // analyze the incoming frame outside the INT handler...
864 // (i.e., Worker)
865
866 if (ucInboundMessageType == 1) {
867 fchs = (TachFCHDR_GCMND *) ulFibreFrame; // cast to examine IB frame
868 // don't fill up our Q with garbage - only accept FCP-CMND
869 // or XRDY frames
870 if ((fchs->d_id & 0xFF000000) == 0x06000000) // CMND
871 {
872 // someone sent us a SCSI command
873
874 // fcPutScsiQue( cpqfcHBAdata,
875 // SFQ_UNASSISTED_FCP, ulFibreFrame);
876 } else if (((fchs->d_id & 0xFF000000) == 0x07000000) || // RSP (status)
877 (fchs->d_id & 0xFF000000) == 0x05000000) // XRDY
878 {
879 u32 x_ID;
880 // Unfortunately, ABTS requires a Freeze on the chip so
881 // we can modify the shared memory SEST. When frozen,
882 // any received Exchange frames cannot be processed by
883 // Tachyon, so they will be dumped in here. It is too
884 // complex to attempt the reconstruct these frames in
885 // the correct Exchange context, so we simply seek to
886 // find status or transfer ready frames, and cause the
887 // exchange to complete with errors before the timeout
888 // expires. We use a Linux Scsi Cmnd result code that
889 // causes immediate retry.
890
891
892 // Do we have an open exchange that matches this s_id
893 // and ox_id?
894 for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
895 if ((fchs->s_id & 0xFFFFFF) == (Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF)
896 && (fchs->ox_rx_id & 0xFFFF0000) == (Exchanges->fcExchange[x_ID].fchs.ox_rx_id & 0xFFFF0000)) {
897 // printk(" #R/X frame x_ID %08X# ", fchs->ox_rx_id );
898 // simulate the anticipated error - since the
899 // SEST was frozen, frames were lost...
900 Exchanges->fcExchange[x_ID].status |= SFQ_FRAME;
901
902 // presumes device is still there: send ABTS.
903 cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, &x_ID);
904 break; // done
905 }
906 }
907 }
908
909 }
910
911 else if (ucInboundMessageType == 3) {
912 // FC Link Service frames (e.g. PLOGI, ACC) come in here.
913 cpqfcTSPutLinkQue(cpqfcHBAdata, SFQ_UNKNOWN, ulFibreFrame);
914
915 }
916
917 else if (ucInboundMessageType == 2) // "bad FCP"?
918 {
919 #ifdef IMQ_DEBUG
920 printk("Bad FCP incoming frame discarded\n");
921 #endif
922 }
923
924 else // don't know this type
925 {
926 #ifdef IMQ_DEBUG
927 printk("Incoming frame discarded, type: %Xh\n", ucInboundMessageType);
928 #endif
929 }
930
931 // Check the Frame Manager's error counters. We check them here
932 // because presumably the link is up and healthy enough for the
933 // counters to be meaningful (i.e., don't check them while loop
934 // is initializing).
935 fcChip->Registers.FMLinkStatus1.value = // get TL's counter
936 readl(fcChip->Registers.FMLinkStatus1.address);
937
938
939 fcChip->Registers.FMLinkStatus2.value = // get TL's counter
940 readl(fcChip->Registers.FMLinkStatus2.address);
941
942
943 break;
944
945
946
947
948 // We get this CM because we issued a freeze
949 // command to stop outbound frames. We issue the
950 // freeze command at Link Up time; when this message
951 // is received, the ERQ base can be switched and PDISC
952 // frames can be sent.
953
954
955 case ERQ_FROZEN_COMPLETION: // note: expect ERQ followed immediately
956 // by FCP when freezing TL
957 fcChip->Registers.TYstatus.value = // read what's frozen
958 readl(fcChip->Registers.TYstatus.address);
959 // (do nothing; wait for FCP frozen message)
960 break;
961 case FCP_FROZEN_COMPLETION:
962
963 fcChip->Registers.TYstatus.value = // read what's frozen
964 readl(fcChip->Registers.TYstatus.address);
965
966 // Signal the kernel thread to proceed with SEST modification
967 up(cpqfcHBAdata->TachFrozen);
968
969 break;
970
971
972
973 case INBOUND_C1_TIMEOUT:
974 case MFS_BUF_WARN:
975 case IMQ_BUF_WARN:
976 break;
977
978
979
980
981
982 // In older Tachyons, we 'clear' the internal 'core' interrupt state
983 // by reading the FMstatus register. In newer TachLite (Tachyon),
984 // we must WRITE the register
985 // to clear the condition (TL/TS UG, pg 179)
986 case FRAME_MGR_INTERRUPT:
987 {
988 PFC_LOGGEDIN_PORT pLoggedInPort;
989
990 fcChip->Registers.FMstatus.value = readl(fcChip->Registers.FMstatus.address);
991
992 // PROBLEM: It is possible, especially with "dumb" hubs that
993 // don't automatically LIP on by-pass of ports that are going
994 // away, for the hub by-pass process to destroy critical
995 // ordered sets of a frame. The result of this is a hung LPSM
996 // (Loop Port State Machine), which on Tachyon results in a
997 // (default 2 sec) Loop State Timeout (LST) FM message. We
998 // want to avoid this relatively huge timeout by detecting
999 // likely scenarios which will result in LST.
1000 // To do this, we could examine FMstatus for Loss of Synchronization
1001 // and/or Elastic Store (ES) errors. Of these, Elastic Store is better
1002 // because we get this indication more quickly than the LOS.
1003 // Not all ES errors are harmfull, so we don't want to LIP on every
1004 // ES. Instead, on every ES, detect whether our LPSM in in one
1005 // of the LST states: ARBITRATING, OPEN, OPENED, XMITTED CLOSE,
1006 // or RECEIVED CLOSE. (See TL/TS UG, pg. 181)
1007 // If any of these LPSM states are detected
1008 // in combination with the LIP while LDn is not set,
1009 // send an FM init (LIP F7,F7 for loops)!
1010 // It is critical to the physical link stability NOT to reset (LIP)
1011 // more than absolutely necessary; this is a basic premise of the
1012 // SANMark level 1 spec.
1013 {
1014 u32 Lpsm = (fcChip->Registers.FMstatus.value & 0xF0) >> 4;
1015
1016 if ((fcChip->Registers.FMstatus.value & 0x400) // ElasticStore?
1017 && !(fcChip->Registers.FMstatus.value & 0x100) // NOT LDn
1018 && !(fcChip->Registers.FMstatus.value & 0x1000)) // NOT LF
1019 {
1020 if ((Lpsm != 0) || // not MONITORING? or
1021 !(Lpsm & 0x8)) // not already offline?
1022 {
1023 // now check the particular LST states...
1024 if ((Lpsm == ARBITRATING) || (Lpsm == OPEN) || (Lpsm == OPENED) || (Lpsm == XMITTD_CLOSE) || (Lpsm == RCVD_CLOSE)) {
1025 // re-init the loop before it hangs itself!
1026 printk(" #req FMinit on E-S: LPSM %Xh# ", Lpsm);
1027
1028
1029 fcChip->fcStats.FMinits++;
1030 writel(6, fcChip->Registers.FMcontrol.address); // LIP
1031 }
1032 }
1033 } else if (fcChip->Registers.FMstatus.value & 0x40000) // LST?
1034 {
1035 printk(" #req FMinit on LST, LPSM %Xh# ", Lpsm);
1036
1037 fcChip->fcStats.FMinits++;
1038 writel(6, fcChip->Registers.FMcontrol.address); // LIP
1039 }
1040 }
1041
1042
1043 // clear only the 'interrupting' type bits for this REG read
1044 writel((fcChip->Registers.FMstatus.value & 0xff3fff00L), fcChip->Registers.FMstatus.address);
1045
1046
1047 // copy frame manager status to unused u32 slot
1048 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0] = fcChip->Registers.FMstatus.value; // (for debugging)
1049
1050
1051 // Load the Frame Manager's error counters. We check them here
1052 // because presumably the link is up and healthy enough for the
1053 // counters to be meaningful (i.e., don't check them while loop
1054 // is initializing).
1055 fcChip->Registers.FMLinkStatus1.value = // get TL's counter
1056 readl(fcChip->Registers.FMLinkStatus1.address);
1057
1058 fcChip->Registers.FMLinkStatus2.value = // get TL's counter
1059 readl(fcChip->Registers.FMLinkStatus2.address);
1060
1061 // Get FM BB_Credit Zero Reg - does not clear on READ
1062 fcChip->Registers.FMBB_CreditZero.value = // get TL's counter
1063 readl(fcChip->Registers.FMBB_CreditZero.address);
1064
1065
1066
1067 fcParseLinkStatusCounters(fcChip); // load into 6 s/w accumulators
1068
1069
1070 // LINK DOWN
1071
1072 if (fcChip->Registers.FMstatus.value & 0x100L) // Link DOWN bit
1073 {
1074
1075 #ifdef IMQ_DEBUG
1076 printk("LinkDn\n");
1077 #endif
1078 printk(" #LDn# ");
1079
1080 fcChip->fcStats.linkDown++;
1081
1082 SetTachTOV(cpqfcHBAdata); // must set according to SANMark
1083
1084 // Check the ERQ - force it to be "empty" to prevent Tach
1085 // from sending out frames before we do logins.
1086
1087
1088 if (fcChip->ERQ->producerIndex != fcChip->ERQ->consumerIndex) {
1089 // printk("#ERQ PI != CI#");
1090 CpqTsFreezeTachlite(fcChip, 1); // freeze ERQ only
1091 fcChip->ERQ->producerIndex = fcChip->ERQ->consumerIndex = 0;
1092 writel(fcChip->ERQ->base, (fcChip->Registers.ReMapMemBase + TL_MEM_ERQ_BASE));
1093 // re-writing base forces ERQ PI to equal CI
1094
1095 }
1096 // link down transition occurred -- port_ids can change
1097 // on next LinkUp, so we must invalidate current logins
1098 // (and any I/O in progress) until PDISC or PLOGI/PRLI
1099 // completes
1100 {
1101 pLoggedInPort = &fcChip->fcPorts;
1102 while (pLoggedInPort) // for all ports which are expecting
1103 // PDISC after the next LIP, set the
1104 // logoutTimer
1105 {
1106
1107 if (pLoggedInPort->pdisc) // expecting PDISC within 2 sec?
1108 {
1109 pLoggedInPort->LOGO_timer = 3; // we want 2 seconds
1110 // but Timer granularity
1111 // is 1 second
1112 }
1113 // suspend any I/O in progress until
1114 // PDISC received...
1115 pLoggedInPort->prli = FALSE; // block FCP-SCSI commands
1116
1117 pLoggedInPort = pLoggedInPort->pNextPort;
1118 } // ... all Previously known ports checked
1119 }
1120
1121 // since any hot plugging device may NOT support LILP frames
1122 // (such as early Tachyon chips), clear this flag indicating
1123 // we shouldn't use (our copy of) a LILP map.
1124 // If we receive an LILP frame, we'll set it again.
1125 fcChip->Options.LILPin = 0; // our LILPmap is invalid
1126 cpqfcHBAdata->PortDiscDone = 0; // must re-validate FC ports!
1127
1128 // also, we want to invalidate (i.e. INITIATOR_ABORT) any
1129 // open Login exchanges, in case the LinkDown happened in the
1130 // middle of logins. It's possible that some ports already
1131 // ACCepted login commands which we have not processed before
1132 // another LinkDown occurred. Any accepted Login exhanges are
1133 // invalidated by LinkDown, even before they are acknowledged.
1134 // It's also possible for a port to have a Queued Reply or Request
1135 // for login which was interrupted by LinkDown; it may come later,
1136 // but it will be unacceptable to us.
1137
1138 // we must scan the entire exchange space, find every Login type
1139 // originated by us, and abort it. This is NOT an abort due to
1140 // timeout, so we don't actually send abort to the other port -
1141 // we just complete it to free up the fcExchange slot.
1142
1143 for (i = TACH_SEST_LEN; i < TACH_MAX_XID; i++) { // looking for Extended Link Serv.Exchanges
1144 if (Exchanges->fcExchange[i].type == ELS_PDISC || Exchanges->fcExchange[i].type == ELS_PLOGI || Exchanges->fcExchange[i].type == ELS_PRLI) {
1145 // ABORT the exchange!
1146 #ifdef IMQ_DEBUG
1147 printk("Originator ABORT x_id %Xh, type %Xh, port_id %Xh on LDn\n", i, Exchanges->fcExchange[i].type, Exchanges->fcExchange[i].fchs.d_id);
1148 #endif
1149
1150 Exchanges->fcExchange[i].status |= INITIATOR_ABORT;
1151 cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, i); // abort on LDn
1152 }
1153 }
1154
1155 }
1156 // ################ LINK UP ##################
1157 if (fcChip->Registers.FMstatus.value & 0x200L) // Link Up bit
1158 { // AL_PA could have changed
1159
1160 // We need the following code, duplicated from LinkDn condition,
1161 // because it's possible for the Tachyon to re-initialize (hard
1162 // reset) without ever getting a LinkDn indication.
1163 pLoggedInPort = &fcChip->fcPorts;
1164 while (pLoggedInPort) // for all ports which are expecting
1165 // PDISC after the next LIP, set the
1166 // logoutTimer
1167 {
1168 if (pLoggedInPort->pdisc) // expecting PDISC within 2 sec?
1169 {
1170 pLoggedInPort->LOGO_timer = 3; // we want 2 seconds
1171 // but Timer granularity
1172 // is 1 second
1173
1174 // suspend any I/O in progress until
1175 // PDISC received...
1176
1177 }
1178 pLoggedInPort = pLoggedInPort->pNextPort;
1179 } // ... all Previously known ports checked
1180
1181 // CpqTs acquired AL_PA in register AL_PA (ACQ_ALPA)
1182 fcChip->Registers.rcv_al_pa.value = readl(fcChip->Registers.rcv_al_pa.address);
1183
1184 // Now, if our acquired address is DIFFERENT from our
1185 // previous one, we are not allow to do PDISC - we
1186 // must go back to PLOGI, which will terminate I/O in
1187 // progress for ALL logged in FC devices...
1188 // (This is highly unlikely).
1189
1190 if ((fcChip->Registers.my_al_pa & 0xFF) != ((fcChip->Registers.rcv_al_pa.value >> 16) & 0xFF)) {
1191
1192 // printk(" #our HBA port_id changed!# "); // FC port_id changed!!
1193
1194 pLoggedInPort = &fcChip->fcPorts;
1195 while (pLoggedInPort) // for all ports which are expecting
1196 // PDISC after the next LIP, set the
1197 // logoutTimer
1198 {
1199 pLoggedInPort->pdisc = FALSE;
1200 pLoggedInPort->prli = FALSE;
1201 pLoggedInPort = pLoggedInPort->pNextPort;
1202 } // ... all Previously known ports checked
1203
1204 // when the port_id changes, we must terminate
1205 // all open exchanges.
1206 cpqfcTSTerminateExchange(cpqfcHBAdata, NULL, PORTID_CHANGED);
1207
1208 }
1209 // Replace the entire 24-bit port_id. We only know the
1210 // lower 8 bits (alpa) from Tachyon; if a FLOGI is done,
1211 // we'll get the upper 16-bits from the FLOGI ACC frame.
1212 // If someone plugs into Fabric switch, we'll do FLOGI and
1213 // get full 24-bit port_id; someone could then remove and
1214 // hot-plug us into a dumb hub. If we send a 24-bit PLOGI
1215 // to a "private" loop device, it might blow up.
1216 // Consequently, we force the upper 16-bits of port_id to
1217 // be re-set on every LinkUp transition
1218 fcChip->Registers.my_al_pa = (fcChip->Registers.rcv_al_pa.value >> 16) & 0xFF;
1219
1220
1221 // copy frame manager status to unused u32 slot
1222 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] = fcChip->Registers.my_al_pa; // (for debugging)
1223
1224 // for TachLite, we need to write the acquired al_pa
1225 // back into the FMconfig register, because after
1226 // first initialization, the AQ (prev. acq.) bit gets
1227 // set, causing TL FM to use the AL_PA field in FMconfig.
1228 // (In Tachyon, FM writes the acquired AL_PA for us.)
1229 ulBuff = readl(fcChip->Registers.FMconfig.address);
1230 ulBuff &= 0x00ffffffL; // mask out current al_pa
1231 ulBuff |= (fcChip->Registers.my_al_pa << 24); // or in acq. al_pa
1232 fcChip->Registers.FMconfig.value = ulBuff; // copy it back
1233 writel(fcChip->Registers.FMconfig.value, // put in TachLite
1234 fcChip->Registers.FMconfig.address);
1235
1236
1237 #ifdef IMQ_DEBUG
1238 printk("#LUp %Xh, FMstat 0x%08X#", fcChip->Registers.my_al_pa, fcChip->Registers.FMstatus.value);
1239 #endif
1240
1241 // also set the WRITE-ONLY My_ID Register (for Fabric
1242 // initialization)
1243 writel(fcChip->Registers.my_al_pa, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
1244
1245
1246 fcChip->fcStats.linkUp++;
1247
1248 // reset TL statistics counters
1249 // (we ignore these error counters
1250 // while link is down)
1251 ulBuff = // just reset TL's counter
1252 readl(fcChip->Registers.FMLinkStatus1.address);
1253
1254 ulBuff = // just reset TL's counter
1255 readl(fcChip->Registers.FMLinkStatus2.address);
1256
1257 // for initiator, need to start verifying ports (e.g. PDISC)
1258
1259
1260
1261
1262
1263
1264 CpqTsUnFreezeTachlite(fcChip, 2); // unfreeze Tachlite, if Link OK
1265
1266 // Tachyon creates an interesting problem for us on LILP frames.
1267 // Instead of writing the incoming LILP frame into the SFQ before
1268 // indicating LINK UP (the actual order of events), Tachyon tells
1269 // us LINK UP, and later us the LILP. So we delay, then examine the
1270 // IMQ for an Inbound CM (x04); if found, we can set
1271 // LINKACTIVE after processing the LILP. Otherwise, just proceed.
1272 // Since Tachyon imposes this time delay (and doesn't tell us
1273 // what it is), we have to impose a delay before "Peeking" the IMQ
1274 // for Tach hardware (DMA) delivery.
1275 // Processing LILP is required by SANMark
1276 udelay(1000); // microsec delay waiting for LILP (if it comes)
1277 if (PeekIMQEntry(fcChip, ELS_LILP_FRAME)) { // found SFQ LILP, which will post LINKACTIVE
1278 // printk("skipping LINKACTIVE post\n");
1279
1280 } else
1281 cpqfcTSPutLinkQue(cpqfcHBAdata, LINKACTIVE, ulFibreFrame);
1282 }
1283
1284
1285 // ******* Set Fabric Login indication ********
1286 if (fcChip->Registers.FMstatus.value & 0x2000) {
1287 printk(" #Fabric# ");
1288 fcChip->Options.fabric = 1;
1289 } else
1290 fcChip->Options.fabric = 0;
1291
1292
1293
1294 // ******* LIP(F8,x) or BAD AL_PA? ********
1295 if (fcChip->Registers.FMstatus.value & 0x30000L) {
1296 // copy the error AL_PAs
1297 fcChip->Registers.rcv_al_pa.value = readl(fcChip->Registers.rcv_al_pa.address);
1298
1299 // Bad AL_PA?
1300 if (fcChip->Registers.FMstatus.value & 0x10000L) {
1301 PFC_LOGGEDIN_PORT pLoggedInPort;
1302
1303 // copy "BAD" al_pa field
1304 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1] = (fcChip->Registers.rcv_al_pa.value & 0xff00L) >> 8;
1305
1306 pLoggedInPort = fcFindLoggedInPort(fcChip, NULL, // DON'T search Scsi Nexus
1307 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1], // port id
1308 NULL, // DON'T search linked list for FC WWN
1309 NULL); // DON'T care about end of list
1310
1311 if (pLoggedInPort) {
1312 // Just in case we got this BAD_ALPA because a device
1313 // quietly disappeared (can happen on non-managed hubs such
1314 // as the Vixel Rapport 1000),
1315 // do an Implicit Logout. We never expect this on a Logged
1316 // in port (but do expect it on port discovery).
1317 // (As a reasonable alternative, this could be changed to
1318 // simply start the implicit logout timer, giving the device
1319 // several seconds to "come back".)
1320 //
1321 printk(" #BAD alpa %Xh# ", fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[1]);
1322 cpqfcTSImplicitLogout(cpqfcHBAdata, pLoggedInPort);
1323 }
1324 }
1325 // LIP(f8,x)?
1326 if (fcChip->Registers.FMstatus.value & 0x20000L) {
1327 // for debugging, copy al_pa field
1328 fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[2] = (fcChip->Registers.rcv_al_pa.value & 0xffL);
1329 // get the other port's al_pa
1330 // (one that sent LIP(F8,?) )
1331 }
1332 }
1333 // Elastic store err
1334 if (fcChip->Registers.FMstatus.value & 0x400L) {
1335 // don't count e-s if loop is down!
1336 if (!(u16) (fcChip->Registers.FMstatus.value & 0x80))
1337 fcChip->fcStats.e_stores++;
1338
1339 }
1340 }
1341 break;
1342
1343
1344 case INBOUND_FCP_XCHG_COMPLETION: // 0x0C
1345
1346 // Remarks:
1347 // On Tachlite TL/TS, we get this message when the data phase
1348 // of a SEST inbound transfer is complete. For example, if a WRITE command
1349 // was received with OX_ID 0, we might respond with XFER_RDY with
1350 // RX_ID 8001. This would start the SEST controlled data phases. When
1351 // all data frames are received, we get this inbound completion. This means
1352 // we should send a status frame to complete the status phase of the
1353 // FCP-SCSI exchange, using the same OX_ID,RX_ID that we used for data
1354 // frames.
1355 // See Outbound CM discussion of x_IDs
1356 // Psuedo Code
1357 // Get SEST index (x_ID)
1358 // x_ID out of range, return (err condition)
1359 // set status bits from 2nd dword
1360 // free transactionID & SEST entry
1361 // call fcComplete with transactionID & status
1362
1363 ulBuff = fcChip->IMQ->QEntry[fcChip->IMQ->consumerIndex].word[0];
1364 x_ID = ulBuff & 0x7fffL; // lower 14 bits SEST_Index/Trans_ID
1365 // (mask out MSB "direction" bit)
1366 // Range check CM OX/RX_ID value...
1367 if (x_ID < TACH_SEST_LEN) // don't go beyond SEST array space
1368 {
1369
1370 //#define FCP_COMPLETION_DBG 1
1371 #ifdef FCP_COMPLETION_DBG
1372 printk(" FCP_CM x_ID %Xh, status %Xh, Cmnd %p\n", x_ID, ulBuff, Exchanges->fcExchange[x_ID].Cmnd);
1373 #endif
1374 if (ulBuff & 0x08000000L) // RPC -Response Phase Complete - or -
1375 // time to send response frame?
1376 RPCset = 1; // (SEST transaction)
1377 else
1378 RPCset = 0;
1379 // set the status for this Inbound SCSI transaction's ID
1380 dwStatus = 0L;
1381 if (ulBuff & 0x70000000L) // any errs?
1382 {
1383
1384 if (ulBuff & 0x40000000L)
1385 dwStatus |= LINKFAIL_RX;
1386
1387 if (ulBuff & 0x20000000L)
1388 dwStatus |= COUNT_ERROR;
1389
1390 if (ulBuff & 0x10000000L)
1391 dwStatus |= OVERFLOW;
1392 }
1393
1394 // FCP transaction done - copy status
1395 Exchanges->fcExchange[x_ID].status = dwStatus;
1396
1397
1398 // Did the exchange get an FCP-RSP response frame?
1399 // (Note the little endian/big endian FC payload difference)
1400
1401 if (RPCset) // SEST transaction Response frame rec'd
1402 {
1403 // complete the command in our driver...
1404 cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, x_ID);
1405
1406 } // end "RPCset"
1407
1408 else // ("target" logic)
1409 {
1410 // Tachlite says all data frames have been received - now it's time
1411 // to analyze data transfer (successful?), then send a response
1412 // frame for this exchange
1413
1414 ulFibreFrame[0] = x_ID; // copy for later reference
1415
1416 // if this was a TWE, we have to send satus response
1417 if (Exchanges->fcExchange[x_ID].type == SCSI_TWE) {
1418 // fcPutScsiQue( cpqfcHBAdata,
1419 // NEED_FCP_RSP, ulFibreFrame); // (ulFibreFrame not used here)
1420 }
1421 }
1422 } else // ERROR CONDITION! bogus x_ID in completion message
1423 {
1424 printk("IN FCP_XCHG: bad x_ID: %Xh\n", x_ID);
1425 }
1426
1427 break;
1428
1429
1430
1431
1432 case INBOUND_SCSI_DATA_COMMAND:
1433 case BAD_SCSI_FRAME:
1434 case INB_SCSI_STATUS_COMPLETION:
1435 case BUFFER_PROCESSED_COMPLETION:
1436 break;
1437 }
1438
1439 // Tachyon is producing;
1440 // we are consuming
1441 fcChip->IMQ->consumerIndex++; // increment OUR consumerIndex
1442 if (fcChip->IMQ->consumerIndex >= IMQ_LEN) // check for rollover
1443 fcChip->IMQ->consumerIndex = 0L; // reset it
1444
1445
1446 if (fcChip->IMQ->producerIndex == fcChip->IMQ->consumerIndex) { // all Messages are processed -
1447 iStatus = 0; // no more messages to process
1448
1449 } else
1450 iStatus = 1; // more messages to process
1451
1452 // update TachLite's ConsumerIndex... (clears INTA_L)
1453 // NOTE: according to TL/TS UG, the
1454 // "host must return completion messages in sequential order".
1455 // Does this mean one at a time, in the order received? We
1456 // presume so.
1457
1458 writel(fcChip->IMQ->consumerIndex, (fcChip->Registers.ReMapMemBase + IMQ_CONSUMER_INDEX));
1459
1460 #if IMQ_DEBUG
1461 printk("Process IMQ: writing consumer ndx %d\n ", fcChip->IMQ->consumerIndex);
1462 printk("PI %X, CI %X\n", fcChip->IMQ->producerIndex, fcChip->IMQ->consumerIndex);
1463 #endif
1464
1465
1466
1467 } else {
1468 // hmmm... why did we get interrupted/called with no message?
1469 iStatus = -1; // nothing to process
1470 #if IMQ_DEBUG
1471 printk("Process IMQ: no message PI %Xh CI %Xh", fcChip->IMQ->producerIndex, fcChip->IMQ->consumerIndex);
1472 #endif
1473 }
1474
1475 LEAVE("ProcessIMQEntry");
1476
1477 return iStatus;
1478 }
1479
1480
1481
1482
1483
1484 // This routine initializes Tachyon according to the following
1485 // options (opcode1):
1486 // 1 - RESTART Tachyon, simulate power on condition by shutting
1487 // down laser, resetting the hardware, de-allocating all buffers;
1488 // continue
1489 // 2 - Config Tachyon / PCI registers;
1490 // continue
1491 // 3 - Allocating memory and setting Tachyon queues (write Tachyon regs);
1492 // continue
1493 // 4 - Config frame manager registers, initialize, turn on laser
1494 //
1495 // Returns:
1496 // -1 on fatal error
1497 // 0 on success
1498
CpqTsInitializeTachLite(void * pHBA,int opcode1,int opcode2)1499 int CpqTsInitializeTachLite(void *pHBA, int opcode1, int opcode2)
1500 {
1501 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
1502 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1503 u32 ulBuff;
1504 u8 bBuff;
1505 int iStatus = -1; // assume failure
1506
1507 ENTER("InitializeTachLite");
1508
1509 // verify board's base address (sanity check)
1510
1511 if (!fcChip->Registers.ReMapMemBase) // NULL address for card?
1512 return -1; // FATAL error!
1513
1514
1515
1516 switch (opcode1) {
1517 case 1: // restore hardware to power-on (hard) restart
1518
1519
1520 iStatus = fcChip->ResetTachyon(cpqfcHBAdata, opcode2); // laser off, reset hardware
1521 // de-allocate aligned buffers
1522
1523
1524 /* TBD // reset FC link Q (producer and consumer = 0)
1525 fcLinkQReset(cpqfcHBAdata);
1526
1527 */
1528
1529 if (iStatus)
1530 break;
1531
1532 case 2: // Config PCI/Tachyon registers
1533 // NOTE: For Tach TL/TS, bit 31 must be set to 1. For TS chips, a read
1534 // of bit 31 indicates state of M66EN signal; if 1, chip may run at
1535 // 33-66MHz (see TL/TS UG, pg 159)
1536
1537 ulBuff = 0x80000000; // TachLite Configuration Register
1538
1539 writel(ulBuff, fcChip->Registers.TYconfig.address);
1540 // ulBuff = 0x0147L; // CpqTs PCI CFGCMD register
1541 // WritePCIConfiguration( fcChip->Backplane.bus,
1542 // fcChip->Backplane.slot, TLCFGCMD, ulBuff, 4);
1543 // ulBuff = 0x0L; // test!
1544 // ReadPCIConfiguration( fcChip->Backplane.bus,
1545 // fcChip->Backplane.slot, TLCFGCMD, &ulBuff, 4);
1546
1547 // read back for reference...
1548 fcChip->Registers.TYconfig.value = readl(fcChip->Registers.TYconfig.address);
1549
1550 // what is the PCI bus width?
1551 pci_read_config_byte(cpqfcHBAdata->PciDev, 0x43, // PCIMCTR offset
1552 &bBuff);
1553
1554 fcChip->Registers.PCIMCTR = bBuff;
1555
1556 // set string identifying the chip on the circuit board
1557
1558 fcChip->Registers.TYstatus.value = readl(fcChip->Registers.TYstatus.address);
1559
1560 {
1561 // Now that we are supporting multiple boards, we need to change
1562 // this logic to check for PCI vendor/device IDs...
1563 // for now, quick & dirty is simply checking Chip rev
1564
1565 u32 RevId = (fcChip->Registers.TYstatus.value & 0x3E0) >> 5;
1566 u8 Minor = (u8) (RevId & 0x3);
1567 u8 Major = (u8) ((RevId & 0x1C) >> 2);
1568
1569 printk(" HBA Tachyon RevId %d.%d\n", Major, Minor);
1570 if ((Major == 1) && (Minor == 2)) {
1571 sprintf(cpqfcHBAdata->fcChip.Name, STACHLITE66_TS12);
1572
1573 } else if ((Major == 1) && (Minor == 3)) {
1574 sprintf(cpqfcHBAdata->fcChip.Name, STACHLITE66_TS13);
1575 } else if ((Major == 2) && (Minor == 1)) {
1576 sprintf(cpqfcHBAdata->fcChip.Name, SAGILENT_XL2_21);
1577 } else
1578 sprintf(cpqfcHBAdata->fcChip.Name, STACHLITE_UNKNOWN);
1579 }
1580
1581
1582
1583 case 3: // allocate mem, set Tachyon Que registers
1584 iStatus = CpqTsCreateTachLiteQues(cpqfcHBAdata, opcode2);
1585
1586 if (iStatus)
1587 break;
1588
1589 // now that the Queues exist, Tach can DMA to them, so
1590 // we can begin processing INTs
1591 // INTEN register - enable INT (TachLite interrupt)
1592 writeb(0x1F, fcChip->Registers.ReMapMemBase + IINTEN);
1593
1594 // Fall through
1595 case 4: // Config Fame Manager, Init Loop Command, laser on
1596
1597 // L_PORT or loopback
1598 // depending on Options
1599 iStatus = CpqTsInitializeFrameManager(fcChip, 0);
1600 if (iStatus) {
1601 // failed to initialize Frame Manager
1602 break;
1603 }
1604
1605 default:
1606 break;
1607 }
1608 LEAVE("InitializeTachLite");
1609
1610 return iStatus;
1611 }
1612
1613
1614
1615
1616 // Depending on the type of platform memory allocation (e.g. dynamic),
1617 // it's probably best to free memory in opposite order as it was allocated.
1618 // Order of allocation: see other function
1619
1620
CpqTsDestroyTachLiteQues(void * pHBA,int opcode)1621 int CpqTsDestroyTachLiteQues(void *pHBA, int opcode)
1622 {
1623 CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) pHBA;
1624 PTACHYON fcChip = &cpqfcHBAdata->fcChip;
1625 u16 i, iStatus = 0;
1626 void *vPtr; // mem Align manager sets this to the freed address on success
1627 unsigned long ulPtr; // for 64-bit pointer cast (e.g. Alpa machine)
1628 FC_EXCHANGES *Exchanges = fcChip->Exchanges;
1629 PSGPAGES j, next;
1630
1631 ENTER("DestroyTachLiteQues");
1632
1633 if (fcChip->SEST) {
1634 // search out and free Pool for Extended S/G list pages
1635
1636 for (i = 0; i < TACH_SEST_LEN; i++) // for each exchange
1637 {
1638 // It's possible that extended S/G pages were allocated, mapped, and
1639 // not cleared due to error conditions or O/S driver termination.
1640 // Make sure they're all gone.
1641 if (Exchanges->fcExchange[i].Cmnd != NULL)
1642 cpqfc_pci_unmap(cpqfcHBAdata->PciDev, Exchanges->fcExchange[i].Cmnd, fcChip, i); // undo DMA mappings.
1643
1644 for (j = fcChip->SEST->sgPages[i]; j != NULL; j = next) {
1645 next = j->next;
1646 kfree(j);
1647 }
1648 fcChip->SEST->sgPages[i] = NULL;
1649 }
1650 ulPtr = (unsigned long) fcChip->SEST;
1651 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL); // 'free' mem
1652 fcChip->SEST = 0L; // null invalid ptr
1653 if (!vPtr) {
1654 printk("SEST mem not freed\n");
1655 iStatus = -1;
1656 }
1657 }
1658
1659 if (fcChip->SFQ) {
1660
1661 ulPtr = (unsigned long) fcChip->SFQ;
1662 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL); // 'free' mem
1663 fcChip->SFQ = 0L; // null invalid ptr
1664 if (!vPtr) {
1665 printk("SFQ mem not freed\n");
1666 iStatus = -2;
1667 }
1668 }
1669
1670
1671 if (fcChip->IMQ) {
1672 // clear Indexes to show empty Queue
1673 fcChip->IMQ->producerIndex = 0;
1674 fcChip->IMQ->consumerIndex = 0;
1675
1676 ulPtr = (unsigned long) fcChip->IMQ;
1677 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL); // 'free' mem
1678 fcChip->IMQ = 0L; // null invalid ptr
1679 if (!vPtr) {
1680 printk("IMQ mem not freed\n");
1681 iStatus = -3;
1682 }
1683 }
1684
1685 if (fcChip->ERQ) // release memory blocks used by the queues
1686 {
1687 ulPtr = (unsigned long) fcChip->ERQ;
1688 vPtr = fcMemManager(cpqfcHBAdata->PciDev, &cpqfcHBAdata->dynamic_mem[0], 0, 0, (u32) ulPtr, NULL); // 'free' mem
1689 fcChip->ERQ = 0L; // null invalid ptr
1690 if (!vPtr) {
1691 printk("ERQ mem not freed\n");
1692 iStatus = -4;
1693 }
1694 }
1695 // free up the primary EXCHANGES struct and Link Q
1696 cpqfc_free_dma_consistent(cpqfcHBAdata);
1697
1698 LEAVE("DestroyTachLiteQues");
1699
1700 return iStatus; // non-zero (failed) if any memory not freed
1701 }
1702
1703
1704
1705
1706
1707 // The SFQ is an array with SFQ_LEN length, each element (QEntry)
1708 // with eight 32-bit words. TachLite places incoming FC frames (i.e.
1709 // a valid FC frame with our AL_PA ) in contiguous SFQ entries
1710 // and sends a completion message telling the host where the frame is
1711 // in the que.
1712 // This function copies the current (or oldest not-yet-processed) QEntry to
1713 // a caller's contiguous buffer and updates the Tachyon chip's consumer index
1714 //
1715 // NOTE:
1716 // An FC frame may consume one or many SFQ entries. We know the total
1717 // length from the completion message. The caller passes a buffer large
1718 // enough for the complete message (max 2k).
1719
CpqTsGetSFQEntry(PTACHYON fcChip,u16 producerNdx,u32 * ulDestPtr,u8 UpdateChip)1720 static void CpqTsGetSFQEntry(PTACHYON fcChip, u16 producerNdx, u32 * ulDestPtr, // contiguous destination buffer
1721 u8 UpdateChip)
1722 {
1723 u32 total_bytes = 0;
1724 u32 consumerIndex = fcChip->SFQ->consumerIndex;
1725
1726 // check passed copy of SFQ producer index -
1727 // is a new message waiting for us?
1728 // equal indexes means SFS is copied
1729
1730 while (producerNdx != consumerIndex) { // need to process message
1731 total_bytes += 64; // maintain count to prevent writing past buffer
1732 // don't allow copies over Fibre Channel defined length!
1733 if (total_bytes <= 2048) {
1734 memcpy(ulDestPtr, &fcChip->SFQ->QEntry[consumerIndex], 64); // each SFQ entry is 64 bytes
1735 ulDestPtr += 16; // advance pointer to next 64 byte block
1736 }
1737 // Tachyon is producing,
1738 // and we are consuming
1739
1740 if (++consumerIndex >= SFQ_LEN) // check for rollover
1741 consumerIndex = 0L; // reset it
1742 }
1743
1744 // if specified, update the Tachlite chip ConsumerIndex...
1745 if (UpdateChip) {
1746 fcChip->SFQ->consumerIndex = consumerIndex;
1747 writel(fcChip->SFQ->consumerIndex, fcChip->Registers.SFQconsumerIndex.address);
1748 }
1749 }
1750
1751
1752
1753 // TachLite routinely freezes it's core ques - Outbound FIFO, Inbound FIFO,
1754 // and Exchange Request Queue (ERQ) on error recover -
1755 // (e.g. whenever a LIP occurs). Here
1756 // we routinely RESUME by clearing these bits, but only if the loop is up
1757 // to avoid ERROR IDLE messages forever.
1758
CpqTsUnFreezeTachlite(void * pChip,int type)1759 void CpqTsUnFreezeTachlite(void *pChip, int type)
1760 {
1761 PTACHYON fcChip = (PTACHYON) pChip;
1762 fcChip->Registers.TYcontrol.value = readl(fcChip->Registers.TYcontrol.address);
1763
1764 // (bit 4 of value is GBIC LASER)
1765 // if we 'unfreeze' the core machines before the loop is healthy
1766 // (i.e. FLT, OS, LS failure bits set in FMstatus)
1767 // we can get 'error idle' messages forever. Verify that
1768 // FMstatus (Link Status) is OK before unfreezing.
1769
1770 if (!(fcChip->Registers.FMstatus.value & 0x07000000L) && // bits clear?
1771 !(fcChip->Registers.FMstatus.value & 0x80)) // Active LPSM?
1772 {
1773 fcChip->Registers.TYcontrol.value &= ~0x300L; // clear FEQ, FFA
1774 if (type == 1) // unfreeze ERQ only
1775 {
1776 // printk("Unfreezing ERQ\n");
1777 fcChip->Registers.TYcontrol.value |= 0x10000L; // set REQ
1778 } else // unfreeze both ERQ and FCP-ASSIST (SEST)
1779 {
1780 // printk("Unfreezing ERQ & FCP-ASSIST\n");
1781
1782 // set ROF, RIF, REQ - resume Outbound FCP, Inbnd FCP, ERQ
1783 fcChip->Registers.TYcontrol.value |= 0x70000L; // set ROF, RIF, REQ
1784 }
1785
1786 writel(fcChip->Registers.TYcontrol.value, fcChip->Registers.TYcontrol.address);
1787
1788 }
1789 // readback for verify (TachLite still frozen?)
1790 fcChip->Registers.TYstatus.value = readl(fcChip->Registers.TYstatus.address);
1791 }
1792
1793
1794 // Whenever an FC Exchange Abort is required, we must manipulate the
1795 // Host/Tachyon shared memory SEST table. Before doing this, we
1796 // must freeze Tachyon, which flushes certain buffers and ensure we
1797 // can manipulate the SEST without contention.
1798 // This freeze function will result in FCP & ERQ FROZEN completion
1799 // messages (per argument "type").
1800
CpqTsFreezeTachlite(void * pChip,int type)1801 void CpqTsFreezeTachlite(void *pChip, int type)
1802 {
1803 PTACHYON fcChip = (PTACHYON) pChip;
1804 fcChip->Registers.TYcontrol.value = readl(fcChip->Registers.TYcontrol.address);
1805
1806 //set FFA, FEQ - freezes SCSI assist and ERQ
1807 if (type == 1) // freeze ERQ only
1808 fcChip->Registers.TYcontrol.value |= 0x100L; // (bit 4 is laser)
1809 else // freeze both FCP assists (SEST) and ERQ
1810 fcChip->Registers.TYcontrol.value |= 0x300L; // (bit 4 is laser)
1811
1812 writel(fcChip->Registers.TYcontrol.value, fcChip->Registers.TYcontrol.address);
1813
1814 }
1815
1816
1817
1818
1819 // TL has two Frame Manager Link Status Registers, with three 8-bit
1820 // fields each. These eight bit counters are cleared after each read,
1821 // so we define six 32-bit accumulators for these TL counters. This
1822 // function breaks out each 8-bit field and adds the value to the existing
1823 // sum. (s/w counters cleared independently)
1824
fcParseLinkStatusCounters(PTACHYON fcChip)1825 void fcParseLinkStatusCounters(PTACHYON fcChip)
1826 {
1827 u8 bBuff;
1828 u32 ulBuff;
1829
1830
1831 // The BB0 timer usually increments when TL is initialized, resulting
1832 // in an initially bogus count. If our own counter is ZERO, it means we
1833 // are reading this thing for the first time, so we ignore the first count.
1834 // Also, reading the register does not clear it, so we have to keep an
1835 // additional static counter to detect rollover (yuk).
1836
1837 if (fcChip->fcStats.lastBB0timer == 0L) // TL was reset? (ignore 1st values)
1838 {
1839 // get TL's register counter - the "last" count
1840 fcChip->fcStats.lastBB0timer = fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
1841 } else // subsequent pass - check for rollover
1842 {
1843 // "this" count
1844 ulBuff = fcChip->Registers.FMBB_CreditZero.value & 0x00ffffffL;
1845 if (fcChip->fcStats.lastBB0timer > ulBuff) // rollover happened
1846 {
1847 // counter advanced to max...
1848 fcChip->fcStats.BB0_Timer += (0x00FFFFFFL - fcChip->fcStats.lastBB0timer);
1849 fcChip->fcStats.BB0_Timer += ulBuff; // plus some more
1850
1851
1852 } else // no rollover -- more counts or no change
1853 {
1854 fcChip->fcStats.BB0_Timer += (ulBuff - fcChip->fcStats.lastBB0timer);
1855
1856 }
1857
1858 fcChip->fcStats.lastBB0timer = ulBuff;
1859 }
1860
1861
1862
1863 bBuff = (u8) (fcChip->Registers.FMLinkStatus1.value >> 24);
1864 fcChip->fcStats.LossofSignal += bBuff;
1865
1866 bBuff = (u8) (fcChip->Registers.FMLinkStatus1.value >> 16);
1867 fcChip->fcStats.BadRXChar += bBuff;
1868
1869 bBuff = (u8) (fcChip->Registers.FMLinkStatus1.value >> 8);
1870 fcChip->fcStats.LossofSync += bBuff;
1871
1872
1873 bBuff = (u8) (fcChip->Registers.FMLinkStatus2.value >> 24);
1874 fcChip->fcStats.Rx_EOFa += bBuff;
1875
1876 bBuff = (u8) (fcChip->Registers.FMLinkStatus2.value >> 16);
1877 fcChip->fcStats.Dis_Frm += bBuff;
1878
1879 bBuff = (u8) (fcChip->Registers.FMLinkStatus2.value >> 8);
1880 fcChip->fcStats.Bad_CRC += bBuff;
1881 }
1882
1883
cpqfcTSClearLinkStatusCounters(PTACHYON fcChip)1884 void cpqfcTSClearLinkStatusCounters(PTACHYON fcChip)
1885 {
1886 ENTER("ClearLinkStatusCounters");
1887 memset(&fcChip->fcStats, 0, sizeof(FCSTATS));
1888 LEAVE("ClearLinkStatusCounters");
1889
1890 }
1891
1892
1893
1894
1895 // The following function reads the I2C hardware to get the adapter's
1896 // World Wide Name (WWN).
1897 // If the WWN is "500805f1fadb43e8" (as printed on the card), the
1898 // Tachyon WWN_hi (32-bit) register is 500805f1, and WWN_lo register
1899 // is fadb43e8.
1900 // In the NVRAM, the bytes appear as:
1901 // [2d] ..
1902 // [2e] ..
1903 // [2f] 50
1904 // [30] 08
1905 // [31] 05
1906 // [32] f1
1907 // [33] fa
1908 // [34] db
1909 // [35] 43
1910 // [36] e8
1911 //
1912 // In the Fibre Channel (Big Endian) format, the FC-AL LISM frame will
1913 // be correctly loaded by Tachyon silicon. In the login payload, bytes
1914 // must be correctly swapped for Big Endian format.
1915
CpqTsReadWriteWWN(void * pChip,int Read)1916 int CpqTsReadWriteWWN(void * pChip, int Read)
1917 {
1918 PTACHYON fcChip = (PTACHYON) pChip;
1919 #define NVRAM_SIZE 512
1920 unsigned short i, count = NVRAM_SIZE;
1921 u8 nvRam[NVRAM_SIZE], WWNbuf[8];
1922 u32 ulBuff;
1923 int iStatus = -1; // assume failure
1924 int WWNoffset;
1925
1926 ENTER("ReadWriteWWN");
1927 // Now try to read the WWN from the adapter's NVRAM
1928
1929 if (Read) // READing NVRAM WWN?
1930 {
1931 ulBuff = cpqfcTS_ReadNVRAM(fcChip->Registers.TYstatus.address, fcChip->Registers.TYcontrol.address, count, &nvRam[0]);
1932
1933 if (ulBuff) // NVRAM read successful?
1934 {
1935 iStatus = 0; // success!
1936
1937 // for engineering/ prototype boards, the data may be
1938 // invalid (GIGO, usually all "FF"); this prevents the
1939 // parse routine from working correctly, which means
1940 // nothing will be written to our passed buffer.
1941
1942 WWNoffset = cpqfcTS_GetNVRAM_data(WWNbuf, nvRam);
1943
1944 if (!WWNoffset) // uninitialized NVRAM -- copy bytes directly
1945 {
1946 printk("CAUTION: Copying NVRAM data on fcChip\n");
1947 for (i = 0; i < 8; i++)
1948 WWNbuf[i] = nvRam[i + 0x2f]; // dangerous! some formats won't work
1949 }
1950
1951 fcChip->Registers.wwn_hi = 0L;
1952 fcChip->Registers.wwn_lo = 0L;
1953 for (i = 0; i < 4; i++) // WWN bytes are big endian in NVRAM
1954 {
1955 ulBuff = 0L;
1956 ulBuff = (u32) (WWNbuf[i]) << (8 * (3 - i));
1957 fcChip->Registers.wwn_hi |= ulBuff;
1958 }
1959 for (i = 0; i < 4; i++) // WWN bytes are big endian in NVRAM
1960 {
1961 ulBuff = 0L;
1962 ulBuff = (u32) (WWNbuf[i + 4]) << (8 * (3 - i));
1963 fcChip->Registers.wwn_lo |= ulBuff;
1964 }
1965 } // done reading
1966 else {
1967
1968 printk("cpqfcTS: NVRAM read failed\n");
1969
1970 }
1971 }
1972
1973 else // WRITE
1974 {
1975
1976 // NOTE: WRITE not supported & not used in released driver.
1977
1978
1979 printk("ReadWriteNRAM: can't write NVRAM; aborting write\n");
1980 }
1981
1982 LEAVE("ReadWriteWWN");
1983 return iStatus;
1984 }
1985
1986
1987
1988
1989
1990 // The following function reads or writes the entire "NVRAM" contents of
1991 // the I2C hardware (i.e. the NM24C03). Note that HP's 5121A (TS 66Mhz)
1992 // adapter does not use the NM24C03 chip, so this function only works on
1993 // Compaq's adapters.
1994
CpqTsReadWriteNVRAM(void * pChip,void * buf,int Read)1995 int CpqTsReadWriteNVRAM(void * pChip, void * buf, int Read)
1996 {
1997 PTACHYON fcChip = (PTACHYON) pChip;
1998 #define NVRAM_SIZE 512
1999 u32 ulBuff;
2000 u8 *ucPtr = buf; // cast caller's void ptr to u8 array
2001 int iStatus = -1; // assume failure
2002
2003
2004 if (Read) // READing NVRAM?
2005 {
2006 ulBuff = cpqfcTS_ReadNVRAM( // TRUE on success
2007 fcChip->Registers.TYstatus.address, fcChip->Registers.TYcontrol.address, 256, // bytes to write
2008 ucPtr); // source ptr
2009
2010
2011 if (ulBuff)
2012 iStatus = 0; // success
2013 else {
2014 #ifdef DBG
2015 printk("CAUTION: NVRAM read failed\n");
2016 #endif
2017 }
2018 } // done reading
2019
2020 else // WRITING NVRAM
2021 {
2022
2023 printk("cpqfcTS: WRITE of FC Controller's NVRAM disabled\n");
2024 }
2025
2026 return iStatus;
2027 }
2028