[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] eepro100: Restructure code
From: |
Stefan Weil |
Subject: |
[Qemu-devel] [PATCH] eepro100: Restructure code |
Date: |
Sun, 20 Sep 2009 13:09:57 +0200 |
* 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 <address@hidden>
---
hw/eepro100.c | 241 ++++++++++++++++++++++++++++++---------------------------
1 files changed, 127 insertions(+), 114 deletions(-)
diff --git a/hw/eepro100.c b/hw/eepro100.c
index 6d49bb8..34c2bcf 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -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
@@ -631,49 +636,117 @@ static void dump_statistics(EEPRO100State * s)
//~ missing("CU dump statistical counters");
}
-static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
+static void tx_command(EEPRO100State *s)
{
- 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");
+ uint32_t tbd_array = le32_to_cpu(s->tx.tx_desc_addr);
+ uint16_t tcb_bytes = (le16_to_cpu(s->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, 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");
+ }
+ // 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;
+ 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 (;;) {
+ s->cb_address = s->cu_base + s->cu_offset;
+ cpu_physical_memory_read(s->cb_address, (uint8_t *)&s->tx,
sizeof(s->tx));
+ uint16_t status = le16_to_cpu(s->tx.status);
+ uint16_t 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);
+ val, status, command, s->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_nc = ((command & 0x0010) != 0);
//~ bool bit_sf = ((command & 0x0008) != 0);
uint16_t cmd = command & 0x0007;
- s->cu_offset = le32_to_cpu(tx.link);
+ 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 +754,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 +765,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 +774,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 +818,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:
--
1.5.6.5
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] eepro100: Restructure code,
Stefan Weil <=