📄 dispatchroutines.c
字号:
pdx->PRBStruct->ReceivedCount = 0x00000000;
pdx->PRBStruct->FISType = 0x27;
pdx->PRBStruct->PMP = 0x80;
pdx->PRBStruct->Command_Status = SATAREG48Buffer->cmnd;
pdx->PRBStruct->Features_Error = SATAREG48Buffer->feat_cur;
pdx->PRBStruct->SectorNumber = SATAREG48Buffer->secn_cur;
pdx->PRBStruct->CylLow = SATAREG48Buffer->cyll_cur;
pdx->PRBStruct->CylHigh = SATAREG48Buffer->cylh_cur;
pdx->PRBStruct->DevHead = SATAREG48Buffer->devh;
pdx->PRBStruct->SectorNumberExp = SATAREG48Buffer->secn_pre;
pdx->PRBStruct->CylLowExp = SATAREG48Buffer->cyll_pre;
pdx->PRBStruct->CylHighExp = SATAREG48Buffer->cylh_pre;
pdx->PRBStruct->FeaturesExp = SATAREG48Buffer->feat_pre;
pdx->PRBStruct->SectorCount = SATAREG48Buffer->secc_cur;
pdx->PRBStruct->SectorCountExp = SATAREG48Buffer->secc_pre;
pdx->PRBStruct->Reserved0 = 0x00;
pdx->PRBStruct->DeviceControl = SATAREG48Buffer->fxdc;
pdx->PRBStruct->Reserved1 = 0x00000000;
pdx->PRBStruct->Reserved2 = 0x00000000;
/******************** Begin to Fill SGE **********************************************/
pdx->LogicalAddress = (PHYSICAL_ADDRESS *)ExAllocatePool(NonPagedPool,CountOfSGE*sizeof(PHYSICAL_ADDRESS));
switch(CountOfSGE)
{
case 1:
pdx->LogicalAddress[0] = pdx->ScatterGatherList->Elements[0].Address;
DmaRead = pdx->ScatterGatherList->Elements[0].Length;
pdx->SGEControl = 0x80000000;
DebugPrint("the Address:0x%x....the Length :%u",pdx->LogicalAddress[0].LowPart,DmaRead);
pdx->PRBStruct->SGE0Low = pdx->LogicalAddress[0].LowPart;
pdx->PRBStruct->SGE0High = 0x00000000;
pdx->PRBStruct->SGE0Count = DmaRead;
pdx->PRBStruct->SGE0Control = pdx->SGEControl;
break;
case 2:
// fill first SGE
pdx->LogicalAddress[0] = pdx->ScatterGatherList->Elements[0].Address;
DmaRead = pdx->ScatterGatherList->Elements[0].Length;
pdx->SGEControl = 0x00000000;
DebugPrint("the Address:0x%x....the Length :%u",pdx->LogicalAddress[0].LowPart,DmaRead);
pdx->PRBStruct->SGE0Low = pdx->LogicalAddress[0].LowPart;
pdx->PRBStruct->SGE0High = 0x00000000;
pdx->PRBStruct->SGE0Count = DmaRead;
pdx->PRBStruct->SGE0Control = pdx->SGEControl;
//fill second SGE
pdx->LogicalAddress[1] = pdx->ScatterGatherList->Elements[1].Address;
DmaRead = pdx->ScatterGatherList->Elements[1].Length;
pdx->SGEControl = 0x80000000;
DebugPrint("the Address:0x%x....the Length :%u",pdx->LogicalAddress[1].LowPart,DmaRead);
pdx->PRBStruct->SGE1Low = pdx->LogicalAddress[1].LowPart;
pdx->PRBStruct->SGE1High = 0x00000000;
pdx->PRBStruct->SGE1Count = DmaRead;
pdx->PRBStruct->SGE1Control = pdx->SGEControl;
break;
default:
//if the requested SGE count is larger than two,then we must build SGT in host.
// fill first SGE
pdx->LogicalAddress[0] = pdx->ScatterGatherList->Elements[0].Address;
DmaRead = pdx->ScatterGatherList->Elements[0].Length;
pdx->SGEControl = 0x00000000;
DebugPrint("the Address:0x%x....the Length :%u",pdx->LogicalAddress[0].LowPart,DmaRead);
pdx->PRBStruct->SGE0Low = pdx->LogicalAddress[0].LowPart;
pdx->PRBStruct->SGE0High = 0x00000000;
pdx->PRBStruct->SGE0Count = DmaRead;
pdx->PRBStruct->SGE0Control = pdx->SGEControl;
//calculate the count of needed SG Table
SGTCount = CountOfSGE/3;
SGTRem = CountOfSGE%3;
DebugPrint("the count of SG table:%u",SGTCount);
pdx->SGTPAddress = (PHYSICAL_ADDRESS *)ExAllocatePool(NonPagedPool,SGTCount*sizeof(PHYSICAL_ADDRESS));
pdx->pSGT = (pSGTable)ExAllocatePool(NonPagedPool,SGTCount*sizeof(SGTable));
// DebugPrint("SGT system address is:0x%x",(ULONG)pdx->pSGT);
for(i = 0;i<SGTCount;i++)
{
pdx->SGTPAddress[i] = MmGetPhysicalAddress(pdx->pSGT+i);
DebugPrint("SGT Physical address is:0x%x",(ULONG)pdx->SGTPAddress[i].LowPart);
//Make SGT 8 bytes aligned
while((pdx->SGTPAddress[i].LowPart)% 8 != 0)
{
ExFreePool(pdx->pSGT);
pdx->pSGT = (pSGTable)ExAllocatePool(NonPagedPool,SGTCount*sizeof(SGTable));
for(j=0;j<SGTCount;j++)
pdx->SGTPAddress[j] = MmGetPhysicalAddress(pdx->pSGT+j);
DebugPrint(" After ReAllocate Physical Address is:0x%x\n" ,pdx->SGTPAddress[j].LowPart );
DebugPrint(" After ReAllocate System Address is:0x%x\n" ,(ULONG)pdx->pSGT);
}
}
//fill second SGE which contains the following SGT's address
pdx->LogicalAddress[1] = pdx->SGTPAddress[0];
// DmaRead = pdx->ScatterGatherList->Elements[1].Length;
pdx->SGEControl = 0x40000000;
DebugPrint("the first SGT's Address:0x%x....",pdx->LogicalAddress[1].LowPart);
pdx->PRBStruct->SGE1Low = pdx->LogicalAddress[1].LowPart;
pdx->PRBStruct->SGE1High = 0x00000000;
// pdx->PRBStruct->SGE1Count = DmaRead;
pdx->PRBStruct->SGE1Control = pdx->SGEControl;
//fill SGT
j = 0;
for(i = 0;i<SGTCount;i++)
{
if(i == SGTCount-1)
{
DebugPrint("now the start elements index:%u",i+j+1);
(pdx->pSGT+i)->SGE0Low = pdx->ScatterGatherList->Elements[i+j+1].Address.LowPart;
(pdx->pSGT+i)->SGE0High = 0x00000000;
(pdx->pSGT+i)->SGE0Count = pdx->ScatterGatherList->Elements[i+j+1].Length;
(pdx->pSGT+i)->SGE0Control = 0x00000000;
(pdx->pSGT+i)->SGE1Low = pdx->ScatterGatherList->Elements[i+j+2].Address.LowPart;
(pdx->pSGT+i)->SGE1High = 0x00000000;
(pdx->pSGT+i)->SGE1Count = pdx->ScatterGatherList->Elements[i+j+2].Length;
if(SGTRem == 0)
(pdx->pSGT+i)->SGE1Control = 0x80000000;
else if(SGTRem == 1)
{
(pdx->pSGT+i)->SGE1Control = 0x00000000;
(pdx->pSGT+i)->SGE2Low = pdx->ScatterGatherList->Elements[i+j+3].Address.LowPart;
(pdx->pSGT+i)->SGE2High = 0x00000000;
(pdx->pSGT+i)->SGE2Count = pdx->ScatterGatherList->Elements[i+j+3].Length;
(pdx->pSGT+i)->SGE2Control = 0x80000000;
}
else
{
(pdx->pSGT+i)->SGE1Control = 0x00000000;
(pdx->pSGT+i)->SGE2Low = pdx->ScatterGatherList->Elements[i+j+3].Address.LowPart;
(pdx->pSGT+i)->SGE2High = 0x00000000;
(pdx->pSGT+i)->SGE2Count = pdx->ScatterGatherList->Elements[i+j+3].Length;
(pdx->pSGT+i)->SGE2Control = 0x00000000;
(pdx->pSGT+i)->SGE3Low = pdx->ScatterGatherList->Elements[i+j+4].Address.LowPart;
(pdx->pSGT+i)->SGE3High = 0x00000000;
(pdx->pSGT+i)->SGE3Count = pdx->ScatterGatherList->Elements[i+j+4].Length;
(pdx->pSGT+i)->SGE3Control = 0x80000000;
}
}
else
{ DebugPrint("now the start elements index:%u",i+j+1);
(pdx->pSGT+i)->SGE0Low = pdx->ScatterGatherList->Elements[i+j+1].Address.LowPart;
(pdx->pSGT+i)->SGE0High = 0x00000000;
(pdx->pSGT+i)->SGE0Count = pdx->ScatterGatherList->Elements[i+j+1].Length;
(pdx->pSGT+i)->SGE0Control = 0x00000000;
(pdx->pSGT+i)->SGE1Low = pdx->ScatterGatherList->Elements[i+j+2].Address.LowPart;
(pdx->pSGT+i)->SGE1High = 0x00000000;
(pdx->pSGT+i)->SGE1Count = pdx->ScatterGatherList->Elements[i+j+2].Length;
(pdx->pSGT+i)->SGE1Control = 0x00000000;
(pdx->pSGT+i)->SGE2Low = pdx->ScatterGatherList->Elements[i+j+3].Address.LowPart;
(pdx->pSGT+i)->SGE2High = 0x00000000;
(pdx->pSGT+i)->SGE2Count = pdx->ScatterGatherList->Elements[i+j+3].Length;
(pdx->pSGT+i)->SGE2Control = 0x00000000;
(pdx->pSGT+i)->SGE3Low = pdx->SGTPAddress[i+1].LowPart;
(pdx->pSGT+i)->SGE3High = 0x00000000;
// (pdx->pSGT+i)->SGE3Count = pdx->ScatterGatherList->Elements[i+4].Length;
(pdx->pSGT+i)->SGE3Control = 0x40000000;
}
j+=2;
}
break;
}
/**************************Fill End*********************************************************************/
DebugPrint("the port interrupt status 0x%x",READ_REGISTER_ULONG((PULONG)(PortBaseAddress+0x1008)));
WRITE_REGISTER_ULONG((PULONG)(PortBaseAddress+0x1C00),PAddress.LowPart);
WRITE_REGISTER_ULONG((PULONG)(PortBaseAddress+0x1C04),0x00000000);
pdx->NeedToHandle = TRUE;
DebugPrint("the port slot status as soon as command is issued 0x%x",READ_REGISTER_ULONG((PULONG)(PortBaseAddress+0x1800)));
if(pdx->pDmaContext)
{
ExFreePool(pdx->pDmaContext);
DebugPrint("ExFreePool pdx->pDmaContext");
pdx->pDmaContext = NULL;
}
}
/******************************************************************************
*
* Function : OnInterrupt
*
* Description: The Interrupt Service Routine for the device.
*
* Note:IRS run at DIRQL,so handle carefully
******************************************************************************/
BOOLEAN OnInterrupt(IN PKINTERRUPT pInterrupt,
IN PDEVICE_EXTENSION pdx)//IN PVOID pdx)
{ //OnInterrupt
PDEVICE_OBJECT fdo;
PIRP pIrp;
UCHAR CompleteStatus,ClearInterruptStatus;
if(!pdx->NeedToHandle)
return TRUE;
DebugPrint("Enter ISR Routine...........");
DebugPrint("0x%x,",READ_REGISTER_ULONG((PULONG)(pdx->PortBaseAddress+0x1010)));
DebugPrint("0x%x,0x%x",READ_REGISTER_ULONG((PULONG)(pdx->PortBaseAddress+0x1000)),READ_REGISTER_ULONG((PULONG)(pdx->PortBaseAddress+0x1008)));
CompleteStatus = READ_REGISTER_UCHAR((PUCHAR)(pdx->PortBaseAddress+0x1008));
CompleteStatus &= 0x01;
if(CompleteStatus != 0x01) //check if it is Sil3124's Command Completion Interrupt
{
return TRUE;
}
ClearInterruptStatus = READ_REGISTER_UCHAR((PUCHAR)(pdx->PortBaseAddress+0x1000));
ClearInterruptStatus &= 0x08;
if(ClearInterruptStatus ==0x00)//if Interrupt NCoR ==0
READ_REGISTER_ULONG((PULONG)(pdx->PortBaseAddress+0x1800)); //read port slot status register to clear completion command interrupt
else
WRITE_REGISTER_UCHAR((PUCHAR)pdx->PortBaseAddress+0x1008,0x01);// write 1 to port interrupt status clear register to clear the completion
WRITE_REGISTER_UCHAR((PUCHAR)pdx->PortBaseAddress+0x1008,0x04);//clear the Port Ready Interrupt
//if it is command completion interrupt,set NeedToHandle condition to FLASE,
//it makes power management change interrupt can not be handle by following progress
pdx->NeedToHandle = FALSE;
fdo = ((PDEVICE_EXTENSION)pdx)->pDeviceObject;
if (fdo != NULL)
{
pIrp = fdo->CurrentIrp;
if (pIrp != NULL)
{
IoRequestDpc(fdo, pIrp, (PVOID)pdx);
}
}
return TRUE;
} //OnInterrupt
/******************************************************************************
*
* Function : DpcForIsr
*
* Description: This routine will be triggered by the ISR to service an interrupt.
******************************************************************************/
VOID DpcForIsr(IN PKDPC pDpc,
IN PDEVICE_OBJECT fdo,
IN PIRP pIrp,
IN PDEVICE_EXTENSION pdx)
{ //OnInterrupt DpcForIsr
NTSTATUS status;
ULONG ReturnedValue;
PIO_STACK_LOCATION pIrpStack;
PVOID IoBuffer;
PDMA_ADAPTER pAdapterObject;
PDMA_OPERATIONS pDmaOperation;
DebugPrint("Enter DPC For ISR Routine...........");
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
ReturnedValue = READ_REGISTER_ULONG((PULONG)(pdx->PortBaseAddress+0x04));
IoBuffer = pIrp->AssociatedIrp.SystemBuffer;
status = STATUS_SUCCESS;
switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_3124REGISTER_PIO_READ:
DebugPrint("Sil3124 PIO read enter DPC...");
//copy the data to be written into disk to the WriteBuffer
RtlMoveMemory(IoBuffer,pdx->ReadBuffer,ReturnedValue);
if(pdx->ReadBuffer)
{
ExFreePool(pdx->ReadBuffer);
pdx->ReadBuffer = NULL;
DebugPrint("free pdx->readbuffer");
}
if(pdx->PRBStruct)
{
ExFreePool(pdx->PRBStruct);
pdx->PRBStruct = NULL;
DebugPrint("free pdx->PRBStruct");
}
pdx->BytesTransfered = ReturnedValue;
status = STATUS_SUCCESS;
break;
case IOCTL_3124REGISTER_PIO_WRITE:
DebugPrint("Sil3124 PIO write enter DPC...");
if(pdx->WriteBuffer)
{
ExFreePool(pdx->WriteBuffer);
pdx->WriteBuffer = NULL;
DebugPrint("free pdx->Writebuffer");
}
if(pdx->PRBStruct)
{
ExFreePool(pdx->PRBStruct);
pdx->PRBStruct = NULL;
DebugPrint("free pdx->PRBStruct");
}
pdx->BytesTransfered = pdx->TansferedCount;
status = STATUS_SUCCESS;
break;
case IOCTL_3124REGISTER_COMMAND:
DebugPrint("Sil3124 PIO no data transfer commands enter DPC...");
if(pdx->PRBStruct)
{
ExFreePool(pdx->PRBStruct);
pdx->PRBStruct = NULL;
DebugPrint("free pdx->PRBStruct");
}
pdx->BytesTransfered = 0;
status = STATUS_SUCCESS;
break;
case IOCTL_3124_DMA_READ:
case IOCTL_3124_DMA_WRITE:
DebugPrint("Sil3124 DMA transfer enter DPC...");
if(pdx->LogicalAddress)
{
ExFreePool(pdx->LogicalAddress);
DebugPrint("free pdx->LogiclAddress");
pdx->LogicalAddress = NULL;
}
if(pdx->pSGT)
{
ExFreePool(pdx->pSGT);
DebugPrint("free pdx->pSGT");
pdx->pSGT = NULL;
}
if(pdx->SGTPAddress)
{
ExFreePool(pdx->SGTPAddress);
DebugPri
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -