symbian-qemu-0.9.1-12/qemu-symbian-svp/hw/etraxfs_eth.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * QEMU ETRAX Ethernet Controller.
       
     3  *
       
     4  * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
       
     5  *
       
     6  * Permission is hereby granted, free of charge, to any person obtaining a copy
       
     7  * of this software and associated documentation files (the "Software"), to deal
       
     8  * in the Software without restriction, including without limitation the rights
       
     9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       
    10  * copies of the Software, and to permit persons to whom the Software is
       
    11  * furnished to do so, subject to the following conditions:
       
    12  *
       
    13  * The above copyright notice and this permission notice shall be included in
       
    14  * all copies or substantial portions of the Software.
       
    15  *
       
    16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
       
    19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       
    21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       
    22  * THE SOFTWARE.
       
    23  */
       
    24 
       
    25 #include <stdio.h>
       
    26 #include "hw.h"
       
    27 #include "net.h"
       
    28 
       
    29 #include "etraxfs_dma.h"
       
    30 
       
    31 #define D(x)
       
    32 
       
    33 /* Advertisement control register. */
       
    34 #define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
       
    35 #define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
       
    36 #define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
       
    37 #define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
       
    38 
       
    39 /* 
       
    40  * The MDIO extensions in the TDK PHY model were reversed engineered from the 
       
    41  * linux driver (PHYID and Diagnostics reg).
       
    42  * TODO: Add friendly names for the register nums.
       
    43  */
       
    44 struct qemu_phy
       
    45 {
       
    46 	uint32_t regs[32];
       
    47 
       
    48 	unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
       
    49 	void (*write)(struct qemu_phy *phy, unsigned int req, 
       
    50 		      unsigned int data);
       
    51 };
       
    52 
       
    53 static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
       
    54 {
       
    55 	int regnum;
       
    56 	unsigned r = 0;
       
    57 
       
    58 	regnum = req & 0x1f;
       
    59 
       
    60 	switch (regnum) {
       
    61 		case 1:
       
    62 			/* MR1.	 */
       
    63 			/* Speeds and modes.  */
       
    64 			r |= (1 << 13) | (1 << 14);
       
    65 			r |= (1 << 11) | (1 << 12);
       
    66 			r |= (1 << 5); /* Autoneg complete.  */
       
    67 			r |= (1 << 3); /* Autoneg able.	 */
       
    68 			r |= (1 << 2); /* Link.	 */
       
    69 			break;
       
    70 		case 5:
       
    71 			/* Link partner ability.
       
    72 			   We are kind; always agree with whatever best mode
       
    73 			   the guest advertises.  */
       
    74 			r = 1 << 14; /* Success.  */
       
    75 			/* Copy advertised modes.  */
       
    76 			r |= phy->regs[4] & (15 << 5);
       
    77 			/* Autoneg support.  */
       
    78 			r |= 1;
       
    79 			break;
       
    80 		case 18:
       
    81 		{
       
    82 			/* Diagnostics reg.  */
       
    83 			int duplex = 0;
       
    84 			int speed_100 = 0;
       
    85 
       
    86 			/* Are we advertising 100 half or 100 duplex ? */
       
    87 			speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
       
    88 			speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
       
    89 
       
    90 			/* Are we advertising 10 duplex or 100 duplex ? */
       
    91 			duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
       
    92 			duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
       
    93 			r = (speed_100 << 10) | (duplex << 11);
       
    94 		}
       
    95 		break;
       
    96 
       
    97 		default:
       
    98 			r = phy->regs[regnum];
       
    99 			break;
       
   100 	}
       
   101 	D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum));
       
   102 	return r;
       
   103 }
       
   104 
       
   105 static void 
       
   106 tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
       
   107 {
       
   108 	int regnum;
       
   109 
       
   110 	regnum = req & 0x1f;
       
   111 	D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
       
   112 	switch (regnum) {
       
   113 		default:
       
   114 			phy->regs[regnum] = data;
       
   115 			break;
       
   116 	}
       
   117 }
       
   118 
       
   119 static void 
       
   120 tdk_init(struct qemu_phy *phy)
       
   121 {
       
   122 	phy->regs[0] = 0x3100;
       
   123 	/* PHY Id.  */
       
   124 	phy->regs[2] = 0x0300;
       
   125 	phy->regs[3] = 0xe400;
       
   126 	/* Autonegotiation advertisement reg.  */
       
   127 	phy->regs[4] = 0x01E1;
       
   128 
       
   129 	phy->read = tdk_read;
       
   130 	phy->write = tdk_write;
       
   131 }
       
   132 
       
   133 struct qemu_mdio
       
   134 {
       
   135 	/* bus.	 */
       
   136 	int mdc;
       
   137 	int mdio;
       
   138 
       
   139 	/* decoder.  */
       
   140 	enum {
       
   141 		PREAMBLE,
       
   142 		SOF,
       
   143 		OPC,
       
   144 		ADDR,
       
   145 		REQ,
       
   146 		TURNAROUND,
       
   147 		DATA
       
   148 	} state;
       
   149 	unsigned int drive;
       
   150 
       
   151 	unsigned int cnt;
       
   152 	unsigned int addr;
       
   153 	unsigned int opc;
       
   154 	unsigned int req;
       
   155 	unsigned int data;
       
   156 
       
   157 	struct qemu_phy *devs[32];
       
   158 };
       
   159 
       
   160 static void 
       
   161 mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
       
   162 {
       
   163 	bus->devs[addr & 0x1f] = phy;
       
   164 }
       
   165 
       
   166 #ifdef USE_THIS_DEAD_CODE
       
   167 static void 
       
   168 mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
       
   169 {
       
   170 	bus->devs[addr & 0x1f] = NULL;	
       
   171 }
       
   172 #endif
       
   173 
       
   174 static void mdio_read_req(struct qemu_mdio *bus)
       
   175 {
       
   176 	struct qemu_phy *phy;
       
   177 
       
   178 	phy = bus->devs[bus->addr];
       
   179 	if (phy && phy->read)
       
   180 		bus->data = phy->read(phy, bus->req);
       
   181 	else 
       
   182 		bus->data = 0xffff;
       
   183 }
       
   184 
       
   185 static void mdio_write_req(struct qemu_mdio *bus)
       
   186 {
       
   187 	struct qemu_phy *phy;
       
   188 
       
   189 	phy = bus->devs[bus->addr];
       
   190 	if (phy && phy->write)
       
   191 		phy->write(phy, bus->req, bus->data);
       
   192 }
       
   193 
       
   194 static void mdio_cycle(struct qemu_mdio *bus)
       
   195 {
       
   196 	bus->cnt++;
       
   197 
       
   198 	D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n",
       
   199 		bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive));
       
   200 #if 0
       
   201 	if (bus->mdc)
       
   202 		printf("%d", bus->mdio);
       
   203 #endif
       
   204 	switch (bus->state)
       
   205 	{
       
   206 		case PREAMBLE:
       
   207 			if (bus->mdc) {
       
   208 				if (bus->cnt >= (32 * 2) && !bus->mdio) {
       
   209 					bus->cnt = 0;
       
   210 					bus->state = SOF;
       
   211 					bus->data = 0;
       
   212 				}
       
   213 			}
       
   214 			break;
       
   215 		case SOF:
       
   216 			if (bus->mdc) {
       
   217 				if (bus->mdio != 1)
       
   218 					printf("WARNING: no SOF\n");
       
   219 				if (bus->cnt == 1*2) {
       
   220 					bus->cnt = 0;
       
   221 					bus->opc = 0;
       
   222 					bus->state = OPC;
       
   223 				}
       
   224 			}
       
   225 			break;
       
   226 		case OPC:
       
   227 			if (bus->mdc) {
       
   228 				bus->opc <<= 1;
       
   229 				bus->opc |= bus->mdio & 1;
       
   230 				if (bus->cnt == 2*2) {
       
   231 					bus->cnt = 0;
       
   232 					bus->addr = 0;
       
   233 					bus->state = ADDR;
       
   234 				}
       
   235 			}
       
   236 			break;
       
   237 		case ADDR:
       
   238 			if (bus->mdc) {
       
   239 				bus->addr <<= 1;
       
   240 				bus->addr |= bus->mdio & 1;
       
   241 
       
   242 				if (bus->cnt == 5*2) {
       
   243 					bus->cnt = 0;
       
   244 					bus->req = 0;
       
   245 					bus->state = REQ;
       
   246 				}
       
   247 			}
       
   248 			break;
       
   249 		case REQ:
       
   250 			if (bus->mdc) {
       
   251 				bus->req <<= 1;
       
   252 				bus->req |= bus->mdio & 1;
       
   253 				if (bus->cnt == 5*2) {
       
   254 					bus->cnt = 0;
       
   255 					bus->state = TURNAROUND;
       
   256 				}
       
   257 			}
       
   258 			break;
       
   259 		case TURNAROUND:
       
   260 			if (bus->mdc && bus->cnt == 2*2) {
       
   261 				bus->mdio = 0;
       
   262 				bus->cnt = 0;
       
   263 
       
   264 				if (bus->opc == 2) {
       
   265 					bus->drive = 1;
       
   266 					mdio_read_req(bus);
       
   267 					bus->mdio = bus->data & 1;
       
   268 				}
       
   269 				bus->state = DATA;
       
   270 			}
       
   271 			break;
       
   272 		case DATA:			
       
   273 			if (!bus->mdc) {
       
   274 				if (bus->drive) {
       
   275 					bus->mdio = !!(bus->data & (1 << 15));
       
   276 					bus->data <<= 1;
       
   277 				}
       
   278 			} else {
       
   279 				if (!bus->drive) {
       
   280 					bus->data <<= 1;
       
   281 					bus->data |= bus->mdio;
       
   282 				}
       
   283 				if (bus->cnt == 16 * 2) {
       
   284 					bus->cnt = 0;
       
   285 					bus->state = PREAMBLE;
       
   286 					if (!bus->drive)
       
   287 						mdio_write_req(bus);
       
   288 					bus->drive = 0;
       
   289 				}
       
   290 			}
       
   291 			break;
       
   292 		default:
       
   293 			break;
       
   294 	}
       
   295 }
       
   296 
       
   297 /* ETRAX-FS Ethernet MAC block starts here.  */
       
   298 
       
   299 #define RW_MA0_LO	  0x00
       
   300 #define RW_MA0_HI	  0x04
       
   301 #define RW_MA1_LO	  0x08
       
   302 #define RW_MA1_HI	  0x0c
       
   303 #define RW_GA_LO	  0x10
       
   304 #define RW_GA_HI	  0x14
       
   305 #define RW_GEN_CTRL	  0x18
       
   306 #define RW_REC_CTRL	  0x1c
       
   307 #define RW_TR_CTRL	  0x20
       
   308 #define RW_CLR_ERR	  0x24
       
   309 #define RW_MGM_CTRL	  0x28
       
   310 #define R_STAT		  0x2c
       
   311 #define FS_ETH_MAX_REGS	  0x5c
       
   312 
       
   313 struct fs_eth
       
   314 {
       
   315 	CPUState *env;
       
   316 	qemu_irq *irq;
       
   317 	VLANClientState *vc;
       
   318 	int ethregs;
       
   319 
       
   320 	/* Two addrs in the filter.  */
       
   321 	uint8_t macaddr[2][6];
       
   322 	uint32_t regs[FS_ETH_MAX_REGS];
       
   323 
       
   324 	struct etraxfs_dma_client *dma_out;
       
   325 	struct etraxfs_dma_client *dma_in;
       
   326 
       
   327 	/* MDIO bus.  */
       
   328 	struct qemu_mdio mdio_bus;
       
   329 	unsigned int phyaddr;
       
   330 	int duplex_mismatch;
       
   331 
       
   332 	/* PHY.	 */
       
   333 	struct qemu_phy phy;
       
   334 };
       
   335 
       
   336 static void eth_validate_duplex(struct fs_eth *eth)
       
   337 {
       
   338 	struct qemu_phy *phy;
       
   339 	unsigned int phy_duplex;
       
   340 	unsigned int mac_duplex;
       
   341 	int new_mm = 0;
       
   342 
       
   343 	phy = eth->mdio_bus.devs[eth->phyaddr];
       
   344 	phy_duplex = !!(phy->read(phy, 18) & (1 << 11));
       
   345 	mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128);
       
   346 
       
   347 	if (mac_duplex != phy_duplex)
       
   348 		new_mm = 1;
       
   349 
       
   350 	if (eth->regs[RW_GEN_CTRL] & 1) {
       
   351 		if (new_mm != eth->duplex_mismatch) {
       
   352 			if (new_mm)
       
   353 				printf("HW: WARNING "
       
   354 				       "ETH duplex mismatch MAC=%d PHY=%d\n",
       
   355 				       mac_duplex, phy_duplex);
       
   356 			else
       
   357 				printf("HW: ETH duplex ok.\n");
       
   358 		}
       
   359 		eth->duplex_mismatch = new_mm;
       
   360 	}
       
   361 }
       
   362 
       
   363 static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr)
       
   364 {
       
   365 	struct fs_eth *eth = opaque;
       
   366 	CPUState *env = eth->env;
       
   367 	cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n",
       
   368 		  addr);
       
   369 	return 0;
       
   370 }
       
   371 
       
   372 static uint32_t eth_readl (void *opaque, target_phys_addr_t addr)
       
   373 {
       
   374 	struct fs_eth *eth = opaque;
       
   375 	uint32_t r = 0;
       
   376 
       
   377 	switch (addr) {
       
   378 		case R_STAT:
       
   379 			/* Attach an MDIO/PHY abstraction.  */
       
   380 			r = eth->mdio_bus.mdio & 1;
       
   381 			break;
       
   382 	default:
       
   383 		r = eth->regs[addr];
       
   384 		D(printf ("%s %x\n", __func__, addr));
       
   385 		break;
       
   386 	}
       
   387 	return r;
       
   388 }
       
   389 
       
   390 static void
       
   391 eth_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
       
   392 {
       
   393 	struct fs_eth *eth = opaque;
       
   394 	CPUState *env = eth->env;
       
   395 	cpu_abort(env, "Unsupported short access. reg=" TARGET_FMT_plx "\n",
       
   396 		  addr);
       
   397 }
       
   398 
       
   399 static void eth_update_ma(struct fs_eth *eth, int ma)
       
   400 {
       
   401 	int reg;
       
   402 	int i = 0;
       
   403 
       
   404 	ma &= 1;
       
   405 
       
   406 	reg = RW_MA0_LO;
       
   407 	if (ma)
       
   408 		reg = RW_MA1_LO;
       
   409 
       
   410 	eth->macaddr[ma][i++] = eth->regs[reg];
       
   411 	eth->macaddr[ma][i++] = eth->regs[reg] >> 8;
       
   412 	eth->macaddr[ma][i++] = eth->regs[reg] >> 16;
       
   413 	eth->macaddr[ma][i++] = eth->regs[reg] >> 24;
       
   414 	eth->macaddr[ma][i++] = eth->regs[reg + 4];
       
   415 	eth->macaddr[ma][i++] = eth->regs[reg + 4] >> 8;
       
   416 
       
   417 	D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma,
       
   418 		 eth->macaddr[ma][0], eth->macaddr[ma][1],
       
   419 		 eth->macaddr[ma][2], eth->macaddr[ma][3],
       
   420 		 eth->macaddr[ma][4], eth->macaddr[ma][5]));
       
   421 }
       
   422 
       
   423 static void
       
   424 eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
       
   425 {
       
   426 	struct fs_eth *eth = opaque;
       
   427 
       
   428 	switch (addr)
       
   429 	{
       
   430 		case RW_MA0_LO:
       
   431 			eth->regs[addr] = value;
       
   432 			eth_update_ma(eth, 0);
       
   433 			break;
       
   434 		case RW_MA0_HI:
       
   435 			eth->regs[addr] = value;
       
   436 			eth_update_ma(eth, 0);
       
   437 			break;
       
   438 		case RW_MA1_LO:
       
   439 			eth->regs[addr] = value;
       
   440 			eth_update_ma(eth, 1);
       
   441 			break;
       
   442 		case RW_MA1_HI:
       
   443 			eth->regs[addr] = value;
       
   444 			eth_update_ma(eth, 1);
       
   445 			break;
       
   446 
       
   447 		case RW_MGM_CTRL:
       
   448 			/* Attach an MDIO/PHY abstraction.  */
       
   449 			if (value & 2)
       
   450 				eth->mdio_bus.mdio = value & 1;
       
   451 			if (eth->mdio_bus.mdc != (value & 4)) {
       
   452 				mdio_cycle(&eth->mdio_bus);
       
   453 				eth_validate_duplex(eth);
       
   454 			}
       
   455 			eth->mdio_bus.mdc = !!(value & 4);
       
   456 			break;
       
   457 
       
   458 		case RW_REC_CTRL:
       
   459 			eth->regs[addr] = value;
       
   460 			eth_validate_duplex(eth);
       
   461 			break;
       
   462 
       
   463 		default:
       
   464 			eth->regs[addr] = value;
       
   465 			D(printf ("%s %x %x\n",
       
   466 				  __func__, addr, value));
       
   467 			break;
       
   468 	}
       
   469 }
       
   470 
       
   471 /* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom
       
   472    filter dropping group addresses we have not joined.	The filter has 64
       
   473    bits (m). The has function is a simple nible xor of the group addr.	*/
       
   474 static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa)
       
   475 {
       
   476 	unsigned int hsh;
       
   477 	int m_individual = eth->regs[RW_REC_CTRL] & 4;
       
   478 	int match;
       
   479 
       
   480 	/* First bit on the wire of a MAC address signals multicast or
       
   481 	   physical address.  */
       
   482 	if (!m_individual && !sa[0] & 1)
       
   483 		return 0;
       
   484 
       
   485 	/* Calculate the hash index for the GA registers. */
       
   486 	hsh = 0;
       
   487 	hsh ^= (*sa) & 0x3f;
       
   488 	hsh ^= ((*sa) >> 6) & 0x03;
       
   489 	++sa;
       
   490 	hsh ^= ((*sa) << 2) & 0x03c;
       
   491 	hsh ^= ((*sa) >> 4) & 0xf;
       
   492 	++sa;
       
   493 	hsh ^= ((*sa) << 4) & 0x30;
       
   494 	hsh ^= ((*sa) >> 2) & 0x3f;
       
   495 	++sa;
       
   496 	hsh ^= (*sa) & 0x3f;
       
   497 	hsh ^= ((*sa) >> 6) & 0x03;
       
   498 	++sa;
       
   499 	hsh ^= ((*sa) << 2) & 0x03c;
       
   500 	hsh ^= ((*sa) >> 4) & 0xf;
       
   501 	++sa;
       
   502 	hsh ^= ((*sa) << 4) & 0x30;
       
   503 	hsh ^= ((*sa) >> 2) & 0x3f;
       
   504 
       
   505 	hsh &= 63;
       
   506 	if (hsh > 31)
       
   507 		match = eth->regs[RW_GA_HI] & (1 << (hsh - 32));
       
   508 	else
       
   509 		match = eth->regs[RW_GA_LO] & (1 << hsh);
       
   510 	D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh,
       
   511 		 eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match));
       
   512 	return match;
       
   513 }
       
   514 
       
   515 static int eth_can_receive(void *opaque)
       
   516 {
       
   517 	return 1;
       
   518 }
       
   519 
       
   520 static void eth_receive(void *opaque, const uint8_t *buf, int size)
       
   521 {
       
   522 	unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
       
   523 	struct fs_eth *eth = opaque;
       
   524 	int use_ma0 = eth->regs[RW_REC_CTRL] & 1;
       
   525 	int use_ma1 = eth->regs[RW_REC_CTRL] & 2;
       
   526 	int r_bcast = eth->regs[RW_REC_CTRL] & 8;
       
   527 
       
   528 	if (size < 12)
       
   529 		return;
       
   530 
       
   531 	D(printf("%x.%x.%x.%x.%x.%x ma=%d %d bc=%d\n",
       
   532 		 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
       
   533 		 use_ma0, use_ma1, r_bcast));
       
   534 	       
       
   535 	/* Does the frame get through the address filters?  */
       
   536 	if ((!use_ma0 || memcmp(buf, eth->macaddr[0], 6))
       
   537 	    && (!use_ma1 || memcmp(buf, eth->macaddr[1], 6))
       
   538 	    && (!r_bcast || memcmp(buf, sa_bcast, 6))
       
   539 	    && !eth_match_groupaddr(eth, buf))
       
   540 		return;
       
   541 
       
   542 	/* FIXME: Find another way to pass on the fake csum.  */
       
   543 	etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1);
       
   544 }
       
   545 
       
   546 static int eth_tx_push(void *opaque, unsigned char *buf, int len)
       
   547 {
       
   548 	struct fs_eth *eth = opaque;
       
   549 
       
   550 	D(printf("%s buf=%p len=%d\n", __func__, buf, len));
       
   551 	qemu_send_packet(eth->vc, buf, len);
       
   552 	return len;
       
   553 }
       
   554 
       
   555 static CPUReadMemoryFunc *eth_read[] = {
       
   556 	&eth_rinvalid,
       
   557 	&eth_rinvalid,
       
   558 	&eth_readl,
       
   559 };
       
   560 
       
   561 static CPUWriteMemoryFunc *eth_write[] = {
       
   562 	&eth_winvalid,
       
   563 	&eth_winvalid,
       
   564 	&eth_writel,
       
   565 };
       
   566 
       
   567 void *etraxfs_eth_init(NICInfo *nd, CPUState *env, 
       
   568 		       qemu_irq *irq, target_phys_addr_t base)
       
   569 {
       
   570 	struct etraxfs_dma_client *dma = NULL;	
       
   571 	struct fs_eth *eth = NULL;
       
   572 
       
   573 	dma = qemu_mallocz(sizeof *dma * 2);
       
   574 	if (!dma)
       
   575 		return NULL;
       
   576 
       
   577 	eth = qemu_mallocz(sizeof *eth);
       
   578 	if (!eth)
       
   579 		goto err;
       
   580 
       
   581 	dma[0].client.push = eth_tx_push;
       
   582 	dma[0].client.opaque = eth;
       
   583 	dma[1].client.opaque = eth;
       
   584 	dma[1].client.pull = NULL;
       
   585 
       
   586 	eth->env = env;
       
   587 	eth->irq = irq;
       
   588 	eth->dma_out = dma;
       
   589 	eth->dma_in = dma + 1;
       
   590 
       
   591 	/* Connect the phy.  */
       
   592 	eth->phyaddr = 1;
       
   593 	tdk_init(&eth->phy);
       
   594 	mdio_attach(&eth->mdio_bus, &eth->phy, eth->phyaddr);
       
   595 
       
   596 	eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth);
       
   597 	cpu_register_physical_memory (base, 0x5c, eth->ethregs);
       
   598 
       
   599 	eth->vc = qemu_new_vlan_client(nd->vlan, 
       
   600 				       eth_receive, eth_can_receive, eth);
       
   601 
       
   602 	return dma;
       
   603   err:
       
   604 	qemu_free(eth);
       
   605 	qemu_free(dma);
       
   606 	return NULL;
       
   607 }