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

📄 via-velocity.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		list_del(&vptr->list);	spin_unlock_irqrestore(&velocity_dev_list_lock, flags);#endif	unregister_netdev(dev);	iounmap(vptr->mac_regs);	pci_release_regions(pdev);	pci_disable_device(pdev);	pci_set_drvdata(pdev, NULL);	free_netdev(dev);	velocity_nics--;}/** *	velocity_set_int_opt	-	parser for integer options *	@opt: pointer to option value *	@val: value the user requested (or -1 for default) *	@min: lowest value allowed *	@max: highest value allowed *	@def: default value *	@name: property name *	@dev: device name * *	Set an integer property in the module options. This function does *	all the verification and checking as well as reporting so that *	we don't duplicate code for each option. */static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, char *devname){	if (val == -1)		*opt = def;	else if (val < min || val > max) {		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n",					devname, name, min, max);		*opt = def;	} else {		VELOCITY_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n",					devname, name, val);		*opt = val;	}}/** *	velocity_set_bool_opt	-	parser for boolean options *	@opt: pointer to option value *	@val: value the user requested (or -1 for default) *	@def: default value (yes/no) *	@flag: numeric value to set for true. *	@name: property name *	@dev: device name * *	Set a boolean property in the module options. This function does *	all the verification and checking as well as reporting so that *	we don't duplicate code for each option. */static void __devinit velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag, char *name, char *devname){	(*opt) &= (~flag);	if (val == -1)		*opt |= (def ? flag : 0);	else if (val < 0 || val > 1) {		printk(KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",			devname, name);		*opt |= (def ? flag : 0);	} else {		printk(KERN_INFO "%s: set parameter %s to %s\n",			devname, name, val ? "TRUE" : "FALSE");		*opt |= (val ? flag : 0);	}}/** *	velocity_get_options	-	set options on device *	@opts: option structure for the device *	@index: index of option to use in module options array *	@devname: device name * *	Turn the module and command options into a single structure *	for the current device */static void __devinit velocity_get_options(struct velocity_opt *opts, int index, char *devname){	velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname);	velocity_set_int_opt(&opts->DMA_length, DMA_length[index], DMA_LENGTH_MIN, DMA_LENGTH_MAX, DMA_LENGTH_DEF, "DMA_length", devname);	velocity_set_int_opt(&opts->numrx, RxDescriptors[index], RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, "RxDescriptors", devname);	velocity_set_int_opt(&opts->numtx, TxDescriptors[index], TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, "TxDescriptors", devname);	velocity_set_bool_opt(&opts->flags, txcsum_offload[index], TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM, "txcsum_offload", devname);	velocity_set_int_opt(&opts->flow_cntl, flow_control[index], FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control", devname);	velocity_set_bool_opt(&opts->flags, IP_byte_align[index], IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN, "IP_byte_align", devname);	velocity_set_bool_opt(&opts->flags, ValPktLen[index], VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN, "ValPktLen", devname);	velocity_set_int_opt((int *) &opts->spd_dpx, speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF, "Media link mode", devname);	velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index], WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF, "Wake On Lan options", devname);	velocity_set_int_opt((int *) &opts->int_works, int_works[index], INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF, "Interrupt service works", devname);	opts->numrx = (opts->numrx & ~3);}/** *	velocity_init_cam_filter	-	initialise CAM *	@vptr: velocity to program * *	Initialize the content addressable memory used for filters. Load *	appropriately according to the presence of VLAN */static void velocity_init_cam_filter(struct velocity_info *vptr){	struct mac_regs __iomem * regs = vptr->mac_regs;	unsigned short vid;	/* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */	WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);	WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);	/* Disable all CAMs */	memset(vptr->vCAMmask, 0, sizeof(u8) * 8);	memset(vptr->mCAMmask, 0, sizeof(u8) * 8);	mac_set_vlan_cam_mask(regs, vptr->vCAMmask);	mac_set_cam_mask(regs, vptr->mCAMmask);	/* Enable first VCAM */	if (vptr->vlgrp) {		for (vid = 0; vid < VLAN_VID_MASK; vid++) {			if (vlan_group_get_device(vptr->vlgrp, vid)) {				/* If Tagging option is enabled and				   VLAN ID is not zero, then				   turn on MCFG_RTGOPT also */				if (vid != 0)					WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);				mac_set_vlan_cam(regs, 0, (u8 *) &vid);			}		}		vptr->vCAMmask[0] |= 1;		mac_set_vlan_cam_mask(regs, vptr->vCAMmask);	} else {		u16 temp = 0;		mac_set_vlan_cam(regs, 0, (u8 *) &temp);		temp = 1;		mac_set_vlan_cam_mask(regs, (u8 *) &temp);	}}static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid){	struct velocity_info *vptr = netdev_priv(dev);        spin_lock_irq(&vptr->lock);	velocity_init_cam_filter(vptr);        spin_unlock_irq(&vptr->lock);}static void velocity_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid){	struct velocity_info *vptr = netdev_priv(dev);        spin_lock_irq(&vptr->lock);	vlan_group_set_device(vptr->vlgrp, vid, NULL);	velocity_init_cam_filter(vptr);        spin_unlock_irq(&vptr->lock);}/** *	velocity_rx_reset	-	handle a receive reset *	@vptr: velocity we are resetting * *	Reset the ownership and status for the receive ring side. *	Hand all the receive queue to the NIC. */static void velocity_rx_reset(struct velocity_info *vptr){	struct mac_regs __iomem * regs = vptr->mac_regs;	int i;	vptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0;	/*	 *	Init state, all RD entries belong to the NIC	 */	for (i = 0; i < vptr->options.numrx; ++i)		vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC;	writew(vptr->options.numrx, &regs->RBRDU);	writel(vptr->rd_pool_dma, &regs->RDBaseLo);	writew(0, &regs->RDIdx);	writew(vptr->options.numrx - 1, &regs->RDCSize);}/** *	velocity_init_registers	-	initialise MAC registers *	@vptr: velocity to init *	@type: type of initialisation (hot or cold) * *	Initialise the MAC on a reset or on first set up on the *	hardware. */static void velocity_init_registers(struct velocity_info *vptr,				    enum velocity_init_type type){	struct mac_regs __iomem * regs = vptr->mac_regs;	int i, mii_status;	mac_wol_reset(regs);	switch (type) {	case VELOCITY_INIT_RESET:	case VELOCITY_INIT_WOL:		netif_stop_queue(vptr->dev);		/*		 *	Reset RX to prevent RX pointer not on the 4X location		 */		velocity_rx_reset(vptr);		mac_rx_queue_run(regs);		mac_rx_queue_wake(regs);		mii_status = velocity_get_opt_media_mode(vptr);		if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {			velocity_print_link_status(vptr);			if (!(vptr->mii_status & VELOCITY_LINK_FAIL))				netif_wake_queue(vptr->dev);		}		enable_flow_control_ability(vptr);		mac_clear_isr(regs);		writel(CR0_STOP, &regs->CR0Clr);		writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT),							&regs->CR0Set);		break;	case VELOCITY_INIT_COLD:	default:		/*		 *	Do reset		 */		velocity_soft_reset(vptr);		mdelay(5);		mac_eeprom_reload(regs);		for (i = 0; i < 6; i++) {			writeb(vptr->dev->dev_addr[i], &(regs->PAR[i]));		}		/*		 *	clear Pre_ACPI bit.		 */		BYTE_REG_BITS_OFF(CFGA_PACPI, &(regs->CFGA));		mac_set_rx_thresh(regs, vptr->options.rx_thresh);		mac_set_dma_length(regs, vptr->options.DMA_length);		writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);		/*		 *	Back off algorithm use original IEEE standard		 */		BYTE_REG_BITS_SET(CFGB_OFSET, (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA | CFGB_BAKOPT), &regs->CFGB);		/*		 *	Init CAM filter		 */		velocity_init_cam_filter(vptr);		/*		 *	Set packet filter: Receive directed and broadcast address		 */		velocity_set_multi(vptr->dev);		/*		 *	Enable MII auto-polling		 */		enable_mii_autopoll(regs);		vptr->int_mask = INT_MASK_DEF;		writel(cpu_to_le32(vptr->rd_pool_dma), &regs->RDBaseLo);		writew(vptr->options.numrx - 1, &regs->RDCSize);		mac_rx_queue_run(regs);		mac_rx_queue_wake(regs);		writew(vptr->options.numtx - 1, &regs->TDCSize);		for (i = 0; i < vptr->num_txq; i++) {			writel(cpu_to_le32(vptr->td_pool_dma[i]), &(regs->TDBaseLo[i]));			mac_tx_queue_run(regs, i);		}		init_flow_control_register(vptr);		writel(CR0_STOP, &regs->CR0Clr);		writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), &regs->CR0Set);		mii_status = velocity_get_opt_media_mode(vptr);		netif_stop_queue(vptr->dev);		mii_init(vptr, mii_status);		if (velocity_set_media_mode(vptr, mii_status) != VELOCITY_LINK_CHANGE) {			velocity_print_link_status(vptr);			if (!(vptr->mii_status & VELOCITY_LINK_FAIL))				netif_wake_queue(vptr->dev);		}		enable_flow_control_ability(vptr);		mac_hw_mibs_init(regs);		mac_write_int_mask(vptr->int_mask, regs);		mac_clear_isr(regs);	}}/** *	velocity_soft_reset	-	soft reset *	@vptr: velocity to reset * *	Kick off a soft reset of the velocity adapter and then poll *	until the reset sequence has completed before returning. */static int velocity_soft_reset(struct velocity_info *vptr){	struct mac_regs __iomem * regs = vptr->mac_regs;	int i = 0;	writel(CR0_SFRST, &regs->CR0Set);	for (i = 0; i < W_MAX_TIMEOUT; i++) {		udelay(5);		if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, &regs->CR0Set))			break;	}	if (i == W_MAX_TIMEOUT) {		writel(CR0_FORSRST, &regs->CR0Set);		/* FIXME: PCI POSTING */		/* delay 2ms */		mdelay(2);	}	return 0;}/** *	velocity_found1		-	set up discovered velocity card *	@pdev: PCI device *	@ent: PCI device table entry that matched * *	Configure a discovered adapter from scratch. Return a negative *	errno error code on failure paths. */static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent){	static int first = 1;	struct net_device *dev;	int i;	const struct velocity_info_tbl *info = &chip_info_table[ent->driver_data];	struct velocity_info *vptr;	struct mac_regs __iomem * regs;	int ret = -ENOMEM;	/* FIXME: this driver, like almost all other ethernet drivers,	 * can support more than MAX_UNITS.	 */	if (velocity_nics >= MAX_UNITS) {		dev_notice(&pdev->dev, "already found %d NICs.\n",			   velocity_nics);		return -ENODEV;	}	dev = alloc_etherdev(sizeof(struct velocity_info));	if (!dev) {		dev_err(&pdev->dev, "allocate net device failed.\n");		goto out;	}	/* Chain it all together */	SET_NETDEV_DEV(dev, &pdev->dev);	vptr = netdev_priv(dev);	if (first) {		printk(KERN_INFO "%s Ver. %s\n",			VELOCITY_FULL_DRV_NAM, VELOCITY_VERSION);		printk(KERN_INFO "Copyright (c) 2002, 2003 VIA Networking Technologies, Inc.\n");		printk(KERN_INFO "Copyright (c) 2004 Red Hat Inc.\n");		first = 0;	}	velocity_init_info(pdev, vptr, info);	vptr->dev = dev;	dev->irq = pdev->irq;	ret = pci_enable_device(pdev);	if (ret < 0)		goto err_free_dev;	ret = velocity_get_pci_info(vptr, pdev);	if (ret < 0) {		/* error message already printed */		goto err_disable;	}	ret = pci_request_regions(pdev, VELOCITY_NAME);	if (ret < 0) {		dev_err(&pdev->dev, "No PCI resources.\n");		goto err_disable;	}	regs = ioremap(vptr->memaddr, VELOCITY_IO_SIZE);	if (regs == NULL) {		ret = -EIO;		goto err_release_res;	}	vptr->mac_regs = regs;	mac_wol_reset(regs);	dev->base_addr = vptr->ioaddr;	for (i = 0; i < 6; i++)		dev->dev_addr[i] = readb(&regs->PAR[i]);	velocity_get_options(&vptr->options, velocity_nics, dev->name);	/*	 *	Mask out the options cannot be set to the chip	 */	vptr->options.flags &= info->flags;	/*	 *	Enable the chip specified capbilities	 */	vptr->flags = vptr->options.flags | (info->flags & 0xFF000000UL);	vptr->wol_opts = vptr->options.wol_opts;	vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;	vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);	dev->irq = pdev->irq;	dev->open = velocity_open;	dev->hard_start_xmit = velocity_xmit;	dev->stop = velocity_close;	dev->get_stats = velocity_get_stats;	dev->set_multicast_list = velocity_set_multi;	dev->do_ioctl = velocity_ioctl;	dev->ethtool_ops = &velocity_ethtool_ops;	dev->change_mtu = velocity_change_mtu;	dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid;	dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid;#ifdef  VELOCITY_ZERO_COPY_SUPPORT	dev->features |= NETIF_F_SG;#endif	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER;	if (vptr->flags & VELOCITY_FLAGS_TX_CSUM)		dev->features |= NETIF_F_IP_CSUM;	ret = register_netdev(dev);	if (ret < 0)		goto err_iounmap;	if (velocity_get_link(dev))		netif_carrier_off(dev);	velocity_print_info(vptr);	pci_set_drvdata(pdev, dev);	/* and leave the chip powered down */	pci_set_power_state(pdev, PCI_D3hot);#ifdef CONFIG_PM	{		unsigned long flags;		spin_lock_irqsave(&velocity_dev_list_lock, flags);		list_add(&vptr->list, &velocity_dev_list);		spin_unlock_irqrestore(&velocity_dev_list_lock, flags);	}

⌨️ 快捷键说明

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