- Moved hlt() to it's own header.
[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->path.type == DEVICE_PATH_PCI) &&
38                         (dev->bus->secondary == bus) && 
39                         (dev->path.u.pci.devfn == devfn)) {
40                         result = dev;
41                         break;
42                 }
43         }
44         return result;
45 }
46
47 /** Find a device of a given vendor and type
48  * @param vendor Vendor ID (e.g. 0x8086 for Intel)
49  * @param device Device ID
50  * @param from Pointer to the device structure, used as a starting point
51  *        in the linked list of all_devices, which can be 0 to start at the 
52  *        head of the list (i.e. all_devices)
53  * @return Pointer to the device struct 
54  */
55 struct device *dev_find_device(unsigned int vendor, unsigned int device, struct device *from)
56 {
57         if (!from)
58                 from = all_devices;
59         else
60                 from = from->next;
61         while (from && (from->vendor != vendor || from->device != device)) {
62                 from = from->next;
63         }
64         return from;
65 }
66
67 /** Find a device of a given class
68  * @param class Class of the device
69  * @param from Pointer to the device structure, used as a starting point
70  *        in the linked list of all_devices, which can be 0 to start at the 
71  *        head of the list (i.e. all_devices)
72  * @return Pointer to the device struct 
73  */
74 struct device *dev_find_class(unsigned int class, struct device *from)
75 {
76         if (!from)
77                 from = all_devices;
78         else
79                 from = from->next;
80         while (from && (from->class & 0xffffff00) != class)
81                 from = from->next;
82         return from;
83 }
84
85
86 const char *dev_path(device_t dev)
87 {
88         static char buffer[DEVICE_PATH_MAX];
89         buffer[0] = '\0';
90         if (!dev) {
91                 memcpy(buffer, "<null>", 7);
92         }
93         else {
94                 switch(dev->path.type) {
95                 case DEVICE_PATH_ROOT:
96                         memcpy(buffer, "Root Device", 12);
97                         break;
98                 case DEVICE_PATH_PCI:
99                         sprintf(buffer, "PCI: %02x:%02x.%01x",
100                                 dev->bus->secondary, 
101                                 PCI_SLOT(dev->path.u.pci.devfn), PCI_FUNC(dev->path.u.pci.devfn));
102                         break;
103                 case DEVICE_PATH_PNP:
104                         sprintf(buffer, "PNP: %04x.%01x",
105                                 dev->path.u.pnp.port, dev->path.u.pnp.device);
106                         break;
107                 case DEVICE_PATH_I2C:
108                         sprintf(buffer, "I2C: %02x",
109                                 dev->path.u.i2c.device);
110                         break;
111                 default:
112                         printk_err("Unknown device path type: %d\n", dev->path.type);
113                         break;
114                 }
115         }
116         return buffer;
117 }
118
119 int path_eq(struct device_path *path1, struct device_path *path2)
120 {
121         int equal = 0;
122         if (path1->type == path2->type) {
123                 switch(path1->type) {
124                 case DEVICE_PATH_NONE:
125                         break;
126                 case DEVICE_PATH_ROOT:
127                         equal = 1;
128                         break;
129                 case DEVICE_PATH_PCI:
130                         equal = (path1->u.pci.bus == path2->u.pci.bus) &&
131                                 (path1->u.pci.devfn == path2->u.pci.devfn);
132                         break;
133                 case DEVICE_PATH_PNP:
134                         equal = (path1->u.pnp.port == path2->u.pnp.port) &&
135                                 (path1->u.pnp.device == path2->u.pnp.device);
136                         break;
137                 case DEVICE_PATH_I2C:
138                         equal = (path1->u.i2c.device == path2->u.i2c.device);
139                         break;
140                 default:
141                         printk_err("Uknown device type: %d\n", path1->type);
142                         break;
143                 }
144         }
145         return equal;
146 }
147
148 /**
149  * See if we have unused but allocated resource structures.
150  * If so remove the allocation.
151  * @param dev The device to find the resource on
152  */
153 void compact_resources(device_t dev)
154 {
155         struct resource *resource;
156         int i;
157         /* Move all of the free resources to the end */
158         for(i = 0; i < dev->resources;) {
159                 resource = &dev->resource[i];
160                 if (!resource->flags) {
161                         memmove(resource, resource + 1, dev->resources - i);
162                         dev->resources -= 1;
163                         memset(&dev->resource[dev->resources], 0, sizeof(*resource));
164                 } else {
165                         i++;
166                 }
167         }
168 }
169
170 /**
171  * See if a resource structure already exists for a given index and if
172  * not allocate one.
173  * @param dev The device to find the resource on
174  * @param index  The index of the resource on the device.
175  */
176 struct resource *get_resource(device_t dev, unsigned index)
177 {
178         struct resource *resource;
179         int i;
180
181         /* First move all of the free resources to the end */
182         compact_resources(dev);
183
184         /* See if there is a resource with the appropriate index */
185         resource = 0;
186         for(i = 0; i < dev->resources; i++) {
187                 if (dev->resource[i].index == index) {
188                         resource = &dev->resource[i];
189                         break;
190                 }
191         }
192         if (!resource) {
193                 if (dev->resources == MAX_RESOURCES) {
194                         die("MAX_RESOURCES exceeded.");
195                 }
196                 resource = &dev->resource[dev->resources];
197                 memset(resource, 0, sizeof(*resource));
198                 dev->resources++;
199         }
200         /* Initialize the resource values */
201         if (!(resource->flags & IORESOURCE_FIXED)) {
202                 resource->flags = 0;
203                 resource->base = 0;
204         }
205         resource->size  = 0;
206         resource->limit = 0;
207         resource->index = index;
208         resource->align = 0;
209         resource->gran  = 0;
210
211         return resource;
212 }
213