1 // SPDX-License-Identifier: GPL-2.0-only
3 * rsrc_iodyn.c -- Resource management routines for MEM-static sockets.
5 * The initial developer of the original code is David A. Hinds
6 * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
7 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
9 * (C) 1999 David A. Hinds
12 #include <linux/slab.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
16 #include <pcmcia/ss.h>
17 #include <pcmcia/cistpl.h>
18 #include "cs_internal.h"
21 struct pcmcia_align_data
{
26 static resource_size_t
pcmcia_align(void *align_data
,
27 const struct resource
*res
,
28 resource_size_t size
, resource_size_t align
)
30 struct pcmcia_align_data
*data
= align_data
;
31 resource_size_t start
;
33 start
= (res
->start
& ~data
->mask
) + data
->offset
;
34 if (start
< res
->start
)
35 start
+= data
->mask
+ 1;
38 if (res
->flags
& IORESOURCE_IO
) {
40 start
= (start
+ 0x3ff) & ~0x3ff;
45 if (res
->flags
& IORESOURCE_IO
) {
46 if ((res
->start
+ size
- 1) >= 1024)
55 static struct resource
*__iodyn_find_io_region(struct pcmcia_socket
*s
,
56 unsigned long base
, int num
,
59 struct resource
*res
= pcmcia_make_resource(0, num
, IORESOURCE_IO
,
61 struct pcmcia_align_data data
;
62 unsigned long min
= base
;
65 data
.mask
= align
- 1;
66 data
.offset
= base
& data
.mask
;
70 ret
= pci_bus_alloc_resource(s
->cb_dev
->bus
, res
, num
, 1,
71 min
, 0, pcmcia_align
, &data
);
74 ret
= allocate_resource(&ioport_resource
, res
, num
, min
, ~0UL,
75 1, pcmcia_align
, &data
);
84 static int iodyn_find_io(struct pcmcia_socket
*s
, unsigned int attr
,
85 unsigned int *base
, unsigned int num
,
86 unsigned int align
, struct resource
**parent
)
90 /* Check for an already-allocated window that must conflict with
91 * what was asked for. It is a hack because it does not catch all
92 * potential conflicts, just the most obvious ones.
94 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
101 if ((s
->io
[i
].res
->start
& (align
-1)) == *base
)
105 for (i
= 0; i
< MAX_IO_WIN
; i
++) {
106 struct resource
*res
= s
->io
[i
].res
;
109 if (res
&& (res
->flags
& IORESOURCE_BITS
) !=
110 (attr
& IORESOURCE_BITS
))
117 res
= s
->io
[i
].res
= __iodyn_find_io_region(s
, *base
,
123 s
->io
[i
].res
->flags
=
124 ((res
->flags
& ~IORESOURCE_BITS
) |
125 (attr
& IORESOURCE_BITS
));
126 s
->io
[i
].InUse
= num
;
131 /* Try to extend top of window */
133 if ((*base
== 0) || (*base
== try)) {
134 if (adjust_resource(s
->io
[i
].res
, res
->start
,
135 resource_size(res
) + num
))
138 s
->io
[i
].InUse
+= num
;
143 /* Try to extend bottom of window */
144 try = res
->start
- num
;
145 if ((*base
== 0) || (*base
== try)) {
146 if (adjust_resource(s
->io
[i
].res
,
148 resource_size(res
) + num
))
151 s
->io
[i
].InUse
+= num
;
161 struct pccard_resource_ops pccard_iodyn_ops
= {
162 .validate_mem
= NULL
,
163 .find_io
= iodyn_find_io
,
168 EXPORT_SYMBOL(pccard_iodyn_ops
);