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

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [peripheral/] [ps2kbd.c] - Blame information for rev 684

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 664 markom
/* ps2kbd.c -- Very simple (and limited) PS/2 keyboard simulation
2
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdlib.h>
21
#include <stdio.h>
22
#include <string.h>
23
#include "ps2kbd.h"
24
#include "sim-config.h"
25
#include "abstract.h"
26
 
27
/* ASCII to scan code conversion table */
28
const static struct {
29
  /* Whether shift must be pressed */
30
  unsigned char shift;
31
  /* Scan code to be generated */
32
  unsigned char code;
33
} scan_table [128] = {
34
/* 0 - 15 */
35
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
36
{0, 0x0E}, {0, 0x0F}, {0, 0x1C}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
37
/* 16 - 31 */
38
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
39
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x01}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
40
/* 32 - 47 */
41
{0, 0x39}, {1, 0x02}, {1, 0x28}, {1, 0x04}, {1, 0x05}, {1, 0x06}, {1, 0x08}, {0, 0x28},
42
{1, 0x0A}, {1, 0x0B}, {1, 0x09}, {1, 0x0D}, {0, 0x33}, {0, 0x0C}, {0, 0x34}, {0, 0x35},
43
/* 48 - 63 */
44
{0, 0x0B}, {0, 0x02}, {0, 0x03}, {0, 0x04}, {0, 0x05}, {0, 0x06}, {0, 0x07}, {0, 0x08},
45
{0, 0x09}, {0, 0x0A}, {1, 0x27}, {0, 0x27}, {1, 0x33}, {0, 0x0D}, {1, 0x34}, {1, 0x35},
46
/* 64 - 79 */
47
{1, 0x03}, {1, 0x1E}, {1, 0x30}, {1, 0x2E}, {1, 0x20}, {1, 0x12}, {1, 0x21}, {1, 0x22},
48
{1, 0x23}, {1, 0x17}, {1, 0x24}, {1, 0x25}, {1, 0x26}, {1, 0x32}, {1, 0x31}, {1, 0x18},
49
/* 80 - 95 */
50
{1, 0x19}, {1, 0x10}, {1, 0x13}, {1, 0x1F}, {1, 0x14}, {1, 0x16}, {1, 0x2F}, {1, 0x11},
51
{1, 0x2D}, {1, 0x15}, {1, 0x2C}, {0, 0x1A}, {0, 0x2B}, {0, 0x1B}, {1, 0x07}, {1, 0x0C},
52
/* 96 - 111 */
53
{0, 0x29}, {0, 0x1E}, {0, 0x30}, {0, 0x2E}, {0, 0x20}, {0, 0x12}, {0, 0x21}, {0, 0x22},
54
{0, 0x23}, {0, 0x17}, {0, 0x24}, {0, 0x25}, {0, 0x26}, {0, 0x32}, {0, 0x31}, {0, 0x18},
55
/* 112 - 127 */
56
{0, 0x19}, {0, 0x10}, {0, 0x13}, {0, 0x1F}, {0, 0x14}, {0, 0x16}, {0, 0x2F}, {0, 0x11},
57
{0, 0x2D}, {0, 0x15}, {0, 0x2C}, {1, 0x1A}, {1, 0x2B}, {1, 0x1B}, {1, 0x29}, {0, 0x00}
58
};
59
 
60
/* Temporary buffer to store incoming scan codes */
61
static unsigned char kbd_buf[KBD_MAX_BUF] = {0};
62
 
63
/* Number of scan codes in buffer */
64
static unsigned long kbd_buf_count = 0;
65
static unsigned long kbd_buf_head = 0;
66
static unsigned long kbd_buf_tail = 0;
67
 
68
/* Input stream */
69
static FILE *kbd_rxfs = NULL;
70 684 lampret
 
71
/* Controller Command (write into 0x64) */
72
static int kbd_ccmd;
73
 
74
/* Keyboard Command (write into 0x60) */
75
static unsigned char kbd_kcmd;
76
 
77
/* Controller Command Byte */
78
static unsigned char kbd_ccmdbyte;
79
 
80
/* Keyboard response pending */
81
static unsigned long kbd_kresp;
82
 
83 664 markom
static void kbd_put (unsigned char c)
84
{
85
  if (kbd_buf_count >= KBD_MAX_BUF) {
86
    fprintf (stderr, "WARNING: Keyboard buffer overflow.\n");
87
  } else {
88
    kbd_buf[kbd_buf_head] = c;
89
    kbd_buf_head = (kbd_buf_head + 1) % KBD_MAX_BUF;
90
    kbd_buf_count++;
91
  }
92
}
93
 
94
/* Decodes ascii code c into multiple scan codes, placed into buf, length is returned */
95
static void scan_decode (unsigned char c)
96
{
97
  /* Do not handle special characters and extended ascii */
98
  if (c >= 128 || !scan_table[c].code)
99
    return;
100
 
101
  /* Make shift? */
102
  if (scan_table[c].shift) kbd_put (0x2a);
103
  /* Make char */
104
  kbd_put (scan_table[c].code);
105
  /* Break char */
106
  kbd_put (scan_table[c].code | 0x80);
107
  /* Break shift? */
108
  if (scan_table[c].shift) kbd_put (0xaa);
109
}
110
 
111
/* Write a register */
112
void kbd_write8 (unsigned long addr, unsigned long value)
113
{
114
  int a = (addr - config.kbd.baseaddr);
115
  switch (a) {
116 684 lampret
    case KBD_CTRL:
117
      kbd_ccmd = value & 0xff;
118
      if (kbd_ccmd == KBD_CCMD_RCB)
119
          kbd_kresp = 0x1;
120
      if (kbd_ccmd == KBD_CCMD_ST1)
121
          kbd_kresp = 0x1;
122
      if (kbd_ccmd == KBD_CCMD_ST2)
123
          kbd_kresp = 0x1;
124
      if (kbd_ccmd == KBD_CCMD_DKI)
125
        kbd_ccmdbyte |= KBD_CCMDBYTE_EN;
126
      if (kbd_ccmd == KBD_CCMD_EKI)
127
        kbd_ccmdbyte &= ~KBD_CCMDBYTE_EN;
128
      if (config.sim.verbose)
129
        printf("kbd_write8(%x) %x\n", addr, value);
130
      break;
131
    case KBD_DATA:
132
      if (kbd_ccmd == KBD_CCMD_WCB) {
133
        kbd_ccmdbyte = value & 0xff;
134
        kbd_ccmd = 0x00;
135
      } else
136
        kbd_kcmd = value & 0xff;
137
      if (kbd_kcmd == KBD_KCMD_DK)
138
        kbd_ccmdbyte |= KBD_CCMDBYTE_EN;
139
      if (kbd_kcmd == KBD_KCMD_EK)
140
        kbd_ccmdbyte &= ~KBD_CCMDBYTE_EN;
141
      kbd_kresp = 0x1;
142
      kbd_ccmd = 0x00;
143
      if (config.sim.verbose)
144
        printf("kbd_write8(%x) %x\n", addr, value);
145
      break;
146 664 markom
    default:
147
      fprintf (stderr, "Write out of keyboard space (0x%08x)!\n", addr);
148
      cont_run = 0;
149
      break;
150
  }
151
}
152
 
153
/* Read a register */
154
unsigned long kbd_read8 (unsigned long addr)
155
{
156
  int a = (addr - config.kbd.baseaddr);
157
  switch (a) {
158 684 lampret
    case KBD_CTRL: {
159
      unsigned long c = 0x0;
160
      if (kbd_kresp || kbd_buf_count)
161
        c |= KBD_STATUS_OBF;
162
      c |= kbd_ccmdbyte & KBD_CCMDBYTE_SYS;
163
      c |= KBD_STATUS_INH;
164
      if (config.sim.verbose)
165
        printf("kbd_read8(%x) %x\n", addr, c);
166
      return c;
167
    }
168
    case KBD_DATA:
169
      if (kbd_ccmd) {
170
        unsigned long rc;
171
        if (kbd_ccmd == KBD_CCMD_RCB)
172
          rc = kbd_ccmdbyte;
173
        if (kbd_ccmd == KBD_CCMD_ST1)
174
          rc = 0x55;
175
        if (kbd_ccmd == KBD_CCMD_ST2)
176
          rc = 0x00;
177
        kbd_ccmd = 0x00;
178
        kbd_kresp = 0x0;
179
        if (config.sim.verbose)
180
          printf("kbd_read8(%x) %x\n", addr, rc);
181
        return rc;
182
      }
183
      else if (kbd_kresp) {
184
        unsigned long rc;
185
        if (kbd_kresp == 0x2) {
186
          kbd_kresp = 0x0;
187
          rc = KBD_KRESP_RSTOK;
188
        } else if (kbd_kcmd == KBD_KCMD_RST) {
189
          kbd_kresp = 0x2;
190
          rc = KBD_KRESP_ACK;
191
        } else if (kbd_kcmd == KBD_KCMD_ECHO) {
192
          kbd_kresp = 0x0;
193
          rc = KBD_KRESP_ECHO;
194
        } else {
195
          kbd_kresp = 0x0;
196
          rc = KBD_KRESP_ACK;
197
        }
198
        kbd_kcmd = 0x00;
199
        if (config.sim.verbose)
200
          printf("kbd_read8(%x) %x\n", addr, rc);
201
        return rc;
202
      } else if (kbd_buf_count) {
203 664 markom
        unsigned long c = kbd_buf[kbd_buf_tail];
204
        kbd_buf_tail = (kbd_buf_tail + 1) % KBD_MAX_BUF;
205
        kbd_buf_count--;
206 684 lampret
        kbd_kresp = 0x0;
207
        if (config.sim.verbose)
208
          printf("kbd_read8(%x) %x\n", addr, c);
209 664 markom
        return c;
210
      }
211 684 lampret
      kbd_kresp = 0x0;
212
      if (config.sim.verbose)
213
        printf("kbd_read8(%x) fifo empty\n", addr);
214 664 markom
      return 0;
215
    default:
216
      fprintf (stderr, "Read out of keyboard space (0x%08x)!\n", addr);
217
      cont_run = 0;
218
      return 0;
219
  }
220 670 markom
}
221 664 markom
 
222
/* Reset all VGAs */
223
void kbd_reset ()
224
{
225
  if (config.kbd.enabled) {
226
    kbd_buf_count = 0;
227
    kbd_buf_head = 0;
228
    kbd_buf_tail = 0;
229 684 lampret
    kbd_kresp = 0x0;
230
    kbd_ccmdbyte = 0x65; /* We reset into default normal operation. */
231 664 markom
    register_memoryarea(config.kbd.baseaddr, KBD_SPACE, 1, kbd_read8, kbd_write8);
232
 
233
    if (!(kbd_rxfs = fopen(config.kbd.rxfile, "r"))
234
     && !(kbd_rxfs = fopen(config.kbd.rxfile, "r+"))) {
235
      fprintf (stderr, "WARNING: Keyboard has problems with RX file stream.\n");
236
    }
237
  }
238
}
239
 
240 684 lampret
 
241
void kbd_info()
242
{
243
        printf("kbd_kcmd: %x\n", kbd_kcmd);
244
        printf("kbd_ccmd: %x\n", kbd_ccmd);
245
        printf("kbd_ccmdbyte: %x\n", kbd_ccmdbyte);
246
        printf("kbd_kresp: %x\n", kbd_kresp);
247
        printf("kbd_buf_count: %x\n", kbd_buf_count);
248
}
249
 
250 664 markom
/* Simulation hook. Must be called every clock cycle to simulate incomming data. */
251
void kbd_clock()
252
{
253
  int c;
254 684 lampret
  int kbd_int = 0;
255 664 markom
  /* Check if there is something waiting, and decode it into kdb_buf */
256
  if((c = fgetc(kbd_rxfs)) != EOF) {
257
    scan_decode (c);
258
  }
259 684 lampret
  kbd_int = kbd_kresp || kbd_buf_count;
260
  kbd_int = kbd_kresp || kbd_buf_count ? kbd_ccmdbyte & KBD_CCMDBYTE_INT : 0;
261
  if (config.sim.verbose && kbd_int)
262
    printf("Keyboard Interrupt.... kbd_kresp %x  kbd_buf_count %x \n", kbd_kresp, kbd_buf_count);
263
  if (kbd_int) report_interrupt(config.kbd.irq);
264 664 markom
}

powered by: WebSVN 2.1.0

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