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

📄 fore200e.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
static int __initfore200e_sba_prom_read(struct fore200e* fore200e, struct prom_data* prom){    struct sbus_dev* sbus_dev = (struct sbus_dev*) fore200e->bus_dev;    int                       len;    len = prom_getproperty(sbus_dev->prom_node, "macaddrlo2", &prom->mac_addr[ 4 ], 4);    if (len < 0)	return -EBUSY;    len = prom_getproperty(sbus_dev->prom_node, "macaddrhi4", &prom->mac_addr[ 2 ], 4);    if (len < 0)	return -EBUSY;        prom_getproperty(sbus_dev->prom_node, "serialnumber",		     (char*)&prom->serial_number, sizeof(prom->serial_number));        prom_getproperty(sbus_dev->prom_node, "promversion",		     (char*)&prom->hw_revision, sizeof(prom->hw_revision));        return 0;}static intfore200e_sba_proc_read(struct fore200e* fore200e, char *page){    struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev;    return sprintf(page, "   SBUS slot/device:\t\t%d/'%s'\n", sbus_dev->slot, sbus_dev->prom_name);}#endif /* CONFIG_ATM_FORE200E_SBA */static voidfore200e_irq_tx(struct fore200e* fore200e){    struct host_txq_entry* entry;    int i;        entry = fore200e->host_txq.host_entry;    for (i = 0; i < QUEUE_SIZE_TX; i++) {	if (*entry->status & STATUS_COMPLETE) {	    DPRINTK(3, "TX COMPLETED: entry = %p, vcc = %p, skb = %p\n", entry, entry->vcc, entry->skb);	    /* free copy of misaligned data */	    if (entry->data)		kfree(entry->data);	    /* remove DMA mapping */	    fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,				     FORE200E_DMA_TODEVICE);	    /* notify tx completion */	    if (entry->vcc->pop)		entry->vcc->pop(entry->vcc, entry->skb);	    else		dev_kfree_skb_irq(entry->skb);	    /* check error condition */	    if (*entry->status & STATUS_ERROR)		atomic_inc(&entry->vcc->stats->tx_err);	    else		atomic_inc(&entry->vcc->stats->tx);	    *entry->status = STATUS_FREE;	    	    fore200e->host_txq.txing--;	}	entry++;    }}static voidfore200e_supply(struct fore200e* fore200e){    int  scheme, magn, i;    struct host_bsq*       bsq;    struct host_bsq_entry* entry;    struct buffer*         buffer;    for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {	for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {	    bsq = &fore200e->host_bsq[ scheme ][ magn ];	    if (fore200e_rx_buf_nbr[ scheme ][ magn ] - bsq->count > RBD_BLK_SIZE) {		DPRINTK(2, "supplying rx buffers to queue %d / %d, count = %d\n",			scheme, magn, bsq->count);		entry = &bsq->host_entry[ bsq->head ];				FORE200E_NEXT_ENTRY(bsq->head, QUEUE_SIZE_BS);		for (i = 0; i < RBD_BLK_SIZE; i++) {		    buffer = &bsq->buffer[ bsq->free ];		    		    FORE200E_NEXT_ENTRY(bsq->free, fore200e_rx_buf_nbr[ scheme ][ magn ]);		    		    entry->rbd_block->rbd[ i ].buffer_haddr = buffer->data.dma_addr;		    entry->rbd_block->rbd[ i ].handle       = FORE200E_BUF2HDL(buffer);		}		/* increase the number of supplied rx buffers */		bsq->count += RBD_BLK_SIZE;				*entry->status = STATUS_PENDING;		fore200e->bus->write(entry->rbd_block_dma, &entry->cp_entry->rbd_block_haddr);	    }	}    }}static struct atm_vcc* fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd){    struct atm_vcc* vcc;    for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) {	if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci)	    break;    }        return vcc;}static voidfore200e_push_rpd(struct fore200e* fore200e, struct rpd* rpd){    struct atm_vcc*      vcc;    struct sk_buff*      skb;    struct buffer*       buffer;    struct fore200e_vcc* fore200e_vcc;    int                  i, pdu_len = 0;#ifdef FORE200E_52BYTE_AAL0_SDU    u32                  cell_header = 0;#endif    vcc = fore200e_find_vcc(fore200e, rpd);    if (vcc == NULL) {		printk(FORE200E "no vcc found for PDU received on %d.%d.%d\n",	       fore200e->atm_dev->number, rpd->atm_header.vpi, rpd->atm_header.vci);	return;    }    fore200e_vcc = FORE200E_VCC(vcc);#ifdef FORE200E_52BYTE_AAL0_SDU    if ((vcc->qos.aal == ATM_AAL0) && (vcc->qos.rxtp.max_sdu == ATM_AAL0_SDU)) {	cell_header = (rpd->atm_header.gfc << ATM_HDR_GFC_SHIFT) |	              (rpd->atm_header.vpi << ATM_HDR_VPI_SHIFT) |                      (rpd->atm_header.vci << ATM_HDR_VCI_SHIFT) |                      (rpd->atm_header.plt << ATM_HDR_PTI_SHIFT) |                        rpd->atm_header.clp;	pdu_len = 4;    }#endif        /* compute total PDU length */    for (i = 0; i < rpd->nseg; i++)	pdu_len += rpd->rsd[ i ].length;        skb = alloc_skb(pdu_len, GFP_ATOMIC);    if (skb == NULL) {		printk(FORE200E "unable to alloc new skb, rx PDU length = %d\n", pdu_len);	atomic_inc(&vcc->stats->rx_drop);	return;    }     skb->stamp = vcc->timestamp = xtime;    #ifdef FORE200E_52BYTE_AAL0_SDU    if (cell_header) {	*((u32*)skb_put(skb, 4)) = cell_header;    }#endif    /* reassemble segments */    for (i = 0; i < rpd->nseg; i++) {		/* rebuild rx buffer address from rsd handle */	buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle);		/* ensure DMA synchronisation */	fore200e->bus->dma_sync(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, FORE200E_DMA_FROMDEVICE);		memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data.align_addr, rpd->rsd[ i ].length);    }        DPRINTK(3, "rx skb: len = %d, truesize = %d\n", skb->len, skb->truesize);        if (pdu_len < fore200e_vcc->rx_min_pdu)	fore200e_vcc->rx_min_pdu = pdu_len;    if (pdu_len > fore200e_vcc->rx_max_pdu)	fore200e_vcc->rx_max_pdu = pdu_len;    /* push PDU */    if (atm_charge(vcc, skb->truesize) == 0) {	DPRINTK(2, "receive buffers saturated for %d.%d.%d - PDU dropped\n",		vcc->itf, vcc->vpi, vcc->vci);	dev_kfree_skb_irq(skb);	return;    }    vcc->push(vcc, skb);    atomic_inc(&vcc->stats->rx);}static voidfore200e_collect_rpd(struct fore200e* fore200e, struct rpd* rpd){    struct buffer* buffer;    int            i;        for (i = 0; i < rpd->nseg; i++) {	/* rebuild rx buffer address from rsd handle */	buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle);	/* decrease the number of supplied rx buffers */	fore200e->host_bsq[ buffer->scheme ][ buffer->magn ].count--;    }}static voidfore200e_irq_rx(struct fore200e* fore200e){    struct host_rxq*       rxq = &fore200e->host_rxq;    struct host_rxq_entry* entry;    for (;;) {		entry = &rxq->host_entry[ rxq->head ];	/* no more received PDUs */	if ((*entry->status & STATUS_COMPLETE) == 0)	    break;	FORE200E_NEXT_ENTRY(rxq->head, QUEUE_SIZE_RX);	if ((*entry->status & STATUS_ERROR) == 0) {	    fore200e_push_rpd(fore200e, entry->rpd);	}	else {	    printk(FORE200E "damaged PDU on %d.%d.%d\n", 		   fore200e->atm_dev->number, entry->rpd->atm_header.vpi, entry->rpd->atm_header.vci);	}	fore200e_collect_rpd(fore200e, entry->rpd);	fore200e_supply(fore200e);	/* rewrite the rpd address to ack the received PDU */	fore200e->bus->write(entry->rpd_dma, &entry->cp_entry->rpd_haddr);	*entry->status = STATUS_FREE;    }}static voidfore200e_interrupt(int irq, void* dev, struct pt_regs* regs){    struct fore200e* fore200e = FORE200E_DEV((struct atm_dev*)dev);    if (fore200e->bus->irq_check(fore200e) == 0) {		DPRINTK(3, "unexpected interrupt on device %c\n", fore200e->name[9]);	return;    }    DPRINTK(3, "valid interrupt on device %c\n", fore200e->name[9]);    tasklet_schedule(&fore200e->tasklet);        fore200e->bus->irq_ack(fore200e);}static voidfore200e_tasklet(unsigned long data){    struct fore200e* fore200e = (struct fore200e*) data;    fore200e_irq_rx(fore200e);        if (fore200e->host_txq.txing)	fore200e_irq_tx(fore200e);}static intfore200e_select_scheme(struct atm_vcc* vcc){    int scheme;#if 1    /* fairly balance VCs over (identical) buffer schemes */    scheme =  vcc->vci % 2 ? BUFFER_SCHEME_ONE : BUFFER_SCHEME_TWO;#else    /* bit 7 of VPI magically selects the second buffer scheme */    if (vcc->vpi & (1<<7)) {	vcc->vpi &= ((1<<7) - 1);    /* reset the magic bit */	scheme = BUFFER_SCHEME_TWO;    }    else {	scheme = BUFFER_SCHEME_ONE;    }#endif        DPRINTK(1, "vpvc %d.%d.%d uses the %s buffer scheme\n",	    vcc->itf, vcc->vpi, vcc->vci, scheme == BUFFER_SCHEME_ONE ? "first" : "second");    return scheme;}static int fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc* vcc, int mtu){    struct host_cmdq*        cmdq  = &fore200e->host_cmdq;    struct host_cmdq_entry*  entry = &cmdq->host_entry[ cmdq->head ];    struct activate_opcode   activ_opcode;    struct deactivate_opcode deactiv_opcode;    struct vpvc              vpvc;    int                      ok;    enum fore200e_aal        aal = fore200e_atm2fore_aal(vcc->qos.aal);    FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);        if (activate) {	FORE200E_VCC(vcc)->scheme = fore200e_select_scheme(vcc);		activ_opcode.opcode = OPCODE_ACTIVATE_VCIN;	activ_opcode.aal    = aal;	activ_opcode.scheme = FORE200E_VCC(vcc)->scheme;	activ_opcode.pad    = 0;    }    else {	deactiv_opcode.opcode = OPCODE_DEACTIVATE_VCIN;	deactiv_opcode.pad    = 0;    }    vpvc.vci = vcc->vci;    vpvc.vpi = vcc->vpi;    *entry->status = STATUS_PENDING;    if (activate) {#ifdef FORE200E_52BYTE_AAL0_SDU	mtu = 48;#endif	/* the MTU is unused by the cp, except in the case of AAL0 */	fore200e->bus->write(mtu,                        &entry->cp_entry->cmd.activate_block.mtu);	fore200e->bus->write(*(u32*)&vpvc,         (u32*)&entry->cp_entry->cmd.activate_block.vpvc);	fore200e->bus->write(*(u32*)&activ_opcode, (u32*)&entry->cp_entry->cmd.activate_block.opcode);    }    else {	fore200e->bus->write(*(u32*)&vpvc,           (u32*)&entry->cp_entry->cmd.deactivate_block.vpvc);	fore200e->bus->write(*(u32*)&deactiv_opcode, (u32*)&entry->cp_entry->cmd.deactivate_block.opcode);    }    ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);    *entry->status = STATUS_FREE;    if (ok == 0) {	printk(FORE200E "unable to %s vpvc %d.%d on device %s\n",	       activate ? "open" : "close", vcc->vpi, vcc->vci, fore200e->name);	return -EIO;    }    DPRINTK(1, "vpvc %d.%d %sed on device %s\n", vcc->vpi, vcc->vci, 	    activate ? "open" : "clos", fore200e->name);    return 0;}static intfore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci){    struct atm_vcc* walk;    /* find a free VPI */    if (*vpi == ATM_VPI_ANY) {	for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) {	    if ((walk->vci == *vci) && (walk->vpi == *vpi)) {		(*vpi)++;		walk = vcc->dev->vccs;	    }	}    }    /* find a free VCI */    if (*vci == ATM_VCI_ANY) {		for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk; walk = walk->next) {	    if ((walk->vpi = *vpi) && (walk->vci == *vci)) {		*vci = walk->vci + 1;		walk = vcc->dev->vccs;	    }	}    }    return 0;}#define FORE200E_MAX_BACK2BACK_CELLS 255    /* XXX depends on CDVT */static voidfore200e_rate_ctrl(struct atm_qos* qos, struct tpd_rate* rate){    if (qos->txtp.max_pcr < ATM_OC3_PCR) {    	/* compute the data cells to idle cells ratio from the PCR */	rate->data_cells = qos->txtp.max_pcr * FORE200E_MAX_BACK2BACK_CELLS / ATM_OC3_PCR;	rate->idle_cells = FORE200E_MAX_BACK2BACK_CELLS - rate->data_cells;    }    else {	/* disable rate control */	rate->data_cells = rate->idle_cells = 0;    }}static intfore200e_open(struct atm_vcc *vcc, short vpi, int vci){    struct fore200e*     fore200e = FORE200E_DEV(vcc->dev);    struct fore200e_vcc* fore200e_vcc;        /* find a free VPI/VCI */    fore200e_walk_vccs(vcc, &vpi, &vci);    vcc->vpi = vpi;    vcc->vci = vci;    /* ressource checking only? */    if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)	return 0;    set_bit(ATM_VF_ADDR, &vcc->flags);    vcc->itf    = vcc->dev->number;    DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "	    "rx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d)\n",	    vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),	    fore200e_traffic_class[ vcc->qos.txtp.traffic_class ],	    vcc->qos.txtp.min_pcr, vcc->qos.txtp.max_pcr, vcc->qos.txtp.max_cdv, vcc->qos.txtp.max_sdu,	    fore200e_traffic_class[ vcc->qos.rxtp.traffic_class ],	    vcc->qos.rxtp.min_pcr, vcc->qos.rxtp.max_pcr, vcc->qos.rxtp.max_cdv, vcc->qos.rxtp.max_sdu);    

⌨️ 快捷键说明

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