File: /usr/src/linux/drivers/acpi/ospm/processor/pr_osl.c
1 /******************************************************************************
2 *
3 * Module Name: pr_osl.c
4 * $Revision: 18 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 Andrew Grover
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/init.h>
30 #include <linux/types.h>
31 #include <linux/proc_fs.h>
32 #include <linux/pci.h>
33 #include <acpi.h>
34 #include <bm.h>
35 #include "pr.h"
36
37
38 MODULE_AUTHOR("Andrew Grover");
39 MODULE_DESCRIPTION("ACPI Component Architecture (CA) - IA32 Processor Driver");
40 MODULE_LICENSE("GPL");
41
42
43 #define PR_PROC_ROOT "processor"
44 #define PR_PROC_STATUS "status"
45 #define PR_PROC_INFO "info"
46
47 extern struct proc_dir_entry *bm_proc_root;
48 static struct proc_dir_entry *pr_proc_root = NULL;
49 extern unsigned short acpi_piix4_bmisx;
50
51
52 /****************************************************************************
53 *
54 * FUNCTION: pr_osl_proc_read_status
55 *
56 ****************************************************************************/
57
58 static int
59 pr_osl_proc_read_status (
60 char *page,
61 char **start,
62 off_t off,
63 int count,
64 int *eof,
65 void *context)
66 {
67 PR_CONTEXT *processor = NULL;
68 char *p = page;
69 int len = 0;
70
71 if (!context || (off != 0)) {
72 goto end;
73 }
74
75 processor = (PR_CONTEXT*)context;
76
77 p += sprintf(p, "Bus Mastering Activity: %08x\n",
78 processor->power.bm_activity);
79
80 p += sprintf(p, "C-State Utilization: C1[%d] C2[%d] C3[%d]\n",
81 processor->power.state[PR_C1].utilization,
82 processor->power.state[PR_C2].utilization,
83 processor->power.state[PR_C3].utilization);
84
85 end:
86 len = (p - page);
87 if (len <= off+count) *eof = 1;
88 *start = page + off;
89 len -= off;
90 if (len>count) len = count;
91 if (len<0) len = 0;
92
93 return(len);
94 }
95
96
97 /****************************************************************************
98 *
99 * FUNCTION: pr_osl_proc_read_info
100 *
101 ****************************************************************************/
102
103 static int
104 pr_osl_proc_read_info (
105 char *page,
106 char **start,
107 off_t off,
108 int count,
109 int *eof,
110 void *context)
111 {
112 PR_CONTEXT *processor = NULL;
113 char *p = page;
114 int len = 0;
115
116 if (!context || (off != 0)) {
117 goto end;
118 }
119
120 processor = (PR_CONTEXT*)context;
121
122 p += sprintf(p, "<TBD>\n");
123
124 end:
125 len = (p - page);
126 if (len <= off+count) *eof = 1;
127 *start = page + off;
128 len -= off;
129 if (len>count) len = count;
130 if (len<0) len = 0;
131
132 return(len);
133 }
134
135
136 /****************************************************************************
137 *
138 * FUNCTION: pr_osl_add_device
139 *
140 ****************************************************************************/
141
142 acpi_status
143 pr_osl_add_device(
144 PR_CONTEXT *processor)
145 {
146 u32 i = 0;
147 struct proc_dir_entry *proc_entry = NULL;
148 char processor_uid[16];
149
150 if (!processor) {
151 return(AE_BAD_PARAMETER);
152 }
153
154 printk("Processor[%x]:", processor->uid);
155 for (i=0; i<processor->power.state_count; i++) {
156 if (processor->power.state[i].is_valid) {
157 printk(" C%d", i);
158 }
159 }
160
161 if (processor->performance.state_count > 1) {
162 printk(", throttling states: %d", processor->performance.state_count);
163 }
164
165 if (acpi_piix4_bmisx)
166 printk(", PIIX workaround active");
167
168 printk("\n");
169
170 sprintf(processor_uid, "%d", processor->uid);
171
172 proc_entry = proc_mkdir(processor_uid, pr_proc_root);
173 if (!proc_entry) {
174 return(AE_ERROR);
175 }
176
177 create_proc_read_entry(PR_PROC_STATUS, S_IFREG | S_IRUGO,
178 proc_entry, pr_osl_proc_read_status, (void*)processor);
179
180 create_proc_read_entry(PR_PROC_INFO, S_IFREG | S_IRUGO,
181 proc_entry, pr_osl_proc_read_info, (void*)processor);
182
183 return(AE_OK);
184 }
185
186
187 /****************************************************************************
188 *
189 * FUNCTION: pr_osl_remove_device
190 *
191 ****************************************************************************/
192
193 acpi_status
194 pr_osl_remove_device (
195 PR_CONTEXT *processor)
196 {
197 char proc_entry[64];
198
199 if (!processor) {
200 return(AE_BAD_PARAMETER);
201 }
202
203 sprintf(proc_entry, "%d/%s", processor->uid, PR_PROC_INFO);
204 remove_proc_entry(proc_entry, pr_proc_root);
205
206 sprintf(proc_entry, "%d/%s", processor->uid, PR_PROC_STATUS);
207 remove_proc_entry(proc_entry, pr_proc_root);
208
209 sprintf(proc_entry, "%d", processor->uid);
210 remove_proc_entry(proc_entry, pr_proc_root);
211
212 return(AE_OK);
213 }
214
215
216 /****************************************************************************
217 *
218 * FUNCTION: pr_osl_generate_event
219 *
220 ****************************************************************************/
221
222 acpi_status
223 pr_osl_generate_event (
224 u32 event,
225 PR_CONTEXT *processor)
226 {
227 acpi_status status = AE_OK;
228 char processor_uid[16];
229
230 if (!processor) {
231 return(AE_BAD_PARAMETER);
232 }
233
234 switch (event) {
235
236 case PR_NOTIFY_PERF_STATES:
237 case PR_NOTIFY_POWER_STATES:
238 sprintf(processor_uid, "%d", processor->uid);
239 status = bm_osl_generate_event(processor->device_handle,
240 PR_PROC_ROOT, processor_uid, event, 0);
241 break;
242
243 default:
244 return(AE_BAD_PARAMETER);
245 break;
246 }
247
248 return(status);
249 }
250
251
252 /****************************************************************************
253 * Errata Handling
254 ****************************************************************************/
255
256 void acpi_pr_errata (void)
257 {
258 struct pci_dev *dev = NULL;
259
260 while ((dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
261 PCI_ANY_ID, PCI_ANY_ID, dev))) {
262 switch (dev->device) {
263 case PCI_DEVICE_ID_INTEL_82801BA_8: /* PIIX4U4 */
264 case PCI_DEVICE_ID_INTEL_82801BA_9: /* PIIX4U3 */
265 case PCI_DEVICE_ID_INTEL_82451NX: /* PIIX4NX */
266 case PCI_DEVICE_ID_INTEL_82372FB_1: /* PIIX4U2 */
267 case PCI_DEVICE_ID_INTEL_82801AA_1: /* PIIX4U */
268 case PCI_DEVICE_ID_INTEL_82443MX_1: /* PIIX4E2 */
269 case PCI_DEVICE_ID_INTEL_82801AB_1: /* PIIX4E */
270 case PCI_DEVICE_ID_INTEL_82371AB: /* PIIX4 */
271 acpi_piix4_bmisx = pci_resource_start(dev, 4);
272 return;
273 }
274 }
275
276 return;
277 }
278
279
280 /****************************************************************************
281 *
282 * FUNCTION: pr_osl_init
283 *
284 * PARAMETERS: <none>
285 *
286 * RETURN: 0: Success
287 *
288 * DESCRIPTION: Module initialization.
289 *
290 ****************************************************************************/
291
292 static int __init
293 pr_osl_init (void)
294 {
295 acpi_status status = AE_OK;
296
297 /* abort if no busmgr */
298 if (!bm_proc_root)
299 return -ENODEV;
300
301 acpi_pr_errata();
302
303 pr_proc_root = proc_mkdir(PR_PROC_ROOT, bm_proc_root);
304 if (!pr_proc_root) {
305 status = AE_ERROR;
306 }
307 else {
308 status = pr_initialize();
309 if (ACPI_FAILURE(status)) {
310 remove_proc_entry(PR_PROC_ROOT, bm_proc_root);
311 }
312
313 }
314
315 return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
316 }
317
318
319 /****************************************************************************
320 *
321 * FUNCTION: pr_osl_cleanup
322 *
323 * PARAMETERS: <none>
324 *
325 * RETURN: <none>
326 *
327 * DESCRIPTION: Module cleanup.
328 *
329 ****************************************************************************/
330
331 static void __exit
332 pr_osl_cleanup (void)
333 {
334 pr_terminate();
335
336 if (pr_proc_root) {
337 remove_proc_entry(PR_PROC_ROOT, bm_proc_root);
338 }
339
340 return;
341 }
342
343
344 module_init(pr_osl_init);
345 module_exit(pr_osl_cleanup);
346