コード例 #1
0
static void elp_set_mc_list(struct net_device *dev)
{
	elp_device *adapter = netdev_priv(dev);
	struct netdev_hw_addr *ha;
	int i;
	unsigned long flags;

	if (elp_debug >= 3)
		pr_debug("%s: request to set multicast list\n", dev->name);

	spin_lock_irqsave(&adapter->lock, flags);

	if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
		/*                                                                     */
		/*                                          */
		adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST;
		adapter->tx_pcb.length = 6 * netdev_mc_count(dev);
		i = 0;
		netdev_for_each_mc_addr(ha, dev)
			memcpy(adapter->tx_pcb.data.multicast[i++],
			       ha->addr, 6);
		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
		if (!send_pcb(dev, &adapter->tx_pcb))
			pr_err("%s: couldn't send set_multicast command\n", dev->name);
		else {
			unsigned long timeout = jiffies + TIMEOUT;
			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));
			if (time_after_eq(jiffies, timeout)) {
				TIMEOUT_MSG(__LINE__);
			}
		}
		if (!netdev_mc_empty(dev))
			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI;
		else		/*                */
			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
	} else
		adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC;
	/*
                                                              
                         
  */
	if (elp_debug >= 3)
		pr_debug("%s: sending 82586 configure command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
	adapter->tx_pcb.length = 2;
	adapter->got[CMD_CONFIGURE_82586] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
	{
		spin_unlock_irqrestore(&adapter->lock, flags);
		pr_err("%s: couldn't send 82586 configure command\n", dev->name);
	}
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		spin_unlock_irqrestore(&adapter->lock, flags);
		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}
}
コード例 #2
0
ファイル: 3c505.c プロジェクト: smx-smx/dsl-n55u
static void elp_set_mc_list(struct net_device *dev)
{
	elp_device *adapter = (elp_device *) dev->priv;
	struct dev_mc_list *dmi = dev->mc_list;
	int i;
	unsigned long flags;

	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: request to set multicast list\n", dev->name);

	spin_lock_irqsave(&adapter->lock, flags);

	if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {
		/* send a "load multicast list" command to the board, max 10 addrs/cmd */
		/* if num_addrs==0 the list will be cleared */
		adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST;
		adapter->tx_pcb.length = 6 * dev->mc_count;
		for (i = 0; i < dev->mc_count; i++) {
			memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr, 6);
			dmi = dmi->next;
		}
		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
		if (!send_pcb(dev, &adapter->tx_pcb))
			printk(KERN_ERR "%s: couldn't send set_multicast command\n", dev->name);
		else {
			unsigned long timeout = jiffies + TIMEOUT;
			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));
			if (time_after_eq(jiffies, timeout)) {
				TIMEOUT_MSG(__LINE__);
			}
		}
		if (dev->mc_count)
			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI;
		else		/* num_addrs == 0 */
			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
	} else
		adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC;
	/*
	 * configure adapter to receive messages (as specified above)
	 * and wait for response
	 */
	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
	adapter->tx_pcb.length = 2;
	adapter->got[CMD_CONFIGURE_82586] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
	{
		spin_unlock_irqrestore(&adapter->lock, flags);
		printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name);
	}
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		spin_unlock_irqrestore(&adapter->lock, flags);
		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}
}
コード例 #3
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static void elp_set_mc_list(struct device *dev, int num_addrs, void *addrs)
{
    elp_device *adapter = (elp_device *) dev->priv;
    int i;

    if (elp_debug >= 3)
        printk("%s: request to set multicast list\n", dev->name);

    if (num_addrs != -1) {
        /* send a "load multicast list" command to the board, max 10 addrs/cmd */
        /* if num_addrs==0 the list will be cleared */
        adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST;
        adapter->tx_pcb.length  = 6*num_addrs;
        for (i=0; i<num_addrs; i++)
            memcpy(adapter->tx_pcb.data.multicast[i], addrs+6*i,6);
        adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;
        if (!send_pcb(adapter, &adapter->tx_pcb))
            printk("%s: couldn't send set_multicast command\n", dev->name);
        else {
            int timeout = jiffies + TIMEOUT;
            while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && jiffies < timeout)
                ;
            if (jiffies >= timeout) {
                TIMEOUT_MSG();
            }
        }
        if (num_addrs)
            adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI;
        else /* num_addrs == 0 */
            adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
    } else /* num_addrs == -1 */
        adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_ALL;
    /*
     * configure adapter to receive messages (as specified above)
     * and wait for response
     */
    if (elp_debug >= 3)
        printk("%s: sending 82586 configure command\n", dev->name);
    adapter->tx_pcb.command = CMD_CONFIGURE_82586;
    adapter->tx_pcb.length  = 2;
    adapter->got[CMD_CONFIGURE_82586]  = 0;
    if (!send_pcb(adapter, &adapter->tx_pcb))
        printk("%s: couldn't send 82586 configure command\n", dev->name);
    else {
        int timeout = jiffies + TIMEOUT;
        while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout)
            ;
        if (jiffies >= timeout)
            TIMEOUT_MSG();
    }
}
コード例 #4
0
ファイル: 3c505.c プロジェクト: smx-smx/dsl-n55u
static struct net_device_stats *elp_get_stats(struct net_device *dev)
{
	elp_device *adapter = (elp_device *) dev->priv;

	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: request for stats\n", dev->name);

	/* If the device is closed, just return the latest stats we have,
	   - we cannot ask from the adapter without interrupts */
	if (!netif_running(dev))
		return &adapter->stats;

	/* send a get statistics command to the board */
	adapter->tx_pcb.command = CMD_NETWORK_STATISTICS;
	adapter->tx_pcb.length = 0;
	adapter->got[CMD_NETWORK_STATISTICS] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		printk(KERN_ERR "%s: couldn't send get statistics command\n", dev->name);
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout)) {
			TIMEOUT_MSG(__LINE__);
			return &adapter->stats;
		}
	}

	/* statistics are now up to date */
	return &adapter->stats;
}
コード例 #5
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static struct enet_statistics * elp_get_stats(struct device *dev)

{
    elp_device *adapter = (elp_device *) dev->priv;

    if (elp_debug >= 3)
        printk("%s: request for stats\n", dev->name);

    /* If the device is closed, just return the latest stats we have,
       - we cannot ask from the adapter without interrupts */
    if (!dev->start)
        return &adapter->stats;

    /* send a get statistics command to the board */
    adapter->tx_pcb.command = CMD_NETWORK_STATISTICS;
    adapter->tx_pcb.length  = 0;
    adapter->got[CMD_NETWORK_STATISTICS] = 0;
    if (!send_pcb(adapter, &adapter->tx_pcb))
        printk("%s: couldn't send get statistics command\n", dev->name);
    else
    {
        int timeout = jiffies + TIMEOUT;
        while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && jiffies < timeout)
            ;
        if (jiffies >= timeout) {
            TIMEOUT_MSG();
            return &adapter->stats;
        }
    }

    /* statistics are now up to date */
    return &adapter->stats;
}
コード例 #6
0
static struct net_device_stats *elp_get_stats(struct net_device *dev)
{
	elp_device *adapter = netdev_priv(dev);

	if (elp_debug >= 3)
		pr_debug("%s: request for stats\n", dev->name);

	if (!netif_running(dev))
		return &dev->stats;

	
	adapter->tx_pcb.command = CMD_NETWORK_STATISTICS;
	adapter->tx_pcb.length = 0;
	adapter->got[CMD_NETWORK_STATISTICS] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		pr_err("%s: couldn't send get statistics command\n", dev->name);
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout)) {
			TIMEOUT_MSG(__LINE__);
			return &dev->stats;
		}
	}

	
	return &dev->stats;
}
コード例 #7
0
ファイル: 3c505.c プロジェクト: smx-smx/dsl-n55u
static inline int get_status(unsigned int base_addr)
{
	unsigned long timeout = jiffies + 10*HZ/100;
	register int stat1;
	do {
		stat1 = inb_status(base_addr);
	} while (stat1 != inb_status(base_addr) && time_before(jiffies, timeout));
	if (time_after_eq(jiffies, timeout))
		TIMEOUT_MSG(__LINE__);
	return stat1;
}
コード例 #8
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static int get_status (elp_device * adapter)

{
    int timeout = jiffies + TIMEOUT;
    register int stat1;
    do {
        stat1 = INB(adapter->io_addr+PORT_STATUS);
    } while (stat1 != INB(adapter->io_addr+PORT_STATUS) && jiffies < timeout);
    if (jiffies >= timeout)
        TIMEOUT_MSG();
    return stat1;
}
コード例 #9
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static int wait_hcre(elp_device * adapter, int toval)

{
    int timeout = jiffies + toval;
    while(((INB(adapter->io_addr+PORT_STATUS)&STATUS_HCRE)==0) &&
            (jiffies <= timeout))
        ;
    if (jiffies >= timeout) {
        TIMEOUT_MSG();
        return FALSE;
    }
    return TRUE;
}
コード例 #10
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static int elp_open (struct device *dev)

{
    elp_device * adapter = (elp_device *) dev->priv;

    CHECK_NULL(dev);

    if (elp_debug >= 3)
        printk("%s: request to open device\n", dev->name);

    /*
     * make sure we actually found the device
     */
    if (adapter == NULL) {
        printk("%s: Opening a non-existent physical device\n", dev->name);
        return -EAGAIN;
    }

    /*
     * disable interrupts on the board
     */
    OUTB(0x00, adapter->io_addr+PORT_CONTROL);

    /*
     * clear any pending interrupts
     */
    INB(adapter->io_addr+PORT_COMMAND);

    /*
     * interrupt routine not entered
     */
    dev->interrupt = 0;

    /*
     *  transmitter not busy
     */
    dev->tbusy = 0;

    /*
     * install our interrupt service routine
     */
    if (request_irq(dev->irq, &elp_interrupt, 0, "3c505"))
        return -EAGAIN;

    /*
     * make sure we can find the device header given the interrupt number
     */
    irq2dev_map[dev->irq] = dev;

    /*
     * enable interrupts on the board
     */
    OUTB(CONTROL_CMDE, adapter->io_addr+PORT_CONTROL);

    /*
     * device is now officially open!
     */
    dev->start = 1;

    /*
     * configure adapter memory: we need 10 multicast addresses, default==0
     */
    if (elp_debug >= 3)
        printk("%s: sending 3c505 memory configuration command\n", dev->name);
    adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
    adapter->tx_pcb.data.memconf.cmd_q = 10;
    adapter->tx_pcb.data.memconf.rcv_q = 20;
    adapter->tx_pcb.data.memconf.mcast = 10;
    adapter->tx_pcb.data.memconf.frame = 20;
    adapter->tx_pcb.data.memconf.rcv_b = 20;
    adapter->tx_pcb.data.memconf.progs = 0;
    adapter->tx_pcb.length = sizeof(struct Memconf);
    adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
    if (!send_pcb(adapter, &adapter->tx_pcb))
        printk("%s: couldn't send memory configuration command\n", dev->name);
    else {
        int timeout = jiffies + TIMEOUT;
        while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && jiffies < timeout)
            ;
        if (jiffies >= timeout)
            TIMEOUT_MSG();
    }


    /*
     * configure adapter to receive broadcast messages and wait for response
     */
    if (elp_debug >= 3)
        printk("%s: sending 82586 configure command\n", dev->name);
    adapter->tx_pcb.command = CMD_CONFIGURE_82586;
    adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
    adapter->tx_pcb.length  = 2;
    adapter->got[CMD_CONFIGURE_82586] = 0;
    if (!send_pcb(adapter, &adapter->tx_pcb))
        printk("%s: couldn't send 82586 configure command\n", dev->name);
    else {
        int timeout = jiffies + TIMEOUT;
        while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout)
            ;
        if (jiffies >= timeout)
            TIMEOUT_MSG();
    }

    /*
     * queue receive commands to provide buffering
     */
    if (!start_receive(adapter, &adapter->tx_pcb))
        printk("%s: start receive command failed \n", dev->name);
    if (elp_debug >= 3)
        printk("%s: start receive command sent\n", dev->name);

    return 0;			/* Always succeed */
}
コード例 #11
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static void elp_interrupt(int reg_ptr)

{
    int len;
    int dlen;
    int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
    struct device *dev;
    elp_device * adapter;
    int timeout;

    if (irq < 0 || irq > 15) {
        printk ("elp_interrupt(): illegal IRQ number found in interrupt routine (%i)\n", irq);
        return;
    }

    /* FIXME: How do I do this kind of check without a fixed IRQ? */
#if 0
    if (irq != ELP_IRQ) {
        printk ("elp_interrupt(): - interrupt routine has incorrect IRQ of %i\n", irq);
        return;
    }
#endif

    dev = irq2dev_map[irq];

    if (dev == NULL) {
        printk ("elp_interrupt(): irq %d for unknown device.\n", irq);
        return;
    }

    adapter = (elp_device *) dev->priv;

    CHECK_NULL(adapter);

    if (dev->interrupt)
        if (elp_debug >= 2)
            printk("%s: Re-entering the interrupt handler.\n", dev->name);
    dev->interrupt = 1;

    /*
     * allow interrupts (we need timers!)
     */
    sti();

    /*
     * receive a PCB from the adapter
     */
    timeout = jiffies + TIMEOUT;
    while ((INB(adapter->io_addr+PORT_STATUS)&STATUS_ACRF) != 0 &&
            jiffies < timeout) {

        if (receive_pcb(adapter, &adapter->irx_pcb)) {

            switch (adapter->irx_pcb.command) {

            /*
             * 82586 configured correctly
             */
            case CMD_CONFIGURE_82586_RESPONSE:
                adapter->got[CMD_CONFIGURE_82586] = 1;
                if (elp_debug >= 3)
                    printk("%s: interrupt - configure response received\n", dev->name);
                break;

            /*
             * Adapter memory configuration
             */
            case CMD_CONFIGURE_ADAPTER_RESPONSE:
                adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1;
                if (elp_debug >= 3)
                    printk("%s: Adapter memory configuration %s.",dev->name,
                           adapter->irx_pcb.data.failed?"failed":"succeeded");
                break;

            /*
             * Multicast list loading
             */
            case CMD_LOAD_MULTICAST_RESPONSE:
                adapter->got[CMD_LOAD_MULTICAST_LIST] = 1;
                if (elp_debug >= 3)
                    printk("%s: Multicast address list loading %s.",dev->name,
                           adapter->irx_pcb.data.failed?"failed":"succeeded");
                break;

            /*
             * Station address setting
             */
            case CMD_SET_ADDRESS_RESPONSE:
                adapter->got[CMD_SET_STATION_ADDRESS] = 1;
                if (elp_debug >= 3)
                    printk("%s: Ethernet address setting %s.",dev->name,
                           adapter->irx_pcb.data.failed?"failed":"succeeded");
                break;


            /*
             * received board statistics
             */
            case CMD_NETWORK_STATISTICS_RESPONSE:
                adapter->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv;
                adapter->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit;
                adapter->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC;
                adapter->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align;
                adapter->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun;
                adapter->got[CMD_NETWORK_STATISTICS] = 1;
                if (elp_debug >= 3)
                    printk("%s: interrupt - statistics response received\n", dev->name);
                break;

            /*
             * received a packet
             */
            case CMD_RECEIVE_PACKET_COMPLETE:
                /* if the device isn't open, don't pass packets up the stack */
                if (dev->start == 0)
                    break;
                len = adapter->irx_pcb.data.rcv_resp.pkt_len;
                dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
                if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
                    printk("%s: interrupt - packet not received correctly\n", dev->name);
                } else {
                    if (elp_debug >= 3)
                        printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
                    receive_packet(dev, adapter, dlen);
                    if (elp_debug >= 3)
                        printk("%s: packet received\n", dev->name);
                }
                if (dev->start && !start_receive(adapter, &adapter->itx_pcb))
                    if (elp_debug >= 2)
                        printk("%s: interrupt - failed to send receive start PCB\n", dev->name);
                if (elp_debug >= 3)
                    printk("%s: receive procedure complete\n", dev->name);

                break;

            /*
             * sent a packet
             */
            case CMD_TRANSMIT_PACKET_COMPLETE:
                if (elp_debug >= 3)
                    printk("%s: interrupt - packet sent\n", dev->name);
                if (dev->start == 0)
                    break;
                if (adapter->irx_pcb.data.xmit_resp.c_stat != 0)
                    if (elp_debug >= 2)
                        printk("%s: interrupt - error sending packet %4.4x\n",
                               dev->name, adapter->irx_pcb.data.xmit_resp.c_stat);
                dev->tbusy = 0;
#if (ELP_KERNEL_TYPE < 3)
                mark_bh(INET_BH);
#else
                mark_bh(NET_BH);
#endif
                break;

            /*
             * some unknown PCB
             */
            default:
                printk("%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command);
                break;
            }
        } else
            printk("%s: failed to read PCB on interrupt\n", dev->name);
    }
    if (jiffies >= timeout)
        TIMEOUT_MSG();

    /*
     * indicate no longer in interrupt routine
     */
    dev->interrupt = 0;
}
コード例 #12
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static void receive_packet(struct device * dev,
                           elp_device * adapter,
                           int len)

{
    register int i;
    unsigned short * ptr;
    short d;
    int timeout;
    int rlen;
    struct sk_buff *skb;

    /*
     * allocate a buffer to put the packet into.
     * (for kernels prior to 1.1.4 only)
     */
#if (ELP_KERNEL_TYPE < 2)
    int sksize = sizeof(struct sk_buff) + len + 4;
#endif

    CHECK_NULL(dev);
    CHECK_NULL(adapter);

    if (len <= 0 || ((len & ~1) != len))
        if (elp_debug >= 3)
            printk("*** bad packet len %d at %s(%d)\n",len,filename,__LINE__);

    rlen = (len+1) & ~1;

#if (ELP_KERNEL_TYPE < 2)
    skb = alloc_skb(sksize, GFP_ATOMIC);
#else
    skb = alloc_skb(rlen, GFP_ATOMIC);
#endif

    /*
     * make sure the data register is going the right way
     */
    OUTB(INB(adapter->io_addr+PORT_CONTROL)|CONTROL_DIR, adapter->io_addr+PORT_CONTROL);

    /*
     * if buffer could not be allocated, swallow it
     */
    if (skb == NULL) {
        for (i = 0; i < (rlen/2); i++) {
            timeout = jiffies + TIMEOUT;
            while ((INB(adapter->io_addr+PORT_STATUS)&STATUS_HRDY) == 0 &&
                    jiffies < timeout)
                ;
            if (jiffies >= timeout)
                TIMEOUT_MSG();

            d = inw(adapter->io_addr+PORT_DATA);
        }
        adapter->stats.rx_dropped++;

    } else {
        skb->lock     = 0;
        skb->len = rlen;
        skb->dev = dev;

        /*
         * for kernels before 1.1.4, the driver allocated the buffer
         */
#if (ELP_KERNEL_TYPE < 2)
        skb->mem_len = sksize;
        skb->mem_addr = skb;
#endif

        /*
         * now read the data from the adapter
         */
        ptr = (unsigned short *)SKB_DATA;
        for (i = 0; i < (rlen/2); i++) {
            timeout = jiffies + TIMEOUT;
            while ((INB(adapter->io_addr+PORT_STATUS)&STATUS_HRDY) == 0 &&
                    jiffies < timeout)
                ;
            if (jiffies >= timeout)
            {
                printk("*** timeout at %s(%d) reading word %d of %d ***\n",
                       filename,__LINE__, i, rlen/2);
#if (ELP_KERNEL_TYPE < 2)
                kfree_s(skb, sksize);
#else
                kfree_s(skb, rlen);
#endif
                return;
            }

            *ptr = inw(adapter->io_addr+PORT_DATA);
            ptr++;
        }

        /*
         * the magic routine "dev_rint" passes the packet up the
         * protocol chain. If it returns 0, we can assume the packet was
         * swallowed up. If not, then we are responsible for freeing memory
         */

        IS_SKB(skb);

        /*
         * for kernels before 1.1.4, the driver allocated the buffer, so it had
         * to free it
         */
#if (ELP_KERNEL_TYPE < 2)
        if (dev_rint((unsigned char *)skb, rlen, IN_SKBUFF, dev) != 0) {
            printk("%s: receive buffers full.\n", dev->name);
            kfree_s(skb, sksize);
        }
#else
        netif_rx(skb);
#endif
    }

    OUTB(INB(adapter->io_addr+PORT_CONTROL)&(~CONTROL_DIR), adapter->io_addr+PORT_CONTROL);
}
コード例 #13
0
static bool receive_pcb(struct net_device *dev, pcb_struct * pcb)
{
	int i, j;
	int total_length;
	int stat;
	unsigned long timeout;
	unsigned long flags;

	elp_device *adapter = netdev_priv(dev);

	set_hsf(dev, 0);

	
	timeout = jiffies + 2*HZ/100;
	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
	if (time_after_eq(jiffies, timeout)) {
		TIMEOUT_MSG(__LINE__);
		return false;
	}
	pcb->command = inb_command(dev->base_addr);

	
	timeout = jiffies + 3*HZ/100;
	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
	if (time_after_eq(jiffies, timeout)) {
		TIMEOUT_MSG(__LINE__);
		pr_info("%s: status %02x\n", dev->name, stat);
		return false;
	}
	pcb->length = inb_command(dev->base_addr);

	if (pcb->length > MAX_PCB_DATA) {
		INVALID_PCB_MSG(pcb->length);
		adapter_reset(dev);
		return false;
	}
	
	spin_lock_irqsave(&adapter->lock, flags);
	for (i = 0; i < MAX_PCB_DATA; i++) {
		for (j = 0; j < 20000; j++) {
			stat = get_status(dev->base_addr);
			if (stat & ACRF)
				break;
		}
		pcb->data.raw[i] = inb_command(dev->base_addr);
		if ((stat & ASF_PCB_MASK) == ASF_PCB_END || j >= 20000)
			break;
	}
	spin_unlock_irqrestore(&adapter->lock, flags);
	if (i >= MAX_PCB_DATA) {
		INVALID_PCB_MSG(i);
		return false;
	}
	if (j >= 20000) {
		TIMEOUT_MSG(__LINE__);
		return false;
	}
	
	total_length = pcb->data.raw[i];

	
	if (total_length != (pcb->length + 2)) {
		if (elp_debug >= 2)
			pr_warning("%s: mangled PCB received\n", dev->name);
		set_hsf(dev, HSF_PCB_NAK);
		return false;
	}

	if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) {
		if (test_and_set_bit(0, (void *) &adapter->busy)) {
			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {
				set_hsf(dev, HSF_PCB_NAK);
				pr_warning("%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
				pcb->command = 0;
				return true;
			} else {
				pcb->command = 0xff;
			}
		}
	}
	set_hsf(dev, HSF_PCB_ACK);
	return true;
}
コード例 #14
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static int send_pcb(elp_device * adapter, pcb_struct * pcb)

{
    int i;
    int cont;
    int retry = 0;
    int timeout;

    CHECK_NULL(pcb);
    CHECK_NULL(adapter);

    if (pcb->length > MAX_PCB_DATA)
        printk(invalid_pcb_msg, pcb->length, filename, __LINE__);

    while (1) {

        cont = 1;

        /*
         * load each byte into the command register and
         * wait for the HCRE bit to indicate the adapter
         * had read the byte
         */
        SET_HSF(0);
        OUTB(pcb->command, (adapter->io_addr)+PORT_COMMAND);
        cont = WAIT_HCRE(5);

        if (cont) {
            OUTB(pcb->length, (adapter->io_addr)+PORT_COMMAND);
            cont = WAIT_HCRE(2);
        }

        for (i = 0; cont && (i < pcb->length); i++) {
            OUTB(pcb->data.raw[i], (adapter->io_addr)+PORT_COMMAND);
            cont = WAIT_HCRE(2);
        }

        /* set the host status bits to indicate end of PCB */
        /* send the total packet length as well */
        /* wait for the adapter to indicate that it has read the PCB */
        if (cont) {
            SET_HSF(HSF_PCB_END);
            OUTB(2+pcb->length, adapter->io_addr+PORT_COMMAND);
            timeout = jiffies + 6;
            while (jiffies < timeout) {
                i = GET_ASF();
                if ((i == ASF_PCB_ACK) ||
                        (i == ASF_PCB_NAK))
                    break;
            }

            if (jiffies >= timeout)
                TIMEOUT_MSG();

            if (i == ASF_PCB_ACK) {
                SET_HSF(0);
                return TRUE;
            } else if (i == ASF_PCB_NAK) {
                SET_HSF(0);
                printk("%s: PCB send was NAKed\n", adapter->name);
                {
                    int to = jiffies + 5;
                    while (jiffies < to)
                        ;
                }
            }
        }

        if (elp_debug >= 2)
            printk("%s: NAK/timeout on send PCB\n", adapter->name);
        if ((retry++ & 7) == 0)
            printk("%s: retry #%i on send PCB\n", adapter->name, retry);
    }

    return FALSE;
}
コード例 #15
0
static int elp_open(struct net_device *dev)
{
	elp_device *adapter = netdev_priv(dev);
	int retval;

	if (elp_debug >= 3)
		pr_debug("%s: request to open device\n", dev->name);

	if (adapter == NULL) {
		pr_err("%s: Opening a non-existent physical device\n", dev->name);
		return -EAGAIN;
	}
	outb_control(0, dev);

	inb_command(dev->base_addr);
	adapter_reset(dev);

	adapter->rx_active = 0;

	adapter->busy = 0;
	adapter->send_pcb_semaphore = 0;
	adapter->rx_backlog.in = 0;
	adapter->rx_backlog.out = 0;

	spin_lock_init(&adapter->lock);

	if ((retval = request_irq(dev->irq, elp_interrupt, 0, dev->name, dev))) {
		pr_err("%s: could not allocate IRQ%d\n", dev->name, dev->irq);
		return retval;
	}
	if ((retval = request_dma(dev->dma, dev->name))) {
		free_irq(dev->irq, dev);
		pr_err("%s: could not allocate DMA%d channel\n", dev->name, dev->dma);
		return retval;
	}
	adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE);
	if (!adapter->dma_buffer) {
		pr_err("%s: could not allocate DMA buffer\n", dev->name);
		free_dma(dev->dma);
		free_irq(dev->irq, dev);
		return -ENOMEM;
	}
	adapter->dmaing = 0;

	outb_control(CMDE, dev);

	if (elp_debug >= 3)
		pr_debug("%s: sending 3c505 memory configuration command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
	adapter->tx_pcb.data.memconf.cmd_q = 10;
	adapter->tx_pcb.data.memconf.rcv_q = 20;
	adapter->tx_pcb.data.memconf.mcast = 10;
	adapter->tx_pcb.data.memconf.frame = 20;
	adapter->tx_pcb.data.memconf.rcv_b = 20;
	adapter->tx_pcb.data.memconf.progs = 0;
	adapter->tx_pcb.length = sizeof(struct Memconf);
	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		pr_err("%s: couldn't send memory configuration command\n", dev->name);
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}


	if (elp_debug >= 3)
		pr_debug("%s: sending 82586 configure command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
	adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
	adapter->tx_pcb.length = 2;
	adapter->got[CMD_CONFIGURE_82586] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		pr_err("%s: couldn't send 82586 configure command\n", dev->name);
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}

	
	

	prime_rx(dev);
	if (elp_debug >= 3)
		pr_debug("%s: %d receive PCBs active\n", dev->name, adapter->rx_active);


	netif_start_queue(dev);
	return 0;
}
コード例 #16
0
ファイル: 3c505.c プロジェクト: smx-smx/dsl-n55u
static int receive_pcb(struct net_device *dev, pcb_struct * pcb)
{
	int i, j;
	int total_length;
	int stat;
	unsigned long timeout;
	unsigned long flags;

	elp_device *adapter = dev->priv;

	set_hsf(dev, 0);

	/* get the command code */
	timeout = jiffies + 2*HZ/100;
	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
	if (time_after_eq(jiffies, timeout)) {
		TIMEOUT_MSG(__LINE__);
		return FALSE;
	}
	pcb->command = inb_command(dev->base_addr);

	/* read the data length */
	timeout = jiffies + 3*HZ/100;
	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
	if (time_after_eq(jiffies, timeout)) {
		TIMEOUT_MSG(__LINE__);
		printk(KERN_INFO "%s: status %02x\n", dev->name, stat);
		return FALSE;
	}
	pcb->length = inb_command(dev->base_addr);

	if (pcb->length > MAX_PCB_DATA) {
		INVALID_PCB_MSG(pcb->length);
		adapter_reset(dev);
		return FALSE;
	}
	/* read the data */
	spin_lock_irqsave(&adapter->lock, flags);
	i = 0;
	do {
		j = 0;
		while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && j++ < 20000);
		pcb->data.raw[i++] = inb_command(dev->base_addr);
		if (i > MAX_PCB_DATA)
			INVALID_PCB_MSG(i);
	} while ((stat & ASF_PCB_MASK) != ASF_PCB_END && j < 20000);
	spin_unlock_irqrestore(&adapter->lock, flags);
	if (j >= 20000) {
		TIMEOUT_MSG(__LINE__);
		return FALSE;
	}
	/* woops, the last "data" byte was really the length! */
	total_length = pcb->data.raw[--i];

	/* safety check total length vs data length */
	if (total_length != (pcb->length + 2)) {
		if (elp_debug >= 2)
			printk(KERN_WARNING "%s: mangled PCB received\n", dev->name);
		set_hsf(dev, HSF_PCB_NAK);
		return FALSE;
	}

	if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) {
		if (test_and_set_bit(0, (void *) &adapter->busy)) {
			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {
				set_hsf(dev, HSF_PCB_NAK);
				printk(KERN_WARNING "%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
				pcb->command = 0;
				return TRUE;
			} else {
				pcb->command = 0xff;
			}
		}
	}
	set_hsf(dev, HSF_PCB_ACK);
	return TRUE;
}
コード例 #17
0
ファイル: 3c505.c プロジェクト: smx-smx/dsl-n55u
static int elp_open(struct net_device *dev)
{
	elp_device *adapter;
	int retval;

	adapter = dev->priv;

	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: request to open device\n", dev->name);

	/*
	 * make sure we actually found the device
	 */
	if (adapter == NULL) {
		printk(KERN_ERR "%s: Opening a non-existent physical device\n", dev->name);
		return -EAGAIN;
	}
	/*
	 * disable interrupts on the board
	 */
	outb_control(0, dev);

	/*
	 * clear any pending interrupts
	 */
	inb_command(dev->base_addr);
	adapter_reset(dev);

	/*
	 * no receive PCBs active
	 */
	adapter->rx_active = 0;

	adapter->busy = 0;
	adapter->send_pcb_semaphore = 0;
	adapter->rx_backlog.in = 0;
	adapter->rx_backlog.out = 0;

	spin_lock_init(&adapter->lock);

	/*
	 * install our interrupt service routine
	 */
	if ((retval = request_irq(dev->irq, &elp_interrupt, 0, dev->name, dev))) {
		printk(KERN_ERR "%s: could not allocate IRQ%d\n", dev->name, dev->irq);
		return retval;
	}
	if ((retval = request_dma(dev->dma, dev->name))) {
		free_irq(dev->irq, dev);
		printk(KERN_ERR "%s: could not allocate DMA%d channel\n", dev->name, dev->dma);
		return retval;
	}
	adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE);
	if (!adapter->dma_buffer) {
		printk(KERN_ERR "%s: could not allocate DMA buffer\n", dev->name);
		free_dma(dev->dma);
		free_irq(dev->irq, dev);
		return -ENOMEM;
	}
	adapter->dmaing = 0;

	/*
	 * enable interrupts on the board
	 */
	outb_control(CMDE, dev);

	/*
	 * configure adapter memory: we need 10 multicast addresses, default==0
	 */
	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: sending 3c505 memory configuration command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
	adapter->tx_pcb.data.memconf.cmd_q = 10;
	adapter->tx_pcb.data.memconf.rcv_q = 20;
	adapter->tx_pcb.data.memconf.mcast = 10;
	adapter->tx_pcb.data.memconf.frame = 20;
	adapter->tx_pcb.data.memconf.rcv_b = 20;
	adapter->tx_pcb.data.memconf.progs = 0;
	adapter->tx_pcb.length = sizeof(struct Memconf);
	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		printk(KERN_ERR "%s: couldn't send memory configuration command\n", dev->name);
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}


	/*
	 * configure adapter to receive broadcast messages and wait for response
	 */
	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: sending 82586 configure command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
	adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
	adapter->tx_pcb.length = 2;
	adapter->got[CMD_CONFIGURE_82586] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		printk(KERN_ERR "%s: couldn't send 82586 configure command\n", dev->name);
	else {
		unsigned long timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}

	/* enable burst-mode DMA */
	/* outb(0x1, dev->base_addr + PORT_AUXDMA); */

	/*
	 * queue receive commands to provide buffering
	 */
	prime_rx(dev);
	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: %d receive PCBs active\n", dev->name, adapter->rx_active);

	/*
	 * device is now officially open!
	 */

	netif_start_queue(dev);
	return 0;
}
コード例 #18
0
ファイル: 3c505.c プロジェクト: Lakshmipathi/Linux-historic
static int receive_pcb(elp_device * adapter, pcb_struct * pcb)

{
    int i;
    int total_length;
    int stat;
    int timeout;

    CHECK_NULL(pcb);
    CHECK_NULL(adapter);

    /* get the command code */
    timeout = jiffies + TIMEOUT;
    while (((stat = GET_STATUS())&STATUS_ACRF) == 0 && jiffies < timeout)
        ;
    if (jiffies >= timeout)
        TIMEOUT_MSG();

    SET_HSF(0);
    pcb->command = INB(adapter->io_addr+PORT_COMMAND);
    if ((stat & ASF_PCB_MASK) != ASF_PCB_END) {

        /* read the data length */
        timeout = jiffies + TIMEOUT;
        while (((stat = GET_STATUS())&STATUS_ACRF) == 0 && jiffies < timeout)
            ;
        if (jiffies >= timeout)
            TIMEOUT_MSG();
        pcb->length = INB(adapter->io_addr+PORT_COMMAND);

        if (pcb->length > MAX_PCB_DATA)
            printk(invalid_pcb_msg, pcb->length, filename,__LINE__);

        if ((stat & ASF_PCB_MASK) != ASF_PCB_END) {

            /* read the data */
            i = 0;
            timeout = jiffies + TIMEOUT;
            do {
                while (((stat = GET_STATUS())&STATUS_ACRF) == 0 && jiffies < timeout)
                    ;
                pcb->data.raw[i++] = INB(adapter->io_addr+PORT_COMMAND);
                if (i > MAX_PCB_DATA)
                    printk(invalid_pcb_msg, i, filename, __LINE__);
            } while ((stat & ASF_PCB_MASK) != ASF_PCB_END && jiffies < timeout);

            if (jiffies >= timeout)
                TIMEOUT_MSG();

            /* woops, the last "data" byte was really the length! */
            total_length = pcb->data.raw[--i];

            /* safety check total length vs data length */
            if (total_length != (pcb->length + 2)) {
                if (elp_debug >= 2)
                    printk("%s: mangled PCB received\n", adapter->name);
                SET_HSF(HSF_PCB_NAK);
                return FALSE;
            }

            SET_HSF(HSF_PCB_ACK);
            return TRUE;
        }
    }

    SET_HSF(HSF_PCB_NAK);
    return FALSE;
}