rename walk_static_devices
[coreboot.git] / src / devices / pnp_device.c
1 /* Copyright 2004 Linux Networx  */
2 /* This code is distrubted wihtout warrant under the GPL v2 (see COPYING) */
3
4 #include <console/console.h>
5 #include <stdlib.h>
6 #include <stdint.h>
7 #include <bitops.h>
8 #include <string.h>
9 #include <arch/io.h>
10 #include <device/device.h>
11 #include <device/pnp.h>
12
13 /* PNP fundamental operations */
14
15 void pnp_write_config(device_t dev, uint8_t reg, uint8_t value)
16 {
17         outb(reg, dev->path.u.pnp.port);
18         outb(value, dev->path.u.pnp.port + 1);
19 }
20
21 uint8_t pnp_read_config(device_t dev, uint8_t reg)
22 {
23         outb(reg, dev->path.u.pnp.port);
24         return inb(dev->path.u.pnp.port + 1);
25 }
26
27 void pnp_set_logical_device(device_t dev)
28 {
29         pnp_write_config(dev, 0x07, dev->path.u.pnp.device);
30 }
31
32 void pnp_set_enable(device_t dev, int enable)
33 {
34         pnp_write_config(dev, 0x30, enable?0x1:0x0);
35 }
36
37 int pnp_read_enable(device_t dev)
38 {
39         return !!pnp_read_config(dev, 0x30);
40 }
41
42 void pnp_set_iobase(device_t dev, unsigned index, unsigned iobase)
43 {
44         /* Index == 0x60 or 0x62 */
45         pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff);
46         pnp_write_config(dev, index + 1, iobase & 0xff);
47 }
48
49 void pnp_set_irq(device_t dev, unsigned index, unsigned irq)
50 {
51         /* Index == 0x70 or 0x72 */
52         pnp_write_config(dev, index, irq);
53 }
54
55 void pnp_set_drq(device_t dev, unsigned drq, unsigned index)
56 {
57         /* Index == 0x74 */
58         pnp_write_config(dev, index, drq & 0xff);
59 }
60
61 /* PNP device operations */
62
63 void pnp_read_resources(device_t dev)
64 {
65         return;
66 }
67
68 static void pnp_set_resource(device_t dev, struct resource *resource)
69 {
70         if (!(resource->flags & IORESOURCE_ASSIGNED)) {
71                 printk_err("ERROR: %s %02x not allocated\n",
72                            dev_path(dev), resource->index);
73                 return;
74         }
75
76         /* Now store the resource */
77         if (resource->flags & IORESOURCE_IO) {
78                 pnp_set_iobase(dev, resource->index, resource->base);
79         } else if (resource->flags & IORESOURCE_DRQ) {
80                 pnp_set_drq(dev, resource->index, resource->base);
81         } else if (resource->flags  & IORESOURCE_IRQ) {
82                 pnp_set_irq(dev, resource->index, resource->base);
83         } else {
84                 printk_err("ERROR: %s %02x unknown resource type\n",
85                            dev_path(dev), resource->index);
86                 return;
87         }
88         resource->flags |= IORESOURCE_STORED;
89
90         printk_debug("%s %02x <- [0x%08lx - 0x%08lx] %s\n", dev_path(dev),
91                      resource->index, resource->base,
92                      resource->base + resource->size - 1,
93                      (resource->flags & IORESOURCE_IO)? "io":
94                      (resource->flags & IORESOURCE_DRQ)? "drq":
95                      (resource->flags & IORESOURCE_IRQ)? "irq":
96                      (resource->flags & IORESOURCE_MEM)? "mem":
97                      "???");
98 }
99
100 void pnp_set_resources(device_t dev)
101 {
102         int i;
103
104         /* Select the device */
105         pnp_set_logical_device(dev);
106
107         /* Paranoia says I should disable the device here... */
108         for (i = 0; i < dev->resources; i++) {
109                 pnp_set_resource(dev, &dev->resource[i]);
110         }
111 }
112
113 void pnp_enable_resources(device_t dev)
114 {
115         pnp_set_logical_device(dev);
116         pnp_set_enable(dev, 1);
117 }
118
119 void pnp_enable(device_t dev)
120 {
121         if (!dev->enabled) {
122                 pnp_set_logical_device(dev);
123                 pnp_set_enable(dev, 0);
124         }
125 }
126
127 struct device_operations pnp_ops = {
128         .read_resources   = pnp_read_resources,
129         .set_resources    = pnp_set_resources,
130         .enable_resources = pnp_enable_resources,
131         .enable           = pnp_enable,
132 };
133
134 /* PNP chip opertations */
135
136 static void pnp_get_ioresource(device_t dev, unsigned index,
137                                struct io_info *info)
138 {
139         struct resource *resource;
140         uint32_t size;
141
142         resource = get_resource(dev, index);
143         
144         /* Initilize the resource */
145         resource->limit = 0xffff;
146         resource->flags |= IORESOURCE_IO;
147         
148         /* Set the resource size and alignment */
149         size = (0xffff & info->mask);
150         resource->size  = (~(size | 0xfffff800) + 1);
151         resource->align = log2(resource->size);
152         resource->gran  = resource->align;
153 }
154
155 static void get_resources(device_t dev, struct pnp_info *info)
156 {
157         struct resource *resource;
158
159 //      pnp_set_logical_device(dev);   // coment out by LYH
160
161         if (info->flags & PNP_IO0) {
162                 pnp_get_ioresource(dev, PNP_IDX_IO0, &info->io0);
163         }
164         if (info->flags & PNP_IO1) {
165                 pnp_get_ioresource(dev, PNP_IDX_IO1, &info->io1);
166         }
167         if (info->flags & PNP_IRQ0) {
168                 resource = get_resource(dev, PNP_IDX_IRQ0);
169                 resource->size = 1;
170                 resource->flags |= IORESOURCE_IRQ;
171         }
172         if (info->flags & PNP_IRQ1) {
173                 resource = get_resource(dev, PNP_IDX_IRQ1);
174                 resource->size = 1;
175                 resource->flags |= IORESOURCE_IRQ;
176         }
177         if (info->flags & PNP_DRQ0) {
178                 resource = get_resource(dev, PNP_IDX_DRQ0);
179                 resource->size = 1;
180                 resource->flags |= IORESOURCE_DRQ;
181         }
182         if (info->flags & PNP_DRQ1) {
183                 resource = get_resource(dev, PNP_IDX_DRQ1);
184                 resource->size = 1;
185                 resource->flags |= IORESOURCE_DRQ;
186         }       
187
188
189 void pnp_enumerate(struct chip *chip, unsigned functions, 
190                    struct device_operations *ops, struct pnp_info *info)
191 {
192         struct device_path path;
193         device_t dev;
194         int i;
195
196         chip_enumerate(chip);
197
198         path.type       = DEVICE_PATH_PNP;
199         path.u.pnp.port = chip->dev->path.u.pnp.port;
200         
201         /* Setup the ops and resources on the newly allocated devices */
202         for (i = 0; i < functions; i++) {
203                 path.u.pnp.device = info[i].function;
204
205                 dev = alloc_find_dev(chip->bus, &path);
206
207                 if (info[i].ops == 0) {
208                         dev->ops = ops;
209                 } else { 
210                         dev->ops = info[i].ops;
211                 }
212                 get_resources(dev, &info[i]);
213         }
214 }