Re: char interface to sdio, chdio.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wednesday 16 July 2014 22:33:47 Greg KH wrote:
> + mmc: Char SDIO Device Driver

A few comments on the ioctl interface, since I suppose we'll have
to live with that once it gets merged.

> +Interface
> +=========
> +The Char SDIO Device Driver has two char device interfaces:
> + - Control Interface;
> + - Function Interface.
> +
> +Char SDIO Device Driver Control Interface consists of:
> + - open()   - device node is /dev/csdio0;
> + - close()
> + - ioctl()  - the following options are available:
> +   - CSDIO_IOC_ENABLE_HIGHSPEED_MODE;
> +   - CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS;
> +   - CSDIO_IOC_ENABLE_ISR;
> +   - CSDIO_IOC_DISABLE_ISR.


The documentation doesn't match the code.:

CSDIO_IOC_GET/SET_VDD are implemented in the control device,
not the function device, and that is probably a good idea.
CSDIO_IOC_ENABLE_HIGHSPEED_MODE is not implemented
at all. CSDIO_IOC_ENABLE_ISR seems redundant with what
the CSDIO_IOC_{DIS,}CONNECT_ISR functions do, but I could be
wrong here.

The sysfs interface may actually be more appropriate than the
control node, if I was to pick one of the two.

> +Char SDIO Device Driver Function Interface consists of:
> + - open()  - device node is /dev/csdiofX, where X is Function Id;
> + - close()
> + - read()  - send CMD53 read;
> + - write() - send CMD53 write;
> + - ioctl() - the following options are available:
> +   - CSDIO_IOC_SET_OP_CODE - 0 fixed adrress, 1 autoincrement.
> +   - CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE;
> +   - CSDIO_IOC_SET_BLOCK_MODE - 0 byte mode, 1 block mode;
> +   - CSDIO_IOC_CMD52 - execute CMD52, receives the
> +        following structure as a parameter:
> +            struct csdio_cmd52_ctrl_t {
> +	            uint32_t    m_write; // 0 - read, 1 -write
> +	            uint32_t    m_address;
> +	            uint32_t    m_data;  // data to write or read data
> +	            uint32_t    m_ret;   // command execution status
> +            }__attribute__ ((packed));
> +   - CSDIO_IOC_CMD53 - setup CMD53 data transfer, receives the
> +        following structure as a parameter:
> +            struct csdio_cmd53_ctrl_t {
> +	            uint32_t    m_block_mode;
> +	            uint32_t    m_op_code;
> +	            uint32_t    m_address;
> +            }__attribute__ ((packed));
> +   - CSDIO_IOC_CONNECT_ISR;
> +   - CSDIO_IOC_DISCONNECT_ISR;
> +   - CSDIO_IOC_GET_VDD;
> +   - CSDIO_IOC_SET_VDD.
> +
> +Additionally, user space application can use fcntl system call with
> +parameters F_SETOWN and F_SETFL in order to set an asynchronous
> +callback for SDIO interrupt.

The read/write API seems very strange. SDIO has multiple ways of
passing data between OS and device using CMD52 and CMD53, and they
are all done differently here:

- A one-byte read or write uses a single CSDIO_IOC_CMD52 ioctl.
  This could be done using pread/pwrite with length '1' rather than
  an ioctl, if we want to.

- a byte-addressed multi-byte read/write needs to first 'seek' using
  CSDIO_IOC_CMD53 or and then transfer using read() or write().

- a block-addressed read/write is similar, but the number of bytes
  copied to/from user space is now multiplied with the block size (!).
  The block size needs to be set using both CSDIO_IOC_SET_BLOCK_MODE
  and CSDIO_IOC_CMD53, using the same value.

- to do a multi-byte read/write at a constant address rather than
  a block copy, CSDIO_IOC_CMD53 needs to set at least one bit (not
  necessarily the one used in the actual command) in m_op_code.

I guess all of this could be done using pread/pwrite, using the
loff_t value to encode the m_address in the lower bits and the
mode (single-byte, multi-byte, multi-byte auto-increment,
block, block auto-increment) in some of the upper bits.

Alternatively, the read/write functions could be removed completely
and everything be done in the ioctls, but in a more consistent
way.

> +
> +#define CSDIO_IOC_MAGIC  'm'
> +
> +#define CSDIO_IOC_ENABLE_HIGHSPEED_MODE      _IO(CSDIO_IOC_MAGIC, 0)
> +#define CSDIO_IOC_SET_DATA_TRANSFER_CLOCKS   _IO(CSDIO_IOC_MAGIC, 1)
> +#define CSDIO_IOC_SET_OP_CODE                _IO(CSDIO_IOC_MAGIC, 2)
> +#define CSDIO_IOC_FUNCTION_SET_BLOCK_SIZE    _IO(CSDIO_IOC_MAGIC, 3)
> +#define CSDIO_IOC_SET_BLOCK_MODE             _IO(CSDIO_IOC_MAGIC, 4)
> +#define CSDIO_IOC_CONNECT_ISR                _IO(CSDIO_IOC_MAGIC, 5)
> +#define CSDIO_IOC_DISCONNECT_ISR             _IO(CSDIO_IOC_MAGIC, 6)
> +#define CSDIO_IOC_CMD52                      _IO(CSDIO_IOC_MAGIC, 7)
> +#define CSDIO_IOC_CMD53                      _IO(CSDIO_IOC_MAGIC, 8)
> +#define CSDIO_IOC_ENABLE_ISR                 _IO(CSDIO_IOC_MAGIC, 9)
> +#define CSDIO_IOC_DISABLE_ISR                _IO(CSDIO_IOC_MAGIC, 10)
> +#define CSDIO_IOC_SET_VDD                    _IO(CSDIO_IOC_MAGIC, 11)
> +#define CSDIO_IOC_GET_VDD                    _IO(CSDIO_IOC_MAGIC, 12)
> +
> +#define CSDIO_IOC_MAXNR   12

The command codes above should use _IOR or _IOW where appropriate to
encode the size of the transferred data.

> +
> +struct csdio_cmd53_ctrl_t {
> +	uint32_t    m_block_mode;   /* data tran. byte(0)/block(1) mode */
> +	uint32_t    m_op_code;      /* address auto increment flag */
> +	uint32_t    m_address;
> +} __attribute__ ((packed));
> +
> +struct csdio_cmd52_ctrl_t {
> +	uint32_t    m_write;
> +	uint32_t    m_address;
> +	uint32_t    m_data;
> +	uint32_t    m_ret;
> +} __attribute__ ((packed));

The packing is not necessary here, but at least all of these are
compatible between 32 and 64 bit, so enabling compat mode is a one-line
change and requires no conversion.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux