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