I’m writing a resource manager for my PCI card. The program correctly
detects my card, creates a device in /dev, and all the other things a
resource manager is supposed to do. But I can’t figure out why my
io_devctl isn’t working.
My devctl resource manager function, basically looks like this:
int
ve2_devctl(resmgr_context_t* ctp, io_devctl_t* msg, ve2_ocb_t* ocb)
{
// If it’s a standard POSIX-supported devctl(), let Neutrino
// handle it.
int result = iofunc_devctl_default(ctp, msg, &ocb->ocb);
if (_RESMGR_DEFAULT == result)
{
int nbytes = 0;
void* data = _DEVCTL_DATA(msg);
result = _RESMGR_NPARTS(1);
switch (msg->i.dcmd)
{
case DEVC_VE2_CONTROL_FUNC
ControlArgs* const args = (ControlArgs*) data;
// Calculate how much data is in the message already
const int ctpDataSize = ctp->size - sizeof(*msg);
std::cout << “Received message with " << ctpDataSize
<< " size” << std::endl;
ve2_control(*ocb, *args);
nbytes = args->fSizeOfArgs;
break;
default:
std::cout << “Unknown dcmd " << std::hex << msg->i.dcmd
<< " received” << std::endl;
// Unknown command
result = ENOSYS;
break;
}
memset(&msg->o, 0, sizeof(msg->o));
msg->o.nbytes = nbytes;
SETIOV(ctp->iov, &msg->o, sizeof(msg->o) + nbytes);
}
return result;
}
Similarly, the call site in the client application looks like this:
{
ControlArgs args;
… fill in the args structure appropriately
devctl(fd, DEVC_VE2_CONTROL_FUNC, &args, sizeof(args), NULL);
}
And the command is defined like this:
#define DEVC_VE2_CONTROL_FUNC __DIOTF(_DCMD_VE2,
VE2_DCMD_GET_PHYSICAL,
ControlArgs)
Each time ve2_devctl is called, it prints out a size which seems
appropriate for the ControlArgs structure (e.g. ctpDataSize ==
sizeof(ControlArgs)). However, when ve2_control tries to access data
inside the args structure, the data it reads is not what the client
application put in it. It’s almost like Neutrino is not properly copying
the data from the client’s argument structure into my resource manager’s
application.
What’s more, if ve2_devctl changes the data in its ControlArgs, that
data is never returned to the client. If I print out msg->i.dcmd, the
command shows both high order bits set, indicating a data transfer both
two and from the resource manager program. I’m stymied.
Am I doing something wrong in my io_devctl routine? Is there more I
shoud do? Isn’t it sufficient to check ctp->size to see if the entire
message has arrived?
Any pointers or assistance is appreciated. Thanks in advance.