aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/rsrc_nonstatic.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/rsrc_nonstatic.c')
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c315
1 files changed, 162 insertions, 153 deletions
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 7039f3cf5b77..9b0dc433a8c3 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -24,9 +24,9 @@
24#include <linux/timer.h> 24#include <linux/timer.h>
25#include <linux/pci.h> 25#include <linux/pci.h>
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/io.h>
27 28
28#include <asm/irq.h> 29#include <asm/irq.h>
29#include <asm/io.h>
30 30
31#include <pcmcia/cs_types.h> 31#include <pcmcia/cs_types.h>
32#include <pcmcia/ss.h> 32#include <pcmcia/ss.h>
@@ -144,43 +144,44 @@ static int add_interval(struct resource_map *map, u_long base, u_long num)
144 144
145static int sub_interval(struct resource_map *map, u_long base, u_long num) 145static int sub_interval(struct resource_map *map, u_long base, u_long num)
146{ 146{
147 struct resource_map *p, *q; 147 struct resource_map *p, *q;
148 148
149 for (p = map; ; p = q) { 149 for (p = map; ; p = q) {
150 q = p->next; 150 q = p->next;
151 if (q == map) 151 if (q == map)
152 break; 152 break;
153 if ((q->base+q->num > base) && (base+num > q->base)) { 153 if ((q->base+q->num > base) && (base+num > q->base)) {
154 if (q->base >= base) { 154 if (q->base >= base) {
155 if (q->base+q->num <= base+num) { 155 if (q->base+q->num <= base+num) {
156 /* Delete whole block */ 156 /* Delete whole block */
157 p->next = q->next; 157 p->next = q->next;
158 kfree(q); 158 kfree(q);
159 /* don't advance the pointer yet */ 159 /* don't advance the pointer yet */
160 q = p; 160 q = p;
161 } else { 161 } else {
162 /* Cut off bit from the front */ 162 /* Cut off bit from the front */
163 q->num = q->base + q->num - base - num; 163 q->num = q->base + q->num - base - num;
164 q->base = base + num; 164 q->base = base + num;
165 } 165 }
166 } else if (q->base+q->num <= base+num) { 166 } else if (q->base+q->num <= base+num) {
167 /* Cut off bit from the end */ 167 /* Cut off bit from the end */
168 q->num = base - q->base; 168 q->num = base - q->base;
169 } else { 169 } else {
170 /* Split the block into two pieces */ 170 /* Split the block into two pieces */
171 p = kmalloc(sizeof(struct resource_map), GFP_KERNEL); 171 p = kmalloc(sizeof(struct resource_map),
172 if (!p) { 172 GFP_KERNEL);
173 printk(KERN_WARNING "out of memory to update resources\n"); 173 if (!p) {
174 return -ENOMEM; 174 printk(KERN_WARNING "out of memory to update resources\n");
175 return -ENOMEM;
176 }
177 p->base = base+num;
178 p->num = q->base+q->num - p->base;
179 q->num = base - q->base;
180 p->next = q->next ; q->next = p;
181 }
175 } 182 }
176 p->base = base+num;
177 p->num = q->base+q->num - p->base;
178 q->num = base - q->base;
179 p->next = q->next ; q->next = p;
180 }
181 } 183 }
182 } 184 return 0;
183 return 0;
184} 185}
185 186
186/*====================================================================== 187/*======================================================================
@@ -194,69 +195,72 @@ static int sub_interval(struct resource_map *map, u_long base, u_long num)
194static void do_io_probe(struct pcmcia_socket *s, unsigned int base, 195static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
195 unsigned int num) 196 unsigned int num)
196{ 197{
197 struct resource *res; 198 struct resource *res;
198 struct socket_data *s_data = s->resource_data; 199 struct socket_data *s_data = s->resource_data;
199 unsigned int i, j, bad; 200 unsigned int i, j, bad;
200 int any; 201 int any;
201 u_char *b, hole, most; 202 u_char *b, hole, most;
202 203
203 dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:", 204 dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:",
204 base, base+num-1); 205 base, base+num-1);
205 206
206 /* First, what does a floating port look like? */ 207 /* First, what does a floating port look like? */
207 b = kzalloc(256, GFP_KERNEL); 208 b = kzalloc(256, GFP_KERNEL);
208 if (!b) { 209 if (!b) {
209 printk("\n"); 210 printk("\n");
210 dev_printk(KERN_ERR, &s->dev, 211 dev_printk(KERN_ERR, &s->dev,
211 "do_io_probe: unable to kmalloc 256 bytes"); 212 "do_io_probe: unable to kmalloc 256 bytes");
212 return; 213 return;
213 }
214 for (i = base, most = 0; i < base+num; i += 8) {
215 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
216 if (!res)
217 continue;
218 hole = inb(i);
219 for (j = 1; j < 8; j++)
220 if (inb(i+j) != hole) break;
221 free_region(res);
222 if ((j == 8) && (++b[hole] > b[most]))
223 most = hole;
224 if (b[most] == 127) break;
225 }
226 kfree(b);
227
228 bad = any = 0;
229 for (i = base; i < base+num; i += 8) {
230 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
231 if (!res)
232 continue;
233 for (j = 0; j < 8; j++)
234 if (inb(i+j) != most) break;
235 free_region(res);
236 if (j < 8) {
237 if (!any)
238 printk(" excluding");
239 if (!bad)
240 bad = any = i;
241 } else {
242 if (bad) {
243 sub_interval(&s_data->io_db, bad, i-bad);
244 printk(" %#x-%#x", bad, i-1);
245 bad = 0;
246 }
247 } 214 }
248 } 215 for (i = base, most = 0; i < base+num; i += 8) {
249 if (bad) { 216 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
250 if ((num > 16) && (bad == base) && (i == base+num)) { 217 if (!res)
251 printk(" nothing: probe failed.\n"); 218 continue;
252 return; 219 hole = inb(i);
253 } else { 220 for (j = 1; j < 8; j++)
254 sub_interval(&s_data->io_db, bad, i-bad); 221 if (inb(i+j) != hole)
255 printk(" %#x-%#x", bad, i-1); 222 break;
223 free_region(res);
224 if ((j == 8) && (++b[hole] > b[most]))
225 most = hole;
226 if (b[most] == 127)
227 break;
256 } 228 }
257 } 229 kfree(b);
258 230
259 printk(any ? "\n" : " clean.\n"); 231 bad = any = 0;
232 for (i = base; i < base+num; i += 8) {
233 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
234 if (!res)
235 continue;
236 for (j = 0; j < 8; j++)
237 if (inb(i+j) != most)
238 break;
239 free_region(res);
240 if (j < 8) {
241 if (!any)
242 printk(" excluding");
243 if (!bad)
244 bad = any = i;
245 } else {
246 if (bad) {
247 sub_interval(&s_data->io_db, bad, i-bad);
248 printk(" %#x-%#x", bad, i-1);
249 bad = 0;
250 }
251 }
252 }
253 if (bad) {
254 if ((num > 16) && (bad == base) && (i == base+num)) {
255 printk(" nothing: probe failed.\n");
256 return;
257 } else {
258 sub_interval(&s_data->io_db, bad, i-bad);
259 printk(" %#x-%#x", bad, i-1);
260 }
261 }
262
263 printk(any ? "\n" : " clean.\n");
260} 264}
261#endif 265#endif
262 266
@@ -327,8 +331,9 @@ cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
327 unsigned int info1, info2; 331 unsigned int info1, info2;
328 int ret = 0; 332 int ret = 0;
329 333
330 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe"); 334 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
331 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe"); 335 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
336 "PCMCIA memprobe");
332 337
333 if (res1 && res2) { 338 if (res1 && res2) {
334 ret = readable(s, res1, &info1); 339 ret = readable(s, res1, &info1);
@@ -347,8 +352,9 @@ checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
347 struct resource *res1, *res2; 352 struct resource *res1, *res2;
348 int a = -1, b = -1; 353 int a = -1, b = -1;
349 354
350 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe"); 355 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
351 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe"); 356 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
357 "PCMCIA memprobe");
352 358
353 if (res1 && res2) { 359 if (res1 && res2) {
354 a = checksum(s, res1); 360 a = checksum(s, res1);
@@ -371,42 +377,43 @@ checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
371 377
372static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s) 378static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
373{ 379{
374 struct socket_data *s_data = s->resource_data; 380 struct socket_data *s_data = s->resource_data;
375 u_long i, j, bad, fail, step; 381 u_long i, j, bad, fail, step;
376 382
377 dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:", 383 dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
378 base, base+num-1); 384 base, base+num-1);
379 bad = fail = 0; 385 bad = fail = 0;
380 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff); 386 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
381 /* don't allow too large steps */ 387 /* don't allow too large steps */
382 if (step > 0x800000) 388 if (step > 0x800000)
383 step = 0x800000; 389 step = 0x800000;
384 /* cis_readable wants to map 2x map_size */ 390 /* cis_readable wants to map 2x map_size */
385 if (step < 2 * s->map_size) 391 if (step < 2 * s->map_size)
386 step = 2 * s->map_size; 392 step = 2 * s->map_size;
387 for (i = j = base; i < base+num; i = j + step) { 393 for (i = j = base; i < base+num; i = j + step) {
388 if (!fail) { 394 if (!fail) {
389 for (j = i; j < base+num; j += step) { 395 for (j = i; j < base+num; j += step) {
390 if (cis_readable(s, j, step)) 396 if (cis_readable(s, j, step))
391 break; 397 break;
392 } 398 }
393 fail = ((i == base) && (j == base+num)); 399 fail = ((i == base) && (j == base+num));
394 } 400 }
395 if (fail) { 401 if (fail) {
396 for (j = i; j < base+num; j += 2*step) 402 for (j = i; j < base+num; j += 2*step)
397 if (checksum_match(s, j, step) && 403 if (checksum_match(s, j, step) &&
398 checksum_match(s, j + step, step)) 404 checksum_match(s, j + step, step))
399 break; 405 break;
400 } 406 }
401 if (i != j) { 407 if (i != j) {
402 if (!bad) printk(" excluding"); 408 if (!bad)
403 printk(" %#05lx-%#05lx", i, j-1); 409 printk(" excluding");
404 sub_interval(&s_data->mem_db, i, j-i); 410 printk(" %#05lx-%#05lx", i, j-1);
405 bad += j-i; 411 sub_interval(&s_data->mem_db, i, j-i);
412 bad += j-i;
413 }
406 } 414 }
407 } 415 printk(bad ? "\n" : " clean.\n");
408 printk(bad ? "\n" : " clean.\n"); 416 return num - bad;
409 return (num - bad);
410} 417}
411 418
412#ifdef CONFIG_PCMCIA_PROBE 419#ifdef CONFIG_PCMCIA_PROBE
@@ -656,7 +663,7 @@ static struct resource *nonstatic_find_io_region(unsigned long base, int num,
656 return res; 663 return res;
657} 664}
658 665
659static struct resource * nonstatic_find_mem_region(u_long base, u_long num, 666static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
660 u_long align, int low, struct pcmcia_socket *s) 667 u_long align, int low, struct pcmcia_socket *s)
661{ 668{
662 struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev)); 669 struct resource *res = make_resource(0, num, IORESOURCE_MEM, dev_name(&s->dev));
@@ -794,7 +801,7 @@ static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
794 return -EINVAL; 801 return -EINVAL;
795#endif 802#endif
796 803
797 for (i=0; i < PCI_BUS_NUM_RESOURCES; i++) { 804 for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
798 res = s->cb_dev->bus->resource[i]; 805 res = s->cb_dev->bus->resource[i];
799 if (!res) 806 if (!res)
800 continue; 807 continue;
@@ -908,14 +915,14 @@ static ssize_t show_io_db(struct device *dev,
908 for (p = data->io_db.next; p != &data->io_db; p = p->next) { 915 for (p = data->io_db.next; p != &data->io_db; p = p->next) {
909 if (ret > (PAGE_SIZE - 10)) 916 if (ret > (PAGE_SIZE - 10))
910 continue; 917 continue;
911 ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1), 918 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
912 "0x%08lx - 0x%08lx\n", 919 "0x%08lx - 0x%08lx\n",
913 ((unsigned long) p->base), 920 ((unsigned long) p->base),
914 ((unsigned long) p->base + p->num - 1)); 921 ((unsigned long) p->base + p->num - 1));
915 } 922 }
916 923
917 mutex_unlock(&rsrc_mutex); 924 mutex_unlock(&rsrc_mutex);
918 return (ret); 925 return ret;
919} 926}
920 927
921static ssize_t store_io_db(struct device *dev, 928static ssize_t store_io_db(struct device *dev,
@@ -927,12 +934,13 @@ static ssize_t store_io_db(struct device *dev,
927 unsigned int add = ADD_MANAGED_RESOURCE; 934 unsigned int add = ADD_MANAGED_RESOURCE;
928 ssize_t ret = 0; 935 ssize_t ret = 0;
929 936
930 ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); 937 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
931 if (ret != 2) { 938 if (ret != 2) {
932 ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); 939 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
933 add = REMOVE_MANAGED_RESOURCE; 940 add = REMOVE_MANAGED_RESOURCE;
934 if (ret != 2) { 941 if (ret != 2) {
935 ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); 942 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
943 &end_addr);
936 add = ADD_MANAGED_RESOURCE; 944 add = ADD_MANAGED_RESOURCE;
937 if (ret != 2) 945 if (ret != 2)
938 return -EINVAL; 946 return -EINVAL;
@@ -963,14 +971,14 @@ static ssize_t show_mem_db(struct device *dev,
963 for (p = data->mem_db.next; p != &data->mem_db; p = p->next) { 971 for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
964 if (ret > (PAGE_SIZE - 10)) 972 if (ret > (PAGE_SIZE - 10))
965 continue; 973 continue;
966 ret += snprintf (&buf[ret], (PAGE_SIZE - ret - 1), 974 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
967 "0x%08lx - 0x%08lx\n", 975 "0x%08lx - 0x%08lx\n",
968 ((unsigned long) p->base), 976 ((unsigned long) p->base),
969 ((unsigned long) p->base + p->num - 1)); 977 ((unsigned long) p->base + p->num - 1));
970 } 978 }
971 979
972 mutex_unlock(&rsrc_mutex); 980 mutex_unlock(&rsrc_mutex);
973 return (ret); 981 return ret;
974} 982}
975 983
976static ssize_t store_mem_db(struct device *dev, 984static ssize_t store_mem_db(struct device *dev,
@@ -982,12 +990,13 @@ static ssize_t store_mem_db(struct device *dev,
982 unsigned int add = ADD_MANAGED_RESOURCE; 990 unsigned int add = ADD_MANAGED_RESOURCE;
983 ssize_t ret = 0; 991 ssize_t ret = 0;
984 992
985 ret = sscanf (buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr); 993 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
986 if (ret != 2) { 994 if (ret != 2) {
987 ret = sscanf (buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr); 995 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
988 add = REMOVE_MANAGED_RESOURCE; 996 add = REMOVE_MANAGED_RESOURCE;
989 if (ret != 2) { 997 if (ret != 2) {
990 ret = sscanf (buf, "0x%lx - 0x%lx", &start_addr, &end_addr); 998 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
999 &end_addr);
991 add = ADD_MANAGED_RESOURCE; 1000 add = ADD_MANAGED_RESOURCE;
992 if (ret != 2) 1001 if (ret != 2)
993 return -EINVAL; 1002 return -EINVAL;