io_devctl message isn't getting into my resource manager

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.

I am having the same problem, the DEVCTL_DATA macro does a memory index
into the io_devctl_t structure, but if you look at the structure
definition in iomsg.h, the data in that structure have been commented
out - it may just be a helpful comment, but something has gone awry and
the data area has not been initialised in the right place or sthg.

Maybe the DEVCTL_MSG macro needs to be modified to match some change
there. My program does report that the data has been transferred, but
it is not where I think it should be.

I am watching for some more informed response :slight_smile:

Simon

In article <berdahl-473A8F.17391910112000@inn.qnx.com>, Eric Berdahl
<berdahl@intelligentparadigm.com> writes

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.


Simon Wakley

Eric Berdahl a écrit :

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.

Ok, I’m not absolutely sure about the issue because I didn’t really
understand the reason of the tip and it may be only true in 2.00. I think
your problem comes from the fact you don’t reread the message (which is the
recommended method according to QSSL).
As far as I remember (but I’d like to read the true answer from QNX to
understand what is about) there is a problem with the size field in the ctp
structure which seems not to be filled correctly if you receive a simple
message instead of a combined message. So, if it’s the case, it’s simple to
verify, you can solve your problem like that:

typedef struct {
struct _io_msg hdr;
int msgLen;
}your_msg_t;

int
ve2_devctl(resmgr_context_t* ctp, io_devctl_t* msg, ve2_ocb_t* ocb)
{
your_msg_type_t your_msg;
char *body;

Msgread(ctp->rcvid, &your_msg, sizeof(your_msg), 0);
body = malloc(your_msg.msgLen);

Msgread(ctp->rcvid, body, your_msg.msgLen, sizeof(your_msg.msgLen);


}


The problem, if I’m not completely out of the bound, is that we make the
transfert twice by doing that (I think).

Alain.

In article <3A0FBB8A.D9FCCA5E@icbt.com>, Alain Bonnefoy
<alain.bonnefoy@icbt.com> wrote:

Ok, I’m not absolutely sure about the issue because I didn’t really
understand the reason of the tip and it may be only true in 2.00. I think
your problem comes from the fact you don’t reread the message (which is
the
recommended method according to QSSL).

Interesting. From all the docs I’ve found – the QNX online docs and
Krten’s book – rereading the message is not the recommended method
unless the message is particularly large.

What’s more, ctp->size is supposed to be the size of the data read from
the message. So, my understanding is that I don’t have to reread the
message if ctp->size is large enough. Can someone from QNX confirm this
assumption?

As far as I remember (but I’d like to read the true answer from QNX to
understand what is about) there is a problem with the size field in the
ctp
structure which seems not to be filled correctly if you receive a simple
message instead of a combined message. So, if it’s the case, it’s simple
to
verify, you can solve your problem like that:

typedef struct {
struct _io_msg hdr;
int msgLen;
}your_msg_t;

Ok, so you recommend that I reread the entire message. I see that that
will fix my “getting data from the client to the resource manager”
problem. What’s the best way to return data to the client from the
resource manager? I can’t seem to get that to work either.

Eric

Curiouser and curiouser.

I’ve broken down the sample to something pathetically simple, and I
still can’t get it to work. I started with rm1.c from Rob Krten’s web
site (a basic /dev/null implementation using Resource Manager APIs found
in his Neutrino book). From that base, I changed the device name to
/dev/quack and changed the devctl routine to be my custom routine:

int
quack_devctl (resmgr_context_t *ctp, io_devctl_t *msg,
iofunc_ocb_t ocb)
{
int sts;
void
data;
int nbytes;

if ((sts = iofunc_devctl_default (ctp, msg, ocb)) !=
_RESMGR_DEFAULT) {
return (sts);
}

// 1) assign a pointer to the data area of the message
data = _DEVCTL_DATA (msg);

// 2) preset the number of bytes that we’ll return to zero
nbytes = 0;

// check for all commands, we’ll just show the ones we’re
// interested in here
switch (msg → i.dcmd) {
// 3) process the SET command
case DCMD_AUDIO_SET_SAMPLE_RATE:
printf(“Setting sample rate to %x\n”, * (int*) data);
break;

// 4) process the GET command
case DCMD_AUDIO_GET_SAMPLE_RATE:

  • (int *) data = 0x55AA;
    nbytes = sizeof (int);
    break;
    }

// 5) return data (if any) to the client
memset (&msg → o, 0, sizeof (msg → o));
msg → o.nbytes = nbytes;
SETIOV (ctp → iov, &msg → o, sizeof (msg → o) + nbytes);
return (_RESMGR_NPARTS (1));
}

Actually, this is mostly stolen from Krten’s io_devctl2.c sample (from
his book and web site).

The test app is pitifully simple:

int
main()
{
int fd;
int err;
int arg;

fd = open("/dev/quack", O_RDWR);
if (fd < 0)
printf(“Error opening device\n”);

arg = 0x1234;
err = devctl(fd, DCMD_AUDIO_SET_SAMPLE_RATE, &arg,
sizeof(arg), NULL);
if (EOK != err)
printf(“Error from devctl = %d\n”, err);

err = devctl(fd, DCMD_AUDIO_GET_SAMPLE_RATE, &arg,
sizeof(arg), NULL);
if (EOK != err)
printf(“Error from devctl = %d\n”, err);
else
printf(“Sample rate from server is %x\n”, arg);

return EXIT_SUCCESS;
}

When the test app runs, the “sample rate” is not transferred to the
driver in the SET_SAMPLE_RATE call, nor is it read back from the
GET_SAMPLE_RATE call. This code is pretty much boiler plate from the
books, but doesn’t seem to work. I feel like I’m missing something
fundamental.

Any hints appreciated.

Eric

Good one, thanks! Your problem is here:

int
quack_devctl (resmgr_context_t *ctp, io_devctl_t *msg,
iofunc_ocb_t *ocb)

// 1) assign a pointer to the data area of the message
data = _DEVCTL_DATA (msg);

_DEVCTL_DATA (msg) does a sizeof(msg) under the covers, which
of course is 4 bytes. See its definition in <devctl.h>.
What you want to do is:

data = _DEVCTL_DATA (msg->i);

Looks like you copied the error from Rob’s book.

Steven Dufresne <stevend@qnx.com> wrote:

Good one, thanks! Your problem is here:

int
quack_devctl (resmgr_context_t *ctp, io_devctl_t *msg,
iofunc_ocb_t *ocb)

// 1) assign a pointer to the data area of the message
data = _DEVCTL_DATA (msg);

_DEVCTL_DATA (msg) does a sizeof(msg) under the covers, which
of course is 4 bytes. See its definition in <devctl.h>.
What you want to do is:

data = _DEVCTL_DATA (msg->i);

Looks like you copied the error from Rob’s book.

I would also suggest to anyone lurking that you can take a look
at my example devctl handler source here:

http://www.qnx.com/~thomas/nto.html

Thomas

Thomas Fletcher <thomasf@qnx.com> wrote:

Steven Dufresne <> stevend@qnx.com> > wrote:
Good one, thanks! Your problem is here:

int
quack_devctl (resmgr_context_t *ctp, io_devctl_t *msg,
iofunc_ocb_t *ocb)

// 1) assign a pointer to the data area of the message
data = _DEVCTL_DATA (msg);

_DEVCTL_DATA (msg) does a sizeof(msg) under the covers, which
of course is 4 bytes. See its definition in <devctl.h>.
What you want to do is:

data = _DEVCTL_DATA (msg->i);

Looks like you copied the error from Rob’s book.

I would also suggest to anyone lurking that you can take a look
at my example devctl handler source here:

http://www.qnx.com/~thomas/nto.html

http://www.qnx.com/~thomasf/nto.html

Thomas

In article <8ve151$5o1$1@nntp.qnx.com>, Steven Dufresne
<stevend@qnx.com> wrote:

Good one, thanks! Your problem is here:

int
quack_devctl (resmgr_context_t *ctp, io_devctl_t *msg,
iofunc_ocb_t *ocb)

// 1) assign a pointer to the data area of the message
data = _DEVCTL_DATA (msg);

_DEVCTL_DATA (msg) does a sizeof(msg) under the covers, which
of course is 4 bytes. See its definition in <devctl.h>.
What you want to do is:

data = _DEVCTL_DATA (msg->i);

DOH!!!

Yep, that was the error, all right, both in the little sample (which you
caught) and in the real driver (which started this whole thread). Thanks
for the catch.

Looks like you copied the error from Rob’s book.

Yup. Hook, line, and sinker.

Now, where’s that errata list…?

Steven Dufresne wrote:

Thomas Fletcher <> thomasf@qnx.com> > wrote:
Steven Dufresne <> stevend@qnx.com> > wrote:
[ clip … ]
I would also suggest to anyone lurking that you can take a look
at my example devctl handler source here:

http://www.qnx.com/~thomas/nto.html

http://www.qnx.com/~thomasf/nto.html

Thanks’s for all of your efforts … but the
devctl-ex.tgz is corrupted.
That’s murphey’s law :slight_smile: Let us know when there is
a new one …

Armin

Armin Steinhoff <A-Steinhoff@web_.de> wrote:

Thanks’s for all of your efforts … but the
devctl-ex.tgz is corrupted.
That’s murphey’s law > :slight_smile: > Let us know when there is
a new one …

Hmm that is odd … I just downloaded it to my QNX4
maching and to my NTO machine and it was fine in
both cases … as is the archive on the server.

Try again? http://staff.qnx.com/~thomasf/nto.html

Thomas

Thomas Fletcher wrote:

Armin Steinhoff <A-Steinhoff@web_.de> wrote:

Thanks’s for all of your efforts … but the
devctl-ex.tgz is corrupted.
That’s murphey’s law > :slight_smile: > Let us know when there is
a new one …

Hmm that is odd … I just downloaded it to my QNX4
maching and to my NTO machine and it was fine in
both cases … as is the archive on the server.

Try again? > http://staff.qnx.com/~thomasf/nto.html

I did it again with my SUSE box + Netscape and it
works :slight_smile:
So don’t rely on Netscape + Win95 =:-/

Thanks so far.

Armin


Thomas