rawrabbit.h 4.87 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
/*
 * Public header for the raw I/O interface for PCI or PCI express interfaces
 *
 * Copyright (C) 2010 CERN (www.cern.ch)
 * Author: Alessandro Rubini <rubini@gnudd.com>
 *
 * Released according to the GNU GPL, version 2 or any later version.
 *
 * This work is part of the White Rabbit project, a research effort led
 * by CERN, the European Institute for Nuclear Research.
 */
#ifndef __RAWRABBIT_H__
#define __RAWRABBIT_H__
#include <linux/types.h>
#include <linux/ioctl.h>

#ifdef __KERNEL__ /* The initial part of the file is driver-internal stuff */
#include <linux/pci.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/wait.h>
#include <linux/completion.h>

struct rr_devsel;

struct rr_dev {
	struct rr_devsel	*devsel;
	struct pci_driver	*pci_driver;
	struct pci_device_id	*id_table;
	struct pci_dev		*pdev;		/* non-null after pciprobe */
	struct mutex		mutex;
	wait_queue_head_t	 q;
	void			*dmabuf;
	char			*fwname;
	struct timespec		 irqtime;
	unsigned long		 irqcount;
	struct completion	 complete;
	struct resource		*area[3];	/* bar 0, 2, 4 */
	void			*remap[3];	/* ioremap of bar 0, 2, 4 */
	unsigned long		 flags;
	struct work_struct	work;
	const struct firmware	*fw;
	struct completion	 fw_load;
	void			(*load_program)(struct rr_dev *); /* lm32 */
	int			 usecount;
#ifdef IS_SPEC_DEMO
	struct miscdevice	 misc;
	char			 miscname[32]; /* "spec-demo-<bus>-<slot> */
	struct list_head	 list;
#endif
};

extern char *rr_fwname; /* module parameter. If "" then defaults apply */

#define RR_FLAG_REGISTERED	0x00000001
#define RR_FLAG_IRQDISABLE	0x00000002
#define RR_FLAG_IRQREQUEST	0x00000002


#define RR_PROBE_TIMEOUT	(HZ)		/* for pci_register_drv */

/* These two live in ./loader.c */
extern void rr_ask_firmware(struct rr_dev *dev);
extern void rr_load_firmware(struct work_struct *work);

/* And, for the spec only, this is in ./spec-loader.c */
extern void spec_ask_program(struct rr_dev *dev);

#endif /* __KERNEL__ */

/* By default, the driver registers for this vendor/devid */
#define RR_DEFAULT_VENDOR	0x1a39
#define RR_DEFAULT_DEVICE	0x0004

#define RR_DEFAULT_FWNAME	"rrabbit-%P-%p@%b"
#define RR_MAX_FWNAME_SIZE	64
#define RR_DEFAULT_BUFSIZE	(1<<20)		/* 1MB */
#define RR_PLIST_SIZE		4096		/* no PAGE_SIZE in user space */
#define RR_PLIST_LEN		(RR_PLIST_SIZE / sizeof(void *))
#define RR_MAX_BUFSIZE		(RR_PLIST_SIZE * RR_PLIST_LEN)


/* This structure is used to select the device to be accessed, via ioctl */
struct rr_devsel {
	__u16 vendor;
	__u16 device;
	__u16 subvendor;	/* RR_DEVSEL_UNUSED to ignore subvendor/dev */
	__u16 subdevice;
	__u16 bus;		/* RR_DEVSEL_UNUSED to ignore bus and devfn */
	__u16 devfn;
};

#define RR_DEVSEL_UNUSED	0xffff

/* Offsets for BAR areas in llseek() and/or ioctl */
#define RR_BAR_0		0x00000000
#define RR_BAR_2		0x20000000
#define RR_BAR_4		0x40000000
#define RR_BAR_BUF		0xc0000000	/* The DMA buffer */
#define RR_IS_DMABUF(addr)	((addr) >= RR_BAR_BUF)
#define __RR_GET_BAR(x)		((x) >> 28)
#define __RR_SET_BAR(x)		((x) << 28)
#define __RR_GET_OFF(x)		((x) & 0x0fffffff)

static inline int rr_is_valid_bar(unsigned long address)
{
	int bar = __RR_GET_BAR(address);
	return bar == 0 || bar == 2 || bar == 4 || bar == 0x0c;
}

static inline int rr_is_dmabuf_bar(unsigned long address)
{
	int bar = __RR_GET_BAR(address);
	return bar == 0x0c;
}

struct rr_iocmd {
	__u32 address; /* bar and offset */
	__u32 datasize; /* 1 or 2 or 4 or 8 */
	union {
		__u8 data8;
		__u16 data16;
		__u32 data32;
		__u64 data64;
	};
};

/* ioctl commands */
#define __RR_IOC_MAGIC '4' /* random or so */

#define RR_DEVSEL	 _IOW(__RR_IOC_MAGIC, 0, struct rr_devsel)
#define RR_DEVGET	 _IOR(__RR_IOC_MAGIC, 1, struct rr_devsel)
#define RR_READ		_IOWR(__RR_IOC_MAGIC, 2, struct rr_iocmd)
#define RR_WRITE	 _IOW(__RR_IOC_MAGIC, 3, struct rr_iocmd)
#define RR_IRQWAIT	  _IO(__RR_IOC_MAGIC, 4)
#define RR_IRQENA	  _IO(__RR_IOC_MAGIC, 5)
#define RR_GETDMASIZE	  _IO(__RR_IOC_MAGIC, 6)
/* #define RR_SETDMASIZE	  _IO(__RR_IOC_MAGIC, 7, unsigned long) */
#define RR_GETPLIST	  _IO(__RR_IOC_MAGIC, 8) /* returns a whole page */


#define VFAT_IOCTL_READDIR_BOTH         _IOR('r', 1, struct dirent [2])

/* Registers from the gennum header files */
enum {
	GNGPIO_BASE = 0xA00,
	GNGPIO_DIRECTION_MODE = GNGPIO_BASE + 0x4,
	GNGPIO_OUTPUT_ENABLE = GNGPIO_BASE + 0x8,
	GNGPIO_OUTPUT_VALUE = GNGPIO_BASE + 0xC,
	GNGPIO_INPUT_VALUE = GNGPIO_BASE + 0x10,

	FCL_BASE	= 0xB00,
	FCL_CTRL	= FCL_BASE,
	FCL_STATUS	= FCL_BASE + 0x4,
	FCL_IODATA_IN	= FCL_BASE + 0x8,
	FCL_IODATA_OUT	= FCL_BASE + 0xC,
	FCL_EN		= FCL_BASE + 0x10,
	FCL_TIMER_0	= FCL_BASE + 0x14,
	FCL_TIMER_1	= FCL_BASE + 0x18,
	FCL_CLK_DIV	= FCL_BASE + 0x1C,
	FCL_IRQ		= FCL_BASE + 0x20,
	FCL_TIMER_CTRL	= FCL_BASE + 0x24,
	FCL_IM		= FCL_BASE + 0x28,
	FCL_TIMER2_0	= FCL_BASE + 0x2C,
	FCL_TIMER2_1	= FCL_BASE + 0x30,
	FCL_DBG_STS	= FCL_BASE + 0x34,
	FCL_FIFO	= 0xE00,
	PCI_SYS_CFG_SYSTEM = 0x800
};

#endif /* __RAWRABBIT_H__ */