Contents of /alx-src/tags/kernel26-2.6.12-alx-r9/drivers/mca/mca-proc.c
Parent Directory
|
Revision Log
Revision 630 -
(show annotations)
(download)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 7286 byte(s)
Wed Mar 4 11:03:09 2009 UTC (15 years, 3 months ago) by niro
File MIME type: text/plain
File size: 7286 byte(s)
Tag kernel26-2.6.12-alx-r9
1 | /* -*- mode: c; c-basic-offset: 8 -*- */ |
2 | |
3 | /* |
4 | * MCA bus support functions for the proc fs. |
5 | * |
6 | * NOTE: this code *requires* the legacy MCA api. |
7 | * |
8 | * Legacy API means the API that operates in terms of MCA slot number |
9 | * |
10 | * (C) 2002 James Bottomley <James.Bottomley@HansenPartnership.com> |
11 | * |
12 | **----------------------------------------------------------------------------- |
13 | ** |
14 | ** This program is free software; you can redistribute it and/or modify |
15 | ** it under the terms of the GNU General Public License as published by |
16 | ** the Free Software Foundation; either version 2 of the License, or |
17 | ** (at your option) any later version. |
18 | ** |
19 | ** This program is distributed in the hope that it will be useful, |
20 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
21 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22 | ** GNU General Public License for more details. |
23 | ** |
24 | ** You should have received a copy of the GNU General Public License |
25 | ** along with this program; if not, write to the Free Software |
26 | ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
27 | ** |
28 | **----------------------------------------------------------------------------- |
29 | */ |
30 | #include <linux/module.h> |
31 | #include <linux/init.h> |
32 | #include <linux/proc_fs.h> |
33 | #include <linux/mca.h> |
34 | |
35 | static int get_mca_info_helper(struct mca_device *mca_dev, char *page, int len) |
36 | { |
37 | int j; |
38 | |
39 | for(j=0; j<8; j++) |
40 | len += sprintf(page+len, "%02x ", |
41 | mca_dev ? mca_dev->pos[j] : 0xff); |
42 | len += sprintf(page+len, " %s\n", mca_dev ? mca_dev->name : ""); |
43 | return len; |
44 | } |
45 | |
46 | static int get_mca_info(char *page, char **start, off_t off, |
47 | int count, int *eof, void *data) |
48 | { |
49 | int i, len = 0; |
50 | |
51 | if(MCA_bus) { |
52 | struct mca_device *mca_dev; |
53 | /* Format POS registers of eight MCA slots */ |
54 | |
55 | for(i=0; i<MCA_MAX_SLOT_NR; i++) { |
56 | mca_dev = mca_find_device_by_slot(i); |
57 | |
58 | len += sprintf(page+len, "Slot %d: ", i+1); |
59 | len = get_mca_info_helper(mca_dev, page, len); |
60 | } |
61 | |
62 | /* Format POS registers of integrated video subsystem */ |
63 | |
64 | mca_dev = mca_find_device_by_slot(MCA_INTEGVIDEO); |
65 | len += sprintf(page+len, "Video : "); |
66 | len = get_mca_info_helper(mca_dev, page, len); |
67 | |
68 | /* Format POS registers of integrated SCSI subsystem */ |
69 | |
70 | mca_dev = mca_find_device_by_slot(MCA_INTEGSCSI); |
71 | len += sprintf(page+len, "SCSI : "); |
72 | len = get_mca_info_helper(mca_dev, page, len); |
73 | |
74 | /* Format POS registers of motherboard */ |
75 | |
76 | mca_dev = mca_find_device_by_slot(MCA_MOTHERBOARD); |
77 | len += sprintf(page+len, "Planar: "); |
78 | len = get_mca_info_helper(mca_dev, page, len); |
79 | } else { |
80 | /* Leave it empty if MCA not detected - this should *never* |
81 | * happen! |
82 | */ |
83 | } |
84 | |
85 | if (len <= off+count) *eof = 1; |
86 | *start = page + off; |
87 | len -= off; |
88 | if (len>count) len = count; |
89 | if (len<0) len = 0; |
90 | return len; |
91 | } |
92 | |
93 | /*--------------------------------------------------------------------*/ |
94 | |
95 | static int mca_default_procfn(char* buf, struct mca_device *mca_dev) |
96 | { |
97 | int len = 0, i; |
98 | int slot = mca_dev->slot; |
99 | |
100 | /* Print out the basic information */ |
101 | |
102 | if(slot < MCA_MAX_SLOT_NR) { |
103 | len += sprintf(buf+len, "Slot: %d\n", slot+1); |
104 | } else if(slot == MCA_INTEGSCSI) { |
105 | len += sprintf(buf+len, "Integrated SCSI Adapter\n"); |
106 | } else if(slot == MCA_INTEGVIDEO) { |
107 | len += sprintf(buf+len, "Integrated Video Adapter\n"); |
108 | } else if(slot == MCA_MOTHERBOARD) { |
109 | len += sprintf(buf+len, "Motherboard\n"); |
110 | } |
111 | if (mca_dev->name[0]) { |
112 | |
113 | /* Drivers might register a name without /proc handler... */ |
114 | |
115 | len += sprintf(buf+len, "Adapter Name: %s\n", |
116 | mca_dev->name); |
117 | } else { |
118 | len += sprintf(buf+len, "Adapter Name: Unknown\n"); |
119 | } |
120 | len += sprintf(buf+len, "Id: %02x%02x\n", |
121 | mca_dev->pos[1], mca_dev->pos[0]); |
122 | len += sprintf(buf+len, "Enabled: %s\nPOS: ", |
123 | mca_device_status(mca_dev) == MCA_ADAPTER_NORMAL ? |
124 | "Yes" : "No"); |
125 | for(i=0; i<8; i++) { |
126 | len += sprintf(buf+len, "%02x ", mca_dev->pos[i]); |
127 | } |
128 | len += sprintf(buf+len, "\nDriver Installed: %s", |
129 | mca_device_claimed(mca_dev) ? "Yes" : "No"); |
130 | buf[len++] = '\n'; |
131 | buf[len] = 0; |
132 | |
133 | return len; |
134 | } /* mca_default_procfn() */ |
135 | |
136 | static int get_mca_machine_info(char* page, char **start, off_t off, |
137 | int count, int *eof, void *data) |
138 | { |
139 | int len = 0; |
140 | |
141 | len += sprintf(page+len, "Model Id: 0x%x\n", machine_id); |
142 | len += sprintf(page+len, "Submodel Id: 0x%x\n", machine_submodel_id); |
143 | len += sprintf(page+len, "BIOS Revision: 0x%x\n", BIOS_revision); |
144 | |
145 | if (len <= off+count) *eof = 1; |
146 | *start = page + off; |
147 | len -= off; |
148 | if (len>count) len = count; |
149 | if (len<0) len = 0; |
150 | return len; |
151 | } |
152 | |
153 | static int mca_read_proc(char *page, char **start, off_t off, |
154 | int count, int *eof, void *data) |
155 | { |
156 | struct mca_device *mca_dev = (struct mca_device *)data; |
157 | int len = 0; |
158 | |
159 | /* Get the standard info */ |
160 | |
161 | len = mca_default_procfn(page, mca_dev); |
162 | |
163 | /* Do any device-specific processing, if there is any */ |
164 | |
165 | if(mca_dev->procfn) { |
166 | len += mca_dev->procfn(page+len, mca_dev->slot, |
167 | mca_dev->proc_dev); |
168 | } |
169 | if (len <= off+count) *eof = 1; |
170 | *start = page + off; |
171 | len -= off; |
172 | if (len>count) len = count; |
173 | if (len<0) len = 0; |
174 | return len; |
175 | } /* mca_read_proc() */ |
176 | |
177 | /*--------------------------------------------------------------------*/ |
178 | |
179 | void __init mca_do_proc_init(void) |
180 | { |
181 | int i; |
182 | struct proc_dir_entry *proc_mca; |
183 | struct proc_dir_entry* node = NULL; |
184 | struct mca_device *mca_dev; |
185 | |
186 | proc_mca = proc_mkdir("mca", &proc_root); |
187 | create_proc_read_entry("pos",0,proc_mca,get_mca_info,NULL); |
188 | create_proc_read_entry("machine",0,proc_mca,get_mca_machine_info,NULL); |
189 | |
190 | /* Initialize /proc/mca entries for existing adapters */ |
191 | |
192 | for(i = 0; i < MCA_NUMADAPTERS; i++) { |
193 | enum MCA_AdapterStatus status; |
194 | mca_dev = mca_find_device_by_slot(i); |
195 | if(!mca_dev) |
196 | continue; |
197 | |
198 | mca_dev->procfn = NULL; |
199 | |
200 | if(i < MCA_MAX_SLOT_NR) sprintf(mca_dev->procname,"slot%d", i+1); |
201 | else if(i == MCA_INTEGVIDEO) sprintf(mca_dev->procname,"video"); |
202 | else if(i == MCA_INTEGSCSI) sprintf(mca_dev->procname,"scsi"); |
203 | else if(i == MCA_MOTHERBOARD) sprintf(mca_dev->procname,"planar"); |
204 | |
205 | status = mca_device_status(mca_dev); |
206 | if (status != MCA_ADAPTER_NORMAL && |
207 | status != MCA_ADAPTER_DISABLED) |
208 | continue; |
209 | |
210 | node = create_proc_read_entry(mca_dev->procname, 0, proc_mca, |
211 | mca_read_proc, (void *)mca_dev); |
212 | |
213 | if(node == NULL) { |
214 | printk("Failed to allocate memory for MCA proc-entries!"); |
215 | return; |
216 | } |
217 | } |
218 | |
219 | } /* mca_do_proc_init() */ |
220 | |
221 | /** |
222 | * mca_set_adapter_procfn - Set the /proc callback |
223 | * @slot: slot to configure |
224 | * @procfn: callback function to call for /proc |
225 | * @dev: device information passed to the callback |
226 | * |
227 | * This sets up an information callback for /proc/mca/slot?. The |
228 | * function is called with the buffer, slot, and device pointer (or |
229 | * some equally informative context information, or nothing, if you |
230 | * prefer), and is expected to put useful information into the |
231 | * buffer. The adapter name, ID, and POS registers get printed |
232 | * before this is called though, so don't do it again. |
233 | * |
234 | * This should be called with a %NULL @procfn when a module |
235 | * unregisters, thus preventing kernel crashes and other such |
236 | * nastiness. |
237 | */ |
238 | |
239 | void mca_set_adapter_procfn(int slot, MCA_ProcFn procfn, void* proc_dev) |
240 | { |
241 | struct mca_device *mca_dev = mca_find_device_by_slot(slot); |
242 | |
243 | if(!mca_dev) |
244 | return; |
245 | |
246 | mca_dev->procfn = procfn; |
247 | mca_dev->proc_dev = proc_dev; |
248 | } |
249 | EXPORT_SYMBOL(mca_set_adapter_procfn); |