示例#1
0
static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len)
{
	struct mc32_local *lp = netdev_priv(dev);
	int ioaddr = dev->base_addr;
	int ret = 0;

	down(&lp->cmd_mutex);

	/*
	 *     My Turn
	 */

	lp->cmd_nonblocking=0;
	lp->exec_box->mbox=0;
	lp->exec_box->mbox=cmd;
	memcpy((void *)lp->exec_box->data, data, len);
	barrier();	/* the memcpy forgot the volatile so be sure */

	mc32_ready_poll(dev);
	outb(1<<6, ioaddr+HOST_CMD);

	wait_for_completion(&lp->execution_cmd);

	if(lp->exec_box->mbox&(1<<13))
		ret = -1;

	up(&lp->cmd_mutex);

	/*
	 *	A multicast set got blocked - try it now
         */

	if(lp->mc_reload_wait)
	{
		mc32_reset_multicast_list(dev);
	}

	return ret;
}
static irqreturn_t mc32_interrupt(int irq, void *dev_id)
{
    struct net_device *dev = dev_id;
    struct mc32_local *lp;
    int ioaddr, status, boguscount = 0;
    int rx_event = 0;
    int tx_event = 0;

    ioaddr = dev->base_addr;
    lp = netdev_priv(dev);

    /* See whats cooking */

    while((inb(ioaddr+HOST_STATUS)&HOST_STATUS_CWR) && boguscount++<2000)
    {
        status=inb(ioaddr+HOST_CMD);

#ifdef DEBUG_IRQ
        printk("Status TX%d RX%d EX%d OV%d BC%d\n",
               (status&7), (status>>3)&7, (status>>6)&1,
               (status>>7)&1, boguscount);
#endif

        switch(status&7)
        {
        case 0:
            break;
        case 6: /* TX fail */
        case 2:	/* TX ok */
            tx_event = 1;
            break;
        case 3: /* Halt */
        case 4: /* Abort */
            complete(&lp->xceiver_cmd);
            break;
        default:
            printk("%s: strange tx ack %d\n", dev->name, status&7);
        }
        status>>=3;
        switch(status&7)
        {
        case 0:
            break;
        case 2:	/* RX */
            rx_event=1;
            break;
        case 3: /* Halt */
        case 4: /* Abort */
            complete(&lp->xceiver_cmd);
            break;
        case 6:
            /* Out of RX buffers stat */
            /* Must restart rx */
            dev->stats.rx_dropped++;
            mc32_rx_ring(dev);
            mc32_start_transceiver(dev);
            break;
        default:
            printk("%s: strange rx ack %d\n",
                   dev->name, status&7);
        }
        status>>=3;
        if(status&1)
        {
            /*
             * No thread is waiting: we need to tidy
             * up ourself.
             */

            if (lp->cmd_nonblocking) {
                up(&lp->cmd_mutex);
                if (lp->mc_reload_wait)
                    mc32_reset_multicast_list(dev);
            }
            else complete(&lp->execution_cmd);
        }
        if(status&2)
        {
            /*
             *	We get interrupted once per
             *	counter that is about to overflow.
             */

            mc32_update_stats(dev);
        }
    }


    /*
     *	Process the transmit and receive rings
         */

    if(tx_event)
        mc32_tx_ring(dev);

    if(rx_event)
        mc32_rx_ring(dev);

    return IRQ_HANDLED;
}