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
|
#ifndef XPP_PROTO_H
#define XPP_PROTO_H
#include "xpd.h"
#include "slic.h"
#ifdef __KERNEL__
#include <linux/list.h>
#endif
#define PCM_CHUNKSIZE (CHANNELS_PERXPD * ZT_MAX_CHUNKSIZE)
typedef enum xpp_opcode {
XPP_NOTIMP = 0x00,
//
XPP_DESC_REQ = 0x04,
XPP_DEV_DESC = 0x05,
//
XPP_SIG_CHANGED = 0x06,
//
XPP_SLIC_WRITE = 0x0F, // Write to SLIC
XPP_CHAN_ENABLE = 0x0F, // Write to SLIC
XPP_CHAN_POWER = 0x0F, // Write to SLIC
XPP_RING = 0x0F, // Write to SLIC
XPP_SETHOOK = 0x0F, // Write to SLIC
XPP_LED = 0x0F, // Write to SLIC
XPP_RELAY_OUT = 0x0F, // Write to SLIC
XPP_SLIC_INIT = 0x0F, // Write to SLIC
XPP_SLIC_QUERY = 0x0F, // Write to SLIC
//
XPP_SLIC_REPLY = 0x10,
//
XPP_PCM_WRITE = 0x11,
XPP_PCM_READ = 0x12,
//
XPP_PCM_GEN = 0x13,
//
XPP_SYNC_SOURCE = 0x19,
XPP_SYNC_REPLY = 0x1A,
//
XPP_LOOPBACK_AX = 0x31,
XPP_LOOPBACK_XA = 0x32,
XPP_DIAG_FE = 0xFE,
} xpp_opcode_t;
/*------------------------- PROTOCOL COMMANDS ----------------------*/
#define XPP_MAX_DATA 50
typedef struct slic_data {
byte len;
byte data[40];
} __attribute__((packed)) slic_data_t;
#define PROTO_FUNC(name) xpp_proto_ ## name
#define CALL_PROTO(name, ...) PROTO_FUNC(name)( __VA_ARGS__ )
#define DECLARE_CMD(name, ...) \
int CALL_PROTO(name, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ )
/* 0x04 */ DECLARE_CMD(DESC_REQ, int xpd_num);
/* 0x0F */ DECLARE_CMD(CHAN_ENABLE, xpp_line_t lines, bool on);
/* 0x0F */ DECLARE_CMD(CHAN_POWER, xpp_line_t lines, bool on);
/* 0x0F */ DECLARE_CMD(RING, int pos, bool on);
/* 0x0F */ DECLARE_CMD(SETHOOK, xpp_line_t hook_status);
/* 0x0F */ DECLARE_CMD(LED, xpp_line_t lines, byte which, bool on);
/* 0x0F */ DECLARE_CMD(RELAY_OUT, byte which, bool on);
/* 0x0F */ DECLARE_CMD(SLIC_INIT);
/* 0x0F */ DECLARE_CMD(SLIC_QUERY, int pos, byte reg_num);
/* 0x11 */ DECLARE_CMD(PCM_WRITE, xpp_line_t hookstate, volatile byte *buf);
/* 0x13 */ DECLARE_CMD(PCM_GEN, xpp_line_t lines, volatile byte *buf);
/* 0x19 */ DECLARE_CMD(SYNC_SOURCE, bool setit, bool is_master);
/* 0x31 */ DECLARE_CMD(LOOPBACK_AX, byte *data, unsigned int size);
#define H_(op, ...) struct { \
__VA_ARGS__ \
} __attribute__((packed)) cmd_##op
/*
* This struct must be packed exactly as the wire
* representation of the packet header after the
* XPD address byte
*/
typedef struct xpp_packet_r {
byte opcode;
xpp_addr_t addr;
union {
H_(NOTIMP);
H_(DESC_REQ);
H_(DEV_DESC,
byte rev; /* Revision number */
byte type;
xpp_line_t line_status; /* hook/ring status, depending on unit */
);
H_(SIG_CHANGED,
byte type; /* unused -- we have it from DEV_DESC */
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
H_(SLIC_INIT,
xpp_line_t lines;
slic_data_t slic_data;
);
H_(SLIC_WRITE,
slic_cmd_t slic_cmd;
);
H_(SLIC_REPLY, /* Get status of a single SLIC (for debugging) */
xpp_line_t lines;
slic_reply_t info;
);
H_(PCM_WRITE,
xpp_line_t lines; // Must be 0xFF
byte pcm[PCM_CHUNKSIZE];
);
H_(PCM_READ,
xpp_line_t lines; // Must be 0xFF
byte pcm[PCM_CHUNKSIZE];
);
H_(PCM_GEN,
xpp_line_t lines;
byte gen;
byte pcm_seq[ZT_CHUNKSIZE];
);
H_(SYNC_SOURCE,
byte mask;
);
H_(SYNC_REPLY,
byte mask;
);
H_(LOOPBACK_AX,
byte data[XPP_MAX_DATA]; // FIXME: what data size?
);
H_(LOOPBACK_XA,
byte data[XPP_MAX_DATA]; // FIXME: what data size?
);
H_(DIAG_FE);
unsigned char raw[0];
};
} __attribute__((packed)) xpp_packet_r_t;
#undef H_
#ifdef __KERNEL__
enum {
XPP_PACKET_FIREANDFORGET = 0x1,
};
/**
* The packet that will actually be sent on the wire.
*
* TODO: not a good medium-level abstrction
*/
struct xpp_packet {
struct xpp_packet_r content;
unsigned int flags;
size_t datalen;
struct list_head list;
};
#define DATA_LEN(p, name) \
sizeof(p->content.cmd_ ## name)
#define PACKET_LEN(p) \
((p)->datalen + sizeof(xpp_addr_t) + 1)
#define PACKET_INIT(p, name) \
p->content.opcode = XPP_ ## name; \
p->datalen = DATA_LEN(p, name)
#define PACKET_FIELD(p, name, field) \
p->content.cmd_ ## name.field
void dump_packet(const char *msg, xpacket_t *packet, bool print_dbg);
void enqueue_xmit(xbus_t *xbus, xpacket_t *pack);
void process_sim_queue(void *xbus);
int validate_reply(xpacket_t *reply);
int packet_receive(xbus_t *xbus, xpacket_t *pack);
int proc_xpd_slic_write(struct file *file, const char __user *buffer, unsigned long count, void *data);
int proc_xpd_slic_read(char *page, char **start, off_t off, int count, int *eof, void *data);
#endif
#endif /* XPP_PROTO_H */
|