Root/
Source at commit 1166 created 13 years 10 days ago. By meklort, Fixed recent Makefile changes. Please do not use /Users/evan/SourceCode/tmp/chameleon/trunk or VPATH. the *only* time you should use /Users/evan/SourceCode/tmp/chameleon/trunk is when setting the SRCROOT variable. Also note that very soon make pkg is going to be removed. The pkg build script in trunk is very out of date. Instead please use the package maker at http://forge.voodooprojects.org/p/chameleonApplications/. Once this is ready for trunk it will be merged. | |
---|---|
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 | ␊ |
23 | void force_enable_hpet_intel(pci_dt_t *lpc_dev);␊ |
24 | void force_enable_hpet_via(pci_dt_t *lpc_dev);␊ |
25 | ␊ |
26 | ␊ |
27 | void HPET_hook(void* arg1, void* arg2, void* arg3, void* arg4)␊ |
28 | {␊ |
29 | ␉pci_dt_t* current = arg1;␊ |
30 | ␉␊ |
31 | ␉if(current->class_id != PCI_CLASS_BRIDGE_ISA) return;␊ |
32 | ␉␊ |
33 | ␉␊ |
34 | ␉bool do_enable_hpet = true;␊ |
35 | ␉getBoolForKey(kForceHPET, &do_enable_hpet, &bootInfo->bootConfig);␊ |
36 | ␊ |
37 | ␉if (do_enable_hpet)␊ |
38 | ␉␉force_enable_hpet(current);␊ |
39 | }␊ |
40 | ␊ |
41 | void HPET_start()␊ |
42 | {␊ |
43 | ␉register_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 | ␊ |
52 | static 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 | ␊ |
88 | static struct lpc_controller_t lpc_controllers_via[] = {␊ |
89 | ␉// Default unknown chipset␊ |
90 | ␉{ 0, 0, "" },␊ |
91 | ␉␊ |
92 | ␉{ 0x1106, 0x3372, "VT8237S" },␊ |
93 | };␊ |
94 | ␊ |
95 | ␊ |
96 | void force_enable_hpet(pci_dt_t *lpc_dev)␊ |
97 | {␊ |
98 | ␉switch(lpc_dev->vendor_id)␊ |
99 | ␉{␊ |
100 | ␉␉case 0x8086:␊ |
101 | ␉␉␉force_enable_hpet_intel(lpc_dev);␊ |
102 | ␉␉␉break;␊ |
103 | ␉␉␉␊ |
104 | ␉␉case 0x1106:␊ |
105 | ␉␉␉force_enable_hpet_via(lpc_dev);␊ |
106 | ␉␉␉break;␊ |
107 | ␉}␊ |
108 | ␉␊ |
109 | ␉␊ |
110 | #if DEBUG_HPET␊ |
111 | ␉printf("Press [Enter] to continue...\n");␊ |
112 | ␉getc();␊ |
113 | #endif␊ |
114 | }␊ |
115 | ␊ |
116 | void force_enable_hpet_via(pci_dt_t *lpc_dev)␊ |
117 | {␊ |
118 | ␉uint32_t␉val, hpet_address = 0xFED00000;␊ |
119 | ␉int i;␊ |
120 | ␉␊ |
121 | ␉for(i = 1; i < sizeof(lpc_controllers_via) / sizeof(lpc_controllers_via[0]); i++)␊ |
122 | ␉{␊ |
123 | ␉␉if (␉(lpc_controllers_via[i].vendor == lpc_dev->vendor_id) ␊ |
124 | ␉␉␉&& (lpc_controllers_via[i].device == lpc_dev->device_id))␊ |
125 | ␉␉{␉␊ |
126 | ␉␉␉val = pci_config_read32(lpc_dev->dev.addr, 0x68);␊ |
127 | ␉␉␉␊ |
128 | ␉␉␉DBG("VIA %s LPC Interface [%04x:%04x], MMIO\n", ␊ |
129 | ␉␉␉␉lpc_controllers_via[i].name, lpc_dev->vendor_id, lpc_dev->device_id);␊ |
130 | ␉␉␉␊ |
131 | ␉␉␉if (val & 0x80) {␊ |
132 | ␉␉␉␉hpet_address = (val & ~0x3ff);␊ |
133 | ␉␉␉␉DBG("HPET at 0x%lx\n", hpet_address);␊ |
134 | ␉␉␉}␊ |
135 | ␉␉␉else ␊ |
136 | ␉␉␉{␊ |
137 | ␉␉␉␉val = 0xfed00000 | 0x80;␊ |
138 | ␉␉␉␉pci_config_write32(lpc_dev->dev.addr, 0x68, val);␊ |
139 | ␉␉␉␉val = pci_config_read32(lpc_dev->dev.addr, 0x68);␊ |
140 | ␉␉␉␉if (val & 0x80) {␊ |
141 | ␉␉␉␉␉hpet_address = (val & ~0x3ff);␊ |
142 | ␉␉␉␉␉DBG("Force enabled HPET at 0x%lx\n", hpet_address);␊ |
143 | ␉␉␉␉}␊ |
144 | ␉␉␉␉else {␊ |
145 | ␉␉␉␉␉DBG("Unable to enable HPET");␊ |
146 | ␉␉␉␉}␊ |
147 | ␉␉␉}␊ |
148 | ␉␉}␊ |
149 | ␉}␊ |
150 | }␊ |
151 | ␊ |
152 | ␊ |
153 | ␊ |
154 | void force_enable_hpet_intel(pci_dt_t *lpc_dev)␊ |
155 | {␊ |
156 | ␉uint32_t␉val, hpet_address = 0xFED00000;␊ |
157 | ␉int i;␊ |
158 | ␉void␉␉*rcba;␊ |
159 | ␉␊ |
160 | ␉/* LPC on Intel ICH is always (?) at 00:1f.0 */␊ |
161 | ␉for(i = 1; i < sizeof(lpc_controllers_intel) / sizeof(lpc_controllers_intel[0]); i++)␊ |
162 | ␉{␊ |
163 | ␉␉if (␉(lpc_controllers_intel[i].vendor == lpc_dev->vendor_id) ␊ |
164 | ␉␉␉&& (lpc_controllers_intel[i].device == lpc_dev->device_id))␊ |
165 | ␉␉{␉␊ |
166 | ␉␉␉␊ |
167 | ␉␉␉rcba = (void *)(pci_config_read32(lpc_dev->dev.addr, 0xF0) & 0xFFFFC000);␊ |
168 | ␉␉␉␊ |
169 | ␉␉␉DBG("Intel(R) %s LPC Interface [%04x:%04x], MMIO @ 0x%lx\n", ␊ |
170 | ␉␉␉␉lpc_controllers_intel[i].name, lpc_dev->vendor_id, lpc_dev->device_id, rcba);␊ |
171 | ␉␉␉␊ |
172 | ␉␉␉if (rcba == 0)␊ |
173 | ␉␉␉␉printf(" RCBA disabled; cannot force enable HPET\n");␊ |
174 | ␉␉␉else␊ |
175 | ␉␉␉{␊ |
176 | ␉␉␉␉val = REG32(rcba, 0x3404);␊ |
177 | ␉␉␉␉if (val & 0x80)␊ |
178 | ␉␉␉␉{␊ |
179 | ␉␉␉␉␉// HPET is enabled in HPTC. Just not reported by BIOS␊ |
180 | ␉␉␉␉␉DBG(" HPET is enabled in HPTC, just not reported by BIOS\n");␊ |
181 | ␉␉␉␉␉hpet_address |= (val & 3) << 12 ;␊ |
182 | ␉␉␉␉␉DBG(" HPET MMIO @ 0x%lx\n", hpet_address);␊ |
183 | ␉␉␉␉}␊ |
184 | ␉␉␉␉else␊ |
185 | ␉␉␉␉{␊ |
186 | ␉␉␉␉␉// HPET disabled in HPTC. Trying to enable␊ |
187 | ␉␉␉␉␉DBG(" HPET is disabled in HPTC, trying to enable\n");␉␉␉␉␉␉␉␉␉␊ |
188 | ␉␉␉␉␉REG32(rcba, 0x3404) = val | 0x80;␊ |
189 | ␉␉␉␉␉hpet_address |= (val & 3) << 12 ;␊ |
190 | ␉␉␉␉␉DBG(" Force enabled HPET, MMIO @ 0x%lx\n", hpet_address);␊ |
191 | ␉␉␉␉}␊ |
192 | ␉␉␉␉␊ |
193 | ␉␉␉␉// verify if the job is done␊ |
194 | ␉␉␉␉val = REG32(rcba, 0x3404);␊ |
195 | ␉␉␉␉if (!(val & 0x80))␊ |
196 | ␉␉␉␉␉printf(" Failed to force enable HPET\n");␊ |
197 | ␉␉␉}␊ |
198 | ␉␉␉break;␊ |
199 | ␉␉␉␊ |
200 | ␉␉}␊ |
201 | ␉}␊ |
202 | } |