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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [ps2kbd.c] - Blame information for rev 146

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

Line No. Rev Author Line
1 19 jeremybenn
/* ps2kbd.c -- Very simple (and limited) PS/2 keyboard simulation
2
 
3
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14
 
15
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19
 
20
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
#include "port.h"
30
 
31
/* System includes */
32
#include <stdlib.h>
33
#include <stdio.h>
34
 
35
/* Package includes */
36
#include "arch.h"
37
#include "pic.h"
38
#include "sim-config.h"
39
#include "abstract.h"
40
#include "sched.h"
41
#include "toplevel-support.h"
42
#include "sim-cmd.h"
43
 
44
 
45
/* Device registers */
46
#define KBD_CTRL              4
47
#define KBD_DATA              0
48
#define KBD_SPACE             8
49
 
50
/* Keyboard commands */
51
#define KBD_KCMD_RST       0xFF
52
#define KBD_KCMD_DK        0xF5
53
#define KBD_KCMD_EK        0xF4
54
#define KBD_KCMD_ECHO      0xFF
55
#define KBD_KCMD_SRL       0xED
56
 
57
/* Keyboard responses */
58
#define KBD_KRESP_RSTOK    0xAA
59
#define KBD_KRESP_ECHO     0xEE
60
#define KBD_KRESP_ACK      0xFA
61
 
62
/* Controller commands */
63
#define KBD_CCMD_RCB       0x20
64
#define KBD_CCMD_WCB       0x60
65
#define KBD_CCMD_ST1       0xAA
66
#define KBD_CCMD_ST2       0xAB
67
#define KBD_CCMD_DKI       0xAD
68
#define KBD_CCMD_EKI       0xAE
69
 
70
/* Status register bits */
71
#define KBD_STATUS_OBF     0x01
72
#define KBD_STATUS_IBF     0x02
73
#define KBD_STATUS_SYS     0x04
74
#define KBD_STATUS_A2      0x08
75
#define KBD_STATUS_INH     0x10
76
#define KBD_STATUS_MOBF    0x20
77
#define KBD_STATUS_TO      0x40
78
#define KBD_STATUS_PERR    0x80
79
 
80
/* Command byte register bits */
81
#define KBD_CCMDBYTE_INT   0x01
82
#define KBD_CCMDBYTE_INT2  0x02
83
#define KBD_CCMDBYTE_SYS   0x04
84
#define KBD_CCMDBYTE_EN    0x10
85
#define KBD_CCMDBYTE_EN2   0x20
86
#define KBD_CCMDBYTE_XLAT  0x40
87
 
88
/* Length of internal scan code fifo */
89
#define KBD_MAX_BUF       0x100
90
 
91
/* Keyboard is checked every KBD_SLOWDOWN cycle */
92
#define KBD_BAUD_RATE      1200
93
 
94
/* ASCII to scan code conversion table */
95
const static struct
96
{
97
  /* Whether shift must be pressed */
98
  unsigned char shift;
99
  /* Scan code to be generated */
100
  unsigned char code;
101
} scan_table[128] =
102
{
103
/* 0 - 15 */
104
  {
105
  0, 0x00},
106
  {
107
  0, 0x00},
108
  {
109
  0, 0x00},
110
  {
111
  0, 0x00},
112
  {
113
  0, 0x00},
114
  {
115
  0, 0x00},
116
  {
117
  0, 0x00},
118
  {
119
  0, 0x00},
120
  {
121
  0, 0x0E},
122
  {
123
  0, 0x0F},
124
  {
125
  0, 0x1C},
126
  {
127
  0, 0x00},
128
  {
129
  0, 0x00},
130
  {
131
  0, 0x00},
132
  {
133
  0, 0x00},
134
  {
135
  0, 0x00},
136
/* 16 - 31 */
137
  {
138
  0, 0x00},
139
  {
140
  0, 0x00},
141
  {
142
  0, 0x00},
143
  {
144
  0, 0x00},
145
  {
146
  0, 0x00},
147
  {
148
  0, 0x00},
149
  {
150
  0, 0x00},
151
  {
152
  0, 0x00},
153
  {
154
  0, 0x00},
155
  {
156
  0, 0x00},
157
  {
158
  0, 0x00},
159
  {
160
  0, 0x01},
161
  {
162
  0, 0x00},
163
  {
164
  0, 0x00},
165
  {
166
  0, 0x00},
167
  {
168
  0, 0x00},
169
/* 32 - 47 */
170
  {
171
  0, 0x39},
172
  {
173
  1, 0x02},
174
  {
175
  1, 0x28},
176
  {
177
  1, 0x04},
178
  {
179
  1, 0x05},
180
  {
181
  1, 0x06},
182
  {
183
  1, 0x08},
184
  {
185
  0, 0x28},
186
  {
187
  1, 0x0A},
188
  {
189
  1, 0x0B},
190
  {
191
  1, 0x09},
192
  {
193
  1, 0x0D},
194
  {
195
  0, 0x33},
196
  {
197
  0, 0x0C},
198
  {
199
  0, 0x34},
200
  {
201
  0, 0x35},
202
/* 48 - 63 */
203
  {
204
  0, 0x0B},
205
  {
206
  0, 0x02},
207
  {
208
  0, 0x03},
209
  {
210
  0, 0x04},
211
  {
212
  0, 0x05},
213
  {
214
  0, 0x06},
215
  {
216
  0, 0x07},
217
  {
218
  0, 0x08},
219
  {
220
  0, 0x09},
221
  {
222
  0, 0x0A},
223
  {
224
  1, 0x27},
225
  {
226
  0, 0x27},
227
  {
228
  1, 0x33},
229
  {
230
  0, 0x0D},
231
  {
232
  1, 0x34},
233
  {
234
  1, 0x35},
235
/* 64 - 79 */
236
  {
237
  1, 0x03},
238
  {
239
  1, 0x1E},
240
  {
241
  1, 0x30},
242
  {
243
  1, 0x2E},
244
  {
245
  1, 0x20},
246
  {
247
  1, 0x12},
248
  {
249
  1, 0x21},
250
  {
251
  1, 0x22},
252
  {
253
  1, 0x23},
254
  {
255
  1, 0x17},
256
  {
257
  1, 0x24},
258
  {
259
  1, 0x25},
260
  {
261
  1, 0x26},
262
  {
263
  1, 0x32},
264
  {
265
  1, 0x31},
266
  {
267
  1, 0x18},
268
/* 80 - 95 */
269
  {
270
  1, 0x19},
271
  {
272
  1, 0x10},
273
  {
274
  1, 0x13},
275
  {
276
  1, 0x1F},
277
  {
278
  1, 0x14},
279
  {
280
  1, 0x16},
281
  {
282
  1, 0x2F},
283
  {
284
  1, 0x11},
285
  {
286
  1, 0x2D},
287
  {
288
  1, 0x15},
289
  {
290
  1, 0x2C},
291
  {
292
  0, 0x1A},
293
  {
294
  0, 0x2B},
295
  {
296
  0, 0x1B},
297
  {
298
  1, 0x07},
299
  {
300
  1, 0x0C},
301
/* 96 - 111 */
302
  {
303
  0, 0x29},
304
  {
305
  0, 0x1E},
306
  {
307
  0, 0x30},
308
  {
309
  0, 0x2E},
310
  {
311
  0, 0x20},
312
  {
313
  0, 0x12},
314
  {
315
  0, 0x21},
316
  {
317
  0, 0x22},
318
  {
319
  0, 0x23},
320
  {
321
  0, 0x17},
322
  {
323
  0, 0x24},
324
  {
325
  0, 0x25},
326
  {
327
  0, 0x26},
328
  {
329
  0, 0x32},
330
  {
331
  0, 0x31},
332
  {
333
  0, 0x18},
334
/* 112 - 127 */
335
  {
336
  0, 0x19},
337
  {
338
  0, 0x10},
339
  {
340
  0, 0x13},
341
  {
342
  0, 0x1F},
343
  {
344
  0, 0x14},
345
  {
346
  0, 0x16},
347
  {
348
  0, 0x2F},
349
  {
350
  0, 0x11},
351
  {
352
  0, 0x2D},
353
  {
354
  0, 0x15},
355
  {
356
  0, 0x2C},
357
  {
358
  1, 0x1A},
359
  {
360
  1, 0x2B},
361
  {
362
  1, 0x1B},
363
  {
364
  1, 0x29},
365
  {
366
  0, 0x00}
367
};
368
 
369
struct kbd_state
370
{
371
  /* Temporary buffer to store incoming scan codes */
372
  uint8_t buf[KBD_MAX_BUF];
373
 
374
  /* Number of scan codes in buffer */
375
  unsigned long buf_count;
376
  unsigned long buf_head;
377
  unsigned long buf_tail;
378
 
379
  /* Input stream */
380
  FILE *rxfs;
381
 
382
  /* Controller Command (write into 0x64) */
383
  int ccmd;
384
 
385
  /* Keyboard Command (write into 0x60) */
386
  uint8_t kcmd;
387
 
388
  /* Controller Command Byte */
389
  uint8_t ccmdbyte;
390
 
391
  /* Keyboard response pending */
392
  unsigned long kresp;
393
 
394
  /* Keyboard slowdown factor */
395
  long slowdown;
396
 
397
  /* Cofiguration */
398
  int enabled;
399
  int irq;
400
  oraddr_t baseaddr;
401
  char *rxfile;
402
};
403
 
404
static void
405
kbd_put (struct kbd_state *kbd, unsigned char c)
406
{
407
  if (kbd->buf_count >= KBD_MAX_BUF)
408
    {
409
      fprintf (stderr, "WARNING: Keyboard buffer overflow.\n");
410
    }
411
  else
412
    {
413
      kbd->buf[kbd->buf_head] = c;
414
      kbd->buf_head = (kbd->buf_head + 1) % KBD_MAX_BUF;
415
      kbd->buf_count++;
416
    }
417
}
418
 
419
/* Decodes ascii code c into multiple scan codes, placed into buf, length is returned */
420
static void
421
scan_decode (struct kbd_state *kbd, unsigned char c)
422
{
423
  /* Do not handle special characters and extended ascii */
424
  if (c >= 128 || !scan_table[c].code)
425
    return;
426
 
427
  /* Make shift? */
428
  if (scan_table[c].shift)
429
    kbd_put (kbd, 0x2a);
430
  /* Make char */
431
  kbd_put (kbd, scan_table[c].code);
432
  /* Break char */
433
  kbd_put (kbd, scan_table[c].code | 0x80);
434
  /* Break shift? */
435
  if (scan_table[c].shift)
436
    kbd_put (kbd, 0xaa);
437
}
438
 
439
/* Write a register */
440
static void
441
kbd_write8 (oraddr_t addr, uint8_t value, void *dat)
442
{
443
  struct kbd_state *kbd = dat;
444
  switch (addr)
445
    {
446
    case KBD_CTRL:
447
      kbd->ccmd = value & 0xff;
448
      if (kbd->ccmd == KBD_CCMD_RCB)
449
        kbd->kresp = 0x1;
450
      if (kbd->ccmd == KBD_CCMD_ST1)
451
        kbd->kresp = 0x1;
452
      if (kbd->ccmd == KBD_CCMD_ST2)
453
        kbd->kresp = 0x1;
454
      if (kbd->ccmd == KBD_CCMD_DKI)
455
        {
456
          clear_interrupt (kbd->irq);
457
          kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
458
        }
459
      if (kbd->ccmd == KBD_CCMD_EKI)
460
        kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
461
      if (config.sim.verbose)
462
        PRINTF ("kbd_write8(%" PRIxADDR ") %02x\n", addr, value);
463
      break;
464
    case KBD_DATA:
465
      if (kbd->ccmd == KBD_CCMD_WCB)
466
        {
467
          kbd->ccmdbyte = value & 0xff;
468
          kbd->ccmd = 0x00;
469
        }
470
      else
471
        kbd->kcmd = value & 0xff;
472
      if (kbd->kcmd == KBD_KCMD_DK)
473
        kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
474
      if (kbd->kcmd == KBD_KCMD_EK)
475
        kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
476
      kbd->kresp = 0x1;
477
      kbd->ccmd = 0x00;
478
      if (config.sim.verbose)
479
        PRINTF ("kbd_write8(%" PRIxADDR ") %02x\n", addr, value);
480
      break;
481
    default:
482
      fprintf (stderr, "Write out of keyboard space (0x%" PRIxADDR ")!\n",
483
               addr);
484
      break;
485
    }
486
}
487
 
488
/* Read a register */
489
static uint8_t
490
kbd_read8 (oraddr_t addr, void *dat)
491
{
492
  struct kbd_state *kbd = dat;
493
  switch (addr)
494
    {
495
    case KBD_CTRL:
496
      {
497
        unsigned long c = 0x0;
498
        if (kbd->kresp || kbd->buf_count)
499
          c |= KBD_STATUS_OBF;
500
        c |= kbd->ccmdbyte & KBD_CCMDBYTE_SYS;
501
        c |= KBD_STATUS_INH;
502
        if (config.sim.verbose)
503
          PRINTF ("kbd_read8(%" PRIxADDR ") %lx\n", addr, c);
504
        return c;
505
      }
506
    case KBD_DATA:
507
      clear_interrupt (kbd->irq);
508
      if (kbd->ccmd)
509
        {
510
          unsigned long rc = 0;
511
          if (kbd->ccmd == KBD_CCMD_RCB)
512
            rc = kbd->ccmdbyte;
513
          if (kbd->ccmd == KBD_CCMD_ST1)
514
            rc = 0x55;
515
          if (kbd->ccmd == KBD_CCMD_ST2)
516
            rc = 0x00;
517
          kbd->ccmd = 0x00;
518
          kbd->kresp = 0x0;
519
          if (config.sim.verbose)
520
            PRINTF ("kbd_read8(%" PRIxADDR ") %lx\n", addr, rc);
521
          return rc;
522
        }
523
      else if (kbd->kresp)
524
        {
525
          unsigned long rc;
526
          if (kbd->kresp == 0x2)
527
            {
528
              kbd->kresp = 0x0;
529
              rc = KBD_KRESP_RSTOK;
530
            }
531
          else if (kbd->kcmd == KBD_KCMD_RST)
532
            {
533
              kbd->kresp = 0x2;
534
              rc = KBD_KRESP_ACK;
535
            }
536
          else if (kbd->kcmd == KBD_KCMD_ECHO)
537
            {
538
              kbd->kresp = 0x0;
539
              rc = KBD_KRESP_ECHO;
540
            }
541
          else
542
            {
543
              kbd->kresp = 0x0;
544
              rc = KBD_KRESP_ACK;
545
            }
546
          kbd->kcmd = 0x00;
547
          if (config.sim.verbose)
548
            PRINTF ("kbd_read8(%" PRIxADDR ") %lx\n", addr, rc);
549
          return rc;
550
        }
551
      else if (kbd->buf_count)
552
        {
553
          unsigned long c = kbd->buf[kbd->buf_tail];
554
          kbd->buf_tail = (kbd->buf_tail + 1) % KBD_MAX_BUF;
555
          kbd->buf_count--;
556
          kbd->kresp = 0x0;
557
          if (config.sim.verbose)
558
            PRINTF ("kbd_read8(%" PRIxADDR ") %lx\n", addr, c);
559
          return c;
560
        }
561
      kbd->kresp = 0x0;
562
      if (config.sim.verbose)
563
        PRINTF ("kbd_read8(%" PRIxADDR ") fifo empty\n", addr);
564
      return 0;
565
    default:
566
      fprintf (stderr, "Read out of keyboard space (0x%" PRIxADDR ")!\n",
567
               addr);
568
      return 0;
569
    }
570
}
571
 
572
 
573
/* Simulation hook. Must be called every couple of clock cycles to simulate incomming data. */
574
static void
575
kbd_job (void *dat)
576
{
577
  struct kbd_state *kbd = dat;
578
  int c;
579
  int kbd_int = 0;
580
 
581
  /* Check if there is something waiting, and decode it into kdb_buf */
582
  if ((c = fgetc (kbd->rxfs)) != EOF)
583
    {
584
      scan_decode (kbd, c);
585
    }
586
  kbd_int = kbd->kresp
587
    || kbd->buf_count ? kbd->ccmdbyte & KBD_CCMDBYTE_INT : 0;
588
/*
589
  if (config.sim.verbose && kbd_int)
590
    PRINTF("Keyboard Interrupt.... kbd_kresp %lx  kbd_buf_count %lx \n",
591
           kbd->kresp, kbd->buf_count);
592
*/
593
  if (kbd_int)
594
    report_interrupt (kbd->irq);
595
  SCHED_ADD (kbd_job, dat, kbd->slowdown);
596
}
597
 
598
/* Reset all (simulated) ps2 controlers/keyboards */
599
static void
600
kbd_reset (void *dat)
601
{
602
  struct kbd_state *kbd = dat;
603
  long int system_kfreq =
604
    (long) ((1000000000.0 / (double) config.sim.clkcycle_ps));
605
 
606
  system_kfreq = (system_kfreq < 1) ? 1 : system_kfreq;
607
 
608
  kbd->buf_count = 0;
609
  kbd->buf_head = 0;
610
  kbd->buf_tail = 0;
611
  kbd->kresp = 0x0;
612
  kbd->ccmdbyte = 0x65;         /* We reset into default normal operation. */
613
 
614
  if (!(kbd->rxfs = fopen (kbd->rxfile, "r"))
615
      && !(kbd->rxfs = fopen (kbd->rxfile, "r+")))
616
    {
617 86 jeremybenn
      /* Bug 1723 fixed: Clearer message */
618
      fprintf (stderr,
619 87 jeremybenn
               "Warning: PS2 keyboard unable to open RX file stream.\n");
620 19 jeremybenn
      return;
621
    }
622
  kbd->slowdown = (long) ((system_kfreq * 1000.0) / KBD_BAUD_RATE);
623
  if (kbd->slowdown <= 0)
624
    kbd->slowdown = 1;
625
  SCHED_ADD (kbd_job, dat, kbd->slowdown);
626
}
627
 
628
 
629
static void
630
kbd_info (void *dat)
631
{
632
  struct kbd_state *kbd = dat;
633
  PRINTF ("kbd_kcmd: %x\n", kbd->kcmd);
634
  PRINTF ("kbd_ccmd: %x\n", kbd->ccmd);
635
  PRINTF ("kbd_ccmdbyte: %x\n", kbd->ccmdbyte);
636
  PRINTF ("kbd_kresp: %lx\n", kbd->kresp);
637
  PRINTF ("kbd_buf_count: %lx\n", kbd->buf_count);
638
}
639
 
640
/*----------------------------------------------------[ KBD Configuration ]---*/
641
 
642
 
643
static void
644
kbd_enabled (union param_val val, void *dat)
645
{
646
  struct kbd_state *kbd = dat;
647
  kbd->enabled = val.int_val;
648
}
649
 
650
 
651
static void
652
kbd_baseaddr (union param_val val, void *dat)
653
{
654
  struct kbd_state *kbd = dat;
655
  kbd->baseaddr = val.addr_val;
656
}
657
 
658
 
659
static void
660
kbd_irq (union param_val val, void *dat)
661
{
662
  struct kbd_state *kbd = dat;
663
  kbd->irq = val.int_val;
664
}
665
 
666
 
667
/*---------------------------------------------------------------------------*/
668
/*!Set the keyboard input file
669
 
670
   Free any previously allocated value.
671
 
672
   @param[in] val  The value to use
673
   @param[in] dat  The config data structure                                 */
674
/*---------------------------------------------------------------------------*/
675
static void
676
kbd_rxfile (union param_val val, void *dat)
677
{
678
  struct kbd_state *kbd = dat;
679
 
680
  if (NULL != kbd->rxfile)
681
    {
682
      free (kbd->rxfile);
683
      kbd->rxfile = NULL;
684
    }
685
 
686
  if (!(kbd->rxfile = strdup (val.str_val)))
687
    {
688
      fprintf (stderr, "Peripheral KBD: Run out of memory\n");
689
      exit (-1);
690
    }
691
}                               /* kbd_rxfile() */
692
 
693
 
694
/*---------------------------------------------------------------------------*/
695
/*!Initialize a new keyboard configuration
696
 
697
   ALL parameters are set explicitly to default values.                      */
698
/*---------------------------------------------------------------------------*/
699
static void *
700
kbd_sec_start ()
701
{
702
  struct kbd_state *new = malloc (sizeof (struct kbd_state));
703
 
704
  if (!new)
705
    {
706
      fprintf (stderr, "Peripheral KBD: Run out of memory\n");
707
      exit (-1);
708
    }
709
 
710
  new->enabled = 1;
711
  new->baseaddr = 0;
712
  new->irq = 0;
713
  new->rxfile = strdup ("kbd_in");
714
 
715
  new->buf_count = 0;
716
  new->buf_head = 0;
717
  new->buf_tail = 0;
718
  new->rxfs = NULL;
719
 
720
  return new;
721
 
722
}                               /* kbd_sec_start() */
723
 
724
 
725
static void
726
kbd_sec_end (void *dat)
727
{
728
  struct kbd_state *kbd = dat;
729
  struct mem_ops ops;
730
 
731
  if (!kbd->enabled)
732
    {
733
      free (kbd->rxfile);
734
      free (kbd);
735
      return;
736
    }
737
 
738
  memset (&ops, 0, sizeof (struct mem_ops));
739
 
740
  ops.readfunc8 = kbd_read8;
741
  ops.writefunc8 = kbd_write8;
742
  ops.read_dat8 = dat;
743
  ops.write_dat8 = dat;
744
 
745
  /* FIXME: Correct delay? */
746
  ops.delayr = 2;
747
  ops.delayw = 2;
748
 
749
  reg_mem_area (kbd->baseaddr, KBD_SPACE, 0, &ops);
750
  reg_sim_reset (kbd_reset, dat);
751
  reg_sim_stat (kbd_info, dat);
752
}
753
 
754
void
755
reg_kbd_sec ()
756
{
757
  struct config_section *sec =
758
    reg_config_sec ("kbd", kbd_sec_start, kbd_sec_end);
759
 
760
  reg_config_param (sec, "baseaddr", paramt_addr, kbd_baseaddr);
761
  reg_config_param (sec, "enabled", paramt_int, kbd_enabled);
762
  reg_config_param (sec, "irq", paramt_int, kbd_irq);
763
  reg_config_param (sec, "rxfile", paramt_str, kbd_rxfile);
764
}

powered by: WebSVN 2.1.0

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