yenta_socket.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,148 行 · 第 1/3 页
C
1,148 行
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 unsigned int yenta_events(struct yenta_socket *socket){ u8 csc; u32 cb_event; unsigned int events; /* 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; } return events;}static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs){ unsigned int events; struct yenta_socket *socket = (struct yenta_socket *) dev_id; events = yenta_events(socket); if (events) { pcmcia_parse_events(&socket->socket, events); return IRQ_HANDLED; } return IRQ_NONE;}static void yenta_interrupt_wrapper(unsigned long data){ struct yenta_socket *socket = (struct yenta_socket *) data; yenta_interrupt(0, (void *)socket, NULL); socket->poll_timer.expires = jiffies + HZ; add_timer(&socket->poll_timer);}static void yenta_clear_maps(struct yenta_socket *socket){ int i; struct resource res = { .start = 0, .end = 0x0fff }; pccard_io_map io = { 0, 0, 0, 0, 1 }; pccard_mem_map mem = { .res = &res, }; yenta_set_socket(&socket->socket, &dead_socket); for (i = 0; i < 2; i++) { io.map = i; yenta_set_io_map(&socket->socket, &io); } for (i = 0; i < 5; i++) { mem.map = i; yenta_set_mem_map(&socket->socket, &mem); }}/* Called at resume and initialization events */static int yenta_sock_init(struct pcmcia_socket *sock){ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); u32 state; u16 bridge; bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR; if (!socket->cb_irq) bridge |= CB_BRIDGE_INTR; config_writew(socket, CB_BRIDGE_CONTROL, bridge); exca_writeb(socket, I365_GBLCTL, 0x00); exca_writeb(socket, I365_GENCTL, 0x00); /* Redo card voltage interrogation */ state = cb_readl(socket, CB_SOCKET_STATE); if (!(state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD))) cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST); yenta_clear_maps(socket); if (socket->type && socket->type->sock_init) socket->type->sock_init(socket); /* Re-enable CSC interrupts */ cb_writel(socket, CB_SOCKET_MASK, CB_CDMASK); return 0;}static int yenta_sock_suspend(struct pcmcia_socket *sock){ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); yenta_set_socket(sock, &dead_socket); /* Disable CSC interrupts */ cb_writel(socket, CB_SOCKET_MASK, 0x0); return 0;}/* * Use an adaptive allocation for the memory resource, * sometimes the memory behind pci bridges is limited: * 1/8 of the size of the io window of the parent. * max 4 MB, min 16 kB. */#define BRIDGE_MEM_MAX 4*1024*1024#define BRIDGE_MEM_MIN 16*1024#define BRIDGE_IO_MAX 256#define BRIDGE_IO_MIN 32#ifndef PCIBIOS_MIN_CARDBUS_IO#define PCIBIOS_MIN_CARDBUS_IO PCIBIOS_MIN_IO#endifstatic void yenta_allocate_res(struct yenta_socket *socket, int nr, unsigned type){ struct pci_bus *bus; struct resource *root, *res; u32 start, end; u32 align, size, min; unsigned offset; unsigned mask; /* The granularity of the memory limit is 4kB, on IO it's 4 bytes */ mask = ~0xfff; if (type & IORESOURCE_IO) mask = ~3; 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) & mask; end = config_readl(socket, offset+4) | ~mask; if (start && end > start) { res->start = start; res->end = end; if (request_resource(root, res) == 0) return; printk(KERN_INFO "yenta %s: Preassigned resource %d busy, reconfiguring...\n", pci_name(socket->dev), nr); res->start = res->end = 0; } if (type & IORESOURCE_IO) { align = 1024; size = BRIDGE_IO_MAX; min = BRIDGE_IO_MIN; start = PCIBIOS_MIN_CARDBUS_IO; end = ~0U; } else { unsigned long avail = root->end - root->start; int i; size = BRIDGE_MEM_MAX; if (size > avail/8) { size=(avail+1)/8; /* round size down to next power of 2 */ i = 0; while ((size /= 2) != 0) i++; size = 1 << i; } if (size < BRIDGE_MEM_MIN) size = BRIDGE_MEM_MIN; min = BRIDGE_MEM_MIN; align = size; start = PCIBIOS_MIN_MEM; end = ~0U; } do { if (allocate_resource(root, res, size, start, end, align, NULL, NULL)==0) { config_writel(socket, offset, res->start); config_writel(socket, offset+4, res->end); return; } size = size/2; align = size; } while (size >= min); printk(KERN_INFO "yenta %s: no resource of type %x available, trying to continue...\n", pci_name(socket->dev), type); res->start = res->end = 0;}/* * Allocate the bridge mappings for the device.. */static void yenta_allocate_resources(struct yenta_socket *socket){ yenta_allocate_res(socket, 0, IORESOURCE_MEM|IORESOURCE_PREFETCH); yenta_allocate_res(socket, 1, IORESOURCE_MEM); yenta_allocate_res(socket, 2, IORESOURCE_IO); yenta_allocate_res(socket, 3, IORESOURCE_IO); /* PCI isn't clever enough to use this one yet */}/* * Free the bridge mappings for the device.. */static void yenta_free_resources(struct yenta_socket *socket){ int i; for (i=0;i<4;i++) { struct resource *res; res = socket->dev->resource + PCI_BRIDGE_RESOURCES + i; if (res->start != 0 && res->end != 0) release_resource(res); res->start = res->end = 0; }}/* * Close it down - release our resources and go home.. */static void yenta_close(struct pci_dev *dev){ struct yenta_socket *sock = pci_get_drvdata(dev); /* we don't want a dying socket registered */ pcmcia_unregister_socket(&sock->socket); /* Disable all events so we don't die in an IRQ storm */ cb_writel(sock, CB_SOCKET_MASK, 0x0); exca_writeb(sock, I365_CSCINT, 0); if (sock->cb_irq) free_irq(sock->cb_irq, sock); else del_timer_sync(&sock->poll_timer); if (sock->base) iounmap(sock->base); yenta_free_resources(sock); pci_release_regions(dev); pci_set_drvdata(dev, NULL);}static struct pccard_operations yenta_socket_operations = { .init = yenta_sock_init, .suspend = yenta_sock_suspend, .get_status = yenta_get_status, .get_socket = yenta_get_socket, .set_socket = yenta_set_socket, .set_io_map = yenta_set_io_map, .set_mem_map = yenta_set_mem_map,};#include "ti113x.h"#include "ricoh.h"#include "topic.h"#include "o2micro.h"enum { CARDBUS_TYPE_DEFAULT = -1, CARDBUS_TYPE_TI, CARDBUS_TYPE_TI113X, CARDBUS_TYPE_TI12XX, CARDBUS_TYPE_TI1250, CARDBUS_TYPE_RICOH, CARDBUS_TYPE_TOPIC97, CARDBUS_TYPE_O2MICRO,};/* * Different cardbus controllers have slightly different * initialization sequences etc details. List them here.. */struct cardbus_type cardbus_type[] = { [CARDBUS_TYPE_TI] = { .override = ti_override, .save_state = ti_save_state, .restore_state = ti_restore_state, .sock_init = ti_init, }, [CARDBUS_TYPE_TI113X] = { .override = ti113x_override, .save_state = ti_save_state, .restore_state = ti_restore_state, .sock_init = ti_init, }, [CARDBUS_TYPE_TI12XX] = { .override = ti12xx_override, .save_state = ti_save_state, .restore_state = ti_restore_state, .sock_init = ti_init, }, [CARDBUS_TYPE_TI1250] = { .override = ti1250_override, .save_state = ti_save_state, .restore_state = ti_restore_state, .sock_init = ti_init, }, [CARDBUS_TYPE_RICOH] = { .override = ricoh_override, .save_state = ricoh_save_state, .restore_state = ricoh_restore_state, }, [CARDBUS_TYPE_TOPIC97] = { .override = topic97_override, }, [CARDBUS_TYPE_O2MICRO] = { .override = o2micro_override, .restore_state = o2micro_restore_state, },};/* * Only probe "regular" interrupts, don't * touch dangerous spots like the mouse irq, * because there are mice that apparently * get really confused if they get fondled * too intimately. * * Default to 11, 10, 9, 7, 6, 5, 4, 3. */static u32 isa_interrupts = 0x0ef8;static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mask){ int i; unsigned long val; u16 bridge_ctrl; u32 mask; /* Set up ISA irq routing to probe the ISA irqs.. */ bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL); 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); exca_writeb(socket, I365_CSCINT, 0); val = probe_irq_on() & isa_irq_mask; for (i = 1; i < 16; i++) { if (!((val >> i) & 1)) continue;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?