aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/chan_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers/chan_kern.c')
-rw-r--r--arch/um/drivers/chan_kern.c124
1 files changed, 70 insertions, 54 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 5b58fad45290..8b1262e9fb66 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -58,7 +58,7 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
58{ 58{
59 my_puts("Using a channel type which is configured out of " 59 my_puts("Using a channel type which is configured out of "
60 "UML\n"); 60 "UML\n");
61 return(NULL); 61 return NULL;
62} 62}
63 63
64static int not_configged_open(int input, int output, int primary, void *data, 64static int not_configged_open(int input, int output, int primary, void *data,
@@ -66,7 +66,7 @@ static int not_configged_open(int input, int output, int primary, void *data,
66{ 66{
67 my_puts("Using a channel type which is configured out of " 67 my_puts("Using a channel type which is configured out of "
68 "UML\n"); 68 "UML\n");
69 return(-ENODEV); 69 return -ENODEV;
70} 70}
71 71
72static void not_configged_close(int fd, void *data) 72static void not_configged_close(int fd, void *data)
@@ -79,21 +79,21 @@ static int not_configged_read(int fd, char *c_out, void *data)
79{ 79{
80 my_puts("Using a channel type which is configured out of " 80 my_puts("Using a channel type which is configured out of "
81 "UML\n"); 81 "UML\n");
82 return(-EIO); 82 return -EIO;
83} 83}
84 84
85static int not_configged_write(int fd, const char *buf, int len, void *data) 85static int not_configged_write(int fd, const char *buf, int len, void *data)
86{ 86{
87 my_puts("Using a channel type which is configured out of " 87 my_puts("Using a channel type which is configured out of "
88 "UML\n"); 88 "UML\n");
89 return(-EIO); 89 return -EIO;
90} 90}
91 91
92static int not_configged_console_write(int fd, const char *buf, int len) 92static int not_configged_console_write(int fd, const char *buf, int len)
93{ 93{
94 my_puts("Using a channel type which is configured out of " 94 my_puts("Using a channel type which is configured out of "
95 "UML\n"); 95 "UML\n");
96 return(-EIO); 96 return -EIO;
97} 97}
98 98
99static int not_configged_window_size(int fd, void *data, unsigned short *rows, 99static int not_configged_window_size(int fd, void *data, unsigned short *rows,
@@ -101,7 +101,7 @@ static int not_configged_window_size(int fd, void *data, unsigned short *rows,
101{ 101{
102 my_puts("Using a channel type which is configured out of " 102 my_puts("Using a channel type which is configured out of "
103 "UML\n"); 103 "UML\n");
104 return(-ENODEV); 104 return -ENODEV;
105} 105}
106 106
107static void not_configged_free(void *data) 107static void not_configged_free(void *data)
@@ -135,17 +135,17 @@ int generic_read(int fd, char *c_out, void *unused)
135 n = os_read_file(fd, c_out, sizeof(*c_out)); 135 n = os_read_file(fd, c_out, sizeof(*c_out));
136 136
137 if(n == -EAGAIN) 137 if(n == -EAGAIN)
138 return(0); 138 return 0;
139 else if(n == 0) 139 else if(n == 0)
140 return(-EIO); 140 return -EIO;
141 return(n); 141 return n;
142} 142}
143 143
144/* XXX Trivial wrapper around os_write_file */ 144/* XXX Trivial wrapper around os_write_file */
145 145
146int generic_write(int fd, const char *buf, int n, void *unused) 146int generic_write(int fd, const char *buf, int n, void *unused)
147{ 147{
148 return(os_write_file(fd, buf, n)); 148 return os_write_file(fd, buf, n);
149} 149}
150 150
151int generic_window_size(int fd, void *unused, unsigned short *rows_out, 151int generic_window_size(int fd, void *unused, unsigned short *rows_out,
@@ -156,14 +156,14 @@ int generic_window_size(int fd, void *unused, unsigned short *rows_out,
156 156
157 ret = os_window_size(fd, &rows, &cols); 157 ret = os_window_size(fd, &rows, &cols);
158 if(ret < 0) 158 if(ret < 0)
159 return(ret); 159 return ret;
160 160
161 ret = ((*rows_out != rows) || (*cols_out != cols)); 161 ret = ((*rows_out != rows) || (*cols_out != cols));
162 162
163 *rows_out = rows; 163 *rows_out = rows;
164 *cols_out = cols; 164 *cols_out = cols;
165 165
166 return(ret); 166 return ret;
167} 167}
168 168
169void generic_free(void *data) 169void generic_free(void *data)
@@ -186,25 +186,29 @@ static void tty_receive_char(struct tty_struct *tty, char ch)
186 } 186 }
187 } 187 }
188 188
189 if((tty->flip.flag_buf_ptr == NULL) || 189 if((tty->flip.flag_buf_ptr == NULL) ||
190 (tty->flip.char_buf_ptr == NULL)) 190 (tty->flip.char_buf_ptr == NULL))
191 return; 191 return;
192 tty_insert_flip_char(tty, ch, TTY_NORMAL); 192 tty_insert_flip_char(tty, ch, TTY_NORMAL);
193} 193}
194 194
195static int open_one_chan(struct chan *chan, int input, int output, int primary) 195static int open_one_chan(struct chan *chan)
196{ 196{
197 int fd; 197 int fd;
198 198
199 if(chan->opened) return(0); 199 if(chan->opened)
200 if(chan->ops->open == NULL) fd = 0; 200 return 0;
201 else fd = (*chan->ops->open)(input, output, primary, chan->data, 201
202 &chan->dev); 202 if(chan->ops->open == NULL)
203 if(fd < 0) return(fd); 203 fd = 0;
204 else fd = (*chan->ops->open)(chan->input, chan->output, chan->primary,
205 chan->data, &chan->dev);
206 if(fd < 0)
207 return fd;
204 chan->fd = fd; 208 chan->fd = fd;
205 209
206 chan->opened = 1; 210 chan->opened = 1;
207 return(0); 211 return 0;
208} 212}
209 213
210int open_chan(struct list_head *chans) 214int open_chan(struct list_head *chans)
@@ -215,11 +219,11 @@ int open_chan(struct list_head *chans)
215 219
216 list_for_each(ele, chans){ 220 list_for_each(ele, chans){
217 chan = list_entry(ele, struct chan, list); 221 chan = list_entry(ele, struct chan, list);
218 ret = open_one_chan(chan, chan->input, chan->output, 222 ret = open_one_chan(chan);
219 chan->primary); 223 if(chan->primary)
220 if(chan->primary) err = ret; 224 err = ret;
221 } 225 }
222 return(err); 226 return err;
223} 227}
224 228
225void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) 229void chan_enable_winch(struct list_head *chans, struct tty_struct *tty)
@@ -267,7 +271,7 @@ void close_chan(struct list_head *chans)
267 } 271 }
268} 272}
269 273
270int write_chan(struct list_head *chans, const char *buf, int len, 274int write_chan(struct list_head *chans, const char *buf, int len,
271 int write_irq) 275 int write_irq)
272{ 276{
273 struct list_head *ele; 277 struct list_head *ele;
@@ -285,7 +289,7 @@ int write_chan(struct list_head *chans, const char *buf, int len,
285 reactivate_fd(chan->fd, write_irq); 289 reactivate_fd(chan->fd, write_irq);
286 } 290 }
287 } 291 }
288 return(ret); 292 return ret;
289} 293}
290 294
291int console_write_chan(struct list_head *chans, const char *buf, int len) 295int console_write_chan(struct list_head *chans, const char *buf, int len)
@@ -301,10 +305,11 @@ int console_write_chan(struct list_head *chans, const char *buf, int len)
301 n = chan->ops->console_write(chan->fd, buf, len); 305 n = chan->ops->console_write(chan->fd, buf, len);
302 if(chan->primary) ret = n; 306 if(chan->primary) ret = n;
303 } 307 }
304 return(ret); 308 return ret;
305} 309}
306 310
307int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) 311int console_open_chan(struct line *line, struct console *co,
312 struct chan_opts *opts)
308{ 313{
309 if (!list_empty(&line->chan_list)) 314 if (!list_empty(&line->chan_list))
310 return 0; 315 return 0;
@@ -327,12 +332,13 @@ int chan_window_size(struct list_head *chans, unsigned short *rows_out,
327 list_for_each(ele, chans){ 332 list_for_each(ele, chans){
328 chan = list_entry(ele, struct chan, list); 333 chan = list_entry(ele, struct chan, list);
329 if(chan->primary){ 334 if(chan->primary){
330 if(chan->ops->window_size == NULL) return(0); 335 if(chan->ops->window_size == NULL)
331 return(chan->ops->window_size(chan->fd, chan->data, 336 return 0;
332 rows_out, cols_out)); 337 return chan->ops->window_size(chan->fd, chan->data,
338 rows_out, cols_out);
333 } 339 }
334 } 340 }
335 return(0); 341 return 0;
336} 342}
337 343
338void free_one_chan(struct chan *chan) 344void free_one_chan(struct chan *chan)
@@ -363,23 +369,23 @@ static int one_chan_config_string(struct chan *chan, char *str, int size,
363 369
364 if(chan == NULL){ 370 if(chan == NULL){
365 CONFIG_CHUNK(str, size, n, "none", 1); 371 CONFIG_CHUNK(str, size, n, "none", 1);
366 return(n); 372 return n;
367 } 373 }
368 374
369 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 375 CONFIG_CHUNK(str, size, n, chan->ops->type, 0);
370 376
371 if(chan->dev == NULL){ 377 if(chan->dev == NULL){
372 CONFIG_CHUNK(str, size, n, "", 1); 378 CONFIG_CHUNK(str, size, n, "", 1);
373 return(n); 379 return n;
374 } 380 }
375 381
376 CONFIG_CHUNK(str, size, n, ":", 0); 382 CONFIG_CHUNK(str, size, n, ":", 0);
377 CONFIG_CHUNK(str, size, n, chan->dev, 0); 383 CONFIG_CHUNK(str, size, n, chan->dev, 0);
378 384
379 return(n); 385 return n;
380} 386}
381 387
382static int chan_pair_config_string(struct chan *in, struct chan *out, 388static int chan_pair_config_string(struct chan *in, struct chan *out,
383 char *str, int size, char **error_out) 389 char *str, int size, char **error_out)
384{ 390{
385 int n; 391 int n;
@@ -390,7 +396,7 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
390 396
391 if(in == out){ 397 if(in == out){
392 CONFIG_CHUNK(str, size, n, "", 1); 398 CONFIG_CHUNK(str, size, n, "", 1);
393 return(n); 399 return n;
394 } 400 }
395 401
396 CONFIG_CHUNK(str, size, n, ",", 1); 402 CONFIG_CHUNK(str, size, n, ",", 1);
@@ -399,10 +405,10 @@ static int chan_pair_config_string(struct chan *in, struct chan *out,
399 size -= n; 405 size -= n;
400 CONFIG_CHUNK(str, size, n, "", 1); 406 CONFIG_CHUNK(str, size, n, "", 1);
401 407
402 return(n); 408 return n;
403} 409}
404 410
405int chan_config_string(struct list_head *chans, char *str, int size, 411int chan_config_string(struct list_head *chans, char *str, int size,
406 char **error_out) 412 char **error_out)
407{ 413{
408 struct list_head *ele; 414 struct list_head *ele;
@@ -418,7 +424,7 @@ int chan_config_string(struct list_head *chans, char *str, int size,
418 out = chan; 424 out = chan;
419 } 425 }
420 426
421 return(chan_pair_config_string(in, out, str, size, error_out)); 427 return chan_pair_config_string(in, out, str, size, error_out);
422} 428}
423 429
424struct chan_type { 430struct chan_type {
@@ -462,7 +468,7 @@ struct chan_type chan_table[] = {
462#endif 468#endif
463}; 469};
464 470
465static struct chan *parse_chan(char *str, int pri, int device, 471static struct chan *parse_chan(char *str, int pri, int device,
466 struct chan_opts *opts) 472 struct chan_opts *opts)
467{ 473{
468 struct chan_type *entry; 474 struct chan_type *entry;
@@ -484,14 +490,17 @@ static struct chan *parse_chan(char *str, int pri, int device,
484 if(ops == NULL){ 490 if(ops == NULL){
485 my_printf("parse_chan couldn't parse \"%s\"\n", 491 my_printf("parse_chan couldn't parse \"%s\"\n",
486 str); 492 str);
487 return(NULL); 493 return NULL;
488 } 494 }
489 if(ops->init == NULL) return(NULL); 495 if(ops->init == NULL)
496 return NULL;
490 data = (*ops->init)(str, device, opts); 497 data = (*ops->init)(str, device, opts);
491 if(data == NULL) return(NULL); 498 if(data == NULL)
499 return NULL;
492 500
493 chan = kmalloc(sizeof(*chan), GFP_ATOMIC); 501 chan = kmalloc(sizeof(*chan), GFP_ATOMIC);
494 if(chan == NULL) return(NULL); 502 if(chan == NULL)
503 return NULL;
495 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 504 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list),
496 .primary = 1, 505 .primary = 1,
497 .input = 0, 506 .input = 0,
@@ -501,7 +510,7 @@ static struct chan *parse_chan(char *str, int pri, int device,
501 .pri = pri, 510 .pri = pri,
502 .ops = ops, 511 .ops = ops,
503 .data = data }); 512 .data = data });
504 return(chan); 513 return chan;
505} 514}
506 515
507int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, 516int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
@@ -512,7 +521,8 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
512 521
513 if(!list_empty(chans)){ 522 if(!list_empty(chans)){
514 chan = list_entry(chans->next, struct chan, list); 523 chan = list_entry(chans->next, struct chan, list);
515 if(chan->pri >= pri) return(0); 524 if(chan->pri >= pri)
525 return 0;
516 free_chan(chans); 526 free_chan(chans);
517 INIT_LIST_HEAD(chans); 527 INIT_LIST_HEAD(chans);
518 } 528 }
@@ -523,23 +533,29 @@ int parse_chan_pair(char *str, struct list_head *chans, int pri, int device,
523 *out = '\0'; 533 *out = '\0';
524 out++; 534 out++;
525 new = parse_chan(in, pri, device, opts); 535 new = parse_chan(in, pri, device, opts);
526 if(new == NULL) return(-1); 536 if(new == NULL)
537 return -1;
538
527 new->input = 1; 539 new->input = 1;
528 list_add(&new->list, chans); 540 list_add(&new->list, chans);
529 541
530 new = parse_chan(out, pri, device, opts); 542 new = parse_chan(out, pri, device, opts);
531 if(new == NULL) return(-1); 543 if(new == NULL)
544 return -1;
545
532 list_add(&new->list, chans); 546 list_add(&new->list, chans);
533 new->output = 1; 547 new->output = 1;
534 } 548 }
535 else { 549 else {
536 new = parse_chan(str, pri, device, opts); 550 new = parse_chan(str, pri, device, opts);
537 if(new == NULL) return(-1); 551 if(new == NULL)
552 return -1;
553
538 list_add(&new->list, chans); 554 list_add(&new->list, chans);
539 new->input = 1; 555 new->input = 1;
540 new->output = 1; 556 new->output = 1;
541 } 557 }
542 return(0); 558 return 0;
543} 559}
544 560
545int chan_out_fd(struct list_head *chans) 561int chan_out_fd(struct list_head *chans)
@@ -550,9 +566,9 @@ int chan_out_fd(struct list_head *chans)
550 list_for_each(ele, chans){ 566 list_for_each(ele, chans){
551 chan = list_entry(ele, struct chan, list); 567 chan = list_entry(ele, struct chan, list);
552 if(chan->primary && chan->output) 568 if(chan->primary && chan->output)
553 return(chan->fd); 569 return chan->fd;
554 } 570 }
555 return(-1); 571 return -1;
556} 572}
557 573
558void chan_interrupt(struct list_head *chans, struct work_struct *task, 574void chan_interrupt(struct list_head *chans, struct work_struct *task,
@@ -567,7 +583,7 @@ void chan_interrupt(struct list_head *chans, struct work_struct *task,
567 chan = list_entry(ele, struct chan, list); 583 chan = list_entry(ele, struct chan, list);
568 if(!chan->input || (chan->ops->read == NULL)) continue; 584 if(!chan->input || (chan->ops->read == NULL)) continue;
569 do { 585 do {
570 if((tty != NULL) && 586 if((tty != NULL) &&
571 (tty->flip.count >= TTY_FLIPBUF_SIZE)){ 587 (tty->flip.count >= TTY_FLIPBUF_SIZE)){
572 schedule_work(task); 588 schedule_work(task);
573 goto out; 589 goto out;