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 + -
显示快捷键?