151 lines
3.5 KiB
C
151 lines
3.5 KiB
C
/*
|
|
* Freescale UUT driver
|
|
*
|
|
* Copyright 2008-2014 Freescale Semiconductor, Inc.
|
|
* Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
|
|
*/
|
|
|
|
/*
|
|
* The code contained herein is licensed under the GNU General Public
|
|
* License. You may obtain a copy of the GNU General Public License
|
|
* Version 2 or later at the following locations:
|
|
*
|
|
* http://www.opensource.org/licenses/gpl-license.html
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
#ifndef __FSL_UPDATER_H
|
|
#define __FSL_UPDATER_H
|
|
|
|
#include <linux/miscdevice.h>
|
|
#include <linux/list.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/ioctl.h>
|
|
/* #include <mach/hardware.h> */
|
|
|
|
static int utp_init(struct fsg_dev *fsg);
|
|
static void utp_exit(struct fsg_dev *fsg);
|
|
static ssize_t utp_file_read(struct file *file,
|
|
char __user *buf,
|
|
size_t size,
|
|
loff_t *off);
|
|
|
|
static ssize_t utp_file_write(struct file *file,
|
|
const char __user *buf,
|
|
size_t size,
|
|
loff_t *off);
|
|
|
|
static long utp_ioctl(struct file *file,
|
|
unsigned int cmd, unsigned long arg);
|
|
static struct utp_user_data *utp_user_data_alloc(size_t size);
|
|
static void utp_user_data_free(struct utp_user_data *uud);
|
|
static int utp_get_sense(struct fsg_dev *fsg);
|
|
static int utp_do_read(struct fsg_dev *fsg, void *data, size_t size);
|
|
static int utp_do_write(struct fsg_dev *fsg, void *data, size_t size);
|
|
static inline void utp_set_sense(struct fsg_dev *fsg, u16 code, u64 reply);
|
|
static int utp_handle_message(struct fsg_dev *fsg,
|
|
char *cdb_data,
|
|
int default_reply);
|
|
|
|
#define UTP_REPLY_PASS 0
|
|
#define UTP_REPLY_EXIT 0x8001
|
|
#define UTP_REPLY_BUSY 0x8002
|
|
#define UTP_REPLY_SIZE 0x8003
|
|
#define UTP_SENSE_KEY 9
|
|
|
|
#define UTP_MINOR 222
|
|
/* MISC_DYNAMIC_MINOR would be better, but... */
|
|
|
|
#define UTP_COMMAND_SIZE 80
|
|
|
|
#define UTP_SS_EXIT(fsg, r) utp_set_sense(fsg, UTP_REPLY_EXIT, (u64)r)
|
|
#define UTP_SS_PASS(fsg) utp_set_sense(fsg, UTP_REPLY_PASS, 0)
|
|
#define UTP_SS_BUSY(fsg, r) utp_set_sense(fsg, UTP_REPLY_BUSY, (u64)r)
|
|
#define UTP_SS_SIZE(fsg, r) utp_set_sense(fsg, UTP_REPLY_SIZE, (u64)r)
|
|
|
|
#define UTP_IOCTL_BASE 'U'
|
|
#define UTP_GET_CPU_ID _IOR(UTP_IOCTL_BASE, 0, int)
|
|
/* the structure of utp message which is mapped to 16-byte SCSI CBW's CDB */
|
|
#pragma pack(1)
|
|
struct utp_msg {
|
|
u8 f0;
|
|
u8 utp_msg_type;
|
|
u32 utp_msg_tag;
|
|
union {
|
|
struct {
|
|
u32 param_lsb;
|
|
u32 param_msb;
|
|
};
|
|
u64 param;
|
|
};
|
|
};
|
|
|
|
enum utp_msg_type {
|
|
UTP_POLL = 0,
|
|
UTP_EXEC,
|
|
UTP_GET,
|
|
UTP_PUT,
|
|
};
|
|
|
|
static struct utp_context {
|
|
wait_queue_head_t wq;
|
|
wait_queue_head_t list_full_wq;
|
|
struct mutex lock;
|
|
struct list_head read;
|
|
struct list_head write;
|
|
u32 sd, sdinfo, sdinfo_h; /* sense data */
|
|
int processed;
|
|
u8 *buffer;
|
|
u32 counter;
|
|
u64 utp_version;
|
|
u32 cur_state;
|
|
} utp_context;
|
|
|
|
static const struct file_operations utp_fops = {
|
|
.open = nonseekable_open,
|
|
.read = utp_file_read,
|
|
.write = utp_file_write,
|
|
/* .ioctl = utp_ioctl, */
|
|
.unlocked_ioctl = utp_ioctl,
|
|
};
|
|
|
|
static struct miscdevice utp_dev = {
|
|
.minor = UTP_MINOR,
|
|
.name = "utp",
|
|
.fops = &utp_fops,
|
|
};
|
|
|
|
#define UTP_FLAG_COMMAND 0x00000001
|
|
#define UTP_FLAG_DATA 0x00000002
|
|
#define UTP_FLAG_STATUS 0x00000004
|
|
#define UTP_FLAG_REPORT_BUSY 0x10000000
|
|
struct utp_message {
|
|
u32 flags;
|
|
size_t size;
|
|
union {
|
|
struct {
|
|
u64 payload;
|
|
char command[1];
|
|
};
|
|
struct {
|
|
size_t bufsize;
|
|
u8 data[1];
|
|
};
|
|
u32 status;
|
|
};
|
|
};
|
|
|
|
struct utp_user_data {
|
|
struct list_head link;
|
|
struct utp_message data;
|
|
};
|
|
#pragma pack()
|
|
|
|
static inline struct utp_context *UTP_CTX(struct fsg_dev *fsg)
|
|
{
|
|
return (struct utp_context *)fsg->utp;
|
|
}
|
|
|
|
#endif /* __FSL_UPDATER_H */
|
|
|