0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/errno.h>
0012 #include <linux/module.h>
0013 #include <linux/init.h>
0014 #include <linux/kernel.h>
0015 #include <linux/pnp.h>
0016 #include <linux/bitmap.h>
0017 #include <linux/mutex.h>
0018 #include "base.h"
0019
0020 DEFINE_MUTEX(pnp_res_mutex);
0021
0022 static struct resource *pnp_find_resource(struct pnp_dev *dev,
0023 unsigned char rule,
0024 unsigned long type,
0025 unsigned int bar)
0026 {
0027 struct resource *res = pnp_get_resource(dev, type, bar);
0028
0029
0030 if (res) {
0031 res->flags &= ~IORESOURCE_BITS;
0032 res->flags |= rule & IORESOURCE_BITS;
0033 }
0034
0035 return res;
0036 }
0037
0038 static int pnp_assign_port(struct pnp_dev *dev, struct pnp_port *rule, int idx)
0039 {
0040 struct resource *res, local_res;
0041
0042 res = pnp_find_resource(dev, rule->flags, IORESOURCE_IO, idx);
0043 if (res) {
0044 pnp_dbg(&dev->dev, " io %d already set to %#llx-%#llx "
0045 "flags %#lx\n", idx, (unsigned long long) res->start,
0046 (unsigned long long) res->end, res->flags);
0047 return 0;
0048 }
0049
0050 res = &local_res;
0051 res->flags = rule->flags | IORESOURCE_AUTO;
0052 res->start = 0;
0053 res->end = 0;
0054
0055 if (!rule->size) {
0056 res->flags |= IORESOURCE_DISABLED;
0057 pnp_dbg(&dev->dev, " io %d disabled\n", idx);
0058 goto __add;
0059 }
0060
0061 res->start = rule->min;
0062 res->end = res->start + rule->size - 1;
0063
0064 while (!pnp_check_port(dev, res)) {
0065 res->start += rule->align;
0066 res->end = res->start + rule->size - 1;
0067 if (res->start > rule->max || !rule->align) {
0068 pnp_dbg(&dev->dev, " couldn't assign io %d "
0069 "(min %#llx max %#llx)\n", idx,
0070 (unsigned long long) rule->min,
0071 (unsigned long long) rule->max);
0072 return -EBUSY;
0073 }
0074 }
0075
0076 __add:
0077 pnp_add_io_resource(dev, res->start, res->end, res->flags);
0078 return 0;
0079 }
0080
0081 static int pnp_assign_mem(struct pnp_dev *dev, struct pnp_mem *rule, int idx)
0082 {
0083 struct resource *res, local_res;
0084
0085 res = pnp_find_resource(dev, rule->flags, IORESOURCE_MEM, idx);
0086 if (res) {
0087 pnp_dbg(&dev->dev, " mem %d already set to %#llx-%#llx "
0088 "flags %#lx\n", idx, (unsigned long long) res->start,
0089 (unsigned long long) res->end, res->flags);
0090 return 0;
0091 }
0092
0093 res = &local_res;
0094 res->flags = rule->flags | IORESOURCE_AUTO;
0095 res->start = 0;
0096 res->end = 0;
0097
0098
0099 if (!(rule->flags & IORESOURCE_MEM_WRITEABLE))
0100 res->flags |= IORESOURCE_READONLY;
0101 if (rule->flags & IORESOURCE_MEM_RANGELENGTH)
0102 res->flags |= IORESOURCE_RANGELENGTH;
0103 if (rule->flags & IORESOURCE_MEM_SHADOWABLE)
0104 res->flags |= IORESOURCE_SHADOWABLE;
0105
0106 if (!rule->size) {
0107 res->flags |= IORESOURCE_DISABLED;
0108 pnp_dbg(&dev->dev, " mem %d disabled\n", idx);
0109 goto __add;
0110 }
0111
0112 res->start = rule->min;
0113 res->end = res->start + rule->size - 1;
0114
0115 while (!pnp_check_mem(dev, res)) {
0116 res->start += rule->align;
0117 res->end = res->start + rule->size - 1;
0118 if (res->start > rule->max || !rule->align) {
0119 pnp_dbg(&dev->dev, " couldn't assign mem %d "
0120 "(min %#llx max %#llx)\n", idx,
0121 (unsigned long long) rule->min,
0122 (unsigned long long) rule->max);
0123 return -EBUSY;
0124 }
0125 }
0126
0127 __add:
0128 pnp_add_mem_resource(dev, res->start, res->end, res->flags);
0129 return 0;
0130 }
0131
0132 static int pnp_assign_irq(struct pnp_dev *dev, struct pnp_irq *rule, int idx)
0133 {
0134 struct resource *res, local_res;
0135 int i;
0136
0137
0138 static unsigned short xtab[16] = {
0139 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
0140 };
0141
0142 res = pnp_find_resource(dev, rule->flags, IORESOURCE_IRQ, idx);
0143 if (res) {
0144 pnp_dbg(&dev->dev, " irq %d already set to %d flags %#lx\n",
0145 idx, (int) res->start, res->flags);
0146 return 0;
0147 }
0148
0149 res = &local_res;
0150 res->flags = rule->flags | IORESOURCE_AUTO;
0151 res->start = -1;
0152 res->end = -1;
0153
0154 if (bitmap_empty(rule->map.bits, PNP_IRQ_NR)) {
0155 res->flags |= IORESOURCE_DISABLED;
0156 pnp_dbg(&dev->dev, " irq %d disabled\n", idx);
0157 goto __add;
0158 }
0159
0160
0161 res->start = find_next_bit(rule->map.bits, PNP_IRQ_NR, 16);
0162 if (res->start < PNP_IRQ_NR) {
0163 res->end = res->start;
0164 goto __add;
0165 }
0166 for (i = 0; i < 16; i++) {
0167 if (test_bit(xtab[i], rule->map.bits)) {
0168 res->start = res->end = xtab[i];
0169 if (pnp_check_irq(dev, res))
0170 goto __add;
0171 }
0172 }
0173
0174 if (rule->flags & IORESOURCE_IRQ_OPTIONAL) {
0175 res->start = -1;
0176 res->end = -1;
0177 res->flags |= IORESOURCE_DISABLED;
0178 pnp_dbg(&dev->dev, " irq %d disabled (optional)\n", idx);
0179 goto __add;
0180 }
0181
0182 pnp_dbg(&dev->dev, " couldn't assign irq %d\n", idx);
0183 return -EBUSY;
0184
0185 __add:
0186 pnp_add_irq_resource(dev, res->start, res->flags);
0187 return 0;
0188 }
0189
0190 #ifdef CONFIG_ISA_DMA_API
0191 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
0192 {
0193 struct resource *res, local_res;
0194 int i;
0195
0196
0197 static unsigned short xtab[8] = {
0198 1, 3, 5, 6, 7, 0, 2, 4
0199 };
0200
0201 res = pnp_find_resource(dev, rule->flags, IORESOURCE_DMA, idx);
0202 if (res) {
0203 pnp_dbg(&dev->dev, " dma %d already set to %d flags %#lx\n",
0204 idx, (int) res->start, res->flags);
0205 return 0;
0206 }
0207
0208 res = &local_res;
0209 res->flags = rule->flags | IORESOURCE_AUTO;
0210 res->start = -1;
0211 res->end = -1;
0212
0213 if (!rule->map) {
0214 res->flags |= IORESOURCE_DISABLED;
0215 pnp_dbg(&dev->dev, " dma %d disabled\n", idx);
0216 goto __add;
0217 }
0218
0219 for (i = 0; i < 8; i++) {
0220 if (rule->map & (1 << xtab[i])) {
0221 res->start = res->end = xtab[i];
0222 if (pnp_check_dma(dev, res))
0223 goto __add;
0224 }
0225 }
0226
0227 pnp_dbg(&dev->dev, " couldn't assign dma %d\n", idx);
0228 return -EBUSY;
0229
0230 __add:
0231 pnp_add_dma_resource(dev, res->start, res->flags);
0232 return 0;
0233 }
0234 #endif
0235
0236 void pnp_init_resources(struct pnp_dev *dev)
0237 {
0238 pnp_free_resources(dev);
0239 }
0240
0241 static void pnp_clean_resource_table(struct pnp_dev *dev)
0242 {
0243 struct pnp_resource *pnp_res, *tmp;
0244
0245 list_for_each_entry_safe(pnp_res, tmp, &dev->resources, list) {
0246 if (pnp_res->res.flags & IORESOURCE_AUTO)
0247 pnp_free_resource(pnp_res);
0248 }
0249 }
0250
0251
0252
0253
0254
0255
0256 static int pnp_assign_resources(struct pnp_dev *dev, int set)
0257 {
0258 struct pnp_option *option;
0259 int nport = 0, nmem = 0, nirq = 0;
0260 int ndma __maybe_unused = 0;
0261 int ret = 0;
0262
0263 pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
0264 mutex_lock(&pnp_res_mutex);
0265 pnp_clean_resource_table(dev);
0266
0267 list_for_each_entry(option, &dev->options, list) {
0268 if (pnp_option_is_dependent(option) &&
0269 pnp_option_set(option) != set)
0270 continue;
0271
0272 switch (option->type) {
0273 case IORESOURCE_IO:
0274 ret = pnp_assign_port(dev, &option->u.port, nport++);
0275 break;
0276 case IORESOURCE_MEM:
0277 ret = pnp_assign_mem(dev, &option->u.mem, nmem++);
0278 break;
0279 case IORESOURCE_IRQ:
0280 ret = pnp_assign_irq(dev, &option->u.irq, nirq++);
0281 break;
0282 #ifdef CONFIG_ISA_DMA_API
0283 case IORESOURCE_DMA:
0284 ret = pnp_assign_dma(dev, &option->u.dma, ndma++);
0285 break;
0286 #endif
0287 default:
0288 ret = -EINVAL;
0289 break;
0290 }
0291 if (ret < 0)
0292 break;
0293 }
0294
0295 mutex_unlock(&pnp_res_mutex);
0296 if (ret < 0) {
0297 pnp_dbg(&dev->dev, "pnp_assign_resources failed (%d)\n", ret);
0298 pnp_clean_resource_table(dev);
0299 } else
0300 dbg_pnp_show_resources(dev, "pnp_assign_resources succeeded");
0301 return ret;
0302 }
0303
0304
0305
0306
0307
0308 int pnp_auto_config_dev(struct pnp_dev *dev)
0309 {
0310 int i, ret;
0311
0312 if (!pnp_can_configure(dev)) {
0313 pnp_dbg(&dev->dev, "configuration not supported\n");
0314 return -ENODEV;
0315 }
0316
0317 ret = pnp_assign_resources(dev, 0);
0318 if (ret == 0)
0319 return 0;
0320
0321 for (i = 1; i < dev->num_dependent_sets; i++) {
0322 ret = pnp_assign_resources(dev, i);
0323 if (ret == 0)
0324 return 0;
0325 }
0326
0327 dev_err(&dev->dev, "unable to assign resources\n");
0328 return ret;
0329 }
0330
0331
0332
0333
0334
0335
0336
0337 int pnp_start_dev(struct pnp_dev *dev)
0338 {
0339 if (!pnp_can_write(dev)) {
0340 pnp_dbg(&dev->dev, "activation not supported\n");
0341 return -EINVAL;
0342 }
0343
0344 dbg_pnp_show_resources(dev, "pnp_start_dev");
0345 if (dev->protocol->set(dev) < 0) {
0346 dev_err(&dev->dev, "activation failed\n");
0347 return -EIO;
0348 }
0349
0350 dev_info(&dev->dev, "activated\n");
0351 return 0;
0352 }
0353 EXPORT_SYMBOL(pnp_start_dev);
0354
0355
0356
0357
0358
0359
0360
0361 int pnp_stop_dev(struct pnp_dev *dev)
0362 {
0363 if (!pnp_can_disable(dev)) {
0364 pnp_dbg(&dev->dev, "disabling not supported\n");
0365 return -EINVAL;
0366 }
0367 if (dev->protocol->disable(dev) < 0) {
0368 dev_err(&dev->dev, "disable failed\n");
0369 return -EIO;
0370 }
0371
0372 dev_info(&dev->dev, "disabled\n");
0373 return 0;
0374 }
0375 EXPORT_SYMBOL(pnp_stop_dev);
0376
0377
0378
0379
0380
0381
0382
0383 int pnp_activate_dev(struct pnp_dev *dev)
0384 {
0385 int error;
0386
0387 if (dev->active)
0388 return 0;
0389
0390
0391 if (pnp_auto_config_dev(dev))
0392 return -EBUSY;
0393
0394 error = pnp_start_dev(dev);
0395 if (error)
0396 return error;
0397
0398 dev->active = 1;
0399 return 0;
0400 }
0401 EXPORT_SYMBOL(pnp_activate_dev);
0402
0403
0404
0405
0406
0407
0408
0409 int pnp_disable_dev(struct pnp_dev *dev)
0410 {
0411 int error;
0412
0413 if (!dev->active)
0414 return 0;
0415
0416 error = pnp_stop_dev(dev);
0417 if (error)
0418 return error;
0419
0420 dev->active = 0;
0421
0422
0423 mutex_lock(&pnp_res_mutex);
0424 pnp_clean_resource_table(dev);
0425 mutex_unlock(&pnp_res_mutex);
0426
0427 return 0;
0428 }
0429 EXPORT_SYMBOL(pnp_disable_dev);