- Major update of the dynamic device tree so it can handle
[coreboot.git] / src / devices / device_util.c
1 #include <console/console.h>
2 #include <device/device.h>
3 #include <device/path.h>
4 #include <device/pci.h>
5 #include <string.h>
6
7
8 /**
9  * See if a device structure already exists and if not allocate it
10  * @param bus The bus to find the device on
11  * @param path The relative path from the bus to the appropriate device
12  * @return pointer a device structure for the device on bus at path
13  */
14 device_t alloc_find_dev(struct bus *parent, struct device_path *path)
15 {
16         device_t child;
17         for(child = parent->children; child; child = child->sibling) {
18                 if (path_eq(path, &child->path)) {
19                         return child;
20                 }
21         }
22         return alloc_dev(parent, path);
23 }
24
25 /**
26  * Given a bus and a devfn number, find the device structure
27  * @param bus The bus number
28  * @param devfn a device/function number
29  * @return pointer to the device structure
30  */
31 struct device *dev_find_slot(unsigned int bus, unsigned int devfn)
32 {
33         struct device *dev;
34
35         for (dev = all_devices; dev; dev = dev->next) {
36                 if ((dev->bus->secondary == bus) && 
37                         (dev->path.u.pci.devfn == devfn)) {
38                         break;
39                 }
40         }
41         return dev;
42 }
43
44 /** Find a device of a given vendor and type
45  * @param vendor Vendor ID (e.g. 0x8086 for Intel)
46  * @param device Device ID
47  * @param from Pointer to the device structure, used as a starting point
48  *        in the linked list of all_devices, which can be 0 to start at the 
49  *        head of the list (i.e. all_devices)
50  * @return Pointer to the device struct 
51  */
52 struct device *dev_find_device(unsigned int vendor, unsigned int device, struct device *from)
53 {
54         if (!from)
55                 from = all_devices;
56         else
57                 from = from->next;
58         while (from && (from->vendor != vendor || from->device != device))
59                 from = from->next;
60         return from;
61 }
62
63 /** Find a device of a given class
64  * @param class Class of the device
65  * @param from Pointer to the device structure, used as a starting point
66  *        in the linked list of all_devices, which can be 0 to start at the 
67  *        head of the list (i.e. all_devices)
68  * @return Pointer to the device struct 
69  */
70 struct device *dev_find_class(unsigned int class, struct device *from)
71 {
72         if (!from)
73                 from = all_devices;
74         else
75                 from = from->next;
76         while (from && from->class != class)
77                 from = from->next;
78         return from;
79 }
80
81
82 const char *dev_path(device_t dev)
83 {
84         static char buffer[DEVICE_PATH_MAX];
85         buffer[0] = '\0';
86         if (!dev) {
87                 memcpy(buffer, "<null>", 7);
88         }
89         else {
90                 switch(dev->path.type) {
91                 case DEVICE_PATH_PCI:
92                         sprintf(buffer, "PCI: %02x:%02x.%01x",
93                                 dev->bus->secondary, 
94                                 PCI_SLOT(dev->path.u.pci.devfn), PCI_FUNC(dev->path.u.pci.devfn));
95                         break;
96                 case DEVICE_PATH_PNP:
97                         sprintf(buffer, "PNP: %04x.%01x",
98                                 dev->path.u.pnp.port, dev->path.u.pnp.device);
99                         break;
100                 case DEVICE_PATH_I2C:
101                         sprintf(buffer, "I2C: %02x",
102                                 dev->path.u.i2c.device);
103                         break;
104                 default:
105                         printk_err("Unknown device path type: %d\n", dev->path.type);
106                         break;
107                 }
108         }
109         return buffer;
110 }
111
112 int path_eq(struct device_path *path1, struct device_path *path2)
113 {
114         int equal = 0;
115         if (path1->type == path2->type) {
116                 switch(path1->type) {
117                 case DEVICE_PATH_NONE:
118                         break;
119                 case DEVICE_PATH_PCI:
120                         equal = path1->u.pci.devfn == path2->u.pci.devfn;
121                         break;
122                 case DEVICE_PATH_PNP:
123                         equal = (path1->u.pnp.port == path2->u.pnp.port) &&
124                                 (path1->u.pnp.device == path2->u.pnp.device);
125                         break;
126                 case DEVICE_PATH_I2C:
127                         equal = (path1->u.i2c.device == path2->u.i2c.device);
128                         break;
129                 default:
130                         printk_err("Uknown device type: %d\n", path1->type);
131                         break;
132                 }
133         }
134         return equal;
135 }