예제 #1
0
/*
 * TX/RX related routines.
 */
static int rt2x00_start_xmit(struct rtskb *rtskb, struct rtnet_device *rtnet_dev) {

    struct rtwlan_device	* rtwlan_dev = rtnetdev_priv(rtnet_dev);
    struct _rt2x00_core		* core   = rtwlan_priv(rtwlan_dev);
    u16				xmit_flags = 0x0000;
    u8				rate = 0x00;

    if (unlikely(rtskb)) {

        rate = core->config.bitrate;
        if(ieee80211_is_ofdm_rate(rate))
            xmit_flags |= XMIT_OFDM;

        /* Check if the packet should be acknowledged */
        if(core->rtwlan_dev->mode == RTWLAN_TXMODE_ACK)
            xmit_flags |= XMIT_ACK;

        if(core->handler->dev_xmit_packet(core, rtskb, rate, xmit_flags)) 
            ERROR("Packet dropped !");

        dev_kfree_rtskb(rtskb);
    }
  
    return 0;
}
예제 #2
0
파일: rt_fec.c 프로젝트: hiddeate2m/rtnet
static void
fec_stop(struct rtnet_device *ndev)
{
	struct fec_enet_private *fep = rtnetdev_priv(ndev);
	const struct platform_device_id *id_entry =
				platform_get_device_id(fep->pdev);
	u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);

	/* We cannot expect a graceful transmit stop without link !!! */
	if (fep->link) {
		writel(1, fep->hwp + FEC_X_CNTRL); /* Graceful transmit stop */
		udelay(10);
		if (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_GRA))
			printk("fec_stop : Graceful transmit stop did not complete !\n");
	}

	/* Whack a reset.  We should wait for this. */
	writel(1, fep->hwp + FEC_ECNTRL);
	udelay(10);
	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);

	/* We have to keep ENET enabled to have MII interrupt stay working */
	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
		writel(2, fep->hwp + FEC_ECNTRL);
		writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
	}
}
예제 #3
0
void rt2x00_core_remove(struct rtnet_device * rtnet_dev) {

    struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev);

    rtskb_pool_release(&rtwlan_dev->skb_pool);
    rt_unregister_rtnetdev(rtnet_dev);
    rt_rtdev_disconnect(rtnet_dev);

    rtdev_free(rtnet_dev);
  
}
예제 #4
0
파일: rt_fec.c 프로젝트: hiddeate2m/rtnet
/* ------------------------------------------------------------------------- */
static void __inline__ fec_get_mac(struct rtnet_device *ndev)
{
	struct fec_enet_private *fep = rtnetdev_priv(ndev);
	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
	unsigned char *iap, tmpaddr[ETH_ALEN];

	/*
	 * try to get mac address in following order:
	 *
	 * 1) module parameter via kernel command line in form
	 *    fec.macaddr=0x00,0x04,0x9f,0x01,0x30,0xe0
	 */
	iap = macaddr;

#ifdef CONFIG_OF
	/*
	 * 2) from device tree data
	 */
	if (!is_valid_ether_addr(iap)) {
		struct device_node *np = fep->pdev->dev.of_node;
		if (np) {
			const char *mac = of_get_mac_address(np);
			if (mac)
				iap = (unsigned char *) mac;
		}
	}
#endif

	/*
	 * 3) from flash or fuse (via platform data)
	 */
	if (!is_valid_ether_addr(iap)) {
#ifdef CONFIG_M5272
		if (FEC_FLASHMAC)
			iap = (unsigned char *)FEC_FLASHMAC;
#else
		if (pdata)
			iap = (unsigned char *)&pdata->mac;
#endif
	}

	/*
	 * 4) FEC mac registers set by bootloader
	 */
	if (!is_valid_ether_addr(iap)) {
		*((unsigned long *) &tmpaddr[0]) =
			be32_to_cpu(readl(fep->hwp + FEC_ADDR_LOW));
		*((unsigned short *) &tmpaddr[4]) =
			be16_to_cpu(readl(fep->hwp + FEC_ADDR_HIGH) >> 16);
		iap = &tmpaddr[0];
	}
예제 #5
0
static void rt2x00_interrupt_rxdone(struct _data_ring * ring, nanosecs_t *time_stamp) {

    struct _rt2x00_pci	 * rt2x00pci  = rt2x00_priv(ring->device);
    struct rtnet_device  * rtnet_dev  = ring->device->rtnet_dev; 
    struct rtwlan_device * rtwlan     = rtnetdev_priv(rtnet_dev);
    struct _rxd		 * rxd = NULL;
    struct rtskb         * rtskb;
    void		 * data = NULL;
    u16			   size = 0x0000;
    /*    u16                    rssi = 0x0000; */

    while(1){

        rxd = DESC_ADDR(ring);
        data = DATA_ADDR(ring);

        if(rt2x00_get_field32(rxd->word0, RXD_W0_OWNER_NIC))
            break;

        size = rt2x00_get_field32(rxd->word0, RXD_W0_DATABYTE_COUNT);
        /*	rssi = rt2x00_get_field32(rxd->word2, RXD_W2_RSSI); */

        /* prepare rtskb */
        rtskb = dev_alloc_rtskb(size + NET_IP_ALIGN, &rtwlan->skb_pool);
        if(!rtskb){
            ERROR("Couldn't allocate rtskb, packet dropped.\n");
            break;
        }
        rtskb->rtdev = rtnet_dev;
        rtskb->time_stamp = *time_stamp;
        rtskb_reserve(rtskb, NET_IP_ALIGN);

        memcpy(rtskb->data, data, size);
        rtskb_put(rtskb, size);

        /* give incoming frame to rtwlan stack */
        rtwlan_rx(rtskb, rtnet_dev);

        /* forward rtskb to rtnet */
        rtnetif_rx(rtskb);

        rtwlan->stats.rx_packets++;

        rt2x00_set_field32(&rxd->word0, RXD_W0_OWNER_NIC, 1);
        rt2x00_ring_index_inc(&rt2x00pci->rx);
    }
}
예제 #6
0
/*
 * Interrupt routines.
 * rt2x00_interrupt_txdone processes all transmitted packetss results.
 * rt2x00_interrupt_rxdone processes all received rx packets.
 */
static void rt2x00_interrupt_txdone(struct _data_ring * ring) {

    struct rtwlan_device * rtwlan     = rtnetdev_priv(ring->device->rtnet_dev);
    struct _txd		 *txd         = NULL;
    u8			tx_result     = 0x00;
    /*    u8			retry_count = 0x00; */


    do{
        txd = DESC_ADDR_DONE(ring);
	
        if(rt2x00_get_field32(txd->word0, TXD_W0_OWNER_NIC)
           || !rt2x00_get_field32(txd->word0, TXD_W0_VALID))
            break;

        if(ring->ring_type == RING_TX){
            tx_result = rt2x00_get_field32(txd->word0, TXD_W0_RESULT);
            /*	    retry_count = rt2x00_get_field32(txd->word0, TXD_W0_RETRY_COUNT); */

            switch(tx_result) {
            case TX_SUCCESS:
                rtwlan->stats.tx_packets++;
                break;
            case TX_SUCCESS_RETRY:
                rtwlan->stats.tx_retry++;
                break;
            case TX_FAIL_RETRY:
                DEBUG("TX_FAIL_RETRY.\n");
                break;
            case TX_FAIL_INVALID:
                DEBUG("TX_FAIL_INVALID.\n");
                break;
            case TX_FAIL_OTHER:
                DEBUG("TX_FAIL_OTHER.\n");
                break;
            default:
                DEBUG("Unknown tx result.\n");
            }
        }

        rt2x00_set_field32(&txd->word0, TXD_W0_VALID, 0);

        rt2x00_ring_index_done_inc(ring);
    }while(!rt2x00_ring_empty(ring));
}
예제 #7
0
파일: rt_fec.c 프로젝트: hiddeate2m/rtnet
static int
fec_enet_interrupt(rtdm_irq_t *irq_handle)
{
	struct rtnet_device *ndev =
		rtdm_irq_get_arg(irq_handle, struct rtnet_device); /* RTnet */
	struct fec_enet_private *fep = rtnetdev_priv(ndev);
	uint int_events;
	irqreturn_t ret = RTDM_IRQ_NONE;
	/* RTnet */
	nanosecs_abs_t time_stamp = rtdm_clock_read();
	int packets = 0;

	do {
		int_events = readl(fep->hwp + FEC_IEVENT);
		writel(int_events, fep->hwp + FEC_IEVENT);

		if (int_events & FEC_ENET_RXF) {
			ret = RTDM_IRQ_HANDLED;
			fec_enet_rx(ndev, &packets, &time_stamp);
		}

		/* Transmit OK, or non-fatal error. Update the buffer
		 * descriptors. FEC handles all errors, we just discover
		 * them as part of the transmit process.
		 */
		if (int_events & FEC_ENET_TXF) {
			ret = RTDM_IRQ_HANDLED;
			fec_enet_tx(ndev);
		}

		if (int_events & FEC_ENET_MII) {
			ret = RTDM_IRQ_HANDLED;
			rtdm_nrtsig_pend(&fep->mdio_done_sig);
		}
	} while (int_events);

	if (packets > 0)
		rt_mark_stack_mgr(ndev);

	return ret;
}
예제 #8
0
int rtwlan_rx(struct rtskb * rtskb, struct rtnet_device * rtnet_dev)
{
    struct rtwlan_device * rtwlan = rtnetdev_priv(rtnet_dev);
    struct ieee80211_hdr  * hdr = (struct ieee80211_hdr *)rtskb->data;
    u16 fc = le16_to_cpu(hdr->frame_ctl);

    switch(rtwlan->mode) {
        case RTWLAN_MODE_RAW:
        case RTWLAN_MODE_ACK:
            rtskb_pull(rtskb, ieee80211_get_hdrlen(fc));
            rtskb->protocol = rt_eth_type_trans (rtskb, rtnet_dev);
            break;

        case RTWLAN_MODE_MON:
            rtskb->mac.raw = rtskb->data;
            rtcap_mark_incoming(rtskb);
            break;
    }

    return 0;
}
예제 #9
0
/***
 *  rt2x00_close
 *  @rtdev
 */
static int rt2x00_close (struct rtnet_device *rtnet_dev) {

    struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev);
    struct _rt2x00_core  * core   = rtwlan_priv(rtwlan_dev);

    DEBUG("Start.\n");

    if(!test_and_clear_bit(DEVICE_ENABLED, &core->flags)){
        ERROR("device already disabled.\n");
        return -EBUSY;
    }

    rt2x00_radio_off(core);

    rtnetif_stop_queue(rtnet_dev);
    rt_stack_disconnect(rtnet_dev);

    RTNET_MOD_DEC_USE_COUNT;

    return 0;
}
예제 #10
0
int rt2x00_interrupt(rtdm_irq_t *irq_handle) {

    nanosecs_t time_stamp = rtdm_clock_read();

    struct rtnet_device   * rtnet_dev = rtdm_irq_get_arg(irq_handle, struct rtnet_device);
    struct _rt2x00_device * device    = rtwlan_priv(rtnet_dev);
    struct _rt2x00_pci	  * rt2x00pci = rt2x00_priv(device);
    struct rtwlan_device  * rtwlan    = rtnetdev_priv(rtnet_dev);
    unsigned int old_packet_cnt       = rtwlan->stats.rx_packets;
    u32			reg           = 0x00000000;
    rtdm_lockctx_t context;

    rtdm_lock_get_irqsave(&rtwlan->lock, context);

    rt2x00_register_read(rt2x00pci, CSR7, &reg);
    rt2x00_register_write(rt2x00pci, CSR7, reg);

    if(!reg)
        return RTDM_IRQ_NONE;

    if(rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))		/* Beacon timer expired interrupt. */
        DEBUG("Beacon timer expired.\n");
    if(rt2x00_get_field32(reg, CSR7_RXDONE))		/* Rx ring done interrupt. */
        rt2x00_interrupt_rxdone(&rt2x00pci->rx, &time_stamp);
    if(rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))	/* Atim ring transmit done interrupt. */
        DEBUG("AtimTxDone.\n");
    if(rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))	/* Priority ring transmit done interrupt. */
        DEBUG("PrioTxDone.\n");
    if(rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))	/* Tx ring transmit done interrupt. */
        rt2x00_interrupt_txdone(&rt2x00pci->tx);

    if (old_packet_cnt != rtwlan->stats.rx_packets)
        rt_mark_stack_mgr(rtnet_dev);

    rtdm_lock_put_irqrestore(&rtwlan->lock, context);

    return RTDM_IRQ_HANDLED;
}
예제 #11
0
/***
 *  rt2x00_open
 *  @rtdev
 */
static int rt2x00_open (struct rtnet_device *rtnet_dev) {

    struct rtwlan_device * rtwlan_dev = rtnetdev_priv(rtnet_dev);
    struct _rt2x00_core  * core   = rtwlan_priv(rtwlan_dev);
    int			  status  = 0x00000000;

    DEBUG("Start.\n");

    if(test_and_set_bit(DEVICE_ENABLED, &core->flags)){
        ERROR("device already enabled.\n");
        return -EBUSY;
    }

    /*
     * Start rtnet interface.
     */
    rt_stack_connect(rtnet_dev, &STACK_manager);

    status = rt2x00_radio_on(core);
    if(status){
        clear_bit(DEVICE_ENABLED, &core->flags);
        ERROR("Couldn't activate radio.\n");
        return status;
    }

    core->config.led_status = 1;
    core->config.update_flags |= UPDATE_LED_STATUS;
    rt2x00_update_config(core);
  
    rtnetif_start_queue(rtnet_dev);

    RTNET_MOD_INC_USE_COUNT;

    DEBUG("Exit success.\n");

    return 0;
}
예제 #12
0
int rtwlan_tx(struct rtskb *rtskb, struct rtnet_device *rtnet_dev)
{
    struct rtwlan_device * rtwlan = rtnetdev_priv(rtnet_dev);
    struct ieee80211_hdr_3addr header = {	/* Ensure zero initialized */
        .duration_id = 0,
        .seq_ctl = 0
    };
    u8 dest[ETH_ALEN], src[ETH_ALEN];

    /* Save source and destination addresses */
    memcpy(dest, rtskb->data, ETH_ALEN);
    memcpy(src, rtskb->data + ETH_ALEN, ETH_ALEN);

    /* Generate ieee80211 compatible header */
    memcpy(header.addr3, src, ETH_ALEN);	/* BSSID */
    memcpy(header.addr2, src, ETH_ALEN);	/* SA */
    memcpy(header.addr1, dest, ETH_ALEN);	/* DA */

    /* Frame Control */
    switch(rtwlan->mode) {
        case RTWLAN_MODE_RAW:
            header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
            break;

        case RTWLAN_MODE_ACK:
            header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
            break;

        default:
            return -1;
    }

    memcpy(rtskb_push(rtskb, IEEE80211_3ADDR_LEN), &header, IEEE80211_3ADDR_LEN);

    return 0;
}

EXPORT_SYMBOL(rtwlan_tx);


/**
 * rtalloc_wlandev - Allocates and sets up a wlan device
 * @sizeof_priv: size of additional driver-private structure to
 *               be allocated for this wlan device
 *
 * Fill in the fields of the device structure with wlan-generic
 * values. Basically does everything except registering the device.
 *
 * A 32-byte alignment is enforced for the private data area.
 */

struct rtnet_device * rtwlan_alloc_dev(int sizeof_priv)
{
    struct rtnet_device *rtnet_dev;

    RTWLAN_DEBUG("Start.\n");

    rtnet_dev = rt_alloc_etherdev(sizeof(struct rtwlan_device) + sizeof_priv);
    if (!rtnet_dev)
        return NULL;

    rtdev_alloc_name(rtnet_dev, "rtwlan%d");

    return rtnet_dev;
}

EXPORT_SYMBOL(rtwlan_alloc_dev);


int rtwlan_ioctl(struct rtnet_device * rtdev,
                 unsigned int request,
                 unsigned long arg)
{
    struct rtwlan_cmd cmd;
    int ret=0;

    if (copy_from_user(&cmd, (void *)arg, sizeof(cmd)) != 0)
        return -EFAULT;

    switch(request) {
        case IOC_RTWLAN_IFINFO:
            if (cmd.args.info.ifindex > 0)
                rtdev = rtdev_get_by_index(cmd.args.info.ifindex);
            else
                rtdev = rtdev_get_by_name(cmd.head.if_name);
            if (rtdev == NULL)
                return -ENODEV;

            if (down_interruptible(&rtdev->nrt_lock)) {
                rtdev_dereference(rtdev);
                return -ERESTARTSYS;
            }

            if (rtdev->do_ioctl)
                ret = rtdev->do_ioctl(rtdev, request, &cmd);
            else 
                ret = -ENORTWLANDEV;

            memcpy(cmd.head.if_name, rtdev->name, IFNAMSIZ);
            cmd.args.info.ifindex      = rtdev->ifindex;
            cmd.args.info.flags        = rtdev->flags;

            up(&rtdev->nrt_lock);

            rtdev_dereference(rtdev);

            break;

        case IOC_RTWLAN_MODE:
        case IOC_RTWLAN_BITRATE:
        case IOC_RTWLAN_CHANNEL:
        case IOC_RTWLAN_TXPOWER:
        case IOC_RTWLAN_DROPBCAST:
        case IOC_RTWLAN_DROPMCAST:
        case IOC_RTWLAN_REGREAD:
        case IOC_RTWLAN_REGWRITE:
        case IOC_RTWLAN_BBPWRITE:
        case IOC_RTWLAN_BBPREAD:
        case IOC_RTWLAN_BBPSENS:
            if (down_interruptible(&rtdev->nrt_lock))
                return -ERESTARTSYS;

            if (rtdev->do_ioctl)
                ret = rtdev->do_ioctl(rtdev, request, &cmd);
            else
                ret = -ENORTWLANDEV;

            up(&rtdev->nrt_lock);

            break;

        default:
            ret = -ENOTTY;
    }

    if (copy_to_user((void *)arg, &cmd, sizeof(cmd)) != 0)
        return -EFAULT;

    return ret;
}


struct rtnet_ioctls rtnet_wlan_ioctls = {
    service_name: "rtwlan ioctl",
    ioctl_type: RTNET_IOC_TYPE_RTWLAN,
    handler: rtwlan_ioctl
};
예제 #13
0
파일: rt_fec.c 프로젝트: hiddeate2m/rtnet
/* During a receive, the cur_rx points to the current incoming buffer.
 * When we update through the ring, if the next incoming buffer has
 * not been given to the system, we just set the empty indicator,
 * effectively tossing the packet.
 */
static void
fec_enet_rx(struct rtnet_device *ndev, int *packets, nanosecs_abs_t *time_stamp)
{
	struct fec_enet_private *fep = rtnetdev_priv(ndev);
	const struct platform_device_id *id_entry =
				platform_get_device_id(fep->pdev);
	struct bufdesc *bdp;
	unsigned short status;
	struct	rtskb	*skb;
	ushort	pkt_len;
	__u8 *data;

#ifdef CONFIG_M532x
	flush_cache_all();
#endif
	rtdm_lock_get(&fep->hw_lock);

	/* First, grab all of the stats for the incoming packet.
	 * These get messed up if we get called due to a busy condition.
	 */
	bdp = fep->cur_rx;

	while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {

		/* Since we have allocated space to hold a complete frame,
		 * the last indicator should be set.
		 */
		if ((status & BD_ENET_RX_LAST) == 0)
			printk("FEC ENET: rcv is not +last\n");

		if (!fep->opened)
			goto rx_processing_done;

		/* Check for errors. */
		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
			fep->stats.rx_errors++;
			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
				/* Frame too long or too short. */
				fep->stats.rx_length_errors++;
			}
			if (status & BD_ENET_RX_NO)	/* Frame alignment */
				fep->stats.rx_frame_errors++;
			if (status & BD_ENET_RX_CR)	/* CRC Error */
				fep->stats.rx_crc_errors++;
			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
				fep->stats.rx_fifo_errors++;
		}

		/* Report late collisions as a frame error.
		 * On this error, the BD is closed, but we don't know what we
		 * have in the buffer.  So, just drop this frame on the floor.
		 */
		if (status & BD_ENET_RX_CL) {
			fep->stats.rx_errors++;
			fep->stats.rx_frame_errors++;
			goto rx_processing_done;
		}

		/* Process the incoming frame. */
		fep->stats.rx_packets++;
		pkt_len = bdp->cbd_datlen;
		fep->stats.rx_bytes += pkt_len;
		data = (__u8*)__va(bdp->cbd_bufaddr);

		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);

		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
			swap_buffer(data, pkt_len);

		/* This does 16 byte alignment, exactly what we need.
		 * The packet length includes FCS, but we don't want to
		 * include that when passing upstream as it messes up
		 * bridging applications.
		 */
		skb = dev_alloc_rtskb(pkt_len - 4 + NET_IP_ALIGN,
				      &fep->skb_pool); /* RTnet */

		if (unlikely(!skb)) {
			printk("%s: Memory squeeze, dropping packet.\n",
					ndev->name);
			fep->stats.rx_dropped++;
		} else {
			rtskb_reserve(skb, NET_IP_ALIGN);
			rtskb_put(skb, pkt_len - 4);	/* Make room */
			memcpy(skb->data, data, pkt_len - 4);
			skb->protocol = rt_eth_type_trans(skb, ndev);
			skb->rtdev = ndev;
			skb->time_stamp = *time_stamp;
			rtnetif_rx(skb);
			(*packets)++; /* RTnet */
		}

		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
rx_processing_done:
		/* Clear the status flags for this buffer */
		status &= ~BD_ENET_RX_STATS;

		/* Mark the buffer empty */
		status |= BD_ENET_RX_EMPTY;
		bdp->cbd_sc = status;

		/* Update BD pointer to next entry */
		if (status & BD_ENET_RX_WRAP)
			bdp = fep->rx_bd_base;
		else
			bdp++;
		/* Doing this here will keep the FEC running while we process
		 * incoming frames.  On a heavily loaded network, we should be
		 * able to keep up at the expense of system resources.
		 */
		writel(0, fep->hwp + FEC_R_DES_ACTIVE);
	}
	fep->cur_rx = bdp;

	rtdm_lock_put(&fep->hw_lock);
}
예제 #14
0
파일: rt_fec.c 프로젝트: hiddeate2m/rtnet
/* This function is called to start or restart the FEC during a link
 * change.  This only happens when switching between half and full
 * duplex.
 */
static void
fec_restart(struct rtnet_device *ndev, int duplex)
{
	struct fec_enet_private *fep = rtnetdev_priv(ndev);
	const struct platform_device_id *id_entry =
				platform_get_device_id(fep->pdev);
	int i;
	u32 temp_mac[2];
	u32 rcntl = OPT_FRAME_SIZE | 0x04;
	u32 ecntl = 0x2; /* ETHEREN */

	/* Whack a reset.  We should wait for this. */
	writel(1, fep->hwp + FEC_ECNTRL);
	udelay(10);

	/*
	 * enet-mac reset will reset mac address registers too,
	 * so need to reconfigure it.
	 */
	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
		memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
	}

	/* Clear any outstanding interrupt. */
	writel(0xffc00000, fep->hwp + FEC_IEVENT);

	/* Reset all multicast.	*/
	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
#ifndef CONFIG_M5272
	writel(0, fep->hwp + FEC_HASH_TABLE_HIGH);
	writel(0, fep->hwp + FEC_HASH_TABLE_LOW);
#endif

	/* Set maximum receive buffer size. */
	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);

	/* Set receive and transmit descriptor base. */
	writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
	writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) * RX_RING_SIZE,
			fep->hwp + FEC_X_DES_START);

	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
	fep->cur_rx = fep->rx_bd_base;

	/* Reset SKB transmit buffers. */
	fep->skb_cur = fep->skb_dirty = 0;
	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
		if (fep->tx_skbuff[i]) {
			dev_kfree_rtskb(fep->tx_skbuff[i]);
			fep->tx_skbuff[i] = NULL;
		}
	}

	/* Enable MII mode */
	if (duplex) {
		/* FD enable */
		writel(0x04, fep->hwp + FEC_X_CNTRL);
	} else {
		/* No Rcv on Xmit */
		rcntl |= 0x02;
		writel(0x0, fep->hwp + FEC_X_CNTRL);
	}

	fep->full_duplex = duplex;

	/* Set MII speed */
	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);

	/*
	 * The phy interface and speed need to get configured
	 * differently on enet-mac.
	 */
	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
		/* Enable flow control and length check */
		rcntl |= 0x40000000 | 0x00000020;

		/* RGMII, RMII or MII */
		if (fep->phy_interface == PHY_INTERFACE_MODE_RGMII)
			rcntl |= (1 << 6);
		else if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
			rcntl |= (1 << 8);
		else
			rcntl &= ~(1 << 8);

		/* 1G, 100M or 10M */
		if (fep->phy_dev) {
			if (fep->phy_dev->speed == SPEED_1000)
				ecntl |= (1 << 5);
			else if (fep->phy_dev->speed == SPEED_100)
				rcntl &= ~(1 << 9);
			else
				rcntl |= (1 << 9);
		}
	} else {
#ifdef FEC_MIIGSK_ENR
		if (id_entry->driver_data & FEC_QUIRK_USE_GASKET) {
			u32 cfgr;
			/* disable the gasket and wait */
			writel(0, fep->hwp + FEC_MIIGSK_ENR);
			while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
				udelay(1);

			/*
			 * configure the gasket:
			 *   RMII, 50 MHz, no loopback, no echo
			 *   MII, 25 MHz, no loopback, no echo
			 */
			cfgr = (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
				? BM_MIIGSK_CFGR_RMII : BM_MIIGSK_CFGR_MII;
			if (fep->phy_dev && fep->phy_dev->speed == SPEED_10)
				cfgr |= BM_MIIGSK_CFGR_FRCONT_10M;
			writel(cfgr, fep->hwp + FEC_MIIGSK_CFGR);

			/* re-enable the gasket */
			writel(2, fep->hwp + FEC_MIIGSK_ENR);
		}
#endif
	}
	writel(rcntl, fep->hwp + FEC_R_CNTRL);

	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
		/* enable ENET endian swap */
		ecntl |= (1 << 8);
		/* enable ENET store and forward mode */
		writel(1 << 8, fep->hwp + FEC_X_WMRK);
	}

	/* And last, enable the transmit and receive processing */
	writel(ecntl, fep->hwp + FEC_ECNTRL);
	writel(0, fep->hwp + FEC_R_DES_ACTIVE);

	/* Enable interrupts we wish to service */
	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
}
예제 #15
0
파일: rt_fec.c 프로젝트: hiddeate2m/rtnet
static int
fec_enet_start_xmit(struct rtskb *skb, struct rtnet_device *ndev)
{
	struct fec_enet_private *fep = rtnetdev_priv(ndev);
	const struct platform_device_id *id_entry =
				platform_get_device_id(fep->pdev);
	struct bufdesc *bdp;
	void *bufaddr;
	unsigned short	status;
	unsigned long context;

	if (!fep->link) {
		/* Link is down or autonegotiation is in progress. */
		printk("%s: tx link down!.\n", ndev->name);
		rtnetif_stop_queue(ndev);
		return 1;	/* RTnet: will call kfree_rtskb() */
	}

	rtdm_lock_get_irqsave(&fep->hw_lock, context);

	/* RTnet */
	if (skb->xmit_stamp)
		*skb->xmit_stamp = cpu_to_be64(rtdm_clock_read() +
					       *skb->xmit_stamp);

	/* Fill in a Tx ring entry */
	bdp = fep->cur_tx;

	status = bdp->cbd_sc;

	if (status & BD_ENET_TX_READY) {
		/* Ooops.  All transmit buffers are full.  Bail out.
		 * This should not happen, since ndev->tbusy should be set.
		 */
		printk("%s: tx queue full!.\n", ndev->name);
		rtdm_lock_put_irqrestore(&fep->hw_lock, context);
		return 1;	/* RTnet: will call kfree_rtskb() */
	}

	/* Clear all of the status flags */
	status &= ~BD_ENET_TX_STATS;

	/* Set buffer length and buffer pointer */
	bufaddr = skb->data;
	bdp->cbd_datlen = skb->len;

	/*
	 * On some FEC implementations data must be aligned on
	 * 4-byte boundaries. Use bounce buffers to copy data
	 * and get it aligned. Ugh.
	 */
	if (((unsigned long) bufaddr) & FEC_ALIGNMENT) {
		unsigned int index;
		index = bdp - fep->tx_bd_base;
		memcpy(fep->tx_bounce[index], skb->data, skb->len);
		bufaddr = fep->tx_bounce[index];
	}

	/*
	 * Some design made an incorrect assumption on endian mode of
	 * the system that it's running on. As the result, driver has to
	 * swap every frame going to and coming from the controller.
	 */
	if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
		swap_buffer(bufaddr, skb->len);

	/* Save skb pointer */
	fep->tx_skbuff[fep->skb_cur] = skb;

	fep->stats.tx_bytes += skb->len;
	fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;

	/* Push the data cache so the CPM does not get stale memory
	 * data.
	 */
	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
			FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);

	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
	 * it's the last BD of the frame, and to put the CRC on the end.
	 */
	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
	bdp->cbd_sc = status;

	/* Trigger transmission start */
	writel(0, fep->hwp + FEC_X_DES_ACTIVE);

	/* If this was the last BD in the ring, start at the beginning again. */
	if (status & BD_ENET_TX_WRAP)
		bdp = fep->tx_bd_base;
	else
		bdp++;

	if (bdp == fep->dirty_tx) {
		fep->tx_full = 1;
		rtnetif_stop_queue(ndev);
	}

	fep->cur_tx = bdp;

	rtdm_lock_put_irqrestore(&fep->hw_lock, context);

	return NETDEV_TX_OK;
}
예제 #16
0
struct rtnet_device * rt2x00_core_probe(struct _rt2x00_dev_handler * handler, 
					void * priv, 
					u32 sizeof_dev) {

    struct rtnet_device	 * rtnet_dev  = NULL;
    struct _rt2x00_core	 * core       = NULL;
    struct rtwlan_device * rtwlan_dev = NULL;
    static int cards_found = -1;
    int err;

    DEBUG("Start.\n");

    cards_found++;
    if (cards[cards_found] == 0)
        goto exit;

    rtnet_dev = rtwlan_alloc_dev(sizeof_dev + sizeof(*core));
    if(!rtnet_dev)
        goto exit;

    rt_rtdev_connect(rtnet_dev, &RTDEV_manager);
    RTNET_SET_MODULE_OWNER(rtnet_dev);
    rtnet_dev->vers = RTDEV_VERS_2_0;

    rtwlan_dev = rtnetdev_priv(rtnet_dev);
    memset(rtwlan_dev, 0x00, sizeof(*rtwlan_dev));

    core = rtwlan_priv(rtwlan_dev);
    memset(core, 0x00, sizeof(*core));

    core->rtwlan_dev = rtwlan_dev;
    core->handler = handler;
    core->priv = (void*)core + sizeof(*core);
    core->rtnet_dev = rtnet_dev;  

    if (rtskb_pool_init(&core->rtwlan_dev->skb_pool, RX_ENTRIES*2) < RX_ENTRIES*2) {
        rtskb_pool_release(&core->rtwlan_dev->skb_pool);
        ERROR("rtskb_pool_init failed.\n");
        goto exit;
    }

    /* Set configuration default values. */
    rt2x00_init_config(core);

    if(core->handler->dev_probe
       && core->handler->dev_probe(core, priv)){
        ERROR("device probe failed.\n");
        goto exit;
    }
    INFO("Device " MAC_FMT " detected.\n", MAC_ARG(rtnet_dev->dev_addr));

    rtwlan_dev->hard_start_xmit = rt2x00_start_xmit;

    rtnet_dev->open = &rt2x00_open;
    rtnet_dev->stop = &rt2x00_close;
    rtnet_dev->do_ioctl = &rt2x00_ioctl;
    rtnet_dev->hard_header = &rt_eth_header;

    if ((err = rt_register_rtnetdev(rtnet_dev)) != 0) {
        rtdev_free(rtnet_dev);
        ERROR("rtnet_device registration failed.\n");
        printk("err=%d\n", err);
        goto exit_dev_remove;
    }
    
    set_bit(DEVICE_AWAKE, &core->flags);

    return rtnet_dev;

  exit_dev_remove:
    if(core->handler->dev_remove)
        core->handler->dev_remove(core);

  exit:
    return NULL; 
}
예제 #17
0
파일: rt_fec.c 프로젝트: hiddeate2m/rtnet
static void
fec_enet_tx(struct rtnet_device *ndev)
{
	struct	fec_enet_private *fep;
	struct bufdesc *bdp;
	unsigned short status;
	struct	rtskb	*skb;

	fep = rtnetdev_priv(ndev);
	rtdm_lock_get(&fep->hw_lock);
	bdp = fep->dirty_tx;

	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
		if (bdp == fep->cur_tx && fep->tx_full == 0)
			break;

		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
				FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
		bdp->cbd_bufaddr = 0;

		skb = fep->tx_skbuff[fep->skb_dirty];
		/* Check for errors. */
		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
				   BD_ENET_TX_RL | BD_ENET_TX_UN |
				   BD_ENET_TX_CSL)) {
			fep->stats.tx_errors++;
			if (status & BD_ENET_TX_HB)  /* No heartbeat */
				fep->stats.tx_heartbeat_errors++;
			if (status & BD_ENET_TX_LC)  /* Late collision */
				fep->stats.tx_window_errors++;
			if (status & BD_ENET_TX_RL)  /* Retrans limit */
				fep->stats.tx_aborted_errors++;
			if (status & BD_ENET_TX_UN)  /* Underrun */
				fep->stats.tx_fifo_errors++;
			if (status & BD_ENET_TX_CSL) /* Carrier lost */
				fep->stats.tx_carrier_errors++;
		} else {
			fep->stats.tx_packets++;
		}

		if (status & BD_ENET_TX_READY)
			printk("HEY! Enet xmit interrupt and TX_READY.\n");

		/* Deferred means some collisions occurred during transmit,
		 * but we eventually sent the packet OK.
		 */
		if (status & BD_ENET_TX_DEF)
			fep->stats.collisions++;

		/* Free the sk buffer associated with this last transmit */
		dev_kfree_rtskb(skb); /* RTnet */
		fep->tx_skbuff[fep->skb_dirty] = NULL;
		fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;

		/* Update pointer to next buffer descriptor to be transmitted */
		if (status & BD_ENET_TX_WRAP)
			bdp = fep->tx_bd_base;
		else
			bdp++;

		/* Since we have freed up a buffer, the ring is no longer full
		 */
		if (fep->tx_full) {
			fep->tx_full = 0;
			if (rtnetif_queue_stopped(ndev))
				rtnetif_wake_queue(ndev);
		}
	}
	fep->dirty_tx = bdp;
	rtdm_lock_put(&fep->hw_lock);
}
예제 #18
0
/*
 * user space io handler
 */
static int rt2x00_ioctl(struct rtnet_device * rtnet_dev, unsigned int request, void * arg) {

    struct rtwlan_device * rtwlan_dev  = rtnetdev_priv(rtnet_dev);
    struct _rt2x00_core * core     = rtwlan_priv(rtwlan_dev);
    struct rtwlan_cmd * cmd;
    u8 rate, dsss_rate, ofdm_rate;
    u32 address, value;

    cmd = (struct rtwlan_cmd *)arg;

    switch(request) {

    case IOC_RTWLAN_IFINFO:
        cmd->args.info.bitrate = core->config.bitrate;
        cmd->args.info.channel = core->config.channel;
        cmd->args.info.retry   = core->config.short_retry;
        cmd->args.info.txpower = core->config.txpower;
        cmd->args.info.bbpsens = core->config.bbpsens;
        cmd->args.info.mode    = core->rtwlan_dev->mode;
        cmd->args.info.rx_packets = core->rtwlan_dev->stats.rx_packets;
        cmd->args.info.tx_packets = core->rtwlan_dev->stats.tx_packets;
        cmd->args.info.tx_retry   = core->rtwlan_dev->stats.tx_retry;
        cmd->args.info.autoresponder = core->config.config_flags & CONFIG_AUTORESP ? 1 : 0;
        cmd->args.info.dropbcast = core->config.config_flags & CONFIG_DROP_BCAST ? 1 : 0;
        cmd->args.info.dropmcast = core->config.config_flags & CONFIG_DROP_MCAST ? 1 : 0;
	DEBUG("rtwlan_dev->mode=%d\n", rtwlan_dev->mode);
        break;
    case IOC_RTWLAN_BITRATE:
        rate = cmd->args.set.bitrate;
        ofdm_rate = ieee80211_is_ofdm_rate(rate);
        dsss_rate = ieee80211_is_dsss_rate(rate);
        DEBUG("bitrate=%d\n", rate);
        if(!(dsss_rate ^ ofdm_rate))
            NOTICE("Rate %d is not DSSS and not OFDM.\n", rate);
        core->config.bitrate = rate;
        core->config.update_flags |= UPDATE_BITRATE;
        break;
    case IOC_RTWLAN_CHANNEL:
        DEBUG("channel=%d\n", cmd->args.set.channel);
        core->config.channel = cmd->args.set.channel;
        core->config.update_flags |= UPDATE_CHANNEL;
        break;
    case IOC_RTWLAN_RETRY:
        core->config.short_retry = cmd->args.set.retry;
        core->config.update_flags |= UPDATE_RETRY;
        break;
    case IOC_RTWLAN_TXPOWER:
        core->config.txpower = cmd->args.set.txpower;
        core->config.update_flags |= UPDATE_TXPOWER;
        break;
    case IOC_RTWLAN_AUTORESP:
        if(cmd->args.set.autoresponder)
            core->config.config_flags |= CONFIG_AUTORESP;
        else
            core->config.config_flags &= ~CONFIG_AUTORESP;
        core->config.update_flags |= UPDATE_AUTORESP;
        break;
    case IOC_RTWLAN_DROPBCAST:
        if(cmd->args.set.dropbcast) 
            core->config.config_flags |= CONFIG_DROP_BCAST;
        else 
            core->config.config_flags &= ~CONFIG_DROP_BCAST;
        core->config.update_flags |= UPDATE_PACKET_FILTER;
        break;
    case IOC_RTWLAN_DROPMCAST:
        if(cmd->args.set.dropmcast)
            core->config.config_flags |= CONFIG_DROP_MCAST;
        else
            core->config.config_flags &= ~CONFIG_DROP_MCAST;
        core->config.update_flags |= UPDATE_PACKET_FILTER;
        break;
    case IOC_RTWLAN_TXMODE:
        core->rtwlan_dev->mode = cmd->args.set.mode;
        break;
    case IOC_RTWLAN_BBPSENS:
        value = cmd->args.set.bbpsens;
        if(value < 0)
            value = 0;
        if(value > 127)
            value = 127;
        core->config.bbpsens = value;
        core->config.update_flags |= UPDATE_BBPSENS;
        break;
    case IOC_RTWLAN_REGREAD:
    case IOC_RTWLAN_BBPREAD:
        address = cmd->args.reg.address;
        core->handler->dev_register_access(core, request, address, &value);
        cmd->args.reg.value = value;
        break;
    case IOC_RTWLAN_REGWRITE:
    case IOC_RTWLAN_BBPWRITE:
        address = cmd->args.reg.address;
        value = cmd->args.reg.value;
        core->handler->dev_register_access(core, request, address, &value) ;
        break;
    default:
        ERROR("Unknown request!\n");
        return -1;
    }

    if(request != IOC_RTWLAN_IFINFO)
        rt2x00_update_config(core);

    return 0;
}