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