title: ioctl command wrong in 64 bit system from 32 bit user code
body: <p>I'm upgrading a device driver from a 32bit RHEL 2.6.32 to 64bit RHEL 2.6.33.9.</p>
  
  <p>I have a program that talks to that driver using ioctl.  It works perfectly when both the driver and the program are either 64bit or 32bit.  But when the driver is 64bit, and my program is 32 bit, the ioctl command received by the driver (in compat_ioctl) does not match the values defined by the _IOR and _IOW macros.</p>
  
  <p>In my driver's switch statement, the default case prints out the values of all the valid commands, which are 1-12.  The 32bit ioctl command is nowhere near those values.</p>
  
  <p>Can someone tell me what would cause the command from a 32bit user program to be messed up when received in a 64bit driver?</p>
  
  <p>Here's some of the code: I had to type it in; the code is on a secured system without internet access, so please forgive any typos.  It actually does comile and run!</p>
  
  <pre><code>// IOCTL commands from the include file - most omitted
  // ...
  #define PORTIO_GET_IRQ_CNT_CMD  10
  #define PORTIO_CLR_IRQ_CNT_CMD  11
  #define PORTIO_GET_IRQ_TIME_CMD 12
  
  #define PORTIO_IOCTL     'k'  // magic number for ioctl
  
  // IOCTL Macros
  #define PORTIO_GET_IRQ_CNT_IOCTL    _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_CNT_CMD, unsigned long)
  #define PORTIO_CLR_IRQ_CNT_IOCTL    _IOR(PORTIO_IOCTL, PORTIO_CLR_IRQ_CNT_CMD, unsigned long)
  #define PORTIO_GET_IRQ_TIME_IOCTL   _IOR(PORTIO_IOCTL, PORTIO_GET_IRQ_TIME_CMD, unsigned long)
  </code></pre>
  
  <p>Here's the 32 bit compatible IOCTL routine, from portio.c.  I've confirmed that this is being called only when my program is compiled as 32bit, and the driver is 64bit.</p>
  
  <pre><code>static long portio_compat_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
  {
  unsigned char cmd_number;
  int cmd_size=0;
  //...
  cmd_number = _IOC_NR( cmd );
  cmd_size = _IOC_SIZE( cmd );
  
  printk( KERN_ALERT "Portio Compat IOCTL number,size = %d,%d, cmd_number, cmd_size );
  //... Switch statement and cases, based on cmd_number
  }
  </code></pre>
  
  <p>The output looks like this:</p>
  
  <p>Portio Compat IOTCL number,size = 224,3157</p>
  
  <p>Of course, the code expects IOCTL numbers from 1-12, and sizes around 4 or 8.  That's exactly what comes back when the code and driver are both either 64bit or 32bit.  </p>