1 /* 2 * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6 #include <linux/stddef.h> 7 #include <linux/kernel.h> 8 #include <linux/list.h> 9 #include <linux/slab.h> 10 #include <linux/tty.h> 11 #include <linux/string.h> 12 #include <linux/tty_flip.h> 13 #include <asm/irq.h> 14 #include "chan_kern.h" 15 #include "user_util.h" 16 #include "kern.h" 17 #include "irq_user.h" 18 #include "sigio.h" 19 #include "line.h" 20 #include "os.h" 21 22 #ifdef CONFIG_NOCONFIG_CHAN 23 24 /* The printk's here are wrong because we are complaining that there is no 25 * output device, but printk is printing to that output device. The user will 26 * never see the error. printf would be better, except it can't run on a 27 * kernel stack because it will overflow it. 28 * Use printk for now since that will avoid crashing. 29 */ 30 31 static void *not_configged_init(char *str, int device, struct chan_opts *opts) 32 { 33 printk(KERN_ERR "Using a channel type which is configured out of " 34 "UML\n"); 35 return(NULL); 36 } 37 38 static int not_configged_open(int input, int output, int primary, void *data, 39 char **dev_out) 40 { 41 printk(KERN_ERR "Using a channel type which is configured out of " 42 "UML\n"); 43 return(-ENODEV); 44 } 45 46 static void not_configged_close(int fd, void *data) 47 { 48 printk(KERN_ERR "Using a channel type which is configured out of " 49 "UML\n"); 50 } 51 52 static int not_configged_read(int fd, char *c_out, void *data) 53 { 54 printk(KERN_ERR "Using a channel type which is configured out of " 55 "UML\n"); 56 return(-EIO); 57 } 58 59 static int not_configged_write(int fd, const char *buf, int len, void *data) 60 { 61 printk(KERN_ERR "Using a channel type which is configured out of " 62 "UML\n"); 63 return(-EIO); 64 } 65 66 static int not_configged_console_write(int fd, const char *buf, int len, 67 void *data) 68 { 69 printk(KERN_ERR "Using a channel type which is configured out of " 70 "UML\n"); 71 return(-EIO); 72 } 73 74 static int not_configged_window_size(int fd, void *data, unsigned short *rows, 75 unsigned short *cols) 76 { 77 printk(KERN_ERR "Using a channel type which is configured out of " 78 "UML\n"); 79 return(-ENODEV); 80 } 81 82 static void not_configged_free(void *data) 83 { 84 printf(KERN_ERR "Using a channel type which is configured out of " 85 "UML\n"); 86 } 87 88 static struct chan_ops not_configged_ops = { 89 .init = not_configged_init, 90 .open = not_configged_open, 91 .close = not_configged_close, 92 .read = not_configged_read, 93 .write = not_configged_write, 94 .console_write = not_configged_console_write, 95 .window_size = not_configged_window_size, 96 .free = not_configged_free, 97 .winch = 0, 98 }; 99 #endif /* CONFIG_NOCONFIG_CHAN */ 100 101 void generic_close(int fd, void *unused) 102 { 103 os_close_file(fd); 104 } 105 106 int generic_read(int fd, char *c_out, void *unused) 107 { 108 int n; 109 110 n = os_read_file(fd, c_out, sizeof(*c_out)); 111 112 if(n == -EAGAIN) 113 return(0); 114 else if(n == 0) 115 return(-EIO); 116 return(n); 117 } 118 119 /* XXX Trivial wrapper around os_write_file */ 120 121 int generic_write(int fd, const char *buf, int n, void *unused) 122 { 123 return(os_write_file(fd, buf, n)); 124 } 125 126 int generic_window_size(int fd, void *unused, unsigned short *rows_out, 127 unsigned short *cols_out) 128 { 129 int rows, cols; 130 int ret; 131 132 ret = os_window_size(fd, &rows, &cols); 133 if(ret < 0) 134 return(ret); 135 136 ret = ((*rows_out != rows) || (*cols_out != cols)); 137 138 *rows_out = rows; 139 *cols_out = cols; 140 141 return(ret); 142 } 143 144 void generic_free(void *data) 145 { 146 kfree(data); 147 } 148 149 static void tty_receive_char(struct tty_struct *tty, char ch) 150 { 151 if(tty == NULL) return; 152 153 if(I_IXON(tty) && !I_IXOFF(tty) && !tty->raw) { 154 if(ch == STOP_CHAR(tty)){ 155 stop_tty(tty); 156 return; 157 } 158 else if(ch == START_CHAR(tty)){ 159 start_tty(tty); 160 return; 161 } 162 } 163 164 if((tty->flip.flag_buf_ptr == NULL) || 165 (tty->flip.char_buf_ptr == NULL)) 166 return; 167 tty_insert_flip_char(tty, ch, TTY_NORMAL); 168 } 169 170 static int open_one_chan(struct chan *chan, int input, int output, int primary) 171 { 172 int fd; 173 174 if(chan->opened) return(0); 175 if(chan->ops->open == NULL) fd = 0; 176 else fd = (*chan->ops->open)(input, output, primary, chan->data, 177 &chan->dev); 178 if(fd < 0) return(fd); 179 chan->fd = fd; 180 181 chan->opened = 1; 182 return(0); 183 } 184 185 int open_chan(struct list_head *chans) 186 { 187 struct list_head *ele; 188 struct chan *chan; 189 int ret, err = 0; 190 191 list_for_each(ele, chans){ 192 chan = list_entry(ele, struct chan, list); 193 ret = open_one_chan(chan, chan->input, chan->output, 194 chan->primary); 195 if(chan->primary) err = ret; 196 } 197 return(err); 198 } 199 200 void chan_enable_winch(struct list_head *chans, struct tty_struct *tty) 201 { 202 struct list_head *ele; 203 struct chan *chan; 204 205 list_for_each(ele, chans){ 206 chan = list_entry(ele, struct chan, list); 207 if(chan->primary && chan->output && chan->ops->winch){ 208 register_winch(chan->fd, tty); 209 return; 210 } 211 } 212 } 213 214 void enable_chan(struct list_head *chans, struct tty_struct *tty) 215 { 216 struct list_head *ele; 217 struct chan *chan; 218 219 list_for_each(ele, chans){ 220 chan = list_entry(ele, struct chan, list); 221 if(!chan->opened) continue; 222 223 line_setup_irq(chan->fd, chan->input, chan->output, tty); 224 } 225 } 226 227 void close_chan(struct list_head *chans) 228 { 229 struct chan *chan; 230 231 /* Close in reverse order as open in case more than one of them 232 * refers to the same device and they save and restore that device's 233 * state. Then, the first one opened will have the original state, 234 * so it must be the last closed. 235 */ 236 list_for_each_entry_reverse(chan, chans, list) { 237 if(!chan->opened) continue; 238 if(chan->ops->close != NULL) 239 (*chan->ops->close)(chan->fd, chan->data); 240 chan->opened = 0; 241 chan->fd = -1; 242 } 243 } 244 245 int write_chan(struct list_head *chans, const char *buf, int len, 246 int write_irq) 247 { 248 struct list_head *ele; 249 struct chan *chan = NULL; 250 int n, ret = 0; 251 252 list_for_each(ele, chans) { 253 chan = list_entry(ele, struct chan, list); 254 if (!chan->output || (chan->ops->write == NULL)) 255 continue; 256 n = chan->ops->write(chan->fd, buf, len, chan->data); 257 if (chan->primary) { 258 ret = n; 259 if ((ret == -EAGAIN) || ((ret >= 0) && (ret < len))) 260 reactivate_fd(chan->fd, write_irq); 261 } 262 } 263 return(ret); 264 } 265 266 int console_write_chan(struct list_head *chans, const char *buf, int len) 267 { 268 struct list_head *ele; 269 struct chan *chan; 270 int n, ret = 0; 271 272 list_for_each(ele, chans){ 273 chan = list_entry(ele, struct chan, list); 274 if(!chan->output || (chan->ops->console_write == NULL)) 275 continue; 276 n = chan->ops->console_write(chan->fd, buf, len, chan->data); 277 if(chan->primary) ret = n; 278 } 279 return(ret); 280 } 281 282 int console_open_chan(struct line *line, struct console *co, struct chan_opts *opts) 283 { 284 if (!list_empty(&line->chan_list)) 285 return 0; 286 287 if (0 != parse_chan_pair(line->init_str, &line->chan_list, 288 line->init_pri, co->index, opts)) 289 return -1; 290 if (0 != open_chan(&line->chan_list)) 291 return -1; 292 printk("Console initialized on /dev/%s%d\n",co->name,co->index); 293 return 0; 294 } 295 296 int chan_window_size(struct list_head *chans, unsigned short *rows_out, 297 unsigned short *cols_out) 298 { 299 struct list_head *ele; 300 struct chan *chan; 301 302 list_for_each(ele, chans){ 303 chan = list_entry(ele, struct chan, list); 304 if(chan->primary){ 305 if(chan->ops->window_size == NULL) return(0); 306 return(chan->ops->window_size(chan->fd, chan->data, 307 rows_out, cols_out)); 308 } 309 } 310 return(0); 311 } 312 313 void free_one_chan(struct chan *chan) 314 { 315 list_del(&chan->list); 316 if(chan->ops->free != NULL) 317 (*chan->ops->free)(chan->data); 318 free_irq_by_fd(chan->fd); 319 if(chan->primary && chan->output) ignore_sigio_fd(chan->fd); 320 kfree(chan); 321 } 322 323 void free_chan(struct list_head *chans) 324 { 325 struct list_head *ele, *next; 326 struct chan *chan; 327 328 list_for_each_safe(ele, next, chans){ 329 chan = list_entry(ele, struct chan, list); 330 free_one_chan(chan); 331 } 332 } 333 334 static int one_chan_config_string(struct chan *chan, char *str, int size, 335 char **error_out) 336 { 337 int n = 0; 338 339 if(chan == NULL){ 340 CONFIG_CHUNK(str, size, n, "none", 1); 341 return(n); 342 } 343 344 CONFIG_CHUNK(str, size, n, chan->ops->type, 0); 345 346 if(chan->dev == NULL){ 347 CONFIG_CHUNK(str, size, n, "", 1); 348 return(n); 349 } 350 351 CONFIG_CHUNK(str, size, n, ":", 0); 352 CONFIG_CHUNK(str, size, n, chan->dev, 0); 353 354 return(n); 355 } 356 357 static int chan_pair_config_string(struct chan *in, struct chan *out, 358 char *str, int size, char **error_out) 359 { 360 int n; 361 362 n = one_chan_config_string(in, str, size, error_out); 363 str += n; 364 size -= n; 365 366 if(in == out){ 367 CONFIG_CHUNK(str, size, n, "", 1); 368 return(n); 369 } 370 371 CONFIG_CHUNK(str, size, n, ",", 1); 372 n = one_chan_config_string(out, str, size, error_out); 373 str += n; 374 size -= n; 375 CONFIG_CHUNK(str, size, n, "", 1); 376 377 return(n); 378 } 379 380 int chan_config_string(struct list_head *chans, char *str, int size, 381 char **error_out) 382 { 383 struct list_head *ele; 384 struct chan *chan, *in = NULL, *out = NULL; 385 386 list_for_each(ele, chans){ 387 chan = list_entry(ele, struct chan, list); 388 if(!chan->primary) 389 continue; 390 if(chan->input) 391 in = chan; 392 if(chan->output) 393 out = chan; 394 } 395 396 return(chan_pair_config_string(in, out, str, size, error_out)); 397 } 398 399 struct chan_type { 400 char *key; 401 struct chan_ops *ops; 402 }; 403 404 struct chan_type chan_table[] = { 405 { "fd", &fd_ops }, 406 407 #ifdef CONFIG_NULL_CHAN 408 { "null", &null_ops }, 409 #else 410 { "null", ¬_configged_ops }, 411 #endif 412 413 #ifdef CONFIG_PORT_CHAN 414 { "port", &port_ops }, 415 #else 416 { "port", ¬_configged_ops }, 417 #endif 418 419 #ifdef CONFIG_PTY_CHAN 420 { "pty", &pty_ops }, 421 { "pts", &pts_ops }, 422 #else 423 { "pty", ¬_configged_ops }, 424 { "pts", ¬_configged_ops }, 425 #endif 426 427 #ifdef CONFIG_TTY_CHAN 428 { "tty", &tty_ops }, 429 #else 430 { "tty", ¬_configged_ops }, 431 #endif 432 433 #ifdef CONFIG_XTERM_CHAN 434 { "xterm", &xterm_ops }, 435 #else 436 { "xterm", ¬_configged_ops }, 437 #endif 438 }; 439 440 static struct chan *parse_chan(char *str, int pri, int device, 441 struct chan_opts *opts) 442 { 443 struct chan_type *entry; 444 struct chan_ops *ops; 445 struct chan *chan; 446 void *data; 447 int i; 448 449 ops = NULL; 450 data = NULL; 451 for(i = 0; i < sizeof(chan_table)/sizeof(chan_table[0]); i++){ 452 entry = &chan_table[i]; 453 if(!strncmp(str, entry->key, strlen(entry->key))){ 454 ops = entry->ops; 455 str += strlen(entry->key); 456 break; 457 } 458 } 459 if(ops == NULL){ 460 printk(KERN_ERR "parse_chan couldn't parse \"%s\"\n", 461 str); 462 return(NULL); 463 } 464 if(ops->init == NULL) return(NULL); 465 data = (*ops->init)(str, device, opts); 466 if(data == NULL) return(NULL); 467 468 chan = kmalloc(sizeof(*chan), GFP_KERNEL); 469 if(chan == NULL) return(NULL); 470 *chan = ((struct chan) { .list = LIST_HEAD_INIT(chan->list), 471 .primary = 1, 472 .input = 0, 473 .output = 0, 474 .opened = 0, 475 .fd = -1, 476 .pri = pri, 477 .ops = ops, 478 .data = data }); 479 return(chan); 480 } 481 482 int parse_chan_pair(char *str, struct list_head *chans, int pri, int device, 483 struct chan_opts *opts) 484 { 485 struct chan *new, *chan; 486 char *in, *out; 487 488 if(!list_empty(chans)){ 489 chan = list_entry(chans->next, struct chan, list); 490 if(chan->pri >= pri) return(0); 491 free_chan(chans); 492 INIT_LIST_HEAD(chans); 493 } 494 495 out = strchr(str, ','); 496 if(out != NULL){ 497 in = str; 498 *out = '\0'; 499 out++; 500 new = parse_chan(in, pri, device, opts); 501 if(new == NULL) return(-1); 502 new->input = 1; 503 list_add(&new->list, chans); 504 505 new = parse_chan(out, pri, device, opts); 506 if(new == NULL) return(-1); 507 list_add(&new->list, chans); 508 new->output = 1; 509 } 510 else { 511 new = parse_chan(str, pri, device, opts); 512 if(new == NULL) return(-1); 513 list_add(&new->list, chans); 514 new->input = 1; 515 new->output = 1; 516 } 517 return(0); 518 } 519 520 int chan_out_fd(struct list_head *chans) 521 { 522 struct list_head *ele; 523 struct chan *chan; 524 525 list_for_each(ele, chans){ 526 chan = list_entry(ele, struct chan, list); 527 if(chan->primary && chan->output) 528 return(chan->fd); 529 } 530 return(-1); 531 } 532 533 void chan_interrupt(struct list_head *chans, struct work_struct *task, 534 struct tty_struct *tty, int irq) 535 { 536 struct list_head *ele, *next; 537 struct chan *chan; 538 int err; 539 char c; 540 541 list_for_each_safe(ele, next, chans){ 542 chan = list_entry(ele, struct chan, list); 543 if(!chan->input || (chan->ops->read == NULL)) continue; 544 do { 545 if((tty != NULL) && 546 (tty->flip.count >= TTY_FLIPBUF_SIZE)){ 547 schedule_work(task); 548 goto out; 549 } 550 err = chan->ops->read(chan->fd, &c, chan->data); 551 if(err > 0) 552 tty_receive_char(tty, c); 553 } while(err > 0); 554 555 if(err == 0) reactivate_fd(chan->fd, irq); 556 if(err == -EIO){ 557 if(chan->primary){ 558 if(tty != NULL) 559 tty_hangup(tty); 560 line_disable(tty, irq); 561 close_chan(chans); 562 free_chan(chans); 563 return; 564 } 565 else { 566 if(chan->ops->close != NULL) 567 chan->ops->close(chan->fd, chan->data); 568 free_one_chan(chan); 569 } 570 } 571 } 572 out: 573 if(tty) tty_flip_buffer_push(tty); 574 } 575 576 /* 577 * Overrides for Emacs so that we follow Linus's tabbing style. 578 * Emacs will notice this stuff at the end of the file and automatically 579 * adjust the settings for this buffer only. This must remain at the end 580 * of the file. 581 * --------------------------------------------------------------------------- 582 * Local variables: 583 * c-file-style: "linux" 584 * End: 585 */ 586