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
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
/** arch/arm/mach-msm/smd_rpcrouter.h
*
* Copyright (C) 2007 Google, Inc.
* Copyright (c) 2007-2011, The Linux Foundation. All rights reserved.
* Author: San Mehat <san@android.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _ARCH_ARM_MACH_MSM_SMD_RPCROUTER_H
#define _ARCH_ARM_MACH_MSM_SMD_RPCROUTER_H
#include <linux/types.h>
#include <linux/list.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
#include <linux/msm_rpcrouter.h>
#include <linux/wakelock.h>
#include <mach/msm_smd.h>
#include <mach/msm_rpcrouter.h>
/* definitions for the R2R wire protcol */
#define RPCROUTER_VERSION 1
#define RPCROUTER_PROCESSORS_MAX 4
#define RPCROUTER_MSGSIZE_MAX 512
#define RPCROUTER_PEND_REPLIES_MAX 32
#define RPCROUTER_CLIENT_BCAST_ID 0xffffffff
#define RPCROUTER_ROUTER_ADDRESS 0xfffffffe
#define RPCROUTER_PID_LOCAL 1
#define RPCROUTER_CTRL_CMD_DATA 1
#define RPCROUTER_CTRL_CMD_HELLO 2
#define RPCROUTER_CTRL_CMD_BYE 3
#define RPCROUTER_CTRL_CMD_NEW_SERVER 4
#define RPCROUTER_CTRL_CMD_REMOVE_SERVER 5
#define RPCROUTER_CTRL_CMD_REMOVE_CLIENT 6
#define RPCROUTER_CTRL_CMD_RESUME_TX 7
#define RPCROUTER_CTRL_CMD_EXIT 8
#define RPCROUTER_CTRL_CMD_PING 9
#define RPCROUTER_DEFAULT_RX_QUOTA 5
#define RPCROUTER_XPRT_EVENT_DATA 1
#define RPCROUTER_XPRT_EVENT_OPEN 2
#define RPCROUTER_XPRT_EVENT_CLOSE 3
/* Restart states for endpoint.
*
* Two different bits are specified here, one for
* the remote server notification (RESTART_PEND_SVR)
* and one for client notification (RESTART_PEND_NTFY).
* The client notification is used to ensure that
* the client gets notified by an ENETRESET return
* code at least once, even if they miss the actual
* reset event. The server notification is used to
* properly handle the reset state of the endpoint.
*/
#define RESTART_NORMAL 0x0
#define RESTART_PEND_SVR 0x1
#define RESTART_PEND_NTFY 0x2
#define RESTART_PEND_NTFY_SVR (RESTART_PEND_SVR | RESTART_PEND_NTFY)
union rr_control_msg {
uint32_t cmd;
struct {
uint32_t cmd;
uint32_t prog;
uint32_t vers;
uint32_t pid;
uint32_t cid;
} srv;
struct {
uint32_t cmd;
uint32_t pid;
uint32_t cid;
} cli;
};
struct rr_header {
uint32_t version;
uint32_t type;
uint32_t src_pid;
uint32_t src_cid;
uint32_t confirm_rx;
uint32_t size;
uint32_t dst_pid;
uint32_t dst_cid;
};
/* internals */
#define RPCROUTER_MAX_REMOTE_SERVERS 100
struct rr_fragment {
unsigned char data[RPCROUTER_MSGSIZE_MAX];
uint32_t length;
struct rr_fragment *next;
};
struct rr_packet {
struct list_head list;
struct rr_fragment *first;
struct rr_fragment *last;
struct rr_header hdr;
uint32_t mid;
uint32_t length;
};
#define PACMARK_LAST(n) ((n) & 0x80000000)
#define PACMARK_MID(n) (((n) >> 16) & 0xFF)
#define PACMARK_LEN(n) ((n) & 0xFFFF)
static inline uint32_t PACMARK(uint32_t len, uint32_t mid, uint32_t first,
uint32_t last)
{
return (len & 0xFFFF) |
((mid & 0xFF) << 16) |
((!!first) << 30) |
((!!last) << 31);
}
struct rr_server {
struct list_head list;
uint32_t pid;
uint32_t cid;
uint32_t prog;
uint32_t vers;
dev_t device_number;
struct cdev cdev;
struct device *device;
struct rpcsvr_platform_device p_device;
char pdev_name[32];
};
struct rr_remote_endpoint {
uint32_t pid;
uint32_t cid;
int tx_quota_cntr;
int quota_restart_state;
spinlock_t quota_lock;
wait_queue_head_t quota_wait;
struct list_head list;
};
struct msm_rpc_reply {
struct list_head list;
uint32_t pid;
uint32_t cid;
uint32_t prog; /* be32 */
uint32_t vers; /* be32 */
uint32_t xid; /* be32 */
};
struct msm_rpc_endpoint {
struct list_head list;
/* incomplete packets waiting for assembly */
struct list_head incomplete;
spinlock_t incomplete_lock;
/* complete packets waiting to be read */
struct list_head read_q;
spinlock_t read_q_lock;
struct wake_lock read_q_wake_lock;
wait_queue_head_t wait_q;
unsigned flags;
uint32_t forced_wakeup;
/* restart handling */
int restart_state;
spinlock_t restart_lock;
wait_queue_head_t restart_wait;
/* modem restart notifications */
int do_setup_notif;
void *client_data;
void (*cb_restart_teardown)(void *client_data);
void (*cb_restart_setup)(void *client_data);
/* endpoint address */
uint32_t pid;
uint32_t cid;
/* bound remote address
* if not connected (dst_pid == 0xffffffff) RPC_CALL writes fail
* RPC_CALLs must be to the prog/vers below or they will fail
*/
uint32_t dst_pid;
uint32_t dst_cid;
uint32_t dst_prog; /* be32 */
uint32_t dst_vers; /* be32 */
/* reply queue for inbound messages */
struct list_head reply_pend_q;
struct list_head reply_avail_q;
spinlock_t reply_q_lock;
uint32_t reply_cnt;
struct wake_lock reply_q_wake_lock;
/* device node if this endpoint is accessed via userspace */
dev_t dev;
};
enum write_data_type {
HEADER = 1,
PACKMARK,
PAYLOAD,
};
struct rpcrouter_xprt {
char *name;
void *priv;
int (*read_avail)(void);
int (*read)(void *data, uint32_t len);
int (*write_avail)(void);
int (*write)(void *data, uint32_t len, enum write_data_type type);
int (*close)(void);
};
/* shared between smd_rpcrouter*.c */
void msm_rpcrouter_xprt_notify(struct rpcrouter_xprt *xprt, unsigned event);
int __msm_rpc_read(struct msm_rpc_endpoint *ept,
struct rr_fragment **frag,
unsigned len, long timeout);
int msm_rpcrouter_close(void);
struct msm_rpc_endpoint *msm_rpcrouter_create_local_endpoint(dev_t dev);
int msm_rpcrouter_destroy_local_endpoint(struct msm_rpc_endpoint *ept);
int msm_rpcrouter_create_server_cdev(struct rr_server *server);
int msm_rpcrouter_create_server_pdev(struct rr_server *server);
int msm_rpcrouter_init_devices(void);
void msm_rpcrouter_exit_devices(void);
void get_requesting_client(struct msm_rpc_endpoint *ept, uint32_t xid,
struct msm_rpc_client_info *clnt_info);
extern dev_t msm_rpcrouter_devno;
extern struct completion rpc_remote_router_up;
extern struct class *msm_rpcrouter_class;
void xdr_init(struct msm_rpc_xdr *xdr);
void xdr_init_input(struct msm_rpc_xdr *xdr, void *buf, uint32_t size);
void xdr_init_output(struct msm_rpc_xdr *xdr, void *buf, uint32_t size);
void xdr_clean_input(struct msm_rpc_xdr *xdr);
void xdr_clean_output(struct msm_rpc_xdr *xdr);
uint32_t xdr_read_avail(struct msm_rpc_xdr *xdr);
#endif
|