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

📄 triocs8900.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* uCcs89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. *//*	Port for uCsimm 1999 D. Jeff Dionne, Rt-Control Inc.	Written 1996 by Russell Nelson, with reference to skeleton.c	written 1993-1994 by Donald Becker.	This software may be used and distributed according to the terms	of the GNU Public License, incorporated herein by reference.	The author may be reached at nelson@crynwr.com, Crynwr	Software, 11 Grant St., Potsdam, NY 13676  Changelog:  Mike Cruse        : mcruse@cti-ltd.com                    : Changes for Linux 2.0 compatibility.                     : Added dev_id parameter in net_interrupt(),                    : request_irq() and free_irq(). Just NULL for now.  Mike Cruse        : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros                    : in net_open() and net_close() so kerneld would know                    : that the module is in use and wouldn't eject the                     : driver prematurely.  Mike Cruse        : Rewrote init_module() and cleanup_module using 8390.c                    : as an example. Disabled autoprobing in init_module(),                    : not a good thing to do to other devices while Linux                    : is running from all accounts.*/static char *version ="cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\ncs89x0.c:68EZ328 support D. Jeff Dionne <jeff@rt-control.com> 1999\n";/* ======================= configure the driver here ======================= *//* use 0 for production, 1 for verification, >2 for debug */#ifndef NET_DEBUG#define NET_DEBUG 2#endif/* ======================= end of configuration ======================= *//* Always include 'config.h' first in case the user wants to turn on   or override something. */#include <linux/config.h>#define PRINTK(x) printk x/*  Sources:	Crynwr packet driver epktisa.	Crystal Semiconductor data sheets.*/#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/string.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/irq.h>#include <linux/errno.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include "trioCS8900.h"#define NET_BASE 0x10000300static unsigned int net_debug = NET_DEBUG;/* The number of low I/O ports used by the ethercard. */#define NETCARD_IO_EXTENT	16void *irq2dev_map[1]; /* FIXME:  This does NOT go here *//* Information that need to be kept for each board. */struct net_local {	struct enet_statistics stats;	int chip_type;		/* one of: CS8900, CS8920, CS8920M */	char chip_revision;	/* revision letter of the chip ('A'...) */	int send_cmd;		/* the propercommand used to send a packet. */	int auto_neg_cnf;	int adapter_cnf;	int isa_config;	int irq_map;	int rx_mode;	int curr_rx_cfg;        int linectl;        int send_underrun;      /* keep track of how many underruns in a row we get */	struct sk_buff *skb;};/* Index to functions, as function prototypes. */extern int cs89x0_probe(struct device *dev);static int cs89x0_probe1(struct device *dev, int ioaddr);static int net_open(struct device *dev);static int	net_send_packet(struct sk_buff *skb, struct device *dev);static void cs8900_interrupt(int irq, void *dev_id, struct pt_regs *regs);static void set_multicast_list(struct device *dev);static void net_rx(struct device *dev);static int net_close(struct device *dev);static struct enet_statistics *net_get_stats(struct device *dev);static void reset_chip(struct device *dev);static int set_mac_address(struct device *dev, void *addr);/* Example routines you must write ;->. */#define tx_done(dev) 1/* Check for a network adaptor of this type, and return '0' iff one exists.   If dev->base_addr == 0, probe all likely locations.   If dev->base_addr == 1, always return failure.   If dev->base_addr == 2, allocate space for the device and return success   (detachable devices only).   */intcs89x0_probe(struct device *dev){	int base_addr = NET_BASE;	return cs89x0_probe1(dev, base_addr);}int inlinereadreg(struct device *dev, int portno){	outw(portno, dev->base_addr + ADD_PORT);	return inw(dev->base_addr + DATA_PORT);}void inlinewritereg(struct device *dev, int portno, int value){	outw(portno, dev->base_addr + ADD_PORT);	outw(value,  dev->base_addr + DATA_PORT);}int inlinereadword(struct device *dev, int portno){	return inw(dev->base_addr + portno);}void inlinewriteword(struct device *dev, int portno, int value){	outw(value, dev->base_addr + portno);}/* This is the real probe routine.  */static int cs89x0_probe1(struct device *dev, int ioaddr){	struct net_local *lp;	static unsigned version_printed = 0;	unsigned rev_type = 0;	irq2dev_map[0] = dev;	/* Initialize the device structure. */	if (dev->priv == NULL) {		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);        memset(dev->priv, 0, sizeof(struct net_local));    }	dev->base_addr = ioaddr;	lp = (struct net_local *)dev->priv;	if (readreg(dev, PP_ChipID) != CHIP_EISA_ID_SIG) {	  printk("cs89x0.c: No CrystalLan device found.\n");		return ENODEV;	}	/* get the chip type */	rev_type = readreg(dev, PRODUCT_ID_ADD);	lp->chip_type = rev_type &~ REVISON_BITS;	lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';	/* Check the chip type and revision in order to set the correct send command	CS8920 revision C and CS8900 revision F can use the faster send. */	lp->send_cmd = TX_AFTER_ALL;#if 0	if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')		lp->send_cmd = TX_NOW;	if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')		lp->send_cmd = TX_NOW;#endif	if (net_debug  &&  version_printed++ == 0)		printk(version);	printk("%s: cs89%c0%s rev %c found at 0x%.8x %s",	       dev->name,	       lp->chip_type==CS8900?'0':'2',	       lp->chip_type==CS8920M?"M":"",	       lp->chip_revision,	       dev->base_addr,	       readreg(dev, PP_SelfST) & ACTIVE_33V ? "3.3Volts" : "5Volts");	reset_chip(dev);	/* Fill this in, we don't have an EEPROM */	lp->adapter_cnf = A_CNF_10B_T | A_CNF_MEDIA_10B_T;	lp->auto_neg_cnf = EE_AUTO_NEG_ENABLE;	printk(" media %s%s%s",	       (lp->adapter_cnf & A_CNF_10B_T)?"RJ-45,":"",	       (lp->adapter_cnf & A_CNF_AUI)?"AUI,":"",	       (lp->adapter_cnf & A_CNF_10B_2)?"BNC,":"");	lp->irq_map = 0xffff;#ifndef CONFIG_TRIO_CS8900	#if 0/* hack */dev->dev_addr[0] = 0x00;dev->dev_addr[1] = 0x00;dev->dev_addr[2] = 0xc0;dev->dev_addr[3] = 0xff;dev->dev_addr[4] = 0xee;dev->dev_addr[5] = 0x01;#else{ extern unsigned char *cs8900a_hwaddr; memcpy(dev->dev_addr, cs8900a_hwaddr, 6);}#endif	/* print the ethernet address. */for (i = 0; i < ETH_ALEN; i++)	printk(" %2.2x", dev->dev_addr[i]);#endif /* not CONFIG_TRIO */#ifdef FIXME	/* Grab the region so we can find another board if autoIRQ fails. */	request_region(ioaddr, NETCARD_IO_EXTENT,"cs89x0");#endif	dev->open		= net_open;	dev->stop		= net_close;	dev->hard_start_xmit = net_send_packet;	dev->get_stats	= net_get_stats;	dev->set_multicast_list = &set_multicast_list;	dev->set_mac_address = &set_mac_address;	/* Fill in the fields of the device structure with ethernet values. */	ether_setup(dev);	printk("\n");	return 0;}voidreset_chip(struct device *dev){	int reset_start_time;	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);	/* wait 30 ms */	current->state = TASK_INTERRUPTIBLE;	current->timeout = jiffies + 3;	schedule();	/* Wait until the chip is reset */	reset_start_time = jiffies;	while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)		;}static intdetect_tp(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int timenow = jiffies;	if (net_debug > 1) printk("%s: Attempting TP\n", dev->name);        /* If connected to another full duplex capable 10-Base-T card the link pulses           seem to be lost when the auto detect bit in the LineCTL is set.           To overcome this the auto detect bit will be cleared whilst testing the           10-Base-T interface.  This would not be necessary for the sparrow chip but           is simpler to do it anyway. */	writereg(dev, PP_LineCTL, lp->linectl &~ AUI_ONLY);        /* Delay for the hardware to work out if the TP cable is present - 150ms */	for (timenow = jiffies; jiffies - timenow < 15; )                ;	if ((readreg(dev, PP_LineST) & LINK_OK) == 0)		return 0;	return A_CNF_MEDIA_10B_T;}/* send a test packet - return true if carrier bits are ok */intsend_test_pkt(struct device *dev){	int ioaddr = dev->base_addr;	char test_packet[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,				 0, 46, /* A 46 in network order */				 0, 0, /* DSAP=0 & SSAP=0 fields */				 0xf3, 0 /* Control (Test Req + P bit set) */ };	long timenow = jiffies;	unsigned short event;	writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_TX_ON);	memcpy(test_packet,          dev->dev_addr, ETH_ALEN);	memcpy(test_packet+ETH_ALEN, dev->dev_addr, ETH_ALEN);        outw(TX_AFTER_ALL, ioaddr + TX_CMD_PORT);        outw(ETH_ZLEN, ioaddr + TX_LEN_PORT);	/* Test to see if the chip has allocated memory for the packet */	while (jiffies - timenow < 5)		if (readreg(dev, PP_BusST) & READY_FOR_TX_NOW)			break;	if (jiffies - timenow >= 5)		return 0;	/* this shouldn't happen */	/* Write the contents of the packet */	outsw(ioaddr + TX_FRAME_PORT,test_packet,(ETH_ZLEN+1) >>1);	if (net_debug > 1) printk("Sending test packet ");	/* wait a couple of jiffies for packet to be received */	for (timenow = jiffies; jiffies - timenow < 60; )                ;        if (((event = readreg(dev, PP_TxEvent)) & TX_SEND_OK_BITS) == TX_OK) {                if (net_debug > 1) printk("succeeded\n");                return 1;        }	if (net_debug > 1) printk("failed TxEvent 0x%.4x\n",event);	return 0;}voidwrite_irq(struct device *dev, int chip_type, int irq){  /* we only hooked up 0 :-) */	writereg(dev, PP_CS8900_ISAINT, 0);}/* Open/initialize the board.  This is called (in the current kernel)   sometime after booting when the 'ifconfig' program is run.   This routine should set everything up anew at each open, even   registers that "should" only need to be set once at boot, so that   there is non-reboot way to recover if something goes wrong.   */static struct irqaction irq_cs8900 = { cs8900_interrupt, 0, 0, "cs8900A", NULL, NULL};extern int setup_arm_irq(int, struct irqaction *);static intnet_open(struct device *dev){	struct net_local *lp = (struct net_local *)dev->priv;	int result = 0;	write_irq(dev, lp->chip_type, 0);	irq2dev_map[/* FIXME */ 0] = dev;

⌨️ 快捷键说明

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