Esempio n. 1
0
static void keyboard_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
  u_char acia_stat;
  int scancode;
  int break_flag;

  /* save frame for register dump */
  kbd_pt_regs = fp;

 repeat:
  if (acia.mid_ctrl & ACIA_IRQ)
	if (atari_MIDI_interrupt_hook)
		atari_MIDI_interrupt_hook();
  acia_stat = acia.key_ctrl;
  /* check out if the interrupt came from this ACIA */
  if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
	return;

    if (acia_stat & ACIA_OVRN)
    {
	/* a very fast typist or a slow system, give a warning */
	/* ...happens often if interrupts were disabled for too long */
	printk( KERN_DEBUG "Keyboard overrun\n" );
	scancode = acia.key_data;
	/* Turn off autorepeating in case a break code has been lost */
	del_timer( &atakeyb_rep_timer );
	rep_scancode = 0;
	if (ikbd_self_test)
	    /* During self test, don't do resyncing, just process the code */
	    goto interpret_scancode;
	else if (IS_SYNC_CODE(scancode)) {
	    /* This code seem already to be the start of a new packet or a
	     * single scancode */
	    kb_state.state = KEYBOARD;
	    goto interpret_scancode;
	}
	else {
	    /* Go to RESYNC state and skip this byte */
	    kb_state.state = RESYNC;
	    kb_state.len = 1; /* skip max. 1 another byte */
	    goto repeat;
	}
    }

    if (acia_stat & ACIA_RDRF)	/* received a character */
    {
	scancode = acia.key_data;	/* get it or reset the ACIA, I'll get it! */
	mark_bh(KEYBOARD_BH);
      interpret_scancode:
	switch (kb_state.state)
	{
	  case KEYBOARD:
	    switch (scancode)
	    {
	      case 0xF7:
		kb_state.state = AMOUSE;
		kb_state.len = 0;
		break;

	      case 0xF8:
	      case 0xF9:
     	      case 0xFA:
	      case 0xFB:
		kb_state.state = RMOUSE;
	    	kb_state.len = 1;
		kb_state.buf[0] = scancode;
		break;

	      case 0xFC:
		kb_state.state = CLOCK;
		kb_state.len = 0;
		break;

	      case 0xFE:
	      case 0xFF:
		kb_state.state = JOYSTICK;
		kb_state.len = 1;
		kb_state.buf[0] = scancode;
		break;

	      case 0xF1:
		/* during self-test, note that 0xf1 received */
		if (ikbd_self_test) {
		    ++ikbd_self_test;
		    self_test_last_rcv = jiffies;
		    break;
		}
		/* FALL THROUGH */
		
	      default:
		break_flag = scancode & BREAK_MASK;
		scancode &= ~BREAK_MASK;

		if (ikbd_self_test) {
		    /* Scancodes sent during the self-test stand for broken
		     * keys (keys being down). The code *should* be a break
		     * code, but nevertheless some AT keyboard interfaces send
		     * make codes instead. Therefore, simply ignore
		     * break_flag...
		     * */
		    int keyval = plain_map[scancode], keytyp;
		    
		    set_bit( scancode, broken_keys );
		    self_test_last_rcv = jiffies;
		    keyval = plain_map[scancode];
		    keytyp = KTYP(keyval) - 0xf0;
		    keyval = KVAL(keyval);

		    printk( KERN_WARNING "Key with scancode %d ", scancode );
		    if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
			if (keyval < ' ')
			    printk( "('^%c') ", keyval + '@' );
			else
			    printk( "('%c') ", keyval );
		    }
		    printk( "is broken -- will be ignored.\n" );
		    break;
		}
		else if (test_bit( scancode, broken_keys ))
		    break;

		if (break_flag) {
		    del_timer( &atakeyb_rep_timer );
		    rep_scancode = 0;
		}
		else {
		    del_timer( &atakeyb_rep_timer );
		    rep_scancode = scancode;
		    atakeyb_rep_timer.expires = jiffies + key_repeat_delay;
		    atakeyb_rep_timer.prev = atakeyb_rep_timer.next = NULL;
		    add_timer( &atakeyb_rep_timer );
		}

		handle_scancode(break_flag | scancode);
		break;
	    }
	    break;

	  case AMOUSE:
	    kb_state.buf[kb_state.len++] = scancode;
	    if (kb_state.len == 5)
	    {
		kb_state.state = KEYBOARD;
		/* not yet used */
		/* wake up someone waiting for this */
	    }
	    break;	

	  case RMOUSE:
	    kb_state.buf[kb_state.len++] = scancode;
	    if (kb_state.len == 3)
	    {
		kb_state.state = KEYBOARD;
		if (atari_mouse_interrupt_hook)
			atari_mouse_interrupt_hook(kb_state.buf);
	    }
	    break;

	  case JOYSTICK:
	    kb_state.buf[1] = scancode;
	    kb_state.state = KEYBOARD;
	    atari_joystick_interrupt(kb_state.buf);
	    break;

	  case CLOCK:
	    kb_state.buf[kb_state.len++] = scancode;
	    if (kb_state.len == 6)
	    {
		kb_state.state = KEYBOARD;
		/* wake up someone waiting for this.
		   But will this ever be used, as Linux keeps its own time.
		   Perhaps for synchronization purposes? */
		/* wake_up_interruptible(&clock_wait); */
	    }
	    break;

	  case RESYNC:
	    if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
		kb_state.state = KEYBOARD;
		goto interpret_scancode;
	    }
	    kb_state.len--;
	    break;
	}
    }

#if 0
    if (acia_stat & ACIA_CTS)
	/* cannot happen */;
#endif

    if (acia_stat & (ACIA_FE | ACIA_PE))
    {
	printk("Error in keyboard communication\n");
    }

    /* handle_scancode() can take a lot of time, so check again if
	 * some character arrived
	 */
    goto repeat;
}
Esempio n. 2
0
static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy)
{
	u_char acia_stat;
	int scancode;
	int break_flag;

repeat:
	if (acia.mid_ctrl & ACIA_IRQ)
		if (atari_MIDI_interrupt_hook)
			atari_MIDI_interrupt_hook();
	acia_stat = acia.key_ctrl;
	
	if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ))
		return IRQ_HANDLED;

	if (acia_stat & ACIA_OVRN) {
		
		
		printk(KERN_DEBUG "Keyboard overrun\n");
		scancode = acia.key_data;
		if (ikbd_self_test)
			
			goto interpret_scancode;
		else if (IS_SYNC_CODE(scancode)) {
			kb_state.state = KEYBOARD;
			goto interpret_scancode;
		} else {
			
			kb_state.state = RESYNC;
			kb_state.len = 1;	
			goto repeat;
		}
	}

	if (acia_stat & ACIA_RDRF) {
		
		scancode = acia.key_data;	
		tasklet_schedule(&keyboard_tasklet);
	interpret_scancode:
		switch (kb_state.state) {
		case KEYBOARD:
			switch (scancode) {
			case 0xF7:
				kb_state.state = AMOUSE;
				kb_state.len = 0;
				break;

			case 0xF8:
			case 0xF9:
			case 0xFA:
			case 0xFB:
				kb_state.state = RMOUSE;
				kb_state.len = 1;
				kb_state.buf[0] = scancode;
				break;

			case 0xFC:
				kb_state.state = CLOCK;
				kb_state.len = 0;
				break;

			case 0xFE:
			case 0xFF:
				kb_state.state = JOYSTICK;
				kb_state.len = 1;
				kb_state.buf[0] = scancode;
				break;

			case 0xF1:
				
				if (ikbd_self_test) {
					++ikbd_self_test;
					self_test_last_rcv = jiffies;
					break;
				}
				

			default:
				break_flag = scancode & BREAK_MASK;
				scancode &= ~BREAK_MASK;
				if (ikbd_self_test) {
					int keyval, keytyp;

					set_bit(scancode, broken_keys);
					self_test_last_rcv = jiffies;
					
					keyval = scancode;
					keytyp = KTYP(keyval) - 0xf0;
					keyval = KVAL(keyval);

					printk(KERN_WARNING "Key with scancode %d ", scancode);
					if (keytyp == KT_LATIN || keytyp == KT_LETTER) {
						if (keyval < ' ')
							printk("('^%c') ", keyval + '@');
						else
							printk("('%c') ", keyval);
					}
					printk("is broken -- will be ignored.\n");
					break;
				} else if (test_bit(scancode, broken_keys))
					break;

				if (atari_input_keyboard_interrupt_hook)
					atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag);
				break;
			}
			break;

		case AMOUSE:
			kb_state.buf[kb_state.len++] = scancode;
			if (kb_state.len == 5) {
				kb_state.state = KEYBOARD;
				
				
			}
			break;

		case RMOUSE:
			kb_state.buf[kb_state.len++] = scancode;
			if (kb_state.len == 3) {
				kb_state.state = KEYBOARD;
				if (atari_input_mouse_interrupt_hook)
					atari_input_mouse_interrupt_hook(kb_state.buf);
			}
			break;

		case JOYSTICK:
			kb_state.buf[1] = scancode;
			kb_state.state = KEYBOARD;
#ifdef FIXED_ATARI_JOYSTICK
			atari_joystick_interrupt(kb_state.buf);
#endif
			break;

		case CLOCK:
			kb_state.buf[kb_state.len++] = scancode;
			if (kb_state.len == 6) {
				kb_state.state = KEYBOARD;
				
			}
			break;

		case RESYNC:
			if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) {
				kb_state.state = KEYBOARD;
				goto interpret_scancode;
			}
			kb_state.len--;
			break;
		}
	}

#if 0
	if (acia_stat & ACIA_CTS)
		;
#endif

	if (acia_stat & (ACIA_FE | ACIA_PE)) {
		printk("Error in keyboard communication\n");
	}

	goto repeat;
}