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