Revision f3a52e50

b/hw/eepro100.c
212 212
    uint32_t ru_offset;         /* RU address offset */
213 213
    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
214 214

  
215
    /* Temporary status information (no need to save these values),
216
     * used while processing CU commands. */
217
    eepro100_tx_t tx;           /* transmit buffer descriptor */
218
    uint32_t cb_address;        /* = cu_base + cu_offset */
219

  
215 220
    /* Statistical counters. Also used for wake-up packet (i82559). */
216 221
    eepro100_stats_t statistics;
217 222

  
......
760 765
    //~ missing("CU dump statistical counters");
761 766
}
762 767

  
768
static void tx_command(EEPRO100State *s)
769
{
770
    uint32_t tbd_array = le32_to_cpu(s->tx.tx_desc_addr);
771
    uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
772
    /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
773
    uint8_t buf[2600];
774
    uint16_t size = 0;
775
    uint32_t tbd_address = s->cb_address + 0x10;
776
    TRACE(RXTX, logout
777
        ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
778
         tbd_array, tcb_bytes, s->tx.tbd_count));
779

  
780
    if (tcb_bytes > 2600) {
781
        logout("TCB byte count too large, using 2600\n");
782
        tcb_bytes = 2600;
783
    }
784
    if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
785
        logout
786
            ("illegal values of TBD array address and TCB byte count!\n");
787
    }
788
    assert(tcb_bytes <= sizeof(buf));
789
    while (size < tcb_bytes) {
790
        uint32_t tx_buffer_address = ldl_phys(tbd_address);
791
        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
792
        //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
793
        tbd_address += 8;
794
        TRACE(RXTX, logout
795
            ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
796
             tx_buffer_address, tx_buffer_size));
797
        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
798
        cpu_physical_memory_read(tx_buffer_address, &buf[size],
799
                                 tx_buffer_size);
800
        size += tx_buffer_size;
801
    }
802
    if (tbd_array == 0xffffffff) {
803
        /* Simplified mode. Was already handled by code above. */
804
    } else {
805
        /* Flexible mode. */
806
        uint8_t tbd_count = 0;
807
        if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
808
            /* Extended Flexible TCB. */
809
            for (; tbd_count < 2; tbd_count++) {
810
                uint32_t tx_buffer_address = ldl_phys(tbd_address);
811
                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
812
                uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
813
                tbd_address += 8;
814
                TRACE(RXTX, logout
815
                    ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
816
                     tx_buffer_address, tx_buffer_size));
817
                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
818
                cpu_physical_memory_read(tx_buffer_address, &buf[size],
819
                                         tx_buffer_size);
820
                size += tx_buffer_size;
821
                if (tx_buffer_el & 1) {
822
                    break;
823
                }
824
            }
825
        }
826
        tbd_address = tbd_array;
827
        for (; tbd_count < s->tx.tbd_count; tbd_count++) {
828
            uint32_t tx_buffer_address = ldl_phys(tbd_address);
829
            uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
830
            uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
831
            tbd_address += 8;
832
            TRACE(RXTX, logout
833
                ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
834
                 tx_buffer_address, tx_buffer_size));
835
            tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
836
            cpu_physical_memory_read(tx_buffer_address, &buf[size],
837
                                     tx_buffer_size);
838
            size += tx_buffer_size;
839
            if (tx_buffer_el & 1) {
840
                break;
841
            }
842
        }
843
    }
844
    TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
845
    qemu_send_packet(&s->nic->nc, buf, size);
846
    s->statistics.tx_good_frames++;
847
    /* Transmit with bad status would raise an CX/TNO interrupt.
848
     * (82557 only). Emulation never has bad status. */
849
    //~ eepro100_cx_interrupt(s);
850
}
851

  
763 852
static void action_command(EEPRO100State *s)
764 853
{
765 854
    for (;;) {
766
        uint32_t cb_address = s->cu_base + s->cu_offset;
767
        eepro100_tx_t tx;
768
        cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx));
769
        uint16_t status = le16_to_cpu(tx.status);
770
        uint16_t command = le16_to_cpu(tx.command);
855
        s->cb_address = s->cu_base + s->cu_offset;
856
        cpu_physical_memory_read(s->cb_address, (uint8_t *)&s->tx, sizeof(s->tx));
857
        uint16_t status = le16_to_cpu(s->tx.status);
858
        uint16_t command = le16_to_cpu(s->tx.command);
771 859
        logout
772 860
            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
773
             val, status, command, tx.link);
861
             val, status, command, s->tx.link);
774 862
        bool bit_el = ((command & 0x8000) != 0);
775 863
        bool bit_s = ((command & 0x4000) != 0);
776 864
        bool bit_i = ((command & 0x2000) != 0);
......
778 866
        bool success = true;
779 867
        //~ bool bit_sf = ((command & 0x0008) != 0);
780 868
        uint16_t cmd = command & 0x0007;
781
        s->cu_offset = le32_to_cpu(tx.link);
869
        s->cu_offset = le32_to_cpu(s->tx.link);
782 870
        switch (cmd) {
783 871
        case CmdNOp:
784 872
            /* Do nothing. */
785 873
            break;
786 874
        case CmdIASetup:
787
            cpu_physical_memory_read(cb_address + 8, &s->conf.macaddr.a[0], 6);
875
            cpu_physical_memory_read(s->cb_address + 8, &s->conf.macaddr.a[0], 6);
788 876
            TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)));
789 877
            break;
790 878
        case CmdConfigure:
791
            cpu_physical_memory_read(cb_address + 8, &s->configuration[0],
879
            cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0],
792 880
                                     sizeof(s->configuration));
793 881
            TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));
794 882
            break;
......
796 884
            //~ missing("multicast list");
797 885
            break;
798 886
        case CmdTx:
799
            (void)0;
800
            uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr);
801
            uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff);
802
            TRACE(RXTX, logout
803
                ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
804
                 tbd_array, tcb_bytes, tx.tbd_count));
805

  
806 887
            if (bit_nc) {
807 888
                missing("CmdTx: NC = 0");
808 889
                success = false;
809 890
                break;
810 891
            }
811
            //~ assert(!bit_sf);
812
            if (tcb_bytes > 2600) {
813
                logout("TCB byte count too large, using 2600\n");
814
                tcb_bytes = 2600;
815
            }
816
            /* Next assertion fails for local configuration. */
817
            //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));
818
            if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
819
                logout
820
                    ("illegal values of TBD array address and TCB byte count!\n");
821
            }
822
            // sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes
823
            uint8_t buf[2600];
824
            uint16_t size = 0;
825
            uint32_t tbd_address = cb_address + 0x10;
826
            assert(tcb_bytes <= sizeof(buf));
827
            while (size < tcb_bytes) {
828
                uint32_t tx_buffer_address = ldl_phys(tbd_address);
829
                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
830
                //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
831
                tbd_address += 8;
832
                TRACE(RXTX, logout
833
                    ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
834
                     tx_buffer_address, tx_buffer_size));
835
                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
836
                cpu_physical_memory_read(tx_buffer_address, &buf[size],
837
                                         tx_buffer_size);
838
                size += tx_buffer_size;
839
            }
840
            if (tbd_array == 0xffffffff) {
841
                /* Simplified mode. Was already handled by code above. */
842
            } else {
843
                /* Flexible mode. */
844
                uint8_t tbd_count = 0;
845
                if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
846
                    /* Extended Flexible TCB. */
847
                    for (; tbd_count < 2; tbd_count++) {
848
                        uint32_t tx_buffer_address = ldl_phys(tbd_address);
849
                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
850
                        uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
851
                        tbd_address += 8;
852
                        TRACE(RXTX, logout
853
                            ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
854
                             tx_buffer_address, tx_buffer_size));
855
                        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
856
                        cpu_physical_memory_read(tx_buffer_address, &buf[size],
857
                                                 tx_buffer_size);
858
                        size += tx_buffer_size;
859
                        if (tx_buffer_el & 1) {
860
                            break;
861
                        }
862
                    }
863
                }
864
                tbd_address = tbd_array;
865
                for (; tbd_count < tx.tbd_count; tbd_count++) {
866
                    uint32_t tx_buffer_address = ldl_phys(tbd_address);
867
                    uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
868
                    uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
869
                    tbd_address += 8;
870
                    TRACE(RXTX, logout
871
                        ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
872
                         tx_buffer_address, tx_buffer_size));
873
                    tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
874
                    cpu_physical_memory_read(tx_buffer_address, &buf[size],
875
                                             tx_buffer_size);
876
                    size += tx_buffer_size;
877
                    if (tx_buffer_el & 1) {
878
                        break;
879
                    }
880
                }
881
            }
882
            TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
883
            qemu_send_packet(&s->nic->nc, buf, size);
884
            s->statistics.tx_good_frames++;
885
            /* Transmit with bad status would raise an CX/TNO interrupt.
886
             * (82557 only). Emulation never has bad status. */
887
            //~ eepro100_cx_interrupt(s);
892
            tx_command(s);
888 893
            break;
889 894
        case CmdTDR:
890 895
            TRACE(OTHER, logout("load microcode\n"));
......
897 902
            break;
898 903
        }
899 904
        /* Write new status. */
900
        stw_phys(cb_address, status | 0x8000 | (success ? 0x2000 : 0));
905
        stw_phys(s->cb_address, status | 0x8000 | (success ? 0x2000 : 0));
901 906
        if (bit_i) {
902 907
            /* CU completed action. */
903 908
            eepro100_cx_interrupt(s);

Also available in: Unified diff