aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/manager.c')
-rw-r--r--drivers/pnp/manager.c220
1 files changed, 55 insertions, 165 deletions
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 90bd9cb65563..165b624081ad 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -19,40 +19,30 @@ DEFINE_MUTEX(pnp_res_mutex);
19 19
20static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) 20static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
21{ 21{
22 struct pnp_resource *pnp_res; 22 struct resource *res, local_res;
23 struct resource *res;
24 23
25 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx); 24 res = pnp_get_resource(dev, IORESOURCE_IO, idx);
26 if (!pnp_res) { 25 if (res) {
27 dev_err(&dev->dev, "too many I/O port resources\n");
28 /* pretend we were successful so at least the manager won't try again */
29 return 1;
30 }
31
32 res = &pnp_res->res;
33
34 /* check if this resource has been manually set, if so skip */
35 if (!(res->flags & IORESOURCE_AUTO)) {
36 dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " 26 dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
37 "flags %#lx\n", idx, (unsigned long long) res->start, 27 "flags %#lx\n", idx, (unsigned long long) res->start,
38 (unsigned long long) res->end, res->flags); 28 (unsigned long long) res->end, res->flags);
39 return 1; 29 return 1;
40 } 30 }
41 31
42 /* set the initial values */ 32 res = &local_res;
43 res->flags |= rule->flags | IORESOURCE_IO; 33 res->flags = rule->flags | IORESOURCE_AUTO;
44 res->flags &= ~IORESOURCE_UNSET; 34 res->start = 0;
35 res->end = 0;
45 36
46 if (!rule->size) { 37 if (!rule->size) {
47 res->flags |= IORESOURCE_DISABLED; 38 res->flags |= IORESOURCE_DISABLED;
48 dev_dbg(&dev->dev, " io %d disabled\n", idx); 39 dev_dbg(&dev->dev, " io %d disabled\n", idx);
49 return 1; /* skip disabled resource requests */ 40 goto __add;
50 } 41 }
51 42
52 res->start = rule->min; 43 res->start = rule->min;
53 res->end = res->start + rule->size - 1; 44 res->end = res->start + rule->size - 1;
54 45
55 /* run through until pnp_check_port is happy */
56 while (!pnp_check_port(dev, res)) { 46 while (!pnp_check_port(dev, res)) {
57 res->start += rule->align; 47 res->start += rule->align;
58 res->end = res->start + rule->size - 1; 48 res->end = res->start + rule->size - 1;
@@ -61,38 +51,29 @@ static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
61 return 0; 51 return 0;
62 } 52 }
63 } 53 }
64 dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, 54
65 (unsigned long long) res->start, (unsigned long long) res->end); 55__add:
56 pnp_add_io_resource(dev, res->start, res->end, res->flags);
66 return 1; 57 return 1;
67} 58}
68 59
69static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) 60static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
70{ 61{
71 struct pnp_resource *pnp_res; 62 struct resource *res, local_res;
72 struct resource *res;
73 63
74 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx); 64 res = pnp_get_resource(dev, IORESOURCE_MEM, idx);
75 if (!pnp_res) { 65 if (res) {
76 dev_err(&dev->dev, "too many memory resources\n");
77 /* pretend we were successful so at least the manager won't try again */
78 return 1;
79 }
80
81 res = &pnp_res->res;
82
83 /* check if this resource has been manually set, if so skip */
84 if (!(res->flags & IORESOURCE_AUTO)) {
85 dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " 66 dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
86 "flags %#lx\n", idx, (unsigned long long) res->start, 67 "flags %#lx\n", idx, (unsigned long long) res->start,
87 (unsigned long long) res->end, res->flags); 68 (unsigned long long) res->end, res->flags);
88 return 1; 69 return 1;
89 } 70 }
90 71
91 /* set the initial values */ 72 res = &local_res;
92 res->flags |= rule->flags | IORESOURCE_MEM; 73 res->flags = rule->flags | IORESOURCE_AUTO;
93 res->flags &= ~IORESOURCE_UNSET; 74 res->start = 0;
75 res->end = 0;
94 76
95 /* convert pnp flags to standard Linux flags */
96 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) 77 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
97 res->flags |= IORESOURCE_READONLY; 78 res->flags |= IORESOURCE_READONLY;
98 if (rule->flags & IORESOURCE_MEM_CACHEABLE) 79 if (rule->flags & IORESOURCE_MEM_CACHEABLE)
@@ -105,13 +86,12 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
105 if (!rule->size) { 86 if (!rule->size) {
106 res->flags |= IORESOURCE_DISABLED; 87 res->flags |= IORESOURCE_DISABLED;
107 dev_dbg(&dev->dev, " mem %d disabled\n", idx); 88 dev_dbg(&dev->dev, " mem %d disabled\n", idx);
108 return 1; /* skip disabled resource requests */ 89 goto __add;
109 } 90 }
110 91
111 res->start = rule->min; 92 res->start = rule->min;
112 res->end = res->start + rule->size - 1; 93 res->end = res->start + rule->size - 1;
113 94
114 /* run through until pnp_check_mem is happy */
115 while (!pnp_check_mem(dev, res)) { 95 while (!pnp_check_mem(dev, res)) {
116 res->start += rule->align; 96 res->start += rule->align;
117 res->end = res->start + rule->size - 1; 97 res->end = res->start + rule->size - 1;
@@ -120,15 +100,15 @@ static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
120 return 0; 100 return 0;
121 } 101 }
122 } 102 }
123 dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, 103
124 (unsigned long long) res->start, (unsigned long long) res->end); 104__add:
105 pnp_add_mem_resource(dev, res->start, res->end, res->flags);
125 return 1; 106 return 1;
126} 107}
127 108
128static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) 109static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
129{ 110{
130 struct pnp_resource *pnp_res; 111 struct resource *res, local_res;
131 struct resource *res;
132 int i; 112 int i;
133 113
134 /* IRQ priority: this table is good for i386 */ 114 /* IRQ priority: this table is good for i386 */
@@ -136,58 +116,48 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
136 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 116 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
137 }; 117 };
138 118
139 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx); 119 res = pnp_get_resource(dev, IORESOURCE_IRQ, idx);
140 if (!pnp_res) { 120 if (res) {
141 dev_err(&dev->dev, "too many IRQ resources\n");
142 /* pretend we were successful so at least the manager won't try again */
143 return 1;
144 }
145
146 res = &pnp_res->res;
147
148 /* check if this resource has been manually set, if so skip */
149 if (!(res->flags & IORESOURCE_AUTO)) {
150 dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", 121 dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
151 idx, (int) res->start, res->flags); 122 idx, (int) res->start, res->flags);
152 return 1; 123 return 1;
153 } 124 }
154 125
155 /* set the initial values */ 126 res = &local_res;
156 res->flags |= rule->flags | IORESOURCE_IRQ; 127 res->flags = rule->flags | IORESOURCE_AUTO;
157 res->flags &= ~IORESOURCE_UNSET; 128 res->start = -1;
129 res->end = -1;
158 130
159 if (bitmap_empty(rule->map, PNP_IRQ_NR)) { 131 if (bitmap_empty(rule->map, PNP_IRQ_NR)) {
160 res->flags |= IORESOURCE_DISABLED; 132 res->flags |= IORESOURCE_DISABLED;
161 dev_dbg(&dev->dev, " irq %d disabled\n", idx); 133 dev_dbg(&dev->dev, " irq %d disabled\n", idx);
162 return 1; /* skip disabled resource requests */ 134 goto __add;
163 } 135 }
164 136
165 /* TBD: need check for >16 IRQ */ 137 /* TBD: need check for >16 IRQ */
166 res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16); 138 res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16);
167 if (res->start < PNP_IRQ_NR) { 139 if (res->start < PNP_IRQ_NR) {
168 res->end = res->start; 140 res->end = res->start;
169 dev_dbg(&dev->dev, " assign irq %d %d\n", idx, 141 goto __add;
170 (int) res->start);
171 return 1;
172 } 142 }
173 for (i = 0; i < 16; i++) { 143 for (i = 0; i < 16; i++) {
174 if (test_bit(xtab[i], rule->map)) { 144 if (test_bit(xtab[i], rule->map)) {
175 res->start = res->end = xtab[i]; 145 res->start = res->end = xtab[i];
176 if (pnp_check_irq(dev, res)) { 146 if (pnp_check_irq(dev, res))
177 dev_dbg(&dev->dev, " assign irq %d %d\n", idx, 147 goto __add;
178 (int) res->start);
179 return 1;
180 }
181 } 148 }
182 } 149 }
183 dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); 150 dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
184 return 0; 151 return 0;
152
153__add:
154 pnp_add_irq_resource(dev, res->start, res->flags);
155 return 1;
185} 156}
186 157
187static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) 158static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
188{ 159{
189 struct pnp_resource *pnp_res; 160 struct resource *res, local_res;
190 struct resource *res;
191 int i; 161 int i;
192 162
193 /* DMA priority: this table is good for i386 */ 163 /* DMA priority: this table is good for i386 */
@@ -195,127 +165,47 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
195 1, 3, 5, 6, 7, 0, 2, 4 165 1, 3, 5, 6, 7, 0, 2, 4
196 }; 166 };
197 167
198 pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx); 168 res = pnp_get_resource(dev, IORESOURCE_DMA, idx);
199 if (!pnp_res) { 169 if (res) {
200 dev_err(&dev->dev, "too many DMA resources\n");
201 return;
202 }
203
204 res = &pnp_res->res;
205
206 /* check if this resource has been manually set, if so skip */
207 if (!(res->flags & IORESOURCE_AUTO)) {
208 dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", 170 dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
209 idx, (int) res->start, res->flags); 171 idx, (int) res->start, res->flags);
210 return; 172 return;
211 } 173 }
212 174
213 /* set the initial values */ 175 res = &local_res;
214 res->flags |= rule->flags | IORESOURCE_DMA; 176 res->flags = rule->flags | IORESOURCE_AUTO;
215 res->flags &= ~IORESOURCE_UNSET; 177 res->start = -1;
178 res->end = -1;
216 179
217 for (i = 0; i < 8; i++) { 180 for (i = 0; i < 8; i++) {
218 if (rule->map & (1 << xtab[i])) { 181 if (rule->map & (1 << xtab[i])) {
219 res->start = res->end = xtab[i]; 182 res->start = res->end = xtab[i];
220 if (pnp_check_dma(dev, res)) { 183 if (pnp_check_dma(dev, res))
221 dev_dbg(&dev->dev, " assign dma %d %d\n", idx, 184 goto __add;
222 (int) res->start);
223 return;
224 }
225 } 185 }
226 } 186 }
227#ifdef MAX_DMA_CHANNELS 187#ifdef MAX_DMA_CHANNELS
228 res->start = res->end = MAX_DMA_CHANNELS; 188 res->start = res->end = MAX_DMA_CHANNELS;
229#endif 189#endif
230 res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; 190 res->flags |= IORESOURCE_DISABLED;
231 dev_dbg(&dev->dev, " disable dma %d\n", idx); 191 dev_dbg(&dev->dev, " disable dma %d\n", idx);
232}
233 192
234void pnp_init_resource(struct resource *res) 193__add:
235{ 194 pnp_add_dma_resource(dev, res->start, res->flags);
236 unsigned long type;
237
238 type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM |
239 IORESOURCE_IRQ | IORESOURCE_DMA);
240
241 res->name = NULL;
242 res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET;
243 if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) {
244 res->start = -1;
245 res->end = -1;
246 } else {
247 res->start = 0;
248 res->end = 0;
249 }
250} 195}
251 196
252/**
253 * pnp_init_resources - Resets a resource table to default values.
254 * @table: pointer to the desired resource table
255 */
256void pnp_init_resources(struct pnp_dev *dev) 197void pnp_init_resources(struct pnp_dev *dev)
257{ 198{
258 struct resource *res; 199 pnp_free_resources(dev);
259 int idx;
260
261 for (idx = 0; idx < PNP_MAX_IRQ; idx++) {
262 res = &dev->res->irq[idx].res;
263 res->flags = IORESOURCE_IRQ;
264 pnp_init_resource(res);
265 }
266 for (idx = 0; idx < PNP_MAX_DMA; idx++) {
267 res = &dev->res->dma[idx].res;
268 res->flags = IORESOURCE_DMA;
269 pnp_init_resource(res);
270 }
271 for (idx = 0; idx < PNP_MAX_PORT; idx++) {
272 res = &dev->res->port[idx].res;
273 res->flags = IORESOURCE_IO;
274 pnp_init_resource(res);
275 }
276 for (idx = 0; idx < PNP_MAX_MEM; idx++) {
277 res = &dev->res->mem[idx].res;
278 res->flags = IORESOURCE_MEM;
279 pnp_init_resource(res);
280 }
281} 200}
282 201
283/**
284 * pnp_clean_resources - clears resources that were not manually set
285 * @res: the resources to clean
286 */
287static void pnp_clean_resource_table(struct pnp_dev *dev) 202static void pnp_clean_resource_table(struct pnp_dev *dev)
288{ 203{
289 struct resource *res; 204 struct pnp_resource *pnp_res, *tmp;
290 int idx; 205
291 206 list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
292 for (idx = 0; idx < PNP_MAX_IRQ; idx++) { 207 if (pnp_res->res.flags & IORESOURCE_AUTO)
293 res = &dev->res->irq[idx].res; 208 pnp_free_resource(pnp_res);
294 if (res->flags & IORESOURCE_AUTO) {
295 res->flags = IORESOURCE_IRQ;
296 pnp_init_resource(res);
297 }
298 }
299 for (idx = 0; idx < PNP_MAX_DMA; idx++) {
300 res = &dev->res->dma[idx].res;
301 if (res->flags & IORESOURCE_AUTO) {
302 res->flags = IORESOURCE_DMA;
303 pnp_init_resource(res);
304 }
305 }
306 for (idx = 0; idx < PNP_MAX_PORT; idx++) {
307 res = &dev->res->port[idx].res;
308 if (res->flags & IORESOURCE_AUTO) {
309 res->flags = IORESOURCE_IO;
310 pnp_init_resource(res);
311 }
312 }
313 for (idx = 0; idx < PNP_MAX_MEM; idx++) {
314 res = &dev->res->mem[idx].res;
315 if (res->flags & IORESOURCE_AUTO) {
316 res->flags = IORESOURCE_MEM;
317 pnp_init_resource(res);
318 }
319 } 209 }
320} 210}
321 211