📄 aha154x.c
字号:
//
// Wait for HACC by hand.
//
SpinForInterrupt(HwDeviceExtension, FALSE);
//
// If the 1st bytethe adapter inquiry command is 0x41,
// then the adapter is an AHA154XB; if 0x44 or 0x45 then
// it is an AHA154XC or CF respectively
//
// if we've already checked all the possible locations for
// an AHA154XB bios don't waste time mapping the ports
//
if ((inboundData == 0x41)&&(Context->biosScanStart < 6)) {
//
// Get the system physical address for this BIOS section.
//
biosSpace =
ScsiPortGetDeviceBase(HwDeviceExtension,
ConfigInfo->AdapterInterfaceType,
ConfigInfo->SystemIoBusNumber,
ScsiPortConvertUlongToPhysicalAddress(0xC8000),
0x18000,
FALSE);
//
// Loop through all BIOS base possibilities. Use the context information
// to pick up where we left off the last time around.
//
for (i = Context->biosScanStart; i < 6; i ++) {
biosPtr = biosSpace + i * 0x4000 + 16;
//
// Compare the second 16 bytes to BIOS header
for (j = 0; j < 16; j++) {
if (aha154xBSignature[j] != ScsiPortReadRegisterUchar(biosPtr)) {
break;
}
biosPtr++;
}
if (j == 16) {
//
// Found the BIOS. Set up ConfigInfo->AccessRanges
//
(*ConfigInfo->AccessRanges)[1].RangeStart =
ScsiPortConvertUlongToPhysicalAddress(0xC8000 + i * 0x4000);
(*ConfigInfo->AccessRanges)[1].RangeLength = 0x4000;
(*ConfigInfo->AccessRanges)[1].RangeInMemory = TRUE;
DebugPrint((1,
"A154xClaimBiosSpace: 154XB BIOS address = %lX\n",
0xC8000 + i * 0x4000 ));
break;
}
}
Context->biosScanStart = i + 1;
ScsiPortFreeDeviceBase(HwDeviceExtension, (PVOID)biosSpace);
} else {
if ((inboundData == 0x44) || (inboundData == 0x45)) {
//
// Fill in BIOS address information
//
ScsiPortWritePortUchar(&BaseIoAddress->StatusRegister,
IOP_INTERRUPT_RESET);
if (WriteCommandRegister(HwDeviceExtension,
AC_RETURN_SETUP_DATA,TRUE) == FALSE) {
return;
}
//
// Send length of incoming transfer for the Return Setup Data
//
if (WriteDataRegister(HwDeviceExtension,0x27) == FALSE) {
return;
}
//
// Magic Adaptec C rev byte.
//
for (i = 0; i < 0x27; i++) {
if ((ReadCommandRegister(HwDeviceExtension,
&inboundData,TRUE)) == FALSE) {
return;
}
}
//
// Interrupt handler is not yet installed so wait for HACC by hand.
//
SpinForInterrupt(HwDeviceExtension, FALSE);
inboundData >>= 4;
inboundData &= 0x07; // Filter BIOS bits out
baseBIOSAddress = 0xC8000;
if (inboundData != 0x07 && inboundData != 0x06) {
baseBIOSAddress +=
(ULONG)((~inboundData & 0x07) - 2) * 0x4000;
(*ConfigInfo->AccessRanges)[1].RangeStart =
ScsiPortConvertUlongToPhysicalAddress(baseBIOSAddress);
(*ConfigInfo->AccessRanges)[1].RangeLength = 0x4000;
(*ConfigInfo->AccessRanges)[1].RangeInMemory = TRUE;
DebugPrint((1,
"A154xClaimBiosSpace: 154XC BIOS address = %lX\n",
baseBIOSAddress));
}
}
}
return;
}
BOOLEAN
A154xHwInitialize(
IN PVOID HwDeviceExtension
)
/*++
Routine Description:
This routine is called from ScsiPortInitialize
to set up the adapter so that it is ready to service requests.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
Return Value:
TRUE - if initialization successful.
FALSE - if initialization unsuccessful.
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PNONCACHED_EXTENSION noncachedExtension =
deviceExtension->NoncachedExtension;
PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
UCHAR status;
ULONG i;
DebugPrint((2,"A154xHwInitialize: Reset aha154X and SCSI bus\n"));
//
// Reset SCSI chip.
//
ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_HARD_RESET);
//
// Inform the port driver that the bus has been reset.
//
ScsiPortNotification(ResetDetected, HwDeviceExtension, 0);
ScsiPortStallExecution(500*1000);
//
// Wait up to 5000 microseconds for adapter to initialize.
//
for (i = 0; i < 5000; i++) {
ScsiPortStallExecution(1);
status = ScsiPortReadPortUchar(&deviceExtension->BaseIoAddress->StatusRegister);
if (status & IOP_SCSI_HBA_IDLE) {
break;
}
}
//
// Check if reset failed or succeeded.
//
if (!(status & IOP_SCSI_HBA_IDLE) || !(status & IOP_MAILBOX_INIT_REQUIRED)) {
DebugPrint((1,"A154xInitialize: Reset SCSI bus failed\n"));
return FALSE;
}
//
// Unlock mailboxes in case the adapter is a 1540B with 1Gb support
// or 1540C with extended translation enabled.
//
status = UnlockMailBoxes(deviceExtension);
(VOID) SpinForInterrupt(deviceExtension,FALSE); // eddy
//
// Zero out mailboxes.
//
for (i=0; i<MB_COUNT; i++) {
PMBO mailboxOut;
PMBI mailboxIn;
mailboxIn = &noncachedExtension->Mbi[i];
mailboxOut = &noncachedExtension->Mbo[i];
mailboxOut->Command = mailboxIn->Status = 0;
}
//
// Zero preivous indexes.
//
deviceExtension->MboIndex = 0;
deviceExtension->MbiIndex = 0;
DebugPrint((3,"A154xHwInitialize: Initialize mailbox\n"));
if (!WriteCommandRegister(deviceExtension,AC_MAILBOX_INITIALIZATION, TRUE)) {
DebugPrint((1,"A154xHwInitialize: Can't initialize mailboxes\n"));
return FALSE;
}
//
// Send Adapter number of mailbox locations.
//
if (!WriteDataRegister(deviceExtension, MB_COUNT)) {
return FALSE;
}
//
// Send the most significant byte of the mailbox physical address.
//
if (!WriteDataRegister(deviceExtension,
((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte2)) {
return FALSE;
}
//
// Send the middle byte of the mailbox physical address.
//
if (!WriteDataRegister(deviceExtension,
((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte1)) {
return FALSE;
}
//
// Send the least significant byte of the mailbox physical address.
//
if (!WriteDataRegister(deviceExtension,
((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte0)) {
return FALSE;
}
#ifdef FORCE_DMA_SPEED
//
// Set the DMA transfer speed to 5.0 MB/second. This is because
// faster transfer speeds cause data corruption on 486/33 machines.
// This overrides the card jumper setting.
//
if (!WriteCommandRegister(deviceExtension, AC_SET_TRANSFER_SPEED, TRUE)) {
DebugPrint((1,"Can't set dma transfer speed\n"));
} else if (!WriteDataRegister(deviceExtension, DMA_SPEED_50_MBS)) {
DebugPrint((1,"Can't set dma transfer speed\n"));
}
//
// Wait for interrupt.
//
if (!SpinForInterrupt(deviceExtension,TRUE)) {
DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
return TRUE;
}
#endif
//
// Override default setting for bus on time. This makes floppy
// drives work better with this adapter.
//
if (!WriteCommandRegister(deviceExtension, AC_SET_BUS_ON_TIME, TRUE)) {
DebugPrint((1,"Can't set bus on time\n"));
} else if (!WriteDataRegister(deviceExtension, deviceExtension->BusOnTime)) {
DebugPrint((1,"Can't set bus on time\n"));
}
//
// Wait for interrupt.
//
if (!SpinForInterrupt(deviceExtension,TRUE)) {
DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
return TRUE;
}
//
// Override the default CCB timeout of 250 mseconds to 500 (0x1F4).
//
if (!WriteCommandRegister(deviceExtension, AC_SET_SELECTION_TIMEOUT, TRUE)) {
DebugPrint((1,"A154xHwInitialize: Can't set CCB timeout\n"));
}
else {
if (!WriteDataRegister(deviceExtension,0x01)) {
DebugPrint((1,"A154xHwInitialize: Can't set timeout selection enable\n"));
}
if (!WriteDataRegister(deviceExtension,0x00)) {
DebugPrint((1,"A154xHwInitialize: Can't set second byte\n"));
}
if (!WriteDataRegister(deviceExtension,0x01)) {
DebugPrint((1,"A154xHwInitialize: Can't set MSB\n"));
}
if (!WriteDataRegister(deviceExtension,0xF4)) {
DebugPrint((1,"A154xHwInitialize: Can't set LSB\n"));
}
}
//
// Wait for interrupt.
//
if (!SpinForInterrupt(deviceExtension,TRUE)) {
DebugPrint((1,"Timed out waiting for adapter command to complete\n"));
return TRUE;
}
#if defined(_SCAM_ENABLED)
//
// SCAM because A154xHwInitialize reset's the SCSI bus.
//
PerformScamProtocol(deviceExtension);
#endif
return TRUE;
} // end A154xHwInitialize()
#if defined(_SCAM_ENABLED)
BOOLEAN
PerformScamProtocol(
IN PHW_DEVICE_EXTENSION deviceExtension
)
{
if (deviceExtension->PerformScam) {
DebugPrint((1,"AHA154x => Starting SCAM operation.\n"));
if (!WriteCommandRegister(deviceExtension, AC_PERFORM_SCAM, TRUE)) {
DebugPrint((0,"AHA154x => Adapter time out, SCAM command failure.\n"));
ScsiPortLogError(deviceExtension,
NULL,
0,
deviceExtension->HostTargetId,
0,
SP_INTERNAL_ADAPTER_ERROR,
0xA << 8);
return FALSE;
} else {
DebugPrint((1,"AHA154x => SCAM Performed OK.\n"));
return TRUE;
}
} else {
DebugPrint((1,"AHA154x => SCAM not performed, non-SCAM adapter.\n"));
return FALSE;
}
} //End PerformScamProtocol
#endif
BOOLEAN
A154xStartIo(
IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb
)
/*++
Routine Description:
This routine is called from the SCSI port driver synchronized
with the kernel. The mailboxes are scanned for an empty one and
the CCB is written to it. Then the doorbell is rung and the
OS port driver is notified that the adapter can take
another request, if any are available.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
Srb - IO request packet
Return Value:
TRUE
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PNONCACHED_EXTENSION noncachedExtension =
deviceExtension->NoncachedExtension;
PMBO mailboxOut;
PCCB ccb;
PHW_LU_EXTENSION luExtension;
ULONG i = deviceExtension->MboIndex;
ULONG physicalCcb;
ULONG length;
DebugPrint((3,"A154xStartIo: Enter routine\n"));
//
// Check if command is a WMI request.
//
if (Srb->Function == SRB_FUNCTION_WMI) {
//
// Process the WMI request and return.
//
return A154xWmiSrb(HwDeviceExtension, (PSCSI_WMI_REQUEST_BLOCK) Srb);
}
//
// Check if command is an ABORT request.
//
if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
//
// Verify that SRB to abort is still outstanding.
//
luExtension =
ScsiPortGetLogicalUnit(deviceExtension,
Srb->PathId,
Srb->TargetId,
Srb->Lun);
if ((luExtension == NULL) ||
(luExtension->CurrentSrb == NULL)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -