1/*
2 *  linux/drivers/char/pdc_console.c
3 *
4 *  2001, Christoph Plattner
5 *
6 *  Driver template was linux's serial.c
7 *
8 */
9
10static char *pdc_drv_version = "0.3";
11static char *pdc_drv_revdate = "2001-11-17";
12#define AUTHOR "christoph.plattner@gmx.at"
13#include <linux/config.h>
14#include <linux/version.h>
15
16#undef PDC_DRV_DEBUG
17
18#undef SERIAL_PARANOIA_CHECK
19#define CONFIG_SERIAL_NOPAUSE_IO
20#define SERIAL_DO_RESTART
21
22#define PDC_POLL_DELAY (30 * HZ / 1000)
23
24/*
25 * End of serial driver configuration section.
26 */
27
28#include <linux/module.h>
29
30#include <linux/types.h>
31#include <linux/serial.h>
32#include <linux/serialP.h>
33#include <linux/serial_reg.h>
34#include <asm/serial.h>
35#define LOCAL_VERSTRING ""
36
37#include <linux/errno.h>
38#include <linux/signal.h>
39#include <linux/sched.h>
40#include <linux/timer.h>
41#include <linux/interrupt.h>
42#include <linux/tty.h>
43#include <linux/tty_flip.h>
44#include <linux/major.h>
45#include <linux/string.h>
46#include <linux/fcntl.h>
47#include <linux/ptrace.h>
48#include <linux/ioport.h>
49#include <linux/mm.h>
50#include <linux/slab.h>
51#include <linux/init.h>
52#include <asm/uaccess.h>
53#include <linux/delay.h>
54
55#include <asm/system.h>
56#include <asm/io.h>
57#include <asm/irq.h>
58#include <asm/bitops.h>
59
60#ifdef CONFIG_GSC
61#include <asm/gsc.h>
62#endif
63
64extern int pdc_console_poll_key(void *);
65extern void pdc_outc(unsigned char);
66
67static char *pdc_drv_name = "PDC Software Console";
68
69static struct tty_driver pdc_drv_driver;
70static int pdc_drv_refcount = 0;
71static struct async_struct *pdc_drv_info;
72
73static struct timer_list pdc_drv_timer;
74
75/* serial subtype definitions */
76#ifndef SERIAL_TYPE_NORMAL
77#define SERIAL_TYPE_NORMAL	1
78#define SERIAL_TYPE_CALLOUT	2
79#endif
80
81#define NR_PORTS 1
82#define PDC_DUMMY_BUF 2048
83
84static struct tty_struct *pdc_drv_table[NR_PORTS];
85static struct termios *pdc_drv_termios[NR_PORTS];
86static struct termios *pdc_drv_termios_locked[NR_PORTS];
87
88/*
89 * tmp_buf is used as a temporary buffer by serial_write.  We need to
90 * lock it in case the copy_from_user blocks while swapping in a page,
91 * and some other program tries to do a serial write at the same time.
92 * Since the lock will only come under contention when the system is
93 * swapping and available memory is low, it makes sense to share one
94 * buffer across all the serial ports, since it significantly saves
95 * memory if large numbers of serial ports are open.
96 */
97static unsigned char *tmp_buf;
98#ifdef DECLARE_MUTEX
99static DECLARE_MUTEX(tmp_buf_sem);
100#else
101static struct semaphore tmp_buf_sem = MUTEX;
102#endif
103
104/*
105 * ------------------------------------------------------------
106 * pdc_stop() and pdc_start()
107 *
108 * This routines are called before setting or resetting tty->stopped.
109 * They enable or disable transmitter interrupts, as necessary.
110 * ------------------------------------------------------------
111 */
112static void
113pdc_stop(struct tty_struct *tty)
114{
115}
116
117static void
118pdc_start(struct tty_struct *tty)
119{
120}
121
122/*
123 * ----------------------------------------------------------------------
124 *
125 * Here starts the interrupt handling routines.  All of the following
126 * subroutines are declared as inline and are folded into
127 * rs_interrupt().  They were separated out for readability's sake.
128 *
129 * Note: rs_interrupt() is a "fast" interrupt, which means that it
130 * runs with interrupts turned off.  People who may want to modify
131 * rs_interrupt() should try to keep the interrupt handler as fast as
132 * possible.  After you are done making modifications, it is not a bad
133 * idea to do:
134 *
135 * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
136 *
137 * and look at the resulting assemble code in serial.s.
138 *
139 * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
140 * -----------------------------------------------------------------------
141 */
142
143static void
144receive_chars(struct async_struct *info, int *status, struct pt_regs *regs)
145{
146	struct tty_struct *tty = info->tty;
147	unsigned char ch;
148	int __ch;
149
150	while (1) {
151		__ch = pdc_console_poll_key(NULL);
152
153		if (__ch == -1)	/* no character available */
154			break;
155
156		ch = (unsigned char) ((unsigned) __ch & 0x000000ffu);
157
158		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
159			continue;
160
161		*tty->flip.char_buf_ptr = ch;
162		*tty->flip.flag_buf_ptr = 0;
163
164		tty->flip.flag_buf_ptr++;
165		tty->flip.char_buf_ptr++;
166		tty->flip.count++;
167	}
168
169	tty_flip_buffer_push(tty);
170}
171
172static void
173pdc_drv_poll(unsigned long dummy)
174{
175	struct async_struct *info;
176	int status = 0;
177
178	info = pdc_drv_info;
179
180	if (!info || !info->tty || (pdc_drv_refcount == 0)) {
181		/* do nothing */
182	} else {
183		receive_chars(info, &status, NULL);
184		info->last_active = jiffies;
185	}
186
187	mod_timer(&pdc_drv_timer, jiffies + PDC_POLL_DELAY);
188}
189
190static void
191pdc_put_char(struct tty_struct *tty, unsigned char ch)
192{
193#ifdef PDC_DRV_DEBUG
194	printk(KERN_NOTICE "[%s] %c return\n", __FUNCTION__, ch);
195#endif
196	pdc_outc(ch);
197}
198
199static void
200pdc_flush_chars(struct tty_struct *tty)
201{
202	/* PCD console always flushed all characters */
203
204#ifdef PDC_DRV_DEBUG
205	printk(KERN_NOTICE "[%s] return\n", __FUNCTION__);
206#endif
207
208	/* nothing to do */
209}
210
211static int
212pdc_write(struct tty_struct *tty, int from_user,
213	  const unsigned char *buf, int count)
214{
215	char pdc_tmp_buf[PDC_DUMMY_BUF];
216	char *pdc_tmp_buf_ptr;
217	int len;
218	int ret = 0;
219
220#ifdef PDC_DRV_DEBUG
221	printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__);
222#endif
223	while (count) {
224		if (count < PDC_DUMMY_BUF)
225			len = count;
226		else
227			len = PDC_DUMMY_BUF;
228
229		if (from_user) {
230			copy_from_user(pdc_tmp_buf, buf, len);
231			pdc_tmp_buf_ptr = pdc_tmp_buf;
232		} else
233			pdc_tmp_buf_ptr = (char *) buf;
234
235		while (len) {
236			pdc_outc(*pdc_tmp_buf_ptr);
237			buf++;
238			pdc_tmp_buf_ptr++;
239			ret++;
240			count--;
241			len--;
242		}
243	}
244#ifdef PDC_DRV_DEBUG
245	printk(KERN_NOTICE "[%s] return\n", __FUNCTION__);
246#endif
247	return ret;
248}
249
250static int
251pdc_write_room(struct tty_struct *tty)
252{
253#ifdef PDC_DRV_DEBUG
254	printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__);
255#endif
256	return PDC_DUMMY_BUF;
257}
258
259static int
260pdc_chars_in_buffer(struct tty_struct *tty)
261{
262#ifdef PDC_DRV_DEBUG
263	printk(KERN_NOTICE "[%s] entry\n", __FUNCTION__);
264#endif
265	return 0;		/* no characters in buffer, always flushed ! */
266}
267
268static void
269pdc_flush_buffer(struct tty_struct *tty)
270{
271#ifdef PDC_DRV_DEBUG
272	printk(KERN_NOTICE "[%s] return\n", __FUNCTION__);
273#endif
274}
275
276/*
277 * This function is used to send a high-priority XON/XOFF character to
278 * the device
279 */
280static void
281pdc_send_xchar(struct tty_struct *tty, char ch)
282{
283}
284
285/*
286 * ------------------------------------------------------------
287 * pdc_throttle()
288 *
289 * This routine is called by the upper-layer tty layer to signal that
290 * incoming characters should be throttled.
291 * ------------------------------------------------------------
292 */
293static void
294pdc_throttle(struct tty_struct *tty)
295{
296}
297
298static void
299pdc_unthrottle(struct tty_struct *tty)
300{
301}
302
303/*
304 * ------------------------------------------------------------
305 * pdc_ioctl() and friends
306 * ------------------------------------------------------------
307 */
308
309static void
310pdc_break(struct tty_struct *tty, int break_state)
311{
312}
313
314static int
315get_serial_info(struct async_struct * info,
316                           struct serial_struct * retinfo)
317{
318	struct serial_struct tmp;
319
320	if (!retinfo)
321		return -EFAULT;
322	memset(&tmp, 0, sizeof(tmp));
323	tmp.line = info->line;
324	tmp.port = info->line;
325	tmp.flags = info->flags;
326	tmp.close_delay = info->close_delay;
327	return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0;
328}
329
330static int get_modem_info(struct async_struct * info, unsigned int *value)
331{
332	unsigned int result = TIOCM_DTR|TIOCM_CAR|TIOCM_CTS|TIOCM_RTS;
333
334	return copy_to_user(value, &result, sizeof(int)) ? -EFAULT : 0;
335}
336
337static int get_lsr_info(struct async_struct * info, unsigned int *value)
338{
339	unsigned int result = TIOCSER_TEMT;
340
341	return copy_to_user(value, &result, sizeof(int)) ? -EFAULT : 0;
342}
343
344static int
345pdc_ioctl(struct tty_struct *tty, struct file *file,
346	  unsigned int cmd, unsigned long arg)
347{
348	struct async_struct *info = (struct async_struct *) tty->driver_data;
349
350	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
351	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
352	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
353		if (tty->flags & (1 << TTY_IO_ERROR))
354			return -EIO;
355	}
356
357	switch (cmd) {
358	case TIOCMGET:
359		return get_modem_info(info, (unsigned int *) arg);
360	case TIOCMBIS:
361	case TIOCMBIC:
362	case TIOCMSET:
363		return 0;
364	case TIOCGSERIAL:
365		return get_serial_info(info, (struct serial_struct *) arg);
366	case TIOCSSERIAL:
367		return 0;
368	case TIOCSERCONFIG:
369		return 0;
370
371	case TIOCSERGETLSR:	/* Get line status register */
372		return get_lsr_info(info, (unsigned int *) arg);
373
374	case TIOCSERGSTRUCT:
375		if (copy_to_user((struct async_struct *) arg,
376				 info, sizeof (struct async_struct)))
377			return -EFAULT;
378		return 0;
379
380	case TIOCMIWAIT:
381		return 0;
382
383	case TIOCGICOUNT:
384		return 0;
385	case TIOCSERGWILD:
386	case TIOCSERSWILD:
387		/* "setserial -W" is called in Debian boot */
388		printk("TIOCSER?WILD ioctl obsolete, ignored.\n");
389		return 0;
390
391	default:
392		return -ENOIOCTLCMD;
393	}
394	return 0;
395}
396
397static void
398pdc_set_termios(struct tty_struct *tty, struct termios *old_termios)
399{
400
401}
402
403/*
404 * ------------------------------------------------------------
405 * pdc_close()
406 *
407 * This routine is called when the serial port gets closed.  First, we
408 * wait for the last remaining data to be sent.  Then, we unlink its
409 * async structure from the interrupt chain if necessary, and we free
410 * that IRQ if nothing is left in the chain.
411 * ------------------------------------------------------------
412 */
413static void
414pdc_close(struct tty_struct *tty, struct file *filp)
415{
416	struct async_struct *info = (struct async_struct *) tty->driver_data;
417
418#ifdef PDC_DEBUG_OPEN
419	printk("pdc_close ttyB%d, count = %d\n", info->line, state->count);
420#endif
421	pdc_drv_refcount--;
422	if (pdc_drv_refcount > 0)
423		return;
424
425	info->flags |= ASYNC_CLOSING;
426
427	/*
428	 * Save the termios structure, since this port may have
429	 * separate termios for callout and dialin.
430	 */
431	if (info->flags & ASYNC_NORMAL_ACTIVE)
432		info->state->normal_termios = *tty->termios;
433	if (info->flags & ASYNC_CALLOUT_ACTIVE)
434		info->state->callout_termios = *tty->termios;
435
436	/*
437	 * At this point we stop accepting input.  To do this, we
438	 * disable the receive line status interrupts, and tell the
439	 * interrupt driver to stop checking the data ready bit in the
440	 * line status register.
441	 */
442
443
444	if (tty->driver.flush_buffer)
445		tty->driver.flush_buffer(tty);
446	if (tty->ldisc.flush_buffer)
447		tty->ldisc.flush_buffer(tty);
448	tty->closing = 0;
449	info->event = 0;
450	info->tty = 0;
451	pdc_drv_info = NULL;
452	if (info->blocked_open) {
453		if (info->close_delay) {
454			set_current_state(TASK_INTERRUPTIBLE);
455			schedule_timeout(info->close_delay);
456		}
457		wake_up_interruptible(&info->open_wait);
458	}
459	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE |
460			 ASYNC_CLOSING);
461	wake_up_interruptible(&info->close_wait);
462	MOD_DEC_USE_COUNT;
463}
464
465/*
466 * pdc_wait_until_sent() --- wait until the transmitter is empty
467 */
468static void
469pdc_wait_until_sent(struct tty_struct *tty, int timeout)
470{
471	/* we always send immideate */
472}
473
474/*
475 * pdc_hangup() --- called by tty_hangup() when a hangup is signaled.
476 */
477static void
478pdc_hangup(struct tty_struct *tty)
479{
480}
481
482/*
483 * ------------------------------------------------------------
484 * pdc_open() and friends
485 * ------------------------------------------------------------
486 */
487
488static int
489get_async_struct(int line, struct async_struct **ret_info)
490{
491	struct async_struct *info;
492
493	info = kmalloc(sizeof (struct async_struct), GFP_KERNEL);
494	if (!info) {
495		return -ENOMEM;
496	}
497	memset(info, 0, sizeof (struct async_struct));
498	init_waitqueue_head(&info->open_wait);
499	init_waitqueue_head(&info->close_wait);
500	init_waitqueue_head(&info->delta_msr_wait);
501	info->magic = SERIAL_MAGIC;
502	info->port = 0;
503	info->flags = 0;
504	info->io_type = 0;
505	info->iomem_base = 0;
506	info->iomem_reg_shift = 0;
507	info->xmit_fifo_size = PDC_DUMMY_BUF;
508	info->line = line;
509	info->tqueue.routine = NULL;
510	info->tqueue.data = info;
511	info->state = NULL;
512	*ret_info = info;
513	return 0;
514}
515
516/*
517 * This routine is called whenever a serial port is opened.  It
518 * enables interrupts for a serial port, linking in its async structure into
519 * the IRQ chain.   It also performs the serial-specific
520 * initialization for the tty structure.
521 */
522static int
523pdc_open(struct tty_struct *tty, struct file *filp)
524{
525	struct async_struct *info;
526	int retval, line;
527	unsigned long page;
528
529	MOD_INC_USE_COUNT;
530	line = MINOR(tty->device) - tty->driver.minor_start;
531	if ((line < 0) || (line >= NR_PORTS)) {
532		MOD_DEC_USE_COUNT;
533		return -ENODEV;
534	}
535	retval = get_async_struct(line, &info);
536	if (retval) {
537		MOD_DEC_USE_COUNT;
538		return retval;
539	}
540	tty->driver_data = info;
541	info->tty = tty;
542	pdc_drv_info = info;
543
544#ifdef PDC_DEBUG_OPEN
545	printk("pdc_open %s%d, count = %d\n", tty->driver.name, info->line,
546	       info->state->count);
547#endif
548	info->tty->low_latency = 0;
549	if (!tmp_buf) {
550		page = get_zeroed_page(GFP_KERNEL);
551		if (!page) {
552			MOD_DEC_USE_COUNT;
553			return -ENOMEM;
554		}
555		if (tmp_buf)
556			free_page(page);
557		else
558			tmp_buf = (unsigned char *) page;
559	}
560
561	info->session = current->session;
562	info->pgrp = current->pgrp;
563
564#ifdef PDC_DEBUG_OPEN
565	printk("pdc_open ttyB%d successful...", info->line);
566#endif
567	pdc_drv_refcount++;
568	return 0;
569}
570
571/*
572 * ---------------------------------------------------------------------
573 * pdc_init() and friends
574 *
575 * pdc_init() is called at boot-time to initialize the pdc driver.
576 * ---------------------------------------------------------------------
577 */
578
579static void
580show_pdc_drv_version(void)
581{
582	printk(KERN_INFO "%s version %s%s (%s), %s\n", pdc_drv_name,
583	       pdc_drv_version, LOCAL_VERSTRING, pdc_drv_revdate, AUTHOR);
584}
585
586/*
587 * The serial driver boot-time initialization code!
588 */
589static int __init
590pdc_drv_init(void)
591{
592	init_timer(&pdc_drv_timer);
593	pdc_drv_timer.function = pdc_drv_poll;
594	mod_timer(&pdc_drv_timer, jiffies + PDC_POLL_DELAY);
595
596	show_pdc_drv_version();
597
598	/* Initialize the tty_driver structure */
599
600	memset(&pdc_drv_driver, 0, sizeof (struct tty_driver));
601	pdc_drv_driver.magic = TTY_DRIVER_MAGIC;
602	pdc_drv_driver.driver_name = "pdc_console";
603#ifdef CONFIG_DEVFS_FS
604	pdc_drv_driver.name = "ttb/%d";
605#else
606	pdc_drv_driver.name = "ttyB";
607#endif
608	pdc_drv_driver.major = PDCCONS_MAJOR;
609	pdc_drv_driver.minor_start = 0;
610	pdc_drv_driver.num = NR_PORTS;
611	pdc_drv_driver.type = TTY_DRIVER_TYPE_SERIAL;
612	pdc_drv_driver.subtype = SERIAL_TYPE_NORMAL;
613	pdc_drv_driver.init_termios = tty_std_termios;
614	pdc_drv_driver.init_termios.c_cflag =
615	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
616	pdc_drv_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
617	pdc_drv_driver.refcount = &pdc_drv_refcount;
618	pdc_drv_driver.table = pdc_drv_table;
619	pdc_drv_driver.termios = pdc_drv_termios;
620	pdc_drv_driver.termios_locked = pdc_drv_termios_locked;
621
622	pdc_drv_driver.open = pdc_open;
623	pdc_drv_driver.close = pdc_close;
624	pdc_drv_driver.write = pdc_write;
625	pdc_drv_driver.put_char = pdc_put_char;
626	pdc_drv_driver.flush_chars = pdc_flush_chars;
627	pdc_drv_driver.write_room = pdc_write_room;
628	pdc_drv_driver.chars_in_buffer = pdc_chars_in_buffer;
629	pdc_drv_driver.flush_buffer = pdc_flush_buffer;
630	pdc_drv_driver.ioctl = pdc_ioctl;
631	pdc_drv_driver.throttle = pdc_throttle;
632	pdc_drv_driver.unthrottle = pdc_unthrottle;
633	pdc_drv_driver.set_termios = pdc_set_termios;
634	pdc_drv_driver.stop = pdc_stop;
635	pdc_drv_driver.start = pdc_start;
636	pdc_drv_driver.hangup = pdc_hangup;
637	pdc_drv_driver.break_ctl = pdc_break;
638	pdc_drv_driver.send_xchar = pdc_send_xchar;
639	pdc_drv_driver.wait_until_sent = pdc_wait_until_sent;
640	pdc_drv_driver.read_proc = NULL;
641
642	if (tty_register_driver(&pdc_drv_driver))
643		panic("Couldn't register pdc_console driver\n");
644
645	return 0;
646}
647
648static void __exit
649pdc_fini(void)
650{
651	int e1;
652
653	if ((e1 = tty_unregister_driver(&pdc_drv_driver)))
654		printk("pdc_console: failed to unregister pdc_drv driver (%d)\n",
655		       e1);
656}
657
658module_init(pdc_drv_init);
659module_exit(pdc_fini);
660MODULE_DESCRIPTION("PDC Software Console");
661MODULE_AUTHOR(AUTHOR);
662