eepro100: Restructure code (new function tx_command)
Handling of transmit commands is rather complex, so about 80 lines of code were moved from function action_command to the new function tx_command. The two new values "tx" and "cb_address" in the eepro100 status structure made this possible without passing too many parameters. In addition, the moved code was cleaned a little bit: old comments marked with //~ were removed, C++ style comments were replaced by C style comments, C++ like variable declarations after code were reordered. Simplified mode is still broken. Nor did I fix endianess issues. Both problems will be fixed in additional patches (which need this one). Signed-off-by: Stefan Weil <weil@mail.berlios.de> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
		
							parent
							
								
									1c39457adf
								
							
						
					
					
						commit
						f3a52e503b
					
				
							
								
								
									
										193
									
								
								hw/eepro100.c
								
								
								
								
							
							
						
						
									
										193
									
								
								hw/eepro100.c
								
								
								
								
							| 
						 | 
					@ -212,6 +212,11 @@ typedef struct {
 | 
				
			||||||
    uint32_t ru_offset;         /* RU address offset */
 | 
					    uint32_t ru_offset;         /* RU address offset */
 | 
				
			||||||
    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
 | 
					    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Temporary status information (no need to save these values),
 | 
				
			||||||
 | 
					     * used while processing CU commands. */
 | 
				
			||||||
 | 
					    eepro100_tx_t tx;           /* transmit buffer descriptor */
 | 
				
			||||||
 | 
					    uint32_t cb_address;        /* = cu_base + cu_offset */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Statistical counters. Also used for wake-up packet (i82559). */
 | 
					    /* Statistical counters. Also used for wake-up packet (i82559). */
 | 
				
			||||||
    eepro100_stats_t statistics;
 | 
					    eepro100_stats_t statistics;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -760,17 +765,100 @@ static void dump_statistics(EEPRO100State * s)
 | 
				
			||||||
    //~ missing("CU dump statistical counters");
 | 
					    //~ missing("CU dump statistical counters");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tx_command(EEPRO100State *s)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint32_t tbd_array = le32_to_cpu(s->tx.tx_desc_addr);
 | 
				
			||||||
 | 
					    uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
 | 
				
			||||||
 | 
					    /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
 | 
				
			||||||
 | 
					    uint8_t buf[2600];
 | 
				
			||||||
 | 
					    uint16_t size = 0;
 | 
				
			||||||
 | 
					    uint32_t tbd_address = s->cb_address + 0x10;
 | 
				
			||||||
 | 
					    TRACE(RXTX, logout
 | 
				
			||||||
 | 
					        ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
 | 
				
			||||||
 | 
					         tbd_array, tcb_bytes, s->tx.tbd_count));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (tcb_bytes > 2600) {
 | 
				
			||||||
 | 
					        logout("TCB byte count too large, using 2600\n");
 | 
				
			||||||
 | 
					        tcb_bytes = 2600;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
 | 
				
			||||||
 | 
					        logout
 | 
				
			||||||
 | 
					            ("illegal values of TBD array address and TCB byte count!\n");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    assert(tcb_bytes <= sizeof(buf));
 | 
				
			||||||
 | 
					    while (size < tcb_bytes) {
 | 
				
			||||||
 | 
					        uint32_t tx_buffer_address = ldl_phys(tbd_address);
 | 
				
			||||||
 | 
					        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
 | 
				
			||||||
 | 
					        //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
 | 
				
			||||||
 | 
					        tbd_address += 8;
 | 
				
			||||||
 | 
					        TRACE(RXTX, logout
 | 
				
			||||||
 | 
					            ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
 | 
				
			||||||
 | 
					             tx_buffer_address, tx_buffer_size));
 | 
				
			||||||
 | 
					        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
 | 
				
			||||||
 | 
					        cpu_physical_memory_read(tx_buffer_address, &buf[size],
 | 
				
			||||||
 | 
					                                 tx_buffer_size);
 | 
				
			||||||
 | 
					        size += tx_buffer_size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (tbd_array == 0xffffffff) {
 | 
				
			||||||
 | 
					        /* Simplified mode. Was already handled by code above. */
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        /* Flexible mode. */
 | 
				
			||||||
 | 
					        uint8_t tbd_count = 0;
 | 
				
			||||||
 | 
					        if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
 | 
				
			||||||
 | 
					            /* Extended Flexible TCB. */
 | 
				
			||||||
 | 
					            for (; tbd_count < 2; tbd_count++) {
 | 
				
			||||||
 | 
					                uint32_t tx_buffer_address = ldl_phys(tbd_address);
 | 
				
			||||||
 | 
					                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
 | 
				
			||||||
 | 
					                uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
 | 
				
			||||||
 | 
					                tbd_address += 8;
 | 
				
			||||||
 | 
					                TRACE(RXTX, logout
 | 
				
			||||||
 | 
					                    ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
 | 
				
			||||||
 | 
					                     tx_buffer_address, tx_buffer_size));
 | 
				
			||||||
 | 
					                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
 | 
				
			||||||
 | 
					                cpu_physical_memory_read(tx_buffer_address, &buf[size],
 | 
				
			||||||
 | 
					                                         tx_buffer_size);
 | 
				
			||||||
 | 
					                size += tx_buffer_size;
 | 
				
			||||||
 | 
					                if (tx_buffer_el & 1) {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        tbd_address = tbd_array;
 | 
				
			||||||
 | 
					        for (; tbd_count < s->tx.tbd_count; tbd_count++) {
 | 
				
			||||||
 | 
					            uint32_t tx_buffer_address = ldl_phys(tbd_address);
 | 
				
			||||||
 | 
					            uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
 | 
				
			||||||
 | 
					            uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
 | 
				
			||||||
 | 
					            tbd_address += 8;
 | 
				
			||||||
 | 
					            TRACE(RXTX, logout
 | 
				
			||||||
 | 
					                ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
 | 
				
			||||||
 | 
					                 tx_buffer_address, tx_buffer_size));
 | 
				
			||||||
 | 
					            tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
 | 
				
			||||||
 | 
					            cpu_physical_memory_read(tx_buffer_address, &buf[size],
 | 
				
			||||||
 | 
					                                     tx_buffer_size);
 | 
				
			||||||
 | 
					            size += tx_buffer_size;
 | 
				
			||||||
 | 
					            if (tx_buffer_el & 1) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
 | 
				
			||||||
 | 
					    qemu_send_packet(&s->nic->nc, buf, size);
 | 
				
			||||||
 | 
					    s->statistics.tx_good_frames++;
 | 
				
			||||||
 | 
					    /* Transmit with bad status would raise an CX/TNO interrupt.
 | 
				
			||||||
 | 
					     * (82557 only). Emulation never has bad status. */
 | 
				
			||||||
 | 
					    //~ eepro100_cx_interrupt(s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void action_command(EEPRO100State *s)
 | 
					static void action_command(EEPRO100State *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for (;;) {
 | 
					    for (;;) {
 | 
				
			||||||
        uint32_t cb_address = s->cu_base + s->cu_offset;
 | 
					        s->cb_address = s->cu_base + s->cu_offset;
 | 
				
			||||||
        eepro100_tx_t tx;
 | 
					        cpu_physical_memory_read(s->cb_address, (uint8_t *)&s->tx, sizeof(s->tx));
 | 
				
			||||||
        cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx));
 | 
					        uint16_t status = le16_to_cpu(s->tx.status);
 | 
				
			||||||
        uint16_t status = le16_to_cpu(tx.status);
 | 
					        uint16_t command = le16_to_cpu(s->tx.command);
 | 
				
			||||||
        uint16_t command = le16_to_cpu(tx.command);
 | 
					 | 
				
			||||||
        logout
 | 
					        logout
 | 
				
			||||||
            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
 | 
					            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
 | 
				
			||||||
             val, status, command, tx.link);
 | 
					             val, status, command, s->tx.link);
 | 
				
			||||||
        bool bit_el = ((command & 0x8000) != 0);
 | 
					        bool bit_el = ((command & 0x8000) != 0);
 | 
				
			||||||
        bool bit_s = ((command & 0x4000) != 0);
 | 
					        bool bit_s = ((command & 0x4000) != 0);
 | 
				
			||||||
        bool bit_i = ((command & 0x2000) != 0);
 | 
					        bool bit_i = ((command & 0x2000) != 0);
 | 
				
			||||||
| 
						 | 
					@ -778,17 +866,17 @@ static void action_command(EEPRO100State *s)
 | 
				
			||||||
        bool success = true;
 | 
					        bool success = true;
 | 
				
			||||||
        //~ bool bit_sf = ((command & 0x0008) != 0);
 | 
					        //~ bool bit_sf = ((command & 0x0008) != 0);
 | 
				
			||||||
        uint16_t cmd = command & 0x0007;
 | 
					        uint16_t cmd = command & 0x0007;
 | 
				
			||||||
        s->cu_offset = le32_to_cpu(tx.link);
 | 
					        s->cu_offset = le32_to_cpu(s->tx.link);
 | 
				
			||||||
        switch (cmd) {
 | 
					        switch (cmd) {
 | 
				
			||||||
        case CmdNOp:
 | 
					        case CmdNOp:
 | 
				
			||||||
            /* Do nothing. */
 | 
					            /* Do nothing. */
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case CmdIASetup:
 | 
					        case CmdIASetup:
 | 
				
			||||||
            cpu_physical_memory_read(cb_address + 8, &s->conf.macaddr.a[0], 6);
 | 
					            cpu_physical_memory_read(s->cb_address + 8, &s->conf.macaddr.a[0], 6);
 | 
				
			||||||
            TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)));
 | 
					            TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case CmdConfigure:
 | 
					        case CmdConfigure:
 | 
				
			||||||
            cpu_physical_memory_read(cb_address + 8, &s->configuration[0],
 | 
					            cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0],
 | 
				
			||||||
                                     sizeof(s->configuration));
 | 
					                                     sizeof(s->configuration));
 | 
				
			||||||
            TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));
 | 
					            TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
| 
						 | 
					@ -796,95 +884,12 @@ static void action_command(EEPRO100State *s)
 | 
				
			||||||
            //~ missing("multicast list");
 | 
					            //~ missing("multicast list");
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case CmdTx:
 | 
					        case CmdTx:
 | 
				
			||||||
            (void)0;
 | 
					 | 
				
			||||||
            uint32_t tbd_array = le32_to_cpu(tx.tx_desc_addr);
 | 
					 | 
				
			||||||
            uint16_t tcb_bytes = (le16_to_cpu(tx.tcb_bytes) & 0x3fff);
 | 
					 | 
				
			||||||
            TRACE(RXTX, logout
 | 
					 | 
				
			||||||
                ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
 | 
					 | 
				
			||||||
                 tbd_array, tcb_bytes, tx.tbd_count));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (bit_nc) {
 | 
					            if (bit_nc) {
 | 
				
			||||||
                missing("CmdTx: NC = 0");
 | 
					                missing("CmdTx: NC = 0");
 | 
				
			||||||
                success = false;
 | 
					                success = false;
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            //~ assert(!bit_sf);
 | 
					            tx_command(s);
 | 
				
			||||||
            if (tcb_bytes > 2600) {
 | 
					 | 
				
			||||||
                logout("TCB byte count too large, using 2600\n");
 | 
					 | 
				
			||||||
                tcb_bytes = 2600;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            /* Next assertion fails for local configuration. */
 | 
					 | 
				
			||||||
            //~ assert((tcb_bytes > 0) || (tbd_array != 0xffffffff));
 | 
					 | 
				
			||||||
            if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
 | 
					 | 
				
			||||||
                logout
 | 
					 | 
				
			||||||
                    ("illegal values of TBD array address and TCB byte count!\n");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            // sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes
 | 
					 | 
				
			||||||
            uint8_t buf[2600];
 | 
					 | 
				
			||||||
            uint16_t size = 0;
 | 
					 | 
				
			||||||
            uint32_t tbd_address = cb_address + 0x10;
 | 
					 | 
				
			||||||
            assert(tcb_bytes <= sizeof(buf));
 | 
					 | 
				
			||||||
            while (size < tcb_bytes) {
 | 
					 | 
				
			||||||
                uint32_t tx_buffer_address = ldl_phys(tbd_address);
 | 
					 | 
				
			||||||
                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
 | 
					 | 
				
			||||||
                //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
 | 
					 | 
				
			||||||
                tbd_address += 8;
 | 
					 | 
				
			||||||
                TRACE(RXTX, logout
 | 
					 | 
				
			||||||
                    ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
 | 
					 | 
				
			||||||
                     tx_buffer_address, tx_buffer_size));
 | 
					 | 
				
			||||||
                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
 | 
					 | 
				
			||||||
                cpu_physical_memory_read(tx_buffer_address, &buf[size],
 | 
					 | 
				
			||||||
                                         tx_buffer_size);
 | 
					 | 
				
			||||||
                size += tx_buffer_size;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (tbd_array == 0xffffffff) {
 | 
					 | 
				
			||||||
                /* Simplified mode. Was already handled by code above. */
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                /* Flexible mode. */
 | 
					 | 
				
			||||||
                uint8_t tbd_count = 0;
 | 
					 | 
				
			||||||
                if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
 | 
					 | 
				
			||||||
                    /* Extended Flexible TCB. */
 | 
					 | 
				
			||||||
                    for (; tbd_count < 2; tbd_count++) {
 | 
					 | 
				
			||||||
                        uint32_t tx_buffer_address = ldl_phys(tbd_address);
 | 
					 | 
				
			||||||
                        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
 | 
					 | 
				
			||||||
                        uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
 | 
					 | 
				
			||||||
                        tbd_address += 8;
 | 
					 | 
				
			||||||
                        TRACE(RXTX, logout
 | 
					 | 
				
			||||||
                            ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
 | 
					 | 
				
			||||||
                             tx_buffer_address, tx_buffer_size));
 | 
					 | 
				
			||||||
                        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
 | 
					 | 
				
			||||||
                        cpu_physical_memory_read(tx_buffer_address, &buf[size],
 | 
					 | 
				
			||||||
                                                 tx_buffer_size);
 | 
					 | 
				
			||||||
                        size += tx_buffer_size;
 | 
					 | 
				
			||||||
                        if (tx_buffer_el & 1) {
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                tbd_address = tbd_array;
 | 
					 | 
				
			||||||
                for (; tbd_count < tx.tbd_count; tbd_count++) {
 | 
					 | 
				
			||||||
                    uint32_t tx_buffer_address = ldl_phys(tbd_address);
 | 
					 | 
				
			||||||
                    uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
 | 
					 | 
				
			||||||
                    uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
 | 
					 | 
				
			||||||
                    tbd_address += 8;
 | 
					 | 
				
			||||||
                    TRACE(RXTX, logout
 | 
					 | 
				
			||||||
                        ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
 | 
					 | 
				
			||||||
                         tx_buffer_address, tx_buffer_size));
 | 
					 | 
				
			||||||
                    tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
 | 
					 | 
				
			||||||
                    cpu_physical_memory_read(tx_buffer_address, &buf[size],
 | 
					 | 
				
			||||||
                                             tx_buffer_size);
 | 
					 | 
				
			||||||
                    size += tx_buffer_size;
 | 
					 | 
				
			||||||
                    if (tx_buffer_el & 1) {
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
 | 
					 | 
				
			||||||
            qemu_send_packet(&s->nic->nc, buf, size);
 | 
					 | 
				
			||||||
            s->statistics.tx_good_frames++;
 | 
					 | 
				
			||||||
            /* Transmit with bad status would raise an CX/TNO interrupt.
 | 
					 | 
				
			||||||
             * (82557 only). Emulation never has bad status. */
 | 
					 | 
				
			||||||
            //~ eepro100_cx_interrupt(s);
 | 
					 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case CmdTDR:
 | 
					        case CmdTDR:
 | 
				
			||||||
            TRACE(OTHER, logout("load microcode\n"));
 | 
					            TRACE(OTHER, logout("load microcode\n"));
 | 
				
			||||||
| 
						 | 
					@ -897,7 +902,7 @@ static void action_command(EEPRO100State *s)
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /* Write new status. */
 | 
					        /* Write new status. */
 | 
				
			||||||
        stw_phys(cb_address, status | 0x8000 | (success ? 0x2000 : 0));
 | 
					        stw_phys(s->cb_address, status | 0x8000 | (success ? 0x2000 : 0));
 | 
				
			||||||
        if (bit_i) {
 | 
					        if (bit_i) {
 | 
				
			||||||
            /* CU completed action. */
 | 
					            /* CU completed action. */
 | 
				
			||||||
            eepro100_cx_interrupt(s);
 | 
					            eepro100_cx_interrupt(s);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue