diff options
Diffstat (limited to 'drivers/pnp/manager.c')
| -rw-r--r-- | drivers/pnp/manager.c | 356 |
1 files changed, 168 insertions, 188 deletions
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index c28caf272c11..bea0914ff947 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
| @@ -19,100 +19,118 @@ DEFINE_MUTEX(pnp_res_mutex); | |||
| 19 | 19 | ||
| 20 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) | 20 | static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx) |
| 21 | { | 21 | { |
| 22 | resource_size_t *start, *end; | 22 | struct pnp_resource *pnp_res; |
| 23 | unsigned long *flags; | 23 | struct resource *res; |
| 24 | 24 | ||
| 25 | if (idx >= PNP_MAX_PORT) { | 25 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IO, idx); |
| 26 | if (!pnp_res) { | ||
| 26 | dev_err(&dev->dev, "too many I/O port resources\n"); | 27 | dev_err(&dev->dev, "too many I/O port resources\n"); |
| 27 | /* pretend we were successful so at least the manager won't try again */ | 28 | /* pretend we were successful so at least the manager won't try again */ |
| 28 | return 1; | 29 | return 1; |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 32 | res = &pnp_res->res; | ||
| 33 | |||
| 31 | /* check if this resource has been manually set, if so skip */ | 34 | /* check if this resource has been manually set, if so skip */ |
| 32 | if (!(dev->res.port_resource[idx].flags & IORESOURCE_AUTO)) | 35 | if (!(res->flags & IORESOURCE_AUTO)) { |
| 36 | dev_dbg(&dev->dev, " io %d already set to %#llx-%#llx " | ||
| 37 | "flags %#lx\n", idx, (unsigned long long) res->start, | ||
| 38 | (unsigned long long) res->end, res->flags); | ||
| 33 | return 1; | 39 | return 1; |
| 34 | 40 | } | |
| 35 | start = &dev->res.port_resource[idx].start; | ||
| 36 | end = &dev->res.port_resource[idx].end; | ||
| 37 | flags = &dev->res.port_resource[idx].flags; | ||
| 38 | 41 | ||
| 39 | /* set the initial values */ | 42 | /* set the initial values */ |
| 40 | *flags |= rule->flags | IORESOURCE_IO; | 43 | pnp_res->index = idx; |
| 41 | *flags &= ~IORESOURCE_UNSET; | 44 | res->flags |= rule->flags | IORESOURCE_IO; |
| 45 | res->flags &= ~IORESOURCE_UNSET; | ||
| 42 | 46 | ||
| 43 | if (!rule->size) { | 47 | if (!rule->size) { |
| 44 | *flags |= IORESOURCE_DISABLED; | 48 | res->flags |= IORESOURCE_DISABLED; |
| 49 | dev_dbg(&dev->dev, " io %d disabled\n", idx); | ||
| 45 | return 1; /* skip disabled resource requests */ | 50 | return 1; /* skip disabled resource requests */ |
| 46 | } | 51 | } |
| 47 | 52 | ||
| 48 | *start = rule->min; | 53 | res->start = rule->min; |
| 49 | *end = *start + rule->size - 1; | 54 | res->end = res->start + rule->size - 1; |
| 50 | 55 | ||
| 51 | /* run through until pnp_check_port is happy */ | 56 | /* run through until pnp_check_port is happy */ |
| 52 | while (!pnp_check_port(dev, idx)) { | 57 | while (!pnp_check_port(dev, res)) { |
| 53 | *start += rule->align; | 58 | res->start += rule->align; |
| 54 | *end = *start + rule->size - 1; | 59 | res->end = res->start + rule->size - 1; |
| 55 | if (*start > rule->max || !rule->align) | 60 | if (res->start > rule->max || !rule->align) { |
| 61 | dev_dbg(&dev->dev, " couldn't assign io %d\n", idx); | ||
| 56 | return 0; | 62 | return 0; |
| 63 | } | ||
| 57 | } | 64 | } |
| 65 | dev_dbg(&dev->dev, " assign io %d %#llx-%#llx\n", idx, | ||
| 66 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
| 58 | return 1; | 67 | return 1; |
| 59 | } | 68 | } |
| 60 | 69 | ||
| 61 | static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) | 70 | static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx) |
| 62 | { | 71 | { |
| 63 | resource_size_t *start, *end; | 72 | struct pnp_resource *pnp_res; |
| 64 | unsigned long *flags; | 73 | struct resource *res; |
| 65 | 74 | ||
| 66 | if (idx >= PNP_MAX_MEM) { | 75 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_MEM, idx); |
| 76 | if (!pnp_res) { | ||
| 67 | dev_err(&dev->dev, "too many memory resources\n"); | 77 | dev_err(&dev->dev, "too many memory resources\n"); |
| 68 | /* pretend we were successful so at least the manager won't try again */ | 78 | /* pretend we were successful so at least the manager won't try again */ |
| 69 | return 1; | 79 | return 1; |
| 70 | } | 80 | } |
| 71 | 81 | ||
| 82 | res = &pnp_res->res; | ||
| 83 | |||
| 72 | /* check if this resource has been manually set, if so skip */ | 84 | /* check if this resource has been manually set, if so skip */ |
| 73 | if (!(dev->res.mem_resource[idx].flags & IORESOURCE_AUTO)) | 85 | if (!(res->flags & IORESOURCE_AUTO)) { |
| 86 | dev_dbg(&dev->dev, " mem %d already set to %#llx-%#llx " | ||
| 87 | "flags %#lx\n", idx, (unsigned long long) res->start, | ||
| 88 | (unsigned long long) res->end, res->flags); | ||
| 74 | return 1; | 89 | return 1; |
| 75 | 90 | } | |
| 76 | start = &dev->res.mem_resource[idx].start; | ||
| 77 | end = &dev->res.mem_resource[idx].end; | ||
| 78 | flags = &dev->res.mem_resource[idx].flags; | ||
| 79 | 91 | ||
| 80 | /* set the initial values */ | 92 | /* set the initial values */ |
| 81 | *flags |= rule->flags | IORESOURCE_MEM; | 93 | pnp_res->index = idx; |
| 82 | *flags &= ~IORESOURCE_UNSET; | 94 | res->flags |= rule->flags | IORESOURCE_MEM; |
| 95 | res->flags &= ~IORESOURCE_UNSET; | ||
| 83 | 96 | ||
| 84 | /* convert pnp flags to standard Linux flags */ | 97 | /* convert pnp flags to standard Linux flags */ |
| 85 | if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) | 98 | if (!(rule->flags & IORESOURCE_MEM_WRITEABLE)) |
| 86 | *flags |= IORESOURCE_READONLY; | 99 | res->flags |= IORESOURCE_READONLY; |
| 87 | if (rule->flags & IORESOURCE_MEM_CACHEABLE) | 100 | if (rule->flags & IORESOURCE_MEM_CACHEABLE) |
| 88 | *flags |= IORESOURCE_CACHEABLE; | 101 | res->flags |= IORESOURCE_CACHEABLE; |
| 89 | if (rule->flags & IORESOURCE_MEM_RANGELENGTH) | 102 | if (rule->flags & IORESOURCE_MEM_RANGELENGTH) |
| 90 | *flags |= IORESOURCE_RANGELENGTH; | 103 | res->flags |= IORESOURCE_RANGELENGTH; |
| 91 | if (rule->flags & IORESOURCE_MEM_SHADOWABLE) | 104 | if (rule->flags & IORESOURCE_MEM_SHADOWABLE) |
| 92 | *flags |= IORESOURCE_SHADOWABLE; | 105 | res->flags |= IORESOURCE_SHADOWABLE; |
| 93 | 106 | ||
| 94 | if (!rule->size) { | 107 | if (!rule->size) { |
| 95 | *flags |= IORESOURCE_DISABLED; | 108 | res->flags |= IORESOURCE_DISABLED; |
| 109 | dev_dbg(&dev->dev, " mem %d disabled\n", idx); | ||
| 96 | return 1; /* skip disabled resource requests */ | 110 | return 1; /* skip disabled resource requests */ |
| 97 | } | 111 | } |
| 98 | 112 | ||
| 99 | *start = rule->min; | 113 | res->start = rule->min; |
| 100 | *end = *start + rule->size - 1; | 114 | res->end = res->start + rule->size - 1; |
| 101 | 115 | ||
| 102 | /* run through until pnp_check_mem is happy */ | 116 | /* run through until pnp_check_mem is happy */ |
| 103 | while (!pnp_check_mem(dev, idx)) { | 117 | while (!pnp_check_mem(dev, res)) { |
| 104 | *start += rule->align; | 118 | res->start += rule->align; |
| 105 | *end = *start + rule->size - 1; | 119 | res->end = res->start + rule->size - 1; |
| 106 | if (*start > rule->max || !rule->align) | 120 | if (res->start > rule->max || !rule->align) { |
| 121 | dev_dbg(&dev->dev, " couldn't assign mem %d\n", idx); | ||
| 107 | return 0; | 122 | return 0; |
| 123 | } | ||
| 108 | } | 124 | } |
| 125 | dev_dbg(&dev->dev, " assign mem %d %#llx-%#llx\n", idx, | ||
| 126 | (unsigned long long) res->start, (unsigned long long) res->end); | ||
| 109 | return 1; | 127 | return 1; |
| 110 | } | 128 | } |
| 111 | 129 | ||
| 112 | static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) | 130 | static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) |
| 113 | { | 131 | { |
| 114 | resource_size_t *start, *end; | 132 | struct pnp_resource *pnp_res; |
| 115 | unsigned long *flags; | 133 | struct resource *res; |
| 116 | int i; | 134 | int i; |
| 117 | 135 | ||
| 118 | /* IRQ priority: this table is good for i386 */ | 136 | /* IRQ priority: this table is good for i386 */ |
| @@ -120,49 +138,59 @@ static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx) | |||
| 120 | 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 | 138 | 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2 |
| 121 | }; | 139 | }; |
| 122 | 140 | ||
| 123 | if (idx >= PNP_MAX_IRQ) { | 141 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_IRQ, idx); |
| 142 | if (!pnp_res) { | ||
| 124 | dev_err(&dev->dev, "too many IRQ resources\n"); | 143 | dev_err(&dev->dev, "too many IRQ resources\n"); |
| 125 | /* pretend we were successful so at least the manager won't try again */ | 144 | /* pretend we were successful so at least the manager won't try again */ |
| 126 | return 1; | 145 | return 1; |
| 127 | } | 146 | } |
| 128 | 147 | ||
| 148 | res = &pnp_res->res; | ||
| 149 | |||
| 129 | /* check if this resource has been manually set, if so skip */ | 150 | /* check if this resource has been manually set, if so skip */ |
| 130 | if (!(dev->res.irq_resource[idx].flags & IORESOURCE_AUTO)) | 151 | if (!(res->flags & IORESOURCE_AUTO)) { |
| 152 | dev_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n", | ||
| 153 | idx, (int) res->start, res->flags); | ||
| 131 | return 1; | 154 | return 1; |
| 132 | 155 | } | |
| 133 | start = &dev->res.irq_resource[idx].start; | ||
| 134 | end = &dev->res.irq_resource[idx].end; | ||
| 135 | flags = &dev->res.irq_resource[idx].flags; | ||
| 136 | 156 | ||
| 137 | /* set the initial values */ | 157 | /* set the initial values */ |
| 138 | *flags |= rule->flags | IORESOURCE_IRQ; | 158 | pnp_res->index = idx; |
| 139 | *flags &= ~IORESOURCE_UNSET; | 159 | res->flags |= rule->flags | IORESOURCE_IRQ; |
| 160 | res->flags &= ~IORESOURCE_UNSET; | ||
| 140 | 161 | ||
| 141 | if (bitmap_empty(rule->map, PNP_IRQ_NR)) { | 162 | if (bitmap_empty(rule->map, PNP_IRQ_NR)) { |
| 142 | *flags |= IORESOURCE_DISABLED; | 163 | res->flags |= IORESOURCE_DISABLED; |
| 164 | dev_dbg(&dev->dev, " irq %d disabled\n", idx); | ||
| 143 | return 1; /* skip disabled resource requests */ | 165 | return 1; /* skip disabled resource requests */ |
| 144 | } | 166 | } |
| 145 | 167 | ||
| 146 | /* TBD: need check for >16 IRQ */ | 168 | /* TBD: need check for >16 IRQ */ |
| 147 | *start = find_next_bit(rule->map, PNP_IRQ_NR, 16); | 169 | res->start = find_next_bit(rule->map, PNP_IRQ_NR, 16); |
| 148 | if (*start < PNP_IRQ_NR) { | 170 | if (res->start < PNP_IRQ_NR) { |
| 149 | *end = *start; | 171 | res->end = res->start; |
| 172 | dev_dbg(&dev->dev, " assign irq %d %d\n", idx, | ||
| 173 | (int) res->start); | ||
| 150 | return 1; | 174 | return 1; |
| 151 | } | 175 | } |
| 152 | for (i = 0; i < 16; i++) { | 176 | for (i = 0; i < 16; i++) { |
| 153 | if (test_bit(xtab[i], rule->map)) { | 177 | if (test_bit(xtab[i], rule->map)) { |
| 154 | *start = *end = xtab[i]; | 178 | res->start = res->end = xtab[i]; |
| 155 | if (pnp_check_irq(dev, idx)) | 179 | if (pnp_check_irq(dev, res)) { |
| 180 | dev_dbg(&dev->dev, " assign irq %d %d\n", idx, | ||
| 181 | (int) res->start); | ||
| 156 | return 1; | 182 | return 1; |
| 183 | } | ||
| 157 | } | 184 | } |
| 158 | } | 185 | } |
| 186 | dev_dbg(&dev->dev, " couldn't assign irq %d\n", idx); | ||
| 159 | return 0; | 187 | return 0; |
| 160 | } | 188 | } |
| 161 | 189 | ||
| 162 | static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) | 190 | static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) |
| 163 | { | 191 | { |
| 164 | resource_size_t *start, *end; | 192 | struct pnp_resource *pnp_res; |
| 165 | unsigned long *flags; | 193 | struct resource *res; |
| 166 | int i; | 194 | int i; |
| 167 | 195 | ||
| 168 | /* DMA priority: this table is good for i386 */ | 196 | /* DMA priority: this table is good for i386 */ |
| @@ -170,71 +198,89 @@ static void pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx) | |||
| 170 | 1, 3, 5, 6, 7, 0, 2, 4 | 198 | 1, 3, 5, 6, 7, 0, 2, 4 |
| 171 | }; | 199 | }; |
| 172 | 200 | ||
| 173 | if (idx >= PNP_MAX_DMA) { | 201 | pnp_res = pnp_get_pnp_resource(dev, IORESOURCE_DMA, idx); |
| 202 | if (!pnp_res) { | ||
| 174 | dev_err(&dev->dev, "too many DMA resources\n"); | 203 | dev_err(&dev->dev, "too many DMA resources\n"); |
| 175 | return; | 204 | return; |
| 176 | } | 205 | } |
| 177 | 206 | ||
| 207 | res = &pnp_res->res; | ||
| 208 | |||
| 178 | /* check if this resource has been manually set, if so skip */ | 209 | /* check if this resource has been manually set, if so skip */ |
| 179 | if (!(dev->res.dma_resource[idx].flags & IORESOURCE_AUTO)) | 210 | if (!(res->flags & IORESOURCE_AUTO)) { |
| 211 | dev_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n", | ||
| 212 | idx, (int) res->start, res->flags); | ||
| 180 | return; | 213 | return; |
| 181 | 214 | } | |
| 182 | start = &dev->res.dma_resource[idx].start; | ||
| 183 | end = &dev->res.dma_resource[idx].end; | ||
| 184 | flags = &dev->res.dma_resource[idx].flags; | ||
| 185 | 215 | ||
| 186 | /* set the initial values */ | 216 | /* set the initial values */ |
| 187 | *flags |= rule->flags | IORESOURCE_DMA; | 217 | pnp_res->index = idx; |
| 188 | *flags &= ~IORESOURCE_UNSET; | 218 | res->flags |= rule->flags | IORESOURCE_DMA; |
| 219 | res->flags &= ~IORESOURCE_UNSET; | ||
| 189 | 220 | ||
| 190 | for (i = 0; i < 8; i++) { | 221 | for (i = 0; i < 8; i++) { |
| 191 | if (rule->map & (1 << xtab[i])) { | 222 | if (rule->map & (1 << xtab[i])) { |
| 192 | *start = *end = xtab[i]; | 223 | res->start = res->end = xtab[i]; |
| 193 | if (pnp_check_dma(dev, idx)) | 224 | if (pnp_check_dma(dev, res)) { |
| 225 | dev_dbg(&dev->dev, " assign dma %d %d\n", idx, | ||
| 226 | (int) res->start); | ||
| 194 | return; | 227 | return; |
| 228 | } | ||
| 195 | } | 229 | } |
| 196 | } | 230 | } |
| 197 | #ifdef MAX_DMA_CHANNELS | 231 | #ifdef MAX_DMA_CHANNELS |
| 198 | *start = *end = MAX_DMA_CHANNELS; | 232 | res->start = res->end = MAX_DMA_CHANNELS; |
| 199 | #endif | 233 | #endif |
| 200 | *flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; | 234 | res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; |
| 235 | dev_dbg(&dev->dev, " disable dma %d\n", idx); | ||
| 236 | } | ||
| 237 | |||
| 238 | void pnp_init_resource(struct resource *res) | ||
| 239 | { | ||
| 240 | unsigned long type; | ||
| 241 | |||
| 242 | type = res->flags & (IORESOURCE_IO | IORESOURCE_MEM | | ||
| 243 | IORESOURCE_IRQ | IORESOURCE_DMA); | ||
| 244 | |||
| 245 | res->name = NULL; | ||
| 246 | res->flags = type | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 247 | if (type == IORESOURCE_IRQ || type == IORESOURCE_DMA) { | ||
| 248 | res->start = -1; | ||
| 249 | res->end = -1; | ||
| 250 | } else { | ||
| 251 | res->start = 0; | ||
| 252 | res->end = 0; | ||
| 253 | } | ||
| 201 | } | 254 | } |
| 202 | 255 | ||
| 203 | /** | 256 | /** |
| 204 | * pnp_init_resources - Resets a resource table to default values. | 257 | * pnp_init_resources - Resets a resource table to default values. |
| 205 | * @table: pointer to the desired resource table | 258 | * @table: pointer to the desired resource table |
| 206 | */ | 259 | */ |
| 207 | void pnp_init_resource_table(struct pnp_resource_table *table) | 260 | void pnp_init_resources(struct pnp_dev *dev) |
| 208 | { | 261 | { |
| 262 | struct resource *res; | ||
| 209 | int idx; | 263 | int idx; |
| 210 | 264 | ||
| 211 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { | 265 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { |
| 212 | table->irq_resource[idx].name = NULL; | 266 | res = &dev->res->irq[idx].res; |
| 213 | table->irq_resource[idx].start = -1; | 267 | res->flags = IORESOURCE_IRQ; |
| 214 | table->irq_resource[idx].end = -1; | 268 | pnp_init_resource(res); |
| 215 | table->irq_resource[idx].flags = | ||
| 216 | IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 217 | } | 269 | } |
| 218 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { | 270 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { |
| 219 | table->dma_resource[idx].name = NULL; | 271 | res = &dev->res->dma[idx].res; |
| 220 | table->dma_resource[idx].start = -1; | 272 | res->flags = IORESOURCE_DMA; |
| 221 | table->dma_resource[idx].end = -1; | 273 | pnp_init_resource(res); |
| 222 | table->dma_resource[idx].flags = | ||
| 223 | IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 224 | } | 274 | } |
| 225 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { | 275 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { |
| 226 | table->port_resource[idx].name = NULL; | 276 | res = &dev->res->port[idx].res; |
| 227 | table->port_resource[idx].start = 0; | 277 | res->flags = IORESOURCE_IO; |
| 228 | table->port_resource[idx].end = 0; | 278 | pnp_init_resource(res); |
| 229 | table->port_resource[idx].flags = | ||
| 230 | IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 231 | } | 279 | } |
| 232 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { | 280 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { |
| 233 | table->mem_resource[idx].name = NULL; | 281 | res = &dev->res->mem[idx].res; |
| 234 | table->mem_resource[idx].start = 0; | 282 | res->flags = IORESOURCE_MEM; |
| 235 | table->mem_resource[idx].end = 0; | 283 | pnp_init_resource(res); |
| 236 | table->mem_resource[idx].flags = | ||
| 237 | IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 238 | } | 284 | } |
| 239 | } | 285 | } |
| 240 | 286 | ||
| @@ -242,41 +288,38 @@ void pnp_init_resource_table(struct pnp_resource_table *table) | |||
| 242 | * pnp_clean_resources - clears resources that were not manually set | 288 | * pnp_clean_resources - clears resources that were not manually set |
| 243 | * @res: the resources to clean | 289 | * @res: the resources to clean |
| 244 | */ | 290 | */ |
| 245 | static void pnp_clean_resource_table(struct pnp_resource_table *res) | 291 | static void pnp_clean_resource_table(struct pnp_dev *dev) |
| 246 | { | 292 | { |
| 293 | struct resource *res; | ||
| 247 | int idx; | 294 | int idx; |
| 248 | 295 | ||
| 249 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { | 296 | for (idx = 0; idx < PNP_MAX_IRQ; idx++) { |
| 250 | if (!(res->irq_resource[idx].flags & IORESOURCE_AUTO)) | 297 | res = &dev->res->irq[idx].res; |
| 251 | continue; | 298 | if (res->flags & IORESOURCE_AUTO) { |
| 252 | res->irq_resource[idx].start = -1; | 299 | res->flags = IORESOURCE_IRQ; |
| 253 | res->irq_resource[idx].end = -1; | 300 | pnp_init_resource(res); |
| 254 | res->irq_resource[idx].flags = | 301 | } |
| 255 | IORESOURCE_IRQ | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 256 | } | 302 | } |
| 257 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { | 303 | for (idx = 0; idx < PNP_MAX_DMA; idx++) { |
| 258 | if (!(res->dma_resource[idx].flags & IORESOURCE_AUTO)) | 304 | res = &dev->res->dma[idx].res; |
| 259 | continue; | 305 | if (res->flags & IORESOURCE_AUTO) { |
| 260 | res->dma_resource[idx].start = -1; | 306 | res->flags = IORESOURCE_DMA; |
| 261 | res->dma_resource[idx].end = -1; | 307 | pnp_init_resource(res); |
| 262 | res->dma_resource[idx].flags = | 308 | } |
| 263 | IORESOURCE_DMA | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 264 | } | 309 | } |
| 265 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { | 310 | for (idx = 0; idx < PNP_MAX_PORT; idx++) { |
| 266 | if (!(res->port_resource[idx].flags & IORESOURCE_AUTO)) | 311 | res = &dev->res->port[idx].res; |
| 267 | continue; | 312 | if (res->flags & IORESOURCE_AUTO) { |
| 268 | res->port_resource[idx].start = 0; | 313 | res->flags = IORESOURCE_IO; |
| 269 | res->port_resource[idx].end = 0; | 314 | pnp_init_resource(res); |
| 270 | res->port_resource[idx].flags = | 315 | } |
| 271 | IORESOURCE_IO | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 272 | } | 316 | } |
| 273 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { | 317 | for (idx = 0; idx < PNP_MAX_MEM; idx++) { |
| 274 | if (!(res->mem_resource[idx].flags & IORESOURCE_AUTO)) | 318 | res = &dev->res->mem[idx].res; |
| 275 | continue; | 319 | if (res->flags & IORESOURCE_AUTO) { |
| 276 | res->mem_resource[idx].start = 0; | 320 | res->flags = IORESOURCE_MEM; |
| 277 | res->mem_resource[idx].end = 0; | 321 | pnp_init_resource(res); |
| 278 | res->mem_resource[idx].flags = | 322 | } |
| 279 | IORESOURCE_MEM | IORESOURCE_AUTO | IORESOURCE_UNSET; | ||
| 280 | } | 323 | } |
| 281 | } | 324 | } |
| 282 | 325 | ||
| @@ -298,9 +341,11 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
| 298 | if (!pnp_can_configure(dev)) | 341 | if (!pnp_can_configure(dev)) |
| 299 | return -ENODEV; | 342 | return -ENODEV; |
| 300 | 343 | ||
| 344 | dbg_pnp_show_resources(dev, "before pnp_assign_resources"); | ||
| 301 | mutex_lock(&pnp_res_mutex); | 345 | mutex_lock(&pnp_res_mutex); |
| 302 | pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ | 346 | pnp_clean_resource_table(dev); |
| 303 | if (dev->independent) { | 347 | if (dev->independent) { |
| 348 | dev_dbg(&dev->dev, "assigning independent options\n"); | ||
| 304 | port = dev->independent->port; | 349 | port = dev->independent->port; |
| 305 | mem = dev->independent->mem; | 350 | mem = dev->independent->mem; |
| 306 | irq = dev->independent->irq; | 351 | irq = dev->independent->irq; |
| @@ -333,6 +378,8 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
| 333 | if (depnum) { | 378 | if (depnum) { |
| 334 | struct pnp_option *dep; | 379 | struct pnp_option *dep; |
| 335 | int i; | 380 | int i; |
| 381 | |||
| 382 | dev_dbg(&dev->dev, "assigning dependent option %d\n", depnum); | ||
| 336 | for (i = 1, dep = dev->dependent; i < depnum; | 383 | for (i = 1, dep = dev->dependent; i < depnum; |
| 337 | i++, dep = dep->next) | 384 | i++, dep = dep->next) |
| 338 | if (!dep) | 385 | if (!dep) |
| @@ -368,68 +415,17 @@ static int pnp_assign_resources(struct pnp_dev *dev, int depnum) | |||
| 368 | goto fail; | 415 | goto fail; |
| 369 | 416 | ||
| 370 | mutex_unlock(&pnp_res_mutex); | 417 | mutex_unlock(&pnp_res_mutex); |
| 418 | dbg_pnp_show_resources(dev, "after pnp_assign_resources"); | ||
| 371 | return 1; | 419 | return 1; |
| 372 | 420 | ||
| 373 | fail: | 421 | fail: |
| 374 | pnp_clean_resource_table(&dev->res); | 422 | pnp_clean_resource_table(dev); |
| 375 | mutex_unlock(&pnp_res_mutex); | 423 | mutex_unlock(&pnp_res_mutex); |
| 424 | dbg_pnp_show_resources(dev, "after pnp_assign_resources (failed)"); | ||
| 376 | return 0; | 425 | return 0; |
| 377 | } | 426 | } |
| 378 | 427 | ||
| 379 | /** | 428 | /** |
| 380 | * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table | ||
| 381 | * @dev: pointer to the desired device | ||
| 382 | * @res: pointer to the new resource config | ||
| 383 | * @mode: 0 or PNP_CONFIG_FORCE | ||
| 384 | * | ||
| 385 | * This function can be used by drivers that want to manually set thier resources. | ||
| 386 | */ | ||
| 387 | int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, | ||
| 388 | int mode) | ||
| 389 | { | ||
| 390 | int i; | ||
| 391 | struct pnp_resource_table *bak; | ||
| 392 | |||
| 393 | if (!pnp_can_configure(dev)) | ||
| 394 | return -ENODEV; | ||
| 395 | bak = pnp_alloc(sizeof(struct pnp_resource_table)); | ||
| 396 | if (!bak) | ||
| 397 | return -ENOMEM; | ||
| 398 | *bak = dev->res; | ||
| 399 | |||
| 400 | mutex_lock(&pnp_res_mutex); | ||
| 401 | dev->res = *res; | ||
| 402 | if (!(mode & PNP_CONFIG_FORCE)) { | ||
| 403 | for (i = 0; i < PNP_MAX_PORT; i++) { | ||
| 404 | if (!pnp_check_port(dev, i)) | ||
| 405 | goto fail; | ||
| 406 | } | ||
| 407 | for (i = 0; i < PNP_MAX_MEM; i++) { | ||
| 408 | if (!pnp_check_mem(dev, i)) | ||
| 409 | goto fail; | ||
| 410 | } | ||
| 411 | for (i = 0; i < PNP_MAX_IRQ; i++) { | ||
| 412 | if (!pnp_check_irq(dev, i)) | ||
| 413 | goto fail; | ||
| 414 | } | ||
| 415 | for (i = 0; i < PNP_MAX_DMA; i++) { | ||
| 416 | if (!pnp_check_dma(dev, i)) | ||
| 417 | goto fail; | ||
| 418 | } | ||
| 419 | } | ||
| 420 | mutex_unlock(&pnp_res_mutex); | ||
| 421 | |||
| 422 | kfree(bak); | ||
| 423 | return 0; | ||
| 424 | |||
| 425 | fail: | ||
| 426 | dev->res = *bak; | ||
| 427 | mutex_unlock(&pnp_res_mutex); | ||
| 428 | kfree(bak); | ||
| 429 | return -EINVAL; | ||
| 430 | } | ||
| 431 | |||
| 432 | /** | ||
| 433 | * pnp_auto_config_dev - automatically assigns resources to a device | 429 | * pnp_auto_config_dev - automatically assigns resources to a device |
| 434 | * @dev: pointer to the desired device | 430 | * @dev: pointer to the desired device |
| 435 | */ | 431 | */ |
| @@ -473,7 +469,8 @@ int pnp_start_dev(struct pnp_dev *dev) | |||
| 473 | return -EINVAL; | 469 | return -EINVAL; |
| 474 | } | 470 | } |
| 475 | 471 | ||
| 476 | if (dev->protocol->set(dev, &dev->res) < 0) { | 472 | dbg_pnp_show_resources(dev, "pnp_start_dev"); |
| 473 | if (dev->protocol->set(dev) < 0) { | ||
| 477 | dev_err(&dev->dev, "activation failed\n"); | 474 | dev_err(&dev->dev, "activation failed\n"); |
| 478 | return -EIO; | 475 | return -EIO; |
| 479 | } | 476 | } |
| @@ -549,30 +546,13 @@ int pnp_disable_dev(struct pnp_dev *dev) | |||
| 549 | 546 | ||
| 550 | /* release the resources so that other devices can use them */ | 547 | /* release the resources so that other devices can use them */ |
| 551 | mutex_lock(&pnp_res_mutex); | 548 | mutex_lock(&pnp_res_mutex); |
| 552 | pnp_clean_resource_table(&dev->res); | 549 | pnp_clean_resource_table(dev); |
| 553 | mutex_unlock(&pnp_res_mutex); | 550 | mutex_unlock(&pnp_res_mutex); |
| 554 | 551 | ||
| 555 | return 0; | 552 | return 0; |
| 556 | } | 553 | } |
| 557 | 554 | ||
| 558 | /** | ||
| 559 | * pnp_resource_change - change one resource | ||
| 560 | * @resource: pointer to resource to be changed | ||
| 561 | * @start: start of region | ||
| 562 | * @size: size of region | ||
| 563 | */ | ||
| 564 | void pnp_resource_change(struct resource *resource, resource_size_t start, | ||
| 565 | resource_size_t size) | ||
| 566 | { | ||
| 567 | resource->flags &= ~(IORESOURCE_AUTO | IORESOURCE_UNSET); | ||
| 568 | resource->start = start; | ||
| 569 | resource->end = start + size - 1; | ||
| 570 | } | ||
| 571 | |||
| 572 | EXPORT_SYMBOL(pnp_manual_config_dev); | ||
| 573 | EXPORT_SYMBOL(pnp_start_dev); | 555 | EXPORT_SYMBOL(pnp_start_dev); |
| 574 | EXPORT_SYMBOL(pnp_stop_dev); | 556 | EXPORT_SYMBOL(pnp_stop_dev); |
| 575 | EXPORT_SYMBOL(pnp_activate_dev); | 557 | EXPORT_SYMBOL(pnp_activate_dev); |
| 576 | EXPORT_SYMBOL(pnp_disable_dev); | 558 | EXPORT_SYMBOL(pnp_disable_dev); |
| 577 | EXPORT_SYMBOL(pnp_resource_change); | ||
| 578 | EXPORT_SYMBOL(pnp_init_resource_table); | ||
