⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fore200e.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
    if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {		down(&fore200e->rate_sf);	if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) {	    up(&fore200e->rate_sf);	    return -EAGAIN;	}	/* reserving the pseudo-CBR bandwidth at this point grants us	   to reduce the length of the critical section protected	   by 'rate_sf'. in counterpart, we have to reset the available	   bandwidth if we later encounter an error */	fore200e->available_cell_rate -= vcc->qos.txtp.max_pcr;	up(&fore200e->rate_sf);    }        fore200e_vcc = fore200e_kmalloc(sizeof(struct fore200e_vcc), GFP_KERNEL);    if (fore200e_vcc == NULL) {	down(&fore200e->rate_sf);	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;	up(&fore200e->rate_sf);	return -ENOMEM;    }    FORE200E_VCC(vcc) = fore200e_vcc;        if (fore200e_activate_vcin(fore200e, 1, vcc, vcc->qos.rxtp.max_sdu) < 0) {	kfree(fore200e_vcc);	down(&fore200e->rate_sf);	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;	up(&fore200e->rate_sf);	return -EBUSY;    }        /* compute rate control parameters */    if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {		fore200e_rate_ctrl(&vcc->qos, &fore200e_vcc->rate);	DPRINTK(3, "tx on %d.%d.%d:%d, tx PCR = %d, rx PCR = %d, data_cells = %u, idle_cells = %u\n",		vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),		vcc->qos.txtp.max_pcr, vcc->qos.rxtp.max_pcr, 		fore200e_vcc->rate.data_cells, fore200e_vcc->rate.idle_cells);    }        fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = 65536;    fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0;        set_bit(ATM_VF_READY, &vcc->flags);    return 0;}static voidfore200e_close(struct atm_vcc* vcc){    struct fore200e* fore200e = FORE200E_DEV(vcc->dev);        DPRINTK(2, "closing %d.%d.%d:%d\n", vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal));        fore200e_activate_vcin(fore200e, 0, vcc, 0);        kfree(FORE200E_VCC(vcc));	    if ((vcc->qos.txtp.traffic_class == ATM_CBR) && (vcc->qos.txtp.max_pcr > 0)) {	down(&fore200e->rate_sf);	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;	up(&fore200e->rate_sf);    }    clear_bit(ATM_VF_READY, &vcc->flags);}#if 0#define FORE200E_SYNC_SEND    /* wait tx completion before returning */#endifstatic intfore200e_send(struct atm_vcc *vcc, struct sk_buff *skb){    struct fore200e*       fore200e     = FORE200E_DEV(vcc->dev);    struct fore200e_vcc*   fore200e_vcc = FORE200E_VCC(vcc);    struct host_txq*       txq          = &fore200e->host_txq;    struct host_txq_entry* entry;    struct tpd*            tpd;    struct tpd_haddr       tpd_haddr;    //unsigned long          flags;    int                    retry        = CONFIG_ATM_FORE200E_TX_RETRY;    int                    tx_copy      = 0;    int                    tx_len       = skb->len;    u32*                   cell_header  = NULL;    unsigned char*         skb_data;    int                    skb_len;#ifdef FORE200E_52BYTE_AAL0_SDU    if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.txtp.max_sdu == ATM_AAL0_SDU)) {	cell_header = (u32*) skb->data;	skb_data    = skb->data + 4;    /* skip 4-byte cell header */	skb_len     = tx_len = skb->len  - 4;	DPRINTK(3, "skipping user-supplied cell header 0x%08x", *cell_header);    }    else #endif    {	skb_data = skb->data;	skb_len  = skb->len;    }      retry_here:        tasklet_disable(&fore200e->tasklet);    entry = &txq->host_entry[ txq->head ];        if (*entry->status != STATUS_FREE) {		/* try to free completed tx queue entries */	fore200e_irq_tx(fore200e);		if (*entry->status != STATUS_FREE) {	    	    tasklet_enable(&fore200e->tasklet);	    /* retry once again? */	    if(--retry > 0)		goto retry_here;	    	    atomic_inc(&vcc->stats->tx_err);	    	    printk(FORE200E "tx queue of device %s is saturated, PDU dropped - heartbeat is %08x\n",		   fore200e->name, fore200e->cp_queues->heartbeat);	    if (vcc->pop)		vcc->pop(vcc, skb);	    else		dev_kfree_skb(skb);	    return -EIO;	}    }    tpd = entry->tpd;    if (((unsigned long)skb_data) & 0x3) {	DPRINTK(2, "misaligned tx PDU on device %s\n", fore200e->name);	tx_copy = 1;	tx_len  = skb_len;    }    if ((vcc->qos.aal == ATM_AAL0) && (skb_len % ATM_CELL_PAYLOAD)) {	/* this simply NUKES the PCA-200E board */	DPRINTK(2, "incomplete tx AAL0 PDU on device %s\n", fore200e->name);	tx_copy = 1;	tx_len  = ((skb_len / ATM_CELL_PAYLOAD) + 1) * ATM_CELL_PAYLOAD;    }        if (tx_copy) {		entry->data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);	if (entry->data == NULL) {	    	    tasklet_enable(&fore200e->tasklet);	    if (vcc->pop)		vcc->pop(vcc, skb);	    else		dev_kfree_skb(skb);	    return -ENOMEM;	}	memcpy(entry->data, skb_data, skb_len);	if (skb_len < tx_len)	    memset(entry->data + skb_len, 0x00, tx_len - skb_len);		tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, entry->data, tx_len, FORE200E_DMA_TODEVICE);    }    else {	entry->data = NULL;	tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, skb_data, tx_len, FORE200E_DMA_TODEVICE);    }    tpd->tsd[ 0 ].length = tx_len;    FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);    txq->txing++;    tasklet_enable(&fore200e->tasklet);    /* ensure DMA synchronisation */    fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);        DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n", 	    vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),	    tpd->tsd[0].length, skb_len);    if (skb_len < fore200e_vcc->tx_min_pdu)	fore200e_vcc->tx_min_pdu = skb_len;    if (skb_len > fore200e_vcc->tx_max_pdu)	fore200e_vcc->tx_max_pdu = skb_len;        entry->vcc = vcc;    entry->skb = skb;    /* set tx rate control information */    tpd->rate.data_cells = fore200e_vcc->rate.data_cells;    tpd->rate.idle_cells = fore200e_vcc->rate.idle_cells;    if (cell_header) {	tpd->atm_header.clp = (*cell_header & ATM_HDR_CLP);	tpd->atm_header.plt = (*cell_header & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT;	tpd->atm_header.vci = (*cell_header & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT;	tpd->atm_header.vpi = (*cell_header & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT;	tpd->atm_header.gfc = (*cell_header & ATM_HDR_GFC_MASK) >> ATM_HDR_GFC_SHIFT;    }    else {	/* set the ATM header, common to all cells conveying the PDU */	tpd->atm_header.clp = 0;	tpd->atm_header.plt = 0;	tpd->atm_header.vci = vcc->vci;	tpd->atm_header.vpi = vcc->vpi;	tpd->atm_header.gfc = 0;    }    tpd->spec.length = tx_len;    tpd->spec.nseg   = 1;    tpd->spec.aal    = fore200e_atm2fore_aal(vcc->qos.aal);#ifdef FORE200E_SYNC_SEND    tpd->spec.intr   = 0;#else    tpd->spec.intr   = 1;#endif    tpd_haddr.size  = sizeof(struct tpd) / 32;    /* size is expressed in 32 byte blocks */    tpd_haddr.pad   = 0;    tpd_haddr.haddr = entry->tpd_dma >> 5;        /* shift the address, as we are in a bitfield */    *entry->status = STATUS_PENDING;    fore200e->bus->write(*(u32*)&tpd_haddr, (u32*)&entry->cp_entry->tpd_haddr);#ifdef FORE200E_SYNC_SEND    {	int ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 10);	fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,				 FORE200E_DMA_TODEVICE);		/* free tmp copy of misaligned data */	if (entry->data)	    kfree(entry->data);	/* notify tx completion */	if (vcc->pop)	    vcc->pop(vcc, skb);	else	    dev_kfree_skb(skb);	if (ok == 0) {	    printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci);	    atomic_inc(&entry->vcc->stats->tx_err);	    return -EIO;	}	atomic_inc(&entry->vcc->stats->tx);	DPRINTK(3, "synchronous tx on %d:%d:%d succeeded\n", vcc->itf, vcc->vpi, vcc->vci);    }#endif    return 0;}static intfore200e_getstats(struct fore200e* fore200e){    struct host_cmdq*       cmdq  = &fore200e->host_cmdq;    struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];    struct stats_opcode     opcode;    int                     ok;    u32                     stats_dma_addr;    if (fore200e->stats == NULL) {	fore200e->stats = fore200e_kmalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA);	if (fore200e->stats == NULL)	    return -ENOMEM;    }        stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, sizeof(struct stats), FORE200E_DMA_FROMDEVICE);        FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);    opcode.opcode = OPCODE_GET_STATS;    opcode.pad    = 0;    fore200e->bus->write(stats_dma_addr, &entry->cp_entry->cmd.stats_block.stats_haddr);        *entry->status = STATUS_PENDING;    fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.stats_block.opcode);    ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);    *entry->status = STATUS_FREE;    fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats), FORE200E_DMA_FROMDEVICE);        if (ok == 0) {	printk(FORE200E "unable to get statistics from device %s\n", fore200e->name);	return -EIO;    }    return 0;}static intfore200e_getsockopt (struct atm_vcc* vcc, int level, int optname, void* optval, int optlen){    // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);    DPRINTK(2, "getsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",	    vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);    return -EINVAL;}static intfore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void* optval, int optlen){    // struct fore200e* fore200e = FORE200E_DEV(vcc->dev);        DPRINTK(2, "setsockopt %d.%d.%d, level = %d, optname = 0x%x, optval = 0x%p, optlen = %d\n",	    vcc->itf, vcc->vpi, vcc->vci, level, optname, optval, optlen);        return -EINVAL;}#if 0 /* currently unused */static intfore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs){    struct host_cmdq*       cmdq  = &fore200e->host_cmdq;    struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];    struct oc3_opcode       opcode;    int                     ok;    u32                     oc3_regs_dma_addr;    oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE);    FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);    opcode.opcode = OPCODE_GET_OC3;    opcode.reg    = 0;    opcode.value  = 0;    opcode.mask   = 0;    fore200e->bus->write(oc3_regs_dma_addr, &entry->cp_entry->cmd.oc3_block.regs_haddr);        *entry->status = STATUS_PENDING;    fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.oc3_block.opcode);    ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);    *entry->status = STATUS_FREE;    fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE);        if (ok == 0) {	printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name);	return -EIO;    }    return 0;}#endifstatic intfore200e_set_oc3(struct fore200e* fore200e, u32 reg, u32 value, u32 mask){    struct host_cmdq*       cmdq  = &fore200e->host_cmdq;    struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];    struct oc3_opcode       opcode;    int                     ok;    FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);    opcode.opcode = OPCODE_SET_OC3;    opcode.reg    = reg;    opcode.value  = value;    opcode.mask   = mask;    fore200e->bus->write(0, &entry->cp_entry->cmd.oc3_block.regs_haddr);        *entry->status = STATUS_PENDING;    fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.oc3_block.opcode);    ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);    *entry->status = STATUS_FREE;    if (ok == 0) {	printk(FORE200E "unable to set OC-3 reg 0x%02x of device %s\n", reg, fore200e->name);	return -EIO;    }    return 0;}static intfore200e_setloop(struct fore200e* fore200e, int loop_mode){    u32 mct_value, mct_mask;    int error;    if (!capable(CAP_NET_ADMIN))	return -EPERM;        switch (loop_mode) {    case ATM_LM_NONE:	mct_value = 0; 	mct_mask  = SUNI_MCT_DLE | SUNI_MCT_LLE;	break;	    case ATM_LM_LOC_PHY:	mct_value = mct_mask = SUNI_MCT_DLE;	break;    case ATM_LM_RMT_PHY:	mct_value = mct_mask = SUNI_MCT_LLE;	break;    default:	return -EINVAL;    }    error = fore200e_set_oc3(fore200e, SUNI_MCT, mct_value, mct_mask);    if ( error == 0)	fore200e->loop_mode = loop_mode;    return error;}static inline unsigned intfore200e_swap(unsigned int in){#if defined(__LITTLE_ENDIAN)    return swab32(in);#else    return in;#endif}static intfore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats* arg){    struct sonet_stats tmp;    if (fore200e_getstats(fore200e) < 0)	return -EIO;    tmp.section_bip = fore200e_swap(fore200e->stats->oc3.section_bip8_errors);    tmp.line_bip    = fore200e_swap(fore200e->stats->oc3.line_bip24_errors);    tmp.path_bip    = fore200e_swap(fore200e->stats->oc3.path_bip8_errors);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -