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
174
175
176
177
178
179
180
181
182
183
184
185
|
/*
* linux/drivers/misc/xillybus.h
*
* Copyright 2011 Xillybus Ltd, http://xillybus.com
*
* Header file for the Xillybus FPGA/host framework.
*
* This program is free software; you can redistribute it and/or modify
* it under the smems of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*/
#ifndef __XILLYBUS_H
#define __XILLYBUS_H
#include <linux/list.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/workqueue.h>
char xillyname[] = "xillybus";
struct xilly_endpoint_hardware;
struct xilly_page {
struct list_head node;
unsigned long addr;
unsigned int order;
};
struct xilly_dma {
struct list_head node;
struct pci_dev *pdev;
struct device *dev;
dma_addr_t dma_addr;
size_t size;
int direction;
};
struct xilly_buffer {
void *addr;
dma_addr_t dma_addr;
int end_offset; /* Counting elements, not bytes */
};
struct xilly_cleanup {
struct list_head to_kfree;
struct list_head to_pagefree;
struct list_head to_unmap;
};
struct xilly_idt_handle {
unsigned char *chandesc;
unsigned char *idt;
int entries;
};
/*
* Read-write confusion: wr_* and rd_* notation sticks to FPGA view, so
* wr_* buffers are those consumed by read(), since the FPGA writes to them
* and vice versa.
*/
struct xilly_channel {
struct xilly_endpoint *endpoint;
int chan_num;
int log2_element_size;
int seekable;
struct xilly_buffer **wr_buffers; /* FPGA writes, driver reads! */
int num_wr_buffers;
unsigned int wr_buf_size; /* In bytes */
int wr_fpga_buf_idx;
int wr_host_buf_idx;
int wr_host_buf_pos;
int wr_empty;
int wr_ready; /* Significant only when wr_empty == 1 */
int wr_sleepy;
int wr_eof;
int wr_hangup;
spinlock_t wr_spinlock;
struct mutex wr_mutex;
wait_queue_head_t wr_wait;
wait_queue_head_t wr_ready_wait;
int wr_ref_count;
int wr_synchronous;
int wr_allow_partial;
int wr_exclusive_open;
int wr_supports_nonempty;
struct xilly_buffer **rd_buffers; /* FPGA reads, driver writes! */
int num_rd_buffers;
unsigned int rd_buf_size; /* In bytes */
int rd_fpga_buf_idx;
int rd_host_buf_pos;
int rd_host_buf_idx;
int rd_full;
spinlock_t rd_spinlock;
struct mutex rd_mutex;
wait_queue_head_t rd_wait;
int rd_ref_count;
int rd_allow_partial;
int rd_synchronous;
int rd_exclusive_open;
struct delayed_work rd_workitem;
unsigned char rd_leftovers[4];
};
struct xilly_endpoint {
/*
* One of pdev and dev is always NULL, and the other is a valid
* pointer, depending on the type of device
*/
struct pci_dev *pdev;
struct device *dev;
struct resource res; /* OF devices only */
struct xilly_endpoint_hardware *ephw;
struct list_head ep_list;
int dma_using_dac; /* =1 if 64-bit DMA is used, =0 otherwise. */
u32 *registers;
int fatal_error;
struct mutex register_mutex;
wait_queue_head_t ep_wait;
/* List of memory allocations, to make release easy */
struct xilly_cleanup cleanup;
/* Channels and message handling */
struct cdev cdev;
int major;
int lowest_minor; /* Highest minor = lowest_minor + num_channels - 1 */
int num_channels; /* EXCLUDING message buffer */
struct xilly_channel **channels;
int msg_counter;
int failed_messages;
int idtlen;
u32 *msgbuf_addr;
dma_addr_t msgbuf_dma_addr;
unsigned int msg_buf_size;
};
struct xilly_endpoint_hardware {
struct module *owner;
void (*sync_single_for_cpu)(struct xilly_endpoint *,
dma_addr_t,
size_t,
int);
void (*sync_single_for_device)(struct xilly_endpoint *,
dma_addr_t,
size_t,
int);
dma_addr_t (*map_single)(struct xilly_cleanup *,
struct xilly_endpoint *,
void *,
size_t,
int);
void (*unmap_single)(struct xilly_dma *entry);
};
irqreturn_t xillybus_isr(int irq, void *data);
void xillybus_do_cleanup(struct xilly_cleanup *mem,
struct xilly_endpoint *endpoint);
struct xilly_endpoint *xillybus_init_endpoint(struct pci_dev *pdev,
struct device *dev,
struct xilly_endpoint_hardware
*ephw);
int xillybus_endpoint_discovery(struct xilly_endpoint *endpoint);
void xillybus_endpoint_remove(struct xilly_endpoint *endpoint);
#endif /* __XILLYBUS_H */
|