xref: /linux/drivers/pcmcia/rsrc_iodyn.c (revision 49b1153adfe18a3cce7e70aa26c690f275917cd0)
1*49b1153aSDominik Brodowski /*
2*49b1153aSDominik Brodowski  * rsrc_iodyn.c -- Resource management routines for MEM-static sockets.
3*49b1153aSDominik Brodowski  *
4*49b1153aSDominik Brodowski  * This program is free software; you can redistribute it and/or modify
5*49b1153aSDominik Brodowski  * it under the terms of the GNU General Public License version 2 as
6*49b1153aSDominik Brodowski  * published by the Free Software Foundation.
7*49b1153aSDominik Brodowski  *
8*49b1153aSDominik Brodowski  * The initial developer of the original code is David A. Hinds
9*49b1153aSDominik Brodowski  * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
10*49b1153aSDominik Brodowski  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
11*49b1153aSDominik Brodowski  *
12*49b1153aSDominik Brodowski  * (C) 1999		David A. Hinds
13*49b1153aSDominik Brodowski  */
14*49b1153aSDominik Brodowski 
15*49b1153aSDominik Brodowski #include <linux/module.h>
16*49b1153aSDominik Brodowski #include <linux/kernel.h>
17*49b1153aSDominik Brodowski 
18*49b1153aSDominik Brodowski #include <pcmcia/cs_types.h>
19*49b1153aSDominik Brodowski #include <pcmcia/ss.h>
20*49b1153aSDominik Brodowski #include <pcmcia/cs.h>
21*49b1153aSDominik Brodowski #include <pcmcia/cistpl.h>
22*49b1153aSDominik Brodowski #include "cs_internal.h"
23*49b1153aSDominik Brodowski 
24*49b1153aSDominik Brodowski 
25*49b1153aSDominik Brodowski struct pcmcia_align_data {
26*49b1153aSDominik Brodowski 	unsigned long	mask;
27*49b1153aSDominik Brodowski 	unsigned long	offset;
28*49b1153aSDominik Brodowski };
29*49b1153aSDominik Brodowski 
30*49b1153aSDominik Brodowski static resource_size_t pcmcia_align(void *align_data,
31*49b1153aSDominik Brodowski 				const struct resource *res,
32*49b1153aSDominik Brodowski 				resource_size_t size, resource_size_t align)
33*49b1153aSDominik Brodowski {
34*49b1153aSDominik Brodowski 	struct pcmcia_align_data *data = align_data;
35*49b1153aSDominik Brodowski 	resource_size_t start;
36*49b1153aSDominik Brodowski 
37*49b1153aSDominik Brodowski 	start = (res->start & ~data->mask) + data->offset;
38*49b1153aSDominik Brodowski 	if (start < res->start)
39*49b1153aSDominik Brodowski 		start += data->mask + 1;
40*49b1153aSDominik Brodowski 
41*49b1153aSDominik Brodowski #ifdef CONFIG_X86
42*49b1153aSDominik Brodowski 	if (res->flags & IORESOURCE_IO) {
43*49b1153aSDominik Brodowski 		if (start & 0x300)
44*49b1153aSDominik Brodowski 			start = (start + 0x3ff) & ~0x3ff;
45*49b1153aSDominik Brodowski 	}
46*49b1153aSDominik Brodowski #endif
47*49b1153aSDominik Brodowski 
48*49b1153aSDominik Brodowski #ifdef CONFIG_M68K
49*49b1153aSDominik Brodowski 	if (res->flags & IORESOURCE_IO) {
50*49b1153aSDominik Brodowski 		if ((res->start + size - 1) >= 1024)
51*49b1153aSDominik Brodowski 			start = res->end;
52*49b1153aSDominik Brodowski 	}
53*49b1153aSDominik Brodowski #endif
54*49b1153aSDominik Brodowski 
55*49b1153aSDominik Brodowski 	return start;
56*49b1153aSDominik Brodowski }
57*49b1153aSDominik Brodowski 
58*49b1153aSDominik Brodowski 
59*49b1153aSDominik Brodowski static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start,
60*49b1153aSDominik Brodowski 		unsigned long r_end, struct pcmcia_socket *s)
61*49b1153aSDominik Brodowski {
62*49b1153aSDominik Brodowski 	return adjust_resource(res, r_start, r_end - r_start + 1);
63*49b1153aSDominik Brodowski }
64*49b1153aSDominik Brodowski 
65*49b1153aSDominik Brodowski 
66*49b1153aSDominik Brodowski static struct resource *iodyn_find_io_region(unsigned long base, int num,
67*49b1153aSDominik Brodowski 		unsigned long align, struct pcmcia_socket *s)
68*49b1153aSDominik Brodowski {
69*49b1153aSDominik Brodowski 	struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
70*49b1153aSDominik Brodowski 						dev_name(&s->dev));
71*49b1153aSDominik Brodowski 	struct pcmcia_align_data data;
72*49b1153aSDominik Brodowski 	unsigned long min = base;
73*49b1153aSDominik Brodowski 	int ret;
74*49b1153aSDominik Brodowski 
75*49b1153aSDominik Brodowski 	if (align == 0)
76*49b1153aSDominik Brodowski 		align = 0x10000;
77*49b1153aSDominik Brodowski 
78*49b1153aSDominik Brodowski 	data.mask = align - 1;
79*49b1153aSDominik Brodowski 	data.offset = base & data.mask;
80*49b1153aSDominik Brodowski 
81*49b1153aSDominik Brodowski #ifdef CONFIG_PCI
82*49b1153aSDominik Brodowski 	if (s->cb_dev) {
83*49b1153aSDominik Brodowski 		ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
84*49b1153aSDominik Brodowski 					     min, 0, pcmcia_align, &data);
85*49b1153aSDominik Brodowski 	} else
86*49b1153aSDominik Brodowski #endif
87*49b1153aSDominik Brodowski 		ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
88*49b1153aSDominik Brodowski 					1, pcmcia_align, &data);
89*49b1153aSDominik Brodowski 
90*49b1153aSDominik Brodowski 	if (ret != 0) {
91*49b1153aSDominik Brodowski 		kfree(res);
92*49b1153aSDominik Brodowski 		res = NULL;
93*49b1153aSDominik Brodowski 	}
94*49b1153aSDominik Brodowski 	return res;
95*49b1153aSDominik Brodowski }
96*49b1153aSDominik Brodowski 
97*49b1153aSDominik Brodowski struct pccard_resource_ops pccard_iodyn_ops = {
98*49b1153aSDominik Brodowski 	.validate_mem = NULL,
99*49b1153aSDominik Brodowski 	.adjust_io_region = iodyn_adjust_io_region,
100*49b1153aSDominik Brodowski 	.find_io = iodyn_find_io_region,
101*49b1153aSDominik Brodowski 	.find_mem = NULL,
102*49b1153aSDominik Brodowski 	.add_io = NULL,
103*49b1153aSDominik Brodowski 	.add_mem = NULL,
104*49b1153aSDominik Brodowski 	.init = static_init,
105*49b1153aSDominik Brodowski 	.exit = NULL,
106*49b1153aSDominik Brodowski };
107*49b1153aSDominik Brodowski EXPORT_SYMBOL(pccard_iodyn_ops);
108