Beispiel #1
0
static void do_io_probe(ioaddr_t base, ioaddr_t num)
{
    
    ioaddr_t i, j, bad, any;
    u_char *b, hole, most;
    
    printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
	   base, base+num-1);
    
    /* First, what does a floating port look like? */
    b = kmalloc(256, GFP_KERNEL);
    if (!b) {
	printk(KERN_INFO " kmalloc failed!\n");
	return;
    }
    memset(b, 0, 256);
    for (i = base, most = 0; i < base+num; i += 8) {
	if (check_region(i, 8) || check_io_region(i, 8))
	    continue;
	hole = inb(i);
	for (j = 1; j < 8; j++)
	    if (inb(i+j) != hole) break;
	if ((j == 8) && (++b[hole] > b[most]))
	    most = hole;
	if (b[most] == 127) break;
    }
    kfree(b);

    bad = any = 0;
    for (i = base; i < base+num; i += 8) {
	if (check_region(i, 8) || check_io_region(i, 8))
	    continue;
	for (j = 0; j < 8; j++)
	    if (inb(i+j) != most) break;
	if (j < 8) {
	    if (!any)
		printk(" excluding");
	    if (!bad)
		bad = any = i;
	} else {
	    if (bad) {
		sub_interval(&io_db, bad, i-bad);
		printk(" %#04x-%#04x", bad, i-1);
		bad = 0;
	    }
	}
    }
    if (bad) {
	if ((num > 16) && (bad == base) && (i == base+num)) {
	    printk(" nothing: probe failed.\n");
	    return;
	} else {
	    sub_interval(&io_db, bad, i-bad);
	    printk(" %#04x-%#04x", bad, i-1);
	}
    }
    
    printk(any ? "\n" : " clean.\n");
}
Beispiel #2
0
static int do_mem_probe(u_long base, u_long num,
			int (*is_valid)(u_long), int (*do_cksum)(u_long))
{
    u_long i, j, bad, fail, step;

    printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
	   base, base+num-1);
    bad = fail = 0;
    step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
    for (i = j = base; i < base+num; i = j + step) {
	if (!fail) {	
	    for (j = i; j < base+num; j += step)
		if ((check_mem_region(j, step) == 0) && is_valid(j))
		    break;
	    fail = ((i == base) && (j == base+num));
	}
	if (fail) {
	    for (j = i; j < base+num; j += 2*step)
		if ((check_mem_region(j, 2*step) == 0) &&
		    do_cksum(j) && do_cksum(j+step))
		    break;
	}
	if (i != j) {
	    if (!bad) printk(" excluding");
	    printk(" %#05lx-%#05lx", i, j-1);
	    sub_interval(&mem_db, i, j-i);
	    bad += j-i;
	}
    }
    printk(bad ? "\n" : " clean.\n");
    return (num - bad);
}
Beispiel #3
0
static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
{
	struct socket_data *data = s->resource_data;
	unsigned long size = end - start + 1;
	int ret = 0;

	if (end < start)
		return -EINVAL;

	down(&rsrc_sem);
	switch (action) {
	case ADD_MANAGED_RESOURCE:
		ret = add_interval(&data->mem_db, start, size);
		break;
	case REMOVE_MANAGED_RESOURCE:
		ret = sub_interval(&data->mem_db, start, size);
		if (!ret) {
			struct pcmcia_socket *socket;
			down_read(&pcmcia_socket_list_rwsem);
			list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
				release_cis_mem(socket);
			up_read(&pcmcia_socket_list_rwsem);
		}
		break;
	default:
		ret = -EINVAL;
	}
	up(&rsrc_sem);

	return ret;
}
Beispiel #4
0
static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
{
	struct socket_data *data = s->resource_data;
	unsigned long size = end - start + 1;
	int ret = 0;

	if (end < start)
		return -EINVAL;

	if (end > IO_SPACE_LIMIT)
		return -EINVAL;

	down(&rsrc_sem);
	switch (action) {
	case ADD_MANAGED_RESOURCE:
		if (add_interval(&data->io_db, start, size) != 0) {
			ret = -EBUSY;
			break;
		}
#ifdef CONFIG_PCMCIA_PROBE
		if (probe_io)
			do_io_probe(s, start, size);
#endif
		break;
	case REMOVE_MANAGED_RESOURCE:
		sub_interval(&data->io_db, start, size);
		break;
	default:
		ret = -EINVAL;
		break;
	}
	up(&rsrc_sem);

	return ret;
}
Beispiel #5
0
static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
{
    struct socket_data *s_data = s->resource_data;
    u_long ok;
    if (m == &s_data->mem_db)
	return 0;
    ok = inv_probe(m->next, s);
    if (ok) {
	if (m->base >= 0x100000)
	    sub_interval(&s_data->mem_db, m->base, m->num);
	return ok;
    }
    if (m->base < 0x100000)
	return 0;
    return do_mem_probe(m->base, m->num, s);
}
Beispiel #6
0
static u_long inv_probe(int (*is_valid)(u_long),
			int (*do_cksum)(u_long),
			resource_map_t *m)
{
    u_long ok;
    if (m == &mem_db)
	return 0;
    ok = inv_probe(is_valid, do_cksum, m->next);
    if (ok) {
	if (m->base >= 0x100000)
	    sub_interval(&mem_db, m->base, m->num);
	return ok;
    }
    if (m->base < 0x100000)
	return 0;
    return do_mem_probe(m->base, m->num, is_valid, do_cksum);
}
static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
{
	struct resource_map *m, mm;
	static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
	unsigned long b, i, ok = 0;
	struct socket_data *s_data = s->resource_data;

	/* We do up to four passes through the list */
	if (probe_mask & MEM_PROBE_HIGH) {
		if (inv_probe(s_data->mem_db.next, s) > 0)
			return 0;
		dev_printk(KERN_NOTICE, &s->dev,
			   "cs: warning: no high memory space available!\n");
		return -ENODEV;
	}

	for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
		mm = *m;
		/* Only probe < 1 MB */
		if (mm.base >= 0x100000)
			continue;
		if ((mm.base | mm.num) & 0xffff) {
			ok += do_mem_probe(mm.base, mm.num, s);
			continue;
		}
		/* Special probe for 64K-aligned block */
		for (i = 0; i < 4; i++) {
			b = order[i] << 12;
			if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
				if (ok >= mem_limit)
					sub_interval(&s_data->mem_db, b, 0x10000);
				else
					ok += do_mem_probe(b, 0x10000, s);
			}
		}
	}

	if (ok > 0)
		return 0;

	return -ENODEV;
}
Beispiel #8
0
static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
{
    struct socket_data *s_data = s->resource_data;
    u_long i, j, bad, fail, step;

    printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
	   base, base+num-1);
    bad = fail = 0;
    step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
    /* don't allow too large steps */
    if (step > 0x800000)
	step = 0x800000;
    /* cis_readable wants to map 2x map_size */
    if (step < 2 * s->map_size)
	step = 2 * s->map_size;
    for (i = j = base; i < base+num; i = j + step) {
	if (!fail) {
	    for (j = i; j < base+num; j += step) {
		if (cis_readable(s, j, step))
		    break;
	    }
	    fail = ((i == base) && (j == base+num));
	}
	if (fail) {
	    for (j = i; j < base+num; j += 2*step)
		if (checksum_match(s, j, step) &&
		    checksum_match(s, j + step, step))
		    break;
	}
	if (i != j) {
	    if (!bad) printk(" excluding");
	    printk(" %#05lx-%#05lx", i, j-1);
	    sub_interval(&s_data->mem_db, i, j-i);
	    bad += j-i;
	}
    }
    printk(bad ? "\n" : " clean.\n");
    return (num - bad);
}
void validate_mem(int (*is_valid)(u_long), int (*do_cksum)(u_long),
		  int force_low, socket_info_t *s)
{
    resource_map_t *m, *n;
    static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
    static int hi = 0, lo = 0;
    u_long b, i, ok = 0;
    
    if (!probe_mem) return;
    /* We do up to four passes through the list */
    if (!force_low) {
	if (hi++ || (inv_probe(is_valid, do_cksum, mem_db.next, s) > 0))
	    return;
	printk(KERN_NOTICE "cs: warning: no high memory space "
	       "available!\n");
    }
    if (lo++) return;
    for (m = mem_db.next; m != &mem_db; m = n) {
	n = m->next;
	/* Only probe < 1 MB */
	if (m->base >= 0x100000) continue;
	if ((m->base | m->num) & 0xffff) {
	    ok += do_mem_probe(m->base, m->num, is_valid, do_cksum, s);
	    continue;
	}
	/* Special probe for 64K-aligned block */
	for (i = 0; i < 4; i++) {
	    b = order[i] << 12;
	    if ((b >= m->base) && (b+0x10000 <= m->base+m->num)) {
		if (ok >= mem_limit)
		    sub_interval(&mem_db, b, 0x10000);
		else
		    ok += do_mem_probe(b, 0x10000, is_valid, do_cksum, s);
	    }
	}
    }
}
Beispiel #10
0
static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num)
{
    struct resource *res;
    struct socket_data *s_data = s->resource_data;
    kio_addr_t i, j, bad;
    int any;
    u_char *b, hole, most;

    printk(KERN_INFO "cs: IO port probe %#lx-%#lx:",
	   base, base+num-1);

    /* First, what does a floating port look like? */
    b = kmalloc(256, GFP_KERNEL);
    if (!b) {
            printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
            return;
    }
    memset(b, 0, 256);
    for (i = base, most = 0; i < base+num; i += 8) {
	res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
	if (!res)
	    continue;
	hole = inb(i);
	for (j = 1; j < 8; j++)
	    if (inb(i+j) != hole) break;
	free_region(res);
	if ((j == 8) && (++b[hole] > b[most]))
	    most = hole;
	if (b[most] == 127) break;
    }
    kfree(b);

    bad = any = 0;
    for (i = base; i < base+num; i += 8) {
	res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
	if (!res)
	    continue;
	for (j = 0; j < 8; j++)
	    if (inb(i+j) != most) break;
	free_region(res);
	if (j < 8) {
	    if (!any)
		printk(" excluding");
	    if (!bad)
		bad = any = i;
	} else {
	    if (bad) {
		sub_interval(&s_data->io_db, bad, i-bad);
		printk(" %#lx-%#lx", bad, i-1);
		bad = 0;
	    }
	}
    }
    if (bad) {
	if ((num > 16) && (bad == base) && (i == base+num)) {
	    printk(" nothing: probe failed.\n");
	    return;
	} else {
	    sub_interval(&s_data->io_db, bad, i-bad);
	    printk(" %#lx-%#lx", bad, i-1);
	}
    }

    printk(any ? "\n" : " clean.\n");
}