OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [orpmon/] [drivers/] [keyboard.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 858 markom
#include "common.h"
2 855 markom
#include "board.h"
3
#include "support.h"
4
#include "int.h"
5
#include "keyboard.h"
6
 
7
#if KBD_ENABLED
8
 
9 858 markom
volatile int kbd_tail = 0;
10
volatile int kbd_head = 0;
11
volatile int kbd_buf[KBDBUF_SIZE];
12 855 markom
 
13
static const unsigned char scan2ascii[2][0x40] = {
14
 {0x1f, 0x00, '1', '2',  '3', '4', '5', '6',   /* 0x00 */
15
  '7', '8', '9', '0',    '-', '=', '\b', '\t',
16 858 markom
  'q', 'w', 'e', 'r',    't', 'y', 'u', 'i',   /* 0x10 */
17
  'o', 'p', '[', ']',    '\n', 0x00, 'a', 's',
18
  'd', 'f', 'g', 'h',    'j', 'k', 'l', ';',   /* 0x20 */
19
  '\'', '`', 0xff, '\\', 'z', 'x', 'c', 'v',
20
  'b', 'n', 'm', ',',    '.', '/', 0xff, 0x00, /* 0x30 */
21 855 markom
  0x00, ' ', 0x00, 0x00, 0x00, 0x00,0x00,0x00},
22
 
23
 {0x00, 0x00, '!', '@',  '#', '$', '%', '^',  /* 0x00 */
24
  '&',  '*', '(', ')',   '_', '+', 0x00,0x00,
25 858 markom
  'Q', 'W', 'E', 'R',    'T', 'Y', 'U', 'I',  /* 0X10 */
26
  'O', 'P', '{', '}',    '\n', 0x00, 'A', 'S',
27
  'D', 'F', 'G', 'H',    'J', 'K', 'L', ':',  /* 0X20 */
28
  '"', '~', 0xff, '|',   'Z', 'X', 'C', 'V',
29
  'B', 'N', 'M', '<',    '>', '?', 0xff, 0x00,/* 0x30 */
30 855 markom
  0x00, ' ', 0x00, 0x00, 0x00, 0x00,0x00,0x00}};
31
 
32
static int shift_state = 0;
33
 
34
static void put_queue(int ch)
35
{
36 858 markom
  //putc (ch);
37
  debug ("put_queue %c (%i,%i)\n", ch, kbd_head, kbd_tail);
38 855 markom
        kbd_buf[kbd_head] = ch;
39
        kbd_head = (kbd_head + 1) % KBDBUF_SIZE;
40
}
41
 
42
static void handle_scancode (unsigned char scan)
43
{
44
  unsigned char c;
45 858 markom
  if (scan >= 0x40) {
46
    scan &= 0x7f;
47
    if (scan >= 0x40) return;
48
    c = scan2ascii[shift_state][scan];
49
    if (c == 0xff) shift_state = 0;
50
    return;
51
  }
52 855 markom
  c = scan2ascii[shift_state][scan];
53 858 markom
  if (c == 0xff) shift_state = 1;
54
  else put_queue (c);
55 855 markom
}
56
 
57
static void keyboard_interrupt(void)
58
{
59
        unsigned char status = REG8(KBD_BASE_ADD + 0x4);
60 858 markom
        debug ("keyboard_interrupt\n");
61 855 markom
        do {
62
                if (status & 0x01) handle_scancode(REG8(KBD_BASE_ADD + 0x0));
63
                status = REG8(KBD_BASE_ADD + 0x4);
64
        } while (status & 0x01);
65
}
66
 
67
static int kbd_wait_for_input(void)
68
{
69
  int     n;
70
  int     status, data;
71
 
72
  n = TIMEOUT_CONST;
73
  do {
74
    status = REG8(KBD_STATUS_REG);
75
     /*
76
      * Wait for input data to become available.  This bit will
77
      * then be cleared by the following read of the DATA
78
      * register.
79
      */
80
 
81
    if (!(status & KBD_OBF)) continue;
82
 
83
                data = REG8(KBD_DATA_REG);
84
 
85
    /*
86
     * Check to see if a timeout error has occurred.  This means
87
     * that transmission was started but did not complete in the
88
     * normal time cycle.  PERR is set when a parity error occurred
89
     * in the last transmission.
90
     */
91
    if (status & (KBD_GTO | KBD_PERR)) continue;
92
 
93
                return (data & 0xff);
94
  } while (--n);
95
  return (-1);  /* timed-out if fell through to here... */
96
}
97
 
98
static void kbd_write (int address, int data)
99
{
100
        int status;
101
        do {
102
                status = REG8(KBD_STATUS_REG);  /* spin until input buffer empty*/
103
        } while (status & KBD_IBF);
104
  REG8 (address) = data;               /* write out the data*/
105
}
106
 
107
int kbd_init(void)
108
{
109
        int_add (KBD_IRQ, keyboard_interrupt);
110
 
111
        /* Flush any pending input. */
112
        while (kbd_wait_for_input() != -1) continue;
113
 
114
        /*
115
         * Test the keyboard interface.
116
         * This seems to be the only way to get it going.
117
         * If the test is successful a x55 is placed in the input buffer.
118
         */
119
        kbd_write(KBD_CNTL_REG, KBD_SELF_TEST);
120
        if (kbd_wait_for_input() != 0x55) {
121 858 markom
                printf ("initialize_kbd: keyboard failed self test.\n");
122 855 markom
                return(-1);
123
        }
124
 
125
        /*
126
         * Perform a keyboard interface test.  This causes the controller
127
         * to test the keyboard clock and data lines.  The results of the
128
         * test are placed in the input buffer.
129
         */
130
        kbd_write(KBD_CNTL_REG, KBD_SELF_TEST2);
131
        if (kbd_wait_for_input() != 0x00) {
132 858 markom
                printf ("initialize_kbd: keyboard failed self test 2.\n");
133 855 markom
                return(-1);
134
        }
135
 
136
        /* Enable the keyboard by allowing the keyboard clock to run. */
137
        kbd_write(KBD_CNTL_REG, KBD_CNTL_ENABLE);
138
 
139
        /*
140
         * Reset keyboard. If the read times out
141
         * then the assumption is that no keyboard is
142
         * plugged into the machine.
143
         * This defaults the keyboard to scan-code set 2.
144
         */
145
        kbd_write(KBD_DATA_REG, KBD_RESET);
146
        if (kbd_wait_for_input() != KBD_ACK) {
147 858 markom
                printf ("initialize_kbd: reset kbd failed, no ACK.\n");
148 855 markom
                return(-1);
149
        }
150
 
151
        if (kbd_wait_for_input() != KBD_POR) {
152 858 markom
                printf ("initialize_kbd: reset kbd failed, not POR.\n");
153 855 markom
                return(-1);
154
        }
155
 
156
        /*
157
         * now do a DEFAULTS_DISABLE always
158
         */
159
        kbd_write(KBD_DATA_REG, KBD_DISABLE);
160
        if (kbd_wait_for_input() != KBD_ACK) {
161 858 markom
                printf ("initialize_kbd: disable kbd failed, no ACK.\n");
162 855 markom
                return(-1);
163
        }
164
 
165
        /*
166
         * Enable keyboard interrupt, operate in "sys" mode,
167
         *  enable keyboard (by clearing the disable keyboard bit),
168
         *  disable mouse, do conversion of keycodes.
169
         */
170
        kbd_write(KBD_CNTL_REG, KBD_WRITE_MODE);
171
        kbd_write(KBD_DATA_REG, KBD_EKI|KBD_SYS|KBD_DMS|KBD_KCC);
172
 
173
        /*
174
         * now ENABLE the keyboard to set it scanning...
175
         */
176
        kbd_write(KBD_DATA_REG, KBD_ENABLE);
177
        if (kbd_wait_for_input() != KBD_ACK) {
178 858 markom
                printf ("initialize_kbd: keyboard enable failed.\n");
179 855 markom
                return(-1);
180
        }
181
 
182 858 markom
  int_enable (KBD_IRQ);
183
        printf ("PS/2 keyboard initialized at 0x%x (irq = %d).\n", KBD_BASE_ADD, KBD_IRQ);
184 855 markom
        return (1);
185
}
186
 
187
#endif /* KBD_ENABLED */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.