diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/n_r3964.c | 2097 |
1 files changed, 981 insertions, 1116 deletions
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index dc6d41841457..fab1b7d42858 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c | |||
@@ -60,62 +60,56 @@ | |||
60 | #include <linux/slab.h> | 60 | #include <linux/slab.h> |
61 | #include <linux/tty.h> | 61 | #include <linux/tty.h> |
62 | #include <linux/errno.h> | 62 | #include <linux/errno.h> |
63 | #include <linux/string.h> /* used in new tty drivers */ | 63 | #include <linux/string.h> /* used in new tty drivers */ |
64 | #include <linux/signal.h> /* used in new tty drivers */ | 64 | #include <linux/signal.h> /* used in new tty drivers */ |
65 | #include <linux/ioctl.h> | 65 | #include <linux/ioctl.h> |
66 | #include <linux/n_r3964.h> | 66 | #include <linux/n_r3964.h> |
67 | #include <linux/poll.h> | 67 | #include <linux/poll.h> |
68 | #include <linux/init.h> | 68 | #include <linux/init.h> |
69 | #include <asm/uaccess.h> | 69 | #include <asm/uaccess.h> |
70 | 70 | ||
71 | 71 | /*#define DEBUG_QUEUE*/ | |
72 | //#define DEBUG_QUEUE | ||
73 | 72 | ||
74 | /* Log successful handshake and protocol operations */ | 73 | /* Log successful handshake and protocol operations */ |
75 | //#define DEBUG_PROTO_S | 74 | /*#define DEBUG_PROTO_S*/ |
76 | 75 | ||
77 | /* Log handshake and protocol errors: */ | 76 | /* Log handshake and protocol errors: */ |
78 | //#define DEBUG_PROTO_E | 77 | /*#define DEBUG_PROTO_E*/ |
79 | 78 | ||
80 | /* Log Linediscipline operations (open, close, read, write...): */ | 79 | /* Log Linediscipline operations (open, close, read, write...): */ |
81 | //#define DEBUG_LDISC | 80 | /*#define DEBUG_LDISC*/ |
82 | 81 | ||
83 | /* Log module and memory operations (init, cleanup; kmalloc, kfree): */ | 82 | /* Log module and memory operations (init, cleanup; kmalloc, kfree): */ |
84 | //#define DEBUG_MODUL | 83 | /*#define DEBUG_MODUL*/ |
85 | 84 | ||
86 | /* Macro helpers for debug output: */ | 85 | /* Macro helpers for debug output: */ |
87 | #define TRACE(format, args...) printk("r3964: " format "\n" , ## args); | 86 | #define TRACE(format, args...) printk("r3964: " format "\n" , ## args) |
88 | 87 | ||
89 | #ifdef DEBUG_MODUL | 88 | #ifdef DEBUG_MODUL |
90 | #define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args); | 89 | #define TRACE_M(format, args...) printk("r3964: " format "\n" , ## args) |
91 | #else | 90 | #else |
92 | #define TRACE_M(fmt, arg...) /**/ | 91 | #define TRACE_M(fmt, arg...) do {} while (0) |
93 | #endif | 92 | #endif |
94 | |||
95 | #ifdef DEBUG_PROTO_S | 93 | #ifdef DEBUG_PROTO_S |
96 | #define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args); | 94 | #define TRACE_PS(format, args...) printk("r3964: " format "\n" , ## args) |
97 | #else | 95 | #else |
98 | #define TRACE_PS(fmt, arg...) /**/ | 96 | #define TRACE_PS(fmt, arg...) do {} while (0) |
99 | #endif | 97 | #endif |
100 | |||
101 | #ifdef DEBUG_PROTO_E | 98 | #ifdef DEBUG_PROTO_E |
102 | #define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args); | 99 | #define TRACE_PE(format, args...) printk("r3964: " format "\n" , ## args) |
103 | #else | 100 | #else |
104 | #define TRACE_PE(fmt, arg...) /**/ | 101 | #define TRACE_PE(fmt, arg...) do {} while (0) |
105 | #endif | 102 | #endif |
106 | |||
107 | #ifdef DEBUG_LDISC | 103 | #ifdef DEBUG_LDISC |
108 | #define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args); | 104 | #define TRACE_L(format, args...) printk("r3964: " format "\n" , ## args) |
109 | #else | 105 | #else |
110 | #define TRACE_L(fmt, arg...) /**/ | 106 | #define TRACE_L(fmt, arg...) do {} while (0) |
111 | #endif | 107 | #endif |
112 | |||
113 | #ifdef DEBUG_QUEUE | 108 | #ifdef DEBUG_QUEUE |
114 | #define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args); | 109 | #define TRACE_Q(format, args...) printk("r3964: " format "\n" , ## args) |
115 | #else | 110 | #else |
116 | #define TRACE_Q(fmt, arg...) /**/ | 111 | #define TRACE_Q(fmt, arg...) do {} while (0) |
117 | #endif | 112 | #endif |
118 | |||
119 | static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); | 113 | static void add_tx_queue(struct r3964_info *, struct r3964_block_header *); |
120 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); | 114 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code); |
121 | static void put_char(struct r3964_info *pInfo, unsigned char ch); | 115 | static void put_char(struct r3964_info *pInfo, unsigned char ch); |
@@ -126,937 +120,830 @@ static void receive_char(struct r3964_info *pInfo, const unsigned char c); | |||
126 | static void receive_error(struct r3964_info *pInfo, const char flag); | 120 | static void receive_error(struct r3964_info *pInfo, const char flag); |
127 | static void on_timeout(unsigned long priv); | 121 | static void on_timeout(unsigned long priv); |
128 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); | 122 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg); |
129 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf); | 123 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, |
124 | unsigned char __user * buf); | ||
130 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, | 125 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, |
131 | int error_code, struct r3964_block_header *pBlock); | 126 | int error_code, struct r3964_block_header *pBlock); |
132 | static struct r3964_message* remove_msg(struct r3964_info *pInfo, | 127 | static struct r3964_message *remove_msg(struct r3964_info *pInfo, |
133 | struct r3964_client_info *pClient); | 128 | struct r3964_client_info *pClient); |
134 | static void remove_client_block(struct r3964_info *pInfo, | 129 | static void remove_client_block(struct r3964_info *pInfo, |
135 | struct r3964_client_info *pClient); | 130 | struct r3964_client_info *pClient); |
136 | 131 | ||
137 | static int r3964_open(struct tty_struct *tty); | 132 | static int r3964_open(struct tty_struct *tty); |
138 | static void r3964_close(struct tty_struct *tty); | 133 | static void r3964_close(struct tty_struct *tty); |
139 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | 134 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, |
140 | unsigned char __user *buf, size_t nr); | 135 | unsigned char __user * buf, size_t nr); |
141 | static ssize_t r3964_write(struct tty_struct * tty, struct file * file, | 136 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, |
142 | const unsigned char * buf, size_t nr); | 137 | const unsigned char *buf, size_t nr); |
143 | static int r3964_ioctl(struct tty_struct * tty, struct file * file, | 138 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, |
144 | unsigned int cmd, unsigned long arg); | 139 | unsigned int cmd, unsigned long arg); |
145 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old); | 140 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old); |
146 | static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, | 141 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, |
147 | struct poll_table_struct *wait); | 142 | struct poll_table_struct *wait); |
148 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 143 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, |
149 | char *fp, int count); | 144 | char *fp, int count); |
150 | 145 | ||
151 | static struct tty_ldisc tty_ldisc_N_R3964 = { | 146 | static struct tty_ldisc tty_ldisc_N_R3964 = { |
152 | .owner = THIS_MODULE, | 147 | .owner = THIS_MODULE, |
153 | .magic = TTY_LDISC_MAGIC, | 148 | .magic = TTY_LDISC_MAGIC, |
154 | .name = "R3964", | 149 | .name = "R3964", |
155 | .open = r3964_open, | 150 | .open = r3964_open, |
156 | .close = r3964_close, | 151 | .close = r3964_close, |
157 | .read = r3964_read, | 152 | .read = r3964_read, |
158 | .write = r3964_write, | 153 | .write = r3964_write, |
159 | .ioctl = r3964_ioctl, | 154 | .ioctl = r3964_ioctl, |
160 | .set_termios = r3964_set_termios, | 155 | .set_termios = r3964_set_termios, |
161 | .poll = r3964_poll, | 156 | .poll = r3964_poll, |
162 | .receive_buf = r3964_receive_buf, | 157 | .receive_buf = r3964_receive_buf, |
163 | }; | 158 | }; |
164 | 159 | ||
165 | |||
166 | |||
167 | static void dump_block(const unsigned char *block, unsigned int length) | 160 | static void dump_block(const unsigned char *block, unsigned int length) |
168 | { | 161 | { |
169 | unsigned int i,j; | 162 | unsigned int i, j; |
170 | char linebuf[16*3+1]; | 163 | char linebuf[16 * 3 + 1]; |
171 | 164 | ||
172 | for(i=0;i<length;i+=16) | 165 | for (i = 0; i < length; i += 16) { |
173 | { | 166 | for (j = 0; (j < 16) && (j + i < length); j++) { |
174 | for(j=0;(j<16) && (j+i<length);j++) | 167 | sprintf(linebuf + 3 * j, "%02x ", block[i + j]); |
175 | { | 168 | } |
176 | sprintf(linebuf+3*j,"%02x ",block[i+j]); | 169 | linebuf[3 * j] = '\0'; |
177 | } | 170 | TRACE_PS("%s", linebuf); |
178 | linebuf[3*j]='\0'; | 171 | } |
179 | TRACE_PS("%s",linebuf); | ||
180 | } | ||
181 | } | 172 | } |
182 | 173 | ||
183 | |||
184 | |||
185 | |||
186 | /************************************************************* | 174 | /************************************************************* |
187 | * Driver initialisation | 175 | * Driver initialisation |
188 | *************************************************************/ | 176 | *************************************************************/ |
189 | 177 | ||
190 | |||
191 | /************************************************************* | 178 | /************************************************************* |
192 | * Module support routines | 179 | * Module support routines |
193 | *************************************************************/ | 180 | *************************************************************/ |
194 | 181 | ||
195 | static void __exit r3964_exit(void) | 182 | static void __exit r3964_exit(void) |
196 | { | 183 | { |
197 | int status; | 184 | int status; |
198 | 185 | ||
199 | TRACE_M ("cleanup_module()"); | 186 | TRACE_M("cleanup_module()"); |
200 | 187 | ||
201 | status=tty_unregister_ldisc(N_R3964); | 188 | status = tty_unregister_ldisc(N_R3964); |
202 | 189 | ||
203 | if(status!=0) | 190 | if (status != 0) { |
204 | { | 191 | printk(KERN_ERR "r3964: error unregistering linediscipline: " |
205 | printk(KERN_ERR "r3964: error unregistering linediscipline: %d\n", status); | 192 | "%d\n", status); |
206 | } | 193 | } else { |
207 | else | 194 | TRACE_L("linediscipline successfully unregistered"); |
208 | { | 195 | } |
209 | TRACE_L("linediscipline successfully unregistered"); | ||
210 | } | ||
211 | |||
212 | } | 196 | } |
213 | 197 | ||
214 | static int __init r3964_init(void) | 198 | static int __init r3964_init(void) |
215 | { | 199 | { |
216 | int status; | 200 | int status; |
217 | 201 | ||
218 | printk ("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); | 202 | printk("r3964: Philips r3964 Driver $Revision: 1.10 $\n"); |
219 | 203 | ||
220 | /* | 204 | /* |
221 | * Register the tty line discipline | 205 | * Register the tty line discipline |
222 | */ | 206 | */ |
223 | 207 | ||
224 | status = tty_register_ldisc (N_R3964, &tty_ldisc_N_R3964); | 208 | status = tty_register_ldisc(N_R3964, &tty_ldisc_N_R3964); |
225 | if (status == 0) | 209 | if (status == 0) { |
226 | { | 210 | TRACE_L("line discipline %d registered", N_R3964); |
227 | TRACE_L("line discipline %d registered", N_R3964); | 211 | TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, |
228 | TRACE_L("flags=%x num=%x", tty_ldisc_N_R3964.flags, | 212 | tty_ldisc_N_R3964.num); |
229 | tty_ldisc_N_R3964.num); | 213 | TRACE_L("open=%p", tty_ldisc_N_R3964.open); |
230 | TRACE_L("open=%p", tty_ldisc_N_R3964.open); | 214 | TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); |
231 | TRACE_L("tty_ldisc_N_R3964 = %p", &tty_ldisc_N_R3964); | 215 | } else { |
232 | } | 216 | printk(KERN_ERR "r3964: error registering line discipline: " |
233 | else | 217 | "%d\n", status); |
234 | { | 218 | } |
235 | printk (KERN_ERR "r3964: error registering line discipline: %d\n", status); | 219 | return status; |
236 | } | ||
237 | return status; | ||
238 | } | 220 | } |
239 | 221 | ||
240 | module_init(r3964_init); | 222 | module_init(r3964_init); |
241 | module_exit(r3964_exit); | 223 | module_exit(r3964_exit); |
242 | 224 | ||
243 | |||
244 | /************************************************************* | 225 | /************************************************************* |
245 | * Protocol implementation routines | 226 | * Protocol implementation routines |
246 | *************************************************************/ | 227 | *************************************************************/ |
247 | 228 | ||
248 | static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) | 229 | static void add_tx_queue(struct r3964_info *pInfo, |
230 | struct r3964_block_header *pHeader) | ||
249 | { | 231 | { |
250 | unsigned long flags; | 232 | unsigned long flags; |
251 | 233 | ||
252 | spin_lock_irqsave(&pInfo->lock, flags); | 234 | spin_lock_irqsave(&pInfo->lock, flags); |
253 | 235 | ||
254 | pHeader->next = NULL; | 236 | pHeader->next = NULL; |
255 | 237 | ||
256 | if(pInfo->tx_last == NULL) | 238 | if (pInfo->tx_last == NULL) { |
257 | { | 239 | pInfo->tx_first = pInfo->tx_last = pHeader; |
258 | pInfo->tx_first = pInfo->tx_last = pHeader; | 240 | } else { |
259 | } | 241 | pInfo->tx_last->next = pHeader; |
260 | else | 242 | pInfo->tx_last = pHeader; |
261 | { | 243 | } |
262 | pInfo->tx_last->next = pHeader; | 244 | |
263 | pInfo->tx_last = pHeader; | 245 | spin_unlock_irqrestore(&pInfo->lock, flags); |
264 | } | 246 | |
265 | 247 | TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", | |
266 | spin_unlock_irqrestore(&pInfo->lock, flags); | 248 | pHeader, pHeader->length, pInfo->tx_first); |
267 | |||
268 | TRACE_Q("add_tx_queue %p, length %d, tx_first = %p", | ||
269 | pHeader, pHeader->length, pInfo->tx_first ); | ||
270 | } | 249 | } |
271 | 250 | ||
272 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) | 251 | static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code) |
273 | { | 252 | { |
274 | struct r3964_block_header *pHeader; | 253 | struct r3964_block_header *pHeader; |
275 | unsigned long flags; | 254 | unsigned long flags; |
276 | #ifdef DEBUG_QUEUE | 255 | #ifdef DEBUG_QUEUE |
277 | struct r3964_block_header *pDump; | 256 | struct r3964_block_header *pDump; |
278 | #endif | 257 | #endif |
279 | |||
280 | pHeader = pInfo->tx_first; | ||
281 | 258 | ||
282 | if(pHeader==NULL) | 259 | pHeader = pInfo->tx_first; |
283 | return; | 260 | |
261 | if (pHeader == NULL) | ||
262 | return; | ||
284 | 263 | ||
285 | #ifdef DEBUG_QUEUE | 264 | #ifdef DEBUG_QUEUE |
286 | printk("r3964: remove_from_tx_queue: %p, length %u - ", | 265 | printk("r3964: remove_from_tx_queue: %p, length %u - ", |
287 | pHeader, pHeader->length ); | 266 | pHeader, pHeader->length); |
288 | for(pDump=pHeader;pDump;pDump=pDump->next) | 267 | for (pDump = pHeader; pDump; pDump = pDump->next) |
289 | printk("%p ", pDump); | 268 | printk("%p ", pDump); |
290 | printk("\n"); | 269 | printk("\n"); |
291 | #endif | 270 | #endif |
292 | 271 | ||
272 | if (pHeader->owner) { | ||
273 | if (error_code) { | ||
274 | add_msg(pHeader->owner, R3964_MSG_ACK, 0, | ||
275 | error_code, NULL); | ||
276 | } else { | ||
277 | add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, | ||
278 | error_code, NULL); | ||
279 | } | ||
280 | wake_up_interruptible(&pInfo->read_wait); | ||
281 | } | ||
282 | |||
283 | spin_lock_irqsave(&pInfo->lock, flags); | ||
284 | |||
285 | pInfo->tx_first = pHeader->next; | ||
286 | if (pInfo->tx_first == NULL) { | ||
287 | pInfo->tx_last = NULL; | ||
288 | } | ||
289 | |||
290 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
291 | |||
292 | kfree(pHeader); | ||
293 | TRACE_M("remove_from_tx_queue - kfree %p", pHeader); | ||
293 | 294 | ||
294 | if(pHeader->owner) | 295 | TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", |
295 | { | 296 | pInfo->tx_first, pInfo->tx_last); |
296 | if(error_code) | ||
297 | { | ||
298 | add_msg(pHeader->owner, R3964_MSG_ACK, 0, | ||
299 | error_code, NULL); | ||
300 | } | ||
301 | else | ||
302 | { | ||
303 | add_msg(pHeader->owner, R3964_MSG_ACK, pHeader->length, | ||
304 | error_code, NULL); | ||
305 | } | ||
306 | wake_up_interruptible (&pInfo->read_wait); | ||
307 | } | ||
308 | |||
309 | spin_lock_irqsave(&pInfo->lock, flags); | ||
310 | |||
311 | pInfo->tx_first = pHeader->next; | ||
312 | if(pInfo->tx_first==NULL) | ||
313 | { | ||
314 | pInfo->tx_last = NULL; | ||
315 | } | ||
316 | |||
317 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
318 | |||
319 | kfree(pHeader); | ||
320 | TRACE_M("remove_from_tx_queue - kfree %p",pHeader); | ||
321 | |||
322 | TRACE_Q("remove_from_tx_queue: tx_first = %p, tx_last = %p", | ||
323 | pInfo->tx_first, pInfo->tx_last ); | ||
324 | } | 297 | } |
325 | 298 | ||
326 | static void add_rx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader) | 299 | static void add_rx_queue(struct r3964_info *pInfo, |
300 | struct r3964_block_header *pHeader) | ||
327 | { | 301 | { |
328 | unsigned long flags; | 302 | unsigned long flags; |
329 | 303 | ||
330 | spin_lock_irqsave(&pInfo->lock, flags); | 304 | spin_lock_irqsave(&pInfo->lock, flags); |
331 | 305 | ||
332 | pHeader->next = NULL; | 306 | pHeader->next = NULL; |
333 | 307 | ||
334 | if(pInfo->rx_last == NULL) | 308 | if (pInfo->rx_last == NULL) { |
335 | { | 309 | pInfo->rx_first = pInfo->rx_last = pHeader; |
336 | pInfo->rx_first = pInfo->rx_last = pHeader; | 310 | } else { |
337 | } | 311 | pInfo->rx_last->next = pHeader; |
338 | else | 312 | pInfo->rx_last = pHeader; |
339 | { | 313 | } |
340 | pInfo->rx_last->next = pHeader; | 314 | pInfo->blocks_in_rx_queue++; |
341 | pInfo->rx_last = pHeader; | 315 | |
342 | } | 316 | spin_unlock_irqrestore(&pInfo->lock, flags); |
343 | pInfo->blocks_in_rx_queue++; | 317 | |
344 | 318 | TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", | |
345 | spin_unlock_irqrestore(&pInfo->lock, flags); | 319 | pHeader, pHeader->length, |
346 | 320 | pInfo->rx_first, pInfo->blocks_in_rx_queue); | |
347 | TRACE_Q("add_rx_queue: %p, length = %d, rx_first = %p, count = %d", | ||
348 | pHeader, pHeader->length, | ||
349 | pInfo->rx_first, pInfo->blocks_in_rx_queue); | ||
350 | } | 321 | } |
351 | 322 | ||
352 | static void remove_from_rx_queue(struct r3964_info *pInfo, | 323 | static void remove_from_rx_queue(struct r3964_info *pInfo, |
353 | struct r3964_block_header *pHeader) | 324 | struct r3964_block_header *pHeader) |
354 | { | 325 | { |
355 | unsigned long flags; | 326 | unsigned long flags; |
356 | struct r3964_block_header *pFind; | 327 | struct r3964_block_header *pFind; |
357 | 328 | ||
358 | if(pHeader==NULL) | 329 | if (pHeader == NULL) |
359 | return; | 330 | return; |
360 | 331 | ||
361 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", | 332 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", |
362 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); | 333 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); |
363 | TRACE_Q("remove_from_rx_queue: %p, length %u", | 334 | TRACE_Q("remove_from_rx_queue: %p, length %u", |
364 | pHeader, pHeader->length ); | 335 | pHeader, pHeader->length); |
365 | 336 | ||
366 | spin_lock_irqsave(&pInfo->lock, flags); | 337 | spin_lock_irqsave(&pInfo->lock, flags); |
367 | 338 | ||
368 | if(pInfo->rx_first == pHeader) | 339 | if (pInfo->rx_first == pHeader) { |
369 | { | 340 | /* Remove the first block in the linked list: */ |
370 | /* Remove the first block in the linked list: */ | 341 | pInfo->rx_first = pHeader->next; |
371 | pInfo->rx_first = pHeader->next; | 342 | |
372 | 343 | if (pInfo->rx_first == NULL) { | |
373 | if(pInfo->rx_first==NULL) | 344 | pInfo->rx_last = NULL; |
374 | { | 345 | } |
375 | pInfo->rx_last = NULL; | 346 | pInfo->blocks_in_rx_queue--; |
376 | } | 347 | } else { |
377 | pInfo->blocks_in_rx_queue--; | 348 | /* Find block to remove: */ |
378 | } | 349 | for (pFind = pInfo->rx_first; pFind; pFind = pFind->next) { |
379 | else | 350 | if (pFind->next == pHeader) { |
380 | { | 351 | /* Got it. */ |
381 | /* Find block to remove: */ | 352 | pFind->next = pHeader->next; |
382 | for(pFind=pInfo->rx_first; pFind; pFind=pFind->next) | 353 | pInfo->blocks_in_rx_queue--; |
383 | { | 354 | if (pFind->next == NULL) { |
384 | if(pFind->next == pHeader) | 355 | /* Oh, removed the last one! */ |
385 | { | 356 | pInfo->rx_last = pFind; |
386 | /* Got it. */ | 357 | } |
387 | pFind->next = pHeader->next; | 358 | break; |
388 | pInfo->blocks_in_rx_queue--; | 359 | } |
389 | if(pFind->next==NULL) | 360 | } |
390 | { | 361 | } |
391 | /* Oh, removed the last one! */ | 362 | |
392 | pInfo->rx_last = pFind; | 363 | spin_unlock_irqrestore(&pInfo->lock, flags); |
393 | } | 364 | |
394 | break; | 365 | kfree(pHeader); |
395 | } | 366 | TRACE_M("remove_from_rx_queue - kfree %p", pHeader); |
396 | } | 367 | |
397 | } | 368 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", |
398 | 369 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue); | |
399 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
400 | |||
401 | kfree(pHeader); | ||
402 | TRACE_M("remove_from_rx_queue - kfree %p",pHeader); | ||
403 | |||
404 | TRACE_Q("remove_from_rx_queue: rx_first = %p, rx_last = %p, count = %d", | ||
405 | pInfo->rx_first, pInfo->rx_last, pInfo->blocks_in_rx_queue ); | ||
406 | } | 370 | } |
407 | 371 | ||
408 | static void put_char(struct r3964_info *pInfo, unsigned char ch) | 372 | static void put_char(struct r3964_info *pInfo, unsigned char ch) |
409 | { | 373 | { |
410 | struct tty_struct *tty = pInfo->tty; | 374 | struct tty_struct *tty = pInfo->tty; |
411 | 375 | ||
412 | if(tty==NULL) | 376 | if (tty == NULL) |
413 | return; | 377 | return; |
414 | 378 | ||
415 | if(tty->driver->put_char) | 379 | if (tty->driver->put_char) { |
416 | { | 380 | tty->driver->put_char(tty, ch); |
417 | tty->driver->put_char(tty, ch); | 381 | } |
418 | } | 382 | pInfo->bcc ^= ch; |
419 | pInfo->bcc ^= ch; | ||
420 | } | 383 | } |
421 | 384 | ||
422 | static void flush(struct r3964_info *pInfo) | 385 | static void flush(struct r3964_info *pInfo) |
423 | { | 386 | { |
424 | struct tty_struct *tty = pInfo->tty; | 387 | struct tty_struct *tty = pInfo->tty; |
425 | 388 | ||
426 | if(tty==NULL) | 389 | if (tty == NULL) |
427 | return; | 390 | return; |
428 | 391 | ||
429 | if(tty->driver->flush_chars) | 392 | if (tty->driver->flush_chars) { |
430 | { | 393 | tty->driver->flush_chars(tty); |
431 | tty->driver->flush_chars(tty); | 394 | } |
432 | } | ||
433 | } | 395 | } |
434 | 396 | ||
435 | static void trigger_transmit(struct r3964_info *pInfo) | 397 | static void trigger_transmit(struct r3964_info *pInfo) |
436 | { | 398 | { |
437 | unsigned long flags; | 399 | unsigned long flags; |
438 | |||
439 | 400 | ||
440 | spin_lock_irqsave(&pInfo->lock, flags); | 401 | spin_lock_irqsave(&pInfo->lock, flags); |
441 | 402 | ||
442 | if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL)) | 403 | if ((pInfo->state == R3964_IDLE) && (pInfo->tx_first != NULL)) { |
443 | { | 404 | pInfo->state = R3964_TX_REQUEST; |
444 | pInfo->state = R3964_TX_REQUEST; | 405 | pInfo->nRetry = 0; |
445 | pInfo->nRetry=0; | 406 | pInfo->flags &= ~R3964_ERROR; |
446 | pInfo->flags &= ~R3964_ERROR; | 407 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); |
447 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); | ||
448 | 408 | ||
449 | spin_unlock_irqrestore(&pInfo->lock, flags); | 409 | spin_unlock_irqrestore(&pInfo->lock, flags); |
450 | 410 | ||
451 | TRACE_PS("trigger_transmit - sent STX"); | 411 | TRACE_PS("trigger_transmit - sent STX"); |
452 | 412 | ||
453 | put_char(pInfo, STX); | 413 | put_char(pInfo, STX); |
454 | flush(pInfo); | 414 | flush(pInfo); |
455 | 415 | ||
456 | pInfo->bcc = 0; | 416 | pInfo->bcc = 0; |
457 | } | 417 | } else { |
458 | else | 418 | spin_unlock_irqrestore(&pInfo->lock, flags); |
459 | { | 419 | } |
460 | spin_unlock_irqrestore(&pInfo->lock, flags); | ||
461 | } | ||
462 | } | 420 | } |
463 | 421 | ||
464 | static void retry_transmit(struct r3964_info *pInfo) | 422 | static void retry_transmit(struct r3964_info *pInfo) |
465 | { | 423 | { |
466 | if(pInfo->nRetry<R3964_MAX_RETRIES) | 424 | if (pInfo->nRetry < R3964_MAX_RETRIES) { |
467 | { | 425 | TRACE_PE("transmission failed. Retry #%d", pInfo->nRetry); |
468 | TRACE_PE("transmission failed. Retry #%d", | 426 | pInfo->bcc = 0; |
469 | pInfo->nRetry); | 427 | put_char(pInfo, STX); |
470 | pInfo->bcc = 0; | 428 | flush(pInfo); |
471 | put_char(pInfo, STX); | 429 | pInfo->state = R3964_TX_REQUEST; |
472 | flush(pInfo); | 430 | pInfo->nRetry++; |
473 | pInfo->state = R3964_TX_REQUEST; | 431 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); |
474 | pInfo->nRetry++; | 432 | } else { |
475 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); | 433 | TRACE_PE("transmission failed after %d retries", |
476 | } | 434 | R3964_MAX_RETRIES); |
477 | else | 435 | |
478 | { | 436 | remove_from_tx_queue(pInfo, R3964_TX_FAIL); |
479 | TRACE_PE("transmission failed after %d retries", | 437 | |
480 | R3964_MAX_RETRIES); | 438 | put_char(pInfo, NAK); |
481 | 439 | flush(pInfo); | |
482 | remove_from_tx_queue(pInfo, R3964_TX_FAIL); | 440 | pInfo->state = R3964_IDLE; |
483 | 441 | ||
484 | put_char(pInfo, NAK); | 442 | trigger_transmit(pInfo); |
485 | flush(pInfo); | 443 | } |
486 | pInfo->state = R3964_IDLE; | ||
487 | |||
488 | trigger_transmit(pInfo); | ||
489 | } | ||
490 | } | 444 | } |
491 | 445 | ||
492 | |||
493 | static void transmit_block(struct r3964_info *pInfo) | 446 | static void transmit_block(struct r3964_info *pInfo) |
494 | { | 447 | { |
495 | struct tty_struct *tty = pInfo->tty; | 448 | struct tty_struct *tty = pInfo->tty; |
496 | struct r3964_block_header *pBlock = pInfo->tx_first; | 449 | struct r3964_block_header *pBlock = pInfo->tx_first; |
497 | int room=0; | 450 | int room = 0; |
498 | 451 | ||
499 | if((tty==NULL) || (pBlock==NULL)) | 452 | if ((tty == NULL) || (pBlock == NULL)) { |
500 | { | 453 | return; |
501 | return; | 454 | } |
502 | } | 455 | |
503 | 456 | if (tty->driver->write_room) | |
504 | if(tty->driver->write_room) | 457 | room = tty->driver->write_room(tty); |
505 | room=tty->driver->write_room(tty); | 458 | |
506 | 459 | TRACE_PS("transmit_block %p, room %d, length %d", | |
507 | TRACE_PS("transmit_block %p, room %d, length %d", | 460 | pBlock, room, pBlock->length); |
508 | pBlock, room, pBlock->length); | 461 | |
509 | 462 | while (pInfo->tx_position < pBlock->length) { | |
510 | while(pInfo->tx_position < pBlock->length) | 463 | if (room < 2) |
511 | { | 464 | break; |
512 | if(room<2) | 465 | |
513 | break; | 466 | if (pBlock->data[pInfo->tx_position] == DLE) { |
514 | 467 | /* send additional DLE char: */ | |
515 | if(pBlock->data[pInfo->tx_position]==DLE) | 468 | put_char(pInfo, DLE); |
516 | { | 469 | } |
517 | /* send additional DLE char: */ | 470 | put_char(pInfo, pBlock->data[pInfo->tx_position++]); |
518 | put_char(pInfo, DLE); | 471 | |
519 | } | 472 | room--; |
520 | put_char(pInfo, pBlock->data[pInfo->tx_position++]); | 473 | } |
521 | 474 | ||
522 | room--; | 475 | if ((pInfo->tx_position == pBlock->length) && (room >= 3)) { |
523 | } | 476 | put_char(pInfo, DLE); |
524 | 477 | put_char(pInfo, ETX); | |
525 | if((pInfo->tx_position == pBlock->length) && (room>=3)) | 478 | if (pInfo->flags & R3964_BCC) { |
526 | { | 479 | put_char(pInfo, pInfo->bcc); |
527 | put_char(pInfo, DLE); | 480 | } |
528 | put_char(pInfo, ETX); | 481 | pInfo->state = R3964_WAIT_FOR_TX_ACK; |
529 | if(pInfo->flags & R3964_BCC) | 482 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); |
530 | { | 483 | } |
531 | put_char(pInfo, pInfo->bcc); | 484 | flush(pInfo); |
532 | } | ||
533 | pInfo->state = R3964_WAIT_FOR_TX_ACK; | ||
534 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ); | ||
535 | } | ||
536 | flush(pInfo); | ||
537 | } | 485 | } |
538 | 486 | ||
539 | static void on_receive_block(struct r3964_info *pInfo) | 487 | static void on_receive_block(struct r3964_info *pInfo) |
540 | { | 488 | { |
541 | unsigned int length; | 489 | unsigned int length; |
542 | struct r3964_client_info *pClient; | 490 | struct r3964_client_info *pClient; |
543 | struct r3964_block_header *pBlock; | 491 | struct r3964_block_header *pBlock; |
544 | 492 | ||
545 | length=pInfo->rx_position; | 493 | length = pInfo->rx_position; |
546 | 494 | ||
547 | /* compare byte checksum characters: */ | 495 | /* compare byte checksum characters: */ |
548 | if(pInfo->flags & R3964_BCC) | 496 | if (pInfo->flags & R3964_BCC) { |
549 | { | 497 | if (pInfo->bcc != pInfo->last_rx) { |
550 | if(pInfo->bcc!=pInfo->last_rx) | 498 | TRACE_PE("checksum error - got %x but expected %x", |
551 | { | 499 | pInfo->last_rx, pInfo->bcc); |
552 | TRACE_PE("checksum error - got %x but expected %x", | 500 | pInfo->flags |= R3964_CHECKSUM; |
553 | pInfo->last_rx, pInfo->bcc); | 501 | } |
554 | pInfo->flags |= R3964_CHECKSUM; | 502 | } |
555 | } | 503 | |
556 | } | 504 | /* check for errors (parity, overrun,...): */ |
557 | 505 | if (pInfo->flags & R3964_ERROR) { | |
558 | /* check for errors (parity, overrun,...): */ | 506 | TRACE_PE("on_receive_block - transmission failed error %x", |
559 | if(pInfo->flags & R3964_ERROR) | 507 | pInfo->flags & R3964_ERROR); |
560 | { | 508 | |
561 | TRACE_PE("on_receive_block - transmission failed error %x", | 509 | put_char(pInfo, NAK); |
562 | pInfo->flags & R3964_ERROR); | 510 | flush(pInfo); |
563 | 511 | if (pInfo->nRetry < R3964_MAX_RETRIES) { | |
564 | put_char(pInfo, NAK); | 512 | pInfo->state = R3964_WAIT_FOR_RX_REPEAT; |
565 | flush(pInfo); | 513 | pInfo->nRetry++; |
566 | if(pInfo->nRetry<R3964_MAX_RETRIES) | 514 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); |
567 | { | 515 | } else { |
568 | pInfo->state=R3964_WAIT_FOR_RX_REPEAT; | 516 | TRACE_PE("on_receive_block - failed after max retries"); |
569 | pInfo->nRetry++; | 517 | pInfo->state = R3964_IDLE; |
570 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC); | 518 | } |
571 | } | 519 | return; |
572 | else | 520 | } |
573 | { | 521 | |
574 | TRACE_PE("on_receive_block - failed after max retries"); | 522 | /* received block; submit DLE: */ |
575 | pInfo->state=R3964_IDLE; | 523 | put_char(pInfo, DLE); |
576 | } | 524 | flush(pInfo); |
577 | return; | 525 | del_timer_sync(&pInfo->tmr); |
578 | } | 526 | TRACE_PS(" rx success: got %d chars", length); |
579 | 527 | ||
580 | 528 | /* prepare struct r3964_block_header: */ | |
581 | /* received block; submit DLE: */ | 529 | pBlock = kmalloc(length + sizeof(struct r3964_block_header), |
582 | put_char(pInfo, DLE); | 530 | GFP_KERNEL); |
583 | flush(pInfo); | 531 | TRACE_M("on_receive_block - kmalloc %p", pBlock); |
584 | del_timer_sync(&pInfo->tmr); | 532 | |
585 | TRACE_PS(" rx success: got %d chars", length); | 533 | if (pBlock == NULL) |
586 | 534 | return; | |
587 | /* prepare struct r3964_block_header: */ | 535 | |
588 | pBlock = kmalloc(length+sizeof(struct r3964_block_header), GFP_KERNEL); | 536 | pBlock->length = length; |
589 | TRACE_M("on_receive_block - kmalloc %p",pBlock); | 537 | pBlock->data = ((unsigned char *)pBlock) + |
590 | 538 | sizeof(struct r3964_block_header); | |
591 | if(pBlock==NULL) | 539 | pBlock->locks = 0; |
592 | return; | 540 | pBlock->next = NULL; |
593 | 541 | pBlock->owner = NULL; | |
594 | pBlock->length = length; | 542 | |
595 | pBlock->data = ((unsigned char*)pBlock)+sizeof(struct r3964_block_header); | 543 | memcpy(pBlock->data, pInfo->rx_buf, length); |
596 | pBlock->locks = 0; | 544 | |
597 | pBlock->next = NULL; | 545 | /* queue block into rx_queue: */ |
598 | pBlock->owner = NULL; | 546 | add_rx_queue(pInfo, pBlock); |
599 | 547 | ||
600 | memcpy(pBlock->data, pInfo->rx_buf, length); | 548 | /* notify attached client processes: */ |
601 | 549 | for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { | |
602 | /* queue block into rx_queue: */ | 550 | if (pClient->sig_flags & R3964_SIG_DATA) { |
603 | add_rx_queue(pInfo, pBlock); | 551 | add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, |
604 | 552 | pBlock); | |
605 | /* notify attached client processes: */ | 553 | } |
606 | for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) | 554 | } |
607 | { | 555 | wake_up_interruptible(&pInfo->read_wait); |
608 | if(pClient->sig_flags & R3964_SIG_DATA) | ||
609 | { | ||
610 | add_msg(pClient, R3964_MSG_DATA, length, R3964_OK, pBlock); | ||
611 | } | ||
612 | } | ||
613 | wake_up_interruptible (&pInfo->read_wait); | ||
614 | |||
615 | pInfo->state = R3964_IDLE; | ||
616 | |||
617 | trigger_transmit(pInfo); | ||
618 | } | ||
619 | 556 | ||
557 | pInfo->state = R3964_IDLE; | ||
558 | |||
559 | trigger_transmit(pInfo); | ||
560 | } | ||
620 | 561 | ||
621 | static void receive_char(struct r3964_info *pInfo, const unsigned char c) | 562 | static void receive_char(struct r3964_info *pInfo, const unsigned char c) |
622 | { | 563 | { |
623 | switch(pInfo->state) | 564 | switch (pInfo->state) { |
624 | { | 565 | case R3964_TX_REQUEST: |
625 | case R3964_TX_REQUEST: | 566 | if (c == DLE) { |
626 | if(c==DLE) | 567 | TRACE_PS("TX_REQUEST - got DLE"); |
627 | { | 568 | |
628 | TRACE_PS("TX_REQUEST - got DLE"); | 569 | pInfo->state = R3964_TRANSMITTING; |
629 | 570 | pInfo->tx_position = 0; | |
630 | pInfo->state = R3964_TRANSMITTING; | 571 | |
631 | pInfo->tx_position = 0; | 572 | transmit_block(pInfo); |
632 | 573 | } else if (c == STX) { | |
633 | transmit_block(pInfo); | 574 | if (pInfo->nRetry == 0) { |
634 | } | 575 | TRACE_PE("TX_REQUEST - init conflict"); |
635 | else if(c==STX) | 576 | if (pInfo->priority == R3964_SLAVE) { |
636 | { | 577 | goto start_receiving; |
637 | if(pInfo->nRetry==0) | 578 | } |
638 | { | 579 | } else { |
639 | TRACE_PE("TX_REQUEST - init conflict"); | 580 | TRACE_PE("TX_REQUEST - secondary init " |
640 | if(pInfo->priority == R3964_SLAVE) | 581 | "conflict!? Switching to SLAVE mode " |
641 | { | 582 | "for next rx."); |
642 | goto start_receiving; | 583 | goto start_receiving; |
643 | } | 584 | } |
644 | } | 585 | } else { |
645 | else | 586 | TRACE_PE("TX_REQUEST - char != DLE: %x", c); |
646 | { | 587 | retry_transmit(pInfo); |
647 | TRACE_PE("TX_REQUEST - secondary init conflict!?" | 588 | } |
648 | " Switching to SLAVE mode for next rx."); | 589 | break; |
649 | goto start_receiving; | 590 | case R3964_TRANSMITTING: |
650 | } | 591 | if (c == NAK) { |
651 | } | 592 | TRACE_PE("TRANSMITTING - got NAK"); |
652 | else | 593 | retry_transmit(pInfo); |
653 | { | 594 | } else { |
654 | TRACE_PE("TX_REQUEST - char != DLE: %x", c); | 595 | TRACE_PE("TRANSMITTING - got invalid char"); |
655 | retry_transmit(pInfo); | 596 | |
656 | } | 597 | pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; |
657 | break; | 598 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); |
658 | case R3964_TRANSMITTING: | 599 | } |
659 | if(c==NAK) | 600 | break; |
660 | { | 601 | case R3964_WAIT_FOR_TX_ACK: |
661 | TRACE_PE("TRANSMITTING - got NAK"); | 602 | if (c == DLE) { |
662 | retry_transmit(pInfo); | 603 | TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); |
663 | } | 604 | remove_from_tx_queue(pInfo, R3964_OK); |
664 | else | 605 | |
665 | { | 606 | pInfo->state = R3964_IDLE; |
666 | TRACE_PE("TRANSMITTING - got invalid char"); | 607 | trigger_transmit(pInfo); |
667 | 608 | } else { | |
668 | pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY; | 609 | retry_transmit(pInfo); |
669 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 610 | } |
670 | } | 611 | break; |
671 | break; | 612 | case R3964_WAIT_FOR_RX_REPEAT: |
672 | case R3964_WAIT_FOR_TX_ACK: | 613 | /* FALLTROUGH */ |
673 | if(c==DLE) | 614 | case R3964_IDLE: |
674 | { | 615 | if (c == STX) { |
675 | TRACE_PS("WAIT_FOR_TX_ACK - got DLE"); | 616 | /* Prevent rx_queue from overflow: */ |
676 | remove_from_tx_queue(pInfo, R3964_OK); | 617 | if (pInfo->blocks_in_rx_queue >= |
677 | 618 | R3964_MAX_BLOCKS_IN_RX_QUEUE) { | |
678 | pInfo->state = R3964_IDLE; | 619 | TRACE_PE("IDLE - got STX but no space in " |
679 | trigger_transmit(pInfo); | 620 | "rx_queue!"); |
680 | } | 621 | pInfo->state = R3964_WAIT_FOR_RX_BUF; |
681 | else | 622 | mod_timer(&pInfo->tmr, |
682 | { | 623 | jiffies + R3964_TO_NO_BUF); |
683 | retry_transmit(pInfo); | 624 | break; |
684 | } | 625 | } |
685 | break; | ||
686 | case R3964_WAIT_FOR_RX_REPEAT: | ||
687 | /* FALLTROUGH */ | ||
688 | case R3964_IDLE: | ||
689 | if(c==STX) | ||
690 | { | ||
691 | /* Prevent rx_queue from overflow: */ | ||
692 | if(pInfo->blocks_in_rx_queue >= R3964_MAX_BLOCKS_IN_RX_QUEUE) | ||
693 | { | ||
694 | TRACE_PE("IDLE - got STX but no space in rx_queue!"); | ||
695 | pInfo->state=R3964_WAIT_FOR_RX_BUF; | ||
696 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_NO_BUF); | ||
697 | break; | ||
698 | } | ||
699 | start_receiving: | 626 | start_receiving: |
700 | /* Ok, start receiving: */ | 627 | /* Ok, start receiving: */ |
701 | TRACE_PS("IDLE - got STX"); | 628 | TRACE_PS("IDLE - got STX"); |
702 | pInfo->rx_position = 0; | 629 | pInfo->rx_position = 0; |
703 | pInfo->last_rx = 0; | 630 | pInfo->last_rx = 0; |
704 | pInfo->flags &= ~R3964_ERROR; | 631 | pInfo->flags &= ~R3964_ERROR; |
705 | pInfo->state=R3964_RECEIVING; | 632 | pInfo->state = R3964_RECEIVING; |
706 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 633 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); |
707 | pInfo->nRetry = 0; | 634 | pInfo->nRetry = 0; |
708 | put_char(pInfo, DLE); | 635 | put_char(pInfo, DLE); |
709 | flush(pInfo); | 636 | flush(pInfo); |
710 | pInfo->bcc = 0; | 637 | pInfo->bcc = 0; |
711 | } | 638 | } |
712 | break; | 639 | break; |
713 | case R3964_RECEIVING: | 640 | case R3964_RECEIVING: |
714 | if(pInfo->rx_position < RX_BUF_SIZE) | 641 | if (pInfo->rx_position < RX_BUF_SIZE) { |
715 | { | 642 | pInfo->bcc ^= c; |
716 | pInfo->bcc ^= c; | 643 | |
717 | 644 | if (c == DLE) { | |
718 | if(c==DLE) | 645 | if (pInfo->last_rx == DLE) { |
719 | { | 646 | pInfo->last_rx = 0; |
720 | if(pInfo->last_rx==DLE) | 647 | goto char_to_buf; |
721 | { | 648 | } |
722 | pInfo->last_rx = 0; | 649 | pInfo->last_rx = DLE; |
723 | goto char_to_buf; | 650 | break; |
724 | } | 651 | } else if ((c == ETX) && (pInfo->last_rx == DLE)) { |
725 | pInfo->last_rx = DLE; | 652 | if (pInfo->flags & R3964_BCC) { |
726 | break; | 653 | pInfo->state = R3964_WAIT_FOR_BCC; |
727 | } | 654 | mod_timer(&pInfo->tmr, |
728 | else if((c==ETX) && (pInfo->last_rx==DLE)) | 655 | jiffies + R3964_TO_ZVZ); |
729 | { | 656 | } else { |
730 | if(pInfo->flags & R3964_BCC) | 657 | on_receive_block(pInfo); |
731 | { | 658 | } |
732 | pInfo->state = R3964_WAIT_FOR_BCC; | 659 | } else { |
733 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 660 | pInfo->last_rx = c; |
734 | } | ||
735 | else | ||
736 | { | ||
737 | on_receive_block(pInfo); | ||
738 | } | ||
739 | } | ||
740 | else | ||
741 | { | ||
742 | pInfo->last_rx = c; | ||
743 | char_to_buf: | 661 | char_to_buf: |
744 | pInfo->rx_buf[pInfo->rx_position++] = c; | 662 | pInfo->rx_buf[pInfo->rx_position++] = c; |
745 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); | 663 | mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ); |
746 | } | 664 | } |
747 | } | 665 | } |
748 | /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ | 666 | /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ |
749 | break; | 667 | break; |
750 | case R3964_WAIT_FOR_BCC: | 668 | case R3964_WAIT_FOR_BCC: |
751 | pInfo->last_rx = c; | 669 | pInfo->last_rx = c; |
752 | on_receive_block(pInfo); | 670 | on_receive_block(pInfo); |
753 | break; | 671 | break; |
754 | } | 672 | } |
755 | } | 673 | } |
756 | 674 | ||
757 | static void receive_error(struct r3964_info *pInfo, const char flag) | 675 | static void receive_error(struct r3964_info *pInfo, const char flag) |
758 | { | 676 | { |
759 | switch (flag) | 677 | switch (flag) { |
760 | { | 678 | case TTY_NORMAL: |
761 | case TTY_NORMAL: | 679 | break; |
762 | break; | 680 | case TTY_BREAK: |
763 | case TTY_BREAK: | 681 | TRACE_PE("received break"); |
764 | TRACE_PE("received break") | 682 | pInfo->flags |= R3964_BREAK; |
765 | pInfo->flags |= R3964_BREAK; | 683 | break; |
766 | break; | 684 | case TTY_PARITY: |
767 | case TTY_PARITY: | 685 | TRACE_PE("parity error"); |
768 | TRACE_PE("parity error") | 686 | pInfo->flags |= R3964_PARITY; |
769 | pInfo->flags |= R3964_PARITY; | 687 | break; |
770 | break; | 688 | case TTY_FRAME: |
771 | case TTY_FRAME: | 689 | TRACE_PE("frame error"); |
772 | TRACE_PE("frame error") | 690 | pInfo->flags |= R3964_FRAME; |
773 | pInfo->flags |= R3964_FRAME; | 691 | break; |
774 | break; | 692 | case TTY_OVERRUN: |
775 | case TTY_OVERRUN: | 693 | TRACE_PE("frame overrun"); |
776 | TRACE_PE("frame overrun") | 694 | pInfo->flags |= R3964_OVERRUN; |
777 | pInfo->flags |= R3964_OVERRUN; | 695 | break; |
778 | break; | 696 | default: |
779 | default: | 697 | TRACE_PE("receive_error - unknown flag %d", flag); |
780 | TRACE_PE("receive_error - unknown flag %d", flag); | 698 | pInfo->flags |= R3964_UNKNOWN; |
781 | pInfo->flags |= R3964_UNKNOWN; | 699 | break; |
782 | break; | 700 | } |
783 | } | ||
784 | } | 701 | } |
785 | 702 | ||
786 | static void on_timeout(unsigned long priv) | 703 | static void on_timeout(unsigned long priv) |
787 | { | 704 | { |
788 | struct r3964_info *pInfo = (void *)priv; | 705 | struct r3964_info *pInfo = (void *)priv; |
789 | 706 | ||
790 | switch(pInfo->state) | 707 | switch (pInfo->state) { |
791 | { | 708 | case R3964_TX_REQUEST: |
792 | case R3964_TX_REQUEST: | 709 | TRACE_PE("TX_REQUEST - timeout"); |
793 | TRACE_PE("TX_REQUEST - timeout"); | 710 | retry_transmit(pInfo); |
794 | retry_transmit(pInfo); | 711 | break; |
795 | break; | 712 | case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: |
796 | case R3964_WAIT_ZVZ_BEFORE_TX_RETRY: | 713 | put_char(pInfo, NAK); |
797 | put_char(pInfo, NAK); | 714 | flush(pInfo); |
798 | flush(pInfo); | 715 | retry_transmit(pInfo); |
799 | retry_transmit(pInfo); | 716 | break; |
800 | break; | 717 | case R3964_WAIT_FOR_TX_ACK: |
801 | case R3964_WAIT_FOR_TX_ACK: | 718 | TRACE_PE("WAIT_FOR_TX_ACK - timeout"); |
802 | TRACE_PE("WAIT_FOR_TX_ACK - timeout"); | 719 | retry_transmit(pInfo); |
803 | retry_transmit(pInfo); | 720 | break; |
804 | break; | 721 | case R3964_WAIT_FOR_RX_BUF: |
805 | case R3964_WAIT_FOR_RX_BUF: | 722 | TRACE_PE("WAIT_FOR_RX_BUF - timeout"); |
806 | TRACE_PE("WAIT_FOR_RX_BUF - timeout"); | 723 | put_char(pInfo, NAK); |
807 | put_char(pInfo, NAK); | 724 | flush(pInfo); |
808 | flush(pInfo); | 725 | pInfo->state = R3964_IDLE; |
809 | pInfo->state=R3964_IDLE; | 726 | break; |
810 | break; | 727 | case R3964_RECEIVING: |
811 | case R3964_RECEIVING: | 728 | TRACE_PE("RECEIVING - timeout after %d chars", |
812 | TRACE_PE("RECEIVING - timeout after %d chars", | 729 | pInfo->rx_position); |
813 | pInfo->rx_position); | 730 | put_char(pInfo, NAK); |
814 | put_char(pInfo, NAK); | 731 | flush(pInfo); |
815 | flush(pInfo); | 732 | pInfo->state = R3964_IDLE; |
816 | pInfo->state=R3964_IDLE; | 733 | break; |
817 | break; | 734 | case R3964_WAIT_FOR_RX_REPEAT: |
818 | case R3964_WAIT_FOR_RX_REPEAT: | 735 | TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); |
819 | TRACE_PE("WAIT_FOR_RX_REPEAT - timeout"); | 736 | pInfo->state = R3964_IDLE; |
820 | pInfo->state=R3964_IDLE; | 737 | break; |
821 | break; | 738 | case R3964_WAIT_FOR_BCC: |
822 | case R3964_WAIT_FOR_BCC: | 739 | TRACE_PE("WAIT_FOR_BCC - timeout"); |
823 | TRACE_PE("WAIT_FOR_BCC - timeout"); | 740 | put_char(pInfo, NAK); |
824 | put_char(pInfo, NAK); | 741 | flush(pInfo); |
825 | flush(pInfo); | 742 | pInfo->state = R3964_IDLE; |
826 | pInfo->state=R3964_IDLE; | 743 | break; |
827 | break; | 744 | } |
828 | } | ||
829 | } | 745 | } |
830 | 746 | ||
831 | static struct r3964_client_info *findClient( | 747 | static struct r3964_client_info *findClient(struct r3964_info *pInfo, |
832 | struct r3964_info *pInfo, struct pid *pid) | 748 | struct pid *pid) |
833 | { | 749 | { |
834 | struct r3964_client_info *pClient; | 750 | struct r3964_client_info *pClient; |
835 | 751 | ||
836 | for(pClient=pInfo->firstClient; pClient; pClient=pClient->next) | 752 | for (pClient = pInfo->firstClient; pClient; pClient = pClient->next) { |
837 | { | 753 | if (pClient->pid == pid) { |
838 | if(pClient->pid == pid) | 754 | return pClient; |
839 | { | 755 | } |
840 | return pClient; | 756 | } |
841 | } | 757 | return NULL; |
842 | } | ||
843 | return NULL; | ||
844 | } | 758 | } |
845 | 759 | ||
846 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) | 760 | static int enable_signals(struct r3964_info *pInfo, struct pid *pid, int arg) |
847 | { | 761 | { |
848 | struct r3964_client_info *pClient; | 762 | struct r3964_client_info *pClient; |
849 | struct r3964_client_info **ppClient; | 763 | struct r3964_client_info **ppClient; |
850 | struct r3964_message *pMsg; | 764 | struct r3964_message *pMsg; |
851 | 765 | ||
852 | if((arg & R3964_SIG_ALL)==0) | 766 | if ((arg & R3964_SIG_ALL) == 0) { |
853 | { | 767 | /* Remove client from client list */ |
854 | /* Remove client from client list */ | 768 | for (ppClient = &pInfo->firstClient; *ppClient; |
855 | for(ppClient=&pInfo->firstClient; *ppClient; ppClient=&(*ppClient)->next) | 769 | ppClient = &(*ppClient)->next) { |
856 | { | 770 | pClient = *ppClient; |
857 | pClient = *ppClient; | 771 | |
858 | 772 | if (pClient->pid == pid) { | |
859 | if(pClient->pid == pid) | 773 | TRACE_PS("removing client %d from client list", |
860 | { | 774 | pid_nr(pid)); |
861 | TRACE_PS("removing client %d from client list", pid_nr(pid)); | 775 | *ppClient = pClient->next; |
862 | *ppClient = pClient->next; | 776 | while (pClient->msg_count) { |
863 | while(pClient->msg_count) | 777 | pMsg = remove_msg(pInfo, pClient); |
864 | { | 778 | if (pMsg) { |
865 | pMsg=remove_msg(pInfo, pClient); | 779 | kfree(pMsg); |
866 | if(pMsg) | 780 | TRACE_M("enable_signals - msg " |
867 | { | 781 | "kfree %p", pMsg); |
868 | kfree(pMsg); | 782 | } |
869 | TRACE_M("enable_signals - msg kfree %p",pMsg); | 783 | } |
870 | } | 784 | put_pid(pClient->pid); |
871 | } | 785 | kfree(pClient); |
872 | put_pid(pClient->pid); | 786 | TRACE_M("enable_signals - kfree %p", pClient); |
873 | kfree(pClient); | 787 | return 0; |
874 | TRACE_M("enable_signals - kfree %p",pClient); | 788 | } |
875 | return 0; | 789 | } |
876 | } | 790 | return -EINVAL; |
877 | } | 791 | } else { |
878 | return -EINVAL; | 792 | pClient = findClient(pInfo, pid); |
879 | } | 793 | if (pClient) { |
880 | else | 794 | /* update signal options */ |
881 | { | 795 | pClient->sig_flags = arg; |
882 | pClient=findClient(pInfo, pid); | 796 | } else { |
883 | if(pClient) | 797 | /* add client to client list */ |
884 | { | 798 | pClient = kmalloc(sizeof(struct r3964_client_info), |
885 | /* update signal options */ | 799 | GFP_KERNEL); |
886 | pClient->sig_flags=arg; | 800 | TRACE_M("enable_signals - kmalloc %p", pClient); |
887 | } | 801 | if (pClient == NULL) |
888 | else | 802 | return -ENOMEM; |
889 | { | 803 | |
890 | /* add client to client list */ | 804 | TRACE_PS("add client %d to client list", pid_nr(pid)); |
891 | pClient=kmalloc(sizeof(struct r3964_client_info), GFP_KERNEL); | 805 | spin_lock_init(&pClient->lock); |
892 | TRACE_M("enable_signals - kmalloc %p",pClient); | 806 | pClient->sig_flags = arg; |
893 | if(pClient==NULL) | 807 | pClient->pid = get_pid(pid); |
894 | return -ENOMEM; | 808 | pClient->next = pInfo->firstClient; |
895 | 809 | pClient->first_msg = NULL; | |
896 | TRACE_PS("add client %d to client list", pid_nr(pid)); | 810 | pClient->last_msg = NULL; |
897 | spin_lock_init(&pClient->lock); | 811 | pClient->next_block_to_read = NULL; |
898 | pClient->sig_flags=arg; | 812 | pClient->msg_count = 0; |
899 | pClient->pid = get_pid(pid); | 813 | pInfo->firstClient = pClient; |
900 | pClient->next=pInfo->firstClient; | 814 | } |
901 | pClient->first_msg = NULL; | 815 | } |
902 | pClient->last_msg = NULL; | 816 | |
903 | pClient->next_block_to_read = NULL; | 817 | return 0; |
904 | pClient->msg_count = 0; | ||
905 | pInfo->firstClient=pClient; | ||
906 | } | ||
907 | } | ||
908 | |||
909 | return 0; | ||
910 | } | 818 | } |
911 | 819 | ||
912 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, unsigned char __user *buf) | 820 | static int read_telegram(struct r3964_info *pInfo, struct pid *pid, |
821 | unsigned char __user * buf) | ||
913 | { | 822 | { |
914 | struct r3964_client_info *pClient; | 823 | struct r3964_client_info *pClient; |
915 | struct r3964_block_header *block; | 824 | struct r3964_block_header *block; |
916 | 825 | ||
917 | if(!buf) | 826 | if (!buf) { |
918 | { | 827 | return -EINVAL; |
919 | return -EINVAL; | 828 | } |
920 | } | 829 | |
921 | 830 | pClient = findClient(pInfo, pid); | |
922 | pClient=findClient(pInfo,pid); | 831 | if (pClient == NULL) { |
923 | if(pClient==NULL) | 832 | return -EINVAL; |
924 | { | 833 | } |
925 | return -EINVAL; | 834 | |
926 | } | 835 | block = pClient->next_block_to_read; |
927 | 836 | if (!block) { | |
928 | block=pClient->next_block_to_read; | 837 | return 0; |
929 | if(!block) | 838 | } else { |
930 | { | 839 | if (copy_to_user(buf, block->data, block->length)) |
931 | return 0; | 840 | return -EFAULT; |
932 | } | 841 | |
933 | else | 842 | remove_client_block(pInfo, pClient); |
934 | { | 843 | return block->length; |
935 | if (copy_to_user (buf, block->data, block->length)) | 844 | } |
936 | return -EFAULT; | 845 | |
937 | 846 | return -EINVAL; | |
938 | remove_client_block(pInfo, pClient); | ||
939 | return block->length; | ||
940 | } | ||
941 | |||
942 | return -EINVAL; | ||
943 | } | 847 | } |
944 | 848 | ||
945 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, | 849 | static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg, |
946 | int error_code, struct r3964_block_header *pBlock) | 850 | int error_code, struct r3964_block_header *pBlock) |
947 | { | 851 | { |
948 | struct r3964_message *pMsg; | 852 | struct r3964_message *pMsg; |
949 | unsigned long flags; | 853 | unsigned long flags; |
950 | 854 | ||
951 | if(pClient->msg_count<R3964_MAX_MSG_COUNT-1) | 855 | if (pClient->msg_count < R3964_MAX_MSG_COUNT - 1) { |
952 | { | ||
953 | queue_the_message: | 856 | queue_the_message: |
954 | 857 | ||
955 | pMsg = kmalloc(sizeof(struct r3964_message), | 858 | pMsg = kmalloc(sizeof(struct r3964_message), |
956 | error_code?GFP_ATOMIC:GFP_KERNEL); | 859 | error_code ? GFP_ATOMIC : GFP_KERNEL); |
957 | TRACE_M("add_msg - kmalloc %p",pMsg); | 860 | TRACE_M("add_msg - kmalloc %p", pMsg); |
958 | if(pMsg==NULL) { | 861 | if (pMsg == NULL) { |
959 | return; | 862 | return; |
960 | } | 863 | } |
961 | 864 | ||
962 | spin_lock_irqsave(&pClient->lock, flags); | 865 | spin_lock_irqsave(&pClient->lock, flags); |
963 | 866 | ||
964 | pMsg->msg_id = msg_id; | 867 | pMsg->msg_id = msg_id; |
965 | pMsg->arg = arg; | 868 | pMsg->arg = arg; |
966 | pMsg->error_code = error_code; | 869 | pMsg->error_code = error_code; |
967 | pMsg->block = pBlock; | 870 | pMsg->block = pBlock; |
968 | pMsg->next = NULL; | 871 | pMsg->next = NULL; |
969 | 872 | ||
970 | if(pClient->last_msg==NULL) | 873 | if (pClient->last_msg == NULL) { |
971 | { | 874 | pClient->first_msg = pClient->last_msg = pMsg; |
972 | pClient->first_msg=pClient->last_msg=pMsg; | 875 | } else { |
973 | } | 876 | pClient->last_msg->next = pMsg; |
974 | else | 877 | pClient->last_msg = pMsg; |
975 | { | 878 | } |
976 | pClient->last_msg->next = pMsg; | 879 | |
977 | pClient->last_msg=pMsg; | 880 | pClient->msg_count++; |
978 | } | 881 | |
979 | 882 | if (pBlock != NULL) { | |
980 | pClient->msg_count++; | 883 | pBlock->locks++; |
981 | 884 | } | |
982 | if(pBlock!=NULL) | 885 | spin_unlock_irqrestore(&pClient->lock, flags); |
983 | { | 886 | } else { |
984 | pBlock->locks++; | 887 | if ((pClient->last_msg->msg_id == R3964_MSG_ACK) |
985 | } | 888 | && (pClient->last_msg->error_code == R3964_OVERFLOW)) { |
986 | spin_unlock_irqrestore(&pClient->lock, flags); | 889 | pClient->last_msg->arg++; |
987 | } | 890 | TRACE_PE("add_msg - inc prev OVERFLOW-msg"); |
988 | else | 891 | } else { |
989 | { | 892 | msg_id = R3964_MSG_ACK; |
990 | if((pClient->last_msg->msg_id == R3964_MSG_ACK) | 893 | arg = 0; |
991 | && (pClient->last_msg->error_code==R3964_OVERFLOW)) | 894 | error_code = R3964_OVERFLOW; |
992 | { | 895 | pBlock = NULL; |
993 | pClient->last_msg->arg++; | 896 | TRACE_PE("add_msg - queue OVERFLOW-msg"); |
994 | TRACE_PE("add_msg - inc prev OVERFLOW-msg"); | 897 | goto queue_the_message; |
995 | } | 898 | } |
996 | else | 899 | } |
997 | { | 900 | /* Send SIGIO signal to client process: */ |
998 | msg_id = R3964_MSG_ACK; | 901 | if (pClient->sig_flags & R3964_USE_SIGIO) { |
999 | arg = 0; | 902 | kill_pid(pClient->pid, SIGIO, 1); |
1000 | error_code = R3964_OVERFLOW; | 903 | } |
1001 | pBlock = NULL; | ||
1002 | TRACE_PE("add_msg - queue OVERFLOW-msg"); | ||
1003 | goto queue_the_message; | ||
1004 | } | ||
1005 | } | ||
1006 | /* Send SIGIO signal to client process: */ | ||
1007 | if(pClient->sig_flags & R3964_USE_SIGIO) | ||
1008 | { | ||
1009 | kill_pid(pClient->pid, SIGIO, 1); | ||
1010 | } | ||
1011 | } | 904 | } |
1012 | 905 | ||
1013 | static struct r3964_message *remove_msg(struct r3964_info *pInfo, | 906 | static struct r3964_message *remove_msg(struct r3964_info *pInfo, |
1014 | struct r3964_client_info *pClient) | 907 | struct r3964_client_info *pClient) |
1015 | { | 908 | { |
1016 | struct r3964_message *pMsg=NULL; | 909 | struct r3964_message *pMsg = NULL; |
1017 | unsigned long flags; | 910 | unsigned long flags; |
1018 | 911 | ||
1019 | if(pClient->first_msg) | 912 | if (pClient->first_msg) { |
1020 | { | 913 | spin_lock_irqsave(&pClient->lock, flags); |
1021 | spin_lock_irqsave(&pClient->lock, flags); | 914 | |
1022 | 915 | pMsg = pClient->first_msg; | |
1023 | pMsg = pClient->first_msg; | 916 | pClient->first_msg = pMsg->next; |
1024 | pClient->first_msg = pMsg->next; | 917 | if (pClient->first_msg == NULL) { |
1025 | if(pClient->first_msg==NULL) | 918 | pClient->last_msg = NULL; |
1026 | { | 919 | } |
1027 | pClient->last_msg = NULL; | 920 | |
1028 | } | 921 | pClient->msg_count--; |
1029 | 922 | if (pMsg->block) { | |
1030 | pClient->msg_count--; | 923 | remove_client_block(pInfo, pClient); |
1031 | if(pMsg->block) | 924 | pClient->next_block_to_read = pMsg->block; |
1032 | { | 925 | } |
1033 | remove_client_block(pInfo, pClient); | 926 | spin_unlock_irqrestore(&pClient->lock, flags); |
1034 | pClient->next_block_to_read = pMsg->block; | 927 | } |
1035 | } | 928 | return pMsg; |
1036 | spin_unlock_irqrestore(&pClient->lock, flags); | ||
1037 | } | ||
1038 | return pMsg; | ||
1039 | } | 929 | } |
1040 | 930 | ||
1041 | static void remove_client_block(struct r3964_info *pInfo, | 931 | static void remove_client_block(struct r3964_info *pInfo, |
1042 | struct r3964_client_info *pClient) | 932 | struct r3964_client_info *pClient) |
1043 | { | 933 | { |
1044 | struct r3964_block_header *block; | 934 | struct r3964_block_header *block; |
1045 | 935 | ||
1046 | TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); | 936 | TRACE_PS("remove_client_block PID %d", pid_nr(pClient->pid)); |
1047 | |||
1048 | block=pClient->next_block_to_read; | ||
1049 | if(block) | ||
1050 | { | ||
1051 | block->locks--; | ||
1052 | if(block->locks==0) | ||
1053 | { | ||
1054 | remove_from_rx_queue(pInfo, block); | ||
1055 | } | ||
1056 | } | ||
1057 | pClient->next_block_to_read = NULL; | ||
1058 | } | ||
1059 | 937 | ||
938 | block = pClient->next_block_to_read; | ||
939 | if (block) { | ||
940 | block->locks--; | ||
941 | if (block->locks == 0) { | ||
942 | remove_from_rx_queue(pInfo, block); | ||
943 | } | ||
944 | } | ||
945 | pClient->next_block_to_read = NULL; | ||
946 | } | ||
1060 | 947 | ||
1061 | /************************************************************* | 948 | /************************************************************* |
1062 | * Line discipline routines | 949 | * Line discipline routines |
@@ -1064,342 +951,320 @@ static void remove_client_block(struct r3964_info *pInfo, | |||
1064 | 951 | ||
1065 | static int r3964_open(struct tty_struct *tty) | 952 | static int r3964_open(struct tty_struct *tty) |
1066 | { | 953 | { |
1067 | struct r3964_info *pInfo; | 954 | struct r3964_info *pInfo; |
1068 | 955 | ||
1069 | TRACE_L("open"); | 956 | TRACE_L("open"); |
1070 | TRACE_L("tty=%p, PID=%d, disc_data=%p", | 957 | TRACE_L("tty=%p, PID=%d, disc_data=%p", |
1071 | tty, current->pid, tty->disc_data); | 958 | tty, current->pid, tty->disc_data); |
1072 | 959 | ||
1073 | pInfo=kmalloc(sizeof(struct r3964_info), GFP_KERNEL); | 960 | pInfo = kmalloc(sizeof(struct r3964_info), GFP_KERNEL); |
1074 | TRACE_M("r3964_open - info kmalloc %p",pInfo); | 961 | TRACE_M("r3964_open - info kmalloc %p", pInfo); |
1075 | 962 | ||
1076 | if(!pInfo) | 963 | if (!pInfo) { |
1077 | { | 964 | printk(KERN_ERR "r3964: failed to alloc info structure\n"); |
1078 | printk(KERN_ERR "r3964: failed to alloc info structure\n"); | 965 | return -ENOMEM; |
1079 | return -ENOMEM; | 966 | } |
1080 | } | 967 | |
1081 | 968 | pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); | |
1082 | pInfo->rx_buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL); | 969 | TRACE_M("r3964_open - rx_buf kmalloc %p", pInfo->rx_buf); |
1083 | TRACE_M("r3964_open - rx_buf kmalloc %p",pInfo->rx_buf); | 970 | |
1084 | 971 | if (!pInfo->rx_buf) { | |
1085 | if(!pInfo->rx_buf) | 972 | printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); |
1086 | { | 973 | kfree(pInfo); |
1087 | printk(KERN_ERR "r3964: failed to alloc receive buffer\n"); | 974 | TRACE_M("r3964_open - info kfree %p", pInfo); |
1088 | kfree(pInfo); | 975 | return -ENOMEM; |
1089 | TRACE_M("r3964_open - info kfree %p",pInfo); | 976 | } |
1090 | return -ENOMEM; | 977 | |
1091 | } | 978 | pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); |
1092 | 979 | TRACE_M("r3964_open - tx_buf kmalloc %p", pInfo->tx_buf); | |
1093 | pInfo->tx_buf = kmalloc(TX_BUF_SIZE, GFP_KERNEL); | 980 | |
1094 | TRACE_M("r3964_open - tx_buf kmalloc %p",pInfo->tx_buf); | 981 | if (!pInfo->tx_buf) { |
1095 | 982 | printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); | |
1096 | if(!pInfo->tx_buf) | 983 | kfree(pInfo->rx_buf); |
1097 | { | 984 | TRACE_M("r3964_open - rx_buf kfree %p", pInfo->rx_buf); |
1098 | printk(KERN_ERR "r3964: failed to alloc transmit buffer\n"); | 985 | kfree(pInfo); |
1099 | kfree(pInfo->rx_buf); | 986 | TRACE_M("r3964_open - info kfree %p", pInfo); |
1100 | TRACE_M("r3964_open - rx_buf kfree %p",pInfo->rx_buf); | 987 | return -ENOMEM; |
1101 | kfree(pInfo); | 988 | } |
1102 | TRACE_M("r3964_open - info kfree %p",pInfo); | 989 | |
1103 | return -ENOMEM; | 990 | spin_lock_init(&pInfo->lock); |
1104 | } | 991 | pInfo->tty = tty; |
1105 | 992 | init_waitqueue_head(&pInfo->read_wait); | |
1106 | spin_lock_init(&pInfo->lock); | 993 | pInfo->priority = R3964_MASTER; |
1107 | pInfo->tty = tty; | 994 | pInfo->rx_first = pInfo->rx_last = NULL; |
1108 | init_waitqueue_head (&pInfo->read_wait); | 995 | pInfo->tx_first = pInfo->tx_last = NULL; |
1109 | pInfo->priority = R3964_MASTER; | 996 | pInfo->rx_position = 0; |
1110 | pInfo->rx_first = pInfo->rx_last = NULL; | 997 | pInfo->tx_position = 0; |
1111 | pInfo->tx_first = pInfo->tx_last = NULL; | 998 | pInfo->last_rx = 0; |
1112 | pInfo->rx_position = 0; | 999 | pInfo->blocks_in_rx_queue = 0; |
1113 | pInfo->tx_position = 0; | 1000 | pInfo->firstClient = NULL; |
1114 | pInfo->last_rx = 0; | 1001 | pInfo->state = R3964_IDLE; |
1115 | pInfo->blocks_in_rx_queue = 0; | 1002 | pInfo->flags = R3964_DEBUG; |
1116 | pInfo->firstClient=NULL; | 1003 | pInfo->nRetry = 0; |
1117 | pInfo->state=R3964_IDLE; | 1004 | |
1118 | pInfo->flags = R3964_DEBUG; | 1005 | tty->disc_data = pInfo; |
1119 | pInfo->nRetry = 0; | 1006 | tty->receive_room = 65536; |
1120 | 1007 | ||
1121 | tty->disc_data = pInfo; | 1008 | init_timer(&pInfo->tmr); |
1122 | tty->receive_room = 65536; | 1009 | pInfo->tmr.data = (unsigned long)pInfo; |
1123 | 1010 | pInfo->tmr.function = on_timeout; | |
1124 | init_timer(&pInfo->tmr); | 1011 | |
1125 | pInfo->tmr.data = (unsigned long)pInfo; | 1012 | return 0; |
1126 | pInfo->tmr.function = on_timeout; | ||
1127 | |||
1128 | return 0; | ||
1129 | } | 1013 | } |
1130 | 1014 | ||
1131 | static void r3964_close(struct tty_struct *tty) | 1015 | static void r3964_close(struct tty_struct *tty) |
1132 | { | 1016 | { |
1133 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1017 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1134 | struct r3964_client_info *pClient, *pNext; | 1018 | struct r3964_client_info *pClient, *pNext; |
1135 | struct r3964_message *pMsg; | 1019 | struct r3964_message *pMsg; |
1136 | struct r3964_block_header *pHeader, *pNextHeader; | 1020 | struct r3964_block_header *pHeader, *pNextHeader; |
1137 | unsigned long flags; | 1021 | unsigned long flags; |
1138 | 1022 | ||
1139 | TRACE_L("close"); | 1023 | TRACE_L("close"); |
1140 | 1024 | ||
1141 | /* | 1025 | /* |
1142 | * Make sure that our task queue isn't activated. If it | 1026 | * Make sure that our task queue isn't activated. If it |
1143 | * is, take it out of the linked list. | 1027 | * is, take it out of the linked list. |
1144 | */ | 1028 | */ |
1145 | del_timer_sync(&pInfo->tmr); | 1029 | del_timer_sync(&pInfo->tmr); |
1146 | 1030 | ||
1147 | /* Remove client-structs and message queues: */ | 1031 | /* Remove client-structs and message queues: */ |
1148 | pClient=pInfo->firstClient; | 1032 | pClient = pInfo->firstClient; |
1149 | while(pClient) | 1033 | while (pClient) { |
1150 | { | 1034 | pNext = pClient->next; |
1151 | pNext=pClient->next; | 1035 | while (pClient->msg_count) { |
1152 | while(pClient->msg_count) | 1036 | pMsg = remove_msg(pInfo, pClient); |
1153 | { | 1037 | if (pMsg) { |
1154 | pMsg=remove_msg(pInfo, pClient); | 1038 | kfree(pMsg); |
1155 | if(pMsg) | 1039 | TRACE_M("r3964_close - msg kfree %p", pMsg); |
1156 | { | 1040 | } |
1157 | kfree(pMsg); | 1041 | } |
1158 | TRACE_M("r3964_close - msg kfree %p",pMsg); | 1042 | put_pid(pClient->pid); |
1159 | } | 1043 | kfree(pClient); |
1160 | } | 1044 | TRACE_M("r3964_close - client kfree %p", pClient); |
1161 | put_pid(pClient->pid); | 1045 | pClient = pNext; |
1162 | kfree(pClient); | 1046 | } |
1163 | TRACE_M("r3964_close - client kfree %p",pClient); | 1047 | /* Remove jobs from tx_queue: */ |
1164 | pClient=pNext; | 1048 | spin_lock_irqsave(&pInfo->lock, flags); |
1165 | } | 1049 | pHeader = pInfo->tx_first; |
1166 | /* Remove jobs from tx_queue: */ | 1050 | pInfo->tx_first = pInfo->tx_last = NULL; |
1167 | spin_lock_irqsave(&pInfo->lock, flags); | ||
1168 | pHeader=pInfo->tx_first; | ||
1169 | pInfo->tx_first=pInfo->tx_last=NULL; | ||
1170 | spin_unlock_irqrestore(&pInfo->lock, flags); | 1051 | spin_unlock_irqrestore(&pInfo->lock, flags); |
1171 | 1052 | ||
1172 | while(pHeader) | 1053 | while (pHeader) { |
1173 | { | 1054 | pNextHeader = pHeader->next; |
1174 | pNextHeader=pHeader->next; | 1055 | kfree(pHeader); |
1175 | kfree(pHeader); | 1056 | pHeader = pNextHeader; |
1176 | pHeader=pNextHeader; | ||
1177 | } | 1057 | } |
1178 | 1058 | ||
1179 | /* Free buffers: */ | 1059 | /* Free buffers: */ |
1180 | wake_up_interruptible(&pInfo->read_wait); | 1060 | wake_up_interruptible(&pInfo->read_wait); |
1181 | kfree(pInfo->rx_buf); | 1061 | kfree(pInfo->rx_buf); |
1182 | TRACE_M("r3964_close - rx_buf kfree %p",pInfo->rx_buf); | 1062 | TRACE_M("r3964_close - rx_buf kfree %p", pInfo->rx_buf); |
1183 | kfree(pInfo->tx_buf); | 1063 | kfree(pInfo->tx_buf); |
1184 | TRACE_M("r3964_close - tx_buf kfree %p",pInfo->tx_buf); | 1064 | TRACE_M("r3964_close - tx_buf kfree %p", pInfo->tx_buf); |
1185 | kfree(pInfo); | 1065 | kfree(pInfo); |
1186 | TRACE_M("r3964_close - info kfree %p",pInfo); | 1066 | TRACE_M("r3964_close - info kfree %p", pInfo); |
1187 | } | 1067 | } |
1188 | 1068 | ||
1189 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, | 1069 | static ssize_t r3964_read(struct tty_struct *tty, struct file *file, |
1190 | unsigned char __user *buf, size_t nr) | 1070 | unsigned char __user * buf, size_t nr) |
1191 | { | 1071 | { |
1192 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1072 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1193 | struct r3964_client_info *pClient; | 1073 | struct r3964_client_info *pClient; |
1194 | struct r3964_message *pMsg; | 1074 | struct r3964_message *pMsg; |
1195 | struct r3964_client_message theMsg; | 1075 | struct r3964_client_message theMsg; |
1196 | DECLARE_WAITQUEUE (wait, current); | 1076 | DECLARE_WAITQUEUE(wait, current); |
1197 | 1077 | ||
1198 | int count; | 1078 | int count; |
1199 | 1079 | ||
1200 | TRACE_L("read()"); | 1080 | TRACE_L("read()"); |
1201 | 1081 | ||
1202 | pClient=findClient(pInfo, task_pid(current)); | 1082 | pClient = findClient(pInfo, task_pid(current)); |
1203 | if(pClient) | 1083 | if (pClient) { |
1204 | { | 1084 | pMsg = remove_msg(pInfo, pClient); |
1205 | pMsg = remove_msg(pInfo, pClient); | 1085 | if (pMsg == NULL) { |
1206 | if(pMsg==NULL) | 1086 | /* no messages available. */ |
1207 | { | 1087 | if (file->f_flags & O_NONBLOCK) { |
1208 | /* no messages available. */ | 1088 | return -EAGAIN; |
1209 | if (file->f_flags & O_NONBLOCK) | 1089 | } |
1210 | { | 1090 | /* block until there is a message: */ |
1211 | return -EAGAIN; | 1091 | add_wait_queue(&pInfo->read_wait, &wait); |
1212 | } | ||
1213 | /* block until there is a message: */ | ||
1214 | add_wait_queue(&pInfo->read_wait, &wait); | ||
1215 | repeat: | 1092 | repeat: |
1216 | current->state = TASK_INTERRUPTIBLE; | 1093 | current->state = TASK_INTERRUPTIBLE; |
1217 | pMsg = remove_msg(pInfo, pClient); | 1094 | pMsg = remove_msg(pInfo, pClient); |
1218 | if (!pMsg && !signal_pending(current)) | 1095 | if (!pMsg && !signal_pending(current)) { |
1219 | { | 1096 | schedule(); |
1220 | schedule(); | 1097 | goto repeat; |
1221 | goto repeat; | 1098 | } |
1222 | } | 1099 | current->state = TASK_RUNNING; |
1223 | current->state = TASK_RUNNING; | 1100 | remove_wait_queue(&pInfo->read_wait, &wait); |
1224 | remove_wait_queue(&pInfo->read_wait, &wait); | 1101 | } |
1225 | } | 1102 | |
1226 | 1103 | /* If we still haven't got a message, we must have been signalled */ | |
1227 | /* If we still haven't got a message, we must have been signalled */ | 1104 | |
1228 | 1105 | if (!pMsg) | |
1229 | if (!pMsg) return -EINTR; | 1106 | return -EINTR; |
1230 | 1107 | ||
1231 | /* deliver msg to client process: */ | 1108 | /* deliver msg to client process: */ |
1232 | theMsg.msg_id = pMsg->msg_id; | 1109 | theMsg.msg_id = pMsg->msg_id; |
1233 | theMsg.arg = pMsg->arg; | 1110 | theMsg.arg = pMsg->arg; |
1234 | theMsg.error_code = pMsg->error_code; | 1111 | theMsg.error_code = pMsg->error_code; |
1235 | count = sizeof(struct r3964_client_message); | 1112 | count = sizeof(struct r3964_client_message); |
1236 | 1113 | ||
1237 | kfree(pMsg); | 1114 | kfree(pMsg); |
1238 | TRACE_M("r3964_read - msg kfree %p",pMsg); | 1115 | TRACE_M("r3964_read - msg kfree %p", pMsg); |
1239 | 1116 | ||
1240 | if (copy_to_user(buf,&theMsg, count)) | 1117 | if (copy_to_user(buf, &theMsg, count)) |
1241 | return -EFAULT; | 1118 | return -EFAULT; |
1242 | 1119 | ||
1243 | TRACE_PS("read - return %d", count); | 1120 | TRACE_PS("read - return %d", count); |
1244 | return count; | 1121 | return count; |
1245 | } | 1122 | } |
1246 | return -EPERM; | 1123 | return -EPERM; |
1247 | } | 1124 | } |
1248 | 1125 | ||
1249 | static ssize_t r3964_write(struct tty_struct * tty, struct file * file, | 1126 | static ssize_t r3964_write(struct tty_struct *tty, struct file *file, |
1250 | const unsigned char *data, size_t count) | 1127 | const unsigned char *data, size_t count) |
1251 | { | 1128 | { |
1252 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1129 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1253 | struct r3964_block_header *pHeader; | 1130 | struct r3964_block_header *pHeader; |
1254 | struct r3964_client_info *pClient; | 1131 | struct r3964_client_info *pClient; |
1255 | unsigned char *new_data; | 1132 | unsigned char *new_data; |
1256 | 1133 | ||
1257 | TRACE_L("write request, %d characters", count); | 1134 | TRACE_L("write request, %d characters", count); |
1258 | /* | 1135 | /* |
1259 | * Verify the pointers | 1136 | * Verify the pointers |
1260 | */ | 1137 | */ |
1261 | 1138 | ||
1262 | if(!pInfo) | 1139 | if (!pInfo) |
1263 | return -EIO; | 1140 | return -EIO; |
1264 | 1141 | ||
1265 | /* | 1142 | /* |
1266 | * Ensure that the caller does not wish to send too much. | 1143 | * Ensure that the caller does not wish to send too much. |
1267 | */ | 1144 | */ |
1268 | if (count > R3964_MTU) | 1145 | if (count > R3964_MTU) { |
1269 | { | 1146 | if (pInfo->flags & R3964_DEBUG) { |
1270 | if (pInfo->flags & R3964_DEBUG) | 1147 | TRACE_L(KERN_WARNING "r3964_write: truncating user " |
1271 | { | 1148 | "packet from %u to mtu %d", count, R3964_MTU); |
1272 | TRACE_L (KERN_WARNING | 1149 | } |
1273 | "r3964_write: truncating user packet " | 1150 | count = R3964_MTU; |
1274 | "from %u to mtu %d", count, R3964_MTU); | 1151 | } |
1275 | } | ||
1276 | count = R3964_MTU; | ||
1277 | } | ||
1278 | /* | 1152 | /* |
1279 | * Allocate a buffer for the data and copy it from the buffer with header prepended | 1153 | * Allocate a buffer for the data and copy it from the buffer with header prepended |
1280 | */ | 1154 | */ |
1281 | new_data = kmalloc (count+sizeof(struct r3964_block_header), GFP_KERNEL); | 1155 | new_data = kmalloc(count + sizeof(struct r3964_block_header), |
1282 | TRACE_M("r3964_write - kmalloc %p",new_data); | 1156 | GFP_KERNEL); |
1283 | if (new_data == NULL) { | 1157 | TRACE_M("r3964_write - kmalloc %p", new_data); |
1284 | if (pInfo->flags & R3964_DEBUG) | 1158 | if (new_data == NULL) { |
1285 | { | 1159 | if (pInfo->flags & R3964_DEBUG) { |
1286 | printk (KERN_ERR | 1160 | printk(KERN_ERR "r3964_write: no memory\n"); |
1287 | "r3964_write: no memory\n"); | 1161 | } |
1288 | } | 1162 | return -ENOSPC; |
1289 | return -ENOSPC; | 1163 | } |
1290 | } | 1164 | |
1291 | 1165 | pHeader = (struct r3964_block_header *)new_data; | |
1292 | pHeader = (struct r3964_block_header *)new_data; | 1166 | pHeader->data = new_data + sizeof(struct r3964_block_header); |
1293 | pHeader->data = new_data + sizeof(struct r3964_block_header); | 1167 | pHeader->length = count; |
1294 | pHeader->length = count; | 1168 | pHeader->locks = 0; |
1295 | pHeader->locks = 0; | 1169 | pHeader->owner = NULL; |
1296 | pHeader->owner = NULL; | 1170 | |
1297 | 1171 | pClient = findClient(pInfo, task_pid(current)); | |
1298 | pClient=findClient(pInfo, task_pid(current)); | 1172 | if (pClient) { |
1299 | if(pClient) | 1173 | pHeader->owner = pClient; |
1300 | { | 1174 | } |
1301 | pHeader->owner = pClient; | 1175 | |
1302 | } | 1176 | memcpy(pHeader->data, data, count); /* We already verified this */ |
1303 | 1177 | ||
1304 | memcpy(pHeader->data, data, count); /* We already verified this */ | 1178 | if (pInfo->flags & R3964_DEBUG) { |
1305 | 1179 | dump_block(pHeader->data, count); | |
1306 | if(pInfo->flags & R3964_DEBUG) | 1180 | } |
1307 | { | ||
1308 | dump_block(pHeader->data, count); | ||
1309 | } | ||
1310 | 1181 | ||
1311 | /* | 1182 | /* |
1312 | * Add buffer to transmit-queue: | 1183 | * Add buffer to transmit-queue: |
1313 | */ | 1184 | */ |
1314 | add_tx_queue(pInfo, pHeader); | 1185 | add_tx_queue(pInfo, pHeader); |
1315 | trigger_transmit(pInfo); | 1186 | trigger_transmit(pInfo); |
1316 | 1187 | ||
1317 | return 0; | 1188 | return 0; |
1318 | } | 1189 | } |
1319 | 1190 | ||
1320 | static int r3964_ioctl(struct tty_struct * tty, struct file * file, | 1191 | static int r3964_ioctl(struct tty_struct *tty, struct file *file, |
1321 | unsigned int cmd, unsigned long arg) | 1192 | unsigned int cmd, unsigned long arg) |
1322 | { | 1193 | { |
1323 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1194 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1324 | if(pInfo==NULL) | 1195 | if (pInfo == NULL) |
1325 | return -EINVAL; | 1196 | return -EINVAL; |
1326 | switch(cmd) | 1197 | switch (cmd) { |
1327 | { | 1198 | case R3964_ENABLE_SIGNALS: |
1328 | case R3964_ENABLE_SIGNALS: | 1199 | return enable_signals(pInfo, task_pid(current), arg); |
1329 | return enable_signals(pInfo, task_pid(current), arg); | 1200 | case R3964_SETPRIORITY: |
1330 | case R3964_SETPRIORITY: | 1201 | if (arg < R3964_MASTER || arg > R3964_SLAVE) |
1331 | if(arg<R3964_MASTER || arg>R3964_SLAVE) | 1202 | return -EINVAL; |
1332 | return -EINVAL; | 1203 | pInfo->priority = arg & 0xff; |
1333 | pInfo->priority = arg & 0xff; | 1204 | return 0; |
1334 | return 0; | 1205 | case R3964_USE_BCC: |
1335 | case R3964_USE_BCC: | 1206 | if (arg) |
1336 | if(arg) | 1207 | pInfo->flags |= R3964_BCC; |
1337 | pInfo->flags |= R3964_BCC; | 1208 | else |
1338 | else | 1209 | pInfo->flags &= ~R3964_BCC; |
1339 | pInfo->flags &= ~R3964_BCC; | 1210 | return 0; |
1340 | return 0; | 1211 | case R3964_READ_TELEGRAM: |
1341 | case R3964_READ_TELEGRAM: | 1212 | return read_telegram(pInfo, task_pid(current), |
1342 | return read_telegram(pInfo, task_pid(current), (unsigned char __user *)arg); | 1213 | (unsigned char __user *)arg); |
1343 | default: | 1214 | default: |
1344 | return -ENOIOCTLCMD; | 1215 | return -ENOIOCTLCMD; |
1345 | } | 1216 | } |
1346 | } | 1217 | } |
1347 | 1218 | ||
1348 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios * old) | 1219 | static void r3964_set_termios(struct tty_struct *tty, struct ktermios *old) |
1349 | { | 1220 | { |
1350 | TRACE_L("set_termios"); | 1221 | TRACE_L("set_termios"); |
1351 | } | 1222 | } |
1352 | 1223 | ||
1353 | /* Called without the kernel lock held - fine */ | 1224 | /* Called without the kernel lock held - fine */ |
1354 | static unsigned int r3964_poll(struct tty_struct * tty, struct file * file, | 1225 | static unsigned int r3964_poll(struct tty_struct *tty, struct file *file, |
1355 | struct poll_table_struct *wait) | 1226 | struct poll_table_struct *wait) |
1356 | { | 1227 | { |
1357 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1228 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1358 | struct r3964_client_info *pClient; | 1229 | struct r3964_client_info *pClient; |
1359 | struct r3964_message *pMsg=NULL; | 1230 | struct r3964_message *pMsg = NULL; |
1360 | unsigned long flags; | 1231 | unsigned long flags; |
1361 | int result = POLLOUT; | 1232 | int result = POLLOUT; |
1362 | 1233 | ||
1363 | TRACE_L("POLL"); | 1234 | TRACE_L("POLL"); |
1364 | 1235 | ||
1365 | pClient=findClient(pInfo, task_pid(current)); | 1236 | pClient = findClient(pInfo, task_pid(current)); |
1366 | if(pClient) | 1237 | if (pClient) { |
1367 | { | 1238 | poll_wait(file, &pInfo->read_wait, wait); |
1368 | poll_wait(file, &pInfo->read_wait, wait); | 1239 | spin_lock_irqsave(&pInfo->lock, flags); |
1369 | spin_lock_irqsave(&pInfo->lock, flags); | 1240 | pMsg = pClient->first_msg; |
1370 | pMsg=pClient->first_msg; | 1241 | spin_unlock_irqrestore(&pInfo->lock, flags); |
1371 | spin_unlock_irqrestore(&pInfo->lock, flags); | 1242 | if (pMsg) |
1372 | if(pMsg) | 1243 | result |= POLLIN | POLLRDNORM; |
1373 | result |= POLLIN | POLLRDNORM; | 1244 | } else { |
1374 | } | 1245 | result = -EINVAL; |
1375 | else | 1246 | } |
1376 | { | 1247 | return result; |
1377 | result = -EINVAL; | ||
1378 | } | ||
1379 | return result; | ||
1380 | } | 1248 | } |
1381 | 1249 | ||
1382 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, | 1250 | static void r3964_receive_buf(struct tty_struct *tty, const unsigned char *cp, |
1383 | char *fp, int count) | 1251 | char *fp, int count) |
1384 | { | 1252 | { |
1385 | struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; | 1253 | struct r3964_info *pInfo = (struct r3964_info *)tty->disc_data; |
1386 | const unsigned char *p; | 1254 | const unsigned char *p; |
1387 | char *f, flags = 0; | 1255 | char *f, flags = 0; |
1388 | int i; | 1256 | int i; |
1389 | 1257 | ||
1390 | for (i=count, p = cp, f = fp; i; i--, p++) { | 1258 | for (i = count, p = cp, f = fp; i; i--, p++) { |
1391 | if (f) | 1259 | if (f) |
1392 | flags = *f++; | 1260 | flags = *f++; |
1393 | if(flags==TTY_NORMAL) | 1261 | if (flags == TTY_NORMAL) { |
1394 | { | 1262 | receive_char(pInfo, *p); |
1395 | receive_char(pInfo, *p); | 1263 | } else { |
1396 | } | 1264 | receive_error(pInfo, flags); |
1397 | else | 1265 | } |
1398 | { | 1266 | |
1399 | receive_error(pInfo, flags); | 1267 | } |
1400 | } | ||
1401 | |||
1402 | } | ||
1403 | } | 1268 | } |
1404 | 1269 | ||
1405 | MODULE_LICENSE("GPL"); | 1270 | MODULE_LICENSE("GPL"); |