summaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-16 01:07:24 +0000
commit95db6b748fc86297827fbd9c9ef174d491c9ad89 (patch)
tree27a92a942821cde1edda9a1b088718d436b3efe4 /drivers/pcmcia
parent45b27b0a0652331d104c953a5b192d843fff88f8 (diff)
Merge with Linux 2.3.40.
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/bulkmem.c7
-rw-r--r--drivers/pcmcia/cardbus.c147
-rw-r--r--drivers/pcmcia/cb_enabler.c18
-rw-r--r--drivers/pcmcia/cistpl.c112
-rw-r--r--drivers/pcmcia/cs.c126
-rw-r--r--drivers/pcmcia/ds.c91
-rw-r--r--drivers/pcmcia/i82365.c1
-rw-r--r--drivers/pcmcia/pci_socket.c7
-rw-r--r--drivers/pcmcia/pci_socket.h11
-rw-r--r--drivers/pcmcia/ricoh.h72
-rw-r--r--drivers/pcmcia/rsrc_mgr.c47
-rw-r--r--drivers/pcmcia/tcic.c7
-rw-r--r--drivers/pcmcia/ti113x.h125
-rw-r--r--drivers/pcmcia/yenta.c204
14 files changed, 581 insertions, 394 deletions
diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
index 269f5c337..1c0a21146 100644
--- a/drivers/pcmcia/bulkmem.c
+++ b/drivers/pcmcia/bulkmem.c
@@ -2,7 +2,7 @@
PCMCIA Bulk Memory Services
- bulkmem.c 1.33 1999/10/25 20:03:33
+ bulkmem.c 1.34 1999/11/17 01:37:55
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -179,7 +179,7 @@ static void retry_erase(erase_busy_t *busy, u_int cause)
}
busy->client->event_callback_args.info = erase;
EVENT(busy->client, CS_EVENT_ERASE_COMPLETE, CS_EVENT_PRI_LOW);
- kfree_s(busy, sizeof(*busy));
+ kfree(busy);
/* Resubmit anything waiting for a request to finish */
wake_up_interruptible(&mtd->mtd_req);
retry_erase_list(&mtd->erase_busy, 0);
@@ -484,6 +484,7 @@ int pcmcia_register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header,
if ((handle == NULL) || CHECK_HANDLE(*handle))
return CS_BAD_HANDLE;
queue = kmalloc(sizeof(*queue), GFP_KERNEL);
+ if (!queue) return CS_OUT_OF_RESOURCE;
queue->eraseq_magic = ERASEQ_MAGIC;
queue->handle = *handle;
queue->count = header->QueueEntryCnt;
@@ -502,7 +503,7 @@ int pcmcia_deregister_erase_queue(eraseq_handle_t eraseq)
if (i < eraseq->count)
return CS_BUSY;
eraseq->eraseq_magic = 0;
- kfree_s(eraseq, sizeof(*eraseq));
+ kfree(eraseq);
return CS_SUCCESS;
} /* deregister_erase_queue */
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 88175e08d..74114b4fe 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -99,11 +99,6 @@ static int pc_debug = PCMCIA_DEBUG;
#define PCDATA_CODE_TYPE 0x0014
#define PCDATA_INDICATOR 0x0015
-#ifndef CONFIG_PROC_FS
-#define pci_proc_attach_device(dev) do { } while (0)
-#define pci_proc_detach_device(dev) do { } while (0)
-#endif
-
typedef struct cb_config_t {
struct pci_dev dev;
} cb_config_t;
@@ -111,39 +106,12 @@ typedef struct cb_config_t {
/*=====================================================================
Expansion ROM's have a special layout, and pointers specify an
- image number and an offset within that image. check_rom()
- verifies that the expansion ROM exists and has the standard
- layout. xlate_rom_addr() converts an image/offset address to an
- absolute offset from the ROM's base address.
+ image number and an offset within that image. xlate_rom_addr()
+ converts an image/offset address to an absolute offset from the
+ ROM's base address.
=====================================================================*/
-static int check_rom(u_char * b, u_long len)
-{
- u_int img = 0, ofs = 0, sz;
- u_short data;
- DEBUG(0, "ROM image dump:\n");
- while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
- data = readb(b + ROM_DATA_PTR) +
- (readb(b + ROM_DATA_PTR + 1) << 8);
- sz = 512 * (readb(b + data + PCDATA_IMAGE_SZ) +
- (readb(b + data + PCDATA_IMAGE_SZ + 1) << 8));
- DEBUG(0, " image %d: 0x%06x-0x%06x, signature %c%c%c%c\n",
- img, ofs, ofs + sz - 1,
- readb(b + data + PCDATA_SIGNATURE),
- readb(b + data + PCDATA_SIGNATURE + 1),
- readb(b + data + PCDATA_SIGNATURE + 2),
- readb(b + data + PCDATA_SIGNATURE + 3));
- ofs += sz;
- img++;
- if ((readb(b + data + PCDATA_INDICATOR) & 0x80) ||
- (sz == 0) || (ofs >= len))
- break;
- b += sz;
- }
- return img;
-}
-
static u_int xlate_rom_addr(u_char * b, u_int addr)
{
u_int img = 0, ofs = 0, sz;
@@ -261,6 +229,21 @@ fail:
=====================================================================*/
+static int cb_assign_irq(u32 mask)
+{
+ int irq, try;
+
+ for (try = 0; try < 2; try++) {
+ for (irq = 1; irq < 32; irq++) {
+ if ((mask >> irq) & 1) {
+ if (try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0)
+ return irq;
+ }
+ }
+ }
+ return 0;
+}
+
int cb_alloc(socket_info_t * s)
{
struct pci_bus *bus;
@@ -268,6 +251,7 @@ int cb_alloc(socket_info_t * s)
u_short vend, v, dev;
u_char i, hdr, fn;
cb_config_t *c;
+ int irq;
bus = s->cap.cb_dev->subordinate;
memset(&tmp, 0, sizeof(tmp));
@@ -297,8 +281,10 @@ int cb_alloc(socket_info_t * s)
return CS_OUT_OF_RESOURCE;
memset(c, 0, fn * sizeof(struct cb_config_t));
+ irq = s->cap.pci_irq;
for (i = 0; i < fn; i++) {
struct pci_dev *dev = &c[i].dev;
+ u8 irq_pin;
int r;
dev->bus = bus;
@@ -306,41 +292,35 @@ int cb_alloc(socket_info_t * s)
dev->devfn = i;
dev->vendor = vend;
pci_readw(dev, PCI_DEVICE_ID, &dev->device);
- dev->hdr_type = hdr;
+ dev->hdr_type = hdr & 0x7f;
pci_setup_device(dev);
+
/* FIXME: Do we need to enable the expansion ROM? */
for (r = 0; r < 7; r++) {
struct resource *res = dev->resource + r;
- if (res->flags) {
- /* Unset resource address, assign new one! */
- res->end -= res->start;
- res->start = 0;
+ if (res->flags)
pci_assign_resource(dev, r);
- }
}
-
- list_add_tail(&dev->bus_list, &bus->devices);
- list_add_tail(&dev->global_list, &pci_devices);
- pci_proc_attach_device(dev);
pci_enable_device(dev);
+
+ /* Does this function have an interrupt at all? */
+ pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
+ if (irq_pin) {
+ if (!irq)
+ irq = cb_assign_irq(s->cap.irq_mask);
+ dev->irq = irq;
+ pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
+ }
+
+ pci_insert_device(dev, bus);
}
s->cb_config = c;
+ s->irq.AssignedIRQ = irq;
return CS_SUCCESS;
}
-static void free_resources(struct pci_dev *dev)
-{
- int i;
-
- for (i = 0; i < 7; i++) {
- struct resource *res = dev->resource + i;
- if (res->parent)
- release_resource(res);
- }
-}
-
void cb_free(socket_info_t * s)
{
cb_config_t *c = s->cb_config;
@@ -349,14 +329,9 @@ void cb_free(socket_info_t * s)
int i;
s->cb_config = NULL;
- for(i=0; i<s->functions; i++) {
- struct pci_dev *dev = &c[i].dev;
+ for (i = 0 ; i < s->functions ; i++)
+ pci_remove_device(&c[i].dev);
- list_del(&dev->bus_list);
- list_del(&dev->global_list);
- free_resources(dev);
- pci_proc_detach_device(dev);
- }
kfree(c);
printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
}
@@ -374,54 +349,8 @@ void cb_free(socket_info_t * s)
======================================================================*/
-static int cb_assign_irq(u32 mask)
-{
- int irq, try;
-
- for (try = 0; try < 2; try++) {
- for (irq = 1; irq < 32; irq++) {
- if ((mask >> irq) & 1) {
- if (try_irq(IRQ_TYPE_EXCLUSIVE, irq, try) == 0)
- return irq;
- }
- }
- }
- return 0;
-}
-
int cb_config(socket_info_t * s)
{
- cb_config_t *c = s->cb_config;
- u_char fn = s->functions;
- int i, irq;
-
- printk(KERN_INFO "cs: cb_config(bus %d)\n", s->cap.cb_dev->subordinate->number);
-
- /*
- * If we have a PCI interrupt for the bridge,
- * then use that..
- */
- irq = s->cap.pci_irq;
-
- for (i = 0; i < fn; i++) {
- struct pci_dev *dev = &c[i].dev;
- u8 irq_pin;
-
- /* Does this function have an interrupt at all? */
- pci_readb(dev, PCI_INTERRUPT_PIN, &irq_pin);
- if (!irq_pin)
- continue;
-
- if (!irq) {
- irq = cb_assign_irq(s->cap.irq_mask);
- if (!irq)
- return CS_OUT_OF_RESOURCE;
- }
-
- dev->irq = irq;
- pci_writeb(dev, PCI_INTERRUPT_LINE, irq);
- }
- s->irq.AssignedIRQ = irq;
return CS_SUCCESS;
}
diff --git a/drivers/pcmcia/cb_enabler.c b/drivers/pcmcia/cb_enabler.c
index bb8fe17b2..0e5ddeb93 100644
--- a/drivers/pcmcia/cb_enabler.c
+++ b/drivers/pcmcia/cb_enabler.c
@@ -1,8 +1,8 @@
/*======================================================================
- Cardbus device enabler
+ CardBus device enabler
- cb_enabler.c 1.25 1999/10/25 20:03:33
+ cb_enabler.c 1.28 1999/12/09 20:57:37
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -58,11 +58,14 @@ static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static char *version =
-"cb_enabler.c 1.25 1999/10/25 20:03:33 (David Hinds)";
+"cb_enabler.c 1.28 1999/12/09 20:57:37 (David Hinds)";
#else
#define DEBUG(n, args...) do { } while (0)
#endif
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("CardBus stub enabler module");
+
/*====================================================================*/
/* Parameters that can be set with 'insmod' */
@@ -126,10 +129,11 @@ struct dev_link_t *cb_attach(int n)
DEBUG(0, "cb_attach(%d)\n", n);
- MOD_INC_USE_COUNT;
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
- memset(link, 0, sizeof(struct dev_link_t));
+ if (!link) return NULL;
+ MOD_INC_USE_COUNT;
+ memset(link, 0, sizeof(struct dev_link_t));
link->conf.IntType = INT_CARDBUS;
link->conf.Vcc = 33;
@@ -142,7 +146,7 @@ struct dev_link_t *cb_attach(int n)
client_reg.dev_info = &driver[n].dev_info;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.event_handler = &cb_event;
- client_reg.EventMask =
+ client_reg.EventMask = CS_EVENT_RESET_PHYSICAL |
CS_EVENT_RESET_REQUEST | CS_EVENT_CARD_RESET |
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
@@ -186,7 +190,7 @@ static void cb_detach(dev_link_t *link)
pcmcia_deregister_client(link->handle);
*linkp = link->next;
- kfree_s(link, sizeof(struct dev_link_t));
+ kfree(link);
MOD_DEC_USE_COUNT;
}
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index eb287bee9..acca17316 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -2,7 +2,7 @@
PCMCIA Card Information Structure parser
- cistpl.c 1.74 1999/11/08 20:47:02
+ cistpl.c 1.77 2000/01/16 19:19:01
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -52,6 +52,7 @@
#include <pcmcia/ss.h>
#include <pcmcia/cs.h>
#include <pcmcia/bulkmem.h>
+#include <pcmcia/cisreg.h>
#include <pcmcia/cistpl.h>
#include "cs_internal.h"
#include "rsrc_mgr.h"
@@ -83,12 +84,15 @@ static const u_int exponent[] = {
======================================================================*/
+/* Bits in attr field */
+#define IS_ATTR 1
+#define IS_INDIRECT 8
+
void read_cis_mem(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr)
{
pccard_mem_map *mem = &s->cis_mem;
- u_char *sys;
- u_int inc = 1;
+ u_char *sys, *buf = ptr;
DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (setup_cis_mem(s) != 0) {
@@ -96,47 +100,81 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr,
return;
}
mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
- if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
- sys = s->cis_virt + (addr & (s->cap.map_size-1));
- mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
+ sys = s->cis_virt;
+
+ if (attr & IS_INDIRECT) {
+ /* Indirect accesses use a bunch of special registers at fixed
+ locations in common memory */
+ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+ if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
+ mem->card_start = 0;
s->ss_entry->set_mem_map(s->sock, mem);
- DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
- bus_readb(s->cap.bus, sys),
- bus_readb(s->cap.bus, sys+inc),
- bus_readb(s->cap.bus, sys+2*inc),
- bus_readb(s->cap.bus, sys+3*inc),
- bus_readb(s->cap.bus, sys+4*inc));
- for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) {
- if (sys == s->cis_virt+s->cap.map_size) break;
- *(u_char *)ptr = bus_readb(s->cap.bus, sys);
+ bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
+ bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
+ bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
+ bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+ bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0);
+ } else {
+ u_int inc = 1;
+ if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
+ sys += (addr & (s->cap.map_size-1));
+ mem->card_start = addr & ~(s->cap.map_size-1);
+
+ for (; len > 0; sys = s->cis_virt) {
+ s->ss_entry->set_mem_map(s->sock, mem);
+ for ( ; len > 0; len--, buf++, sys += inc) {
+ if (sys == s->cis_virt+s->cap.map_size) break;
+ *buf = bus_readb(s->cap.bus, sys);
+ }
+ mem->card_start += s->cap.map_size;
}
- mem->card_start += s->cap.map_size;
}
+ DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
+ *(u_char *)(ptr+0), *(u_char *)(ptr+1),
+ *(u_char *)(ptr+2), *(u_char *)(ptr+3));
}
void write_cis_mem(socket_info_t *s, int attr, u_int addr,
u_int len, void *ptr)
{
pccard_mem_map *mem = &s->cis_mem;
- u_char *sys;
- int inc = 1;
+ u_char *sys, *buf = ptr;
DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
if (setup_cis_mem(s) != 0) return;
- mem->flags &= ~MAP_ATTRIB;
- if (attr) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
- sys = s->cis_virt + (addr & (s->cap.map_size-1));
- mem->card_start = addr & ~(s->cap.map_size-1);
-
- for (; len > 0; sys = s->cis_virt) {
+ mem->flags |= MAP_ACTIVE; mem->flags &= ~MAP_ATTRIB;
+ sys = s->cis_virt;
+
+ if (attr & IS_INDIRECT) {
+ /* Indirect accesses use a bunch of special registers at fixed
+ locations in common memory */
+ u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
+ if (attr & IS_ATTR) { addr *= 2; flags = ICTRL0_AUTOINC; }
+ mem->card_start = 0;
s->ss_entry->set_mem_map(s->sock, mem);
- for ( ; len > 0; len--, ((u_char *)ptr)++, sys += inc) {
- if (sys == s->cis_virt+s->cap.map_size) break;
- bus_writeb(s->cap.bus, *(u_char *)ptr, sys);
+ bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0);
+ bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0);
+ bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1);
+ bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2);
+ bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3);
+ for ( ; len > 0; len--, buf++)
+ bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0);
+ } else {
+ int inc = 1;
+ if (attr & IS_ATTR) { mem->flags |= MAP_ATTRIB; inc++; addr *= 2; }
+ sys += (addr & (s->cap.map_size-1));
+ mem->card_start = addr & ~(s->cap.map_size-1);
+
+ for (; len > 0; sys = s->cis_virt) {
+ s->ss_entry->set_mem_map(s->sock, mem);
+ for ( ; len > 0; len--, buf++, sys += inc) {
+ if (sys == s->cis_virt+s->cap.map_size) break;
+ bus_writeb(s->cap.bus, *buf, sys);
+ }
+ mem->card_start += s->cap.map_size;
}
- mem->card_start += s->cap.map_size;
}
}
@@ -342,10 +380,10 @@ int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis)
======================================================================*/
typedef struct tuple_flags {
- u_int link_space:3;
+ u_int link_space:4;
u_int has_link:1;
u_int mfc_fn:3;
- u_int space:3;
+ u_int space:4;
} tuple_flags;
#define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
@@ -469,18 +507,24 @@ int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
(link[0] == CISTPL_LONGLINK_C) ||
(link[0] == CISTPL_LONGLINK_MFC) ||
(link[0] == CISTPL_LINKTARGET) ||
+ (link[0] == CISTPL_INDIRECT) ||
(link[0] == CISTPL_NO_LINK)) {
switch (link[0]) {
case CISTPL_LONGLINK_A:
HAS_LINK(tuple->Flags) = 1;
- LINK_SPACE(tuple->Flags) = 1;
+ LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
break;
case CISTPL_LONGLINK_C:
HAS_LINK(tuple->Flags) = 1;
- LINK_SPACE(tuple->Flags) = 0;
+ LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
break;
+ case CISTPL_INDIRECT:
+ HAS_LINK(tuple->Flags) = 1;
+ LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
+ tuple->LinkOffset = 0;
+ break;
case CISTPL_LONGLINK_MFC:
tuple->LinkOffset = ofs + 3;
LINK_SPACE(tuple->Flags) = attr;
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index d44d505ca..bd671c1b2 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -2,7 +2,7 @@
PCMCIA Card Services -- core services
- cs.c 1.235 1999/11/11 17:52:05
+ cs.c 1.247 2000/01/15 04:30:35
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -59,7 +59,6 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/bus_ops.h>
-
#include "cs_internal.h"
#include "rsrc_mgr.h"
@@ -72,28 +71,40 @@ static int handle_apm_event(apm_event_t event);
int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
static const char *version =
-"cs.c 1.235 1999/11/11 17:52:05 (David Hinds)";
+"cs.c 1.247 2000/01/15 04:30:35 (David Hinds)";
#endif
-static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
-#ifdef MODULE
-static const char *kernel = "kernel build: " UTS_RELEASE " " UTS_VERSION;
-#endif
-static const char *options = "options: "
#ifdef CONFIG_PCI
-" [pci]"
+#define PCI_OPT " [pci]"
+#else
+#define PCI_OPT ""
#endif
#ifdef CONFIG_CARDBUS
-" [cardbus]"
+#define CB_OPT " [cardbus]"
+#else
+#define CB_OPT ""
#endif
#ifdef CONFIG_APM
-" [apm]"
+#define APM_OPT " [apm]"
+#else
+#define APM_OPT ""
#endif
#if !defined(CONFIG_CARDBUS) && !defined(CONFIG_PCI) && \
- !defined(CONFIG_APM) && !defined(CONFIG_PNP_BIOS)
-" none"
+ !defined(CONFIG_APM)
+#define OPTIONS " none"
+#else
+#define OPTIONS PCI_OPT CB_OPT APM_OPT
+#endif
+
+static const char *release = "Linux PCMCIA Card Services " CS_RELEASE;
+#ifdef MODULE
+static const char *kernel = "kernel build: " UTS_RELEASE " " UTS_VERSION;
#endif
-;
+static const char *options = "options: " OPTIONS;
+
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("Linux PCMCIA Card Services " CS_RELEASE
+ "\n options:" OPTIONS);
/*====================================================================*/
@@ -263,11 +274,6 @@ static int set_socket(socket_info_t *s, socket_state_t *state)
return s->ss_entry->set_socket(s->sock, state);
}
-static int get_io_map(socket_info_t *s, struct pccard_io_map *io)
-{
- return s->ss_entry->get_io_map(s->sock, io);
-}
-
static int set_io_map(socket_info_t *s, struct pccard_io_map *io)
{
return s->ss_entry->set_io_map(s->sock, io);
@@ -734,18 +740,18 @@ static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,
int i;
ioaddr_t try, align;
- align = (*base) ? (1<<lines) : 1;
+ align = (*base) ? (lines ? 1<<lines : 0) : 1;
if (align && (align < num)) {
- printk(KERN_INFO "odd IO request: num %04x align %04x\n",
- num, align);
- if (*base)
+ if (*base) {
+ DEBUG(0, "odd IO request: num %04x align %04x\n",
+ num, align);
align = 0;
- else
+ } else
while (align && (align < num)) align <<= 1;
}
if (*base & ~(align-1)) {
- printk(KERN_INFO "odd IO request: base %04x align %04x\n",
- *base, align);
+ DEBUG(0, "odd IO request: base %04x align %04x\n",
+ *base, align);
align = 0;
}
for (i = 0; i < MAX_IO_WIN; i++) {
@@ -862,6 +868,7 @@ int pcmcia_bind_device(bind_req_t *req)
s = SOCKET(req);
client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL);
+ if (!client) return CS_OUT_OF_RESOURCE;
memset(client, '\0', sizeof(client_t));
client->client_magic = CLIENT_MAGIC;
strncpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN);
@@ -1122,18 +1129,18 @@ int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req)
if (win->ctl.flags & MAP_ACTIVE)
req->Attributes |= WIN_ENABLE;
if (win->ctl.flags & MAP_16BIT)
- req->Attributes |= WIN_DATA_WIDTH;
+ req->Attributes |= WIN_DATA_WIDTH_16;
if (win->ctl.flags & MAP_USE_WAIT)
req->Attributes |= WIN_USE_WAIT;
*handle = win;
return CS_SUCCESS;
} /* get_window */
-int pcmcia_get_first_window(client_handle_t *handle, win_req_t *req)
+int pcmcia_get_first_window(window_handle_t *win, win_req_t *req)
{
- if ((handle == NULL) || CHECK_HANDLE(*handle))
+ if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC))
return CS_BAD_HANDLE;
- return pcmcia_get_window((window_handle_t *)handle, 0, req);
+ return pcmcia_get_window(win, 0, req);
}
int pcmcia_get_next_window(window_handle_t *win, win_req_t *req)
@@ -1143,6 +1150,29 @@ int pcmcia_get_next_window(window_handle_t *win, win_req_t *req)
return pcmcia_get_window(win, (*win)->index+1, req);
}
+/*=====================================================================
+
+ Return the PCI device associated with a card..
+
+======================================================================*/
+
+#ifdef CONFIG_CARDBUS
+
+struct pci_bus *pcmcia_lookup_bus(client_handle_t handle)
+{
+ socket_info_t *s;
+
+ if (CHECK_HANDLE(handle))
+ return NULL;
+ s = SOCKET(handle);
+ if (!(s->state & SOCKET_CARDBUS))
+ return NULL;
+
+ return s->cap.cb_dev->subordinate;
+}
+
+#endif
+
/*======================================================================
Get the current socket state bits. We don't support the latched
@@ -1308,7 +1338,7 @@ int pcmcia_modify_window(window_handle_t win, modwin_t *req)
win->ctl.flags |= MAP_ATTRIB;
if (req->Attributes & WIN_ENABLE)
win->ctl.flags |= MAP_ACTIVE;
- if (req->Attributes & WIN_DATA_WIDTH)
+ if (req->Attributes & WIN_DATA_WIDTH_16)
win->ctl.flags |= MAP_16BIT;
if (req->Attributes & WIN_USE_WAIT)
win->ctl.flags |= MAP_USE_WAIT;
@@ -1403,7 +1433,7 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
int pcmcia_release_configuration(client_handle_t handle)
{
- pccard_io_map io;
+ pccard_io_map io = { 0, 0, 0, 0, 1 };
socket_info_t *s;
int i;
@@ -1437,8 +1467,6 @@ int pcmcia_release_configuration(client_handle_t handle)
if (s->io[i].Config != 0)
continue;
io.map = i;
- get_io_map(s, &io);
- io.flags &= ~MAP_ACTIVE;
set_io_map(s, &io);
}
c->state &= ~CONFIG_LOCKED;
@@ -1840,7 +1868,8 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
{
socket_info_t *s;
window_t *win;
- int w, align;
+ u_long align;
+ int w;
if (CHECK_HANDLE(*handle))
return CS_BAD_HANDLE;
@@ -1850,16 +1879,25 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
if (req->Attributes & (WIN_PAGED | WIN_SHARED))
return CS_BAD_ATTRIBUTE;
- for (w = 0; w < MAX_WIN; w++)
- if (!(s->state & SOCKET_WIN_REQ(w))) break;
- if (w == MAX_WIN)
- return CS_OUT_OF_RESOURCE;
-
/* Window size defaults to smallest available */
if (req->Size == 0)
req->Size = s->cap.map_size;
+ align = (((s->cap.features & SS_CAP_MEM_ALIGN) ||
+ (req->Attributes & WIN_STRICT_ALIGN)) ?
+ req->Size : s->cap.map_size);
+ if (req->Size & (s->cap.map_size-1))
+ return CS_BAD_SIZE;
+ if (req->Base & (align-1))
+ return CS_BAD_BASE;
+ if (req->Base)
+ align = 0;
/* Allocate system memory window */
+ for (w = 0; w < MAX_WIN; w++)
+ if (!(s->state & SOCKET_WIN_REQ(w))) break;
+ if (w == MAX_WIN)
+ return CS_OUT_OF_RESOURCE;
+
win = &s->win[w];
win->magic = WINDOW_MAGIC;
win->index = w;
@@ -1867,10 +1905,8 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
win->sock = s;
win->base = req->Base;
win->size = req->Size;
- align = ((s->cap.features & SS_CAP_MEM_ALIGN) ||
- (req->Attributes & WIN_STRICT_ALIGN));
- if (find_mem_region(&win->base, win->size,
- (align ? req->Size : s->cap.map_size),
+
+ if (find_mem_region(&win->base, win->size, align,
(req->Attributes & WIN_MAP_BELOW_1MB) ||
!(s->cap.features & SS_CAP_PAGE_REGS),
(*handle)->dev_info))
@@ -1886,7 +1922,7 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle
win->ctl.flags |= MAP_ATTRIB;
if (req->Attributes & WIN_ENABLE)
win->ctl.flags |= MAP_ACTIVE;
- if (req->Attributes & WIN_DATA_WIDTH)
+ if (req->Attributes & WIN_DATA_WIDTH_16)
win->ctl.flags |= MAP_16BIT;
if (req->Attributes & WIN_USE_WAIT)
win->ctl.flags |= MAP_USE_WAIT;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 5a9b1a4e7..f85e2b4f9 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -2,7 +2,7 @@
PC Card Driver Services
- ds.c 1.100 1999/11/08 20:47:02
+ ds.c 1.104 2000/01/11 01:18:02
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -46,6 +46,7 @@
#include <linux/ioctl.h>
#include <linux/proc_fs.h>
#include <linux/poll.h>
+#include <linux/pci.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
@@ -59,11 +60,14 @@ int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
static const char *version =
-"ds.c 1.100 1999/11/08 20:47:02 (David Hinds)";
+"ds.c 1.104 2000/01/11 01:18:02 (David Hinds)";
#else
#define DEBUG(n, args...)
#endif
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("PCMCIA Driver Services " CS_RELEASE);
+
/*====================================================================*/
typedef struct driver_info_t {
@@ -154,6 +158,7 @@ int register_pccard_driver(dev_info_t *dev_info,
break;
if (!driver) {
driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
+ if (!driver) return -ENOMEM;
strncpy(driver->dev_info, (char *)dev_info, DEV_NAME_LEN);
driver->use_count = 0;
driver->status = init_status;
@@ -192,7 +197,7 @@ int unregister_pccard_driver(dev_info_t *dev_info)
DEV_NAME_LEN) != 0))
d = &(*d)->next;
if (*d == NULL)
- return -1;
+ return -ENODEV;
target = *d;
if (target->use_count == 0) {
@@ -376,6 +381,7 @@ static int bind_request(int i, bind_info_t *bind_info)
break;
if (driver == NULL) {
driver = kmalloc(sizeof(driver_info_t), GFP_KERNEL);
+ if (!driver) return -ENOMEM;
strncpy(driver->dev_info, bind_info->dev_info, DEV_NAME_LEN);
driver->use_count = 0;
driver->next = root_driver;
@@ -429,15 +435,55 @@ static int get_device_info(int i, bind_info_t *bind_info, int first)
socket_info_t *s = &socket_table[i];
socket_bind_t *b;
dev_node_t *node;
-
+
+#ifdef CONFIG_CARDBUS
+ /*
+ * Some unbelievably ugly code to associate the PCI cardbus
+ * device and its driver with the PCMCIA "bind" information.
+ */
+ {
+ struct pci_bus *bus;
+
+ bus = pcmcia_lookup_bus(s->handle);
+ if (bus) {
+ struct list_head *list;
+ struct pci_dev *dev = NULL;
+
+ list = bus->devices.next;
+ while (list != &bus->devices) {
+ struct pci_dev *pdev = pci_dev_b(list);
+ list = list->next;
+
+ if (first) {
+ dev = pdev;
+ break;
+ }
+
+ /* Try to handle "next" here some way? */
+ }
+ if (dev && dev->driver) {
+ strncpy(bind_info->name, dev->driver->name, DEV_NAME_LEN);
+ bind_info->name[DEV_NAME_LEN-1] = '\0';
+ bind_info->major = 0;
+ bind_info->minor = 0;
+ bind_info->next = NULL;
+ return 0;
+ }
+ }
+ }
+#endif
+
for (b = s->bind; b; b = b->next)
if (strcmp((char *)b->driver->dev_info,
(char *)bind_info->dev_info) == 0)
break;
if (b == NULL) return -ENODEV;
- if ((b->instance == NULL) ||
- (b->instance->state & DEV_CONFIG_PENDING))
+
+ if (b->instance == NULL)
return -EAGAIN;
+ if (b->instance->state & DEV_CONFIG_PENDING)
+ return -EAGAIN;
+
if (first)
node = b->instance->dev;
else
@@ -481,11 +527,11 @@ static int unbind_request(int i, bind_info_t *bind_info)
for (d = &root_driver; *d; d = &((*d)->next))
if (c->driver == *d) break;
*d = (*d)->next;
- kfree_s(c->driver, sizeof(driver_info_t));
+ kfree(c->driver);
}
}
*b = c->next;
- kfree_s(c, sizeof(socket_bind_t));
+ kfree(c);
return 0;
} /* unbind_request */
@@ -513,8 +559,9 @@ static int ds_open(struct inode *inode, struct file *file)
s->state |= SOCKET_BUSY;
}
- MOD_INC_USE_COUNT;
user = kmalloc(sizeof(user_info_t), GFP_KERNEL);
+ if (!user) return -ENOMEM;
+ MOD_INC_USE_COUNT;
user->event_tail = user->event_head = 0;
user->next = s->user;
user->user_magic = USER_MAGIC;
@@ -552,7 +599,7 @@ static int ds_release(struct inode *inode, struct file *file)
return 0;
*link = user->next;
user->user_magic = 0;
- kfree_s(user, sizeof(user_info_t));
+ kfree(user);
MOD_DEC_USE_COUNT;
return 0;
@@ -663,7 +710,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
if (size > sizeof(ds_ioctl_arg_t)) return -EINVAL;
/* Permission check */
- if (!(cmd & IOC_OUT) && !suser())
+ if (!(cmd & IOC_OUT) && !capable(CAP_SYS_ADMIN))
return -EPERM;
if (cmd & IOC_IN) {
@@ -732,7 +779,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pcmcia_insert_card(s->handle, NULL);
break;
case DS_ACCESS_CONFIGURATION_REGISTER:
- if ((buf.conf_reg.Action == CS_WRITE) && !suser())
+ if ((buf.conf_reg.Action == CS_WRITE) && !capable(CAP_SYS_ADMIN))
return -EPERM;
ret = pcmcia_access_configuration_register(s->handle, &buf.conf_reg);
break;
@@ -757,7 +804,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
ret = pcmcia_replace_cis(s->handle, &buf.cisdump);
break;
case DS_BIND_REQUEST:
- if (!suser()) return -EPERM;
+ if (!capable(CAP_SYS_ADMIN)) return -EPERM;
err = bind_request(i, &buf.bind_info);
break;
case DS_GET_DEVICE_INFO:
@@ -806,17 +853,12 @@ static int ds_ioctl(struct inode * inode, struct file * file,
/*====================================================================*/
static struct file_operations ds_fops = {
- NULL, /* lseek */
- ds_read, /* read */
- ds_write, /* write */
- NULL, /* readdir */
- ds_poll, /* poll */
- ds_ioctl, /* ioctl */
- NULL, /* mmap */
- ds_open, /* open */
- NULL, /* flush */
- ds_release, /* release */
- NULL /* fsync */
+ open: ds_open,
+ release: ds_release,
+ ioctl: ds_ioctl,
+ read: ds_read,
+ write: ds_write,
+ poll: ds_poll
};
EXPORT_SYMBOL(register_pccard_driver);
@@ -846,6 +888,7 @@ int __init init_pcmcia_ds(void)
sockets = serv.Count;
socket_table = kmalloc(sockets*sizeof(socket_info_t), GFP_KERNEL);
+ if (!socket_table) return -1;
for (i = 0, s = socket_table; i < sockets; i++, s++) {
s->state = 0;
s->user = NULL;
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 8c96585c6..73c177d8d 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -66,7 +66,6 @@
/* PCI-bus controllers */
#include "old-yenta.h"
-#include "ti113x.h"
#include "smc34c90.h"
#include "topic.h"
diff --git a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c
index 51981e41e..3f4463e75 100644
--- a/drivers/pcmcia/pci_socket.c
+++ b/drivers/pcmcia/pci_socket.c
@@ -70,9 +70,8 @@ static int pci_inquire_socket(unsigned int sock, socket_cap_t *cap)
{
pci_socket_t *socket = pci_socket_array + sock;
- if (socket->op && socket->op->inquire)
- return socket->op->inquire(socket, cap);
- return -EINVAL;
+ *cap = socket->cap;
+ return 0;
}
static int pci_get_status(unsigned int sock, unsigned int *value)
@@ -166,8 +165,10 @@ static int __init add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_
{
pci_socket_t *socket = nr + pci_socket_array;
+ memset(socket, 0, sizeof(*socket));
socket->dev = dev;
socket->op = ops;
+ init_waitqueue_head(&socket->wait);
return socket->op->open(socket);
}
diff --git a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h
index 41ea4ec09..8db7c68b5 100644
--- a/drivers/pcmcia/pci_socket.h
+++ b/drivers/pcmcia/pci_socket.h
@@ -4,6 +4,9 @@
* (C) Copyright 1999 Linus Torvalds
*/
+#ifndef __PCI_SOCKET_H
+#define __PCI_SOCKET_H
+
struct pci_socket_ops;
typedef struct pci_socket {
@@ -14,7 +17,11 @@ typedef struct pci_socket {
void *info;
struct pci_socket_ops *op;
socket_cap_t cap;
- struct timer_list timer;
+ wait_queue_head_t wait;
+ unsigned int events;
+
+ /* A few words of private data for the low-level driver.. */
+ unsigned int private[8];
} pci_socket_t;
struct pci_socket_ops {
@@ -23,7 +30,6 @@ struct pci_socket_ops {
int (*init)(struct pci_socket *);
int (*suspend)(struct pci_socket *);
- int (*inquire)(struct pci_socket *, socket_cap_t *cap);
int (*get_status)(struct pci_socket *, unsigned int *);
int (*get_socket)(struct pci_socket *, socket_state_t *);
int (*set_socket)(struct pci_socket *, socket_state_t *);
@@ -37,3 +43,4 @@ struct pci_socket_ops {
extern struct pci_socket_ops yenta_operations;
extern struct pci_socket_ops ricoh_operations;
+#endif
diff --git a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h
index 8cfd30dac..3084dd5b9 100644
--- a/drivers/pcmcia/ricoh.h
+++ b/drivers/pcmcia/ricoh.h
@@ -30,6 +30,8 @@
#ifndef _LINUX_RICOH_H
#define _LINUX_RICOH_H
+#include <linux/config.h>
+
#define RF5C_MODE_CTL 0x1f /* Mode control */
#define RF5C_PWR_CTL 0x2f /* Mixed voltage control */
#define RF5C_CHIP_ID 0x3a /* Chip identification */
@@ -70,25 +72,6 @@
/* Register definitions for Ricoh PCI-to-CardBus bridges */
-#ifndef PCI_VENDOR_ID_RICOH
-#define PCI_VENDOR_ID_RICOH 0x1180
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C465
-#define PCI_DEVICE_ID_RICOH_RL5C465 0x0465
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C466
-#define PCI_DEVICE_ID_RICOH_RL5C466 0x0466
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C475
-#define PCI_DEVICE_ID_RICOH_RL5C475 0x0475
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C476
-#define PCI_DEVICE_ID_RICOH_RL5C476 0x0476
-#endif
-#ifndef PCI_DEVICE_ID_RICOH_RL5C478
-#define PCI_DEVICE_ID_RICOH_RL5C478 0x0478
-#endif
-
/* Extra bits in CB_BRIDGE_CONTROL */
#define RL5C46X_BCR_3E0_ENA 0x0800
#define RL5C46X_BCR_3E2_ENA 0x1000
@@ -129,4 +112,55 @@
#define RL5C4XX_HOLD_MASK 0x1c00
#define RL5C4XX_HOLD_SHIFT 10
+#ifdef __YENTA_H
+
+#define rl_misc(socket) ((socket)->private[0])
+#define rl_ctl(socket) ((socket)->private[1])
+#define rl_io(socket) ((socket)->private[2])
+#define rl_mem(socket) ((socket)->private[3])
+
+/*
+ * Magic Ricoh initialization code.. Save state at
+ * beginning, re-initialize it after suspend.
+ */
+static int ricoh_open(pci_socket_t *socket)
+{
+ rl_misc(socket) = config_readw(socket, RL5C4XX_MISC);
+ rl_ctl(socket) = config_readw(socket, RL5C4XX_16BIT_CTL);
+ rl_io(socket) = config_readw(socket, RL5C4XX_16BIT_IO_0);
+ rl_mem(socket) = config_readw(socket, RL5C4XX_16BIT_MEM_0);
+
+ /* Set the default timings, don't trust the original values */
+ rl_ctl(socket) = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
+ return 0;
+}
+
+static int ricoh_init(pci_socket_t *socket)
+{
+ yenta_init(socket);
+
+ config_writew(socket, RL5C4XX_MISC, rl_misc(socket));
+ config_writew(socket, RL5C4XX_16BIT_CTL, rl_ctl(socket));
+ config_writew(socket, RL5C4XX_16BIT_IO_0, rl_io(socket));
+ config_writew(socket, RL5C4XX_16BIT_MEM_0, rl_mem(socket));
+ return 0;
+}
+
+static struct pci_socket_ops ricoh_ops = {
+ ricoh_open,
+ yenta_close,
+ ricoh_init,
+ yenta_suspend,
+ yenta_get_status,
+ yenta_get_socket,
+ yenta_set_socket,
+ yenta_get_io_map,
+ yenta_set_io_map,
+ yenta_get_mem_map,
+ yenta_set_mem_map,
+ yenta_proc_setup
+};
+
+#endif /* CONFIG_CARDBUS */
+
#endif /* _LINUX_RICOH_H */
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index 569ff8678..d059c4fdb 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -2,7 +2,7 @@
Resource management routines
- rsrc_mgr.c 1.76 1999/11/08 20:47:02
+ rsrc_mgr.c 1.77 1999/11/16 03:32:59
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -124,10 +124,11 @@ static int add_interval(resource_map_t *map, u_long base, u_long num)
break;
}
q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
+ if (!q) return CS_OUT_OF_RESOURCE;
q->base = base; q->num = num;
q->next = p->next; p->next = q;
- return 0;
-} /* add_interval */
+ return CS_SUCCESS;
+}
/*====================================================================*/
@@ -158,6 +159,7 @@ static int sub_interval(resource_map_t *map, u_long base, u_long num)
} else {
/* Split the block into two pieces */
p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
+ if (!p) return CS_OUT_OF_RESOURCE;
p->base = base+num;
p->num = q->base+q->num - p->base;
q->num = base - q->base;
@@ -165,8 +167,8 @@ static int sub_interval(resource_map_t *map, u_long base, u_long num)
}
}
}
- return 0;
-} /* sub_interval */
+ return CS_SUCCESS;
+}
/*======================================================================
@@ -383,7 +385,7 @@ int find_io_region(ioaddr_t *base, ioaddr_t num, ioaddr_t align,
}
}
return -1;
-} /* find_io_region */
+}
int find_mem_region(u_long *base, u_long num, u_long align,
int force_low, char *name)
@@ -411,7 +413,7 @@ int find_mem_region(u_long *base, u_long num, u_long align,
force_low++;
}
return -1;
-} /* find_mem_region */
+}
/*======================================================================
@@ -482,7 +484,7 @@ int try_irq(u_int Attributes, int irq, int specific)
}
}
return 0;
-} /* try_irq */
+}
#endif
@@ -524,34 +526,35 @@ void undo_irq(u_int Attributes, int irq)
static int adjust_memory(adjust_t *adj)
{
u_long base, num;
- int i;
+ int i, ret;
base = adj->resource.memory.Base;
num = adj->resource.memory.Size;
if ((num == 0) || (base+num-1 < base))
return CS_BAD_SIZE;
+ ret = CS_SUCCESS;
switch (adj->Action) {
case ADD_MANAGED_RESOURCE:
- if (add_interval(&mem_db, base, num) != 0)
- return CS_IN_USE;
+ ret = add_interval(&mem_db, base, num);
break;
case REMOVE_MANAGED_RESOURCE:
- sub_interval(&mem_db, base, num);
- for (i = 0; i < sockets; i++) {
- release_cis_mem(socket_table[i]);
+ ret = sub_interval(&mem_db, base, num);
+ if (ret == CS_SUCCESS) {
+ for (i = 0; i < sockets; i++) {
+ release_cis_mem(socket_table[i]);
#ifdef CONFIG_CARDBUS
- cb_release_cis_mem(socket_table[i]);
+ cb_release_cis_mem(socket_table[i]);
#endif
+ }
}
break;
default:
- return CS_UNSUPPORTED_FUNCTION;
- break;
+ ret = CS_UNSUPPORTED_FUNCTION;
}
- return CS_SUCCESS;
-} /* adjust_mem */
+ return ret;
+}
/*====================================================================*/
@@ -584,7 +587,7 @@ static int adjust_io(adjust_t *adj)
}
return CS_SUCCESS;
-} /* adjust_io */
+}
/*====================================================================*/
@@ -625,7 +628,7 @@ static int adjust_irq(adjust_t *adj)
}
#endif
return CS_SUCCESS;
-} /* adjust_irq */
+}
/*====================================================================*/
@@ -646,7 +649,7 @@ int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
break;
}
return CS_UNSUPPORTED_FUNCTION;
-} /* adjust_resource_info */
+}
/*====================================================================*/
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index d5900c6f8..ff25ac893 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -2,7 +2,7 @@
Device driver for Databook TCIC-2 PCMCIA controller
- tcic.c 1.107 1999/10/25 20:03:34
+ tcic.c 1.108 1999/12/09 20:17:29
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@@ -60,12 +60,15 @@
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
static const char *version =
-"tcic.c 1.107 1999/10/25 20:03:34 (David Hinds)";
+"tcic.c 1.108 1999/12/09 20:17:29 (David Hinds)";
#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
#else
#define DEBUG(n, args...)
#endif
+MODULE_AUTHOR("David Hinds <dhinds@pcmcia.sourceforge.org>");
+MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
+
/*====================================================================*/
/* Parameters that can be set with 'insmod' */
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index f37faeba5..b8664c6b5 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -30,49 +30,7 @@
#ifndef _LINUX_TI113X_H
#define _LINUX_TI113X_H
-#ifndef PCI_VENDOR_ID_TI
-#define PCI_VENDOR_ID_TI 0x104c
-#endif
-
-#ifndef PCI_DEVICE_ID_TI_1130
-#define PCI_DEVICE_ID_TI_1130 0xac12
-#endif
-#ifndef PCI_DEVICE_ID_TI_1131
-#define PCI_DEVICE_ID_TI_1131 0xac15
-#endif
-#ifndef PCI_DEVICE_ID_TI_1031
-#define PCI_DEVICE_ID_TI_1031 0xac13
-#endif
-#ifndef PCI_DEVICE_ID_TI_1250A
-#define PCI_DEVICE_ID_TI_1250A 0xac16
-#endif
-#ifndef PCI_DEVICE_ID_TI_1220
-#define PCI_DEVICE_ID_TI_1220 0xac17
-#endif
-#ifndef PCI_DEVICE_ID_TI_1221
-#define PCI_DEVICE_ID_TI_1221 0xac19
-#endif
-#ifndef PCI_DEVICE_ID_TI_1210
-#define PCI_DEVICE_ID_TI_1210 0xac1a
-#endif
-#ifndef PCI_DEVICE_ID_TI_1450
-#define PCI_DEVICE_ID_TI_1450 0xac1b
-#endif
-#ifndef PCI_DEVICE_ID_TI_1225
-#define PCI_DEVICE_ID_TI_1225 0xac1c
-#endif
-#ifndef PCI_DEVICE_ID_TI_1251A
-#define PCI_DEVICE_ID_TI_1251A 0xac1d
-#endif
-#ifndef PCI_DEVICE_ID_TI_1211
-#define PCI_DEVICE_ID_TI_1211 0xac1e
-#endif
-#ifndef PCI_DEVICE_ID_TI_1251B
-#define PCI_DEVICE_ID_TI_1251B 0xac1f
-#endif
-#ifndef PCI_DEVICE_ID_TI_1420
-#define PCI_DEVICE_ID_TI_1420 0xac51
-#endif
+#include <linux/config.h>
/* Register definitions for TI 113X PCI-to-CardBus bridges */
@@ -176,5 +134,86 @@
/* ExCA IO offset registers */
#define TI113X_IO_OFFSET(map) (0x36+((map)<<1))
+#ifdef CONFIG_CARDBUS
+
+#define ti_sysctl(socket) ((socket)->private[0])
+#define ti_cardctl(socket) ((socket)->private[1])
+#define ti_devctl(socket) ((socket)->private[2])
+
+static int ti113x_open(pci_socket_t *socket)
+{
+ ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ ti_cardctl(socket) = config_readb(socket, TI113X_CARD_CONTROL);
+ ti_devctl(socket) = config_readb(socket, TI113X_DEVICE_CONTROL);
+
+ ti_cardctl(socket) &= ~(TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
+ if (socket->cb_irq)
+ ti_cardctl(socket) |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC | TI113X_CCR_PCI_IREQ;
+ return 0;
+}
+
+static int ti113x_init(pci_socket_t *socket)
+{
+ yenta_init(socket);
+
+ config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket));
+ config_writeb(socket, TI113X_CARD_CONTROL, ti_cardctl(socket));
+ config_writeb(socket, TI113X_DEVICE_CONTROL, ti_devctl(socket));
+
+ return 0;
+}
+
+static struct pci_socket_ops ti113x_ops = {
+ ti113x_open,
+ yenta_close,
+ ti113x_init,
+ yenta_suspend,
+ yenta_get_status,
+ yenta_get_socket,
+ yenta_set_socket,
+ yenta_get_io_map,
+ yenta_set_io_map,
+ yenta_get_mem_map,
+ yenta_set_mem_map,
+ yenta_proc_setup
+};
+
+#define ti_diag(socket) ((socket)->private[0])
+
+static int ti1250_open(pci_socket_t *socket)
+{
+ ti_diag(socket) = config_readb(socket, TI1250_DIAGNOSTIC);
+
+ ti_diag(socket) &= ~(TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ);
+ if (socket->cb_irq)
+ ti_diag(socket) |= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
+ return 0;
+}
+
+static int ti1250_init(pci_socket_t *socket)
+{
+ yenta_init(socket);
+
+ config_writeb(socket, TI1250_DIAGNOSTIC, ti_diag(socket));
+ return 0;
+}
+
+static struct pci_socket_ops ti1250_ops = {
+ ti1250_open,
+ yenta_close,
+ ti1250_init,
+ yenta_suspend,
+ yenta_get_status,
+ yenta_get_socket,
+ yenta_set_socket,
+ yenta_get_io_map,
+ yenta_set_io_map,
+ yenta_get_mem_map,
+ yenta_set_mem_map,
+ yenta_proc_setup
+};
+
+#endif /* CONFIG_CARDBUS */
+
#endif /* _LINUX_TI113X_H */
diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
index e686a6436..b5a2e35de 100644
--- a/drivers/pcmcia/yenta.c
+++ b/drivers/pcmcia/yenta.c
@@ -15,7 +15,6 @@
#include "yenta.h"
#include "i82365.h"
-#include "ricoh.h"
/* Don't ask.. */
#define to_cycles(ns) ((ns)/120)
@@ -68,12 +67,6 @@ static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val)
exca_writeb(socket, reg+1, val >> 8);
}
-static int yenta_inquire(pci_socket_t *socket, socket_cap_t *cap)
-{
- *cap = socket->cap;
- return 0;
-}
-
/*
* Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
* on what kind of card is inserted..
@@ -190,20 +183,22 @@ static int yenta_set_socket(pci_socket_t *socket, socket_state_t *state)
u16 bridge;
yenta_set_power(socket, state);
- bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_CRST;
+ socket->io_irq = state->io_irq;
+ bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR);
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0;
- bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
/* ISA interrupt control? */
- if (bridge & CB_BRIDGE_INTR) {
+ if (!socket->cb_irq) {
u8 intr = exca_readb(socket, I365_INTCTL);
intr = (intr & ~0xf) | state->io_irq;
exca_writeb(socket, I365_INTCTL, intr);
+ bridge |= CB_BRIDGE_INTR;
}
} else {
u8 reg;
+ bridge |= CB_BRIDGE_INTR;
reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA);
reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
@@ -385,13 +380,12 @@ static void yenta_proc_setup(pci_socket_t *socket, struct proc_dir_entry *base)
/* Not done yet */
}
-static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static unsigned int yenta_events(pci_socket_t *socket)
{
u8 csc;
u32 cb_event;
unsigned int events;
- pci_socket_t *socket = (pci_socket_t *) dev_id;
-
+
/* Clear interrupt status for the event */
cb_event = cb_readl(socket, CB_SOCKET_EVENT);
cb_writel(socket, CB_SOCKET_EVENT, cb_event);
@@ -407,16 +401,50 @@ static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
events |= (csc & I365_CSC_READY) ? SS_READY : 0;
}
+ return events;
+}
- if (events && socket->handler)
- socket->handler(socket->info, events);
+static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned int events;
+ pci_socket_t *socket = (pci_socket_t *) dev_id;
- mod_timer(&socket->timer, jiffies + HZ);
+ events = yenta_events(socket);
+ if (events) {
+ socket->events |= events;
+ wake_up_interruptible(&socket->wait);
+ }
}
-static void yenta_timer(unsigned long data)
+/*
+ * Watch a socket every second (and possibly in a
+ * more timely manner if the state change interrupt
+ * works..)
+ */
+static int yenta_socket_thread(void * data)
{
- yenta_interrupt(0, (pci_socket_t *) data, NULL);
+ pci_socket_t * socket = (pci_socket_t *) data;
+ DECLARE_WAITQUEUE(wait, current);
+
+ daemonize();
+ strcpy(current->comm, "CardBus Watcher");
+
+ do {
+ unsigned int events = socket->events | yenta_events(socket);
+
+ if (events) {
+ socket->events = 0;
+ if (socket->handler)
+ socket->handler(socket->info, events);
+ }
+
+ current->state = TASK_INTERRUPTIBLE;
+ add_wait_queue(&socket->wait, &wait);
+ if (!socket->events)
+ schedule_timeout(HZ);
+ remove_wait_queue(&socket->wait, &wait);
+ } while (!signal_pending(current));
+ return 0;
}
static unsigned int yenta_probe_irq(pci_socket_t *socket)
@@ -424,20 +452,10 @@ static unsigned int yenta_probe_irq(pci_socket_t *socket)
int i;
unsigned long val;
u16 bridge_ctrl;
+ u32 mask;
- /* Are we set up to route the IO irq to the PCI irq? */
+ /* Set up ISA irq routing to probe the ISA irqs.. */
bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
- if (socket->cb_irq) {
- if (bridge_ctrl & CB_BRIDGE_INTR) {
- bridge_ctrl &= ~CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
- }
- printk("CardBus: using PCI interrupt %d\n", socket->cb_irq);
- return 1 << socket->cb_irq;
- }
-
- /* Uhhuh. No PCI interrupt: try falling back on ISA interrupts */
- printk("CardBus: Hmm.. No PCI irq routing (irq%d).\n", socket->cb_irq);
if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
bridge_ctrl |= CB_BRIDGE_INTR;
config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
@@ -459,7 +477,13 @@ static unsigned int yenta_probe_irq(pci_socket_t *socket)
cb_writel(socket, CB_SOCKET_EVENT, -1);
}
cb_writel(socket, CB_SOCKET_MASK, 0);
- return probe_irq_mask(val) & 0xffff;
+
+ mask = probe_irq_mask(val) & 0xffff;
+
+ bridge_ctrl &= ~CB_BRIDGE_INTR;
+ config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
+
+ return mask;
}
static void yenta_clear_maps(pci_socket_t *socket)
@@ -483,6 +507,7 @@ static void yenta_clear_maps(pci_socket_t *socket)
/* Called at resume and initialization events */
static int yenta_init(pci_socket_t *socket)
{
+ u16 bridge;
struct pci_dev *dev = socket->dev;
pci_set_power_state(socket->dev, 0);
@@ -503,6 +528,19 @@ static int yenta_init(pci_socket_t *socket)
config_writeb(socket, PCI_SECONDARY_BUS, dev->subordinate->number);
config_writeb(socket, PCI_SUBORDINATE_BUS, dev->subordinate->number);
+ /*
+ * Set up the bridging state:
+ * - enable write posting.
+ * - memory window 0 prefetchable, window 1 non-prefetchable
+ * - PCI interrupts enabled if a PCI interrupt exists..
+ */
+ bridge = config_readw(socket, CB_BRIDGE_CONTROL);
+ bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
+ bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
+ if (!socket->cb_irq)
+ bridge |= CB_BRIDGE_INTR;
+ config_writew(socket, CB_BRIDGE_CONTROL, bridge);
+
exca_writeb(socket, I365_GBLCTL, 0x00);
exca_writeb(socket, I365_GENCTL, 0x00);
@@ -510,29 +548,6 @@ static int yenta_init(pci_socket_t *socket)
return 0;
}
-/*
- * More of an example than anything else... The standard
- * yenta init code works well enough - but this is how
- * you'd do it if you wanted to have a special init sequence.
- */
-static int ricoh_init(pci_socket_t *socket)
-{
- u16 misc = config_readw(socket, RL5C4XX_MISC);
- u16 ctl = config_readw(socket, RL5C4XX_16BIT_CTL);
- u16 io = config_readw(socket, RL5C4XX_16BIT_IO_0);
- u16 mem = config_readw(socket, RL5C4XX_16BIT_MEM_0);
-
- ctl = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
-
- config_writew(socket, RL5C4XX_MISC, misc);
- config_writew(socket, RL5C4XX_16BIT_CTL, ctl);
- config_writew(socket, RL5C4XX_16BIT_IO_0, io);
- config_writew(socket, RL5C4XX_16BIT_MEM_0, mem);
-
- return yenta_init(socket);
-}
-
-
static int yenta_suspend(pci_socket_t *socket)
{
yenta_set_socket(socket, &dead_socket);
@@ -552,7 +567,7 @@ static void yenta_get_socket_capabilities(pci_socket_t *socket)
socket->cap.cb_dev = socket->dev;
socket->cap.bus = NULL;
- printk("Yenta IRQ list %04x\n", socket->cap.irq_mask);
+ printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);
}
static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
@@ -585,11 +600,11 @@ static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
}
align = size = 4*1024*1024;
- min = 0x10000000; max = ~0U;
+ min = PCIBIOS_MIN_MEM; max = ~0U;
if (type & IORESOURCE_IO) {
align = 1024;
size = 256;
- min = 0x1000;
+ min = PCIBIOS_MIN_IO;
max = 0xffff;
}
@@ -611,12 +626,50 @@ static void yenta_allocate_resources(pci_socket_t *socket)
}
/*
+ * Close it down - release our resources and go home..
+ */
+static void yenta_close(pci_socket_t *sock)
+{
+ if (sock->cb_irq)
+ free_irq(sock->cb_irq, sock);
+ if (sock->base)
+ iounmap(sock->base);
+}
+
+#include "ti113x.h"
+#include "ricoh.h"
+
+/*
+ * Different cardbus controllers have slightly different
+ * initialization sequences etc details. List them here..
+ */
+#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y
+static struct cardbus_override_struct {
+ unsigned short vendor;
+ unsigned short device;
+ struct pci_socket_ops *op;
+} cardbus_override[] = {
+ { PD(TI,1130), &ti113x_ops },
+ { PD(TI,1131), &ti113x_ops },
+ { PD(TI,1250), &ti1250_ops },
+
+ { PD(RICOH,RL5C465), &ricoh_ops },
+ { PD(RICOH,RL5C466), &ricoh_ops },
+ { PD(RICOH,RL5C475), &ricoh_ops },
+ { PD(RICOH,RL5C476), &ricoh_ops },
+ { PD(RICOH,RL5C478), &ricoh_ops }
+};
+
+#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
+
+/*
* Initialize a cardbus controller. Make sure we have a usable
* interrupt, and that we can map the cardbus area. Fill in the
* socket information structure..
*/
static int yenta_open(pci_socket_t *socket)
{
+ int i;
struct pci_dev *dev = socket->dev;
/*
@@ -645,38 +698,31 @@ static int yenta_open(pci_socket_t *socket)
/* Set up the bridge regions.. */
yenta_allocate_resources(socket);
- /*
- * Always poll the socket too, just in case the cardbus interrupt
- * doesn't exist (it happens), or we just lose an interrupt..
- */
- init_timer(&socket->timer);
- socket->timer.expires = jiffies + HZ;
- socket->timer.data = (unsigned long)socket;
- socket->timer.function = yenta_timer;
- add_timer(&socket->timer);
-
if (dev->irq && !request_irq(dev->irq, yenta_interrupt, SA_SHIRQ, dev->name, socket))
socket->cb_irq = dev->irq;
/* And figure out what the dang thing can do for the PCMCIA layer... */
yenta_get_socket_capabilities(socket);
+ /* Do we have special options for the device? */
+ for (i = 0; i < NR_OVERRIDES; i++) {
+ struct cardbus_override_struct *d = cardbus_override+i;
+ if (dev->vendor == d->vendor && dev->device == d->device) {
+ socket->op = d->op;
+ if (d->op->open) {
+ int retval = d->op->open(socket);
+ if (retval < 0)
+ return retval;
+ }
+ }
+ }
+
+ kernel_thread(yenta_socket_thread, socket, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
return 0;
}
/*
- * Close it down - release our resources and go home..
- */
-static void yenta_close(pci_socket_t *sock)
-{
- if (sock->cb_irq)
- free_irq(sock->cb_irq, sock);
- if (sock->base)
- iounmap(sock->base);
-}
-
-/*
* Standard plain cardbus - no frills, no extensions
*/
struct pci_socket_ops yenta_operations = {
@@ -684,7 +730,6 @@ struct pci_socket_ops yenta_operations = {
yenta_close,
yenta_init,
yenta_suspend,
- yenta_inquire,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,
@@ -704,7 +749,6 @@ struct pci_socket_ops ricoh_operations = {
yenta_close,
ricoh_init,
yenta_suspend,
- yenta_inquire,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,