static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)

{

    CadenceGEMState *s;

    unsigned   rxbufsize, bytes_to_copy;

    unsigned   rxbuf_offset;

    uint8_t    rxbuf[2048];

    uint8_t   *rxbuf_ptr;

    bool first_desc = true;

    int maf;



    s = qemu_get_nic_opaque(nc);



    /* Is this destination MAC address "for us" ? */

    maf = gem_mac_address_filter(s, buf);

    if (maf == GEM_RX_REJECT) {

        return -1;




    /* Discard packets with receive length error enabled ? */

    if (s->regs[GEM_NWCFG] & GEM_NWCFG_LERR_DISC) {

        unsigned type_len;



        /* Fish the ethertype / length field out of the RX packet */

        type_len = buf[12] << 8 | buf[13];

        /* It is a length field, not an ethertype */

        if (type_len < 0x600) {

            if (size < type_len) {

                /* discard */

                return -1;






    /*

     * Determine configured receive buffer offset (probably 0)

     */

    rxbuf_offset = (s->regs[GEM_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >>

                   GEM_NWCFG_BUFF_OFST_S;



    /* The configure size of each receive buffer.  Determines how many

     * buffers needed to hold this packet.

     */

    rxbufsize = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >>

                 GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;




    /* Pad to minimum length. Assume FCS field is stripped, logic

     * below will increment it to the real minimum of 64 when

     * not FCS stripping

     */

    if (size < 60) {

        size = 60;




    /* Strip of FCS field ? (usually yes) */

    if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) {

        rxbuf_ptr = (void *)buf;

    } else {

        unsigned crc_val;







        /* The application wants the FCS field, which QEMU does not provide.

         * We must try and calculate one.

         */



        memcpy(rxbuf, buf, size);

        memset(rxbuf + size, 0, sizeof(rxbuf) - size);

        rxbuf_ptr = rxbuf;

        crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));

        memcpy(rxbuf + size, &crc_val, sizeof(crc_val));



        bytes_to_copy += 4;

        size += 4;




    DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);



    while (bytes_to_copy) {

        /* Do nothing if receive is not enabled. */

        if (!gem_can_receive(nc)) {

            assert(!first_desc);

            return -1;




        DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),

                rx_desc_get_buffer(s->rx_desc));



        /* Copy packet data to emulated DMA buffer */

        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset,

                                  rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));

        rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);

        bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);



        /* Update the descriptor.  */

        if (first_desc) {

            rx_desc_set_sof(s->rx_desc);

            first_desc = false;


        if (bytes_to_copy == 0) {

            rx_desc_set_eof(s->rx_desc);

            rx_desc_set_length(s->rx_desc, size);


        rx_desc_set_ownership(s->rx_desc);



        switch (maf) {

        case GEM_RX_PROMISCUOUS_ACCEPT:

            break;

        case GEM_RX_BROADCAST_ACCEPT:

            rx_desc_set_broadcast(s->rx_desc);

            break;

        case GEM_RX_UNICAST_HASH_ACCEPT:

            rx_desc_set_unicast_hash(s->rx_desc);

            break;

        case GEM_RX_MULTICAST_HASH_ACCEPT:

            rx_desc_set_multicast_hash(s->rx_desc);

            break;

        case GEM_RX_REJECT:

            abort();

        default: /* SAR */

            rx_desc_set_sar(s->rx_desc, maf);




        /* Descriptor write-back.  */

        cpu_physical_memory_write(s->rx_desc_addr,

                                  (uint8_t *)s->rx_desc, sizeof(s->rx_desc));



        /* Next descriptor */

        if (rx_desc_get_wrap(s->rx_desc)) {

            DB_PRINT("wrapping RX descriptor list\n");

            s->rx_desc_addr = s->regs[GEM_RXQBASE];

        } else {

            DB_PRINT("incrementing RX descriptor list\n");

            s->rx_desc_addr += 8;


        gem_get_rx_desc(s);




    /* Count it */

    gem_receive_updatestats(s, buf, size);



    s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;

    s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]);



    /* Handle interrupt consequences */

    gem_update_int_status(s);



    return size;

static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)

{

    CadenceGEMState *s;

    unsigned   rxbufsize, bytes_to_copy;

    unsigned   rxbuf_offset;

    uint8_t    rxbuf[2048];

    uint8_t   *rxbuf_ptr;

    bool first_desc = true;

    int maf;



    s = qemu_get_nic_opaque(nc);



    

    maf = gem_mac_address_filter(s, buf);

    if (maf == GEM_RX_REJECT) {

        return -1;




    

    if (s->regs[GEM_NWCFG] & GEM_NWCFG_LERR_DISC) {

        unsigned type_len;



        

        type_len = buf[12] << 8 | buf[13];

        

        if (type_len < 0x600) {

            if (size < type_len) {

                

                return -1;






    





    rxbuf_offset = (s->regs[GEM_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >>

                   GEM_NWCFG_BUFF_OFST_S;



    





    rxbufsize = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >>

                 GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;




    







    if (size < 60) {

        size = 60;




    

    if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) {

        rxbuf_ptr = (void *)buf;

    } else {

        unsigned crc_val;







        







        memcpy(rxbuf, buf, size);

        memset(rxbuf + size, 0, sizeof(rxbuf) - size);

        rxbuf_ptr = rxbuf;

        crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));

        memcpy(rxbuf + size, &crc_val, sizeof(crc_val));



        bytes_to_copy += 4;

        size += 4;




    DB_PRINT("config bufsize: %d packet size: %ld\n", rxbufsize, size);



    while (bytes_to_copy) {

        

        if (!gem_can_receive(nc)) {

            assert(!first_desc);

            return -1;




        DB_PRINT("copy %d bytes to 0x%x\n", MIN(bytes_to_copy, rxbufsize),

                rx_desc_get_buffer(s->rx_desc));



        

        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + rxbuf_offset,

                                  rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));

        rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);

        bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);



        

        if (first_desc) {

            rx_desc_set_sof(s->rx_desc);

            first_desc = false;


        if (bytes_to_copy == 0) {

            rx_desc_set_eof(s->rx_desc);

            rx_desc_set_length(s->rx_desc, size);


        rx_desc_set_ownership(s->rx_desc);



        switch (maf) {

        case GEM_RX_PROMISCUOUS_ACCEPT:

            break;

        case GEM_RX_BROADCAST_ACCEPT:

            rx_desc_set_broadcast(s->rx_desc);

            break;

        case GEM_RX_UNICAST_HASH_ACCEPT:

            rx_desc_set_unicast_hash(s->rx_desc);

            break;

        case GEM_RX_MULTICAST_HASH_ACCEPT:

            rx_desc_set_multicast_hash(s->rx_desc);

            break;

        case GEM_RX_REJECT:

            abort();

        default: 

            rx_desc_set_sar(s->rx_desc, maf);




        

        cpu_physical_memory_write(s->rx_desc_addr,

                                  (uint8_t *)s->rx_desc, sizeof(s->rx_desc));



        

        if (rx_desc_get_wrap(s->rx_desc)) {

            DB_PRINT("wrapping RX descriptor list\n");

            s->rx_desc_addr = s->regs[GEM_RXQBASE];

        } else {

            DB_PRINT("incrementing RX descriptor list\n");

            s->rx_desc_addr += 8;


        gem_get_rx_desc(s);




    

    gem_receive_updatestats(s, buf, size);



    s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;

    s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]);



    

    gem_update_int_status(s);



    return size;

static ssize_t FUNC_0(NetClientState *nc, const uint8_t *buf, size_t size)

{

    CadenceGEMState *s;

    unsigned   VAR_0, VAR_1;

    unsigned   VAR_2;

    uint8_t    rxbuf[2048];

    uint8_t   *rxbuf_ptr;

    bool first_desc = true;

    int VAR_3;



    s = qemu_get_nic_opaque(nc);



    

    VAR_3 = gem_mac_address_filter(s, buf);

    if (VAR_3 == GEM_RX_REJECT) {

        return -1;




    

    if (s->regs[GEM_NWCFG] & GEM_NWCFG_LERR_DISC) {

        unsigned VAR_4;



        

        VAR_4 = buf[12] << 8 | buf[13];

        

        if (VAR_4 < 0x600) {

            if (size < VAR_4) {

                

                return -1;






    





    VAR_2 = (s->regs[GEM_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >>

                   GEM_NWCFG_BUFF_OFST_S;



    





    VAR_0 = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >>

                 GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;




    







    if (size < 60) {

        size = 60;




    

    if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) {

        rxbuf_ptr = (void *)buf;

    } else {

        unsigned VAR_5;







        







        memcpy(rxbuf, buf, size);

        memset(rxbuf + size, 0, sizeof(rxbuf) - size);

        rxbuf_ptr = rxbuf;

        VAR_5 = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));

        memcpy(rxbuf + size, &VAR_5, sizeof(VAR_5));



        VAR_1 += 4;

        size += 4;




    DB_PRINT("config bufsize: %d packet size: %ld\n", VAR_0, size);



    while (VAR_1) {

        

        if (!gem_can_receive(nc)) {

            assert(!first_desc);

            return -1;




        DB_PRINT("copy %d bytes to 0x%x\n", MIN(VAR_1, VAR_0),

                rx_desc_get_buffer(s->rx_desc));



        

        cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + VAR_2,

                                  rxbuf_ptr, MIN(VAR_1, VAR_0));

        rxbuf_ptr += MIN(VAR_1, VAR_0);

        VAR_1 -= MIN(VAR_1, VAR_0);



        

        if (first_desc) {

            rx_desc_set_sof(s->rx_desc);

            first_desc = false;


        if (VAR_1 == 0) {

            rx_desc_set_eof(s->rx_desc);

            rx_desc_set_length(s->rx_desc, size);


        rx_desc_set_ownership(s->rx_desc);



        switch (VAR_3) {

        case GEM_RX_PROMISCUOUS_ACCEPT:

            break;

        case GEM_RX_BROADCAST_ACCEPT:

            rx_desc_set_broadcast(s->rx_desc);

            break;

        case GEM_RX_UNICAST_HASH_ACCEPT:

            rx_desc_set_unicast_hash(s->rx_desc);

            break;

        case GEM_RX_MULTICAST_HASH_ACCEPT:

            rx_desc_set_multicast_hash(s->rx_desc);

            break;

        case GEM_RX_REJECT:

            abort();

        default: 

            rx_desc_set_sar(s->rx_desc, VAR_3);




        

        cpu_physical_memory_write(s->rx_desc_addr,

                                  (uint8_t *)s->rx_desc, sizeof(s->rx_desc));



        

        if (rx_desc_get_wrap(s->rx_desc)) {

            DB_PRINT("wrapping RX descriptor list\n");

            s->rx_desc_addr = s->regs[GEM_RXQBASE];

        } else {

            DB_PRINT("incrementing RX descriptor list\n");

            s->rx_desc_addr += 8;


        gem_get_rx_desc(s);




    

    gem_receive_updatestats(s, buf, size);



    s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;

    s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]);



    

    gem_update_int_status(s);



    return size;

static ssize_t FUNC_0(NetClientState *nc, const uint8_t *buf, size_t size)
{ CadenceGEMState *s; unsigned   VAR_0, VAR_1; unsigned   VAR_2; uint8_t    rxbuf[2048]; uint8_t   *rxbuf_ptr; bool first_desc = true; int VAR_3; s = qemu_get_nic_opaque(nc); VAR_3 = gem_mac_address_filter(s, buf); if (VAR_3 == GEM_RX_REJECT) { return -1; if (s->regs[GEM_NWCFG] & GEM_NWCFG_LERR_DISC) { unsigned VAR_4; VAR_4 = buf[12] << 8 | buf[13]; if (VAR_4 < 0x600) { if (size < VAR_4) { return -1; VAR_2 = (s->regs[GEM_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >>
GEM_NWCFG_BUFF_OFST_S; VAR_0 = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >>
GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL; if (size < 60) { size = 60; if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) { rxbuf_ptr = (void *)buf; } else { unsigned VAR_5; memcpy(rxbuf, buf, size); memset(rxbuf + size, 0, sizeof(rxbuf) - size); rxbuf_ptr = rxbuf; VAR_5 = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60))); memcpy(rxbuf + size, &VAR_5, sizeof(VAR_5)); VAR_1 += 4; size += 4; DB_PRINT("config bufsize: %d packet size: %ld\n", VAR_0, size); while (VAR_1) { if (!gem_can_receive(nc)) { assert(!first_desc); return -1; DB_PRINT("copy %d bytes to 0x%x\n", MIN(VAR_1, VAR_0),
rx_desc_get_buffer(s->rx_desc)); cpu_physical_memory_write(rx_desc_get_buffer(s->rx_desc) + VAR_2,
rxbuf_ptr, MIN(VAR_1, VAR_0)); rxbuf_ptr += MIN(VAR_1, VAR_0); VAR_1 -= MIN(VAR_1, VAR_0); if (first_desc) { rx_desc_set_sof(s->rx_desc); first_desc = false; if (VAR_1 == 0) { rx_desc_set_eof(s->rx_desc); rx_desc_set_length(s->rx_desc, size); rx_desc_set_ownership(s->rx_desc); switch (VAR_3) { case GEM_RX_PROMISCUOUS_ACCEPT:
break; case GEM_RX_BROADCAST_ACCEPT:
rx_desc_set_broadcast(s->rx_desc); break; case GEM_RX_UNICAST_HASH_ACCEPT:
rx_desc_set_unicast_hash(s->rx_desc); break; case GEM_RX_MULTICAST_HASH_ACCEPT:
rx_desc_set_multicast_hash(s->rx_desc); break; case GEM_RX_REJECT:
abort(); default:
rx_desc_set_sar(s->rx_desc, VAR_3); cpu_physical_memory_write(s->rx_desc_addr,
(uint8_t *)s->rx_desc, sizeof(s->rx_desc)); if (rx_desc_get_wrap(s->rx_desc)) { DB_PRINT("wrapping RX descriptor list\n"); s->rx_desc_addr = s->regs[GEM_RXQBASE]; } else { DB_PRINT("incrementing RX descriptor list\n"); s->rx_desc_addr += 8; gem_get_rx_desc(s); gem_receive_updatestats(s, buf, size); s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD; s->regs[GEM_ISR] |= GEM_INT_RXCMPL & ~(s->regs[GEM_IMR]); gem_update_int_status(s); return size;