/*
* rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* The initial developer of the original code is David A. Hinds
* <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
* are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
*
* (C) 1999 David A. Hinds
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/timer.h>
#include <linux/pci.h>
#include <linux/device.h>
#include <linux/io.h>
#include <asm/irq.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
/* moved to rsrc_mgr.c
MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
MODULE_LICENSE("GPL");
*/
/* Parameters that can be set with 'insmod' */
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
#ifdef CONFIG_PCMCIA_PROBE
INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
INT_MODULE_PARM(mem_limit, 0x10000);
#endif
/* for io_db and mem_db */
struct resource_map {
u_long base, num;
struct resource_map *next;
};
struct socket_data {
struct resource_map mem_db;
struct resource_map mem_db_valid;
struct resource_map io_db;
};
#define MEM_PROBE_LOW (1 << 0)
#define MEM_PROBE_HIGH (1 << 1)
/*======================================================================
Linux resource management extensions
======================================================================*/
static struct resource *
claim_region(struct pcmcia_socket *s, resource_size_t base,
resource_size_t size, int type, char *name)
{
struct resource *res, *parent;
parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
res = pcmcia_make_resource(base, size, type | IORESOURCE_BUSY, name);
if (res) {
#ifdef CONFIG_PCI
if (s && s->cb_dev)
parent = pci_find_parent_resource(s->cb_dev, res);
#endif
if (!parent || request_resource(parent, res)) {
kfree(res);
res = NULL;
}
}
return res;
}
static void free_region(struct resource *res)
{
if (res) {
release_resource(res);
kfree(res);
}
}
/*======================================================================
These manage the internal databases of available resources.
======================================================================*/
static int add_interval(struct resource_map *map, u_long base, u_long num)
{
struct resource_map *p, *q;
for (p = map; ; p = p->next) {
if ((p != map) && (p->base+p->num >= base)) {
p->num = max(num + base - p->base, p->num