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

📄 islpci_dev.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	DEFINE_WAIT(wait);	prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE);	/* now the last step is to reset the interface */	isl38xx_interface_reset(priv->device_base, priv->device_host_address);	islpci_set_state(priv, PRV_STATE_PREINIT);        for(count = 0; count < 2 && result; count++) {		/* The software reset acknowledge needs about 220 msec here.		 * Be conservative and wait for up to one second. */		remaining = schedule_timeout_uninterruptible(HZ);		if(remaining > 0) {			result = 0;			break;		}		/* If we're here it's because our IRQ hasn't yet gone through.		 * Retry a bit more...		 */		printk(KERN_ERR "%s: no 'reset complete' IRQ seen - retrying\n",			priv->ndev->name);	}	finish_wait(&priv->reset_done, &wait);	if (result) {		printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name);		return result;	}	islpci_set_state(priv, PRV_STATE_INIT);	/* Now that the device is 100% up, let's allow	 * for the other interrupts --	 * NOTE: this is not *yet* true since we've only allowed the	 * INIT interrupt on the IRQ line. We can perhaps poll	 * the IRQ line until we know for sure the reset went through */	isl38xx_enable_common_interrupts(priv->device_base);	down_write(&priv->mib_sem);	result = mgt_commit(priv);	if (result) {		printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name);		up_write(&priv->mib_sem);		return result;	}	up_write(&priv->mib_sem);	islpci_set_state(priv, PRV_STATE_READY);	printk(KERN_DEBUG "%s: interface reset complete\n", priv->ndev->name);	return 0;}intislpci_reset(islpci_private *priv, int reload_firmware){	isl38xx_control_block *cb =    /* volatile not needed */		(isl38xx_control_block *) priv->control_block;	unsigned counter;	int rc;	if (reload_firmware)		islpci_set_state(priv, PRV_STATE_PREBOOT);	else		islpci_set_state(priv, PRV_STATE_POSTBOOT);	printk(KERN_DEBUG "%s: resetting device...\n", priv->ndev->name);	/* disable all device interrupts in case they weren't */	isl38xx_disable_interrupts(priv->device_base);	/* flush all management queues */	priv->index_mgmt_tx = 0;	priv->index_mgmt_rx = 0;	/* clear the indexes in the frame pointer */	for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) {		cb->driver_curr_frag[counter] = cpu_to_le32(0);		cb->device_curr_frag[counter] = cpu_to_le32(0);	}	/* reset the mgmt receive queue */	for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) {		isl38xx_fragment *frag = &cb->rx_data_mgmt[counter];		frag->size = cpu_to_le16(MGMT_FRAME_SIZE);		frag->flags = 0;		frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr);	}	for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) {		cb->rx_data_low[counter].address =		    cpu_to_le32((u32) priv->pci_map_rx_address[counter]);	}	/* since the receive queues are filled with empty fragments, now we can	 * set the corresponding indexes in the Control Block */	priv->control_block->driver_curr_frag[ISL38XX_CB_RX_DATA_LQ] =	    cpu_to_le32(ISL38XX_CB_RX_QSIZE);	priv->control_block->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] =	    cpu_to_le32(ISL38XX_CB_MGMT_QSIZE);	/* reset the remaining real index registers and full flags */	priv->free_data_rx = 0;	priv->free_data_tx = 0;	priv->data_low_tx_full = 0;	if (reload_firmware) { /* Should we load the firmware ? */	/* now that the data structures are cleaned up, upload	 * firmware and reset interface */		rc = islpci_upload_fw(priv);		if (rc) {			printk(KERN_ERR "%s: islpci_reset: failure\n",				priv->ndev->name);			return rc;		}	}	/* finally reset interface */	rc = islpci_reset_if(priv);	if (rc)		printk(KERN_ERR "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n");	return rc;}static struct net_device_stats *islpci_statistics(struct net_device *ndev){	islpci_private *priv = netdev_priv(ndev);#if VERBOSE > SHOW_ERROR_MESSAGES	DEBUG(SHOW_FUNCTION_CALLS, "islpci_statistics\n");#endif	return &priv->statistics;}/******************************************************************************    Network device configuration functions******************************************************************************/static intislpci_alloc_memory(islpci_private *priv){	int counter;#if VERBOSE > SHOW_ERROR_MESSAGES	printk(KERN_DEBUG "islpci_alloc_memory\n");#endif	/* remap the PCI device base address to accessable */	if (!(priv->device_base =	      ioremap(pci_resource_start(priv->pdev, 0),		      ISL38XX_PCI_MEM_SIZE))) {		/* error in remapping the PCI device memory address range */		printk(KERN_ERR "PCI memory remapping failed \n");		return -1;	}	/* memory layout for consistent DMA region:	 *	 * Area 1: Control Block for the device interface	 * Area 2: Power Save Mode Buffer for temporary frame storage. Be aware that	 *         the number of supported stations in the AP determines the minimal	 *         size of the buffer !	 */	/* perform the allocation */	priv->driver_mem_address = pci_alloc_consistent(priv->pdev,							HOST_MEM_BLOCK,							&priv->							device_host_address);	if (!priv->driver_mem_address) {		/* error allocating the block of PCI memory */		printk(KERN_ERR "%s: could not allocate DMA memory, aborting!",		       "prism54");		return -1;	}	/* assign the Control Block to the first address of the allocated area */	priv->control_block =	    (isl38xx_control_block *) priv->driver_mem_address;	/* set the Power Save Buffer pointer directly behind the CB */	priv->device_psm_buffer =		priv->device_host_address + CONTROL_BLOCK_SIZE;	/* make sure all buffer pointers are initialized */	for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) {		priv->control_block->driver_curr_frag[counter] = cpu_to_le32(0);		priv->control_block->device_curr_frag[counter] = cpu_to_le32(0);	}	priv->index_mgmt_rx = 0;	memset(priv->mgmt_rx, 0, sizeof(priv->mgmt_rx));	memset(priv->mgmt_tx, 0, sizeof(priv->mgmt_tx));	/* allocate rx queue for management frames */	if (islpci_mgmt_rx_fill(priv->ndev) < 0)		goto out_free;	/* now get the data rx skb's */	memset(priv->data_low_rx, 0, sizeof (priv->data_low_rx));	memset(priv->pci_map_rx_address, 0, sizeof (priv->pci_map_rx_address));	for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) {		struct sk_buff *skb;		/* allocate an sk_buff for received data frames storage		 * each frame on receive size consists of 1 fragment		 * include any required allignment operations */		if (!(skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2))) {			/* error allocating an sk_buff structure elements */			printk(KERN_ERR "Error allocating skb.\n");			skb = NULL;			goto out_free;		}		skb_reserve(skb, (4 - (long) skb->data) & 0x03);		/* add the new allocated sk_buff to the buffer array */		priv->data_low_rx[counter] = skb;		/* map the allocated skb data area to pci */		priv->pci_map_rx_address[counter] =		    pci_map_single(priv->pdev, (void *) skb->data,				   MAX_FRAGMENT_SIZE_RX + 2,				   PCI_DMA_FROMDEVICE);		if (!priv->pci_map_rx_address[counter]) {			/* error mapping the buffer to device			   accessable memory address */			printk(KERN_ERR "failed to map skb DMA'able\n");			goto out_free;		}	}	prism54_acl_init(&priv->acl);	prism54_wpa_bss_ie_init(priv);	if (mgt_init(priv))		goto out_free;	return 0; out_free:	islpci_free_memory(priv);	return -1;}intislpci_free_memory(islpci_private *priv){	int counter;	if (priv->device_base)		iounmap(priv->device_base);	priv->device_base = NULL;	/* free consistent DMA area... */	if (priv->driver_mem_address)		pci_free_consistent(priv->pdev, HOST_MEM_BLOCK,				    priv->driver_mem_address,				    priv->device_host_address);	/* clear some dangling pointers */	priv->driver_mem_address = NULL;	priv->device_host_address = 0;	priv->device_psm_buffer = 0;	priv->control_block = NULL;        /* clean up mgmt rx buffers */        for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) {		struct islpci_membuf *buf = &priv->mgmt_rx[counter];		if (buf->pci_addr)			pci_unmap_single(priv->pdev, buf->pci_addr,					 buf->size, PCI_DMA_FROMDEVICE);		buf->pci_addr = 0;		kfree(buf->mem);		buf->size = 0;		buf->mem = NULL;        }	/* clean up data rx buffers */	for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) {		if (priv->pci_map_rx_address[counter])			pci_unmap_single(priv->pdev,					 priv->pci_map_rx_address[counter],					 MAX_FRAGMENT_SIZE_RX + 2,					 PCI_DMA_FROMDEVICE);		priv->pci_map_rx_address[counter] = 0;		if (priv->data_low_rx[counter])			dev_kfree_skb(priv->data_low_rx[counter]);		priv->data_low_rx[counter] = NULL;	}	/* Free the acces control list and the WPA list */	prism54_acl_clean(&priv->acl);	prism54_wpa_bss_ie_clean(priv);	mgt_clean(priv);	return 0;}#if 0static voidislpci_set_multicast_list(struct net_device *dev){	/* put device into promisc mode and let network layer handle it */}#endifstatic void islpci_ethtool_get_drvinfo(struct net_device *dev,                                       struct ethtool_drvinfo *info){	strcpy(info->driver, DRV_NAME);	strcpy(info->version, DRV_VERSION);}static struct ethtool_ops islpci_ethtool_ops = {	.get_drvinfo = islpci_ethtool_get_drvinfo,};struct net_device *islpci_setup(struct pci_dev *pdev){	islpci_private *priv;	struct net_device *ndev = alloc_etherdev(sizeof (islpci_private));	if (!ndev)		return ndev;	pci_set_drvdata(pdev, ndev);#if defined(SET_NETDEV_DEV)	SET_NETDEV_DEV(ndev, &pdev->dev);#endif	/* setup the structure members */	ndev->base_addr = pci_resource_start(pdev, 0);	ndev->irq = pdev->irq;	/* initialize the function pointers */	ndev->open = &islpci_open;	ndev->stop = &islpci_close;	ndev->get_stats = &islpci_statistics;	ndev->do_ioctl = &prism54_ioctl;	ndev->wireless_handlers =	    (struct iw_handler_def *) &prism54_handler_def;	ndev->ethtool_ops = &islpci_ethtool_ops;	ndev->hard_start_xmit = &islpci_eth_transmit;	/* ndev->set_multicast_list = &islpci_set_multicast_list; */	ndev->addr_len = ETH_ALEN;	ndev->set_mac_address = &prism54_set_mac_address;	/* Get a non-zero dummy MAC address for nameif. Jean II */	memcpy(ndev->dev_addr, dummy_mac, 6);#ifdef HAVE_TX_TIMEOUT	ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT;	ndev->tx_timeout = &islpci_eth_tx_timeout;#endif	/* allocate a private device structure to the network device  */	priv = netdev_priv(ndev);	priv->ndev = ndev;	priv->pdev = pdev;	priv->monitor_type = ARPHRD_IEEE80211;	priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ?		priv->monitor_type : ARPHRD_ETHER;	/* Add pointers to enable iwspy support. */	priv->wireless_data.spy_data = &priv->spy_data;	ndev->wireless_data = &priv->wireless_data;	/* save the start and end address of the PCI memory area */	ndev->mem_start = (unsigned long) priv->device_base;	ndev->mem_end = ndev->mem_start + ISL38XX_PCI_MEM_SIZE;#if VERBOSE > SHOW_ERROR_MESSAGES	DEBUG(SHOW_TRACING, "PCI Memory remapped to 0x%p\n", priv->device_base);#endif	init_waitqueue_head(&priv->reset_done);	/* init the queue read locks, process wait counter */	sema_init(&priv->mgmt_sem, 1);	priv->mgmt_received = NULL;	init_waitqueue_head(&priv->mgmt_wqueue);	sema_init(&priv->stats_sem, 1);	spin_lock_init(&priv->slock);	/* init state machine with off#1 state */	priv->state = PRV_STATE_OFF;	priv->state_off = 1;	/* initialize workqueue's */	INIT_WORK(&priv->stats_work, prism54_update_stats);	priv->stats_timestamp = 0;	INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake);	priv->reset_task_pending = 0;	/* allocate various memory areas */	if (islpci_alloc_memory(priv))		goto do_free_netdev;	/* select the firmware file depending on the device id */	switch (pdev->device) {	case 0x3877:		strcpy(priv->firmware, ISL3877_IMAGE_FILE);		break;	case 0x3886:		strcpy(priv->firmware, ISL3886_IMAGE_FILE);		break;	default:		strcpy(priv->firmware, ISL3890_IMAGE_FILE);		break;	}	if (register_netdev(ndev)) {		DEBUG(SHOW_ERROR_MESSAGES,		      "ERROR: register_netdev() failed \n");		goto do_islpci_free_memory;	}	return ndev;      do_islpci_free_memory:	islpci_free_memory(priv);      do_free_netdev:	pci_set_drvdata(pdev, NULL);	free_netdev(ndev);	priv = NULL;	return NULL;}islpci_state_tislpci_set_state(islpci_private *priv, islpci_state_t new_state){	islpci_state_t old_state;	/* lock */	old_state = priv->state;	/* this means either a race condition or some serious error in	 * the driver code */	switch (new_state) {	case PRV_STATE_OFF:		priv->state_off++;	default:		priv->state = new_state;		break;	case PRV_STATE_PREBOOT:		/* there are actually many off-states, enumerated by		 * state_off */		if (old_state == PRV_STATE_OFF)			priv->state_off--;		/* only if hw_unavailable is zero now it means we either		 * were in off#1 state, or came here from		 * somewhere else */		if (!priv->state_off)			priv->state = new_state;		break;	};#if 0	printk(KERN_DEBUG "%s: state transition %d -> %d (off#%d)\n",	       priv->ndev->name, old_state, new_state, priv->state_off);#endif	/* invariants */	BUG_ON(priv->state_off < 0);	BUG_ON(priv->state_off && (priv->state != PRV_STATE_OFF));	BUG_ON(!priv->state_off && (priv->state == PRV_STATE_OFF));	/* unlock */	return old_state;}

⌨️ 快捷键说明

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