1 /*
2  * vmscsi-- Miniport driver for the Buslogic BT 958 SCSI Controller
3  *          under Windows 2000/XP/Server 2003
4  *
5  *          Based in parts on the buslogic driver for the same device
6  *          available with the GNU Linux Operating System.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  */
22 
23 //____________________________________________________________________________________
24 //
25 // File description :The driver for BusLogic-BT958 SCSI Host adapter card.
26 // This driver assumes that the host adapter(HA from now on) is a PCI device.
27 // This is an effort to build a driver for this card for the windows XP environment
28 // since the native XP installation doesnt provide this driver.
29 //
30 // The technical reference for this device is at :
31 //
32 // Author: Namita Lal, Sirish Raghuram Calsoft Pvt Ltd
33 // Date:   5th Feb 2003
34 // Status: Driver version 1.2.0.0
35 //         Performance tuned
36 //         Correctness tested for
37 //            1. Installation at OS install time
38 //            2. Installation in an installed OS
39 //            3. Installation by upgrading a previous version
40 //         on all flavours of WinXP and Win Server 2003
41 //         For Win2k however, please refer PR 22812
42 /*
43 Revision History:
44 v1.0.0.4  // Pre final release to VMware in Sep 2001, without WMI
45     |
46     |
47     v
48 v1.0.0.5  // Sep 2001 release to VMware, with WMI
49     |
50     |
51     v
52 v1.0.0.6  // Fix for bug with Nero Burning ROM in XP
53     |     // where SCSI_AUTO_SENSE is turned off at times
54     |
55     |
56     |---------> v1.1.0.0    // Performance optimizations:
57     |           |           // A. WMI disabled, B. Queueing depth increased
58     |           |           // C. Control flow changed (bug)
59     |           |
60     |           v
61     |       v1.1.0.1    // Fix for .NET restart freeze with 1.1.0.0
62     |                   // Breaks on XP
63     |
64     v
65 v1.2.0.0  // A. WMI disabled, B. Queueing depth increased
66     |
67     |
68     |
69     v
70 v1.2.0.1  // Fix PR 40284, affects pure ACPI Win2k systems.
71     |
72     |
73     |
74     v
75 v1.2.0.2  // Fix PR 40284 correctly, disable interrupts in the initialization routine.
76           // CURRENT VERSION
77 */
78 //____________________________________________________________________________________
79 
80 #include "BusLogic958.h"
81 
82 ULONG
83 NTAPI
DriverEntry(IN PVOID DriverObject,IN PVOID Argument2)84 DriverEntry(IN PVOID DriverObject,
85             IN PVOID Argument2
86            )
87 //_________________________________________________________________________
88 // Routine Description:
89 //              Installable driver initialization entry point for system.
90 // Arguments:
91 //              Driver Object
92 // Return Value:
93 //              Status from ScsiPortInitialize()
94 //_________________________________________________________________________
95 {
96     HW_INITIALIZATION_DATA hwInitializationData;
97     ULONG Status;
98     ULONG i;
99     ULONG HwContext;
100 //    static int    cardNo = 0;
101 
102     UCHAR VendorId[4] = { '1', '0', '4', 'b'        };
103     UCHAR DeviceId[4] = { '1', '0', '4', '0'        };
104 
105     DebugPrint((TRACE,"\n BusLogic -  Inside the DriverEntry function \n"));
106 
107     // Zero out structure.
108     for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++)
109     {
110         ((PUCHAR) & hwInitializationData)[i] = 0;
111     }
112 
113     // Set size of hwInitializationData.
114     hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
115 
116     // Set entry points.
117     hwInitializationData.HwInitialize =     BT958HwInitialize;
118     hwInitializationData.HwResetBus =       BT958HwResetBus;
119     hwInitializationData.HwStartIo =        BT958HwStartIO;
120     hwInitializationData.HwInterrupt =      BT958HwInterrupt;
121     hwInitializationData.HwAdapterControl = BT958HwAdapterControl;
122     hwInitializationData.HwFindAdapter =    BT958HwFindAdapter;
123 
124     // Indicate no buffer mapping but will need physical addresses
125     hwInitializationData.NeedPhysicalAddresses = TRUE;
126 
127     // Indicate Auto request sense is supported
128     hwInitializationData.AutoRequestSense = TRUE;
129     hwInitializationData.MultipleRequestPerLu = TRUE;
130 
131 #if TAG_QUEUING
132     hwInitializationData.TaggedQueuing = TRUE;
133 #else
134     hwInitializationData.TaggedQueuing = FALSE;
135 #endif
136 
137     hwInitializationData.AdapterInterfaceType = PCIBus;
138 
139     // Fill in the vendor id and the device id
140     hwInitializationData.VendorId = &VendorId;
141     hwInitializationData.VendorIdLength = 4;
142     hwInitializationData.DeviceId = &DeviceId;
143     hwInitializationData.DeviceIdLength = 4;
144 
145 
146     hwInitializationData.NumberOfAccessRanges = 2;
147 
148 
149     // Specify size of extensions.
150     hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
151 
152     // logical unit extension
153     hwInitializationData.SrbExtensionSize = sizeof(BusLogic_CCB_T);
154 
155     HwContext = 0;
156 
157     DebugPrint((TRACE,"\n BusLogic -  Calling the ScsiPortInitialize Routine\n"));
158 
159     Status = ScsiPortInitialize(DriverObject,
160                                 Argument2,
161                                 &hwInitializationData,
162                                 &HwContext);
163 
164     DebugPrint((TRACE,"\n BusLogic -  Exiting the DriverEntry function \n"));
165     DebugPrint((INFO,"\n BusLogic - Status = %ul \n", Status));
166     return( Status );
167 
168 } // end DriverEntry()
169 
170 
171 ULONG
172 NTAPI
BT958HwFindAdapter(IN PVOID HwDeviceExtension,IN PVOID Context,IN PVOID BusInformation,IN PCHAR ArgumentString,IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,OUT PBOOLEAN Again)173 BT958HwFindAdapter(IN PVOID HwDeviceExtension,
174                    IN PVOID Context,
175                    IN PVOID BusInformation,
176                    IN PCHAR ArgumentString,
177                    IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
178                    OUT PBOOLEAN  Again
179                   )
180 //_________________________________________________________________________________________________
181 // Routine Description:
182 //              This function is called by the OS-specific port driver after the necessary storage
183 //              has been allocated, to gather information about the adapter's configuration.
184 //
185 // Arguments:
186 //              HwDeviceExtension - HBA miniport driver's adapter data storage
187 //              Context - Register base address
188 //              ConfigInfo - Configuration information structure describing HBA
189 //              This structure is defined in PORT.H.
190 //
191 // Return Value:
192 //              HwScsiFindAdapter must return one of the following status values:
193 //              SP_RETURN_FOUND: Indicates a supported HBA was found and that the HBA-relevant
194 //                               configuration information was successfully determined and set in
195 //                               the PORT_CONFIGURATION_INFORMATION structure.
196 //              SP_RETURN_ERROR: Indicates an HBA was found but there was error obtaining the
197 //                               configuration information. If possible, such an error should be
198 //                               logged with ScsiPortLogError.
199 //              SP_RETURN_BAD_CONFIG: Indicates the supplied configuration information was invalid
200 //                                    for the adapter.
201 //              SP_RETURN_NOT_FOUND: Indicates no supported HBA was found for the supplied
202 //                                   configuration information.
203 //________________________________________________________________________________________________
204 {
205     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
206     BusLogic_HostAdapter_T *hcsp = &(deviceExtension->hcs);
207 //    static UCHAR k = 0;
208     PACCESS_RANGE   accessRange;
209 //    PCI_COMMON_CONFIG PCICommonConfig;
210     PUCHAR   pciAddress;
211     char    NumPort = 0;
212 
213     DebugPrint((TRACE,"\n BusLogic -  Inside the Find Adapter Routine\n"));
214 
215     *Again = FALSE;
216 
217     accessRange = &((*(ConfigInfo->AccessRanges))[0]);
218 
219     // Inform SCSIPORT that we are NOT a WMI data provider
220     // Sirish, 10th June 2002
221     ConfigInfo->WmiDataProvider = FALSE;
222     /*Sirish, 10th June 2002 BT958WmiInitialize(deviceExtension);*/
223 
224     // Check for configuration information passed in form the system
225     if ((*ConfigInfo->AccessRanges)[0].RangeLength != 0)
226     {
227         // check if the system supplied bus-relative address is valid and has not been
228         // claimed by another device
229         if ( ScsiPortValidateRange(deviceExtension,
230                                    ConfigInfo->AdapterInterfaceType,
231                                    ConfigInfo->SystemIoBusNumber,
232                                    accessRange->RangeStart,
233                                    accessRange->RangeLength,
234                                    TRUE) )  // TRUE: iniospace
235         {
236             DebugPrint((INFO,"\n BusLogic - Validate Range function succeeded \n"));
237 
238             // Map the Bus-relative range addresses to system-space logical range addresses
239             // so that these mapped logical addresses can be called with SciPortRead/Writexxx
240             // to determine whether the adapter is an HBA that the driver supports
241 
242             pciAddress = (PUCHAR) ScsiPortGetDeviceBase(deviceExtension,
243                                                        ConfigInfo->AdapterInterfaceType,
244                                                        ConfigInfo->SystemIoBusNumber,
245                                                        accessRange->RangeStart,
246                                                        accessRange->RangeLength,
247                                                        TRUE);  // TRUE: iniospace
248 
249             if(pciAddress)
250             {
251                 DebugPrint((INFO,"\n BusLogic -  Get Device Base  function succeeded \n"));
252 
253                 memset(hcsp, 0, sizeof(BusLogic_HostAdapter_T));
254 
255                 // points to structure of type BT958_HA which has device specific information. This needs
256                 // to be either changed or modified with our specific info.
257                 hcsp->IO_Address = pciAddress;
258                 hcsp->IRQ_Channel = (UCHAR)ConfigInfo->BusInterruptLevel;
259                 NumPort++;
260             }
261         }
262     }
263 
264     if (NumPort == 0)
265     {
266         return(SP_RETURN_NOT_FOUND);
267     }
268 
269     //  Hardware found, let's find out hardware configuration
270     //  and fill out ConfigInfo table for WinNT
271     ConfigInfo->NumberOfBuses = 1;
272     ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE;
273 
274 #if SG_SUPPORT
275     ConfigInfo->ScatterGather = TRUE;
276 #else
277     ConfigInfo->ScatterGather = FALSE;
278 #endif
279 
280     ConfigInfo->Master = TRUE;
281     ConfigInfo->NeedPhysicalAddresses = TRUE;
282     ConfigInfo->Dma32BitAddresses = TRUE;
283     ConfigInfo->InterruptMode =  LevelSensitive;
284 
285 #if TAG_QUEUING
286     ConfigInfo->TaggedQueuing = TRUE;
287 #else
288     ConfigInfo->TaggedQueuing = FALSE;
289 #endif
290 
291     // Should we change this to double-word aligned to increase performance
292     ConfigInfo->AlignmentMask = 0x0;
293 
294     if (!Buslogic_InitBT958(deviceExtension,ConfigInfo)) // hardware specific initializations. Find what's for our card
295     {
296        ScsiPortLogError(deviceExtension,
297                          NULL,
298                          0,
299                          0,
300                          0,
301                          SP_INTERNAL_ADAPTER_ERROR,
302                          7 << 8);
303 
304        return(SP_RETURN_ERROR);
305     }
306 
307     if (NumPort != 0)
308         *Again = TRUE;
309 
310     return(SP_RETURN_FOUND);
311 
312 } // end BT958FindAdapter()
313 
314 
315 BOOLEAN
Buslogic_InitBT958(PHW_DEVICE_EXTENSION deviceExtension,PPORT_CONFIGURATION_INFORMATION ConfigInfo)316 Buslogic_InitBT958(PHW_DEVICE_EXTENSION deviceExtension,
317                    PPORT_CONFIGURATION_INFORMATION ConfigInfo)
318 //_________________________________________________________________________
319 // Routine Description:
320 //              This routine is called from the driver's FindAdapter routine
321 //              On invocation this routine probes the host adapter to check
322 //              if its hardware registers are responding correctly, and
323 //              initializes the device and makes it ready for IO
324 // Arguments:
325 //              1. deviceExtension
326 //              2. Port Configuration info
327 // Return Value:
328 //              TRUE : Device initialized properly
329 //              FALSE : Device failed to initialize
330 //_________________________________________________________________________
331 {
332     CHAR ch;
333 
334     BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
335 
336     // Probe the Host Adapter.
337     // If unsuccessful, abort further initialization.
338     if (!BusLogic_ProbeHostAdapter(HostAdapter))
339         return   FALSE;
340 
341     // Hard Reset the Host Adapter.
342     // If unsuccessful, abort further initialization.
343     if (!BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE))
344         return FALSE;
345 
346     /*
347      * PR 40284 -- Disable interrupts until driver initialization is complete.
348      */
349     ch = 0;
350     if (BusLogic_Command(HostAdapter, BusLogic_DisableHostAdapterInterrupt,
351 			 &ch, sizeof(ch), NULL, 0) < 0) {
352         DebugPrint((WARNING, "\n BusLogic - Could not disable interrupts!\n"));
353     } else {
354         DebugPrint((INFO, "\n BusLogic - Disabled interrupts.\n"));
355     }
356 
357     // Check the Host Adapter.
358     // If unsuccessful, abort further initialization.
359     if (!BusLogic_CheckHostAdapter(HostAdapter))
360         return FALSE;
361 
362     // Allocate a Noncached Extension to use for mail boxes.
363     deviceExtension->NoncachedExtension =  ScsiPortGetUncachedExtension(deviceExtension,
364                                                                       ConfigInfo,
365                                                                       sizeof(NONCACHED_EXTENSION));
366 
367     if (deviceExtension->NoncachedExtension == NULL)
368     {
369         // Log error.
370         ScsiPortLogError(deviceExtension,
371                              NULL,
372                              0,
373                              0,
374                              0,
375                              SP_INTERNAL_ADAPTER_ERROR,
376                              7 << 8);
377 
378         // abort further initialization
379         return FALSE;
380     }
381 
382     // Read the Host Adapter Configuration, Configure the Host Adapter,
383     // Acquire the System Resources necessary to use the Host Adapter, then
384     // Create the Initial CCBs, Initialize the Host Adapter, and finally
385     // perform Target Device Inquiry.
386     if (BusLogic_ReadHostAdapterConfiguration(HostAdapter)           &&
387         //BusLogic_ReportHostAdapterConfiguration(HostAdapter)       &&
388         BusLogic_InitializeHostAdapter(deviceExtension, ConfigInfo)  &&
389         BusLogic_TargetDeviceInquiry(HostAdapter))
390     {
391         // Fill in the:
392         // 1.Maximum number of scsi target devices that are supported by our adapter
393         ConfigInfo->MaximumNumberOfTargets = HostAdapter->MaxTargetDevices;
394         // 2. Maximum number of logical units per target the HBA can control.
395         ConfigInfo->MaximumNumberOfLogicalUnits  = HostAdapter->MaxLogicalUnits;
396         ConfigInfo->InitiatorBusId[0] = HostAdapter->SCSI_ID;
397         // Maximum number of breaks between address ranges that a data buffer can
398         // have if the HBA supports scatter/gather. In other words, the number of
399         // scatter/gather lists minus one.
400         ConfigInfo->NumberOfPhysicalBreaks = HostAdapter->DriverScatterGatherLimit;
401     }
402     else
403     {
404         // An error occurred during Host Adapter Configuration Querying, Host
405         // Adapter Configuration, Host Adapter Initialization, or Target Device Inquiry,
406         // so return FALSE
407 
408         return FALSE;
409     }
410     // Initialization completed successfully
411     return TRUE;
412 } // end Buslogic_InitBT958
413 
414 
415 BOOLEAN
BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T * HostAdapter)416 BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
417 //____________________________________________________________________________________
418 // Routine Description: BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
419 //                      The routine reads the status, interrupt and geometry regiter and
420 //                      checks if their contents are valid
421 // Arguments:
422 //              1. Host Adapter structure
423 //
424 // Return Value:
425 //              TRUE: Probe completed successfully
426 //              FALSE: Probe failed
427 //____________________________________________________________________________________
428 {
429   BusLogic_StatusRegister_T StatusRegister;
430   BusLogic_InterruptRegister_T InterruptRegister;
431   BusLogic_GeometryRegister_T GeometryRegister;
432 
433   DebugPrint((TRACE,"\n BusLogic -  Inside ProbeHostaAdapter function \n"));
434   //  Read the Status, Interrupt, and Geometry Registers to test if there are I/O
435   //  ports that respond, and to check the values to determine if they are from a
436   //  BusLogic Host Adapter.  A nonexistent I/O port will return 0xFF, in which
437   //  case there is definitely no BusLogic Host Adapter at this base I/O Address.
438   //  The test here is a subset of that used by the BusLogic Host Adapter BIOS.
439 
440   InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
441   GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
442   StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
443 
444   if (StatusRegister.All == 0 ||
445       StatusRegister.Bits.DiagnosticActive ||
446       StatusRegister.Bits.CommandParameterRegisterBusy ||
447       StatusRegister.Bits.Reserved ||
448       StatusRegister.Bits.CommandInvalid ||
449       InterruptRegister.Bits.Reserved != 0)
450     return FALSE;
451 
452   //  Check the undocumented Geometry Register to test if there is an I/O port
453   //  that responded.  Adaptec Host Adapters do not implement the Geometry
454   //  Register, so this test helps serve to avoid incorrectly recognizing an
455   //  Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
456   //  series does respond to the Geometry Register I/O port, but it will be
457   //  rejected later when the Inquire Extended Setup Information command is
458   //  issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
459   //  BusLogic clone that implements the same interface as earlier BusLogic
460   //  Host Adapters, including the undocumented commands, and is therefore
461   //  supported by this driver.  However, the AMI FastDisk always returns 0x00
462   //  upon reading the Geometry Register, so the extended translation option
463   //  should always be left disabled on the AMI FastDisk.
464 
465   if (GeometryRegister.All == 0xFF) return FALSE;
466   return TRUE;
467 }// end BusLogic_ProbeHostAdapter
468 
469 BOOLEAN
BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T * HostAdapter,BOOLEAN HardReset)470 BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T  *HostAdapter,
471                                   BOOLEAN HardReset)
472 //_________________________________________________________________________
473 // Routine Description: BusLogic_HardwareResetHostAdapter issues a Hardware
474 //                      Reset to the Host Adapter and waits for Host Adapter
475 //                      Diagnostics to complete.  If HardReset is TRUE, a
476 //                      Hard Reset is performed which also initiates a SCSI
477 //                      Bus Reset.  Otherwise, a Soft Reset is performed which
478 //                      only resets the Host Adapter without forcing a SCSI
479 //                      Bus Reset.
480 // Arguments:
481 //              1. Host Adapter structure
482 //              2. Boolean HardReset - True: Do hard reset
483 // Return Value:
484 //              TRUE : Reset completed successfully
485 //              FALSE : Reset failed
486 //_________________________________________________________________________
487 {
488   BusLogic_StatusRegister_T StatusRegister;
489   int TimeoutCounter;
490 
491   //  Issue a Hard Reset or Soft Reset Command to the Host Adapter.  The Host
492   //  Adapter should respond by setting Diagnostic Active in the Status Register.
493   if (HardReset)
494     BusLogic_HardReset(HostAdapter);
495   else
496     BusLogic_SoftReset(HostAdapter);
497 
498   // Wait until Diagnostic Active is set in the Status Register.
499   TimeoutCounter = 100;
500   while (--TimeoutCounter >= 0)
501   {
502       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
503       if (StatusRegister.Bits.DiagnosticActive)
504           break;
505   }
506 
507   // if in spite of waiting for time out period , if it didn't et set, then something is wrong-- so just return.
508   if (TimeoutCounter < 0)
509       return FALSE;
510 
511   //
512   //  Wait 100 microseconds to allow completion of any initial diagnostic
513   //  activity which might leave the contents of the Status Register
514   //  unpredictable.
515   ScsiPortStallExecution(100);
516 
517   //  Wait until Diagnostic Active is reset in the Status Register.
518   TimeoutCounter = 10*10000;
519   while (--TimeoutCounter >= 0)
520   {
521       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
522       if (!StatusRegister.Bits.DiagnosticActive)
523           break;
524       ScsiPortStallExecution(100);
525   }
526 
527   if (TimeoutCounter < 0)
528       return FALSE;
529 
530   //  Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
531   //  or Data In Register Ready bits is set in the Status Register.
532   TimeoutCounter = 10000;
533   while (--TimeoutCounter >= 0)
534   {
535       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
536       if (StatusRegister.Bits.DiagnosticFailure ||
537           StatusRegister.Bits.HostAdapterReady ||
538           StatusRegister.Bits.DataInRegisterReady)
539       {
540         break;
541       }
542       ScsiPortStallExecution(100);
543    }
544 
545   //device didn't respond to reset
546   if (TimeoutCounter < 0)
547       return FALSE;
548 
549   //  If Diagnostic Failure is set or Host Adapter Ready is reset, then an
550   //  error occurred during the Host Adapter diagnostics.  If Data In Register
551   //  Ready is set, then there is an Error Code available.
552   if (StatusRegister.Bits.DiagnosticFailure || !StatusRegister.Bits.HostAdapterReady)
553   {
554       DebugPrint((ERROR, "\n BusLogic - Failure - HOST ADAPTER STATUS REGISTER = %02X\n", StatusRegister.All));
555 
556       if (StatusRegister.Bits.DataInRegisterReady)
557       {
558         DebugPrint((ERROR, "HOST ADAPTER ERROR CODE = %d\n", BusLogic_ReadDataInRegister(HostAdapter)));
559       }
560       return FALSE;
561   }
562 
563   //  Indicate the Host Adapter Hard Reset completed successfully.
564   return TRUE;
565 }// end BusLogic_HardwareResetHostAdapter
566 
567 
568 BOOLEAN
BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T * HostAdapter)569 BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
570 //_________________________________________________________________________
571 // Routine Description: BusLogic_CheckHostAdapter checks to be sure this
572 //                      really is a BusLogic
573 // Arguments:
574 //              1. Host Adapter Structure
575 // Return Value:
576 //              TRUE : Buslogic adapter detected
577 //              FALSE : Card is not a Buslogic adapter
578 //_________________________________________________________________________
579 {
580   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
581   BusLogic_RequestedReplyLength_T RequestedReplyLength;
582   BOOLEAN Result = TRUE;
583 
584   DebugPrint((TRACE, "\n BusLogic -  Inside BusLogic_CheckHostAdapter function \n"));
585 
586   //
587   //  Issue the Inquire Extended Setup Information command.  Only genuine
588   //  BusLogic Host Adapters and TRUE clones support this command.  Adaptec 1542C
589   //  series Host Adapters that respond to the Geometry Register I/O port will
590   //  fail this command.
591   RequestedReplyLength = sizeof(ExtendedSetupInformation);
592   if (BusLogic_Command(HostAdapter,
593                        BusLogic_InquireExtendedSetupInformation,
594                        &RequestedReplyLength,
595                        sizeof(RequestedReplyLength),
596                        &ExtendedSetupInformation,
597                        sizeof(ExtendedSetupInformation))
598       != sizeof(ExtendedSetupInformation))
599   {
600     Result = FALSE;
601   }
602   return Result;
603 }// end BusLogic_CheckHostAdapter
604 
605 int
BusLogic_Command(BusLogic_HostAdapter_T * HostAdapter,BusLogic_OperationCode_T OperationCode,void * ParameterData,int ParameterLength,void * ReplyData,int ReplyLength)606 BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
607                  BusLogic_OperationCode_T OperationCode,
608                  void *ParameterData,
609                  int ParameterLength,
610                  void *ReplyData,
611                  int ReplyLength)
612 //______________________________________________________________________________________________
613 // Routine Description:
614 //                      BusLogic_Command sends the command OperationCode to HostAdapter, optionally
615 //                      providing ParameterLength bytes of ParameterData and receiving at most
616 //                      ReplyLength bytes of ReplyData; any excess reply data is received but
617 //                      discarded.
618 //
619 //                      BusLogic_Command is called exclusively during host adapter detection and
620 //                      initialization, so performance and latency are not critical, and exclusive
621 //                      access to the Host Adapter hardware is assumed.  Once the host adapter and
622 //                      driver are initialized, the only Host Adapter command that is issued is the
623 //                      single byte Execute Mailbox Command operation code, which does not require
624 //                      waiting for the Host Adapter Ready bit to be set in the Status Register.
625 // Arguments:
626 //              1. HostAdapter - Host Adapter structure
627 //              2. OperationCode - Operation code for the command
628 //              3. ParameterData - Buffer containing parameters that needs to be passed as part
629 //                 of the command
630 //              4. ParameterLength - Number of parameters
631 //              5. ReplyData - Buffer where reply data is copied
632 //              6. ReplyLength - The length of the reply data
633 // Return Value:
634 //              On success, this function returns the number of reply bytes read from
635 //              the Host Adapter (including any discarded data); on failure, it returns
636 //              -1 if the command was invalid, or -2 if a timeout occurred.
637 //_________________________________________________________________________________________________
638 {
639   UCHAR *ParameterPointer = (UCHAR *) ParameterData;
640   UCHAR *ReplyPointer = (UCHAR *) ReplyData;
641   BusLogic_StatusRegister_T StatusRegister;
642   BusLogic_InterruptRegister_T InterruptRegister;
643   int ReplyBytes = 0, Result;
644   long TimeoutCounter;
645 
646   //  Clear out the Reply Data if provided.
647   if (ReplyLength > 0)
648     memset(ReplyData, 0, ReplyLength);
649 
650   //  If the IRQ Channel has not yet been acquired, then interrupts must be
651   //  disabled while issuing host adapter commands since a Command Complete
652   //  interrupt could occur if the IRQ Channel was previously enabled by another
653   //  BusLogic Host Adapter or another driver sharing the same IRQ Channel.
654 
655   //  Wait for the Host Adapter Ready bit to be set and the Command/Parameter
656   //  Register Busy bit to be reset in the Status Register.
657   TimeoutCounter = 10000;
658   while (--TimeoutCounter >= 0)
659   {
660       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
661       if ( StatusRegister.Bits.HostAdapterReady &&
662           !StatusRegister.Bits.CommandParameterRegisterBusy)
663       {
664             break;
665       }
666       ScsiPortStallExecution(100);
667   }
668   if (TimeoutCounter < 0)
669   {
670       //BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
671       Result = -2;
672       goto Done;
673   }
674 
675   //  Write the OperationCode to the Command/Parameter Register.
676   HostAdapter->HostAdapterCommandCompleted = FALSE;
677   BusLogic_WriteCommandParameterRegister(HostAdapter, (UCHAR)OperationCode);
678 
679   //Write any additional Parameter Bytes.
680   TimeoutCounter = 10000;
681   while (ParameterLength > 0 && --TimeoutCounter >= 0)
682   {
683     //
684     // Wait 100 microseconds to give the Host Adapter enough time to determine
685     // whether the last value written to the Command/Parameter Register was
686     // valid or not.  If the Command Complete bit is set in the Interrupt
687     // Register, then the Command Invalid bit in the Status Register will be
688     // reset if the Operation Code or Parameter was valid and the command
689     // has completed, or set if the Operation Code or Parameter was invalid.
690     // If the Data In Register Ready bit is set in the Status Register, then
691     // the Operation Code was valid, and data is waiting to be read back
692     // from the Host Adapter.  Otherwise, wait for the Command/Parameter
693     // Register Busy bit in the Status Register to be reset.
694 
695       ScsiPortStallExecution(100);
696       InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
697       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
698       if (InterruptRegister.Bits.CommandComplete)
699           break;
700       if (HostAdapter->HostAdapterCommandCompleted)
701           break;
702       if (StatusRegister.Bits.DataInRegisterReady)
703           break;
704       if (StatusRegister.Bits.CommandParameterRegisterBusy)
705           continue;
706       BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
707       ParameterLength--;
708   }
709   if (TimeoutCounter < 0)
710   {
711       //BusLogic_CommandFailureReason =  "Timeout waiting for Parameter Acceptance";
712       Result = -2;
713       goto Done;
714   }
715 
716   // The Modify I/O Address command does not cause a Command Complete Interrupt.
717   if (OperationCode == BusLogic_ModifyIOAddress)
718   {
719     StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
720     if (StatusRegister.Bits.CommandInvalid)
721     {
722       //BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
723       Result = -1;
724       goto Done;
725     }
726     Result = 0;
727     goto Done;
728   }
729 
730   //  Select an appropriate timeout value for awaiting command completion.
731   switch (OperationCode)
732   {
733     case BusLogic_InquireInstalledDevicesID0to7:
734     case BusLogic_InquireInstalledDevicesID8to15:
735     case BusLogic_InquireTargetDevices:
736       // Approximately 60 seconds.
737       TimeoutCounter = 60*10000;
738       break;
739     default:
740       // Approximately 1 second.
741       TimeoutCounter = 10000;
742       break;
743   }
744 
745   //
746   //  Receive any Reply Bytes, waiting for either the Command Complete bit to
747   //  be set in the Interrupt Register, or for the Interrupt Handler to set the
748   //  Host Adapter Command Completed bit in the Host Adapter structure.
749   while (--TimeoutCounter >= 0)
750   {
751     InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
752     StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
753     if (InterruptRegister.Bits.CommandComplete)
754         break;
755     if (HostAdapter->HostAdapterCommandCompleted)
756         break;
757     if (StatusRegister.Bits.DataInRegisterReady)
758     {
759       if (++ReplyBytes <= ReplyLength)
760       {
761         *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
762       }
763       else
764       {
765           BusLogic_ReadDataInRegister(HostAdapter);
766       }
767     }
768     if (OperationCode == BusLogic_FetchHostAdapterLocalRAM &&
769         StatusRegister.Bits.HostAdapterReady)
770     {
771       break;
772     }
773     ScsiPortStallExecution(100);
774   }
775   if (TimeoutCounter < 0)
776   {
777       //BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
778       Result = -2;
779       goto Done;
780   }
781 
782   //  Clear any pending Command Complete Interrupt.
783   BusLogic_InterruptReset(HostAdapter);
784 
785   //  Process Command Invalid conditions.
786   if (StatusRegister.Bits.CommandInvalid)
787   {
788     //
789     // Some early BusLogic Host Adapters may not recover properly from
790     // a Command Invalid condition, so if this appears to be the case,
791     // a Soft Reset is issued to the Host Adapter.  Potentially invalid
792     // commands are never attempted after Mailbox Initialization is
793     // performed, so there should be no Host Adapter state lost by a
794     // Soft Reset in response to a Command Invalid condition.
795 
796     ScsiPortStallExecution(1000);
797     StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
798     if (StatusRegister.Bits.CommandInvalid             ||
799       StatusRegister.Bits.Reserved                     ||
800       StatusRegister.Bits.DataInRegisterReady          ||
801       StatusRegister.Bits.CommandParameterRegisterBusy ||
802       !StatusRegister.Bits.HostAdapterReady            ||
803       !StatusRegister.Bits.InitializationRequired      ||
804       StatusRegister.Bits.DiagnosticActive             ||
805       StatusRegister.Bits.DiagnosticFailure)
806     {
807         BusLogic_SoftReset(HostAdapter);
808         ScsiPortStallExecution(1000);
809     }
810     //BusLogic_CommandFailureReason = "Command Invalid";
811     Result = -1;
812     goto Done;
813   }
814 
815   // Handle Excess Parameters Supplied conditions.
816   if (ParameterLength > 0)
817   {
818       //BusLogic_CommandFailureReason = "Excess Parameters Supplied";
819       Result = -1;
820       goto Done;
821   }
822 
823   //  Indicate the command completed successfully.
824   Result = ReplyBytes;
825 
826   //  Restore the interrupt status if necessary and return.
827 Done:
828   return Result;
829 }// end BusLogic_Command
830 
831 
832 BOOLEAN
BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T * HostAdapter)833 BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T  *HostAdapter)
834 //___________________________________________________________________________________________
835 // Routine Description:
836 //                  BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
837 //                  from Host Adapter and initializes the Host Adapter structure.
838 // Arguments:
839 //              1. Host adapter structure
840 // Return Value:
841 //              TRUE : Configuration read properly
842 //              FALSE : Encounter failure
843 //___________________________________________________________________________________________
844 {
845   BusLogic_BoardID_T BoardID;
846   BusLogic_Configuration_T Configuration;
847   BusLogic_SetupInformation_T SetupInformation;
848   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
849   BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber;
850   BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit;
851   BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter;
852   BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
853   BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest;
854   BusLogic_AutoSCSIData_T AutoSCSIData;
855   BusLogic_GeometryRegister_T GeometryRegister;
856   BusLogic_RequestedReplyLength_T RequestedReplyLength;
857   UCHAR *TargetPointer, Character;
858   ULONG /*TargetID,*/ i;
859 
860 
861   //  Issue the Inquire Board ID command.
862   if (BusLogic_Command(HostAdapter,
863                        BusLogic_InquireBoardID,
864                        NULL,
865                        0,
866                        &BoardID, sizeof(BoardID))
867       != sizeof(BoardID))
868   {
869         DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE BOARD ID\n"));
870         return FALSE;
871   }
872 
873   //  Issue the Inquire Configuration command.
874   if (BusLogic_Command(HostAdapter,
875                        BusLogic_InquireConfiguration,
876                        NULL,
877                        0,
878                        &Configuration, sizeof(Configuration))
879       != sizeof(Configuration))
880   {
881       DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE CONFIGURATION\n"));
882       return FALSE;
883   }
884 
885   //  Issue the Inquire Setup Information command.
886   RequestedReplyLength = sizeof(SetupInformation);
887   if (BusLogic_Command(HostAdapter,
888                        BusLogic_InquireSetupInformation,
889                        &RequestedReplyLength,
890                        sizeof(RequestedReplyLength),
891                        &SetupInformation,
892                        sizeof(SetupInformation))
893       != sizeof(SetupInformation))
894   {
895      DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SETUP INFORMATION\n"));
896      return FALSE;
897   }
898 
899   //  Issue the Inquire Extended Setup Information command.
900   RequestedReplyLength = sizeof(ExtendedSetupInformation);
901   if (BusLogic_Command(HostAdapter,
902                        BusLogic_InquireExtendedSetupInformation,
903                        &RequestedReplyLength,
904                        sizeof(RequestedReplyLength),
905                        &ExtendedSetupInformation,
906                        sizeof(ExtendedSetupInformation))
907       != sizeof(ExtendedSetupInformation))
908   {
909       DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE EXTENDED SETUP INFORMATION\n"));
910       return FALSE;
911   }
912 
913   //  Issue the Inquire Firmware Version 3rd Digit command.
914   FirmwareVersion3rdDigit = '\0';
915   if (BoardID.FirmwareVersion1stDigit > '0')
916   {
917     if (BusLogic_Command(HostAdapter,
918                          BusLogic_InquireFirmwareVersion3rdDigit,
919                          NULL,
920                          0,
921                          &FirmwareVersion3rdDigit,
922                          sizeof(FirmwareVersion3rdDigit))
923         != sizeof(FirmwareVersion3rdDigit))
924     {
925         DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE FIRMWARE 3RD DIGIT\n"));
926         return FALSE;
927     }
928   }
929 
930   //  Issue the Inquire Host Adapter Model Number command.
931   RequestedReplyLength = sizeof(HostAdapterModelNumber);
932   if (BusLogic_Command(HostAdapter,
933                        BusLogic_InquireHostAdapterModelNumber,
934                        &RequestedReplyLength,
935                        sizeof(RequestedReplyLength),
936                        &HostAdapterModelNumber,
937                        sizeof(HostAdapterModelNumber))
938       != sizeof(HostAdapterModelNumber))
939   {
940       DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE HOST ADAPTER MODEL NUMBER\n"));
941       return FALSE;
942   }
943 
944   //  BusLogic MultiMaster Host Adapters can be identified by their model number
945   //  and the major version number of their firmware as follows:
946   //
947   //  5.xx  BusLogic "W" Series Host Adapters:
948   //          BT-948/958/958D
949   //  Save the Model Name and Host Adapter Name in the Host Adapter structure.
950   TargetPointer = HostAdapter->ModelName;
951   *TargetPointer++ = 'B';
952   *TargetPointer++ = 'T';
953   *TargetPointer++ = '-';
954   for (i = 0; i < sizeof(HostAdapterModelNumber); i++)
955   {
956       Character = HostAdapterModelNumber[i];
957       if (Character == ' ' || Character == '\0') break;
958       *TargetPointer++ = Character;
959   }
960   *TargetPointer++ = '\0';
961 
962   // Save the Firmware Version in the Host Adapter structure.
963   TargetPointer = HostAdapter->FirmwareVersion;
964   *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
965   *TargetPointer++ = '.';
966   *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
967   if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
968     *TargetPointer++ = FirmwareVersion3rdDigit;
969   *TargetPointer = '\0';
970 
971   // Issue the Inquire Firmware Version Letter command.
972   if (strcmp((char*)HostAdapter->FirmwareVersion, "3.3") >= 0)
973   {
974       if (BusLogic_Command(HostAdapter,
975                            BusLogic_InquireFirmwareVersionLetter,
976                            NULL,
977                            0,
978                            &FirmwareVersionLetter,
979                            sizeof(FirmwareVersionLetter))
980           != sizeof(FirmwareVersionLetter))
981       {
982           DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE FIRMWARE VERSION LETTER\n"));
983           return FALSE;
984       }
985       if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
986       {
987         *TargetPointer++ = FirmwareVersionLetter;
988       }
989       *TargetPointer = '\0';
990   }
991 
992 
993   //  Save the Host Adapter SCSI ID in the Host Adapter structure.
994   HostAdapter->SCSI_ID = Configuration.HostAdapterID;
995 
996   //  Determine the Bus Type and save it in the Host Adapter structure, determine
997   //  and save the IRQ Channel if necessary, and determine and save the DMA
998   //  Channel for ISA Host Adapters.
999   HostAdapter->HostAdapterBusType =  BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
1000 
1001   GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
1002 
1003   //  Determine whether Extended Translation is enabled and save it in
1004   //  the Host Adapter structure.
1005   //  HostAdapter->ExtendedTranslationEnabled =  GeometryRegister.Bits.ExtendedTranslationEnabled;
1006   HostAdapter->ExtendedTranslationEnabled =  GeometryRegister.All;
1007 
1008 
1009   //  Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
1010   //  SCSI flag, Differential SCSI flag, SCAM Supported flag, and
1011   //  Ultra SCSI flag in the Host Adapter structure.
1012   HostAdapter->HostAdapterScatterGatherLimit =  ExtendedSetupInformation.ScatterGatherLimit;
1013 
1014   HostAdapter->DriverScatterGatherLimit =   HostAdapter->HostAdapterScatterGatherLimit;
1015 
1016   if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
1017   {
1018     HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
1019   }
1020   if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
1021   {
1022     HostAdapter->LevelSensitiveInterrupt = TRUE;
1023   }
1024 
1025   HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
1026 
1027   HostAdapter->HostDifferentialSCSI =  ExtendedSetupInformation.HostDifferentialSCSI;
1028 
1029   HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
1030 
1031   HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
1032 
1033 
1034   //  Determine whether Extended LUN Format CCBs are supported and save the
1035   //  information in the Host Adapter structure.
1036   if (HostAdapter->FirmwareVersion[0] == '5' ||
1037       (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
1038   {
1039     HostAdapter->ExtendedLUNSupport = TRUE;
1040   }
1041   // Issue the Inquire PCI Host Adapter Information command to read the
1042   // Termination Information from "W" series MultiMaster Host Adapters.
1043   if (HostAdapter->FirmwareVersion[0] == '5')
1044   {
1045       if (BusLogic_Command(HostAdapter,
1046                            BusLogic_InquirePCIHostAdapterInformation,
1047                            NULL,
1048                            0,
1049                            &PCIHostAdapterInformation,
1050                            sizeof(PCIHostAdapterInformation))
1051           != sizeof(PCIHostAdapterInformation))
1052       {
1053           DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE PCI HOST ADAPTER INFORMATION\n"));
1054           return FALSE;
1055       }
1056 
1057        // Save the Termination Information in the Host Adapter structure.
1058       if (PCIHostAdapterInformation.GenericInfoValid)
1059       {
1060         HostAdapter->TerminationInfoValid = TRUE;
1061         HostAdapter->LowByteTerminated =  PCIHostAdapterInformation.LowByteTerminated;
1062         HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated;
1063       }
1064   }
1065 
1066   //  Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
1067   //  from "W" and "C" series MultiMaster Host Adapters.
1068   if (HostAdapter->FirmwareVersion[0] >= '4')
1069   {
1070       FetchHostAdapterLocalRAMRequest.ByteOffset =  BusLogic_AutoSCSI_BaseOffset;
1071       FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
1072       if (BusLogic_Command(HostAdapter,
1073                            BusLogic_FetchHostAdapterLocalRAM,
1074                            &FetchHostAdapterLocalRAMRequest,
1075                            sizeof(FetchHostAdapterLocalRAMRequest),
1076                            &AutoSCSIData,
1077                            sizeof(AutoSCSIData))
1078           != sizeof(AutoSCSIData))
1079       {
1080           DebugPrint((ERROR, "\n BusLogic - Failure: FETCH HOST ADAPTER LOCAL RAM\n"));
1081           return FALSE;
1082       }
1083       // Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
1084       // Information in the Host Adapter structure.
1085       HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
1086       HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
1087 
1088       // Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
1089       // Disconnect Permitted, Ultra Permitted, and SCAM Information in the
1090       // Host Adapter structure.
1091       HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
1092       HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
1093       HostAdapter->SynchronousPermitted =   AutoSCSIData.SynchronousPermitted;
1094       HostAdapter->DisconnectPermitted =    AutoSCSIData.DisconnectPermitted;
1095       if (HostAdapter->HostUltraSCSI)
1096       {
1097         HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
1098       }
1099       if (HostAdapter->HostSupportsSCAM)
1100       {
1101           HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
1102           HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
1103       }
1104     }
1105 
1106     // Determine the maximum number of Target IDs and Logical Units supported by
1107     // this driver for Wide and Narrow Host Adapters.
1108     HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
1109     HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
1110 
1111     // Select appropriate values for the Mailbox Count,
1112     // Initial CCBs, and Incremental CCBs variables based on whether or not Strict
1113     // Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
1114     // then there is no performance degradation in using the maximum possible
1115     // number of Outgoing and Incoming Mailboxes and allowing the Tagged and
1116     // Untagged Queue Depths to determine the actual utilization.  If Strict Round
1117     // Robin Mode is not supported, then the Host Adapter must scan all the
1118     // Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
1119     // cause a substantial performance penalty.  The host adapters actually have
1120     // room to store the following number of CCBs internally; that is, they can
1121     // internally queue and manage this many active commands on the SCSI bus
1122     // simultaneously.  Performance measurements demonstrate that the Driver Queue
1123     // Depth should be set to the Mailbox Count, rather than the Host Adapter
1124     // Queue Depth (internal CCB capacity), as it is more efficient to have the
1125     // queued commands waiting in Outgoing Mailboxes if necessary than to block
1126     // the process in the higher levels of the SCSI Subsystem.
1127     //
1128     // 192    BT-948/958/958D
1129     if (HostAdapter->FirmwareVersion[0] == '5')
1130     {
1131         HostAdapter->HostAdapterQueueDepth = 192;
1132     }
1133 
1134     if (strcmp((char*)HostAdapter->FirmwareVersion, "3.31") >= 0)
1135     {
1136       HostAdapter->StrictRoundRobinModeSupport = TRUE;
1137       HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
1138     }
1139 
1140     //
1141     // Tagged Queuing support is available and operates properly on all "W" series
1142     // MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
1143     // firmware version 4.22 and above, and on "S" series MultiMaster Host
1144     // Adapters with firmware version 3.35 and above.
1145     HostAdapter->TaggedQueuingPermitted = 0xFFFF;
1146 
1147     //
1148     // Determine the Host Adapter BIOS Address if the BIOS is enabled and
1149     ///save it in the Host Adapter structure.  The BIOS is disabled if the
1150     // BIOS_Address is 0.
1151     HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
1152 
1153     //
1154     //Initialize parameters for MultiMaster Host Adapters.
1155 
1156     //
1157     // Initialize the Host Adapter Full Model Name from the Model Name.
1158     strcpy((char*)HostAdapter->FullModelName, "BusLogic ");
1159     strcat((char*)HostAdapter->FullModelName, (char*)HostAdapter->ModelName);
1160 
1161     // Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
1162     // Therefore, mask the Tagged Queuing Permitted Default bits with the
1163     // Disconnect/Reconnect Permitted bits.
1164     HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
1165 
1166     // Select an appropriate value for Bus Settle Time either from a BusLogic
1167     // Driver Options specification, or from BusLogic_DefaultBusSettleTime.
1168     HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
1169 
1170     // Indicate reading the Host Adapter Configuration completed successfully.
1171     return TRUE;
1172 }// end BusLogic_ReadHostAdapterConfiguration
1173 
1174 BOOLEAN
BusLogic_InitializeHostAdapter(PHW_DEVICE_EXTENSION deviceExtension,PPORT_CONFIGURATION_INFORMATION ConfigInfo)1175 BusLogic_InitializeHostAdapter(PHW_DEVICE_EXTENSION deviceExtension,
1176                                PPORT_CONFIGURATION_INFORMATION ConfigInfo)
1177 //_____________________________________________________________________________________________
1178 // Routine Description:
1179 //                  BusLogic_InitializeHostAdapter initializes Host Adapter.  This is the only
1180 //                  function called during SCSI Host Adapter detection which modifies the state
1181 //                  of the Host Adapter from its initial power on or hard reset state.
1182 // Arguments:
1183 //              1. device extension
1184 //              2. port config information
1185 // Return Value:
1186 //              TRUE : Host Adapter initialization completed successfully
1187 //              FALSE : Initialization failed
1188 //______________________________________________________________________________________________
1189 {
1190   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
1191   BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest;
1192   UCHAR RoundRobinModeRequest;
1193   UCHAR SetCCBFormatRequest;
1194   int TargetID, LunID;
1195 
1196   // Used when we get the Physical address of the mail boxes
1197   ULONG length;
1198 
1199   // Initialize the pointers to the first and last CCBs that are queued for
1200   // completion processing.
1201   HostAdapter->FirstCompletedCCB = NULL;
1202   HostAdapter->LastCompletedCCB = NULL;
1203 
1204   //  Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
1205   //  Command Successful Flag, Active Commands, and Commands Since Reset
1206   //  for each Target Device.
1207   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1208   {
1209       HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
1210       HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE;
1211       HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = FALSE;
1212 
1213       HostAdapter->ActiveCommandsPerTarget[TargetID] = 0;
1214       for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++)
1215         HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0;
1216 
1217       HostAdapter->CommandsSinceReset[TargetID] = 0;
1218   }
1219 
1220   // Convert virtual to physical mailbox address.
1221   deviceExtension->NoncachedExtension->MailboxPA =   ScsiPortConvertPhysicalAddressToUlong(
1222                                                                         ScsiPortGetPhysicalAddress(deviceExtension,
1223                                                                                                    NULL,
1224                                                                                                    deviceExtension->NoncachedExtension->MailboxOut,
1225                                                                                                    &length));
1226 
1227   HostAdapter->FirstOutgoingMailbox = (BusLogic_OutgoingMailbox_T *) deviceExtension->NoncachedExtension->MailboxOut;
1228   HostAdapter->LastOutgoingMailbox =  HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
1229   HostAdapter->NextOutgoingMailbox =  HostAdapter->FirstOutgoingMailbox;
1230 
1231   HostAdapter->FirstIncomingMailbox = (BusLogic_IncomingMailbox_T *) deviceExtension->NoncachedExtension->MailboxIn;
1232   HostAdapter->LastIncomingMailbox =  HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
1233   HostAdapter->NextIncomingMailbox =  HostAdapter->FirstIncomingMailbox;
1234 
1235   //  Initialize the Outgoing and Incoming Mailbox structures.
1236   memset(HostAdapter->FirstOutgoingMailbox,
1237          0,
1238          HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T));
1239   memset(HostAdapter->FirstIncomingMailbox,
1240          0,
1241          HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T));
1242 
1243 
1244   ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
1245   ExtendedMailboxRequest.BaseMailboxAddress = deviceExtension->NoncachedExtension->MailboxPA ;
1246 
1247   if (BusLogic_Command(HostAdapter,
1248                        BusLogic_InitializeExtendedMailbox,
1249                        &ExtendedMailboxRequest,
1250                        sizeof(ExtendedMailboxRequest),
1251                        NULL, 0)
1252        < 0)
1253   {
1254       DebugPrint((ERROR, "\n BusLogic - Failure: MAILBOX INITIALIZATION\n"));
1255       return FALSE;
1256   }
1257 
1258   //  Enable Strict Round Robin Mode if supported by the Host Adapter.  In
1259   //  Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
1260   //  Mailbox for each new command, rather than scanning through all the
1261   //  Outgoing Mailboxes to find any that have new commands in them.  Strict
1262   //  Round Robin Mode is significantly more efficient.
1263   if (HostAdapter->StrictRoundRobinModeSupport)
1264   {
1265         RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
1266         if (BusLogic_Command(HostAdapter,
1267                              BusLogic_EnableStrictRoundRobinMode,
1268                              &RoundRobinModeRequest,
1269                              sizeof(RoundRobinModeRequest),
1270                              NULL,
1271                              0)
1272             < 0)
1273         {
1274             DebugPrint((ERROR, "\n BusLogic - Failure: ENABLE STRICT ROUND ROBIN MODE\n"));
1275             return FALSE;
1276         }
1277    }
1278 
1279   //  For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
1280   //  Format command to allow 32 Logical Units per Target Device.
1281 
1282   if (HostAdapter->ExtendedLUNSupport)
1283   {
1284       SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
1285       if (BusLogic_Command(HostAdapter,
1286                            BusLogic_SetCCBFormat,
1287                            &SetCCBFormatRequest,
1288                            sizeof(SetCCBFormatRequest),
1289                            NULL,
1290                            0)
1291           < 0)
1292       {
1293           DebugPrint((ERROR, "\n BusLogic - Failure: SET CCB FORMAT\n"));
1294           return FALSE;
1295       }
1296     }
1297 
1298   //  Announce Successful Initialization.
1299   if (!HostAdapter->HostAdapterInitialized)
1300   {
1301       DebugPrint((INFO, "\n BusLogic - %s Initialized Successfully\n",
1302                   HostAdapter, HostAdapter->FullModelName));
1303   }
1304   else
1305   {
1306       DebugPrint((WARNING, "\n BusLogic - %s not initialized Successfully\n",
1307                   HostAdapter, HostAdapter->FullModelName));
1308   }
1309   HostAdapter->HostAdapterInitialized = TRUE;
1310   //  Indicate the Host Adapter Initialization completed successfully.
1311   return TRUE;
1312 }// end BusLogic_InitializeHostAdapter
1313 
1314 
1315 BOOLEAN
BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T * HostAdapter)1316 BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *HostAdapter)
1317 //_________________________________________________________________________________________
1318 // Routine Description:
1319 //                  BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible
1320 //                  through Host Adapter.
1321 // Arguments:
1322 //              1. Host Adapter structure
1323 //              2.
1324 // Return Value:
1325 //              TRUE : Inquiry successful
1326 //              FALSE : Inquiry failed
1327 //_________________________________________________________________________
1328 {
1329   BusLogic_InstalledDevices_T InstalledDevices;
1330 //  BusLogic_InstalledDevices8_T InstalledDevicesID0to7;
1331   BusLogic_SetupInformation_T SetupInformation;
1332   BusLogic_SynchronousPeriod_T SynchronousPeriod;
1333   BusLogic_RequestedReplyLength_T RequestedReplyLength;
1334   int TargetID;
1335 
1336   //  Wait a few seconds between the Host Adapter Hard Reset which initiates
1337   //  a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
1338   //  confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
1339   ScsiPortStallExecution(HostAdapter->BusSettleTime);
1340 
1341   //
1342   //  Issue the Inquire Target Devices command for host adapters with firmware
1343   //  version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
1344   //  for older host adapters.  This is necessary to force Synchronous Transfer
1345   //  Negotiation so that the Inquire Setup Information and Inquire Synchronous
1346   //  Period commands will return valid data.  The Inquire Target Devices command
1347   //  is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
1348   //  Logical Unit 0 of each Target Device.
1349   if (strcmp((char*)HostAdapter->FirmwareVersion, "4.25") >= 0)
1350   {
1351       if (BusLogic_Command(HostAdapter,
1352                            BusLogic_InquireTargetDevices,
1353                            NULL,
1354                            0,
1355                            &InstalledDevices,
1356                            sizeof(InstalledDevices))
1357             != sizeof(InstalledDevices))
1358       {
1359           DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE TARGET DEVICES\n"));
1360           return FALSE;
1361       }
1362       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1363       {
1364             HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? TRUE : FALSE);
1365       }
1366   }
1367 
1368   //  Issue the Inquire Setup Information command.
1369   RequestedReplyLength = sizeof(SetupInformation);
1370   if (BusLogic_Command(HostAdapter,
1371                        BusLogic_InquireSetupInformation,
1372                        &RequestedReplyLength,
1373                        sizeof(RequestedReplyLength),
1374                &SetupInformation, sizeof(SetupInformation))
1375       != sizeof(SetupInformation))
1376   {
1377       DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SETUP INFORMATION\n"));
1378       return FALSE;
1379   }
1380 
1381   for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1382   {
1383       HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8
1384                                                   ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset
1385                                                   : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset);
1386   }
1387   if (strcmp((char*)HostAdapter->FirmwareVersion, "5.06L") >= 0)
1388   {
1389     for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1390     {
1391       HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8
1392                                                                 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
1393                                                                     ? TRUE : FALSE)
1394                                                                 : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8))
1395                                                                     ? TRUE : FALSE));
1396     }
1397   }
1398 
1399 
1400   //  Issue the Inquire Synchronous Period command.
1401   if (HostAdapter->FirmwareVersion[0] >= '3')
1402   {
1403       RequestedReplyLength = sizeof(SynchronousPeriod);
1404       if (BusLogic_Command(HostAdapter,
1405                            BusLogic_InquireSynchronousPeriod,
1406                            &RequestedReplyLength,
1407                            sizeof(RequestedReplyLength),
1408                            &SynchronousPeriod,
1409                            sizeof(SynchronousPeriod))
1410         != sizeof(SynchronousPeriod))
1411       {
1412           DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SYNCHRONOUS PERIOD\n"));
1413           return FALSE;
1414       }
1415       for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
1416       {
1417         HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
1418       }
1419   }
1420 
1421   //  Indicate the Target Device Inquiry completed successfully.
1422   return TRUE;
1423 }// end BusLogic_TargetDeviceInquiry
1424 
BusLogic_InitializeCCB(PBuslogic_CCB_T CCB)1425 VOID BusLogic_InitializeCCB( PBuslogic_CCB_T CCB)
1426 {
1427   CCB->Opcode = BusLogic_InitiatorCCB;
1428   CCB->DataDirection = 0;
1429   CCB->TagEnable = 0;
1430   CCB->QueueTag = 0 ;
1431   CCB->CDB_Length = 0;
1432   CCB->SenseDataLength = 0;
1433   CCB->DataLength = 0;
1434   CCB->DataPointer = 0;
1435   CCB->HostAdapterStatus = 0;
1436   CCB->TargetDeviceStatus = 0;
1437   CCB->TargetID = 0;
1438   CCB->LogicalUnit = 0;
1439   CCB->LegacyTagEnable = 0;
1440   CCB->LegacyQueueTag = 0;
1441 
1442   CCB->SenseDataPointer = 0;
1443 
1444   // BusLogic Driver Defined Portion
1445   CCB->Status = 0;
1446   CCB->SerialNumber = 0;
1447   CCB->Next = NULL;
1448   CCB->HostAdapter = NULL;
1449 
1450   CCB->CompletionCode = 0;
1451   // Pointer to the CCB
1452   CCB->SrbAddress = NULL;
1453   CCB->AbortSrb = NULL;
1454 }
1455 
1456 BOOLEAN
1457 NTAPI
BT958HwStartIO(IN PVOID HwDeviceExtension,IN PSCSI_REQUEST_BLOCK Srb)1458 BT958HwStartIO(IN PVOID HwDeviceExtension,
1459                IN PSCSI_REQUEST_BLOCK Srb
1460               )
1461 //__________________________________________________________________________________
1462 // Routine Description:
1463 //                    As soon as it receives the initial request for a
1464 //                    target peripheral, the OS-specific port driver calls
1465 //                    the HwScsiStartIo routine with an input SRB. After
1466 //                    this call, the HBA miniport driver owns the request
1467 //                     and is expected to complete it.
1468 // Arguments:
1469 //           1. DeviceExtension: Points to the miniport driver's per-HBA storage area.
1470 //           2. Srb: Points to the SCSI request block to be started.
1471 // Return Value:
1472 //              TRUE : HwScsiStartIo returns TRUE to acknowledge receipt of the SRB.
1473 //__________________________________________________________________________________
1474 {
1475     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1476 //    PNONCACHED_EXTENSION noncachedExtension =   deviceExtension->NoncachedExtension;
1477     BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
1478 //    BusLogic_OutgoingMailbox_T mailboxOut;
1479     PSCSI_REQUEST_BLOCK AbortSRB;
1480 
1481     PBuslogic_CCB_T ccb;
1482     BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId];
1483 
1484 
1485     DebugPrint((TRACE, "\n BusLogic - Inside Start IO routine\n"));
1486 
1487     // Make sure that this request isn't too long for the adapter.  If so
1488     // bounce it back as an invalid request
1489     if (BusLogic_CDB_MaxLength < Srb->CdbLength)
1490     {
1491 
1492         DebugPrint((WARNING, "\n BusLogic - Srb->CdbLength [%d] > MaxCdbLength [%d]."
1493                     " Invalid request\n", Srb->CdbLength, BusLogic_CDB_MaxLength));
1494 
1495         Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1496         ScsiPortNotification(RequestComplete,deviceExtension,Srb);
1497         ScsiPortNotification(NextRequest,deviceExtension,NULL);
1498         return TRUE;
1499     }
1500 
1501     switch (Srb->Function)
1502     {
1503         /*
1504         Sirish, 10th June 2002
1505         // Check if command is a WMI request.
1506         case SRB_FUNCTION_WMI:
1507             // Process the WMI request and return.
1508             return BT958WmiSrb(HwDeviceExtension, (PSCSI_WMI_REQUEST_BLOCK) Srb);
1509         */
1510 
1511         case SRB_FUNCTION_EXECUTE_SCSI:
1512 
1513             // get the ccb structure from the extension
1514             ccb = Srb->SrbExtension;
1515             BusLogic_InitializeCCB(ccb);
1516 
1517             // Save SRB back pointer in CCB.
1518             ccb->SrbAddress = Srb;
1519 
1520             // Build CCB. - Have some way of knowing that a srb has already been
1521             // completed and you just need to return from here
1522             BusLogic_QueueCommand(HwDeviceExtension ,Srb,   ccb);
1523 
1524             // Place the CCB in an Outgoing Mailbox.  The higher levels of the SCSI
1525             // Subsystem should not attempt to queue more commands than can be placed
1526             // in Outgoing Mailboxes, so there should always be one free.  In the
1527             // unlikely event that there are none available, wait 1 second and try
1528             // again.  If that fails, the Host Adapter is probably hung so signal an
1529             // error as a Host Adapter Hard Reset should be initiated soon.
1530 
1531             if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb))
1532             {
1533                 DebugPrint((ERROR, "\n BusLogic - Unable to write Outgoing Mailbox - "
1534                             "Pausing for 1 second\n"));
1535                 ScsiPortStallExecution(1000);
1536                 if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb))
1537                 {
1538                       DebugPrint((ERROR, "\n BusLogic - Still unable to write Outgoing"
1539                                   "Mailbox - Host Adapter Dead?\n"));
1540 
1541                       Srb->SrbStatus = SRB_STATUS_ERROR;
1542                       ScsiPortNotification(RequestComplete,deviceExtension,Srb);
1543                       ScsiPortNotification(NextRequest,deviceExtension,NULL);
1544 
1545                 }
1546             }
1547             else
1548             {
1549                 /*
1550                  * Reverted to pre 1.1.0.0 control flow
1551                  * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts
1552                  * And the fix for that in 1.1.0.1 causes BSODs in XP
1553                  * Side note: Ben: the Buslogic emulation never exports more than 1 lun
1554                  */
1555                 if (TargetFlags->TaggedQueuingActive
1556                     && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS)  {
1557                     ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
1558                 }
1559                 else    {
1560                     ScsiPortNotification(NextRequest,deviceExtension,NULL);
1561                 }
1562             }
1563             return TRUE;
1564 
1565         case SRB_FUNCTION_ABORT_COMMAND:
1566 
1567             // Get CCB to abort.
1568             ccb = Srb->NextSrb->SrbExtension;
1569 
1570             // Set abort SRB for completion.
1571             ccb->AbortSrb = Srb;
1572 
1573             AbortSRB = ScsiPortGetSrb(HwDeviceExtension,
1574                                       Srb->PathId,
1575                                       Srb->TargetId,
1576                                       Srb->Lun,
1577                                       Srb->QueueTag);
1578 
1579             if ((AbortSRB != Srb->NextSrb) || (AbortSRB->SrbStatus != SRB_STATUS_PENDING))
1580             {
1581                 Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
1582                 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
1583                 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
1584                 return TRUE;
1585             }
1586 
1587             // write the abort information into a mailbox
1588             if (BusLogic_WriteOutgoingMailbox( deviceExtension, BusLogic_MailboxAbortCommand, ccb))
1589             {
1590               DebugPrint((WARNING, "\n BusLogic - Aborting CCB #%ld to Target %d\n",
1591                           ccb->SerialNumber, Srb->TargetId));
1592               // Adapter ready for next request.
1593 
1594                 /*
1595                  * Reverted to pre 1.1.0.0 control flow
1596                  * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts
1597                  * And the fix for that in 1.1.0.1 causes BSODs in XP
1598                  * Side note: Ben: the Buslogic emulation never exports more than 1 lun
1599                  */
1600                 if (TargetFlags->TaggedQueuingActive
1601                     && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS)  {
1602                     ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
1603                 }
1604                 else    {
1605                     ScsiPortNotification(NextRequest,deviceExtension,NULL);
1606                 }
1607             }
1608             else
1609             {
1610               DebugPrint((WARNING, "\n BusLogic - Unable to Abort CCB #%ld to Target %d"
1611                           " - No Outgoing Mailboxes\n", ccb->SerialNumber,
1612                           Srb->TargetId));
1613               Srb->SrbStatus = SRB_STATUS_ERROR;
1614               ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
1615               ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
1616             }
1617             return TRUE;
1618 
1619 
1620         case SRB_FUNCTION_RESET_BUS:
1621 
1622             // Reset SCSI bus.
1623             DebugPrint((INFO, "\n BusLogic - SRB_FUNCTION_RESET_BUS, srb=%x \n",Srb));
1624             BT958HwResetBus(HwDeviceExtension, Srb->PathId);
1625 
1626             Srb->SrbStatus = SRB_STATUS_SUCCESS;
1627             ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
1628             ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
1629             return TRUE;
1630 
1631 
1632         case SRB_FUNCTION_RESET_DEVICE:
1633 
1634             ccb = Srb->SrbExtension;
1635             BusLogic_InitializeCCB(ccb);
1636 
1637             // Save SRB back pointer in CCB.
1638             ccb->SrbAddress = Srb;
1639 
1640             if(!BusLogic_SendBusDeviceReset(HostAdapter, Srb))
1641             {
1642                 BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED);
1643                 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1644                 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
1645                 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
1646                 return TRUE;
1647             }
1648 
1649             /*
1650              * Reverted to pre 1.1.0.0 control flow
1651              * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts
1652              * And the fix for that in 1.1.0.1 causes BSODs in XP
1653              * Side note: Ben: the Buslogic emulation never exports more than 1 lun
1654              */
1655             if (TargetFlags->TaggedQueuingActive
1656                 && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS)  {
1657                 ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
1658             }
1659             else    {
1660                 ScsiPortNotification(NextRequest,deviceExtension,NULL);
1661             }
1662             return TRUE;
1663 
1664         default:
1665 
1666             // Set error, complete request and signal ready for next request.
1667             Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1668             ScsiPortNotification(RequestComplete,deviceExtension,Srb);
1669             ScsiPortNotification(NextRequest,deviceExtension,NULL);
1670 
1671             return TRUE;
1672 
1673     } // end switch
1674 
1675 }// end BusLogic_TargetDeviceInquiry
1676 
1677 
1678 BOOLEAN
BusLogic_WriteOutgoingMailbox(PHW_DEVICE_EXTENSION deviceExtension,BusLogic_ActionCode_T ActionCode,BusLogic_CCB_T * CCB)1679 BusLogic_WriteOutgoingMailbox(PHW_DEVICE_EXTENSION deviceExtension ,
1680                               BusLogic_ActionCode_T ActionCode,
1681                               BusLogic_CCB_T *CCB)
1682 //______________________________________________________________________________________________
1683 // Routine Description:
1684 //                     BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
1685 //                     Mailbox for execution by Host Adapter.  The Host Adapter's Lock should
1686 //                     already have been acquired by the caller.
1687 
1688 // Arguments:
1689 //              1. deviceExtension: device extension
1690 //              2. ActionCode : action code for the mailbox which can be
1691 //                  BusLogic_OutgoingMailboxFree =      0x00,
1692 //                  BusLogic_MailboxStartCommand =      0x01,
1693 //                  BusLogic_MailboxAbortCommand =      0x02
1694 //              3. CCB :The CCB that has to be written into the mailbox
1695 // Return Value:
1696 //              TRUE : write to the mailbox was successful
1697 //              FALSE : write failed
1698 //______________________________________________________________________________________________
1699 {
1700   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
1701   BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
1702   ULONG length;
1703 
1704   NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
1705 
1706   if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
1707   {
1708       CCB->Status = BusLogic_CCB_Active;
1709 
1710       // The CCB field must be written before the Action Code field since
1711       // the Host Adapter is operating asynchronously and the locking code
1712       // does not protect against simultaneous access by the Host Adapter.
1713 
1714       // Get CCB physical address.
1715       NextOutgoingMailbox->CCB = ScsiPortConvertPhysicalAddressToUlong( ScsiPortGetPhysicalAddress(deviceExtension,
1716                                                                                     NULL,
1717                                                                                     CCB,
1718                                                                                     &length));
1719 
1720       NextOutgoingMailbox->ActionCode = (UCHAR)ActionCode;
1721 
1722       BusLogic_StartMailboxCommand(HostAdapter);
1723 
1724       if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
1725       {
1726         NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
1727       }
1728 
1729       HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
1730       if (ActionCode == BusLogic_MailboxStartCommand)
1731       {
1732         HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]++;
1733         // check this Namita
1734         HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]++;
1735         if (CCB->Opcode != BusLogic_BusDeviceReset)
1736         {
1737           HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
1738         }
1739       }
1740       return TRUE;
1741   }
1742   return FALSE;
1743 }// end BusLogic_WriteOutgoingMailbox
1744 
1745 
1746 int
BusLogic_QueueCommand(IN PVOID HwDeviceExtension,IN PSCSI_REQUEST_BLOCK Srb,PBuslogic_CCB_T CCB)1747 BusLogic_QueueCommand(IN PVOID HwDeviceExtension ,
1748                       IN PSCSI_REQUEST_BLOCK Srb,
1749                       PBuslogic_CCB_T CCB)
1750 //_________________________________________________________________________
1751 // Routine Description:
1752 //                      BusLogic_QueueCommand creates a CCB for Command
1753 // Arguments:
1754 //              1. HwDeviceExtension: device extension
1755 //              2. Srb: Pointe to the SRB
1756 //              3. CCB: POinter to the buffer containing the space for CCB
1757 // Return Value:
1758 //              Function returns 0 if successful
1759 //_________________________________________________________________________
1760 {
1761   PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1762   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
1763   BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId];
1764   BusLogic_TargetStatistics_T *TargetStatistics = HostAdapter->TargetStatistics;
1765 
1766   ULONG length;
1767 
1768 //  UCHAR *Cdb = Srb->Cdb;
1769 //  PCDB RealCdb ;
1770   UCHAR CDB_Length = Srb->CdbLength;
1771   UCHAR TargetID = Srb->TargetId;
1772   UCHAR LogicalUnit = Srb->Lun;
1773 //  void *BufferPointer = Srb->DataBuffer;
1774   int BufferLength = Srb->DataTransferLength;
1775 
1776   if (Srb->DataTransferLength > 0)
1777   {
1778     CCB->DataLength = Srb->DataTransferLength;
1779 
1780   // Initialize the fields in the BusLogic Command Control Block (CCB).
1781 #if SG_SUPPORT
1782     {
1783         ULONG xferLength, remainLength;
1784         PVOID virtualAddress;
1785         UCHAR i = 0;
1786 
1787         virtualAddress =  Srb->DataBuffer;
1788         xferLength = Srb->DataTransferLength;
1789         remainLength = xferLength;
1790         /* Build scatter gather list  */
1791         do
1792         {
1793             CCB->ScatterGatherList[i].SegmentDataPointer =  (ULONG)ScsiPortConvertPhysicalAddressToUlong(
1794                                                                         ScsiPortGetPhysicalAddress(HwDeviceExtension,
1795                                                                                                    Srb,
1796                                                                                                    virtualAddress,
1797                                                                                                    &length));
1798             if ( length > remainLength )
1799                 length = remainLength;
1800             CCB->ScatterGatherList[i].SegmentByteCount = length;
1801 
1802             virtualAddress = (PUCHAR) virtualAddress + length;
1803             if (length >= remainLength)
1804                 remainLength = 0;
1805             else
1806                 remainLength -= length;
1807             i++;
1808         } while ( remainLength > 0);
1809 
1810         // For data transfers that have less than one scatter gather element, convert
1811         // CCB to one transfer without using SG element. This will clear up the data
1812         // overrun/underrun problem with small transfers that reak havoc with scanners
1813         // and CD-ROM's etc. This is the method employed in ASPI4DOS to avoid similar
1814         // problems.
1815         if (i > 1)
1816         {
1817             CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
1818             CCB->DataLength = i * sizeof(BusLogic_ScatterGatherSegment_T);
1819             virtualAddress = (PVOID) & (CCB->ScatterGatherList);
1820             CCB->DataPointer =  ScsiPortConvertPhysicalAddressToUlong(
1821                                     ScsiPortGetPhysicalAddress(HwDeviceExtension,
1822                                                                0,
1823                                                                (PVOID)virtualAddress,
1824                                                                &length));
1825         }
1826         else /* Turn off SG */
1827         {
1828             CCB->Opcode = BusLogic_InitiatorCCB;
1829             CCB->DataLength = CCB->ScatterGatherList[0].SegmentByteCount;
1830             CCB->DataPointer = CCB->ScatterGatherList[0].SegmentDataPointer;
1831 
1832         }
1833     }
1834 #else
1835     CCB->Opcode = BusLogic_InitiatorCCB;
1836     CCB->DataLength = BufferLength;
1837     CCB->DataPointer =  ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(deviceExtension,
1838                                                                                        Srb,
1839                                                                                        BufferPointer,
1840                                                                                        &length));
1841 #endif
1842   }
1843 
1844   switch (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION)
1845   {
1846     case SRB_FLAGS_NO_DATA_TRANSFER:
1847         CCB->DataDirection = BusLogic_NoDataTransfer;
1848         break;
1849 
1850     case SRB_FLAGS_DATA_IN:
1851         CCB->DataDirection = BusLogic_DataInLengthChecked;
1852         TargetStatistics[TargetID].ReadCommands++;
1853         BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead,
1854                                       BufferLength);
1855         BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets,
1856                                      BufferLength);
1857         break;
1858 
1859     case SRB_FLAGS_DATA_OUT:
1860         CCB->DataDirection = BusLogic_DataOutLengthChecked;
1861         TargetStatistics[TargetID].WriteCommands++;
1862         BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten,
1863                                       BufferLength);
1864         BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets,
1865                                      BufferLength);
1866 
1867         break;
1868 
1869     case SRB_FLAGS_UNSPECIFIED_DIRECTION:  /* let device decide direction */
1870     default:
1871         CCB->DataDirection = BusLogic_UncheckedDataTransfer;
1872         break;
1873   }
1874 
1875 
1876   CCB->CDB_Length = CDB_Length;
1877   CCB->SenseDataLength = Srb->SenseInfoBufferLength;
1878   CCB->HostAdapterStatus = 0;
1879   CCB->TargetDeviceStatus = 0;
1880   CCB->TargetID = TargetID;
1881   CCB->LogicalUnit = LogicalUnit;
1882   CCB->TagEnable = FALSE;
1883   CCB->LegacyTagEnable = FALSE;
1884 
1885   //  BusLogic recommends that after a Reset the first couple of commands that
1886   //  are sent to a Target Device be sent in a non Tagged Queue fashion so that
1887   //  the Host Adapter and Target Device can establish Synchronous and Wide
1888   //  Transfer before Queue Tag messages can interfere with the Synchronous and
1889   //  Wide Negotiation messages.  By waiting to enable Tagged Queuing until after
1890   //  the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
1891   //  assured that after a Reset any pending commands are requeued before Tagged
1892   //  Queuing is enabled and that the Tagged Queuing message will not occur while
1893   //  the partition table is being printed.  In addition, some devices do not
1894   //  properly handle the transition from non-tagged to tagged commands, so it is
1895   //  necessary to wait until there are no pending commands for a target device
1896   //  before queuing tagged commands.
1897 
1898   if (HostAdapter->CommandsSinceReset[TargetID]++ >= BusLogic_MaxTaggedQueueDepth &&
1899       HostAdapter->ActiveCommandsPerTarget[TargetID] == 0                         &&
1900       !TargetFlags->TaggedQueuingActive                                           &&
1901       TargetFlags->TaggedQueuingSupported                                         &&
1902       (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
1903   {
1904       TargetFlags->TaggedQueuingActive = TRUE;
1905       DebugPrint((INFO, "\n BusLogic - Tagged Queuing now active for Target %d\n",
1906                   TargetID));
1907   }
1908   if (TargetFlags->TaggedQueuingActive)
1909   {
1910     BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag;
1911 
1912     // When using Tagged Queuing with Simple Queue Tags, it appears that disk
1913     // drive controllers do not guarantee that a queued command will not
1914     // remain in a disconnected state indefinitely if commands that read or
1915     // write nearer the head position continue to arrive without interruption.
1916     // Therefore, for each Target Device this driver keeps track of the last
1917     // time either the queue was empty or an Ordered Queue Tag was issued.  If
1918     // more than 4 seconds (one fifth of the 20 second disk timeout) have
1919     // elapsed since this last sequence point, this command will be issued
1920     // with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
1921     // the Target Device to complete all previously queued commands before
1922     // this command may be executed.
1923     /*
1924     if (HostAdapter->ActiveCommandsPerTarget[TargetID] == 0)
1925         HostAdapter->LastSequencePoint[TargetID] = jiffies;
1926     else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
1927     {
1928       HostAdapter->LastSequencePoint[TargetID] = jiffies;
1929       QueueTag = BusLogic_OrderedQueueTag;
1930     }
1931     */
1932       if (HostAdapter->ExtendedLUNSupport)
1933     {
1934       CCB->TagEnable = TRUE;
1935       CCB->QueueTag = (UCHAR)QueueTag;
1936     }
1937     else
1938     {
1939       CCB->LegacyTagEnable = TRUE;
1940       CCB->LegacyQueueTag = (UCHAR)QueueTag;
1941     }
1942   }
1943 
1944   ScsiPortMoveMemory(CCB->CDB, Srb->Cdb, CDB_Length);
1945 
1946   //Fix for the XP Port driver - shuts of auto sense at times. 22nd May 2002
1947   //{sirish, shobhit}@calsoftinc.com
1948   if ((Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) ||
1949         (Srb->SenseInfoBufferLength <= 0)) {
1950 
1951       //Disable auto request sense
1952       CCB->SenseDataLength = BusLogic_DisableAutoReqSense;
1953   } else {
1954       //Enable auto request sense
1955       CCB->SenseDataLength  = (unsigned char) Srb->SenseInfoBufferLength;
1956 
1957       //Sense Buffer physical addr
1958       CCB->SenseDataPointer = ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(HwDeviceExtension,
1959                                                                                            Srb,
1960                                                                                            Srb->SenseInfoBuffer,
1961                                                                                            &length));
1962       if (Srb->SenseInfoBufferLength > length ) {
1963           CCB->SenseDataLength = (unsigned char) length;
1964       }
1965   }
1966 
1967   return 0;
1968 }// end BusLogic_QueueCommand
1969 
1970 
1971 BOOLEAN
1972 NTAPI
BT958HwInterrupt(IN PVOID HwDeviceExtension)1973 BT958HwInterrupt(IN PVOID HwDeviceExtension)
1974 //_________________________________________________________________________
1975 // Routine Description:
1976 //                      HwScsiInterrupt is called when the HBA generates an
1977 //                      interrupt. Miniport drivers of HBAs that do not
1978 //                      generate interrupts do not have this routine.
1979 //                      HwScsiInterrupt is responsible for completing
1980 //                      interrupt-driven I/O operations. This routine must
1981 //                      clear the interrupt on the HBA before it returns TRUE.
1982 // Arguments:
1983 //              1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area.
1984 // Return Value:
1985 //              TRUE : Acknowledged the interrupts on the HBA
1986 //              FALSE: If the miniport finds that its HBA did not generate
1987 //                     the interrupt, HwScsiInterrupt should return FALSE
1988 //                     as soon as possible.
1989 //_________________________________________________________________________
1990 {
1991     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
1992 //    PNONCACHED_EXTENSION noncachedExtension =    deviceExtension->NoncachedExtension;
1993     BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
1994 //    PBuslogic_CCB_T ccb;
1995 //    PSCSI_REQUEST_BLOCK srb;
1996 
1997 //    ULONG residualBytes;
1998 //    ULONG i;
1999 
2000     BusLogic_InterruptRegister_T InterruptRegister;
2001 
2002 
2003     // Read the Host Adapter Interrupt Register.
2004     InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
2005     if (InterruptRegister.Bits.InterruptValid)
2006     {
2007 
2008       // Acknowledge the interrupt and reset the Host Adapter
2009       // Interrupt Register.
2010       BusLogic_InterruptReset(HostAdapter);
2011       // Process valid External SCSI Bus Reset and Incoming Mailbox
2012       // Loaded Interrupts.  Command Complete Interrupts are noted,
2013       // and Outgoing Mailbox Available Interrupts are ignored, as
2014       // they are never enabled.
2015       if (InterruptRegister.Bits.ExternalBusReset)
2016       {
2017         HostAdapter->HostAdapterExternalReset = TRUE;
2018       }
2019       else if (InterruptRegister.Bits.IncomingMailboxLoaded)
2020       {
2021         BusLogic_ScanIncomingMailboxes(deviceExtension);
2022       }
2023       else if (InterruptRegister.Bits.CommandComplete)
2024       {
2025         HostAdapter->HostAdapterCommandCompleted = TRUE;
2026       }
2027     }
2028     else
2029         return FALSE;
2030 
2031     // Process any completed CCBs.
2032     if (HostAdapter->FirstCompletedCCB != NULL)
2033         BusLogic_ProcessCompletedCCBs(deviceExtension);
2034 
2035     // Reset the Host Adapter if requested.
2036     if (HostAdapter->HostAdapterExternalReset ||
2037         HostAdapter->HostAdapterInternalError)
2038     {
2039       // I have replaced the NULL with srb->pathid check if this is correct
2040       BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED);
2041       HostAdapter->HostAdapterExternalReset = FALSE;
2042       HostAdapter->HostAdapterInternalError = FALSE;
2043     }
2044     return TRUE;
2045 }// end BT958HwInterrupt
2046 
2047 void
BusLogic_ScanIncomingMailboxes(PHW_DEVICE_EXTENSION deviceExtension)2048 BusLogic_ScanIncomingMailboxes(PHW_DEVICE_EXTENSION deviceExtension)
2049 //________________________________________________________________________________________
2050 // Routine Description:
2051 //                  BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
2052 //                  Incoming Mailbox entries for completion processing.
2053 // Arguments:
2054 //              1. deviceExtension : pointer to the device extension
2055 //_________________________________________________________________________________________
2056 {
2057   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
2058 
2059 
2060   //  Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
2061   //  any completed CCBs for further processing.  It is essential that for each
2062   //  CCB and SCSI Command issued, command completion processing is performed
2063   //  exactly once.  Therefore, only Incoming Mailboxes with completion code
2064   //  Command Completed Without Error, Command Completed With Error, or Command
2065   //  Aborted At Host Request are saved for completion processing.  When an
2066   //  Incoming Mailbox has a completion code of Aborted Command Not Found, the
2067   //  CCB had already completed or been aborted before the current Abort request
2068   //  was processed, and so completion processing has already occurred and no
2069   //  further action should be taken.
2070   BusLogic_IncomingMailbox_T *NextIncomingMailbox =    HostAdapter->NextIncomingMailbox;
2071   BusLogic_CompletionCode_T CompletionCode;
2072 
2073   while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree)
2074   {
2075       // Convert Physical CCB to Virtual.
2076       BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) ScsiPortGetVirtualAddress(deviceExtension,
2077                                                                          ScsiPortConvertUlongToPhysicalAddress(NextIncomingMailbox->CCB));
2078 
2079       DebugPrint((INFO, "\n Buslogic - Virtual CCB %lx\n", CCB));
2080       if (CompletionCode != BusLogic_AbortedCommandNotFound)
2081       {
2082         if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset)
2083         {
2084 
2085             // Save the Completion Code for this CCB and queue the CCB
2086             // for completion processing.
2087             CCB->CompletionCode = CompletionCode;
2088             BusLogic_QueueCompletedCCB(deviceExtension,CCB);
2089         }
2090         else
2091         {
2092             // If a CCB ever appears in an Incoming Mailbox and is not marked
2093             // as status Active or Reset, then there is most likely a bug in
2094             // the Host Adapter firmware.
2095             DebugPrint((ERROR, "\n BusLogic - Illegal CCB #%ld status %d in "
2096                         "Incoming Mailbox\n", CCB->SerialNumber, CCB->Status));
2097         }
2098       }
2099       NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
2100       if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
2101         NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
2102   }
2103   HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
2104 }// end BusLogic_ScanIncomingMailboxes
2105 
2106 
2107 void
BusLogic_QueueCompletedCCB(PHW_DEVICE_EXTENSION deviceExtension,BusLogic_CCB_T * CCB)2108 BusLogic_QueueCompletedCCB(PHW_DEVICE_EXTENSION deviceExtension,
2109                            BusLogic_CCB_T *CCB)
2110 //_________________________________________________________________________________
2111 // Routine Description:
2112 //                  BusLogic_QueueCompletedCCB queues CCB for completion processing.
2113 // Arguments:
2114 //              1. deviceExtension : pointer to device extension
2115 //              2. CCB: pointe t CCB that needs to be queued
2116 //_________________________________________________________________________________
2117 {
2118   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
2119 
2120   CCB->Status = BusLogic_CCB_Completed;
2121   CCB->Next = NULL;
2122   if (HostAdapter->FirstCompletedCCB == NULL)
2123   {
2124       HostAdapter->FirstCompletedCCB = CCB;
2125       HostAdapter->LastCompletedCCB = CCB;
2126   }
2127   else
2128   {
2129       HostAdapter->LastCompletedCCB->Next = CCB;
2130       HostAdapter->LastCompletedCCB = CCB;
2131   }
2132   HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]--;
2133   HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]--;
2134 
2135 }// end BusLogic_QueueCompletedCCB
2136 
2137 
2138 void
BusLogic_ProcessCompletedCCBs(PHW_DEVICE_EXTENSION deviceExtension)2139 BusLogic_ProcessCompletedCCBs(PHW_DEVICE_EXTENSION deviceExtension)
2140 //_________________________________________________________________________________
2141 // Routine Description:
2142 //            BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
2143 //            Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
2144 //            calling the SCSI Subsystem Completion Routines.  The Host Adapter's Lock
2145 //            should already have been acquired by the caller.
2146 //
2147 // Arguments:
2148 //              1. deviceExtension : pointer to device extension
2149 //_________________________________________________________________________________
2150 {
2151   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
2152   PSCSI_REQUEST_BLOCK srb;
2153   PCDB RealCdb;
2154 
2155   if (HostAdapter->ProcessCompletedCCBsActive)
2156       return;
2157   HostAdapter->ProcessCompletedCCBsActive = TRUE;
2158   while (HostAdapter->FirstCompletedCCB != NULL)
2159   {
2160       BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB;
2161 
2162       // Get SRB from CCB.
2163       srb = CCB->SrbAddress;
2164 
2165        HostAdapter->FirstCompletedCCB = CCB->Next;
2166        if (HostAdapter->FirstCompletedCCB == NULL)
2167             HostAdapter->LastCompletedCCB = NULL;
2168 
2169       // Process the Completed CCB.
2170       if (CCB->Opcode == BusLogic_BusDeviceReset)
2171       {
2172           int TargetID = CCB->TargetID, LunID;
2173           DebugPrint((TRACE, "\n BusLogic - Bus Device Reset CCB #%ld to Target "
2174                       "%d Completed\n", CCB->SerialNumber, TargetID));
2175           BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
2176 
2177           HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE;
2178           HostAdapter->CommandsSinceReset[TargetID] = 0;
2179           //HostAdapter->LastResetCompleted[TargetID] = jiffies;
2180           HostAdapter->ActiveCommandsPerTarget[TargetID] = 0;
2181           for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++)
2182             HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0;
2183 
2184           // Complete all outstanding requests with SRB_STATUS_BUS_RESET.
2185           ScsiPortCompleteRequest(deviceExtension,
2186                                   (UCHAR)srb->PathId,
2187                                   srb->TargetId,
2188                                   0xFF,
2189                                   (ULONG)SRB_STATUS_BUS_RESET);
2190 
2191 
2192           HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
2193       }
2194       else
2195       {
2196           // Translate the Completion Code, Host Adapter Status, and Target
2197           // Device Status into a SCSI Subsystem Result Code.
2198           switch (CCB->CompletionCode)
2199           {
2200             case BusLogic_IncomingMailboxFree:
2201             case BusLogic_InvalidCCB:
2202             {
2203                 DebugPrint((ERROR, "\n BusLogic - CCB #%ld to Target %d Impossible "
2204                             "State\n", CCB->SerialNumber, CCB->TargetID));
2205                 break;
2206             }
2207 
2208             //Processing for CCB that was to be aborted
2209             case BusLogic_AbortedCommandNotFound:
2210             {
2211                 srb = CCB->AbortSrb;
2212                 srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
2213                 break;
2214             }
2215 
2216             case BusLogic_CommandCompletedWithoutError:
2217             {
2218                HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++;
2219                HostAdapter->TargetFlags[CCB->TargetID].CommandSuccessfulFlag = TRUE;
2220 
2221                srb->SrbStatus = SRB_STATUS_SUCCESS;
2222                break;
2223             }
2224 
2225             case BusLogic_CommandAbortedAtHostRequest:
2226             {
2227               DebugPrint((TRACE, "\n BusLogic - CCB #%ld to Target %d Aborted\n",
2228                           CCB->SerialNumber, CCB->TargetID));
2229               //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID].CommandAbortsCompleted);
2230 
2231               srb->SrbStatus = SRB_STATUS_ABORTED;
2232 
2233               // Call notification routine for the aborted SRB.
2234               ScsiPortNotification(RequestComplete,
2235                                    deviceExtension,
2236                                    srb);
2237 
2238               // Get the abort SRB from CCB.
2239               srb = CCB->AbortSrb;
2240 
2241                // Set status for completing abort request.
2242               srb->SrbStatus = SRB_STATUS_SUCCESS;
2243               break;
2244             }
2245 
2246             case BusLogic_CommandCompletedWithError:
2247             {
2248               RealCdb = (PCDB)CCB->CDB;
2249               DebugPrint((ERROR, "\n BusLogic - %x Command completed with error Host - "
2250                           "%x Target %x \n", RealCdb->CDB6GENERIC.OperationCode,
2251                           CCB->HostAdapterStatus, CCB->TargetDeviceStatus));
2252 
2253               srb->SrbStatus = BusLogic_ComputeResultCode(HostAdapter,
2254                                                            CCB->HostAdapterStatus,
2255                                                            CCB->TargetDeviceStatus,
2256                                                            CCB->SenseDataLength);
2257               if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
2258               {
2259                 HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++;
2260               }
2261               break;
2262             }
2263 
2264             default:
2265             {
2266                        // Log the error.
2267                ScsiPortLogError(deviceExtension,
2268                                 NULL,
2269                                 0,
2270                                 srb->TargetId,
2271                                 0,
2272                                 SP_INTERNAL_ADAPTER_ERROR,
2273                                 143);
2274 
2275                 DebugPrint((ERROR, "\n BusLogic - Unrecognized mailbox status\n"));
2276             }
2277 
2278           }// end switch
2279 
2280 
2281           // When an INQUIRY command completes normally, save the CmdQue (Tagged Queuing Supported)
2282           // and WBus16 (16 Bit Wide Data Transfers Supported) bits.
2283           RealCdb = (PCDB) CCB->CDB;
2284           if (RealCdb->CDB6INQUIRY.OperationCode == SCSIOP_INQUIRY &&
2285               CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally)
2286           {
2287               BusLogic_TargetFlags_T *TargetFlags =&HostAdapter->TargetFlags[CCB->TargetID];
2288               SCSI_Inquiry_T *InquiryResult =(SCSI_Inquiry_T *) srb->DataBuffer;
2289               TargetFlags->TargetExists = TRUE;
2290               TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
2291               TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
2292           }
2293 
2294           DebugPrint((INFO, "\n BusLogic - SCSI Status %x\n", srb->ScsiStatus));
2295           DebugPrint((INFO, "\n BusLogic - HBA Status %x\n", CCB->HostAdapterStatus));
2296 
2297           // Update target status in SRB.
2298           srb->ScsiStatus = (UCHAR)CCB->TargetDeviceStatus;
2299 
2300           // Signal request completion.
2301           ScsiPortNotification(RequestComplete, (PVOID)deviceExtension, srb);
2302        }
2303     }
2304     HostAdapter->ProcessCompletedCCBsActive = FALSE;
2305 }// end BusLogic_ProcessCompletedCCBs
2306 
2307 
2308 UCHAR
BusLogic_ComputeResultCode(BusLogic_HostAdapter_T * HostAdapter,BusLogic_HostAdapterStatus_T HostAdapterStatus,BusLogic_TargetDeviceStatus_T TargetDeviceStatus,UCHAR SenseDataLength)2309 BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter,
2310                            BusLogic_HostAdapterStatus_T HostAdapterStatus,
2311                            BusLogic_TargetDeviceStatus_T TargetDeviceStatus,
2312                            UCHAR SenseDataLength)
2313 //_________________________________________________________________________________________
2314 // Routine Description:
2315 //                BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
2316 //                the Host Adapter Status and Target Device Status.
2317 // Arguments:
2318 //              1.HostAdapter:  Pointer to the host adapter structure
2319 //              2.HostAdapterStatus: Host adapter status returned in the completed CCB
2320 //              3.TargetDeviceStatus:
2321 // Return Value:
2322 //              This function returns the error code that should be returned to port driver
2323 //_________________________________________________________________________________________
2324 {
2325   UCHAR HostStatus = 0;
2326 
2327   // Namita 2Oct CDROM issue
2328   if (TargetDeviceStatus != BusLogic_OperationGood && (HostAdapterStatus == BusLogic_CommandCompletedNormally ||
2329                                                        HostAdapterStatus == BusLogic_LinkedCommandCompleted   ||
2330                                                        HostAdapterStatus == BusLogic_LinkedCommandCompletedWithFlag))
2331   {
2332     switch(TargetDeviceStatus)
2333     {
2334         case BusLogic_CheckCondition:
2335         {
2336             HostStatus = SRB_STATUS_ERROR;
2337             if(SenseDataLength != BusLogic_DisableAutoReqSense)
2338                 HostStatus |= SRB_STATUS_AUTOSENSE_VALID;
2339             break;
2340         }
2341         case BusLogic_DeviceBusy:
2342         {
2343             HostStatus = SRB_STATUS_BUSY;
2344             break;
2345         }
2346         case BusLogic_OperationGood:
2347         {
2348             HostStatus = SRB_STATUS_SUCCESS;
2349             break;
2350         }
2351 	}
2352   }
2353 
2354   else
2355   {
2356 
2357       switch (HostAdapterStatus)
2358       {
2359             case BusLogic_CommandCompletedNormally:
2360             case BusLogic_LinkedCommandCompleted:
2361             case BusLogic_LinkedCommandCompletedWithFlag:
2362             {
2363               HostStatus = SRB_STATUS_SUCCESS;
2364               break;
2365             }
2366             case BusLogic_SCSISelectionTimeout:
2367             {
2368               HostStatus = SRB_STATUS_SELECTION_TIMEOUT;
2369               break;
2370             }
2371             case BusLogic_InvalidOutgoingMailboxActionCode:
2372             case BusLogic_InvalidCommandOperationCode:
2373             case BusLogic_InvalidCommandParameter:
2374               DebugPrint((WARNING, "\n BusLogic - Driver Protocol Error 0x%02X\n",
2375                           HostAdapterStatus));
2376             case BusLogic_DataUnderRun:
2377 
2378             case BusLogic_DataOverRun:
2379                 // SRB_STATUS_DATA_OVERRUN
2380 
2381             case BusLogic_LinkedCCBhasInvalidLUN:
2382 
2383             case BusLogic_TaggedQueuingMessageRejected:
2384                 // SRB_STATUS_MESSAGE_REJECTED
2385             case BusLogic_TargetDeviceReconnectedImproperly:
2386             case BusLogic_AbortQueueGenerated:
2387             case BusLogic_HostAdapterSoftwareError:
2388 
2389             case BusLogic_HostAdapterHardwareTimeoutError:
2390                 // SRB_STATUS_TIMEOUT
2391             {
2392               HostStatus = SRB_STATUS_ERROR;
2393               break;
2394             }
2395             case BusLogic_TargetFailedResponseToATN:
2396             case BusLogic_HostAdapterAssertedRST:
2397             case BusLogic_OtherDeviceAssertedRST:
2398             case BusLogic_HostAdapterAssertedBusDeviceReset:
2399             {
2400               HostStatus = SRB_STATUS_BUS_RESET;
2401               break;
2402             }
2403             case BusLogic_SCSIParityErrorDetected:
2404             {
2405                 HostStatus = SRB_STATUS_PARITY_ERROR;
2406                 break;
2407             }
2408             case BusLogic_UnexpectedBusFree:
2409             {
2410                 HostStatus = SRB_STATUS_UNEXPECTED_BUS_FREE;
2411                 break;
2412             }
2413             case BusLogic_InvalidBusPhaseRequested:
2414             {
2415                 HostStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
2416                 break;
2417             }
2418             case BusLogic_AutoRequestSenseFailed:
2419             {
2420                 HostStatus = SRB_STATUS_REQUEST_SENSE_FAILED;
2421                 break;
2422             }
2423             case BusLogic_UnsupportedMessageReceived:
2424             {
2425                 HostStatus = SRB_STATUS_INVALID_REQUEST;
2426                 break;
2427             }
2428             case BusLogic_HostAdapterHardwareFailed:
2429             {
2430                 HostStatus = SRB_STATUS_NO_HBA;
2431                 break;
2432             }
2433             default:
2434             {
2435               DebugPrint((WARNING, "\n BusLogic - Unknown HBA Status 0x%02X\n",
2436                           HostAdapterStatus));
2437               HostStatus = SRB_STATUS_ERROR;
2438               break;
2439             }
2440         }
2441   }
2442   return HostStatus;
2443 }// end BusLogic_ComputeResultCode
2444 
2445 
2446 BOOLEAN
2447 NTAPI
BT958HwResetBus(IN PVOID HwDeviceExtension,IN ULONG PathId)2448 BT958HwResetBus(IN PVOID HwDeviceExtension,
2449                 IN ULONG PathId)
2450 //_____________________________________________________________________________________
2451 // Routine Description:
2452 //                   BT958HwResetBus resets Host Adapter if possible, marking all
2453 //                   currently executing SCSI Commands as having been Reset.
2454 // Arguments:
2455 //           1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area.
2456 //           2. PathId: Identifies the SCSI bus to be reset.
2457 // Return Value:
2458 //              TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE.
2459 //              FALSE : reset did not complete successfully
2460 //_____________________________________________________________________________________
2461 {
2462   PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
2463   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
2464 //  BusLogic_CCB_T *CCB;
2465 //  int TargetID;
2466   BOOLEAN Result;
2467   BOOLEAN HardReset;
2468 
2469   DebugPrint((TRACE, "\n BusLogic - Reset SCSI bus\n"));
2470 
2471   // Complete all outstanding requests with SRB_STATUS_BUS_RESET.
2472   ScsiPortCompleteRequest(deviceExtension,
2473                                 (UCHAR)PathId,
2474                                 0xFF,
2475                                 0xFF,
2476                                 (ULONG) SRB_STATUS_BUS_RESET);
2477 
2478   if (HostAdapter->HostAdapterExternalReset)
2479   {
2480       //BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
2481       HardReset = FALSE;
2482   }
2483   else if (HostAdapter->HostAdapterInternalError)
2484   {
2485       //BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
2486       HardReset = TRUE;
2487   }
2488   else
2489   {
2490       //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsRequested);
2491       HardReset = TRUE;
2492   }
2493 
2494   // Think of a way of doing this - Namita
2495   /*
2496   if(srb == NULL)
2497   {
2498     if (HostAdapter->HostAdapterInternalError)
2499         DebugPrint((0,"BusLogic Warning: Resetting %s due to Host Adapter Internal Error\n",HostAdapter->FullModelName));
2500     else
2501         DebugPrint((0,"BUsLogic Warning: Resetting %s due to External SCSI Bus Reset\n",HostAdapter->FullModelName));
2502   }
2503   else
2504   {
2505       DebugPrint((0,"BusLogic Warning: Resetting %s due to Target %d\n", HostAdapter->FullModelName, srb->TargetId));
2506       //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsAttempted);
2507   }
2508   */
2509 
2510   // Attempt to Reset and Reinitialize the Host Adapter.
2511   // Change the initialize routine to make allocation some place else
2512   if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(deviceExtension, NULL)))
2513   {
2514       DebugPrint((ERROR, "\n Buslogic - Resetting %s Failed\n",
2515                   HostAdapter->FullModelName));
2516       Result = FALSE;
2517       goto Done;
2518   }
2519 
2520   // Check if we have to do this, document says that the scsi port driver takes care of the reset delays - Namita
2521   // Wait a few seconds between the Host Adapter Hard Reset which initiates
2522   // a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
2523   // confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
2524   // Note that a timer interrupt may occur here, but all active CCBs have
2525   // already been marked Reset and so a reentrant call will return Pending.
2526   if (HardReset)
2527     ScsiPortStallExecution(HostAdapter->BusSettleTime);
2528   Result = TRUE;
2529 
2530 Done:
2531   return Result;
2532 }// end BT958HwResetBus
2533 
2534 BOOLEAN
BusLogic_SendBusDeviceReset(IN PVOID HwDeviceExtension,PSCSI_REQUEST_BLOCK Srb)2535 BusLogic_SendBusDeviceReset(IN PVOID HwDeviceExtension,
2536                             PSCSI_REQUEST_BLOCK Srb)
2537 //_____________________________________________________________________________________
2538 // Routine Description:
2539 //                     BusLogic_SendBusDeviceReset causes a BUS DEVICE reset command to
2540 //                     be send to particular target.
2541 // Arguments:
2542 //           1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area.
2543 //           2. Srb: pointer to the SCSI request block
2544 // Return Value:
2545 //              TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE.
2546 //              FALSE : reset did not complete successfully
2547 //_____________________________________________________________________________________
2548 {
2549 
2550   PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
2551   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
2552 
2553   UCHAR TargetID = Srb->TargetId;
2554   PBuslogic_CCB_T CCB = Srb->SrbExtension;
2555   BOOLEAN Result = FALSE;
2556   BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested);
2557 
2558   //  If this is a Synchronous Reset and a Bus Device Reset is already pending
2559   //  for this Target Device, do not send a second one.  Add this Command to
2560   //  the list of Commands for which completion processing must be performed
2561   //  when the Bus Device Reset CCB completes.
2562 
2563   if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL)
2564   {
2565     DebugPrint((WARNING, "\n BusLogic - Unable to Reset Command to Target %d - "
2566                 "Reset Pending\n", TargetID));
2567     Result = TRUE;
2568     goto Done;
2569   }
2570 
2571   DebugPrint((WARNING, "\n BusLogic - Sending Bus Device Reset CCB #%ld to Target %d\n",
2572               CCB->SerialNumber, TargetID));
2573   CCB->Opcode = BusLogic_BusDeviceReset;
2574   CCB->TargetID = TargetID;
2575 
2576 
2577   //    Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB.
2578   //    If sending a Bus Device Reset is impossible, attempt a full Host
2579   //    Adapter Hard Reset and SCSI Bus Reset.
2580   if (!(BusLogic_WriteOutgoingMailbox(deviceExtension, BusLogic_MailboxStartCommand, CCB)))
2581   {
2582       DebugPrint((WARNING, "\n BusLogic - Unable to write Outgoing Mailbox for "
2583                   "Bus Device Reset\n"));
2584       goto Done;
2585   }
2586 
2587   //  If there is a currently executing CCB in the Host Adapter for this Command
2588   //  (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be
2589   //  made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset.
2590   //  If there is no active CCB for this Command (i.e. this is a Synchronous
2591   //  Reset), then the Bus Device Reset CCB's Command field will have been set
2592   //  to the Command so that the interrupt for the completion of the Bus Device
2593   //  Reset can call the Completion Routine for the Command.  On successful
2594   //  execution of a Bus Device Reset, older firmware versions did return the
2595   //  pending CCBs with the appropriate completion code, but more recent firmware
2596   //  versions only return the Bus Device Reset CCB itself.  This driver handles
2597   //  both cases by marking all the currently executing CCBs to this Target
2598   //  Device as Reset.  When the Bus Device Reset CCB is processed by the
2599   //  interrupt handler, any remaining CCBs marked as Reset will have completion
2600   //  processing performed.
2601 
2602   BusLogic_IncrementErrorCounter( &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted);
2603   HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB;
2604   //HostAdapter->LastResetAttempted[TargetID] = jiffies;
2605 
2606   // FlashPoint Host Adapters may have already completed the Bus Device
2607   // Reset and BusLogic_QueueCompletedCCB been called, or it may still be
2608   // pending.
2609 
2610   Result = TRUE;
2611   //  If a Bus Device Reset was not possible for some reason, force a full
2612   //  Host Adapter Hard Reset and SCSI Bus Reset.
2613 
2614 Done:
2615   return Result;
2616 }
2617 
2618 BOOLEAN
2619 NTAPI
BT958HwInitialize(IN PVOID HwDeviceExtension)2620 BT958HwInitialize(IN PVOID HwDeviceExtension)
2621 //_______________________________________________________________________________
2622 // Routine Description:
2623 //              This routine initializes the adapter by enabling its interrupts
2624 // Arguments:
2625 //              1. device extension
2626 // Return Value:
2627 //              TRUE : initialization successful
2628 //              FALSE : initialization failed
2629 //_______________________________________________________________________________
2630 {
2631     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
2632     BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
2633     CHAR Parameter = 1;
2634 
2635     // enable interrupts
2636     if (BusLogic_Command(HostAdapter,
2637                            BusLogic_DisableHostAdapterInterrupt,
2638                            &Parameter,
2639                            sizeof(Parameter),
2640                            NULL,
2641                            0)
2642         < 0)
2643     {
2644        return FALSE;
2645     }
2646     return TRUE;
2647 }// end BT958HwInitialize
2648 
2649 SCSI_ADAPTER_CONTROL_STATUS
2650 NTAPI
BT958HwAdapterControl(IN PVOID HwDeviceExtension,IN SCSI_ADAPTER_CONTROL_TYPE ControlType,IN PVOID Parameters)2651 BT958HwAdapterControl(IN PVOID HwDeviceExtension,
2652                       IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
2653                       IN PVOID Parameters)
2654 //__________________________________________________________________________________________
2655 // Routine Description:
2656 //               A miniport driver's HwScsiAdapterControl routine is called to perform
2657 //               synchronous operations to control the state or behavior of an HBA, such as
2658 //               stopping or restarting the HBA for power management.
2659 // Arguments:
2660 //              1. HwDeviceExtension: device extension
2661 //              2. ControlType: Specifies one of the following adapter-control operations.
2662 //                 ScsiQuerySupportedControlTypes : Reports the adapter-control operations
2663 //                                                  implemented by the miniport.
2664 //                 ScsiStopAdapter:  Shuts down the HBA.
2665 //                 ScsiRestartAdapter: Reinitializes an HBA.
2666 //                 ScsiSetBootConfig: Not supported
2667 //                 ScsiSetRunningConfig: Not supported
2668 //              3. Parameters:
2669 // Return Value:
2670 //              TRUE :
2671 //              FALSE :
2672 //_________________________________________________________________________
2673 {
2674     PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
2675     BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
2676 //	UCHAR *ParameterPointer;
2677 //	BusLogic_StatusRegister_T StatusRegister;
2678 //	BusLogic_InterruptRegister_T InterruptRegister;
2679 //	int Result,ParameterLength;
2680 //	long TimeoutCounter;
2681 
2682     PSCSI_SUPPORTED_CONTROL_TYPE_LIST ControlTypeList;
2683     ULONG AdjustedMaxControlType;
2684 
2685     ULONG Index;
2686 //    UCHAR Retries;
2687 
2688     // Default Status
2689 //    SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
2690 
2691     //
2692     // Structure defining which functions this miniport supports
2693     //
2694     BOOLEAN SupportedConrolTypes[ScsiAdapterControlMax] =
2695     {
2696         TRUE,   // ScsiQuerySupportedControlTypes
2697         TRUE,   // ScsiStopAdapter
2698         TRUE,   // ScsiRestartAdapter
2699         FALSE,  // ScsiSetBootConfig
2700         FALSE   // ScsiSetRunningConfig
2701     };
2702 
2703     DebugPrint((TRACE, "\n BusLogic -  Inside HwAdapterControl function \n"));
2704     switch(ControlType)
2705     {
2706         case ScsiQuerySupportedControlTypes:
2707         //  Reports the adapter-control operations implemented by the miniport. The port
2708         //  driver calls HwScsiAdapterControl with this control type after the HBA has been
2709         //  initialized but before the first I/O. The miniport fills in the
2710         //  SCSI_SUPPORTED_CONTROL_TYPE_LIST structure at Parameters with the operations it
2711         //  supports. After HwScsiAdapterControl returns from this call, the port driver
2712         //  calls the miniport's HwScsiAdapterControl only for supported operations.
2713         {
2714 
2715             // This entry point provides the method by which SCSIPort determines the
2716             // supported ControlTypes. Parameters is a pointer to a
2717             // SCSI_SUPPORTED_CONTROL_TYPE_LIST structure. Fill in this structure
2718             // honoring the size limits.
2719             ControlTypeList = Parameters;
2720             AdjustedMaxControlType =  (ControlTypeList->MaxControlType < ScsiAdapterControlMax) ?  ControlTypeList->MaxControlType :ScsiAdapterControlMax;
2721             for (Index = 0; Index < AdjustedMaxControlType; Index++)
2722             {
2723                 ControlTypeList->SupportedTypeList[Index] = SupportedConrolTypes[Index];
2724             }
2725             break;
2726         }
2727 
2728         case ScsiStopAdapter:
2729         // Shuts down the HBA. The port driver calls HwScsiAdapterControl with this control
2730         // type when the HBA has been removed from the system, stopped for resource reconfiguration,
2731         // shut down for power management, or otherwise reconfigured or disabled. The port driver
2732         // ensures that there are no uncompleted requests and issues an SRB_FUNCTION_FLUSH request
2733         // to the miniport before calling this routine. The miniport disables interrupts on its HBA,
2734         // halts all processing, (including background processing not subject to interrupts or processing
2735         // of which the port driver is unaware, such as reconstructing fault-tolerant volumes), flushes
2736         // any remaining cached data to persistent storage, and puts the HBA into a state from which it
2737         // can be reinitialized or restarted.
2738         // The miniport should not free its resources when stopping its HBA. If the HBA was removed or
2739         // stopped for PnP resource reconfiguration, the port driver releases resources on behalf of the
2740         // miniport driver. If the HBA is shut down for power management, the miniport's resources are
2741         // preserved so the HBA can be restarted.
2742         {
2743             CHAR Parameter = 0;
2744             DebugPrint((INFO, "\n BusLogic -  stopping the device \n"));
2745             if (BusLogic_Command(HostAdapter,
2746                                    BusLogic_DisableHostAdapterInterrupt,
2747                                    &Parameter,
2748                                    sizeof(Parameter),
2749                                    NULL,
2750                                    0)
2751                 < 0)
2752             {
2753                   return ScsiAdapterControlUnsuccessful;
2754             }
2755             break;
2756         }
2757 
2758         case ScsiRestartAdapter:
2759         // Reinitializes an HBA. The port driver calls HwScsiAdapterControl with this control type to power
2760         // up an HBA that was shut down for power management. All resources previously assigned to the miniport
2761         // are still available, and its device extension and logical unit extensions, if any, are intact.
2762         // The miniport performs the same operations as in its HwScsiInitialize routine, such as setting up
2763         // the HBA's registers and its initial state, if any.
2764         // The miniport must not call routines that can only be called from HwScsiFindAdapter or from
2765         // HwScsiAdapterControl when the control type is ScsiSetRunningConfig, such as ScsiPortGetBusData and
2766         // ScsiPortSetBusDataByOffset. If the miniport must call such routines to restart its HBA, it must also
2767         // implement ScsiSetRunningConfig.
2768         // If the miniport does not implement ScsiRestartAdapter, the port driver calls the miniport's HwScsiFindAdapter and HwScsiInitialize routines. However, because such routines might do detection work which is unnecessary for restarting the HBA, such a miniport will not power up its HBA as quickly as a miniport that implements ScsiRestartAdapter.
2769 
2770         // See PR 69004. We were not calling BT958HwInitialize earlier if the
2771         // first two calls succeeded thus causing resume from standby to fail.
2772         {
2773             if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE) &&
2774                   BusLogic_InitializeHostAdapter(deviceExtension, NULL) &&
2775                   BT958HwInitialize(HwDeviceExtension))
2776                )
2777             {
2778                 DebugPrint((ERROR, "\n Buslogic - Resetting %s Failed\n",
2779                             HostAdapter->FullModelName));
2780                 return ScsiAdapterControlUnsuccessful;
2781             }
2782 
2783             ScsiPortStallExecution(HostAdapter->BusSettleTime);
2784             break;
2785         }
2786         default:
2787         {
2788             return ScsiAdapterControlUnsuccessful;
2789         }
2790     }
2791     return ScsiAdapterControlSuccess;
2792 }// end BT958HwAdapterControl
2793 
2794 // END OF FILE BusLogic958.c
2795