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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [peripheral/] [ps2kbd.c] - Diff between revs 1446 and 1461

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 1446 Rev 1461
/* ps2kbd.c -- Very simple (and limited) PS/2 keyboard simulation
/* ps2kbd.c -- Very simple (and limited) PS/2 keyboard simulation
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
   Copyright (C) 2002 Marko Mlinar, markom@opencores.org
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
This file is part of OpenRISC 1000 Architectural Simulator.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
 
 
#include "config.h"
#include "config.h"
 
 
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "port.h"
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "ps2kbd.h"
#include "ps2kbd.h"
#include "sim-config.h"
#include "sim-config.h"
#include "abstract.h"
#include "abstract.h"
#include "sched.h"
#include "sched.h"
#include "pic.h"
#include "pic.h"
 
 
/* ASCII to scan code conversion table */
/* ASCII to scan code conversion table */
const static struct {
const static struct {
  /* Whether shift must be pressed */
  /* Whether shift must be pressed */
  unsigned char shift;
  unsigned char shift;
  /* Scan code to be generated */
  /* Scan code to be generated */
  unsigned char code;
  unsigned char code;
} scan_table [128] = {
} scan_table [128] = {
/* 0 - 15 */
/* 0 - 15 */
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
{0, 0x0E}, {0, 0x0F}, {0, 0x1C}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
{0, 0x0E}, {0, 0x0F}, {0, 0x1C}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
/* 16 - 31 */
/* 16 - 31 */
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x01}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x01}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
/* 32 - 47 */
/* 32 - 47 */
{0, 0x39}, {1, 0x02}, {1, 0x28}, {1, 0x04}, {1, 0x05}, {1, 0x06}, {1, 0x08}, {0, 0x28},
{0, 0x39}, {1, 0x02}, {1, 0x28}, {1, 0x04}, {1, 0x05}, {1, 0x06}, {1, 0x08}, {0, 0x28},
{1, 0x0A}, {1, 0x0B}, {1, 0x09}, {1, 0x0D}, {0, 0x33}, {0, 0x0C}, {0, 0x34}, {0, 0x35},
{1, 0x0A}, {1, 0x0B}, {1, 0x09}, {1, 0x0D}, {0, 0x33}, {0, 0x0C}, {0, 0x34}, {0, 0x35},
/* 48 - 63 */
/* 48 - 63 */
{0, 0x0B}, {0, 0x02}, {0, 0x03}, {0, 0x04}, {0, 0x05}, {0, 0x06}, {0, 0x07}, {0, 0x08},
{0, 0x0B}, {0, 0x02}, {0, 0x03}, {0, 0x04}, {0, 0x05}, {0, 0x06}, {0, 0x07}, {0, 0x08},
{0, 0x09}, {0, 0x0A}, {1, 0x27}, {0, 0x27}, {1, 0x33}, {0, 0x0D}, {1, 0x34}, {1, 0x35},
{0, 0x09}, {0, 0x0A}, {1, 0x27}, {0, 0x27}, {1, 0x33}, {0, 0x0D}, {1, 0x34}, {1, 0x35},
/* 64 - 79 */
/* 64 - 79 */
{1, 0x03}, {1, 0x1E}, {1, 0x30}, {1, 0x2E}, {1, 0x20}, {1, 0x12}, {1, 0x21}, {1, 0x22},
{1, 0x03}, {1, 0x1E}, {1, 0x30}, {1, 0x2E}, {1, 0x20}, {1, 0x12}, {1, 0x21}, {1, 0x22},
{1, 0x23}, {1, 0x17}, {1, 0x24}, {1, 0x25}, {1, 0x26}, {1, 0x32}, {1, 0x31}, {1, 0x18},
{1, 0x23}, {1, 0x17}, {1, 0x24}, {1, 0x25}, {1, 0x26}, {1, 0x32}, {1, 0x31}, {1, 0x18},
/* 80 - 95 */
/* 80 - 95 */
{1, 0x19}, {1, 0x10}, {1, 0x13}, {1, 0x1F}, {1, 0x14}, {1, 0x16}, {1, 0x2F}, {1, 0x11},
{1, 0x19}, {1, 0x10}, {1, 0x13}, {1, 0x1F}, {1, 0x14}, {1, 0x16}, {1, 0x2F}, {1, 0x11},
{1, 0x2D}, {1, 0x15}, {1, 0x2C}, {0, 0x1A}, {0, 0x2B}, {0, 0x1B}, {1, 0x07}, {1, 0x0C},
{1, 0x2D}, {1, 0x15}, {1, 0x2C}, {0, 0x1A}, {0, 0x2B}, {0, 0x1B}, {1, 0x07}, {1, 0x0C},
/* 96 - 111 */
/* 96 - 111 */
{0, 0x29}, {0, 0x1E}, {0, 0x30}, {0, 0x2E}, {0, 0x20}, {0, 0x12}, {0, 0x21}, {0, 0x22},
{0, 0x29}, {0, 0x1E}, {0, 0x30}, {0, 0x2E}, {0, 0x20}, {0, 0x12}, {0, 0x21}, {0, 0x22},
{0, 0x23}, {0, 0x17}, {0, 0x24}, {0, 0x25}, {0, 0x26}, {0, 0x32}, {0, 0x31}, {0, 0x18},
{0, 0x23}, {0, 0x17}, {0, 0x24}, {0, 0x25}, {0, 0x26}, {0, 0x32}, {0, 0x31}, {0, 0x18},
/* 112 - 127 */
/* 112 - 127 */
{0, 0x19}, {0, 0x10}, {0, 0x13}, {0, 0x1F}, {0, 0x14}, {0, 0x16}, {0, 0x2F}, {0, 0x11},
{0, 0x19}, {0, 0x10}, {0, 0x13}, {0, 0x1F}, {0, 0x14}, {0, 0x16}, {0, 0x2F}, {0, 0x11},
{0, 0x2D}, {0, 0x15}, {0, 0x2C}, {1, 0x1A}, {1, 0x2B}, {1, 0x1B}, {1, 0x29}, {0, 0x00}
{0, 0x2D}, {0, 0x15}, {0, 0x2C}, {1, 0x1A}, {1, 0x2B}, {1, 0x1B}, {1, 0x29}, {0, 0x00}
};
};
 
 
struct kbd_state {
struct kbd_state {
  /* Temporary buffer to store incoming scan codes */
  /* Temporary buffer to store incoming scan codes */
  uint8_t buf[KBD_MAX_BUF];
  uint8_t buf[KBD_MAX_BUF];
 
 
  /* Number of scan codes in buffer */
  /* Number of scan codes in buffer */
  unsigned long buf_count;
  unsigned long buf_count;
  unsigned long buf_head;
  unsigned long buf_head;
  unsigned long buf_tail;
  unsigned long buf_tail;
 
 
  /* Input stream */
  /* Input stream */
  FILE *rxfs;
  FILE *rxfs;
 
 
  /* Controller Command (write into 0x64) */
  /* Controller Command (write into 0x64) */
  int ccmd;
  int ccmd;
 
 
  /* Keyboard Command (write into 0x60) */
  /* Keyboard Command (write into 0x60) */
  uint8_t kcmd;
  uint8_t kcmd;
 
 
  /* Controller Command Byte */
  /* Controller Command Byte */
  uint8_t ccmdbyte;
  uint8_t ccmdbyte;
 
 
  /* Keyboard response pending */
  /* Keyboard response pending */
  unsigned long kresp;
  unsigned long kresp;
 
 
  /* Keyboard slowdown factor */
  /* Keyboard slowdown factor */
  long slowdown;
  long slowdown;
 
 
  /* Cofiguration */
  /* Cofiguration */
 
  int enabled;
  int irq;
  int irq;
  oraddr_t baseaddr;
  oraddr_t baseaddr;
  char *rxfile;
  char *rxfile;
};
};
 
 
static void kbd_put (struct kbd_state *kbd, unsigned char c)
static void kbd_put (struct kbd_state *kbd, unsigned char c)
{
{
  if (kbd->buf_count >= KBD_MAX_BUF) {
  if (kbd->buf_count >= KBD_MAX_BUF) {
    fprintf (stderr, "WARNING: Keyboard buffer overflow.\n");
    fprintf (stderr, "WARNING: Keyboard buffer overflow.\n");
  } else {
  } else {
    kbd->buf[kbd->buf_head] = c;
    kbd->buf[kbd->buf_head] = c;
    kbd->buf_head = (kbd->buf_head + 1) % KBD_MAX_BUF;
    kbd->buf_head = (kbd->buf_head + 1) % KBD_MAX_BUF;
    kbd->buf_count++;
    kbd->buf_count++;
  }
  }
}
}
 
 
/* Decodes ascii code c into multiple scan codes, placed into buf, length is returned */
/* Decodes ascii code c into multiple scan codes, placed into buf, length is returned */
static void scan_decode (struct kbd_state *kbd, unsigned char c)
static void scan_decode (struct kbd_state *kbd, unsigned char c)
{
{
  /* Do not handle special characters and extended ascii */
  /* Do not handle special characters and extended ascii */
  if (c >= 128 || !scan_table[c].code)
  if (c >= 128 || !scan_table[c].code)
    return;
    return;
 
 
  /* Make shift? */
  /* Make shift? */
  if (scan_table[c].shift) kbd_put (kbd, 0x2a);
  if (scan_table[c].shift) kbd_put (kbd, 0x2a);
  /* Make char */
  /* Make char */
  kbd_put (kbd, scan_table[c].code);
  kbd_put (kbd, scan_table[c].code);
  /* Break char */
  /* Break char */
  kbd_put (kbd, scan_table[c].code | 0x80);
  kbd_put (kbd, scan_table[c].code | 0x80);
  /* Break shift? */
  /* Break shift? */
  if (scan_table[c].shift) kbd_put (kbd, 0xaa);
  if (scan_table[c].shift) kbd_put (kbd, 0xaa);
}
}
 
 
/* Write a register */
/* Write a register */
void kbd_write8 (oraddr_t addr, uint32_t value, void *dat)
void kbd_write8 (oraddr_t addr, uint32_t value, void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
  int a = (addr - kbd->baseaddr);
  int a = (addr - kbd->baseaddr);
  switch (a) {
  switch (a) {
    case KBD_CTRL:
    case KBD_CTRL:
      kbd->ccmd = value & 0xff;
      kbd->ccmd = value & 0xff;
      if (kbd->ccmd == KBD_CCMD_RCB)
      if (kbd->ccmd == KBD_CCMD_RCB)
          kbd->kresp = 0x1;
          kbd->kresp = 0x1;
      if (kbd->ccmd == KBD_CCMD_ST1)
      if (kbd->ccmd == KBD_CCMD_ST1)
          kbd->kresp = 0x1;
          kbd->kresp = 0x1;
      if (kbd->ccmd == KBD_CCMD_ST2)
      if (kbd->ccmd == KBD_CCMD_ST2)
          kbd->kresp = 0x1;
          kbd->kresp = 0x1;
      if (kbd->ccmd == KBD_CCMD_DKI)
      if (kbd->ccmd == KBD_CCMD_DKI)
        kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
        kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
      if (kbd->ccmd == KBD_CCMD_EKI)
      if (kbd->ccmd == KBD_CCMD_EKI)
        kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
        kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
      if (config.sim.verbose)
      if (config.sim.verbose)
        PRINTF("kbd_write8(%"PRIxADDR") %"PRIx32"\n", addr, value);
        PRINTF("kbd_write8(%"PRIxADDR") %"PRIx32"\n", addr, value);
      break;
      break;
    case KBD_DATA:
    case KBD_DATA:
      if (kbd->ccmd == KBD_CCMD_WCB) {
      if (kbd->ccmd == KBD_CCMD_WCB) {
        kbd->ccmdbyte = value & 0xff;
        kbd->ccmdbyte = value & 0xff;
        kbd->ccmd = 0x00;
        kbd->ccmd = 0x00;
      } else
      } else
        kbd->kcmd = value & 0xff;
        kbd->kcmd = value & 0xff;
      if (kbd->kcmd == KBD_KCMD_DK)
      if (kbd->kcmd == KBD_KCMD_DK)
        kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
        kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
      if (kbd->kcmd == KBD_KCMD_EK)
      if (kbd->kcmd == KBD_KCMD_EK)
        kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
        kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
      kbd->kresp = 0x1;
      kbd->kresp = 0x1;
      kbd->ccmd = 0x00;
      kbd->ccmd = 0x00;
      if (config.sim.verbose)
      if (config.sim.verbose)
        PRINTF("kbd_write8(%"PRIxADDR") %"PRIx32"\n", addr, value);
        PRINTF("kbd_write8(%"PRIxADDR") %"PRIx32"\n", addr, value);
      break;
      break;
    default:
    default:
      fprintf (stderr, "Write out of keyboard space (0x%"PRIxADDR")!\n", addr);
      fprintf (stderr, "Write out of keyboard space (0x%"PRIxADDR")!\n", addr);
      runtime.sim.cont_run = 0;
      runtime.sim.cont_run = 0;
      break;
      break;
  }
  }
}
}
 
 
/* Read a register */
/* Read a register */
uint32_t kbd_read8 (oraddr_t addr, void *dat)
uint32_t kbd_read8 (oraddr_t addr, void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
  int a = (addr - kbd->baseaddr);
  int a = (addr - kbd->baseaddr);
  switch (a) {
  switch (a) {
    case KBD_CTRL: {
    case KBD_CTRL: {
      unsigned long c = 0x0;
      unsigned long c = 0x0;
      if (kbd->kresp || kbd->buf_count)
      if (kbd->kresp || kbd->buf_count)
        c |= KBD_STATUS_OBF;
        c |= KBD_STATUS_OBF;
      c |= kbd->ccmdbyte & KBD_CCMDBYTE_SYS;
      c |= kbd->ccmdbyte & KBD_CCMDBYTE_SYS;
      c |= KBD_STATUS_INH;
      c |= KBD_STATUS_INH;
      if (config.sim.verbose)
      if (config.sim.verbose)
        PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, c);
        PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, c);
      return c;
      return c;
    }
    }
    case KBD_DATA:
    case KBD_DATA:
      if (kbd->ccmd) {
      if (kbd->ccmd) {
        unsigned long rc;
        unsigned long rc;
        if (kbd->ccmd == KBD_CCMD_RCB)
        if (kbd->ccmd == KBD_CCMD_RCB)
          rc = kbd->ccmdbyte;
          rc = kbd->ccmdbyte;
        if (kbd->ccmd == KBD_CCMD_ST1)
        if (kbd->ccmd == KBD_CCMD_ST1)
          rc = 0x55;
          rc = 0x55;
        if (kbd->ccmd == KBD_CCMD_ST2)
        if (kbd->ccmd == KBD_CCMD_ST2)
          rc = 0x00;
          rc = 0x00;
        kbd->ccmd = 0x00;
        kbd->ccmd = 0x00;
        kbd->kresp = 0x0;
        kbd->kresp = 0x0;
        if (config.sim.verbose)
        if (config.sim.verbose)
          PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, rc);
          PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, rc);
        return rc;
        return rc;
      }
      }
      else if (kbd->kresp) {
      else if (kbd->kresp) {
        unsigned long rc;
        unsigned long rc;
        if (kbd->kresp == 0x2) {
        if (kbd->kresp == 0x2) {
          kbd->kresp = 0x0;
          kbd->kresp = 0x0;
          rc = KBD_KRESP_RSTOK;
          rc = KBD_KRESP_RSTOK;
        } else if (kbd->kcmd == KBD_KCMD_RST) {
        } else if (kbd->kcmd == KBD_KCMD_RST) {
          kbd->kresp = 0x2;
          kbd->kresp = 0x2;
          rc = KBD_KRESP_ACK;
          rc = KBD_KRESP_ACK;
        } else if (kbd->kcmd == KBD_KCMD_ECHO) {
        } else if (kbd->kcmd == KBD_KCMD_ECHO) {
          kbd->kresp = 0x0;
          kbd->kresp = 0x0;
          rc = KBD_KRESP_ECHO;
          rc = KBD_KRESP_ECHO;
        } else {
        } else {
          kbd->kresp = 0x0;
          kbd->kresp = 0x0;
          rc = KBD_KRESP_ACK;
          rc = KBD_KRESP_ACK;
        }
        }
        kbd->kcmd = 0x00;
        kbd->kcmd = 0x00;
        if (config.sim.verbose)
        if (config.sim.verbose)
          PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, rc);
          PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, rc);
        return rc;
        return rc;
      } else if (kbd->buf_count) {
      } else if (kbd->buf_count) {
        unsigned long c = kbd->buf[kbd->buf_tail];
        unsigned long c = kbd->buf[kbd->buf_tail];
        kbd->buf_tail = (kbd->buf_tail + 1) % KBD_MAX_BUF;
        kbd->buf_tail = (kbd->buf_tail + 1) % KBD_MAX_BUF;
        kbd->buf_count--;
        kbd->buf_count--;
        kbd->kresp = 0x0;
        kbd->kresp = 0x0;
        if (config.sim.verbose)
        if (config.sim.verbose)
          PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, c);
          PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, c);
        return c;
        return c;
      }
      }
      kbd->kresp = 0x0;
      kbd->kresp = 0x0;
      if (config.sim.verbose)
      if (config.sim.verbose)
        PRINTF("kbd_read8(%"PRIxADDR") fifo empty\n", addr);
        PRINTF("kbd_read8(%"PRIxADDR") fifo empty\n", addr);
      return 0;
      return 0;
    default:
    default:
      fprintf (stderr, "Read out of keyboard space (0x%"PRIxADDR")!\n", addr);
      fprintf (stderr, "Read out of keyboard space (0x%"PRIxADDR")!\n", addr);
      runtime.sim.cont_run = 0;
      runtime.sim.cont_run = 0;
      return 0;
      return 0;
  }
  }
}
}
 
 
 
 
/* Simulation hook. Must be called every couple of clock cycles to simulate incomming data. */
/* Simulation hook. Must be called every couple of clock cycles to simulate incomming data. */
void kbd_job(void *dat)
void kbd_job(void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
  int c;
  int c;
  int kbd_int = 0;
  int kbd_int = 0;
 
 
  /* Check if there is something waiting, and decode it into kdb_buf */
  /* Check if there is something waiting, and decode it into kdb_buf */
  if((c = fgetc(kbd->rxfs)) != EOF) {
  if((c = fgetc(kbd->rxfs)) != EOF) {
    scan_decode (kbd, c);
    scan_decode (kbd, c);
  }
  }
  kbd_int = kbd->kresp || kbd->buf_count ? kbd->ccmdbyte & KBD_CCMDBYTE_INT : 0;
  kbd_int = kbd->kresp || kbd->buf_count ? kbd->ccmdbyte & KBD_CCMDBYTE_INT : 0;
  if (config.sim.verbose && kbd_int)
  if (config.sim.verbose && kbd_int)
    PRINTF("Keyboard Interrupt.... kbd_kresp %lx  kbd_buf_count %lx \n",
    PRINTF("Keyboard Interrupt.... kbd_kresp %lx  kbd_buf_count %lx \n",
           kbd->kresp, kbd->buf_count);
           kbd->kresp, kbd->buf_count);
  if (kbd_int) report_interrupt(kbd->irq);
  if (kbd_int) report_interrupt(kbd->irq);
  SCHED_ADD(kbd_job, dat, kbd->slowdown);
  SCHED_ADD(kbd_job, dat, kbd->slowdown);
}
}
 
 
/* Reset all (simulated) ps2 controlers/keyboards */
/* Reset all (simulated) ps2 controlers/keyboards */
void kbd_reset (void *dat)
void kbd_reset (void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
 
 
  kbd->buf_count = 0;
  kbd->buf_count = 0;
  kbd->buf_head = 0;
  kbd->buf_head = 0;
  kbd->buf_tail = 0;
  kbd->buf_tail = 0;
  kbd->kresp = 0x0;
  kbd->kresp = 0x0;
  kbd->ccmdbyte = 0x65; /* We reset into default normal operation. */
  kbd->ccmdbyte = 0x65; /* We reset into default normal operation. */
 
 
  if (!(kbd->rxfs = fopen(kbd->rxfile, "r"))
  if (!(kbd->rxfs = fopen(kbd->rxfile, "r"))
      && !(kbd->rxfs = fopen(kbd->rxfile, "r+"))) {
      && !(kbd->rxfs = fopen(kbd->rxfile, "r+"))) {
    fprintf (stderr, "WARNING: Unable to open RX file stream.\n");
    fprintf (stderr, "WARNING: Unable to open RX file stream.\n");
    return;
    return;
  }
  }
  kbd->slowdown = (long) ((config.sim.system_kfreq * 1000.) / KBD_BAUD_RATE);
  kbd->slowdown = (long) ((config.sim.system_kfreq * 1000.) / KBD_BAUD_RATE);
  if (kbd->slowdown <= 0) kbd->slowdown = 1;
  if (kbd->slowdown <= 0) kbd->slowdown = 1;
  SCHED_ADD(kbd_job, dat, kbd->slowdown);
  SCHED_ADD(kbd_job, dat, kbd->slowdown);
}
}
 
 
 
 
void kbd_info(void *dat)
void kbd_info(void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
  PRINTF("kbd_kcmd: %x\n", kbd->kcmd);
  PRINTF("kbd_kcmd: %x\n", kbd->kcmd);
  PRINTF("kbd_ccmd: %x\n", kbd->ccmd);
  PRINTF("kbd_ccmd: %x\n", kbd->ccmd);
  PRINTF("kbd_ccmdbyte: %x\n", kbd->ccmdbyte);
  PRINTF("kbd_ccmdbyte: %x\n", kbd->ccmdbyte);
  PRINTF("kbd_kresp: %lx\n", kbd->kresp);
  PRINTF("kbd_kresp: %lx\n", kbd->kresp);
  PRINTF("kbd_buf_count: %lx\n", kbd->buf_count);
  PRINTF("kbd_buf_count: %lx\n", kbd->buf_count);
}
}
 
 
/*----------------------------------------------------[ KBD Configuration ]---*/
/*----------------------------------------------------[ KBD Configuration ]---*/
void kbd_baseaddr(union param_val val, void *dat)
void kbd_baseaddr(union param_val val, void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
  kbd->baseaddr = val.addr_val;
  kbd->baseaddr = val.addr_val;
}
}
 
 
void kbd_irq(union param_val val, void *dat)
void kbd_irq(union param_val val, void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
  kbd->irq = val.int_val;
  kbd->irq = val.int_val;
}
}
 
 
void kbd_rxfile(union param_val val, void *dat)
void kbd_rxfile(union param_val val, void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
  if(!(kbd->rxfile = strdup(val.str_val))) {
  if(!(kbd->rxfile = strdup(val.str_val))) {
    fprintf(stderr, "Peripheral KBD: Run out of memory\n");
    fprintf(stderr, "Peripheral KBD: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
}
}
 
 
 
void kbd_enabled(union param_val val, void *dat)
 
{
 
  struct kbd_state *kbd = dat;
 
  kbd->enabled = val.int_val;
 
}
 
 
void *kbd_sec_start(void)
void *kbd_sec_start(void)
{
{
  struct kbd_state *new = malloc(sizeof(struct kbd_state));
  struct kbd_state *new = malloc(sizeof(struct kbd_state));
 
 
  if(!new) {
  if(!new) {
    fprintf(stderr, "Peripheral KBD: Run out of memory\n");
    fprintf(stderr, "Peripheral KBD: Run out of memory\n");
    exit(-1);
    exit(-1);
  }
  }
 
 
  new->buf_count = 0;
  new->buf_count = 0;
  new->buf_head = 0;
  new->buf_head = 0;
  new->buf_tail = 0;
  new->buf_tail = 0;
  new->rxfs = NULL;
  new->rxfs = NULL;
 
  new->enabled = 1;
 
 
  return new;
  return new;
}
}
 
 
void kbd_sec_end(void *dat)
void kbd_sec_end(void *dat)
{
{
  struct kbd_state *kbd = dat;
  struct kbd_state *kbd = dat;
 
 
 
  if(!kbd->enabled) {
 
    free(dat);
 
    return;
 
  }
 
 
  register_memoryarea(kbd->baseaddr, KBD_SPACE, 1, 0, kbd_read8, kbd_write8, dat);
  register_memoryarea(kbd->baseaddr, KBD_SPACE, 1, 0, kbd_read8, kbd_write8, dat);
  reg_sim_reset(kbd_reset, dat);
  reg_sim_reset(kbd_reset, dat);
  reg_sim_stat(kbd_info, dat);
  reg_sim_stat(kbd_info, dat);
}
}
 
 
void reg_kbd_sec(void)
void reg_kbd_sec(void)
{
{
  struct config_section *sec = reg_config_sec("kbd", kbd_sec_start, kbd_sec_end);
  struct config_section *sec = reg_config_sec("kbd", kbd_sec_start, kbd_sec_end);
 
 
  reg_config_param(sec, "baseaddr", paramt_int, kbd_baseaddr);
  reg_config_param(sec, "baseaddr", paramt_addr, kbd_baseaddr);
 
  reg_config_param(sec, "enabled", paramt_int, kbd_enabled);
  reg_config_param(sec, "irq", paramt_int, kbd_irq);
  reg_config_param(sec, "irq", paramt_int, kbd_irq);
  reg_config_param(sec, "rxfile", paramt_str, kbd_rxfile);
  reg_config_param(sec, "rxfile", paramt_str, kbd_rxfile);
}
}
 
 

powered by: WebSVN 2.1.0

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