NIX mode.
[akaros.git] / kern / arch / x86 / intel.c
1 /* Copyright (c) 2014 The Regents of the University of California
2  * See LICENSE for details.
3  *
4  * Barret Rhoden <brho@cs.berkeley.edu> */
5
6 #include <arch/x86.h>
7 #include <arch/pci.h>
8 #include <trap.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <assert.h>
12 #include <kmalloc.h>
13 #include <time.h>
14 #include <mm.h>
15
16 /* super-shoddy LPC chip initialization.
17  *
18  * the PCH (old southbridge) is a c602, TBDF x:1f:00 LPC controller
19  * - PMBASE is the mnemonic for "ACPI Base Address"
20  * - TCO is 0x60 off in the PMBASE space
21  * - PMBASE + 0x30 is an SMI control reg
22  *
23  * TODO:
24  * - why don't we find the other functions (1f.2 and 1f.3, in linux)?
25  */
26 static void lpc_init_pci(struct pci_device *pcidev)
27 {
28         uint32_t pmbase = pcidev_read32(pcidev, 0x40);
29
30         pmbase &= ~1; /* clear bit 0 */
31         uint32_t smi_ctl = inl(pmbase + 0x30);
32         #if 0
33         /* halt the tco timer: this busts things, and won't work with the lock on */
34         uint16_t tco1 = inw(pmbase + 0x60 + 0x08);
35         if (tco1 & (1 << 12)) {
36                 printk("\t\tTCO_LOCK is on!\n");
37         } else {
38                 outw(pmbase + 0x60 + 0x08, tco1 & ~(1 << 11));
39                 tco1 = inw(pmbase + 0x60 + 0x08);
40         }
41         #endif
42         /* bit 6 is another timer, one that messes up c89. */
43         outl(pmbase + 0x30, smi_ctl & ~(1 << 6));
44         smi_ctl = inl(pmbase + 0x30);
45 }
46
47 void intel_lpc_init()
48 {
49         struct pci_device *i;
50         STAILQ_FOREACH(i, &pci_devices, all_dev) {
51                 if ((i->dev == 0x1f) && (i->func == 0x00))
52                         lpc_init_pci(i);
53         }
54 }