PageRenderTime 97ms CodeModel.GetById 13ms app.highlight 76ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/ia64/hp/sim/simserial.c

https://bitbucket.org/evzijst/gittest
C | 1032 lines | 689 code | 150 blank | 193 comment | 137 complexity | 55e9cbad67c75557c82b5a8a45d2de19 MD5 | raw file
   1/*
   2 * Simulated Serial Driver (fake serial)
   3 *
   4 * This driver is mostly used for bringup purposes and will go away.
   5 * It has a strong dependency on the system console. All outputs
   6 * are rerouted to the same facility as the one used by printk which, in our
   7 * case means sys_sim.c console (goes via the simulator). The code hereafter
   8 * is completely leveraged from the serial.c driver.
   9 *
  10 * Copyright (C) 1999-2000, 2002-2003 Hewlett-Packard Co
  11 *	Stephane Eranian <eranian@hpl.hp.com>
  12 *	David Mosberger-Tang <davidm@hpl.hp.com>
  13 *
  14 * 02/04/00 D. Mosberger	Merged in serial.c bug fixes in rs_close().
  15 * 02/25/00 D. Mosberger	Synced up with 2.3.99pre-5 version of serial.c.
  16 * 07/30/02 D. Mosberger	Replace sti()/cli() with explicit spinlocks & local irq masking
  17 */
  18
  19#include <linux/config.h>
  20#include <linux/init.h>
  21#include <linux/errno.h>
  22#include <linux/sched.h>
  23#include <linux/tty.h>
  24#include <linux/tty_flip.h>
  25#include <linux/major.h>
  26#include <linux/fcntl.h>
  27#include <linux/mm.h>
  28#include <linux/slab.h>
  29#include <linux/console.h>
  30#include <linux/module.h>
  31#include <linux/serial.h>
  32#include <linux/serialP.h>
  33
  34#include <asm/irq.h>
  35#include <asm/hw_irq.h>
  36#include <asm/uaccess.h>
  37
  38#ifdef CONFIG_KDB
  39# include <linux/kdb.h>
  40#endif
  41
  42#undef SIMSERIAL_DEBUG	/* define this to get some debug information */
  43
  44#define KEYBOARD_INTR	3	/* must match with simulator! */
  45
  46#define NR_PORTS	1	/* only one port for now */
  47#define SERIAL_INLINE	1
  48
  49#ifdef SERIAL_INLINE
  50#define _INLINE_ inline
  51#endif
  52
  53#define IRQ_T(info) ((info->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT)
  54
  55#define SSC_GETCHAR	21
  56
  57extern long ia64_ssc (long, long, long, long, int);
  58extern void ia64_ssc_connect_irq (long intr, long irq);
  59
  60static char *serial_name = "SimSerial driver";
  61static char *serial_version = "0.6";
  62
  63/*
  64 * This has been extracted from asm/serial.h. We need one eventually but
  65 * I don't know exactly what we're going to put in it so just fake one
  66 * for now.
  67 */
  68#define BASE_BAUD ( 1843200 / 16 )
  69
  70#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
  71
  72/*
  73 * Most of the values here are meaningless to this particular driver.
  74 * However some values must be preserved for the code (leveraged from serial.c
  75 * to work correctly).
  76 * port must not be 0
  77 * type must not be UNKNOWN
  78 * So I picked arbitrary (guess from where?) values instead
  79 */
  80static struct serial_state rs_table[NR_PORTS]={
  81  /* UART CLK   PORT IRQ     FLAGS        */
  82  { 0, BASE_BAUD, 0x3F8, 0, STD_COM_FLAGS,0,PORT_16550 }  /* ttyS0 */
  83};
  84
  85/*
  86 * Just for the fun of it !
  87 */
  88static struct serial_uart_config uart_config[] = {
  89	{ "unknown", 1, 0 },
  90	{ "8250", 1, 0 },
  91	{ "16450", 1, 0 },
  92	{ "16550", 1, 0 },
  93	{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO },
  94	{ "cirrus", 1, 0 },
  95	{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH },
  96	{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
  97		  UART_STARTECH },
  98	{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
  99	{ 0, 0}
 100};
 101
 102struct tty_driver *hp_simserial_driver;
 103
 104static struct async_struct *IRQ_ports[NR_IRQS];
 105
 106static struct console *console;
 107
 108static unsigned char *tmp_buf;
 109static DECLARE_MUTEX(tmp_buf_sem);
 110
 111extern struct console *console_drivers; /* from kernel/printk.c */
 112
 113/*
 114 * ------------------------------------------------------------
 115 * rs_stop() and rs_start()
 116 *
 117 * This routines are called before setting or resetting tty->stopped.
 118 * They enable or disable transmitter interrupts, as necessary.
 119 * ------------------------------------------------------------
 120 */
 121static void rs_stop(struct tty_struct *tty)
 122{
 123#ifdef SIMSERIAL_DEBUG
 124	printk("rs_stop: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n",
 125		tty->stopped, tty->hw_stopped, tty->flow_stopped);
 126#endif
 127
 128}
 129
 130static void rs_start(struct tty_struct *tty)
 131{
 132#if SIMSERIAL_DEBUG
 133	printk("rs_start: tty->stopped=%d tty->hw_stopped=%d tty->flow_stopped=%d\n",
 134		tty->stopped, tty->hw_stopped, tty->flow_stopped);
 135#endif
 136}
 137
 138static  void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
 139{
 140	unsigned char ch;
 141	static unsigned char seen_esc = 0;
 142
 143	while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) {
 144		if ( ch == 27 && seen_esc == 0 ) {
 145			seen_esc = 1;
 146			continue;
 147		} else {
 148			if ( seen_esc==1 && ch == 'O' ) {
 149				seen_esc = 2;
 150				continue;
 151			} else if ( seen_esc == 2 ) {
 152				if ( ch == 'P' ) show_state();		/* F1 key */
 153#ifdef CONFIG_KDB
 154				if ( ch == 'S' )
 155					kdb(KDB_REASON_KEYBOARD, 0, (kdb_eframe_t) regs);
 156#endif
 157
 158				seen_esc = 0;
 159				continue;
 160			}
 161		}
 162		seen_esc = 0;
 163		if (tty->flip.count >= TTY_FLIPBUF_SIZE) break;
 164
 165		*tty->flip.char_buf_ptr = ch;
 166
 167		*tty->flip.flag_buf_ptr = 0;
 168
 169		tty->flip.flag_buf_ptr++;
 170		tty->flip.char_buf_ptr++;
 171		tty->flip.count++;
 172	}
 173	tty_flip_buffer_push(tty);
 174}
 175
 176/*
 177 * This is the serial driver's interrupt routine for a single port
 178 */
 179static irqreturn_t rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs)
 180{
 181	struct async_struct * info;
 182
 183	/*
 184	 * I don't know exactly why they don't use the dev_id opaque data
 185	 * pointer instead of this extra lookup table
 186	 */
 187	info = IRQ_ports[irq];
 188	if (!info || !info->tty) {
 189		printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info);
 190		return IRQ_NONE;
 191	}
 192	/*
 193	 * pretty simple in our case, because we only get interrupts
 194	 * on inbound traffic
 195	 */
 196	receive_chars(info->tty, regs);
 197	return IRQ_HANDLED;
 198}
 199
 200/*
 201 * -------------------------------------------------------------------
 202 * Here ends the serial interrupt routines.
 203 * -------------------------------------------------------------------
 204 */
 205
 206#if 0
 207/*
 208 * not really used in our situation so keep them commented out for now
 209 */
 210static DECLARE_TASK_QUEUE(tq_serial); /* used to be at the top of the file */
 211static void do_serial_bh(void)
 212{
 213	run_task_queue(&tq_serial);
 214	printk(KERN_ERR "do_serial_bh: called\n");
 215}
 216#endif
 217
 218static void do_softint(void *private_)
 219{
 220	printk(KERN_ERR "simserial: do_softint called\n");
 221}
 222
 223static void rs_put_char(struct tty_struct *tty, unsigned char ch)
 224{
 225	struct async_struct *info = (struct async_struct *)tty->driver_data;
 226	unsigned long flags;
 227
 228	if (!tty || !info->xmit.buf) return;
 229
 230	local_irq_save(flags);
 231	if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
 232		local_irq_restore(flags);
 233		return;
 234	}
 235	info->xmit.buf[info->xmit.head] = ch;
 236	info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
 237	local_irq_restore(flags);
 238}
 239
 240static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
 241{
 242	int count;
 243	unsigned long flags;
 244
 245
 246	local_irq_save(flags);
 247
 248	if (info->x_char) {
 249		char c = info->x_char;
 250
 251		console->write(console, &c, 1);
 252
 253		info->state->icount.tx++;
 254		info->x_char = 0;
 255
 256		goto out;
 257	}
 258
 259	if (info->xmit.head == info->xmit.tail || info->tty->stopped || info->tty->hw_stopped) {
 260#ifdef SIMSERIAL_DEBUG
 261		printk("transmit_chars: head=%d, tail=%d, stopped=%d\n",
 262		       info->xmit.head, info->xmit.tail, info->tty->stopped);
 263#endif
 264		goto out;
 265	}
 266	/*
 267	 * We removed the loop and try to do it in to chunks. We need
 268	 * 2 operations maximum because it's a ring buffer.
 269	 *
 270	 * First from current to tail if possible.
 271	 * Then from the beginning of the buffer until necessary
 272	 */
 273
 274	count = min(CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE),
 275		    SERIAL_XMIT_SIZE - info->xmit.tail);
 276	console->write(console, info->xmit.buf+info->xmit.tail, count);
 277
 278	info->xmit.tail = (info->xmit.tail+count) & (SERIAL_XMIT_SIZE-1);
 279
 280	/*
 281	 * We have more at the beginning of the buffer
 282	 */
 283	count = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
 284	if (count) {
 285		console->write(console, info->xmit.buf, count);
 286		info->xmit.tail += count;
 287	}
 288out:
 289	local_irq_restore(flags);
 290}
 291
 292static void rs_flush_chars(struct tty_struct *tty)
 293{
 294	struct async_struct *info = (struct async_struct *)tty->driver_data;
 295
 296	if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped ||
 297	    !info->xmit.buf)
 298		return;
 299
 300	transmit_chars(info, NULL);
 301}
 302
 303
 304static int rs_write(struct tty_struct * tty,
 305		    const unsigned char *buf, int count)
 306{
 307	int	c, ret = 0;
 308	struct async_struct *info = (struct async_struct *)tty->driver_data;
 309	unsigned long flags;
 310
 311	if (!tty || !info->xmit.buf || !tmp_buf) return 0;
 312
 313	local_irq_save(flags);
 314	while (1) {
 315		c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
 316		if (count < c)
 317			c = count;
 318		if (c <= 0) {
 319			break;
 320		}
 321		memcpy(info->xmit.buf + info->xmit.head, buf, c);
 322		info->xmit.head = ((info->xmit.head + c) &
 323				   (SERIAL_XMIT_SIZE-1));
 324		buf += c;
 325		count -= c;
 326		ret += c;
 327	}
 328	local_irq_restore(flags);
 329	/*
 330	 * Hey, we transmit directly from here in our case
 331	 */
 332	if (CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE)
 333	    && !tty->stopped && !tty->hw_stopped) {
 334		transmit_chars(info, NULL);
 335	}
 336	return ret;
 337}
 338
 339static int rs_write_room(struct tty_struct *tty)
 340{
 341	struct async_struct *info = (struct async_struct *)tty->driver_data;
 342
 343	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
 344}
 345
 346static int rs_chars_in_buffer(struct tty_struct *tty)
 347{
 348	struct async_struct *info = (struct async_struct *)tty->driver_data;
 349
 350	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
 351}
 352
 353static void rs_flush_buffer(struct tty_struct *tty)
 354{
 355	struct async_struct *info = (struct async_struct *)tty->driver_data;
 356	unsigned long flags;
 357
 358	local_irq_save(flags);
 359	info->xmit.head = info->xmit.tail = 0;
 360	local_irq_restore(flags);
 361
 362	wake_up_interruptible(&tty->write_wait);
 363
 364	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
 365	    tty->ldisc.write_wakeup)
 366		(tty->ldisc.write_wakeup)(tty);
 367}
 368
 369/*
 370 * This function is used to send a high-priority XON/XOFF character to
 371 * the device
 372 */
 373static void rs_send_xchar(struct tty_struct *tty, char ch)
 374{
 375	struct async_struct *info = (struct async_struct *)tty->driver_data;
 376
 377	info->x_char = ch;
 378	if (ch) {
 379		/*
 380		 * I guess we could call console->write() directly but
 381		 * let's do that for now.
 382		 */
 383		transmit_chars(info, NULL);
 384	}
 385}
 386
 387/*
 388 * ------------------------------------------------------------
 389 * rs_throttle()
 390 *
 391 * This routine is called by the upper-layer tty layer to signal that
 392 * incoming characters should be throttled.
 393 * ------------------------------------------------------------
 394 */
 395static void rs_throttle(struct tty_struct * tty)
 396{
 397	if (I_IXOFF(tty)) rs_send_xchar(tty, STOP_CHAR(tty));
 398
 399	printk(KERN_INFO "simrs_throttle called\n");
 400}
 401
 402static void rs_unthrottle(struct tty_struct * tty)
 403{
 404	struct async_struct *info = (struct async_struct *)tty->driver_data;
 405
 406	if (I_IXOFF(tty)) {
 407		if (info->x_char)
 408			info->x_char = 0;
 409		else
 410			rs_send_xchar(tty, START_CHAR(tty));
 411	}
 412	printk(KERN_INFO "simrs_unthrottle called\n");
 413}
 414
 415/*
 416 * rs_break() --- routine which turns the break handling on or off
 417 */
 418static void rs_break(struct tty_struct *tty, int break_state)
 419{
 420}
 421
 422static int rs_ioctl(struct tty_struct *tty, struct file * file,
 423		    unsigned int cmd, unsigned long arg)
 424{
 425	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 426	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
 427	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
 428		if (tty->flags & (1 << TTY_IO_ERROR))
 429		    return -EIO;
 430	}
 431
 432	switch (cmd) {
 433		case TIOCMGET:
 434			printk(KERN_INFO "rs_ioctl: TIOCMGET called\n");
 435			return -EINVAL;
 436		case TIOCMBIS:
 437		case TIOCMBIC:
 438		case TIOCMSET:
 439			printk(KERN_INFO "rs_ioctl: TIOCMBIS/BIC/SET called\n");
 440			return -EINVAL;
 441		case TIOCGSERIAL:
 442			printk(KERN_INFO "simrs_ioctl TIOCGSERIAL called\n");
 443			return 0;
 444		case TIOCSSERIAL:
 445			printk(KERN_INFO "simrs_ioctl TIOCSSERIAL called\n");
 446			return 0;
 447		case TIOCSERCONFIG:
 448			printk(KERN_INFO "rs_ioctl: TIOCSERCONFIG called\n");
 449			return -EINVAL;
 450
 451		case TIOCSERGETLSR: /* Get line status register */
 452			printk(KERN_INFO "rs_ioctl: TIOCSERGETLSR called\n");
 453			return  -EINVAL;
 454
 455		case TIOCSERGSTRUCT:
 456			printk(KERN_INFO "rs_ioctl: TIOCSERGSTRUCT called\n");
 457#if 0
 458			if (copy_to_user((struct async_struct *) arg,
 459					 info, sizeof(struct async_struct)))
 460				return -EFAULT;
 461#endif
 462			return 0;
 463
 464		/*
 465		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
 466		 * - mask passed in arg for lines of interest
 467		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
 468		 * Caller should use TIOCGICOUNT to see which one it was
 469		 */
 470		case TIOCMIWAIT:
 471			printk(KERN_INFO "rs_ioctl: TIOCMIWAIT: called\n");
 472			return 0;
 473		/*
 474		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
 475		 * Return: write counters to the user passed counter struct
 476		 * NB: both 1->0 and 0->1 transitions are counted except for
 477		 *     RI where only 0->1 is counted.
 478		 */
 479		case TIOCGICOUNT:
 480			printk(KERN_INFO "rs_ioctl: TIOCGICOUNT called\n");
 481			return 0;
 482
 483		case TIOCSERGWILD:
 484		case TIOCSERSWILD:
 485			/* "setserial -W" is called in Debian boot */
 486			printk (KERN_INFO "TIOCSER?WILD ioctl obsolete, ignored.\n");
 487			return 0;
 488
 489		default:
 490			return -ENOIOCTLCMD;
 491		}
 492	return 0;
 493}
 494
 495#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
 496
 497static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
 498{
 499	unsigned int cflag = tty->termios->c_cflag;
 500
 501	if (   (cflag == old_termios->c_cflag)
 502	    && (   RELEVANT_IFLAG(tty->termios->c_iflag)
 503		== RELEVANT_IFLAG(old_termios->c_iflag)))
 504	  return;
 505
 506
 507	/* Handle turning off CRTSCTS */
 508	if ((old_termios->c_cflag & CRTSCTS) &&
 509	    !(tty->termios->c_cflag & CRTSCTS)) {
 510		tty->hw_stopped = 0;
 511		rs_start(tty);
 512	}
 513}
 514/*
 515 * This routine will shutdown a serial port; interrupts are disabled, and
 516 * DTR is dropped if the hangup on close termio flag is on.
 517 */
 518static void shutdown(struct async_struct * info)
 519{
 520	unsigned long	flags;
 521	struct serial_state *state;
 522	int		retval;
 523
 524	if (!(info->flags & ASYNC_INITIALIZED)) return;
 525
 526	state = info->state;
 527
 528#ifdef SIMSERIAL_DEBUG
 529	printk("Shutting down serial port %d (irq %d)....", info->line,
 530	       state->irq);
 531#endif
 532
 533	local_irq_save(flags);
 534	{
 535		/*
 536		 * First unlink the serial port from the IRQ chain...
 537		 */
 538		if (info->next_port)
 539			info->next_port->prev_port = info->prev_port;
 540		if (info->prev_port)
 541			info->prev_port->next_port = info->next_port;
 542		else
 543			IRQ_ports[state->irq] = info->next_port;
 544
 545		/*
 546		 * Free the IRQ, if necessary
 547		 */
 548		if (state->irq && (!IRQ_ports[state->irq] ||
 549				   !IRQ_ports[state->irq]->next_port)) {
 550			if (IRQ_ports[state->irq]) {
 551				free_irq(state->irq, NULL);
 552				retval = request_irq(state->irq, rs_interrupt_single,
 553						     IRQ_T(info), "serial", NULL);
 554
 555				if (retval)
 556					printk(KERN_ERR "serial shutdown: request_irq: error %d"
 557					       "  Couldn't reacquire IRQ.\n", retval);
 558			} else
 559				free_irq(state->irq, NULL);
 560		}
 561
 562		if (info->xmit.buf) {
 563			free_page((unsigned long) info->xmit.buf);
 564			info->xmit.buf = 0;
 565		}
 566
 567		if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
 568
 569		info->flags &= ~ASYNC_INITIALIZED;
 570	}
 571	local_irq_restore(flags);
 572}
 573
 574/*
 575 * ------------------------------------------------------------
 576 * rs_close()
 577 *
 578 * This routine is called when the serial port gets closed.  First, we
 579 * wait for the last remaining data to be sent.  Then, we unlink its
 580 * async structure from the interrupt chain if necessary, and we free
 581 * that IRQ if nothing is left in the chain.
 582 * ------------------------------------------------------------
 583 */
 584static void rs_close(struct tty_struct *tty, struct file * filp)
 585{
 586	struct async_struct * info = (struct async_struct *)tty->driver_data;
 587	struct serial_state *state;
 588	unsigned long flags;
 589
 590	if (!info ) return;
 591
 592	state = info->state;
 593
 594	local_irq_save(flags);
 595	if (tty_hung_up_p(filp)) {
 596#ifdef SIMSERIAL_DEBUG
 597		printk("rs_close: hung_up\n");
 598#endif
 599		local_irq_restore(flags);
 600		return;
 601	}
 602#ifdef SIMSERIAL_DEBUG
 603	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
 604#endif
 605	if ((tty->count == 1) && (state->count != 1)) {
 606		/*
 607		 * Uh, oh.  tty->count is 1, which means that the tty
 608		 * structure will be freed.  state->count should always
 609		 * be one in these conditions.  If it's greater than
 610		 * one, we've got real problems, since it means the
 611		 * serial port won't be shutdown.
 612		 */
 613		printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, "
 614		       "state->count is %d\n", state->count);
 615		state->count = 1;
 616	}
 617	if (--state->count < 0) {
 618		printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n",
 619		       info->line, state->count);
 620		state->count = 0;
 621	}
 622	if (state->count) {
 623		local_irq_restore(flags);
 624		return;
 625	}
 626	info->flags |= ASYNC_CLOSING;
 627	local_irq_restore(flags);
 628
 629	/*
 630	 * Now we wait for the transmit buffer to clear; and we notify
 631	 * the line discipline to only process XON/XOFF characters.
 632	 */
 633	shutdown(info);
 634	if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty);
 635	if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty);
 636	info->event = 0;
 637	info->tty = 0;
 638	if (info->blocked_open) {
 639		if (info->close_delay) {
 640			current->state = TASK_INTERRUPTIBLE;
 641			schedule_timeout(info->close_delay);
 642		}
 643		wake_up_interruptible(&info->open_wait);
 644	}
 645	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 646	wake_up_interruptible(&info->close_wait);
 647}
 648
 649/*
 650 * rs_wait_until_sent() --- wait until the transmitter is empty
 651 */
 652static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
 653{
 654}
 655
 656
 657/*
 658 * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
 659 */
 660static void rs_hangup(struct tty_struct *tty)
 661{
 662	struct async_struct * info = (struct async_struct *)tty->driver_data;
 663	struct serial_state *state = info->state;
 664
 665#ifdef SIMSERIAL_DEBUG
 666	printk("rs_hangup: called\n");
 667#endif
 668
 669	state = info->state;
 670
 671	rs_flush_buffer(tty);
 672	if (info->flags & ASYNC_CLOSING)
 673		return;
 674	shutdown(info);
 675
 676	info->event = 0;
 677	state->count = 0;
 678	info->flags &= ~ASYNC_NORMAL_ACTIVE;
 679	info->tty = 0;
 680	wake_up_interruptible(&info->open_wait);
 681}
 682
 683
 684static int get_async_struct(int line, struct async_struct **ret_info)
 685{
 686	struct async_struct *info;
 687	struct serial_state *sstate;
 688
 689	sstate = rs_table + line;
 690	sstate->count++;
 691	if (sstate->info) {
 692		*ret_info = sstate->info;
 693		return 0;
 694	}
 695	info = kmalloc(sizeof(struct async_struct), GFP_KERNEL);
 696	if (!info) {
 697		sstate->count--;
 698		return -ENOMEM;
 699	}
 700	memset(info, 0, sizeof(struct async_struct));
 701	init_waitqueue_head(&info->open_wait);
 702	init_waitqueue_head(&info->close_wait);
 703	init_waitqueue_head(&info->delta_msr_wait);
 704	info->magic = SERIAL_MAGIC;
 705	info->port = sstate->port;
 706	info->flags = sstate->flags;
 707	info->xmit_fifo_size = sstate->xmit_fifo_size;
 708	info->line = line;
 709	INIT_WORK(&info->work, do_softint, info);
 710	info->state = sstate;
 711	if (sstate->info) {
 712		kfree(info);
 713		*ret_info = sstate->info;
 714		return 0;
 715	}
 716	*ret_info = sstate->info = info;
 717	return 0;
 718}
 719
 720static int
 721startup(struct async_struct *info)
 722{
 723	unsigned long flags;
 724	int	retval=0;
 725	irqreturn_t (*handler)(int, void *, struct pt_regs *);
 726	struct serial_state *state= info->state;
 727	unsigned long page;
 728
 729	page = get_zeroed_page(GFP_KERNEL);
 730	if (!page)
 731		return -ENOMEM;
 732
 733	local_irq_save(flags);
 734
 735	if (info->flags & ASYNC_INITIALIZED) {
 736		free_page(page);
 737		goto errout;
 738	}
 739
 740	if (!state->port || !state->type) {
 741		if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
 742		free_page(page);
 743		goto errout;
 744	}
 745	if (info->xmit.buf)
 746		free_page(page);
 747	else
 748		info->xmit.buf = (unsigned char *) page;
 749
 750#ifdef SIMSERIAL_DEBUG
 751	printk("startup: ttys%d (irq %d)...", info->line, state->irq);
 752#endif
 753
 754	/*
 755	 * Allocate the IRQ if necessary
 756	 */
 757	if (state->irq && (!IRQ_ports[state->irq] ||
 758			  !IRQ_ports[state->irq]->next_port)) {
 759		if (IRQ_ports[state->irq]) {
 760			retval = -EBUSY;
 761			goto errout;
 762		} else
 763			handler = rs_interrupt_single;
 764
 765		retval = request_irq(state->irq, handler, IRQ_T(info), "simserial", NULL);
 766		if (retval) {
 767			if (capable(CAP_SYS_ADMIN)) {
 768				if (info->tty)
 769					set_bit(TTY_IO_ERROR,
 770						&info->tty->flags);
 771				retval = 0;
 772			}
 773			goto errout;
 774		}
 775	}
 776
 777	/*
 778	 * Insert serial port into IRQ chain.
 779	 */
 780	info->prev_port = 0;
 781	info->next_port = IRQ_ports[state->irq];
 782	if (info->next_port)
 783		info->next_port->prev_port = info;
 784	IRQ_ports[state->irq] = info;
 785
 786	if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags);
 787
 788	info->xmit.head = info->xmit.tail = 0;
 789
 790#if 0
 791	/*
 792	 * Set up serial timers...
 793	 */
 794	timer_table[RS_TIMER].expires = jiffies + 2*HZ/100;
 795	timer_active |= 1 << RS_TIMER;
 796#endif
 797
 798	/*
 799	 * Set up the tty->alt_speed kludge
 800	 */
 801	if (info->tty) {
 802		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
 803			info->tty->alt_speed = 57600;
 804		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
 805			info->tty->alt_speed = 115200;
 806		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
 807			info->tty->alt_speed = 230400;
 808		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
 809			info->tty->alt_speed = 460800;
 810	}
 811
 812	info->flags |= ASYNC_INITIALIZED;
 813	local_irq_restore(flags);
 814	return 0;
 815
 816errout:
 817	local_irq_restore(flags);
 818	return retval;
 819}
 820
 821
 822/*
 823 * This routine is called whenever a serial port is opened.  It
 824 * enables interrupts for a serial port, linking in its async structure into
 825 * the IRQ chain.   It also performs the serial-specific
 826 * initialization for the tty structure.
 827 */
 828static int rs_open(struct tty_struct *tty, struct file * filp)
 829{
 830	struct async_struct	*info;
 831	int			retval, line;
 832	unsigned long		page;
 833
 834	line = tty->index;
 835	if ((line < 0) || (line >= NR_PORTS))
 836		return -ENODEV;
 837	retval = get_async_struct(line, &info);
 838	if (retval)
 839		return retval;
 840	tty->driver_data = info;
 841	info->tty = tty;
 842
 843#ifdef SIMSERIAL_DEBUG
 844	printk("rs_open %s, count = %d\n", tty->name, info->state->count);
 845#endif
 846	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 847
 848	if (!tmp_buf) {
 849		page = get_zeroed_page(GFP_KERNEL);
 850		if (!page)
 851			return -ENOMEM;
 852		if (tmp_buf)
 853			free_page(page);
 854		else
 855			tmp_buf = (unsigned char *) page;
 856	}
 857
 858	/*
 859	 * If the port is the middle of closing, bail out now
 860	 */
 861	if (tty_hung_up_p(filp) ||
 862	    (info->flags & ASYNC_CLOSING)) {
 863		if (info->flags & ASYNC_CLOSING)
 864			interruptible_sleep_on(&info->close_wait);
 865#ifdef SERIAL_DO_RESTART
 866		return ((info->flags & ASYNC_HUP_NOTIFY) ?
 867			-EAGAIN : -ERESTARTSYS);
 868#else
 869		return -EAGAIN;
 870#endif
 871	}
 872
 873	/*
 874	 * Start up serial port
 875	 */
 876	retval = startup(info);
 877	if (retval) {
 878		return retval;
 879	}
 880
 881	/*
 882	 * figure out which console to use (should be one already)
 883	 */
 884	console = console_drivers;
 885	while (console) {
 886		if ((console->flags & CON_ENABLED) && console->write) break;
 887		console = console->next;
 888	}
 889
 890#ifdef SIMSERIAL_DEBUG
 891	printk("rs_open ttys%d successful\n", info->line);
 892#endif
 893	return 0;
 894}
 895
 896/*
 897 * /proc fs routines....
 898 */
 899
 900static inline int line_info(char *buf, struct serial_state *state)
 901{
 902	return sprintf(buf, "%d: uart:%s port:%lX irq:%d\n",
 903		       state->line, uart_config[state->type].name,
 904		       state->port, state->irq);
 905}
 906
 907static int rs_read_proc(char *page, char **start, off_t off, int count,
 908		 int *eof, void *data)
 909{
 910	int i, len = 0, l;
 911	off_t	begin = 0;
 912
 913	len += sprintf(page, "simserinfo:1.0 driver:%s\n", serial_version);
 914	for (i = 0; i < NR_PORTS && len < 4000; i++) {
 915		l = line_info(page + len, &rs_table[i]);
 916		len += l;
 917		if (len+begin > off+count)
 918			goto done;
 919		if (len+begin < off) {
 920			begin += len;
 921			len = 0;
 922		}
 923	}
 924	*eof = 1;
 925done:
 926	if (off >= len+begin)
 927		return 0;
 928	*start = page + (begin-off);
 929	return ((count < begin+len-off) ? count : begin+len-off);
 930}
 931
 932/*
 933 * ---------------------------------------------------------------------
 934 * rs_init() and friends
 935 *
 936 * rs_init() is called at boot-time to initialize the serial driver.
 937 * ---------------------------------------------------------------------
 938 */
 939
 940/*
 941 * This routine prints out the appropriate serial driver version
 942 * number, and identifies which options were configured into this
 943 * driver.
 944 */
 945static inline void show_serial_version(void)
 946{
 947	printk(KERN_INFO "%s version %s with", serial_name, serial_version);
 948	printk(KERN_INFO " no serial options enabled\n");
 949}
 950
 951static struct tty_operations hp_ops = {
 952	.open = rs_open,
 953	.close = rs_close,
 954	.write = rs_write,
 955	.put_char = rs_put_char,
 956	.flush_chars = rs_flush_chars,
 957	.write_room = rs_write_room,
 958	.chars_in_buffer = rs_chars_in_buffer,
 959	.flush_buffer = rs_flush_buffer,
 960	.ioctl = rs_ioctl,
 961	.throttle = rs_throttle,
 962	.unthrottle = rs_unthrottle,
 963	.send_xchar = rs_send_xchar,
 964	.set_termios = rs_set_termios,
 965	.stop = rs_stop,
 966	.start = rs_start,
 967	.hangup = rs_hangup,
 968	.break_ctl = rs_break,
 969	.wait_until_sent = rs_wait_until_sent,
 970	.read_proc = rs_read_proc,
 971};
 972
 973/*
 974 * The serial driver boot-time initialization code!
 975 */
 976static int __init
 977simrs_init (void)
 978{
 979	int			i;
 980	struct serial_state	*state;
 981
 982	if (!ia64_platform_is("hpsim"))
 983		return -ENODEV;
 984
 985	hp_simserial_driver = alloc_tty_driver(1);
 986	if (!hp_simserial_driver)
 987		return -ENOMEM;
 988
 989	show_serial_version();
 990
 991	/* Initialize the tty_driver structure */
 992
 993	hp_simserial_driver->owner = THIS_MODULE;
 994	hp_simserial_driver->driver_name = "simserial";
 995	hp_simserial_driver->name = "ttyS";
 996	hp_simserial_driver->major = TTY_MAJOR;
 997	hp_simserial_driver->minor_start = 64;
 998	hp_simserial_driver->type = TTY_DRIVER_TYPE_SERIAL;
 999	hp_simserial_driver->subtype = SERIAL_TYPE_NORMAL;
1000	hp_simserial_driver->init_termios = tty_std_termios;
1001	hp_simserial_driver->init_termios.c_cflag =
1002		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1003	hp_simserial_driver->flags = TTY_DRIVER_REAL_RAW;
1004	tty_set_operations(hp_simserial_driver, &hp_ops);
1005
1006	/*
1007	 * Let's have a little bit of fun !
1008	 */
1009	for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
1010
1011		if (state->type == PORT_UNKNOWN) continue;
1012
1013		if (!state->irq) {
1014			state->irq = assign_irq_vector(AUTO_ASSIGN);
1015			ia64_ssc_connect_irq(KEYBOARD_INTR, state->irq);
1016		}
1017
1018		printk(KERN_INFO "ttyS%d at 0x%04lx (irq = %d) is a %s\n",
1019		       state->line,
1020		       state->port, state->irq,
1021		       uart_config[state->type].name);
1022	}
1023
1024	if (tty_register_driver(hp_simserial_driver))
1025		panic("Couldn't register simserial driver\n");
1026
1027	return 0;
1028}
1029
1030#ifndef MODULE
1031__initcall(simrs_init);
1032#endif