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

📄 i82092.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * Driver for Intel I82092AA PCI-PCMCIA bridge. * * (C) 2001 Red Hat, Inc. * * Author: Arjan Van De Ven <arjanv@redhat.com> * Loosly based on i82365.c from the pcmcia-cs package * * $Id: i82092aa.c,v 1.2 2001/10/23 14:43:34 arjanv Exp $ */#include <linux/kernel.h>#include <linux/config.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/init.h>#include <pcmcia/cs_types.h>#include <pcmcia/ss.h>#include <pcmcia/cs.h>#include <asm/system.h>#include <asm/io.h>#include "i82092aa.h"#include "i82365.h"/* PCI core routines */static struct pci_device_id i82092aa_pci_ids[] = {	{	      vendor:PCI_VENDOR_ID_INTEL,	      device:PCI_DEVICE_ID_INTEL_82092AA_0,	      subvendor:PCI_ANY_ID,	      subdevice:PCI_ANY_ID,	      class: 0, class_mask:0,	 },	 {} };static struct pci_driver i82092aa_pci_drv = {	name:           "i82092aa",	id_table:       i82092aa_pci_ids,	probe:          i82092aa_pci_probe,	remove:         __devexit_p(i82092aa_pci_remove),	suspend:        NULL,	resume:         NULL };/* the pccard structure and its functions */static struct pccard_operations i82092aa_operations = {	init: 		 	i82092aa_init,	suspend:	   	i82092aa_suspend,	register_callback: 	i82092aa_register_callback,	inquire_socket:		i82092aa_inquire_socket,   	get_status:		i82092aa_get_status,	get_socket:		i82092aa_get_socket,	set_socket:		i82092aa_set_socket,	get_io_map:		i82092aa_get_io_map,	set_io_map:		i82092aa_set_io_map,	get_mem_map:		i82092aa_get_mem_map,	set_mem_map:		i82092aa_set_mem_map,	proc_setup:		i82092aa_proc_setup,};/* The card can do upto 4 sockets, allocate a structure for each of them */struct socket_info {	int	card_state; 	/*  0 = no socket,				    1 = empty socket, 				    2 = card but not initialized,				    3 = operational card */	int 	io_base; 	/* base io address of the socket */	socket_cap_t cap;		unsigned int pending_events; /* Pending events on this interface */		void	(*handler)(void *info, u_int events); 				/* callback to the driver of the card */	void	*info;		/* to be passed to the handler */		struct pci_dev *dev;	/* The PCI device for the socket */};#define MAX_SOCKETS 4static struct socket_info sockets[MAX_SOCKETS];static int socket_count;  /* shortcut */                                  	                                	static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id){	unsigned char configbyte;	int i;		enter("i82092aa_pci_probe");		if (pci_enable_device(dev))		return -EIO;			pci_read_config_byte(dev, 0x40, &configbyte);  /* PCI Configuration Control */	switch(configbyte&6) {		case 0:			printk(KERN_INFO "i82092aa: configured as a 2 socket device.\n");			socket_count = 2;			break;		case 2:			printk(KERN_INFO "i82092aa: configured as a 1 socket device.\n");			socket_count = 1;			break;		case 4:		case 6:			printk(KERN_INFO "i82092aa: configured as a 4 socket device.\n");			socket_count = 4;			break;					default:			printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.\n");			return -EIO;			break;	}		for (i = 0;i<socket_count;i++) {		sockets[i].card_state = 1; /* 1 = present but empty */		sockets[i].io_base = (dev->resource[0].start & ~1);		 if (sockets[i].io_base > 0) 		 	request_region(sockets[i].io_base, 2, "i82092aa");		 				sockets[i].cap.features |= SS_CAP_PCCARD;		sockets[i].cap.map_size = 0x1000;		sockets[i].cap.irq_mask = 0;		sockets[i].cap.pci_irq  = dev->irq;				if (card_present(i)) {			sockets[i].card_state = 3;			dprintk(KERN_DEBUG "i82092aa: slot %i is occupied\n",i);		} else {			dprintk(KERN_DEBUG "i82092aa: slot %i is vacant\n",i);		}	}			/* Now, specifiy that all interrupts are to be done as PCI interrupts */	configbyte = 0xFF; /* bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt */	pci_write_config_byte(dev, 0x50, configbyte); /* PCI Interrupt Routing Register */	/* Register the interrupt handler */	dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq);	if (request_irq(dev->irq, i82092aa_interrupt, SA_SHIRQ, "i82092aa", i82092aa_interrupt)) {		printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq);		return -EIO;	}		 		if (register_ss_entry(socket_count, &i82092aa_operations) != 0)		printk(KERN_NOTICE "i82092aa: register_ss_entry() failed\n");	leave("i82092aa_pci_probe");	return 0;}static void __devexit i82092aa_pci_remove(struct pci_dev *dev){	enter("i82092aa_pci_remove");		free_irq(dev->irq, i82092aa_interrupt);	leave("i82092aa_pci_remove");}static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;/* basic value read/write functions */static unsigned char indirect_read(int socket, unsigned short reg){	unsigned short int port;	unsigned char val;	unsigned long flags;	spin_lock_irqsave(&port_lock,flags);	reg += socket * 0x40;	port = sockets[socket].io_base;	outb(reg,port);	val = inb(port+1);	spin_unlock_irqrestore(&port_lock,flags);	return val;}static unsigned short indirect_read16(int socket, unsigned short reg){	unsigned short int port;	unsigned short tmp;	unsigned long flags;	spin_lock_irqsave(&port_lock,flags);	reg  = reg + socket * 0x40;	port = sockets[socket].io_base;	outb(reg,port);	tmp = inb(port+1);	reg++;	outb(reg,port);	tmp = tmp | (inb(port+1)<<8);	spin_unlock_irqrestore(&port_lock,flags);	return tmp;}static void indirect_write(int socket, unsigned short reg, unsigned char value){	unsigned short int port;	unsigned long flags;	spin_lock_irqsave(&port_lock,flags);	reg = reg + socket * 0x40;	port = sockets[socket].io_base; 	outb(reg,port);	outb(value,port+1);	spin_unlock_irqrestore(&port_lock,flags);}static void indirect_setbit(int socket, unsigned short reg, unsigned char mask){	unsigned short int port;	unsigned char val;	unsigned long flags;	spin_lock_irqsave(&port_lock,flags);	reg = reg + socket * 0x40;	port = sockets[socket].io_base; 	outb(reg,port);	val = inb(port+1);	val |= mask;	outb(reg,port);	outb(val,port+1);	spin_unlock_irqrestore(&port_lock,flags);}static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask){	unsigned short int port;	unsigned char val;	unsigned long flags;	spin_lock_irqsave(&port_lock,flags);	reg = reg + socket * 0x40;	port = sockets[socket].io_base; 	outb(reg,port);	val = inb(port+1);	val &= ~mask;	outb(reg,port);	outb(val,port+1);	spin_unlock_irqrestore(&port_lock,flags);}static void indirect_write16(int socket, unsigned short reg, unsigned short value){	unsigned short int port;	unsigned char val;	unsigned long flags;	spin_lock_irqsave(&port_lock,flags);	reg = reg + socket * 0x40;	port = sockets[socket].io_base; 		outb(reg,port);	val = value & 255;	outb(val,port+1);		reg++;		outb(reg,port);	val = value>>8;	outb(val,port+1);	spin_unlock_irqrestore(&port_lock,flags);}/* simple helper functions *//* External clock time, in nanoseconds.  120 ns = 8.33 MHz */static int cycle_time = 120;static int to_cycles(int ns){	if (cycle_time!=0)		return ns/cycle_time;	else		return 0;}    static int to_ns(int cycles){	return cycle_time*cycles;}/* Interrupt handler functionality */static void i82092aa_bh(void *dummy){        unsigned int events;	int i;                        for (i=0; i < socket_count; i++) {        	events = xchg(&(sockets[i].pending_events),0);        	printk("events = %x \n",events);                if (sockets[i].handler)                	sockets[i].handler(sockets[i].info, events);	}}                                                                                                                                        static struct tq_struct i82092aa_task = {        routine:        i82092aa_bh};        static void i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs){	int i;	int loopcount = 0;		unsigned int events, active=0;	/*	enter("i82092aa_interrupt");*/		while (1) {		loopcount++;		if (loopcount>20) {			printk(KERN_ERR "i82092aa: infinite eventloop in interrupt \n");			break;		}				active = 0;				for (i=0;i<socket_count;i++) {			int csc;			if (sockets[i].card_state==0) /* Inactive socket, should not happen */				continue;						csc = indirect_read(i,I365_CSC); /* card status change register */						if ((csc==0) ||  /* no events on this socket */			   (sockets[i].handler==NULL)) /* no way to handle events */			   	continue;			events = 0;			 			if (csc & I365_CSC_DETECT) {				events |= SS_DETECT;				printk("Card detected in socket %i!\n",i);			 }						if (indirect_read(i,I365_INTCTL) & I365_PC_IOCARD) { 				/* For IO/CARDS, bit 0 means "read the card" */				events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; 			} else {				/* Check for battery/ready events */				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) {				sockets[i].pending_events |= events;				schedule_task(&i82092aa_task);			}			active |= events;		}						if (active==0) /* no more events to handle */			break;							}	/*	leave("i82092aa_interrupt");*/}/* socket functions */static int card_present(int socketno){		unsigned int val;	enter("card_present");		if ((socketno<0) || (socketno > MAX_SOCKETS))		return 0;	if (sockets[socketno].io_base == 0)		return 0;			val = indirect_read(socketno, 1); /* Interface status register */	if ((val&12)==12) {		leave("card_present 1");		return 1;	}			leave("card_present 0");	return 0;}static void set_bridge_state(int sock){	enter("set_bridge_state");	indirect_write(sock, I365_GBLCTL,0x00);	indirect_write(sock, I365_GENCTL,0x00);		indirect_setbit(sock, I365_INTCTL,0x08);	leave("set_bridge_state");}      static int i82092aa_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 };                enter("i82092aa_init");                                mem.sys_stop = 0x0fff;        i82092aa_set_socket(s, &dead_socket);        for (i = 0; i < 2; i++) {        	io.map = i;                i82092aa_set_io_map(s, &io);	}        for (i = 0; i < 5; i++) {        	mem.map = i;                i82092aa_set_mem_map(s, &mem);	}		leave("i82092aa_init");	return 0;}                                                                                                                                                                                                                                              static int i82092aa_suspend(unsigned int sock){	int retval;	enter("i82092aa_suspend");        retval =  i82092aa_set_socket(sock, &dead_socket);        leave("i82092aa_suspend");        return retval;}       static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info){	enter("i82092aa_register_callback");	sockets[sock].handler = handler;        sockets[sock].info = info;        if (handler == NULL) {           	MOD_DEC_USE_COUNT;    	} else {		MOD_INC_USE_COUNT;	}	leave("i82092aa_register_callback");	return 0;

⌨️ 快捷键说明

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