RE: how to use the function copyout()

2005-07-26 Thread Felix-KM
 I think that could work (only an idea, not tested):
 
 
 struct Region
 {
   void * p;
   size_t s;
 };
 
 
 #define IOBIG _IOWR ('b', 123, struct Region)
 
 
 userland:
 
   char data[1000];
   struct Region r;
 
   r.p = data;
   r.s = sizeof data;
   int error = ioctl (fd, IOBIG, r);
 
 
 kernel:
   int my_ioctl(..., caddr_t data, ...)
   {
 ...
 char data[1000];
 ...
 return copyout(data, ((struct Region *) data)-p, ((struct Region *)
 data)-s);
   }
 
 
 Have a try and tell us if it works.
 
 
 Norbert
 

Yes! Now the program works!
I have changed the code in this way:

struct Region
{
  void * p;
  size_t s;
};

#define IOBIG _IOWR ('b', 123, struct Region)

 driver 

struct my_softc {
 ...
 short unsigned int B;
};

...

static int
my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
   struct thread *td)
{
 struct my_softc *my_sc;
 int unit, error;
 unit = minor(dev);
 
 my_sc = (struct my_softc *)devclass_get_softc(my_devclass, unit);
 if (my_sc == NULL)
   return (ENXIO);
 
 switch(cmd)
 {
   ...
   case IOCTL_GET_B:
 error = copyout(my_sc-B, (((struct Datas *)data)-d)+0x1850, 
sizeof(my_sc-B));
 break;
   default:
 break;
 }
return 0;
}

---user program --

...

short unsigned int data[32768];
struct Region r;

int
main(int argc, char *argv[])
{
 ...

 r.p = data;
 r.s = sizeof data;
 
 if (ioctl(fd0, IOCTL_GET_B, r) == -1)
   err(1, IOCTL_GET_B);

 ...
}

Now I have access to each element of the array (e.g. 0x1850).
Thank you very much!
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-26 Thread Scott Long

Felix-KM wrote:

I think that could work (only an idea, not tested):


struct Region
{
 void * p;
 size_t s;
};


#define IOBIG _IOWR ('b', 123, struct Region)


userland:

 char data[1000];
 struct Region r;

 r.p = data;
 r.s = sizeof data;
 int error = ioctl (fd, IOBIG, r);


kernel:
 int my_ioctl(..., caddr_t data, ...)
 {
   ...
   char data[1000];
   ...
   return copyout(data, ((struct Region *) data)-p, ((struct Region *)
data)-s);
 }


Have a try and tell us if it works.


Norbert




Yes! Now the program works!
I have changed the code in this way:

struct Region
{
  void * p;
  size_t s;
};

#define IOBIG _IOWR ('b', 123, struct Region)



Unless your ioctl handler is going to modify values in the Region struct
and pass them back out to userland, you should just use _IOR instead of 
_IORW.


Scott
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


how to use the function copyout()

2005-07-25 Thread Felix-KM
I can't understand how to use the function copyout().
It is necessary to write the data from a device driver to the
array defined in user program.
I do it this way:

#define IOCTL_GET_B_IOWR(F, 127, 0x4)

 driver 

struct my_softc {
 ...
 short unsigned int B;
};

...

static int
my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
   struct thread *td)
{
 struct my_softc *my_sc;
 int unit, error;
 unit = minor(dev);
  my_sc = (struct my_softc *)devclass_get_softc(my_devclass, unit);
 if (my_sc == NULL)
   return (ENXIO);
switch(cmd)
 {
   ...
   case IOCTL_GET_B:
 error = copyout(my_sc-B, data, sizeof(my_sc-B));
 switch (error)
 {
   case 0:
 printf( IOCTL_GET_B: %d\n, my_sc-B);
 break;
   case EFAULT:
 printf(EFAULT\n);
 break;
   case EIO:
 printf(EIO\n);
 break;
   case ENOMEM:
 printf(ENOMEM\n);
 break;
   case ENOSPC:
 printf(ENOSPC\n);
 break;
 }
 break;
  default:
 break;
 }
return 0;
}

---user program --

...

short unsigned int Data[32768];

int
main(int argc, char *argv[])
{ ...

 if (ioctl(fd0, IOCTL_GET_B, Data) == -1)
   err(1, IOCTL_GET_B);

 ...
}

---

Here I get EFAULT.

What have I done wrong? How can I do it correctly?
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Stefan Sperling
On Mon, Jul 25, 2005 at 04:35:20PM +0400, Felix-KM wrote:
 I can't understand how to use the function copyout().
 It is necessary to write the data from a device driver to the
 array defined in user program.
 I do it this way:
 
 #define IOCTL_GET_B_IOWR(F, 127, 0x4)

snip

 Here I get EFAULT.
 
 What have I done wrong? How can I do it correctly?

You may need to add your ioctl to another middle layer.

For example, to add ioctls to network devices, I first added
defines to sockio.h only, and it wouldn't work (device not
configured). Then I found out that I had to add my ioctls
to a rather large switch statement in if.c too.

hope this helps,
-- 
stefan
http://stsp.in-berlin.de PGP Key: 0xF59D25F0
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Kamal R. Prasad
Im not sure of the bug in your code, but you have got
to assume that copyout() would fail if the user/kernel
addr passed to it is not accessible.

regards
-kamal


--- Felix-KM [EMAIL PROTECTED] wrote:

 I can't understand how to use the function
 copyout().
 It is necessary to write the data from a device
 driver to the
 array defined in user program.
 I do it this way:
 
 #define IOCTL_GET_B_IOWR(F, 127, 0x4)
 
  driver 
 
 struct my_softc {
  ...
  short unsigned int B;
 };
 
 ...
 
 static int
 my_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
 int flag,
   
 struct thread *td)
 {
  struct my_softc *my_sc;
  int unit, error;
  unit = minor(dev);
   my_sc = (struct my_softc
 *)devclass_get_softc(my_devclass, unit);
  if (my_sc == NULL)
return (ENXIO);
 switch(cmd)
  {
...
case IOCTL_GET_B:
  error = copyout(my_sc-B, data,
 sizeof(my_sc-B));
  switch (error)
  {
case 0:
  printf( IOCTL_GET_B: %d\n, my_sc-B);
  break;
case EFAULT:
  printf(EFAULT\n);
  break;
case EIO:
  printf(EIO\n);
  break;
case ENOMEM:
  printf(ENOMEM\n);
  break;
case ENOSPC:
  printf(ENOSPC\n);
  break;
  }
  break;
   default:
  break;
  }
 return 0;
 }
 
 ---user program --
 
 ...
 
 short unsigned int Data[32768];
 
 int
 main(int argc, char *argv[])
 { ...
 
  if (ioctl(fd0, IOCTL_GET_B, Data) == -1)
err(1, IOCTL_GET_B);
 
  ...
 }
 
 ---
 
 Here I get EFAULT.
 
 What have I done wrong? How can I do it correctly?
 ___
 freebsd-hackers@freebsd.org mailing list

http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
 To unsubscribe, send any mail to
 [EMAIL PROTECTED]
 



Kamal R. Prasad
UNIX systems consultant 
http://www.kamalprasad.com/
[EMAIL PROTECTED]

In theory, there is no difference between theory and practice. In practice, 
there is.





Start your day with Yahoo! - make it your home page 
http://www.yahoo.com/r/hs 
 
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


RE: how to use the function copyout()

2005-07-25 Thread Norbert Koch
 #define IOCTL_GET_B_IOWR(F, 127, 0x4)

I think the third parameter to _IOWR should directly specify a type,
e.g. _IOWR(F, 127, int) or _IOWR(F, 127, struct MyStruct).

 
  driver 
 
 struct my_softc {
  ...
  short unsigned int B;
 };
 
 ...
 
 static int
 my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
struct thread *td)
 {
  struct my_softc *my_sc;
  int unit, error;
  unit = minor(dev);
   my_sc = (struct my_softc *)devclass_get_softc(my_devclass, unit);
  if (my_sc == NULL)
return (ENXIO);
 switch(cmd)
  {
...
case IOCTL_GET_B:
  error = copyout(my_sc-B, data, sizeof(my_sc-B));
  switch (error)
  {
case 0:
  printf( IOCTL_GET_B: %d\n, my_sc-B);
  break;
case EFAULT:
  printf(EFAULT\n);
  break;
case EIO:
  printf(EIO\n);
  break;
case ENOMEM:
  printf(ENOMEM\n);
  break;
case ENOSPC:
  printf(ENOSPC\n);
  break;
  }
  break;
   default:
  break;
  }
 return 0;
 }
 
 ---user program --
 
 ...
 
 short unsigned int Data[32768];
 
 int
 main(int argc, char *argv[])
 { ...
 
  if (ioctl(fd0, IOCTL_GET_B, Data) == -1)
err(1, IOCTL_GET_B);
 
  ...
 }
 
 ---
 
 Here I get EFAULT.
 
 What have I done wrong? How can I do it correctly?

The caddr_t data in your ioctl is already mapped into kernel
memory. Look into the source of other device drivers. You'll
find a lot of *(int *) data = ...
So your copyout() has to fail because it tries to address
memory which is not a part of your application's
memory.
From errno(2): EFAULT: Bad address...

I have no idea if it is possible for ioctls to have mapped more
than a few 100 bytes for data exchange.
You should use read and uiomove() instead.

Norbert
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


RE: how to use the function copyout()

2005-07-25 Thread Felix-KM
 #define IOCTL_GET_B_IOWR(F, 127, 0x4)

I think the third parameter to _IOWR should directly specify a type,
e.g. _IOWR(F, 127, int) or _IOWR(F, 127, struct MyStruct).

 
  driver 
 
 struct my_softc {
  ...
  short unsigned int B;
 };
 
 ...
 
 static int
 my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
struct thread *td)
 {
  struct my_softc *my_sc;
  int unit, error;
  unit = minor(dev);
   my_sc = (struct my_softc *)devclass_get_softc(my_devclass, unit);
  if (my_sc == NULL)
return (ENXIO);
 switch(cmd)
  {
...
case IOCTL_GET_B:
  error = copyout(my_sc-B, data, sizeof(my_sc-B));
  switch (error)
  {
case 0:
  printf( IOCTL_GET_B: %d\n, my_sc-B);
  break;
case EFAULT:
  printf(EFAULT\n);
  break;
case EIO:
  printf(EIO\n);
  break;
case ENOMEM:
  printf(ENOMEM\n);
  break;
case ENOSPC:
  printf(ENOSPC\n);
  break;
  }
  break;
   default:
  break;
  }
 return 0;
 }
 
 ---user program --
 
 ...
 
 short unsigned int Data[32768];
 
 int
 main(int argc, char *argv[])
 { ...
 
  if (ioctl(fd0, IOCTL_GET_B, Data) == -1)
err(1, IOCTL_GET_B);
 
  ...
 }
 
 ---
 
 Here I get EFAULT.
 
 What have I done wrong? How can I do it correctly?

The caddr_t data in your ioctl is already mapped into kernel
memory. Look into the source of other device drivers. You'll
find a lot of *(int *) data = ...
So your copyout() has to fail because it tries to address
memory which is not a part of your application's
memory.
From errno(2): EFAULT: Bad address...

I have no idea if it is possible for ioctls to have mapped more
than a few 100 bytes for data exchange.
You should use read and uiomove() instead.

So if I get it right, it's impossible in FreeBSD to gain access to 64KB of 
user's program memory with ioctl?

My situation is this - I have a device driver for Linux. My task is port it as 
it is (1:1) into FreeBSD.

In the Linux driver Ioctl is realized with the macroses _put_user _get_user all 
over it. As I understand in FreeBSD their analogues are functions described in 
store(9), copy(9) and fetch(9). 

So the problem is that in my user program an array short unsigned int 
Data[32768] is defined. I need to gain access to the array(to each element of 
it) from device driver with Ioctl handler.

Is it possible to do? If yes, then how it can be done?


Norbert
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


-- 
Где Яндекс.Деньги - там хорошие скидки http://money.yandex.ru/discount/
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Giorgos Keramidas
On 2005-07-25 18:14, Felix-KM [EMAIL PROTECTED] wrote:
 I have no idea if it is possible for ioctls to have mapped more than
 a few 100 bytes for data exchange.  You should use read and uiomove()
 instead.
 
 So if I get it right, it's impossible in FreeBSD to gain access to
 64KB of user's program memory with ioctl?
 
 My situation is this - I have a device driver for Linux. My task is
 port it as it is (1:1) into FreeBSD.
 
 In the Linux driver Ioctl is realized with the macroses _put_user
 _get_user all over it. As I understand in FreeBSD their analogues are
 functions described in store(9), copy(9) and fetch(9).

 So the problem is that in my user program an array short unsigned int
 Data[32768] is defined. I need to gain access to the array(to each
 element of it) from device driver with Ioctl handler.

 Is it possible to do? If yes, then how it can be done?

A better alternative that doesn't involve copying huge amounts of data
from userlevel to kernel space and vice versa is probably to pass just
the address of the area with an ioctl() and then map the appropriate
pages from the address space of the user process to an area where the
kernel can access the data directly?

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


RE: how to use the function copyout()

2005-07-25 Thread Norbert Koch

  So if I get it right, it's impossible in FreeBSD to gain access to
  64KB of user's program memory with ioctl?
 
  My situation is this - I have a device driver for Linux. My task is
  port it as it is (1:1) into FreeBSD.
 
  In the Linux driver Ioctl is realized with the macroses _put_user
  _get_user all over it. As I understand in FreeBSD their analogues are
  functions described in store(9), copy(9) and fetch(9).
 
  So the problem is that in my user program an array short unsigned int
  Data[32768] is defined. I need to gain access to the array(to each
  element of it) from device driver with Ioctl handler.
 
  Is it possible to do? If yes, then how it can be done?

 A better alternative that doesn't involve copying huge amounts of data
 from userlevel to kernel space and vice versa is probably to pass just
 the address of the area with an ioctl() and then map the appropriate
 pages from the address space of the user process to an area where the
 kernel can access the data directly?


I think that could work (only an idea, not tested):


struct Region
{
  void * p;
  size_t s;
};


#define IOBIG _IOWR ('b', 123, struct Region)


userland:

  char data[1000];
  struct Region r;

  r.p = data;
  r.s = sizeof data;
  int error = ioctl (fd, IOBIG, r);


kernel:
  int my_ioctl(..., caddr_t data, ...)
  {
...
char data[1000];
...
return copyout(data, ((struct Region *) data)-p, ((struct Region *)
data)-s);
  }


Have a try and tell us if it works.


Norbert

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


RE: how to use the function copyout()

2005-07-25 Thread Matthew N. Dodd

On Mon, 25 Jul 2005, Felix-KM wrote:
In the Linux driver Ioctl is realized with the macroses _put_user 
_get_user all over it. As I understand in FreeBSD their analogues are 
functions described in store(9), copy(9) and fetch(9).


Linux doesn't provide any help for driver IOCTL routines, FreeBSD does.

Just declare your IOCTLs correctly and the kernel will perform any copy 
in/out as specified by the _IOW/_IOR/_IOWR macros.


--
10 40 80 C0 00 FF FF FF FF C0 00 00 00 00 10 AA AA 03 00 00 00 08 00
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Julian Elischer



Felix-KM wrote:


#define IOCTL_GET_B_IOWR(F, 127, 0x4)
 


I think the third parameter to _IOWR should directly specify a type,
e.g. _IOWR(F, 127, int) or _IOWR(F, 127, struct MyStruct).

   


 driver 

struct my_softc {
...
short unsigned int B;
};

...

static int
my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
  struct thread *td)
{
struct my_softc *my_sc;
int unit, error;
unit = minor(dev);
 my_sc = (struct my_softc *)devclass_get_softc(my_devclass, unit);
if (my_sc == NULL)
  return (ENXIO);
   switch(cmd)
{
  ...
  case IOCTL_GET_B:
error = copyout(my_sc-B, data, sizeof(my_sc-B));
switch (error)
{
  case 0:
printf( IOCTL_GET_B: %d\n, my_sc-B);
break;
  case EFAULT:
printf(EFAULT\n);
break;
  case EIO:
printf(EIO\n);
break;
  case ENOMEM:
printf(ENOMEM\n);
break;
  case ENOSPC:
printf(ENOSPC\n);
break;
}
break;
 default:
break;
}
   return 0;
}

---user program --

...

short unsigned int Data[32768];

int
main(int argc, char *argv[])
{ ...

if (ioctl(fd0, IOCTL_GET_B, Data) == -1)
  err(1, IOCTL_GET_B);

...
}

---

Here I get EFAULT.

What have I done wrong? How can I do it correctly?
 


The caddr_t data in your ioctl is already mapped into kernel
memory. Look into the source of other device drivers. You'll
find a lot of *(int *) data = ...
So your copyout() has to fail because it tries to address
memory which is not a part of your application's
memory.

From errno(2): EFAULT: Bad address...


I have no idea if it is possible for ioctls to have mapped more
than a few 100 bytes for data exchange.
You should use read and uiomove() instead.
   



So if I get it right, it's impossible in FreeBSD to gain access to 64KB of 
user's program memory with ioctl?
 



no you do not get it right.

you should pass in a pointer to your 64k object.
ioccom.h describes the definition of the ioctl name.
this includes:
#define IOCPARM_MASK0x1fff  /* parameter length, at most 13 
bits */

so the maximum that the system will AUTOMATICALLY COPYIN() is 8k
For larger amounts you can always have the address as teh parameter and 
do the copyin yourself.
in other words the automatically moved data would be only a smal 
structure specifying address and size,

and you would use those parameters to copyin the larger structure.


My situation is this - I have a device driver for Linux. My task is port it as 
it is (1:1) into FreeBSD.

In the Linux driver Ioctl is realized with the macroses _put_user _get_user all over it. As I understand in FreeBSD their analogues are functions described in store(9), copy(9) and fetch(9). 


So the problem is that in my user program an array short unsigned int 
Data[32768] is defined. I need to gain access to the array(to each element of 
it) from device driver with Ioctl handler.

Is it possible to do? If yes, then how it can be done?
 




 


Norbert
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]
   




 


___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Scott Long

Kamal R. Prasad wrote:


Im not sure of the bug in your code, but you have got
to assume that copyout() would fail if the user/kernel
addr passed to it is not accessible.

regards
-kamal



The whole point of copyin and copyout is to deal with copying
to and from user virtual memory that might not be paged in at the
moment.  Your statement thus makes little sense.

Scott

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Scott Long

Giorgos Keramidas wrote:


On 2005-07-25 18:14, Felix-KM [EMAIL PROTECTED] wrote:


I have no idea if it is possible for ioctls to have mapped more than
a few 100 bytes for data exchange.  You should use read and uiomove()
instead.


So if I get it right, it's impossible in FreeBSD to gain access to
64KB of user's program memory with ioctl?

My situation is this - I have a device driver for Linux. My task is
port it as it is (1:1) into FreeBSD.

In the Linux driver Ioctl is realized with the macroses _put_user
_get_user all over it. As I understand in FreeBSD their analogues are
functions described in store(9), copy(9) and fetch(9).

So the problem is that in my user program an array short unsigned int
Data[32768] is defined. I need to gain access to the array(to each
element of it) from device driver with Ioctl handler.

Is it possible to do? If yes, then how it can be done?



A better alternative that doesn't involve copying huge amounts of data
from userlevel to kernel space and vice versa is probably to pass just
the address of the area with an ioctl() and then map the appropriate
pages from the address space of the user process to an area where the
kernel can access the data directly?



The kernel can see all of the user address space already, assuming that 
it's operating in the same process context as the user application (i.e.

you haven't defered the ioctl call to a kthread, which is not normally
the case).  Mapping isn't the problem.

Scott
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Scott Long

Felix-KM wrote:


I can't understand how to use the function copyout().
It is necessary to write the data from a device driver to the
array defined in user program.
I do it this way:

#define IOCTL_GET_B_IOWR(F, 127, 0x4)



What you've declared here is an ioctl that will copy in 4 bytes of
user data on entry, and copy out 4 bytes back out on exit.  The argument
that you supply to the ioctl(2) must be a pointer to a 4 byte word that
you want to copy.  This probably isn't what you want.  Based on your
code snippets, you want:

#define IOCTL_GET_B _IOW(F, 127, unsigned short)

static int my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int 
flag, struct thread *td)

{
unsigned short data;
[...]

case IOCTL_GET_B:
*(unsigned short *)arg = data;
break;
[...]


Similar code will work for all integral types, as well as simple
structures.  The generic ioctl layer will handle all of the copying
magic for you.  Copying compound structures (ones that have pointers
to other data that you also want to copy) require explicit copyin
or copyout operations on the pointers that are embedded into the
struct.  Likewise, copying arbitrary data that isn't a structure or
integral type (like an array) also requires an explicit copy operation.
You could do something like the following:

struct mysubdata {
int foo;
int bar;
};

struct mystruct {
struct mysubdata *msd;
};

#define IOCTL_SET_COMPOUNT_STRUCT   _IOR(F, 123, struct mystruct)
#define IOCTL_SET_BIGDATA   _IO(F, 124)

static int my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int 
flag, struct thread *td)

{
struct mystruct *ms;
struct mysubdata msd;
char *bigdata *bd;

[...]

case IOCTL_SET_COMPOUNT_STRUCT:
ms = *(struct mystruct *)arg;
copyin(ms-msd, msd, sizeof(struct mysubdata));
break;
case IOCTL_SET_BIGDATA:
bd = malloc(65536, M_DEVBUF, M_WAITOK);
copyin(arg, bd, 65536);
break;
[...]


Note that the BIGDATA ioctl doesn't copy in anything on its own.  For
ioctls like this, it's often convenient to pass a structure anyway that
contains the size of the data to be copied in and a pointer to the data,
like so:

struct mybigdata {
int datasize;
char*bigdata;
}

#define IOCTL_SET_BIGDATA   _IOR(B, 123, struct mybigdata)

case IOCTL_GET_BIGDATA:
mbd = *(struct mybigdata *)arg;
bd = malloc(mbd-datasize, M_DEVBUF, M_WAITOK);
copyin(mbd-bigdata, bd, mbd-datasize);
break;

Does this make sense?  Fell free to contact me with questions on this or
anything else.

Scott

___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]


Re: how to use the function copyout()

2005-07-25 Thread Scott Long

Scott Long wrote:

Felix-KM wrote:


I can't understand how to use the function copyout().
It is necessary to write the data from a device driver to the
array defined in user program.
I do it this way:

#define IOCTL_GET_B_IOWR(F, 127, 0x4)



What you've declared here is an ioctl that will copy in 4 bytes of
user data on entry, and copy out 4 bytes back out on exit.  The argument
that you supply to the ioctl(2) must be a pointer to a 4 byte word that
you want to copy.  This probably isn't what you want.  Based on your
code snippets, you want:

#define IOCTL_GET_B_IOW(F, 127, unsigned short)

static int my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int 
flag, struct thread *td)

{
unsigned short data;
[...]

case IOCTL_GET_B:
*(unsigned short *)arg = data;
break;
[...]


Similar code will work for all integral types, as well as simple
structures.  The generic ioctl layer will handle all of the copying
magic for you.  Copying compound structures (ones that have pointers
to other data that you also want to copy) require explicit copyin
or copyout operations on the pointers that are embedded into the
struct.  Likewise, copying arbitrary data that isn't a structure or
integral type (like an array) also requires an explicit copy operation.
You could do something like the following:

struct mysubdata {
int foo;
int bar;
};

struct mystruct {
struct mysubdata *msd;
};

#define IOCTL_SET_COMPOUNT_STRUCT_IOR(F, 123, struct mystruct)
#define IOCTL_SET_BIGDATA_IO(F, 124)

static int my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int 
flag, struct thread *td)

{
struct mystruct *ms;
struct mysubdata msd;
char *bigdata *bd;

[...]

case IOCTL_SET_COMPOUNT_STRUCT:
ms = *(struct mystruct *)arg;
copyin(ms-msd, msd, sizeof(struct mysubdata));
break;
case IOCTL_SET_BIGDATA:
bd = malloc(65536, M_DEVBUF, M_WAITOK);
copyin(arg, bd, 65536);
break;
[...]


Note that the BIGDATA ioctl doesn't copy in anything on its own.  For
ioctls like this, it's often convenient to pass a structure anyway that
contains the size of the data to be copied in and a pointer to the data,
like so:

struct mybigdata {
intdatasize;
char*bigdata;
}

#define IOCTL_SET_BIGDATA_IOR(B, 123, struct mybigdata)

case IOCTL_GET_BIGDATA:
mbd = *(struct mybigdata *)arg;
bd = malloc(mbd-datasize, M_DEVBUF, M_WAITOK);
copyin(mbd-bigdata, bd, mbd-datasize);
break;

Does this make sense?  Fell free to contact me with questions on this or
anything else.

Scott



Oops, I made a small but important mistake in these examples.  When you 
use _IOR or _IOW, the data argument passed to your routine will be a
pointer (in kernel address space) to the data that you specified, not a 
pointer to a pointer.  So in the above example, you'd do:


mbd = (struct mybigdata *)arg;

not:

mbd = *(struct mybigdata *)arg;

For integral types, you'd still do:

data = *(unsigned short *)arg;

For ioctls that are specified with merely _IO, the data argument is a 
pointer in user address space.  Technically you could just use bcopy on
this, but the physical pages backing that address might have been 
swapped out in between the time the syscall was started and the time

that your handler got called.  The whole point of copyin/copyout is
to safely and transparently handle this situation.

Sorry for the confusion.

Scott
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to [EMAIL PROTECTED]