Chameleon

Chameleon Svn Source Tree

Root/branches/slice/i386/modules/HPET/HPET.c

1/*
2 * Copyright (c) 2009 Evan Lojewski. All rights reserved.
3 *
4 */
5
6#include "libsaio.h"
7#include "modules.h"
8#include "boot.h"
9#include "bootstruct.h"
10#include "pci.h"
11#include "hpet.h"
12
13#ifndef DEBUG_HPET
14#define DEBUG_HPET 0
15#endif
16
17#if DEBUG_HPET
18#define DBG(x...) printf(x)
19#else
20#define DBG(x...)
21#endif
22
23void force_enable_hpet_intel(pci_dt_t *lpc_dev);
24void force_enable_hpet_via(pci_dt_t *lpc_dev);
25
26
27void HPET_hook(void* arg1, void* arg2, void* arg3, void* arg4)
28{
29pci_dt_t* current = arg1;
30
31if(current->class_id != PCI_CLASS_BRIDGE_ISA) return;
32
33
34bool do_enable_hpet = true;
35getBoolForKey(kForceHPET, &do_enable_hpet, &bootInfo->bootConfig);
36
37if (do_enable_hpet)
38force_enable_hpet(current);
39}
40
41void HPET_start()
42{
43register_hook_callback("PCIDevice", &HPET_hook);
44}
45
46/*
47 * Force HPET enabled
48 *
49 * via fix from http://forum.voodooprojects.org/index.php/topic,1596.0.html
50 */
51
52static struct lpc_controller_t lpc_controllers_intel[] = {
53
54// Default unknown chipset
55{ 0, 0, "" },
56
57// Intel
58{ 0x8086, 0x24dc, "ICH5" },
59{ 0x8086, 0x2640, "ICH6" },
60{ 0x8086, 0x2641, "ICH6M" },
61
62{ 0x8086, 0x27b0, "ICH7 DH" },
63{ 0x8086, 0x27b8, "ICH7" },
64{ 0x8086, 0x27b9, "ICH7M" },
65{ 0x8086, 0x27bd, "ICH7M DH" },
66
67{ 0x8086, 0x27bc, "NM10" },
68
69{ 0x8086, 0x2810, "ICH8R" },
70{ 0x8086, 0x2811, "ICH8M-E" },
71{ 0x8086, 0x2812, "ICH8DH" },
72{ 0x8086, 0x2814, "ICH8DO" },
73{ 0x8086, 0x2815, "ICH8M" },
74
75{ 0x8086, 0x2912, "ICH9DH" },
76{ 0x8086, 0x2914, "ICH9DO" },
77{ 0x8086, 0x2916, "ICH9R" },
78{ 0x8086, 0x2917, "ICH9M-E" },
79{ 0x8086, 0x2918, "ICH9" },
80{ 0x8086, 0x2919, "ICH9M" },
81
82{ 0x8086, 0x3a14, "ICH10DO" },
83{ 0x8086, 0x3a16, "ICH10R" },
84{ 0x8086, 0x3a18, "ICH10" },
85{ 0x8086, 0x3a1a, "ICH10D" },
86};
87
88static struct lpc_controller_t lpc_controllers_via[] = {
89// Default unknown chipset
90{ 0, 0, "" },
91
92{ 0x1106, 0x3372, "VT8237S" },
93};
94
95
96void force_enable_hpet(pci_dt_t *lpc_dev)
97{
98switch(lpc_dev->vendor_id)
99{
100case 0x8086:
101force_enable_hpet_intel(lpc_dev);
102break;
103
104case 0x1106:
105force_enable_hpet_via(lpc_dev);
106break;
107}
108
109
110#if DEBUG_HPET
111printf("Press [Enter] to continue...\n");
112getc();
113#endif
114}
115
116void force_enable_hpet_via(pci_dt_t *lpc_dev)
117{
118uint32_tval, hpet_address = 0xFED00000;
119int i;
120
121for(i = 1; i < sizeof(lpc_controllers_via) / sizeof(lpc_controllers_via[0]); i++)
122{
123if ((lpc_controllers_via[i].vendor == lpc_dev->vendor_id)
124&& (lpc_controllers_via[i].device == lpc_dev->device_id))
125{
126val = pci_config_read32(lpc_dev->dev.addr, 0x68);
127
128DBG("VIA %s LPC Interface [%04x:%04x], MMIO\n",
129lpc_controllers_via[i].name, lpc_dev->vendor_id, lpc_dev->device_id);
130
131if (val & 0x80) {
132hpet_address = (val & ~0x3ff);
133DBG("HPET at 0x%lx\n", hpet_address);
134}
135else
136{
137val = 0xfed00000 | 0x80;
138pci_config_write32(lpc_dev->dev.addr, 0x68, val);
139val = pci_config_read32(lpc_dev->dev.addr, 0x68);
140if (val & 0x80) {
141hpet_address = (val & ~0x3ff);
142DBG("Force enabled HPET at 0x%lx\n", hpet_address);
143}
144else {
145DBG("Unable to enable HPET");
146}
147}
148}
149}
150}
151
152
153
154void force_enable_hpet_intel(pci_dt_t *lpc_dev)
155{
156uint32_tval, hpet_address = 0xFED00000;
157int i;
158void*rcba;
159
160/* LPC on Intel ICH is always (?) at 00:1f.0 */
161for(i = 1; i < sizeof(lpc_controllers_intel) / sizeof(lpc_controllers_intel[0]); i++)
162{
163if ((lpc_controllers_intel[i].vendor == lpc_dev->vendor_id)
164&& (lpc_controllers_intel[i].device == lpc_dev->device_id))
165{
166
167rcba = (void *)(pci_config_read32(lpc_dev->dev.addr, 0xF0) & 0xFFFFC000);
168
169DBG("Intel(R) %s LPC Interface [%04x:%04x], MMIO @ 0x%lx\n",
170lpc_controllers_intel[i].name, lpc_dev->vendor_id, lpc_dev->device_id, rcba);
171
172if (rcba == 0)
173printf(" RCBA disabled; cannot force enable HPET\n");
174else
175{
176val = REG32(rcba, 0x3404);
177if (val & 0x80)
178{
179// HPET is enabled in HPTC. Just not reported by BIOS
180DBG(" HPET is enabled in HPTC, just not reported by BIOS\n");
181hpet_address |= (val & 3) << 12 ;
182DBG(" HPET MMIO @ 0x%lx\n", hpet_address);
183}
184else
185{
186// HPET disabled in HPTC. Trying to enable
187DBG(" HPET is disabled in HPTC, trying to enable\n");
188REG32(rcba, 0x3404) = val | 0x80;
189hpet_address |= (val & 3) << 12 ;
190DBG(" Force enabled HPET, MMIO @ 0x%lx\n", hpet_address);
191}
192
193// verify if the job is done
194val = REG32(rcba, 0x3404);
195if (!(val & 0x80))
196printf(" Failed to force enable HPET\n");
197}
198break;
199}
200#if DEBUG_HPET
201printf("Press [Enter] to continue...\n");
202getc();
203#endif
204}
205}

Archive Download this file

Revision: 676