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/ss.h>
20 #include <pcmcia/cs.h>
21 #include <pcmcia/cistpl.h>
22 #include "cs_internal.h"
25 struct pcmcia_align_data
{
30 static resource_size_t
pcmcia_align(void *align_data
,
31 const struct resource
*res
,
32 resource_size_t size
, resource_size_t align
)
34 struct pcmcia_align_data
*data
= align_data
;
35 resource_size_t start
;
37 start
= (res
->start
& ~data
->mask
) + data
->offset
;
38 if (start
< res
->start
)
39 start
+= data
->mask
+ 1;
42 if (res
->flags
& IORESOURCE_IO
) {
44 start
= (start
+ 0x3ff) & ~0x3ff;
49 if (res
->flags
& IORESOURCE_IO
) {
50 if ((res
->start
+ size
- 1) >= 1024)
59 static struct resource
*__iodyn_find_io_region(struct pcmcia_socket
*s
,
60 unsigned long base
, int num
,
63 struct resource
*res
= pcmcia_make_resource(0, num
, IORESOURCE_IO
,
65 struct pcmcia_align_data data
;
66 unsigned long min
= base
;
69 data
.mask
= align
- 1;
70 data
.offset
= base
& data
.mask
;
74 ret
= pci_bus_alloc_resource(s
->cb_dev
->bus
, res
, num
, 1,
75 min
, 0, pcmcia_align
, &data
);
78 ret
= allocate_resource(&ioport_resource
, res
, num
, min
, ~0UL,
79 1, pcmcia_align
, &data
);
88 static int iodyn_find_io(struct pcmcia_socket
*s
, unsigned int attr
,
89 unsigned int *base
, unsigned int num
,
90 unsigned int align
, struct resource
**parent
)
94 /* Check for an already-allocated window that must conflict with
95 * what was asked for. It is a hack because it does not catch all
96 * potential conflicts, just the most obvious ones.
98 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
105 if ((s
->io
[i
].res
->start
& (align
-1)) == *base
)
109 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
110 struct resource
*res
= s
->io
[i
].res
;
113 if (res
&& (res
->flags
& IORESOURCE_BITS
) !=
114 (attr
& IORESOURCE_BITS
))
121 res
= s
->io
[i
].res
= __iodyn_find_io_region(s
, *base
,
127 s
->io
[i
].res
->flags
=
128 ((res
->flags
& ~IORESOURCE_BITS
) |
129 (attr
& IORESOURCE_BITS
));
130 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
;
147 /* Try to extend bottom of window */
148 try = res
->start
- num
;
149 if ((*base
== 0) || (*base
== try)) {
150 if (adjust_resource(s
->io
[i
].res
,
152 res
->end
- res
->start
+ num
+ 1))
155 s
->io
[i
].InUse
+= num
;
165 struct pccard_resource_ops pccard_iodyn_ops
= {
166 .validate_mem
= NULL
,
167 .find_io
= iodyn_find_io
,
172 EXPORT_SYMBOL(pccard_iodyn_ops
);