示例#1
0
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;

	SET_MODULE_OWNER(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;
}
示例#2
0
struct net_device * islpci_probe(struct net_device *nwdev, struct pci_dev *pci_device, long ioaddr, int irq)
{
    unsigned char mac_addr[ETH_ALEN];
    long counter;
    queue_entry *pointerq;
    islpci_private *private_config;
    struct sk_buff *skb;
    
    if (nwdev == NULL)
    {
    	nwdev = init_etherdev(0,0);
    	if (nwdev == NULL)
    	    return NULL;
    }
    
    firmware_uploaded = 0;

    // setup the structure members
    nwdev->base_addr = ioaddr;
    nwdev->irq = irq;

    // initialize the function pointers
    nwdev->open = &islpci_open;
    nwdev->stop = &islpci_close;
    nwdev->get_stats = &islpci_statistics;
#ifdef WIRELESS_IOCTLS
    nwdev->do_ioctl = &isl_ioctl;
#endif

    nwdev->hard_start_xmit = &islpci_eth_transmit;

//    nwdev->set_multicast_list = &set_rx_mode;

#ifdef HAVE_TX_TIMEOUT
    nwdev->watchdog_timeo = ISLPCI_TX_TIMEOUT;
    nwdev->tx_timeout = &islpci_eth_tx_timeout;
#endif

    // FIXme
    mac_addr[0] = 0x01;
    mac_addr[1] = 0x01;
    mac_addr[2] = 0x01;
    mac_addr[3] = 0x01;
    mac_addr[4] = 0x01;
    mac_addr[5] = 0x01;
    mac_addr[6] = 0x01;
    mac_addr[7] = 0x01;
    memcpy(nwdev->dev_addr, mac_addr, ETH_ALEN);
    ether_setup(nwdev);
    
    // allocate a private device structure to the network device 
#ifdef CONFIG_ARCH_ISL3893
    if ( ( private_config = kmalloc(sizeof(islpci_private), GFP_KERNEL ) ) == NULL )
#else
    if ( ( private_config = kmalloc(sizeof(islpci_private), GFP_KERNEL | GFP_DMA ) ) == NULL )
#endif
    {
        // error allocating the DMA accessable memory area
        DEBUG(SHOW_ERROR_MESSAGES, "ERROR: Could not allocate additional "
            "memory \n");
        return NULL;
    }

    memset(private_config, 0, sizeof(islpci_private));
    nwdev->priv = private_config;
    private_config->next_module = root_islpci_device;
    root_islpci_device = nwdev;
    private_config->my_module = nwdev;
    private_config->pci_device = pci_device;

    // remap the PCI device base address to accessable
    if (private_config->remapped_device_base = ioremap(nwdev->base_addr, 
        ISL38XX_PCI_MEM_SIZE), private_config->remapped_device_base == NULL)
    {
        // error in remapping the PCI device memory address range
        DEBUG(SHOW_ERROR_MESSAGES, "ERROR: PCI memory remapping failed \n");
        return NULL;
    }
    
#ifdef CONFIG_ARCH_ISL3893
    // make sure the device is not running (anymore)
    writel(ISL38XX_DEV_INT_ABORT, private_config->remapped_device_base 
        + ISL38XX_DEV_INT_REG);
#endif

    // save the start and end address of the PCI memory area
    nwdev->mem_start = (unsigned long) private_config->remapped_device_base;
    nwdev->mem_end = nwdev->mem_start + ISL38XX_PCI_MEM_SIZE;

#if VERBOSE > SHOW_ERROR_MESSAGES 
    DEBUG(SHOW_TRACING, "PCI Memory remapped to 0x%p \n", 
        private_config->remapped_device_base );
#endif

    // initialize all the queues in the private configuration structure
    islpci_init_queue(&private_config->mgmt_tx_freeq);
    islpci_init_queue(&private_config->mgmt_rx_freeq);
    islpci_init_queue(&private_config->mgmt_tx_shadowq);
    islpci_init_queue(&private_config->mgmt_rx_shadowq);
    islpci_init_queue(&private_config->ioctl_rx_queue);
    islpci_init_queue(&private_config->trap_rx_queue);
    islpci_init_queue(&private_config->pimfor_rx_queue);
    
#ifdef WDS_LINKS
    private_config->wdsp = kmalloc(sizeof(struct wds_priv), GFP_KERNEL );
    memset(private_config->wdsp, 0, sizeof(struct wds_priv));
#endif    
    
    // allocate the consistent DMA memory depending on the mode    
    if( islpci_alloc_memory( private_config, ALLOC_MEMORY_MODE ))
        return NULL;
 
    // clear the indexes in the frame pointer
    for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++)
    {
        private_config->control_block->driver_curr_frag[counter] = cpu_to_le32(0);
        private_config->control_block->device_curr_frag[counter] = cpu_to_le32(0);
    }

    // Joho, ready setting up the queueing stuff, now fill the shadow rx queues
    // of both the management and data queues
    for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++)
    {
        // get an entry from the freeq and put it in the shadow queue
        if (islpci_get_queue(private_config->remapped_device_base, 
            &private_config->mgmt_rx_freeq, &pointerq))
        {
            // Oops, no more entries in the freeq ?
            DEBUG(SHOW_ERROR_MESSAGES, "Error: No more entries in freeq\n");
            return NULL;
        }
        else
        {
            // use the entry for the device interface management rx queue
            // these should always be inline !
            private_config->control_block->rx_data_mgmt[counter].address =
                cpu_to_le32(pointerq->dev_address);

            // put the entry got from the freeq in the shadow queue
            islpci_put_queue(private_config->remapped_device_base, 
                &private_config->mgmt_rx_shadowq, pointerq);
        }
    }

    for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++)
    {
        // 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+2), skb == NULL)
        {
            // error allocating an sk_buff structure elements
            DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n");
            return NULL;
        }

		// add the new allocated sk_buff to the buffer array
		private_config->data_low_rx[counter] = skb;

		// map the allocated skb data area to pci
        private_config->pci_map_rx_address[counter] = pci_map_single(
        	private_config->pci_device, (void *) skb->data, MAX_FRAGMENT_SIZE+2,
            PCI_DMA_FROMDEVICE );
        if( private_config->pci_map_rx_address[counter] == (dma_addr_t) NULL )
        {
            // error mapping the buffer to device accessable memory address
            DEBUG(SHOW_ERROR_MESSAGES, "Error mapping DMA address\n");
            return NULL;
        }

		// update the fragment address values in the contro block rx queue
        private_config->control_block->rx_data_low[counter].address = cpu_to_le32( (u32) 
		 	private_config->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
    private_config->control_block->driver_curr_frag[ISL38XX_CB_RX_DATA_LQ] =
        cpu_to_le32(ISL38XX_CB_RX_QSIZE);
    private_config->control_block->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] =
        cpu_to_le32(ISL38XX_CB_MGMT_QSIZE);

    // reset the real index registers and full flags
    private_config->index_mgmt_rx = 0;
	private_config->index_mgmt_tx = 0;
    private_config->free_data_rx = 0;
    private_config->free_data_tx = 0;
    private_config->data_low_tx_full = 0;

    // reset the queue read locks, process wait counter
    private_config->ioctl_queue_lock = 0;
    private_config->processes_in_wait = 0;

    // set the power save state
    private_config->powerstate = ISL38XX_PSM_ACTIVE_STATE;
    private_config->resetdevice = 0;

    return nwdev;
}