📄 amcc_orig.cpp
字号:
/*
Function Name:
SheldonFIFOWrite
Routine Description:
Write to the FIFO.
Arguments:
Irp - I/O request being serviced
pdx - pointer to the device extension.
Return Value:
STATUS_SUCCESS
*/
NTSTATUS SheldonFIFOWrite(PIRP Irp, PDEVICE_EXTENSION pdx)
{
PULONG params;
// get a ULONG pointer to the mailbox number
params = (PULONG) Irp->AssociatedIrp.SystemBuffer;
// write the data
/////////////////
// IO and memory mapped
/////////////////
if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
// make sure the write FIFO is not full, as writing to a full FIFO locks
// the machine with this PCI controller
if(READ_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR) & AMCC_WRITE_FIFO_FULL_MASK)
return STATUS_BUFFER_TOO_SMALL;
WRITE_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_FIFO, *params);
}
else {
// make sure the write FIFO is not full, as writing to a full FIFO locks
// the machine with this PCI controller
if(READ_PORT_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR) & AMCC_WRITE_FIFO_FULL_MASK)
return STATUS_BUFFER_TOO_SMALL;
WRITE_PORT_ULONG(pdx->base[AMCC_OPREGS] + AMCC_FIFO, *params);
}
/////////////////
// Memory mapped Only
/////////////////
// // make sure the write FIFO is not full, as writing to a full FIFO locks
// // the machine with this PCI controller
// if(READ_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_MCSR) & AMCC_WRITE_FIFO_FULL_MASK)
// return STATUS_BUFFER_TOO_SMALL;
//
// WRITE_REGISTER_ULONG(pdx->base[AMCC_OPREGS] + AMCC_FIFO, *params);
return STATUS_SUCCESS;
}
/*
Function Name:
SheldonNVRead
Routine Description:
Read from the NVRam.
Arguments:
Irp - I/O request being serviced
pdx - pointer to the device extension.
Return Value:
STATUS_SUCCESS if successful
STATUS_TIMEOUT if timeout occurs
*/
NTSTATUS SheldonNVRamRead(PIRP Irp, PDEVICE_EXTENSION pdx)
{
PULONG params;
PUCHAR NV_Control_Reg, NV_Data_Reg;
ULONG Attempts = 0;
params = (PULONG) Irp->AssociatedIrp.SystemBuffer;
NV_Control_Reg = ((PUCHAR) (pdx->base[AMCC_OPREGS])) + AMCC_NV_CONTROL_REG_OFFSET;
NV_Data_Reg=((PUCHAR) (pdx->base[AMCC_OPREGS])) + AMCC_NV_DATA_REG_OFFSET;
/////////////////
// IO and memory mapped
/////////////////
if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
// wait while device busy
while(Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if(Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
// once free, set the control reg for low address
WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_LOW_ADDRESS_COMMAND);
// then write the low part of the address
WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) (*params & 0x000000FF));
// set up for high half of address
WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_HIGH_ADDRESS_COMMAND);
// then write the high part of the address
WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) ((*params >> 8) & 0x000000FF));
// now send the read command
WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_READ_COMMAND);
Attempts = 0; // reset the timeout counter
// wait while device busy
while(Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if(Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
// now read the data and put it into the outgoing buffer
*params = (ULONG) READ_REGISTER_UCHAR(NV_Data_Reg);
}
else {
// wait while device busy
while(Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_PORT_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if(Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
// once free, set the control reg for low address
WRITE_PORT_UCHAR(NV_Control_Reg, AMCC_NV_LOW_ADDRESS_COMMAND);
// then write the low part of the address
WRITE_PORT_UCHAR(NV_Data_Reg, (UCHAR) (*params & 0x000000FF));
// set up for high half of address
WRITE_PORT_UCHAR(NV_Control_Reg, AMCC_NV_HIGH_ADDRESS_COMMAND);
// then write the high part of the address
WRITE_PORT_UCHAR(NV_Data_Reg, (UCHAR) ((*params >> 8) & 0x000000FF));
// now send the read command
WRITE_PORT_UCHAR(NV_Control_Reg, AMCC_NV_READ_COMMAND);
Attempts = 0; // reset the timeout counter
// wait while device busy
while(Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_PORT_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if(Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
// now read the data and put it into the outgoing buffer
*params = (ULONG) READ_PORT_UCHAR(NV_Data_Reg);
}
/////////////////
// Memory mapped Only
/////////////////
// // wait while device busy
// while(Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
// Attempts++;
//
// if(Attempts == AMCC_NV_MAX_ATTEMPTS)
// return STATUS_TIMEOUT;
//
// // once free, set the control reg for low address
// WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_LOW_ADDRESS_COMMAND);
// // then write the low part of the address
// WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) (*params & 0x000000FF));
// // set up for high half of address
// WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_HIGH_ADDRESS_COMMAND);
// // then write the high part of the address
// WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) ((*params >> 8) & 0x000000FF));
// // now send the read command
// WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_READ_COMMAND);
//
// Attempts = 0; // reset the timeout counter
//
// // wait while device busy
// while(Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
// Attempts++;
//
// if(Attempts == AMCC_NV_MAX_ATTEMPTS)
// return STATUS_TIMEOUT;
//
// // now read the data and put it into the outgoing buffer
// *params = (ULONG) READ_REGISTER_UCHAR(NV_Data_Reg);
return STATUS_SUCCESS;
}
/*
Function Name:
SheldonNVRAMWrite
Routine Description:
Write to the NVRam.
Arguments:
Irp - I/O request being serviced
pdx - pointer to the device extension.
Return Value:
STATUS_SUCCESS if successful
STATUS_TIMEOUT if timeout occurs
*/
NTSTATUS SheldonNVRamWrite(PIRP Irp, PDEVICE_EXTENSION pdx)
{
PULONG params;
PUCHAR NV_Control_Reg, NV_Data_Reg;
ULONG Attempts = 0;
params = (PULONG) Irp->AssociatedIrp.SystemBuffer;
NV_Control_Reg = ((PUCHAR) (pdx->base[AMCC_OPREGS])) + AMCC_NV_CONTROL_REG_OFFSET;
NV_Data_Reg=((PUCHAR) (pdx->base[AMCC_OPREGS])) + AMCC_NV_DATA_REG_OFFSET;
/////////////////
// IO and memory mapped
/////////////////
if( (ULONG)pdx->base[AMCC_OPREGS] & 0xffff0000 ) {
// wait while device busy
while (Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if (Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
// once free, set the control reg for low address
WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_LOW_ADDRESS_COMMAND);
// then write the low part of the address
WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) (params[SI_NV_OFFSET_INDEX] & 0x000000FF));
// set up for high half of address
WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_HIGH_ADDRESS_COMMAND);
// then write the high part of the address
WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) ((params[SI_NV_OFFSET_INDEX] >> 8) & 0x000000FF));
// now send a dummy command to latch the address
WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_NO_COMMAND);
// now set the data into the data reg
WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) params[SI_NV_WRITE_DATA_INDEX]);
// now send the write command
WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_WRITE_COMMAND);
// wait while device busy
while (Attempts<AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if (Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
}
else {
// wait while device busy
while (Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_PORT_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if (Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
// once free, set the control reg for low address
WRITE_PORT_UCHAR(NV_Control_Reg, AMCC_NV_LOW_ADDRESS_COMMAND);
// then write the low part of the address
WRITE_PORT_UCHAR(NV_Data_Reg, (UCHAR) (params[SI_NV_OFFSET_INDEX] & 0x000000FF));
// set up for high half of address
WRITE_PORT_UCHAR(NV_Control_Reg, AMCC_NV_HIGH_ADDRESS_COMMAND);
// then write the high part of the address
WRITE_PORT_UCHAR(NV_Data_Reg, (UCHAR) ((params[SI_NV_OFFSET_INDEX] >> 8) & 0x000000FF));
// now send a dummy command to latch the address
WRITE_PORT_UCHAR(NV_Control_Reg, AMCC_NV_NO_COMMAND);
// now set the data into the data reg
WRITE_PORT_UCHAR(NV_Data_Reg, (UCHAR) params[SI_NV_WRITE_DATA_INDEX]);
// now send the write command
WRITE_PORT_UCHAR(NV_Control_Reg, AMCC_NV_WRITE_COMMAND);
// wait while device busy
while (Attempts<AMCC_NV_MAX_ATTEMPTS && (READ_PORT_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
Attempts++;
if (Attempts == AMCC_NV_MAX_ATTEMPTS)
return STATUS_TIMEOUT;
}
/////////////////
// Memory mapped Only
/////////////////
// // wait while device busy
// while (Attempts < AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
// Attempts++;
//
// if (Attempts == AMCC_NV_MAX_ATTEMPTS)
// return STATUS_TIMEOUT;
//
// // once free, set the control reg for low address
// WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_LOW_ADDRESS_COMMAND);
// // then write the low part of the address
// WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) (params[SI_NV_OFFSET_INDEX] & 0x000000FF));
// // set up for high half of address
// WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_HIGH_ADDRESS_COMMAND);
// // then write the high part of the address
// WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) ((params[SI_NV_OFFSET_INDEX] >> 8) & 0x000000FF));
// // now send a dummy command to latch the address
// WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_NO_COMMAND);
// // now set the data into the data reg
// WRITE_REGISTER_UCHAR(NV_Data_Reg, (UCHAR) params[SI_NV_WRITE_DATA_INDEX]);
// // now send the write command
// WRITE_REGISTER_UCHAR(NV_Control_Reg, AMCC_NV_WRITE_COMMAND);
//
// // wait while device busy
// while (Attempts<AMCC_NV_MAX_ATTEMPTS && (READ_REGISTER_UCHAR(NV_Control_Reg) & AMCC_NV_BUSY_MASK))
// Attempts++;
//
// if (Attempts == AMCC_NV_MAX_ATTEMPTS)
// return STATUS_TIMEOUT;
return STATUS_SUCCESS;
}
/*
Function Name:
SheldonMapDirect
Routine Description:
Enables the user application to directly access the memory map of the device.
Arguments:
Irp - I/O request being serviced
pdx - pointer to the device extension.
Return Value:
STATUS_SUCCESS if successful
NT status code
*/
NTSTATUS SheldonMapDirect(PIRP Irp, PDEVICE_EXTENSION pdx)
{
PULONG params;
NTSTATUS ntStatus = STATUS_SUCCESS;
int i;
ULONG length;
UNICODE_STRING physicalMemoryUnicodeString;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE physicalMemoryHandle = NULL;
PVOID PhysicalMemorySection = NULL;
PHYSICAL_ADDRESS viewBase;
ULONG virtualAddress;
KdPrint(("SIWDM - Entering SheldonMapDirect\n"));
// get a ULONG pointer to the mailbox number
params = (PULONG) Irp->AssociatedIrp.SystemBuffer;
for(i=0;i<PCI_TYPE0_ADDRESSES;i++)
{
// Section Used
if(pdx->base[i])
{
pdx->Mdl[i] = IoAllocateMdl((PVOID) pdx->base[i],
pdx->base_len[i], FALSE,
FALSE, NULL);
if(pdx->Mdl[i] == NULL)
{
SheldonUnMapDirect(pdx);
return STATUS_NO_MEMORY;
}
__try
{
MmBuildMdlForNonPagedPool(pdx->Mdl[i]);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("SIWDM - SheldonMapDirect: MmBuildMdlForNonPagedPool Exception\n"));
SheldonUnMapDirect(pdx);
return STATUS_NO_MEMORY;
}
__try
{
pdx->Direct_Baddr[i] =
((PULONG) (((ULONG) PAGE_ALIGN(MmMapLockedPages(pdx->Mdl[i], UserMode)))
+ MmGetMdlByteOffset(pdx->Mdl[i])));
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("SIWDM - SheldonMapDirect: MmMapLockedPages Exception\n"));
SheldonUnMapDirect(pdx);
return STATUS_NO_MEMORY;
}
params[i] = (ULONG) pdx->Direct_Baddr[i];
}
// not used
else
params[i] = 0;
}
KdPrint(("SIWDM - Exiting SheldonMapDirect\n"));
return ntStatus;
}
/*
Function Name:
SheldonUnMapDirect
Routine Description:
Frees the memory allocated by SheldonMapDirect.
Arguments:
pdx - pointer to the device extension.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -