Revision 7b8737de hw/eepro100.c

b/hw/eepro100.c
140 140
    uint16_t status;
141 141
    uint16_t command;
142 142
    uint32_t link;              /* void * */
143
    uint32_t tx_desc_addr;      /* transmit buffer decsriptor array address. */
143
    uint32_t tbd_array_addr;    /* transmit buffer descriptor array address. */
144 144
    uint16_t tcb_bytes;         /* transmit command block byte count (in lower 14 bits */
145 145
    uint8_t tx_threshold;       /* transmit threshold */
146 146
    uint8_t tbd_count;          /* TBD number */
......
267 267

  
268 268
/* From FreeBSD */
269 269
/* XXX: optimize */
270
static int compute_mcast_idx(const uint8_t * ep)
270
static unsigned compute_mcast_idx(const uint8_t * ep)
271 271
{
272 272
    uint32_t crc;
273 273
    int carry, i, j;
......
285 285
            }
286 286
        }
287 287
    }
288
    return (crc >> 26);
288
    return (crc & BITS(7, 2)) >> 2;
289 289
}
290 290

  
291 291
#if defined(DEBUG_EEPRO100)
......
648 648
{
649 649
    EEPRO100State *s = opaque;
650 650
    TRACE(OTHER, logout("%p\n", s));
651
    /* TODO: Clearing of multicast table for selective reset, too? */
652
    memset(&s->mult[0], 0, sizeof(s->mult));
651 653
    nic_selective_reset(s);
652 654
}
653 655

  
......
767 769

  
768 770
static void tx_command(EEPRO100State *s)
769 771
{
770
    uint32_t tbd_array = le32_to_cpu(s->tx.tx_desc_addr);
772
    uint32_t tbd_array = le32_to_cpu(s->tx.tbd_array_addr);
771 773
    uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
772 774
    /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
773 775
    uint8_t buf[2600];
......
849 851
    //~ eepro100_cx_interrupt(s);
850 852
}
851 853

  
854
static void set_multicast_list(EEPRO100State *s)
855
{
856
    uint16_t multicast_count = s->tx.tbd_array_addr & BITS(13, 0);
857
    uint16_t i;
858
    memset(&s->mult[0], 0, sizeof(s->mult));
859
    TRACE(OTHER, logout("multicast list, multicast count = %u\n", multicast_count));
860
    for (i = 0; i < multicast_count; i += 6) {
861
        uint8_t multicast_addr[6];
862
        cpu_physical_memory_read(s->cb_address + 10 + i, multicast_addr, 6);
863
        TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
864
        unsigned mcast_idx = compute_mcast_idx(multicast_addr);
865
        assert(mcast_idx < 64);
866
        s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
867
    }
868
}
869

  
852 870
static void action_command(EEPRO100State *s)
853 871
{
854 872
    for (;;) {
......
881 899
            TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));
882 900
            break;
883 901
        case CmdMulticastList:
884
            //~ missing("multicast list");
902
            set_multicast_list(s);
885 903
            break;
886 904
        case CmdTx:
887 905
            if (bit_nc) {
......
1664 1682
        /* Broadcast frame. */
1665 1683
        TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size));
1666 1684
        rfd_status |= 0x0002;
1667
    } else if (buf[0] & 0x01) { // !!!
1685
    } else if (buf[0] & 0x01) {
1668 1686
        /* Multicast frame. */
1669
        TRACE(RXTX, logout("%p received multicast, len=%zu\n", s, size));
1670
        /* TODO: check multicast all bit. */
1687
        TRACE(RXTX, logout("%p received multicast, len=%zu,%s\n", s, size, nic_dump(buf, size)));
1671 1688
        if (s->configuration[21] & BIT(3)) {
1672
            missing("Multicast All bit");
1673
        }
1674
        int mcast_idx = compute_mcast_idx(buf);
1675
        if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) {
1676
            return size;
1689
          /* Multicast all bit is set, receive all multicast frames. */
1690
        } else {
1691
          unsigned mcast_idx = compute_mcast_idx(buf);
1692
          assert(mcast_idx < 64);
1693
          if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1694
            /* Multicast frame is allowed in hash table. */
1695
          } else if (s->configuration[15] & 1) {
1696
              /* Promiscuous: receive all. */
1697
              rfd_status |= 0x0004;
1698
          } else {
1699
              TRACE(RXTX, logout("%p multicast ignored\n", s));
1700
              return -1;
1701
          }
1677 1702
        }
1703
        /* TODO: Next not for promiscuous mode? */
1678 1704
        rfd_status |= 0x0002;
1679 1705
    } else if (s->configuration[15] & 1) {
1680 1706
        /* Promiscuous: receive all. */

Also available in: Unified diff