예제 #1
0
static void ps2_debug_sysrq(int c)
{
	printk("\n%02ld:%02ld.%02ld: sysrq:%c ...\n",
		jiffies / (HZ *60) % 60,
		jiffies / HZ % 60,
		jiffies % HZ,
		c);
	handle_sysrq(c, 0, 0, 0);
	printk("%02ld:%02ld.%02ld: sysrq:%c done.\n",
		jiffies / (HZ *60) % 60,
		jiffies / HZ % 60,
		jiffies % HZ,
		c);
}
예제 #2
0
static void hvc_poll(int index)
{
	struct hvc_struct *hp = &hvc_struct[index];
	struct tty_struct *tty;
	int i, n;
	char buf[16] __ALIGNED__;
	unsigned long flags;

	spin_lock_irqsave(&hp->lock, flags);

	if (hp->n_outbuf > 0)
		hvc_push(hp);

	tty = hp->tty;
	if (tty) {
		for (;;) {
			if (TTY_FLIPBUF_SIZE - tty->flip.count < sizeof(buf))
				break;
			n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf));
			if (n <= 0)
				break;
			for (i = 0; i < n; ++i) {
#ifdef CONFIG_MAGIC_SYSRQ		/* Handle the SysRq Hack */
				if (buf[i] == '\x0f') {	/* ^O -- should support a sequence */
					sysrq_pressed = 1;
					continue;
				} else if (sysrq_pressed) {
					handle_sysrq(buf[i], NULL, NULL, tty);
					sysrq_pressed = 0;
					continue;
				}
#endif
				tty_insert_flip_char(tty, buf[i], 0);
			}
		}
		if (tty->flip.count)
			tty_schedule_flip(tty);

		if (hp->do_wakeup) {
			hp->do_wakeup = 0;
			if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
			    && tty->ldisc.write_wakeup)
				(tty->ldisc.write_wakeup)(tty);
			wake_up_interruptible(&tty->write_wait);
		}
	}

	spin_unlock_irqrestore(&hp->lock, flags);
}
예제 #3
0
static irqreturn_t s3c2410wdt_irq(int irqno, void *param)
{
	dev_info(wdt_dev, "watchdog timer expired (irq)\n");
	s3c2410wdt_keepalive(&s3c2410_wdd);

	/* Clear the interrupt */
	s3c2410wdt_int_clear(&s3c2410_wdd);

	/* Print backtrace of all cpus. */
	handle_sysrq('l');

	/* Restart for availability */
	pr_info("%s: emergency reboot\n", __func__);
	emergency_restart();

	return IRQ_HANDLED;
}
예제 #4
0
static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
{
	int i;

	for (i=0; i < len; i++) {
		char c = buf[i];
#ifdef CONFIG_MAGIC_SYSRQ
		if (c == '\0') {
			hp->sysrq = 1;
			continue;
		} else if (hp->sysrq) {
			handle_sysrq(c, NULL, hp->tty);
			hp->sysrq = 0;
			continue;
		}
#endif /* CONFIG_MAGIC_SYSRQ */
		tty_insert_flip_char(hp->tty, c, 0);
	}
}
예제 #5
0
void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
{
	int           i;
	unsigned long flags;

	spin_lock_irqsave(&xencons_lock, flags);
	if (xencons_tty == NULL)
		goto out;

	for (i = 0; i < len; i++) {
#ifdef CONFIG_MAGIC_SYSRQ
		if (sysrq_enabled) {
			if (buf[i] == '\x0f') { /* ^O */
				sysrq_requested = jiffies;
				continue; /* don't print the sysrq key */
			} else if (sysrq_requested) {
				unsigned long sysrq_timeout =
					sysrq_requested + HZ*2;
				sysrq_requested = 0;
				if (time_before(jiffies, sysrq_timeout)) {
					spin_unlock_irqrestore(
						&xencons_lock, flags);
					handle_sysrq(
						buf[i], regs, xencons_tty);
					spin_lock_irqsave(
						&xencons_lock, flags);
					continue;
				}
			}
		}
#endif
		tty_insert_flip_char(xencons_tty, buf[i], 0);
	}
	tty_flip_buffer_push(xencons_tty);

 out:
	spin_unlock_irqrestore(&xencons_lock, flags);
}
예제 #6
0
static  void receive_chars(struct tty_struct *tty, struct pt_regs *regs)
{
	unsigned char ch;
	static unsigned char seen_esc = 0;

	while ( (ch = ia64_ssc(0, 0, 0, 0, SSC_GETCHAR)) ) {
		if ( ch == 27 && seen_esc == 0 ) {
			seen_esc = 1;
			continue;
		} else {
			if ( seen_esc==1 && ch == 'O' ) {
				seen_esc = 2;
				continue;
			} else if ( seen_esc == 2 ) {
				if ( ch == 'P' ) /* F1 */
					show_state();
#ifdef CONFIG_MAGIC_SYSRQ
				if ( ch == 'S' ) { /* F4 */
					do
						ch = ia64_ssc(0, 0, 0, 0,
							      SSC_GETCHAR);
					while (!ch);
					handle_sysrq(ch, regs, NULL);
				}
#endif
				seen_esc = 0;
				continue;
			}
		}
		seen_esc = 0;

		if (tty_insert_flip_char(tty, ch, TTY_NORMAL) == 0)
			break;
	}
	tty_flip_buffer_push(tty);
}
예제 #7
0
파일: sunkbd.c 프로젝트: dmgerman/original
/* This is our keyboard 'interrupt' routine.
 * Must run under sunkbd_lock.
 */
static void __sunkbd_inchar(unsigned char ch, struct pt_regs *regs)
{
	unsigned char keycode;
	char up_flag;                          /* 0 or SUNKBD_UBIT */
	char raw_mode;

	if(ch == SKBD_RESET) {
		kbd_reset_pending = 1;
		goto out;
	}
	if(ch == SKBD_LYOUT) {
		kbd_layout_pending = 1;
		goto out;
	}
	if(kbd_reset_pending) {
		sunkbd_type = ch;
		kbd_reset_pending = 0;
		if(ch == SUNKBD_TYPE4)
			send_cmd(SKBDCMD_GLAYOUT);
		goto out;
	} else if(kbd_layout_pending) {
		sunkbd_layout = ch;
		kbd_layout_pending = 0;
		goto out;
	} else if(ch == SKBD_ALLUP) {
		del_timer (&auto_repeat_timer);
		memset(key_down, 0, sizeof(key_down));
		sun_compute_shiftstate();
		goto out;
	}
#ifdef SKBD_DEBUG
	if(ch == 0x7f)
		printk("KBD<ALL KEYS UP>");
	else
		printk("KBD<%x %s>", ch,
		       ((ch&0x80) ? "UP" : "DOWN"));
#endif

	/* Whee, a real character. */
	if(regs) {
		pt_regs = regs;
		last_keycode = keycode = ch;
	} else {
		keycode = ch;
	}
	
	do_poke_blanked_console = 1;
	tasklet_schedule(&console_tasklet);
	add_keyboard_randomness(keycode);

	tty = ttytab? ttytab[fg_console]: NULL;
	if (tty && (!tty->driver_data)) {
		/* This is to workaround ugly bug in tty_io.c, which
                   does not do locking when it should */
		tty = NULL;
	}
	kbd = kbd_table + fg_console;
	if((raw_mode = (kbd->kbdmode == VC_RAW))) {
		if (kbd_redirected == fg_console+1)
			push_kbd (keycode);
		else
			put_queue(keycode);
		/* we do not return yet, because we want to maintain
		 * the key_down array, so that we have the correct
		 * values  when finishing RAW mode or when changing VT's.
		 */
	}
	up_flag = (keycode & SUNKBD_UBIT);  /* The 'up' bit */
	keycode &= SUNKBD_KMASK;            /* all the rest */
	del_timer (&auto_repeat_timer);
	if(up_flag) {
		rep = 0;
		clear_bit(keycode, key_down);
	} else {
		if (!norepeat_keys[keycode]) {
			if (kbd_rate_ticks) {
				auto_repeat_timer.expires =
						jiffies + kbd_delay_ticks;
				add_timer (&auto_repeat_timer);
			}
		}
		rep = test_and_set_bit(keycode, key_down);
	}

#ifdef CONFIG_MAGIC_SYSRQ			/* Handle the SysRq hack */
	if (l1a_state.l1_down) {
		if (!up_flag)
			handle_sysrq(sun_sysrq_xlate[keycode], pt_regs, kbd, tty);
		goto out;
	}
#endif

	if(raw_mode)
		goto out;

	if(kbd->kbdmode == VC_MEDIUMRAW) {
		put_queue(keycode + up_flag);
		goto out;
	}

 	/*
	 * Small change in philosophy: earlier we defined repetition by
	 *	 rep = keycode == prev_keycode;
	 *	 prev_keycode = keycode;
	 * but now by the fact that the depressed key was down already.
	 * Does this ever make a difference? Yes.
	 */

	/*
 	 *  Repeat a key only if the input buffers are empty or the
 	 *  characters get echoed locally. This makes key repeat usable
 	 *  with slow applications and under heavy loads.
	 */
	if (!rep ||
	    (vc_kbd_mode(kbd,VC_REPEAT) && tty &&
	     (L_ECHO(tty) || (tty->driver.chars_in_buffer(tty) == 0)))) {
		u_short keysym;
		u_char type;

		/* the XOR below used to be an OR */
		int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate;
		ushort *key_map = key_maps[shift_final];

		if (key_map != NULL) {
			keysym = key_map[keycode];
			type = KTYP(keysym);

			if (type >= 0xf0) {
			    type -= 0xf0;
			    if (type == KT_LETTER) {
				type = KT_LATIN;
				if (vc_kbd_led(kbd, VC_CAPSLOCK)) {
				    key_map = key_maps[shift_final ^ (1<<KG_SHIFT)];
				    if (key_map)
				      keysym = key_map[keycode];
				}
			    }
			    (*key_handler[type])(keysym & 0xff, up_flag);
			    if (type != KT_SLOCK)
			      kbd->slockstate = 0;
			}
		} else {
			/* maybe beep? */
			/* we have at least to update shift_state */
			sun_compute_shiftstate();
		}
	}
out:
	tasklet_schedule(&keyboard_tasklet);
}
static irqreturn_t sci_keypad_isr(int irq, void *dev_id)
{
	unsigned short key = 0;
	unsigned long value;
	struct sci_keypad_t *sci_kpd = dev_id;
	unsigned long int_status = keypad_readl(KPD_INT_MASK_STATUS);
	unsigned long key_status = keypad_readl(KPD_KEY_STATUS);
	unsigned short *keycodes = sci_kpd->input_dev->keycode;
	unsigned int row_shift = get_count_order(sci_kpd->cols);
	int col, row;

	value = keypad_readl(KPD_INT_CLR);
	value |= KPD_INT_ALL;
	keypad_writel(KPD_INT_CLR, value);

	if ((int_status & KPD_PRESS_INT0)) {
		col = KPD_INT0_COL(key_status);
		row = KPD_INT0_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];
		input_report_key(sci_kpd->input_dev, key, 1);
		input_sync(sci_kpd->input_dev);
		printk("%03dD\n", key);
	}
	if (int_status & KPD_RELEASE_INT0) {
		col = KPD_INT0_COL(key_status);
		row = KPD_INT0_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];

		input_report_key(sci_kpd->input_dev, key, 0);
		input_sync(sci_kpd->input_dev);
		printk("%03dU\n", key);
	}

	if ((int_status & KPD_PRESS_INT1)) {
		col = KPD_INT1_COL(key_status);
		row = KPD_INT1_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];

		input_report_key(sci_kpd->input_dev, key, 1);
		input_sync(sci_kpd->input_dev);
		printk("%03dD\n", key);
	}
	if (int_status & KPD_RELEASE_INT1) {
		col = KPD_INT1_COL(key_status);
		row = KPD_INT1_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];

		input_report_key(sci_kpd->input_dev, key, 0);
		input_sync(sci_kpd->input_dev);
		printk("%03dU\n", key);
	}

	if ((int_status & KPD_PRESS_INT2)) {
		col = KPD_INT2_COL(key_status);
		row = KPD_INT2_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];

		input_report_key(sci_kpd->input_dev, key, 1);
		input_sync(sci_kpd->input_dev);
		printk("%03d\n", key);
	}
	if (int_status & KPD_RELEASE_INT2) {
		col = KPD_INT2_COL(key_status);
		row = KPD_INT2_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];

		input_report_key(sci_kpd->input_dev, key, 0);
		input_sync(sci_kpd->input_dev);
		printk("%03d\n", key);
	}

	if (int_status & KPD_PRESS_INT3) {
		col = KPD_INT3_COL(key_status);
		row = KPD_INT3_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];

		input_report_key(sci_kpd->input_dev, key, 1);
		input_sync(sci_kpd->input_dev);
		printk("%03d\n", key);
	}
	if (int_status & KPD_RELEASE_INT3) {
		col = KPD_INT3_COL(key_status);
		row = KPD_INT3_ROW(key_status);
		key = keycodes[MATRIX_SCAN_CODE(row, col, row_shift)];

		input_report_key(sci_kpd->input_dev, key, 0);
		input_sync(sci_kpd->input_dev);
		printk("%03d\n", key);
	}

#ifdef CONFIG_MAGIC_SYSRQ
	{
		static unsigned long key_status_prev = 0;

		if (check_key_down(sci_kpd, key_status, SPRD_CAMERA_KEY) &&
			check_key_down(sci_kpd, key_status, SPRD_VOL_DOWN_KEY) && key_status != key_status_prev) {
			key_status_prev = key_status;
			panic("!!!! Combine key: vol_down + camera !!!!\n");
		}

		if (check_key_down(sci_kpd, key_status, SPRD_CAMERA_KEY) &&
			check_key_down(sci_kpd, key_status, SPRD_VOL_UP_KEY) && key_status != key_status_prev) {
			unsigned long flags;
			static int rebooted = 0;
			key_status_prev = key_status;
			local_irq_save(flags);
			if (rebooted == 0) {
				rebooted = 1;
				pr_warn("!!!!!! Combine Key : vol_up + camera is Down !!!!!!\n");
				/* handle_sysrq('t'); */
				handle_sysrq('m');
				handle_sysrq('w');
				handle_sysrq('b');
				pr_warn("!!!!!! /proc/sys/kernel/sysrq is disabled !!!!!!\n");
				rebooted = 0;
			}
			local_irq_restore(flags);
		}
	}
#endif
	return IRQ_HANDLED;
}
/*
 * Handle a data charLpEvent. 
 */
static void vioHandleData(struct HvLpEvent *event)
{
	struct tty_struct *tty;
	unsigned long flags;
	struct viocharlpevent *cevent = (struct viocharlpevent *)event;
	struct port_info *pi;
	int index;
	u8 port = cevent->virtual_device;

	if (port >= VTTY_PORTS) {
		printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n",
				port);
		return;
	}

	/*
	 * Hold the spinlock so that we don't take an interrupt that
	 * changes tty between the time we fetch the port_info
	 * pointer and the time we paranoia check.
	 */
	spin_lock_irqsave(&consolelock, flags);
	pi = &port_info[port];

	/*
	 * Change 05/01/2003 - Ryan Arnold: If a partition other than
	 * the current exclusive partition tries to send us data
	 * events then just drop them on the floor because we don't
	 * want his stinking data.  He isn't authorized to receive
	 * data because he wasn't the first one to get the console,
	 * therefore he shouldn't be allowed to send data either.
	 * This will work without an iSeries fix.
	 */
	if (pi->lp != event->xSourceLp) {
		spin_unlock_irqrestore(&consolelock, flags);
		return;
	}

	tty = pi->tty;
	if (tty == NULL) {
		spin_unlock_irqrestore(&consolelock, flags);
		printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n",
				port);
		return;
	}

	if (tty->magic != TTY_MAGIC) {
		spin_unlock_irqrestore(&consolelock, flags);
		printk(VIOCONS_KERN_WARN "tty bad magic\n");
		return;
	}

	/*
	 * Just to be paranoid, make sure the tty points back to this port
	 */
	pi = (struct port_info *)tty->driver_data;
	if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) {
		spin_unlock_irqrestore(&consolelock, flags);
		return;
	}
	spin_unlock_irqrestore(&consolelock, flags);

	/*
	 * Change 07/21/2003 - Ryan Arnold: functionality added to
	 * support sysrq utilizing ^O as the sysrq key.  The sysrq
	 * functionality will only work if built into the kernel and
	 * then only if sysrq is enabled through the proc filesystem.
	 */
	for (index = 0; index < cevent->len; index++) {
#ifdef CONFIG_MAGIC_SYSRQ
		if (sysrq_enabled) {
			/* 0x0f is the ascii character for ^O */
			if (cevent->data[index] == '\x0f') {
				vio_sysrq_pressed = 1;
				/*
				 * continue because we don't want to add
				 * the sysrq key into the data string.
				 */
				continue;
			} else if (vio_sysrq_pressed) {
				handle_sysrq(cevent->data[index], NULL, tty);
				vio_sysrq_pressed = 0;
				/*
				 * continue because we don't want to add
				 * the sysrq sequence into the data string.
				 */
				continue;
			}
		}
#endif
		/*
		 * The sysrq sequence isn't included in this check if
		 * sysrq is enabled and compiled into the kernel because
		 * the sequence will never get inserted into the buffer.
		 * Don't attempt to copy more data into the buffer than we
		 * have room for because it would fail without indication.
		 */
		if ((tty->flip.count + 1) > TTY_FLIPBUF_SIZE) {
			printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
			break;
		}
		tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL);
	}

	/* if cevent->len == 0 then no data was added to the buffer and flip.count == 0 */
	if (tty->flip.count)
		/* The next call resets flip.count when the data is flushed. */
		tty_flip_buffer_push(tty);
}
예제 #10
0
static void
ctrlchar_handle_sysrq(struct work_struct *work)
{
    handle_sysrq(ctrlchar_sysrq_key, sysrq_tty);
}