aboutsummaryrefslogtreecommitdiff
path: root/devices/i8042.c
blob: cfd96a84dbe1ff9e794d325c12578235b8da7010 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
/*
 * https://wiki.osdev.org/%228042%22_PS/2_Controller
 */

#include "keyboard.h"
#include "ps2_controller.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/io.h>

/* r   status register */
/*  w  command register */
#define comm_port 0x64
#define comm_enable_first_ps2 0xae
#define comm_enable_second_ps2 0xa8
#define comm_read_ctrl_config 0x20
#define comm_write_ctrl_config 0x60

#define data_port 0x60
#define data_enable_scanning 0xf4

/* TODO: All output to port 0x60 or 0x64 must be preceded by waiting for bit 1 (value=2) of port 0x64 to become clear.
 * TODO: Similarly, bytes cannot be read from port 0x60 until bit 0 (value=1) of port 0x64 is set. */

void
ps2_ctrl_init()
{
  int i;
  uint8_t test, conf;

  /* eat all previous keystrikes */
  while (inb(comm_port) & 0x1) inb(data_port);

  outb(0xaa, comm_port);
  test = inb(data_port);
  printf("i8042: self test  0xaa:%x %s\n", test, test == 0x55 ? "ok" : "failed");
  outb(0xab, comm_port);
  test = inb(data_port);
  printf("i8042: port1 test 0xab:%x %s\n", test, test == 0x00 ? "ok" : "failed");
  outb(0xa9, comm_port);
  test = inb(data_port);
  printf("i8042: port2 test 0xa9:%x %s\n", test, test == 0x00 ? "ok" : "failed");

  /* printf("8042: init keyboard\n"); */

  outb(comm_enable_first_ps2, comm_port);
  outb(comm_enable_second_ps2, comm_port);

  /* resets the cpu */
  /* outb(0xfe, 0x64); */

  outb(0xf2, 0x60);
  printf("i8042: id port1: ");
  while ((inb(0x64) & 0x01) == 0) {}
  for (i = 0; i < 3; ++i) printf("%x ", inb(0x60));
  printf("\n");

  outb(0xd4, 0x64);
  outb(0xf2, 0x60);
  printf("i8042: id port2: ");
  while ((inb(0x64) & 0x01) == 0) {}
  for (i = 0; i < 3; ++i) printf("%x ", inb(0x60));
  printf("\n");

  outb(comm_read_ctrl_config, comm_port);
  conf = (uint8_t)((inb(data_port) | 1) & ~0x10);
  conf |= 0x22; /* mouse */
  outb(comm_write_ctrl_config, comm_port);

  outb(conf, data_port);
  outb(data_enable_scanning, data_port);

  outb(0xd4, 0x64);
  outb(0xf4, 0x60);
}

unsigned char
ps2_read_port1()
{
  return inb(data_port);
}

unsigned char
ps2_read_port2()
{
  outb(0xd4, 0x64);
  return inb(0x60);
}