void
isl38xx_handle_sleep_request(isl38xx_control_block *control_block,
			     int *powerstate, void __iomem *device_base)
{
	/* device requests to go into sleep mode
	 * check whether the transmit queues for data and management are empty */
	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ))
		/* data tx queue not empty */
		return;

	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
		/* management tx queue not empty */
		return;

	/* check also whether received frames are pending */
	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ))
		/* data rx queue not empty */
		return;

	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ))
		/* management rx queue not empty */
		return;

#if VERBOSE > SHOW_ERROR_MESSAGES
	DEBUG(SHOW_TRACING, "Device going to sleep mode\n");
#endif

	/* all queues are empty, allow the device to go into sleep mode */
	*powerstate = ISL38XX_PSM_POWERSAVE_STATE;

	/* assert the Sleep interrupt in the Device Interrupt Register */
	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP,
			  ISL38XX_DEV_INT_REG);
	udelay(ISL38XX_WRITEIO_DELAY);
}
void
isl38xx_handle_sleep_request(isl38xx_control_block *control_block,
			     int *powerstate, void __iomem *device_base)
{
	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ))
		
		return;

	if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
		
		return;

	
	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ))
		
		return;

	if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ))
		
		return;

#if VERBOSE > SHOW_ERROR_MESSAGES
	DEBUG(SHOW_TRACING, "Device going to sleep mode\n");
#endif

	
	*powerstate = ISL38XX_PSM_POWERSAVE_STATE;

	
	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP,
			  ISL38XX_DEV_INT_REG);
	udelay(ISL38XX_WRITEIO_DELAY);
}
void
isl38xx_handle_wakeup(isl38xx_control_block *control_block,
		      int *powerstate, void __iomem *device_base)
{
	
	*powerstate = ISL38XX_PSM_ACTIVE_STATE;

	
	if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)
	    && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
		return;

#if VERBOSE > SHOW_ERROR_MESSAGES
	DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n");
#endif

	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
			  ISL38XX_DEV_INT_REG);
	udelay(ISL38XX_WRITEIO_DELAY);
}
void
isl38xx_handle_wakeup(isl38xx_control_block *control_block,
		      int *powerstate, void __iomem *device_base)
{
	/* device is in active state, update the powerstate flag */
	*powerstate = ISL38XX_PSM_ACTIVE_STATE;

	/* now check whether there are frames pending for the card */
	if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)
	    && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ))
		return;

#if VERBOSE > SHOW_ERROR_MESSAGES
	DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n");
#endif

	/* either data or management transmit queue has a frame pending
	 * trigger the device by setting the Update bit in the Device Int reg */
	isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE,
			  ISL38XX_DEV_INT_REG);
	udelay(ISL38XX_WRITEIO_DELAY);
}
Exemple #5
0
irqreturn_t
islpci_interrupt(int irq, void *config)
{
	u32 reg;
	islpci_private *priv = config;
	struct net_device *ndev = priv->ndev;
	void __iomem *device = priv->device_base;
	int powerstate = ISL38XX_PSM_POWERSAVE_STATE;

	/* lock the interrupt handler */
	spin_lock(&priv->slock);

	/* received an interrupt request on a shared IRQ line
	 * first check whether the device is in sleep mode */
	reg = readl(device + ISL38XX_CTRL_STAT_REG);
	if (reg & ISL38XX_CTRL_STAT_SLEEPMODE)
		/* device is in sleep mode, IRQ was generated by someone else */
	{
#if VERBOSE > SHOW_ERROR_MESSAGES
		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
#endif
		spin_unlock(&priv->slock);
		return IRQ_NONE;
	}


	/* check whether there is any source of interrupt on the device */
	reg = readl(device + ISL38XX_INT_IDENT_REG);

	/* also check the contents of the Interrupt Enable Register, because this
	 * will filter out interrupt sources from other devices on the same irq ! */
	reg &= readl(device + ISL38XX_INT_EN_REG);
	reg &= ISL38XX_INT_SOURCES;

	if (reg != 0) {
		if (islpci_get_state(priv) != PRV_STATE_SLEEP)
			powerstate = ISL38XX_PSM_ACTIVE_STATE;

		/* reset the request bits in the Identification register */
		isl38xx_w32_flush(device, reg, ISL38XX_INT_ACK_REG);

#if VERBOSE > SHOW_ERROR_MESSAGES
		DEBUG(SHOW_FUNCTION_CALLS,
		      "IRQ: Identification register 0x%p 0x%x \n", device, reg);
#endif

		/* check for each bit in the register separately */
		if (reg & ISL38XX_INT_IDENT_UPDATE) {
#if VERBOSE > SHOW_ERROR_MESSAGES
			/* Queue has been updated */
			DEBUG(SHOW_TRACING, "IRQ: Update flag \n");

			DEBUG(SHOW_QUEUE_INDEXES,
			      "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n",
			      le32_to_cpu(priv->control_block->
					  driver_curr_frag[0]),
			      le32_to_cpu(priv->control_block->
					  driver_curr_frag[1]),
			      le32_to_cpu(priv->control_block->
					  driver_curr_frag[2]),
			      le32_to_cpu(priv->control_block->
					  driver_curr_frag[3]),
			      le32_to_cpu(priv->control_block->
					  driver_curr_frag[4]),
			      le32_to_cpu(priv->control_block->
					  driver_curr_frag[5])
			    );

			DEBUG(SHOW_QUEUE_INDEXES,
			      "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n",
			      le32_to_cpu(priv->control_block->
					  device_curr_frag[0]),
			      le32_to_cpu(priv->control_block->
					  device_curr_frag[1]),
			      le32_to_cpu(priv->control_block->
					  device_curr_frag[2]),
			      le32_to_cpu(priv->control_block->
					  device_curr_frag[3]),
			      le32_to_cpu(priv->control_block->
					  device_curr_frag[4]),
			      le32_to_cpu(priv->control_block->
					  device_curr_frag[5])
			    );
#endif

			/* cleanup the data low transmit queue */
			islpci_eth_cleanup_transmit(priv, priv->control_block);

			/* device is in active state, update the
			 * powerstate flag if necessary */
			powerstate = ISL38XX_PSM_ACTIVE_STATE;

			/* check all three queues in priority order
			 * call the PIMFOR receive function until the
			 * queue is empty */
			if (isl38xx_in_queue(priv->control_block,
						ISL38XX_CB_RX_MGMTQ) != 0) {
#if VERBOSE > SHOW_ERROR_MESSAGES
				DEBUG(SHOW_TRACING,
				      "Received frame in Management Queue\n");
#endif
				islpci_mgt_receive(ndev);

				islpci_mgt_cleanup_transmit(ndev);

				/* Refill slots in receive queue */
				islpci_mgmt_rx_fill(ndev);

				/* no need to trigger the device, next
                                   islpci_mgt_transaction does it */
			}

			while (isl38xx_in_queue(priv->control_block,
						ISL38XX_CB_RX_DATA_LQ) != 0) {
#if VERBOSE > SHOW_ERROR_MESSAGES
				DEBUG(SHOW_TRACING,
				      "Received frame in Data Low Queue \n");
#endif
				islpci_eth_receive(priv);
			}

			/* check whether the data transmit queues were full */
			if (priv->data_low_tx_full) {
				/* check whether the transmit is not full anymore */
				if (ISL38XX_CB_TX_QSIZE -
				    isl38xx_in_queue(priv->control_block,
						     ISL38XX_CB_TX_DATA_LQ) >=
				    ISL38XX_MIN_QTHRESHOLD) {
					/* nope, the driver is ready for more network frames */
					netif_wake_queue(priv->ndev);

					/* reset the full flag */
					priv->data_low_tx_full = 0;
				}
			}
		}

		if (reg & ISL38XX_INT_IDENT_INIT) {
			/* Device has been initialized */
#if VERBOSE > SHOW_ERROR_MESSAGES
			DEBUG(SHOW_TRACING,
			      "IRQ: Init flag, device initialized \n");
#endif
			wake_up(&priv->reset_done);
		}

		if (reg & ISL38XX_INT_IDENT_SLEEP) {
			/* Device intends to move to powersave state */
#if VERBOSE > SHOW_ERROR_MESSAGES
			DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n");
#endif
			isl38xx_handle_sleep_request(priv->control_block,
						     &powerstate,
						     priv->device_base);
		}

		if (reg & ISL38XX_INT_IDENT_WAKEUP) {
			/* Device has been woken up to active state */
#if VERBOSE > SHOW_ERROR_MESSAGES
			DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n");
#endif

			isl38xx_handle_wakeup(priv->control_block,
					      &powerstate, priv->device_base);
		}
	} else {
#if VERBOSE > SHOW_ERROR_MESSAGES
		DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n");
#endif
		spin_unlock(&priv->slock);
		return IRQ_NONE;
	}

	/* sleep -> ready */
	if (islpci_get_state(priv) == PRV_STATE_SLEEP
	    && powerstate == ISL38XX_PSM_ACTIVE_STATE)
		islpci_set_state(priv, PRV_STATE_READY);

	/* !sleep -> sleep */
	if (islpci_get_state(priv) != PRV_STATE_SLEEP
	    && powerstate == ISL38XX_PSM_POWERSAVE_STATE)
		islpci_set_state(priv, PRV_STATE_SLEEP);

	/* unlock the interrupt handler */
	spin_unlock(&priv->slock);

	return IRQ_HANDLED;
}
Exemple #6
0
int islpci_eth_transmit(struct sk_buff *skb, struct net_device *nwdev)
{
    islpci_private *private_config = nwdev->priv;
    isl38xx_control_block *control_block = private_config->control_block;
    isl38xx_fragment *fragment;
    u32 index, counter, pci_map_address;
    int fragments;
    int frame_size;
    int offset;
    struct sk_buff *newskb;
    int newskb_offset;
	unsigned long flags;
	unsigned char wds_mac[6];
#if VERBOSE > SHOW_ERROR_MESSAGES 
    DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n");
#endif

    // lock the driver code
    driver_lock( &private_config->slock, &flags );

    // check whether the deviec is running
//      if( !netif_running( nwdev ) )
//      {
//              DEBUG( SHOW_ERROR_MESSAGES, "%s: Tx on stopped device!\n",
//                     nwdev->name);
//              return 1;
//      }

//      tx_timeout_check( nwdev, islpci_eth_tx_timeout );
//      skb_tx_check( nwdev, skb );

    // determine the amount of fragments needed to store the frame
    memset (wds_mac, 0, 6);
#ifdef WDS_LINKS
    check_skb_for_wds(skb, wds_mac);
#ifdef ISLPCI_ETH_DEBUG
    if ( wds_mac[0] || wds_mac[1] || wds_mac[2] || wds_mac[3] || wds_mac[4] || wds_mac[5] ) {
        printk("islpci_eth_transmit:check_skb_for_wds ! %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", 
               wds_mac[0], wds_mac[1], wds_mac[2], wds_mac[3], wds_mac[4], wds_mac[5] );
    } else {
        printk("islpci_eth_transmit:check_skb_for_wds %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", 
               wds_mac[0], wds_mac[1], wds_mac[2], wds_mac[3], wds_mac[4], wds_mac[5] );
    }
#endif
#endif
    
    frame_size = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
    if( init_wds ) frame_size += 6;
    fragments = frame_size / MAX_FRAGMENT_SIZE;
    fragments += frame_size % MAX_FRAGMENT_SIZE == 0 ? 0 : 1;


#if VERBOSE > SHOW_ERROR_MESSAGES 
    DEBUG(SHOW_TRACING, "Fragments needed for frame %i\n", fragments);
#endif

    // check whether the destination queue has enough fragments for the frame
    if (ISL38XX_CB_TX_QSIZE - isl38xx_in_queue( control_block, 
		ISL38XX_CB_TX_DATA_LQ ) < fragments )
    {
        // Error, cannot add the frame because the queue is full
        DEBUG(SHOW_ERROR_MESSAGES, "Error: Queue [%i] not enough room\n",
	        ISL38XX_CB_TX_DATA_LQ);

        // trigger the device by setting the Update bit in the Device Int reg
        writel(ISL38XX_DEV_INT_UPDATE, private_config->remapped_device_base + 
            ISL38XX_DEV_INT_REG);
        udelay(ISL38XX_WRITEIO_DELAY);

        // unlock the driver code
        driver_unlock( &private_config->slock, &flags );
        return -EBUSY;
    }

    // Check alignment and WDS frame formatting. The start of the packet should
    // be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes
    // and add WDS address information
    if( ((int) skb->data & 0x03) | init_wds )
    {
        // get the number of bytes to add and re-allign
        offset = (int) skb->data & 0x03;
		offset += init_wds ? 6 : 0;		

		// check whether the current skb can be used 
        if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset))
        {
            unsigned char *src = skb->data;

#if VERBOSE > SHOW_ERROR_MESSAGES 
	        DEBUG(SHOW_TRACING, "skb offset %i wds %i\n", offset, init_wds );
#endif

			// allign the buffer on 4-byte boundary
            skb_reserve(skb, (int) skb->data & 0x03 );
            if( init_wds )
            {
            	// wds requires an additional address field of 6 bytes
				skb_put( skb, 6 ); 
#ifdef ISLPCI_ETH_DEBUG
                printk("islpci_eth_transmit:wds_mac\n" );
#endif			    
                memmove( skb->data+6, src, skb->len );
                memcpy( skb->data, wds_mac, 6 );
            }
            else
			{
                memmove( skb->data, src, skb->len );
			}
			
#if VERBOSE > SHOW_ERROR_MESSAGES 
            DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data, src,
                skb->len );
#endif
        }
        else
        {
            newskb = dev_alloc_skb( init_wds ? skb->len+6 : skb->len );
            newskb_offset = (int) newskb->data & 0x03;

            // Check if newskb->data is aligned
            if( newskb_offset )
                skb_reserve(newskb, newskb_offset);

            skb_put(newskb, init_wds ? skb->len+6 : skb->len );
            if( init_wds )
            {
                memcpy( newskb->data+6, skb->data, skb->len );
                memcpy( newskb->data, wds_mac, 6 );
#ifdef ISLPCI_ETH_DEBUG
                printk("islpci_eth_transmit:wds_mac\n" );
#endif
            }
            else
                memcpy( newskb->data, skb->data, skb->len );

#if VERBOSE > SHOW_ERROR_MESSAGES 
            DEBUG(SHOW_TRACING, "memcpy %p %p %i wds %i\n", newskb->data,
                skb->data, skb->len, init_wds );
#endif

            newskb->dev = skb->dev;
            dev_kfree_skb(skb);
            skb = newskb;
        }
    }

    // display the buffer contents for debugging
#if VERBOSE > SHOW_ERROR_MESSAGES 
    DEBUG( SHOW_BUFFER_CONTENTS, "\ntx %p ", skb->data );
    display_buffer((char *) skb->data, skb->len );
#endif

	// map the skb buffer to pci memory for DMA operation
	pci_map_address = pci_map_single( private_config->pci_device, 
		(void *) skb->data, skb->len, PCI_DMA_TODEVICE );
    if( pci_map_address == (dma_addr_t) NULL )
	{
    	// error mapping the buffer to device accessable memory address
	    DEBUG(SHOW_ERROR_MESSAGES, "Error map DMA addr, data lost\n" );

	    // free the skbuf structure before aborting
    	dev_kfree_skb(skb);

        // unlock the driver code
        driver_unlock( &private_config->slock, &flags );
	    return -EIO;
    }

	// place each fragment in the control block structure and store in the last
	// needed fragment entry of the pci_map_tx_address and data_low_tx arrays 
	// the skb frame information
    for (counter = 0; counter < fragments; counter++ )
	{
		// get a pointer to the target control block fragment
	    index = (counter + le32_to_cpu(
	        control_block->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ])) %
    	    ISL38XX_CB_TX_QSIZE;			
	    fragment = &control_block->tx_data_low[index];
	
		// check whether this frame fragment is the last one
		if( counter == fragments-1 )
		{
			// the fragment is the last one, add the streaming DMA mapping for 
			// proper PCI bus operation
    		private_config->pci_map_tx_address[index] = 
                (dma_addr_t) pci_map_address;
			
			// store the skb address for future freeing 
			private_config->data_low_tx[index] = skb;
		}
		else
		{
			// the fragment will be followed by more fragments
			// clear the pci_map_tx_address and data_low_tx entries
		    private_config->pci_map_tx_address[index] = (dma_addr_t) NULL;
			private_config->data_low_tx[index] = NULL;
		}
			
		// set the proper fragment start address and size information
        fragment->address = cpu_to_le32( pci_map_address + 
			counter*MAX_FRAGMENT_SIZE );
        fragment->size = cpu_to_le16( frame_size > MAX_FRAGMENT_SIZE ?
            MAX_FRAGMENT_SIZE : frame_size );
        fragment->flags = cpu_to_le16( frame_size > MAX_FRAGMENT_SIZE ? 1 : 0 );
        frame_size -= MAX_FRAGMENT_SIZE;
	}

	// ready loading all fragements to the control block and setup pci mapping
	// update the control block interface information
    add_le32p(&control_block->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ],
        fragments);

    // check whether the data tx queue is full now
    if( ISL38XX_CB_TX_QSIZE - isl38xx_in_queue( control_block, 
		ISL38XX_CB_TX_DATA_LQ ) < ISL38XX_MIN_QTHRESHOLD )
    {
        // stop the transmission of network frames to the driver
        netif_stop_queue(nwdev);

        // set the full flag for the data low transmission queue
        private_config->data_low_tx_full = 1;
    }

    // trigger the device
    isl38xx_trigger_device( &private_config->powerstate,
        private_config->remapped_device_base );

    // set the transmission time
    nwdev->trans_start = jiffies;
    private_config->statistics.tx_packets++;
    private_config->statistics.tx_bytes += skb->len;

    // cleanup the data low transmit queue
    islpci_eth_cleanup_transmit( private_config, private_config->control_block );

    // unlock the driver code
    driver_unlock( &private_config->slock, &flags );
    return 0;
}
Exemple #7
0
/******************************************************************************
    Device Interrupt Handler
******************************************************************************/
void islpci_interrupt(int irq, void *config, struct pt_regs *regs)
{
    u32 reg;
    islpci_private *private_config = config;
    void *device = private_config->device_id;
    u16 status;
    
    // received an interrupt request on a shared IRQ line
    // first check whether the device is in sleep mode
    if( reg = readl( device + ISL38XX_CTRL_STAT_REG),
        reg & ISL38XX_CTRL_STAT_SLEEPMODE )
        // device is in sleep mode, IRQ was generated by someone else
        return;
    
    // lock the interrupt handler
    spin_lock( &private_config->slock );
     
#ifdef CONFIG_ARCH_ISL3893
    // check the interrupt source on the host registers
    reg = (u32) uPCI->ARMIntReg;
    reg &= (u32) uPCI->ARMIntEnReg;
    
//    pci_unmap_single( private_config->pci_device, private_config->control_block, 
//                    sizeof(struct isl38xx_cb), PCI_DMA_FROMDEVICE );
    flush_cache_all();

#else
    // check whether there is any source of interrupt on the device
    reg = readl(device + ISL38XX_INT_IDENT_REG);

    // also check the contents of the Interrupt Enable Register, because this
    // will filter out interrupt sources from other devices on the same irq !
    reg &= readl(device + ISL38XX_INT_EN_REG);
#endif

    if (reg &= ISL38XX_INT_SOURCES, reg != 0)
    {
#ifdef CONFIG_ARCH_ISL3893
        // write the acknowledge register on the host
        uPCI->ARMIntAckReg = reg;
#else
        // reset the request bits in the Identification register
        writel(reg, device + ISL38XX_INT_ACK_REG);
#endif

#if VERBOSE > SHOW_ERROR_MESSAGES 
        DEBUG(SHOW_FUNCTION_CALLS,
	        "IRQ: Identification register value 0x%x \n", reg );
#endif

        // check for each bit in the register separately
        if (reg & ISL38XX_INT_IDENT_UPDATE)
        {
#if VERBOSE > SHOW_ERROR_MESSAGES 
            // Queue has been updated
            DEBUG(SHOW_TRACING, "IRQ: Update flag \n");

            DEBUG(SHOW_QUEUE_INDEXES,
                "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n",
                le32_to_cpu(private_config->control_block->driver_curr_frag[0]),
                le32_to_cpu(private_config->control_block->driver_curr_frag[1]),
                le32_to_cpu(private_config->control_block->driver_curr_frag[2]),
                le32_to_cpu(private_config->control_block->driver_curr_frag[3]),
                le32_to_cpu(private_config->control_block->driver_curr_frag[4]),
                le32_to_cpu(private_config->control_block->driver_curr_frag[5])
                );

            DEBUG(SHOW_QUEUE_INDEXES,
                "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n",
                le32_to_cpu(private_config->control_block->device_curr_frag[0]),
                le32_to_cpu(private_config->control_block->device_curr_frag[1]),
                le32_to_cpu(private_config->control_block->device_curr_frag[2]),
                le32_to_cpu(private_config->control_block->device_curr_frag[3]),
                le32_to_cpu(private_config->control_block->device_curr_frag[4]),
                le32_to_cpu(private_config->control_block->device_curr_frag[5])
                );
#endif

            // device is in active state, update the powerstate flag
            private_config->powerstate = ISL38XX_PSM_ACTIVE_STATE;

            // check all three queues in priority order
            // call the PIMFOR receive function until the queue is empty
            while (isl38xx_in_queue(private_config->control_block,
                ISL38XX_CB_RX_MGMTQ) != 0)
            {
#if VERBOSE > SHOW_ERROR_MESSAGES 
                DEBUG(SHOW_TRACING, "Received frame in Management Queue\n");
#endif
                islpci_mgt_receive(private_config);

                // call the pimfor transmit function for processing the next
                // management frame in the shadow queue
                islpci_mgt_transmit( private_config );
            }

            while (isl38xx_in_queue(private_config->control_block,
                ISL38XX_CB_RX_DATA_LQ) != 0)
            {
#if VERBOSE > SHOW_ERROR_MESSAGES 
                DEBUG(SHOW_TRACING, "Received frame in Data Low Queue \n");
#endif
                islpci_eth_receive(private_config);
            }

		// check whether the data transmit queues were full
            if (private_config->data_low_tx_full)
            {
                // check whether the transmit is not full anymore
                if( ISL38XX_CB_TX_QSIZE - isl38xx_in_queue( private_config->control_block, 
		            ISL38XX_CB_TX_DATA_LQ ) >= ISL38XX_MIN_QTHRESHOLD )
                {
                    // nope, the driver is ready for more network frames
                    netif_wake_queue(private_config->my_module);

                    // reset the full flag
                    private_config->data_low_tx_full = 0;
                }
            }
        }

        if (reg & ISL38XX_INT_IDENT_INIT)
        {
            // Device has been initialized
#if VERBOSE > SHOW_ERROR_MESSAGES 
            DEBUG(SHOW_TRACING, "IRQ: Init flag, device initialized \n");
#endif

            // perform card initlialization by sending objects
            islpci_mgt_initialize( private_config );
        }

        if (reg & ISL38XX_INT_IDENT_SLEEP)
        {
            // Device intends to move to powersave state
#if VERBOSE > SHOW_ERROR_MESSAGES 
            DEBUG(SHOW_ANYTHING, "IRQ: Sleep flag \n");
#endif
            isl38xx_handle_sleep_request( private_config->control_block,
                &private_config->powerstate,
                private_config->remapped_device_base );
        }

        if (reg & ISL38XX_INT_IDENT_WAKEUP)
        {
            // Device has been woken up to active state
#if VERBOSE > SHOW_ERROR_MESSAGES 
            DEBUG(SHOW_ANYTHING, "IRQ: Wakeup flag \n");
#endif
        
            isl38xx_handle_wakeup( private_config->control_block,
                &private_config->powerstate,
                private_config->remapped_device_base );
        }
    }

    // unlock the interrupt handler
    spin_unlock( &private_config->slock );

    return;
}
Exemple #8
0
int islpci_reset(islpci_private * private_config, char *firmware )
{
    isl38xx_control_block *control_block = private_config->control_block;
    queue_entry *entry;
//	unsigned long flags;

#if VERBOSE > SHOW_ERROR_MESSAGES 
    DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_reset \n");
#endif

    // lock the driver code
    //driver_lock( &private_config->slock, &flags );

    // stop the transmission of network frames to the driver
    netif_stop_queue(private_config->my_module);

    // disable all device interrupts
    writel(0, private_config->remapped_device_base + ISL38XX_INT_EN_REG);

    // flush all management queues
    while( isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ) != 0 )
    {
        islpci_get_queue(private_config->remapped_device_base,
                &private_config->mgmt_tx_shadowq, &entry);
        islpci_put_queue(private_config->remapped_device_base,
                &private_config->mgmt_tx_freeq, entry);

        // decrement the real management index
        private_config->index_mgmt_tx--;
    }

//    while( isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ) != 0 )
//    {
//        islpci_get_queue(private_config->remapped_device_base,
//                &private_config->mgmt_rx_shadowq, &entry);
//        islpci_put_queue(private_config->remapped_device_base,
//                &private_config->mgmt_rx_freeq, entry);

        // decrement the real management index
//        private_config->index_mgmt_rx--;
//    }

#if VERBOSE > SHOW_ERROR_MESSAGES 
    DEBUG(SHOW_TRACING, "Firmware file: %s \n", firmware );
#endif
	
    if (isl38xx_upload_firmware( firmware, private_config->remapped_device_base,
        private_config->device_host_address ) == -1)
    {
        // error uploading the firmware
        DEBUG(SHOW_ERROR_MESSAGES, "ERROR: could not upload the firmware \n" );

        // unlock the driver code
        //driver_unlock( &private_config->slock, &flags );
        return -1;
    }
    
    // unlock the driver code
    //driver_unlock( &private_config->slock, &flags );

    return 0;
}