diff options
Diffstat (limited to 'drivers/message/i2o/i2o_proc.c')
-rw-r--r-- | drivers/message/i2o/i2o_proc.c | 2112 |
1 files changed, 2112 insertions, 0 deletions
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c new file mode 100644 index 000000000000..b176d0eeff7f --- /dev/null +++ b/drivers/message/i2o/i2o_proc.c | |||
@@ -0,0 +1,2112 @@ | |||
1 | /* | ||
2 | * procfs handler for Linux I2O subsystem | ||
3 | * | ||
4 | * (c) Copyright 1999 Deepak Saxena | ||
5 | * | ||
6 | * Originally written by Deepak Saxena(deepak@plexity.net) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This is an initial test release. The code is based on the design of the | ||
14 | * ide procfs system (drivers/block/ide-proc.c). Some code taken from | ||
15 | * i2o-core module by Alan Cox. | ||
16 | * | ||
17 | * DISCLAIMER: This code is still under development/test and may cause | ||
18 | * your system to behave unpredictably. Use at your own discretion. | ||
19 | * | ||
20 | * | ||
21 | * Fixes/additions: | ||
22 | * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI), | ||
23 | * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI) | ||
24 | * University of Helsinki, Department of Computer Science | ||
25 | * LAN entries | ||
26 | * Markus Lidel <Markus.Lidel@shadowconnect.com> | ||
27 | * Changes for new I2O API | ||
28 | */ | ||
29 | |||
30 | #define OSM_NAME "proc-osm" | ||
31 | #define OSM_VERSION "$Rev$" | ||
32 | #define OSM_DESCRIPTION "I2O ProcFS OSM" | ||
33 | |||
34 | #define I2O_MAX_MODULES 4 | ||
35 | // FIXME! | ||
36 | #define FMT_U64_HEX "0x%08x%08x" | ||
37 | #define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64)) | ||
38 | |||
39 | #include <linux/types.h> | ||
40 | #include <linux/kernel.h> | ||
41 | #include <linux/pci.h> | ||
42 | #include <linux/i2o.h> | ||
43 | #include <linux/proc_fs.h> | ||
44 | #include <linux/seq_file.h> | ||
45 | #include <linux/init.h> | ||
46 | #include <linux/module.h> | ||
47 | #include <linux/errno.h> | ||
48 | #include <linux/spinlock.h> | ||
49 | #include <linux/workqueue.h> | ||
50 | |||
51 | #include <asm/io.h> | ||
52 | #include <asm/uaccess.h> | ||
53 | #include <asm/byteorder.h> | ||
54 | |||
55 | /* Structure used to define /proc entries */ | ||
56 | typedef struct _i2o_proc_entry_t { | ||
57 | char *name; /* entry name */ | ||
58 | mode_t mode; /* mode */ | ||
59 | struct file_operations *fops; /* open function */ | ||
60 | } i2o_proc_entry; | ||
61 | |||
62 | /* global I2O /proc/i2o entry */ | ||
63 | static struct proc_dir_entry *i2o_proc_dir_root; | ||
64 | |||
65 | /* proc OSM driver struct */ | ||
66 | static struct i2o_driver i2o_proc_driver = { | ||
67 | .name = OSM_NAME, | ||
68 | }; | ||
69 | |||
70 | static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len) | ||
71 | { | ||
72 | int i; | ||
73 | |||
74 | /* 19990419 -sralston | ||
75 | * The I2O v1.5 (and v2.0 so far) "official specification" | ||
76 | * got serial numbers WRONG! | ||
77 | * Apparently, and despite what Section 3.4.4 says and | ||
78 | * Figure 3-35 shows (pg 3-39 in the pdf doc), | ||
79 | * the convention / consensus seems to be: | ||
80 | * + First byte is SNFormat | ||
81 | * + Second byte is SNLen (but only if SNFormat==7 (?)) | ||
82 | * + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format | ||
83 | */ | ||
84 | switch (serialno[0]) { | ||
85 | case I2O_SNFORMAT_BINARY: /* Binary */ | ||
86 | seq_printf(seq, "0x"); | ||
87 | for (i = 0; i < serialno[1]; i++) { | ||
88 | seq_printf(seq, "%02X", serialno[2 + i]); | ||
89 | } | ||
90 | break; | ||
91 | |||
92 | case I2O_SNFORMAT_ASCII: /* ASCII */ | ||
93 | if (serialno[1] < ' ') { /* printable or SNLen? */ | ||
94 | /* sanity */ | ||
95 | max_len = | ||
96 | (max_len < serialno[1]) ? max_len : serialno[1]; | ||
97 | serialno[1 + max_len] = '\0'; | ||
98 | |||
99 | /* just print it */ | ||
100 | seq_printf(seq, "%s", &serialno[2]); | ||
101 | } else { | ||
102 | /* print chars for specified length */ | ||
103 | for (i = 0; i < serialno[1]; i++) { | ||
104 | seq_printf(seq, "%c", serialno[2 + i]); | ||
105 | } | ||
106 | } | ||
107 | break; | ||
108 | |||
109 | case I2O_SNFORMAT_UNICODE: /* UNICODE */ | ||
110 | seq_printf(seq, "UNICODE Format. Can't Display\n"); | ||
111 | break; | ||
112 | |||
113 | case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */ | ||
114 | seq_printf(seq, | ||
115 | "LAN-48 MAC address @ %02X:%02X:%02X:%02X:%02X:%02X", | ||
116 | serialno[2], serialno[3], | ||
117 | serialno[4], serialno[5], serialno[6], serialno[7]); | ||
118 | break; | ||
119 | |||
120 | case I2O_SNFORMAT_WAN: /* WAN MAC Address */ | ||
121 | /* FIXME: Figure out what a WAN access address looks like?? */ | ||
122 | seq_printf(seq, "WAN Access Address"); | ||
123 | break; | ||
124 | |||
125 | /* plus new in v2.0 */ | ||
126 | case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */ | ||
127 | /* FIXME: Figure out what a LAN-64 address really looks like?? */ | ||
128 | seq_printf(seq, | ||
129 | "LAN-64 MAC address @ [?:%02X:%02X:?] %02X:%02X:%02X:%02X:%02X:%02X", | ||
130 | serialno[8], serialno[9], | ||
131 | serialno[2], serialno[3], | ||
132 | serialno[4], serialno[5], serialno[6], serialno[7]); | ||
133 | break; | ||
134 | |||
135 | case I2O_SNFORMAT_DDM: /* I2O DDM */ | ||
136 | seq_printf(seq, | ||
137 | "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh", | ||
138 | *(u16 *) & serialno[2], | ||
139 | *(u16 *) & serialno[4], *(u16 *) & serialno[6]); | ||
140 | break; | ||
141 | |||
142 | case I2O_SNFORMAT_IEEE_REG64: /* IEEE Registered (64-bit) */ | ||
143 | case I2O_SNFORMAT_IEEE_REG128: /* IEEE Registered (128-bit) */ | ||
144 | /* FIXME: Figure if this is even close?? */ | ||
145 | seq_printf(seq, | ||
146 | "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n", | ||
147 | *(u32 *) & serialno[2], | ||
148 | *(u32 *) & serialno[6], | ||
149 | *(u32 *) & serialno[10], *(u32 *) & serialno[14]); | ||
150 | break; | ||
151 | |||
152 | case I2O_SNFORMAT_UNKNOWN: /* Unknown 0 */ | ||
153 | case I2O_SNFORMAT_UNKNOWN2: /* Unknown 0xff */ | ||
154 | default: | ||
155 | seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]); | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * i2o_get_class_name - do i2o class name lookup | ||
164 | * @class: class number | ||
165 | * | ||
166 | * Return a descriptive string for an i2o class | ||
167 | */ | ||
168 | static const char *i2o_get_class_name(int class) | ||
169 | { | ||
170 | int idx = 16; | ||
171 | static char *i2o_class_name[] = { | ||
172 | "Executive", | ||
173 | "Device Driver Module", | ||
174 | "Block Device", | ||
175 | "Tape Device", | ||
176 | "LAN Interface", | ||
177 | "WAN Interface", | ||
178 | "Fibre Channel Port", | ||
179 | "Fibre Channel Device", | ||
180 | "SCSI Device", | ||
181 | "ATE Port", | ||
182 | "ATE Device", | ||
183 | "Floppy Controller", | ||
184 | "Floppy Device", | ||
185 | "Secondary Bus Port", | ||
186 | "Peer Transport Agent", | ||
187 | "Peer Transport", | ||
188 | "Unknown" | ||
189 | }; | ||
190 | |||
191 | switch (class & 0xfff) { | ||
192 | case I2O_CLASS_EXECUTIVE: | ||
193 | idx = 0; | ||
194 | break; | ||
195 | case I2O_CLASS_DDM: | ||
196 | idx = 1; | ||
197 | break; | ||
198 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
199 | idx = 2; | ||
200 | break; | ||
201 | case I2O_CLASS_SEQUENTIAL_STORAGE: | ||
202 | idx = 3; | ||
203 | break; | ||
204 | case I2O_CLASS_LAN: | ||
205 | idx = 4; | ||
206 | break; | ||
207 | case I2O_CLASS_WAN: | ||
208 | idx = 5; | ||
209 | break; | ||
210 | case I2O_CLASS_FIBRE_CHANNEL_PORT: | ||
211 | idx = 6; | ||
212 | break; | ||
213 | case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: | ||
214 | idx = 7; | ||
215 | break; | ||
216 | case I2O_CLASS_SCSI_PERIPHERAL: | ||
217 | idx = 8; | ||
218 | break; | ||
219 | case I2O_CLASS_ATE_PORT: | ||
220 | idx = 9; | ||
221 | break; | ||
222 | case I2O_CLASS_ATE_PERIPHERAL: | ||
223 | idx = 10; | ||
224 | break; | ||
225 | case I2O_CLASS_FLOPPY_CONTROLLER: | ||
226 | idx = 11; | ||
227 | break; | ||
228 | case I2O_CLASS_FLOPPY_DEVICE: | ||
229 | idx = 12; | ||
230 | break; | ||
231 | case I2O_CLASS_BUS_ADAPTER_PORT: | ||
232 | idx = 13; | ||
233 | break; | ||
234 | case I2O_CLASS_PEER_TRANSPORT_AGENT: | ||
235 | idx = 14; | ||
236 | break; | ||
237 | case I2O_CLASS_PEER_TRANSPORT: | ||
238 | idx = 15; | ||
239 | break; | ||
240 | } | ||
241 | |||
242 | return i2o_class_name[idx]; | ||
243 | } | ||
244 | |||
245 | #define SCSI_TABLE_SIZE 13 | ||
246 | static char *scsi_devices[] = { | ||
247 | "Direct-Access Read/Write", | ||
248 | "Sequential-Access Storage", | ||
249 | "Printer", | ||
250 | "Processor", | ||
251 | "WORM Device", | ||
252 | "CD-ROM Device", | ||
253 | "Scanner Device", | ||
254 | "Optical Memory Device", | ||
255 | "Medium Changer Device", | ||
256 | "Communications Device", | ||
257 | "Graphics Art Pre-Press Device", | ||
258 | "Graphics Art Pre-Press Device", | ||
259 | "Array Controller Device" | ||
260 | }; | ||
261 | |||
262 | static char *chtostr(u8 * chars, int n) | ||
263 | { | ||
264 | char tmp[256]; | ||
265 | tmp[0] = 0; | ||
266 | return strncat(tmp, (char *)chars, n); | ||
267 | } | ||
268 | |||
269 | static int i2o_report_query_status(struct seq_file *seq, int block_status, | ||
270 | char *group) | ||
271 | { | ||
272 | switch (block_status) { | ||
273 | case -ETIMEDOUT: | ||
274 | return seq_printf(seq, "Timeout reading group %s.\n", group); | ||
275 | case -ENOMEM: | ||
276 | return seq_printf(seq, "No free memory to read the table.\n"); | ||
277 | case -I2O_PARAMS_STATUS_INVALID_GROUP_ID: | ||
278 | return seq_printf(seq, "Group %s not supported.\n", group); | ||
279 | default: | ||
280 | return seq_printf(seq, | ||
281 | "Error reading group %s. BlockStatus 0x%02X\n", | ||
282 | group, -block_status); | ||
283 | } | ||
284 | } | ||
285 | |||
286 | static char *bus_strings[] = { | ||
287 | "Local Bus", | ||
288 | "ISA", | ||
289 | "EISA", | ||
290 | "MCA", | ||
291 | "PCI", | ||
292 | "PCMCIA", | ||
293 | "NUBUS", | ||
294 | "CARDBUS" | ||
295 | }; | ||
296 | |||
297 | static int i2o_seq_show_hrt(struct seq_file *seq, void *v) | ||
298 | { | ||
299 | struct i2o_controller *c = (struct i2o_controller *)seq->private; | ||
300 | i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt; | ||
301 | u32 bus; | ||
302 | int i; | ||
303 | |||
304 | if (hrt->hrt_version) { | ||
305 | seq_printf(seq, | ||
306 | "HRT table for controller is too new a version.\n"); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | seq_printf(seq, "HRT has %d entries of %d bytes each.\n", | ||
311 | hrt->num_entries, hrt->entry_len << 2); | ||
312 | |||
313 | for (i = 0; i < hrt->num_entries; i++) { | ||
314 | seq_printf(seq, "Entry %d:\n", i); | ||
315 | seq_printf(seq, " Adapter ID: %0#10x\n", | ||
316 | hrt->hrt_entry[i].adapter_id); | ||
317 | seq_printf(seq, " Controlling tid: %0#6x\n", | ||
318 | hrt->hrt_entry[i].parent_tid); | ||
319 | |||
320 | if (hrt->hrt_entry[i].bus_type != 0x80) { | ||
321 | bus = hrt->hrt_entry[i].bus_type; | ||
322 | seq_printf(seq, " %s Information\n", | ||
323 | bus_strings[bus]); | ||
324 | |||
325 | switch (bus) { | ||
326 | case I2O_BUS_LOCAL: | ||
327 | seq_printf(seq, " IOBase: %0#6x,", | ||
328 | hrt->hrt_entry[i].bus.local_bus. | ||
329 | LbBaseIOPort); | ||
330 | seq_printf(seq, " MemoryBase: %0#10x\n", | ||
331 | hrt->hrt_entry[i].bus.local_bus. | ||
332 | LbBaseMemoryAddress); | ||
333 | break; | ||
334 | |||
335 | case I2O_BUS_ISA: | ||
336 | seq_printf(seq, " IOBase: %0#6x,", | ||
337 | hrt->hrt_entry[i].bus.isa_bus. | ||
338 | IsaBaseIOPort); | ||
339 | seq_printf(seq, " MemoryBase: %0#10x,", | ||
340 | hrt->hrt_entry[i].bus.isa_bus. | ||
341 | IsaBaseMemoryAddress); | ||
342 | seq_printf(seq, " CSN: %0#4x,", | ||
343 | hrt->hrt_entry[i].bus.isa_bus.CSN); | ||
344 | break; | ||
345 | |||
346 | case I2O_BUS_EISA: | ||
347 | seq_printf(seq, " IOBase: %0#6x,", | ||
348 | hrt->hrt_entry[i].bus.eisa_bus. | ||
349 | EisaBaseIOPort); | ||
350 | seq_printf(seq, " MemoryBase: %0#10x,", | ||
351 | hrt->hrt_entry[i].bus.eisa_bus. | ||
352 | EisaBaseMemoryAddress); | ||
353 | seq_printf(seq, " Slot: %0#4x,", | ||
354 | hrt->hrt_entry[i].bus.eisa_bus. | ||
355 | EisaSlotNumber); | ||
356 | break; | ||
357 | |||
358 | case I2O_BUS_MCA: | ||
359 | seq_printf(seq, " IOBase: %0#6x,", | ||
360 | hrt->hrt_entry[i].bus.mca_bus. | ||
361 | McaBaseIOPort); | ||
362 | seq_printf(seq, " MemoryBase: %0#10x,", | ||
363 | hrt->hrt_entry[i].bus.mca_bus. | ||
364 | McaBaseMemoryAddress); | ||
365 | seq_printf(seq, " Slot: %0#4x,", | ||
366 | hrt->hrt_entry[i].bus.mca_bus. | ||
367 | McaSlotNumber); | ||
368 | break; | ||
369 | |||
370 | case I2O_BUS_PCI: | ||
371 | seq_printf(seq, " Bus: %0#4x", | ||
372 | hrt->hrt_entry[i].bus.pci_bus. | ||
373 | PciBusNumber); | ||
374 | seq_printf(seq, " Dev: %0#4x", | ||
375 | hrt->hrt_entry[i].bus.pci_bus. | ||
376 | PciDeviceNumber); | ||
377 | seq_printf(seq, " Func: %0#4x", | ||
378 | hrt->hrt_entry[i].bus.pci_bus. | ||
379 | PciFunctionNumber); | ||
380 | seq_printf(seq, " Vendor: %0#6x", | ||
381 | hrt->hrt_entry[i].bus.pci_bus. | ||
382 | PciVendorID); | ||
383 | seq_printf(seq, " Device: %0#6x\n", | ||
384 | hrt->hrt_entry[i].bus.pci_bus. | ||
385 | PciDeviceID); | ||
386 | break; | ||
387 | |||
388 | default: | ||
389 | seq_printf(seq, " Unsupported Bus Type\n"); | ||
390 | } | ||
391 | } else | ||
392 | seq_printf(seq, " Unknown Bus Type\n"); | ||
393 | } | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static int i2o_seq_show_lct(struct seq_file *seq, void *v) | ||
399 | { | ||
400 | struct i2o_controller *c = (struct i2o_controller *)seq->private; | ||
401 | i2o_lct *lct = (i2o_lct *) c->lct; | ||
402 | int entries; | ||
403 | int i; | ||
404 | |||
405 | #define BUS_TABLE_SIZE 3 | ||
406 | static char *bus_ports[] = { | ||
407 | "Generic Bus", | ||
408 | "SCSI Bus", | ||
409 | "Fibre Channel Bus" | ||
410 | }; | ||
411 | |||
412 | entries = (lct->table_size - 3) / 9; | ||
413 | |||
414 | seq_printf(seq, "LCT contains %d %s\n", entries, | ||
415 | entries == 1 ? "entry" : "entries"); | ||
416 | if (lct->boot_tid) | ||
417 | seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid); | ||
418 | |||
419 | seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind); | ||
420 | |||
421 | for (i = 0; i < entries; i++) { | ||
422 | seq_printf(seq, "Entry %d\n", i); | ||
423 | seq_printf(seq, " Class, SubClass : %s", | ||
424 | i2o_get_class_name(lct->lct_entry[i].class_id)); | ||
425 | |||
426 | /* | ||
427 | * Classes which we'll print subclass info for | ||
428 | */ | ||
429 | switch (lct->lct_entry[i].class_id & 0xFFF) { | ||
430 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
431 | switch (lct->lct_entry[i].sub_class) { | ||
432 | case 0x00: | ||
433 | seq_printf(seq, ", Direct-Access Read/Write"); | ||
434 | break; | ||
435 | |||
436 | case 0x04: | ||
437 | seq_printf(seq, ", WORM Drive"); | ||
438 | break; | ||
439 | |||
440 | case 0x05: | ||
441 | seq_printf(seq, ", CD-ROM Drive"); | ||
442 | break; | ||
443 | |||
444 | case 0x07: | ||
445 | seq_printf(seq, ", Optical Memory Device"); | ||
446 | break; | ||
447 | |||
448 | default: | ||
449 | seq_printf(seq, ", Unknown (0x%02x)", | ||
450 | lct->lct_entry[i].sub_class); | ||
451 | break; | ||
452 | } | ||
453 | break; | ||
454 | |||
455 | case I2O_CLASS_LAN: | ||
456 | switch (lct->lct_entry[i].sub_class & 0xFF) { | ||
457 | case 0x30: | ||
458 | seq_printf(seq, ", Ethernet"); | ||
459 | break; | ||
460 | |||
461 | case 0x40: | ||
462 | seq_printf(seq, ", 100base VG"); | ||
463 | break; | ||
464 | |||
465 | case 0x50: | ||
466 | seq_printf(seq, ", IEEE 802.5/Token-Ring"); | ||
467 | break; | ||
468 | |||
469 | case 0x60: | ||
470 | seq_printf(seq, ", ANSI X3T9.5 FDDI"); | ||
471 | break; | ||
472 | |||
473 | case 0x70: | ||
474 | seq_printf(seq, ", Fibre Channel"); | ||
475 | break; | ||
476 | |||
477 | default: | ||
478 | seq_printf(seq, ", Unknown Sub-Class (0x%02x)", | ||
479 | lct->lct_entry[i].sub_class & 0xFF); | ||
480 | break; | ||
481 | } | ||
482 | break; | ||
483 | |||
484 | case I2O_CLASS_SCSI_PERIPHERAL: | ||
485 | if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) | ||
486 | seq_printf(seq, ", %s", | ||
487 | scsi_devices[lct->lct_entry[i]. | ||
488 | sub_class]); | ||
489 | else | ||
490 | seq_printf(seq, ", Unknown Device Type"); | ||
491 | break; | ||
492 | |||
493 | case I2O_CLASS_BUS_ADAPTER_PORT: | ||
494 | if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) | ||
495 | seq_printf(seq, ", %s", | ||
496 | bus_ports[lct->lct_entry[i]. | ||
497 | sub_class]); | ||
498 | else | ||
499 | seq_printf(seq, ", Unknown Bus Type"); | ||
500 | break; | ||
501 | } | ||
502 | seq_printf(seq, "\n"); | ||
503 | |||
504 | seq_printf(seq, " Local TID : 0x%03x\n", | ||
505 | lct->lct_entry[i].tid); | ||
506 | seq_printf(seq, " User TID : 0x%03x\n", | ||
507 | lct->lct_entry[i].user_tid); | ||
508 | seq_printf(seq, " Parent TID : 0x%03x\n", | ||
509 | lct->lct_entry[i].parent_tid); | ||
510 | seq_printf(seq, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", | ||
511 | lct->lct_entry[i].identity_tag[0], | ||
512 | lct->lct_entry[i].identity_tag[1], | ||
513 | lct->lct_entry[i].identity_tag[2], | ||
514 | lct->lct_entry[i].identity_tag[3], | ||
515 | lct->lct_entry[i].identity_tag[4], | ||
516 | lct->lct_entry[i].identity_tag[5], | ||
517 | lct->lct_entry[i].identity_tag[6], | ||
518 | lct->lct_entry[i].identity_tag[7]); | ||
519 | seq_printf(seq, " Change Indicator : %0#10x\n", | ||
520 | lct->lct_entry[i].change_ind); | ||
521 | seq_printf(seq, " Event Capab Mask : %0#10x\n", | ||
522 | lct->lct_entry[i].device_flags); | ||
523 | } | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int i2o_seq_show_status(struct seq_file *seq, void *v) | ||
529 | { | ||
530 | struct i2o_controller *c = (struct i2o_controller *)seq->private; | ||
531 | char prodstr[25]; | ||
532 | int version; | ||
533 | i2o_status_block *sb = c->status_block.virt; | ||
534 | |||
535 | i2o_status_get(c); // reread the status block | ||
536 | |||
537 | seq_printf(seq, "Organization ID : %0#6x\n", sb->org_id); | ||
538 | |||
539 | version = sb->i2o_version; | ||
540 | |||
541 | /* FIXME for Spec 2.0 | ||
542 | if (version == 0x02) { | ||
543 | seq_printf(seq, "Lowest I2O version supported: "); | ||
544 | switch(workspace[2]) { | ||
545 | case 0x00: | ||
546 | seq_printf(seq, "1.0\n"); | ||
547 | break; | ||
548 | case 0x01: | ||
549 | seq_printf(seq, "1.5\n"); | ||
550 | break; | ||
551 | case 0x02: | ||
552 | seq_printf(seq, "2.0\n"); | ||
553 | break; | ||
554 | } | ||
555 | |||
556 | seq_printf(seq, "Highest I2O version supported: "); | ||
557 | switch(workspace[3]) { | ||
558 | case 0x00: | ||
559 | seq_printf(seq, "1.0\n"); | ||
560 | break; | ||
561 | case 0x01: | ||
562 | seq_printf(seq, "1.5\n"); | ||
563 | break; | ||
564 | case 0x02: | ||
565 | seq_printf(seq, "2.0\n"); | ||
566 | break; | ||
567 | } | ||
568 | } | ||
569 | */ | ||
570 | seq_printf(seq, "IOP ID : %0#5x\n", sb->iop_id); | ||
571 | seq_printf(seq, "Host Unit ID : %0#6x\n", sb->host_unit_id); | ||
572 | seq_printf(seq, "Segment Number : %0#5x\n", sb->segment_number); | ||
573 | |||
574 | seq_printf(seq, "I2O version : "); | ||
575 | switch (version) { | ||
576 | case 0x00: | ||
577 | seq_printf(seq, "1.0\n"); | ||
578 | break; | ||
579 | case 0x01: | ||
580 | seq_printf(seq, "1.5\n"); | ||
581 | break; | ||
582 | case 0x02: | ||
583 | seq_printf(seq, "2.0\n"); | ||
584 | break; | ||
585 | default: | ||
586 | seq_printf(seq, "Unknown version\n"); | ||
587 | } | ||
588 | |||
589 | seq_printf(seq, "IOP State : "); | ||
590 | switch (sb->iop_state) { | ||
591 | case 0x01: | ||
592 | seq_printf(seq, "INIT\n"); | ||
593 | break; | ||
594 | |||
595 | case 0x02: | ||
596 | seq_printf(seq, "RESET\n"); | ||
597 | break; | ||
598 | |||
599 | case 0x04: | ||
600 | seq_printf(seq, "HOLD\n"); | ||
601 | break; | ||
602 | |||
603 | case 0x05: | ||
604 | seq_printf(seq, "READY\n"); | ||
605 | break; | ||
606 | |||
607 | case 0x08: | ||
608 | seq_printf(seq, "OPERATIONAL\n"); | ||
609 | break; | ||
610 | |||
611 | case 0x10: | ||
612 | seq_printf(seq, "FAILED\n"); | ||
613 | break; | ||
614 | |||
615 | case 0x11: | ||
616 | seq_printf(seq, "FAULTED\n"); | ||
617 | break; | ||
618 | |||
619 | default: | ||
620 | seq_printf(seq, "Unknown\n"); | ||
621 | break; | ||
622 | } | ||
623 | |||
624 | seq_printf(seq, "Messenger Type : "); | ||
625 | switch (sb->msg_type) { | ||
626 | case 0x00: | ||
627 | seq_printf(seq, "Memory mapped\n"); | ||
628 | break; | ||
629 | case 0x01: | ||
630 | seq_printf(seq, "Memory mapped only\n"); | ||
631 | break; | ||
632 | case 0x02: | ||
633 | seq_printf(seq, "Remote only\n"); | ||
634 | break; | ||
635 | case 0x03: | ||
636 | seq_printf(seq, "Memory mapped and remote\n"); | ||
637 | break; | ||
638 | default: | ||
639 | seq_printf(seq, "Unknown\n"); | ||
640 | } | ||
641 | |||
642 | seq_printf(seq, "Inbound Frame Size : %d bytes\n", | ||
643 | sb->inbound_frame_size << 2); | ||
644 | seq_printf(seq, "Max Inbound Frames : %d\n", | ||
645 | sb->max_inbound_frames); | ||
646 | seq_printf(seq, "Current Inbound Frames : %d\n", | ||
647 | sb->cur_inbound_frames); | ||
648 | seq_printf(seq, "Max Outbound Frames : %d\n", | ||
649 | sb->max_outbound_frames); | ||
650 | |||
651 | /* Spec doesn't say if NULL terminated or not... */ | ||
652 | memcpy(prodstr, sb->product_id, 24); | ||
653 | prodstr[24] = '\0'; | ||
654 | seq_printf(seq, "Product ID : %s\n", prodstr); | ||
655 | seq_printf(seq, "Expected LCT Size : %d bytes\n", | ||
656 | sb->expected_lct_size); | ||
657 | |||
658 | seq_printf(seq, "IOP Capabilities\n"); | ||
659 | seq_printf(seq, " Context Field Size Support : "); | ||
660 | switch (sb->iop_capabilities & 0x0000003) { | ||
661 | case 0: | ||
662 | seq_printf(seq, "Supports only 32-bit context fields\n"); | ||
663 | break; | ||
664 | case 1: | ||
665 | seq_printf(seq, "Supports only 64-bit context fields\n"); | ||
666 | break; | ||
667 | case 2: | ||
668 | seq_printf(seq, "Supports 32-bit and 64-bit context fields, " | ||
669 | "but not concurrently\n"); | ||
670 | break; | ||
671 | case 3: | ||
672 | seq_printf(seq, "Supports 32-bit and 64-bit context fields " | ||
673 | "concurrently\n"); | ||
674 | break; | ||
675 | default: | ||
676 | seq_printf(seq, "0x%08x\n", sb->iop_capabilities); | ||
677 | } | ||
678 | seq_printf(seq, " Current Context Field Size : "); | ||
679 | switch (sb->iop_capabilities & 0x0000000C) { | ||
680 | case 0: | ||
681 | seq_printf(seq, "not configured\n"); | ||
682 | break; | ||
683 | case 4: | ||
684 | seq_printf(seq, "Supports only 32-bit context fields\n"); | ||
685 | break; | ||
686 | case 8: | ||
687 | seq_printf(seq, "Supports only 64-bit context fields\n"); | ||
688 | break; | ||
689 | case 12: | ||
690 | seq_printf(seq, "Supports both 32-bit or 64-bit context fields " | ||
691 | "concurrently\n"); | ||
692 | break; | ||
693 | default: | ||
694 | seq_printf(seq, "\n"); | ||
695 | } | ||
696 | seq_printf(seq, " Inbound Peer Support : %s\n", | ||
697 | (sb-> | ||
698 | iop_capabilities & 0x00000010) ? "Supported" : | ||
699 | "Not supported"); | ||
700 | seq_printf(seq, " Outbound Peer Support : %s\n", | ||
701 | (sb-> | ||
702 | iop_capabilities & 0x00000020) ? "Supported" : | ||
703 | "Not supported"); | ||
704 | seq_printf(seq, " Peer to Peer Support : %s\n", | ||
705 | (sb-> | ||
706 | iop_capabilities & 0x00000040) ? "Supported" : | ||
707 | "Not supported"); | ||
708 | |||
709 | seq_printf(seq, "Desired private memory size : %d kB\n", | ||
710 | sb->desired_mem_size >> 10); | ||
711 | seq_printf(seq, "Allocated private memory size : %d kB\n", | ||
712 | sb->current_mem_size >> 10); | ||
713 | seq_printf(seq, "Private memory base address : %0#10x\n", | ||
714 | sb->current_mem_base); | ||
715 | seq_printf(seq, "Desired private I/O size : %d kB\n", | ||
716 | sb->desired_io_size >> 10); | ||
717 | seq_printf(seq, "Allocated private I/O size : %d kB\n", | ||
718 | sb->current_io_size >> 10); | ||
719 | seq_printf(seq, "Private I/O base address : %0#10x\n", | ||
720 | sb->current_io_base); | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int i2o_seq_show_hw(struct seq_file *seq, void *v) | ||
726 | { | ||
727 | struct i2o_controller *c = (struct i2o_controller *)seq->private; | ||
728 | static u32 work32[5]; | ||
729 | static u8 *work8 = (u8 *) work32; | ||
730 | static u16 *work16 = (u16 *) work32; | ||
731 | int token; | ||
732 | u32 hwcap; | ||
733 | |||
734 | static char *cpu_table[] = { | ||
735 | "Intel 80960 series", | ||
736 | "AMD2900 series", | ||
737 | "Motorola 68000 series", | ||
738 | "ARM series", | ||
739 | "MIPS series", | ||
740 | "Sparc series", | ||
741 | "PowerPC series", | ||
742 | "Intel x86 series" | ||
743 | }; | ||
744 | |||
745 | token = | ||
746 | i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32)); | ||
747 | |||
748 | if (token < 0) { | ||
749 | i2o_report_query_status(seq, token, "0x0000 IOP Hardware"); | ||
750 | return 0; | ||
751 | } | ||
752 | |||
753 | seq_printf(seq, "I2O Vendor ID : %0#6x\n", work16[0]); | ||
754 | seq_printf(seq, "Product ID : %0#6x\n", work16[1]); | ||
755 | seq_printf(seq, "CPU : "); | ||
756 | if (work8[16] > 8) | ||
757 | seq_printf(seq, "Unknown\n"); | ||
758 | else | ||
759 | seq_printf(seq, "%s\n", cpu_table[work8[16]]); | ||
760 | /* Anyone using ProcessorVersion? */ | ||
761 | |||
762 | seq_printf(seq, "RAM : %dkB\n", work32[1] >> 10); | ||
763 | seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10); | ||
764 | |||
765 | hwcap = work32[3]; | ||
766 | seq_printf(seq, "Capabilities : 0x%08x\n", hwcap); | ||
767 | seq_printf(seq, " [%s] Self booting\n", | ||
768 | (hwcap & 0x00000001) ? "+" : "-"); | ||
769 | seq_printf(seq, " [%s] Upgradable IRTOS\n", | ||
770 | (hwcap & 0x00000002) ? "+" : "-"); | ||
771 | seq_printf(seq, " [%s] Supports downloading DDMs\n", | ||
772 | (hwcap & 0x00000004) ? "+" : "-"); | ||
773 | seq_printf(seq, " [%s] Supports installing DDMs\n", | ||
774 | (hwcap & 0x00000008) ? "+" : "-"); | ||
775 | seq_printf(seq, " [%s] Battery-backed RAM\n", | ||
776 | (hwcap & 0x00000010) ? "+" : "-"); | ||
777 | |||
778 | return 0; | ||
779 | } | ||
780 | |||
781 | /* Executive group 0003h - Executing DDM List (table) */ | ||
782 | static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v) | ||
783 | { | ||
784 | struct i2o_controller *c = (struct i2o_controller *)seq->private; | ||
785 | int token; | ||
786 | int i; | ||
787 | |||
788 | typedef struct _i2o_exec_execute_ddm_table { | ||
789 | u16 ddm_tid; | ||
790 | u8 module_type; | ||
791 | u8 reserved; | ||
792 | u16 i2o_vendor_id; | ||
793 | u16 module_id; | ||
794 | u8 module_name_version[28]; | ||
795 | u32 data_size; | ||
796 | u32 code_size; | ||
797 | } i2o_exec_execute_ddm_table; | ||
798 | |||
799 | struct { | ||
800 | u16 result_count; | ||
801 | u16 pad; | ||
802 | u16 block_size; | ||
803 | u8 block_status; | ||
804 | u8 error_info_size; | ||
805 | u16 row_count; | ||
806 | u16 more_flag; | ||
807 | i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES]; | ||
808 | } *result; | ||
809 | |||
810 | i2o_exec_execute_ddm_table ddm_table; | ||
811 | |||
812 | result = kmalloc(sizeof(*result), GFP_KERNEL); | ||
813 | if (!result) | ||
814 | return -ENOMEM; | ||
815 | |||
816 | token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1, | ||
817 | NULL, 0, result, sizeof(*result)); | ||
818 | |||
819 | if (token < 0) { | ||
820 | i2o_report_query_status(seq, token, | ||
821 | "0x0003 Executing DDM List"); | ||
822 | goto out; | ||
823 | } | ||
824 | |||
825 | seq_printf(seq, | ||
826 | "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); | ||
827 | ddm_table = result->ddm_table[0]; | ||
828 | |||
829 | for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) { | ||
830 | seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF); | ||
831 | |||
832 | switch (ddm_table.module_type) { | ||
833 | case 0x01: | ||
834 | seq_printf(seq, "Downloaded DDM "); | ||
835 | break; | ||
836 | case 0x22: | ||
837 | seq_printf(seq, "Embedded DDM "); | ||
838 | break; | ||
839 | default: | ||
840 | seq_printf(seq, " "); | ||
841 | } | ||
842 | |||
843 | seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id); | ||
844 | seq_printf(seq, "%-#8x", ddm_table.module_id); | ||
845 | seq_printf(seq, "%-29s", | ||
846 | chtostr(ddm_table.module_name_version, 28)); | ||
847 | seq_printf(seq, "%9d ", ddm_table.data_size); | ||
848 | seq_printf(seq, "%8d", ddm_table.code_size); | ||
849 | |||
850 | seq_printf(seq, "\n"); | ||
851 | } | ||
852 | out: | ||
853 | kfree(result); | ||
854 | return 0; | ||
855 | } | ||
856 | |||
857 | /* Executive group 0004h - Driver Store (scalar) */ | ||
858 | static int i2o_seq_show_driver_store(struct seq_file *seq, void *v) | ||
859 | { | ||
860 | struct i2o_controller *c = (struct i2o_controller *)seq->private; | ||
861 | u32 work32[8]; | ||
862 | int token; | ||
863 | |||
864 | token = | ||
865 | i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32)); | ||
866 | if (token < 0) { | ||
867 | i2o_report_query_status(seq, token, "0x0004 Driver Store"); | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | seq_printf(seq, "Module limit : %d\n" | ||
872 | "Module count : %d\n" | ||
873 | "Current space : %d kB\n" | ||
874 | "Free space : %d kB\n", | ||
875 | work32[0], work32[1], work32[2] >> 10, work32[3] >> 10); | ||
876 | |||
877 | return 0; | ||
878 | } | ||
879 | |||
880 | /* Executive group 0005h - Driver Store Table (table) */ | ||
881 | static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v) | ||
882 | { | ||
883 | typedef struct _i2o_driver_store { | ||
884 | u16 stored_ddm_index; | ||
885 | u8 module_type; | ||
886 | u8 reserved; | ||
887 | u16 i2o_vendor_id; | ||
888 | u16 module_id; | ||
889 | u8 module_name_version[28]; | ||
890 | u8 date[8]; | ||
891 | u32 module_size; | ||
892 | u32 mpb_size; | ||
893 | u32 module_flags; | ||
894 | } i2o_driver_store_table; | ||
895 | |||
896 | struct i2o_controller *c = (struct i2o_controller *)seq->private; | ||
897 | int token; | ||
898 | int i; | ||
899 | |||
900 | typedef struct { | ||
901 | u16 result_count; | ||
902 | u16 pad; | ||
903 | u16 block_size; | ||
904 | u8 block_status; | ||
905 | u8 error_info_size; | ||
906 | u16 row_count; | ||
907 | u16 more_flag; | ||
908 | i2o_driver_store_table dst[I2O_MAX_MODULES]; | ||
909 | } i2o_driver_result_table; | ||
910 | |||
911 | i2o_driver_result_table *result; | ||
912 | i2o_driver_store_table *dst; | ||
913 | |||
914 | result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL); | ||
915 | if (result == NULL) | ||
916 | return -ENOMEM; | ||
917 | |||
918 | token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1, | ||
919 | NULL, 0, result, sizeof(*result)); | ||
920 | |||
921 | if (token < 0) { | ||
922 | i2o_report_query_status(seq, token, | ||
923 | "0x0005 DRIVER STORE TABLE"); | ||
924 | kfree(result); | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | seq_printf(seq, | ||
929 | "# Module_type Vendor Mod_id Module_name Vrs" | ||
930 | "Date Mod_size Par_size Flags\n"); | ||
931 | for (i = 0, dst = &result->dst[0]; i < result->row_count; | ||
932 | dst = &result->dst[++i]) { | ||
933 | seq_printf(seq, "%-3d", dst->stored_ddm_index); | ||
934 | switch (dst->module_type) { | ||
935 | case 0x01: | ||
936 | seq_printf(seq, "Downloaded DDM "); | ||
937 | break; | ||
938 | case 0x22: | ||
939 | seq_printf(seq, "Embedded DDM "); | ||
940 | break; | ||
941 | default: | ||
942 | seq_printf(seq, " "); | ||
943 | } | ||
944 | |||
945 | seq_printf(seq, "%-#7x", dst->i2o_vendor_id); | ||
946 | seq_printf(seq, "%-#8x", dst->module_id); | ||
947 | seq_printf(seq, "%-29s", chtostr(dst->module_name_version, 28)); | ||
948 | seq_printf(seq, "%-9s", chtostr(dst->date, 8)); | ||
949 | seq_printf(seq, "%8d ", dst->module_size); | ||
950 | seq_printf(seq, "%8d ", dst->mpb_size); | ||
951 | seq_printf(seq, "0x%04x", dst->module_flags); | ||
952 | seq_printf(seq, "\n"); | ||
953 | } | ||
954 | |||
955 | kfree(result); | ||
956 | return 0; | ||
957 | } | ||
958 | |||
959 | /* Generic group F000h - Params Descriptor (table) */ | ||
960 | static int i2o_seq_show_groups(struct seq_file *seq, void *v) | ||
961 | { | ||
962 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
963 | int token; | ||
964 | int i; | ||
965 | u8 properties; | ||
966 | |||
967 | typedef struct _i2o_group_info { | ||
968 | u16 group_number; | ||
969 | u16 field_count; | ||
970 | u16 row_count; | ||
971 | u8 properties; | ||
972 | u8 reserved; | ||
973 | } i2o_group_info; | ||
974 | |||
975 | struct { | ||
976 | u16 result_count; | ||
977 | u16 pad; | ||
978 | u16 block_size; | ||
979 | u8 block_status; | ||
980 | u8 error_info_size; | ||
981 | u16 row_count; | ||
982 | u16 more_flag; | ||
983 | i2o_group_info group[256]; | ||
984 | } *result; | ||
985 | |||
986 | result = kmalloc(sizeof(*result), GFP_KERNEL); | ||
987 | if (!result) | ||
988 | return -ENOMEM; | ||
989 | |||
990 | token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, | ||
991 | result, sizeof(*result)); | ||
992 | |||
993 | if (token < 0) { | ||
994 | i2o_report_query_status(seq, token, "0xF000 Params Descriptor"); | ||
995 | goto out; | ||
996 | } | ||
997 | |||
998 | seq_printf(seq, | ||
999 | "# Group FieldCount RowCount Type Add Del Clear\n"); | ||
1000 | |||
1001 | for (i = 0; i < result->row_count; i++) { | ||
1002 | seq_printf(seq, "%-3d", i); | ||
1003 | seq_printf(seq, "0x%04X ", result->group[i].group_number); | ||
1004 | seq_printf(seq, "%10d ", result->group[i].field_count); | ||
1005 | seq_printf(seq, "%8d ", result->group[i].row_count); | ||
1006 | |||
1007 | properties = result->group[i].properties; | ||
1008 | if (properties & 0x1) | ||
1009 | seq_printf(seq, "Table "); | ||
1010 | else | ||
1011 | seq_printf(seq, "Scalar "); | ||
1012 | if (properties & 0x2) | ||
1013 | seq_printf(seq, " + "); | ||
1014 | else | ||
1015 | seq_printf(seq, " - "); | ||
1016 | if (properties & 0x4) | ||
1017 | seq_printf(seq, " + "); | ||
1018 | else | ||
1019 | seq_printf(seq, " - "); | ||
1020 | if (properties & 0x8) | ||
1021 | seq_printf(seq, " + "); | ||
1022 | else | ||
1023 | seq_printf(seq, " - "); | ||
1024 | |||
1025 | seq_printf(seq, "\n"); | ||
1026 | } | ||
1027 | |||
1028 | if (result->more_flag) | ||
1029 | seq_printf(seq, "There is more...\n"); | ||
1030 | out: | ||
1031 | kfree(result); | ||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | /* Generic group F001h - Physical Device Table (table) */ | ||
1036 | static int i2o_seq_show_phys_device(struct seq_file *seq, void *v) | ||
1037 | { | ||
1038 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1039 | int token; | ||
1040 | int i; | ||
1041 | |||
1042 | struct { | ||
1043 | u16 result_count; | ||
1044 | u16 pad; | ||
1045 | u16 block_size; | ||
1046 | u8 block_status; | ||
1047 | u8 error_info_size; | ||
1048 | u16 row_count; | ||
1049 | u16 more_flag; | ||
1050 | u32 adapter_id[64]; | ||
1051 | } result; | ||
1052 | |||
1053 | token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0, | ||
1054 | &result, sizeof(result)); | ||
1055 | |||
1056 | if (token < 0) { | ||
1057 | i2o_report_query_status(seq, token, | ||
1058 | "0xF001 Physical Device Table"); | ||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | if (result.row_count) | ||
1063 | seq_printf(seq, "# AdapterId\n"); | ||
1064 | |||
1065 | for (i = 0; i < result.row_count; i++) { | ||
1066 | seq_printf(seq, "%-2d", i); | ||
1067 | seq_printf(seq, "%#7x\n", result.adapter_id[i]); | ||
1068 | } | ||
1069 | |||
1070 | if (result.more_flag) | ||
1071 | seq_printf(seq, "There is more...\n"); | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | /* Generic group F002h - Claimed Table (table) */ | ||
1077 | static int i2o_seq_show_claimed(struct seq_file *seq, void *v) | ||
1078 | { | ||
1079 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1080 | int token; | ||
1081 | int i; | ||
1082 | |||
1083 | struct { | ||
1084 | u16 result_count; | ||
1085 | u16 pad; | ||
1086 | u16 block_size; | ||
1087 | u8 block_status; | ||
1088 | u8 error_info_size; | ||
1089 | u16 row_count; | ||
1090 | u16 more_flag; | ||
1091 | u16 claimed_tid[64]; | ||
1092 | } result; | ||
1093 | |||
1094 | token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0, | ||
1095 | &result, sizeof(result)); | ||
1096 | |||
1097 | if (token < 0) { | ||
1098 | i2o_report_query_status(seq, token, "0xF002 Claimed Table"); | ||
1099 | return 0; | ||
1100 | } | ||
1101 | |||
1102 | if (result.row_count) | ||
1103 | seq_printf(seq, "# ClaimedTid\n"); | ||
1104 | |||
1105 | for (i = 0; i < result.row_count; i++) { | ||
1106 | seq_printf(seq, "%-2d", i); | ||
1107 | seq_printf(seq, "%#7x\n", result.claimed_tid[i]); | ||
1108 | } | ||
1109 | |||
1110 | if (result.more_flag) | ||
1111 | seq_printf(seq, "There is more...\n"); | ||
1112 | |||
1113 | return 0; | ||
1114 | } | ||
1115 | |||
1116 | /* Generic group F003h - User Table (table) */ | ||
1117 | static int i2o_seq_show_users(struct seq_file *seq, void *v) | ||
1118 | { | ||
1119 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1120 | int token; | ||
1121 | int i; | ||
1122 | |||
1123 | typedef struct _i2o_user_table { | ||
1124 | u16 instance; | ||
1125 | u16 user_tid; | ||
1126 | u8 claim_type; | ||
1127 | u8 reserved1; | ||
1128 | u16 reserved2; | ||
1129 | } i2o_user_table; | ||
1130 | |||
1131 | struct { | ||
1132 | u16 result_count; | ||
1133 | u16 pad; | ||
1134 | u16 block_size; | ||
1135 | u8 block_status; | ||
1136 | u8 error_info_size; | ||
1137 | u16 row_count; | ||
1138 | u16 more_flag; | ||
1139 | i2o_user_table user[64]; | ||
1140 | } *result; | ||
1141 | |||
1142 | result = kmalloc(sizeof(*result), GFP_KERNEL); | ||
1143 | if (!result) | ||
1144 | return -ENOMEM; | ||
1145 | |||
1146 | token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0, | ||
1147 | result, sizeof(*result)); | ||
1148 | |||
1149 | if (token < 0) { | ||
1150 | i2o_report_query_status(seq, token, "0xF003 User Table"); | ||
1151 | goto out; | ||
1152 | } | ||
1153 | |||
1154 | seq_printf(seq, "# Instance UserTid ClaimType\n"); | ||
1155 | |||
1156 | for (i = 0; i < result->row_count; i++) { | ||
1157 | seq_printf(seq, "%-3d", i); | ||
1158 | seq_printf(seq, "%#8x ", result->user[i].instance); | ||
1159 | seq_printf(seq, "%#7x ", result->user[i].user_tid); | ||
1160 | seq_printf(seq, "%#9x\n", result->user[i].claim_type); | ||
1161 | } | ||
1162 | |||
1163 | if (result->more_flag) | ||
1164 | seq_printf(seq, "There is more...\n"); | ||
1165 | out: | ||
1166 | kfree(result); | ||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | /* Generic group F005h - Private message extensions (table) (optional) */ | ||
1171 | static int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v) | ||
1172 | { | ||
1173 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1174 | int token; | ||
1175 | int i; | ||
1176 | |||
1177 | typedef struct _i2o_private { | ||
1178 | u16 ext_instance; | ||
1179 | u16 organization_id; | ||
1180 | u16 x_function_code; | ||
1181 | } i2o_private; | ||
1182 | |||
1183 | struct { | ||
1184 | u16 result_count; | ||
1185 | u16 pad; | ||
1186 | u16 block_size; | ||
1187 | u8 block_status; | ||
1188 | u8 error_info_size; | ||
1189 | u16 row_count; | ||
1190 | u16 more_flag; | ||
1191 | i2o_private extension[64]; | ||
1192 | } result; | ||
1193 | |||
1194 | token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0, | ||
1195 | &result, sizeof(result)); | ||
1196 | |||
1197 | if (token < 0) { | ||
1198 | i2o_report_query_status(seq, token, | ||
1199 | "0xF005 Private Message Extensions (optional)"); | ||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | seq_printf(seq, "Instance# OrgId FunctionCode\n"); | ||
1204 | |||
1205 | for (i = 0; i < result.row_count; i++) { | ||
1206 | seq_printf(seq, "%0#9x ", result.extension[i].ext_instance); | ||
1207 | seq_printf(seq, "%0#6x ", result.extension[i].organization_id); | ||
1208 | seq_printf(seq, "%0#6x", result.extension[i].x_function_code); | ||
1209 | |||
1210 | seq_printf(seq, "\n"); | ||
1211 | } | ||
1212 | |||
1213 | if (result.more_flag) | ||
1214 | seq_printf(seq, "There is more...\n"); | ||
1215 | |||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | /* Generic group F006h - Authorized User Table (table) */ | ||
1220 | static int i2o_seq_show_authorized_users(struct seq_file *seq, void *v) | ||
1221 | { | ||
1222 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1223 | int token; | ||
1224 | int i; | ||
1225 | |||
1226 | struct { | ||
1227 | u16 result_count; | ||
1228 | u16 pad; | ||
1229 | u16 block_size; | ||
1230 | u8 block_status; | ||
1231 | u8 error_info_size; | ||
1232 | u16 row_count; | ||
1233 | u16 more_flag; | ||
1234 | u32 alternate_tid[64]; | ||
1235 | } result; | ||
1236 | |||
1237 | token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0, | ||
1238 | &result, sizeof(result)); | ||
1239 | |||
1240 | if (token < 0) { | ||
1241 | i2o_report_query_status(seq, token, | ||
1242 | "0xF006 Autohorized User Table"); | ||
1243 | return 0; | ||
1244 | } | ||
1245 | |||
1246 | if (result.row_count) | ||
1247 | seq_printf(seq, "# AlternateTid\n"); | ||
1248 | |||
1249 | for (i = 0; i < result.row_count; i++) { | ||
1250 | seq_printf(seq, "%-2d", i); | ||
1251 | seq_printf(seq, "%#7x ", result.alternate_tid[i]); | ||
1252 | } | ||
1253 | |||
1254 | if (result.more_flag) | ||
1255 | seq_printf(seq, "There is more...\n"); | ||
1256 | |||
1257 | return 0; | ||
1258 | } | ||
1259 | |||
1260 | /* Generic group F100h - Device Identity (scalar) */ | ||
1261 | static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v) | ||
1262 | { | ||
1263 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1264 | static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number | ||
1265 | // == (allow) 512d bytes (max) | ||
1266 | static u16 *work16 = (u16 *) work32; | ||
1267 | int token; | ||
1268 | |||
1269 | token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32)); | ||
1270 | |||
1271 | if (token < 0) { | ||
1272 | i2o_report_query_status(seq, token, "0xF100 Device Identity"); | ||
1273 | return 0; | ||
1274 | } | ||
1275 | |||
1276 | seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0])); | ||
1277 | seq_printf(seq, "Owner TID : %0#5x\n", work16[2]); | ||
1278 | seq_printf(seq, "Parent TID : %0#5x\n", work16[3]); | ||
1279 | seq_printf(seq, "Vendor info : %s\n", | ||
1280 | chtostr((u8 *) (work32 + 2), 16)); | ||
1281 | seq_printf(seq, "Product info : %s\n", | ||
1282 | chtostr((u8 *) (work32 + 6), 16)); | ||
1283 | seq_printf(seq, "Description : %s\n", | ||
1284 | chtostr((u8 *) (work32 + 10), 16)); | ||
1285 | seq_printf(seq, "Product rev. : %s\n", | ||
1286 | chtostr((u8 *) (work32 + 14), 8)); | ||
1287 | |||
1288 | seq_printf(seq, "Serial number : "); | ||
1289 | print_serial_number(seq, (u8 *) (work32 + 16), | ||
1290 | /* allow for SNLen plus | ||
1291 | * possible trailing '\0' | ||
1292 | */ | ||
1293 | sizeof(work32) - (16 * sizeof(u32)) - 2); | ||
1294 | seq_printf(seq, "\n"); | ||
1295 | |||
1296 | return 0; | ||
1297 | } | ||
1298 | |||
1299 | static int i2o_seq_show_dev_name(struct seq_file *seq, void *v) | ||
1300 | { | ||
1301 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1302 | |||
1303 | seq_printf(seq, "%s\n", d->device.bus_id); | ||
1304 | |||
1305 | return 0; | ||
1306 | } | ||
1307 | |||
1308 | /* Generic group F101h - DDM Identity (scalar) */ | ||
1309 | static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v) | ||
1310 | { | ||
1311 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1312 | int token; | ||
1313 | |||
1314 | struct { | ||
1315 | u16 ddm_tid; | ||
1316 | u8 module_name[24]; | ||
1317 | u8 module_rev[8]; | ||
1318 | u8 sn_format; | ||
1319 | u8 serial_number[12]; | ||
1320 | u8 pad[256]; // allow up to 256 byte (max) serial number | ||
1321 | } result; | ||
1322 | |||
1323 | token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result)); | ||
1324 | |||
1325 | if (token < 0) { | ||
1326 | i2o_report_query_status(seq, token, "0xF101 DDM Identity"); | ||
1327 | return 0; | ||
1328 | } | ||
1329 | |||
1330 | seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid); | ||
1331 | seq_printf(seq, "Module name : %s\n", | ||
1332 | chtostr(result.module_name, 24)); | ||
1333 | seq_printf(seq, "Module revision : %s\n", | ||
1334 | chtostr(result.module_rev, 8)); | ||
1335 | |||
1336 | seq_printf(seq, "Serial number : "); | ||
1337 | print_serial_number(seq, result.serial_number, sizeof(result) - 36); | ||
1338 | /* allow for SNLen plus possible trailing '\0' */ | ||
1339 | |||
1340 | seq_printf(seq, "\n"); | ||
1341 | |||
1342 | return 0; | ||
1343 | } | ||
1344 | |||
1345 | /* Generic group F102h - User Information (scalar) */ | ||
1346 | static int i2o_seq_show_uinfo(struct seq_file *seq, void *v) | ||
1347 | { | ||
1348 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1349 | int token; | ||
1350 | |||
1351 | struct { | ||
1352 | u8 device_name[64]; | ||
1353 | u8 service_name[64]; | ||
1354 | u8 physical_location[64]; | ||
1355 | u8 instance_number[4]; | ||
1356 | } result; | ||
1357 | |||
1358 | token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result)); | ||
1359 | |||
1360 | if (token < 0) { | ||
1361 | i2o_report_query_status(seq, token, "0xF102 User Information"); | ||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | seq_printf(seq, "Device name : %s\n", | ||
1366 | chtostr(result.device_name, 64)); | ||
1367 | seq_printf(seq, "Service name : %s\n", | ||
1368 | chtostr(result.service_name, 64)); | ||
1369 | seq_printf(seq, "Physical name : %s\n", | ||
1370 | chtostr(result.physical_location, 64)); | ||
1371 | seq_printf(seq, "Instance number : %s\n", | ||
1372 | chtostr(result.instance_number, 4)); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | /* Generic group F103h - SGL Operating Limits (scalar) */ | ||
1378 | static int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v) | ||
1379 | { | ||
1380 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1381 | static u32 work32[12]; | ||
1382 | static u16 *work16 = (u16 *) work32; | ||
1383 | static u8 *work8 = (u8 *) work32; | ||
1384 | int token; | ||
1385 | |||
1386 | token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32)); | ||
1387 | |||
1388 | if (token < 0) { | ||
1389 | i2o_report_query_status(seq, token, | ||
1390 | "0xF103 SGL Operating Limits"); | ||
1391 | return 0; | ||
1392 | } | ||
1393 | |||
1394 | seq_printf(seq, "SGL chain size : %d\n", work32[0]); | ||
1395 | seq_printf(seq, "Max SGL chain size : %d\n", work32[1]); | ||
1396 | seq_printf(seq, "SGL chain size target : %d\n", work32[2]); | ||
1397 | seq_printf(seq, "SGL frag count : %d\n", work16[6]); | ||
1398 | seq_printf(seq, "Max SGL frag count : %d\n", work16[7]); | ||
1399 | seq_printf(seq, "SGL frag count target : %d\n", work16[8]); | ||
1400 | |||
1401 | /* FIXME | ||
1402 | if (d->i2oversion == 0x02) | ||
1403 | { | ||
1404 | */ | ||
1405 | seq_printf(seq, "SGL data alignment : %d\n", work16[8]); | ||
1406 | seq_printf(seq, "SGL addr limit : %d\n", work8[20]); | ||
1407 | seq_printf(seq, "SGL addr sizes supported : "); | ||
1408 | if (work8[21] & 0x01) | ||
1409 | seq_printf(seq, "32 bit "); | ||
1410 | if (work8[21] & 0x02) | ||
1411 | seq_printf(seq, "64 bit "); | ||
1412 | if (work8[21] & 0x04) | ||
1413 | seq_printf(seq, "96 bit "); | ||
1414 | if (work8[21] & 0x08) | ||
1415 | seq_printf(seq, "128 bit "); | ||
1416 | seq_printf(seq, "\n"); | ||
1417 | /* | ||
1418 | } | ||
1419 | */ | ||
1420 | |||
1421 | return 0; | ||
1422 | } | ||
1423 | |||
1424 | /* Generic group F200h - Sensors (scalar) */ | ||
1425 | static int i2o_seq_show_sensors(struct seq_file *seq, void *v) | ||
1426 | { | ||
1427 | struct i2o_device *d = (struct i2o_device *)seq->private; | ||
1428 | int token; | ||
1429 | |||
1430 | struct { | ||
1431 | u16 sensor_instance; | ||
1432 | u8 component; | ||
1433 | u16 component_instance; | ||
1434 | u8 sensor_class; | ||
1435 | u8 sensor_type; | ||
1436 | u8 scaling_exponent; | ||
1437 | u32 actual_reading; | ||
1438 | u32 minimum_reading; | ||
1439 | u32 low2lowcat_treshold; | ||
1440 | u32 lowcat2low_treshold; | ||
1441 | u32 lowwarn2low_treshold; | ||
1442 | u32 low2lowwarn_treshold; | ||
1443 | u32 norm2lowwarn_treshold; | ||
1444 | u32 lowwarn2norm_treshold; | ||
1445 | u32 nominal_reading; | ||
1446 | u32 hiwarn2norm_treshold; | ||
1447 | u32 norm2hiwarn_treshold; | ||
1448 | u32 high2hiwarn_treshold; | ||
1449 | u32 hiwarn2high_treshold; | ||
1450 | u32 hicat2high_treshold; | ||
1451 | u32 hi2hicat_treshold; | ||
1452 | u32 maximum_reading; | ||
1453 | u8 sensor_state; | ||
1454 | u16 event_enable; | ||
1455 | } result; | ||
1456 | |||
1457 | token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result)); | ||
1458 | |||
1459 | if (token < 0) { | ||
1460 | i2o_report_query_status(seq, token, | ||
1461 | "0xF200 Sensors (optional)"); | ||
1462 | return 0; | ||
1463 | } | ||
1464 | |||
1465 | seq_printf(seq, "Sensor instance : %d\n", result.sensor_instance); | ||
1466 | |||
1467 | seq_printf(seq, "Component : %d = ", result.component); | ||
1468 | switch (result.component) { | ||
1469 | case 0: | ||
1470 | seq_printf(seq, "Other"); | ||
1471 | break; | ||
1472 | case 1: | ||
1473 | seq_printf(seq, "Planar logic Board"); | ||
1474 | break; | ||
1475 | case 2: | ||
1476 | seq_printf(seq, "CPU"); | ||
1477 | break; | ||
1478 | case 3: | ||
1479 | seq_printf(seq, "Chassis"); | ||
1480 | break; | ||
1481 | case 4: | ||
1482 | seq_printf(seq, "Power Supply"); | ||
1483 | break; | ||
1484 | case 5: | ||
1485 | seq_printf(seq, "Storage"); | ||
1486 | break; | ||
1487 | case 6: | ||
1488 | seq_printf(seq, "External"); | ||
1489 | break; | ||
1490 | } | ||
1491 | seq_printf(seq, "\n"); | ||
1492 | |||
1493 | seq_printf(seq, "Component instance : %d\n", | ||
1494 | result.component_instance); | ||
1495 | seq_printf(seq, "Sensor class : %s\n", | ||
1496 | result.sensor_class ? "Analog" : "Digital"); | ||
1497 | |||
1498 | seq_printf(seq, "Sensor type : %d = ", result.sensor_type); | ||
1499 | switch (result.sensor_type) { | ||
1500 | case 0: | ||
1501 | seq_printf(seq, "Other\n"); | ||
1502 | break; | ||
1503 | case 1: | ||
1504 | seq_printf(seq, "Thermal\n"); | ||
1505 | break; | ||
1506 | case 2: | ||
1507 | seq_printf(seq, "DC voltage (DC volts)\n"); | ||
1508 | break; | ||
1509 | case 3: | ||
1510 | seq_printf(seq, "AC voltage (AC volts)\n"); | ||
1511 | break; | ||
1512 | case 4: | ||
1513 | seq_printf(seq, "DC current (DC amps)\n"); | ||
1514 | break; | ||
1515 | case 5: | ||
1516 | seq_printf(seq, "AC current (AC volts)\n"); | ||
1517 | break; | ||
1518 | case 6: | ||
1519 | seq_printf(seq, "Door open\n"); | ||
1520 | break; | ||
1521 | case 7: | ||
1522 | seq_printf(seq, "Fan operational\n"); | ||
1523 | break; | ||
1524 | } | ||
1525 | |||
1526 | seq_printf(seq, "Scaling exponent : %d\n", | ||
1527 | result.scaling_exponent); | ||
1528 | seq_printf(seq, "Actual reading : %d\n", result.actual_reading); | ||
1529 | seq_printf(seq, "Minimum reading : %d\n", result.minimum_reading); | ||
1530 | seq_printf(seq, "Low2LowCat treshold : %d\n", | ||
1531 | result.low2lowcat_treshold); | ||
1532 | seq_printf(seq, "LowCat2Low treshold : %d\n", | ||
1533 | result.lowcat2low_treshold); | ||
1534 | seq_printf(seq, "LowWarn2Low treshold : %d\n", | ||
1535 | result.lowwarn2low_treshold); | ||
1536 | seq_printf(seq, "Low2LowWarn treshold : %d\n", | ||
1537 | result.low2lowwarn_treshold); | ||
1538 | seq_printf(seq, "Norm2LowWarn treshold : %d\n", | ||
1539 | result.norm2lowwarn_treshold); | ||
1540 | seq_printf(seq, "LowWarn2Norm treshold : %d\n", | ||
1541 | result.lowwarn2norm_treshold); | ||
1542 | seq_printf(seq, "Nominal reading : %d\n", result.nominal_reading); | ||
1543 | seq_printf(seq, "HiWarn2Norm treshold : %d\n", | ||
1544 | result.hiwarn2norm_treshold); | ||
1545 | seq_printf(seq, "Norm2HiWarn treshold : %d\n", | ||
1546 | result.norm2hiwarn_treshold); | ||
1547 | seq_printf(seq, "High2HiWarn treshold : %d\n", | ||
1548 | result.high2hiwarn_treshold); | ||
1549 | seq_printf(seq, "HiWarn2High treshold : %d\n", | ||
1550 | result.hiwarn2high_treshold); | ||
1551 | seq_printf(seq, "HiCat2High treshold : %d\n", | ||
1552 | result.hicat2high_treshold); | ||
1553 | seq_printf(seq, "High2HiCat treshold : %d\n", | ||
1554 | result.hi2hicat_treshold); | ||
1555 | seq_printf(seq, "Maximum reading : %d\n", result.maximum_reading); | ||
1556 | |||
1557 | seq_printf(seq, "Sensor state : %d = ", result.sensor_state); | ||
1558 | switch (result.sensor_state) { | ||
1559 | case 0: | ||
1560 | seq_printf(seq, "Normal\n"); | ||
1561 | break; | ||
1562 | case 1: | ||
1563 | seq_printf(seq, "Abnormal\n"); | ||
1564 | break; | ||
1565 | case 2: | ||
1566 | seq_printf(seq, "Unknown\n"); | ||
1567 | break; | ||
1568 | case 3: | ||
1569 | seq_printf(seq, "Low Catastrophic (LoCat)\n"); | ||
1570 | break; | ||
1571 | case 4: | ||
1572 | seq_printf(seq, "Low (Low)\n"); | ||
1573 | break; | ||
1574 | case 5: | ||
1575 | seq_printf(seq, "Low Warning (LoWarn)\n"); | ||
1576 | break; | ||
1577 | case 6: | ||
1578 | seq_printf(seq, "High Warning (HiWarn)\n"); | ||
1579 | break; | ||
1580 | case 7: | ||
1581 | seq_printf(seq, "High (High)\n"); | ||
1582 | break; | ||
1583 | case 8: | ||
1584 | seq_printf(seq, "High Catastrophic (HiCat)\n"); | ||
1585 | break; | ||
1586 | } | ||
1587 | |||
1588 | seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable); | ||
1589 | seq_printf(seq, " [%s] Operational state change. \n", | ||
1590 | (result.event_enable & 0x01) ? "+" : "-"); | ||
1591 | seq_printf(seq, " [%s] Low catastrophic. \n", | ||
1592 | (result.event_enable & 0x02) ? "+" : "-"); | ||
1593 | seq_printf(seq, " [%s] Low reading. \n", | ||
1594 | (result.event_enable & 0x04) ? "+" : "-"); | ||
1595 | seq_printf(seq, " [%s] Low warning. \n", | ||
1596 | (result.event_enable & 0x08) ? "+" : "-"); | ||
1597 | seq_printf(seq, | ||
1598 | " [%s] Change back to normal from out of range state. \n", | ||
1599 | (result.event_enable & 0x10) ? "+" : "-"); | ||
1600 | seq_printf(seq, " [%s] High warning. \n", | ||
1601 | (result.event_enable & 0x20) ? "+" : "-"); | ||
1602 | seq_printf(seq, " [%s] High reading. \n", | ||
1603 | (result.event_enable & 0x40) ? "+" : "-"); | ||
1604 | seq_printf(seq, " [%s] High catastrophic. \n", | ||
1605 | (result.event_enable & 0x80) ? "+" : "-"); | ||
1606 | |||
1607 | return 0; | ||
1608 | } | ||
1609 | |||
1610 | static int i2o_seq_open_hrt(struct inode *inode, struct file *file) | ||
1611 | { | ||
1612 | return single_open(file, i2o_seq_show_hrt, PDE(inode)->data); | ||
1613 | }; | ||
1614 | |||
1615 | static int i2o_seq_open_lct(struct inode *inode, struct file *file) | ||
1616 | { | ||
1617 | return single_open(file, i2o_seq_show_lct, PDE(inode)->data); | ||
1618 | }; | ||
1619 | |||
1620 | static int i2o_seq_open_status(struct inode *inode, struct file *file) | ||
1621 | { | ||
1622 | return single_open(file, i2o_seq_show_status, PDE(inode)->data); | ||
1623 | }; | ||
1624 | |||
1625 | static int i2o_seq_open_hw(struct inode *inode, struct file *file) | ||
1626 | { | ||
1627 | return single_open(file, i2o_seq_show_hw, PDE(inode)->data); | ||
1628 | }; | ||
1629 | |||
1630 | static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file) | ||
1631 | { | ||
1632 | return single_open(file, i2o_seq_show_ddm_table, PDE(inode)->data); | ||
1633 | }; | ||
1634 | |||
1635 | static int i2o_seq_open_driver_store(struct inode *inode, struct file *file) | ||
1636 | { | ||
1637 | return single_open(file, i2o_seq_show_driver_store, PDE(inode)->data); | ||
1638 | }; | ||
1639 | |||
1640 | static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file) | ||
1641 | { | ||
1642 | return single_open(file, i2o_seq_show_drivers_stored, PDE(inode)->data); | ||
1643 | }; | ||
1644 | |||
1645 | static int i2o_seq_open_groups(struct inode *inode, struct file *file) | ||
1646 | { | ||
1647 | return single_open(file, i2o_seq_show_groups, PDE(inode)->data); | ||
1648 | }; | ||
1649 | |||
1650 | static int i2o_seq_open_phys_device(struct inode *inode, struct file *file) | ||
1651 | { | ||
1652 | return single_open(file, i2o_seq_show_phys_device, PDE(inode)->data); | ||
1653 | }; | ||
1654 | |||
1655 | static int i2o_seq_open_claimed(struct inode *inode, struct file *file) | ||
1656 | { | ||
1657 | return single_open(file, i2o_seq_show_claimed, PDE(inode)->data); | ||
1658 | }; | ||
1659 | |||
1660 | static int i2o_seq_open_users(struct inode *inode, struct file *file) | ||
1661 | { | ||
1662 | return single_open(file, i2o_seq_show_users, PDE(inode)->data); | ||
1663 | }; | ||
1664 | |||
1665 | static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file) | ||
1666 | { | ||
1667 | return single_open(file, i2o_seq_show_priv_msgs, PDE(inode)->data); | ||
1668 | }; | ||
1669 | |||
1670 | static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file) | ||
1671 | { | ||
1672 | return single_open(file, i2o_seq_show_authorized_users, | ||
1673 | PDE(inode)->data); | ||
1674 | }; | ||
1675 | |||
1676 | static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file) | ||
1677 | { | ||
1678 | return single_open(file, i2o_seq_show_dev_identity, PDE(inode)->data); | ||
1679 | }; | ||
1680 | |||
1681 | static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file) | ||
1682 | { | ||
1683 | return single_open(file, i2o_seq_show_ddm_identity, PDE(inode)->data); | ||
1684 | }; | ||
1685 | |||
1686 | static int i2o_seq_open_uinfo(struct inode *inode, struct file *file) | ||
1687 | { | ||
1688 | return single_open(file, i2o_seq_show_uinfo, PDE(inode)->data); | ||
1689 | }; | ||
1690 | |||
1691 | static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file) | ||
1692 | { | ||
1693 | return single_open(file, i2o_seq_show_sgl_limits, PDE(inode)->data); | ||
1694 | }; | ||
1695 | |||
1696 | static int i2o_seq_open_sensors(struct inode *inode, struct file *file) | ||
1697 | { | ||
1698 | return single_open(file, i2o_seq_show_sensors, PDE(inode)->data); | ||
1699 | }; | ||
1700 | |||
1701 | static int i2o_seq_open_dev_name(struct inode *inode, struct file *file) | ||
1702 | { | ||
1703 | return single_open(file, i2o_seq_show_dev_name, PDE(inode)->data); | ||
1704 | }; | ||
1705 | |||
1706 | static struct file_operations i2o_seq_fops_lct = { | ||
1707 | .open = i2o_seq_open_lct, | ||
1708 | .read = seq_read, | ||
1709 | .llseek = seq_lseek, | ||
1710 | .release = single_release, | ||
1711 | }; | ||
1712 | |||
1713 | static struct file_operations i2o_seq_fops_hrt = { | ||
1714 | .open = i2o_seq_open_hrt, | ||
1715 | .read = seq_read, | ||
1716 | .llseek = seq_lseek, | ||
1717 | .release = single_release, | ||
1718 | }; | ||
1719 | |||
1720 | static struct file_operations i2o_seq_fops_status = { | ||
1721 | .open = i2o_seq_open_status, | ||
1722 | .read = seq_read, | ||
1723 | .llseek = seq_lseek, | ||
1724 | .release = single_release, | ||
1725 | }; | ||
1726 | |||
1727 | static struct file_operations i2o_seq_fops_hw = { | ||
1728 | .open = i2o_seq_open_hw, | ||
1729 | .read = seq_read, | ||
1730 | .llseek = seq_lseek, | ||
1731 | .release = single_release, | ||
1732 | }; | ||
1733 | |||
1734 | static struct file_operations i2o_seq_fops_ddm_table = { | ||
1735 | .open = i2o_seq_open_ddm_table, | ||
1736 | .read = seq_read, | ||
1737 | .llseek = seq_lseek, | ||
1738 | .release = single_release, | ||
1739 | }; | ||
1740 | |||
1741 | static struct file_operations i2o_seq_fops_driver_store = { | ||
1742 | .open = i2o_seq_open_driver_store, | ||
1743 | .read = seq_read, | ||
1744 | .llseek = seq_lseek, | ||
1745 | .release = single_release, | ||
1746 | }; | ||
1747 | |||
1748 | static struct file_operations i2o_seq_fops_drivers_stored = { | ||
1749 | .open = i2o_seq_open_drivers_stored, | ||
1750 | .read = seq_read, | ||
1751 | .llseek = seq_lseek, | ||
1752 | .release = single_release, | ||
1753 | }; | ||
1754 | |||
1755 | static struct file_operations i2o_seq_fops_groups = { | ||
1756 | .open = i2o_seq_open_groups, | ||
1757 | .read = seq_read, | ||
1758 | .llseek = seq_lseek, | ||
1759 | .release = single_release, | ||
1760 | }; | ||
1761 | |||
1762 | static struct file_operations i2o_seq_fops_phys_device = { | ||
1763 | .open = i2o_seq_open_phys_device, | ||
1764 | .read = seq_read, | ||
1765 | .llseek = seq_lseek, | ||
1766 | .release = single_release, | ||
1767 | }; | ||
1768 | |||
1769 | static struct file_operations i2o_seq_fops_claimed = { | ||
1770 | .open = i2o_seq_open_claimed, | ||
1771 | .read = seq_read, | ||
1772 | .llseek = seq_lseek, | ||
1773 | .release = single_release, | ||
1774 | }; | ||
1775 | |||
1776 | static struct file_operations i2o_seq_fops_users = { | ||
1777 | .open = i2o_seq_open_users, | ||
1778 | .read = seq_read, | ||
1779 | .llseek = seq_lseek, | ||
1780 | .release = single_release, | ||
1781 | }; | ||
1782 | |||
1783 | static struct file_operations i2o_seq_fops_priv_msgs = { | ||
1784 | .open = i2o_seq_open_priv_msgs, | ||
1785 | .read = seq_read, | ||
1786 | .llseek = seq_lseek, | ||
1787 | .release = single_release, | ||
1788 | }; | ||
1789 | |||
1790 | static struct file_operations i2o_seq_fops_authorized_users = { | ||
1791 | .open = i2o_seq_open_authorized_users, | ||
1792 | .read = seq_read, | ||
1793 | .llseek = seq_lseek, | ||
1794 | .release = single_release, | ||
1795 | }; | ||
1796 | |||
1797 | static struct file_operations i2o_seq_fops_dev_name = { | ||
1798 | .open = i2o_seq_open_dev_name, | ||
1799 | .read = seq_read, | ||
1800 | .llseek = seq_lseek, | ||
1801 | .release = single_release, | ||
1802 | }; | ||
1803 | |||
1804 | static struct file_operations i2o_seq_fops_dev_identity = { | ||
1805 | .open = i2o_seq_open_dev_identity, | ||
1806 | .read = seq_read, | ||
1807 | .llseek = seq_lseek, | ||
1808 | .release = single_release, | ||
1809 | }; | ||
1810 | |||
1811 | static struct file_operations i2o_seq_fops_ddm_identity = { | ||
1812 | .open = i2o_seq_open_ddm_identity, | ||
1813 | .read = seq_read, | ||
1814 | .llseek = seq_lseek, | ||
1815 | .release = single_release, | ||
1816 | }; | ||
1817 | |||
1818 | static struct file_operations i2o_seq_fops_uinfo = { | ||
1819 | .open = i2o_seq_open_uinfo, | ||
1820 | .read = seq_read, | ||
1821 | .llseek = seq_lseek, | ||
1822 | .release = single_release, | ||
1823 | }; | ||
1824 | |||
1825 | static struct file_operations i2o_seq_fops_sgl_limits = { | ||
1826 | .open = i2o_seq_open_sgl_limits, | ||
1827 | .read = seq_read, | ||
1828 | .llseek = seq_lseek, | ||
1829 | .release = single_release, | ||
1830 | }; | ||
1831 | |||
1832 | static struct file_operations i2o_seq_fops_sensors = { | ||
1833 | .open = i2o_seq_open_sensors, | ||
1834 | .read = seq_read, | ||
1835 | .llseek = seq_lseek, | ||
1836 | .release = single_release, | ||
1837 | }; | ||
1838 | |||
1839 | /* | ||
1840 | * IOP specific entries...write field just in case someone | ||
1841 | * ever wants one. | ||
1842 | */ | ||
1843 | static i2o_proc_entry i2o_proc_generic_iop_entries[] = { | ||
1844 | {"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt}, | ||
1845 | {"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct}, | ||
1846 | {"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status}, | ||
1847 | {"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw}, | ||
1848 | {"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table}, | ||
1849 | {"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store}, | ||
1850 | {"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored}, | ||
1851 | {NULL, 0, NULL} | ||
1852 | }; | ||
1853 | |||
1854 | /* | ||
1855 | * Device specific entries | ||
1856 | */ | ||
1857 | static i2o_proc_entry generic_dev_entries[] = { | ||
1858 | {"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups}, | ||
1859 | {"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device}, | ||
1860 | {"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed}, | ||
1861 | {"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users}, | ||
1862 | {"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs}, | ||
1863 | {"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users}, | ||
1864 | {"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity}, | ||
1865 | {"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity}, | ||
1866 | {"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo}, | ||
1867 | {"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits}, | ||
1868 | {"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors}, | ||
1869 | {NULL, 0, NULL} | ||
1870 | }; | ||
1871 | |||
1872 | /* | ||
1873 | * Storage unit specific entries (SCSI Periph, BS) with device names | ||
1874 | */ | ||
1875 | static i2o_proc_entry rbs_dev_entries[] = { | ||
1876 | {"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name}, | ||
1877 | {NULL, 0, NULL} | ||
1878 | }; | ||
1879 | |||
1880 | /** | ||
1881 | * i2o_proc_create_entries - Creates proc dir entries | ||
1882 | * @dir: proc dir entry under which the entries should be placed | ||
1883 | * @i2o_pe: pointer to the entries which should be added | ||
1884 | * @data: pointer to I2O controller or device | ||
1885 | * | ||
1886 | * Create proc dir entries for a I2O controller or I2O device. | ||
1887 | * | ||
1888 | * Returns 0 on success or negative error code on failure. | ||
1889 | */ | ||
1890 | static int i2o_proc_create_entries(struct proc_dir_entry *dir, | ||
1891 | i2o_proc_entry * i2o_pe, void *data) | ||
1892 | { | ||
1893 | struct proc_dir_entry *tmp; | ||
1894 | |||
1895 | while (i2o_pe->name) { | ||
1896 | tmp = create_proc_entry(i2o_pe->name, i2o_pe->mode, dir); | ||
1897 | if (!tmp) | ||
1898 | return -1; | ||
1899 | |||
1900 | tmp->data = data; | ||
1901 | tmp->proc_fops = i2o_pe->fops; | ||
1902 | |||
1903 | i2o_pe++; | ||
1904 | } | ||
1905 | |||
1906 | return 0; | ||
1907 | } | ||
1908 | |||
1909 | /** | ||
1910 | * i2o_proc_subdir_remove - Remove child entries from a proc entry | ||
1911 | * @dir: proc dir entry from which the childs should be removed | ||
1912 | * | ||
1913 | * Iterate over each i2o proc entry under dir and remove it. If the child | ||
1914 | * also has entries, remove them too. | ||
1915 | */ | ||
1916 | static void i2o_proc_subdir_remove(struct proc_dir_entry *dir) | ||
1917 | { | ||
1918 | struct proc_dir_entry *pe, *tmp; | ||
1919 | pe = dir->subdir; | ||
1920 | while (pe) { | ||
1921 | tmp = pe->next; | ||
1922 | i2o_proc_subdir_remove(pe); | ||
1923 | remove_proc_entry(pe->name, dir); | ||
1924 | pe = tmp; | ||
1925 | } | ||
1926 | }; | ||
1927 | |||
1928 | /** | ||
1929 | * i2o_proc_device_add - Add an I2O device to the proc dir | ||
1930 | * @dir: proc dir entry to which the device should be added | ||
1931 | * @dev: I2O device which should be added | ||
1932 | * | ||
1933 | * Add an I2O device to the proc dir entry dir and create the entries for | ||
1934 | * the device depending on the class of the I2O device. | ||
1935 | */ | ||
1936 | static void i2o_proc_device_add(struct proc_dir_entry *dir, | ||
1937 | struct i2o_device *dev) | ||
1938 | { | ||
1939 | char buff[10]; | ||
1940 | struct proc_dir_entry *devdir; | ||
1941 | i2o_proc_entry *i2o_pe = NULL; | ||
1942 | |||
1943 | sprintf(buff, "%03x", dev->lct_data.tid); | ||
1944 | |||
1945 | osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff); | ||
1946 | |||
1947 | devdir = proc_mkdir(buff, dir); | ||
1948 | if (!devdir) { | ||
1949 | osm_warn("Could not allocate procdir!\n"); | ||
1950 | return; | ||
1951 | } | ||
1952 | |||
1953 | devdir->data = dev; | ||
1954 | |||
1955 | i2o_proc_create_entries(devdir, generic_dev_entries, dev); | ||
1956 | |||
1957 | /* Inform core that we want updates about this device's status */ | ||
1958 | switch (dev->lct_data.class_id) { | ||
1959 | case I2O_CLASS_SCSI_PERIPHERAL: | ||
1960 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
1961 | i2o_pe = rbs_dev_entries; | ||
1962 | break; | ||
1963 | default: | ||
1964 | break; | ||
1965 | } | ||
1966 | if (i2o_pe) | ||
1967 | i2o_proc_create_entries(devdir, i2o_pe, dev); | ||
1968 | } | ||
1969 | |||
1970 | /** | ||
1971 | * i2o_proc_iop_add - Add an I2O controller to the i2o proc tree | ||
1972 | * @dir: parent proc dir entry | ||
1973 | * @c: I2O controller which should be added | ||
1974 | * | ||
1975 | * Add the entries to the parent proc dir entry. Also each device is added | ||
1976 | * to the controllers proc dir entry. | ||
1977 | * | ||
1978 | * Returns 0 on success or negative error code on failure. | ||
1979 | */ | ||
1980 | static int i2o_proc_iop_add(struct proc_dir_entry *dir, | ||
1981 | struct i2o_controller *c) | ||
1982 | { | ||
1983 | struct proc_dir_entry *iopdir; | ||
1984 | struct i2o_device *dev; | ||
1985 | |||
1986 | osm_debug("adding IOP /proc/i2o/%s\n", c->name); | ||
1987 | |||
1988 | iopdir = proc_mkdir(c->name, dir); | ||
1989 | if (!iopdir) | ||
1990 | return -1; | ||
1991 | |||
1992 | iopdir->data = c; | ||
1993 | |||
1994 | i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c); | ||
1995 | |||
1996 | list_for_each_entry(dev, &c->devices, list) | ||
1997 | i2o_proc_device_add(iopdir, dev); | ||
1998 | |||
1999 | return 0; | ||
2000 | } | ||
2001 | |||
2002 | /** | ||
2003 | * i2o_proc_iop_remove - Removes an I2O controller from the i2o proc tree | ||
2004 | * @dir: parent proc dir entry | ||
2005 | * @c: I2O controller which should be removed | ||
2006 | * | ||
2007 | * Iterate over each i2o proc entry and search controller c. If it is found | ||
2008 | * remove it from the tree. | ||
2009 | */ | ||
2010 | static void i2o_proc_iop_remove(struct proc_dir_entry *dir, | ||
2011 | struct i2o_controller *c) | ||
2012 | { | ||
2013 | struct proc_dir_entry *pe, *tmp; | ||
2014 | |||
2015 | pe = dir->subdir; | ||
2016 | while (pe) { | ||
2017 | tmp = pe->next; | ||
2018 | if (pe->data == c) { | ||
2019 | i2o_proc_subdir_remove(pe); | ||
2020 | remove_proc_entry(pe->name, dir); | ||
2021 | } | ||
2022 | osm_debug("removing IOP /proc/i2o/%s\n", c->name); | ||
2023 | pe = tmp; | ||
2024 | } | ||
2025 | } | ||
2026 | |||
2027 | /** | ||
2028 | * i2o_proc_fs_create - Create the i2o proc fs. | ||
2029 | * | ||
2030 | * Iterate over each I2O controller and create the entries for it. | ||
2031 | * | ||
2032 | * Returns 0 on success or negative error code on failure. | ||
2033 | */ | ||
2034 | static int __init i2o_proc_fs_create(void) | ||
2035 | { | ||
2036 | struct i2o_controller *c; | ||
2037 | |||
2038 | i2o_proc_dir_root = proc_mkdir("i2o", NULL); | ||
2039 | if (!i2o_proc_dir_root) | ||
2040 | return -1; | ||
2041 | |||
2042 | i2o_proc_dir_root->owner = THIS_MODULE; | ||
2043 | |||
2044 | list_for_each_entry(c, &i2o_controllers, list) | ||
2045 | i2o_proc_iop_add(i2o_proc_dir_root, c); | ||
2046 | |||
2047 | return 0; | ||
2048 | }; | ||
2049 | |||
2050 | /** | ||
2051 | * i2o_proc_fs_destroy - Cleanup the all i2o proc entries | ||
2052 | * | ||
2053 | * Iterate over each I2O controller and remove the entries for it. | ||
2054 | * | ||
2055 | * Returns 0 on success or negative error code on failure. | ||
2056 | */ | ||
2057 | static int __exit i2o_proc_fs_destroy(void) | ||
2058 | { | ||
2059 | struct i2o_controller *c; | ||
2060 | |||
2061 | list_for_each_entry(c, &i2o_controllers, list) | ||
2062 | i2o_proc_iop_remove(i2o_proc_dir_root, c); | ||
2063 | |||
2064 | remove_proc_entry("i2o", NULL); | ||
2065 | |||
2066 | return 0; | ||
2067 | }; | ||
2068 | |||
2069 | /** | ||
2070 | * i2o_proc_init - Init function for procfs | ||
2071 | * | ||
2072 | * Registers Proc OSM and creates procfs entries. | ||
2073 | * | ||
2074 | * Returns 0 on success or negative error code on failure. | ||
2075 | */ | ||
2076 | static int __init i2o_proc_init(void) | ||
2077 | { | ||
2078 | int rc; | ||
2079 | |||
2080 | printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n"); | ||
2081 | |||
2082 | rc = i2o_driver_register(&i2o_proc_driver); | ||
2083 | if (rc) | ||
2084 | return rc; | ||
2085 | |||
2086 | rc = i2o_proc_fs_create(); | ||
2087 | if (rc) { | ||
2088 | i2o_driver_unregister(&i2o_proc_driver); | ||
2089 | return rc; | ||
2090 | } | ||
2091 | |||
2092 | return 0; | ||
2093 | }; | ||
2094 | |||
2095 | /** | ||
2096 | * i2o_proc_exit - Exit function for procfs | ||
2097 | * | ||
2098 | * Unregisters Proc OSM and removes procfs entries. | ||
2099 | */ | ||
2100 | static void __exit i2o_proc_exit(void) | ||
2101 | { | ||
2102 | i2o_driver_unregister(&i2o_proc_driver); | ||
2103 | i2o_proc_fs_destroy(); | ||
2104 | }; | ||
2105 | |||
2106 | MODULE_AUTHOR("Deepak Saxena"); | ||
2107 | MODULE_LICENSE("GPL"); | ||
2108 | MODULE_DESCRIPTION(OSM_DESCRIPTION); | ||
2109 | MODULE_VERSION(OSM_VERSION); | ||
2110 | |||
2111 | module_init(i2o_proc_init); | ||
2112 | module_exit(i2o_proc_exit); | ||