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