summaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-05 06:47:02 +0000
commit99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch)
tree3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/pcmcia
parente73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff)
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r--drivers/pcmcia/Config.in2
-rw-r--r--drivers/pcmcia/Makefile10
-rw-r--r--drivers/pcmcia/bulkmem.c23
-rw-r--r--drivers/pcmcia/cardbus.c723
-rw-r--r--drivers/pcmcia/cistpl.c10
-rw-r--r--drivers/pcmcia/cs.c211
-rw-r--r--drivers/pcmcia/cs_internal.h8
-rw-r--r--drivers/pcmcia/i82365.c1503
-rw-r--r--drivers/pcmcia/old-yenta.h153
-rw-r--r--drivers/pcmcia/pci_socket.c205
-rw-r--r--drivers/pcmcia/pci_socket.h39
-rw-r--r--drivers/pcmcia/tcic.c94
-rw-r--r--drivers/pcmcia/yenta.c716
-rw-r--r--drivers/pcmcia/yenta.h244
14 files changed, 1877 insertions, 2064 deletions
diff --git a/drivers/pcmcia/Config.in b/drivers/pcmcia/Config.in
index aaedbf74a..556ecf4c8 100644
--- a/drivers/pcmcia/Config.in
+++ b/drivers/pcmcia/Config.in
@@ -9,7 +9,7 @@ if [ "$CONFIG_PCMCIA" != "n" ]; then
if [ "$CONFIG_PCI" != "n" ]; then
bool ' CardBus support' CONFIG_CARDBUS
fi
- bool ' i82365/Yenta compatible bridge support' CONFIG_I82365
+ bool ' i82365 compatible bridge support' CONFIG_I82365
bool ' Databook TCIC host bridge support' CONFIG_TCIC
fi
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index 703a7c6c8..649e50a14 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -18,16 +18,16 @@ ifeq ($(CONFIG_PCMCIA),y)
O_OBJS := cistpl.o rsrc_mgr.o bulkmem.o
OX_OBJS := ds.o cs.o
O_TARGET := pcmcia.o
+ ifeq ($(CONFIG_CARDBUS),y)
+ O_OBJS += cardbus.o
+ OX_OBJS += cb_enabler.o yenta.o pci_socket.o
+ endif
ifeq ($(CONFIG_I82365),y)
O_OBJS += i82365.o
endif
ifeq ($(CONFIG_TCIC),y)
O_OBJS += tcic.o
endif
- ifeq ($(CONFIG_CARDBUS),y)
- O_OBJS += cardbus.o
- OX_OBJS += cb_enabler.o
- endif
else
ifeq ($(CONFIG_PCMCIA),m)
M_OBJS := pcmcia_core.o
@@ -42,7 +42,7 @@ else
endif
ifeq ($(CONFIG_CARDBUS),y)
CORE_OBJS += cardbus.o
- MX_OBJS += cb_enabler.o
+ MX_OBJS += cb_enabler.o yenta.o pci_socket.o
endif
endif
endif
diff --git a/drivers/pcmcia/bulkmem.c b/drivers/pcmcia/bulkmem.c
index e3c602cd4..269f5c337 100644
--- a/drivers/pcmcia/bulkmem.c
+++ b/drivers/pcmcia/bulkmem.c
@@ -257,7 +257,7 @@ static int mtd_modify_window(window_handle_t win, mtd_mod_win_t *req)
win->ctl.flags |= MAP_ATTRIB;
win->ctl.speed = req->AccessSpeed;
win->ctl.card_start = req->CardOffset;
- win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl);
+ win->sock->ss_entry->set_mem_map(win->sock->sock, &win->ctl);
return CS_SUCCESS;
}
@@ -270,7 +270,7 @@ static int mtd_set_vpp(client_handle_t handle, mtd_vpp_req_t *req)
return CS_BAD_VPP;
s = SOCKET(handle);
s->socket.Vpp = req->Vpp1;
- if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+ if (s->ss_entry->set_socket(s->sock, &s->socket))
return CS_BAD_VPP;
return CS_SUCCESS;
}
@@ -285,7 +285,7 @@ static int mtd_rdy_mask(client_handle_t handle, mtd_rdy_req_t *req)
s->socket.csc_mask |= SS_READY;
else
s->socket.csc_mask &= ~SS_READY;
- if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+ if (s->ss_entry->set_socket(s->sock, &s->socket))
return CS_GENERAL_FAILURE;
return CS_SUCCESS;
}
@@ -294,7 +294,13 @@ int MTDHelperEntry(int func, void *a1, void *a2)
{
switch (func) {
case MTDRequestWindow:
- return pcmcia_request_window(a1, a2);
+ {
+ window_handle_t w;
+ int ret = pcmcia_request_window(a1, a2, &w);
+ (window_handle_t *)a1 = w;
+ return ret;
+ }
+ break;
case MTDReleaseWindow:
return pcmcia_release_window(a1);
case MTDModifyWindow:
@@ -470,7 +476,8 @@ int pcmcia_register_mtd(client_handle_t handle, mtd_reg_t *reg)
======================================================================*/
-int pcmcia_register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header)
+int pcmcia_register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header,
+ eraseq_handle_t *e)
{
eraseq_t *queue;
@@ -481,7 +488,7 @@ int pcmcia_register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header)
queue->handle = *handle;
queue->count = header->QueueEntryCnt;
queue->entry = header->QueueEntryArray;
- *handle = (client_handle_t)queue;
+ *e = queue;
return CS_SUCCESS;
} /* register_erase_queue */
@@ -517,7 +524,7 @@ int pcmcia_check_erase_queue(eraseq_handle_t eraseq)
======================================================================*/
-int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open)
+int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open, memory_handle_t *mh)
{
socket_info_t *s;
memory_handle_t region;
@@ -534,7 +541,7 @@ int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open)
region = region->info.next;
}
if (region && region->mtd) {
- *handle = (client_handle_t)region;
+ *mh = region;
DEBUG(1, "cs: open_memory(0x%p, 0x%x) = 0x%p\n",
handle, open->Offset, region);
return CS_SUCCESS;
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
index 440fd39c5..88175e08d 100644
--- a/drivers/pcmcia/cardbus.c
+++ b/drivers/pcmcia/cardbus.c
@@ -33,9 +33,19 @@
well as setting up and shutting down Cardbus sockets. They are
called from cs.c in response to Request/ReleaseConfiguration and
Request/ReleaseIO calls.
-
+
======================================================================*/
+/*
+ * This file is going away. Cardbus handling has been re-written to be
+ * more of a PCI bridge thing, and the PCI code basically does all the
+ * resource handling. This has wrappers to make the rest of the PCMCIA
+ * subsystem not notice that it's not here any more.
+ *
+ * Linus, Jan 2000
+ */
+
+
#define __NO_VERSION__
#include <linux/module.h>
@@ -68,15 +78,12 @@ static int pc_debug = PCMCIA_DEBUG;
#define FIND_FIRST_BIT(n) ((n) - ((n) & ((n)-1)))
-#define pci_readb pcibios_read_config_byte
-#define pci_writeb pcibios_write_config_byte
-#define pci_readw pcibios_read_config_word
-#define pci_writew pcibios_write_config_word
-#define pci_readl pcibios_read_config_dword
-#define pci_writel pcibios_write_config_dword
-
-#define CB_BAR(n) (PCI_BASE_ADDRESS_0+(4*(n)))
-#define CB_ROM_BASE 0x0030
+#define pci_readb pci_read_config_byte
+#define pci_writeb pci_write_config_byte
+#define pci_readw pci_read_config_word
+#define pci_writew pci_write_config_word
+#define pci_readl pci_read_config_dword
+#define pci_writel pci_write_config_dword
/* Offsets in the Expansion ROM Image Header */
#define ROM_SIGNATURE 0x0000 /* 2 bytes */
@@ -92,18 +99,15 @@ 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 {
- u_int size[7];
- struct pci_dev dev;
+ struct pci_dev dev;
} cb_config_t;
-#define BASE(dev,n) ((dev).resource[n].start)
-#define ROM(dev) ((dev).resource[6].start)
-
-/* There are three classes of bridge maps: IO ports,
- non-prefetchable memory, and prefetchable memory */
-typedef enum { B_IO, B_M1, B_M2 } bridge_type;
-
/*=====================================================================
Expansion ROM's have a special layout, and pointers specify an
@@ -114,45 +118,49 @@ typedef enum { B_IO, B_M1, B_M2 } bridge_type;
=====================================================================*/
-static int check_rom(u_char *b, u_long len)
+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;
+ 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)
+static u_int xlate_rom_addr(u_char * b, u_int addr)
{
- u_int img = 0, ofs = 0, sz;
- u_short data;
- while ((readb(b) == 0x55) && (readb(b+1) == 0xaa)) {
- if (img == (addr >> 28))
- return (addr & 0x0fffffff) + ofs;
- 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));
- if ((sz == 0) || (readb(b+data+PCDATA_INDICATOR) & 0x80))
- break;
- b += sz; ofs += sz; img++;
- }
- return 0;
+ u_int img = 0, ofs = 0, sz;
+ u_short data;
+ while ((readb(b) == 0x55) && (readb(b + 1) == 0xaa)) {
+ if (img == (addr >> 28))
+ return (addr & 0x0fffffff) + ofs;
+ 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));
+ if ((sz == 0) || (readb(b + data + PCDATA_INDICATOR) & 0x80))
+ break;
+ b += sz;
+ ofs += sz;
+ img++;
+ }
+ return 0;
}
/*=====================================================================
@@ -163,76 +171,36 @@ static u_int xlate_rom_addr(u_char *b, u_int addr)
=====================================================================*/
-int cb_setup_cis_mem(socket_info_t *s, int space)
+void cb_release_cis_mem(socket_info_t * s)
{
- cb_bridge_map *m = &s->cb_cis_map;
- u_long base = 0;
- u_int sz, br;
-
- if (space == s->cb_cis_space)
- return CS_SUCCESS;
- else if (s->cb_cis_space != 0)
- cb_release_cis_mem(s);
- DEBUG(1, "cs: cb_setup_cis_mem(space %d)\n", space);
- /* If socket is configured, then use existing memory mapping */
- if (s->lock_count) {
- s->cb_cis_virt =
- ioremap(BASE(s->cb_config[0].dev, space-1),
- s->cb_config[0].size[space-1] & ~3);
- s->cb_cis_space = space;
- return CS_SUCCESS;
- }
-
- /* Not configured? Then set up temporary map */
- br = (space == 7) ? CB_ROM_BASE : CB_BAR(space-1);
- pci_writel(s->cap.cardbus, 0, br, 0xffffffff);
- pci_readl(s->cap.cardbus, 0, br, &sz);
- sz &= PCI_BASE_ADDRESS_MEM_MASK;
- sz = FIND_FIRST_BIT(sz);
- if (sz < PAGE_SIZE) sz = PAGE_SIZE;
- if (find_mem_region(&base, sz, sz, 0, "cb_enabler") != 0) {
- printk(KERN_NOTICE "cs: could not allocate %dK memory for"
- " CardBus socket %d\n", sz/1024, s->sock);
- return CS_OUT_OF_RESOURCE;
- }
- s->cb_cis_space = space;
- s->cb_cis_virt = ioremap(base, sz);
- DEBUG(1, " phys 0x%08lx-0x%08lx, virt 0x%08lx\n",
- base, base+sz-1, (u_long)s->cb_cis_virt);
- pci_writel(s->cap.cardbus, 0, br, base | 1);
- pci_writeb(s->cap.cardbus, 0, PCI_COMMAND, PCI_COMMAND_MEMORY);
- m->map = 0; m->flags = MAP_ACTIVE;
- m->start = base; m->stop = base+sz-1;
- s->ss_entry(s->sock, SS_SetBridge, m);
- if ((space == 7) && (check_rom(s->cb_cis_virt, sz) == 0)) {
- printk(KERN_NOTICE "cs: no valid ROM images found!\n");
- return CS_READ_FAILURE;
- }
- return CS_SUCCESS;
+ if (s->cb_cis_virt) {
+ DEBUG(1, "cs: cb_release_cis_mem()\n");
+ iounmap(s->cb_cis_virt);
+ s->cb_cis_virt = NULL;
+ s->cb_cis_res = 0;
+ }
}
-void cb_release_cis_mem(socket_info_t *s)
+static int cb_setup_cis_mem(socket_info_t * s, struct pci_dev *dev, struct resource *res)
{
- cb_bridge_map *m = &s->cb_cis_map;
- u_int br;
- if (s->cb_cis_virt) {
- DEBUG(1, "cs: cb_release_cis_mem()\n");
- iounmap(s->cb_cis_virt);
- s->cb_cis_virt = NULL;
- s->cb_cis_space = 0;
- }
- if (m->start) {
- /* This is overkill: we probably only need to release the
- memory region, but the rest should be safe */
- br = (s->cb_cis_space == 7) ?
- CB_ROM_BASE : CB_BAR(s->cb_cis_space-1);
- m->map = 0; m->flags = 0;
- s->ss_entry(s->sock, SS_SetBridge, m);
- pci_writeb(s->cap.cardbus, 0, PCI_COMMAND, 0);
- pci_writel(s->cap.cardbus, 0, br, 0);
- release_mem_region(m->start, m->stop - m->start + 1);
- m->start = 0;
- }
+ unsigned int start, size;
+
+ if (res == s->cb_cis_res)
+ return 0;
+
+ if (s->cb_cis_res)
+ cb_release_cis_mem(s);
+
+ start = res->start;
+ size = res->end - start + 1;
+ s->cb_cis_virt = ioremap(start, size);
+
+ if (!s->cb_cis_virt)
+ return -1;
+
+ s->cb_cis_res = res;
+
+ return 0;
}
/*=====================================================================
@@ -242,30 +210,47 @@ void cb_release_cis_mem(socket_info_t *s)
=====================================================================*/
-void read_cb_mem(socket_info_t *s, u_char fn, int space,
+void read_cb_mem(socket_info_t * s, u_char fn, int space,
u_int addr, u_int len, void *ptr)
{
- DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len);
- if (space == 0) {
- if (addr+len > 0x100) goto fail;
- for (; len; addr++, ptr++, len--)
- pci_readb(s->cap.cardbus, fn, addr, (u_char *)ptr);
- } else {
- if (cb_setup_cis_mem(s, space) != 0) goto fail;
+ struct pci_dev *dev;
+ struct resource *res;
+
+ DEBUG(3, "cs: read_cb_mem(%d, %#x, %u)\n", space, addr, len);
+
+ dev = &s->cb_config[fn].dev;
+
+ /* Config space? */
+ if (space == 0) {
+ if (addr + len > 0x100)
+ goto fail;
+ for (; len; addr++, ptr++, len--)
+ pci_readb(dev, addr, (u_char *) ptr);
+ return;
+ }
+
+ res = dev->resource + space - 1;
+ if (!res->flags)
+ goto fail;
+
+ if (cb_setup_cis_mem(s, dev, res) != 0)
+ goto fail;
+
if (space == 7) {
- addr = xlate_rom_addr(s->cb_cis_virt, addr);
- if (addr == 0) goto fail;
+ addr = xlate_rom_addr(s->cb_cis_virt, addr);
+ if (addr == 0)
+ goto fail;
}
- if (addr+len > s->cb_cis_map.stop - s->cb_cis_map.start)
- goto fail;
- if (s->cb_cis_virt != NULL)
- for (; len; addr++, ptr++, len--)
- *(u_char *)ptr = readb(s->cb_cis_virt+addr);
- }
- return;
- fail:
- memset(ptr, 0xff, len);
- return;
+
+ if (addr + len > res->end - res->start)
+ goto fail;
+
+ memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
+ return;
+
+fail:
+ memset(ptr, 0xff, len);
+ return;
}
/*=====================================================================
@@ -276,84 +261,105 @@ void read_cb_mem(socket_info_t *s, u_char fn, int space,
=====================================================================*/
-int cb_alloc(socket_info_t *s)
+int cb_alloc(socket_info_t * s)
{
- struct pci_dev tmp;
- u_short vend, v, dev;
- u_char i, hdr, fn, bus = s->cap.cardbus;
- cb_config_t *c;
-
- tmp.bus = s->cap.cb_bus; tmp.devfn = 0;
- tmp.next = pci_devices; pci_devices = &tmp;
-
- pci_readw(bus, 0, PCI_VENDOR_ID, &vend);
- pci_readw(bus, 0, PCI_DEVICE_ID, &dev);
- printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, "
- "device 0x%04x\n", bus, vend, dev);
-
- pci_readb(bus, 0, PCI_HEADER_TYPE, &hdr);
- if (hdr & 0x80) {
- /* Count functions */
- for (fn = 0; fn < 8; fn++) {
- tmp.devfn = fn;
- pci_readw(bus, fn, PCI_VENDOR_ID, &v);
- if (v != vend) break;
+ struct pci_bus *bus;
+ struct pci_dev tmp;
+ u_short vend, v, dev;
+ u_char i, hdr, fn;
+ cb_config_t *c;
+
+ bus = s->cap.cb_dev->subordinate;
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.bus = bus;
+ tmp.sysdata = bus->sysdata;
+ tmp.devfn = 0;
+
+ pci_readw(&tmp, PCI_VENDOR_ID, &vend);
+ pci_readw(&tmp, PCI_DEVICE_ID, &dev);
+ printk(KERN_INFO "cs: cb_alloc(bus %d): vendor 0x%04x, "
+ "device 0x%04x\n", bus->number, vend, dev);
+
+ pci_readb(&tmp, PCI_HEADER_TYPE, &hdr);
+ fn = 1;
+ if (hdr & 0x80) {
+ do {
+ tmp.devfn = fn;
+ if (pci_readw(&tmp, PCI_VENDOR_ID, &v) || !v || v == 0xffff)
+ break;
+ fn++;
+ } while (fn < 8);
}
- } else fn = 1;
- s->functions = fn;
-
- c = kmalloc(fn * sizeof(struct cb_config_t), GFP_ATOMIC);
- if (!c) return CS_OUT_OF_RESOURCE;
- memset(c, 0, fn * sizeof(struct cb_config_t));
- s->cb_config = c;
-
- pci_devices = tmp.next;
- for (i = 0; i < fn; i++) {
- c[i].dev.bus = s->cap.cb_bus;
- c[i].dev.devfn = i;
- if (i < fn-1) {
- c[i].dev.sibling = c[i].dev.next = &c[i+1].dev;
+ s->functions = fn;
+
+ c = kmalloc(fn * sizeof(struct cb_config_t), GFP_ATOMIC);
+ if (!c)
+ return CS_OUT_OF_RESOURCE;
+ memset(c, 0, fn * sizeof(struct cb_config_t));
+
+ for (i = 0; i < fn; i++) {
+ struct pci_dev *dev = &c[i].dev;
+ int r;
+
+ dev->bus = bus;
+ dev->sysdata = bus->sysdata;
+ dev->devfn = i;
+ dev->vendor = vend;
+ pci_readw(dev, PCI_DEVICE_ID, &dev->device);
+ dev->hdr_type = hdr;
+
+ 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;
+ 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);
}
- }
- s->cap.cb_bus->devices = &c[0].dev;
- /* Link into PCI device chain */
- c[s->functions-1].dev.next = pci_devices;
- pci_devices = &c[0].dev;
- for (i = 0; i < fn; i++) {
- c[i].dev.vendor = vend;
- pci_readw(bus, i, PCI_DEVICE_ID, &c[i].dev.device);
- pci_readl(bus, i, PCI_CLASS_REVISION, &c[i].dev.class);
- c[i].dev.class >>= 8;
- c[i].dev.hdr_type = hdr;
-#ifdef CONFIG_PROC_FS
- pci_proc_attach_device(&c[i].dev);
-#endif
- }
-
- return CS_SUCCESS;
+
+ s->cb_config = c;
+ return CS_SUCCESS;
}
-void cb_free(socket_info_t *s)
+static void free_resources(struct pci_dev *dev)
{
- cb_config_t *c = s->cb_config;
-
- if (c) {
- struct pci_dev **p, *q;
- /* Unlink from PCI device chain */
- for (p = &pci_devices; *p; p = &((*p)->next))
- if (*p == &c[0].dev) break;
- for (q = *p; q; q = q->next) {
- if (q->bus != (*p)->bus) break;
-#ifdef CONFIG_PROC_FS
- pci_proc_detach_device(q);
-#endif
+ 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;
+
+ if (c) {
+ int i;
+
+ s->cb_config = NULL;
+ for(i=0; i<s->functions; i++) {
+ struct pci_dev *dev = &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);
}
- if (*p) *p = q;
- s->cap.cb_bus->devices = NULL;
- kfree(s->cb_config);
- s->cb_config = NULL;
- printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cardbus);
- }
}
/*=====================================================================
@@ -368,143 +374,55 @@ void cb_free(socket_info_t *s)
======================================================================*/
-int cb_config(socket_info_t *s)
+static int cb_assign_irq(u32 mask)
{
- cb_config_t *c = s->cb_config;
- u_char fn = s->functions;
- u_char i, j, bus = s->cap.cardbus, *name;
- u_int sz, align, m, mask[3], num[3], base[3];
- int irq, try, ret;
-
- printk(KERN_INFO "cs: cb_config(bus %d)\n", s->cap.cardbus);
-
- /* Determine IO and memory space needs */
- num[B_IO] = num[B_M1] = num[B_M2] = 0;
- mask[B_IO] = mask[B_M1] = mask[B_M2] = 0;
- for (i = 0; i < fn; i++) {
- for (j = 0; j < 6; j++) {
- pci_writel(bus, i, CB_BAR(j), 0xffffffff);
- pci_readl(bus, i, CB_BAR(j), &sz);
- if (sz == 0) continue;
- if (sz & PCI_BASE_ADDRESS_SPACE) {
- m = B_IO;
- sz &= PCI_BASE_ADDRESS_IO_MASK;
- } else {
- m = (sz & PCI_BASE_ADDRESS_MEM_PREFETCH) ? B_M2 : B_M1;
- sz &= PCI_BASE_ADDRESS_MEM_MASK;
- }
- sz = FIND_FIRST_BIT(sz);
- c[i].size[j] = sz | m;
- if (m && (sz < PAGE_SIZE)) sz = PAGE_SIZE;
- num[m] += sz; mask[m] |= sz;
- }
- pci_writel(bus, i, CB_ROM_BASE, 0xffffffff);
- pci_readl(bus, i, CB_ROM_BASE, &sz);
- if (sz != 0) {
- sz = FIND_FIRST_BIT(sz & ~0x00000001);
- c[i].size[6] = sz | B_M1;
- if (sz < PAGE_SIZE) sz = PAGE_SIZE;
- num[B_M1] += sz; mask[B_M1] |= sz;
- }
- }
-
- /* Allocate system resources */
- name = "cb_enabler";
- s->io[0].NumPorts = num[B_IO];
- s->io[0].BasePort = 0;
- if (num[B_IO]) {
- if (find_io_region(&s->io[0].BasePort, num[B_IO],
- num[B_IO], name) != 0) {
- printk(KERN_NOTICE "cs: could not allocate %d IO ports for"
- " CardBus socket %d\n", num[B_IO], s->sock);
- goto failed;
- }
- base[B_IO] = s->io[0].BasePort + num[B_IO];
- }
- s->win[0].size = num[B_M1];
- s->win[0].base = 0;
- if (num[B_M1]) {
- if (find_mem_region(&s->win[0].base, num[B_M1], num[B_M1],
- 0, name) != 0) {
- printk(KERN_NOTICE "cs: could not allocate %dK memory for"
- " CardBus socket %d\n", num[B_M1]/1024, s->sock);
- goto failed;
- }
- base[B_M1] = s->win[0].base + num[B_M1];
- }
- s->win[1].size = num[B_M2];
- s->win[1].base = 0;
- if (num[B_M2]) {
- if (find_mem_region(&s->win[1].base, num[B_M2], num[B_M2],
- 0, name) != 0) {
- printk(KERN_NOTICE "cs: could not allocate %dK memory for"
- " CardBus socket %d\n", num[B_M2]/1024, s->sock);
- goto failed;
- }
- base[B_M2] = s->win[1].base + num[B_M2];
- }
-
- /* Set up base address registers */
- while (mask[B_IO] | mask[B_M1] | mask[B_M2]) {
- num[B_IO] = FIND_FIRST_BIT(mask[B_IO]); mask[B_IO] -= num[B_IO];
- num[B_M1] = FIND_FIRST_BIT(mask[B_M1]); mask[B_M1] -= num[B_M1];
- num[B_M2] = FIND_FIRST_BIT(mask[B_M2]); mask[B_M2] -= num[B_M2];
- for (i = 0; i < fn; i++) {
- for (j = 0; j < 7; j++) {
- sz = c[i].size[j];
- m = sz & 3; sz &= ~3;
- align = (m && (sz < PAGE_SIZE)) ? PAGE_SIZE : sz;
- if (sz && (align == num[m])) {
- base[m] -= align;
- if (j < 6)
- printk(KERN_INFO " fn %d bar %d: ", i, j+1);
- else
- printk(KERN_INFO " fn %d rom: ", i);
- printk("%s 0x%x-0x%x\n", (m) ? "mem" : "io",
- base[m], base[m]+sz-1);
- BASE(c[i].dev, j) = base[m];
- }
- }
- }
- }
-
- /* Allocate interrupt if needed */
- s->irq.AssignedIRQ = irq = 0; ret = -1;
- for (i = 0; i < fn; i++) {
- pci_readb(bus, i, PCI_INTERRUPT_PIN, &j);
- if (j == 0) continue;
- if (irq == 0) {
- if (s->cap.irq_mask & (1 << s->cap.pci_irq)) {
- irq = s->cap.pci_irq;
- ret = 0;
- }
-#ifdef CONFIG_ISA
- else
- for (try = 0; try < 2; try++) {
- for (irq = 0; irq < 32; irq++)
- if ((s->cap.irq_mask >> irq) & 1) {
- ret = try_irq(IRQ_TYPE_EXCLUSIVE, irq, try);
- if (ret == 0) break;
+ 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;
}
- if (ret == 0) break;
}
- if (ret != 0) {
- printk(KERN_NOTICE "cs: could not allocate interrupt"
- " for CardBus socket %d\n", s->sock);
- goto failed;
- }
-#endif
- s->irq.AssignedIRQ = irq;
}
- }
- for (i = 0; i < fn; i++)
- c[i].dev.irq = irq;
-
- return CS_SUCCESS;
+ return 0;
+}
+
+int cb_config(socket_info_t * s)
+{
+ cb_config_t *c = s->cb_config;
+ u_char fn = s->functions;
+ int i, irq;
-failed:
- cb_release(s);
- return CS_OUT_OF_RESOURCE;
+ 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;
}
/*======================================================================
@@ -517,22 +435,15 @@ failed:
======================================================================*/
-void cb_release(socket_info_t *s)
+void cb_release(socket_info_t * s)
{
- cb_config_t *c = s->cb_config;
-
- DEBUG(0, "cs: cb_release(bus %d)\n", s->cap.cardbus);
-
- if (s->win[0].size > 0)
- release_mem_region(s->win[0].base, s->win[0].size);
- if (s->win[1].size > 0)
- release_mem_region(s->win[1].base, s->win[1].size);
- if (s->io[0].NumPorts > 0)
- release_region(s->io[0].BasePort, s->io[0].NumPorts);
- s->io[0].NumPorts = 0;
+ cb_config_t *c = s->cb_config;
+
+ DEBUG(0, "cs: cb_release(bus %d)\n", s->cap.cb_dev->subordinate->number);
+
#ifdef CONFIG_ISA
- if ((c[0].dev.irq != 0) && (c[0].dev.irq != s->cap.pci_irq))
- undo_irq(IRQ_TYPE_EXCLUSIVE, c[0].dev.irq);
+ if ((c[0].dev.irq != 0) && (c[0].dev.irq != s->cap.pci_irq))
+ undo_irq(IRQ_TYPE_EXCLUSIVE, c[0].dev.irq);
#endif
}
@@ -551,66 +462,32 @@ void cb_release(socket_info_t *s)
======================================================================*/
-void cb_enable(socket_info_t *s)
+void cb_enable(socket_info_t * s)
{
- u_char i, j, bus = s->cap.cardbus;
- cb_config_t *c = s->cb_config;
-
- DEBUG(0, "cs: cb_enable(bus %d)\n", bus);
-
- /* Configure bridge */
- if (s->cb_cis_map.start)
+ struct pci_dev *dev;
+ u_char i, bus = s->cap.cb_dev->subordinate->number;
+
+ DEBUG(0, "cs: cb_enable(bus %d)\n", bus);
+
+ /* Configure bridge */
cb_release_cis_mem(s);
- for (i = 0; i < 3; i++) {
- cb_bridge_map m;
- switch (i) {
- case B_IO:
- m.map = 0; m.flags = MAP_IOSPACE | MAP_ACTIVE;
- m.start = s->io[0].BasePort;
- m.stop = m.start + s->io[0].NumPorts - 1;
- break;
- case B_M1:
- m.map = 0; m.flags = MAP_ACTIVE;
- m.start = s->win[0].base;
- m.stop = m.start + s->win[0].size - 1;
- break;
- case B_M2:
- m.map = 1; m.flags = MAP_PREFETCH | MAP_ACTIVE;
- m.start = s->win[1].base;
- m.stop = m.start + s->win[1].size - 1;
- break;
+
+ /* Set up PCI interrupt and command registers */
+ for (i = 0; i < s->functions; i++) {
+ dev = &s->cb_config[i].dev;
+ pci_writeb(dev, PCI_COMMAND, PCI_COMMAND_MASTER |
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ pci_writeb(dev, PCI_CACHE_LINE_SIZE, 8);
}
- if (m.start == 0) continue;
- DEBUG(0, " bridge %s map %d (flags 0x%x): 0x%x-0x%x\n",
- (m.flags & MAP_IOSPACE) ? "io" : "mem",
- m.map, m.flags, m.start, m.stop);
- s->ss_entry(s->sock, SS_SetBridge, &m);
- }
-
- /* Set up base address registers */
- for (i = 0; i < s->functions; i++) {
- for (j = 0; j < 6; j++) {
- if (BASE(c[i].dev, j) != 0)
- pci_writel(bus, i, CB_BAR(j), BASE(c[i].dev, j));
+
+ if (s->irq.AssignedIRQ) {
+ for (i = 0; i < s->functions; i++) {
+ dev = &s->cb_config[i].dev;
+ pci_writeb(dev, PCI_INTERRUPT_LINE, s->irq.AssignedIRQ);
+ }
+ s->socket.io_irq = s->irq.AssignedIRQ;
+ s->ss_entry->set_socket(s->sock, &s->socket);
}
- if (ROM(c[i].dev) != 0)
- pci_writel(bus, i, CB_ROM_BASE, ROM(c[i].dev) | 1);
- }
-
- /* Set up PCI interrupt and command registers */
- for (i = 0; i < s->functions; i++) {
- pci_writeb(bus, i, PCI_COMMAND, PCI_COMMAND_MASTER |
- PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
- pci_writeb(bus, i, PCI_CACHE_LINE_SIZE, 8);
- }
-
- if (s->irq.AssignedIRQ) {
- for (i = 0; i < s->functions; i++)
- pci_writeb(bus, i, PCI_INTERRUPT_LINE,
- s->irq.AssignedIRQ);
- s->socket.io_irq = s->irq.AssignedIRQ;
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
- }
}
/*======================================================================
@@ -622,22 +499,10 @@ void cb_enable(socket_info_t *s)
======================================================================*/
-void cb_disable(socket_info_t *s)
+void cb_disable(socket_info_t * s)
{
- u_char i;
- cb_bridge_map m = { 0, 0, 0, 0xffff };
-
- DEBUG(0, "cs: cb_disable(bus %d)\n", s->cap.cardbus);
-
- /* Turn off bridge windows */
- if (s->cb_cis_map.start)
+ DEBUG(0, "cs: cb_disable(bus %d)\n", s->cap.cb_dev->subordinate->number);
+
+ /* Turn off bridge windows */
cb_release_cis_mem(s);
- for (i = 0; i < 3; i++) {
- switch (i) {
- case B_IO: m.map = 0; m.flags = MAP_IOSPACE; break;
- case B_M1: m.map = m.flags = 0; break;
- case B_M2: m.map = 1; m.flags = 0; break;
- }
- s->ss_entry(s->sock, SS_SetBridge, &m);
- }
}
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index c2cd8e785..eb287bee9 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -101,7 +101,7 @@ void read_cis_mem(socket_info_t *s, int attr, u_int addr,
mem->card_start = addr & ~(s->cap.map_size-1);
for (; len > 0; sys = s->cis_virt) {
- s->ss_entry(s->sock, SS_SetMemMap, mem);
+ 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),
@@ -131,7 +131,7 @@ void write_cis_mem(socket_info_t *s, int attr, u_int addr,
mem->card_start = addr & ~(s->cap.map_size-1);
for (; len > 0; sys = s->cis_virt) {
- s->ss_entry(s->sock, SS_SetMemMap, mem);
+ 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);
@@ -181,7 +181,7 @@ static int checksum(u_long base)
vs->cis_virt = bus_ioremap(vs->cap.bus, base, vs->cap.map_size);
vs->cis_mem.card_start = 0;
vs->cis_mem.flags = MAP_ACTIVE;
- vs->ss_entry(vs->sock, SS_SetMemMap, &vs->cis_mem);
+ vs->ss_entry->set_mem_map(vs->sock, &vs->cis_mem);
/* Don't bother checking every word... */
a = 0; b = -1;
for (i = 0; i < vs->cap.map_size; i += 44) {
@@ -223,7 +223,7 @@ void release_cis_mem(socket_info_t *s)
{
if (s->cis_mem.sys_start != 0) {
s->cis_mem.flags &= ~MAP_ACTIVE;
- s->ss_entry(s->sock, SS_SetMemMap, &s->cis_mem);
+ s->ss_entry->set_mem_map(s->sock, &s->cis_mem);
release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
bus_iounmap(s->cap.bus, s->cis_virt);
s->cis_mem.sys_start = 0;
@@ -367,7 +367,7 @@ int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple)
#ifdef CONFIG_CARDBUS
if (s->state & SOCKET_CARDBUS) {
u_int ptr;
- pcibios_read_config_dword(s->cap.cardbus, 0, 0x28, &ptr);
+ pcibios_read_config_dword(s->cap.cb_dev->subordinate->number, 0, 0x28, &ptr);
tuple->CISOffset = ptr & ~7;
SPACE(tuple->Flags) = (ptr & 7);
} else
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 3b74627a2..d44d505ca 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -46,6 +46,7 @@
#include <linux/delay.h>
#include <linux/proc_fs.h>
#include <linux/compile.h>
+#include <linux/pci.h>
#include <asm/system.h>
#include <asm/irq.h>
@@ -58,6 +59,7 @@
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/bus_ops.h>
+
#include "cs_internal.h"
#include "rsrc_mgr.h"
@@ -131,7 +133,7 @@ MODULE_PARM(io_speed, "i");
/*====================================================================*/
-static socket_state_t dead_socket = {
+socket_state_t dead_socket = {
0, SS_DETECT, 0, 0, 0
};
@@ -242,27 +244,50 @@ static const lookup_t service_table[] = {
/*======================================================================
- Reset a socket to the default state
-
+ These functions are just shorthand for the actual low-level drivers
+
======================================================================*/
-static void init_socket(socket_info_t *s)
+static int register_callback(socket_info_t *s, void (*handler)(void *, unsigned int), void * info)
{
- int i;
- pccard_io_map io = { 0, 0, 0, 0, 1 };
- pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
-
- mem.sys_stop = s->cap.map_size;
- s->socket = dead_socket;
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
- for (i = 0; i < 2; i++) {
- io.map = i;
- s->ss_entry(s->sock, SS_SetIOMap, &io);
- }
- for (i = 0; i < 5; i++) {
- mem.map = i;
- s->ss_entry(s->sock, SS_SetMemMap, &mem);
- }
+ return s->ss_entry->register_callback(s->sock, handler, info);
+}
+
+static int get_socket_status(socket_info_t *s, int *val)
+{
+ return s->ss_entry->get_status(s->sock, val);
+}
+
+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);
+}
+
+static int set_mem_map(socket_info_t *s, struct pccard_mem_map *mem)
+{
+ return s->ss_entry->set_mem_map(s->sock, mem);
+}
+
+static int suspend_socket(socket_info_t *s)
+{
+ s->socket = dead_socket;
+ return s->ss_entry->suspend(s->sock);
+}
+
+static int init_socket(socket_info_t *s)
+{
+ s->socket = dead_socket;
+ return s->ss_entry->init(s->sock);
}
/*====================================================================*/
@@ -295,7 +320,7 @@ static void reset_socket(u_long i);
static void unreset_socket(u_long i);
static void parse_events(void *info, u_int events);
-int register_ss_entry(int nsock, ss_entry_t ss_entry)
+int register_ss_entry(int nsock, struct pccard_operations * ss_entry)
{
int i, ns;
socket_info_t *s;
@@ -324,7 +349,7 @@ int register_ss_entry(int nsock, ss_entry_t ss_entry)
if (i == sockets) sockets++;
init_socket(s);
- ss_entry(ns, SS_InquireSocket, &s->cap);
+ ss_entry->inquire_socket(ns, &s->cap);
#ifdef CONFIG_PROC_FS
if (proc_pccard) {
char name[3];
@@ -333,7 +358,7 @@ int register_ss_entry(int nsock, ss_entry_t ss_entry)
#ifdef PCMCIA_DEBUG
create_proc_read_entry("clients",0,s->proc,proc_read_clients,s);
#endif
- ss_entry(ns, SS_ProcSetup, s->proc);
+ ss_entry->proc_setup(ns, s->proc);
}
#endif
}
@@ -343,7 +368,7 @@ int register_ss_entry(int nsock, ss_entry_t ss_entry)
/*====================================================================*/
-void unregister_ss_entry(ss_entry_t ss_entry)
+void unregister_ss_entry(struct pccard_operations * ss_entry)
{
int i, j;
socket_info_t *s = NULL;
@@ -421,7 +446,6 @@ static void shutdown_socket(u_long i)
s->state &= SOCKET_PRESENT|SOCKET_SETUP_PENDING;
init_socket(s);
s->irq.AssignedIRQ = s->irq.Config = 0;
- s->functions = 0;
s->lock_count = 0;
s->cis_used = 0;
if (s->fake_cis) {
@@ -432,6 +456,7 @@ static void shutdown_socket(u_long i)
cb_release_cis_mem(s);
cb_free(s);
#endif
+ s->functions = 0;
if (s->config) {
kfree(s->config);
s->config = NULL;
@@ -454,7 +479,7 @@ static void setup_socket(u_long i)
int val;
socket_info_t *s = socket_table[i];
- s->ss_entry(s->sock, SS_GetStatus, &val);
+ get_socket_status(s, &val);
if (val & SS_DETECT) {
DEBUG(1, "cs: setup_socket(%ld): applying power\n", i);
s->state |= SOCKET_PRESENT;
@@ -474,7 +499,7 @@ static void setup_socket(u_long i)
printk(KERN_NOTICE "cs: unsupported card type detected!\n");
#endif
}
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+ set_socket(s, &s->socket);
s->setup.function = &reset_socket;
s->setup.expires = jiffies + vcc_settle;
add_timer(&s->setup);
@@ -497,10 +522,10 @@ static void reset_socket(u_long i)
DEBUG(1, "cs: resetting socket %ld\n", i);
s->socket.flags |= SS_OUTPUT_ENA | SS_RESET;
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+ set_socket(s, &s->socket);
udelay((long)reset_time);
s->socket.flags &= ~SS_RESET;
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+ set_socket(s, &s->socket);
s->unreset_timeout = 0;
s->setup.expires = jiffies + unreset_delay;
s->setup.function = &unreset_socket;
@@ -515,7 +540,7 @@ static void unreset_socket(u_long i)
socket_info_t *s = socket_table[i];
int val;
- s->ss_entry(s->sock, SS_GetStatus, &val);
+ get_socket_status(s, &val);
if (val & SS_READY) {
DEBUG(1, "cs: reset done on socket %ld\n", i);
if (s->state & SOCKET_SUSPEND) {
@@ -607,7 +632,7 @@ static void parse_events(void *info, u_int events)
int status;
u_long flags;
spin_lock_irqsave(&s->lock, flags);
- s->ss_entry(s->sock, SS_GetStatus, &status);
+ get_socket_status(s, &status);
if ((s->state & SOCKET_PRESENT) &&
(!(s->state & SOCKET_SUSPEND) ||
!(status & SS_DETECT)))
@@ -668,7 +693,7 @@ static int handle_apm_event(apm_event_t event)
if ((s->state & SOCKET_PRESENT) &&
!(s->state & SOCKET_SUSPEND)){
send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
- s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
+ suspend_socket(s);
s->state |= SOCKET_SUSPEND;
}
}
@@ -685,7 +710,7 @@ static int handle_apm_event(apm_event_t event)
s = socket_table[i];
/* Do this just to reinitialize the socket */
init_socket(s);
- s->ss_entry(s->sock, SS_GetStatus, &stat);
+ get_socket_status(s, &stat);
/* If there was or is a card here, we need to do something
about it... but parse_events will sort it all out. */
if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT))
@@ -939,7 +964,7 @@ int pcmcia_deregister_client(client_handle_t handle)
}
if (--s->real_clients == 0)
- s->ss_entry(sn, SS_RegisterCallback, NULL);
+ register_callback(s, NULL, NULL);
return CS_SUCCESS;
} /* deregister_client */
@@ -971,7 +996,7 @@ int pcmcia_get_configuration_info(client_handle_t handle,
config->Function = fn;
config->Vcc = s->socket.Vcc;
config->Vpp1 = config->Vpp2 = s->socket.Vpp;
- config->Option = s->cap.cardbus;
+ config->Option = s->cap.cb_dev->subordinate->number;
if (s->cb_config) {
config->Attributes = CONF_VALID_CLIENT;
config->IntType = INT_CARDBUS;
@@ -1134,7 +1159,7 @@ int pcmcia_get_status(client_handle_t handle, cs_status_t *status)
if (CHECK_HANDLE(handle))
return CS_BAD_HANDLE;
s = SOCKET(handle);
- s->ss_entry(s->sock, SS_GetStatus, &val);
+ get_socket_status(s, &val);
status->CardState = status->SocketState = 0;
status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0;
status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0;
@@ -1213,7 +1238,7 @@ int pcmcia_map_mem_page(window_handle_t win, memreq_t *req)
return CS_BAD_PAGE;
s = win->sock;
win->ctl.card_start = req->CardOffset;
- if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0)
+ if (set_mem_map(s, &win->ctl) != 0)
return CS_BAD_OFFSET;
return CS_SUCCESS;
} /* map_mem_page */
@@ -1246,7 +1271,7 @@ int pcmcia_modify_configuration(client_handle_t handle,
c->Attributes &= ~CONF_ENABLE_IRQ;
s->socket.io_irq = 0;
}
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+ set_socket(s, &s->socket);
}
if (mod->Attributes & CONF_VCC_CHANGE_VALID)
@@ -1258,7 +1283,7 @@ int pcmcia_modify_configuration(client_handle_t handle,
if (mod->Vpp1 != mod->Vpp2)
return CS_BAD_VPP;
c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1;
- if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+ if (set_socket(s, &s->socket))
return CS_BAD_VPP;
} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||
(mod->Attributes & CONF_VPP2_CHANGE_VALID))
@@ -1288,7 +1313,7 @@ int pcmcia_modify_window(window_handle_t win, modwin_t *req)
if (req->Attributes & WIN_USE_WAIT)
win->ctl.flags |= MAP_USE_WAIT;
win->ctl.speed = req->AccessSpeed;
- win->sock->ss_entry(win->sock->sock, SS_SetMemMap, &win->ctl);
+ set_mem_map(win->sock, &win->ctl);
return CS_SUCCESS;
} /* modify_window */
@@ -1324,12 +1349,9 @@ int pcmcia_register_client(client_handle_t *handle, client_reg_t *req)
s = socket_table[ns];
if (++s->real_clients == 1) {
- ss_callback_t call;
int status;
- call.handler = &parse_events;
- call.info = s;
- s->ss_entry(ns, SS_RegisterCallback, &call);
- s->ss_entry(ns, SS_GetStatus, &status);
+ register_callback(s, &parse_events, s);
+ get_socket_status(s, &status);
if ((status & SS_DETECT) &&
!(s->state & SOCKET_SETUP_PENDING)) {
s->state |= SOCKET_SETUP_PENDING;
@@ -1405,7 +1427,7 @@ int pcmcia_release_configuration(client_handle_t handle)
s->socket.flags = SS_OUTPUT_ENA;
s->socket.Vpp = 0;
s->socket.io_irq = 0;
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+ set_socket(s, &s->socket);
}
if (c->state & CONFIG_IO_REQ)
for (i = 0; i < MAX_IO_WIN; i++) {
@@ -1415,9 +1437,9 @@ int pcmcia_release_configuration(client_handle_t handle)
if (s->io[i].Config != 0)
continue;
io.map = i;
- s->ss_entry(s->sock, SS_GetIOMap, &io);
+ get_io_map(s, &io);
io.flags &= ~MAP_ACTIVE;
- s->ss_entry(s->sock, SS_SetIOMap, &io);
+ set_io_map(s, &io);
}
c->state &= ~CONFIG_LOCKED;
}
@@ -1520,7 +1542,7 @@ int pcmcia_release_window(window_handle_t win)
/* Shut down memory window */
win->ctl.flags &= ~MAP_ACTIVE;
- s->ss_entry(s->sock, SS_SetMemMap, &win->ctl);
+ set_mem_map(s, &win->ctl);
s->state &= ~SOCKET_WIN_REQ(win->index);
/* Release system memory */
@@ -1574,7 +1596,7 @@ int pcmcia_request_configuration(client_handle_t handle,
if (req->Vpp1 != req->Vpp2)
return CS_BAD_VPP;
s->socket.Vpp = req->Vpp1;
- if (s->ss_entry(s->sock, SS_SetSocket, &s->socket))
+ if (set_socket(s, &s->socket))
return CS_BAD_VPP;
c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1;
@@ -1592,7 +1614,7 @@ int pcmcia_request_configuration(client_handle_t handle,
s->socket.io_irq = s->irq.AssignedIRQ;
else
s->socket.io_irq = 0;
- s->ss_entry(s->sock, SS_SetSocket, &s->socket);
+ set_socket(s, &s->socket);
s->lock_count++;
/* Set up CIS configuration registers */
@@ -1655,7 +1677,7 @@ int pcmcia_request_configuration(client_handle_t handle,
}
iomap.start = s->io[i].BasePort;
iomap.stop = iomap.start + s->io[i].NumPorts - 1;
- s->ss_entry(s->sock, SS_SetIOMap, &iomap);
+ set_io_map(s, &iomap);
s->io[i].Config++;
}
}
@@ -1814,7 +1836,7 @@ int pcmcia_request_irq(client_handle_t handle, irq_req_t *req)
======================================================================*/
-int pcmcia_request_window(client_handle_t *handle, win_req_t *req)
+int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh)
{
socket_info_t *s;
window_t *win;
@@ -1871,12 +1893,12 @@ int pcmcia_request_window(client_handle_t *handle, win_req_t *req)
win->ctl.sys_start = req->Base;
win->ctl.sys_stop = req->Base + req->Size-1;
win->ctl.card_start = 0;
- if (s->ss_entry(s->sock, SS_SetMemMap, &win->ctl) != 0)
+ if (set_mem_map(s, &win->ctl) != 0)
return CS_BAD_ARGS;
s->state |= SOCKET_WIN_REQ(w);
/* Return window handle */
- *handle = (client_handle_t)win;
+ *wh = win;
return CS_SUCCESS;
} /* request_window */
@@ -1939,7 +1961,7 @@ int pcmcia_suspend_card(client_handle_t handle, client_req_t *req)
DEBUG(1, "cs: suspending socket %d\n", i);
send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);
- s->ss_entry(s->sock, SS_SetSocket, &dead_socket);
+ suspend_socket(s);
s->state |= SOCKET_SUSPEND;
return CS_SUCCESS;
@@ -2014,7 +2036,7 @@ int pcmcia_insert_card(client_handle_t handle, client_req_t *req)
if (!(s->state & SOCKET_SETUP_PENDING)) {
s->state |= SOCKET_SETUP_PENDING;
spin_unlock_irqrestore(&s->lock, flags);
- s->ss_entry(i, SS_GetStatus, &status);
+ get_socket_status(s, &status);
if (status & SS_DETECT)
setup_socket(i);
else {
@@ -2141,7 +2163,14 @@ int CardServices(int func, void *a1, void *a2, void *a3)
case ModifyWindow:
return pcmcia_modify_window(a1, a2); break;
case OpenMemory:
- return pcmcia_open_memory(a1, a2);
+/* return pcmcia_open_memory(a1, a2); */
+ {
+ memory_handle_t m;
+ int ret = pcmcia_open_memory(a1, a2, &m);
+ (memory_handle_t *)a1 = m;
+ return ret;
+ }
+ break;
case ParseTuple:
return pcmcia_parse_tuple(a1, a2, a3); break;
case ReadMemory:
@@ -2149,8 +2178,15 @@ int CardServices(int func, void *a1, void *a2, void *a3)
case RegisterClient:
return pcmcia_register_client(a1, a2); break;
case RegisterEraseQueue:
- return pcmcia_register_erase_queue(a1, a2); break;
- case RegisterMTD:
+ {
+ eraseq_handle_t w;
+ int ret = pcmcia_register_erase_queue(a1, a2, &w);
+ (eraseq_handle_t *)a1 = w;
+ return ret;
+ }
+ break;
+/* return pcmcia_register_erase_queue(a1, a2); break; */
+
return pcmcia_register_mtd(a1, a2); break;
case ReleaseConfiguration:
return pcmcia_release_configuration(a1); break;
@@ -2167,7 +2203,13 @@ int CardServices(int func, void *a1, void *a2, void *a3)
case RequestIRQ:
return pcmcia_request_irq(a1, a2); break;
case RequestWindow:
- return pcmcia_request_window(a1, a2); break;
+ {
+ window_handle_t w;
+ int ret = pcmcia_request_window(a1, a2, &w);
+ (window_handle_t *)a1 = w;
+ return ret;
+ }
+ break;
case ResetCard:
return pcmcia_reset_card(a1, a2); break;
case SetEventMask:
@@ -2209,6 +2251,55 @@ int CardServices(int func, void *a1, void *a2, void *a3)
OS-specific module glue goes here
======================================================================*/
+EXPORT_SYMBOL(pcmcia_access_configuration_register);
+EXPORT_SYMBOL(pcmcia_adjust_resource_info);
+EXPORT_SYMBOL(pcmcia_check_erase_queue);
+EXPORT_SYMBOL(pcmcia_close_memory);
+EXPORT_SYMBOL(pcmcia_copy_memory);
+EXPORT_SYMBOL(pcmcia_deregister_client);
+EXPORT_SYMBOL(pcmcia_deregister_erase_queue);
+EXPORT_SYMBOL(pcmcia_get_first_client);
+EXPORT_SYMBOL(pcmcia_get_card_services_info);
+EXPORT_SYMBOL(pcmcia_get_configuration_info);
+EXPORT_SYMBOL(pcmcia_get_next_client);
+EXPORT_SYMBOL(pcmcia_get_first_region);
+EXPORT_SYMBOL(pcmcia_get_first_tuple);
+EXPORT_SYMBOL(pcmcia_get_next_region);
+EXPORT_SYMBOL(pcmcia_get_next_tuple);
+EXPORT_SYMBOL(pcmcia_get_status);
+EXPORT_SYMBOL(pcmcia_get_tuple_data);
+EXPORT_SYMBOL(pcmcia_map_mem_page);
+EXPORT_SYMBOL(pcmcia_modify_configuration);
+EXPORT_SYMBOL(pcmcia_modify_window);
+EXPORT_SYMBOL(pcmcia_open_memory);
+EXPORT_SYMBOL(pcmcia_parse_tuple);
+EXPORT_SYMBOL(pcmcia_read_memory);
+EXPORT_SYMBOL(pcmcia_register_client);
+EXPORT_SYMBOL(pcmcia_register_erase_queue);
+EXPORT_SYMBOL(pcmcia_register_mtd);
+EXPORT_SYMBOL(pcmcia_release_configuration);
+EXPORT_SYMBOL(pcmcia_release_io);
+EXPORT_SYMBOL(pcmcia_release_irq);
+EXPORT_SYMBOL(pcmcia_release_window);
+EXPORT_SYMBOL(pcmcia_request_configuration);
+EXPORT_SYMBOL(pcmcia_request_io);
+EXPORT_SYMBOL(pcmcia_request_irq);
+EXPORT_SYMBOL(pcmcia_request_window);
+EXPORT_SYMBOL(pcmcia_reset_card);
+EXPORT_SYMBOL(pcmcia_set_event_mask);
+EXPORT_SYMBOL(pcmcia_validate_cis);
+EXPORT_SYMBOL(pcmcia_write_memory);
+EXPORT_SYMBOL(pcmcia_bind_device);
+EXPORT_SYMBOL(pcmcia_bind_mtd);
+EXPORT_SYMBOL(pcmcia_report_error);
+EXPORT_SYMBOL(pcmcia_suspend_card);
+EXPORT_SYMBOL(pcmcia_resume_card);
+EXPORT_SYMBOL(pcmcia_eject_card);
+EXPORT_SYMBOL(pcmcia_insert_card);
+EXPORT_SYMBOL(pcmcia_replace_cis);
+EXPORT_SYMBOL(pcmcia_get_first_window);
+EXPORT_SYMBOL(pcmcia_get_next_window);
+EXPORT_SYMBOL(pcmcia_get_mem_page);
EXPORT_SYMBOL(register_ss_entry);
EXPORT_SYMBOL(unregister_ss_entry);
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 82dff3f94..cac2d350a 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -120,7 +120,7 @@ typedef struct config_t {
typedef struct socket_info_t {
spinlock_t lock;
- ss_entry_t ss_entry;
+ struct pccard_operations * ss_entry;
u_int sock;
socket_state_t socket;
socket_cap_t cap;
@@ -136,8 +136,7 @@ typedef struct socket_info_t {
u_char *cis_virt;
config_t *config;
#ifdef CONFIG_CARDBUS
- u_int cb_cis_space;
- cb_bridge_map cb_cis_map;
+ struct resource * cb_cis_res;
u_char *cb_cis_virt;
struct cb_config_t *cb_config;
#endif
@@ -206,8 +205,7 @@ void cb_enable(socket_info_t *s);
void cb_disable(socket_info_t *s);
void read_cb_mem(socket_info_t *s, u_char fn, int space,
u_int addr, u_int len, void *ptr);
-int cb_setup_cis_mem(socket_info_t *s, int space);
-void cb_release_cis_mem(socket_info_t *s);
+void cb_release_cis_mem(socket_info_t * s);
/* In cistpl.c */
void read_cis_mem(socket_info_t *s, int attr,
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 8a97cd541..8c96585c6 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1,7 +1,6 @@
/*======================================================================
- Device driver for Intel 82365 and compatible PC Card controllers,
- and Yenta-compatible PCI-to-CardBus controllers.
+ Device driver for Intel 82365 and compatible PC Card controllers.
i82365.c 1.265 1999/11/10 18:36:21
@@ -66,7 +65,7 @@
#include "o2micro.h"
/* PCI-bus controllers */
-#include "yenta.h"
+#include "old-yenta.h"
#include "ti113x.h"
#include "smc34c90.h"
#include "topic.h"
@@ -156,57 +155,6 @@ MODULE_PARM(setup_time, "i");
MODULE_PARM(cmd_time, "i");
MODULE_PARM(recov_time, "i");
-#ifdef CONFIG_PCI
-/* Scan PCI bus? */
-static int do_pci_probe = 1;
-/* Default memory base address for CardBus controllers */
-static u_int cb_mem_base[] = { 0x68000000, 0xf8000000 };
-static int fast_pci = -1;
-static int hold_time = -1;
-/* Override BIOS interrupt routing mode? */
-static int irq_mode = -1;
-static int has_clkrun = -1;
-static int clkrun_sel = -1;
-static int pci_latency = -1;
-static int cb_latency = -1;
-static int cb_bus_base = 0;
-static int cb_bus_step = 2;
-static int cb_write_post = -1;
-MODULE_PARM(do_pci_probe, "i");
-MODULE_PARM(cb_mem_base, "i");
-MODULE_PARM(fast_pci, "i");
-MODULE_PARM(hold_time, "i");
-MODULE_PARM(irq_mode, "i");
-MODULE_PARM(has_clkrun, "i");
-MODULE_PARM(clkrun_sel, "i");
-MODULE_PARM(pci_latency, "i");
-MODULE_PARM(cb_latency, "i");
-MODULE_PARM(cb_bus_base, "i");
-MODULE_PARM(cb_bus_step, "i");
-MODULE_PARM(cb_write_post, "i");
-#endif
-
-#ifdef CONFIG_ISA
-#ifdef CONFIG_PCI
-/* PCI card status change interrupts? */
-static int pci_csc = 0;
-/* PCI IO card functional interrupts? */
-static int pci_int = 0;
-MODULE_PARM(pci_csc, "i");
-MODULE_PARM(pci_int, "i");
-#else /* no PCI */
-#define pci_csc 0
-#define pci_int 0
-#endif
-#else /* no ISA */
-#ifdef CONFIG_PCI
-#define pci_csc 0
-#define pci_int 1
-#else
-#error "No bus architectures defined!"
-#endif
-#endif
-
/*====================================================================*/
typedef struct cirrus_state_t {
@@ -248,24 +196,9 @@ typedef struct socket_info_t {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc;
#endif
-#ifdef CONFIG_PCI
- u_short vendor, device;
- u_char revision, bus, devfn;
- u_short bcr;
- u_char pci_lat, cb_lat, sub_bus;
- u_char cache, pmcs;
- u_int cb_phys;
- char *cb_virt;
-#endif
union {
cirrus_state_t cirrus;
vg46x_state_t vg46x;
-#ifdef CONFIG_PCI
- o2micro_state_t o2micro;
- ti113x_state_t ti113x;
- rl5c4xx_state_t rl5c4xx;
- topic_state_t topic;
-#endif
} state;
} socket_info_t;
@@ -281,10 +214,8 @@ static socket_info_t socket[8] = {
#ifdef CONFIG_ISA
static int grab_irq;
static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
-#define ISA_LOCK(n, f) \
- if (!(socket[n].flags & IS_CARDBUS)) spin_lock_irqsave(&isa_lock, f)
-#define ISA_UNLOCK(n, f) \
- if (!(socket[n].flags & IS_CARDBUS)) spin_unlock_irqrestore(&isa_lock, f)
+#define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
+#define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
#else
#define ISA_LOCK(n, f) do { } while (0)
#define ISA_UNLOCK(n, f) do { } while (0)
@@ -294,24 +225,10 @@ static struct timer_list poll_timer;
/*====================================================================*/
-#ifdef CONFIG_PCI
-
-#ifndef PCI_VENDOR_ID_INTEL
-#define PCI_VENDOR_ID_INTEL 0x8086
-#endif
-#ifndef PCI_VENDOR_ID_OMEGA
-#define PCI_VENDOR_ID_OMEGA 0x119b
-#endif
-#ifndef PCI_DEVICE_ID_OMEGA_PCMCIA
-#define PCI_DEVICE_ID_OMEGA_PCMCIA 0x1221
-#endif
-
/* Default settings for PCI command configuration register */
#define CMD_DFLT (PCI_COMMAND_IO|PCI_COMMAND_MEMORY| \
PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
-#endif
-
/* These definitions must match the pcic table! */
typedef enum pcic_id {
#ifdef CONFIG_ISA
@@ -319,17 +236,6 @@ typedef enum pcic_id {
IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
IS_PD6710, IS_PD672X, IS_VT83C469,
#endif
-#ifdef CONFIG_PCI
- IS_PD6729, IS_PD6730, IS_OZ6729, IS_OZ6730,
- IS_I82092AA, IS_OM82C092G,
- IS_PD6832, IS_OZ6832, IS_OZ6836, IS_OZ6812,
- IS_RL5C465, IS_RL5C466, IS_RL5C475, IS_RL5C476, IS_RL5C478,
- IS_SMC34C90,
- IS_TI1130, IS_TI1131, IS_TI1250A, IS_TI1220, IS_TI1221, IS_TI1210,
- IS_TI1251A, IS_TI1251B, IS_TI1450, IS_TI1225, IS_TI1211, IS_TI1420,
- IS_TOPIC95_A, IS_TOPIC95_B, IS_TOPIC97,
- IS_UNK_PCI, IS_UNK_CARDBUS
-#endif
} pcic_id;
/* Flags for classifying groups of controllers */
@@ -344,15 +250,11 @@ typedef enum pcic_id {
#define IS_VG_PWR 0x0800
#define IS_DF_PWR 0x1000
#define IS_PCI 0x2000
-#define IS_CARDBUS 0x4000
#define IS_ALIVE 0x8000
typedef struct pcic_t {
char *name;
u_short flags;
-#ifdef CONFIG_PCI
- u_short vendor, device;
-#endif
} pcic_t;
static pcic_t pcic[] = {
@@ -369,72 +271,6 @@ static pcic_t pcic[] = {
{ "Cirrus PD672x", IS_CIRRUS },
{ "VIA VT83C469", IS_CIRRUS|IS_VIA },
#endif
-#ifdef CONFIG_PCI
- { "Cirrus PD6729", IS_CIRRUS|IS_PCI,
- PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729 },
- { "Cirrus PD6730", IS_CIRRUS|IS_PCI,
- PCI_VENDOR_ID_CIRRUS, 0xffff },
- { "O2Micro OZ6729", IS_O2MICRO|IS_PCI|IS_VG_PWR,
- PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_6729 },
- { "O2Micro OZ6730", IS_O2MICRO|IS_PCI|IS_VG_PWR,
- PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_6730 },
- { "Intel 82092AA", IS_PCI,
- PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_OMEGA_PCMCIA },
- { "Omega Micro 82C092G", IS_PCI,
- PCI_VENDOR_ID_OMEGA, PCI_DEVICE_ID_OMEGA_PCMCIA },
- { "Cirrus PD6832", IS_CIRRUS|IS_CARDBUS,
- PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6832 },
- { "O2Micro OZ6832/OZ6833", IS_O2MICRO|IS_CARDBUS|IS_VG_PWR,
- PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_6832 },
- { "O2Micro OZ6836/OZ6860", IS_O2MICRO|IS_CARDBUS|IS_VG_PWR,
- PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_6836 },
- { "O2Micro OZ6812", IS_O2MICRO|IS_CARDBUS|IS_VG_PWR,
- PCI_VENDOR_ID_O2, PCI_DEVICE_ID_O2_6812 },
- { "Ricoh RL5C465", IS_RICOH|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465 },
- { "Ricoh RL5C466", IS_RICOH|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466 },
- { "Ricoh RL5C475", IS_RICOH|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C475 },
- { "Ricoh RL5C476", IS_RICOH|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476 },
- { "Ricoh RL5C478", IS_RICOH|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C478 },
- { "SMC 34C90", IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_SMC, PCI_DEVICE_ID_SMC_34C90 },
- { "TI 1130", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1130 },
- { "TI 1131", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1131 },
- { "TI 1250A", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250A },
- { "TI 1220", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1220 },
- { "TI 1221", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1221 },
- { "TI 1210", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1210 },
- { "TI 1251A", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251A },
- { "TI 1251B", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1251B },
- { "TI 1450", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1450 },
- { "TI 1225", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1225 },
- { "TI 1211", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1211 },
- { "TI 1420", IS_TI|IS_CARDBUS|IS_DF_PWR,
- PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420 },
- { "Toshiba ToPIC95-A", IS_CARDBUS|IS_TOPIC|IS_DF_PWR,
- PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95_A },
- { "Toshiba ToPIC95-B", IS_CARDBUS|IS_TOPIC|IS_DF_PWR,
- PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC95_B },
- { "Toshiba ToPIC97", IS_CARDBUS|IS_TOPIC|IS_DF_PWR,
- PCI_VENDOR_ID_TOSHIBA, PCI_DEVICE_ID_TOSHIBA_TOPIC97 },
- { "Unknown", IS_PCI|IS_UNKNOWN, 0, 0 },
- { "Unknown", IS_CARDBUS|IS_DF_PWR|IS_UNKNOWN, 0, 0 }
-#endif
};
#define PCIC_COUNT (sizeof(pcic)/sizeof(pcic_t))
@@ -443,30 +279,22 @@ static pcic_t pcic[] = {
/* Some PCI shortcuts */
-#define pci_readb pcibios_read_config_byte
-#define pci_writeb pcibios_write_config_byte
-#define pci_readw pcibios_read_config_word
-#define pci_writew pcibios_write_config_word
-#define pci_readl pcibios_read_config_dword
-#define pci_writel pcibios_write_config_dword
+#define config_readb(sock, r, v) pci_read_config_byte((sock)->pdev, r, v)
+#define config_readw(sock, r, v) pci_read_config_word((sock)->pdev, r, v)
+#define config_readl(sock, r, v) pci_read_config_dword((sock)->pdev, r, v)
+#define config_writeb(sock, r, v) pci_write_config_byte((sock)->pdev, r, v)
+#define config_writew(sock, r, v) pci_write_config_word((sock)->pdev, r, v)
+#define config_writel(sock, r, v) pci_write_config_dword((sock)->pdev, r, v)
#define cb_readb(s, r) readb(socket[s].cb_virt + (r))
#define cb_readl(s, r) readl(socket[s].cb_virt + (r))
#define cb_writeb(s, r, v) writeb(v, socket[s].cb_virt + (r))
#define cb_writel(s, r, v) writel(v, socket[s].cb_virt + (r))
-static void cb_get_power(u_short sock, socket_state_t *state);
-static void cb_set_power(u_short sock, socket_state_t *state);
-
/*====================================================================*/
static u_char i365_get(u_short sock, u_short reg)
{
-#ifdef CONFIG_PCI
- if (socket[sock].cb_virt)
- return cb_readb(sock, 0x0800 + reg);
- else
-#endif
{
ioaddr_t port = socket[sock].ioaddr;
u_char val;
@@ -478,11 +306,6 @@ static u_char i365_get(u_short sock, u_short reg)
static void i365_set(u_short sock, u_short reg, u_char data)
{
-#ifdef CONFIG_PCI
- if (socket[sock].cb_virt)
- cb_writeb(sock, 0x0800 + reg, data);
- else
-#endif
{
ioaddr_t port = socket[sock].ioaddr;
u_char val = I365_REG(socket[sock].psock, reg);
@@ -568,14 +391,6 @@ static void cirrus_set_state(u_short s)
i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]);
}
-#ifdef CONFIG_PCI
-static int cirrus_set_irq_mode(u_short s, int pcsc, int pint)
-{
- flip(socket[s].bcr, PD6832_BCR_MGMT_IRQ_ENA, !pcsc);
- return 0;
-}
-#endif /* CONFIG_PCI */
-
static u_int __init cirrus_set_opts(u_short s, char *buf)
{
socket_info_t *t = &socket[s];
@@ -591,7 +406,7 @@ static u_int __init cirrus_set_opts(u_short s, char *buf)
strcat(buf, " [dyn mode]");
if (p->misc1 & PD67_MC1_INPACK_ENA)
strcat(buf, " [inpack]");
- if (!(t->flags & (IS_PCI | IS_CARDBUS))) {
+ if (!(t->flags & IS_PCI)) {
if (p->misc2 & PD67_MC2_IRQ15_RI)
mask &= ~0x8000;
if (has_led > 0) {
@@ -605,13 +420,6 @@ static u_int __init cirrus_set_opts(u_short s, char *buf)
if (p->misc2 & PD67_MC2_FREQ_BYPASS)
strcat(buf, " [freq bypass]");
}
-#ifdef CONFIG_PCI
- } else {
- p->misc1 &= ~PD67_MC1_MEDIA_ENA;
- flip(p->misc2, PD67_MC2_FAST_PCI, fast_pci);
- if (p->misc2 & PD67_MC2_IRQ15_RI)
- mask &= (socket[s].type == IS_PD6730) ? ~0x0400 : ~0x8000;
-#endif
}
if (!(t->flags & IS_VIA)) {
if (setup_time >= 0)
@@ -687,441 +495,6 @@ static u_int __init vg46x_set_opts(u_short s, char *buf)
#endif
-/*======================================================================
-
- Code to save and restore global state information for TI 1130 and
- TI 1131 controllers, and to set and report global configuration
- options.
-
-======================================================================*/
-
-#ifdef CONFIG_PCI
-
-static void ti113x_get_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- ti113x_state_t *p = &socket[s].state.ti113x;
- pci_readl(t->bus, t->devfn, TI113X_SYSTEM_CONTROL, &p->sysctl);
- pci_readb(t->bus, t->devfn, TI113X_CARD_CONTROL, &p->cardctl);
- pci_readb(t->bus, t->devfn, TI113X_DEVICE_CONTROL, &p->devctl);
- pci_readb(t->bus, t->devfn, TI1250_DIAGNOSTIC, &p->diag);
-}
-
-static void ti113x_set_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- ti113x_state_t *p = &socket[s].state.ti113x;
- pci_writel(t->bus, t->devfn, TI113X_SYSTEM_CONTROL, p->sysctl);
- pci_writeb(t->bus, t->devfn, TI113X_CARD_CONTROL, p->cardctl);
- pci_writeb(t->bus, t->devfn, TI113X_DEVICE_CONTROL, p->devctl);
- pci_writeb(t->bus, t->devfn, TI1250_MULTIMEDIA_CTL, 0);
- pci_writeb(t->bus, t->devfn, TI1250_DIAGNOSTIC, p->diag);
- i365_set_pair(s, TI113X_IO_OFFSET(0), 0);
- i365_set_pair(s, TI113X_IO_OFFSET(1), 0);
-}
-
-static int ti113x_set_irq_mode(u_short s, int pcsc, int pint)
-{
- socket_info_t *t = &socket[s];
- ti113x_state_t *p = &t->state.ti113x;
- t->intr = (pcsc) ? I365_INTR_ENA : 0;
- if (t->type <= IS_TI1131) {
- p->cardctl &= ~(TI113X_CCR_PCI_IRQ_ENA |
- TI113X_CCR_PCI_IREQ | TI113X_CCR_PCI_CSC);
- if (pcsc)
- p->cardctl |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_CSC;
- if (pint)
- p->cardctl |= TI113X_CCR_PCI_IRQ_ENA | TI113X_CCR_PCI_IREQ;
- } else if (t->type == IS_TI1250A) {
- p->diag &= TI1250_DIAG_PCI_CSC | TI1250_DIAG_PCI_IREQ;
- if (pcsc)
- p->diag |= TI1250_DIAG_PCI_CSC;
- if (pint)
- p->diag |= TI1250_DIAG_PCI_IREQ;
- }
- return 0;
-}
-
-static u_int __init ti113x_set_opts(u_short s, char *buf)
-{
- socket_info_t *t = &socket[s];
- ti113x_state_t *p = &t->state.ti113x;
- u_int mask = 0xffff;
- int old = (t->type <= IS_TI1131);
-
- flip(p->sysctl, TI113X_SCR_CLKRUN_ENA, has_clkrun);
- flip(p->sysctl, TI113X_SCR_CLKRUN_SEL, clkrun_sel);
- flip(p->cardctl, TI113X_CCR_RIENB, has_ring);
- p->cardctl &= ~TI113X_CCR_ZVENABLE;
- switch (irq_mode) {
- case 1:
- p->devctl &= ~TI113X_DCR_IMODE_MASK;
- p->devctl |= TI113X_DCR_IMODE_ISA;
- break;
- case 2:
- p->devctl &= ~TI113X_DCR_IMODE_MASK;
- p->devctl |= TI113X_DCR_IMODE_SERIAL;
- break;
- case 3:
- p->devctl &= ~TI113X_DCR_IMODE_MASK;
- p->devctl |= TI12XX_DCR_IMODE_ALL_SERIAL;
- break;
- default:
- if ((p->devctl & TI113X_DCR_IMODE_MASK) == 0)
- p->devctl |= TI113X_DCR_IMODE_ISA;
- }
- if (p->cardctl & TI113X_CCR_RIENB) {
- strcat(buf, " [ring]");
- if (old) mask &= ~0x8000;
- }
- if (old && (p->sysctl & TI113X_SCR_CLKRUN_ENA)) {
- if (p->sysctl & TI113X_SCR_CLKRUN_SEL) {
- strcat(buf, " [clkrun irq 12]");
- mask &= ~0x1000;
- } else {
- strcat(buf, " [clkrun irq 10]");
- mask &= ~0x0400;
- }
- }
- if (p->sysctl & TI113X_SCR_PWRSAVINGS)
- strcat(buf, " [pwr save]");
- switch (p->devctl & TI113X_DCR_IMODE_MASK) {
- case TI12XX_DCR_IMODE_PCI_ONLY:
- strcat(buf, " [pci only]");
- mask = 0;
- break;
- case TI113X_DCR_IMODE_ISA:
- strcat(buf, " [isa irq]");
- if (old) mask &= ~0x0018;
- break;
- case TI113X_DCR_IMODE_SERIAL:
- strcat(buf, " [pci + serial irq]");
- mask = 0xffff;
- break;
- case TI12XX_DCR_IMODE_ALL_SERIAL:
- strcat(buf, " [serial pci & irq]");
- mask = 0xffff;
- break;
- }
- return mask;
-}
-
-#endif
-
-/*======================================================================
-
- Code to save and restore global state information for the Ricoh
- RL5C4XX controllers, and to set and report global configuration
- options.
-
-======================================================================*/
-
-#ifdef CONFIG_PCI
-
-static void rl5c4xx_get_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- rl5c4xx_state_t *p = &socket[s].state.rl5c4xx;
- pci_readw(t->bus, t->devfn, RL5C4XX_MISC, &p->misc);
- pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_CTL, &p->ctl);
- pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_IO_0, &p->io);
- pci_readw(t->bus, t->devfn, RL5C4XX_16BIT_MEM_0, &p->mem);
-}
-
-static void rl5c4xx_set_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- rl5c4xx_state_t *p = &socket[s].state.rl5c4xx;
- pci_writew(t->bus, t->devfn, RL5C4XX_MISC, p->misc);
- pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_CTL, p->ctl);
- pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_IO_0, p->io);
- pci_writew(t->bus, t->devfn, RL5C4XX_16BIT_MEM_0, p->mem);
-}
-
-static u_int __init rl5c4xx_set_opts(u_short s, char *buf)
-{
- rl5c4xx_state_t *p = &socket[s].state.rl5c4xx;
- u_int mask = 0xffff;
- int old = (socket[s].type < IS_RL5C475);
-
- p->ctl = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
- if (old) p->ctl |= RL5C46X_16CTL_LEVEL_1 | RL5C46X_16CTL_LEVEL_2;
-
- if (setup_time >= 0) {
- p->io = (p->io & ~RL5C4XX_SETUP_MASK) +
- ((setup_time+1) << RL5C4XX_SETUP_SHIFT);
- p->mem = (p->mem & ~RL5C4XX_SETUP_MASK) +
- (setup_time << RL5C4XX_SETUP_SHIFT);
- }
- if (cmd_time >= 0) {
- p->io = (p->io & ~RL5C4XX_CMD_MASK) +
- (cmd_time << RL5C4XX_CMD_SHIFT);
- p->mem = (p->mem & ~RL5C4XX_CMD_MASK) +
- (cmd_time << RL5C4XX_CMD_SHIFT);
- }
- if (hold_time >= 0) {
- p->io = (p->io & ~RL5C4XX_HOLD_MASK) +
- (hold_time << RL5C4XX_HOLD_SHIFT);
- p->mem = (p->mem & ~RL5C4XX_HOLD_MASK) +
- (hold_time << RL5C4XX_HOLD_SHIFT);
- }
- if (!old) {
- switch (irq_mode) {
- case 1:
- p->misc &= ~RL5C47X_MISC_SRIRQ_ENA; break;
- case 2:
- p->misc |= RL5C47X_MISC_SRIRQ_ENA; break;
- }
- if (p->misc & RL5C47X_MISC_SRIRQ_ENA)
- sprintf(buf, " [serial irq]");
- else
- sprintf(buf, " [isa irq]");
- buf += strlen(buf);
- }
- sprintf(buf, " [io %d/%d/%d] [mem %d/%d/%d]",
- (p->io & RL5C4XX_SETUP_MASK) >> RL5C4XX_SETUP_SHIFT,
- (p->io & RL5C4XX_CMD_MASK) >> RL5C4XX_CMD_SHIFT,
- (p->io & RL5C4XX_HOLD_MASK) >> RL5C4XX_HOLD_SHIFT,
- (p->mem & RL5C4XX_SETUP_MASK) >> RL5C4XX_SETUP_SHIFT,
- (p->mem & RL5C4XX_CMD_MASK) >> RL5C4XX_CMD_SHIFT,
- (p->mem & RL5C4XX_HOLD_MASK) >> RL5C4XX_HOLD_SHIFT);
- return mask;
-}
-
-#endif
-
-/*======================================================================
-
- Code to save and restore global state information for O2Micro
- controllers, and to set and report global configuration options.
-
-======================================================================*/
-
-#ifdef CONFIG_PCI
-
-static void o2micro_get_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- o2micro_state_t *p = &socket[s].state.o2micro;
- if ((t->revision == 0x34) || (t->revision == 0x62) ||
- (t->type == IS_OZ6812)) {
- p->mode_a = i365_get(s, O2_MODE_A_2);
- p->mode_b = i365_get(s, O2_MODE_B_2);
- } else {
- p->mode_a = i365_get(s, O2_MODE_A);
- p->mode_b = i365_get(s, O2_MODE_B);
- }
- p->mode_c = i365_get(s, O2_MODE_C);
- p->mode_d = i365_get(s, O2_MODE_D);
- if (t->flags & IS_CARDBUS) {
- p->mhpg = i365_get(s, O2_MHPG_DMA);
- p->fifo = i365_get(s, O2_FIFO_ENA);
- p->mode_e = i365_get(s, O2_MODE_E);
- }
-}
-
-static void o2micro_set_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- o2micro_state_t *p = &socket[s].state.o2micro;
- if ((t->revision == 0x34) || (t->revision == 0x62) ||
- (t->type == IS_OZ6812)) {
- i365_set(s, O2_MODE_A_2, p->mode_a);
- i365_set(s, O2_MODE_B_2, p->mode_b);
- } else {
- i365_set(s, O2_MODE_A, p->mode_a);
- i365_set(s, O2_MODE_B, p->mode_b);
- }
- i365_set(s, O2_MODE_C, p->mode_c);
- i365_set(s, O2_MODE_D, p->mode_d);
- if (t->flags & IS_CARDBUS) {
- i365_set(s, O2_MHPG_DMA, p->mhpg);
- i365_set(s, O2_FIFO_ENA, p->fifo);
- i365_set(s, O2_MODE_E, p->mode_e);
- }
-}
-
-static u_int __init o2micro_set_opts(u_short s, char *buf)
-{
- socket_info_t *t = &socket[s];
- o2micro_state_t *p = &socket[s].state.o2micro;
- u_int mask = 0xffff;
-
- p->mode_b = (p->mode_b & ~O2_MODE_B_IDENT) | O2_MODE_B_ID_CSTEP;
- flip(p->mode_b, O2_MODE_B_IRQ15_RI, has_ring);
- p->mode_c &= ~(O2_MODE_C_ZVIDEO | O2_MODE_C_DREQ_MASK);
- if (t->flags & IS_CARDBUS) {
- p->mode_d &= ~O2_MODE_D_W97_IRQ;
- p->mode_e &= ~O2_MODE_E_MHPG_DMA;
- p->mhpg |= O2_MHPG_CINT_ENA | O2_MHPG_CSC_ENA;
- p->mhpg &= ~O2_MHPG_CHANNEL;
- if (t->revision == 0x34)
- p->mode_c = 0x20;
- } else {
- if (p->mode_b & O2_MODE_B_IRQ15_RI) mask &= ~0x8000;
- }
- sprintf(buf, " [a %02x] [b %02x] [c %02x] [d %02x]",
- p->mode_a, p->mode_b, p->mode_c, p->mode_d);
- if (t->flags & IS_CARDBUS) {
- buf += strlen(buf);
- sprintf(buf, " [mhpg %02x] [fifo %02x] [e %02x]",
- p->mhpg, p->fifo, p->mode_e);
- }
- return mask;
-}
-
-#endif
-
-/*======================================================================
-
- Code to save and restore global state information for the Toshiba
- ToPIC 95 and 97 controllers, and to set and report global
- configuration options.
-
-======================================================================*/
-
-#ifdef CONFIG_PCI
-
-static void topic_get_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- topic_state_t *p = &socket[s].state.topic;
- pci_readb(t->bus, t->devfn, TOPIC_SLOT_CONTROL, &p->slot);
- pci_readb(t->bus, t->devfn, TOPIC_CARD_CONTROL, &p->ccr);
- pci_readb(t->bus, t->devfn, TOPIC_CARD_DETECT, &p->cdr);
- pci_readl(t->bus, t->devfn, TOPIC_REGISTER_CONTROL, &p->rcr);
-}
-
-static void topic_set_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- topic_state_t *p = &socket[s].state.topic;
- pci_writeb(t->bus, t->devfn, TOPIC_SLOT_CONTROL, p->slot);
- pci_writeb(t->bus, t->devfn, TOPIC_CARD_CONTROL, p->ccr);
- pci_writeb(t->bus, t->devfn, TOPIC_CARD_DETECT, p->cdr);
- pci_writel(t->bus, t->devfn, TOPIC_REGISTER_CONTROL, p->rcr);
-}
-
-static int topic_set_irq_mode(u_short s, int pcsc, int pint)
-{
- if (socket[s].type == IS_TOPIC97) {
- topic_state_t *p = &socket[s].state.topic;
- flip(p->ccr, TOPIC97_ICR_IRQSEL, pcsc);
- return 0;
- } else {
- /* no ISA card status change irq */
- return !pcsc;
- }
-}
-
-static u_int __init topic_set_opts(u_short s, char *buf)
-{
- topic_state_t *p = &socket[s].state.topic;
-
- p->slot |= TOPIC_SLOT_SLOTON|TOPIC_SLOT_SLOTEN|TOPIC_SLOT_ID_LOCK;
- p->cdr |= TOPIC_CDR_MODE_PC32;
- p->cdr &= ~(TOPIC_CDR_SW_DETECT);
- sprintf(buf, " [slot 0x%02x] [ccr 0x%02x] [cdr 0x%02x] [rcr 0x%02x]",
- p->slot, p->ccr, p->cdr, p->rcr);
- return 0xffff;
-}
-
-#endif
-
-/*======================================================================
-
- Routines to handle common CardBus options
-
-======================================================================*/
-
-#ifdef CONFIG_PCI
-
-static void cb_get_state(u_short s)
-{
- socket_info_t *t = &socket[s];
-
- pci_readb(t->bus, t->devfn, PCI_CACHE_LINE_SIZE, &t->cache);
- pci_readb(t->bus, t->devfn, PCI_LATENCY_TIMER, &t->pci_lat);
- pci_readb(t->bus, t->devfn, CB_LATENCY_TIMER, &t->cb_lat);
- pci_readb(t->bus, t->devfn, CB_CARDBUS_BUS, &t->cap.cardbus);
- pci_readb(t->bus, t->devfn, CB_SUBORD_BUS, &t->sub_bus);
- pci_readw(t->bus, t->devfn, CB_BRIDGE_CONTROL, &t->bcr);
- {
- struct pci_dev *pdev = pci_find_slot(t->bus, t->devfn);
- t->cap.pci_irq = (pdev) ? pdev->irq : 0;
- }
- if (t->cap.pci_irq >= NR_IRQS) t->cap.pci_irq = 0;
-}
-
-static void cb_set_state(u_short s)
-{
- socket_info_t *t = &socket[s];
- if (t->pmcs)
- pci_writew(t->bus, t->devfn, t->pmcs, PCI_PMCS_PWR_STATE_D0);
- pci_writel(t->bus, t->devfn, CB_LEGACY_MODE_BASE, 0);
- pci_writel(t->bus, t->devfn, PCI_BASE_ADDRESS_0, t->cb_phys);
- pci_writew(t->bus, t->devfn, PCI_COMMAND, CMD_DFLT);
- pci_writeb(t->bus, t->devfn, PCI_CACHE_LINE_SIZE, t->cache);
- pci_writeb(t->bus, t->devfn, PCI_LATENCY_TIMER, t->pci_lat);
- pci_writeb(t->bus, t->devfn, CB_LATENCY_TIMER, t->cb_lat);
- pci_writeb(t->bus, t->devfn, CB_CARDBUS_BUS, t->cap.cardbus);
- pci_writeb(t->bus, t->devfn, CB_SUBORD_BUS, t->sub_bus);
- pci_writew(t->bus, t->devfn, CB_BRIDGE_CONTROL, t->bcr);
-}
-
-static int cb_get_irq_mode(u_short s)
-{
- return (!(socket[s].bcr & CB_BCR_ISA_IRQ));
-}
-
-static int cb_set_irq_mode(u_short s, int pcsc, int pint)
-{
- socket_info_t *t = &socket[s];
- flip(t->bcr, CB_BCR_ISA_IRQ, !(pint));
- if (t->flags & IS_CIRRUS)
- return cirrus_set_irq_mode(s, pcsc, pint);
- else if (t->flags & IS_TI)
- return ti113x_set_irq_mode(s, pcsc, pint);
- else if (t->flags & IS_TOPIC)
- return topic_set_irq_mode(s, pcsc, pint);
- return 0;
-}
-
-static void __init pci_scan(u_short sock);
-
-static void __init cb_set_opts(u_short s, char *buf)
-{
- socket_info_t *t = &socket[s];
- t->bcr |= CB_BCR_WRITE_POST;
- /* some TI1130's seem to exhibit problems with write posting */
- if (((t->type == IS_TI1130) && (t->revision == 4) &&
- (cb_write_post < 0)) || (cb_write_post == 0))
- t->bcr &= ~CB_BCR_WRITE_POST;
- if (t->cache == 0) t->cache = 8;
- if (pci_latency >= 0) t->pci_lat = pci_latency;
- if (t->pci_lat == 0) t->pci_lat = 0xa8;
- if (cb_latency >= 0) t->cb_lat = cb_latency;
- if (t->cb_lat == 0) t->cb_lat = 0xb0;
- if ((t->cap.pci_irq == 0) && (pci_csc || pci_int) && do_scan)
- pci_scan(s);
- if (t->cap.pci_irq == 0)
- strcat(buf, " [no pci irq]");
- else
- sprintf(buf, " [pci irq %d]", t->cap.pci_irq);
- buf += strlen(buf);
- if ((cb_bus_base > 0) || (t->cap.cardbus == 0)) {
- if (cb_bus_base <= 0) cb_bus_base = 0x20;
- t->cap.cardbus = cb_bus_base;
- t->sub_bus = cb_bus_base+cb_bus_step;
- cb_bus_base += cb_bus_step+1;
- }
- if (!(t->flags & IS_TOPIC))
- t->cap.features |= SS_CAP_PAGE_REGS;
- sprintf(buf, " [lat %d/%d] [bus %d/%d]",
- t->pci_lat, t->cb_lat, t->cap.cardbus, t->sub_bus);
-}
-
-#endif
/*======================================================================
@@ -1138,27 +511,11 @@ static void get_bridge_state(u_short s)
else if (t->flags & IS_VADEM)
vg46x_get_state(s);
#endif
-#ifdef CONFIG_PCI
- else if (t->flags & IS_O2MICRO)
- o2micro_get_state(s);
- else if (t->flags & IS_TI)
- ti113x_get_state(s);
- else if (t->flags & IS_RICOH)
- rl5c4xx_get_state(s);
- else if (t->flags & IS_TOPIC)
- topic_get_state(s);
- if (t->flags & IS_CARDBUS)
- cb_get_state(s);
-#endif
}
static void set_bridge_state(u_short s)
{
socket_info_t *t = &socket[s];
-#ifdef CONFIG_PCI
- if (t->flags & IS_CARDBUS)
- cb_set_state(s);
-#endif
if (t->flags & IS_CIRRUS)
cirrus_set_state(s);
else {
@@ -1170,16 +527,6 @@ static void set_bridge_state(u_short s)
if (t->flags & IS_VADEM)
vg46x_set_state(s);
#endif
-#ifdef CONFIG_PCI
- if (t->flags & IS_O2MICRO)
- o2micro_set_state(s);
- else if (t->flags & IS_TI)
- ti113x_set_state(s);
- else if (t->flags & IS_RICOH)
- rl5c4xx_set_state(s);
- else if (t->flags & IS_TOPIC)
- topic_set_state(s);
-#endif
}
static u_int __init set_bridge_opts(u_short s, u_short ns)
@@ -1201,32 +548,10 @@ static u_int __init set_bridge_opts(u_short s, u_short ns)
else if (socket[i].flags & IS_VADEM)
m = vg46x_set_opts(i, buf);
#endif
-#ifdef CONFIG_PCI
- else if (socket[i].flags & IS_O2MICRO)
- m = o2micro_set_opts(i, buf);
- else if (socket[i].flags & IS_TI)
- m = ti113x_set_opts(i, buf);
- else if (socket[i].flags & IS_RICOH)
- m = rl5c4xx_set_opts(i, buf);
- else if (socket[i].flags & IS_TOPIC)
- m = topic_set_opts(i, buf);
- if (socket[i].flags & IS_CARDBUS)
- cb_set_opts(i, buf+strlen(buf));
-#endif
set_bridge_state(i);
printk(KERN_INFO " host opts [%d]:%s\n", i,
(*buf) ? buf : " none");
}
-#ifdef CONFIG_PCI
- /* Mask out all PCI interrupts */
- for (i = 0; i < sockets; i++)
- m &= ~(1<<socket[i].cap.pci_irq);
- {
- struct pci_dev *p;
- for (p = pci_devices; p; p = p->next)
- m &= ~(1<<p->irq);
- }
-#endif
return m;
}
@@ -1241,11 +566,6 @@ static u_short irq_sock;
static void irq_count(int irq, void *dev, struct pt_regs *regs)
{
-#ifdef CONFIG_PCI
- if (socket[irq_sock].flags & IS_CARDBUS) {
- cb_writel(irq_sock, CB_SOCKET_EVENT, -1);
- } else
-#endif
i365_get(irq_sock, I365_CSC);
irq_hits++;
DEBUG(2, "-> hit on irq %d\n", irq);
@@ -1268,23 +588,9 @@ static u_int __init test_irq(u_short sock, int irq, int pci)
}
/* Generate one interrupt */
-#ifdef CONFIG_PCI
- if (socket[sock].flags & IS_CARDBUS) {
- cb_writel(sock, CB_SOCKET_EVENT, -1);
- i365_set(sock, I365_CSCINT, I365_CSC_STSCHG | (csc << 4));
- cb_writel(sock, CB_SOCKET_EVENT, -1);
- cb_writel(sock, CB_SOCKET_MASK, CB_SM_CSTSCHG);
- cb_writel(sock, CB_SOCKET_FORCE, CB_SE_CSTSCHG);
- udelay(1000);
- cb_writel(sock, CB_SOCKET_EVENT, -1);
- cb_writel(sock, CB_SOCKET_MASK, 0);
- } else
-#endif
- {
- i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (csc << 4));
- i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
- udelay(1000);
- }
+ i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (csc << 4));
+ i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
+ udelay(1000);
free_irq(irq, NULL);
@@ -1308,11 +614,6 @@ static u_int __init isa_scan(u_short sock, u_int mask0)
mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
#endif
-#ifdef CONFIG_PCI
- /* Only scan if we can select ISA csc irq's */
- if (!(socket[sock].flags & IS_CARDBUS) ||
- (cb_set_irq_mode(sock, 0, 0) == 0))
-#endif
if (do_scan) {
set_bridge_state(sock);
i365_set(sock, I365_CSCINT, 0);
@@ -1348,26 +649,6 @@ static u_int __init isa_scan(u_short sock, u_int mask0)
#endif /* CONFIG_ISA */
-#ifdef CONFIG_PCI
-
-static void __init pci_scan(u_short sock)
-{
- u_int i;
-
- cb_set_irq_mode(sock, 1, 0);
- set_bridge_state(sock);
- i365_set(sock, I365_CSCINT, 0);
- /* Only probe irq's 9..11, to be conservative */
- for (i = 9; i < 12; i++) {
- if ((test_irq(sock, i, 1) == 0) &&
- (test_irq(sock, i, 1) == 0))
- break;
- }
- if (i < 12) socket[sock].cap.pci_irq = i;
-}
-
-#endif /* CONFIG_PCI */
-
/*====================================================================*/
/* Time conversion functions */
@@ -1498,18 +779,7 @@ static void __init add_pcic(int ns, int type)
if (base == 0) printk("\n");
printk(KERN_INFO " %s", pcic[type].name);
-#ifdef CONFIG_PCI
- if (t->flags & IS_UNKNOWN)
- printk(" [0x%04x 0x%04x]", t->vendor, t->device);
- if (t->flags & IS_CARDBUS)
- printk(" PCI-to-CardBus at bus %d slot %d, mem 0x%08x",
- t->bus, PCI_SLOT(t->devfn), t->cb_phys);
- else if (t->flags & IS_PCI)
- printk(" PCI-to-PCMCIA at bus %d slot %d, port %#x",
- t->bus, PCI_SLOT(t->devfn), t->ioaddr);
- else
-#endif
- printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
+ printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
t->ioaddr, t->psock*0x40);
printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
@@ -1528,19 +798,7 @@ static void __init add_pcic(int ns, int type)
#else
printk(KERN_INFO " PCI card interrupts,");
#endif
-
-#ifdef CONFIG_PCI
- /* Can we use a PCI interrupt for card status changes? */
- if (pci_csc && t->cap.pci_irq) {
- for (i = 0; i < ns; i++)
- if (_check_irq(t[i].cap.pci_irq, SA_SHIRQ)) break;
- if (i == ns) {
- use_pci = 1;
- printk(" PCI status changes\n");
- }
- }
-#endif
-
+
#ifdef CONFIG_ISA
/* Poll if only two interrupts available */
if (!use_pci && !poll_interval) {
@@ -1578,197 +836,11 @@ static void __init add_pcic(int ns, int type)
t[i].cap.features |= SS_CAP_PCCARD;
t[i].cap.map_size = 0x1000;
t[i].cap.irq_mask = mask;
- if (pci_int && t[i].cap.pci_irq)
- t[i].cap.irq_mask |= (1 << t[i].cap.pci_irq);
t[i].cs_irq = isa_irq;
-#ifdef CONFIG_PCI
- if (t[i].flags & IS_CARDBUS) {
- t[i].cap.features |= SS_CAP_CARDBUS;
- cb_set_irq_mode(i, pci_csc && t[i].cap.pci_irq,
- pci_int && t[i].cap.pci_irq);
- }
-#endif
}
} /* add_pcic */
-/*====================================================================*/
-
-#ifdef CONFIG_PCI
-
-typedef struct pci_dev *pci_id_t;
-static int __init pci_lookup(u_int class, pci_id_t *id,
- u_char *bus, u_char *devfn)
-{
- if ((*id = pci_find_class(class<<8, *id)) != NULL) {
- *bus = (*id)->bus->number;
- *devfn = (*id)->devfn;
- return 0;
- } else return -1;
-}
-
-static void __init add_pci_bridge(int type, u_char bus, u_char devfn,
- u_short v, u_short d)
-{
- socket_info_t *s = &socket[sockets];
- u_short i, ns;
- u_int addr;
-
- if (type == PCIC_COUNT) type = IS_UNK_PCI;
- pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &addr);
- addr &= ~0x1;
- pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT);
- for (i = ns = 0; i < ((type == IS_I82092AA) ? 4 : 2); i++) {
- s->bus = bus; s->devfn = devfn;
- s->vendor = v; s->device = d;
- add_socket(addr, i, type);
- ns++; s++;
- }
- add_pcic(ns, type);
-}
-
-static void __init add_cb_bridge(int type, u_char bus, u_char devfn,
- u_short v, u_short d0)
-{
- socket_info_t *s = &socket[sockets];
- u_short d, ns, i;
- u_char a, b, r, max;
-
- /* PCI bus enumeration is broken on some systems */
- for (ns = 0; ns < sockets; ns++)
- if ((socket[ns].bus == bus) && (socket[ns].devfn == devfn))
- return;
-
- if (type == PCIC_COUNT) type = IS_UNK_CARDBUS;
- pci_readb(bus, devfn, PCI_HEADER_TYPE, &a);
- pci_readb(bus, devfn, PCI_CLASS_REVISION, &r);
- max = (a & 0x80) ? 8 : 1;
- for (ns = 0; ns < max; ns++, s++, devfn++) {
- if (pci_readw(bus, devfn, PCI_DEVICE_ID, &d) || (d != d0))
- break;
- s->bus = bus; s->devfn = devfn;
- s->vendor = v; s->device = d; s->revision = r;
-
- /* Check for power management capabilities */
- pci_readb(bus, devfn, PCI_STATUS, &a);
- if (a & PCI_STATUS_CAPLIST) {
- pci_readb(bus, devfn, PCI_CB_CAPABILITY_POINTER, &b);
- while (b != 0) {
- pci_readb(bus, devfn, b+PCI_CAPABILITY_ID, &a);
- if (a == PCI_CAPABILITY_PM) {
- s->pmcs = b + PCI_PM_CONTROL_STATUS;
- break;
- }
- pci_readb(bus, devfn, b+PCI_NEXT_CAPABILITY, &b);
- }
- }
- /* If capability exists, make sure we're in D0 state */
- if (s->pmcs)
- pci_writew(bus, devfn, s->pmcs, PCI_PMCS_PWR_STATE_D0);
-
- /* Map CardBus registers if they are not already mapped */
- pci_writel(bus, devfn, CB_LEGACY_MODE_BASE, 0);
- pci_readl(bus, devfn, PCI_BASE_ADDRESS_0, &s->cb_phys);
- if (s->cb_phys == 0) {
- pci_writew(bus, devfn, PCI_COMMAND, CMD_DFLT);
- for (i = 0; i < sizeof(cb_mem_base)/sizeof(u_int); i++) {
- s->cb_phys = cb_mem_base[i];
- s->cb_virt = ioremap(s->cb_phys, 0x1000);
- pci_writel(bus, devfn, PCI_BASE_ADDRESS_0, s->cb_phys);
- /* Simple sanity checks */
- if (!(readb(s->cb_virt+0x800+I365_IDENT) & 0x70) &&
- !(readb(s->cb_virt+0x800+I365_CSC) &&
- readb(s->cb_virt+0x800+I365_CSC) &&
- readb(s->cb_virt+0x800+I365_CSC)))
- break;
- iounmap(s->cb_virt);
- }
- if (i == sizeof(cb_mem_base)/sizeof(u_int)) {
- pci_writel(bus, devfn, PCI_BASE_ADDRESS_0, 0);
- s->cb_phys = 0; s->cb_virt = NULL;
- printk("\n");
- printk(KERN_NOTICE " Bridge register mapping failed:"
- " check cb_mem_base setting\n");
- break;
- }
- cb_mem_base[0] = cb_mem_base[i] + PAGE_SIZE;
- } else {
- s->cb_virt = ioremap(s->cb_phys, 0x1000);
- }
-
- request_mem_region(s->cb_phys, 0x1000, "i82365");
- add_socket(0, 0, type);
- }
- if (ns == 0) return;
-
- s -= ns;
- if (ns == 2) {
- /* Nasty special check for bad bus mapping */
- pci_readb(bus, s[0].devfn, CB_CARDBUS_BUS, &a);
- pci_readb(bus, s[1].devfn, CB_CARDBUS_BUS, &b);
- if (a == b) {
- pci_writeb(bus, s[0].devfn, CB_CARDBUS_BUS, 0);
- pci_writeb(bus, s[1].devfn, CB_CARDBUS_BUS, 0);
- }
- }
- add_pcic(ns, type);
-
- /* Re-do card voltage detection, if needed: this checks for
- card presence with no voltage detect bits set */
- for (a = sockets-ns; a < sockets; a++)
- if (!(cb_readl(a, CB_SOCKET_STATE) & 0x3c86))
- cb_writel(a, CB_SOCKET_FORCE, CB_SF_CVSTEST);
- for (i = 0; i < 200; i++) {
- for (a = sockets-ns; a < sockets; a++)
- if (!(cb_readl(a, CB_SOCKET_STATE) & 0x3c86)) break;
- if (a == sockets) break;
- __set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/20);
- }
- if (i == 200)
- printk(KERN_NOTICE "i82365: card voltage interrogation"
- " timed out!\n");
-
- /* Set up PCI bus bridge structures if needed */
- for (a = 0; a < ns; a++) {
- struct pci_dev *self = pci_find_slot(bus, s[a].devfn);
- struct pci_bus *child, *parent = self->bus;
- for (child = parent->children; child; child = child->next)
- if (child->number == s[a].cap.cardbus) break;
- if (!child) {
- child = kmalloc(sizeof(struct pci_bus), GFP_KERNEL);
- memset(child, 0, sizeof(struct pci_bus));
- child->self = self;
- child->primary = bus;
- child->number = child->secondary = s[a].cap.cardbus;
- child->subordinate = s[a].sub_bus;
- child->parent = parent;
- child->ops = parent->ops;
- child->next = parent->children;
- }
- s[a].cap.cb_bus = parent->children = child;
- }
-}
-
-static void __init pci_probe(u_int class, void (add_fn)
- (int, u_char, u_char, u_short, u_short))
-{
- u_short i, v, d;
- u_char bus, devfn;
- pci_id_t id;
-
- id = 0;
- while (pci_lookup(class, &id, &bus, &devfn) == 0) {
- if (PCI_FUNC(devfn) != 0) continue;
- pci_readw(bus, devfn, PCI_VENDOR_ID, &v);
- pci_readw(bus, devfn, PCI_DEVICE_ID, &d);
- for (i = 0; i < PCIC_COUNT; i++)
- if ((pcic[i].vendor == v) && (pcic[i].device == d)) break;
- add_fn(i, bus, devfn, v, d);
- }
-}
-
-#endif /* CONFIG_PCI */
/*====================================================================*/
@@ -1844,13 +916,6 @@ static void pcic_interrupt(int irq, void *dev,
continue;
ISA_LOCK(i, flags);
csc = i365_get(i, I365_CSC);
-#ifdef CONFIG_PCI
- if ((socket[i].flags & IS_CARDBUS) &&
- (cb_readl(i,CB_SOCKET_EVENT) & (CB_SE_CCD1|CB_SE_CCD2))) {
- cb_writel(i, CB_SOCKET_EVENT, CB_SE_CCD1|CB_SE_CCD2);
- csc |= I365_CSC_DETECT;
- }
-#endif
if ((csc == 0) || (!socket[i].handler) ||
(i365_get(i, I365_IDENT) & 0x70)) {
ISA_UNLOCK(i, flags);
@@ -1887,22 +952,21 @@ static void pcic_interrupt_wrapper(u_long data)
/*====================================================================*/
-static int pcic_register_callback(u_short sock, ss_callback_t *call)
+static int pcic_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
{
- if (call == NULL) {
- socket[sock].handler = NULL;
+ socket[sock].handler = handler;
+ socket[sock].info = info;
+ if (handler == NULL) {
MOD_DEC_USE_COUNT;
} else {
MOD_INC_USE_COUNT;
- socket[sock].handler = call->handler;
- socket[sock].info = call->info;
}
return 0;
} /* pcic_register_callback */
/*====================================================================*/
-static int pcic_inquire_socket(u_short sock, socket_cap_t *cap)
+static int pcic_inquire_socket(unsigned int sock, socket_cap_t *cap)
{
*cap = socket[sock].cap;
return 0;
@@ -1927,20 +991,6 @@ static int i365_get_status(u_short sock, u_int *value)
*value |= (status & I365_CS_READY) ? SS_READY : 0;
*value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
-#ifdef CONFIG_PCI
- if (socket[sock].flags & IS_CARDBUS) {
- status = cb_readl(sock, CB_SOCKET_STATE);
-#ifndef CONFIG_CARDBUS
- *value |= (status & CB_SS_32BIT) ? SS_CARDBUS : 0;
-#endif
- *value |= (status & CB_SS_3VCARD) ? SS_3VCARD : 0;
- *value |= (status & CB_SS_XVCARD) ? SS_XVCARD : 0;
- } else if (socket[sock].flags & IS_O2MICRO) {
- status = i365_get(sock, O2_MODE_B);
- *value |= (status & O2_MODE_B_VS1) ? 0 : SS_3VCARD;
- *value |= (status & O2_MODE_B_VS2) ? 0 : SS_XVCARD;
- }
-#endif
#ifdef CONFIG_ISA
if (socket[sock].type == IS_VG469) {
status = i365_get(sock, VG469_VSENSE);
@@ -1970,11 +1020,6 @@ static int i365_get_socket(u_short sock, socket_state_t *state)
state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
state->Vcc = state->Vpp = 0;
-#ifdef CONFIG_PCI
- if (t->flags & IS_CARDBUS) {
- cb_get_power(sock, state);
- } else
-#endif
if (t->flags & IS_CIRRUS) {
if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {
if (reg & I365_VCC_5V) state->Vcc = 33;
@@ -2010,12 +1055,7 @@ static int i365_get_socket(u_short sock, socket_state_t *state)
reg = i365_get(sock, I365_INTCTL);
state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
-#ifdef CONFIG_PCI
- if (cb_get_irq_mode(sock) != 0)
- state->io_irq = t->cap.pci_irq;
- else
-#endif
- state->io_irq = reg & I365_IRQ_MASK;
+ state->io_irq = reg & I365_IRQ_MASK;
/* speaker control */
if (t->flags & IS_CIRRUS) {
@@ -2052,12 +1092,6 @@ static int i365_set_socket(u_short sock, socket_state_t *state)
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
/* First set global controller options */
-#ifdef CONFIG_PCI
- if ((t->flags & IS_CARDBUS) && t->cap.pci_irq)
- cb_set_irq_mode(sock, pci_csc,
- (t->cap.pci_irq == state->io_irq));
- t->bcr &= ~CB_BCR_CB_RESET;
-#endif
set_bridge_state(sock);
/* IO card, RESET flag, IO interrupt */
@@ -2071,13 +1105,6 @@ static int i365_set_socket(u_short sock, socket_state_t *state)
if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
-#ifdef CONFIG_PCI
- if (t->flags & IS_CARDBUS) {
- cb_set_power(sock, state);
- reg |= i365_get(sock, I365_POWER) &
- (I365_VCC_MASK|I365_VPP1_MASK);
- } else
-#endif
if (t->flags & IS_CIRRUS) {
if (state->Vpp != 0) {
if (state->Vpp == 120)
@@ -2159,13 +1186,6 @@ static int i365_set_socket(u_short sock, socket_state_t *state)
}
i365_set(sock, I365_CSCINT, reg);
i365_get(sock, I365_CSC);
-#ifdef CONFIG_PCI
- if (t->flags & IS_CARDBUS) {
- if (t->cs_irq || (pci_csc && t->cap.pci_irq))
- cb_writel(sock, CB_SOCKET_MASK, CB_SM_CCD);
- cb_writel(sock, CB_SOCKET_EVENT, -1);
- }
-#endif
return 0;
} /* i365_set_socket */
@@ -2251,17 +1271,6 @@ static int i365_get_mem_map(u_short sock, struct pccard_mem_map *mem)
mem->flags |= (i & I365_MEM_REG) ? MAP_ATTRIB : 0;
mem->card_start = ((u_int)(i & 0x3fff) << 12) + mem->sys_start;
mem->card_start &= 0x3ffffff;
-
-#ifdef CONFIG_PCI
- /* Take care of high byte, for PCI controllers */
- if (socket[sock].type == IS_PD6729) {
- i365_set(sock, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
- addr = i365_get(sock, PD67_EXT_DATA) << 24;
- } else if (socket[sock].flags & IS_CARDBUS) {
- addr = i365_get(sock, CB_MEM_PAGE(map)) << 24;
- mem->sys_stop += addr; mem->sys_start += addr;
- }
-#endif
DEBUG(1, "i82365: GetMemMap(%d, %d) = %#2.2x, %d ns, %#5.5lx-%#5."
"5lx, %#5.5x\n", sock, mem->map, mem->flags, mem->speed,
@@ -2284,22 +1293,13 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
if ((map > 4) || (mem->card_start > 0x3ffffff) ||
(mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
return -EINVAL;
- if (!(socket[sock].flags & (IS_PCI | IS_CARDBUS)) &&
+ if (!(socket[sock].flags & IS_PCI) &&
((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff)))
return -EINVAL;
/* Turn off the window before changing anything */
if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
-
-#ifdef CONFIG_PCI
- /* Take care of high byte, for PCI controllers */
- if (socket[sock].type == IS_PD6729) {
- i365_set(sock, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
- i365_set(sock, PD67_EXT_DATA, (mem->sys_start >> 24));
- } else if (socket[sock].flags & IS_CARDBUS)
- i365_set(sock, CB_MEM_PAGE(map), mem->sys_start >> 24);
-#endif
base = I365_MEM(map);
i = (mem->sys_start >> 12) & 0x0fff;
@@ -2329,186 +1329,6 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
/*======================================================================
- Power control for Cardbus controllers: used both for 16-bit and
- Cardbus cards.
-
-======================================================================*/
-
-#ifdef CONFIG_PCI
-
-static void cb_get_power(u_short sock, socket_state_t *state)
-{
- u_int reg = cb_readl(sock, CB_SOCKET_CONTROL);
- state->Vcc = state->Vpp = 0;
- switch (reg & CB_SC_VCC_MASK) {
- case CB_SC_VCC_3V: state->Vcc = 33; break;
- case CB_SC_VCC_5V: state->Vcc = 50; break;
- }
- switch (reg & CB_SC_VPP_MASK) {
- case CB_SC_VPP_3V: state->Vpp = 33; break;
- case CB_SC_VPP_5V: state->Vpp = 50; break;
- case CB_SC_VPP_12V: state->Vpp = 120; break;
- }
-}
-
-static void cb_set_power(u_short sock, socket_state_t *state)
-{
- u_int reg = 0;
- switch (state->Vcc) {
- case 33: reg = CB_SC_VCC_3V; break;
- case 50: reg = CB_SC_VCC_5V; break;
- default: reg = 0; break;
- }
- switch (state->Vpp) {
- case 33: reg |= CB_SC_VPP_3V; break;
- case 50: reg |= CB_SC_VPP_5V; break;
- case 120: reg |= CB_SC_VPP_12V; break;
- }
- if (reg != cb_readl(sock, CB_SOCKET_CONTROL))
- cb_writel(sock, CB_SOCKET_CONTROL, reg);
-}
-
-#endif
-
-/*======================================================================
-
- All the stuff that is strictly for Cardbus cards goes here.
-
-======================================================================*/
-
-#ifdef CONFIG_CARDBUS
-
-static int cb_get_status(u_short sock, u_int *value)
-{
- u_int s;
- s = cb_readl(sock, CB_SOCKET_STATE);
- *value = ((s & CB_SS_32BIT) ? SS_CARDBUS : 0);
- *value |= ((s & CB_SS_CCD1) || (s & CB_SS_CCD2)) ? 0 : SS_DETECT;
- *value |= (s & CB_SS_CSTSCHG) ? SS_STSCHG : 0;
- *value |= (s & CB_SS_PWRCYCLE) ? (SS_POWERON|SS_READY) : 0;
- *value |= (s & CB_SS_3VCARD) ? SS_3VCARD : 0;
- *value |= (s & CB_SS_XVCARD) ? SS_XVCARD : 0;
- DEBUG(1, "yenta: GetStatus(%d) = %#4.4x\n", sock, *value);
- return 0;
-} /* cb_get_status */
-
-static int cb_get_socket(u_short sock, socket_state_t *state)
-{
- socket_info_t *s = &socket[sock];
- u_short bcr;
-
- cb_get_power(sock, state);
- pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr);
- state->flags |= (bcr & CB_BCR_CB_RESET) ? SS_RESET : 0;
- if (cb_get_irq_mode(sock) != 0)
- state->io_irq = s->cap.pci_irq;
- else
- state->io_irq = i365_get(sock, I365_INTCTL) & I365_IRQ_MASK;
- DEBUG(1, "yenta: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
- return 0;
-} /* cb_get_socket */
-
-static int cb_set_socket(u_short sock, socket_state_t *state)
-{
- socket_info_t *s = &socket[sock];
- u_int reg;
-
- DEBUG(1, "yenta: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
- "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
- state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-
- /* First set global controller options */
- if (s->cap.pci_irq)
- cb_set_irq_mode(sock, pci_csc,
- (s->cap.pci_irq == state->io_irq));
- s->bcr &= ~CB_BCR_CB_RESET;
- s->bcr |= (state->flags & SS_RESET) ? CB_BCR_CB_RESET : 0;
- set_bridge_state(sock);
-
- cb_set_power(sock, state);
-
- /* Handle IO interrupt using ISA routing */
- reg = s->intr;
- if (state->io_irq != s->cap.pci_irq) reg |= state->io_irq;
- i365_set(sock, I365_INTCTL, reg);
-
- /* Handle CSC mask */
- reg = (socket[sock].cs_irq << 4);
- if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
- i365_set(sock, I365_CSCINT, reg);
- i365_get(sock, I365_CSC);
- if (s->cs_irq || (pci_csc && s->cap.pci_irq))
- cb_writel(sock, CB_SOCKET_MASK, CB_SM_CCD);
- cb_writel(sock, CB_SOCKET_EVENT, -1);
-
- return 0;
-} /* cb_set_socket */
-
-static int cb_get_bridge(u_short sock, struct cb_bridge_map *m)
-{
- socket_info_t *s = &socket[sock];
- u_char map;
-
- map = m->map;
- if (map > 1) return -EINVAL;
- m->flags &= MAP_IOSPACE;
- map += (m->flags & MAP_IOSPACE) ? 2 : 0;
- pci_readl(s->bus, s->devfn, CB_MEM_BASE(map), &m->start);
- pci_readl(s->bus, s->devfn, CB_MEM_LIMIT(map), &m->stop);
- if (m->start || m->stop) {
- m->flags |= MAP_ACTIVE;
- m->stop |= (map > 1) ? 3 : 0x0fff;
- }
- if (map > 1) {
- u_short bcr;
- pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr);
- m->flags |= (bcr & CB_BCR_PREFETCH(map)) ? MAP_PREFETCH : 0;
- }
- DEBUG(1, "yenta: GetBridge(%d, %d) = %#2.2x, %#4.4x-%#4.4x\n",
- sock, map, m->flags, m->start, m->stop);
- return 0;
-}
-
-static int cb_set_bridge(u_short sock, struct cb_bridge_map *m)
-{
- socket_info_t *s = &socket[sock];
- u_char map;
-
- DEBUG(1, "yenta: SetBridge(%d, %d, %#2.2x, %#4.4x-%#4.4x)\n",
- sock, m->map, m->flags, m->start, m->stop);
- map = m->map;
- if (!(s->flags & IS_CARDBUS) || (map > 1) || (m->stop < m->start))
- return -EINVAL;
- if (m->flags & MAP_IOSPACE) {
- if ((m->stop > 0xffff) || (m->start & 3) ||
- ((m->stop & 3) != 3))
- return -EINVAL;
- map += 2;
- } else {
- u_short bcr;
- if ((m->start & 0x0fff) || ((m->stop & 0x0fff) != 0x0fff))
- return -EINVAL;
- pci_readw(s->bus, s->devfn, CB_BRIDGE_CONTROL, &bcr);
- bcr &= ~CB_BCR_PREFETCH(map);
- bcr |= (m->flags & MAP_PREFETCH) ? CB_BCR_PREFETCH(map) : 0;
- pci_writew(s->bus, s->devfn, CB_BRIDGE_CONTROL, bcr);
- }
- if (m->flags & MAP_ACTIVE) {
- pci_writel(s->bus, s->devfn, CB_MEM_BASE(map), m->start);
- pci_writel(s->bus, s->devfn, CB_MEM_LIMIT(map), m->stop);
- } else {
- pci_writel(s->bus, s->devfn, CB_IO_BASE(map), 0);
- pci_writel(s->bus, s->devfn, CB_IO_LIMIT(map), 0);
- }
- return 0;
-}
-
-#endif /* CONFIG_CARDBUS */
-
-/*======================================================================
-
Routines for accessing socket information and register dumps via
/proc/bus/pccard/...
@@ -2523,13 +1343,6 @@ static int proc_read_info(char *buf, char **start, off_t pos,
char *p = buf;
p += sprintf(p, "type: %s\npsock: %d\n",
pcic[s->type].name, s->psock);
-#ifdef CONFIG_PCI
- if (s->flags & (IS_PCI|IS_CARDBUS))
- p += sprintf(p, "bus: %02x\ndevfn: %02x.%1x\n",
- s->bus, PCI_SLOT(s->devfn), PCI_FUNC(s->devfn));
- if (s->flags & IS_CARDBUS)
- p += sprintf(p, "cardbus: %02x\n", s->cap.cardbus);
-#endif
return (p - buf);
}
@@ -2545,8 +1358,6 @@ static int proc_read_exca(char *buf, char **start, off_t pos,
#endif
ISA_LOCK(sock, flags);
top = 0x40;
- if (socket[sock].flags & IS_CARDBUS)
- top = (socket[sock].flags & IS_CIRRUS) ? 0x140 : 0x50;
for (i = 0; i < top; i += 4) {
if (i == 0x50) {
p += sprintf(p, "\n");
@@ -2561,58 +1372,18 @@ static int proc_read_exca(char *buf, char **start, off_t pos,
return (p - buf);
}
-#ifdef CONFIG_PCI
-static int proc_read_pci(char *buf, char **start, off_t pos,
- int count, int *eof, void *data)
-{
- socket_info_t *s = data;
- u_char bus = s->bus, devfn = s->devfn;
- char *p = buf;
- u_int a, b, c, d;
- int i;
-
- for (i = 0; i < 0xc0; i += 0x10) {
- pci_readl(bus, devfn, i, &a);
- pci_readl(bus, devfn, i+4, &b);
- pci_readl(bus, devfn, i+8, &c);
- pci_readl(bus, devfn, i+12, &d);
- p += sprintf(p, "%08x %08x %08x %08x\n", a, b, c, d);
- }
- return (p - buf);
-}
-#endif
-
-#ifdef CONFIG_CARDBUS
-static int proc_read_cardbus(char *buf, char **start, off_t pos,
- int count, int *eof, void *data)
+static void pcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
{
- u_short sock = (socket_info_t *)data - socket;
- char *p = buf;
- int i, top;
+#ifdef CONFIG_PROC_FS
+ socket_info_t *s = &socket[sock];
- top = (socket[sock].flags & IS_O2MICRO) ? 0x30 : 0x20;
- for (i = 0; i < top; i += 0x10)
- p += sprintf(p, "%08x %08x %08x %08x\n",
- cb_readl(sock,i+0x00), cb_readl(sock,i+0x04),
- cb_readl(sock,i+0x08), cb_readl(sock,i+0x0c));
- return (p - buf);
-}
-#endif
+ if (s->flags & IS_ALIVE)
+ return;
-static void pcic_proc_setup(u_short sock, struct proc_dir_entry *base)
-{
- socket_info_t *s = &socket[sock];
create_proc_read_entry("info", 0, base, proc_read_info, s);
create_proc_read_entry("exca", 0, base, proc_read_exca, s);
-#ifdef CONFIG_PCI
- if (s->flags & (IS_PCI|IS_CARDBUS))
- create_proc_read_entry("pci", 0, base, proc_read_pci, s);
-#endif
-#ifdef CONFIG_CARDBUS
- if (s->flags & IS_CARDBUS)
- create_proc_read_entry("cardbus", 0, base, proc_read_cardbus, s);
-#endif
s->proc = base;
+#endif
}
static void pcic_proc_remove(u_short sock)
@@ -2621,82 +1392,130 @@ static void pcic_proc_remove(u_short sock)
if (base == NULL) return;
remove_proc_entry("info", base);
remove_proc_entry("exca", base);
-#ifdef CONFIG_PCI
- if (socket[sock].flags & (IS_PCI|IS_CARDBUS))
- remove_proc_entry("pci", base);
-#endif
-#ifdef CONFIG_CARDBUS
- if (socket[sock].flags & IS_CARDBUS)
- remove_proc_entry("cardbus", base);
-#endif
}
#endif /* CONFIG_PROC_FS */
/*====================================================================*/
-typedef int (*subfn_t)(u_short, void *);
-
-static subfn_t pcic_service_table[] = {
- (subfn_t)&pcic_register_callback,
- (subfn_t)&pcic_inquire_socket,
- (subfn_t)&i365_get_status,
- (subfn_t)&i365_get_socket,
- (subfn_t)&i365_set_socket,
- (subfn_t)&i365_get_io_map,
- (subfn_t)&i365_set_io_map,
- (subfn_t)&i365_get_mem_map,
- (subfn_t)&i365_set_mem_map,
-#ifdef CONFIG_CARDBUS
- (subfn_t)&cb_get_bridge,
- (subfn_t)&cb_set_bridge,
+/*
+ * The locking is rather broken. Why do we only lock for ISA, not for
+ * all other cases? If there are reasons to lock, we should lock. Not
+ * this silly conditional.
+ *
+ * Plan: make it bug-for-bug compatible with the old stuff, and clean
+ * it up when the infrastructure is done.
+ */
+#ifdef CONFIG_ISA
+#define LOCKED(x) do { \
+ int retval; \
+ unsigned long flags; \
+ spin_lock_irqsave(&isa_lock, flags); \
+ retval = x; \
+ spin_unlock_irqrestore(&isa_lock, flags); \
+ return retval; \
+} while (0)
#else
- NULL, NULL,
-#endif
-#ifdef CONFIG_PROC_FS
- (subfn_t)&pcic_proc_setup
+#define LOCKED(x) return x
#endif
-};
+
-#define NFUNC (sizeof(pcic_service_table)/sizeof(subfn_t))
+static int pcic_get_status(unsigned int sock, u_int *value)
+{
+ if (socket[sock].flags & IS_ALIVE) {
+ *value = 0;
+ return -EINVAL;
+ }
-static int pcic_service(u_int sock, u_int cmd, void *arg)
+ LOCKED(i365_get_status(sock, value));
+}
+
+static int pcic_get_socket(unsigned int sock, socket_state_t *state)
{
- subfn_t fn;
- int ret;
-#ifdef CONFIG_ISA
- u_long flags = 0;
-#endif
-
- DEBUG(2, "pcic_ioctl(%d, %d, 0x%p)\n", sock, cmd, arg);
+ if (socket[sock].flags & IS_ALIVE)
+ return -EINVAL;
- if (cmd >= NFUNC)
- return -EINVAL;
+ LOCKED(i365_get_socket(sock, state));
+}
- if (socket[sock].flags & IS_ALIVE) {
- if (cmd == SS_GetStatus)
- *(u_int *)arg = 0;
- return -EINVAL;
- }
-
- fn = pcic_service_table[cmd];
-#ifdef CONFIG_CARDBUS
- if ((socket[sock].flags & IS_CARDBUS) &&
- (cb_readl(sock, CB_SOCKET_STATE) & CB_SS_32BIT)) {
- if (cmd == SS_GetStatus)
- fn = (subfn_t)&cb_get_status;
- else if (cmd == SS_GetSocket)
- fn = (subfn_t)&cb_get_socket;
- else if (cmd == SS_SetSocket)
- fn = (subfn_t)&cb_set_socket;
- }
-#endif
+static int pcic_set_socket(unsigned int sock, socket_state_t *state)
+{
+ if (socket[sock].flags & IS_ALIVE)
+ return -EINVAL;
- ISA_LOCK(sock, flags);
- ret = (fn == NULL) ? -EINVAL : fn(sock, arg);
- ISA_UNLOCK(sock, flags);
- return ret;
-} /* pcic_service */
+ LOCKED(i365_set_socket(sock, state));
+}
+
+static int pcic_get_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+ if (socket[sock].flags & IS_ALIVE)
+ return -EINVAL;
+
+ LOCKED(i365_get_io_map(sock, io));
+}
+
+static int pcic_set_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+ if (socket[sock].flags & IS_ALIVE)
+ return -EINVAL;
+
+ LOCKED(i365_set_io_map(sock, io));
+}
+
+static int pcic_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+ if (socket[sock].flags & IS_ALIVE)
+ return -EINVAL;
+
+ LOCKED(i365_get_mem_map(sock, mem));
+}
+
+static int pcic_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+ if (socket[sock].flags & IS_ALIVE)
+ return -EINVAL;
+
+ LOCKED(i365_set_mem_map(sock, mem));
+}
+
+static int pcic_init(unsigned int s)
+{
+ int i;
+ pccard_io_map io = { 0, 0, 0, 0, 1 };
+ pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
+
+ mem.sys_stop = 0x1000;
+ pcic_set_socket(s, &dead_socket);
+ for (i = 0; i < 2; i++) {
+ io.map = i;
+ pcic_set_io_map(s, &io);
+ }
+ for (i = 0; i < 5; i++) {
+ mem.map = i;
+ pcic_set_mem_map(s, &mem);
+ }
+ return 0;
+}
+
+static int pcic_suspend(unsigned int sock)
+{
+ return pcic_set_socket(sock, &dead_socket);
+}
+
+static struct pccard_operations pcic_operations = {
+ pcic_init,
+ pcic_suspend,
+ pcic_register_callback,
+ pcic_inquire_socket,
+ pcic_get_status,
+ pcic_get_socket,
+ pcic_set_socket,
+ pcic_get_io_map,
+ pcic_set_io_map,
+ pcic_get_mem_map,
+ pcic_set_mem_map,
+ pcic_proc_setup
+};
/*====================================================================*/
@@ -2713,13 +1532,6 @@ static int __init init_i82365(void)
printk(KERN_INFO "Intel PCIC probe: ");
sockets = 0;
-#ifdef CONFIG_PCI
- if (do_pci_probe && pcibios_present()) {
- pci_probe(PCI_CLASS_BRIDGE_CARDBUS, add_cb_bridge);
- pci_probe(PCI_CLASS_BRIDGE_PCMCIA, add_pci_bridge);
- }
-#endif
-
#ifdef CONFIG_ISA
isa_probe();
#endif
@@ -2734,19 +1546,8 @@ static int __init init_i82365(void)
if (grab_irq != 0)
request_irq(cs_irq, pcic_interrupt, 0, "i82365", NULL);
#endif
-#ifdef CONFIG_PCI
- if (pci_csc) {
- u_int i, irq, mask = 0;
- for (i = 0; i < sockets; i++) {
- irq = socket[i].cap.pci_irq;
- if (irq && !(mask & (1<<irq)))
- request_irq(irq, pcic_interrupt, SA_SHIRQ, "i82365", NULL);
- mask |= (1<<irq);
- }
- }
-#endif
- if (register_ss_entry(sockets, &pcic_service) != 0)
+ if (register_ss_entry(sockets, &pcic_operations) != 0)
printk(KERN_NOTICE "i82365: register_ss_entry() failed\n");
/* Finally, schedule a polling interrupt */
@@ -2768,36 +1569,17 @@ static void __exit exit_i82365(void)
#ifdef CONFIG_PROC_FS
for (i = 0; i < sockets; i++) pcic_proc_remove(i);
#endif
- unregister_ss_entry(&pcic_service);
+ unregister_ss_entry(&pcic_operations);
if (poll_interval != 0)
del_timer(&poll_timer);
#ifdef CONFIG_ISA
if (grab_irq != 0)
free_irq(cs_irq, NULL);
#endif
-#ifdef CONFIG_PCI
- if (pci_csc) {
- u_int irq, mask = 0;
- for (i = 0; i < sockets; i++) {
- irq = socket[i].cap.pci_irq;
- if (irq && !(mask & (1<<irq)))
- free_irq(irq, NULL);
- mask |= (1<<irq);
- }
- }
-#endif
for (i = 0; i < sockets; i++) {
/* Turn off all interrupt sources! */
i365_set(i, I365_CSCINT, 0);
-#ifdef CONFIG_PCI
- if (socket[i].flags & IS_CARDBUS)
- cb_writel(i, CB_SOCKET_MASK, 0);
- if (socket[i].cb_virt) {
- iounmap(socket[i].cb_virt);
- release_mem_region(socket[i].cb_phys, 0x1000);
- } else
-#endif
- release_region(socket[i].ioaddr, 2);
+ release_region(socket[i].ioaddr, 2);
}
} /* exit_i82365 */
@@ -2805,4 +1587,3 @@ module_init(init_i82365);
module_exit(exit_i82365);
/*====================================================================*/
-
diff --git a/drivers/pcmcia/old-yenta.h b/drivers/pcmcia/old-yenta.h
new file mode 100644
index 000000000..fbba0b1a3
--- /dev/null
+++ b/drivers/pcmcia/old-yenta.h
@@ -0,0 +1,153 @@
+/*
+ * yenta.h 1.16 1999/10/25 20:03:34
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * The initial developer of the original code is David A. Hinds
+ * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
+ * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU Public License version 2 (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of the
+ * above. If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use
+ * your version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL. If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ */
+
+#ifndef _LINUX_YENTA_H
+#define _LINUX_YENTA_H
+
+/* PCI Configuration Registers */
+
+#define PCI_STATUS_CAPLIST 0x10
+#define PCI_CB_CAPABILITY_POINTER 0x14 /* 8 bit */
+#define PCI_CAPABILITY_ID 0x00 /* 8 bit */
+#define PCI_CAPABILITY_PM 0x01
+#define PCI_NEXT_CAPABILITY 0x01 /* 8 bit */
+#define PCI_PM_CAPABILITIES 0x02 /* 16 bit */
+#define PCI_PMCAP_PME_D3COLD 0x8000
+#define PCI_PMCAP_PME_D3HOT 0x4000
+#define PCI_PMCAP_PME_D2 0x2000
+#define PCI_PMCAP_PME_D1 0x1000
+#define PCI_PMCAP_PME_D0 0x0800
+#define PCI_PMCAP_D2_CAP 0x0400
+#define PCI_PMCAP_D1_CAP 0x0200
+#define PCI_PMCAP_DYN_DATA 0x0100
+#define PCI_PMCAP_DSI 0x0020
+#define PCI_PMCAP_AUX_PWR 0x0010
+#define PCI_PMCAP_PMECLK 0x0008
+#define PCI_PMCAP_VERSION_MASK 0x0007
+#define PCI_PM_CONTROL_STATUS 0x04 /* 16 bit */
+#define PCI_PMCS_PME_STATUS 0x8000
+#define PCI_PMCS_DATASCALE_MASK 0x6000
+#define PCI_PMCS_DATASCALE_SHIFT 13
+#define PCI_PMCS_DATASEL_MASK 0x1e00
+#define PCI_PMCS_DATASEL_SHIFT 9
+#define PCI_PMCS_PME_ENABLE 0x0100
+#define PCI_PMCS_PWR_STATE_MASK 0x0003
+#define PCI_PMCS_PWR_STATE_D0 0x0000
+#define PCI_PMCS_PWR_STATE_D1 0x0001
+#define PCI_PMCS_PWR_STATE_D2 0x0002
+#define PCI_PMCS_PWR_STATE_D3 0x0003
+#define PCI_PM_BRIDGE_EXT 0x06 /* 8 bit */
+#define PCI_PM_DATA 0x07 /* 8 bit */
+
+#define CB_PRIMARY_BUS 0x18 /* 8 bit */
+#define CB_CARDBUS_BUS 0x19 /* 8 bit */
+#define CB_SUBORD_BUS 0x1a /* 8 bit */
+#define CB_LATENCY_TIMER 0x1b /* 8 bit */
+
+#define CB_MEM_BASE(m) (0x1c + 8*(m))
+#define CB_MEM_LIMIT(m) (0x20 + 8*(m))
+#define CB_IO_BASE(m) (0x2c + 8*(m))
+#define CB_IO_LIMIT(m) (0x30 + 8*(m))
+
+#define CB_BRIDGE_CONTROL 0x3e /* 16 bit */
+#define CB_BCR_PARITY_ENA 0x0001
+#define CB_BCR_SERR_ENA 0x0002
+#define CB_BCR_ISA_ENA 0x0004
+#define CB_BCR_VGA_ENA 0x0008
+#define CB_BCR_MABORT 0x0020
+#define CB_BCR_CB_RESET 0x0040
+#define CB_BCR_ISA_IRQ 0x0080
+#define CB_BCR_PREFETCH(m) (0x0100 << (m))
+#define CB_BCR_WRITE_POST 0x0400
+
+#define CB_LEGACY_MODE_BASE 0x44
+
+/* Memory mapped registers */
+
+#define CB_SOCKET_EVENT 0x0000
+#define CB_SE_CSTSCHG 0x00000001
+#define CB_SE_CCD1 0x00000002
+#define CB_SE_CCD2 0x00000004
+#define CB_SE_PWRCYCLE 0x00000008
+
+#define CB_SOCKET_MASK 0x0004
+#define CB_SM_CSTSCHG 0x00000001
+#define CB_SM_CCD 0x00000006
+#define CB_SM_PWRCYCLE 0x00000008
+
+#define CB_SOCKET_STATE 0x0008
+#define CB_SS_CSTSCHG 0x00000001
+#define CB_SS_CCD1 0x00000002
+#define CB_SS_CCD2 0x00000004
+#define CB_SS_PWRCYCLE 0x00000008
+#define CB_SS_16BIT 0x00000010
+#define CB_SS_32BIT 0x00000020
+#define CB_SS_CINT 0x00000040
+#define CB_SS_BADCARD 0x00000080
+#define CB_SS_DATALOST 0x00000100
+#define CB_SS_BADVCC 0x00000200
+#define CB_SS_5VCARD 0x00000400
+#define CB_SS_3VCARD 0x00000800
+#define CB_SS_XVCARD 0x00001000
+#define CB_SS_YVCARD 0x00002000
+#define CB_SS_5VSOCKET 0x10000000
+#define CB_SS_3VSOCKET 0x20000000
+#define CB_SS_XVSOCKET 0x40000000
+#define CB_SS_YVSOCKET 0x80000000
+
+#define CB_SOCKET_FORCE 0x000c
+#define CB_SF_CVSTEST 0x00004000
+
+#define CB_SOCKET_CONTROL 0x0010
+#define CB_SC_VPP_MASK 0x00000007
+#define CB_SC_VPP_OFF 0x00000000
+#define CB_SC_VPP_12V 0x00000001
+#define CB_SC_VPP_5V 0x00000002
+#define CB_SC_VPP_3V 0x00000003
+#define CB_SC_VPP_XV 0x00000004
+#define CB_SC_VPP_YV 0x00000005
+#define CB_SC_VCC_MASK 0x00000070
+#define CB_SC_VCC_OFF 0x00000000
+#define CB_SC_VCC_5V 0x00000020
+#define CB_SC_VCC_3V 0x00000030
+#define CB_SC_VCC_XV 0x00000040
+#define CB_SC_VCC_YV 0x00000050
+#define CB_SC_CCLK_STOP 0x00000080
+
+#define CB_SOCKET_POWER 0x0020
+#define CB_SP_CLK_CTRL 0x00000001
+#define CB_SP_CLK_CTRL_ENA 0x00010000
+#define CB_SP_CLK_MODE 0x01000000
+#define CB_SP_ACCESS 0x02000000
+
+/* Address bits 31..24 for memory windows for 16-bit cards,
+ accessable only by memory mapping the 16-bit register set */
+#define CB_MEM_PAGE(map) (0x40 + (map))
+
+#endif /* _LINUX_YENTA_H */
diff --git a/drivers/pcmcia/pci_socket.c b/drivers/pcmcia/pci_socket.c
new file mode 100644
index 000000000..51981e41e
--- /dev/null
+++ b/drivers/pcmcia/pci_socket.c
@@ -0,0 +1,205 @@
+/*
+ * Generic PCI pccard driver interface.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ *
+ * This implements the common parts of PCI pccard drivers,
+ * notably detection and infrastructure conversion (ie change
+ * from socket index to "struct pci_dev" etc)
+ *
+ * This does NOT implement the actual low-level driver details,
+ * and this has on purpose been left generic enough that it can
+ * be used to set up a PCI PCMCIA controller (ie non-cardbus),
+ * or to set up a controller.
+ *
+ * See for example the "yenta" driver for PCI cardbus controllers
+ * conforming to the yenta cardbus specifications.
+ */
+#include <linux/module.h>
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+
+#include "pci_socket.h"
+
+/*
+ * Arbitrary define. This is the array of active cardbus
+ * entries.
+ */
+#define MAX_SOCKETS (8)
+static pci_socket_t pci_socket_array[MAX_SOCKETS];
+
+static int pci_init_socket(unsigned int sock)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->init)
+ return socket->op->init(socket);
+ return -EINVAL;
+}
+
+static int pci_suspend_socket(unsigned int sock)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->suspend)
+ return socket->op->suspend(socket);
+ return -EINVAL;
+}
+
+static int pci_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ socket->handler = handler;
+ socket->info = info;
+ if (handler)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+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;
+}
+
+static int pci_get_status(unsigned int sock, unsigned int *value)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_status)
+ return socket->op->get_status(socket, value);
+ *value = 0;
+ return -EINVAL;
+}
+
+static int pci_get_socket(unsigned int sock, socket_state_t *state)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_socket)
+ return socket->op->get_socket(socket, state);
+ return -EINVAL;
+}
+
+static int pci_set_socket(unsigned int sock, socket_state_t *state)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->set_socket)
+ return socket->op->set_socket(socket, state);
+ return -EINVAL;
+}
+
+static int pci_get_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_io_map)
+ return socket->op->get_io_map(socket, io);
+ return -EINVAL;
+}
+
+static int pci_set_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->set_io_map)
+ return socket->op->set_io_map(socket, io);
+ return -EINVAL;
+}
+
+static int pci_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->get_mem_map)
+ return socket->op->get_mem_map(socket, mem);
+ return -EINVAL;
+}
+
+static int pci_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->set_mem_map)
+ return socket->op->set_mem_map(socket, mem);
+ return -EINVAL;
+}
+
+static void pci_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+{
+ pci_socket_t *socket = pci_socket_array + sock;
+
+ if (socket->op && socket->op->proc_setup)
+ socket->op->proc_setup(socket, base);
+}
+
+static struct pccard_operations pci_socket_operations = {
+ pci_init_socket,
+ pci_suspend_socket,
+ pci_register_callback,
+ pci_inquire_socket,
+ pci_get_status,
+ pci_get_socket,
+ pci_set_socket,
+ pci_get_io_map,
+ pci_set_io_map,
+ pci_get_mem_map,
+ pci_set_mem_map,
+ pci_proc_setup
+};
+
+static int __init add_pci_socket(int nr, struct pci_dev *dev, struct pci_socket_ops *ops)
+{
+ pci_socket_t *socket = nr + pci_socket_array;
+
+ socket->dev = dev;
+ socket->op = ops;
+ return socket->op->open(socket);
+}
+
+static int __init pci_socket_init(void)
+{
+ struct pci_dev *dev = NULL;
+ int nr = 0;
+
+ while ((dev = pci_find_class(PCI_CLASS_BRIDGE_CARDBUS << 8, dev)) != NULL) {
+ printk("Adding cardbus controller %d: %s\n", nr, dev->name);
+ add_pci_socket(nr, dev, &yenta_operations);
+ nr++;
+ }
+
+ if (nr <= 0)
+ return -1;
+ register_ss_entry(nr, &pci_socket_operations);
+ return 0;
+}
+
+static void __exit pci_socket_exit(void)
+{
+ int i;
+
+ unregister_ss_entry(&pci_socket_operations);
+ for (i = 0; i < MAX_SOCKETS; i++) {
+ pci_socket_t *socket = pci_socket_array + i;
+
+ if (socket->op && socket->op->close)
+ socket->op->close(socket);
+ }
+}
+
+module_init(pci_socket_init);
+module_exit(pci_socket_exit);
diff --git a/drivers/pcmcia/pci_socket.h b/drivers/pcmcia/pci_socket.h
new file mode 100644
index 000000000..41ea4ec09
--- /dev/null
+++ b/drivers/pcmcia/pci_socket.h
@@ -0,0 +1,39 @@
+/*
+ * drivers/pcmcia/pci_socket.h
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ */
+
+struct pci_socket_ops;
+
+typedef struct pci_socket {
+ struct pci_dev *dev;
+ int cb_irq, io_irq;
+ void *base;
+ void (*handler)(void *, unsigned int);
+ void *info;
+ struct pci_socket_ops *op;
+ socket_cap_t cap;
+ struct timer_list timer;
+} pci_socket_t;
+
+struct pci_socket_ops {
+ int (*open)(struct pci_socket *);
+ void (*close)(struct pci_socket *);
+
+ 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 *);
+ int (*get_io_map)(struct pci_socket *, struct pccard_io_map *);
+ int (*set_io_map)(struct pci_socket *, struct pccard_io_map *);
+ int (*get_mem_map)(struct pci_socket *, struct pccard_mem_map *);
+ int (*set_mem_map)(struct pci_socket *, struct pccard_mem_map *);
+ void (*proc_setup)(struct pci_socket *, struct proc_dir_entry *base);
+};
+
+extern struct pci_socket_ops yenta_operations;
+extern struct pci_socket_ops ricoh_operations;
+
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 5ea8e95e4..d5900c6f8 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -109,7 +109,7 @@ MODULE_PARM(cycle_time, "i");
static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs);
static void tcic_timer(u_long data);
-static int tcic_service(u_int sock, u_int cmd, void *arg);
+static struct pccard_operations tcic_operations;
typedef struct socket_info_t {
u_short psock;
@@ -494,7 +494,7 @@ static int __init init_tcic(void)
/* jump start interrupt handler, if needed */
tcic_interrupt(0, NULL, NULL);
- if (register_ss_entry(sockets, &tcic_service) != 0) {
+ if (register_ss_entry(sockets, &tcic_operations) != 0) {
printk(KERN_NOTICE "tcic: register_ss_entry() failed\n");
release_region(tcic_base, 16);
if (cs_irq != 0)
@@ -511,7 +511,7 @@ static int __init init_tcic(void)
static void __exit exit_tcic(void)
{
u_long flags;
- unregister_ss_entry(&tcic_service);
+ unregister_ss_entry(&tcic_operations);
save_flags(flags);
cli();
if (cs_irq != 0) {
@@ -589,22 +589,21 @@ static void tcic_timer(u_long data)
/*====================================================================*/
-static int tcic_register_callback(u_short lsock, ss_callback_t *call)
+static int tcic_register_callback(unsigned int lsock, void (*handler)(void *, unsigned int), void * info)
{
- if (call == NULL) {
- socket_table[lsock].handler = NULL;
+ socket_table[lsock].handler = handler;
+ socket_table[lsock].info = info;
+ if (handler == NULL) {
MOD_DEC_USE_COUNT;
} else {
MOD_INC_USE_COUNT;
- socket_table[lsock].handler = call->handler;
- socket_table[lsock].info = call->info;
}
return 0;
} /* tcic_register_callback */
/*====================================================================*/
-static int tcic_get_status(u_short lsock, u_int *value)
+static int tcic_get_status(unsigned int lsock, u_int *value)
{
u_short psock = socket_table[lsock].psock;
u_char reg;
@@ -630,7 +629,7 @@ static int tcic_get_status(u_short lsock, u_int *value)
/*====================================================================*/
-static int tcic_inquire_socket(u_short lsock, socket_cap_t *cap)
+static int tcic_inquire_socket(unsigned int lsock, socket_cap_t *cap)
{
*cap = tcic_cap;
return 0;
@@ -638,7 +637,7 @@ static int tcic_inquire_socket(u_short lsock, socket_cap_t *cap)
/*====================================================================*/
-static int tcic_get_socket(u_short lsock, socket_state_t *state)
+static int tcic_get_socket(unsigned int lsock, socket_state_t *state)
{
u_short psock = socket_table[lsock].psock;
u_char reg;
@@ -691,7 +690,7 @@ static int tcic_get_socket(u_short lsock, socket_state_t *state)
/*====================================================================*/
-static int tcic_set_socket(u_short lsock, socket_state_t *state)
+static int tcic_set_socket(unsigned int lsock, socket_state_t *state)
{
u_short psock = socket_table[lsock].psock;
u_char reg;
@@ -766,7 +765,7 @@ static int tcic_set_socket(u_short lsock, socket_state_t *state)
/*====================================================================*/
-static int tcic_get_io_map(u_short lsock, struct pccard_io_map *io)
+static int tcic_get_io_map(unsigned int lsock, struct pccard_io_map *io)
{
u_short psock = socket_table[lsock].psock;
u_short base, ioctl;
@@ -804,7 +803,7 @@ static int tcic_get_io_map(u_short lsock, struct pccard_io_map *io)
/*====================================================================*/
-static int tcic_set_io_map(u_short lsock, struct pccard_io_map *io)
+static int tcic_set_io_map(unsigned int lsock, struct pccard_io_map *io)
{
u_short psock = socket_table[lsock].psock;
u_int addr;
@@ -841,7 +840,7 @@ static int tcic_set_io_map(u_short lsock, struct pccard_io_map *io)
/*====================================================================*/
-static int tcic_get_mem_map(u_short lsock, struct pccard_mem_map *mem)
+static int tcic_get_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
{
u_short psock = socket_table[lsock].psock;
u_short addr, ctl;
@@ -886,7 +885,7 @@ static int tcic_get_mem_map(u_short lsock, struct pccard_mem_map *mem)
/*====================================================================*/
-static int tcic_set_mem_map(u_short lsock, struct pccard_mem_map *mem)
+static int tcic_set_mem_map(unsigned int lsock, struct pccard_mem_map *mem)
{
u_short psock = socket_table[lsock].psock;
u_short addr, ctl;
@@ -930,35 +929,48 @@ static int tcic_set_mem_map(u_short lsock, struct pccard_mem_map *mem)
/*====================================================================*/
-typedef int (*subfn_t)(u_short, void *);
-
-static subfn_t service_table[] = {
- (subfn_t)&tcic_register_callback,
- (subfn_t)&tcic_inquire_socket,
- (subfn_t)&tcic_get_status,
- (subfn_t)&tcic_get_socket,
- (subfn_t)&tcic_set_socket,
- (subfn_t)&tcic_get_io_map,
- (subfn_t)&tcic_set_io_map,
- (subfn_t)&tcic_get_mem_map,
- (subfn_t)&tcic_set_mem_map,
-};
-
-#define NFUNC (sizeof(service_table)/sizeof(subfn_t))
-
-static int tcic_service(u_int lsock, u_int cmd, void *arg)
+static void tcic_proc_setup(unsigned int sock, struct proc_dir_entry *base)
{
- int err;
+}
- DEBUG(2, "tcic_service(%d, %d, 0x%p)\n", lsock, cmd, arg);
+static int tcic_init(unsigned int s)
+{
+ int i;
+ pccard_io_map io = { 0, 0, 0, 0, 1 };
+ pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
+
+ mem.sys_stop = 0x1000;
+ tcic_set_socket(s, &dead_socket);
+ for (i = 0; i < 2; i++) {
+ io.map = i;
+ tcic_set_io_map(s, &io);
+ }
+ for (i = 0; i < 5; i++) {
+ mem.map = i;
+ tcic_set_mem_map(s, &mem);
+ }
+ return 0;
+}
- if (cmd < NFUNC)
- err = service_table[cmd](lsock, arg);
- else
- err = -EINVAL;
+static int tcic_suspend(unsigned int sock)
+{
+ return tcic_set_socket(sock, &dead_socket);
+}
- return err;
-} /* tcic_service */
+static struct pccard_operations tcic_operations = {
+ tcic_init,
+ tcic_suspend,
+ tcic_register_callback,
+ tcic_inquire_socket,
+ tcic_get_status,
+ tcic_get_socket,
+ tcic_set_socket,
+ tcic_get_io_map,
+ tcic_set_io_map,
+ tcic_get_mem_map,
+ tcic_set_mem_map,
+ tcic_proc_setup
+};
/*====================================================================*/
diff --git a/drivers/pcmcia/yenta.c b/drivers/pcmcia/yenta.c
new file mode 100644
index 000000000..e686a6436
--- /dev/null
+++ b/drivers/pcmcia/yenta.c
@@ -0,0 +1,716 @@
+/*
+ * Regular lowlevel cardbus driver ("yenta")
+ *
+ * (C) Copyright 1999, 2000 Linus Torvalds
+ */
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <pcmcia/ss.h>
+
+#include <asm/io.h>
+
+#include "yenta.h"
+#include "i82365.h"
+#include "ricoh.h"
+
+/* Don't ask.. */
+#define to_cycles(ns) ((ns)/120)
+#define to_ns(cycles) ((cycles)*120)
+
+/*
+ * Generate easy-to-use ways of reading a cardbus sockets
+ * regular memory space ("cb_xxx"), configuration space
+ * ("config_xxx") and compatibility space ("exca_xxxx")
+ */
+#define cb_readl(sock,reg) readl((sock)->base + (reg))
+#define cb_writel(sock,reg,val) writel(val,(sock)->base + (reg))
+
+static inline u8 config_readb(pci_socket_t *socket, unsigned offset)
+{
+ u8 val;
+ pci_read_config_byte(socket->dev, offset, &val);
+ return val;
+}
+
+static inline u16 config_readw(pci_socket_t *socket, unsigned offset)
+{
+ u16 val;
+ pci_read_config_word(socket->dev, offset, &val);
+ return val;
+}
+
+static inline u32 config_readl(pci_socket_t *socket, unsigned offset)
+{
+ u32 val;
+ pci_read_config_dword(socket->dev, offset, &val);
+ return val;
+}
+
+#define config_writeb(s,off,val) pci_write_config_byte((s)->dev, (off), (val))
+#define config_writew(s,off,val) pci_write_config_word((s)->dev, (off), (val))
+#define config_writel(s,off,val) pci_write_config_dword((s)->dev, (off), (val))
+
+#define exca_readb(sock,reg) readb((sock)->base + 0x800 + (reg))
+#define exca_writeb(sock,reg,v) writeb((v), (sock)->base + 0x800 + (reg))
+
+static u16 exca_readw(pci_socket_t *socket, unsigned reg)
+{
+ return exca_readb(socket, reg) | (exca_readb(socket, reg+1) << 8);
+}
+
+static void exca_writew(pci_socket_t *socket, unsigned reg, u16 val)
+{
+ exca_writeb(socket, reg, 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..
+ */
+static int yenta_get_status(pci_socket_t *socket, unsigned int *value)
+{
+ unsigned int val;
+ u32 state = cb_readl(socket, CB_SOCKET_STATE);
+
+ val = (state & CB_3VCARD) ? SS_3VCARD : 0;
+ val |= (state & CB_XVCARD) ? SS_XVCARD : 0;
+
+ if (state & CB_CBCARD) {
+ val |= SS_CARDBUS;
+ val |= (state & CB_CARDSTS) ? SS_STSCHG : 0;
+ val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
+ val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
+ } else {
+ u8 status = exca_readb(socket, I365_STATUS);
+ val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
+ if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
+ val |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
+ } else {
+ val |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
+ val |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
+ }
+ val |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
+ val |= (status & I365_CS_READY) ? SS_READY : 0;
+ val |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
+ }
+
+ *value = val;
+ return 0;
+}
+
+static int yenta_Vcc_power(u32 control)
+{
+ switch (control & CB_SC_VCC_MASK) {
+ case CB_SC_VCC_5V: return 50;
+ case CB_SC_VCC_3V: return 33;
+ default: return 0;
+ }
+}
+
+static int yenta_Vpp_power(u32 control)
+{
+ switch (control & CB_SC_VPP_MASK) {
+ case CB_SC_VPP_12V: return 120;
+ case CB_SC_VPP_5V: return 50;
+ case CB_SC_VPP_3V: return 33;
+ default: return 0;
+ }
+}
+
+static int yenta_get_socket(pci_socket_t *socket, socket_state_t *state)
+{
+ u8 reg;
+ u32 control;
+
+ control = cb_readl(socket, CB_SOCKET_CONTROL);
+
+ state->Vcc = yenta_Vcc_power(control);
+ state->Vpp = yenta_Vpp_power(control);
+ state->io_irq = socket->io_irq;
+
+ if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
+ u16 bridge = config_readw(socket, CB_BRIDGE_CONTROL);
+ if (bridge & CB_BRIDGE_CRST)
+ state->flags |= SS_RESET;
+ return 0;
+ }
+
+ /* 16-bit card state.. */
+ reg = exca_readb(socket, I365_POWER);
+ state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
+ state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
+
+ reg = exca_readb(socket, I365_INTCTL);
+ state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
+ state->flags |= (reg & I365_PC_IOCARD) ? SS_IOCARD : 0;
+
+ reg = exca_readb(socket, I365_CSCINT);
+ state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
+ if (state->flags & SS_IOCARD) {
+ state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+ } else {
+ state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
+ state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
+ state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
+ }
+
+ return 0;
+}
+
+static void yenta_set_power(pci_socket_t *socket, socket_state_t *state)
+{
+ u32 reg = 0; /* CB_SC_STPCLK? */
+ switch (state->Vcc) {
+ case 33: reg = CB_SC_VCC_3V; break;
+ case 50: reg = CB_SC_VCC_5V; break;
+ default: reg = 0; break;
+ }
+ switch (state->Vpp) {
+ case 33: reg |= CB_SC_VPP_3V; break;
+ case 50: reg |= CB_SC_VPP_5V; break;
+ case 120: reg |= CB_SC_VPP_12V; break;
+ }
+ if (reg != cb_readl(socket, CB_SOCKET_CONTROL))
+ cb_writel(socket, CB_SOCKET_CONTROL, reg);
+}
+
+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;
+ 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) {
+ u8 intr = exca_readb(socket, I365_INTCTL);
+ intr = (intr & ~0xf) | state->io_irq;
+ exca_writeb(socket, I365_INTCTL, intr);
+ }
+ } else {
+ u8 reg;
+
+ 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;
+ reg |= state->io_irq;
+ exca_writeb(socket, I365_INTCTL, reg);
+
+ reg = exca_readb(socket, I365_POWER) & (I365_VCC_MASK|I365_VPP1_MASK);
+ reg |= I365_PWR_NORESET;
+ if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
+ if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
+ if (exca_readb(socket, I365_POWER) != reg)
+ exca_writeb(socket, I365_POWER, reg);
+
+ /* CSC interrupt: no ISA irq for CSC */
+ reg = I365_CSC_DETECT;
+ if (state->flags & SS_IOCARD) {
+ if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
+ } else {
+ if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
+ if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
+ if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
+ }
+ exca_writeb(socket, I365_CSCINT, reg);
+ exca_readb(socket, I365_CSC);
+ }
+ config_writew(socket, CB_BRIDGE_CONTROL, bridge);
+ /* Socket event mask: get card insert/remove events.. */
+ cb_writel(socket, CB_SOCKET_EVENT, -1);
+ cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK);
+ return 0;
+}
+
+static int yenta_get_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+{
+ int map;
+ unsigned char ioctl, addr;
+
+ map = io->map;
+ if (map > 1)
+ return -EINVAL;
+
+ io->start = exca_readw(socket, I365_IO(map)+I365_W_START);
+ io->stop = exca_readw(socket, I365_IO(map)+I365_W_STOP);
+
+ ioctl = exca_readb(socket, I365_IOCTL);
+ addr = exca_readb(socket, I365_ADDRWIN);
+ io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
+ io->flags = (addr & I365_ENA_IO(map)) ? MAP_ACTIVE : 0;
+ io->flags |= (ioctl & I365_IOCTL_0WS(map)) ? MAP_0WS : 0;
+ io->flags |= (ioctl & I365_IOCTL_16BIT(map)) ? MAP_16BIT : 0;
+ io->flags |= (ioctl & I365_IOCTL_IOCS16(map)) ? MAP_AUTOSZ : 0;
+
+ return 0;
+}
+
+static int yenta_set_io_map(pci_socket_t *socket, struct pccard_io_map *io)
+{
+ int map;
+ unsigned char ioctl, addr, enable;
+
+ map = io->map;
+
+ if (map > 1)
+ return -EINVAL;
+
+ enable = I365_ENA_IO(map);
+ addr = exca_readb(socket, I365_ADDRWIN);
+
+ /* Disable the window before changing it.. */
+ if (addr & enable) {
+ addr &= ~enable;
+ exca_writeb(socket, I365_ADDRWIN, addr);
+ }
+
+ exca_writew(socket, I365_IO(map)+I365_W_START, io->start);
+ exca_writew(socket, I365_IO(map)+I365_W_STOP, io->stop);
+
+ ioctl = exca_readb(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map);
+ if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
+ if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
+ if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
+ exca_writeb(socket, I365_IOCTL, ioctl);
+
+ if (io->flags & MAP_ACTIVE)
+ exca_writeb(socket, I365_ADDRWIN, addr | enable);
+ return 0;
+}
+
+static int yenta_get_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+{
+ int map;
+ unsigned char addr;
+ unsigned int start, stop, page, offset;
+
+ map = mem->map;
+ if (map > 4)
+ return -EINVAL;
+
+ addr = exca_readb(socket, I365_ADDRWIN);
+ mem->flags = (addr & I365_ENA_MEM(map)) ? MAP_ACTIVE : 0;
+
+ start = exca_readw(socket, I365_MEM(map) + I365_W_START);
+ mem->flags |= (start & I365_MEM_16BIT) ? MAP_16BIT : 0;
+ mem->flags |= (start & I365_MEM_0WS) ? MAP_0WS : 0;
+ start = (start & 0x0fff) << 12;
+
+ stop = exca_readw(socket, I365_MEM(map) + I365_W_STOP);
+ mem->speed = to_ns(stop >> 14);
+ stop = ((stop & 0x0fff) << 12) + 0x0fff;
+
+ offset = exca_readw(socket, I365_MEM(map) + I365_W_OFF);
+ mem->flags |= (offset & I365_MEM_WRPROT) ? MAP_WRPROT : 0;
+ mem->flags |= (offset & I365_MEM_REG) ? MAP_ATTRIB : 0;
+ offset = ((offset & 0x3fff) << 12) + start;
+ mem->card_start = offset & 0x3ffffff;
+
+ page = exca_readb(socket, CB_MEM_PAGE(map)) << 24;
+ mem->sys_start = start + page;
+ mem->sys_stop = start + page;
+
+ return 0;
+}
+
+static int yenta_set_mem_map(pci_socket_t *socket, struct pccard_mem_map *mem)
+{
+ int map;
+ unsigned char addr, enable;
+ unsigned int start, stop, card_start;
+ unsigned short word;
+
+ map = mem->map;
+ start = mem->sys_start;
+ stop = mem->sys_stop;
+ card_start = mem->card_start;
+
+ if (map > 4 || start > stop || ((start ^ stop) >> 24) ||
+ (card_start >> 26) || mem->speed > 1000)
+ return -EINVAL;
+
+ enable = I365_ENA_MEM(map);
+ addr = exca_readb(socket, I365_ADDRWIN);
+ if (addr & enable) {
+ addr &= ~enable;
+ exca_writeb(socket, I365_ADDRWIN, addr);
+ }
+
+ exca_writeb(socket, CB_MEM_PAGE(map), start >> 24);
+
+ word = (start >> 12) & 0x0fff;
+ if (mem->flags & MAP_16BIT)
+ word |= I365_MEM_16BIT;
+ if (mem->flags & MAP_0WS)
+ word |= I365_MEM_0WS;
+ exca_writew(socket, I365_MEM(map) + I365_W_START, word);
+
+ word = (stop >> 12) & 0x0fff;
+ switch (to_cycles(mem->speed)) {
+ case 0: break;
+ case 1: word |= I365_MEM_WS0; break;
+ case 2: word |= I365_MEM_WS1; break;
+ default: word |= I365_MEM_WS1 | I365_MEM_WS0; break;
+ }
+ exca_writew(socket, I365_MEM(map) + I365_W_STOP, word);
+
+ word = ((card_start - start) >> 12) & 0x3fff;
+ if (mem->flags & MAP_WRPROT)
+ word |= I365_MEM_WRPROT;
+ if (mem->flags & MAP_ATTRIB)
+ word |= I365_MEM_REG;
+ exca_writew(socket, I365_MEM(map) + I365_W_OFF, word);
+
+ if (mem->flags & MAP_ACTIVE)
+ exca_writeb(socket, I365_ADDRWIN, addr | enable);
+ return 0;
+}
+
+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)
+{
+ 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);
+
+ csc = exca_readb(socket, I365_CSC);
+
+ events = (cb_event & (CB_CD1EVENT | CB_CD2EVENT)) ? SS_DETECT : 0 ;
+ events |= (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
+ if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
+ events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+ } else {
+ events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
+ events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
+ events |= (csc & I365_CSC_READY) ? SS_READY : 0;
+ }
+
+ if (events && socket->handler)
+ socket->handler(socket->info, events);
+
+ mod_timer(&socket->timer, jiffies + HZ);
+}
+
+static void yenta_timer(unsigned long data)
+{
+ yenta_interrupt(0, (pci_socket_t *) data, NULL);
+}
+
+static unsigned int yenta_probe_irq(pci_socket_t *socket)
+{
+ int i;
+ unsigned long val;
+ u16 bridge_ctrl;
+
+ /* Are we set up to route the IO irq to the PCI irq? */
+ 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);
+ }
+
+ /*
+ * Probe for usable interrupts using the force
+ * register to generate bogus card status events.
+ */
+ cb_writel(socket, CB_SOCKET_EVENT, -1);
+ cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK);
+ val = probe_irq_on();
+ for (i = 1; i < 16; i++) {
+ if (!((val >> i) & 1))
+ continue;
+ exca_writeb(socket, I365_CSCINT, I365_CSC_STSCHG | (i << 4));
+ cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS);
+ udelay(100);
+ cb_writel(socket, CB_SOCKET_EVENT, -1);
+ }
+ cb_writel(socket, CB_SOCKET_MASK, 0);
+ return probe_irq_mask(val) & 0xffff;
+}
+
+static void yenta_clear_maps(pci_socket_t *socket)
+{
+ int i;
+ pccard_io_map io = { 0, 0, 0, 0, 1 };
+ pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
+
+ mem.sys_stop = 0x0fff;
+ yenta_set_socket(socket, &dead_socket);
+ for (i = 0; i < 2; i++) {
+ io.map = i;
+ yenta_set_io_map(socket, &io);
+ }
+ for (i = 0; i < 5; i++) {
+ mem.map = i;
+ yenta_set_mem_map(socket, &mem);
+ }
+}
+
+/* Called at resume and initialization events */
+static int yenta_init(pci_socket_t *socket)
+{
+ struct pci_dev *dev = socket->dev;
+
+ pci_set_power_state(socket->dev, 0);
+
+ config_writel(socket, CB_LEGACY_MODE_BASE, 0);
+ config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start);
+ config_writew(socket, PCI_COMMAND,
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER |
+ PCI_COMMAND_WAIT);
+
+ /* MAGIC NUMBERS! Fixme */
+ config_writeb(socket, PCI_CACHE_LINE_SIZE, 32);
+ config_writeb(socket, PCI_LATENCY_TIMER, 168);
+ config_writeb(socket, PCI_SEC_LATENCY_TIMER, 176);
+ config_writeb(socket, PCI_PRIMARY_BUS, dev->bus->number);
+ config_writeb(socket, PCI_SECONDARY_BUS, dev->subordinate->number);
+ config_writeb(socket, PCI_SUBORDINATE_BUS, dev->subordinate->number);
+
+ exca_writeb(socket, I365_GBLCTL, 0x00);
+ exca_writeb(socket, I365_GENCTL, 0x00);
+
+ yenta_clear_maps(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);
+ pci_set_power_state(socket->dev, 3);
+ return 0;
+}
+
+/*
+ * Set static data that doesn't need re-initializing..
+ */
+static void yenta_get_socket_capabilities(pci_socket_t *socket)
+{
+ socket->cap.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
+ socket->cap.map_size = 0x1000;
+ socket->cap.pci_irq = socket->cb_irq;
+ socket->cap.irq_mask = yenta_probe_irq(socket);
+ socket->cap.cb_dev = socket->dev;
+ socket->cap.bus = NULL;
+
+ printk("Yenta IRQ list %04x\n", socket->cap.irq_mask);
+}
+
+static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
+{
+ struct pci_bus *bus;
+ struct resource *root, *res;
+ u32 start, end;
+ u32 align, size, min, max;
+ unsigned offset;
+
+ offset = 0x1c + 8*nr;
+ bus = socket->dev->subordinate;
+ res = socket->dev->resource + PCI_BRIDGE_RESOURCES + nr;
+ res->name = bus->name;
+ res->flags = type;
+ res->start = 0;
+ res->end = 0;
+ root = pci_find_parent_resource(socket->dev, res);
+
+ if (!root)
+ return;
+
+ start = config_readl(socket, offset);
+ end = config_readl(socket, offset+4) | 0xfff;
+ if (start && end > start) {
+ res->start = start;
+ res->end = end;
+ request_resource(root, res);
+ return;
+ }
+
+ align = size = 4*1024*1024;
+ min = 0x10000000; max = ~0U;
+ if (type & IORESOURCE_IO) {
+ align = 1024;
+ size = 256;
+ min = 0x1000;
+ max = 0xffff;
+ }
+
+ if (allocate_resource(root, res, size, min, max, align, NULL, NULL) < 0)
+ return;
+
+ config_writel(socket, offset, res->start);
+ config_writel(socket, offset+4, res->end);
+}
+
+/*
+ * Allocate the bridge mappings for the device..
+ */
+static void yenta_allocate_resources(pci_socket_t *socket)
+{
+ yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH);
+ yenta_allocate_res(socket, 1, IORESOURCE_MEM);
+ yenta_allocate_res(socket, 2, IORESOURCE_IO);
+}
+
+/*
+ * 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)
+{
+ struct pci_dev *dev = socket->dev;
+
+ /*
+ * Do some basic sanity checking..
+ */
+ if (pci_enable_device(dev)) {
+ printk("Unable to enable device\n");
+ return -1;
+ }
+ if (!dev->resource[0].start) {
+ printk("No cardbus resource!\n");
+ return -1;
+ }
+
+ /*
+ * Ok, start setup.. Map the cardbus registers,
+ * and request the IRQ.
+ */
+ socket->base = ioremap(dev->resource[0].start, 0x1000);
+ if (!socket->base)
+ return -1;
+
+ /* Disable all events */
+ cb_writel(socket, CB_SOCKET_MASK, 0x0);
+
+ /* 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);
+
+ 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 = {
+ yenta_open,
+ yenta_close,
+ yenta_init,
+ yenta_suspend,
+ yenta_inquire,
+ 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
+};
+
+/*
+ * Ricoh cardbus bridge: standard cardbus, except it needs
+ * some extra init code to set timings etc.
+ */
+struct pci_socket_ops ricoh_operations = {
+ yenta_open,
+ yenta_close,
+ ricoh_init,
+ yenta_suspend,
+ yenta_inquire,
+ 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
+};
diff --git a/drivers/pcmcia/yenta.h b/drivers/pcmcia/yenta.h
index fbba0b1a3..c8d61c409 100644
--- a/drivers/pcmcia/yenta.h
+++ b/drivers/pcmcia/yenta.h
@@ -1,153 +1,99 @@
+#ifndef __YENTA_H
+#define __YENTA_H
+
+#include <asm/io.h>
+#include "pci_socket.h"
+
+#define CB_SOCKET_EVENT 0x00
+#define CB_CSTSEVENT 0x00000001 /* Card status event */
+#define CB_CD1EVENT 0x00000002 /* Card detect 1 change event */
+#define CB_CD2EVENT 0x00000004 /* Card detect 2 change event */
+#define CB_PWREVENT 0x00000008 /* PWRCYCLE change event */
+
+#define CB_SOCKET_MASK 0x04
+#define CB_CSTSMASK 0x00000001 /* Card status mask */
+#define CB_CDMASK 0x00000006 /* Card detect 1&2 mask */
+#define CB_PWRMASK 0x00000008 /* PWRCYCLE change mask */
+
+#define CB_SOCKET_STATE 0x08
+#define CB_CARDSTS 0x00000001 /* CSTSCHG status */
+#define CB_CDETECT1 0x00000002 /* Card detect status 1 */
+#define CB_CDETECT2 0x00000004 /* Card detect status 2 */
+#define CB_PWRCYCLE 0x00000008 /* Socket powered */
+#define CB_16BITCARD 0x00000010 /* 16-bit card detected */
+#define CB_CBCARD 0x00000020 /* CardBus card detected */
+#define CB_IREQCINT 0x00000040 /* READY(xIRQ)/xCINT high */
+#define CB_NOTACARD 0x00000080 /* Unrecognizable PC card detected */
+#define CB_DATALOST 0x00000100 /* Potential data loss due to card removal */
+#define CB_BADVCCREQ 0x00000200 /* Invalid Vcc request by host software */
+#define CB_5VCARD 0x00000400 /* Card Vcc at 5.0 volts? */
+#define CB_3VCARD 0x00000800 /* Card Vcc at 3.3 volts? */
+#define CB_XVCARD 0x00001000 /* Card Vcc at X.X volts? */
+#define CB_YVCARD 0x00002000 /* Card Vcc at Y.Y volts? */
+#define CB_5VSOCKET 0x10000000 /* Socket Vcc at 5.0 volts? */
+#define CB_3VSOCKET 0x20000000 /* Socket Vcc at 3.3 volts? */
+#define CB_XVSOCKET 0x40000000 /* Socket Vcc at X.X volts? */
+#define CB_YVSOCKET 0x80000000 /* Socket Vcc at Y.Y volts? */
+
+#define CB_SOCKET_FORCE 0x0C
+#define CB_FCARDSTS 0x00000001 /* Force CSTSCHG */
+#define CB_FCDETECT1 0x00000002 /* Force CD1EVENT */
+#define CB_FCDETECT2 0x00000004 /* Force CD2EVENT */
+#define CB_FPWRCYCLE 0x00000008 /* Force PWREVENT */
+#define CB_F16BITCARD 0x00000010 /* Force 16-bit PCMCIA card */
+#define CB_FCBCARD 0x00000020 /* Force CardBus line */
+#define CB_FNOTACARD 0x00000080 /* Force NOTACARD */
+#define CB_FDATALOST 0x00000100 /* Force data lost */
+#define CB_FBADVCCREQ 0x00000200 /* Force bad Vcc request */
+#define CB_F5VCARD 0x00000400 /* Force 5.0 volt card */
+#define CB_F3VCARD 0x00000800 /* Force 3.3 volt card */
+#define CB_FXVCARD 0x00001000 /* Force X.X volt card */
+#define CB_FYVCARD 0x00002000 /* Force Y.Y volt card */
+#define CB_CVSTEST 0x00004000 /* Card VS test */
+
+#define CB_SOCKET_CONTROL 0x10
+#define CB_SC_VPP_MASK 0x00000007
+#define CB_SC_VPP_OFF 0x00000000
+#define CB_SC_VPP_12V 0x00000001
+#define CB_SC_VPP_5V 0x00000002
+#define CB_SC_VPP_3V 0x00000003
+#define CB_SC_VPP_XV 0x00000004
+#define CB_SC_VPP_YV 0x00000005
+#define CB_SC_VCC_MASK 0x00000070
+#define CB_SC_VCC_OFF 0x00000000
+#define CB_SC_VCC_5V 0x00000020
+#define CB_SC_VCC_3V 0x00000030
+#define CB_SC_VCC_XV 0x00000040
+#define CB_SC_VCC_YV 0x00000050
+#define CB_SC_CCLK_STOP 0x00000080
+
+#define CB_SOCKET_POWER 0x20
+#define CB_SKTACCES 0x02000000 /* A PC card access has occurred (clear on read) */
+#define CB_SKTMODE 0x01000000 /* Clock frequency has changed (clear on read) */
+#define CB_CLKCTRLEN 0x00010000 /* Clock control enabled (RW) */
+#define CB_CLKCTRL 0x00000001 /* Stop(0) or slow(1) CB clock (RW) */
+
/*
- * yenta.h 1.16 1999/10/25 20:03:34
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License
- * at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and
- * limitations under the License.
- *
- * The initial developer of the original code is David A. Hinds
- * <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
- * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
- * case the provisions of the GPL are applicable instead of the
- * above. If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use
- * your version of this file under the MPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL. If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the MPL or the GPL.
+ * Cardbus configuration space
*/
+#define CB_BRIDGE_BASE(m) (0x1c + 8*(m))
+#define CB_BRIDGE_LIMIT(m) (0x20 + 8*(m))
+#define CB_BRIDGE_CONTROL 0x3e
+#define CB_BRIDGE_CPERREN 0x00000001
+#define CB_BRIDGE_CSERREN 0x00000002
+#define CB_BRIDGE_ISAEN 0x00000004
+#define CB_BRIDGE_VGAEN 0x00000008
+#define CB_BRIDGE_MABTMODE 0x00000020
+#define CB_BRIDGE_CRST 0x00000040
+#define CB_BRIDGE_INTR 0x00000080
+#define CB_BRIDGE_PREFETCH0 0x00000100
+#define CB_BRIDGE_PREFETCH1 0x00000200
+#define CB_BRIDGE_POSTEN 0x00000400
+#define CB_LEGACY_MODE_BASE 0x44
-#ifndef _LINUX_YENTA_H
-#define _LINUX_YENTA_H
-
-/* PCI Configuration Registers */
-
-#define PCI_STATUS_CAPLIST 0x10
-#define PCI_CB_CAPABILITY_POINTER 0x14 /* 8 bit */
-#define PCI_CAPABILITY_ID 0x00 /* 8 bit */
-#define PCI_CAPABILITY_PM 0x01
-#define PCI_NEXT_CAPABILITY 0x01 /* 8 bit */
-#define PCI_PM_CAPABILITIES 0x02 /* 16 bit */
-#define PCI_PMCAP_PME_D3COLD 0x8000
-#define PCI_PMCAP_PME_D3HOT 0x4000
-#define PCI_PMCAP_PME_D2 0x2000
-#define PCI_PMCAP_PME_D1 0x1000
-#define PCI_PMCAP_PME_D0 0x0800
-#define PCI_PMCAP_D2_CAP 0x0400
-#define PCI_PMCAP_D1_CAP 0x0200
-#define PCI_PMCAP_DYN_DATA 0x0100
-#define PCI_PMCAP_DSI 0x0020
-#define PCI_PMCAP_AUX_PWR 0x0010
-#define PCI_PMCAP_PMECLK 0x0008
-#define PCI_PMCAP_VERSION_MASK 0x0007
-#define PCI_PM_CONTROL_STATUS 0x04 /* 16 bit */
-#define PCI_PMCS_PME_STATUS 0x8000
-#define PCI_PMCS_DATASCALE_MASK 0x6000
-#define PCI_PMCS_DATASCALE_SHIFT 13
-#define PCI_PMCS_DATASEL_MASK 0x1e00
-#define PCI_PMCS_DATASEL_SHIFT 9
-#define PCI_PMCS_PME_ENABLE 0x0100
-#define PCI_PMCS_PWR_STATE_MASK 0x0003
-#define PCI_PMCS_PWR_STATE_D0 0x0000
-#define PCI_PMCS_PWR_STATE_D1 0x0001
-#define PCI_PMCS_PWR_STATE_D2 0x0002
-#define PCI_PMCS_PWR_STATE_D3 0x0003
-#define PCI_PM_BRIDGE_EXT 0x06 /* 8 bit */
-#define PCI_PM_DATA 0x07 /* 8 bit */
-
-#define CB_PRIMARY_BUS 0x18 /* 8 bit */
-#define CB_CARDBUS_BUS 0x19 /* 8 bit */
-#define CB_SUBORD_BUS 0x1a /* 8 bit */
-#define CB_LATENCY_TIMER 0x1b /* 8 bit */
-
-#define CB_MEM_BASE(m) (0x1c + 8*(m))
-#define CB_MEM_LIMIT(m) (0x20 + 8*(m))
-#define CB_IO_BASE(m) (0x2c + 8*(m))
-#define CB_IO_LIMIT(m) (0x30 + 8*(m))
-
-#define CB_BRIDGE_CONTROL 0x3e /* 16 bit */
-#define CB_BCR_PARITY_ENA 0x0001
-#define CB_BCR_SERR_ENA 0x0002
-#define CB_BCR_ISA_ENA 0x0004
-#define CB_BCR_VGA_ENA 0x0008
-#define CB_BCR_MABORT 0x0020
-#define CB_BCR_CB_RESET 0x0040
-#define CB_BCR_ISA_IRQ 0x0080
-#define CB_BCR_PREFETCH(m) (0x0100 << (m))
-#define CB_BCR_WRITE_POST 0x0400
-
-#define CB_LEGACY_MODE_BASE 0x44
-
-/* Memory mapped registers */
-
-#define CB_SOCKET_EVENT 0x0000
-#define CB_SE_CSTSCHG 0x00000001
-#define CB_SE_CCD1 0x00000002
-#define CB_SE_CCD2 0x00000004
-#define CB_SE_PWRCYCLE 0x00000008
-
-#define CB_SOCKET_MASK 0x0004
-#define CB_SM_CSTSCHG 0x00000001
-#define CB_SM_CCD 0x00000006
-#define CB_SM_PWRCYCLE 0x00000008
-
-#define CB_SOCKET_STATE 0x0008
-#define CB_SS_CSTSCHG 0x00000001
-#define CB_SS_CCD1 0x00000002
-#define CB_SS_CCD2 0x00000004
-#define CB_SS_PWRCYCLE 0x00000008
-#define CB_SS_16BIT 0x00000010
-#define CB_SS_32BIT 0x00000020
-#define CB_SS_CINT 0x00000040
-#define CB_SS_BADCARD 0x00000080
-#define CB_SS_DATALOST 0x00000100
-#define CB_SS_BADVCC 0x00000200
-#define CB_SS_5VCARD 0x00000400
-#define CB_SS_3VCARD 0x00000800
-#define CB_SS_XVCARD 0x00001000
-#define CB_SS_YVCARD 0x00002000
-#define CB_SS_5VSOCKET 0x10000000
-#define CB_SS_3VSOCKET 0x20000000
-#define CB_SS_XVSOCKET 0x40000000
-#define CB_SS_YVSOCKET 0x80000000
-
-#define CB_SOCKET_FORCE 0x000c
-#define CB_SF_CVSTEST 0x00004000
-
-#define CB_SOCKET_CONTROL 0x0010
-#define CB_SC_VPP_MASK 0x00000007
-#define CB_SC_VPP_OFF 0x00000000
-#define CB_SC_VPP_12V 0x00000001
-#define CB_SC_VPP_5V 0x00000002
-#define CB_SC_VPP_3V 0x00000003
-#define CB_SC_VPP_XV 0x00000004
-#define CB_SC_VPP_YV 0x00000005
-#define CB_SC_VCC_MASK 0x00000070
-#define CB_SC_VCC_OFF 0x00000000
-#define CB_SC_VCC_5V 0x00000020
-#define CB_SC_VCC_3V 0x00000030
-#define CB_SC_VCC_XV 0x00000040
-#define CB_SC_VCC_YV 0x00000050
-#define CB_SC_CCLK_STOP 0x00000080
-
-#define CB_SOCKET_POWER 0x0020
-#define CB_SP_CLK_CTRL 0x00000001
-#define CB_SP_CLK_CTRL_ENA 0x00010000
-#define CB_SP_CLK_MODE 0x01000000
-#define CB_SP_ACCESS 0x02000000
-
-/* Address bits 31..24 for memory windows for 16-bit cards,
- accessable only by memory mapping the 16-bit register set */
-#define CB_MEM_PAGE(map) (0x40 + (map))
+/*
+ * ExCA area extensions in Yenta
+ */
+#define CB_MEM_PAGE(map) (0x40 + (map))
-#endif /* _LINUX_YENTA_H */
+#endif