2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
3 * Licensed under the GPL
6 #include "linux/sched.h"
7 #include "linux/slab.h"
8 #include "linux/list.h"
9 #include "linux/interrupt.h"
10 #include "linux/devfs_fs_kernel.h"
11 #include "asm/uaccess.h"
12 #include "chan_kern.h"
16 #include "user_util.h"
17 #include "kern_util.h"
21 #define LINE_BUFSIZE 4096
23 static irqreturn_t
line_interrupt(int irq
, void *data
, struct pt_regs
*unused
)
25 struct line
*dev
= data
;
28 chan_interrupt(&dev
->chan_list
, &dev
->task
, dev
->tty
, irq
,
33 static void line_timer_cb(void *arg
)
35 struct line
*dev
= arg
;
37 line_interrupt(dev
->driver
->read_irq
, dev
, NULL
);
40 static int write_room(struct line
*dev
)
44 if(dev
->buffer
== NULL
) return(LINE_BUFSIZE
- 1);
46 n
= dev
->head
- dev
->tail
;
47 if(n
<= 0) n
= LINE_BUFSIZE
+ n
;
51 static int buffer_data(struct line
*line
, const char *buf
, int len
)
55 if(line
->buffer
== NULL
){
56 line
->buffer
= kmalloc(LINE_BUFSIZE
, GFP_ATOMIC
);
57 if(line
->buffer
== NULL
){
58 printk("buffer_data - atomic allocation failed\n");
61 line
->head
= line
->buffer
;
62 line
->tail
= line
->buffer
;
65 room
= write_room(line
);
66 len
= (len
> room
) ? room
: len
;
68 end
= line
->buffer
+ LINE_BUFSIZE
- line
->tail
;
70 memcpy(line
->tail
, buf
, len
);
74 memcpy(line
->tail
, buf
, end
);
76 memcpy(line
->buffer
, buf
, len
- end
);
77 line
->tail
= line
->buffer
+ len
- end
;
83 static int flush_buffer(struct line
*line
)
87 if((line
->buffer
== NULL
) || (line
->head
== line
->tail
)) return(1);
89 if(line
->tail
< line
->head
){
90 count
= line
->buffer
+ LINE_BUFSIZE
- line
->head
;
91 n
= write_chan(&line
->chan_list
, line
->head
, count
,
92 line
->driver
->write_irq
);
94 if(n
== count
) line
->head
= line
->buffer
;
101 count
= line
->tail
- line
->head
;
102 n
= write_chan(&line
->chan_list
, line
->head
, count
,
103 line
->driver
->write_irq
);
107 return(line
->head
== line
->tail
);
110 int line_write(struct line
*lines
, struct tty_struct
*tty
, int from_user
,
111 const char *buf
, int len
)
116 int n
, err
, i
, ret
= 0;
118 if(tty
->stopped
) return 0;
121 new = kmalloc(len
, GFP_KERNEL
);
124 n
= copy_from_user(new, buf
, len
);
138 if(line
->head
!= line
->tail
){
139 local_irq_save(flags
);
140 ret
+= buffer_data(line
, buf
, len
);
141 err
= flush_buffer(line
);
142 local_irq_restore(flags
);
147 n
= write_chan(&line
->chan_list
, buf
, len
,
148 line
->driver
->write_irq
);
157 ret
+= buffer_data(line
, buf
+ n
, len
);
167 static irqreturn_t
line_write_interrupt(int irq
, void *data
,
168 struct pt_regs
*unused
)
170 struct line
*dev
= data
;
171 struct tty_struct
*tty
= dev
->tty
;
174 err
= flush_buffer(dev
);
178 dev
->head
= dev
->buffer
;
179 dev
->tail
= dev
->buffer
;
185 if(test_bit(TTY_DO_WRITE_WAKEUP
, &tty
->flags
) &&
186 (tty
->ldisc
.write_wakeup
!= NULL
))
187 (tty
->ldisc
.write_wakeup
)(tty
);
190 * In blocking mode, everything sleeps on tty->write_wait.
191 * Sleeping in the console driver would break non-blocking
195 if(waitqueue_active(&tty
->write_wait
))
196 wake_up_interruptible(&tty
->write_wait
);
200 int line_setup_irq(int fd
, int input
, int output
, void *data
)
202 struct line
*line
= data
;
203 struct line_driver
*driver
= line
->driver
;
204 int err
= 0, flags
= SA_INTERRUPT
| SA_SHIRQ
| SA_SAMPLE_RANDOM
;
206 if(input
) err
= um_request_irq(driver
->read_irq
, fd
, IRQ_READ
,
207 line_interrupt
, flags
,
208 driver
->read_irq_name
, line
);
210 if(output
) err
= um_request_irq(driver
->write_irq
, fd
, IRQ_WRITE
,
211 line_write_interrupt
, flags
,
212 driver
->write_irq_name
, line
);
217 void line_disable(struct line
*line
, int current_irq
)
219 if(!line
->have_irq
) return;
221 if(line
->driver
->read_irq
== current_irq
)
222 free_irq_later(line
->driver
->read_irq
, line
);
224 free_irq(line
->driver
->read_irq
, line
);
226 if(line
->driver
->write_irq
== current_irq
)
227 free_irq_later(line
->driver
->write_irq
, line
);
229 free_irq(line
->driver
->write_irq
, line
);
234 int line_open(struct line
*lines
, struct tty_struct
*tty
,
235 struct chan_opts
*opts
)
240 if(tty
== NULL
) n
= 0;
245 if(line
->count
== 0){
250 if(list_empty(&line
->chan_list
)){
251 err
= parse_chan_pair(line
->init_str
, &line
->chan_list
,
252 line
->init_pri
, n
, opts
);
254 err
= open_chan(&line
->chan_list
);
257 enable_chan(&line
->chan_list
, line
);
258 INIT_WORK(&line
->task
, line_timer_cb
, line
);
262 chan_enable_winch(&line
->chan_list
, line
);
266 /* This is outside the if because the initial console is opened
272 tty
->driver_data
= line
;
273 chan_window_size(&line
->chan_list
, &tty
->winsize
.ws_row
,
274 &tty
->winsize
.ws_col
);
283 void line_close(struct line
*lines
, struct tty_struct
*tty
)
288 if(tty
== NULL
) n
= 0;
295 /* I don't like this, but I can't think of anything better. What's
296 * going on is that the tty is in the process of being closed for
297 * the last time. Its count hasn't been dropped yet, so it's still
298 * at 1. This may happen when line->count != 0 because of the initial
299 * console open (without a tty) bumping it up to 1.
301 if((line
->tty
!= NULL
) && (line
->tty
->count
== 1))
304 line_disable(line
, -1);
308 void close_lines(struct line
*lines
, int nlines
)
312 for(i
= 0; i
< nlines
; i
++)
313 close_chan(&lines
[i
].chan_list
);
316 int line_setup(struct line
*lines
, int num
, char *init
, int all_allowed
)
321 if(*init
== '=') n
= -1;
323 n
= simple_strtoul(init
, &end
, 0);
325 printk(KERN_ERR
"line_setup failed to parse \"%s\"\n",
332 if((n
>= 0) && (n
>= num
)){
333 printk("line_setup - %d out of range ((0 ... %d) allowed)\n",
338 if(lines
[n
].count
> 0){
339 printk("line_setup - device %d is open\n", n
);
342 if(lines
[n
].init_pri
<= INIT_ONE
){
343 lines
[n
].init_pri
= INIT_ONE
;
344 if(!strcmp(init
, "none")) lines
[n
].valid
= 0;
346 lines
[n
].init_str
= init
;
351 else if(!all_allowed
){
352 printk("line_setup - can't configure all devices from "
357 for(i
= 0; i
< num
; i
++){
358 if(lines
[i
].init_pri
<= INIT_ALL
){
359 lines
[i
].init_pri
= INIT_ALL
;
360 if(!strcmp(init
, "none")) lines
[i
].valid
= 0;
362 lines
[i
].init_str
= init
;
371 int line_config(struct line
*lines
, int num
, char *str
)
373 char *new = uml_strdup(str
);
376 printk("line_config - uml_strdup failed\n");
379 return(!line_setup(lines
, num
, new, 0));
382 int line_get_config(char *name
, struct line
*lines
, int num
, char *str
,
383 int size
, char **error_out
)
389 dev
= simple_strtoul(name
, &end
, 0);
390 if((*end
!= '\0') || (end
== name
)){
391 *error_out
= "line_get_config failed to parse device number";
395 if((dev
< 0) || (dev
>= num
)){
396 *error_out
= "device number of of range";
404 CONFIG_CHUNK(str
, size
, n
, "none", 1);
405 else if(line
->count
== 0)
406 CONFIG_CHUNK(str
, size
, n
, line
->init_str
, 1);
407 else n
= chan_config_string(&line
->chan_list
, str
, size
, error_out
);
413 int line_remove(struct line
*lines
, int num
, char *str
)
415 char config
[sizeof("conxxxx=none\0")];
417 sprintf(config
, "%s=none", str
);
418 return(!line_setup(lines
, num
, config
, 0));
421 int line_write_room(struct tty_struct
*tty
)
423 struct line
*dev
= tty
->driver_data
;
425 return(write_room(dev
));
428 struct tty_driver
*line_register_devfs(struct lines
*set
,
429 struct line_driver
*line_driver
,
430 struct tty_operations
*ops
, struct line
*lines
,
435 struct tty_driver
*driver
= alloc_tty_driver(nlines
);
440 driver
->driver_name
= line_driver
->name
;
441 driver
->name
= line_driver
->device_name
;
442 driver
->devfs_name
= line_driver
->devfs_name
;
443 driver
->major
= line_driver
->major
;
444 driver
->minor_start
= line_driver
->minor_start
;
445 driver
->type
= line_driver
->type
;
446 driver
->subtype
= line_driver
->subtype
;
447 driver
->flags
= TTY_DRIVER_REAL_RAW
;
448 driver
->init_termios
= tty_std_termios
;
449 tty_set_operations(driver
, ops
);
451 if (tty_register_driver(driver
))
452 panic("line_register_devfs : Couldn't register driver\n");
454 from
= line_driver
->symlink_from
;
455 to
= line_driver
->symlink_to
;
456 err
= devfs_mk_symlink(from
, to
);
457 if(err
) printk("Symlink creation from /dev/%s to /dev/%s "
458 "returned %d\n", from
, to
, err
);
460 for(i
= 0; i
< nlines
; i
++){
462 tty_unregister_device(driver
, i
);
465 mconsole_register_dev(&line_driver
->mc
);
469 void lines_init(struct line
*lines
, int nlines
)
474 for(i
= 0; i
< nlines
; i
++){
476 INIT_LIST_HEAD(&line
->chan_list
);
477 sema_init(&line
->sem
, 1);
478 if(line
->init_str
!= NULL
){
479 line
->init_str
= uml_strdup(line
->init_str
);
480 if(line
->init_str
== NULL
)
481 printk("lines_init - uml_strdup returned "
488 struct list_head list
;
495 irqreturn_t
winch_interrupt(int irq
, void *data
, struct pt_regs
*unused
)
497 struct winch
*winch
= data
;
498 struct tty_struct
*tty
;
503 err
= generic_read(winch
->fd
, &c
, NULL
);
506 printk("winch_interrupt : read failed, "
507 "errno = %d\n", -err
);
508 printk("fd %d is losing SIGWINCH support\n",
515 tty
= winch
->line
->tty
;
517 chan_window_size(&winch
->line
->chan_list
,
518 &tty
->winsize
.ws_row
,
519 &tty
->winsize
.ws_col
);
520 kill_pg(tty
->pgrp
, SIGWINCH
, 1);
524 reactivate_fd(winch
->fd
, WINCH_IRQ
);
528 DECLARE_MUTEX(winch_handler_sem
);
529 LIST_HEAD(winch_handlers
);
531 void register_winch_irq(int fd
, int tty_fd
, int pid
, void *line
)
535 down(&winch_handler_sem
);
536 winch
= kmalloc(sizeof(*winch
), GFP_KERNEL
);
538 printk("register_winch_irq - kmalloc failed\n");
541 *winch
= ((struct winch
) { .list
= LIST_HEAD_INIT(winch
->list
),
546 list_add(&winch
->list
, &winch_handlers
);
547 if(um_request_irq(WINCH_IRQ
, fd
, IRQ_READ
, winch_interrupt
,
548 SA_INTERRUPT
| SA_SHIRQ
| SA_SAMPLE_RANDOM
,
550 printk("register_winch_irq - failed to register IRQ\n");
552 up(&winch_handler_sem
);
555 static void winch_cleanup(void)
557 struct list_head
*ele
;
560 list_for_each(ele
, &winch_handlers
){
561 winch
= list_entry(ele
, struct winch
, list
);
563 deactivate_fd(winch
->fd
, WINCH_IRQ
);
564 os_close_file(winch
->fd
);
567 os_kill_process(winch
->pid
, 1);
571 __uml_exitcall(winch_cleanup
);
573 char *add_xterm_umid(char *base
)
579 if(umid
== NULL
) return(base
);
581 len
= strlen(base
) + strlen(" ()") + strlen(umid
) + 1;
582 title
= kmalloc(len
, GFP_KERNEL
);
584 printk("Failed to allocate buffer for xterm title\n");
588 snprintf(title
, len
, "%s (%s)", base
, umid
);
593 * Overrides for Emacs so that we follow Linus's tabbing style.
594 * Emacs will notice this stuff at the end of the file and automatically
595 * adjust the settings for this buffer only. This must remain at the end
597 * ---------------------------------------------------------------------------
599 * c-file-style: "linux"