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

📄 eepro100_cb.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/* How to wait for the command unit to accept a command.   Typically this takes 0 ticks. */static inline void wait_for_cmd_done(long cmd_ioaddr){	int wait = 1000;	do   ;	while(inb(cmd_ioaddr) && --wait >= 0);}/* Offsets to the various registers.   All accesses need not be longword aligned. */enum speedo_offsets {	SCBStatus = 0, SCBCmd = 2,	/* Rx/Command Unit command and status. */	SCBPointer = 4,				/* General purpose pointer. */	SCBPort = 8,				/* Misc. commands and operands.  */	SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */	SCBCtrlMDI = 16,			/* MDI interface control. */	SCBEarlyRx = 20,			/* Early receive byte count. */};/* Commands that can be put in a command list entry. */enum commands {	CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000,	CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000,	CmdDump = 0x60000, CmdDiagnose = 0x70000,	CmdSuspend = 0x40000000,	/* Suspend after completion. */	CmdIntr = 0x20000000,		/* Interrupt after completion. */	CmdTxFlex = 0x00080000,		/* Use "Flexible mode" for CmdTx command. */};/* Do atomically if possible. */#if defined(__i386__)#define clear_suspend(cmd)   ((char *)(&(cmd)->cmd_status))[3] &= ~0x40#elif defined(__alpha__)#define clear_suspend(cmd)   clear_bit(30, &(cmd)->cmd_status)#elif defined(__powerpc__) || defined(__sparc__) || (__BIG_ENDIAN)#define clear_suspend(cmd)	clear_bit(6, &(cmd)->cmd_status)#else#warning Undefined architecture.#define clear_suspend(cmd)	(cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)#endifenum SCBCmdBits {     SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,     SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,     SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,     /* The rest are Rx and Tx commands. */     CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,     CUCmdBase=0x0060,  /* CU Base address (set to zero) . */     CUDumpStats=0x0070, /* Dump then reset stats counters. */     RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,     RxResumeNoResources=0x0007,};enum SCBPort_cmds {	PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,};/* The Speedo3 Rx and Tx frame/buffer descriptors. */struct descriptor {			/* A generic descriptor. */	s32 cmd_status;			/* All command and status fields. */	u32 link;					/* struct descriptor *  */	unsigned char params[0];};/* The Speedo3 Rx and Tx buffer descriptors. */struct RxFD {					/* Receive frame descriptor. */	s32 status;	u32 link;					/* struct RxFD * */	u32 rx_buf_addr;			/* void * */	u32 count;};/* Selected elements of the Tx/RxFD.status word. */enum RxFD_bits {	RxComplete=0x8000, RxOK=0x2000,	RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,	RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,	TxUnderrun=0x1000,  StatusComplete=0x8000,};struct TxFD {					/* Transmit frame descriptor set. */	s32 status;	u32 link;					/* void * */	u32 tx_desc_addr;			/* Always points to the tx_buf_addr element. */	s32 count;					/* # of TBD (=1), Tx start thresh., etc. */	/* This constitutes two "TBD" entries -- we only use one. */	u32 tx_buf_addr0;			/* void *, frame to be transmitted.  */	s32 tx_buf_size0;			/* Length of Tx frame. */	u32 tx_buf_addr1;			/* void *, frame to be transmitted.  */	s32 tx_buf_size1;			/* Length of Tx frame. */};/* Elements of the dump_statistics block. This block must be lword aligned. */struct speedo_stats {	u32 tx_good_frames;	u32 tx_coll16_errs;	u32 tx_late_colls;	u32 tx_underruns;	u32 tx_lost_carrier;	u32 tx_deferred;	u32 tx_one_colls;	u32 tx_multi_colls;	u32 tx_total_colls;	u32 rx_good_frames;	u32 rx_crc_errs;	u32 rx_align_errs;	u32 rx_resource_errs;	u32 rx_overrun_errs;	u32 rx_colls_errs;	u32 rx_runt_errs;	u32 done_marker;};/* Do not change the position (alignment) of the first few elements!   The later elements are grouped for cache locality. */struct speedo_private {	struct TxFD	tx_ring[TX_RING_SIZE];	/* Commands (usually CmdTxPacket). */	struct RxFD *rx_ringp[RX_RING_SIZE];	/* Rx descriptor, used as ring. */	/* The addresses of a Tx/Rx-in-place packets/buffers. */	struct sk_buff* tx_skbuff[TX_RING_SIZE];	struct sk_buff* rx_skbuff[RX_RING_SIZE];	struct descriptor  *last_cmd;	/* Last command sent. */	unsigned int cur_tx, dirty_tx;	/* The ring entries to be free()ed. */	spinlock_t lock;				/* Group with Tx control cache line. */	u32 tx_threshold;					/* The value for txdesc.count. */	unsigned long last_cmd_time;	struct RxFD *last_rxf;	/* Last command sent. */	unsigned int cur_rx, dirty_rx;		/* The next free ring entry */	long last_rx_time;			/* Last Rx, in jiffies, to handle Rx hang. */	const char *product_name;	struct net_device *next_module;	void *priv_addr;					/* Unaligned address for kfree */	struct net_device_stats stats;	struct speedo_stats lstats;	int chip_id;	struct pci_dev *pci_dev;	unsigned char acpi_pwr;	struct timer_list timer;	/* Media selection timer. */	int mc_setup_frm_len;			 	/* The length of an allocated.. */	struct descriptor *mc_setup_frm; 	/* ..multicast setup frame. */	int mc_setup_busy;					/* Avoid double-use of setup frame. */	char rx_mode;						/* Current PROMISC/ALLMULTI setting. */	unsigned int tx_full:1;				/* The Tx queue is full. */	unsigned int full_duplex:1;			/* Full-duplex operation requested. */	unsigned int flow_ctrl:1;			/* Use 802.3x flow control. */	unsigned int rx_bug:1;				/* Work around receiver hang errata. */	unsigned int rx_bug10:1;			/* Receiver might hang at 10mbps. */	unsigned int rx_bug100:1;			/* Receiver might hang at 100mbps. */	unsigned char default_port:8;		/* Last dev->if_port value. */	unsigned short phy[2];				/* PHY media interfaces available. */	unsigned short advertising;			/* Current PHY advertised caps. */	unsigned short partner;				/* Link partner caps. */	long last_reset;};/* The parameters for a CmdConfigure operation.   There are so many options that it would be difficult to document each bit.   We mostly use the default or recommended settings. */const char i82557_config_cmd[22] = {	22, 0x08, 0, 0,  0, 0, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */	0, 0x2E, 0,  0x60, 0,	0xf2, 0x48,   0, 0x40, 0xf2, 0x80, 		/* 0x40=Force full-duplex */	0x3f, 0x05, };const char i82558_config_cmd[22] = {	22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */	0, 0x2E, 0,  0x60, 0x08, 0x88,	0x68, 0, 0x40, 0xf2, 0xBD, 		/* 0xBD->0xFD=Force full-duplex */	0x31, 0x05, };/* PHY media interface chips. */static const char *phys[] = {	"None", "i82553-A/B", "i82553-C", "i82503",	"DP83840", "80c240", "80c24", "i82555",	"unknown-8", "unknown-9", "DP83840A", "unknown-11",	"unknown-12", "unknown-13", "unknown-14", "unknown-15", };enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,					 S80C24, I82555, DP83840A=10, };static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };#define EE_READ_CMD		(6)static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);static int mdio_read(long ioaddr, int phy_id, int location);static int mdio_write(long ioaddr, int phy_id, int location, int value);static int speedo_open(struct net_device *dev);static void speedo_resume(struct net_device *dev);static void speedo_timer(unsigned long data);static void speedo_init_rx_ring(struct net_device *dev);static void speedo_tx_timeout(struct net_device *dev);static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);static int speedo_rx(struct net_device *dev);static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int speedo_close(struct net_device *dev);static struct net_device_stats *speedo_get_stats(struct net_device *dev);static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static void set_rx_mode(struct net_device *dev);#ifdef honor_default_port/* Optional driver feature to allow forcing the transceiver setting.   Not recommended. */static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,						   0x2000, 0x2100, 0x0400, 0x3100};#endif/* A list of all installed Speedo devices, for removing the driver module. */static struct net_device *root_speedo_dev = NULL;#if ! defined(HAS_PCI_NETIF)const int min_pci_latency = 32;static int pci_drv_register(struct drv_id_info *drv_id, void *initial_device){	int pci_index, cards_found = 0;	unsigned char pci_bus, pci_device_fn;	struct pci_dev *pdev;	struct pci_id_info *pci_tbl = drv_id->pci_dev_tbl;	void *newdev;	if ( ! pcibios_present())		return -ENODEV;	for (pci_index = 0; pci_index < 0xff; pci_index++) {		u32 pci_id, subsys_id, pci_class_rev;		u16 pci_command, new_command;		int chip_idx, irq, pci_flags;		long pciaddr;		long ioaddr;		if (pcibios_find_class (drv_id->pci_class, pci_index,								&pci_bus, &pci_device_fn)			!= PCIBIOS_SUCCESSFUL)			break;		pcibios_read_config_dword(pci_bus, pci_device_fn,								  PCI_VENDOR_ID, &pci_id);		pcibios_read_config_dword(pci_bus, pci_device_fn,								  PCI_SUBSYSTEM_ID, &subsys_id);		pcibios_read_config_dword(pci_bus, pci_device_fn,								  PCI_REVISION_ID, &pci_class_rev);		for (chip_idx = 0; pci_tbl[chip_idx].name; chip_idx++) {			struct pci_id_info *chip = &pci_tbl[chip_idx];			if ((pci_id & chip->id.pci_mask) == chip->id.pci				&& (subsys_id & chip->id.subsystem_mask) == chip->id.subsystem				&& (pci_class_rev&chip->id.revision_mask) == chip->id.revision)				break;		}		if (pci_tbl[chip_idx].name == 0) 		/* Compiled out! */			continue;		pci_flags = pci_tbl[chip_idx].pci_flags;		pdev = pci_find_slot(pci_bus, pci_device_fn);#if LINUX_VERSION_CODE >= 0x020328		pciaddr = pdev->resource[0].start;		irq = pdev->irq;#elif LINUX_VERSION_CODE >= 0x20155		pciaddr = pdev->base_address[(pci_flags >> 4) & 7];		irq = pdev->irq;#else		{			u32 pci_busaddr;			u8 pci_irq_line;			pcibios_read_config_byte(pci_bus, pci_device_fn,									 PCI_INTERRUPT_LINE, &pci_irq_line);			pcibios_read_config_dword(pci_bus, pci_device_fn,									  ((pci_flags >> 2) & 0x1C) + 0x10,								  &pci_busaddr);			irq = pci_irq_line;			pciaddr = pci_busaddr;		}#endif		if (debug > 2)			printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n",				   pci_tbl[chip_idx].name, pciaddr, irq);		if ((pciaddr & PCI_BASE_ADDRESS_SPACE_IO)) {			ioaddr = pciaddr & PCI_BASE_ADDRESS_IO_MASK;			if (check_region(ioaddr, pci_tbl[chip_idx].io_size))				continue;		} else if ((ioaddr = (long)ioremap(pciaddr & PCI_BASE_ADDRESS_MEM_MASK,										   pci_tbl[chip_idx].io_size)) == 0) {			printk(KERN_INFO "Failed to map PCI address %#lx.\n",				   pciaddr);			continue;		}		pcibios_read_config_word(pci_bus, pci_device_fn,								 PCI_COMMAND, &pci_command);		new_command = pci_command | (pci_flags & 7);		if (pci_command != new_command) {			printk(KERN_INFO "  The PCI BIOS has not enabled the"				   " device at %d/%d!  Updating PCI command %4.4x->%4.4x.\n",				   pci_bus, pci_device_fn, pci_command, new_command);			pcibios_write_config_word(pci_bus, pci_device_fn,									  PCI_COMMAND, new_command);		}		newdev = drv_id->probe1(pdev, initial_device,							   ioaddr, irq, chip_idx, cards_found);		if (newdev  && (pci_flags & PCI_COMMAND_MASTER)) {			u8 pci_latency;			pcibios_read_config_byte(pci_bus, pci_device_fn,									 PCI_LATENCY_TIMER, &pci_latency);			if (pci_latency < min_pci_latency) {				printk(KERN_INFO "  PCI latency timer (CFLT) is "					   "unreasonably low at %d.  Setting to %d clocks.\n",					   pci_latency, min_pci_latency);				pcibios_write_config_byte(pci_bus, pci_device_fn,										  PCI_LATENCY_TIMER, min_pci_latency);			}		}		initial_device = 0;		cards_found++;	}	return cards_found ? 0 : -ENODEV;}#define pci_drv_unregister(drv_id)  do { } while(0)#endifstatic void *speedo_found1(struct pci_dev *pdev, void *init_dev,						   long ioaddr, int irq, int chip_idx, int card_idx){	struct net_device *dev;	struct speedo_private *sp;	const char *product;	int i, option;	u16 eeprom[0x100];	int acpi_idle_state = 0;	dev = init_etherdev(init_dev, sizeof(struct speedo_private));	if (dev->mem_start > 0)		option = dev->mem_start;	else if (card_idx >= 0  &&  options[card_idx] >= 0)		option = options[card_idx];	else		option = 0;	acpi_idle_state = acpi_set_pwr_state(pdev, ACPI_D0);	/* Read the station address EEPROM before doing the reset.	   Nominally his should even be done before accepting the device, but	   then we wouldn't have a device name with which to report the error.	   The size test is for 6 bit vs. 8 bit address serial EEPROMs.	*/	{		u16 sum = 0;		int j;		int read_cmd, ee_size;		if ((do_eeprom_cmd(ioaddr, EE_READ_CMD << 24, 27) & 0xffe0000)			== 0xffe0000) {			ee_size = 0x100;			read_cmd = EE_READ_CMD << 24;		} else {			ee_size = 0x40;			read_cmd = EE_READ_CMD << 22;		}		for (j = 0, i = 0; i < ee_size; i++) {			u16 value = do_eeprom_cmd(ioaddr, read_cmd | (i << 16), 27);			eeprom[i] = value;			sum += value;			if (i < 3) {				dev->dev_addr[j++] = value;				dev->dev_addr[j++] = value >> 8;			}		}		if (sum != 0xBABA)			printk(KERN_WARNING "%s: Invalid EEPROM checksum %#4.4x, "				   "check settings before activating this device!\n",				   dev->name, sum);		/* Don't  unregister_netdev(dev);  as the EEPro may actually be		   usable, especially if the MAC address is set later. */	}	/* Reset the chip: stop Tx and Rx processes and clear counters.	   This takes less than 10usec and will easily finish before the next	   action. */	outl(PortReset, ioaddr + SCBPort);	if (eeprom[3] & 0x0100)		product = "OEM i82557/i82558 10/100 Ethernet";	else

⌨️ 快捷键说明

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