qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] Intel 8255x/eepro100 compatibility patches
@ 2009-08-09 21:14 Reimar Döffinger
  2009-08-10  4:36 ` Stefan Weil
  2009-08-11 18:27 ` Reimar Döffinger
  0 siblings, 2 replies; 19+ messages in thread
From: Reimar Döffinger @ 2009-08-09 21:14 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 2126 bytes --]

Hello everyone,
I have been playing around a bit with the OS X/darwin network drivers for these
cards and noticed that they seem to differ quite a bit from the Linux ones.
If you're interested, the source of the core part is here:
http://www.opensource.apple.com/source/AppleIntel8255x/AppleIntel8255x-19/i82557Private.cpp
Attached is a series of patches that makes things work with at least
some version of that (sorry, I only tried some binary I found on the
net, didn't compile from source).
In addition, I also used the documentation from here:
http://www.intel.com/design/network/manuals/8255X_OpenSDM.htm

The first patch does not set the SBAck flag for MDI interrupts when
interrupts are actually disabled for MDI.
I think (have not tested yet) that this is not necessary to fix
anything, but according to the documentation the current code is wrong.

The second patch is to ensure that a driver will not
accidentally/incorrectly change the RU/CU state with a write.
This is incomplete and a bit ugly, but good enough for these drivers.

The third patch adds support for some kind of receive buffers "flexible
mode". The Intel documentation as I read it claims that no such mode exist
for receive, but the fact that those (working with real hardware I
expect) drivers use it contradicts that...
This _definitely_ is necessary to support these drivers.

And the last patch expands received data shorter than 60 bytes so no
short-frame detection is incorrectly triggered, and of course also
throws away all short-frame detection code since it makes no sense.
It was also wrong since size is without CRC and thus the short frame
limit is 60, not 64. And related to that (but without a patch), I think
that the
>    } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & 8)) {
check is wrong, too, and the + 4 should not be there...
Back to the patch, e.g. the rtl8139 driver also expands those frames
(and I just copied the code for that).
This too _definitely_ is necessary to support these drivers.

Hope this is interesting to someone and maybe we can even get these
merged...

Thanks,
Reimar Döffinger

[-- Attachment #2: 0001-Setting-the-MDI-SCBAck-flag-when-interrupts-for-MDI-.patch --]
[-- Type: text/plain, Size: 998 bytes --]

>From cdd96658f21e571c077fee08a4ba64e79d49c0b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= <reimar@hokum.(none)>
Date: Sun, 9 Aug 2009 21:36:45 +0200
Subject: [PATCH 1/4] Setting the MDI SCBAck flag when interrupts for MDI are disabled is
 wrong, even if it does not seem to cause any real issue with known
 drivers.

---
 hw/eepro100.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/hw/eepro100.c b/hw/eepro100.c
index ec31a6a..bf5d920 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1043,9 +1043,7 @@ static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
             }
             data = s->mdimem[reg];
         }
-        /* Emulation takes no time to finish MDI transaction.
-         * Set MDI bit in SCB status register. */
-        s->mem[SCBAck] |= 0x08;
+        /* Emulation takes no time to finish MDI transaction. */
         val |= BIT(28);
         if (raiseint) {
             eepro100_mdi_interrupt(s);
-- 
1.6.4


[-- Attachment #3: 0002-Hack-to-make-sure-that-drivers-like-AppleIntel8255x-.patch --]
[-- Type: text/plain, Size: 1035 bytes --]

>From 84f2d6ecf89c1dbd5f83676251aa2f646e2270b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= <reimar@hokum.(none)>
Date: Sun, 9 Aug 2009 21:39:36 +0200
Subject: [PATCH 2/4] Hack to make sure that drivers like AppleIntel8255x will not meddle
 with the RU/CU state when the ACK the interrupt with a 16 bit write.

---
 hw/eepro100.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/hw/eepro100.c b/hw/eepro100.c
index bf5d920..f619d36 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1249,7 +1249,11 @@ static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
 static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
 {
     if (addr <= sizeof(s->mem) - sizeof(val)) {
+        ru_state_t rtmp = get_ru_state(s);
+        cu_state_t ctmp = get_cu_state(s);
         memcpy(&s->mem[addr], &val, sizeof(val));
+        set_cu_state(s, ctmp);
+        set_ru_state(s, rtmp);
     }
 
     logout("addr=%s val=0x%04x\n", regname(addr), val);
-- 
1.6.4


[-- Attachment #4: 0003-Add-support-for-receiving-via-receive-buffers.patch --]
[-- Type: text/plain, Size: 3486 bytes --]

>From 670b2dcb0a0914415f58eabf56c304f72c9c23b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= <reimar@hokum.(none)>
Date: Sun, 9 Aug 2009 20:06:46 +0200
Subject: [PATCH 3/4] Add support for receiving via receive buffers.
 While the Intel documentation claims this is unsupported, the OS X drivers use it,
 causing an assertion failure since rx buffer size is 0.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
---
 hw/eepro100.c |   27 ++++++++++++++++++++++++---
 1 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/hw/eepro100.c b/hw/eepro100.c
index f619d36..5620bc7 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -153,6 +153,14 @@ typedef struct {
     char packet[MAX_ETH_FRAME_SIZE + 4];
 } eepro100_rx_t;
 
+/* Receive buffer descriptor. */
+typedef struct {
+    uint32_t count;
+    uint32_t link;
+    uint32_t buffer;
+    uint32_t size;
+} eepro100_rbd_t;
+
 typedef struct {
     uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions,
         tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
@@ -218,6 +226,7 @@ typedef struct {
     /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
     uint32_t ru_base;           /* RU base address */
     uint32_t ru_offset;         /* RU address offset */
+    uint32_t rbd_addr;
     uint32_t statsaddr;         /* pointer to eepro100_stats_t */
     eepro100_stats_t statistics;        /* statistical counters */
 #if 0
@@ -843,6 +852,7 @@ static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
         }
         set_ru_state(s, ru_ready);
         s->ru_offset = s->pointer;
+        s->rbd_addr = 0;
         logout("val=0x%02x (rx start)\n", val);
         break;
     case RX_RESUME:
@@ -1512,7 +1522,19 @@ static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size
     cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx,
                              offsetof(eepro100_rx_t, packet));
     uint16_t rfd_command = le16_to_cpu(rx.command);
-    uint16_t rfd_size = le16_to_cpu(rx.size);
+    uint32_t rfd_size = le16_to_cpu(rx.size);
+    uint32_t dst_addr = s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, packet);
+    if (rfd_command & 8) {
+        // argh! Flexible mode. Intel docs say it is not support but the Mac OS driver uses it anyway.
+        eepro100_rbd_t rbd;
+        if (!s->rbd_addr)
+            s->rbd_addr = le32_to_cpu(rx.rx_buf_addr);
+        cpu_physical_memory_read(s->rbd_addr, (uint8_t *) & rbd, sizeof(rbd));
+        rfd_size = le32_to_cpu(rbd.size);
+        dst_addr = le32_to_cpu(rbd.buffer);
+        stl_phys(s->rbd_addr + offsetof(eepro100_rbd_t, count), size | 0x8000);
+        s->rbd_addr = le32_to_cpu(rbd.link);
+    }
     assert(size <= rfd_size);
     if (size < 64) {
         rfd_status |= 0x0080;
@@ -1528,8 +1550,7 @@ static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size
     assert(!(s->configuration[18] & 4));
     /* TODO: check stripping enable bit. */
     //~ assert(!(s->configuration[17] & 1));
-    cpu_physical_memory_write(s->ru_base + s->ru_offset +
-                              offsetof(eepro100_rx_t, packet), buf, size);
+    cpu_physical_memory_write(dst_addr, buf, size);
     s->statistics.rx_good_frames++;
     eepro100_fr_interrupt(s);
     s->ru_offset = le32_to_cpu(rx.link);
-- 
1.6.4


[-- Attachment #5: 0004-Short-frames-do-not-exist-so-remove-code-to-handle-t.patch --]
[-- Type: text/plain, Size: 2959 bytes --]

>From da19bed5b3ac1b409f0db91c881983360fbde946 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= <reimar@hokum.(none)>
Date: Sun, 9 Aug 2009 22:57:06 +0200
Subject: [PATCH 4/4] Short frames do not exist, so remove code to handle them.
 Also expand packets that are smaller than the shor frame limit,
 otherwise the OS X network stack seems to discard them.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
---
 hw/eepro100.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/hw/eepro100.c b/hw/eepro100.c
index 5620bc7..d2c18cc 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -1452,6 +1452,8 @@ static int nic_can_receive(VLANClientState *vc)
     //~ return !eepro100_buffer_full(s);
 }
 
+#define MIN_BUF_SIZE 60
+
 static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size)
 {
     /* TODO:
@@ -1459,6 +1461,7 @@ static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size
      * - Interesting packets should set bit 29 in power management driver register.
      */
     EEPRO100State *s = vc->opaque;
+    uint8_t buf1[MIN_BUF_SIZE];
     uint16_t rfd_status = 0xa000;
     static const uint8_t broadcast_macaddr[6] =
         { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -1466,16 +1469,18 @@ static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size
     /* TODO: check multiple IA bit. */
     assert(!(s->configuration[20] & BIT(6)));
 
+    /* Short frames can not happen on virtual hardware, so expand them. */
+    if (size < MIN_BUF_SIZE) {
+        memcpy(buf1, buf, size);
+        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
+        buf = buf1;
+        size = MIN_BUF_SIZE;
+    }
+
     if (s->configuration[8] & 0x80) {
         /* CSMA is disabled. */
         logout("%p received while CSMA is disabled\n", s);
         return -1;
-    } else if (size < 64 && (s->configuration[7] & 1)) {
-        /* Short frame and configuration byte 7/0 (discard short receive) set:
-         * Short frame is discarded */
-        logout("%p received short frame (%d byte)\n", s, size);
-        s->statistics.rx_short_frame_errors++;
-        //~ return -1;
     } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & 8)) {
         /* Long frame and configuration byte 18/3 (long receive ok) not set:
          * Long frames are discarded. */
@@ -1536,9 +1541,6 @@ static ssize_t nic_receive(VLANClientState *vc, const uint8_t * buf, size_t size
         s->rbd_addr = le32_to_cpu(rbd.link);
     }
     assert(size <= rfd_size);
-    if (size < 64) {
-        rfd_status |= 0x0080;
-    }
     logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command,
            rx.link, rx.rx_buf_addr, rfd_size);
     stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
-- 
1.6.4


^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2009-08-17  8:13 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-08-09 21:14 [Qemu-devel] [PATCH] Intel 8255x/eepro100 compatibility patches Reimar Döffinger
2009-08-10  4:36 ` Stefan Weil
2009-08-10  6:42   ` Reimar Döffinger
2009-08-17  7:47   ` Reimar Döffinger
2009-08-11 18:27 ` Reimar Döffinger
2009-08-11 20:26   ` Anthony Liguori
2009-08-11 21:13     ` [Qemu-devel] " Reimar Döffinger
2009-08-15 12:32       ` Reimar Döffinger
2009-08-11 21:14     ` [Qemu-devel] [PATCH 1/5] Setting the MDI SCBAck flag when interrupts for MDI are disabled is wrong, even if it does not seem to cause any real issue with known drivers Reimar Döffinger
2009-08-11 21:14     ` [Qemu-devel] [PATCH 2/5] Hack to make sure that drivers like AppleIntel8255x will not meddle with the RU/CU state when the ACK the interrupt with a 16 bit write Reimar Döffinger
2009-08-11 21:15     ` [Qemu-devel] [PATCH 3/5] Add support for receiving via receive buffers. While the Intel documentation claims this is unsupported, the OS X drivers use it, causing an assertion failure since rx buffer size is 0 Reimar Döffinger
2009-08-11 23:04       ` malc
2009-08-12  0:35         ` Reimar Döffinger
2009-08-12 17:34           ` malc
2009-08-12 18:24             ` Anthony Liguori
2009-08-13 13:25           ` Reimar Döffinger
2009-08-11 21:15     ` [Qemu-devel] [PATCH 4/5] Short frames do not exist, so remove code to handle them. Also expand packets that are smaller than the shor frame limit, otherwise the OS X network stack seems to discard them Reimar Döffinger
2009-08-11 21:15     ` [Qemu-devel] [PATCH 5/5] Set the RU state to ru_no_resources instead of asserting when we used up the last receive buffer. This should not usually happen with good drivers, but it can happen with the OS X drivers at least Reimar Döffinger
2009-08-12  8:53     ` [Qemu-devel] [PATCH 6/5] Implement the trivial diagnose CU and RU abort commands. These are necessary to make the device work with OpenSolaris 0609 (111b) Reimar Döffinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).