Commit 0747e35e authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://bk.arm.linux.org.uk/linux-2.6-pcmcia

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 1a44cb0b f364acc5
......@@ -336,11 +336,6 @@ void ide_config(dev_link_t *link)
CS_CHECK(RequestIRQ, pcmcia_request_irq(handle, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(handle, &link->conf));
/* deal with brain dead IDE resource management */
release_region(link->io.BasePort1, link->io.NumPorts1);
if (link->io.NumPorts2)
release_region(link->io.BasePort2, link->io.NumPorts2);
/* disable drive interrupts during IDE probe */
outb(0x02, ctl_base);
......
......@@ -69,6 +69,13 @@ config CARDBUS
depends on YENTA
default y if YENTA
config PD6729
tristate "Cirrus PD6729 compatible bridge support"
depends on PCMCIA && PCI
help
This provides support for the Cirrus PD6729 PCI-to-PCMCIA bridge
device, found in some older laptops and PCMCIA card readers.
config I82092
tristate "i82092 compatible bridge support"
depends on PCMCIA && PCI
......
......@@ -9,6 +9,7 @@ endif
obj-$(CONFIG_PCMCIA) += pcmcia_core.o ds.o
obj-$(CONFIG_YENTA) += yenta_socket.o
obj-$(CONFIG_PD6729) += pd6729.o
obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o
......
......@@ -85,13 +85,15 @@ INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
void release_cis_mem(struct pcmcia_socket *s)
{
if (s->cis_mem.sys_start != 0) {
if (s->cis_mem.flags & MAP_ACTIVE) {
s->cis_mem.flags &= ~MAP_ACTIVE;
s->ops->set_mem_map(s, &s->cis_mem);
if (!(s->features & SS_CAP_STATIC_MAP))
release_mem_region(s->cis_mem.sys_start, s->map_size);
if (s->cis_mem.res) {
release_resource(s->cis_mem.res);
kfree(s->cis_mem.res);
s->cis_mem.res = NULL;
}
iounmap(s->cis_virt);
s->cis_mem.sys_start = 0;
s->cis_virt = NULL;
}
}
......@@ -105,17 +107,16 @@ static unsigned char *
set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
{
pccard_mem_map *mem = &s->cis_mem;
if (!(s->features & SS_CAP_STATIC_MAP) &&
mem->sys_start == 0) {
validate_mem(s);
mem->sys_start = 0;
if (find_mem_region(&mem->sys_start, s->map_size,
s->map_size, 0, "card services", s)) {
if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) {
mem->res = find_mem_region(0, s->map_size, s->map_size, 0,
"card services", s);
if (mem->res == NULL) {
printk(KERN_NOTICE "cs: unable to map card memory!\n");
return NULL;
}
mem->sys_stop = mem->sys_start+s->map_size-1;
s->cis_virt = ioremap(mem->sys_start, s->map_size);
mem->sys_start = mem->res->start;
mem->sys_stop = mem->res->end;
s->cis_virt = ioremap(mem->res->start, s->map_size);
}
mem->card_start = card_offset;
mem->flags = flags;
......
......@@ -1100,8 +1100,8 @@ int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req)
if (w == MAX_WIN)
return CS_NO_MORE_ITEMS;
win = &s->win[w];
req->Base = win->ctl.sys_start;
req->Size = win->ctl.sys_stop - win->ctl.sys_start + 1;
req->Base = win->ctl.res->start;
req->Size = win->ctl.res->end - win->ctl.res->start + 1;
req->AccessSpeed = win->ctl.speed;
req->Attributes = 0;
if (win->ctl.flags & MAP_ATTRIB)
......@@ -1548,8 +1548,11 @@ int pcmcia_release_window(window_handle_t win)
s->state &= ~SOCKET_WIN_REQ(win->index);
/* Release system memory */
if(!(s->features & SS_CAP_STATIC_MAP))
release_mem_region(win->base, win->size);
if (win->ctl.res) {
release_resource(win->ctl.res);
kfree(win->ctl.res);
win->ctl.res = NULL;
}
win->handle->state &= ~CLIENT_WIN_REQ(win->index);
win->magic = 0;
......@@ -1871,14 +1874,19 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
win->index = w;
win->handle = *handle;
win->sock = s;
win->base = req->Base;
win->size = req->Size;
if (!(s->features & SS_CAP_STATIC_MAP) &&
find_mem_region(&win->base, win->size, align,
(req->Attributes & WIN_MAP_BELOW_1MB),
(*handle)->dev_info, s))
return CS_IN_USE;
if (!(s->features & SS_CAP_STATIC_MAP)) {
win->ctl.res = find_mem_region(req->Base, req->Size, align,
(req->Attributes & WIN_MAP_BELOW_1MB),
(*handle)->dev_info, s);
if (!win->ctl.res)
return CS_IN_USE;
win->ctl.sys_start = win->ctl.res->start;
win->ctl.sys_stop = win->ctl.res->end;
} else {
win->ctl.sys_start = req->Base;
win->ctl.sys_stop = req->Base + req->Size - 1;
}
(*handle)->state |= CLIENT_WIN_REQ(w);
/* Configure the socket controller */
......@@ -1893,8 +1901,6 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
win->ctl.flags |= MAP_16BIT;
if (req->Attributes & WIN_USE_WAIT)
win->ctl.flags |= MAP_USE_WAIT;
win->ctl.sys_start = win->base;
win->ctl.sys_stop = win->base + win->size-1;
win->ctl.card_start = 0;
if (s->ops->set_mem_map(s, &win->ctl) != 0)
return CS_BAD_ARGS;
......
......@@ -180,12 +180,12 @@ int write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf);
int copy_memory(memory_handle_t handle, copy_op_t *req);
/* In rsrc_mgr */
void validate_mem(struct pcmcia_socket *s);
void pcmcia_validate_mem(struct pcmcia_socket *s);
struct resource *find_io_region(unsigned long base, int num, unsigned long align,
char *name, struct pcmcia_socket *s);
int adjust_io_region(struct resource *res, unsigned long r_start,
unsigned long r_end, struct pcmcia_socket *s);
int find_mem_region(u_long *base, u_long num, u_long align,
struct resource *find_mem_region(u_long base, u_long num, u_long align,
int low, char *name, struct pcmcia_socket *s);
int try_irq(u_int Attributes, int irq, int specific);
void undo_irq(u_int Attributes, int irq);
......
......@@ -941,6 +941,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pcmcia_get_configuration_info(s->handle, &buf.config);
break;
case DS_GET_FIRST_TUPLE:
pcmcia_validate_mem(s->parent);
ret = pcmcia_get_first_tuple(s->handle, &buf.tuple);
break;
case DS_GET_NEXT_TUPLE:
......@@ -962,6 +963,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pcmcia_get_status(s->handle, &buf.status);
break;
case DS_VALIDATE_CIS:
pcmcia_validate_mem(s->parent);
ret = pcmcia_validate_cis(s->handle, &buf.cisinfo);
break;
case DS_SUSPEND_CARD:
......
......@@ -420,12 +420,12 @@ static void set_bridge_state(int sock)
static int i82092aa_init(struct pcmcia_socket *sock)
{
int i;
struct resource res = { .start = 0, .end = 0x0fff };
pccard_io_map io = { 0, 0, 0, 0, 1 };
pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, };
enter("i82092aa_init");
mem.sys_stop = 0x0fff;
for (i = 0; i < 2; i++) {
io.map = i;
i82092aa_set_io_map(sock, &io);
......
......@@ -1307,10 +1307,10 @@ static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
static int pcic_init(struct pcmcia_socket *s)
{
int i;
struct resource res = { .start = 0, .end = 0x1000 };
pccard_io_map io = { 0, 0, 0, 0, 1 };
pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, };
mem.sys_stop = 0x1000;
for (i = 0; i < 2; i++) {
io.map = i;
pcic_set_io_map(s, &io);
......
This diff is collapsed.
#ifndef _INCLUDE_GUARD_PD6729_H_
#define _INCLUDE_GUARD_PD6729_H_
/* Debuging defines */
#ifdef NOTRACE
#define dprintk(fmt, args...) printk(fmt , ## args)
#else
#define dprintk(fmt, args...) do {} while (0)
#endif
/* Flags for I365_GENCTL */
#define I365_DF_VS1 0x40 /* DF-step Voltage Sense */
#define I365_DF_VS2 0x80
/* Fields in PD67_EXTERN_DATA */
#define PD67_EXD_VS1(s) (0x01 << ((s) << 1))
#define PD67_EXD_VS2(s) (0x02 << ((s) << 1))
struct pd6729_socket {
int number;
unsigned long io_base; /* base io address of the socket */
struct pcmcia_socket socket;
};
#endif
......@@ -118,7 +118,7 @@ make_resource(unsigned long b, unsigned long n, int flags, char *name)
res->name = name;
res->start = b;
res->end = b + n - 1;
res->flags = flags | IORESOURCE_BUSY;
res->flags = flags;
}
return res;
}
......@@ -303,6 +303,7 @@ static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *in
s->cis_mem.sys_start = res->start;
s->cis_mem.sys_stop = res->end;
s->cis_mem.res = res;
s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) {
ret = pcmcia_validate_cis(s->clients, info);
......@@ -313,6 +314,7 @@ static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *in
}
s->cis_mem.sys_start = 0;
s->cis_mem.sys_stop = 0;
s->cis_mem.res = NULL;
if ((ret != 0) || (info->Chains == 0))
return 0;
return 1;
......@@ -332,6 +334,7 @@ static int checksum(struct pcmcia_socket *s, struct resource *res)
map.speed = 0;
map.sys_start = res->start;
map.sys_stop = res->end;
map.res = res;
map.card_start = 0;
s->ops->set_mem_map(s, &map);
......@@ -454,7 +457,7 @@ static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
return do_mem_probe(m->base, m->num, s);
}
void validate_mem(struct pcmcia_socket *s)
static void validate_mem(struct pcmcia_socket *s)
{
resource_map_t *m, mm;
static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
......@@ -462,9 +465,6 @@ void validate_mem(struct pcmcia_socket *s)
u_long b, i, ok = 0;
int force_low = !(s->features & SS_CAP_PAGE_REGS);
if (!probe_mem)
return;
down(&rsrc_sem);
/* We do up to four passes through the list */
if (!force_low) {
......@@ -500,12 +500,12 @@ void validate_mem(struct pcmcia_socket *s)
#else /* CONFIG_PCMCIA_PROBE */
void validate_mem(struct pcmcia_socket *s)
static void validate_mem(struct pcmcia_socket *s)
{
resource_map_t *m, mm;
static int done = 0;
if (probe_mem && done++ == 0) {
if (done++ == 0) {
down(&rsrc_sem);
for (m = mem_db.next; m != &mem_db; m = mm.next) {
mm = *m;
......@@ -518,6 +518,18 @@ void validate_mem(struct pcmcia_socket *s)
#endif /* CONFIG_PCMCIA_PROBE */
void pcmcia_validate_mem(struct pcmcia_socket *s)
{
down(&s->skt_sem);
if (probe_mem && s->state & SOCKET_PRESENT)
validate_mem(s);
up(&s->skt_sem);
}
EXPORT_SYMBOL(pcmcia_validate_mem);
struct pcmcia_align_data {
unsigned long mask;
unsigned long offset;
......@@ -622,7 +634,7 @@ int adjust_io_region(struct resource *res, unsigned long r_start,
struct resource *find_io_region(unsigned long base, int num,
unsigned long align, char *name, struct pcmcia_socket *s)
{
struct resource *res = make_resource(0, num, IORESOURCE_IO, name);
struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
struct pcmcia_align_data data;
unsigned long min = base;
int ret;
......@@ -641,8 +653,8 @@ struct resource *find_io_region(unsigned long base, int num,
min, 0, pcmcia_align, &data);
} else
#endif
ret = allocate_resource(&ioport_resource, res, num, min, ~0UL, 0,
pcmcia_align, &data);
ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
1, pcmcia_align, &data);
up(&rsrc_sem);
if (ret != 0) {
......@@ -652,10 +664,10 @@ struct resource *find_io_region(unsigned long base, int num,
return res;
}
int find_mem_region(u_long *base, u_long num, u_long align,
int low, char *name, struct pcmcia_socket *s)
struct resource *find_mem_region(u_long base, u_long num, u_long align,
int low, char *name, struct pcmcia_socket *s)
{
struct resource *res = make_resource(0, num, IORESOURCE_MEM, name);
struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
struct pcmcia_align_data data;
unsigned long min, max;
int ret, i;
......@@ -663,16 +675,16 @@ int find_mem_region(u_long *base, u_long num, u_long align,
low = low || !(s->features & SS_CAP_PAGE_REGS);
data.mask = align - 1;
data.offset = *base & data.mask;
data.offset = base & data.mask;
data.map = &mem_db;
for (i = 0; i < 2; i++) {
if (low) {
max = 0x100000UL;
min = *base < max ? *base : 0;
min = base < max ? base : 0;
} else {
max = ~0UL;
min = 0x100000UL + *base;
min = 0x100000UL + base;
}
down(&rsrc_sem);
......@@ -684,7 +696,7 @@ int find_mem_region(u_long *base, u_long num, u_long align,
} else
#endif
ret = allocate_resource(&iomem_resource, res, num, min,
max, 0, pcmcia_align, &data);
max, 1, pcmcia_align, &data);
up(&rsrc_sem);
if (ret == 0 || low)
break;
......@@ -693,10 +705,9 @@ int find_mem_region(u_long *base, u_long num, u_long align,
if (ret != 0) {
kfree(res);
} else {
*base = res->start;
res = NULL;
}
return ret;
return res;
}
/*======================================================================
......
......@@ -868,10 +868,10 @@ static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m
static int tcic_init(struct pcmcia_socket *s)
{
int i;
struct resource res = { .start = 0, .end = 0x1000 };
pccard_io_map io = { 0, 0, 0, 0, 1 };
pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
pccard_mem_map mem = { .res = &res, .sys_stop = 0x1000, };
mem.sys_stop = 0x1000;
for (i = 0; i < 2; i++) {
io.map = i;
tcic_set_io_map(s, &io);
......
......@@ -445,10 +445,10 @@ static void yenta_interrupt_wrapper(unsigned long data)
static void yenta_clear_maps(struct yenta_socket *socket)
{
int i;
struct resource res = { .start = 0, .end = 0x0fff };
pccard_io_map io = { 0, 0, 0, 0, 1 };
pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
pccard_mem_map mem = { .res = &res, .sys_stop = 0x0fff, };
mem.sys_stop = 0x0fff;
yenta_set_socket(&socket->socket, &dead_socket);
for (i = 0; i < 2; i++) {
io.map = i;
......
......@@ -105,6 +105,7 @@ typedef struct pccard_mem_map {
u_short speed;
u_long sys_start, sys_stop;
u_int card_start;
struct resource *res;
} pccard_mem_map;
typedef struct cb_bridge_map {
......@@ -154,8 +155,6 @@ typedef struct window_t {
u_short index;
client_handle_t handle;
struct pcmcia_socket *sock;
u_long base;
u_long size;
pccard_mem_map ctl;
} window_t;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment