📄 aha154x.c
字号:
DebugPrint((1, "A154xStartIo: SRB to abort already completed\n"));
//
// Complete abort SRB.
//
Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
ScsiPortNotification(RequestComplete,
deviceExtension,
Srb);
//
// Adapter ready for next request.
//
ScsiPortNotification(NextRequest,
deviceExtension,
NULL);
return TRUE;
}
//
// Get CCB to abort.
//
ccb = Srb->NextSrb->SrbExtension;
//
// Set abort SRB for completion.
//
ccb->AbortSrb = Srb;
} else {
ccb = Srb->SrbExtension;
//
// Save SRB back pointer in CCB.
//
ccb->SrbAddress = Srb;
}
//
// Make sure that this request isn't too long for the adapter. If so
// bounce it back as an invalid request
//
if ((deviceExtension->MaxCdbLength) &&
(deviceExtension->MaxCdbLength < Srb->CdbLength)) {
DebugPrint((1,"A154xStartIo: Srb->CdbLength [%d] > MaxCdbLength [%d]. Invalid request\n",
Srb->CdbLength,
deviceExtension->MaxCdbLength
));
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
ScsiPortNotification(RequestComplete,
deviceExtension,
Srb);
ScsiPortNotification(NextRequest,
deviceExtension,
NULL);
return TRUE;
}
//
// Get CCB physical address.
//
physicalCcb = ScsiPortConvertPhysicalAddressToUlong(
ScsiPortGetPhysicalAddress(deviceExtension, NULL, ccb, &length));
//
// Find free mailboxOut.
//
do {
mailboxOut = &noncachedExtension->Mbo[i % MB_COUNT];
i++;
} while (mailboxOut->Command != MBO_FREE);
//
// Save the next free location.
//
deviceExtension->MboIndex = (UCHAR) (i % MB_COUNT);
DebugPrint((3,"A154xStartIo: MBO address %lx, Loop count = %d\n", mailboxOut, i));
//
// Write CCB to mailbox.
//
FOUR_TO_THREE(&mailboxOut->Address,
(PFOUR_BYTE)&physicalCcb);
switch (Srb->Function) {
case SRB_FUNCTION_ABORT_COMMAND:
DebugPrint((1, "A154xStartIo: Abort request received\n"));
//
// Race condition (what if CCB to be aborted
// completes after setting new SrbAddress?)
//
mailboxOut->Command = MBO_ABORT;
break;
case SRB_FUNCTION_RESET_BUS:
//
// Reset aha154x and SCSI bus.
//
DebugPrint((1, "A154xStartIo: Reset bus request received\n"));
if (!A154xResetBus(
deviceExtension,
Srb->PathId
)) {
DebugPrint((1,"A154xStartIo: Reset bus failed\n"));
Srb->SrbStatus = SRB_STATUS_ERROR;
} else {
Srb->SrbStatus = SRB_STATUS_SUCCESS;
}
ScsiPortNotification(RequestComplete,
deviceExtension,
Srb);
ScsiPortNotification(NextRequest,
deviceExtension,
NULL);
return TRUE;
case SRB_FUNCTION_EXECUTE_SCSI:
//
// Get logical unit extension.
//
luExtension =
ScsiPortGetLogicalUnit(deviceExtension,
Srb->PathId,
Srb->TargetId,
Srb->Lun);
//
// Move SRB to logical unit extension.
//
luExtension->CurrentSrb = Srb;
//
// Build CCB.
//
BuildCcb(deviceExtension, Srb);
mailboxOut->Command = MBO_START;
break;
case SRB_FUNCTION_RESET_DEVICE:
DebugPrint((1,"A154xStartIo: Reset device not supported\n"));
//
// Drop through to default.
//
default:
//
// Set error, complete request
// and signal ready for next request.
//
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
ScsiPortNotification(RequestComplete,
deviceExtension,
Srb);
ScsiPortNotification(NextRequest,
deviceExtension,
NULL);
return TRUE;
} // end switch
//
// Tell 154xb a CCB is available now.
//
if (!WriteCommandRegister(deviceExtension,AC_START_SCSI_COMMAND, FALSE)) {
//
// Let request time out and fail.
//
DebugPrint((1,"A154xStartIo: Can't write command to adapter\n"));
deviceExtension->PendingRequest = TRUE;
} else {
//
// Command(s) submitted. Clear pending request flag.
//
deviceExtension->PendingRequest = FALSE;
//
// Adapter ready for next request.
//
ScsiPortNotification(NextRequest,
deviceExtension,
NULL);
}
return TRUE;
} // end A154xStartIo()
BOOLEAN
A154xInterrupt(
IN PVOID HwDeviceExtension
)
/*++
Routine Description:
This is the interrupt service routine for the adaptec 154x SCSI adapter.
It reads the interrupt register to determine if the adapter is indeed
the source of the interrupt and clears the interrupt at the device.
If the adapter is interrupting because a mailbox is full, the CCB is
retrieved to complete the request.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
Return Value:
TRUE if MailboxIn full
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PNONCACHED_EXTENSION noncachedExtension =
deviceExtension->NoncachedExtension;
PCCB ccb;
PSCSI_REQUEST_BLOCK srb;
PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
PMBI mailboxIn;
ULONG physicalCcb;
PHW_LU_EXTENSION luExtension;
ULONG residualBytes;
ULONG i;
UCHAR InterruptFlags;
InterruptFlags = ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister);
//
// Determine cause of interrupt.
//
if(InterruptFlags == 0) {
DebugPrint((4,"A154xInterrupt: Spurious interrupt\n"));
return FALSE;
}
if (InterruptFlags & IOP_COMMAND_COMPLETE) {
//
// Adapter command completed.
//
DebugPrint((2,"A154xInterrupt: Adapter Command complete\n"));
DebugPrint((3,"A154xInterrupt: Interrupt flags %x\n", InterruptFlags));
DebugPrint((3,"A154xInterrupt: Status %x\n",
ScsiPortReadPortUchar(&baseIoAddress->StatusRegister)));
//
// Clear interrupt on adapter.
//
ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
return TRUE;
} else if (InterruptFlags & IOP_MBI_FULL) {
DebugPrint((3,"A154xInterrupt: MBI Full\n"));
//
// Clear interrupt on adapter.
//
ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
} else if (InterruptFlags & IOP_SCSI_RESET_DETECTED) {
DebugPrint((1,"A154xInterrupt: SCSI Reset detected\n"));
//
// Clear interrupt on adapter.
//
ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
//
// Notify of reset.
//
ScsiPortNotification(ResetDetected,
deviceExtension,
NULL);
#if defined(_SCAM_ENABLED)
//
// Interrupt handler where reset is detected
//
PerformScamProtocol(deviceExtension);
#endif
return TRUE;
}
//
// Determine which MailboxIn location contains the CCB.
//
for (i=0; i<MB_COUNT; i++) {
mailboxIn = &noncachedExtension->Mbi[deviceExtension->MbiIndex];
//
// Look for a mailbox entry with a legitimate status.
//
if (mailboxIn->Status != MBI_FREE) {
//
// Point to the next in box.
//
deviceExtension->MbiIndex = (deviceExtension->MbiIndex + 1) % MB_COUNT;
//
// MBI found. Convert CCB to big endian.
//
THREE_TO_FOUR((PFOUR_BYTE)&physicalCcb,
&mailboxIn->Address);
DebugPrint((3, "A154xInterrupt: Physical CCB %lx\n", physicalCcb));
//
// Check if physical CCB is zero.
// This is done to cover for hardware errors.
//
if (!physicalCcb) {
DebugPrint((1,"A154xInterrupt: Physical CCB address is 0\n"));
//
// Indicate MBI is available.
//
mailboxIn->Status = MBI_FREE;
continue;
}
//
// Convert Physical CCB to Virtual.
//
ccb = ScsiPortGetVirtualAddress(deviceExtension, ScsiPortConvertUlongToPhysicalAddress(physicalCcb));
DebugPrint((3, "A154xInterrupt: Virtual CCB %lx\n", ccb));
//
// Make sure the virtual address was found.
//
if (ccb == NULL) {
//
// A bad physcial address was return by the adapter.
// Log it as an error.
//
ScsiPortLogError(
HwDeviceExtension,
NULL,
0,
deviceExtension->HostTargetId,
0,
SP_INTERNAL_ADAPTER_ERROR,
5 << 8
);
//
// Indicate MBI is available.
//
mailboxIn->Status = MBI_FREE;
continue;
}
//
// Get SRB from CCB.
//
srb = ccb->SrbAddress;
//
// Get logical unit extension.
//
luExtension =
ScsiPortGetLogicalUnit(deviceExtension,
srb->PathId,
srb->TargetId,
srb->Lun);
//
// Make sure the luExtension was found and it has a current request.
//
if (luExtension == NULL || (luExtension->CurrentSrb == NULL &&
mailboxIn->Status != MBI_NOT_FOUND)) {
//
// A bad physcial address was return by the adapter.
// Log it as an error.
//
ScsiPortLogError(
HwDeviceExtension,
NULL,
0,
deviceExtension->HostTargetId,
0,
SP_INTERNAL_ADAPTER_ERROR,
(6 << 8) | mailboxIn->Status
);
//
// Indicate MBI is available.
//
mailboxIn->Status = MBI_FREE;
continue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -