- O2, enums, and switch statements work in romcc
[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, *result;
34
35         result = 0;
36         for (dev = all_devices; dev; dev = dev->next) {
37                 if ((dev->bus->secondary == bus) && 
38                         (dev->path.u.pci.devfn == devfn)) {
39                         result = dev;
40                         break;
41                 }
42         }
43         return result;
44 }
45
46 /** Find a device of a given vendor and type
47  * @param vendor Vendor ID (e.g. 0x8086 for Intel)
48  * @param device Device ID
49  * @param from Pointer to the device structure, used as a starting point
50  *        in the linked list of all_devices, which can be 0 to start at the 
51  *        head of the list (i.e. all_devices)
52  * @return Pointer to the device struct 
53  */
54 struct device *dev_find_device(unsigned int vendor, unsigned int device, struct device *from)
55 {
56         if (!from)
57                 from = all_devices;
58         else
59                 from = from->next;
60         while (from && (from->vendor != vendor || from->device != device))
61                 from = from->next;
62         return from;
63 }
64
65 /** Find a device of a given class
66  * @param class Class of the device
67  * @param from Pointer to the device structure, used as a starting point
68  *        in the linked list of all_devices, which can be 0 to start at the 
69  *        head of the list (i.e. all_devices)
70  * @return Pointer to the device struct 
71  */
72 struct device *dev_find_class(unsigned int class, struct device *from)
73 {
74         if (!from)
75                 from = all_devices;
76         else
77                 from = from->next;
78         while (from && from->class != class)
79                 from = from->next;
80         return from;
81 }
82
83
84 const char *dev_path(device_t dev)
85 {
86         static char buffer[DEVICE_PATH_MAX];
87         buffer[0] = '\0';
88         if (!dev) {
89                 memcpy(buffer, "<null>", 7);
90         }
91         else {
92                 switch(dev->path.type) {
93                 case DEVICE_PATH_ROOT:
94                         memcpy(buffer, "Root Device", 12);
95                         break;
96                 case DEVICE_PATH_PCI:
97                         sprintf(buffer, "PCI: %02x:%02x.%01x",
98                                 dev->bus->secondary, 
99                                 PCI_SLOT(dev->path.u.pci.devfn), PCI_FUNC(dev->path.u.pci.devfn));
100                         break;
101                 case DEVICE_PATH_PNP:
102                         sprintf(buffer, "PNP: %04x.%01x",
103                                 dev->path.u.pnp.port, dev->path.u.pnp.device);
104                         break;
105                 case DEVICE_PATH_I2C:
106                         sprintf(buffer, "I2C: %02x",
107                                 dev->path.u.i2c.device);
108                         break;
109                 default:
110                         printk_err("Unknown device path type: %d\n", dev->path.type);
111                         break;
112                 }
113         }
114         return buffer;
115 }
116
117 int path_eq(struct device_path *path1, struct device_path *path2)
118 {
119         int equal = 0;
120         if (path1->type == path2->type) {
121                 switch(path1->type) {
122                 case DEVICE_PATH_NONE:
123                         break;
124                 case DEVICE_PATH_ROOT:
125                         equal = 1;
126                         break;
127                 case DEVICE_PATH_PCI:
128                         equal = (path1->u.pci.bus == path2->u.pci.bus) &&
129                                 (path1->u.pci.devfn == path2->u.pci.devfn);
130                         break;
131                 case DEVICE_PATH_PNP:
132                         equal = (path1->u.pnp.port == path2->u.pnp.port) &&
133                                 (path1->u.pnp.device == path2->u.pnp.device);
134                         break;
135                 case DEVICE_PATH_I2C:
136                         equal = (path1->u.i2c.device == path2->u.i2c.device);
137                         break;
138                 default:
139                         printk_err("Uknown device type: %d\n", path1->type);
140                         break;
141                 }
142         }
143         return equal;
144 }