/** Transmit packet over DMA, which comes from the Tx Queue */
static int ifx_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
    IFX_switch_priv_t *priv		= ifx_eth_fw_netdev_priv(dev);
    int len , rc = NETDEV_TX_OK;
    char *data;
    struct dma_device_info* dma_dev=g_dma_device;

    len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
    data = skb->data;
    priv->skb = skb;
    dev->trans_start = jiffies;
    /*select the tx channel*/
    dma_dev->current_tx_chan = ifx_select_tx_chan (skb, dev);
    if (dma_device_write(dma_dev, data, len, skb) != len ) {
        if (skb)
            dev_kfree_skb_any(skb);
        priv->stats.tx_errors++;
        priv->stats.tx_dropped++;
  /*      rc = NETDEV_TX_BUSY;  */
    } else {
        priv->stats.tx_packets++;
        priv->stats.tx_bytes+=len;
    }
    return rc;
}
Example #2
0
int ifxmips_mii_hw_tx(char *buf, int len, struct net_device *dev)
{
	int ret = 0;
	struct ifxmips_mii_priv *priv = dev->priv;
	struct dma_device_info *dma_dev = priv->dma_device;
	ret = dma_device_write(dma_dev, buf, len, priv->skb);
	return ret;
}
static void md5_transform(u32 *hash, u32 const *in)
{
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	int							i = 0;
	volatile register u32		tmp;
	unsigned long			    flag;
#ifndef ONLY_IN_MEM
	volatile struct deu_hash_t	*hashs = (struct hash_t *) HASH_START;
	volatile struct deu_dma_t	*dma = (struct deu_dma_t *) DMA_CON;
#else
	unsigned char				*prin = NULL;
	struct deu_hash_t			*hashs = NULL;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	hashs = (struct deu_hash_t *) kmalloc(sizeof(*hashs), GFP_KERNEL);
	memset(hashs, 0, sizeof(*hashs));
	prin = (unsigned char *) hashs;
#endif

	//printk("md5_transform running\n");

	local_irq_save(flag);

#ifndef CONFIG_CRYPTO_DEV_DANUBE_DMA	//dma or not
	asm("sync");
	for(i = 0; i < 16; i++)
	{
#ifdef DEBUG_MD5
		//printk("%u:%x    ",i,in[i]);
		printk("%u:%x\n", i, cpu_to_le32(in[i]));
#endif //DEBUG_MD5
		hashs->MR = cpu_to_le32(in[i]);
		asm("sync");
	};

	//wait for processing
	while(hashs->controlr.BSY)
	{
		// this will not take long
	}

#else //dma
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
	struct dma_device_info	*dma_device = ifx_deu[0].dma_device;
	_ifx_deu_device			*pDev = ifx_deu;
	/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

	pDev->len = sizeof(in);
	pDev->src = in;
	*DANUBE_DMA_PS = 1;
	*DANUBE_DMA_PCTRL |= (0x3 << 10);	//byte swapping
	while(dma->controlr.BSY)
	{
		// this will not take long
	}

	dma_device_write(dma_device, (u8 *) in, 64, NULL);
	udelay(10);

	while(dma->controlr.BSY)
	{
		// this will not take long
	}

	*DANUBE_DMA_PS = 1;
	*DANUBE_DMA_PCTRL &= ~(0x3 << 10);	//byte swapping deactivate
#endif

	local_irq_restore(flag);
}
/*! \fn void ifx_deu_aes_core (void *ctx_arg, u8 *out_arg, const u8 *in_arg, u8 *iv_arg, size_t nbytes, int encdec, int mode)
 *  \ingroup IFX_AES_FUNCTIONS
 *  \brief main interface to AES hardware
 *  \param ctx_arg crypto algo context  
 *  \param out_arg output bytestream  
 *  \param in_arg input bytestream   
 *  \param iv_arg initialization vector  
 *  \param nbytes length of bytestream  
 *  \param encdec 1 for encrypt; 0 for decrypt  
 *  \param mode operation mode such as ebc, cbc, ctr  
 *
*/                                 
void ifx_deu_aes_core (void *ctx_arg, u8 *out_arg, const u8 *in_arg,
        u8 *iv_arg, size_t nbytes, int encdec, int mode)
#endif

{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
    volatile struct aes_t *aes = (volatile struct aes_t *) AES_START;
    struct aes_ctx *ctx = (struct aes_ctx *)ctx_arg;
    u32 *in_key = ctx->buf;
    unsigned long flag;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
    int key_len = ctx->key_length;

#ifndef CONFIG_CRYPTO_DEV_DMA 
    int i = 0;
    int byte_cnt = nbytes; 

#else
    volatile struct deu_dma_t *dma = (struct deu_dma_t *) IFX_DEU_DMA_CON;
    struct dma_device_info *dma_device = ifx_deu[0].dma_device;
    //deu_drv_priv_t *deu_priv = (deu_drv_priv_t *)dma_device->priv;
    int wlen = 0;
    u32 *outcopy = NULL;
    u32 *dword_mem_aligned_in = NULL;

#ifdef CONFIG_CRYPTO_DEV_POLL_DMA
    u32 timeout = 0;
    u32 *out_dma = NULL;
#endif    
    
#endif

    CRTCL_SECT_START;
    /* 128, 192 or 256 bit key length */
    aes->controlr.K = key_len / 8 - 2;
        if (key_len == 128 / 8) {
        aes->K3R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 0));
        aes->K2R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 1));
        aes->K1R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 2));
        aes->K0R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 3));
    }
    else if (key_len == 192 / 8) {
        aes->K5R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 0));
        aes->K4R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 1));
        aes->K3R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 2));
        aes->K2R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 3));
        aes->K1R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 4));
        aes->K0R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 5));
    }
    else if (key_len == 256 / 8) {
        aes->K7R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 0));
        aes->K6R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 1));
        aes->K5R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 2));
        aes->K4R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 3));
        aes->K3R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 4));
        aes->K2R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 5));
        aes->K1R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 6));
        aes->K0R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 7));
    }
    else {
        printk (KERN_ERR "[%s %s %d]: Invalid key_len : %d\n", __FILE__, __func__, __LINE__, key_len);
        CRTCL_SECT_END;
        return;// -EINVAL;
    }

    /* let HW pre-process DEcryption key in any case (even if
       ENcryption is used). Key Valid (KV) bit is then only
       checked in decryption routine! */
    aes->controlr.PNK = 1;

#ifdef CONFIG_CRYPTO_DEV_DMA
    while (aes->controlr.BUS) {
        // this will not take long
    }
    AES_DMA_MISC_CONFIG();
#endif

    aes->controlr.E_D = !encdec;    //encryption
    aes->controlr.O = mode; //0 ECB 1 CBC 2 OFB 3 CFB 4 CTR 

    //aes->controlr.F = 128; //default; only for CFB and OFB modes; change only for customer-specific apps
    if (mode > 0) {
        aes->IV3R = DEU_ENDIAN_SWAP(*(u32 *) iv_arg);
        aes->IV2R = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 1));
        aes->IV1R = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 2));
        aes->IV0R = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 3));
    };


#ifndef CONFIG_CRYPTO_DEV_DMA
    i = 0;
    while (byte_cnt >= 16) {

        aes->ID3R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 0));
        aes->ID2R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 1));
        aes->ID1R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 2));
        aes->ID0R = INPUT_ENDIAN_SWAP(*((u32 *) in_arg + (i * 4) + 3));    /* start crypto */
        
        while (aes->controlr.BUS) {
            // this will not take long
        }

        *((volatile u32 *) out_arg + (i * 4) + 0) = aes->OD3R;
        *((volatile u32 *) out_arg + (i * 4) + 1) = aes->OD2R;
        *((volatile u32 *) out_arg + (i * 4) + 2) = aes->OD1R;
        *((volatile u32 *) out_arg + (i * 4) + 3) = aes->OD0R;

        i++;
        byte_cnt -= 16;
    }

#else // dma
   
    /* memory alignment issue */ 
    dword_mem_aligned_in = (u32 *) DEU_DWORD_REORDERING(in_arg, aes_buff_in, BUFFER_IN, nbytes);

    dma->controlr.ALGO = 1;   //AES
    dma->controlr.BS = 0;
    aes->controlr.DAU = 0;
    dma->controlr.EN = 1;

    while (aes->controlr.BUS) {
         // wait for AES to be ready
    };

    wlen = dma_device_write (dma_device, (u8 *)dword_mem_aligned_in, nbytes, NULL);
    if (wlen != nbytes) {
        dma->controlr.EN = 0;
        CRTCL_SECT_END;
        printk (KERN_ERR "[%s %s %d]: dma_device_write fail!\n", __FILE__, __func__, __LINE__);
        return; // -EINVAL;
    }

    WAIT_AES_DMA_READY();
    outcopy = (u32 *) DEU_DWORD_REORDERING(out_arg, aes_buff_out, BUFFER_OUT, nbytes);

#ifdef CONFIG_CRYPTO_DEV_POLL_DMA

    // polling DMA rx channel
    while ((dma_device_read (dma_device, (u8 **) &out_dma, NULL)) == 0) {
        timeout++;
        
        if (timeout >= 333000) {
            dma->controlr.EN = 0;
            CRTCL_SECT_END;
            printk (KERN_ERR "[%s %s %d]: timeout!!\n", __FILE__, __func__, __LINE__);
            return; // -EINVAL;
        }
    }

    WAIT_AES_DMA_READY();  
    AES_MEMORY_COPY(outcopy, out_dma, out_arg, nbytes); 
   
#else  
    /* Prepare Rx buf length used in dma psuedo interrupt */
    deu_priv->deu_rx_buf = out_arg;
    deu_priv->outcopy = outcopy; 
    deu_priv->deu_rx_len = nbytes;

    CRTCL_SECT_END;

    /* Sleep and wait for Rx finished */
    DEU_WAIT_EVENT(deu_priv->deu_thread_wait, DEU_EVENT, deu_priv->deu_event_flags);

    CRTCL_SECT_START;
#endif

#endif // dma

    //tc.chen : copy iv_arg back
    if (mode > 0) {
        *((u32 *) iv_arg) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg));
        *((u32 *) iv_arg + 1) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 1));             
        *((u32 *) iv_arg + 2) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 2));             
        *((u32 *) iv_arg + 3) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 3));              
    }

    CRTCL_SECT_END;
}
static int lq_deu_aes_core (void *ctx_arg, u8 *out_arg, const u8 *in_arg,
                            u8 *iv_arg, size_t nbytes, int encdec, int mode)
{
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
    volatile struct aes_t *aes = (volatile struct aes_t *) AES_START;
    struct aes_ctx *ctx = (struct aes_ctx *)ctx_arg;
    u32 *in_key = ctx->buf;
    unsigned long flag;
    /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
    int key_len = ctx->key_length;

    volatile struct deu_dma_t *dma = (struct deu_dma_t *) IFX_DEU_DMA_CON;
    struct dma_device_info *dma_device = ifx_deu[0].dma_device;
    deu_drv_priv_t *deu_priv = (deu_drv_priv_t *)dma_device->priv;
    int wlen = 0;
    //u32 *outcopy = NULL;
    u32 *dword_mem_aligned_in = NULL;

    CRTCL_SECT_START;

    /* 128, 192 or 256 bit key length */
    aes->controlr.K = key_len / 8 - 2;
        if (key_len == 128 / 8) {
        aes->K3R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 0));
        aes->K2R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 1));
        aes->K1R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 2));
        aes->K0R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 3));
    }
    else if (key_len == 192 / 8) {
        aes->K5R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 0));
        aes->K4R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 1));
        aes->K3R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 2));
        aes->K2R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 3));
        aes->K1R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 4));
        aes->K0R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 5));
    }
    else if (key_len == 256 / 8) {
        aes->K7R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 0));
        aes->K6R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 1));
        aes->K5R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 2));
        aes->K4R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 3));
        aes->K3R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 4));
        aes->K2R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 5));
        aes->K1R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 6));
        aes->K0R = DEU_ENDIAN_SWAP(*((u32 *) in_key + 7));
    }
    else {
        printk (KERN_ERR "[%s %s %d]: Invalid key_len : %d\n", __FILE__, __func__, __LINE__, key_len);
        CRTCL_SECT_END;
        return -EINVAL;
    }

    /* let HW pre-process DEcryption key in any case (even if
       ENcryption is used). Key Valid (KV) bit is then only
       checked in decryption routine! */
    aes->controlr.PNK = 1;

    while (aes->controlr.BUS) {
        // this will not take long
    }
    AES_DMA_MISC_CONFIG();

    aes->controlr.E_D = !encdec;    //encryption
    aes->controlr.O = mode; //0 ECB 1 CBC 2 OFB 3 CFB 4 CTR 

    //aes->controlr.F = 128; //default; only for CFB and OFB modes; change only for customer-specific apps
    if (mode > 0) {
        aes->IV3R = DEU_ENDIAN_SWAP(*(u32 *) iv_arg);
        aes->IV2R = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 1));
        aes->IV1R = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 2));
        aes->IV0R = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 3));
    };


    /* Prepare Rx buf length used in dma psuedo interrupt */
    deu_priv->deu_rx_buf = (u32 *)out_arg;
    deu_priv->deu_rx_len = nbytes;
   
    /* memory alignment issue */ 
    dword_mem_aligned_in = (u32 *) DEU_DWORD_REORDERING(in_arg, aes_buff_in, BUFFER_IN, nbytes);

    dma->controlr.ALGO = 1;   //AES
    dma->controlr.BS = 0;
    aes->controlr.DAU = 0;
    dma->controlr.EN = 1;

    while (aes->controlr.BUS) {
         // wait for AES to be ready
    };

    deu_priv->outcopy = (u32 *) DEU_DWORD_REORDERING(out_arg, aes_buff_out, BUFFER_OUT, nbytes);
    deu_priv->event_src = AES_ASYNC_EVENT;

    wlen = dma_device_write (dma_device, (u8 *)dword_mem_aligned_in, nbytes, NULL);
    if (wlen != nbytes) {
        dma->controlr.EN = 0;
        CRTCL_SECT_END;
        printk (KERN_ERR "[%s %s %d]: dma_device_write fail!\n", __FILE__, __func__, __LINE__);
        return -EINVAL;
    }

   // WAIT_AES_DMA_READY();

    CRTCL_SECT_END;

    if (mode > 0) {
        *((u32 *) iv_arg) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg));
        *((u32 *) iv_arg + 1) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 1));
        *((u32 *) iv_arg + 2) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 2));
        *((u32 *) iv_arg + 3) = DEU_ENDIAN_SWAP(*((u32 *) iv_arg + 3));
    }
   
    return -EINPROGRESS;	
}