From patchwork Fri Oct 2 18:57:52 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Weil X-Patchwork-Id: 34874 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2C74FB7BF9 for ; Sat, 3 Oct 2009 04:59:08 +1000 (EST) Received: from localhost ([127.0.0.1]:50418 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MtnLL-0001y4-Hn for incoming@patchwork.ozlabs.org; Fri, 02 Oct 2009 14:59:03 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MtnKp-0001xs-Jh for qemu-devel@nongnu.org; Fri, 02 Oct 2009 14:58:31 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MtnKl-0001up-Ue for qemu-devel@nongnu.org; Fri, 02 Oct 2009 14:58:31 -0400 Received: from [199.232.76.173] (port=59444 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MtnKl-0001uh-OO for qemu-devel@nongnu.org; Fri, 02 Oct 2009 14:58:27 -0400 Received: from moutng.kundenserver.de ([212.227.126.177]:51203) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MtnKk-0004Pw-QJ for qemu-devel@nongnu.org; Fri, 02 Oct 2009 14:58:27 -0400 Received: from flocke.weilnetz.de (p54ADF8A8.dip.t-dialin.net [84.173.248.168]) by mrelayeu.kundenserver.de (node=mreu2) with ESMTP (Nemesis) id 0MKdiF-1MsPsk1c1v-001hHO; Fri, 02 Oct 2009 20:57:53 +0200 Received: from stefan by flocke.weilnetz.de with local (Exim 4.69) (envelope-from ) id 1MtnKC-0003XR-9y; Fri, 02 Oct 2009 20:57:52 +0200 From: Stefan Weil To: QEMU Developers Date: Fri, 2 Oct 2009 20:57:52 +0200 Message-Id: <1254509872-13051-1-git-send-email-weil@mail.berlios.de> X-Mailer: git-send-email 1.5.6.5 X-Provags-ID: V01U2FsdGVkX1/3eZjMkXaroYd6zlKvMRyljVJ5dPUq1yZ365h m/UBpDrjLl3IerOXnLnz97FHsekAFE/aOV/r5D9H3KSCE85m/V RQ9wfQgHBASDYEJI6vsH7bxptbsV+Lya1J8yzbfcPQ= X-detected-operating-system: by monty-python.gnu.org: Genre and OS details not recognized. Cc: Subject: [Qemu-devel] [PATCH] eepro100: Restructure code X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org * Move common code for CU_START, CU_RESUME to new function action_command. * Move code for CmdTx to new function tx_command. This patch is a step to synchronize my maintainer version of eepro100.c (git://repo.or.cz/qemu/ar7.git) with the version integrated in QEMU. Signed-off-by: Stefan Weil --- hw/eepro100.c | 270 ++++++++++++++++++++++++++++++--------------------------- 1 files changed, 142 insertions(+), 128 deletions(-) diff --git a/hw/eepro100.c b/hw/eepro100.c index 6d49bb8..e2f6e8a 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -56,7 +56,7 @@ #define KiB 1024 /* Debug EEPRO100 card. */ -//~ #define DEBUG_EEPRO100 +/* #define DEBUG_EEPRO100 */ #ifdef DEBUG_EEPRO100 #define logout(fmt, ...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ## __VA_ARGS__) @@ -214,6 +214,11 @@ typedef struct { uint32_t ru_base; /* RU base address */ uint32_t ru_offset; /* RU address offset */ uint32_t statsaddr; /* pointer to eepro100_stats_t */ + + /* Temporary data. */ + eepro100_tx_t tx; + uint32_t cb_address; + /* Statistical counters. Also used for wake-up packet (i82559). */ eepro100_stats_t statistics; #if 0 @@ -412,13 +417,9 @@ static void pci_reset(EEPRO100State * s) /* check cache line size!!! */ //~ PCI_CONFIG_8(0x0c, 0x00); /* PCI Latency Timer */ - PCI_CONFIG_8(0x0d, 0x20); // latency timer = 32 clocks + PCI_CONFIG_8(0x0d, 0x20); /* latency timer = 32 clocks */ /* PCI Header Type */ /* BIST (built-in self test) */ -#if defined(TARGET_I386) -// !!! workaround for buggy bios -//~ #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0 -#endif #if 0 /* PCI Base Address Registers */ /* CSR Memory Mapped Base Address */ @@ -437,7 +438,7 @@ static void pci_reset(EEPRO100State * s) PCI_CONFIG_8(0x34, 0xdc); /* Interrupt Line */ /* Interrupt Pin */ - PCI_CONFIG_8(0x3d, 1); // interrupt pin 0 + PCI_CONFIG_8(0x3d, 1); /* interrupt pin 0 */ /* Minimum Grant */ PCI_CONFIG_8(0x3e, 0x08); /* Maximum Latency */ @@ -631,49 +632,122 @@ static void dump_statistics(EEPRO100State * s) //~ missing("CU dump statistical counters"); } -static void eepro100_cu_command(EEPRO100State * s, uint8_t val) -{ - eepro100_tx_t tx; - uint32_t cb_address; - switch (val) { - case CU_NOP: - /* No operation. */ - break; - case CU_START: - if (get_cu_state(s) != cu_idle) { - /* Intel documentation says that CU must be idle for the CU - * start command. Intel driver for Linux also starts the CU - * from suspended state. */ - logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle); - //~ assert(!"wrong CU state"); +static void tx_command(EEPRO100State *s) +{ + /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */ + uint8_t buf[2600]; + uint16_t size = 0; + uint32_t tbd_array = le32_to_cpu(s->tx.tx_desc_addr); + uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff); + uint32_t tbd_address; + 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)); + //~ assert(!bit_sf); + assert(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"); + } + tbd_address = s->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 (device_supports_eTxCB(s) && !(s->configuration[6] & BIT(4))) { + /* Extended Flexible TCB. */ + assert(tcb_bytes == 0); + 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; + } + } } - set_cu_state(s, cu_active); - s->cu_offset = s->pointer; - next_command: - cb_address = s->cu_base + s->cu_offset; - cpu_physical_memory_read(cb_address, (uint8_t *) & tx, sizeof(tx)); - uint16_t status = le16_to_cpu(tx.status); - uint16_t command = le16_to_cpu(tx.command); + 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->vc, 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) +{ + for (;;) { + uint16_t status; + uint16_t command; + bool bit_el; + bool bit_s; + bool bit_i; + uint16_t cmd; + s->cb_address = s->cu_base + s->cu_offset; + cpu_physical_memory_read(s->cb_address, (uint8_t *)&s->tx, sizeof(s->tx)); + status = le16_to_cpu(s->tx.status); + command = le16_to_cpu(s->tx.command); logout ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n", - val, status, command, tx.link); - bool bit_el = ((command & 0x8000) != 0); - bool bit_s = ((command & 0x4000) != 0); - bool bit_i = ((command & 0x2000) != 0); - bool bit_nc = ((command & 0x0010) != 0); - //~ bool bit_sf = ((command & 0x0008) != 0); - uint16_t cmd = command & 0x0007; - s->cu_offset = le32_to_cpu(tx.link); + val, status, command, s->tx.link); + bit_el = ((command & 0x8000) != 0); + bit_s = ((command & 0x4000) != 0); + bit_i = ((command & 0x2000) != 0); + cmd = command & 0x0007; + s->cu_offset = le32_to_cpu(s->tx.link); switch (cmd) { case CmdNOp: /* Do nothing. */ break; case CmdIASetup: - cpu_physical_memory_read(cb_address + 8, &s->macaddr[0], 6); + cpu_physical_memory_read(s->cb_address + 8, &s->macaddr[0], 6); TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6))); break; 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)); TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16))); break; @@ -681,88 +755,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) //~ missing("multicast list"); break; 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)); - assert(!bit_nc); - //~ assert(!bit_sf); - assert(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 (device_supports_eTxCB(s) && !(s->configuration[6] & BIT(4))) { - /* Extended Flexible TCB. */ - assert(tcb_bytes == 0); - 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->vc, 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); + tx_command(s); break; case CmdTDR: TRACE(OTHER, logout("load microcode\n")); @@ -773,7 +766,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) missing("undefined command"); } /* Write new status (success). */ - stw_phys(cb_address, status | 0x8000 | 0x2000); + stw_phys(s->cb_address, status | 0x8000 | 0x2000); if (bit_i) { /* CU completed action. */ eepro100_cx_interrupt(s); @@ -782,17 +775,38 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) /* CU becomes idle. Terminate command loop. */ set_cu_state(s, cu_idle); eepro100_cna_interrupt(s); + break; } else if (bit_s) { - /* CU becomes suspended. */ + /* CU becomes suspended. Terminate command loop. */ set_cu_state(s, cu_suspended); eepro100_cna_interrupt(s); + break; } else { /* More entries in list. */ TRACE(OTHER, logout("CU list with at least one more entry\n")); - goto next_command; } - TRACE(OTHER, logout("CU list empty\n")); - /* List is empty. Now CU is idle or suspended. */ + } + TRACE(OTHER, logout("CU list empty\n")); + /* List is empty. Now CU is idle or suspended. */ +} + +static void eepro100_cu_command(EEPRO100State * s, uint8_t val) +{ + switch (val) { + case CU_NOP: + /* No operation. */ + break; + case CU_START: + if (get_cu_state(s) != cu_idle) { + /* Intel documentation says that CU must be idle for the CU + * start command. Intel driver for Linux also starts the CU + * from suspended state. */ + logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle); + //~ assert(!"wrong CU state"); + } + set_cu_state(s, cu_active); + s->cu_offset = s->pointer; + action_command(s); break; case CU_RESUME: if (get_cu_state(s) != cu_suspended) { @@ -805,7 +819,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) if (get_cu_state(s) == cu_suspended) { TRACE(OTHER, logout("CU resuming\n")); set_cu_state(s, cu_active); - goto next_command; + action_command(s); } break; case CU_STATSADDR: @@ -1505,7 +1519,7 @@ static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size * Long frames are discarded. */ logout("%p received long frame (%zu byte), ignored\n", s, size); return -1; - } else if (memcmp(buf, s->macaddr, 6) == 0) { // !!! + } else if (memcmp(buf, s->macaddr, 6) == 0) { /* !!! */ /* Frame matches individual address. */ /* TODO: check configuration byte 15/4 (ignore U/L). */ TRACE(RXTX, logout("%p received frame for me, len=%zu\n", s, size)); @@ -1513,7 +1527,7 @@ static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size /* Broadcast frame. */ TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size)); rfd_status |= 0x0002; - } else if (buf[0] & 0x01) { // !!! + } else if (buf[0] & 0x01) { /* !!! */ /* Multicast frame. */ TRACE(RXTX, logout("%p received multicast, len=%zu\n", s, size)); /* TODO: check multicast all bit. */