Hello,
I read the suggested articles and deepened my knowledge in windows driver development.
I came to the conclusion, that it's the best way to start with the driver/application communication and began to implement IOCTLs.
This went fine and I can call my own IOCTLs from a test application.
The next step was to read and write registers.
I implemented an IOCTL that takes a memory offset and returns the value:
=================================================
case IOCTL_CM_REGISTER_READ:
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Called IOCTL_CM_REGISTER_READ\n");
status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
if(!NT_SUCCESS(status)) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
ASSERT(bufSize == InputBufferLength);
regdata = *(PREGDATA)inBuf;
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Application sent: %08X\n", regdata.offset);
status = WdfRequestRetrieveOutputBuffer(Request, 0, &outBuf, &bufSize);
if(!NT_SUCCESS(status)) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
ASSERT(bufSize == OutputBufferLength);
// Writing to the buffer over-writes the input buffer content
//
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Reading at: "%p"\n", devCtx->RegsBase+regdata.offset);
regdata.data = *(unsigned int*)(devCtx->RegsBase+regdata.offset);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Driver read: "%08X" at offset "%08X"\n", regdata.data, regdata.offset);
regdata.data = (unsigned int)READ_REGISTER_UCHAR(devCtx->RegsBase+regdata.offset);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Driver read (READ_REGISTER_ULONG): "%08X" at offset "%08X"\n", regdata.data, regdata.offset); // Unexpected data
RtlCopyMemory(outBuf, ®data, OutputBufferLength);
// Assign the length of the data copied to IoStatus.Information
// of the request and complete the request.
//
WdfRequestSetInformation(Request,
OutputBufferLength < datalen ? OutputBufferLength:datalen);
// When the request is completed the content of the SystemBuffer
// is copied to the User output buffer and the SystemBuffer is
// is freed.
break;
As you can see, I tried two ways of reading: simply return the value, or use READ_REGISTER_UCHAR.
Both ways lead to the same result: I am getting values in the dumps, and these are the same everything I try it.
So far so good.
Then I wanted to write registers. But it seems the registers are read-only or something. No matter how i try it, the value in the registers remains unchanged.
Here's my code:
=================================================
case IOCTL_CM_REGISTER_WRITE:
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Called IOCTL_CM_REGISTER_WRITE\n");
status = WdfRequestRetrieveInputBuffer(Request, 0, &inBuf, &bufSize);
if(!NT_SUCCESS(status)) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
ASSERT(bufSize == InputBufferLength);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "InputBuffer: %p , BufferSize: %08X", inBuf, bufSize);
regdata = *(PREGDATA)inBuf;
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Regdata: Offset-> %08X Size->%08X", regdata.offset, sizeof(regdata.data));
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Application wants to write "%08X" to offset "%08X"\n", regdata.data, regdata.offset);
// Writing to the buffer over-writes the input buffer content
//
memPointer = (PULONG)(devCtx->RegsBase + regdata.offset);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Address: %p\n", memPointer);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Data at %p before copy: 0x%08X", memPointer, *memPointer);
regdata.data = *(PULONG)(devCtx->RegsBase+regdata.offset);
regdata.data = regdata.data | ( 1 << 1);
//memcpy(memPointer, ®data.data, sizeof(regdata.data));
WRITE_REGISTER_ULONG(memPointer, regdata.data);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Data at %p after copy: 0x%08X", memPointer, *memPointer);
regdata.data = 0;
regdata.offset = 0;
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTLS, "Data at %p after reset: 0x%08X", memPointer, *memPointer);
// Assign the length of the data copied to IoStatus.Information
// of the request and complete the request.
//
WdfRequestSetInformation(Request,
InputBufferLength < datalen ? InputBufferLength:datalen);
// When the request is completed the content of the SystemBuffer
// is copied to the User output buffer and the SystemBuffer is
// is freed.
break;
Again I tried two methods: direct writing and using WRITE_REGISTER_ULONG. The result was the same: no changes...
My question is now: Is my code correct and maybe I'm missing something related to my hardware?
Or is something wrong in the way I try to read and write registers?
mapping of registers:
// Map in the Registers Memory resource: BAR1
devCtx->RegsBase = (PUCHAR) MmMapIoSpace( regsBasePA,
regsLength,
MmNonCached );
devCtx->RegsLength = regsLength;
// Set seperated pointer to PCI5020_REGS structure.
devCtx->Regs = (PREG5020) devCtx->RegsBase;
Thanks in advance,
Florian