/[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 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC revision 34 by dpavlin, Mon Oct 8 16:21:17 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.65 2006/03/04 12:38:48 debug Exp $   *  $Id: dev_pckbc.c,v 1.72 2006/12/30 13:30:58 debug Exp $
29   *     *  
30   *  Standard 8042 PC keyboard controller (and a 8242WB PS2 keyboard/mouse   *  Standard 8042 PC keyboard controller (and a 8242WB PS2 keyboard/mouse
31   *  controller), including the 8048 keyboard chip.   *  controller), including the 8048 keyboard chip.
32   *   *
33     *  Quick source of good info: http://my.execpc.com/~geezer/osd/kbd/kbd.txt
34   *   *
35   *  TODO: Finish the rewrite for 8242.   *
36     *  TODOs:
37     *      Finish the rewrite for 8242.
38   */   */
39    
40  #include <stdio.h>  #include <stdio.h>
# Line 72  struct pckbc_data { Line 75  struct pckbc_data {
75          int             in_use;          int             in_use;
76    
77          int             reg[DEV_PCKBC_LENGTH];          int             reg[DEV_PCKBC_LENGTH];
78          int             keyboard_irqnr;  
79          int             mouse_irqnr;          struct interrupt irq_keyboard;
80            struct interrupt irq_mouse;
81          int             currently_asserted[2];          int             currently_asserted[2];
82          int             type;          int             type;
83          int             pc_style_flag;          int             pc_style_flag;
# Line 98  struct pckbc_data { Line 102  struct pckbc_data {
102  #define STATE_LDCMDBYTE                 1  #define STATE_LDCMDBYTE                 1
103  #define STATE_RDCMDBYTE                 2  #define STATE_RDCMDBYTE                 2
104  #define STATE_WAITING_FOR_TRANSLTABLE   3  #define STATE_WAITING_FOR_TRANSLTABLE   3
105  #define STATE_WAITING_FOR_F3            4  #define STATE_WAITING_FOR_RATE          4
106  #define STATE_WAITING_FOR_FC            5  #define STATE_WAITING_FOR_ONEKEY_MB     5
107  #define STATE_WAITING_FOR_AUX           6  #define STATE_WAITING_FOR_AUX           6
108  #define STATE_WAITING_FOR_AUX_OUT       7  #define STATE_WAITING_FOR_AUX_OUT       7
109  #define STATE_LDOUTPUT                  8  #define STATE_LDOUTPUT                  8
# Line 457  void dev_pckbc_tick(struct cpu *cpu, voi Line 461  void dev_pckbc_tick(struct cpu *cpu, voi
461          for (port_nr=0; port_nr<2; port_nr++) {          for (port_nr=0; port_nr<2; port_nr++) {
462                  /*  Cause receive interrupt, if there's something in the                  /*  Cause receive interrupt, if there's something in the
463                      receive buffer: (Otherwise deassert the interrupt.)  */                      receive buffer: (Otherwise deassert the interrupt.)  */
464    
465                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {
466                          debug("[ pckbc: interrupt port %i ]\n", port_nr);                          debug("[ pckbc: interrupt port %i ]\n", port_nr);
467                          cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr                          if (port_nr == 0)
468                              : d->mouse_irqnr);                                  INTERRUPT_ASSERT(d->irq_keyboard);
469                            else
470                                    INTERRUPT_ASSERT(d->irq_mouse);
471                          d->currently_asserted[port_nr] = 1;                          d->currently_asserted[port_nr] = 1;
472                  } else {                  } else {
473                          if (d->currently_asserted[port_nr])                          if (d->currently_asserted[port_nr]) {
474                                  cpu_interrupt_ack(cpu, port_nr==0?                                  if (port_nr == 0)
475                                      d->keyboard_irqnr : d->mouse_irqnr);                                          INTERRUPT_DEASSERT(d->irq_keyboard);
476                                    else
477                                            INTERRUPT_DEASSERT(d->irq_mouse);
478                            }
479                          d->currently_asserted[port_nr] = 0;                          d->currently_asserted[port_nr] = 0;
480                  }                  }
481          }          }
# Line 500  static void dev_pckbc_command(struct pck Line 510  static void dev_pckbc_command(struct pck
510                  return;                  return;
511          }          }
512    
513          if (d->state == STATE_WAITING_FOR_F3) {          if (d->state == STATE_WAITING_FOR_RATE) {
514                  debug("[ pckbc: (port %i) received '0xf3' data: "                  debug("[ pckbc: (port %i) received Typematic Rate data: "
515                      "0x%02x ]\n", port_nr, cmd);                      "0x%02x ]\n", port_nr, cmd);
516                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
517                  d->state = STATE_NORMAL;                  d->state = STATE_NORMAL;
518                  return;                  return;
519          }          }
520    
521          if (d->state == STATE_WAITING_FOR_FC) {          if (d->state == STATE_WAITING_FOR_ONEKEY_MB) {
522                  debug("[ pckbc: (port %i) received '0xfc' data: "                  debug("[ pckbc: (port %i) received One-key make/break data: "
523                      "0x%02x ]\n", port_nr, cmd);                      "0x%02x ]\n", port_nr, cmd);
524                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
525                  d->state = STATE_NORMAL;                  d->state = STATE_NORMAL;
# Line 535  static void dev_pckbc_command(struct pck Line 545  static void dev_pckbc_command(struct pck
545          }          }
546    
547          switch (cmd) {          switch (cmd) {
548    
549          case 0x00:          case 0x00:
550                    /*
551                     *  TODO: What does this do? This is possibly due to an
552                     *  error in the handling of some other command code.
553                     */
554                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
555                  break;                  break;
556    
557          case KBC_MODEIND:       /*  Set LEDs  */          case KBC_MODEIND:       /*  Set LEDs  */
558                  /*  Just ACK, no LEDs are actually set.  */                  /*  Just ACK, no LEDs are actually set.  */
559                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
560                  break;                  break;
561    
562          case KBC_SETTABLE:          case KBC_SETTABLE:
563                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
564                  d->state = STATE_WAITING_FOR_TRANSLTABLE;                  d->state = STATE_WAITING_FOR_TRANSLTABLE;
565                  break;                  break;
566    
567          case KBC_ENABLE:          case KBC_ENABLE:
568                  d->keyscanning_enabled = 1;                  d->keyscanning_enabled = 1;
569                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
570                  break;                  break;
571    
572          case KBC_DISABLE:          case KBC_DISABLE:
573                  d->keyscanning_enabled = 0;                  d->keyscanning_enabled = 0;
574                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
575                  break;                  break;
576    
577          case KBC_SETDEFAULT:          case KBC_SETDEFAULT:
578                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
579                  break;                  break;
580          case 0xf3:  
581            case KBC_GETID:
582                    /*  Get keyboard ID.  NOTE/TODO: Ugly hardcoded answer.  */
583                    pckbc_add_code(d, KBR_ACK, port_nr);
584                    pckbc_add_code(d, 0xab, port_nr);
585                    pckbc_add_code(d, 0x41, port_nr);
586                    break;
587    
588            case KBC_TYPEMATIC:
589                    /*  Set typematic (auto-repeat) delay/speed:  */
590                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
591                  d->state = STATE_WAITING_FOR_F3;                  d->state = STATE_WAITING_FOR_RATE;
592                  break;                  break;
593          case 0xfa:      /*  Just ack?  */  
594            case KBC_ALLKEYS_TMB:
595                    /*  "Make all keys typematic/make/break"  */
596                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
597                  break;                  break;
598          case 0xfc:  
599            case KBC_ONEKEY_MB:
600                    /*  "Make one key typematic/make/break"  */
601                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
602                  d->state = STATE_WAITING_FOR_FC;                  d->state = STATE_WAITING_FOR_ONEKEY_MB;
603                  break;                  break;
604    
605          case KBC_RESET:          case KBC_RESET:
606                  pckbc_add_code(d, KBR_ACK, port_nr);                  pckbc_add_code(d, KBR_ACK, port_nr);
607                  pckbc_add_code(d, KBR_RSTDONE, port_nr);                  pckbc_add_code(d, KBR_RSTDONE, port_nr);
608                    /*
609                     *  Disable interrupts during reset, or Linux 2.6
610                     *  prints warnings about spurious interrupts.
611                     */
612                    d->rx_int_enable = 0;
613                  break;                  break;
614    
615          default:          default:
616                  fatal("[ pckbc: (port %i) UNIMPLEMENTED 8048 command"                  fatal("[ pckbc: (port %i) UNIMPLEMENTED 8048 command"
617                      " 0x%02x ]\n", port_nr, cmd);                      " 0x%02x ]\n", port_nr, cmd);
618                    exit(1);
619          }          }
620  }  }
621    
622    
 /*  
  *  dev_pckbc_access():  
  */  
623  DEVICE_ACCESS(pckbc)  DEVICE_ACCESS(pckbc)
624  {  {
625          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
# Line 627  if (x&1) Line 665  if (x&1)
665  }  }
666                          if (writeflag == MEM_READ)                          if (writeflag == MEM_READ)
667                                  memory_writemax64(cpu, data, len, odata);                                  memory_writemax64(cpu, data, len, odata);
668                          return 0;                          return 1;
669                  }                  }
670                  if (relative_addr != 0)                  if (relative_addr != 0)
671                          relative_addr = 1;                          relative_addr = 1;
# Line 868  if (x&1) Line 906  if (x&1)
906   *  Type should be PCKBC_8042 or PCKBC_8242.   *  Type should be PCKBC_8042 or PCKBC_8242.
907   */   */
908  int dev_pckbc_init(struct machine *machine, struct memory *mem,  int dev_pckbc_init(struct machine *machine, struct memory *mem,
909          uint64_t baseaddr, int type, int keyboard_irqnr, int mouse_irqnr,          uint64_t baseaddr, int type, char *keyboard_irqpath,
910          int in_use, int pc_style_flag)          char *mouse_irqpath, int in_use, int pc_style_flag)
911  {  {
912          struct pckbc_data *d;          struct pckbc_data *d;
913          int len = DEV_PCKBC_LENGTH;          int len = DEV_PCKBC_LENGTH;
# Line 889  int dev_pckbc_init(struct machine *machi Line 927  int dev_pckbc_init(struct machine *machi
927                  len = DEV_PCKBC_LENGTH + 0x60;                  len = DEV_PCKBC_LENGTH + 0x60;
928          }          }
929    
930            INTERRUPT_CONNECT(keyboard_irqpath, d->irq_keyboard);
931            INTERRUPT_CONNECT(mouse_irqpath, d->irq_mouse);
932    
933          d->type              = type;          d->type              = type;
         d->keyboard_irqnr    = keyboard_irqnr;  
         d->mouse_irqnr       = mouse_irqnr;  
934          d->in_use            = in_use;          d->in_use            = in_use;
935          d->pc_style_flag     = pc_style_flag;          d->pc_style_flag     = pc_style_flag;
936          d->translation_table = 2;          d->translation_table = 2;

Legend:
Removed from v.24  
changed lines
  Added in v.34

  ViewVC Help
Powered by ViewVC 1.1.26