|
|
1.1 root 1: /*
2:
3: Linux Driver for BusLogic MultiMaster and FlashPoint SCSI Host Adapters
4:
5: Copyright 1995-1998 by Leonard N. Zubkoff <[email protected]>
6:
7: This program is free software; you may redistribute and/or modify it under
8: the terms of the GNU General Public License Version 2 as published by the
9: Free Software Foundation.
10:
11: This program is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
13: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: for complete details.
15:
16: The author respectfully requests that any modifications to this software be
17: sent directly to him for evaluation and testing.
18:
19: Special thanks to Wayne Yen, Jin-Lon Hon, and Alex Win of BusLogic, whose
20: advice has been invaluable, to David Gentzel, for writing the original Linux
21: BusLogic driver, and to Paul Gortmaker, for being such a dedicated test site.
22:
23: Finally, special thanks to Mylex/BusLogic for making the FlashPoint SCCB
24: Manager available as freely redistributable source code.
25:
26: */
27:
28:
29: #define BusLogic_DriverVersion "2.0.15"
30: #define BusLogic_DriverDate "17 August 1998"
31:
32:
33: #include <linux/version.h>
34: #include <linux/module.h>
35: #include <linux/config.h>
36: #include <linux/types.h>
37: #include <linux/blkdev.h>
38: #include <linux/delay.h>
39: #include <linux/ioport.h>
40: #include <linux/mm.h>
41: #include <linux/sched.h>
42: #include <linux/stat.h>
43: #include <linux/pci.h>
44: #include <linux/bios32.h>
45: #include <asm/dma.h>
46: #include <asm/io.h>
47: #include <asm/irq.h>
48: #include <asm/system.h>
49: #include "scsi.h"
50: #include "hosts.h"
51: #include "sd.h"
52: #include "BusLogic.h"
53: #include "FlashPoint.c"
54:
55:
56: /*
57: BusLogic_DriverOptionsCount is a count of the number of BusLogic Driver
58: Options specifications provided via the Linux Kernel Command Line or via
59: the Loadable Kernel Module Installation Facility.
60: */
61:
62: static int
63: BusLogic_DriverOptionsCount = 0;
64:
65:
66: /*
67: BusLogic_DriverOptions is an array of Driver Options structures representing
68: BusLogic Driver Options specifications provided via the Linux Kernel Command
69: Line or via the Loadable Kernel Module Installation Facility.
70: */
71:
72: static BusLogic_DriverOptions_T
73: BusLogic_DriverOptions[BusLogic_MaxHostAdapters];
74:
75:
76: /*
77: BusLogic_Options can be assigned a string by the Loadable Kernel Module
78: Installation Facility to be parsed for BusLogic Driver Options
79: specifications.
80: */
81:
82: static char
83: *BusLogic_Options = NULL;
84:
85:
86: /*
87: BusLogic_ProbeOptions is a set of Probe Options to be applied across
88: all BusLogic Host Adapters.
89: */
90:
91: static BusLogic_ProbeOptions_T
92: BusLogic_ProbeOptions = { 0 };
93:
94:
95: /*
96: BusLogic_GlobalOptions is a set of Global Options to be applied across
97: all BusLogic Host Adapters.
98: */
99:
100: static BusLogic_GlobalOptions_T
101: BusLogic_GlobalOptions = { 0 };
102:
103:
104: /*
105: BusLogic_FirstRegisteredHostAdapter and BusLogic_LastRegisteredHostAdapter
106: are pointers to the first and last registered BusLogic Host Adapters.
107: */
108:
109: static BusLogic_HostAdapter_T
110: *BusLogic_FirstRegisteredHostAdapter = NULL,
111: *BusLogic_LastRegisteredHostAdapter = NULL;
112:
113:
114: /*
115: BusLogic_ProbeInfoCount is the number of entries in BusLogic_ProbeInfoList.
116: */
117:
118: static int
119: BusLogic_ProbeInfoCount = 0;
120:
121:
122: /*
123: BusLogic_ProbeInfoList is the list of I/O Addresses and Bus Probe Information
124: to be checked for potential BusLogic Host Adapters. It is initialized by
125: interrogating the PCI Configuration Space on PCI machines as well as from the
126: list of standard BusLogic I/O Addresses.
127: */
128:
129: static BusLogic_ProbeInfo_T
130: *BusLogic_ProbeInfoList = NULL;
131:
132:
133: /*
134: BusLogic_CommandFailureReason holds a string identifying the reason why a
135: call to BusLogic_Command failed. It is only non-NULL when BusLogic_Command
136: returns a failure code.
137: */
138:
139: static char
140: *BusLogic_CommandFailureReason;
141:
142:
143: /*
144: BusLogic_ProcDirectoryEntry is the BusLogic /proc/scsi directory entry.
145: */
146:
147: PROC_DirectoryEntry_T
148: BusLogic_ProcDirectoryEntry =
149: { PROC_SCSI_BUSLOGIC, 8, "BusLogic", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
150:
151:
152: /*
153: BusLogic_AnnounceDriver announces the Driver Version and Date, Author's
154: Name, Copyright Notice, and Electronic Mail Address.
155: */
156:
157: static void BusLogic_AnnounceDriver(BusLogic_HostAdapter_T *HostAdapter)
158: {
159: BusLogic_Announce("***** BusLogic SCSI Driver Version "
160: BusLogic_DriverVersion " of "
161: BusLogic_DriverDate " *****\n", HostAdapter);
162: BusLogic_Announce("Copyright 1995-1998 by Leonard N. Zubkoff "
163: "<[email protected]>\n", HostAdapter);
164: }
165:
166:
167: /*
168: BusLogic_DriverInfo returns the Host Adapter Name to identify this SCSI
169: Driver and Host Adapter.
170: */
171:
172: const char *BusLogic_DriverInfo(SCSI_Host_T *Host)
173: {
174: BusLogic_HostAdapter_T *HostAdapter =
175: (BusLogic_HostAdapter_T *) Host->hostdata;
176: return HostAdapter->FullModelName;
177: }
178:
179:
180: /*
181: BusLogic_RegisterHostAdapter adds Host Adapter to the list of registered
182: BusLogic Host Adapters.
183: */
184:
185: static void BusLogic_RegisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
186: {
187: HostAdapter->Next = NULL;
188: if (BusLogic_FirstRegisteredHostAdapter == NULL)
189: {
190: BusLogic_FirstRegisteredHostAdapter = HostAdapter;
191: BusLogic_LastRegisteredHostAdapter = HostAdapter;
192: }
193: else
194: {
195: BusLogic_LastRegisteredHostAdapter->Next = HostAdapter;
196: BusLogic_LastRegisteredHostAdapter = HostAdapter;
197: }
198: }
199:
200:
201: /*
202: BusLogic_UnregisterHostAdapter removes Host Adapter from the list of
203: registered BusLogic Host Adapters.
204: */
205:
206: static void BusLogic_UnregisterHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
207: {
208: if (HostAdapter == BusLogic_FirstRegisteredHostAdapter)
209: {
210: BusLogic_FirstRegisteredHostAdapter =
211: BusLogic_FirstRegisteredHostAdapter->Next;
212: if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
213: BusLogic_LastRegisteredHostAdapter = NULL;
214: }
215: else
216: {
217: BusLogic_HostAdapter_T *PreviousHostAdapter =
218: BusLogic_FirstRegisteredHostAdapter;
219: while (PreviousHostAdapter != NULL &&
220: PreviousHostAdapter->Next != HostAdapter)
221: PreviousHostAdapter = PreviousHostAdapter->Next;
222: if (PreviousHostAdapter != NULL)
223: PreviousHostAdapter->Next = HostAdapter->Next;
224: }
225: HostAdapter->Next = NULL;
226: }
227:
228:
229: /*
230: BusLogic_InitializeCCBs initializes a group of Command Control Blocks (CCBs)
231: for Host Adapter from the BlockSize bytes located at BlockPointer. The newly
232: created CCBs are added to Host Adapter's free list.
233: */
234:
235: static void BusLogic_InitializeCCBs(BusLogic_HostAdapter_T *HostAdapter,
236: void *BlockPointer, int BlockSize)
237: {
238: BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) BlockPointer;
239: memset(BlockPointer, 0, BlockSize);
240: CCB->AllocationGroupHead = true;
241: while ((BlockSize -= sizeof(BusLogic_CCB_T)) >= 0)
242: {
243: CCB->Status = BusLogic_CCB_Free;
244: CCB->HostAdapter = HostAdapter;
245: if (BusLogic_FlashPointHostAdapterP(HostAdapter))
246: {
247: CCB->CallbackFunction = BusLogic_QueueCompletedCCB;
248: CCB->BaseAddress = HostAdapter->FlashPointInfo.BaseAddress;
249: }
250: CCB->Next = HostAdapter->Free_CCBs;
251: CCB->NextAll = HostAdapter->All_CCBs;
252: HostAdapter->Free_CCBs = CCB;
253: HostAdapter->All_CCBs = CCB;
254: HostAdapter->AllocatedCCBs++;
255: CCB++;
256: }
257: }
258:
259:
260: /*
261: BusLogic_CreateInitialCCBs allocates the initial CCBs for Host Adapter.
262: */
263:
264: static boolean BusLogic_CreateInitialCCBs(BusLogic_HostAdapter_T *HostAdapter)
265: {
266: int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T);
267: while (HostAdapter->AllocatedCCBs < HostAdapter->InitialCCBs)
268: {
269: void *BlockPointer = kmalloc(BlockSize,
270: (HostAdapter->BounceBuffersRequired
271: ? GFP_ATOMIC | GFP_DMA
272: : GFP_ATOMIC));
273: if (BlockPointer == NULL)
274: {
275: BusLogic_Error("UNABLE TO ALLOCATE CCB GROUP - DETACHING\n",
276: HostAdapter);
277: return false;
278: }
279: BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize);
280: }
281: return true;
282: }
283:
284:
285: /*
286: BusLogic_DestroyCCBs deallocates the CCBs for Host Adapter.
287: */
288:
289: static void BusLogic_DestroyCCBs(BusLogic_HostAdapter_T *HostAdapter)
290: {
291: BusLogic_CCB_T *NextCCB = HostAdapter->All_CCBs, *CCB;
292: HostAdapter->All_CCBs = NULL;
293: HostAdapter->Free_CCBs = NULL;
294: while ((CCB = NextCCB) != NULL)
295: {
296: NextCCB = CCB->NextAll;
297: if (CCB->AllocationGroupHead)
298: kfree(CCB);
299: }
300: }
301:
302:
303: /*
304: BusLogic_CreateAdditionalCCBs allocates Additional CCBs for Host Adapter. If
305: allocation fails and there are no remaining CCBs available, the Driver Queue
306: Depth is decreased to a known safe value to avoid potential deadlocks when
307: multiple host adapters share the same IRQ Channel.
308: */
309:
310: static void BusLogic_CreateAdditionalCCBs(BusLogic_HostAdapter_T *HostAdapter,
311: int AdditionalCCBs,
312: boolean SuccessMessageP)
313: {
314: int BlockSize = BusLogic_CCB_AllocationGroupSize * sizeof(BusLogic_CCB_T);
315: int PreviouslyAllocated = HostAdapter->AllocatedCCBs;
316: if (AdditionalCCBs <= 0) return;
317: while (HostAdapter->AllocatedCCBs - PreviouslyAllocated < AdditionalCCBs)
318: {
319: void *BlockPointer = kmalloc(BlockSize,
320: (HostAdapter->BounceBuffersRequired
321: ? GFP_ATOMIC | GFP_DMA
322: : GFP_ATOMIC));
323: if (BlockPointer == NULL) break;
324: BusLogic_InitializeCCBs(HostAdapter, BlockPointer, BlockSize);
325: }
326: if (HostAdapter->AllocatedCCBs > PreviouslyAllocated)
327: {
328: if (SuccessMessageP)
329: BusLogic_Notice("Allocated %d additional CCBs (total now %d)\n",
330: HostAdapter,
331: HostAdapter->AllocatedCCBs - PreviouslyAllocated,
332: HostAdapter->AllocatedCCBs);
333: return;
334: }
335: BusLogic_Notice("Failed to allocate additional CCBs\n", HostAdapter);
336: if (HostAdapter->DriverQueueDepth >
337: HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount)
338: {
339: HostAdapter->DriverQueueDepth =
340: HostAdapter->AllocatedCCBs - HostAdapter->TargetDeviceCount;
341: HostAdapter->SCSI_Host->can_queue = HostAdapter->DriverQueueDepth;
342: }
343: }
344:
345:
346: /*
347: BusLogic_AllocateCCB allocates a CCB from Host Adapter's free list,
348: allocating more memory from the Kernel if necessary. The Host Adapter's
349: Lock should already have been acquired by the caller.
350: */
351:
352: static BusLogic_CCB_T *BusLogic_AllocateCCB(BusLogic_HostAdapter_T
353: *HostAdapter)
354: {
355: static unsigned long SerialNumber = 0;
356: BusLogic_CCB_T *CCB;
357: CCB = HostAdapter->Free_CCBs;
358: if (CCB != NULL)
359: {
360: CCB->SerialNumber = ++SerialNumber;
361: HostAdapter->Free_CCBs = CCB->Next;
362: CCB->Next = NULL;
363: if (HostAdapter->Free_CCBs == NULL)
364: BusLogic_CreateAdditionalCCBs(HostAdapter,
365: HostAdapter->IncrementalCCBs,
366: true);
367: return CCB;
368: }
369: BusLogic_CreateAdditionalCCBs(HostAdapter,
370: HostAdapter->IncrementalCCBs,
371: true);
372: CCB = HostAdapter->Free_CCBs;
373: if (CCB == NULL) return NULL;
374: CCB->SerialNumber = ++SerialNumber;
375: HostAdapter->Free_CCBs = CCB->Next;
376: CCB->Next = NULL;
377: return CCB;
378: }
379:
380:
381: /*
382: BusLogic_DeallocateCCB deallocates a CCB, returning it to the Host Adapter's
383: free list. The Host Adapter's Lock should already have been acquired by the
384: caller.
385: */
386:
387: static void BusLogic_DeallocateCCB(BusLogic_CCB_T *CCB)
388: {
389: BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
390: CCB->Command = NULL;
391: CCB->Status = BusLogic_CCB_Free;
392: CCB->Next = HostAdapter->Free_CCBs;
393: HostAdapter->Free_CCBs = CCB;
394: }
395:
396:
397: /*
398: BusLogic_Command sends the command OperationCode to HostAdapter, optionally
399: providing ParameterLength bytes of ParameterData and receiving at most
400: ReplyLength bytes of ReplyData; any excess reply data is received but
401: discarded.
402:
403: On success, this function returns the number of reply bytes read from
404: the Host Adapter (including any discarded data); on failure, it returns
405: -1 if the command was invalid, or -2 if a timeout occurred.
406:
407: BusLogic_Command is called exclusively during host adapter detection and
408: initialization, so performance and latency are not critical, and exclusive
409: access to the Host Adapter hardware is assumed. Once the host adapter and
410: driver are initialized, the only Host Adapter command that is issued is the
411: single byte Execute Mailbox Command operation code, which does not require
412: waiting for the Host Adapter Ready bit to be set in the Status Register.
413: */
414:
415: static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
416: BusLogic_OperationCode_T OperationCode,
417: void *ParameterData,
418: int ParameterLength,
419: void *ReplyData,
420: int ReplyLength)
421: {
422: unsigned char *ParameterPointer = (unsigned char *) ParameterData;
423: unsigned char *ReplyPointer = (unsigned char *) ReplyData;
424: BusLogic_StatusRegister_T StatusRegister;
425: BusLogic_InterruptRegister_T InterruptRegister;
426: ProcessorFlags_T ProcessorFlags = 0;
427: int ReplyBytes = 0, Result;
428: long TimeoutCounter;
429: /*
430: Clear out the Reply Data if provided.
431: */
432: if (ReplyLength > 0)
433: memset(ReplyData, 0, ReplyLength);
434: /*
435: If the IRQ Channel has not yet been acquired, then interrupts must be
436: disabled while issuing host adapter commands since a Command Complete
437: interrupt could occur if the IRQ Channel was previously enabled by another
438: BusLogic Host Adapter or another driver sharing the same IRQ Channel.
439: */
440: if (!HostAdapter->IRQ_ChannelAcquired)
441: {
442: save_flags(ProcessorFlags);
443: cli();
444: }
445: /*
446: Wait for the Host Adapter Ready bit to be set and the Command/Parameter
447: Register Busy bit to be reset in the Status Register.
448: */
449: TimeoutCounter = 10000;
450: while (--TimeoutCounter >= 0)
451: {
452: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
453: if (StatusRegister.Bits.HostAdapterReady &&
454: !StatusRegister.Bits.CommandParameterRegisterBusy)
455: break;
456: udelay(100);
457: }
458: if (TimeoutCounter < 0)
459: {
460: BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
461: Result = -2;
462: goto Done;
463: }
464: /*
465: Write the OperationCode to the Command/Parameter Register.
466: */
467: HostAdapter->HostAdapterCommandCompleted = false;
468: BusLogic_WriteCommandParameterRegister(HostAdapter, OperationCode);
469: /*
470: Write any additional Parameter Bytes.
471: */
472: TimeoutCounter = 10000;
473: while (ParameterLength > 0 && --TimeoutCounter >= 0)
474: {
475: /*
476: Wait 100 microseconds to give the Host Adapter enough time to determine
477: whether the last value written to the Command/Parameter Register was
478: valid or not. If the Command Complete bit is set in the Interrupt
479: Register, then the Command Invalid bit in the Status Register will be
480: reset if the Operation Code or Parameter was valid and the command
481: has completed, or set if the Operation Code or Parameter was invalid.
482: If the Data In Register Ready bit is set in the Status Register, then
483: the Operation Code was valid, and data is waiting to be read back
484: from the Host Adapter. Otherwise, wait for the Command/Parameter
485: Register Busy bit in the Status Register to be reset.
486: */
487: udelay(100);
488: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
489: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
490: if (InterruptRegister.Bits.CommandComplete) break;
491: if (HostAdapter->HostAdapterCommandCompleted) break;
492: if (StatusRegister.Bits.DataInRegisterReady) break;
493: if (StatusRegister.Bits.CommandParameterRegisterBusy) continue;
494: BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
495: ParameterLength--;
496: }
497: if (TimeoutCounter < 0)
498: {
499: BusLogic_CommandFailureReason =
500: "Timeout waiting for Parameter Acceptance";
501: Result = -2;
502: goto Done;
503: }
504: /*
505: The Modify I/O Address command does not cause a Command Complete Interrupt.
506: */
507: if (OperationCode == BusLogic_ModifyIOAddress)
508: {
509: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
510: if (StatusRegister.Bits.CommandInvalid)
511: {
512: BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
513: Result = -1;
514: goto Done;
515: }
516: if (BusLogic_GlobalOptions.TraceConfiguration)
517: BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: "
518: "(Modify I/O Address)\n", HostAdapter,
519: OperationCode, StatusRegister.All);
520: Result = 0;
521: goto Done;
522: }
523: /*
524: Select an appropriate timeout value for awaiting command completion.
525: */
526: switch (OperationCode)
527: {
528: case BusLogic_InquireInstalledDevicesID0to7:
529: case BusLogic_InquireInstalledDevicesID8to15:
530: case BusLogic_InquireTargetDevices:
531: /* Approximately 60 seconds. */
532: TimeoutCounter = 60*10000;
533: break;
534: default:
535: /* Approximately 1 second. */
536: TimeoutCounter = 10000;
537: break;
538: }
539: /*
540: Receive any Reply Bytes, waiting for either the Command Complete bit to
541: be set in the Interrupt Register, or for the Interrupt Handler to set the
542: Host Adapter Command Completed bit in the Host Adapter structure.
543: */
544: while (--TimeoutCounter >= 0)
545: {
546: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
547: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
548: if (InterruptRegister.Bits.CommandComplete) break;
549: if (HostAdapter->HostAdapterCommandCompleted) break;
550: if (StatusRegister.Bits.DataInRegisterReady)
551: {
552: if (++ReplyBytes <= ReplyLength)
553: *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
554: else BusLogic_ReadDataInRegister(HostAdapter);
555: }
556: if (OperationCode == BusLogic_FetchHostAdapterLocalRAM &&
557: StatusRegister.Bits.HostAdapterReady) break;
558: udelay(100);
559: }
560: if (TimeoutCounter < 0)
561: {
562: BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
563: Result = -2;
564: goto Done;
565: }
566: /*
567: Clear any pending Command Complete Interrupt.
568: */
569: BusLogic_InterruptReset(HostAdapter);
570: /*
571: Provide tracing information if requested.
572: */
573: if (BusLogic_GlobalOptions.TraceConfiguration)
574: {
575: int i;
576: BusLogic_Notice("BusLogic_Command(%02X) Status = %02X: %2d ==> %2d:",
577: HostAdapter, OperationCode,
578: StatusRegister.All, ReplyLength, ReplyBytes);
579: if (ReplyLength > ReplyBytes) ReplyLength = ReplyBytes;
580: for (i = 0; i < ReplyLength; i++)
581: BusLogic_Notice(" %02X", HostAdapter,
582: ((unsigned char *) ReplyData)[i]);
583: BusLogic_Notice("\n", HostAdapter);
584: }
585: /*
586: Process Command Invalid conditions.
587: */
588: if (StatusRegister.Bits.CommandInvalid)
589: {
590: /*
591: Some early BusLogic Host Adapters may not recover properly from
592: a Command Invalid condition, so if this appears to be the case,
593: a Soft Reset is issued to the Host Adapter. Potentially invalid
594: commands are never attempted after Mailbox Initialization is
595: performed, so there should be no Host Adapter state lost by a
596: Soft Reset in response to a Command Invalid condition.
597: */
598: udelay(1000);
599: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
600: if (StatusRegister.Bits.CommandInvalid ||
601: StatusRegister.Bits.Reserved ||
602: StatusRegister.Bits.DataInRegisterReady ||
603: StatusRegister.Bits.CommandParameterRegisterBusy ||
604: !StatusRegister.Bits.HostAdapterReady ||
605: !StatusRegister.Bits.InitializationRequired ||
606: StatusRegister.Bits.DiagnosticActive ||
607: StatusRegister.Bits.DiagnosticFailure)
608: {
609: BusLogic_SoftReset(HostAdapter);
610: udelay(1000);
611: }
612: BusLogic_CommandFailureReason = "Command Invalid";
613: Result = -1;
614: goto Done;
615: }
616: /*
617: Handle Excess Parameters Supplied conditions.
618: */
619: if (ParameterLength > 0)
620: {
621: BusLogic_CommandFailureReason = "Excess Parameters Supplied";
622: Result = -1;
623: goto Done;
624: }
625: /*
626: Indicate the command completed successfully.
627: */
628: BusLogic_CommandFailureReason = NULL;
629: Result = ReplyBytes;
630: /*
631: Restore the interrupt status if necessary and return.
632: */
633: Done:
634: if (!HostAdapter->IRQ_ChannelAcquired)
635: restore_flags(ProcessorFlags);
636: return Result;
637: }
638:
639:
640: /*
641: BusLogic_AppendProbeAddressISA appends a single ISA I/O Address to the list
642: of I/O Address and Bus Probe Information to be checked for potential BusLogic
643: Host Adapters.
644: */
645:
646: static void BusLogic_AppendProbeAddressISA(BusLogic_IO_Address_T IO_Address)
647: {
648: BusLogic_ProbeInfo_T *ProbeInfo;
649: if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return;
650: ProbeInfo = &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
651: ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
652: ProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
653: ProbeInfo->IO_Address = IO_Address;
654: }
655:
656:
657: /*
658: BusLogic_InitializeProbeInfoListISA initializes the list of I/O Address and
659: Bus Probe Information to be checked for potential BusLogic SCSI Host Adapters
660: only from the list of standard BusLogic MultiMaster ISA I/O Addresses.
661: */
662:
663: static void BusLogic_InitializeProbeInfoListISA(BusLogic_HostAdapter_T
664: *PrototypeHostAdapter)
665: {
666: /*
667: If BusLogic Driver Options specifications requested that ISA Bus Probes
668: be inhibited, do not proceed further.
669: */
670: if (BusLogic_ProbeOptions.NoProbeISA) return;
671: /*
672: Append the list of standard BusLogic MultiMaster ISA I/O Addresses.
673: */
674: if (BusLogic_ProbeOptions.LimitedProbeISA
675: ? BusLogic_ProbeOptions.Probe330
676: : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0)
677: BusLogic_AppendProbeAddressISA(0x330);
678: if (BusLogic_ProbeOptions.LimitedProbeISA
679: ? BusLogic_ProbeOptions.Probe334
680: : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0)
681: BusLogic_AppendProbeAddressISA(0x334);
682: if (BusLogic_ProbeOptions.LimitedProbeISA
683: ? BusLogic_ProbeOptions.Probe230
684: : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0)
685: BusLogic_AppendProbeAddressISA(0x230);
686: if (BusLogic_ProbeOptions.LimitedProbeISA
687: ? BusLogic_ProbeOptions.Probe234
688: : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0)
689: BusLogic_AppendProbeAddressISA(0x234);
690: if (BusLogic_ProbeOptions.LimitedProbeISA
691: ? BusLogic_ProbeOptions.Probe130
692: : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0)
693: BusLogic_AppendProbeAddressISA(0x130);
694: if (BusLogic_ProbeOptions.LimitedProbeISA
695: ? BusLogic_ProbeOptions.Probe134
696: : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0)
697: BusLogic_AppendProbeAddressISA(0x134);
698: }
699:
700:
701: #ifdef CONFIG_PCI
702:
703:
704: /*
705: BusLogic_SortProbeInfo sorts a section of BusLogic_ProbeInfoList in order
706: of increasing PCI Bus and Device Number.
707: */
708:
709: static void BusLogic_SortProbeInfo(BusLogic_ProbeInfo_T *ProbeInfoList,
710: int ProbeInfoCount)
711: {
712: int LastInterchange = ProbeInfoCount-1, Bound, j;
713: while (LastInterchange > 0)
714: {
715: Bound = LastInterchange;
716: LastInterchange = 0;
717: for (j = 0; j < Bound; j++)
718: {
719: BusLogic_ProbeInfo_T *ProbeInfo1 = &ProbeInfoList[j];
720: BusLogic_ProbeInfo_T *ProbeInfo2 = &ProbeInfoList[j+1];
721: if (ProbeInfo1->Bus > ProbeInfo2->Bus ||
722: (ProbeInfo1->Bus == ProbeInfo2->Bus &&
723: (ProbeInfo1->Device > ProbeInfo2->Device)))
724: {
725: BusLogic_ProbeInfo_T TempProbeInfo;
726: memcpy(&TempProbeInfo, ProbeInfo1, sizeof(BusLogic_ProbeInfo_T));
727: memcpy(ProbeInfo1, ProbeInfo2, sizeof(BusLogic_ProbeInfo_T));
728: memcpy(ProbeInfo2, &TempProbeInfo, sizeof(BusLogic_ProbeInfo_T));
729: LastInterchange = j;
730: }
731: }
732: }
733: }
734:
735:
736: /*
737: BusLogic_InitializeMultiMasterProbeInfo initializes the list of I/O Address
738: and Bus Probe Information to be checked for potential BusLogic MultiMaster
739: SCSI Host Adapters by interrogating the PCI Configuration Space on PCI
740: machines as well as from the list of standard BusLogic MultiMaster ISA
741: I/O Addresses. It returns the number of PCI MultiMaster Host Adapters found.
742: */
743:
744: static int BusLogic_InitializeMultiMasterProbeInfo(BusLogic_HostAdapter_T
745: *PrototypeHostAdapter)
746: {
747: BusLogic_ProbeInfo_T *PrimaryProbeInfo =
748: &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount];
749: int NonPrimaryPCIMultiMasterIndex = BusLogic_ProbeInfoCount + 1;
750: int NonPrimaryPCIMultiMasterCount = 0, PCIMultiMasterCount = 0;
751: boolean ForceBusDeviceScanningOrder = false;
752: boolean ForceBusDeviceScanningOrderChecked = false;
753: boolean StandardAddressSeen[6];
754: unsigned char Bus, DeviceFunction;
755: unsigned int BaseAddress0, BaseAddress1;
756: unsigned char IRQ_Channel;
757: BusLogic_IO_Address_T IO_Address;
758: BusLogic_PCI_Address_T PCI_Address;
759: unsigned short Index = 0;
760: int i;
761: if (BusLogic_ProbeInfoCount >= BusLogic_MaxHostAdapters) return 0;
762: BusLogic_ProbeInfoCount++;
763: for (i = 0; i < 6; i++)
764: StandardAddressSeen[i] = false;
765: /*
766: Iterate over the MultiMaster PCI Host Adapters. For each enumerated host
767: adapter, determine whether its ISA Compatible I/O Port is enabled and if
768: so, whether it is assigned the Primary I/O Address. A host adapter that is
769: assigned the Primary I/O Address will always be the preferred boot device.
770: The MultiMaster BIOS will first recognize a host adapter at the Primary I/O
771: Address, then any other PCI host adapters, and finally any host adapters
772: located at the remaining standard ISA I/O Addresses. When a PCI host
773: adapter is found with its ISA Compatible I/O Port enabled, a command is
774: issued to disable the ISA Compatible I/O Port, and it is noted that the
775: particular standard ISA I/O Address need not be probed.
776: */
777: PrimaryProbeInfo->IO_Address = 0;
778: while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC,
779: PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER,
780: Index++, &Bus, &DeviceFunction) == 0)
781: if (pcibios_read_config_dword(Bus, DeviceFunction,
782: PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 &&
783: pcibios_read_config_dword(Bus, DeviceFunction,
784: PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 &&
785: pcibios_read_config_byte(Bus, DeviceFunction,
786: PCI_INTERRUPT_LINE, &IRQ_Channel) == 0)
787: {
788: BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
789: BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
790: BusLogic_ModifyIOAddressRequest_T ModifyIOAddressRequest;
791: unsigned char Device = DeviceFunction >> 3;
792: IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
793: PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
794: if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE)
795: != PCI_BASE_ADDRESS_SPACE_IO)
796: {
797: BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
798: "MultiMaster Host Adapter\n", NULL, BaseAddress0);
799: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
800: NULL, Bus, Device, IO_Address);
801: continue;
802: }
803: if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE)
804: != PCI_BASE_ADDRESS_SPACE_MEMORY)
805: {
806: BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
807: "MultiMaster Host Adapter\n", NULL, BaseAddress1);
808: BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
809: NULL, Bus, Device, PCI_Address);
810: continue;
811: }
812: if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
813: {
814: BusLogic_Error("BusLogic: IRQ Channel %d illegal for "
815: "MultiMaster Host Adapter\n", NULL, IRQ_Channel);
816: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
817: NULL, Bus, Device, IO_Address);
818: continue;
819: }
820: if (BusLogic_GlobalOptions.TraceProbe)
821: {
822: BusLogic_Notice("BusLogic: PCI MultiMaster Host Adapter "
823: "detected at\n", NULL);
824: BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
825: "0x%X PCI Address 0x%X\n", NULL,
826: Bus, Device, IO_Address, PCI_Address);
827: }
828: /*
829: Issue the Inquire PCI Host Adapter Information command to determine
830: the ISA Compatible I/O Port. If the ISA Compatible I/O Port is
831: known and enabled, note that the particular Standard ISA I/O
832: Address should not be probed.
833: */
834: HostAdapter->IO_Address = IO_Address;
835: BusLogic_InterruptReset(HostAdapter);
836: if (BusLogic_Command(HostAdapter,
837: BusLogic_InquirePCIHostAdapterInformation,
838: NULL, 0, &PCIHostAdapterInformation,
839: sizeof(PCIHostAdapterInformation))
840: == sizeof(PCIHostAdapterInformation))
841: {
842: if (PCIHostAdapterInformation.ISACompatibleIOPort < 6)
843: StandardAddressSeen[PCIHostAdapterInformation
844: .ISACompatibleIOPort] = true;
845: }
846: else PCIHostAdapterInformation.ISACompatibleIOPort =
847: BusLogic_IO_Disable;
848: /*
849: Issue the Modify I/O Address command to disable the ISA Compatible
850: I/O Port.
851: */
852: ModifyIOAddressRequest = BusLogic_IO_Disable;
853: BusLogic_Command(HostAdapter, BusLogic_ModifyIOAddress,
854: &ModifyIOAddressRequest,
855: sizeof(ModifyIOAddressRequest), NULL, 0);
856: /*
857: For the first MultiMaster Host Adapter enumerated, issue the Fetch
858: Host Adapter Local RAM command to read byte 45 of the AutoSCSI area,
859: for the setting of the "Use Bus And Device # For PCI Scanning Seq."
860: option. Issue the Inquire Board ID command since this option is
861: only valid for the BT-948/958/958D.
862: */
863: if (!ForceBusDeviceScanningOrderChecked)
864: {
865: BusLogic_FetchHostAdapterLocalRAMRequest_T
866: FetchHostAdapterLocalRAMRequest;
867: BusLogic_AutoSCSIByte45_T AutoSCSIByte45;
868: BusLogic_BoardID_T BoardID;
869: FetchHostAdapterLocalRAMRequest.ByteOffset =
870: BusLogic_AutoSCSI_BaseOffset + 45;
871: FetchHostAdapterLocalRAMRequest.ByteCount =
872: sizeof(AutoSCSIByte45);
873: BusLogic_Command(HostAdapter,
874: BusLogic_FetchHostAdapterLocalRAM,
875: &FetchHostAdapterLocalRAMRequest,
876: sizeof(FetchHostAdapterLocalRAMRequest),
877: &AutoSCSIByte45, sizeof(AutoSCSIByte45));
878: BusLogic_Command(HostAdapter, BusLogic_InquireBoardID,
879: NULL, 0, &BoardID, sizeof(BoardID));
880: if (BoardID.FirmwareVersion1stDigit == '5')
881: ForceBusDeviceScanningOrder =
882: AutoSCSIByte45.ForceBusDeviceScanningOrder;
883: ForceBusDeviceScanningOrderChecked = true;
884: }
885: /*
886: Determine whether this MultiMaster Host Adapter has its ISA
887: Compatible I/O Port enabled and is assigned the Primary I/O Address.
888: If it does, then it is the Primary MultiMaster Host Adapter and must
889: be recognized first. If it does not, then it is added to the list
890: for probing after any Primary MultiMaster Host Adapter is probed.
891: */
892: if (PCIHostAdapterInformation.ISACompatibleIOPort == BusLogic_IO_330)
893: {
894: PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
895: PrimaryProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
896: PrimaryProbeInfo->IO_Address = IO_Address;
897: PrimaryProbeInfo->PCI_Address = PCI_Address;
898: PrimaryProbeInfo->Bus = Bus;
899: PrimaryProbeInfo->Device = Device;
900: PrimaryProbeInfo->IRQ_Channel = IRQ_Channel;
901: PCIMultiMasterCount++;
902: }
903: else if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
904: {
905: BusLogic_ProbeInfo_T *ProbeInfo =
906: &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
907: ProbeInfo->HostAdapterType = BusLogic_MultiMaster;
908: ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
909: ProbeInfo->IO_Address = IO_Address;
910: ProbeInfo->PCI_Address = PCI_Address;
911: ProbeInfo->Bus = Bus;
912: ProbeInfo->Device = Device;
913: ProbeInfo->IRQ_Channel = IRQ_Channel;
914: NonPrimaryPCIMultiMasterCount++;
915: PCIMultiMasterCount++;
916: }
917: else BusLogic_Warning("BusLogic: Too many Host Adapters "
918: "detected\n", NULL);
919: }
920: /*
921: If the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option is ON
922: for the first enumerated MultiMaster Host Adapter, and if that host adapter
923: is a BT-948/958/958D, then the MultiMaster BIOS will recognize MultiMaster
924: Host Adapters in the order of increasing PCI Bus and Device Number. In
925: that case, sort the probe information into the same order the BIOS uses.
926: If this option is OFF, then the MultiMaster BIOS will recognize MultiMaster
927: Host Adapters in the order they are enumerated by the PCI BIOS, and hence
928: no sorting is necessary.
929: */
930: if (ForceBusDeviceScanningOrder)
931: BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[
932: NonPrimaryPCIMultiMasterIndex],
933: NonPrimaryPCIMultiMasterCount);
934: /*
935: If no PCI MultiMaster Host Adapter is assigned the Primary I/O Address,
936: then the Primary I/O Address must be probed explicitly before any PCI
937: host adapters are probed.
938: */
939: if (!BusLogic_ProbeOptions.NoProbeISA)
940: if (PrimaryProbeInfo->IO_Address == 0 &&
941: (BusLogic_ProbeOptions.LimitedProbeISA
942: ? BusLogic_ProbeOptions.Probe330
943: : check_region(0x330, BusLogic_MultiMasterAddressCount) == 0))
944: {
945: PrimaryProbeInfo->HostAdapterType = BusLogic_MultiMaster;
946: PrimaryProbeInfo->HostAdapterBusType = BusLogic_ISA_Bus;
947: PrimaryProbeInfo->IO_Address = 0x330;
948: }
949: /*
950: Append the list of standard BusLogic MultiMaster ISA I/O Addresses,
951: omitting the Primary I/O Address which has already been handled.
952: */
953: if (!BusLogic_ProbeOptions.NoProbeISA)
954: {
955: if (!StandardAddressSeen[1] &&
956: (BusLogic_ProbeOptions.LimitedProbeISA
957: ? BusLogic_ProbeOptions.Probe334
958: : check_region(0x334, BusLogic_MultiMasterAddressCount) == 0))
959: BusLogic_AppendProbeAddressISA(0x334);
960: if (!StandardAddressSeen[2] &&
961: (BusLogic_ProbeOptions.LimitedProbeISA
962: ? BusLogic_ProbeOptions.Probe230
963: : check_region(0x230, BusLogic_MultiMasterAddressCount) == 0))
964: BusLogic_AppendProbeAddressISA(0x230);
965: if (!StandardAddressSeen[3] &&
966: (BusLogic_ProbeOptions.LimitedProbeISA
967: ? BusLogic_ProbeOptions.Probe234
968: : check_region(0x234, BusLogic_MultiMasterAddressCount) == 0))
969: BusLogic_AppendProbeAddressISA(0x234);
970: if (!StandardAddressSeen[4] &&
971: (BusLogic_ProbeOptions.LimitedProbeISA
972: ? BusLogic_ProbeOptions.Probe130
973: : check_region(0x130, BusLogic_MultiMasterAddressCount) == 0))
974: BusLogic_AppendProbeAddressISA(0x130);
975: if (!StandardAddressSeen[5] &&
976: (BusLogic_ProbeOptions.LimitedProbeISA
977: ? BusLogic_ProbeOptions.Probe134
978: : check_region(0x134, BusLogic_MultiMasterAddressCount) == 0))
979: BusLogic_AppendProbeAddressISA(0x134);
980: }
981: /*
982: Iterate over the older non-compliant MultiMaster PCI Host Adapters,
983: noting the PCI bus location and assigned IRQ Channel.
984: */
985: Index = 0;
986: while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC,
987: PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC,
988: Index++, &Bus, &DeviceFunction) == 0)
989: if (pcibios_read_config_dword(Bus, DeviceFunction,
990: PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 &&
991: pcibios_read_config_byte(Bus, DeviceFunction,
992: PCI_INTERRUPT_LINE, &IRQ_Channel) == 0)
993: {
994: unsigned char Device = DeviceFunction >> 3;
995: IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
996: if (IO_Address == 0 || IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
997: continue;
998: for (i = 0; i < BusLogic_ProbeInfoCount; i++)
999: {
1000: BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[i];
1001: if (ProbeInfo->IO_Address == IO_Address &&
1002: ProbeInfo->HostAdapterType == BusLogic_MultiMaster)
1003: {
1004: ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
1005: ProbeInfo->PCI_Address = 0;
1006: ProbeInfo->Bus = Bus;
1007: ProbeInfo->Device = Device;
1008: ProbeInfo->IRQ_Channel = IRQ_Channel;
1009: break;
1010: }
1011: }
1012: }
1013: return PCIMultiMasterCount;
1014: }
1015:
1016:
1017: /*
1018: BusLogic_InitializeFlashPointProbeInfo initializes the list of I/O Address
1019: and Bus Probe Information to be checked for potential BusLogic FlashPoint
1020: Host Adapters by interrogating the PCI Configuration Space. It returns the
1021: number of FlashPoint Host Adapters found.
1022: */
1023:
1024: static int BusLogic_InitializeFlashPointProbeInfo(BusLogic_HostAdapter_T
1025: *PrototypeHostAdapter)
1026: {
1027: int FlashPointIndex = BusLogic_ProbeInfoCount, FlashPointCount = 0;
1028: unsigned char Bus, DeviceFunction;
1029: unsigned int BaseAddress0, BaseAddress1;
1030: unsigned char IRQ_Channel;
1031: BusLogic_IO_Address_T IO_Address;
1032: BusLogic_PCI_Address_T PCI_Address;
1033: unsigned short Index = 0;
1034: /*
1035: Interrogate PCI Configuration Space for any FlashPoint Host Adapters.
1036: */
1037: while (pcibios_find_device(PCI_VENDOR_ID_BUSLOGIC,
1038: PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT,
1039: Index++, &Bus, &DeviceFunction) == 0)
1040: if (pcibios_read_config_dword(Bus, DeviceFunction,
1041: PCI_BASE_ADDRESS_0, &BaseAddress0) == 0 &&
1042: pcibios_read_config_dword(Bus, DeviceFunction,
1043: PCI_BASE_ADDRESS_1, &BaseAddress1) == 0 &&
1044: pcibios_read_config_byte(Bus, DeviceFunction,
1045: PCI_INTERRUPT_LINE, &IRQ_Channel) == 0)
1046: {
1047: unsigned char Device = DeviceFunction >> 3;
1048: IO_Address = BaseAddress0 & PCI_BASE_ADDRESS_IO_MASK;
1049: PCI_Address = BaseAddress1 & PCI_BASE_ADDRESS_MEM_MASK;
1050: #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
1051: if ((BaseAddress0 & PCI_BASE_ADDRESS_SPACE)
1052: != PCI_BASE_ADDRESS_SPACE_IO)
1053: {
1054: BusLogic_Error("BusLogic: Base Address0 0x%X not I/O for "
1055: "FlashPoint Host Adapter\n", NULL, BaseAddress0);
1056: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
1057: NULL, Bus, Device, IO_Address);
1058: continue;
1059: }
1060: if ((BaseAddress1 & PCI_BASE_ADDRESS_SPACE)
1061: != PCI_BASE_ADDRESS_SPACE_MEMORY)
1062: {
1063: BusLogic_Error("BusLogic: Base Address1 0x%X not Memory for "
1064: "FlashPoint Host Adapter\n", NULL, BaseAddress1);
1065: BusLogic_Error("at PCI Bus %d Device %d PCI Address 0x%X\n",
1066: NULL, Bus, Device, PCI_Address);
1067: continue;
1068: }
1069: if (IRQ_Channel == 0 || IRQ_Channel >= NR_IRQS)
1070: {
1071: BusLogic_Error("BusLogic: IRQ Channel %d illegal for "
1072: "FlashPoint Host Adapter\n", NULL, IRQ_Channel);
1073: BusLogic_Error("at PCI Bus %d Device %d I/O Address 0x%X\n",
1074: NULL, Bus, Device, IO_Address);
1075: continue;
1076: }
1077: if (BusLogic_GlobalOptions.TraceProbe)
1078: {
1079: BusLogic_Notice("BusLogic: FlashPoint Host Adapter "
1080: "detected at\n", NULL);
1081: BusLogic_Notice("BusLogic: PCI Bus %d Device %d I/O Address "
1082: "0x%X PCI Address 0x%X\n", NULL,
1083: Bus, Device, IO_Address, PCI_Address);
1084: }
1085: if (BusLogic_ProbeInfoCount < BusLogic_MaxHostAdapters)
1086: {
1087: BusLogic_ProbeInfo_T *ProbeInfo =
1088: &BusLogic_ProbeInfoList[BusLogic_ProbeInfoCount++];
1089: ProbeInfo->HostAdapterType = BusLogic_FlashPoint;
1090: ProbeInfo->HostAdapterBusType = BusLogic_PCI_Bus;
1091: ProbeInfo->IO_Address = IO_Address;
1092: ProbeInfo->PCI_Address = PCI_Address;
1093: ProbeInfo->Bus = Bus;
1094: ProbeInfo->Device = Device;
1095: ProbeInfo->IRQ_Channel = IRQ_Channel;
1096: FlashPointCount++;
1097: }
1098: else BusLogic_Warning("BusLogic: Too many Host Adapters "
1099: "detected\n", NULL);
1100: #else
1101: BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
1102: "PCI Bus %d Device %d\n", NULL, Bus, Device);
1103: BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
1104: "but FlashPoint\n", NULL, IO_Address, PCI_Address);
1105: BusLogic_Error("BusLogic: support was omitted in this kernel "
1106: "configuration.\n", NULL);
1107: #endif
1108: }
1109: /*
1110: The FlashPoint BIOS will scan for FlashPoint Host Adapters in the order of
1111: increasing PCI Bus and Device Number, so sort the probe information into
1112: the same order the BIOS uses.
1113: */
1114: BusLogic_SortProbeInfo(&BusLogic_ProbeInfoList[FlashPointIndex],
1115: FlashPointCount);
1116: return FlashPointCount;
1117: }
1118:
1119:
1120: /*
1121: BusLogic_InitializeProbeInfoList initializes the list of I/O Address and Bus
1122: Probe Information to be checked for potential BusLogic SCSI Host Adapters by
1123: interrogating the PCI Configuration Space on PCI machines as well as from the
1124: list of standard BusLogic MultiMaster ISA I/O Addresses. By default, if both
1125: FlashPoint and PCI MultiMaster Host Adapters are present, this driver will
1126: probe for FlashPoint Host Adapters first unless the BIOS primary disk is
1127: controlled by the first PCI MultiMaster Host Adapter, in which case
1128: MultiMaster Host Adapters will be probed first. The BusLogic Driver Options
1129: specifications "MultiMasterFirst" and "FlashPointFirst" can be used to force
1130: a particular probe order.
1131: */
1132:
1133: static void BusLogic_InitializeProbeInfoList(BusLogic_HostAdapter_T
1134: *PrototypeHostAdapter)
1135: {
1136: /*
1137: If a PCI BIOS is present, interrogate it for MultiMaster and FlashPoint
1138: Host Adapters; otherwise, default to the standard ISA MultiMaster probe.
1139: */
1140: if (!BusLogic_ProbeOptions.NoProbePCI && pcibios_present())
1141: {
1142: if (BusLogic_ProbeOptions.MultiMasterFirst)
1143: {
1144: BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
1145: BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
1146: }
1147: else if (BusLogic_ProbeOptions.FlashPointFirst)
1148: {
1149: BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
1150: BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
1151: }
1152: else
1153: {
1154: int FlashPointCount =
1155: BusLogic_InitializeFlashPointProbeInfo(PrototypeHostAdapter);
1156: int PCIMultiMasterCount =
1157: BusLogic_InitializeMultiMasterProbeInfo(PrototypeHostAdapter);
1158: if (FlashPointCount > 0 && PCIMultiMasterCount > 0)
1159: {
1160: BusLogic_ProbeInfo_T *ProbeInfo =
1161: &BusLogic_ProbeInfoList[FlashPointCount];
1162: BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
1163: BusLogic_FetchHostAdapterLocalRAMRequest_T
1164: FetchHostAdapterLocalRAMRequest;
1165: BusLogic_BIOSDriveMapByte_T Drive0MapByte;
1166: while (ProbeInfo->HostAdapterBusType != BusLogic_PCI_Bus)
1167: ProbeInfo++;
1168: HostAdapter->IO_Address = ProbeInfo->IO_Address;
1169: FetchHostAdapterLocalRAMRequest.ByteOffset =
1170: BusLogic_BIOS_BaseOffset + BusLogic_BIOS_DriveMapOffset + 0;
1171: FetchHostAdapterLocalRAMRequest.ByteCount =
1172: sizeof(Drive0MapByte);
1173: BusLogic_Command(HostAdapter,
1174: BusLogic_FetchHostAdapterLocalRAM,
1175: &FetchHostAdapterLocalRAMRequest,
1176: sizeof(FetchHostAdapterLocalRAMRequest),
1177: &Drive0MapByte, sizeof(Drive0MapByte));
1178: /*
1179: If the Map Byte for BIOS Drive 0 indicates that BIOS Drive 0
1180: is controlled by this PCI MultiMaster Host Adapter, then
1181: reverse the probe order so that MultiMaster Host Adapters are
1182: probed before FlashPoint Host Adapters.
1183: */
1184: if (Drive0MapByte.DiskGeometry !=
1185: BusLogic_BIOS_Disk_Not_Installed)
1186: {
1187: BusLogic_ProbeInfo_T
1188: SavedProbeInfo[BusLogic_MaxHostAdapters];
1189: int MultiMasterCount =
1190: BusLogic_ProbeInfoCount - FlashPointCount;
1191: memcpy(SavedProbeInfo,
1192: BusLogic_ProbeInfoList,
1193: BusLogic_ProbeInfoCount
1194: * sizeof(BusLogic_ProbeInfo_T));
1195: memcpy(&BusLogic_ProbeInfoList[0],
1196: &SavedProbeInfo[FlashPointCount],
1197: MultiMasterCount * sizeof(BusLogic_ProbeInfo_T));
1198: memcpy(&BusLogic_ProbeInfoList[MultiMasterCount],
1199: &SavedProbeInfo[0],
1200: FlashPointCount * sizeof(BusLogic_ProbeInfo_T));
1201: }
1202: }
1203: }
1204: }
1205: else BusLogic_InitializeProbeInfoListISA(PrototypeHostAdapter);
1206: }
1207:
1208:
1209: #endif /* CONFIG_PCI */
1210:
1211:
1212: /*
1213: BusLogic_Failure prints a standardized error message, and then returns false.
1214: */
1215:
1216: static boolean BusLogic_Failure(BusLogic_HostAdapter_T *HostAdapter,
1217: char *ErrorMessage)
1218: {
1219: BusLogic_AnnounceDriver(HostAdapter);
1220: if (HostAdapter->HostAdapterBusType == BusLogic_PCI_Bus)
1221: {
1222: BusLogic_Error("While configuring BusLogic PCI Host Adapter at\n",
1223: HostAdapter);
1224: BusLogic_Error("Bus %d Device %d I/O Address 0x%X PCI Address 0x%X:\n",
1225: HostAdapter, HostAdapter->Bus, HostAdapter->Device,
1226: HostAdapter->IO_Address, HostAdapter->PCI_Address);
1227: }
1228: else BusLogic_Error("While configuring BusLogic Host Adapter at "
1229: "I/O Address 0x%X:\n", HostAdapter,
1230: HostAdapter->IO_Address);
1231: BusLogic_Error("%s FAILED - DETACHING\n", HostAdapter, ErrorMessage);
1232: if (BusLogic_CommandFailureReason != NULL)
1233: BusLogic_Error("ADDITIONAL FAILURE INFO - %s\n", HostAdapter,
1234: BusLogic_CommandFailureReason);
1235: return false;
1236: }
1237:
1238:
1239: /*
1240: BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
1241: */
1242:
1243: static boolean BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
1244: {
1245: BusLogic_StatusRegister_T StatusRegister;
1246: BusLogic_InterruptRegister_T InterruptRegister;
1247: BusLogic_GeometryRegister_T GeometryRegister;
1248: /*
1249: FlashPoint Host Adapters are Probed by the FlashPoint SCCB Manager.
1250: */
1251: if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1252: {
1253: FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
1254: FlashPointInfo->BaseAddress =
1255: (BusLogic_Base_Address_T) HostAdapter->IO_Address;
1256: FlashPointInfo->IRQ_Channel = HostAdapter->IRQ_Channel;
1257: FlashPointInfo->Present = false;
1258: if (!(FlashPoint_ProbeHostAdapter(FlashPointInfo) == 0 &&
1259: FlashPointInfo->Present))
1260: {
1261: BusLogic_Error("BusLogic: FlashPoint Host Adapter detected at "
1262: "PCI Bus %d Device %d\n", HostAdapter,
1263: HostAdapter->Bus, HostAdapter->Device);
1264: BusLogic_Error("BusLogic: I/O Address 0x%X PCI Address 0x%X, "
1265: "but FlashPoint\n", HostAdapter,
1266: HostAdapter->IO_Address, HostAdapter->PCI_Address);
1267: BusLogic_Error("BusLogic: Probe Function failed to validate it.\n",
1268: HostAdapter);
1269: return false;
1270: }
1271: if (BusLogic_GlobalOptions.TraceProbe)
1272: BusLogic_Notice("BusLogic_Probe(0x%X): FlashPoint Found\n",
1273: HostAdapter, HostAdapter->IO_Address);
1274: /*
1275: Indicate the Host Adapter Probe completed successfully.
1276: */
1277: return true;
1278: }
1279: /*
1280: Read the Status, Interrupt, and Geometry Registers to test if there are I/O
1281: ports that respond, and to check the values to determine if they are from a
1282: BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which
1283: case there is definitely no BusLogic Host Adapter at this base I/O Address.
1284: The test here is a subset of that used by the BusLogic Host Adapter BIOS.
1285: */
1286: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1287: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
1288: GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
1289: if (BusLogic_GlobalOptions.TraceProbe)
1290: BusLogic_Notice("BusLogic_Probe(0x%X): Status 0x%02X, Interrupt 0x%02X, "
1291: "Geometry 0x%02X\n", HostAdapter,
1292: HostAdapter->IO_Address, StatusRegister.All,
1293: InterruptRegister.All, GeometryRegister.All);
1294: if (StatusRegister.All == 0 ||
1295: StatusRegister.Bits.DiagnosticActive ||
1296: StatusRegister.Bits.CommandParameterRegisterBusy ||
1297: StatusRegister.Bits.Reserved ||
1298: StatusRegister.Bits.CommandInvalid ||
1299: InterruptRegister.Bits.Reserved != 0)
1300: return false;
1301: /*
1302: Check the undocumented Geometry Register to test if there is an I/O port
1303: that responded. Adaptec Host Adapters do not implement the Geometry
1304: Register, so this test helps serve to avoid incorrectly recognizing an
1305: Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C
1306: series does respond to the Geometry Register I/O port, but it will be
1307: rejected later when the Inquire Extended Setup Information command is
1308: issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a
1309: BusLogic clone that implements the same interface as earlier BusLogic
1310: Host Adapters, including the undocumented commands, and is therefore
1311: supported by this driver. However, the AMI FastDisk always returns 0x00
1312: upon reading the Geometry Register, so the extended translation option
1313: should always be left disabled on the AMI FastDisk.
1314: */
1315: if (GeometryRegister.All == 0xFF) return false;
1316: /*
1317: Indicate the Host Adapter Probe completed successfully.
1318: */
1319: return true;
1320: }
1321:
1322:
1323: /*
1324: BusLogic_HardwareResetHostAdapter issues a Hardware Reset to the Host Adapter
1325: and waits for Host Adapter Diagnostics to complete. If HardReset is true, a
1326: Hard Reset is performed which also initiates a SCSI Bus Reset. Otherwise, a
1327: Soft Reset is performed which only resets the Host Adapter without forcing a
1328: SCSI Bus Reset.
1329: */
1330:
1331: static boolean BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T
1332: *HostAdapter,
1333: boolean HardReset)
1334: {
1335: BusLogic_StatusRegister_T StatusRegister;
1336: int TimeoutCounter;
1337: /*
1338: FlashPoint Host Adapters are Hard Reset by the FlashPoint SCCB Manager.
1339: */
1340: if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1341: {
1342: FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
1343: FlashPointInfo->HostSoftReset = !HardReset;
1344: FlashPointInfo->ReportDataUnderrun = true;
1345: HostAdapter->CardHandle =
1346: FlashPoint_HardwareResetHostAdapter(FlashPointInfo);
1347: if (HostAdapter->CardHandle == FlashPoint_BadCardHandle) return false;
1348: /*
1349: Indicate the Host Adapter Hard Reset completed successfully.
1350: */
1351: return true;
1352: }
1353: /*
1354: Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host
1355: Adapter should respond by setting Diagnostic Active in the Status Register.
1356: */
1357: if (HardReset)
1358: BusLogic_HardReset(HostAdapter);
1359: else BusLogic_SoftReset(HostAdapter);
1360: /*
1361: Wait until Diagnostic Active is set in the Status Register.
1362: */
1363: TimeoutCounter = 5*10000;
1364: while (--TimeoutCounter >= 0)
1365: {
1366: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1367: if (StatusRegister.Bits.DiagnosticActive) break;
1368: udelay(100);
1369: }
1370: if (BusLogic_GlobalOptions.TraceHardwareReset)
1371: BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Active, "
1372: "Status 0x%02X\n", HostAdapter,
1373: HostAdapter->IO_Address, StatusRegister.All);
1374: if (TimeoutCounter < 0) return false;
1375: /*
1376: Wait 100 microseconds to allow completion of any initial diagnostic
1377: activity which might leave the contents of the Status Register
1378: unpredictable.
1379: */
1380: udelay(100);
1381: /*
1382: Wait until Diagnostic Active is reset in the Status Register.
1383: */
1384: TimeoutCounter = 10*10000;
1385: while (--TimeoutCounter >= 0)
1386: {
1387: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1388: if (!StatusRegister.Bits.DiagnosticActive) break;
1389: udelay(100);
1390: }
1391: if (BusLogic_GlobalOptions.TraceHardwareReset)
1392: BusLogic_Notice("BusLogic_HardwareReset(0x%X): Diagnostic Completed, "
1393: "Status 0x%02X\n", HostAdapter,
1394: HostAdapter->IO_Address, StatusRegister.All);
1395: if (TimeoutCounter < 0) return false;
1396: /*
1397: Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
1398: or Data In Register Ready bits is set in the Status Register.
1399: */
1400: TimeoutCounter = 10000;
1401: while (--TimeoutCounter >= 0)
1402: {
1403: StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
1404: if (StatusRegister.Bits.DiagnosticFailure ||
1405: StatusRegister.Bits.HostAdapterReady ||
1406: StatusRegister.Bits.DataInRegisterReady)
1407: break;
1408: udelay(100);
1409: }
1410: if (BusLogic_GlobalOptions.TraceHardwareReset)
1411: BusLogic_Notice("BusLogic_HardwareReset(0x%X): Host Adapter Ready, "
1412: "Status 0x%02X\n", HostAdapter,
1413: HostAdapter->IO_Address, StatusRegister.All);
1414: if (TimeoutCounter < 0) return false;
1415: /*
1416: If Diagnostic Failure is set or Host Adapter Ready is reset, then an
1417: error occurred during the Host Adapter diagnostics. If Data In Register
1418: Ready is set, then there is an Error Code available.
1419: */
1420: if (StatusRegister.Bits.DiagnosticFailure ||
1421: !StatusRegister.Bits.HostAdapterReady)
1422: {
1423: BusLogic_CommandFailureReason = NULL;
1424: BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS");
1425: BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n",
1426: HostAdapter, StatusRegister.All);
1427: if (StatusRegister.Bits.DataInRegisterReady)
1428: {
1429: unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter);
1430: BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n",
1431: HostAdapter, ErrorCode);
1432: }
1433: return false;
1434: }
1435: /*
1436: Indicate the Host Adapter Hard Reset completed successfully.
1437: */
1438: return true;
1439: }
1440:
1441:
1442: /*
1443: BusLogic_CheckHostAdapter checks to be sure this really is a BusLogic
1444: Host Adapter.
1445: */
1446:
1447: static boolean BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
1448: {
1449: BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
1450: BusLogic_RequestedReplyLength_T RequestedReplyLength;
1451: boolean Result = true;
1452: /*
1453: FlashPoint Host Adapters do not require this protection.
1454: */
1455: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
1456: /*
1457: Issue the Inquire Extended Setup Information command. Only genuine
1458: BusLogic Host Adapters and true clones support this command. Adaptec 1542C
1459: series Host Adapters that respond to the Geometry Register I/O port will
1460: fail this command.
1461: */
1462: RequestedReplyLength = sizeof(ExtendedSetupInformation);
1463: if (BusLogic_Command(HostAdapter,
1464: BusLogic_InquireExtendedSetupInformation,
1465: &RequestedReplyLength,
1466: sizeof(RequestedReplyLength),
1467: &ExtendedSetupInformation,
1468: sizeof(ExtendedSetupInformation))
1469: != sizeof(ExtendedSetupInformation))
1470: Result = false;
1471: /*
1472: Provide tracing information if requested and return.
1473: */
1474: if (BusLogic_GlobalOptions.TraceProbe)
1475: BusLogic_Notice("BusLogic_Check(0x%X): MultiMaster %s\n", HostAdapter,
1476: HostAdapter->IO_Address, (Result ? "Found" : "Not Found"));
1477: return Result;
1478: }
1479:
1480:
1481: /*
1482: BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
1483: from Host Adapter and initializes the Host Adapter structure.
1484: */
1485:
1486: static boolean BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T
1487: *HostAdapter)
1488: {
1489: BusLogic_BoardID_T BoardID;
1490: BusLogic_Configuration_T Configuration;
1491: BusLogic_SetupInformation_T SetupInformation;
1492: BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
1493: BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber;
1494: BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit;
1495: BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter;
1496: BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
1497: BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest;
1498: BusLogic_AutoSCSIData_T AutoSCSIData;
1499: BusLogic_GeometryRegister_T GeometryRegister;
1500: BusLogic_RequestedReplyLength_T RequestedReplyLength;
1501: unsigned char *TargetPointer, Character;
1502: int TargetID, i;
1503: /*
1504: Configuration Information for FlashPoint Host Adapters is provided in the
1505: FlashPoint_Info structure by the FlashPoint SCCB Manager's Probe Function.
1506: Initialize fields in the Host Adapter structure from the FlashPoint_Info
1507: structure.
1508: */
1509: if (BusLogic_FlashPointHostAdapterP(HostAdapter))
1510: {
1511: FlashPoint_Info_T *FlashPointInfo = &HostAdapter->FlashPointInfo;
1512: TargetPointer = HostAdapter->ModelName;
1513: *TargetPointer++ = 'B';
1514: *TargetPointer++ = 'T';
1515: *TargetPointer++ = '-';
1516: for (i = 0; i < sizeof(FlashPointInfo->ModelNumber); i++)
1517: *TargetPointer++ = FlashPointInfo->ModelNumber[i];
1518: *TargetPointer++ = '\0';
1519: strcpy(HostAdapter->FirmwareVersion, FlashPoint_FirmwareVersion);
1520: HostAdapter->SCSI_ID = FlashPointInfo->SCSI_ID;
1521: HostAdapter->ExtendedTranslationEnabled =
1522: FlashPointInfo->ExtendedTranslationEnabled;
1523: HostAdapter->ParityCheckingEnabled =
1524: FlashPointInfo->ParityCheckingEnabled;
1525: HostAdapter->BusResetEnabled = !FlashPointInfo->HostSoftReset;
1526: HostAdapter->LevelSensitiveInterrupt = true;
1527: HostAdapter->HostWideSCSI = FlashPointInfo->HostWideSCSI;
1528: HostAdapter->HostDifferentialSCSI = false;
1529: HostAdapter->HostSupportsSCAM = true;
1530: HostAdapter->HostUltraSCSI = true;
1531: HostAdapter->ExtendedLUNSupport = true;
1532: HostAdapter->TerminationInfoValid = true;
1533: HostAdapter->LowByteTerminated = FlashPointInfo->LowByteTerminated;
1534: HostAdapter->HighByteTerminated = FlashPointInfo->HighByteTerminated;
1535: HostAdapter->SCAM_Enabled = FlashPointInfo->SCAM_Enabled;
1536: HostAdapter->SCAM_Level2 = FlashPointInfo->SCAM_Level2;
1537: HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
1538: HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
1539: HostAdapter->MaxLogicalUnits = 32;
1540: HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
1541: HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
1542: HostAdapter->DriverQueueDepth = 255;
1543: HostAdapter->HostAdapterQueueDepth = HostAdapter->DriverQueueDepth;
1544: HostAdapter->SynchronousPermitted = FlashPointInfo->SynchronousPermitted;
1545: HostAdapter->FastPermitted = FlashPointInfo->FastPermitted;
1546: HostAdapter->UltraPermitted = FlashPointInfo->UltraPermitted;
1547: HostAdapter->WidePermitted = FlashPointInfo->WidePermitted;
1548: HostAdapter->DisconnectPermitted = FlashPointInfo->DisconnectPermitted;
1549: HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1550: goto Common;
1551: }
1552: /*
1553: Issue the Inquire Board ID command.
1554: */
1555: if (BusLogic_Command(HostAdapter, BusLogic_InquireBoardID, NULL, 0,
1556: &BoardID, sizeof(BoardID)) != sizeof(BoardID))
1557: return BusLogic_Failure(HostAdapter, "INQUIRE BOARD ID");
1558: /*
1559: Issue the Inquire Configuration command.
1560: */
1561: if (BusLogic_Command(HostAdapter, BusLogic_InquireConfiguration, NULL, 0,
1562: &Configuration, sizeof(Configuration))
1563: != sizeof(Configuration))
1564: return BusLogic_Failure(HostAdapter, "INQUIRE CONFIGURATION");
1565: /*
1566: Issue the Inquire Setup Information command.
1567: */
1568: RequestedReplyLength = sizeof(SetupInformation);
1569: if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
1570: &RequestedReplyLength, sizeof(RequestedReplyLength),
1571: &SetupInformation, sizeof(SetupInformation))
1572: != sizeof(SetupInformation))
1573: return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
1574: /*
1575: Issue the Inquire Extended Setup Information command.
1576: */
1577: RequestedReplyLength = sizeof(ExtendedSetupInformation);
1578: if (BusLogic_Command(HostAdapter, BusLogic_InquireExtendedSetupInformation,
1579: &RequestedReplyLength, sizeof(RequestedReplyLength),
1580: &ExtendedSetupInformation,
1581: sizeof(ExtendedSetupInformation))
1582: != sizeof(ExtendedSetupInformation))
1583: return BusLogic_Failure(HostAdapter, "INQUIRE EXTENDED SETUP INFORMATION");
1584: /*
1585: Issue the Inquire Firmware Version 3rd Digit command.
1586: */
1587: FirmwareVersion3rdDigit = '\0';
1588: if (BoardID.FirmwareVersion1stDigit > '0')
1589: if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersion3rdDigit,
1590: NULL, 0, &FirmwareVersion3rdDigit,
1591: sizeof(FirmwareVersion3rdDigit))
1592: != sizeof(FirmwareVersion3rdDigit))
1593: return BusLogic_Failure(HostAdapter, "INQUIRE FIRMWARE 3RD DIGIT");
1594: /*
1595: Issue the Inquire Host Adapter Model Number command.
1596: */
1597: if (ExtendedSetupInformation.BusType == 'A' &&
1598: BoardID.FirmwareVersion1stDigit == '2')
1599: /* BusLogic BT-542B ISA 2.xx */
1600: strcpy(HostAdapterModelNumber, "542B");
1601: else if (ExtendedSetupInformation.BusType == 'E' &&
1602: BoardID.FirmwareVersion1stDigit == '2' &&
1603: (BoardID.FirmwareVersion2ndDigit <= '1' ||
1604: (BoardID.FirmwareVersion2ndDigit == '2' &&
1605: FirmwareVersion3rdDigit == '0')))
1606: /* BusLogic BT-742A EISA 2.1x or 2.20 */
1607: strcpy(HostAdapterModelNumber, "742A");
1608: else if (ExtendedSetupInformation.BusType == 'E' &&
1609: BoardID.FirmwareVersion1stDigit == '0')
1610: /* AMI FastDisk EISA Series 441 0.x */
1611: strcpy(HostAdapterModelNumber, "747A");
1612: else
1613: {
1614: RequestedReplyLength = sizeof(HostAdapterModelNumber);
1615: if (BusLogic_Command(HostAdapter, BusLogic_InquireHostAdapterModelNumber,
1616: &RequestedReplyLength, sizeof(RequestedReplyLength),
1617: &HostAdapterModelNumber,
1618: sizeof(HostAdapterModelNumber))
1619: != sizeof(HostAdapterModelNumber))
1620: return BusLogic_Failure(HostAdapter,
1621: "INQUIRE HOST ADAPTER MODEL NUMBER");
1622: }
1623: /*
1624: BusLogic MultiMaster Host Adapters can be identified by their model number
1625: and the major version number of their firmware as follows:
1626:
1627: 5.xx BusLogic "W" Series Host Adapters:
1628: BT-948/958/958D
1629: 4.xx BusLogic "C" Series Host Adapters:
1630: BT-946C/956C/956CD/747C/757C/757CD/445C/545C/540CF
1631: 3.xx BusLogic "S" Series Host Adapters:
1632: BT-747S/747D/757S/757D/445S/545S/542D
1633: BT-542B/742A (revision H)
1634: 2.xx BusLogic "A" Series Host Adapters:
1635: BT-542B/742A (revision G and below)
1636: 0.xx AMI FastDisk VLB/EISA BusLogic Clone Host Adapter
1637: */
1638: /*
1639: Save the Model Name and Host Adapter Name in the Host Adapter structure.
1640: */
1641: TargetPointer = HostAdapter->ModelName;
1642: *TargetPointer++ = 'B';
1643: *TargetPointer++ = 'T';
1644: *TargetPointer++ = '-';
1645: for (i = 0; i < sizeof(HostAdapterModelNumber); i++)
1646: {
1647: Character = HostAdapterModelNumber[i];
1648: if (Character == ' ' || Character == '\0') break;
1649: *TargetPointer++ = Character;
1650: }
1651: *TargetPointer++ = '\0';
1652: /*
1653: Save the Firmware Version in the Host Adapter structure.
1654: */
1655: TargetPointer = HostAdapter->FirmwareVersion;
1656: *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
1657: *TargetPointer++ = '.';
1658: *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
1659: if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
1660: *TargetPointer++ = FirmwareVersion3rdDigit;
1661: *TargetPointer = '\0';
1662: /*
1663: Issue the Inquire Firmware Version Letter command.
1664: */
1665: if (strcmp(HostAdapter->FirmwareVersion, "3.3") >= 0)
1666: {
1667: if (BusLogic_Command(HostAdapter, BusLogic_InquireFirmwareVersionLetter,
1668: NULL, 0, &FirmwareVersionLetter,
1669: sizeof(FirmwareVersionLetter))
1670: != sizeof(FirmwareVersionLetter))
1671: return BusLogic_Failure(HostAdapter,
1672: "INQUIRE FIRMWARE VERSION LETTER");
1673: if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
1674: *TargetPointer++ = FirmwareVersionLetter;
1675: *TargetPointer = '\0';
1676: }
1677: /*
1678: Save the Host Adapter SCSI ID in the Host Adapter structure.
1679: */
1680: HostAdapter->SCSI_ID = Configuration.HostAdapterID;
1681: /*
1682: Determine the Bus Type and save it in the Host Adapter structure, determine
1683: and save the IRQ Channel if necessary, and determine and save the DMA
1684: Channel for ISA Host Adapters.
1685: */
1686: HostAdapter->HostAdapterBusType =
1687: BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
1688: if (HostAdapter->IRQ_Channel == 0)
1689: {
1690: if (Configuration.IRQ_Channel9)
1691: HostAdapter->IRQ_Channel = 9;
1692: else if (Configuration.IRQ_Channel10)
1693: HostAdapter->IRQ_Channel = 10;
1694: else if (Configuration.IRQ_Channel11)
1695: HostAdapter->IRQ_Channel = 11;
1696: else if (Configuration.IRQ_Channel12)
1697: HostAdapter->IRQ_Channel = 12;
1698: else if (Configuration.IRQ_Channel14)
1699: HostAdapter->IRQ_Channel = 14;
1700: else if (Configuration.IRQ_Channel15)
1701: HostAdapter->IRQ_Channel = 15;
1702: }
1703: if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus)
1704: {
1705: if (Configuration.DMA_Channel5)
1706: HostAdapter->DMA_Channel = 5;
1707: else if (Configuration.DMA_Channel6)
1708: HostAdapter->DMA_Channel = 6;
1709: else if (Configuration.DMA_Channel7)
1710: HostAdapter->DMA_Channel = 7;
1711: }
1712: /*
1713: Determine whether Extended Translation is enabled and save it in
1714: the Host Adapter structure.
1715: */
1716: GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
1717: HostAdapter->ExtendedTranslationEnabled =
1718: GeometryRegister.Bits.ExtendedTranslationEnabled;
1719: /*
1720: Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
1721: SCSI flag, Differential SCSI flag, SCAM Supported flag, and
1722: Ultra SCSI flag in the Host Adapter structure.
1723: */
1724: HostAdapter->HostAdapterScatterGatherLimit =
1725: ExtendedSetupInformation.ScatterGatherLimit;
1726: HostAdapter->DriverScatterGatherLimit =
1727: HostAdapter->HostAdapterScatterGatherLimit;
1728: if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
1729: HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
1730: if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
1731: HostAdapter->LevelSensitiveInterrupt = true;
1732: HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
1733: HostAdapter->HostDifferentialSCSI =
1734: ExtendedSetupInformation.HostDifferentialSCSI;
1735: HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
1736: HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
1737: /*
1738: Determine whether Extended LUN Format CCBs are supported and save the
1739: information in the Host Adapter structure.
1740: */
1741: if (HostAdapter->FirmwareVersion[0] == '5' ||
1742: (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
1743: HostAdapter->ExtendedLUNSupport = true;
1744: /*
1745: Issue the Inquire PCI Host Adapter Information command to read the
1746: Termination Information from "W" series MultiMaster Host Adapters.
1747: */
1748: if (HostAdapter->FirmwareVersion[0] == '5')
1749: {
1750: if (BusLogic_Command(HostAdapter,
1751: BusLogic_InquirePCIHostAdapterInformation,
1752: NULL, 0, &PCIHostAdapterInformation,
1753: sizeof(PCIHostAdapterInformation))
1754: != sizeof(PCIHostAdapterInformation))
1755: return BusLogic_Failure(HostAdapter,
1756: "INQUIRE PCI HOST ADAPTER INFORMATION");
1757: /*
1758: Save the Termination Information in the Host Adapter structure.
1759: */
1760: if (PCIHostAdapterInformation.GenericInfoValid)
1761: {
1762: HostAdapter->TerminationInfoValid = true;
1763: HostAdapter->LowByteTerminated =
1764: PCIHostAdapterInformation.LowByteTerminated;
1765: HostAdapter->HighByteTerminated =
1766: PCIHostAdapterInformation.HighByteTerminated;
1767: }
1768: }
1769: /*
1770: Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
1771: from "W" and "C" series MultiMaster Host Adapters.
1772: */
1773: if (HostAdapter->FirmwareVersion[0] >= '4')
1774: {
1775: FetchHostAdapterLocalRAMRequest.ByteOffset =
1776: BusLogic_AutoSCSI_BaseOffset;
1777: FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
1778: if (BusLogic_Command(HostAdapter,
1779: BusLogic_FetchHostAdapterLocalRAM,
1780: &FetchHostAdapterLocalRAMRequest,
1781: sizeof(FetchHostAdapterLocalRAMRequest),
1782: &AutoSCSIData, sizeof(AutoSCSIData))
1783: != sizeof(AutoSCSIData))
1784: return BusLogic_Failure(HostAdapter, "FETCH HOST ADAPTER LOCAL RAM");
1785: /*
1786: Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
1787: Information in the Host Adapter structure.
1788: */
1789: HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
1790: HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
1791: if (HostAdapter->FirmwareVersion[0] == '4')
1792: {
1793: HostAdapter->TerminationInfoValid = true;
1794: HostAdapter->LowByteTerminated = AutoSCSIData.LowByteTerminated;
1795: HostAdapter->HighByteTerminated = AutoSCSIData.HighByteTerminated;
1796: }
1797: /*
1798: Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
1799: Disconnect Permitted, Ultra Permitted, and SCAM Information in the
1800: Host Adapter structure.
1801: */
1802: HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
1803: HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
1804: HostAdapter->SynchronousPermitted =
1805: AutoSCSIData.SynchronousPermitted;
1806: HostAdapter->DisconnectPermitted =
1807: AutoSCSIData.DisconnectPermitted;
1808: if (HostAdapter->HostUltraSCSI)
1809: HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
1810: if (HostAdapter->HostSupportsSCAM)
1811: {
1812: HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
1813: HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
1814: }
1815: }
1816: /*
1817: Initialize fields in the Host Adapter structure for "S" and "A" series
1818: MultiMaster Host Adapters.
1819: */
1820: if (HostAdapter->FirmwareVersion[0] < '4')
1821: {
1822: if (SetupInformation.SynchronousInitiationEnabled)
1823: {
1824: HostAdapter->SynchronousPermitted = 0xFF;
1825: if (HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)
1826: {
1827: if (ExtendedSetupInformation.Misc.FastOnEISA)
1828: HostAdapter->FastPermitted = 0xFF;
1829: if (strcmp(HostAdapter->ModelName, "BT-757") == 0)
1830: HostAdapter->WidePermitted = 0xFF;
1831: }
1832: }
1833: HostAdapter->DisconnectPermitted = 0xFF;
1834: HostAdapter->ParityCheckingEnabled =
1835: SetupInformation.ParityCheckingEnabled;
1836: HostAdapter->BusResetEnabled = true;
1837: }
1838: /*
1839: Determine the maximum number of Target IDs and Logical Units supported by
1840: this driver for Wide and Narrow Host Adapters.
1841: */
1842: HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
1843: HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
1844: /*
1845: Select appropriate values for the Mailbox Count, Driver Queue Depth,
1846: Initial CCBs, and Incremental CCBs variables based on whether or not Strict
1847: Round Robin Mode is supported. If Strict Round Robin Mode is supported,
1848: then there is no performance degradation in using the maximum possible
1849: number of Outgoing and Incoming Mailboxes and allowing the Tagged and
1850: Untagged Queue Depths to determine the actual utilization. If Strict Round
1851: Robin Mode is not supported, then the Host Adapter must scan all the
1852: Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
1853: cause a substantial performance penalty. The host adapters actually have
1854: room to store the following number of CCBs internally; that is, they can
1855: internally queue and manage this many active commands on the SCSI bus
1856: simultaneously. Performance measurements demonstrate that the Driver Queue
1857: Depth should be set to the Mailbox Count, rather than the Host Adapter
1858: Queue Depth (internal CCB capacity), as it is more efficient to have the
1859: queued commands waiting in Outgoing Mailboxes if necessary than to block
1860: the process in the higher levels of the SCSI Subsystem.
1861:
1862: 192 BT-948/958/958D
1863: 100 BT-946C/956C/956CD/747C/757C/757CD/445C
1864: 50 BT-545C/540CF
1865: 30 BT-747S/747D/757S/757D/445S/545S/542D/542B/742A
1866: */
1867: if (HostAdapter->FirmwareVersion[0] == '5')
1868: HostAdapter->HostAdapterQueueDepth = 192;
1869: else if (HostAdapter->FirmwareVersion[0] == '4')
1870: HostAdapter->HostAdapterQueueDepth =
1871: (HostAdapter->HostAdapterBusType != BusLogic_ISA_Bus ? 100 : 50);
1872: else HostAdapter->HostAdapterQueueDepth = 30;
1873: if (strcmp(HostAdapter->FirmwareVersion, "3.31") >= 0)
1874: {
1875: HostAdapter->StrictRoundRobinModeSupport = true;
1876: HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
1877: }
1878: else
1879: {
1880: HostAdapter->StrictRoundRobinModeSupport = false;
1881: HostAdapter->MailboxCount = 32;
1882: }
1883: HostAdapter->DriverQueueDepth = HostAdapter->MailboxCount;
1884: HostAdapter->InitialCCBs = 4 * BusLogic_CCB_AllocationGroupSize;
1885: HostAdapter->IncrementalCCBs = BusLogic_CCB_AllocationGroupSize;
1886: /*
1887: Tagged Queuing support is available and operates properly on all "W" series
1888: MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
1889: firmware version 4.22 and above, and on "S" series MultiMaster Host
1890: Adapters with firmware version 3.35 and above.
1891: */
1892: HostAdapter->TaggedQueuingPermitted = 0;
1893: switch (HostAdapter->FirmwareVersion[0])
1894: {
1895: case '5':
1896: HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1897: break;
1898: case '4':
1899: if (strcmp(HostAdapter->FirmwareVersion, "4.22") >= 0)
1900: HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1901: break;
1902: case '3':
1903: if (strcmp(HostAdapter->FirmwareVersion, "3.35") >= 0)
1904: HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1905: break;
1906: }
1907: /*
1908: Determine the Host Adapter BIOS Address if the BIOS is enabled and
1909: save it in the Host Adapter structure. The BIOS is disabled if the
1910: BIOS_Address is 0.
1911: */
1912: HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
1913: /*
1914: ISA Host Adapters require Bounce Buffers if there is more than 16MB memory.
1915: */
1916: if (HostAdapter->HostAdapterBusType == BusLogic_ISA_Bus &&
1917: (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1918: HostAdapter->BounceBuffersRequired = true;
1919: /*
1920: BusLogic BT-445S Host Adapters prior to board revision E have a hardware
1921: bug whereby when the BIOS is enabled, transfers to/from the same address
1922: range the BIOS occupies modulo 16MB are handled incorrectly. Only properly
1923: functioning BT-445S Host Adapters have firmware version 3.37, so require
1924: that ISA Bounce Buffers be used for the buggy BT-445S models if there is
1925: more than 16MB memory.
1926: */
1927: if (HostAdapter->BIOS_Address > 0 &&
1928: strcmp(HostAdapter->ModelName, "BT-445S") == 0 &&
1929: strcmp(HostAdapter->FirmwareVersion, "3.37") < 0 &&
1930: (void *) high_memory > (void *) MAX_DMA_ADDRESS)
1931: HostAdapter->BounceBuffersRequired = true;
1932: /*
1933: Initialize parameters common to MultiMaster and FlashPoint Host Adapters.
1934: */
1935: Common:
1936: /*
1937: Initialize the Host Adapter Full Model Name from the Model Name.
1938: */
1939: strcpy(HostAdapter->FullModelName, "BusLogic ");
1940: strcat(HostAdapter->FullModelName, HostAdapter->ModelName);
1941: /*
1942: Select an appropriate value for the Tagged Queue Depth either from a
1943: BusLogic Driver Options specification, or based on whether this Host
1944: Adapter requires that ISA Bounce Buffers be used. The Tagged Queue Depth
1945: is left at 0 for automatic determination in BusLogic_SelectQueueDepths.
1946: Initialize the Untagged Queue Depth.
1947: */
1948: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
1949: {
1950: unsigned char QueueDepth = 0;
1951: if (HostAdapter->DriverOptions != NULL &&
1952: HostAdapter->DriverOptions->QueueDepth[TargetID] > 0)
1953: QueueDepth = HostAdapter->DriverOptions->QueueDepth[TargetID];
1954: else if (HostAdapter->BounceBuffersRequired)
1955: QueueDepth = BusLogic_TaggedQueueDepthBB;
1956: HostAdapter->QueueDepth[TargetID] = QueueDepth;
1957: }
1958: if (HostAdapter->BounceBuffersRequired)
1959: HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepthBB;
1960: else HostAdapter->UntaggedQueueDepth = BusLogic_UntaggedQueueDepth;
1961: if (HostAdapter->DriverOptions != NULL)
1962: HostAdapter->CommonQueueDepth =
1963: HostAdapter->DriverOptions->CommonQueueDepth;
1964: if (HostAdapter->CommonQueueDepth > 0 &&
1965: HostAdapter->CommonQueueDepth < HostAdapter->UntaggedQueueDepth)
1966: HostAdapter->UntaggedQueueDepth = HostAdapter->CommonQueueDepth;
1967: /*
1968: Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
1969: Therefore, mask the Tagged Queuing Permitted Default bits with the
1970: Disconnect/Reconnect Permitted bits.
1971: */
1972: HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
1973: /*
1974: Combine the default Tagged Queuing Permitted bits with any BusLogic Driver
1975: Options Tagged Queuing specification.
1976: */
1977: if (HostAdapter->DriverOptions != NULL)
1978: HostAdapter->TaggedQueuingPermitted =
1979: (HostAdapter->DriverOptions->TaggedQueuingPermitted &
1980: HostAdapter->DriverOptions->TaggedQueuingPermittedMask) |
1981: (HostAdapter->TaggedQueuingPermitted &
1982: ~HostAdapter->DriverOptions->TaggedQueuingPermittedMask);
1983: /*
1984: Select appropriate values for the Error Recovery Strategy array
1985: either from a BusLogic Driver Options specification, or using
1986: BusLogic_ErrorRecovery_Default.
1987: */
1988: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
1989: if (HostAdapter->DriverOptions != NULL)
1990: HostAdapter->ErrorRecoveryStrategy[TargetID] =
1991: HostAdapter->DriverOptions->ErrorRecoveryStrategy[TargetID];
1992: else HostAdapter->ErrorRecoveryStrategy[TargetID] =
1993: BusLogic_ErrorRecovery_Default;
1994: /*
1995: Select an appropriate value for Bus Settle Time either from a BusLogic
1996: Driver Options specification, or from BusLogic_DefaultBusSettleTime.
1997: */
1998: if (HostAdapter->DriverOptions != NULL &&
1999: HostAdapter->DriverOptions->BusSettleTime > 0)
2000: HostAdapter->BusSettleTime = HostAdapter->DriverOptions->BusSettleTime;
2001: else HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
2002: /*
2003: Indicate reading the Host Adapter Configuration completed successfully.
2004: */
2005: return true;
2006: }
2007:
2008:
2009: /*
2010: BusLogic_ReportHostAdapterConfiguration reports the configuration of
2011: Host Adapter.
2012: */
2013:
2014: static boolean BusLogic_ReportHostAdapterConfiguration(BusLogic_HostAdapter_T
2015: *HostAdapter)
2016: {
2017: unsigned short AllTargetsMask = (1 << HostAdapter->MaxTargetDevices) - 1;
2018: unsigned short SynchronousPermitted, FastPermitted;
2019: unsigned short UltraPermitted, WidePermitted;
2020: unsigned short DisconnectPermitted, TaggedQueuingPermitted;
2021: boolean CommonSynchronousNegotiation, CommonTaggedQueueDepth;
2022: boolean CommonErrorRecovery;
2023: char SynchronousString[BusLogic_MaxTargetDevices+1];
2024: char WideString[BusLogic_MaxTargetDevices+1];
2025: char DisconnectString[BusLogic_MaxTargetDevices+1];
2026: char TaggedQueuingString[BusLogic_MaxTargetDevices+1];
2027: char ErrorRecoveryString[BusLogic_MaxTargetDevices+1];
2028: char *SynchronousMessage = SynchronousString;
2029: char *WideMessage = WideString;
2030: char *DisconnectMessage = DisconnectString;
2031: char *TaggedQueuingMessage = TaggedQueuingString;
2032: char *ErrorRecoveryMessage = ErrorRecoveryString;
2033: int TargetID;
2034: BusLogic_Info("Configuring BusLogic Model %s %s%s%s%s SCSI Host Adapter\n",
2035: HostAdapter, HostAdapter->ModelName,
2036: BusLogic_HostAdapterBusNames[HostAdapter->HostAdapterBusType],
2037: (HostAdapter->HostWideSCSI ? " Wide" : ""),
2038: (HostAdapter->HostDifferentialSCSI ? " Differential" : ""),
2039: (HostAdapter->HostUltraSCSI ? " Ultra" : ""));
2040: BusLogic_Info(" Firmware Version: %s, I/O Address: 0x%X, "
2041: "IRQ Channel: %d/%s\n", HostAdapter,
2042: HostAdapter->FirmwareVersion,
2043: HostAdapter->IO_Address, HostAdapter->IRQ_Channel,
2044: (HostAdapter->LevelSensitiveInterrupt ? "Level" : "Edge"));
2045: if (HostAdapter->HostAdapterBusType != BusLogic_PCI_Bus)
2046: {
2047: BusLogic_Info(" DMA Channel: ", HostAdapter);
2048: if (HostAdapter->DMA_Channel > 0)
2049: BusLogic_Info("%d, ", HostAdapter, HostAdapter->DMA_Channel);
2050: else BusLogic_Info("None, ", HostAdapter);
2051: if (HostAdapter->BIOS_Address > 0)
2052: BusLogic_Info("BIOS Address: 0x%X, ", HostAdapter,
2053: HostAdapter->BIOS_Address);
2054: else BusLogic_Info("BIOS Address: None, ", HostAdapter);
2055: }
2056: else
2057: {
2058: BusLogic_Info(" PCI Bus: %d, Device: %d, Address: ",
2059: HostAdapter, HostAdapter->Bus, HostAdapter->Device);
2060: if (HostAdapter->PCI_Address > 0)
2061: BusLogic_Info("0x%X, ", HostAdapter, HostAdapter->PCI_Address);
2062: else BusLogic_Info("Unassigned, ", HostAdapter);
2063: }
2064: BusLogic_Info("Host Adapter SCSI ID: %d\n", HostAdapter,
2065: HostAdapter->SCSI_ID);
2066: BusLogic_Info(" Parity Checking: %s, Extended Translation: %s\n",
2067: HostAdapter,
2068: (HostAdapter->ParityCheckingEnabled
2069: ? "Enabled" : "Disabled"),
2070: (HostAdapter->ExtendedTranslationEnabled
2071: ? "Enabled" : "Disabled"));
2072: AllTargetsMask &= ~(1 << HostAdapter->SCSI_ID);
2073: SynchronousPermitted = HostAdapter->SynchronousPermitted & AllTargetsMask;
2074: FastPermitted = HostAdapter->FastPermitted & AllTargetsMask;
2075: UltraPermitted = HostAdapter->UltraPermitted & AllTargetsMask;
2076: if ((BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
2077: (HostAdapter->FirmwareVersion[0] >= '4' ||
2078: HostAdapter->HostAdapterBusType == BusLogic_EISA_Bus)) ||
2079: BusLogic_FlashPointHostAdapterP(HostAdapter))
2080: {
2081: CommonSynchronousNegotiation = false;
2082: if (SynchronousPermitted == 0)
2083: {
2084: SynchronousMessage = "Disabled";
2085: CommonSynchronousNegotiation = true;
2086: }
2087: else if (SynchronousPermitted == AllTargetsMask)
2088: {
2089: if (FastPermitted == 0)
2090: {
2091: SynchronousMessage = "Slow";
2092: CommonSynchronousNegotiation = true;
2093: }
2094: else if (FastPermitted == AllTargetsMask)
2095: {
2096: if (UltraPermitted == 0)
2097: {
2098: SynchronousMessage = "Fast";
2099: CommonSynchronousNegotiation = true;
2100: }
2101: else if (UltraPermitted == AllTargetsMask)
2102: {
2103: SynchronousMessage = "Ultra";
2104: CommonSynchronousNegotiation = true;
2105: }
2106: }
2107: }
2108: if (!CommonSynchronousNegotiation)
2109: {
2110: for (TargetID = 0;
2111: TargetID < HostAdapter->MaxTargetDevices;
2112: TargetID++)
2113: SynchronousString[TargetID] =
2114: ((!(SynchronousPermitted & (1 << TargetID))) ? 'N' :
2115: (!(FastPermitted & (1 << TargetID)) ? 'S' :
2116: (!(UltraPermitted & (1 << TargetID)) ? 'F' : 'U')));
2117: SynchronousString[HostAdapter->SCSI_ID] = '#';
2118: SynchronousString[HostAdapter->MaxTargetDevices] = '\0';
2119: }
2120: }
2121: else SynchronousMessage =
2122: (SynchronousPermitted == 0 ? "Disabled" : "Enabled");
2123: WidePermitted = HostAdapter->WidePermitted & AllTargetsMask;
2124: if (WidePermitted == 0)
2125: WideMessage = "Disabled";
2126: else if (WidePermitted == AllTargetsMask)
2127: WideMessage = "Enabled";
2128: else
2129: {
2130: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2131: WideString[TargetID] =
2132: ((WidePermitted & (1 << TargetID)) ? 'Y' : 'N');
2133: WideString[HostAdapter->SCSI_ID] = '#';
2134: WideString[HostAdapter->MaxTargetDevices] = '\0';
2135: }
2136: DisconnectPermitted = HostAdapter->DisconnectPermitted & AllTargetsMask;
2137: if (DisconnectPermitted == 0)
2138: DisconnectMessage = "Disabled";
2139: else if (DisconnectPermitted == AllTargetsMask)
2140: DisconnectMessage = "Enabled";
2141: else
2142: {
2143: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2144: DisconnectString[TargetID] =
2145: ((DisconnectPermitted & (1 << TargetID)) ? 'Y' : 'N');
2146: DisconnectString[HostAdapter->SCSI_ID] = '#';
2147: DisconnectString[HostAdapter->MaxTargetDevices] = '\0';
2148: }
2149: TaggedQueuingPermitted =
2150: HostAdapter->TaggedQueuingPermitted & AllTargetsMask;
2151: if (TaggedQueuingPermitted == 0)
2152: TaggedQueuingMessage = "Disabled";
2153: else if (TaggedQueuingPermitted == AllTargetsMask)
2154: TaggedQueuingMessage = "Enabled";
2155: else
2156: {
2157: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2158: TaggedQueuingString[TargetID] =
2159: ((TaggedQueuingPermitted & (1 << TargetID)) ? 'Y' : 'N');
2160: TaggedQueuingString[HostAdapter->SCSI_ID] = '#';
2161: TaggedQueuingString[HostAdapter->MaxTargetDevices] = '\0';
2162: }
2163: BusLogic_Info(" Synchronous Negotiation: %s, Wide Negotiation: %s\n",
2164: HostAdapter, SynchronousMessage, WideMessage);
2165: BusLogic_Info(" Disconnect/Reconnect: %s, Tagged Queuing: %s\n",
2166: HostAdapter, DisconnectMessage, TaggedQueuingMessage);
2167: if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
2168: {
2169: BusLogic_Info(" Scatter/Gather Limit: %d of %d segments, "
2170: "Mailboxes: %d\n", HostAdapter,
2171: HostAdapter->DriverScatterGatherLimit,
2172: HostAdapter->HostAdapterScatterGatherLimit,
2173: HostAdapter->MailboxCount);
2174: BusLogic_Info(" Driver Queue Depth: %d, "
2175: "Host Adapter Queue Depth: %d\n",
2176: HostAdapter, HostAdapter->DriverQueueDepth,
2177: HostAdapter->HostAdapterQueueDepth);
2178: }
2179: else BusLogic_Info(" Driver Queue Depth: %d, "
2180: "Scatter/Gather Limit: %d segments\n",
2181: HostAdapter, HostAdapter->DriverQueueDepth,
2182: HostAdapter->DriverScatterGatherLimit);
2183: BusLogic_Info(" Tagged Queue Depth: ", HostAdapter);
2184: CommonTaggedQueueDepth = true;
2185: for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2186: if (HostAdapter->QueueDepth[TargetID] != HostAdapter->QueueDepth[0])
2187: {
2188: CommonTaggedQueueDepth = false;
2189: break;
2190: }
2191: if (CommonTaggedQueueDepth)
2192: {
2193: if (HostAdapter->QueueDepth[0] > 0)
2194: BusLogic_Info("%d", HostAdapter, HostAdapter->QueueDepth[0]);
2195: else BusLogic_Info("Automatic", HostAdapter);
2196: }
2197: else BusLogic_Info("Individual", HostAdapter);
2198: BusLogic_Info(", Untagged Queue Depth: %d\n", HostAdapter,
2199: HostAdapter->UntaggedQueueDepth);
2200: CommonErrorRecovery = true;
2201: for (TargetID = 1; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2202: if (HostAdapter->ErrorRecoveryStrategy[TargetID] !=
2203: HostAdapter->ErrorRecoveryStrategy[0])
2204: {
2205: CommonErrorRecovery = false;
2206: break;
2207: }
2208: if (CommonErrorRecovery)
2209: ErrorRecoveryMessage =
2210: BusLogic_ErrorRecoveryStrategyNames[
2211: HostAdapter->ErrorRecoveryStrategy[0]];
2212: else
2213: {
2214: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2215: ErrorRecoveryString[TargetID] =
2216: BusLogic_ErrorRecoveryStrategyLetters[
2217: HostAdapter->ErrorRecoveryStrategy[TargetID]];
2218: ErrorRecoveryString[HostAdapter->SCSI_ID] = '#';
2219: ErrorRecoveryString[HostAdapter->MaxTargetDevices] = '\0';
2220: }
2221: BusLogic_Info(" Error Recovery Strategy: %s, SCSI Bus Reset: %s\n",
2222: HostAdapter, ErrorRecoveryMessage,
2223: (HostAdapter->BusResetEnabled ? "Enabled" : "Disabled"));
2224: if (HostAdapter->TerminationInfoValid)
2225: {
2226: if (HostAdapter->HostWideSCSI)
2227: BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter,
2228: (HostAdapter->LowByteTerminated
2229: ? (HostAdapter->HighByteTerminated
2230: ? "Both Enabled" : "Low Enabled")
2231: : (HostAdapter->HighByteTerminated
2232: ? "High Enabled" : "Both Disabled")));
2233: else BusLogic_Info(" SCSI Bus Termination: %s", HostAdapter,
2234: (HostAdapter->LowByteTerminated ?
2235: "Enabled" : "Disabled"));
2236: if (HostAdapter->HostSupportsSCAM)
2237: BusLogic_Info(", SCAM: %s", HostAdapter,
2238: (HostAdapter->SCAM_Enabled
2239: ? (HostAdapter->SCAM_Level2
2240: ? "Enabled, Level 2" : "Enabled, Level 1")
2241: : "Disabled"));
2242: BusLogic_Info("\n", HostAdapter);
2243: }
2244: /*
2245: Indicate reporting the Host Adapter configuration completed successfully.
2246: */
2247: return true;
2248: }
2249:
2250:
2251: /*
2252: BusLogic_AcquireResources acquires the system resources necessary to use
2253: Host Adapter.
2254: */
2255:
2256: static boolean BusLogic_AcquireResources(BusLogic_HostAdapter_T *HostAdapter)
2257: {
2258: if (HostAdapter->IRQ_Channel == 0)
2259: {
2260: BusLogic_Error("NO LEGAL INTERRUPT CHANNEL ASSIGNED - DETACHING\n",
2261: HostAdapter);
2262: return false;
2263: }
2264: /*
2265: Acquire shared access to the IRQ Channel.
2266: */
2267: if (request_irq(HostAdapter->IRQ_Channel, BusLogic_InterruptHandler,
2268: SA_INTERRUPT | SA_SHIRQ,
2269: HostAdapter->FullModelName, HostAdapter) < 0)
2270: {
2271: BusLogic_Error("UNABLE TO ACQUIRE IRQ CHANNEL %d - DETACHING\n",
2272: HostAdapter, HostAdapter->IRQ_Channel);
2273: return false;
2274: }
2275: HostAdapter->IRQ_ChannelAcquired = true;
2276: /*
2277: Acquire exclusive access to the DMA Channel.
2278: */
2279: if (HostAdapter->DMA_Channel > 0)
2280: {
2281: if (request_dma(HostAdapter->DMA_Channel,
2282: HostAdapter->FullModelName) < 0)
2283: {
2284: BusLogic_Error("UNABLE TO ACQUIRE DMA CHANNEL %d - DETACHING\n",
2285: HostAdapter, HostAdapter->DMA_Channel);
2286: return false;
2287: }
2288: set_dma_mode(HostAdapter->DMA_Channel, DMA_MODE_CASCADE);
2289: enable_dma(HostAdapter->DMA_Channel);
2290: HostAdapter->DMA_ChannelAcquired = true;
2291: }
2292: /*
2293: Indicate the System Resource Acquisition completed successfully,
2294: */
2295: return true;
2296: }
2297:
2298:
2299: /*
2300: BusLogic_ReleaseResources releases any system resources previously acquired
2301: by BusLogic_AcquireResources.
2302: */
2303:
2304: static void BusLogic_ReleaseResources(BusLogic_HostAdapter_T *HostAdapter)
2305: {
2306: /*
2307: Release shared access to the IRQ Channel.
2308: */
2309: if (HostAdapter->IRQ_ChannelAcquired)
2310: free_irq(HostAdapter->IRQ_Channel, HostAdapter);
2311: /*
2312: Release exclusive access to the DMA Channel.
2313: */
2314: if (HostAdapter->DMA_ChannelAcquired)
2315: free_dma(HostAdapter->DMA_Channel);
2316: }
2317:
2318:
2319: /*
2320: BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only
2321: function called during SCSI Host Adapter detection which modifies the state
2322: of the Host Adapter from its initial power on or hard reset state.
2323: */
2324:
2325: static boolean BusLogic_InitializeHostAdapter(BusLogic_HostAdapter_T
2326: *HostAdapter)
2327: {
2328: BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest;
2329: BusLogic_RoundRobinModeRequest_T RoundRobinModeRequest;
2330: BusLogic_SetCCBFormatRequest_T SetCCBFormatRequest;
2331: int TargetID;
2332: /*
2333: Initialize the pointers to the first and last CCBs that are queued for
2334: completion processing.
2335: */
2336: HostAdapter->FirstCompletedCCB = NULL;
2337: HostAdapter->LastCompletedCCB = NULL;
2338: /*
2339: Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
2340: Command Successful Flag, Active Commands, and Commands Since Reset
2341: for each Target Device.
2342: */
2343: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2344: {
2345: HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
2346: HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
2347: HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
2348: HostAdapter->ActiveCommands[TargetID] = 0;
2349: HostAdapter->CommandsSinceReset[TargetID] = 0;
2350: }
2351: /*
2352: FlashPoint Host Adapters do not use Outgoing and Incoming Mailboxes.
2353: */
2354: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) goto Done;
2355: /*
2356: Initialize the Outgoing and Incoming Mailbox pointers.
2357: */
2358: HostAdapter->FirstOutgoingMailbox =
2359: (BusLogic_OutgoingMailbox_T *) HostAdapter->MailboxSpace;
2360: HostAdapter->LastOutgoingMailbox =
2361: HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
2362: HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
2363: HostAdapter->FirstIncomingMailbox =
2364: (BusLogic_IncomingMailbox_T *) (HostAdapter->LastOutgoingMailbox + 1);
2365: HostAdapter->LastIncomingMailbox =
2366: HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
2367: HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
2368: /*
2369: Initialize the Outgoing and Incoming Mailbox structures.
2370: */
2371: memset(HostAdapter->FirstOutgoingMailbox, 0,
2372: HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T));
2373: memset(HostAdapter->FirstIncomingMailbox, 0,
2374: HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T));
2375: /*
2376: Initialize the Host Adapter's Pointer to the Outgoing/Incoming Mailboxes.
2377: */
2378: ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
2379: ExtendedMailboxRequest.BaseMailboxAddress =
2380: Virtual_to_Bus(HostAdapter->FirstOutgoingMailbox);
2381: if (BusLogic_Command(HostAdapter, BusLogic_InitializeExtendedMailbox,
2382: &ExtendedMailboxRequest,
2383: sizeof(ExtendedMailboxRequest), NULL, 0) < 0)
2384: return BusLogic_Failure(HostAdapter, "MAILBOX INITIALIZATION");
2385: /*
2386: Enable Strict Round Robin Mode if supported by the Host Adapter. In
2387: Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
2388: Mailbox for each new command, rather than scanning through all the
2389: Outgoing Mailboxes to find any that have new commands in them. Strict
2390: Round Robin Mode is significantly more efficient.
2391: */
2392: if (HostAdapter->StrictRoundRobinModeSupport)
2393: {
2394: RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
2395: if (BusLogic_Command(HostAdapter, BusLogic_EnableStrictRoundRobinMode,
2396: &RoundRobinModeRequest,
2397: sizeof(RoundRobinModeRequest), NULL, 0) < 0)
2398: return BusLogic_Failure(HostAdapter, "ENABLE STRICT ROUND ROBIN MODE");
2399: }
2400: /*
2401: For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
2402: Format command to allow 32 Logical Units per Target Device.
2403: */
2404: if (HostAdapter->ExtendedLUNSupport)
2405: {
2406: SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
2407: if (BusLogic_Command(HostAdapter, BusLogic_SetCCBFormat,
2408: &SetCCBFormatRequest, sizeof(SetCCBFormatRequest),
2409: NULL, 0) < 0)
2410: return BusLogic_Failure(HostAdapter, "SET CCB FORMAT");
2411: }
2412: /*
2413: Announce Successful Initialization.
2414: */
2415: Done:
2416: if (!HostAdapter->HostAdapterInitialized)
2417: {
2418: BusLogic_Info("*** %s Initialized Successfully ***\n",
2419: HostAdapter, HostAdapter->FullModelName);
2420: BusLogic_Info("\n", HostAdapter);
2421: }
2422: else BusLogic_Warning("*** %s Initialized Successfully ***\n",
2423: HostAdapter, HostAdapter->FullModelName);
2424: HostAdapter->HostAdapterInitialized = true;
2425: /*
2426: Indicate the Host Adapter Initialization completed successfully.
2427: */
2428: return true;
2429: }
2430:
2431:
2432: /*
2433: BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible
2434: through Host Adapter.
2435: */
2436:
2437: static boolean BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T
2438: *HostAdapter)
2439: {
2440: BusLogic_InstalledDevices_T InstalledDevices;
2441: BusLogic_InstalledDevices8_T InstalledDevicesID0to7;
2442: BusLogic_SetupInformation_T SetupInformation;
2443: BusLogic_SynchronousPeriod_T SynchronousPeriod;
2444: BusLogic_RequestedReplyLength_T RequestedReplyLength;
2445: int TargetID;
2446: /*
2447: Wait a few seconds between the Host Adapter Hard Reset which initiates
2448: a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get
2449: confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
2450: */
2451: BusLogic_Delay(HostAdapter->BusSettleTime);
2452: /*
2453: FlashPoint Host Adapters do not provide for Target Device Inquiry.
2454: */
2455: if (BusLogic_FlashPointHostAdapterP(HostAdapter)) return true;
2456: /*
2457: Inhibit the Target Device Inquiry if requested.
2458: */
2459: if (HostAdapter->DriverOptions != NULL &&
2460: HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
2461: return true;
2462: /*
2463: Issue the Inquire Target Devices command for host adapters with firmware
2464: version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
2465: for older host adapters. This is necessary to force Synchronous Transfer
2466: Negotiation so that the Inquire Setup Information and Inquire Synchronous
2467: Period commands will return valid data. The Inquire Target Devices command
2468: is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
2469: Logical Unit 0 of each Target Device.
2470: */
2471: if (strcmp(HostAdapter->FirmwareVersion, "4.25") >= 0)
2472: {
2473: if (BusLogic_Command(HostAdapter, BusLogic_InquireTargetDevices, NULL, 0,
2474: &InstalledDevices, sizeof(InstalledDevices))
2475: != sizeof(InstalledDevices))
2476: return BusLogic_Failure(HostAdapter, "INQUIRE TARGET DEVICES");
2477: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2478: HostAdapter->TargetFlags[TargetID].TargetExists =
2479: (InstalledDevices & (1 << TargetID) ? true : false);
2480: }
2481: else
2482: {
2483: if (BusLogic_Command(HostAdapter, BusLogic_InquireInstalledDevicesID0to7,
2484: NULL, 0, &InstalledDevicesID0to7,
2485: sizeof(InstalledDevicesID0to7))
2486: != sizeof(InstalledDevicesID0to7))
2487: return BusLogic_Failure(HostAdapter,
2488: "INQUIRE INSTALLED DEVICES ID 0 TO 7");
2489: for (TargetID = 0; TargetID < 8; TargetID++)
2490: HostAdapter->TargetFlags[TargetID].TargetExists =
2491: (InstalledDevicesID0to7[TargetID] != 0 ? true : false);
2492: }
2493: /*
2494: Issue the Inquire Setup Information command.
2495: */
2496: RequestedReplyLength = sizeof(SetupInformation);
2497: if (BusLogic_Command(HostAdapter, BusLogic_InquireSetupInformation,
2498: &RequestedReplyLength, sizeof(RequestedReplyLength),
2499: &SetupInformation, sizeof(SetupInformation))
2500: != sizeof(SetupInformation))
2501: return BusLogic_Failure(HostAdapter, "INQUIRE SETUP INFORMATION");
2502: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2503: HostAdapter->SynchronousOffset[TargetID] =
2504: (TargetID < 8
2505: ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset
2506: : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset);
2507: if (strcmp(HostAdapter->FirmwareVersion, "5.06L") >= 0)
2508: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2509: HostAdapter->TargetFlags[TargetID].WideTransfersActive =
2510: (TargetID < 8
2511: ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
2512: ? true : false)
2513: : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8))
2514: ? true : false));
2515: /*
2516: Issue the Inquire Synchronous Period command.
2517: */
2518: if (HostAdapter->FirmwareVersion[0] >= '3')
2519: {
2520: RequestedReplyLength = sizeof(SynchronousPeriod);
2521: if (BusLogic_Command(HostAdapter, BusLogic_InquireSynchronousPeriod,
2522: &RequestedReplyLength, sizeof(RequestedReplyLength),
2523: &SynchronousPeriod, sizeof(SynchronousPeriod))
2524: != sizeof(SynchronousPeriod))
2525: return BusLogic_Failure(HostAdapter, "INQUIRE SYNCHRONOUS PERIOD");
2526: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2527: HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
2528: }
2529: else
2530: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2531: if (SetupInformation.SynchronousValuesID0to7[TargetID].Offset > 0)
2532: HostAdapter->SynchronousPeriod[TargetID] =
2533: 20 + 5 * SetupInformation.SynchronousValuesID0to7[TargetID]
2534: .TransferPeriod;
2535: /*
2536: Indicate the Target Device Inquiry completed successfully.
2537: */
2538: return true;
2539: }
2540:
2541:
2542: /*
2543: BusLogic_ReportTargetDeviceInfo reports about the Target Devices accessible
2544: through Host Adapter.
2545: */
2546:
2547: static void BusLogic_ReportTargetDeviceInfo(BusLogic_HostAdapter_T
2548: *HostAdapter)
2549: {
2550: int TargetID;
2551: /*
2552: Inhibit the Target Device Inquiry and Reporting if requested.
2553: */
2554: if (BusLogic_MultiMasterHostAdapterP(HostAdapter) &&
2555: HostAdapter->DriverOptions != NULL &&
2556: HostAdapter->DriverOptions->LocalOptions.InhibitTargetInquiry)
2557: return;
2558: /*
2559: Report on the Target Devices found.
2560: */
2561: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2562: {
2563: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
2564: if (TargetFlags->TargetExists && !TargetFlags->TargetInfoReported)
2565: {
2566: int SynchronousTransferRate = 0;
2567: if (BusLogic_FlashPointHostAdapterP(HostAdapter))
2568: {
2569: boolean WideTransfersActive;
2570: FlashPoint_InquireTargetInfo(
2571: HostAdapter->CardHandle, TargetID,
2572: &HostAdapter->SynchronousPeriod[TargetID],
2573: &HostAdapter->SynchronousOffset[TargetID],
2574: &WideTransfersActive);
2575: TargetFlags->WideTransfersActive = WideTransfersActive;
2576: }
2577: else if (TargetFlags->WideTransfersSupported &&
2578: (HostAdapter->WidePermitted & (1 << TargetID)) &&
2579: strcmp(HostAdapter->FirmwareVersion, "5.06L") < 0)
2580: TargetFlags->WideTransfersActive = true;
2581: if (HostAdapter->SynchronousPeriod[TargetID] > 0)
2582: SynchronousTransferRate =
2583: 100000 / HostAdapter->SynchronousPeriod[TargetID];
2584: if (TargetFlags->WideTransfersActive)
2585: SynchronousTransferRate <<= 1;
2586: if (SynchronousTransferRate >= 9950)
2587: {
2588: SynchronousTransferRate = (SynchronousTransferRate + 50) / 100;
2589: BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
2590: "%d.%01d MB/sec, offset %d\n",
2591: HostAdapter, TargetID,
2592: HostAdapter->QueueDepth[TargetID],
2593: (TargetFlags->WideTransfersActive ? "Wide " : ""),
2594: SynchronousTransferRate / 10,
2595: SynchronousTransferRate % 10,
2596: HostAdapter->SynchronousOffset[TargetID]);
2597: }
2598: else if (SynchronousTransferRate > 0)
2599: {
2600: SynchronousTransferRate = (SynchronousTransferRate + 5) / 10;
2601: BusLogic_Info("Target %d: Queue Depth %d, %sSynchronous at "
2602: "%d.%02d MB/sec, offset %d\n",
2603: HostAdapter, TargetID,
2604: HostAdapter->QueueDepth[TargetID],
2605: (TargetFlags->WideTransfersActive ? "Wide " : ""),
2606: SynchronousTransferRate / 100,
2607: SynchronousTransferRate % 100,
2608: HostAdapter->SynchronousOffset[TargetID]);
2609: }
2610: else BusLogic_Info("Target %d: Queue Depth %d, Asynchronous\n",
2611: HostAdapter, TargetID,
2612: HostAdapter->QueueDepth[TargetID]);
2613: TargetFlags->TargetInfoReported = true;
2614: }
2615: }
2616: }
2617:
2618:
2619: /*
2620: BusLogic_InitializeHostStructure initializes the fields in the SCSI Host
2621: structure. The base, io_port, n_io_ports, irq, and dma_channel fields in the
2622: SCSI Host structure are intentionally left uninitialized, as this driver
2623: handles acquisition and release of these resources explicitly, as well as
2624: ensuring exclusive access to the Host Adapter hardware and data structures
2625: through explicit acquisition and release of the Host Adapter's Lock.
2626: */
2627:
2628: static void BusLogic_InitializeHostStructure(BusLogic_HostAdapter_T
2629: *HostAdapter,
2630: SCSI_Host_T *Host)
2631: {
2632: Host->max_id = HostAdapter->MaxTargetDevices;
2633: Host->max_lun = HostAdapter->MaxLogicalUnits;
2634: Host->max_channel = 0;
2635: Host->unique_id = HostAdapter->IO_Address;
2636: Host->this_id = HostAdapter->SCSI_ID;
2637: Host->can_queue = HostAdapter->DriverQueueDepth;
2638: Host->sg_tablesize = HostAdapter->DriverScatterGatherLimit;
2639: Host->unchecked_isa_dma = HostAdapter->BounceBuffersRequired;
2640: Host->cmd_per_lun = HostAdapter->UntaggedQueueDepth;
2641: }
2642:
2643:
2644: /*
2645: BusLogic_SelectQueueDepths selects Queue Depths for each Target Device based
2646: on the Host Adapter's Total Queue Depth and the number, type, speed, and
2647: capabilities of the Target Devices. When called for the last Host Adapter,
2648: it reports on the Target Device Information for all BusLogic Host Adapters
2649: since all the Target Devices have now been probed.
2650: */
2651:
2652: static void BusLogic_SelectQueueDepths(SCSI_Host_T *Host,
2653: SCSI_Device_T *DeviceList)
2654: {
2655: BusLogic_HostAdapter_T *HostAdapter =
2656: (BusLogic_HostAdapter_T *) Host->hostdata;
2657: int TaggedDeviceCount = 0, AutomaticTaggedDeviceCount = 0;
2658: int UntaggedDeviceCount = 0, AutomaticTaggedQueueDepth = 0;
2659: int AllocatedQueueDepth = 0;
2660: SCSI_Device_T *Device;
2661: int TargetID;
2662: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2663: if (HostAdapter->TargetFlags[TargetID].TargetExists)
2664: {
2665: int QueueDepth = HostAdapter->QueueDepth[TargetID];
2666: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingSupported &&
2667: (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
2668: {
2669: TaggedDeviceCount++;
2670: if (QueueDepth == 0) AutomaticTaggedDeviceCount++;
2671: }
2672: else
2673: {
2674: UntaggedDeviceCount++;
2675: if (QueueDepth == 0 ||
2676: QueueDepth > HostAdapter->UntaggedQueueDepth)
2677: {
2678: QueueDepth = HostAdapter->UntaggedQueueDepth;
2679: HostAdapter->QueueDepth[TargetID] = QueueDepth;
2680: }
2681: }
2682: AllocatedQueueDepth += QueueDepth;
2683: if (QueueDepth == 1)
2684: HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
2685: }
2686: HostAdapter->TargetDeviceCount = TaggedDeviceCount + UntaggedDeviceCount;
2687: if (AutomaticTaggedDeviceCount > 0)
2688: {
2689: AutomaticTaggedQueueDepth =
2690: (HostAdapter->HostAdapterQueueDepth - AllocatedQueueDepth)
2691: / AutomaticTaggedDeviceCount;
2692: if (AutomaticTaggedQueueDepth > BusLogic_MaxAutomaticTaggedQueueDepth)
2693: AutomaticTaggedQueueDepth = BusLogic_MaxAutomaticTaggedQueueDepth;
2694: if (AutomaticTaggedQueueDepth < BusLogic_MinAutomaticTaggedQueueDepth)
2695: AutomaticTaggedQueueDepth = BusLogic_MinAutomaticTaggedQueueDepth;
2696: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
2697: if (HostAdapter->TargetFlags[TargetID].TargetExists &&
2698: HostAdapter->QueueDepth[TargetID] == 0)
2699: {
2700: AllocatedQueueDepth += AutomaticTaggedQueueDepth;
2701: HostAdapter->QueueDepth[TargetID] = AutomaticTaggedQueueDepth;
2702: }
2703: }
2704: for (Device = DeviceList; Device != NULL; Device = Device->next)
2705: if (Device->host == Host)
2706: Device->queue_depth = HostAdapter->QueueDepth[Device->id];
2707: /* Allocate an extra CCB for each Target Device for a Bus Device Reset. */
2708: AllocatedQueueDepth += HostAdapter->TargetDeviceCount;
2709: if (AllocatedQueueDepth > HostAdapter->DriverQueueDepth)
2710: AllocatedQueueDepth = HostAdapter->DriverQueueDepth;
2711: BusLogic_CreateAdditionalCCBs(HostAdapter,
2712: AllocatedQueueDepth
2713: - HostAdapter->AllocatedCCBs,
2714: false);
2715: if (HostAdapter == BusLogic_LastRegisteredHostAdapter)
2716: for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
2717: HostAdapter != NULL;
2718: HostAdapter = HostAdapter->Next)
2719: BusLogic_ReportTargetDeviceInfo(HostAdapter);
2720: }
2721:
2722:
2723: /*
2724: BusLogic_DetectHostAdapter probes for BusLogic Host Adapters at the standard
2725: I/O Addresses where they may be located, initializing, registering, and
2726: reporting the configuration of each BusLogic Host Adapter it finds. It
2727: returns the number of BusLogic Host Adapters successfully initialized and
2728: registered.
2729: */
2730:
2731: int BusLogic_DetectHostAdapter(SCSI_Host_Template_T *HostTemplate)
2732: {
2733: int BusLogicHostAdapterCount = 0, DriverOptionsIndex = 0, ProbeIndex;
2734: BusLogic_HostAdapter_T *PrototypeHostAdapter;
2735: if (BusLogic_ProbeOptions.NoProbe) return 0;
2736: BusLogic_ProbeInfoList = (BusLogic_ProbeInfo_T *)
2737: kmalloc(BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T),
2738: GFP_ATOMIC);
2739: if (BusLogic_ProbeInfoList == NULL)
2740: {
2741: BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
2742: return 0;
2743: }
2744: memset(BusLogic_ProbeInfoList, 0,
2745: BusLogic_MaxHostAdapters * sizeof(BusLogic_ProbeInfo_T));
2746: PrototypeHostAdapter = (BusLogic_HostAdapter_T *)
2747: kmalloc(sizeof(BusLogic_HostAdapter_T), GFP_ATOMIC);
2748: if (PrototypeHostAdapter == NULL)
2749: {
2750: kfree(BusLogic_ProbeInfoList);
2751: BusLogic_Error("BusLogic: Unable to allocate Prototype "
2752: "Host Adapter\n", NULL);
2753: return 0;
2754: }
2755: memset(PrototypeHostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
2756: if (BusLogic_Options != NULL)
2757: BusLogic_ParseDriverOptions(BusLogic_Options);
2758: BusLogic_InitializeProbeInfoList(PrototypeHostAdapter);
2759: for (ProbeIndex = 0; ProbeIndex < BusLogic_ProbeInfoCount; ProbeIndex++)
2760: {
2761: BusLogic_ProbeInfo_T *ProbeInfo = &BusLogic_ProbeInfoList[ProbeIndex];
2762: BusLogic_HostAdapter_T *HostAdapter = PrototypeHostAdapter;
2763: SCSI_Host_T *Host;
2764: if (ProbeInfo->IO_Address == 0) continue;
2765: memset(HostAdapter, 0, sizeof(BusLogic_HostAdapter_T));
2766: HostAdapter->HostAdapterType = ProbeInfo->HostAdapterType;
2767: HostAdapter->HostAdapterBusType = ProbeInfo->HostAdapterBusType;
2768: HostAdapter->IO_Address = ProbeInfo->IO_Address;
2769: HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
2770: HostAdapter->Bus = ProbeInfo->Bus;
2771: HostAdapter->Device = ProbeInfo->Device;
2772: HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
2773: HostAdapter->AddressCount =
2774: BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
2775: /*
2776: Probe the Host Adapter. If unsuccessful, abort further initialization.
2777: */
2778: if (!BusLogic_ProbeHostAdapter(HostAdapter)) continue;
2779: /*
2780: Hard Reset the Host Adapter. If unsuccessful, abort further
2781: initialization.
2782: */
2783: if (!BusLogic_HardwareResetHostAdapter(HostAdapter, true)) continue;
2784: /*
2785: Check the Host Adapter. If unsuccessful, abort further initialization.
2786: */
2787: if (!BusLogic_CheckHostAdapter(HostAdapter)) continue;
2788: /*
2789: Initialize the Driver Options field if provided.
2790: */
2791: if (DriverOptionsIndex < BusLogic_DriverOptionsCount)
2792: HostAdapter->DriverOptions =
2793: &BusLogic_DriverOptions[DriverOptionsIndex++];
2794: /*
2795: Announce the Driver Version and Date, Author's Name, Copyright Notice,
2796: and Electronic Mail Address.
2797: */
2798: BusLogic_AnnounceDriver(HostAdapter);
2799: /*
2800: Register usage of the I/O Address range. From this point onward, any
2801: failure will be assumed to be due to a problem with the Host Adapter,
2802: rather than due to having mistakenly identified this port as belonging
2803: to a BusLogic Host Adapter. The I/O Address range will not be
2804: released, thereby preventing it from being incorrectly identified as
2805: any other type of Host Adapter.
2806: */
2807: request_region(HostAdapter->IO_Address, HostAdapter->AddressCount,
2808: "BusLogic");
2809: /*
2810: Register the SCSI Host structure.
2811: */
2812: Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T));
2813: HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata;
2814: memcpy(HostAdapter, PrototypeHostAdapter, sizeof(BusLogic_HostAdapter_T));
2815: HostAdapter->SCSI_Host = Host;
2816: HostAdapter->HostNumber = Host->host_no;
2817: Host->select_queue_depths = BusLogic_SelectQueueDepths;
2818: /*
2819: Add Host Adapter to the end of the list of registered BusLogic
2820: Host Adapters.
2821: */
2822: BusLogic_RegisterHostAdapter(HostAdapter);
2823: /*
2824: Read the Host Adapter Configuration, Configure the Host Adapter,
2825: Acquire the System Resources necessary to use the Host Adapter, then
2826: Create the Initial CCBs, Initialize the Host Adapter, and finally
2827: perform Target Device Inquiry.
2828: */
2829: if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) &&
2830: BusLogic_ReportHostAdapterConfiguration(HostAdapter) &&
2831: BusLogic_AcquireResources(HostAdapter) &&
2832: BusLogic_CreateInitialCCBs(HostAdapter) &&
2833: BusLogic_InitializeHostAdapter(HostAdapter) &&
2834: BusLogic_TargetDeviceInquiry(HostAdapter))
2835: {
2836: /*
2837: Initialization has been completed successfully. Release and
2838: re-register usage of the I/O Address range so that the Model
2839: Name of the Host Adapter will appear, and initialize the SCSI
2840: Host structure.
2841: */
2842: release_region(HostAdapter->IO_Address,
2843: HostAdapter->AddressCount);
2844: request_region(HostAdapter->IO_Address,
2845: HostAdapter->AddressCount,
2846: HostAdapter->FullModelName);
2847: BusLogic_InitializeHostStructure(HostAdapter, Host);
2848: BusLogicHostAdapterCount++;
2849: }
2850: else
2851: {
2852: /*
2853: An error occurred during Host Adapter Configuration Querying, Host
2854: Adapter Configuration, Resource Acquisition, CCB Creation, Host
2855: Adapter Initialization, or Target Device Inquiry, so remove Host
2856: Adapter from the list of registered BusLogic Host Adapters, destroy
2857: the CCBs, Release the System Resources, and Unregister the SCSI
2858: Host.
2859: */
2860: BusLogic_DestroyCCBs(HostAdapter);
2861: BusLogic_ReleaseResources(HostAdapter);
2862: BusLogic_UnregisterHostAdapter(HostAdapter);
2863: scsi_unregister(Host);
2864: }
2865: }
2866: kfree(PrototypeHostAdapter);
2867: kfree(BusLogic_ProbeInfoList);
2868: BusLogic_ProbeInfoList = NULL;
2869: return BusLogicHostAdapterCount;
2870: }
2871:
2872:
2873: /*
2874: BusLogic_ReleaseHostAdapter releases all resources previously acquired to
2875: support a specific Host Adapter, including the I/O Address range, and
2876: unregisters the BusLogic Host Adapter.
2877: */
2878:
2879: int BusLogic_ReleaseHostAdapter(SCSI_Host_T *Host)
2880: {
2881: BusLogic_HostAdapter_T *HostAdapter =
2882: (BusLogic_HostAdapter_T *) Host->hostdata;
2883: /*
2884: FlashPoint Host Adapters must first be released by the FlashPoint
2885: SCCB Manager.
2886: */
2887: if (BusLogic_FlashPointHostAdapterP(HostAdapter))
2888: FlashPoint_ReleaseHostAdapter(HostAdapter->CardHandle);
2889: /*
2890: Destroy the CCBs and release any system resources acquired to
2891: support Host Adapter.
2892: */
2893: BusLogic_DestroyCCBs(HostAdapter);
2894: BusLogic_ReleaseResources(HostAdapter);
2895: /*
2896: Release usage of the I/O Address range.
2897: */
2898: release_region(HostAdapter->IO_Address, HostAdapter->AddressCount);
2899: /*
2900: Remove Host Adapter from the list of registered BusLogic Host Adapters.
2901: */
2902: BusLogic_UnregisterHostAdapter(HostAdapter);
2903: return 0;
2904: }
2905:
2906:
2907: /*
2908: BusLogic_QueueCompletedCCB queues CCB for completion processing.
2909: */
2910:
2911: static void BusLogic_QueueCompletedCCB(BusLogic_CCB_T *CCB)
2912: {
2913: BusLogic_HostAdapter_T *HostAdapter = CCB->HostAdapter;
2914: CCB->Status = BusLogic_CCB_Completed;
2915: CCB->Next = NULL;
2916: if (HostAdapter->FirstCompletedCCB == NULL)
2917: {
2918: HostAdapter->FirstCompletedCCB = CCB;
2919: HostAdapter->LastCompletedCCB = CCB;
2920: }
2921: else
2922: {
2923: HostAdapter->LastCompletedCCB->Next = CCB;
2924: HostAdapter->LastCompletedCCB = CCB;
2925: }
2926: HostAdapter->ActiveCommands[CCB->TargetID]--;
2927: }
2928:
2929:
2930: /*
2931: BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
2932: the Host Adapter Status and Target Device Status.
2933: */
2934:
2935: static int BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter,
2936: BusLogic_HostAdapterStatus_T
2937: HostAdapterStatus,
2938: BusLogic_TargetDeviceStatus_T
2939: TargetDeviceStatus)
2940: {
2941: int HostStatus;
2942: switch (HostAdapterStatus)
2943: {
2944: case BusLogic_CommandCompletedNormally:
2945: case BusLogic_LinkedCommandCompleted:
2946: case BusLogic_LinkedCommandCompletedWithFlag:
2947: HostStatus = DID_OK;
2948: break;
2949: case BusLogic_SCSISelectionTimeout:
2950: HostStatus = DID_TIME_OUT;
2951: break;
2952: case BusLogic_InvalidOutgoingMailboxActionCode:
2953: case BusLogic_InvalidCommandOperationCode:
2954: case BusLogic_InvalidCommandParameter:
2955: BusLogic_Warning("BusLogic Driver Protocol Error 0x%02X\n",
2956: HostAdapter, HostAdapterStatus);
2957: case BusLogic_DataUnderRun:
2958: case BusLogic_DataOverRun:
2959: case BusLogic_UnexpectedBusFree:
2960: case BusLogic_LinkedCCBhasInvalidLUN:
2961: case BusLogic_AutoRequestSenseFailed:
2962: case BusLogic_TaggedQueuingMessageRejected:
2963: case BusLogic_UnsupportedMessageReceived:
2964: case BusLogic_HostAdapterHardwareFailed:
2965: case BusLogic_TargetDeviceReconnectedImproperly:
2966: case BusLogic_AbortQueueGenerated:
2967: case BusLogic_HostAdapterSoftwareError:
2968: case BusLogic_HostAdapterHardwareTimeoutError:
2969: case BusLogic_SCSIParityErrorDetected:
2970: HostStatus = DID_ERROR;
2971: break;
2972: case BusLogic_InvalidBusPhaseRequested:
2973: case BusLogic_TargetFailedResponseToATN:
2974: case BusLogic_HostAdapterAssertedRST:
2975: case BusLogic_OtherDeviceAssertedRST:
2976: case BusLogic_HostAdapterAssertedBusDeviceReset:
2977: HostStatus = DID_RESET;
2978: break;
2979: default:
2980: BusLogic_Warning("Unknown Host Adapter Status 0x%02X\n",
2981: HostAdapter, HostAdapterStatus);
2982: HostStatus = DID_ERROR;
2983: break;
2984: }
2985: return (HostStatus << 16) | TargetDeviceStatus;
2986: }
2987:
2988:
2989: /*
2990: BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
2991: Incoming Mailbox entries for completion processing.
2992: */
2993:
2994: static void BusLogic_ScanIncomingMailboxes(BusLogic_HostAdapter_T *HostAdapter)
2995: {
2996: /*
2997: Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
2998: any completed CCBs for further processing. It is essential that for each
2999: CCB and SCSI Command issued, command completion processing is performed
3000: exactly once. Therefore, only Incoming Mailboxes with completion code
3001: Command Completed Without Error, Command Completed With Error, or Command
3002: Aborted At Host Request are saved for completion processing. When an
3003: Incoming Mailbox has a completion code of Aborted Command Not Found, the
3004: CCB had already completed or been aborted before the current Abort request
3005: was processed, and so completion processing has already occurred and no
3006: further action should be taken.
3007: */
3008: BusLogic_IncomingMailbox_T *NextIncomingMailbox =
3009: HostAdapter->NextIncomingMailbox;
3010: BusLogic_CompletionCode_T CompletionCode;
3011: while ((CompletionCode = NextIncomingMailbox->CompletionCode) !=
3012: BusLogic_IncomingMailboxFree)
3013: {
3014: BusLogic_CCB_T *CCB = (BusLogic_CCB_T *)
3015: Bus_to_Virtual(NextIncomingMailbox->CCB);
3016: if (CompletionCode != BusLogic_AbortedCommandNotFound)
3017: {
3018: if (CCB->Status == BusLogic_CCB_Active ||
3019: CCB->Status == BusLogic_CCB_Reset)
3020: {
3021: /*
3022: Save the Completion Code for this CCB and queue the CCB
3023: for completion processing.
3024: */
3025: CCB->CompletionCode = CompletionCode;
3026: BusLogic_QueueCompletedCCB(CCB);
3027: }
3028: else
3029: {
3030: /*
3031: If a CCB ever appears in an Incoming Mailbox and is not marked
3032: as status Active or Reset, then there is most likely a bug in
3033: the Host Adapter firmware.
3034: */
3035: BusLogic_Warning("Illegal CCB #%ld status %d in "
3036: "Incoming Mailbox\n", HostAdapter,
3037: CCB->SerialNumber, CCB->Status);
3038: }
3039: }
3040: NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
3041: if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
3042: NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
3043: }
3044: HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
3045: }
3046:
3047:
3048: /*
3049: BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
3050: Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
3051: calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock
3052: should already have been acquired by the caller.
3053: */
3054:
3055: static void BusLogic_ProcessCompletedCCBs(BusLogic_HostAdapter_T *HostAdapter)
3056: {
3057: if (HostAdapter->ProcessCompletedCCBsActive) return;
3058: HostAdapter->ProcessCompletedCCBsActive = true;
3059: while (HostAdapter->FirstCompletedCCB != NULL)
3060: {
3061: BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB;
3062: SCSI_Command_T *Command = CCB->Command;
3063: HostAdapter->FirstCompletedCCB = CCB->Next;
3064: if (HostAdapter->FirstCompletedCCB == NULL)
3065: HostAdapter->LastCompletedCCB = NULL;
3066: /*
3067: Process the Completed CCB.
3068: */
3069: if (CCB->Opcode == BusLogic_BusDeviceReset)
3070: {
3071: int TargetID = CCB->TargetID;
3072: BusLogic_Warning("Bus Device Reset CCB #%ld to Target "
3073: "%d Completed\n", HostAdapter,
3074: CCB->SerialNumber, TargetID);
3075: BusLogic_IncrementErrorCounter(
3076: &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
3077: HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
3078: HostAdapter->CommandsSinceReset[TargetID] = 0;
3079: HostAdapter->LastResetCompleted[TargetID] = jiffies;
3080: /*
3081: Place CCB back on the Host Adapter's free list.
3082: */
3083: BusLogic_DeallocateCCB(CCB);
3084: /*
3085: Bus Device Reset CCBs have the Command field non-NULL only when a
3086: Bus Device Reset was requested for a Command that did not have a
3087: currently active CCB in the Host Adapter (i.e., a Synchronous
3088: Bus Device Reset), and hence would not have its Completion Routine
3089: called otherwise.
3090: */
3091: while (Command != NULL)
3092: {
3093: SCSI_Command_T *NextCommand = Command->reset_chain;
3094: Command->reset_chain = NULL;
3095: Command->result = DID_RESET << 16;
3096: Command->scsi_done(Command);
3097: Command = NextCommand;
3098: }
3099: /*
3100: Iterate over the CCBs for this Host Adapter performing completion
3101: processing for any CCBs marked as Reset for this Target.
3102: */
3103: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3104: if (CCB->Status == BusLogic_CCB_Reset && CCB->TargetID == TargetID)
3105: {
3106: Command = CCB->Command;
3107: BusLogic_DeallocateCCB(CCB);
3108: HostAdapter->ActiveCommands[TargetID]--;
3109: Command->result = DID_RESET << 16;
3110: Command->scsi_done(Command);
3111: }
3112: HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
3113: }
3114: else
3115: {
3116: /*
3117: Translate the Completion Code, Host Adapter Status, and Target
3118: Device Status into a SCSI Subsystem Result Code.
3119: */
3120: switch (CCB->CompletionCode)
3121: {
3122: case BusLogic_IncomingMailboxFree:
3123: case BusLogic_AbortedCommandNotFound:
3124: case BusLogic_InvalidCCB:
3125: BusLogic_Warning("CCB #%ld to Target %d Impossible State\n",
3126: HostAdapter, CCB->SerialNumber, CCB->TargetID);
3127: break;
3128: case BusLogic_CommandCompletedWithoutError:
3129: HostAdapter->TargetStatistics[CCB->TargetID]
3130: .CommandsCompleted++;
3131: HostAdapter->TargetFlags[CCB->TargetID]
3132: .CommandSuccessfulFlag = true;
3133: Command->result = DID_OK << 16;
3134: break;
3135: case BusLogic_CommandAbortedAtHostRequest:
3136: BusLogic_Warning("CCB #%ld to Target %d Aborted\n",
3137: HostAdapter, CCB->SerialNumber, CCB->TargetID);
3138: BusLogic_IncrementErrorCounter(
3139: &HostAdapter->TargetStatistics[CCB->TargetID]
3140: .CommandAbortsCompleted);
3141: Command->result = DID_ABORT << 16;
3142: break;
3143: case BusLogic_CommandCompletedWithError:
3144: Command->result =
3145: BusLogic_ComputeResultCode(HostAdapter,
3146: CCB->HostAdapterStatus,
3147: CCB->TargetDeviceStatus);
3148: if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
3149: {
3150: HostAdapter->TargetStatistics[CCB->TargetID]
3151: .CommandsCompleted++;
3152: if (BusLogic_GlobalOptions.TraceErrors)
3153: {
3154: int i;
3155: BusLogic_Notice("CCB #%ld Target %d: Result %X Host "
3156: "Adapter Status %02X "
3157: "Target Status %02X\n",
3158: HostAdapter, CCB->SerialNumber,
3159: CCB->TargetID, Command->result,
3160: CCB->HostAdapterStatus,
3161: CCB->TargetDeviceStatus);
3162: BusLogic_Notice("CDB ", HostAdapter);
3163: for (i = 0; i < CCB->CDB_Length; i++)
3164: BusLogic_Notice(" %02X", HostAdapter, CCB->CDB[i]);
3165: BusLogic_Notice("\n", HostAdapter);
3166: BusLogic_Notice("Sense ", HostAdapter);
3167: for (i = 0; i < CCB->SenseDataLength; i++)
3168: BusLogic_Notice(" %02X", HostAdapter,
3169: Command->sense_buffer[i]);
3170: BusLogic_Notice("\n", HostAdapter);
3171: }
3172: }
3173: break;
3174: }
3175: /*
3176: When an INQUIRY command completes normally, save the
3177: CmdQue (Tagged Queuing Supported) and WBus16 (16 Bit
3178: Wide Data Transfers Supported) bits.
3179: */
3180: if (CCB->CDB[0] == INQUIRY && CCB->CDB[1] == 0 &&
3181: CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally)
3182: {
3183: BusLogic_TargetFlags_T *TargetFlags =
3184: &HostAdapter->TargetFlags[CCB->TargetID];
3185: SCSI_Inquiry_T *InquiryResult =
3186: (SCSI_Inquiry_T *) Command->request_buffer;
3187: TargetFlags->TargetExists = true;
3188: TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
3189: TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
3190: }
3191: /*
3192: Place CCB back on the Host Adapter's free list.
3193: */
3194: BusLogic_DeallocateCCB(CCB);
3195: /*
3196: Call the SCSI Command Completion Routine.
3197: */
3198: Command->scsi_done(Command);
3199: }
3200: }
3201: HostAdapter->ProcessCompletedCCBsActive = false;
3202: }
3203:
3204:
3205: /*
3206: BusLogic_InterruptHandler handles hardware interrupts from BusLogic Host
3207: Adapters.
3208: */
3209:
3210: static void BusLogic_InterruptHandler(int IRQ_Channel,
3211: void *DeviceIdentifier,
3212: Registers_T *InterruptRegisters)
3213: {
3214: BusLogic_HostAdapter_T *HostAdapter =
3215: (BusLogic_HostAdapter_T *) DeviceIdentifier;
3216: ProcessorFlags_T ProcessorFlags;
3217: /*
3218: Acquire exclusive access to Host Adapter.
3219: */
3220: BusLogic_AcquireHostAdapterLockIH(HostAdapter, &ProcessorFlags);
3221: /*
3222: Handle Interrupts appropriately for each Host Adapter type.
3223: */
3224: if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3225: {
3226: BusLogic_InterruptRegister_T InterruptRegister;
3227: /*
3228: Read the Host Adapter Interrupt Register.
3229: */
3230: InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
3231: if (InterruptRegister.Bits.InterruptValid)
3232: {
3233: /*
3234: Acknowledge the interrupt and reset the Host Adapter
3235: Interrupt Register.
3236: */
3237: BusLogic_InterruptReset(HostAdapter);
3238: /*
3239: Process valid External SCSI Bus Reset and Incoming Mailbox
3240: Loaded Interrupts. Command Complete Interrupts are noted,
3241: and Outgoing Mailbox Available Interrupts are ignored, as
3242: they are never enabled.
3243: */
3244: if (InterruptRegister.Bits.ExternalBusReset)
3245: HostAdapter->HostAdapterExternalReset = true;
3246: else if (InterruptRegister.Bits.IncomingMailboxLoaded)
3247: BusLogic_ScanIncomingMailboxes(HostAdapter);
3248: else if (InterruptRegister.Bits.CommandComplete)
3249: HostAdapter->HostAdapterCommandCompleted = true;
3250: }
3251: }
3252: else
3253: {
3254: /*
3255: Check if there is a pending interrupt for this Host Adapter.
3256: */
3257: if (FlashPoint_InterruptPending(HostAdapter->CardHandle))
3258: switch (FlashPoint_HandleInterrupt(HostAdapter->CardHandle))
3259: {
3260: case FlashPoint_NormalInterrupt:
3261: break;
3262: case FlashPoint_ExternalBusReset:
3263: HostAdapter->HostAdapterExternalReset = true;
3264: break;
3265: case FlashPoint_InternalError:
3266: BusLogic_Warning("Internal FlashPoint Error detected"
3267: " - Resetting Host Adapter\n", HostAdapter);
3268: HostAdapter->HostAdapterInternalError = true;
3269: break;
3270: }
3271: }
3272: /*
3273: Process any completed CCBs.
3274: */
3275: if (HostAdapter->FirstCompletedCCB != NULL)
3276: BusLogic_ProcessCompletedCCBs(HostAdapter);
3277: /*
3278: Reset the Host Adapter if requested.
3279: */
3280: if (HostAdapter->HostAdapterExternalReset ||
3281: HostAdapter->HostAdapterInternalError)
3282: {
3283: BusLogic_ResetHostAdapter(HostAdapter, NULL, 0);
3284: HostAdapter->HostAdapterExternalReset = false;
3285: HostAdapter->HostAdapterInternalError = false;
3286: scsi_mark_host_reset(HostAdapter->SCSI_Host);
3287: }
3288: /*
3289: Release exclusive access to Host Adapter.
3290: */
3291: BusLogic_ReleaseHostAdapterLockIH(HostAdapter, &ProcessorFlags);
3292: }
3293:
3294:
3295: /*
3296: BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
3297: Mailbox for execution by Host Adapter. The Host Adapter's Lock should
3298: already have been acquired by the caller.
3299: */
3300:
3301: static boolean BusLogic_WriteOutgoingMailbox(BusLogic_HostAdapter_T
3302: *HostAdapter,
3303: BusLogic_ActionCode_T ActionCode,
3304: BusLogic_CCB_T *CCB)
3305: {
3306: BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
3307: NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
3308: if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
3309: {
3310: CCB->Status = BusLogic_CCB_Active;
3311: /*
3312: The CCB field must be written before the Action Code field since
3313: the Host Adapter is operating asynchronously and the locking code
3314: does not protect against simultaneous access by the Host Adapter.
3315: */
3316: NextOutgoingMailbox->CCB = Virtual_to_Bus(CCB);
3317: NextOutgoingMailbox->ActionCode = ActionCode;
3318: BusLogic_StartMailboxCommand(HostAdapter);
3319: if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
3320: NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
3321: HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
3322: if (ActionCode == BusLogic_MailboxStartCommand)
3323: {
3324: HostAdapter->ActiveCommands[CCB->TargetID]++;
3325: if (CCB->Opcode != BusLogic_BusDeviceReset)
3326: HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
3327: }
3328: return true;
3329: }
3330: return false;
3331: }
3332:
3333:
3334: /*
3335: BusLogic_QueueCommand creates a CCB for Command and places it into an
3336: Outgoing Mailbox for execution by the associated Host Adapter.
3337: */
3338:
3339: int BusLogic_QueueCommand(SCSI_Command_T *Command,
3340: void (*CompletionRoutine)(SCSI_Command_T *))
3341: {
3342: BusLogic_HostAdapter_T *HostAdapter =
3343: (BusLogic_HostAdapter_T *) Command->host->hostdata;
3344: BusLogic_TargetFlags_T *TargetFlags =
3345: &HostAdapter->TargetFlags[Command->target];
3346: BusLogic_TargetStatistics_T *TargetStatistics =
3347: HostAdapter->TargetStatistics;
3348: unsigned char *CDB = Command->cmnd;
3349: int CDB_Length = Command->cmd_len;
3350: int TargetID = Command->target;
3351: int LogicalUnit = Command->lun;
3352: void *BufferPointer = Command->request_buffer;
3353: int BufferLength = Command->request_bufflen;
3354: int SegmentCount = Command->use_sg;
3355: ProcessorFlags_T ProcessorFlags;
3356: BusLogic_CCB_T *CCB;
3357: /*
3358: SCSI REQUEST_SENSE commands will be executed automatically by the Host
3359: Adapter for any errors, so they should not be executed explicitly unless
3360: the Sense Data is zero indicating that no error occurred.
3361: */
3362: if (CDB[0] == REQUEST_SENSE && Command->sense_buffer[0] != 0)
3363: {
3364: Command->result = DID_OK << 16;
3365: CompletionRoutine(Command);
3366: return 0;
3367: }
3368: /*
3369: Acquire exclusive access to Host Adapter.
3370: */
3371: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3372: /*
3373: Allocate a CCB from the Host Adapter's free list. In the unlikely event
3374: that there are none available and memory allocation fails, wait 1 second
3375: and try again. If that fails, the Host Adapter is probably hung so signal
3376: an error as a Host Adapter Hard Reset should be initiated soon.
3377: */
3378: CCB = BusLogic_AllocateCCB(HostAdapter);
3379: if (CCB == NULL)
3380: {
3381: BusLogic_Delay(1);
3382: CCB = BusLogic_AllocateCCB(HostAdapter);
3383: if (CCB == NULL)
3384: {
3385: Command->result = DID_ERROR << 16;
3386: CompletionRoutine(Command);
3387: goto Done;
3388: }
3389: }
3390: /*
3391: Initialize the fields in the BusLogic Command Control Block (CCB).
3392: */
3393: if (SegmentCount == 0)
3394: {
3395: CCB->Opcode = BusLogic_InitiatorCCB;
3396: CCB->DataLength = BufferLength;
3397: CCB->DataPointer = Virtual_to_Bus(BufferPointer);
3398: }
3399: else
3400: {
3401: SCSI_ScatterList_T *ScatterList = (SCSI_ScatterList_T *) BufferPointer;
3402: int Segment;
3403: CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
3404: CCB->DataLength = SegmentCount * sizeof(BusLogic_ScatterGatherSegment_T);
3405: if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3406: CCB->DataPointer = Virtual_to_Bus(CCB->ScatterGatherList);
3407: else CCB->DataPointer = Virtual_to_32Bit_Virtual(CCB->ScatterGatherList);
3408: for (Segment = 0; Segment < SegmentCount; Segment++)
3409: {
3410: CCB->ScatterGatherList[Segment].SegmentByteCount =
3411: ScatterList[Segment].length;
3412: CCB->ScatterGatherList[Segment].SegmentDataPointer =
3413: Virtual_to_Bus(ScatterList[Segment].address);
3414: }
3415: }
3416: switch (CDB[0])
3417: {
3418: case READ_6:
3419: case READ_10:
3420: CCB->DataDirection = BusLogic_DataInLengthChecked;
3421: TargetStatistics[TargetID].ReadCommands++;
3422: BusLogic_IncrementByteCounter(
3423: &TargetStatistics[TargetID].TotalBytesRead, BufferLength);
3424: BusLogic_IncrementSizeBucket(
3425: TargetStatistics[TargetID].ReadCommandSizeBuckets, BufferLength);
3426: break;
3427: case WRITE_6:
3428: case WRITE_10:
3429: CCB->DataDirection = BusLogic_DataOutLengthChecked;
3430: TargetStatistics[TargetID].WriteCommands++;
3431: BusLogic_IncrementByteCounter(
3432: &TargetStatistics[TargetID].TotalBytesWritten, BufferLength);
3433: BusLogic_IncrementSizeBucket(
3434: TargetStatistics[TargetID].WriteCommandSizeBuckets, BufferLength);
3435: break;
3436: default:
3437: CCB->DataDirection = BusLogic_UncheckedDataTransfer;
3438: break;
3439: }
3440: CCB->CDB_Length = CDB_Length;
3441: CCB->SenseDataLength = sizeof(Command->sense_buffer);
3442: CCB->HostAdapterStatus = 0;
3443: CCB->TargetDeviceStatus = 0;
3444: CCB->TargetID = TargetID;
3445: CCB->LogicalUnit = LogicalUnit;
3446: CCB->TagEnable = false;
3447: CCB->LegacyTagEnable = false;
3448: /*
3449: BusLogic recommends that after a Reset the first couple of commands that
3450: are sent to a Target Device be sent in a non Tagged Queue fashion so that
3451: the Host Adapter and Target Device can establish Synchronous and Wide
3452: Transfer before Queue Tag messages can interfere with the Synchronous and
3453: Wide Negotiation messages. By waiting to enable Tagged Queuing until after
3454: the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
3455: assured that after a Reset any pending commands are requeued before Tagged
3456: Queuing is enabled and that the Tagged Queuing message will not occur while
3457: the partition table is being printed. In addition, some devices do not
3458: properly handle the transition from non-tagged to tagged commands, so it is
3459: necessary to wait until there are no pending commands for a target device
3460: before queuing tagged commands.
3461: */
3462: if (HostAdapter->CommandsSinceReset[TargetID]++ >=
3463: BusLogic_MaxTaggedQueueDepth &&
3464: !TargetFlags->TaggedQueuingActive &&
3465: HostAdapter->ActiveCommands[TargetID] == 0 &&
3466: TargetFlags->TaggedQueuingSupported &&
3467: (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
3468: {
3469: TargetFlags->TaggedQueuingActive = true;
3470: BusLogic_Notice("Tagged Queuing now active for Target %d\n",
3471: HostAdapter, TargetID);
3472: }
3473: if (TargetFlags->TaggedQueuingActive)
3474: {
3475: BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag;
3476: /*
3477: When using Tagged Queuing with Simple Queue Tags, it appears that disk
3478: drive controllers do not guarantee that a queued command will not
3479: remain in a disconnected state indefinitely if commands that read or
3480: write nearer the head position continue to arrive without interruption.
3481: Therefore, for each Target Device this driver keeps track of the last
3482: time either the queue was empty or an Ordered Queue Tag was issued. If
3483: more than 4 seconds (one fifth of the 20 second disk timeout) have
3484: elapsed since this last sequence point, this command will be issued
3485: with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
3486: the Target Device to complete all previously queued commands before
3487: this command may be executed.
3488: */
3489: if (HostAdapter->ActiveCommands[TargetID] == 0)
3490: HostAdapter->LastSequencePoint[TargetID] = jiffies;
3491: else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
3492: {
3493: HostAdapter->LastSequencePoint[TargetID] = jiffies;
3494: QueueTag = BusLogic_OrderedQueueTag;
3495: }
3496: if (HostAdapter->ExtendedLUNSupport)
3497: {
3498: CCB->TagEnable = true;
3499: CCB->QueueTag = QueueTag;
3500: }
3501: else
3502: {
3503: CCB->LegacyTagEnable = true;
3504: CCB->LegacyQueueTag = QueueTag;
3505: }
3506: }
3507: memcpy(CCB->CDB, CDB, CDB_Length);
3508: CCB->SenseDataPointer = Virtual_to_Bus(&Command->sense_buffer);
3509: CCB->Command = Command;
3510: Command->scsi_done = CompletionRoutine;
3511: if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3512: {
3513: /*
3514: Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI
3515: Subsystem should not attempt to queue more commands than can be placed
3516: in Outgoing Mailboxes, so there should always be one free. In the
3517: unlikely event that there are none available, wait 1 second and try
3518: again. If that fails, the Host Adapter is probably hung so signal an
3519: error as a Host Adapter Hard Reset should be initiated soon.
3520: */
3521: if (!BusLogic_WriteOutgoingMailbox(
3522: HostAdapter, BusLogic_MailboxStartCommand, CCB))
3523: {
3524: BusLogic_Warning("Unable to write Outgoing Mailbox - "
3525: "Pausing for 1 second\n", HostAdapter);
3526: BusLogic_Delay(1);
3527: if (!BusLogic_WriteOutgoingMailbox(
3528: HostAdapter, BusLogic_MailboxStartCommand, CCB))
3529: {
3530: BusLogic_Warning("Still unable to write Outgoing Mailbox - "
3531: "Host Adapter Dead?\n", HostAdapter);
3532: BusLogic_DeallocateCCB(CCB);
3533: Command->result = DID_ERROR << 16;
3534: Command->scsi_done(Command);
3535: }
3536: }
3537: }
3538: else
3539: {
3540: /*
3541: Call the FlashPoint SCCB Manager to start execution of the CCB.
3542: */
3543: CCB->Status = BusLogic_CCB_Active;
3544: HostAdapter->ActiveCommands[TargetID]++;
3545: TargetStatistics[TargetID].CommandsAttempted++;
3546: FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
3547: /*
3548: The Command may have already completed and BusLogic_QueueCompletedCCB
3549: been called, or it may still be pending.
3550: */
3551: if (CCB->Status == BusLogic_CCB_Completed)
3552: BusLogic_ProcessCompletedCCBs(HostAdapter);
3553: }
3554: /*
3555: Release exclusive access to Host Adapter.
3556: */
3557: Done:
3558: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
3559: return 0;
3560: }
3561:
3562:
3563: /*
3564: BusLogic_AbortCommand aborts Command if possible.
3565: */
3566:
3567: int BusLogic_AbortCommand(SCSI_Command_T *Command)
3568: {
3569: BusLogic_HostAdapter_T *HostAdapter =
3570: (BusLogic_HostAdapter_T *) Command->host->hostdata;
3571: int TargetID = Command->target;
3572: ProcessorFlags_T ProcessorFlags;
3573: BusLogic_CCB_T *CCB;
3574: int Result;
3575: BusLogic_IncrementErrorCounter(
3576: &HostAdapter->TargetStatistics[TargetID].CommandAbortsRequested);
3577: /*
3578: Acquire exclusive access to Host Adapter.
3579: */
3580: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3581: /*
3582: If this Command has already completed, then no Abort is necessary.
3583: */
3584: if (Command->serial_number != Command->serial_number_at_timeout)
3585: {
3586: BusLogic_Warning("Unable to Abort Command to Target %d - "
3587: "Already Completed\n", HostAdapter, TargetID);
3588: Result = SCSI_ABORT_NOT_RUNNING;
3589: goto Done;
3590: }
3591: /*
3592: Attempt to find an Active CCB for this Command. If no Active CCB for this
3593: Command is found, then no Abort is necessary.
3594: */
3595: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3596: if (CCB->Command == Command) break;
3597: if (CCB == NULL)
3598: {
3599: BusLogic_Warning("Unable to Abort Command to Target %d - "
3600: "No CCB Found\n", HostAdapter, TargetID);
3601: Result = SCSI_ABORT_NOT_RUNNING;
3602: goto Done;
3603: }
3604: else if (CCB->Status == BusLogic_CCB_Completed)
3605: {
3606: BusLogic_Warning("Unable to Abort Command to Target %d - "
3607: "CCB Completed\n", HostAdapter, TargetID);
3608: Result = SCSI_ABORT_NOT_RUNNING;
3609: goto Done;
3610: }
3611: else if (CCB->Status == BusLogic_CCB_Reset)
3612: {
3613: BusLogic_Warning("Unable to Abort Command to Target %d - "
3614: "CCB Reset\n", HostAdapter, TargetID);
3615: Result = SCSI_ABORT_PENDING;
3616: goto Done;
3617: }
3618: if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3619: {
3620: /*
3621: Attempt to Abort this CCB. MultiMaster Firmware versions prior to 5.xx
3622: do not generate Abort Tag messages, but only generate the non-tagged
3623: Abort message. Since non-tagged commands are not sent by the Host
3624: Adapter until the queue of outstanding tagged commands has completed,
3625: and the Abort message is treated as a non-tagged command, it is
3626: effectively impossible to abort commands when Tagged Queuing is active.
3627: Firmware version 5.xx does generate Abort Tag messages, so it is
3628: possible to abort commands when Tagged Queuing is active.
3629: */
3630: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
3631: HostAdapter->FirmwareVersion[0] < '5')
3632: {
3633: BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
3634: "Abort Tag Not Supported\n",
3635: HostAdapter, CCB->SerialNumber, TargetID);
3636: Result = SCSI_ABORT_SNOOZE;
3637: }
3638: else if (BusLogic_WriteOutgoingMailbox(
3639: HostAdapter, BusLogic_MailboxAbortCommand, CCB))
3640: {
3641: BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
3642: HostAdapter, CCB->SerialNumber, TargetID);
3643: BusLogic_IncrementErrorCounter(
3644: &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
3645: Result = SCSI_ABORT_PENDING;
3646: }
3647: else
3648: {
3649: BusLogic_Warning("Unable to Abort CCB #%ld to Target %d - "
3650: "No Outgoing Mailboxes\n",
3651: HostAdapter, CCB->SerialNumber, TargetID);
3652: Result = SCSI_ABORT_BUSY;
3653: }
3654: }
3655: else
3656: {
3657: /*
3658: Call the FlashPoint SCCB Manager to abort execution of the CCB.
3659: */
3660: BusLogic_Warning("Aborting CCB #%ld to Target %d\n",
3661: HostAdapter, CCB->SerialNumber, TargetID);
3662: BusLogic_IncrementErrorCounter(
3663: &HostAdapter->TargetStatistics[TargetID].CommandAbortsAttempted);
3664: FlashPoint_AbortCCB(HostAdapter->CardHandle, CCB);
3665: /*
3666: The Abort may have already been completed and
3667: BusLogic_QueueCompletedCCB been called, or it
3668: may still be pending.
3669: */
3670: Result = SCSI_ABORT_PENDING;
3671: if (CCB->Status == BusLogic_CCB_Completed)
3672: {
3673: BusLogic_ProcessCompletedCCBs(HostAdapter);
3674: Result = SCSI_ABORT_SUCCESS;
3675: }
3676: }
3677: /*
3678: Release exclusive access to Host Adapter.
3679: */
3680: Done:
3681: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
3682: return Result;
3683: }
3684:
3685:
3686: /*
3687: BusLogic_ResetHostAdapter resets Host Adapter if possible, marking all
3688: currently executing SCSI Commands as having been Reset.
3689: */
3690:
3691: static int BusLogic_ResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter,
3692: SCSI_Command_T *Command,
3693: unsigned int ResetFlags)
3694: {
3695: ProcessorFlags_T ProcessorFlags;
3696: BusLogic_CCB_T *CCB;
3697: int TargetID, Result;
3698: boolean HardReset;
3699: if (HostAdapter->HostAdapterExternalReset)
3700: {
3701: BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
3702: HardReset = false;
3703: }
3704: else if (HostAdapter->HostAdapterInternalError)
3705: {
3706: BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
3707: HardReset = true;
3708: }
3709: else
3710: {
3711: BusLogic_IncrementErrorCounter(
3712: &HostAdapter->TargetStatistics[Command->target]
3713: .HostAdapterResetsRequested);
3714: HardReset = true;
3715: }
3716: /*
3717: Acquire exclusive access to Host Adapter.
3718: */
3719: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3720: /*
3721: If this is an Asynchronous Reset and this Command has already completed,
3722: then no Reset is necessary.
3723: */
3724: if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
3725: {
3726: TargetID = Command->target;
3727: if (Command->serial_number != Command->serial_number_at_timeout)
3728: {
3729: BusLogic_Warning("Unable to Reset Command to Target %d - "
3730: "Already Completed or Reset\n",
3731: HostAdapter, TargetID);
3732: Result = SCSI_RESET_NOT_RUNNING;
3733: goto Done;
3734: }
3735: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3736: if (CCB->Command == Command) break;
3737: if (CCB == NULL)
3738: {
3739: BusLogic_Warning("Unable to Reset Command to Target %d - "
3740: "No CCB Found\n", HostAdapter, TargetID);
3741: Result = SCSI_RESET_NOT_RUNNING;
3742: goto Done;
3743: }
3744: else if (CCB->Status == BusLogic_CCB_Completed)
3745: {
3746: BusLogic_Warning("Unable to Reset Command to Target %d - "
3747: "CCB Completed\n", HostAdapter, TargetID);
3748: Result = SCSI_RESET_NOT_RUNNING;
3749: goto Done;
3750: }
3751: else if (CCB->Status == BusLogic_CCB_Reset &&
3752: HostAdapter->BusDeviceResetPendingCCB[TargetID] == NULL)
3753: {
3754: BusLogic_Warning("Unable to Reset Command to Target %d - "
3755: "Reset Pending\n", HostAdapter, TargetID);
3756: Result = SCSI_RESET_PENDING;
3757: goto Done;
3758: }
3759: }
3760: if (Command == NULL)
3761: {
3762: if (HostAdapter->HostAdapterInternalError)
3763: BusLogic_Warning("Resetting %s due to Host Adapter Internal Error\n",
3764: HostAdapter, HostAdapter->FullModelName);
3765: else BusLogic_Warning("Resetting %s due to External SCSI Bus Reset\n",
3766: HostAdapter, HostAdapter->FullModelName);
3767: }
3768: else
3769: {
3770: BusLogic_Warning("Resetting %s due to Target %d\n", HostAdapter,
3771: HostAdapter->FullModelName, Command->target);
3772: BusLogic_IncrementErrorCounter(
3773: &HostAdapter->TargetStatistics[Command->target]
3774: .HostAdapterResetsAttempted);
3775: }
3776: /*
3777: Attempt to Reset and Reinitialize the Host Adapter.
3778: */
3779: if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) &&
3780: BusLogic_InitializeHostAdapter(HostAdapter)))
3781: {
3782: BusLogic_Error("Resetting %s Failed\n", HostAdapter,
3783: HostAdapter->FullModelName);
3784: Result = SCSI_RESET_ERROR;
3785: goto Done;
3786: }
3787: if (Command != NULL)
3788: BusLogic_IncrementErrorCounter(
3789: &HostAdapter->TargetStatistics[Command->target]
3790: .HostAdapterResetsCompleted);
3791: /*
3792: Mark all currently executing CCBs as having been Reset.
3793: */
3794: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3795: if (CCB->Status == BusLogic_CCB_Active)
3796: CCB->Status = BusLogic_CCB_Reset;
3797: /*
3798: Wait a few seconds between the Host Adapter Hard Reset which initiates
3799: a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get
3800: confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
3801: Note that a timer interrupt may occur here, but all active CCBs have
3802: already been marked Reset and so a reentrant call will return Pending.
3803: */
3804: if (HardReset)
3805: BusLogic_Delay(HostAdapter->BusSettleTime);
3806: /*
3807: If this is a Synchronous Reset, perform completion processing for
3808: the Command being Reset.
3809: */
3810: if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
3811: {
3812: Command->result = DID_RESET << 16;
3813: Command->scsi_done(Command);
3814: }
3815: /*
3816: Perform completion processing for all CCBs marked as Reset.
3817: */
3818: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3819: if (CCB->Status == BusLogic_CCB_Reset)
3820: {
3821: Command = CCB->Command;
3822: BusLogic_DeallocateCCB(CCB);
3823: while (Command != NULL)
3824: {
3825: SCSI_Command_T *NextCommand = Command->reset_chain;
3826: Command->reset_chain = NULL;
3827: Command->result = DID_RESET << 16;
3828: Command->scsi_done(Command);
3829: Command = NextCommand;
3830: }
3831: }
3832: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
3833: {
3834: HostAdapter->LastResetAttempted[TargetID] = jiffies;
3835: HostAdapter->LastResetCompleted[TargetID] = jiffies;
3836: }
3837: Result = SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET;
3838: /*
3839: Release exclusive access to Host Adapter.
3840: */
3841: Done:
3842: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
3843: return Result;
3844: }
3845:
3846:
3847: /*
3848: BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target
3849: Device associated with Command.
3850: */
3851:
3852: static int BusLogic_SendBusDeviceReset(BusLogic_HostAdapter_T *HostAdapter,
3853: SCSI_Command_T *Command,
3854: unsigned int ResetFlags)
3855: {
3856: int TargetID = Command->target;
3857: BusLogic_CCB_T *CCB, *XCCB;
3858: ProcessorFlags_T ProcessorFlags;
3859: int Result = -1;
3860: BusLogic_IncrementErrorCounter(
3861: &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested);
3862: /*
3863: Acquire exclusive access to Host Adapter.
3864: */
3865: BusLogic_AcquireHostAdapterLock(HostAdapter, &ProcessorFlags);
3866: /*
3867: If this is an Asynchronous Reset and this Command has already completed,
3868: then no Reset is necessary.
3869: */
3870: if (ResetFlags & SCSI_RESET_ASYNCHRONOUS)
3871: {
3872: if (Command->serial_number != Command->serial_number_at_timeout)
3873: {
3874: BusLogic_Warning("Unable to Reset Command to Target %d - "
3875: "Already Completed\n", HostAdapter, TargetID);
3876: Result = SCSI_RESET_NOT_RUNNING;
3877: goto Done;
3878: }
3879: for (CCB = HostAdapter->All_CCBs; CCB != NULL; CCB = CCB->NextAll)
3880: if (CCB->Command == Command) break;
3881: if (CCB == NULL)
3882: {
3883: BusLogic_Warning("Unable to Reset Command to Target %d - "
3884: "No CCB Found\n", HostAdapter, TargetID);
3885: Result = SCSI_RESET_NOT_RUNNING;
3886: goto Done;
3887: }
3888: else if (CCB->Status == BusLogic_CCB_Completed)
3889: {
3890: BusLogic_Warning("Unable to Reset Command to Target %d - "
3891: "CCB Completed\n", HostAdapter, TargetID);
3892: Result = SCSI_RESET_NOT_RUNNING;
3893: goto Done;
3894: }
3895: else if (CCB->Status == BusLogic_CCB_Reset)
3896: {
3897: BusLogic_Warning("Unable to Reset Command to Target %d - "
3898: "Reset Pending\n", HostAdapter, TargetID);
3899: Result = SCSI_RESET_PENDING;
3900: goto Done;
3901: }
3902: else if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL)
3903: {
3904: BusLogic_Warning("Bus Device Reset already pending to Target %d\n",
3905: HostAdapter, TargetID);
3906: goto Done;
3907: }
3908: }
3909: /*
3910: If this is a Synchronous Reset and a Bus Device Reset is already pending
3911: for this Target Device, do not send a second one. Add this Command to
3912: the list of Commands for which completion processing must be performed
3913: when the Bus Device Reset CCB completes.
3914: */
3915: if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
3916: if ((CCB = HostAdapter->BusDeviceResetPendingCCB[TargetID]) != NULL)
3917: {
3918: Command->reset_chain = CCB->Command;
3919: CCB->Command = Command;
3920: BusLogic_Warning("Unable to Reset Command to Target %d - "
3921: "Reset Pending\n", HostAdapter, TargetID);
3922: Result = SCSI_RESET_PENDING;
3923: goto Done;
3924: }
3925: if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3926: {
3927: /*
3928: MultiMaster Firmware versions prior to 5.xx treat a Bus Device Reset as
3929: a non-tagged command. Since non-tagged commands are not sent by the
3930: Host Adapter until the queue of outstanding tagged commands has
3931: completed, it is effectively impossible to send a Bus Device Reset
3932: while there are tagged commands outstanding. Therefore, in that case a
3933: full Host Adapter Hard Reset and SCSI Bus Reset must be done.
3934: */
3935: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
3936: HostAdapter->ActiveCommands[TargetID] > 0 &&
3937: HostAdapter->FirmwareVersion[0] < '5')
3938: goto Done;
3939: }
3940: /*
3941: Allocate a CCB from the Host Adapter's free list. In the unlikely event
3942: that there are none available and memory allocation fails, attempt a full
3943: Host Adapter Hard Reset and SCSI Bus Reset.
3944: */
3945: CCB = BusLogic_AllocateCCB(HostAdapter);
3946: if (CCB == NULL) goto Done;
3947: BusLogic_Warning("Sending Bus Device Reset CCB #%ld to Target %d\n",
3948: HostAdapter, CCB->SerialNumber, TargetID);
3949: CCB->Opcode = BusLogic_BusDeviceReset;
3950: CCB->TargetID = TargetID;
3951: /*
3952: For Synchronous Resets, arrange for the interrupt handler to perform
3953: completion processing for the Command being Reset.
3954: */
3955: if (ResetFlags & SCSI_RESET_SYNCHRONOUS)
3956: {
3957: Command->reset_chain = NULL;
3958: CCB->Command = Command;
3959: }
3960: if (BusLogic_MultiMasterHostAdapterP(HostAdapter))
3961: {
3962: /*
3963: Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB.
3964: If sending a Bus Device Reset is impossible, attempt a full Host
3965: Adapter Hard Reset and SCSI Bus Reset.
3966: */
3967: if (!(BusLogic_WriteOutgoingMailbox(
3968: HostAdapter, BusLogic_MailboxStartCommand, CCB)))
3969: {
3970: BusLogic_Warning("Unable to write Outgoing Mailbox for "
3971: "Bus Device Reset\n", HostAdapter);
3972: BusLogic_DeallocateCCB(CCB);
3973: goto Done;
3974: }
3975: }
3976: else
3977: {
3978: /*
3979: Call the FlashPoint SCCB Manager to start execution of the CCB.
3980: */
3981: CCB->Status = BusLogic_CCB_Active;
3982: HostAdapter->ActiveCommands[TargetID]++;
3983: FlashPoint_StartCCB(HostAdapter->CardHandle, CCB);
3984: }
3985: /*
3986: If there is a currently executing CCB in the Host Adapter for this Command
3987: (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be
3988: made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset.
3989: If there is no active CCB for this Command (i.e. this is a Synchronous
3990: Reset), then the Bus Device Reset CCB's Command field will have been set
3991: to the Command so that the interrupt for the completion of the Bus Device
3992: Reset can call the Completion Routine for the Command. On successful
3993: execution of a Bus Device Reset, older firmware versions did return the
3994: pending CCBs with the appropriate completion code, but more recent firmware
3995: versions only return the Bus Device Reset CCB itself. This driver handles
3996: both cases by marking all the currently executing CCBs to this Target
3997: Device as Reset. When the Bus Device Reset CCB is processed by the
3998: interrupt handler, any remaining CCBs marked as Reset will have completion
3999: processing performed.
4000: */
4001: BusLogic_IncrementErrorCounter(
4002: &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted);
4003: HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB;
4004: HostAdapter->LastResetAttempted[TargetID] = jiffies;
4005: for (XCCB = HostAdapter->All_CCBs; XCCB != NULL; XCCB = XCCB->NextAll)
4006: if (XCCB->Status == BusLogic_CCB_Active && XCCB->TargetID == TargetID)
4007: XCCB->Status = BusLogic_CCB_Reset;
4008: /*
4009: FlashPoint Host Adapters may have already completed the Bus Device
4010: Reset and BusLogic_QueueCompletedCCB been called, or it may still be
4011: pending.
4012: */
4013: Result = SCSI_RESET_PENDING;
4014: if (BusLogic_FlashPointHostAdapterP(HostAdapter))
4015: if (CCB->Status == BusLogic_CCB_Completed)
4016: {
4017: BusLogic_ProcessCompletedCCBs(HostAdapter);
4018: Result = SCSI_RESET_SUCCESS;
4019: }
4020: /*
4021: If a Bus Device Reset was not possible for some reason, force a full
4022: Host Adapter Hard Reset and SCSI Bus Reset.
4023: */
4024: Done:
4025: if (Result < 0)
4026: Result = BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4027: /*
4028: Release exclusive access to Host Adapter.
4029: */
4030: BusLogic_ReleaseHostAdapterLock(HostAdapter, &ProcessorFlags);
4031: return Result;
4032: }
4033:
4034:
4035: /*
4036: BusLogic_ResetCommand takes appropriate action to reset Command.
4037: */
4038:
4039: int BusLogic_ResetCommand(SCSI_Command_T *Command, unsigned int ResetFlags)
4040: {
4041: BusLogic_HostAdapter_T *HostAdapter =
4042: (BusLogic_HostAdapter_T *) Command->host->hostdata;
4043: int TargetID = Command->target;
4044: BusLogic_ErrorRecoveryStrategy_T
4045: ErrorRecoveryStrategy = HostAdapter->ErrorRecoveryStrategy[TargetID];
4046: /*
4047: Disable Tagged Queuing if it is active for this Target Device and if
4048: it has been less than 10 minutes since the last reset occurred, or since
4049: the system was initialized if no prior resets have occurred.
4050: */
4051: if (HostAdapter->TargetFlags[TargetID].TaggedQueuingActive &&
4052: jiffies - HostAdapter->LastResetCompleted[TargetID] < 10*60*HZ)
4053: {
4054: HostAdapter->TaggedQueuingPermitted &= ~(1 << TargetID);
4055: HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = false;
4056: BusLogic_Warning("Tagged Queuing now disabled for Target %d\n",
4057: HostAdapter, TargetID);
4058: }
4059: switch (ErrorRecoveryStrategy)
4060: {
4061: case BusLogic_ErrorRecovery_Default:
4062: if (ResetFlags & SCSI_RESET_SUGGEST_HOST_RESET)
4063: return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4064: else if (ResetFlags & SCSI_RESET_SUGGEST_BUS_RESET)
4065: return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4066: /* Fall through to Bus Device Reset case. */
4067: case BusLogic_ErrorRecovery_BusDeviceReset:
4068: /*
4069: The Bus Device Reset Error Recovery Strategy only graduates to a Hard
4070: Reset when no commands have completed successfully since the last Bus
4071: Device Reset and it has been at least 100 milliseconds. This prevents
4072: a sequence of commands that all timeout together from immediately
4073: forcing a Hard Reset before the Bus Device Reset has had a chance to
4074: clear the error condition.
4075: */
4076: if (HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag ||
4077: jiffies - HostAdapter->LastResetAttempted[TargetID] < HZ/10)
4078: {
4079: HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = false;
4080: return BusLogic_SendBusDeviceReset(HostAdapter, Command, ResetFlags);
4081: }
4082: /* Fall through to Hard Reset case. */
4083: case BusLogic_ErrorRecovery_HardReset:
4084: return BusLogic_ResetHostAdapter(HostAdapter, Command, ResetFlags);
4085: case BusLogic_ErrorRecovery_None:
4086: BusLogic_Warning("Error Recovery for Target %d Suppressed\n",
4087: HostAdapter, TargetID);
4088: break;
4089: }
4090: return SCSI_RESET_PUNT;
4091: }
4092:
4093:
4094: /*
4095: BusLogic_BIOSDiskParameters returns the Heads/Sectors/Cylinders BIOS Disk
4096: Parameters for Disk. The default disk geometry is 64 heads, 32 sectors, and
4097: the appropriate number of cylinders so as not to exceed drive capacity. In
4098: order for disks equal to or larger than 1 GB to be addressable by the BIOS
4099: without exceeding the BIOS limitation of 1024 cylinders, Extended Translation
4100: may be enabled in AutoSCSI on FlashPoint Host Adapters and on "W" and "C"
4101: series MultiMaster Host Adapters, or by a dip switch setting on "S" and "A"
4102: series MultiMaster Host Adapters. With Extended Translation enabled, drives
4103: between 1 GB inclusive and 2 GB exclusive are given a disk geometry of 128
4104: heads and 32 sectors, and drives above 2 GB inclusive are given a disk
4105: geometry of 255 heads and 63 sectors. However, if the BIOS detects that the
4106: Extended Translation setting does not match the geometry in the partition
4107: table, then the translation inferred from the partition table will be used by
4108: the BIOS, and a warning may be displayed.
4109: */
4110:
4111: int BusLogic_BIOSDiskParameters(SCSI_Disk_T *Disk, KernelDevice_T Device,
4112: int *Parameters)
4113: {
4114: BusLogic_HostAdapter_T *HostAdapter =
4115: (BusLogic_HostAdapter_T *) Disk->device->host->hostdata;
4116: BIOS_DiskParameters_T *DiskParameters = (BIOS_DiskParameters_T *) Parameters;
4117: struct buffer_head *BufferHead;
4118: if (HostAdapter->ExtendedTranslationEnabled &&
4119: Disk->capacity >= 2*1024*1024 /* 1 GB in 512 byte sectors */)
4120: {
4121: if (Disk->capacity >= 4*1024*1024 /* 2 GB in 512 byte sectors */)
4122: {
4123: DiskParameters->Heads = 255;
4124: DiskParameters->Sectors = 63;
4125: }
4126: else
4127: {
4128: DiskParameters->Heads = 128;
4129: DiskParameters->Sectors = 32;
4130: }
4131: }
4132: else
4133: {
4134: DiskParameters->Heads = 64;
4135: DiskParameters->Sectors = 32;
4136: }
4137: DiskParameters->Cylinders =
4138: Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
4139: /*
4140: Attempt to read the first 1024 bytes from the disk device.
4141: */
4142: BufferHead = bread(MKDEV(MAJOR(Device), MINOR(Device) & ~0x0F), 0, 1024);
4143: if (BufferHead == NULL) return 0;
4144: /*
4145: If the boot sector partition table flag is valid, search for a partition
4146: table entry whose end_head matches one of the standard BusLogic geometry
4147: translations (64/32, 128/32, or 255/63).
4148: */
4149: if (*(unsigned short *) (BufferHead->b_data + 0x1FE) == 0xAA55)
4150: {
4151: PartitionTable_T *FirstPartitionEntry =
4152: (PartitionTable_T *) (BufferHead->b_data + 0x1BE);
4153: PartitionTable_T *PartitionEntry = FirstPartitionEntry;
4154: int SavedCylinders = DiskParameters->Cylinders, PartitionNumber;
4155: unsigned char PartitionEntryEndHead, PartitionEntryEndSector;
4156: for (PartitionNumber = 0; PartitionNumber < 4; PartitionNumber++)
4157: {
4158: PartitionEntryEndHead = PartitionEntry->end_head;
4159: PartitionEntryEndSector = PartitionEntry->end_sector & 0x3F;
4160: if (PartitionEntryEndHead == 64-1)
4161: {
4162: DiskParameters->Heads = 64;
4163: DiskParameters->Sectors = 32;
4164: break;
4165: }
4166: else if (PartitionEntryEndHead == 128-1)
4167: {
4168: DiskParameters->Heads = 128;
4169: DiskParameters->Sectors = 32;
4170: break;
4171: }
4172: else if (PartitionEntryEndHead == 255-1)
4173: {
4174: DiskParameters->Heads = 255;
4175: DiskParameters->Sectors = 63;
4176: break;
4177: }
4178: PartitionEntry++;
4179: }
4180: if (PartitionNumber == 4)
4181: {
4182: PartitionEntryEndHead = FirstPartitionEntry->end_head;
4183: PartitionEntryEndSector = FirstPartitionEntry->end_sector & 0x3F;
4184: }
4185: DiskParameters->Cylinders =
4186: Disk->capacity / (DiskParameters->Heads * DiskParameters->Sectors);
4187: if (PartitionNumber < 4 &&
4188: PartitionEntryEndSector == DiskParameters->Sectors)
4189: {
4190: if (DiskParameters->Cylinders != SavedCylinders)
4191: BusLogic_Warning("Adopting Geometry %d/%d from Partition Table\n",
4192: HostAdapter,
4193: DiskParameters->Heads, DiskParameters->Sectors);
4194: }
4195: else if (PartitionEntryEndHead > 0 || PartitionEntryEndSector > 0)
4196: {
4197: BusLogic_Warning("Warning: Partition Table appears to "
4198: "have Geometry %d/%d which is\n", HostAdapter,
4199: PartitionEntryEndHead + 1,
4200: PartitionEntryEndSector);
4201: BusLogic_Warning("not compatible with current BusLogic "
4202: "Host Adapter Geometry %d/%d\n", HostAdapter,
4203: DiskParameters->Heads, DiskParameters->Sectors);
4204: }
4205: }
4206: brelse(BufferHead);
4207: return 0;
4208: }
4209:
4210:
4211: /*
4212: BugLogic_ProcDirectoryInfo implements /proc/scsi/BusLogic/<N>.
4213: */
4214:
4215: int BusLogic_ProcDirectoryInfo(char *ProcBuffer, char **StartPointer,
4216: off_t Offset, int BytesAvailable,
4217: int HostNumber, int WriteFlag)
4218: {
4219: BusLogic_HostAdapter_T *HostAdapter;
4220: BusLogic_TargetStatistics_T *TargetStatistics;
4221: int TargetID, Length;
4222: char *Buffer;
4223: for (HostAdapter = BusLogic_FirstRegisteredHostAdapter;
4224: HostAdapter != NULL;
4225: HostAdapter = HostAdapter->Next)
4226: if (HostAdapter->HostNumber == HostNumber) break;
4227: if (HostAdapter == NULL)
4228: {
4229: BusLogic_Error("Cannot find Host Adapter for SCSI Host %d\n",
4230: NULL, HostNumber);
4231: return 0;
4232: }
4233: TargetStatistics = HostAdapter->TargetStatistics;
4234: if (WriteFlag)
4235: {
4236: HostAdapter->ExternalHostAdapterResets = 0;
4237: HostAdapter->HostAdapterInternalErrors = 0;
4238: memset(TargetStatistics, 0,
4239: BusLogic_MaxTargetDevices * sizeof(BusLogic_TargetStatistics_T));
4240: return 0;
4241: }
4242: Buffer = HostAdapter->MessageBuffer;
4243: Length = HostAdapter->MessageBufferLength;
4244: Length += sprintf(&Buffer[Length], "\n\
4245: Current Driver Queue Depth: %d\n\
4246: Currently Allocated CCBs: %d\n",
4247: HostAdapter->DriverQueueDepth,
4248: HostAdapter->AllocatedCCBs);
4249: Length += sprintf(&Buffer[Length], "\n\n\
4250: DATA TRANSFER STATISTICS\n\
4251: \n\
4252: Target Tagged Queuing Queue Depth Active Attempted Completed\n\
4253: ====== ============== =========== ====== ========= =========\n");
4254: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4255: {
4256: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4257: if (!TargetFlags->TargetExists) continue;
4258: Length +=
4259: sprintf(&Buffer[Length], " %2d %s", TargetID,
4260: (TargetFlags->TaggedQueuingSupported
4261: ? (TargetFlags->TaggedQueuingActive
4262: ? " Active"
4263: : (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)
4264: ? " Permitted" : " Disabled"))
4265: : "Not Supported"));
4266: Length += sprintf(&Buffer[Length],
4267: " %3d %3u %9u %9u\n",
4268: HostAdapter->QueueDepth[TargetID],
4269: HostAdapter->ActiveCommands[TargetID],
4270: TargetStatistics[TargetID].CommandsAttempted,
4271: TargetStatistics[TargetID].CommandsCompleted);
4272: }
4273: Length += sprintf(&Buffer[Length], "\n\
4274: Target Read Commands Write Commands Total Bytes Read Total Bytes Written\n\
4275: ====== ============= ============== =================== ===================\n");
4276: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4277: {
4278: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4279: if (!TargetFlags->TargetExists) continue;
4280: Length +=
4281: sprintf(&Buffer[Length], " %2d %9u %9u", TargetID,
4282: TargetStatistics[TargetID].ReadCommands,
4283: TargetStatistics[TargetID].WriteCommands);
4284: if (TargetStatistics[TargetID].TotalBytesRead.Billions > 0)
4285: Length +=
4286: sprintf(&Buffer[Length], " %9u%09u",
4287: TargetStatistics[TargetID].TotalBytesRead.Billions,
4288: TargetStatistics[TargetID].TotalBytesRead.Units);
4289: else
4290: Length +=
4291: sprintf(&Buffer[Length], " %9u",
4292: TargetStatistics[TargetID].TotalBytesRead.Units);
4293: if (TargetStatistics[TargetID].TotalBytesWritten.Billions > 0)
4294: Length +=
4295: sprintf(&Buffer[Length], " %9u%09u\n",
4296: TargetStatistics[TargetID].TotalBytesWritten.Billions,
4297: TargetStatistics[TargetID].TotalBytesWritten.Units);
4298: else
4299: Length +=
4300: sprintf(&Buffer[Length], " %9u\n",
4301: TargetStatistics[TargetID].TotalBytesWritten.Units);
4302: }
4303: Length += sprintf(&Buffer[Length], "\n\
4304: Target Command 0-1KB 1-2KB 2-4KB 4-8KB 8-16KB\n\
4305: ====== ======= ========= ========= ========= ========= =========\n");
4306: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4307: {
4308: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4309: if (!TargetFlags->TargetExists) continue;
4310: Length +=
4311: sprintf(&Buffer[Length],
4312: " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
4313: TargetStatistics[TargetID].ReadCommandSizeBuckets[0],
4314: TargetStatistics[TargetID].ReadCommandSizeBuckets[1],
4315: TargetStatistics[TargetID].ReadCommandSizeBuckets[2],
4316: TargetStatistics[TargetID].ReadCommandSizeBuckets[3],
4317: TargetStatistics[TargetID].ReadCommandSizeBuckets[4]);
4318: Length +=
4319: sprintf(&Buffer[Length],
4320: " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
4321: TargetStatistics[TargetID].WriteCommandSizeBuckets[0],
4322: TargetStatistics[TargetID].WriteCommandSizeBuckets[1],
4323: TargetStatistics[TargetID].WriteCommandSizeBuckets[2],
4324: TargetStatistics[TargetID].WriteCommandSizeBuckets[3],
4325: TargetStatistics[TargetID].WriteCommandSizeBuckets[4]);
4326: }
4327: Length += sprintf(&Buffer[Length], "\n\
4328: Target Command 16-32KB 32-64KB 64-128KB 128-256KB 256KB+\n\
4329: ====== ======= ========= ========= ========= ========= =========\n");
4330: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4331: {
4332: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4333: if (!TargetFlags->TargetExists) continue;
4334: Length +=
4335: sprintf(&Buffer[Length],
4336: " %2d Read %9u %9u %9u %9u %9u\n", TargetID,
4337: TargetStatistics[TargetID].ReadCommandSizeBuckets[5],
4338: TargetStatistics[TargetID].ReadCommandSizeBuckets[6],
4339: TargetStatistics[TargetID].ReadCommandSizeBuckets[7],
4340: TargetStatistics[TargetID].ReadCommandSizeBuckets[8],
4341: TargetStatistics[TargetID].ReadCommandSizeBuckets[9]);
4342: Length +=
4343: sprintf(&Buffer[Length],
4344: " %2d Write %9u %9u %9u %9u %9u\n", TargetID,
4345: TargetStatistics[TargetID].WriteCommandSizeBuckets[5],
4346: TargetStatistics[TargetID].WriteCommandSizeBuckets[6],
4347: TargetStatistics[TargetID].WriteCommandSizeBuckets[7],
4348: TargetStatistics[TargetID].WriteCommandSizeBuckets[8],
4349: TargetStatistics[TargetID].WriteCommandSizeBuckets[9]);
4350: }
4351: Length += sprintf(&Buffer[Length], "\n\n\
4352: ERROR RECOVERY STATISTICS\n\
4353: \n\
4354: Command Aborts Bus Device Resets Host Adapter Resets\n\
4355: Target Requested Completed Requested Completed Requested Completed\n\
4356: ID \\\\\\\\ Attempted //// \\\\\\\\ Attempted //// \\\\\\\\ Attempted ////\n\
4357: ====== ===== ===== ===== ===== ===== ===== ===== ===== =====\n");
4358: for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
4359: {
4360: BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[TargetID];
4361: if (!TargetFlags->TargetExists) continue;
4362: Length +=
4363: sprintf(&Buffer[Length], "\
4364: %2d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", TargetID,
4365: TargetStatistics[TargetID].CommandAbortsRequested,
4366: TargetStatistics[TargetID].CommandAbortsAttempted,
4367: TargetStatistics[TargetID].CommandAbortsCompleted,
4368: TargetStatistics[TargetID].BusDeviceResetsRequested,
4369: TargetStatistics[TargetID].BusDeviceResetsAttempted,
4370: TargetStatistics[TargetID].BusDeviceResetsCompleted,
4371: TargetStatistics[TargetID].HostAdapterResetsRequested,
4372: TargetStatistics[TargetID].HostAdapterResetsAttempted,
4373: TargetStatistics[TargetID].HostAdapterResetsCompleted);
4374: }
4375: Length += sprintf(&Buffer[Length], "\nExternal Host Adapter Resets: %d\n",
4376: HostAdapter->ExternalHostAdapterResets);
4377: Length += sprintf(&Buffer[Length], "Host Adapter Internal Errors: %d\n",
4378: HostAdapter->HostAdapterInternalErrors);
4379: if (Length >= BusLogic_MessageBufferSize)
4380: BusLogic_Error("Message Buffer length %d exceeds size %d\n",
4381: HostAdapter, Length, BusLogic_MessageBufferSize);
4382: if ((Length -= Offset) <= 0) return 0;
4383: if (Length >= BytesAvailable) Length = BytesAvailable;
4384: *StartPointer = &HostAdapter->MessageBuffer[Offset];
4385: return Length;
4386: }
4387:
4388:
4389: /*
4390: BusLogic_Message prints Driver Messages.
4391: */
4392:
4393: static void BusLogic_Message(BusLogic_MessageLevel_T MessageLevel,
4394: char *Format,
4395: BusLogic_HostAdapter_T *HostAdapter,
4396: ...)
4397: {
4398: static char Buffer[BusLogic_LineBufferSize];
4399: static boolean BeginningOfLine = true;
4400: va_list Arguments;
4401: int Length = 0;
4402: va_start(Arguments, HostAdapter);
4403: Length = vsprintf(Buffer, Format, Arguments);
4404: va_end(Arguments);
4405: if (MessageLevel == BusLogic_AnnounceLevel)
4406: {
4407: static int AnnouncementLines = 0;
4408: strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
4409: Buffer);
4410: HostAdapter->MessageBufferLength += Length;
4411: if (++AnnouncementLines <= 2)
4412: printk("%sscsi: %s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
4413: }
4414: else if (MessageLevel == BusLogic_InfoLevel)
4415: {
4416: strcpy(&HostAdapter->MessageBuffer[HostAdapter->MessageBufferLength],
4417: Buffer);
4418: HostAdapter->MessageBufferLength += Length;
4419: if (BeginningOfLine)
4420: {
4421: if (Buffer[0] != '\n' || Length > 1)
4422: printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
4423: HostAdapter->HostNumber, Buffer);
4424: }
4425: else printk("%s", Buffer);
4426: }
4427: else
4428: {
4429: if (BeginningOfLine)
4430: {
4431: if (HostAdapter != NULL && HostAdapter->HostAdapterInitialized)
4432: printk("%sscsi%d: %s", BusLogic_MessageLevelMap[MessageLevel],
4433: HostAdapter->HostNumber, Buffer);
4434: else printk("%s%s", BusLogic_MessageLevelMap[MessageLevel], Buffer);
4435: }
4436: else printk("%s", Buffer);
4437: }
4438: BeginningOfLine = (Buffer[Length-1] == '\n');
4439: }
4440:
4441:
4442: /*
4443: BusLogic_ParseKeyword parses an individual option keyword. It returns true
4444: and updates the pointer if the keyword is recognized and false otherwise.
4445: */
4446:
4447: static boolean BusLogic_ParseKeyword(char **StringPointer, char *Keyword)
4448: {
4449: char *Pointer = *StringPointer;
4450: while (*Keyword != '\0')
4451: {
4452: char StringChar = *Pointer++;
4453: char KeywordChar = *Keyword++;
4454: if (StringChar >= 'A' && StringChar <= 'Z')
4455: StringChar += 'a' - 'Z';
4456: if (KeywordChar >= 'A' && KeywordChar <= 'Z')
4457: KeywordChar += 'a' - 'Z';
4458: if (StringChar != KeywordChar) return false;
4459: }
4460: *StringPointer = Pointer;
4461: return true;
4462: }
4463:
4464:
4465: /*
4466: BusLogic_ParseDriverOptions handles processing of BusLogic Driver Options
4467: specifications.
4468:
4469: BusLogic Driver Options may be specified either via the Linux Kernel Command
4470: Line or via the Loadable Kernel Module Installation Facility. Driver Options
4471: for multiple host adapters may be specified either by separating the option
4472: strings by a semicolon, or by specifying multiple "BusLogic=" strings on the
4473: command line. Individual option specifications for a single host adapter are
4474: separated by commas. The Probing and Debugging Options apply to all host
4475: adapters whereas the remaining options apply individually only to the
4476: selected host adapter.
4477:
4478: The BusLogic Driver Probing Options comprise the following:
4479:
4480: IO:<integer>
4481:
4482: The "IO:" option specifies an ISA I/O Address to be probed for a non-PCI
4483: MultiMaster Host Adapter. If neither "IO:" nor "NoProbeISA" options are
4484: specified, then the standard list of BusLogic MultiMaster ISA I/O Addresses
4485: will be probed (0x330, 0x334, 0x230, 0x234, 0x130, and 0x134). Multiple
4486: "IO:" options may be specified to precisely determine the I/O Addresses to
4487: be probed, but the probe order will always follow the standard list.
4488:
4489: NoProbe
4490:
4491: The "NoProbe" option disables all probing and therefore no BusLogic Host
4492: Adapters will be detected.
4493:
4494: NoProbeISA
4495:
4496: The "NoProbeISA" option disables probing of the standard BusLogic ISA I/O
4497: Addresses and therefore only PCI MultiMaster and FlashPoint Host Adapters
4498: will be detected.
4499:
4500: NoProbePCI
4501:
4502: The "NoProbePCI" options disables the interrogation of PCI Configuration
4503: Space and therefore only ISA Multimaster Host Adapters will be detected, as
4504: well as PCI Multimaster Host Adapters that have their ISA Compatible I/O
4505: Port set to "Primary" or "Alternate".
4506:
4507: NoSortPCI
4508:
4509: The "NoSortPCI" option forces PCI MultiMaster Host Adapters to be
4510: enumerated in the order provided by the PCI BIOS, ignoring any setting of
4511: the AutoSCSI "Use Bus And Device # For PCI Scanning Seq." option.
4512:
4513: MultiMasterFirst
4514:
4515: The "MultiMasterFirst" option forces MultiMaster Host Adapters to be probed
4516: before FlashPoint Host Adapters. By default, if both FlashPoint and PCI
4517: MultiMaster Host Adapters are present, this driver will probe for
4518: FlashPoint Host Adapters first unless the BIOS primary disk is controlled
4519: by the first PCI MultiMaster Host Adapter, in which case MultiMaster Host
4520: Adapters will be probed first.
4521:
4522: FlashPointFirst
4523:
4524: The "FlashPointFirst" option forces FlashPoint Host Adapters to be probed
4525: before MultiMaster Host Adapters.
4526:
4527: The BusLogic Driver Tagged Queuing Options allow for explicitly specifying
4528: the Queue Depth and whether Tagged Queuing is permitted for each Target
4529: Device (assuming that the Target Device supports Tagged Queuing). The Queue
4530: Depth is the number of SCSI Commands that are allowed to be concurrently
4531: presented for execution (either to the Host Adapter or Target Device). Note
4532: that explicitly enabling Tagged Queuing may lead to problems; the option to
4533: enable or disable Tagged Queuing is provided primarily to allow disabling
4534: Tagged Queuing on Target Devices that do not implement it correctly. The
4535: following options are available:
4536:
4537: QueueDepth:<integer>
4538:
4539: The "QueueDepth:" or QD:" option specifies the Queue Depth to use for all
4540: Target Devices that support Tagged Queuing, as well as the maximum Queue
4541: Depth for devices that do not support Tagged Queuing. If no Queue Depth
4542: option is provided, the Queue Depth will be determined automatically based
4543: on the Host Adapter's Total Queue Depth and the number, type, speed, and
4544: capabilities of the detected Target Devices. For Host Adapters that
4545: require ISA Bounce Buffers, the Queue Depth is automatically set by default
4546: to BusLogic_TaggedQueueDepthBB or BusLogic_UntaggedQueueDepthBB to avoid
4547: excessive preallocation of DMA Bounce Buffer memory. Target Devices that
4548: do not support Tagged Queuing always have their Queue Depth set to
4549: BusLogic_UntaggedQueueDepth or BusLogic_UntaggedQueueDepthBB, unless a
4550: lower Queue Depth option is provided. A Queue Depth of 1 automatically
4551: disables Tagged Queuing.
4552:
4553: QueueDepth:[<integer>,<integer>...]
4554:
4555: The "QueueDepth:[...]" or "QD:[...]" option specifies the Queue Depth
4556: individually for each Target Device. If an <integer> is omitted, the
4557: associated Target Device will have its Queue Depth selected automatically.
4558:
4559: TaggedQueuing:Default
4560:
4561: The "TaggedQueuing:Default" or "TQ:Default" option permits Tagged Queuing
4562: based on the firmware version of the BusLogic Host Adapter and based on
4563: whether the Queue Depth allows queuing multiple commands.
4564:
4565: TaggedQueuing:Enable
4566:
4567: The "TaggedQueuing:Enable" or "TQ:Enable" option enables Tagged Queuing for
4568: all Target Devices on this Host Adapter, overriding any limitation that
4569: would otherwise be imposed based on the Host Adapter firmware version.
4570:
4571: TaggedQueuing:Disable
4572:
4573: The "TaggedQueuing:Disable" or "TQ:Disable" option disables Tagged Queuing
4574: for all Target Devices on this Host Adapter.
4575:
4576: TaggedQueuing:<Target-Spec>
4577:
4578: The "TaggedQueuing:<Target-Spec>" or "TQ:<Target-Spec>" option controls
4579: Tagged Queuing individually for each Target Device. <Target-Spec> is a
4580: sequence of "Y", "N", and "X" characters. "Y" enables Tagged Queuing, "N"
4581: disables Tagged Queuing, and "X" accepts the default based on the firmware
4582: version. The first character refers to Target Device 0, the second to
4583: Target Device 1, and so on; if the sequence of "Y", "N", and "X" characters
4584: does not cover all the Target Devices, unspecified characters are assumed
4585: to be "X".
4586:
4587: The BusLogic Driver Error Recovery Option allows for explicitly specifying
4588: the Error Recovery action to be performed when BusLogic_ResetCommand is
4589: called due to a SCSI Command failing to complete successfully. The following
4590: options are available:
4591:
4592: ErrorRecovery:Default
4593:
4594: The "ErrorRecovery:Default" or "ER:Default" option selects between the Hard
4595: Reset and Bus Device Reset options based on the recommendation of the SCSI
4596: Subsystem.
4597:
4598: ErrorRecovery:HardReset
4599:
4600: The "ErrorRecovery:HardReset" or "ER:HardReset" option will initiate a Host
4601: Adapter Hard Reset which also causes a SCSI Bus Reset.
4602:
4603: ErrorRecovery:BusDeviceReset
4604:
4605: The "ErrorRecovery:BusDeviceReset" or "ER:BusDeviceReset" option will send
4606: a Bus Device Reset message to the individual Target Device causing the
4607: error. If Error Recovery is again initiated for this Target Device and no
4608: SCSI Command to this Target Device has completed successfully since the Bus
4609: Device Reset message was sent, then a Hard Reset will be attempted.
4610:
4611: ErrorRecovery:None
4612:
4613: The "ErrorRecovery:None" or "ER:None" option suppresses Error Recovery.
4614: This option should only be selected if a SCSI Bus Reset or Bus Device Reset
4615: will cause the Target Device or a critical operation to suffer a complete
4616: and unrecoverable failure.
4617:
4618: ErrorRecovery:<Target-Spec>
4619:
4620: The "ErrorRecovery:<Target-Spec>" or "ER:<Target-Spec>" option controls
4621: Error Recovery individually for each Target Device. <Target-Spec> is a
4622: sequence of "D", "H", "B", and "N" characters. "D" selects Default, "H"
4623: selects Hard Reset, "B" selects Bus Device Reset, and "N" selects None.
4624: The first character refers to Target Device 0, the second to Target Device
4625: 1, and so on; if the sequence of "D", "H", "B", and "N" characters does not
4626: cover all the possible Target Devices, unspecified characters are assumed
4627: to be "D".
4628:
4629: The BusLogic Driver Miscellaneous Options comprise the following:
4630:
4631: BusSettleTime:<seconds>
4632:
4633: The "BusSettleTime:" or "BST:" option specifies the Bus Settle Time in
4634: seconds. The Bus Settle Time is the amount of time to wait between a Host
4635: Adapter Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI
4636: Commands. If unspecified, it defaults to BusLogic_DefaultBusSettleTime.
4637:
4638: InhibitTargetInquiry
4639:
4640: The "InhibitTargetInquiry" option inhibits the execution of an Inquire
4641: Target Devices or Inquire Installed Devices command on MultiMaster Host
4642: Adapters. This may be necessary with some older Target Devices that do not
4643: respond correctly when Logical Units above 0 are addressed.
4644:
4645: The BusLogic Driver Debugging Options comprise the following:
4646:
4647: TraceProbe
4648:
4649: The "TraceProbe" option enables tracing of Host Adapter Probing.
4650:
4651: TraceHardwareReset
4652:
4653: The "TraceHardwareReset" option enables tracing of Host Adapter Hardware
4654: Reset.
4655:
4656: TraceConfiguration
4657:
4658: The "TraceConfiguration" option enables tracing of Host Adapter
4659: Configuration.
4660:
4661: TraceErrors
4662:
4663: The "TraceErrors" option enables tracing of SCSI Commands that return an
4664: error from the Target Device. The CDB and Sense Data will be printed for
4665: each SCSI Command that fails.
4666:
4667: Debug
4668:
4669: The "Debug" option enables all debugging options.
4670:
4671: The following examples demonstrate setting the Queue Depth for Target Devices
4672: 1 and 2 on the first host adapter to 7 and 15, the Queue Depth for all Target
4673: Devices on the second host adapter to 31, and the Bus Settle Time on the
4674: second host adapter to 30 seconds.
4675:
4676: Linux Kernel Command Line:
4677:
4678: linux BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30
4679:
4680: LILO Linux Boot Loader (in /etc/lilo.conf):
4681:
4682: append = "BusLogic=QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"
4683:
4684: INSMOD Loadable Kernel Module Installation Facility:
4685:
4686: insmod BusLogic.o \
4687: 'BusLogic_Options="QueueDepth:[,7,15];QueueDepth:31,BusSettleTime:30"'
4688:
4689: NOTE: Module Utilities 2.1.71 or later is required for correct parsing
4690: of driver options containing commas.
4691:
4692: */
4693:
4694: static void BusLogic_ParseDriverOptions(char *OptionsString)
4695: {
4696: while (true)
4697: {
4698: BusLogic_DriverOptions_T *DriverOptions =
4699: &BusLogic_DriverOptions[BusLogic_DriverOptionsCount++];
4700: int TargetID;
4701: memset(DriverOptions, 0, sizeof(BusLogic_DriverOptions_T));
4702: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
4703: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4704: BusLogic_ErrorRecovery_Default;
4705: while (*OptionsString != '\0' && *OptionsString != ';')
4706: {
4707: /* Probing Options. */
4708: if (BusLogic_ParseKeyword(&OptionsString, "IO:"))
4709: {
4710: BusLogic_IO_Address_T IO_Address =
4711: simple_strtoul(OptionsString, &OptionsString, 0);
4712: BusLogic_ProbeOptions.LimitedProbeISA = true;
4713: switch (IO_Address)
4714: {
4715: case 0x330:
4716: BusLogic_ProbeOptions.Probe330 = true;
4717: break;
4718: case 0x334:
4719: BusLogic_ProbeOptions.Probe334 = true;
4720: break;
4721: case 0x230:
4722: BusLogic_ProbeOptions.Probe230 = true;
4723: break;
4724: case 0x234:
4725: BusLogic_ProbeOptions.Probe234 = true;
4726: break;
4727: case 0x130:
4728: BusLogic_ProbeOptions.Probe130 = true;
4729: break;
4730: case 0x134:
4731: BusLogic_ProbeOptions.Probe134 = true;
4732: break;
4733: default:
4734: BusLogic_Error("BusLogic: Invalid Driver Options "
4735: "(illegal I/O Address 0x%X)\n",
4736: NULL, IO_Address);
4737: return;
4738: }
4739: }
4740: else if (BusLogic_ParseKeyword(&OptionsString, "NoProbeISA"))
4741: BusLogic_ProbeOptions.NoProbeISA = true;
4742: else if (BusLogic_ParseKeyword(&OptionsString, "NoProbePCI"))
4743: BusLogic_ProbeOptions.NoProbePCI = true;
4744: else if (BusLogic_ParseKeyword(&OptionsString, "NoProbe"))
4745: BusLogic_ProbeOptions.NoProbe = true;
4746: else if (BusLogic_ParseKeyword(&OptionsString, "NoSortPCI"))
4747: BusLogic_ProbeOptions.NoSortPCI = true;
4748: else if (BusLogic_ParseKeyword(&OptionsString, "MultiMasterFirst"))
4749: BusLogic_ProbeOptions.MultiMasterFirst = true;
4750: else if (BusLogic_ParseKeyword(&OptionsString, "FlashPointFirst"))
4751: BusLogic_ProbeOptions.FlashPointFirst = true;
4752: /* Tagged Queuing Options. */
4753: else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:[") ||
4754: BusLogic_ParseKeyword(&OptionsString, "QD:["))
4755: {
4756: for (TargetID = 0;
4757: TargetID < BusLogic_MaxTargetDevices;
4758: TargetID++)
4759: {
4760: unsigned short QueueDepth =
4761: simple_strtoul(OptionsString, &OptionsString, 0);
4762: if (QueueDepth > BusLogic_MaxTaggedQueueDepth)
4763: {
4764: BusLogic_Error("BusLogic: Invalid Driver Options "
4765: "(illegal Queue Depth %d)\n",
4766: NULL, QueueDepth);
4767: return;
4768: }
4769: DriverOptions->QueueDepth[TargetID] = QueueDepth;
4770: if (*OptionsString == ',')
4771: OptionsString++;
4772: else if (*OptionsString == ']')
4773: break;
4774: else
4775: {
4776: BusLogic_Error("BusLogic: Invalid Driver Options "
4777: "(',' or ']' expected at '%s')\n",
4778: NULL, OptionsString);
4779: return;
4780: }
4781: }
4782: if (*OptionsString != ']')
4783: {
4784: BusLogic_Error("BusLogic: Invalid Driver Options "
4785: "(']' expected at '%s')\n",
4786: NULL, OptionsString);
4787: return;
4788: }
4789: else OptionsString++;
4790: }
4791: else if (BusLogic_ParseKeyword(&OptionsString, "QueueDepth:") ||
4792: BusLogic_ParseKeyword(&OptionsString, "QD:"))
4793: {
4794: unsigned short QueueDepth =
4795: simple_strtoul(OptionsString, &OptionsString, 0);
4796: if (QueueDepth == 0 || QueueDepth > BusLogic_MaxTaggedQueueDepth)
4797: {
4798: BusLogic_Error("BusLogic: Invalid Driver Options "
4799: "(illegal Queue Depth %d)\n",
4800: NULL, QueueDepth);
4801: return;
4802: }
4803: DriverOptions->CommonQueueDepth = QueueDepth;
4804: for (TargetID = 0;
4805: TargetID < BusLogic_MaxTargetDevices;
4806: TargetID++)
4807: DriverOptions->QueueDepth[TargetID] = QueueDepth;
4808: }
4809: else if (BusLogic_ParseKeyword(&OptionsString, "TaggedQueuing:") ||
4810: BusLogic_ParseKeyword(&OptionsString, "TQ:"))
4811: {
4812: if (BusLogic_ParseKeyword(&OptionsString, "Default"))
4813: {
4814: DriverOptions->TaggedQueuingPermitted = 0x0000;
4815: DriverOptions->TaggedQueuingPermittedMask = 0x0000;
4816: }
4817: else if (BusLogic_ParseKeyword(&OptionsString, "Enable"))
4818: {
4819: DriverOptions->TaggedQueuingPermitted = 0xFFFF;
4820: DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
4821: }
4822: else if (BusLogic_ParseKeyword(&OptionsString, "Disable"))
4823: {
4824: DriverOptions->TaggedQueuingPermitted = 0x0000;
4825: DriverOptions->TaggedQueuingPermittedMask = 0xFFFF;
4826: }
4827: else
4828: {
4829: unsigned short TargetBit;
4830: for (TargetID = 0, TargetBit = 1;
4831: TargetID < BusLogic_MaxTargetDevices;
4832: TargetID++, TargetBit <<= 1)
4833: switch (*OptionsString++)
4834: {
4835: case 'Y':
4836: DriverOptions->TaggedQueuingPermitted |= TargetBit;
4837: DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
4838: break;
4839: case 'N':
4840: DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
4841: DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
4842: break;
4843: case 'X':
4844: break;
4845: default:
4846: OptionsString--;
4847: TargetID = BusLogic_MaxTargetDevices;
4848: break;
4849: }
4850: }
4851: }
4852: /* Error Recovery Option. */
4853: else if (BusLogic_ParseKeyword(&OptionsString, "ErrorRecovery:") ||
4854: BusLogic_ParseKeyword(&OptionsString, "ER:"))
4855: {
4856: if (BusLogic_ParseKeyword(&OptionsString, "Default"))
4857: for (TargetID = 0;
4858: TargetID < BusLogic_MaxTargetDevices;
4859: TargetID++)
4860: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4861: BusLogic_ErrorRecovery_Default;
4862: else if (BusLogic_ParseKeyword(&OptionsString, "HardReset"))
4863: for (TargetID = 0;
4864: TargetID < BusLogic_MaxTargetDevices;
4865: TargetID++)
4866: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4867: BusLogic_ErrorRecovery_HardReset;
4868: else if (BusLogic_ParseKeyword(&OptionsString, "BusDeviceReset"))
4869: for (TargetID = 0;
4870: TargetID < BusLogic_MaxTargetDevices;
4871: TargetID++)
4872: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4873: BusLogic_ErrorRecovery_BusDeviceReset;
4874: else if (BusLogic_ParseKeyword(&OptionsString, "None"))
4875: for (TargetID = 0;
4876: TargetID < BusLogic_MaxTargetDevices;
4877: TargetID++)
4878: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4879: BusLogic_ErrorRecovery_None;
4880: else
4881: for (TargetID = 0;
4882: TargetID < BusLogic_MaxTargetDevices;
4883: TargetID++)
4884: switch (*OptionsString++)
4885: {
4886: case 'D':
4887: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4888: BusLogic_ErrorRecovery_Default;
4889: break;
4890: case 'H':
4891: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4892: BusLogic_ErrorRecovery_HardReset;
4893: break;
4894: case 'B':
4895: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4896: BusLogic_ErrorRecovery_BusDeviceReset;
4897: break;
4898: case 'N':
4899: DriverOptions->ErrorRecoveryStrategy[TargetID] =
4900: BusLogic_ErrorRecovery_None;
4901: break;
4902: default:
4903: OptionsString--;
4904: TargetID = BusLogic_MaxTargetDevices;
4905: break;
4906: }
4907: }
4908: /* Miscellaneous Options. */
4909: else if (BusLogic_ParseKeyword(&OptionsString, "BusSettleTime:") ||
4910: BusLogic_ParseKeyword(&OptionsString, "BST:"))
4911: {
4912: unsigned short BusSettleTime =
4913: simple_strtoul(OptionsString, &OptionsString, 0);
4914: if (BusSettleTime > 5 * 60)
4915: {
4916: BusLogic_Error("BusLogic: Invalid Driver Options "
4917: "(illegal Bus Settle Time %d)\n",
4918: NULL, BusSettleTime);
4919: return;
4920: }
4921: DriverOptions->BusSettleTime = BusSettleTime;
4922: }
4923: else if (BusLogic_ParseKeyword(&OptionsString,
4924: "InhibitTargetInquiry"))
4925: DriverOptions->LocalOptions.InhibitTargetInquiry = true;
4926: /* Debugging Options. */
4927: else if (BusLogic_ParseKeyword(&OptionsString, "TraceProbe"))
4928: BusLogic_GlobalOptions.TraceProbe = true;
4929: else if (BusLogic_ParseKeyword(&OptionsString, "TraceHardwareReset"))
4930: BusLogic_GlobalOptions.TraceHardwareReset = true;
4931: else if (BusLogic_ParseKeyword(&OptionsString, "TraceConfiguration"))
4932: BusLogic_GlobalOptions.TraceConfiguration = true;
4933: else if (BusLogic_ParseKeyword(&OptionsString, "TraceErrors"))
4934: BusLogic_GlobalOptions.TraceErrors = true;
4935: else if (BusLogic_ParseKeyword(&OptionsString, "Debug"))
4936: {
4937: BusLogic_GlobalOptions.TraceProbe = true;
4938: BusLogic_GlobalOptions.TraceHardwareReset = true;
4939: BusLogic_GlobalOptions.TraceConfiguration = true;
4940: BusLogic_GlobalOptions.TraceErrors = true;
4941: }
4942: if (*OptionsString == ',')
4943: OptionsString++;
4944: else if (*OptionsString != ';' && *OptionsString != '\0')
4945: {
4946: BusLogic_Error("BusLogic: Unexpected Driver Option '%s' "
4947: "ignored\n", NULL, OptionsString);
4948: *OptionsString = '\0';
4949: }
4950: }
4951: if (!(BusLogic_DriverOptionsCount == 0 ||
4952: BusLogic_ProbeInfoCount == 0 ||
4953: BusLogic_DriverOptionsCount == BusLogic_ProbeInfoCount))
4954: {
4955: BusLogic_Error("BusLogic: Invalid Driver Options "
4956: "(all or no I/O Addresses must be specified)\n", NULL);
4957: return;
4958: }
4959: /*
4960: Tagged Queuing is disabled when the Queue Depth is 1 since queuing
4961: multiple commands is not possible.
4962: */
4963: for (TargetID = 0; TargetID < BusLogic_MaxTargetDevices; TargetID++)
4964: if (DriverOptions->QueueDepth[TargetID] == 1)
4965: {
4966: unsigned short TargetBit = 1 << TargetID;
4967: DriverOptions->TaggedQueuingPermitted &= ~TargetBit;
4968: DriverOptions->TaggedQueuingPermittedMask |= TargetBit;
4969: }
4970: if (*OptionsString == ';') OptionsString++;
4971: if (*OptionsString == '\0') return;
4972: }
4973: }
4974:
4975:
4976: /*
4977: BusLogic_Setup handles processing of Kernel Command Line Arguments.
4978: */
4979:
4980: void BusLogic_Setup(char *CommandLineString, int *CommandLineIntegers)
4981: {
4982: if (CommandLineIntegers[0] != 0)
4983: {
4984: BusLogic_Error("BusLogic: Obsolete Command Line Entry "
4985: "Format Ignored\n", NULL);
4986: return;
4987: }
4988: if (CommandLineString == NULL || *CommandLineString == '\0') return;
4989: BusLogic_ParseDriverOptions(CommandLineString);
4990: }
4991:
4992:
4993: /*
4994: Include Module support if requested.
4995: */
4996:
4997: #ifdef MODULE
4998:
4999: SCSI_Host_Template_T driver_template = BUSLOGIC;
5000:
5001: #include "scsi_module.c"
5002:
5003: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.