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; }
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; }