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

📄 pcnet.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 5 页
字号:
    uint32_t rdra, tdra;#ifdef PCNET_DEBUG    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));#endif    if (BCR_SSIZE32(s)) {        struct pcnet_initblk32 initblk;        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),                (uint8_t *)&initblk, sizeof(initblk), 0);        mode = le16_to_cpu(initblk.mode);        rlen = initblk.rlen >> 4;        tlen = initblk.tlen >> 4;	ladrf[0] = le16_to_cpu(initblk.ladrf[0]);	ladrf[1] = le16_to_cpu(initblk.ladrf[1]);	ladrf[2] = le16_to_cpu(initblk.ladrf[2]);	ladrf[3] = le16_to_cpu(initblk.ladrf[3]);	padr[0] = le16_to_cpu(initblk.padr[0]);	padr[1] = le16_to_cpu(initblk.padr[1]);	padr[2] = le16_to_cpu(initblk.padr[2]);        rdra = le32_to_cpu(initblk.rdra);        tdra = le32_to_cpu(initblk.tdra);    } else {        struct pcnet_initblk16 initblk;        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),                (uint8_t *)&initblk, sizeof(initblk), 0);        mode = le16_to_cpu(initblk.mode);	ladrf[0] = le16_to_cpu(initblk.ladrf[0]);	ladrf[1] = le16_to_cpu(initblk.ladrf[1]);	ladrf[2] = le16_to_cpu(initblk.ladrf[2]);	ladrf[3] = le16_to_cpu(initblk.ladrf[3]);	padr[0] = le16_to_cpu(initblk.padr[0]);	padr[1] = le16_to_cpu(initblk.padr[1]);	padr[2] = le16_to_cpu(initblk.padr[2]);        rdra = le32_to_cpu(initblk.rdra);        tdra = le32_to_cpu(initblk.tdra);        rlen = rdra >> 29;        tlen = tdra >> 29;        rdra &= 0x00ffffff;        tdra &= 0x00ffffff;    }#if defined(PCNET_DEBUG)    printf("rlen=%d tlen=%d\n", rlen, tlen);#endif    CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;    CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;    s->csr[ 6] = (tlen << 12) | (rlen << 8);    s->csr[15] = mode;    s->csr[ 8] = ladrf[0];    s->csr[ 9] = ladrf[1];    s->csr[10] = ladrf[2];    s->csr[11] = ladrf[3];    s->csr[12] = padr[0];    s->csr[13] = padr[1];    s->csr[14] = padr[2];    s->rdra = PHYSADDR(s, rdra);    s->tdra = PHYSADDR(s, tdra);    CSR_RCVRC(s) = CSR_RCVRL(s);    CSR_XMTRC(s) = CSR_XMTRL(s);#ifdef PCNET_DEBUG    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",        BCR_SSIZE32(s),        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));#endif    s->csr[0] |= 0x0101;    s->csr[0] &= ~0x0004;       /* clear STOP bit */}static void pcnet_start(PCNetState *s){#ifdef PCNET_DEBUG    printf("pcnet_start\n");#endif    if (!CSR_DTX(s))        s->csr[0] |= 0x0010;    /* set TXON */    if (!CSR_DRX(s))        s->csr[0] |= 0x0020;    /* set RXON */    s->csr[0] &= ~0x0004;       /* clear STOP bit */    s->csr[0] |= 0x0002;}static void pcnet_stop(PCNetState *s){#ifdef PCNET_DEBUG    printf("pcnet_stop\n");#endif    s->csr[0] &= ~0x7feb;    s->csr[0] |= 0x0014;    s->csr[4] &= ~0x02c2;    s->csr[5] &= ~0x0011;    pcnet_poll_timer(s);}static void pcnet_rdte_poll(PCNetState *s){    s->csr[28] = s->csr[29] = 0;    if (s->rdra) {        int bad = 0;#if 1        target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));        target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));        target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));#else        target_phys_addr_t crda = s->rdra +            (CSR_RCVRL(s) - CSR_RCVRC(s)) *            (BCR_SWSTYLE(s) ? 16 : 8 );        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;        target_phys_addr_t nrda = s->rdra +            (CSR_RCVRL(s) - nrdc) *            (BCR_SWSTYLE(s) ? 16 : 8 );        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;        target_phys_addr_t nnrd = s->rdra +            (CSR_RCVRL(s) - nnrc) *            (BCR_SWSTYLE(s) ? 16 : 8 );#endif        CHECK_RMD(PHYSADDR(s,crda), bad);        if (!bad) {            CHECK_RMD(PHYSADDR(s,nrda), bad);            if (bad || (nrda == crda)) nrda = 0;            CHECK_RMD(PHYSADDR(s,nnrd), bad);            if (bad || (nnrd == crda)) nnrd = 0;            s->csr[28] = crda & 0xffff;            s->csr[29] = crda >> 16;            s->csr[26] = nrda & 0xffff;            s->csr[27] = nrda >> 16;            s->csr[36] = nnrd & 0xffff;            s->csr[37] = nnrd >> 16;#ifdef PCNET_DEBUG            if (bad) {                printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",                       PHYSADDR(s,crda));            }        } else {            printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));#endif        }    }    if (CSR_CRDA(s)) {        struct pcnet_RMD rmd;        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);        CSR_CRST(s) = rmd.status;#ifdef PCNET_DEBUG_RMD_X        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),                rmd.buf_length, rmd.status, rmd.msg_length);        PRINT_RMD(&rmd);#endif    } else {        CSR_CRBC(s) = CSR_CRST(s) = 0;    }    if (CSR_NRDA(s)) {        struct pcnet_RMD rmd;        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);        CSR_NRST(s) = rmd.status;    } else {        CSR_NRBC(s) = CSR_NRST(s) = 0;    }}static int pcnet_tdte_poll(PCNetState *s){    s->csr[34] = s->csr[35] = 0;    if (s->tdra) {        target_phys_addr_t cxda = s->tdra +            (CSR_XMTRL(s) - CSR_XMTRC(s)) *            (BCR_SWSTYLE(s) ? 16 : 8);        int bad = 0;        CHECK_TMD(PHYSADDR(s, cxda),bad);        if (!bad) {            if (CSR_CXDA(s) != cxda) {                s->csr[60] = s->csr[34];                s->csr[61] = s->csr[35];                s->csr[62] = CSR_CXBC(s);                s->csr[63] = CSR_CXST(s);            }            s->csr[34] = cxda & 0xffff;            s->csr[35] = cxda >> 16;#ifdef PCNET_DEBUG_X            printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));#endif        }    }    if (CSR_CXDA(s)) {        struct pcnet_TMD tmd;        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);        CSR_CXST(s) = tmd.status;    } else {        CSR_CXBC(s) = CSR_CXST(s) = 0;    }    return !!(CSR_CXST(s) & 0x8000);}static int pcnet_can_receive(void *opaque){    PCNetState *s = opaque;    if (CSR_STOP(s) || CSR_SPND(s))        return 0;    if (s->recv_pos > 0)        return 0;    return sizeof(s->buffer)-16;}#define MIN_BUF_SIZE 60static void pcnet_receive(void *opaque, const uint8_t *buf, int size){    PCNetState *s = opaque;    int is_padr = 0, is_bcast = 0, is_ladr = 0;    uint8_t buf1[60];    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)        return;#ifdef PCNET_DEBUG    printf("pcnet_receive size=%d\n", size);#endif    /* if too small buffer, then expand it */    if (size < MIN_BUF_SIZE) {        memcpy(buf1, buf, size);        memset(buf1 + size, 0, MIN_BUF_SIZE - size);        buf = buf1;        size = MIN_BUF_SIZE;    }    if (CSR_PROM(s)        || (is_padr=padr_match(s, buf, size))        || (is_bcast=padr_bcast(s, buf, size))        || (is_ladr=ladr_match(s, buf, size))) {        pcnet_rdte_poll(s);        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {            struct pcnet_RMD rmd;            int rcvrc = CSR_RCVRC(s)-1,i;            target_phys_addr_t nrda;            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {                if (rcvrc <= 1)                    rcvrc = CSR_RCVRL(s);                nrda = s->rdra +                    (CSR_RCVRL(s) - rcvrc) *                    (BCR_SWSTYLE(s) ? 16 : 8 );                RMDLOAD(&rmd, PHYSADDR(s,nrda));                if (GET_FIELD(rmd.status, RMDS, OWN)) {#ifdef PCNET_DEBUG_RMD                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",                                rcvrc, CSR_RCVRC(s));#endif                    CSR_RCVRC(s) = rcvrc;                    pcnet_rdte_poll(s);                    break;                }            }        }        if (!(CSR_CRST(s) & 0x8000)) {#ifdef PCNET_DEBUG_RMD            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));#endif            s->csr[0] |= 0x1000; /* Set MISS flag */            CSR_MISSC(s)++;        } else {            uint8_t *src = &s->buffer[8];            target_phys_addr_t crda = CSR_CRDA(s);            struct pcnet_RMD rmd;            int pktcount = 0;            memcpy(src, buf, size);#if 1            /* no need to compute the CRC */            src[size] = 0;            src[size + 1] = 0;            src[size + 2] = 0;            src[size + 3] = 0;            size += 4;#else            /* XXX: avoid CRC generation */            if (!CSR_ASTRP_RCV(s)) {                uint32_t fcs = ~0;                uint8_t *p = src;                while (size < 46) {                    src[size++] = 0;                }                while (p != &src[size]) {                    CRC(fcs, *p++);                }                ((uint32_t *)&src[size])[0] = htonl(fcs);                size += 4; /* FCS at end of packet */            } else size += 4;#endif#ifdef PCNET_DEBUG_MATCH            PRINT_PKTHDR(buf);#endif            RMDLOAD(&rmd, PHYSADDR(s,crda));            /*if (!CSR_LAPPEN(s))*/                SET_FIELD(&rmd.status, RMDS, STP, 1);#define PCNET_RECV_STORE() do {                                 \    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),size); \    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rbadr);          \    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \    src += count; size -= count;                                \    SET_FIELD(&rmd.msg_length, RMDM, MCNT, count);              \    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \    pktcount++;                                                 \} while (0)            PCNET_RECV_STORE();            if ((size > 0) && CSR_NRDA(s)) {                target_phys_addr_t nrda = CSR_NRDA(s);                RMDLOAD(&rmd, PHYSADDR(s,nrda));                if (GET_FIELD(rmd.status, RMDS, OWN)) {                    crda = nrda;                    PCNET_RECV_STORE();                    if ((size > 0) && (nrda=CSR_NNRD(s))) {                        RMDLOAD(&rmd, PHYSADDR(s,nrda));                        if (GET_FIELD(rmd.status, RMDS, OWN)) {                            crda = nrda;                            PCNET_RECV_STORE();                        }                    }                }            }#undef PCNET_RECV_STORE            RMDLOAD(&rmd, PHYSADDR(s,crda));            if (size == 0) {                SET_FIELD(&rmd.status, RMDS, ENP, 1);                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);            } else {                SET_FIELD(&rmd.status, RMDS, OFLO, 1);                SET_FIELD(&rmd.status, RMDS, BUFF, 1);                SET_FIELD(&rmd.status, RMDS, ERR, 1);            }            RMDSTORE(&rmd, PHYSADDR(s,crda));            s->csr[0] |= 0x0400;#ifdef PCNET_DEBUG            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);#endif#ifdef PCNET_DEBUG_RMD            PRINT_RMD(&rmd);#endif            while (pktcount--) {                if (CSR_RCVRC(s) <= 1)                    CSR_RCVRC(s) = CSR_RCVRL(s);                else                    CSR_RCVRC(s)--;            }            pcnet_rdte_poll(s);        }    }    pcnet_poll(s);    pcnet_update_irq(s);}static void pcnet_transmit(PCNetState *s){    target_phys_addr_t xmit_cxda = 0;    int count = CSR_XMTRL(s)-1;    s->xmit_pos = -1;    if (!CSR_TXON(s)) {        s->csr[0] &= ~0x0008;        return;    }    s->tx_busy = 1;    txagain:    if (pcnet_tdte_poll(s)) {        struct pcnet_TMD tmd;        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));#ifdef PCNET_DEBUG_TMD        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));        PRINT_TMD(&tmd);#endif        if (GET_FIELD(tmd.status, TMDS, STP)) {            s->xmit_pos = 0;

⌨️ 快捷键说明

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