aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Panin <pazke@donpac.ru>2005-09-06 18:18:29 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:57:44 -0400
commitebad6a4230bdb5927495e28bc7837f515bf667a7 (patch)
tree373339d76d8424dd749957847b6d83707e65e016
parentc3c7120d552989be94c9137989be5abb6da8954f (diff)
[PATCH] dmi: add onboard devices discovery
This patch adds onboard devices and IPMI BMC discovery into DMI scan code. Drivers can use dmi_find_device() function to search for devices by type and name. Signed-off-by: Andrey Panin <pazke@donpac.ru> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/dmi_scan.c102
-rw-r--r--include/linux/dmi.h36
2 files changed, 123 insertions, 15 deletions
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index ae1a1aed2fc0..c4a73855e38c 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -6,13 +6,6 @@
6#include <linux/bootmem.h> 6#include <linux/bootmem.h>
7 7
8 8
9struct dmi_header {
10 u8 type;
11 u8 length;
12 u16 handle;
13};
14
15
16static char * __init dmi_string(struct dmi_header *dm, u8 s) 9static char * __init dmi_string(struct dmi_header *dm, u8 s)
17{ 10{
18 u8 *bp = ((u8 *) dm) + dm->length; 11 u8 *bp = ((u8 *) dm) + dm->length;
@@ -88,6 +81,7 @@ static int __init dmi_checksum(u8 *buf)
88} 81}
89 82
90static char *dmi_ident[DMI_STRING_MAX]; 83static char *dmi_ident[DMI_STRING_MAX];
84static LIST_HEAD(dmi_devices);
91 85
92/* 86/*
93 * Save a DMI string 87 * Save a DMI string
@@ -106,6 +100,58 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
106 dmi_ident[slot] = p; 100 dmi_ident[slot] = p;
107} 101}
108 102
103static void __init dmi_save_devices(struct dmi_header *dm)
104{
105 int i, count = (dm->length - sizeof(struct dmi_header)) / 2;
106 struct dmi_device *dev;
107
108 for (i = 0; i < count; i++) {
109 char *d = ((char *) dm) + (i * 2);
110
111 /* Skip disabled device */
112 if ((*d & 0x80) == 0)
113 continue;
114
115 dev = alloc_bootmem(sizeof(*dev));
116 if (!dev) {
117 printk(KERN_ERR "dmi_save_devices: out of memory.\n");
118 break;
119 }
120
121 dev->type = *d++ & 0x7f;
122 dev->name = dmi_string(dm, *d);
123 dev->device_data = NULL;
124
125 list_add(&dev->list, &dmi_devices);
126 }
127}
128
129static void __init dmi_save_ipmi_device(struct dmi_header *dm)
130{
131 struct dmi_device *dev;
132 void * data;
133
134 data = alloc_bootmem(dm->length);
135 if (data == NULL) {
136 printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
137 return;
138 }
139
140 memcpy(data, dm, dm->length);
141
142 dev = alloc_bootmem(sizeof(*dev));
143 if (!dev) {
144 printk(KERN_ERR "dmi_save_ipmi_device: out of memory.\n");
145 return;
146 }
147
148 dev->type = DMI_DEV_TYPE_IPMI;
149 dev->name = "IPMI controller";
150 dev->device_data = data;
151
152 list_add(&dev->list, &dmi_devices);
153}
154
109/* 155/*
110 * Process a DMI table entry. Right now all we care about are the BIOS 156 * Process a DMI table entry. Right now all we care about are the BIOS
111 * and machine entries. For 2.5 we should pull the smbus controller info 157 * and machine entries. For 2.5 we should pull the smbus controller info
@@ -113,25 +159,28 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
113 */ 159 */
114static void __init dmi_decode(struct dmi_header *dm) 160static void __init dmi_decode(struct dmi_header *dm)
115{ 161{
116 u8 *data __attribute__((__unused__)) = (u8 *)dm;
117
118 switch(dm->type) { 162 switch(dm->type) {
119 case 0: 163 case 0: /* BIOS Information */
120 dmi_save_ident(dm, DMI_BIOS_VENDOR, 4); 164 dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
121 dmi_save_ident(dm, DMI_BIOS_VERSION, 5); 165 dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
122 dmi_save_ident(dm, DMI_BIOS_DATE, 8); 166 dmi_save_ident(dm, DMI_BIOS_DATE, 8);
123 break; 167 break;
124 case 1: 168 case 1: /* System Information */
125 dmi_save_ident(dm, DMI_SYS_VENDOR, 4); 169 dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
126 dmi_save_ident(dm, DMI_PRODUCT_NAME, 5); 170 dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
127 dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6); 171 dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
128 dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7); 172 dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
129 break; 173 break;
130 case 2: 174 case 2: /* Base Board Information */
131 dmi_save_ident(dm, DMI_BOARD_VENDOR, 4); 175 dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
132 dmi_save_ident(dm, DMI_BOARD_NAME, 5); 176 dmi_save_ident(dm, DMI_BOARD_NAME, 5);
133 dmi_save_ident(dm, DMI_BOARD_VERSION, 6); 177 dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
134 break; 178 break;
179 case 10: /* Onboard Devices Information */
180 dmi_save_devices(dm);
181 break;
182 case 38: /* IPMI Device Information */
183 dmi_save_ipmi_device(dm);
135 } 184 }
136} 185}
137 186
@@ -221,3 +270,32 @@ char *dmi_get_system_info(int field)
221 return dmi_ident[field]; 270 return dmi_ident[field];
222} 271}
223EXPORT_SYMBOL(dmi_get_system_info); 272EXPORT_SYMBOL(dmi_get_system_info);
273
274/**
275 * dmi_find_device - find onboard device by type/name
276 * @type: device type or %DMI_DEV_TYPE_ANY to match all device types
277 * @desc: device name string or %NULL to match all
278 * @from: previous device found in search, or %NULL for new search.
279 *
280 * Iterates through the list of known onboard devices. If a device is
281 * found with a matching @vendor and @device, a pointer to its device
282 * structure is returned. Otherwise, %NULL is returned.
283 * A new search is initiated by passing %NULL to the @from argument.
284 * If @from is not %NULL, searches continue from next device.
285 */
286struct dmi_device * dmi_find_device(int type, const char *name,
287 struct dmi_device *from)
288{
289 struct list_head *d, *head = from ? &from->list : &dmi_devices;
290
291 for(d = head->next; d != &dmi_devices; d = d->next) {
292 struct dmi_device *dev = list_entry(d, struct dmi_device, list);
293
294 if (((type == DMI_DEV_TYPE_ANY) || (dev->type == type)) &&
295 ((name == NULL) || (strcmp(dev->name, name) == 0)))
296 return dev;
297 }
298
299 return NULL;
300}
301EXPORT_SYMBOL(dmi_find_device);
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index 5e93e6dce9a4..c30175e8dec6 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -1,6 +1,8 @@
1#ifndef __DMI_H__ 1#ifndef __DMI_H__
2#define __DMI_H__ 2#define __DMI_H__
3 3
4#include <linux/list.h>
5
4enum dmi_field { 6enum dmi_field {
5 DMI_NONE, 7 DMI_NONE,
6 DMI_BIOS_VENDOR, 8 DMI_BIOS_VENDOR,
@@ -16,6 +18,24 @@ enum dmi_field {
16 DMI_STRING_MAX, 18 DMI_STRING_MAX,
17}; 19};
18 20
21enum dmi_device_type {
22 DMI_DEV_TYPE_ANY = 0,
23 DMI_DEV_TYPE_OTHER,
24 DMI_DEV_TYPE_UNKNOWN,
25 DMI_DEV_TYPE_VIDEO,
26 DMI_DEV_TYPE_SCSI,
27 DMI_DEV_TYPE_ETHERNET,
28 DMI_DEV_TYPE_TOKENRING,
29 DMI_DEV_TYPE_SOUND,
30 DMI_DEV_TYPE_IPMI = -1
31};
32
33struct dmi_header {
34 u8 type;
35 u8 length;
36 u16 handle;
37};
38
19/* 39/*
20 * DMI callbacks for problem boards 40 * DMI callbacks for problem boards
21 */ 41 */
@@ -26,22 +46,32 @@ struct dmi_strmatch {
26 46
27struct dmi_system_id { 47struct dmi_system_id {
28 int (*callback)(struct dmi_system_id *); 48 int (*callback)(struct dmi_system_id *);
29 char *ident; 49 const char *ident;
30 struct dmi_strmatch matches[4]; 50 struct dmi_strmatch matches[4];
31 void *driver_data; 51 void *driver_data;
32}; 52};
33 53
34#define DMI_MATCH(a,b) { a, b } 54#define DMI_MATCH(a, b) { a, b }
55
56struct dmi_device {
57 struct list_head list;
58 int type;
59 const char *name;
60 void *device_data; /* Type specific data */
61};
35 62
36#if defined(CONFIG_X86) && !defined(CONFIG_X86_64) 63#if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
37 64
38extern int dmi_check_system(struct dmi_system_id *list); 65extern int dmi_check_system(struct dmi_system_id *list);
39extern char * dmi_get_system_info(int field); 66extern char * dmi_get_system_info(int field);
40 67extern struct dmi_device * dmi_find_device(int type, const char *name,
68 struct dmi_device *from);
41#else 69#else
42 70
43static inline int dmi_check_system(struct dmi_system_id *list) { return 0; } 71static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
44static inline char * dmi_get_system_info(int field) { return NULL; } 72static inline char * dmi_get_system_info(int field) { return NULL; }
73static struct dmi_device * dmi_find_device(int type, const char *name,
74 struct dmi_device *from) { return NULL; }
45 75
46#endif 76#endif
47 77