diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-05 06:47:02 +0000 |
commit | 99a7e12f34b3661a0d1354eef83a0eef4df5e34c (patch) | |
tree | 3560aca9ca86792f9ab7bd87861ea143a1b3c7a3 /drivers/pcmcia | |
parent | e73a04659c0b8cdee4dd40e58630e2cf63afb316 (diff) |
Merge with Linux 2.3.38.
Diffstat (limited to 'drivers/pcmcia')
-rw-r--r-- | drivers/pcmcia/Config.in | 2 | ||||
-rw-r--r-- | drivers/pcmcia/Makefile | 10 | ||||
-rw-r--r-- | drivers/pcmcia/bulkmem.c | 23 | ||||
-rw-r--r-- | drivers/pcmcia/cardbus.c | 723 | ||||
-rw-r--r-- | drivers/pcmcia/cistpl.c | 10 | ||||
-rw-r--r-- | drivers/pcmcia/cs.c | 211 | ||||
-rw-r--r-- | drivers/pcmcia/cs_internal.h | 8 | ||||
-rw-r--r-- | drivers/pcmcia/i82365.c | 1503 | ||||
-rw-r--r-- | drivers/pcmcia/old-yenta.h | 153 | ||||
-rw-r--r-- | drivers/pcmcia/pci_socket.c | 205 | ||||
-rw-r--r-- | drivers/pcmcia/pci_socket.h | 39 | ||||
-rw-r--r-- | drivers/pcmcia/tcic.c | 94 | ||||
-rw-r--r-- | drivers/pcmcia/yenta.c | 716 | ||||
-rw-r--r-- | drivers/pcmcia/yenta.h | 244 |
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, ¥ta_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 |