/[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 5 by dpavlin, Mon Oct 8 16:18:00 2007 UTC revision 6 by dpavlin, Mon Oct 8 16:18:11 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_pckbc.c,v 1.37 2005/02/22 06:26:10 debug Exp $   *  $Id: dev_pckbc.c,v 1.45 2005/06/02 15:42:49 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.   *  controller), including the 8048 keyboard chip.
32   *   *
33   *   *
34   *  TODO: Finish the rewrite for 8242.   *  TODO: Finish the rewrite for 8242.
# Line 69  Line 69 
69  struct pckbc_data {  struct pckbc_data {
70          int             console_handle;          int             console_handle;
71          int             in_use;          int             in_use;
         int             any_command_used;  
72    
73          int             reg[DEV_PCKBC_LENGTH];          int             reg[DEV_PCKBC_LENGTH];
74          int             keyboard_irqnr;          int             keyboard_irqnr;
75          int             mouse_irqnr;          int             mouse_irqnr;
76          int             type;          int             type;
77            int             pc_style_flag;
78    
79          /*  TODO: one of these for each port?  */          /*  TODO: one of these for each port?  */
80          int             clocksignal;          int             clocksignal;
# Line 84  struct pckbc_data { Line 84  struct pckbc_data {
84          int             keyscanning_enabled;          int             keyscanning_enabled;
85          int             state;          int             state;
86          int             cmdbyte;          int             cmdbyte;
87            int             output_byte;
88          int             last_scancode;          int             last_scancode;
89    
90          unsigned        key_queue[2][MAX_8042_QUEUELEN];          unsigned        key_queue[2][MAX_8042_QUEUELEN];
# Line 94  struct pckbc_data { Line 95  struct pckbc_data {
95  #define STATE_LDCMDBYTE                 1  #define STATE_LDCMDBYTE                 1
96  #define STATE_RDCMDBYTE                 2  #define STATE_RDCMDBYTE                 2
97  #define STATE_WAITING_FOR_TRANSLTABLE   3  #define STATE_WAITING_FOR_TRANSLTABLE   3
98    #define STATE_LDOUTPUT                  4
99    #define STATE_RDOUTPUT                  5
100    
101    
102  /*  /*
# Line 121  int pckbc_get_code(struct pckbc_data *d, Line 124  int pckbc_get_code(struct pckbc_data *d,
124  {  {
125          if (d->head[port] == d->tail[port])          if (d->head[port] == d->tail[port])
126                  fatal("[ pckbc: queue empty, port %i! ]\n", port);                  fatal("[ pckbc: queue empty, port %i! ]\n", port);
127            else
128          d->tail[port] = (d->tail[port]+1) % MAX_8042_QUEUELEN;                  d->tail[port] = (d->tail[port]+1) % MAX_8042_QUEUELEN;
129          return d->key_queue[port][d->tail[port]];          return d->key_queue[port][d->tail[port]];
130  }  }
131    
# Line 135  int pckbc_get_code(struct pckbc_data *d, Line 138  int pckbc_get_code(struct pckbc_data *d,
138   */   */
139  static void ascii_to_pc_scancodes(int a, struct pckbc_data *d)  static void ascii_to_pc_scancodes(int a, struct pckbc_data *d)
140  {  {
141            int old_head;
142          int p = 0;      /*  port  */          int p = 0;      /*  port  */
143          int shift = 0, ctrl = 0;          int shift = 0, ctrl = 0;
144    
# Line 151  static void ascii_to_pc_scancodes(int a, Line 155  static void ascii_to_pc_scancodes(int a,
155                  pckbc_add_code(d, 0x1d, p);                  pckbc_add_code(d, 0x1d, p);
156    
157          /*          /*
158           *  TODO: Release for all of these?           *  Note: The ugly hack used to add release codes for all of these
159             *  keys is as follows:  we remember how much of the kbd buf that
160             *  is in use here, before we add any scancode. After we've added
161             *  one or more scancodes (ie an optional shift + another key)
162             *  then we duplicate the last scancode | 0x80 _if_ the kbd buf
163             *  was altered.
164           */           */
165    
166            old_head = d->head[p];
167    
168          if (a==27)      pckbc_add_code(d, 0x01, p);          if (a==27)      pckbc_add_code(d, 0x01, p);
169    
170          if (a=='1')     pckbc_add_code(d, 0x02, p);          if (a=='1')     pckbc_add_code(d, 0x02, p);
# Line 259  static void ascii_to_pc_scancodes(int a, Line 270  static void ascii_to_pc_scancodes(int a,
270    
271          if (a==' ')     pckbc_add_code(d, 0x39, p);          if (a==' ')     pckbc_add_code(d, 0x39, p);
272    
273            /*  Add release code, if a key was pressed:  */
274            if (d->head[p] != old_head) {
275                    int code = d->key_queue[p][d->head[p]] | 0x80;
276                    pckbc_add_code(d, code, p);
277            }
278    
279          /*  Release ctrl:  */          /*  Release ctrl:  */
280          if (ctrl)          if (ctrl)
281                  pckbc_add_code(d, 0x1d + 0x80, p);                  pckbc_add_code(d, 0x1d + 0x80, p);
# Line 271  static void ascii_to_pc_scancodes(int a, Line 288  static void ascii_to_pc_scancodes(int a,
288  void dev_pckbc_tick(struct cpu *cpu, void *extra)  void dev_pckbc_tick(struct cpu *cpu, void *extra)
289  {  {
290          struct pckbc_data *d = extra;          struct pckbc_data *d = extra;
291          int port_nr;          int port_nr, ch, ints_enabled;
         int ch;  
292    
293          if (d->in_use && d->any_command_used &&          if (d->in_use && console_charavail(d->console_handle)) {
             console_charavail(d->console_handle)) {  
294                  ch = console_readchar(d->console_handle);                  ch = console_readchar(d->console_handle);
295                  if (ch >= 0)                  if (ch >= 0)
296                          ascii_to_pc_scancodes(ch, d);                          ascii_to_pc_scancodes(ch, d);
297          }          }
298    
299            ints_enabled = d->rx_int_enable;
300    
301          /*  TODO: mouse movements?  */          /*  TODO: mouse movements?  */
302    
303            if (d->cmdbyte & KC8_KDISABLE)
304                    ints_enabled = 0;
305    
306          for (port_nr=0; port_nr<2; port_nr++) {          for (port_nr=0; port_nr<2; port_nr++) {
307                  /*  Cause receive interrupt,                  /*  Cause receive interrupt, if there's something in the
308                      if there's something in the receive buffer:  */                      receive buffer: (Otherwise deassert the interrupt.)  */
309                  if (d->head[port_nr] != d->tail[port_nr] && d->rx_int_enable) {                  if (d->head[port_nr] != d->tail[port_nr] && ints_enabled) {
310                          cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr                          cpu_interrupt(cpu, port_nr==0? d->keyboard_irqnr
311                              : d->mouse_irqnr);                              : d->mouse_irqnr);
312                  } else {                  } else {
# Line 299  void dev_pckbc_tick(struct cpu *cpu, voi Line 319  void dev_pckbc_tick(struct cpu *cpu, voi
319    
320  /*  /*
321   *  dev_pckbc_command():   *  dev_pckbc_command():
322     *
323     *  Handle commands to the 8048 in the emulated keyboard.
324   */   */
325  static void dev_pckbc_command(struct pckbc_data *d, int port_nr)  static void dev_pckbc_command(struct pckbc_data *d, int port_nr)
326  {  {
327          int cmd = d->reg[PC_CMD];          int cmd = d->reg[PC_CMD];
328    
         d->any_command_used = 1;  
   
329          if (d->type == PCKBC_8242)          if (d->type == PCKBC_8242)
330                  cmd = d->reg[PS2_TXBUF];                  cmd = d->reg[PS2_TXBUF];
331    
# Line 345  static void dev_pckbc_command(struct pck Line 365  static void dev_pckbc_command(struct pck
365                  pckbc_add_code(d, KBR_RSTDONE, port_nr);                  pckbc_add_code(d, KBR_RSTDONE, port_nr);
366                  break;                  break;
367          default:          default:
368                  fatal("[ pckbc: UNIMPLEMENTED command 0x%02x ]\n", cmd);                  fatal("[ pckbc: UNIMPLEMENTED 8048 command 0x%02x ]\n", cmd);
369          }          }
370  }  }
371    
# Line 373  int dev_pckbc_access(struct cpu *cpu, st Line 393  int dev_pckbc_access(struct cpu *cpu, st
393  #endif  #endif
394    
395          /*  For JAZZ-based machines:  */          /*  For JAZZ-based machines:  */
396          if (relative_addr >= 0x60)          if (relative_addr >= 0x60) {
397                  relative_addr -= 0x60;                  relative_addr -= 0x60;
398                    if (relative_addr != 0)
399          /*  8242 PS2-style:  */                          relative_addr = 1;
400          if (d->type == PCKBC_8242) {          } else if (d->type == PCKBC_8242) {
401                    /*  8242 PS2-style:  */
402                  /*  when using 8-byte alignment...  */                  /*  when using 8-byte alignment...  */
403                  relative_addr /= sizeof(uint64_t);                  relative_addr /= sizeof(uint64_t);
404                  /*  port_nr = 0 for keyboard, 1 for mouse  */                  /*  port_nr = 0 for keyboard, 1 for mouse  */
405                  port_nr = (relative_addr >> 2);                  port_nr = (relative_addr >> 2);
406                  relative_addr &= 3;                  relative_addr &= 3;
407                  relative_addr += PS2;                  relative_addr += PS2;
408            } else if (d->pc_style_flag) {
409                    /*  PC-style:  */
410                    if (relative_addr != 0 && relative_addr != 4) {
411                            /*  TODO (port 0x61)  */
412                            odata = 0x21;
413    {
414    static int x = 0;
415    x++;
416    if (x&1)
417                            odata ^= 0x10;
418    }
419                            if (writeflag == MEM_READ)
420                                    memory_writemax64(cpu, data, len, odata);
421                            return 0;
422                    }
423                    if (relative_addr != 0)
424                            relative_addr = 1;
425          } else {          } else {
426                  /*  The relative_addr is either 0 or 1,                  /*  Others... Non-Jazz ARC-based machines etc.  */
427                      but some machines use longer registers than one byte                  if (relative_addr != 0)
                     each, so this will make things simpler for us:  */  
                 if (relative_addr)  
428                          relative_addr = 1;                          relative_addr = 1;
429          }          }
430    
# Line 400  int dev_pckbc_access(struct cpu *cpu, st Line 436  int dev_pckbc_access(struct cpu *cpu, st
436    
437          case 0:         /*  data  */          case 0:         /*  data  */
438                  if (writeflag==MEM_READ) {                  if (writeflag==MEM_READ) {
439                          if (d->state == STATE_RDCMDBYTE) {                          switch (d->state) {
440                            case STATE_RDCMDBYTE:
441                                  odata = d->cmdbyte;                                  odata = d->cmdbyte;
442                                  d->state = STATE_NORMAL;                                  d->state = STATE_NORMAL;
443                          } else {                                  break;
444                                  if (d->head[0] != d->tail[0]) {                          case STATE_RDOUTPUT:
445                                    odata = d->output_byte;
446                                    d->state = STATE_NORMAL;
447                                    break;
448                            default:if (d->head[0] != d->tail[0]) {
449                                          odata = pckbc_get_code(d, 0);                                          odata = pckbc_get_code(d, 0);
450                                          d->last_scancode = odata;                                          d->last_scancode = odata;
451                                  } else {                                  } else {
# Line 412  int dev_pckbc_access(struct cpu *cpu, st Line 453  int dev_pckbc_access(struct cpu *cpu, st
453                                          d->last_scancode |= 0x80;                                          d->last_scancode |= 0x80;
454                                  }                                  }
455                          }                          }
456                          debug("[ pckbc: read from DATA: 0x%02x ]\n", odata);                          /*  debug("[ pckbc: read from DATA: 0x%02x ]\n",
457                                odata);  */
458                  } else {                  } else {
459                          debug("[ pckbc: write to DATA:");                          debug("[ pckbc: write to DATA:");
460                          for (i=0; i<len; i++)                          for (i=0; i<len; i++)
461                                  debug(" %02x", data[i]);                                  debug(" %02x", data[i]);
462                          debug(" ]\n");                          debug(" ]\n");
463    
464                          if (d->state == STATE_LDCMDBYTE) {                          switch (d->state) {
465                            case STATE_LDCMDBYTE:
466                                  d->cmdbyte = idata;                                  d->cmdbyte = idata;
467                                  d->rx_int_enable = d->cmdbyte &                                  d->rx_int_enable = d->cmdbyte &
468                                      (KC8_KENABLE | KC8_MENABLE) ? 1 : 0;                                      (KC8_KENABLE | KC8_MENABLE) ? 1 : 0;
469                                  d->state = STATE_NORMAL;                                  d->state = STATE_NORMAL;
470                          } else {                                  break;
471                                  d->reg[relative_addr] = idata;                          case STATE_LDOUTPUT:
472                                    d->output_byte = idata;
473                                    d->state = STATE_NORMAL;
474                                    break;
475                            default:d->reg[relative_addr] = idata;
476                                  dev_pckbc_command(d, port_nr);                                  dev_pckbc_command(d, port_nr);
477                          }                          }
478                  }                  }
# Line 438  int dev_pckbc_access(struct cpu *cpu, st Line 485  int dev_pckbc_access(struct cpu *cpu, st
485    
486                          /*  "Data in buffer" bit  */                          /*  "Data in buffer" bit  */
487                          if (d->head[0] != d->tail[0] ||                          if (d->head[0] != d->tail[0] ||
488                              d->state == STATE_RDCMDBYTE)                              d->state == STATE_RDCMDBYTE ||
489                                d->state == STATE_RDOUTPUT)
490                                  odata |= KBS_DIB;                                  odata |= KBS_DIB;
491                          /*  odata |= KBS_OCMD;  */  
492                            if (d->state == STATE_RDCMDBYTE)
493                                    odata |= KBS_OCMD;
494    
495                            odata |= KBS_NOSEC;
496                          /*  debug("[ pckbc: read from CTL status port: "                          /*  debug("[ pckbc: read from CTL status port: "
497                              "0x%02x ]\n", (int)odata);  */                              "0x%02x ]\n", (int)odata);  */
498                  } else {                  } else {
# Line 457  int dev_pckbc_access(struct cpu *cpu, st Line 509  int dev_pckbc_access(struct cpu *cpu, st
509                          case K_LDCMDBYTE:                          case K_LDCMDBYTE:
510                                  d->state = STATE_LDCMDBYTE;                                  d->state = STATE_LDCMDBYTE;
511                                  break;                                  break;
512                            case 0xa7:
513                                    d->cmdbyte |= KC8_MDISABLE;
514                                    break;
515                            case 0xa8:
516                                    d->cmdbyte &= ~KC8_MDISABLE;
517                                    break;
518                          case 0xa9:      /*  test auxiliary port  */                          case 0xa9:      /*  test auxiliary port  */
519                                  debug("[ pckbc: CONTROL 0xa9, TODO ]\n");                                  debug("[ pckbc: CONTROL 0xa9, TODO ]\n");
520                                  break;                                  break;
521                          case 0xaa:      /*  keyboard self-test  */                          case 0xaa:      /*  keyboard self-test  */
522                                  pckbc_add_code(d, 0x55, port_nr);                                  pckbc_add_code(d, 0x55, port_nr);
523                                  break;                                  break;
524                            case 0xad:
525                                    d->cmdbyte |= KC8_KDISABLE;
526                                    break;
527                            case 0xae:
528                                    d->cmdbyte &= ~KC8_KDISABLE;
529                                    break;
530                            case 0xd0:
531                                    d->state = STATE_RDOUTPUT;
532                                    break;
533                            case 0xd1:
534                                    d->state = STATE_LDOUTPUT;
535                                    break;
536                          case 0xd4:      /*  write to auxiliary port  */                          case 0xd4:      /*  write to auxiliary port  */
537                                  debug("[ pckbc: CONTROL 0xd4, TODO ]\n");                                  debug("[ pckbc: CONTROL 0xd4, TODO ]\n");
538                                  break;                                  break;
# Line 633  int dev_pckbc_access(struct cpu *cpu, st Line 703  int dev_pckbc_access(struct cpu *cpu, st
703   */   */
704  int dev_pckbc_init(struct machine *machine, struct memory *mem,  int dev_pckbc_init(struct machine *machine, struct memory *mem,
705          uint64_t baseaddr, int type, int keyboard_irqnr, int mouse_irqnr,          uint64_t baseaddr, int type, int keyboard_irqnr, int mouse_irqnr,
706          int in_use)          int in_use, int pc_style_flag)
707  {  {
708          struct pckbc_data *d;          struct pckbc_data *d;
709          int len = DEV_PCKBC_LENGTH;          int len = DEV_PCKBC_LENGTH;
# Line 654  int dev_pckbc_init(struct machine *machi Line 724  int dev_pckbc_init(struct machine *machi
724          d->keyboard_irqnr = keyboard_irqnr;          d->keyboard_irqnr = keyboard_irqnr;
725          d->mouse_irqnr    = mouse_irqnr;          d->mouse_irqnr    = mouse_irqnr;
726          d->in_use         = in_use;          d->in_use         = in_use;
727            d->pc_style_flag  = pc_style_flag;
728          d->console_handle = console_start_slave_inputonly(machine, "pckbc");          d->console_handle = console_start_slave_inputonly(machine, "pckbc");
729            d->rx_int_enable  = 1;
730            d->output_byte    = 0x02;       /*  A20 enable on PCs  */
731    
732          memory_device_register(mem, "pckbc", baseaddr,          memory_device_register(mem, "pckbc", baseaddr,
733              len, dev_pckbc_access, d, MEM_DEFAULT, NULL);              len, dev_pckbc_access, d, MEM_DEFAULT, NULL);

Legend:
Removed from v.5  
changed lines
  Added in v.6

  ViewVC Help
Powered by ViewVC 1.1.26