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/cistpl.h>
21 #include "cs_internal.h"
24 struct pcmcia_align_data
{
29 static resource_size_t
pcmcia_align(void *align_data
,
30 const struct resource
*res
,
31 resource_size_t size
, resource_size_t align
)
33 struct pcmcia_align_data
*data
= align_data
;
34 resource_size_t start
;
36 start
= (res
->start
& ~data
->mask
) + data
->offset
;
37 if (start
< res
->start
)
38 start
+= data
->mask
+ 1;
41 if (res
->flags
& IORESOURCE_IO
) {
43 start
= (start
+ 0x3ff) & ~0x3ff;
48 if (res
->flags
& IORESOURCE_IO
) {
49 if ((res
->start
+ size
- 1) >= 1024)
58 static struct resource
*__iodyn_find_io_region(struct pcmcia_socket
*s
,
59 unsigned long base
, int num
,
62 struct resource
*res
= pcmcia_make_resource(0, num
, IORESOURCE_IO
,
64 struct pcmcia_align_data data
;
65 unsigned long min
= base
;
68 data
.mask
= align
- 1;
69 data
.offset
= base
& data
.mask
;
73 ret
= pci_bus_alloc_resource(s
->cb_dev
->bus
, res
, num
, 1,
74 min
, 0, pcmcia_align
, &data
);
77 ret
= allocate_resource(&ioport_resource
, res
, num
, min
, ~0UL,
78 1, pcmcia_align
, &data
);
87 static int iodyn_find_io(struct pcmcia_socket
*s
, unsigned int attr
,
88 unsigned int *base
, unsigned int num
,
89 unsigned int align
, struct resource
**parent
)
93 /* Check for an already-allocated window that must conflict with
94 * what was asked for. It is a hack because it does not catch all
95 * potential conflicts, just the most obvious ones.
97 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
104 if ((s
->io
[i
].res
->start
& (align
-1)) == *base
)
108 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
109 struct resource
*res
= s
->io
[i
].res
;
112 if (res
&& (res
->flags
& IORESOURCE_BITS
) !=
113 (attr
& IORESOURCE_BITS
))
120 res
= s
->io
[i
].res
= __iodyn_find_io_region(s
, *base
,
126 s
->io
[i
].res
->flags
=
127 ((res
->flags
& ~IORESOURCE_BITS
) |
128 (attr
& IORESOURCE_BITS
));
129 s
->io
[i
].InUse
= num
;
134 /* Try to extend top of window */
136 if ((*base
== 0) || (*base
== try)) {
137 if (adjust_resource(s
->io
[i
].res
, res
->start
,
138 res
->end
- res
->start
+ num
+ 1))
141 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
;
164 struct pccard_resource_ops pccard_iodyn_ops
= {
165 .validate_mem
= NULL
,
166 .find_io
= iodyn_find_io
,
171 EXPORT_SYMBOL(pccard_iodyn_ops
);