2 * rsrc_iodyn.c -- Resource management routines for MEM-static sockets.
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.
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.
12 * (C) 1999 David A. Hinds
15 #include <linux/slab.h>
16 #include <linux/module.h>
17 #include <linux/kernel.h>
19 #include <pcmcia/cs_types.h>
20 #include <pcmcia/ss.h>
21 #include <pcmcia/cs.h>
22 #include <pcmcia/cistpl.h>
23 #include "cs_internal.h"
26 struct pcmcia_align_data
{
31 static resource_size_t
pcmcia_align(void *align_data
,
32 const struct resource
*res
,
33 resource_size_t size
, resource_size_t align
)
35 struct pcmcia_align_data
*data
= align_data
;
36 resource_size_t start
;
38 start
= (res
->start
& ~data
->mask
) + data
->offset
;
39 if (start
< res
->start
)
40 start
+= data
->mask
+ 1;
43 if (res
->flags
& IORESOURCE_IO
) {
45 start
= (start
+ 0x3ff) & ~0x3ff;
50 if (res
->flags
& IORESOURCE_IO
) {
51 if ((res
->start
+ size
- 1) >= 1024)
60 static struct resource
*__iodyn_find_io_region(struct pcmcia_socket
*s
,
61 unsigned long base
, int num
,
64 struct resource
*res
= pcmcia_make_resource(0, num
, IORESOURCE_IO
,
66 struct pcmcia_align_data data
;
67 unsigned long min
= base
;
70 data
.mask
= align
- 1;
71 data
.offset
= base
& data
.mask
;
75 ret
= pci_bus_alloc_resource(s
->cb_dev
->bus
, res
, num
, 1,
76 min
, 0, pcmcia_align
, &data
);
79 ret
= allocate_resource(&ioport_resource
, res
, num
, min
, ~0UL,
80 1, pcmcia_align
, &data
);
89 static int iodyn_find_io(struct pcmcia_socket
*s
, unsigned int attr
,
90 unsigned int *base
, unsigned int num
,
95 /* Check for an already-allocated window that must conflict with
96 * what was asked for. It is a hack because it does not catch all
97 * potential conflicts, just the most obvious ones.
99 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
106 if ((s
->io
[i
].res
->start
& (align
-1)) == *base
)
110 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
111 struct resource
*res
= s
->io
[i
].res
;
114 if (res
&& (res
->flags
& IORESOURCE_BITS
) !=
115 (attr
& IORESOURCE_BITS
))
122 res
= s
->io
[i
].res
= __iodyn_find_io_region(s
, *base
,
128 s
->io
[i
].res
->flags
=
129 ((res
->flags
& ~IORESOURCE_BITS
) |
130 (attr
& IORESOURCE_BITS
));
131 s
->io
[i
].InUse
= num
;
135 /* Try to extend top of window */
137 if ((*base
== 0) || (*base
== try)) {
138 if (adjust_resource(s
->io
[i
].res
, res
->start
,
139 res
->end
- res
->start
+ num
+ 1))
142 s
->io
[i
].InUse
+= num
;
146 /* Try to extend bottom of window */
147 try = res
->start
- num
;
148 if ((*base
== 0) || (*base
== try)) {
149 if (adjust_resource(s
->io
[i
].res
,
151 res
->end
- res
->start
+ num
+ 1))
154 s
->io
[i
].InUse
+= num
;
163 struct pccard_resource_ops pccard_iodyn_ops
= {
164 .validate_mem
= NULL
,
165 .find_io
= iodyn_find_io
,
172 EXPORT_SYMBOL(pccard_iodyn_ops
);