From owner-freebsd-hackers Wed Sep 3 19:11:48 1997 Return-Path: Received: (from root@localhost) by hub.freebsd.org (8.8.7/8.8.7) id TAA25367 for hackers-outgoing; Wed, 3 Sep 1997 19:11:48 -0700 (PDT) Received: from word.smith.net.au (ppp20.portal.net.au [202.12.71.120]) by hub.freebsd.org (8.8.7/8.8.7) with ESMTP id TAA25362 for ; Wed, 3 Sep 1997 19:11:40 -0700 (PDT) Received: from word.smith.net.au (localhost.smith.net.au [127.0.0.1]) by word.smith.net.au (8.8.7/8.8.5) with ESMTP id LAA00716; Thu, 4 Sep 1997 11:39:47 +0930 (CST) Message-Id: <199709040209.LAA00716@word.smith.net.au> X-Mailer: exmh version 2.0zeta 7/24/97 To: Simon Shapiro cc: Mike Smith , freebsd-hackers@freebsd.org Subject: Re: IOCTL Commands - Where is my mistake? In-reply-to: Your message of "Wed, 03 Sep 1997 18:35:25 MST." Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Thu, 04 Sep 1997 11:39:44 +0930 From: Mike Smith Sender: owner-freebsd-hackers@freebsd.org X-Loop: FreeBSD.org Precedence: bulk > Thax for the help Mike! > > Hi Mike Smith; On 03-Sep-97 you wrote: > > > I want to pass IOCTL commands to a driver. This is what I do: > > > > > > #define DPT_IOCTL_INTERNAL_METRICS _IOW('D', 1, dpt_perf_t) > > > > You want to pass a pointer to the struct, not the struct itself. > > I do. what gave you the idea I do not? dpt_perf_t is common lingo for a structure definition. If you mean that it is a pointer, then you should not be calling it that. > > > switch (cmd) { > > > case DPT_IOCTL_INTERNAL_METRICS: > > > result = copyout((char *)&dpt->performance, > > > (dpt_softc_t *)(*(caddr_t *)cmdarg), > > > sizeof(dpt_perf_t)); > > > > This is *hideously* bogus. Try : > > > > caddr_t dest; > > > > /* get address in userspace */ > > dest = fuword(*(caddr_t *)cmdarg); > > This is *hideously* not portable :-) You assume an integer and a char * > are the same. Should be dest = (caddr_t)fuword.... Given that I am also assuming that a userspace pointer fits in a "word", the extra cast didn't seem worth the effort. If/when fuaddr() comes into the picture, I'll start using it. > I did. I am still getting the SAME result. Maybe I should re-state that: > > If I do: > > #define DPT_IOCTL_INTERNAL_METRICS _IOR('D', 1, dpt_perf_t) > > Then copyout fails! Have you bothered to print the address that you are trying to copy out to? > BUT if I do: > > #define DPT_IOCTL_INTERNAL_METRICS (IOC_INOUT | 1) > > Then it WORKS. So what? You're the benficiary of a fencepost error in that you shouldn't be getting anything copied in or out at all. Look at the definition of the _IO* macros : #define _IOC(inout,group,num,len) \ (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) #define _IO(g,n) _IOC(IOC_VOID, (g), (n), 0) #define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) #define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) /* this should be _IORW, but stdio got there first */ #define _IOWR(g,n,t) _IOC(IOC_INOUT, (g), (n), sizeof(t)) > The fact that the contents of cmd (NOT the identity of cmdarg!) changes > the outcome of copyout, coupled with the fact that your version, although > not nearly as *hideously* bogus as mine, does NOT work, coupled to the > fact that ioctl does work, leads me to belive that I am making a stupid > mistake, but your solution is not indicating my error. I have, indeed, indicated your error. The object supplied as an argument to the ioctl is copied to/from kernel space dependant on the _IO macro flavour. The *address* of this copied object is passed to your ioctl handler in (cmdarg). You can either pass a user-space address in, and use this address as the argument to a copyout, or you can request that the entire structure be copied out and supply an entire structure. mike