Date: Thu, 04 Sep 1997 15:19:14 +1000 From: Stephen McKay <syssgm@dtir.qld.gov.au> To: Mike Smith <mike@smith.net.au>, Simon Shapiro <Shimon@i-Connect.Net> Cc: freebsd-hackers@freebsd.org, syssgm@dtir.qld.gov.au Subject: Re: IOCTL Commands - Where is my mistake? Message-ID: <199709040519.PAA09446@ogre.dtir.qld.gov.au> In-Reply-To: <199709040247.MAA00870@word.smith.net.au> from Mike Smith at "Thu, 04 Sep 1997 02:47:22 %2B0000" References: <199709040247.MAA00870@word.smith.net.au>
index | next in thread | previous in thread | raw e-mail
On Thursday, 4th September 1997, Mike Smith wrote:
>... the correct approach would seem to be :
>
>struct foo {
> int a, b;
>};
>
>#define FOO_IOCTL _IOWR('F', 1, struct foo)
>
>...
> struct foo bar;
>...
> ioctl(fd, FOO_IOCTL, bar);
>...
>
> case FOO_IOCTL:
> {
> struct foo oof = (struct foo *)cmdarg;
>...
> <access foo via oof>
>...
> }
>
>This will copy the 'bar' structure into and out of the kernel (tune
>with the macro to suit), and allow you to call the ioctl handler from
>within the kernel (eg. from one of the ABI emulation layers).
>
>I hope this a) makes sense, and b) works for you.
Well Mike, I'm pretty sure now that you've made a boo-boo. :-)
I direct your attention to TIOCGWINSZ and a typical use of this in
nvi/cl/cl_term.c:
struct winsize win;
if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) {
...
}
The definition of TIOCGWINSZ:
#define TIOCGWINSZ _IOR('t', 104, struct winsize)
and some code from kern/tty.c:
int
ttioctl(tp, cmd, data, flag)
register struct tty *tp;
int cmd, flag;
void *data;
{
...
case TIOCGWINSZ: /* get window size */
*(struct winsize *)data = tp->t_winsize;
break;
...
}
There are a few levels of calls between ioctl() in kern/sys_generic.c and
ttioctl() in kern/tty.c but 'data' stays the same.
>From this, I expect that Simon wants to use his ioctl like:
dpt_perf_t metrics;
if ( (result = ioctl(fd, DPT_IOCTL_INTERNAL_METRICS, &metrics)) != 0 ) {
...
}
Define his ioctl like:
#define DPT_IOCTL_INTERNAL_METRICS _IOR('D', 1, dpt_perf_t)
And put this in his driver:
int
dpt_ioctl(dev_t dev, int cmd, caddr_t cmdarg, int flags, struct proc *p)
...
switch (cmd) {
case DPT_IOCTL_INTERNAL_METRICS:
*(dpt_perf_t *)cmdarg = dpt->performance;
break;
The reason that:
#define DPT_IOCTL_INTERNAL_METRICS IOC_INOUT | 1
works with his current driver code is sheer luck, as Mike says. The size
is encoded as 0, and that falls through some odd code in ioctl() and hands
you a cmdarg that points to the pointer that was passed in from user mode.
A zero size should be an error in my books.
Stephen.
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199709040519.PAA09446>
