⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yenta.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
}static unsigned int yenta_events(pci_socket_t *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 void yenta_bh(void *data){	pci_socket_t *socket = data;	unsigned int events;	spin_lock_irq(&socket->event_lock);	events = socket->events;	socket->events = 0;	spin_unlock_irq(&socket->event_lock);	if (socket->handler)		socket->handler(socket->info, events);}static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs){	unsigned int events;	pci_socket_t *socket = (pci_socket_t *) dev_id;	events = yenta_events(socket);	if (events) {		spin_lock(&socket->event_lock);		socket->events |= events;		spin_unlock(&socket->event_lock);		schedule_task(&socket->tq_task);	}}static void yenta_interrupt_wrapper(unsigned long data){	pci_socket_t *socket = (pci_socket_t *) data;	yenta_interrupt(0, (void *)socket, NULL);	socket->poll_timer.expires = jiffies + HZ;	add_timer(&socket->poll_timer);}/* * 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(pci_socket_t *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;		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);	exca_writeb(socket, I365_CSCINT, 0);		mask = probe_irq_mask(val) & 0xffff;	bridge_ctrl &= ~CB_BRIDGE_INTR;	config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);	return mask;}/* * Set static data that doesn't need re-initializing.. */static void yenta_get_socket_capabilities(pci_socket_t *socket, u32 isa_irq_mask){	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, isa_irq_mask);	socket->cap.cb_dev = socket->dev;	socket->cap.bus = NULL;	printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);}extern void cardbus_register(pci_socket_t *socket);/* * 'Bottom half' for the yenta_open routine. Allocate the interrupt line *  and register the socket with the upper layers. */static void yenta_open_bh(void * data){	pci_socket_t * socket = (pci_socket_t *) data;	/* It's OK to overwrite this now */	socket->tq_task.routine = yenta_bh;	if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->name, socket)) {		/* No IRQ or request_irq failed. Poll */		socket->cb_irq = 0; /* But zero is a valid IRQ number. */		socket->poll_timer.function = yenta_interrupt_wrapper;		socket->poll_timer.data = (unsigned long)socket;		socket->poll_timer.expires = jiffies + HZ;		add_timer(&socket->poll_timer);	}	/* Figure out what the dang thing can do for the PCMCIA layer... */	yenta_get_socket_capabilities(socket, isa_interrupts);	printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));	/* Register it with the pcmcia layer.. */	cardbus_register(socket);	MOD_DEC_USE_COUNT;}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);	}}/* * Initialize the standard cardbus registers */static void yenta_config_init(pci_socket_t *socket){	u16 bridge;	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, L1_CACHE_BYTES / 4);	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);	/*	 * Set up the bridging state:	 *  - enable write posting.	 *  - memory window 0 prefetchable, window 1 non-prefetchable	 *  - PCI interrupts enabled if a PCI interrupt exists..	 */	bridge = config_readw(socket, CB_BRIDGE_CONTROL);	bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);	bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;	if (!socket->cb_irq)		bridge |= CB_BRIDGE_INTR;	config_writew(socket, CB_BRIDGE_CONTROL, bridge);	exca_writeb(socket, I365_GBLCTL, 0x00);	exca_writeb(socket, I365_GENCTL, 0x00);	/* Redo card voltage interrogation */	cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);}/* Called at resume and initialization events */static int yenta_init(pci_socket_t *socket){	yenta_config_init(socket);	yenta_clear_maps(socket);	return 0;}static int yenta_suspend(pci_socket_t *socket){	yenta_set_socket(socket, &dead_socket);	/*	 * This does not work currently. The controller	 * loses too much informationduring D3 to come up	 * cleanly. We should probably fix yenta_init()	 * to update all the critical registers, notably	 * the IO and MEM bridging region data.. That is	 * something that pci_set_power_state() should	 * probably know about bridges anyway.	 *	pci_set_power_state(socket->dev, 3);	 */	return 0;}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 = PCIBIOS_MIN_MEM; max = ~0U;	if (type & IORESOURCE_IO) {		align = 1024;		size = 256;		min = PCIBIOS_MIN_IO;		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);	yenta_allocate_res(socket, 3, IORESOURCE_IO);	/* PCI isn't clever enough to use this one yet */}/* * 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);	else		del_timer_sync(&sock->poll_timer);	if (sock->base)		iounmap(sock->base);}#include "ti113x.h"#include "ricoh.h"/* * Different cardbus controllers have slightly different * initialization sequences etc details. List them here.. */#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##ystatic struct cardbus_override_struct {	unsigned short vendor;	unsigned short device;	struct pci_socket_ops *op;} cardbus_override[] = {	{ PD(TI,1130),	&ti113x_ops },	{ PD(TI,1031),	&ti_ops },	{ PD(TI,1131),	&ti113x_ops },	{ PD(TI,1250),	&ti1250_ops },	{ PD(TI,1220),	&ti_ops },	{ PD(TI,1221),	&ti_ops },	{ PD(TI,1210),	&ti_ops },	{ PD(TI,1450),	&ti_ops },	{ PD(TI,1225),	&ti_ops },	{ PD(TI,1251A),	&ti_ops },	{ PD(TI,1211),	&ti_ops },	{ PD(TI,1251B),	&ti_ops },	{ PD(TI,1420),	&ti_ops },	{ PD(RICOH,RL5C465), &ricoh_ops },	{ PD(RICOH,RL5C466), &ricoh_ops },	{ PD(RICOH,RL5C475), &ricoh_ops },	{ PD(RICOH,RL5C476), &ricoh_ops },	{ PD(RICOH,RL5C478), &ricoh_ops }};#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))/* * Initialize a cardbus controller. Make sure we have a usable * interrupt, and that we can map the cardbus area. Fill in the * socket information structure.. */static int yenta_open(pci_socket_t *socket){	int i;	struct pci_dev *dev = socket->dev;	/*	 * Do some basic sanity checking..	 */	if (pci_enable_device(dev))		return -1;	if (!pci_resource_start(dev, 0)) {		printk("No cardbus resource!\n");		return -1;	}	/*	 * Ok, start setup.. Map the cardbus registers,	 * and request the IRQ.	 */	socket->base = ioremap(pci_resource_start(dev, 0), 0x1000);	if (!socket->base)		return -1;	yenta_config_init(socket);	/* Disable all events */	cb_writel(socket, CB_SOCKET_MASK, 0x0);	/* Set up the bridge regions.. */	yenta_allocate_resources(socket);	socket->cb_irq = dev->irq;	/* Do we have special options for the device? */	for (i = 0; i < NR_OVERRIDES; i++) {		struct cardbus_override_struct *d = cardbus_override+i;		if (dev->vendor == d->vendor && dev->device == d->device) {			socket->op = d->op;			if (d->op->open) {				int retval = d->op->open(socket);				if (retval < 0)					return retval;			}		}	}	/* Get the PCMCIA kernel thread to complete the	   initialisation later. We can't do this here,	   because, er, because Linus says so :)	*/	socket->tq_task.routine = yenta_open_bh;	socket->tq_task.data = socket;	MOD_INC_USE_COUNT;	schedule_task(&socket->tq_task);	return 0;}/* * Standard plain cardbus - no frills, no extensions */struct pci_socket_ops yenta_operations = {	yenta_open,	yenta_close,	yenta_init,	yenta_suspend,	yenta_get_status,	yenta_get_socket,	yenta_set_socket,	yenta_get_io_map,	yenta_set_io_map,	yenta_get_mem_map,	yenta_set_mem_map,	yenta_proc_setup};EXPORT_SYMBOL(yenta_operations);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -