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 997

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

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

powered by: WebSVN 2.1.0

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