Commit 2e56350ef10e06373b4c6aa715bb2f8b3db50f51
1 parent
a37af289
ETRAX: Add some kind of support for simulating 802.3 auto-negotiation.
* Add support for link partner ability and diagnostics reg. * Correct the endianess for MDIO responses. * Dont trash PHY registers after reads. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4456 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
55 additions
and
17 deletions
hw/etraxfs_eth.c
... | ... | @@ -30,18 +30,18 @@ |
30 | 30 | |
31 | 31 | #define D(x) |
32 | 32 | |
33 | -#define R_STAT 0x2c | |
34 | -#define RW_MGM_CTRL 0x28 | |
35 | -#define FS_ETH_MAX_REGS 0x5c | |
36 | - | |
37 | - | |
38 | - | |
33 | +/* | |
34 | + * The MDIO extensions in the TDK PHY model were reversed engineered from the | |
35 | + * linux driver (PHYID and Diagnostics reg). | |
36 | + * TODO: Add friendly names for the register nums. | |
37 | + */ | |
39 | 38 | struct qemu_phy |
40 | 39 | { |
41 | 40 | uint32_t regs[32]; |
42 | 41 | |
43 | 42 | unsigned int (*read)(struct qemu_phy *phy, unsigned int req); |
44 | - void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data); | |
43 | + void (*write)(struct qemu_phy *phy, unsigned int req, | |
44 | + unsigned int data); | |
45 | 45 | }; |
46 | 46 | |
47 | 47 | static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) |
... | ... | @@ -61,11 +61,35 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) |
61 | 61 | r |= (1 << 3); /* Autoneg able. */ |
62 | 62 | r |= (1 << 2); /* Link. */ |
63 | 63 | break; |
64 | + case 5: | |
65 | + /* Link partner ability. | |
66 | + We are kind; always agree with whatever best mode | |
67 | + the guest advertises. */ | |
68 | + r = 1 << 14; /* Success. */ | |
69 | + /* Copy advertised modes. */ | |
70 | + r |= phy->regs[4] & (15 << 5); | |
71 | + /* Autoneg support. */ | |
72 | + r |= 1; | |
73 | + break; | |
74 | + case 18: | |
75 | + { | |
76 | + /* Diagnostics reg. */ | |
77 | + int duplex = 0; | |
78 | + int speed_100 = 0; | |
79 | + | |
80 | + /* Are we advertising 100 half or 100 duplex ? */ | |
81 | + speed_100 = !!(phy->regs[4] & 0x180); | |
82 | + /* Are we advertising 10 duplex or 100 duplex ? */ | |
83 | + duplex = !!(phy->regs[4] & 0x180); | |
84 | + r = (speed_100 << 10) | (duplex << 11); | |
85 | + } | |
86 | + break; | |
87 | + | |
64 | 88 | default: |
65 | 89 | r = phy->regs[regnum]; |
66 | 90 | break; |
67 | 91 | } |
68 | - D(printf("%s %x = reg[%d]\n", __func__, r, regnum)); | |
92 | + D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum)); | |
69 | 93 | return r; |
70 | 94 | } |
71 | 95 | |
... | ... | @@ -86,6 +110,13 @@ tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data) |
86 | 110 | static void |
87 | 111 | tdk_init(struct qemu_phy *phy) |
88 | 112 | { |
113 | + phy->regs[0] = 0x3100; | |
114 | + /* PHY Id. */ | |
115 | + phy->regs[2] = 0x0300; | |
116 | + phy->regs[3] = 0xe400; | |
117 | + /* Autonegotiation advertisement reg. */ | |
118 | + phy->regs[4] = 0x01E1; | |
119 | + | |
89 | 120 | phy->read = tdk_read; |
90 | 121 | phy->write = tdk_write; |
91 | 122 | } |
... | ... | @@ -230,8 +261,8 @@ static void mdio_cycle(struct qemu_mdio *bus) |
230 | 261 | case DATA: |
231 | 262 | if (!bus->mdc) { |
232 | 263 | if (bus->drive) { |
233 | - bus->mdio = bus->data & 1; | |
234 | - bus->data >>= 1; | |
264 | + bus->mdio = !!(bus->data & (1 << 15)); | |
265 | + bus->data <<= 1; | |
235 | 266 | } |
236 | 267 | } else { |
237 | 268 | if (!bus->drive) { |
... | ... | @@ -241,7 +272,9 @@ static void mdio_cycle(struct qemu_mdio *bus) |
241 | 272 | if (bus->cnt == 16 * 2) { |
242 | 273 | bus->cnt = 0; |
243 | 274 | bus->state = PREAMBLE; |
244 | - mdio_write_req(bus); | |
275 | + if (!bus->drive) | |
276 | + mdio_write_req(bus); | |
277 | + bus->drive = 0; | |
245 | 278 | } |
246 | 279 | } |
247 | 280 | break; |
... | ... | @@ -250,6 +283,11 @@ static void mdio_cycle(struct qemu_mdio *bus) |
250 | 283 | } |
251 | 284 | } |
252 | 285 | |
286 | +/* ETRAX-FS Ethernet MAC block starts here. */ | |
287 | + | |
288 | +#define R_STAT 0x2c | |
289 | +#define RW_MGM_CTRL 0x28 | |
290 | +#define FS_ETH_MAX_REGS 0x5c | |
253 | 291 | |
254 | 292 | struct fs_eth |
255 | 293 | { |
... | ... | @@ -398,15 +436,15 @@ static int eth_tx_push(void *opaque, unsigned char *buf, int len) |
398 | 436 | } |
399 | 437 | |
400 | 438 | static CPUReadMemoryFunc *eth_read[] = { |
401 | - ð_rinvalid, | |
402 | - ð_rinvalid, | |
403 | - ð_readl, | |
439 | + ð_rinvalid, | |
440 | + ð_rinvalid, | |
441 | + ð_readl, | |
404 | 442 | }; |
405 | 443 | |
406 | 444 | static CPUWriteMemoryFunc *eth_write[] = { |
407 | - ð_winvalid, | |
408 | - ð_winvalid, | |
409 | - ð_writel, | |
445 | + ð_winvalid, | |
446 | + ð_winvalid, | |
447 | + ð_writel, | |
410 | 448 | }; |
411 | 449 | |
412 | 450 | void *etraxfs_eth_init(NICInfo *nd, CPUState *env, | ... | ... |