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>
next in thread | previous in thread | raw e-mail | index | archive | help
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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199709040519.PAA09446>