/[gxemul]/trunk/src/devices/dev_pckbc.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_pckbc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 42 by dpavlin, Mon Oct 8 16:22:32 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2006  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_pckbc.c,v 1.64 2006/01/01 13:17:16 debug Exp $   *  $Id: dev_pckbc.c,v 1.74 2007/06/15 19:57:33 debug Exp $
29   *     *  
30   *  Standard 8042 PC keyboard controller (and a 8242WB PS2 keyboard/mouse   *  COMMENT: 8042 PC keyboard controller (+ 8242WB Keyboard/Mouse controller)
  *  controller), including the 8048 keyboard chip.  
31   *   *
32     *  This module includes emulation of the 8048 keyboard chip too.
33   *   *
34   *  TODO: Finish the rewrite for 8242.   *  Quick source of good info: http://my.execpc.com/~geezer/osd/kbd/kbd.txt
35     *
36     *
37     *  TODOs:
38     *      Finish the rewrite for 8242.
39   */   */
40    
41  #include <stdio.h>  #include <stdio.h>
# Line 72  struct pckbc_data { Line 76  struct pckbc_data {
76          int             in_use;          int             in_use;
77    
78          int             reg[DEV_PCKBC_LENGTH];          int             reg[DEV_PCKBC_LENGTH];
79          int             keyboard_irqnr;  
80          int             mouse_irqnr;          struct interrupt irq_keyboard;
81            struct interrupt irq_mouse;
82          int             currently_asserted[2];          int             currently_asserted[2];
83          int             type;          int             type;
84          int             pc_style_flag;          int             pc_style_flag;
# Line 98  struct pckbc_data { Line 103  struct pckbc_data {
103  #define STATE_LDCMDBYTE                 1  #define STATE_LDCMDBYTE                 1
104  #define STATE_RDCMDBYTE                 2  #define STATE_RDCMDBYTE                 2
105  #define STATE_WAITING_FOR_TRANSLTABLE   3  #define STATE_WAITING_FOR_TRANSLTABLE   3
106  #define STATE_WAITING_FOR_F3            4  #define STATE_WAITING_FOR_RATE          4
107  #define STATE_WAITING_FOR_FC            5  #define STATE_WAITING_FOR_ONEKEY_MB     5
108  #define STATE_WAITING_FOR_AUX           6  #define STATE_WAITING_FOR_AUX           6
109  #define STATE_WAITING_FOR_AUX_OUT       7  #define STATE_WAITING_FOR_AUX_OUT       7
110  #define STATE_LDOUTPUT                  8  #define STATE_LDOUTPUT                  8
# Line 433  static void ascii_to_pc_scancodes_type2( Line 438  static void ascii_to_pc_scancodes_type2(
438  }  }
439    
440    
441  /*  DEVICE_TICK(pckbc)
  *  dev_pckbc_tick():  
  */  
 void dev_pckbc_tick(struct cpu *cpu, void *extra)  
442  {  {
443          struct pckbc_data *d = extra;          struct pckbc_data *d = extra;
444          int port_nr, ch, ints_enabled;          int port_nr, ch, ints_enabled;
# Line 457  void dev_pckbc_tick(struct cpu *cpu, voi Line 459  void dev_pckbc_tick(struct cpu *cpu, voi
459          for (port_nr=0; port_nr<2; port_nr++) {          for (port_nr=0; port_nr<2; port_nr++) {
460                  /*  Cause receive interrupt, if there's something in the                  /*  Cause receive interrupt, if there's something in the
461                      receive buffer: (Otherwise deassert the interrupt.)  */                      receive buffer: (Otherwise deassert the interrupt.)  */
462    
463                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {
464                          debug("[ pckbc: interrupt port %i ]\n", port_nr);                          debug("[ pckbc: interrupt port %i ]\n", port_nr);
465                          cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr                          if (port_nr == 0)
466                              : d->mouse_irqnr);                                  INTERRUPT_ASSERT(d->irq_keyboard);
467                            else
468                                    INTERRUPT_ASSERT(d->irq_mouse);
469                          d->currently_asserted[port_nr] = 1;                          d->currently_asserted[port_nr] = 1;
470                  } else {                  } else {
471                          if (d->currently_asserted[port_nr])                          if (d->currently_asserted[port_nr]) {
472                                  cpu_interrupt_ack(cpu, port_nr==0?                                  if (port_nr == 0)
473                                      d->keyboard_irqnr : d->mouse_irqnr);                                          INTERRUPT_DEASSERT(d->irq_keyboard);
474                                    else
475                                            INTERRUPT_DEASSERT(d->irq_mouse);
476                            }
477                          d->currently_asserted[port_nr] = 0;                          d->currently_asserted[port_nr] = 0;
478                  }                  }
479          }          }
# Line 500  static void dev_pckbc_command(struct pck Line 508  static void dev_pckbc_command(struct pck
508                  return;                  return;
509          }          }
510    
511          if (d->state == STATE_WAITING_FOR_F3) {          if (d->state == STATE_WAITING_FOR_RATE) {
512                  debug("[ pckbc: (port %i) received '0xf3' data: "                  debug("[ pckbc: (port %i) received Typematic Rate data: "
513                      "0x%02x ]\n", port_nr, cmd);                      "0x%02x ]\n", port_nr, cmd);
514                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
515                  d->state = STATE_NORMAL;                  d->state = STATE_NORMAL;
516                  return;                  return;
517          }          }
518    
519          if (d->state == STATE_WAITING_FOR_FC) {          if (d->state == STATE_WAITING_FOR_ONEKEY_MB) {
520                  debug("[ pckbc: (port %i) received '0xfc' data: "                  debug("[ pckbc: (port %i) received One-key make/break data: "
521                      "0x%02x ]\n", port_nr, cmd);                      "0x%02x ]\n", port_nr, cmd);
522                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
523                  d->state = STATE_NORMAL;                  d->state = STATE_NORMAL;
# Line 535  static void dev_pckbc_command(struct pck Line 543  static void dev_pckbc_command(struct pck
543          }          }
544    
545          switch (cmd) {          switch (cmd) {
546    
547          case 0x00:          case 0x00:
548                    /*
549                     *  TODO: What does this do? This is possibly due to an
550                     *  error in the handling of some other command code.
551                     */
552                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
553                  break;                  break;
554    
555          case KBC_MODEIND:       /*  Set LEDs  */          case KBC_MODEIND:       /*  Set LEDs  */
556                  /*  Just ACK, no LEDs are actually set.  */                  /*  Just ACK, no LEDs are actually set.  */
557                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
558                  break;                  break;
559    
560          case KBC_SETTABLE:          case KBC_SETTABLE:
561                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
562                  d->state = STATE_WAITING_FOR_TRANSLTABLE;                  d->state = STATE_WAITING_FOR_TRANSLTABLE;
563                  break;                  break;
564    
565          case KBC_ENABLE:          case KBC_ENABLE:
566                  d->keyscanning_enabled = 1;                  d->keyscanning_enabled = 1;
567                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
568                  break;                  break;
569    
570          case KBC_DISABLE:          case KBC_DISABLE:
571                  d->keyscanning_enabled = 0;                  d->keyscanning_enabled = 0;
572                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
573                  break;                  break;
574    
575          case KBC_SETDEFAULT:          case KBC_SETDEFAULT:
576                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
577                  break;                  break;
578          case 0xf3:  
579            case KBC_GETID:
580                    /*  Get keyboard ID.  NOTE/TODO: Ugly hardcoded answer.  */
581                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
582                  d->state = STATE_WAITING_FOR_F3;                  pckbc_add_code(d, 0xab, port_nr);
583                    pckbc_add_code(d, 0x41, port_nr);
584                  break;                  break;
585          case 0xfa:      /*  Just ack?  */  
586            case KBC_TYPEMATIC:
587                    /*  Set typematic (auto-repeat) delay/speed:  */
588                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
589                    d->state = STATE_WAITING_FOR_RATE;
590                  break;                  break;
591          case 0xfc:  
592            case KBC_ALLKEYS_TMB:
593                    /*  "Make all keys typematic/make/break"  */
594                    pckbc_add_code(d, KBR_ACK, port_nr);
595                    break;
596    
597            case KBC_ONEKEY_MB:
598                    /*  "Make one key typematic/make/break"  */
599                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
600                  d->state = STATE_WAITING_FOR_FC;                  d->state = STATE_WAITING_FOR_ONEKEY_MB;
601                  break;                  break;
602    
603          case KBC_RESET:          case KBC_RESET:
604                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
605                  pckbc_add_code(d, KBR_RSTDONE, port_nr);                  pckbc_add_code(d, KBR_RSTDONE, port_nr);
606                    /*
607                     *  Disable interrupts during reset, or Linux 2.6
608                     *  prints warnings about spurious interrupts.
609                     */
610                    d->rx_int_enable = 0;
611                  break;                  break;
612    
613          default:          default:
614                  fatal("[ pckbc: (port %i) UNIMPLEMENTED 8048 command"                  fatal("[ pckbc: (port %i) UNIMPLEMENTED 8048 command"
615                      " 0x%02x ]\n", port_nr, cmd);                      " 0x%02x ]\n", port_nr, cmd);
616                    exit(1);
617          }          }
618  }  }
619    
620    
 /*  
  *  dev_pckbc_access():  
  */  
621  DEVICE_ACCESS(pckbc)  DEVICE_ACCESS(pckbc)
622  {  {
623            struct pckbc_data *d = extra;
624          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
625          int port_nr = 0;          int port_nr = 0;
626          size_t i;          size_t i;
         struct pckbc_data *d = extra;  
627    
628          if (writeflag == MEM_WRITE)          if (writeflag == MEM_WRITE)
629                  idata = memory_readmax64(cpu, data, len);                  idata = memory_readmax64(cpu, data, len);
# Line 627  if (x&1) Line 663  if (x&1)
663  }  }
664                          if (writeflag == MEM_READ)                          if (writeflag == MEM_READ)
665                                  memory_writemax64(cpu, data, len, odata);                                  memory_writemax64(cpu, data, len, odata);
666                          return 0;                          return 1;
667                  }                  }
668                  if (relative_addr != 0)                  if (relative_addr != 0)
669                          relative_addr = 1;                          relative_addr = 1;
# Line 868  if (x&1) Line 904  if (x&1)
904   *  Type should be PCKBC_8042 or PCKBC_8242.   *  Type should be PCKBC_8042 or PCKBC_8242.
905   */   */
906  int dev_pckbc_init(struct machine *machine, struct memory *mem,  int dev_pckbc_init(struct machine *machine, struct memory *mem,
907          uint64_t baseaddr, int type, int keyboard_irqnr, int mouse_irqnr,          uint64_t baseaddr, int type, char *keyboard_irqpath,
908          int in_use, int pc_style_flag)          char *mouse_irqpath, int in_use, int pc_style_flag)
909  {  {
910          struct pckbc_data *d;          struct pckbc_data *d;
911          int len = DEV_PCKBC_LENGTH;          int len = DEV_PCKBC_LENGTH;
912    
913          d = malloc(sizeof(struct pckbc_data));          CHECK_ALLOCATION(d = malloc(sizeof(struct pckbc_data)));
         if (d == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
914          memset(d, 0, sizeof(struct pckbc_data));          memset(d, 0, sizeof(struct pckbc_data));
915    
916          if (type == PCKBC_8242)          if (type == PCKBC_8242)
# Line 889  int dev_pckbc_init(struct machine *machi Line 921  int dev_pckbc_init(struct machine *machi
921                  len = DEV_PCKBC_LENGTH + 0x60;                  len = DEV_PCKBC_LENGTH + 0x60;
922          }          }
923    
924            INTERRUPT_CONNECT(keyboard_irqpath, d->irq_keyboard);
925            INTERRUPT_CONNECT(mouse_irqpath, d->irq_mouse);
926    
927          d->type              = type;          d->type              = type;
         d->keyboard_irqnr    = keyboard_irqnr;  
         d->mouse_irqnr       = mouse_irqnr;  
928          d->in_use            = in_use;          d->in_use            = in_use;
929          d->pc_style_flag     = pc_style_flag;          d->pc_style_flag     = pc_style_flag;
930          d->translation_table = 2;          d->translation_table = 2;
# Line 903  int dev_pckbc_init(struct machine *machi Line 936  int dev_pckbc_init(struct machine *machi
936    
937          memory_device_register(mem, "pckbc", baseaddr,          memory_device_register(mem, "pckbc", baseaddr,
938              len, dev_pckbc_access, d, DM_DEFAULT, NULL);              len, dev_pckbc_access, d, DM_DEFAULT, NULL);
939          machine_add_tickfunction(machine, dev_pckbc_tick, d, PCKBC_TICKSHIFT);          machine_add_tickfunction(machine, dev_pckbc_tick, d,
940                PCKBC_TICKSHIFT);
941    
942          return d->console_handle;          return d->console_handle;
943  }  }

Legend:
Removed from v.22  
changed lines
  Added in v.42

  ViewVC Help
Powered by ViewVC 1.1.26