1/* Blackfin Ethernet Media Access Controller (EMAC) model. 2 3 Copyright (C) 2010-2011 Free Software Foundation, Inc. 4 Contributed by Analog Devices, Inc. 5 6 This file is part of simulators. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21#include "config.h" 22 23#include <errno.h> 24#include <fcntl.h> 25#include <unistd.h> 26 27#ifdef HAVE_SYS_IOCTL_H 28#include <sys/ioctl.h> 29#endif 30#ifdef HAVE_NET_IF_H 31#include <net/if.h> 32#endif 33#ifdef HAVE_LINUX_IF_TUN_H 34#include <linux/if_tun.h> 35#endif 36 37#ifdef HAVE_LINUX_IF_TUN_H 38# define WITH_TUN 1 39#else 40# define WITH_TUN 0 41#endif 42 43#include "sim-main.h" 44#include "sim-hw.h" 45#include "devices.h" 46#include "dv-bfin_emac.h" 47 48/* XXX: This doesn't support partial DMA transfers. */ 49/* XXX: The TUN pieces should be pushed to the PHY so that we work with 50 multiple "networks" and the PHY takes care of it. */ 51 52struct bfin_emac 53{ 54 /* This top portion matches common dv_bfin struct. */ 55 bu32 base; 56 struct hw *dma_master; 57 bool acked; 58 59 int tap; 60#if WITH_TUN 61 struct ifreq ifr; 62#endif 63 bu32 rx_crc; 64 65 /* Order after here is important -- matches hardware MMR layout. */ 66 bu32 opmode, addrlo, addrhi, hashlo, hashhi, staadd, stadat, flc, vlan1, vlan2; 67 bu32 _pad0; 68 bu32 wkup_ctl, wkup_ffmsk0, wkup_ffmsk1, wkup_ffmsk2, wkup_ffmsk3; 69 bu32 wkup_ffcmd, wkup_ffoff, wkup_ffcrc0, wkup_ffcrc1; 70 bu32 _pad1[4]; 71 bu32 sysctl, systat, rx_stat, rx_stky, rx_irqe, tx_stat, tx_stky, tx_irqe; 72 bu32 mmc_ctl, mmc_rirqs, mmc_rirqe, mmc_tirqs, mmc_tirqe; 73 bu32 _pad2[3]; 74 bu16 BFIN_MMR_16(ptp_ctl); 75 bu16 BFIN_MMR_16(ptp_ie); 76 bu16 BFIN_MMR_16(ptp_istat); 77 bu32 ptp_foff, ptp_fv1, ptp_fv2, ptp_fv3, ptp_addend, ptp_accr, ptp_offset; 78 bu32 ptp_timelo, ptp_timehi, ptp_rxsnaplo, ptp_rxsnaphi, ptp_txsnaplo; 79 bu32 ptp_txsnaphi, ptp_alarmlo, ptp_alarmhi, ptp_id_off, ptp_id_snap; 80 bu32 ptp_pps_startlo, ptp_pps_starthi, ptp_pps_period; 81 bu32 _pad3[1]; 82 bu32 rxc_ok, rxc_fcs, rxc_lign, rxc_octet, rxc_dmaovf, rxc_unicst, rxc_multi; 83 bu32 rxc_broad, rxc_lnerri, rxc_lnerro, rxc_long, rxc_macctl, rxc_opcode; 84 bu32 rxc_pause, rxc_allfrm, rxc_alloct, rxc_typed, rxc_short, rxc_eq64; 85 bu32 rxc_lt128, rxc_lt256, rxc_lt512, rxc_lt1024, rxc_ge1024; 86 bu32 _pad4[8]; 87 bu32 txc_ok, txc_1col, txc_gt1col, txc_octet, txc_defer, txc_latecl; 88 bu32 txc_xs_col, txc_dmaund, txc_crserr, txc_unicst, txc_multi, txc_broad; 89 bu32 txc_xs_dfr, txc_macctl, txc_allfrm, txc_alloct, txc_eq64, txc_lt128; 90 bu32 txc_lt256, txc_lt512, txc_lt1024, txc_ge1024, txc_abort; 91}; 92#define mmr_base() offsetof(struct bfin_emac, opmode) 93#define mmr_offset(mmr) (offsetof(struct bfin_emac, mmr) - mmr_base()) 94#define mmr_idx(mmr) (mmr_offset (mmr) / 4) 95 96static const char * const mmr_names[BFIN_MMR_EMAC_SIZE / 4] = 97{ 98 "EMAC_OPMODE", "EMAC_ADDRLO", "EMAC_ADDRHI", "EMAC_HASHLO", "EMAC_HASHHI", 99 "EMAC_STAADD", "EMAC_STADAT", "EMAC_FLC", "EMAC_VLAN1", "EMAC_VLAN2", NULL, 100 "EMAC_WKUP_CTL", "EMAC_WKUP_FFMSK0", "EMAC_WKUP_FFMSK1", "EMAC_WKUP_FFMSK2", 101 "EMAC_WKUP_FFMSK3", "EMAC_WKUP_FFCMD", "EMAC_WKUP_FFOFF", "EMAC_WKUP_FFCRC0", 102 "EMAC_WKUP_FFCRC1", [mmr_idx (sysctl)] = "EMAC_SYSCTL", "EMAC_SYSTAT", 103 "EMAC_RX_STAT", "EMAC_RX_STKY", "EMAC_RX_IRQE", "EMAC_TX_STAT", 104 "EMAC_TX_STKY", "EMAC_TX_IRQE", "EMAC_MMC_CTL", "EMAC_MMC_RIRQS", 105 "EMAC_MMC_RIRQE", "EMAC_MMC_TIRQS", "EMAC_MMC_TIRQE", 106 [mmr_idx (ptp_ctl)] = "EMAC_PTP_CTL", "EMAC_PTP_IE", "EMAC_PTP_ISTAT", 107 "EMAC_PTP_FOFF", "EMAC_PTP_FV1", "EMAC_PTP_FV2", "EMAC_PTP_FV3", 108 "EMAC_PTP_ADDEND", "EMAC_PTP_ACCR", "EMAC_PTP_OFFSET", "EMAC_PTP_TIMELO", 109 "EMAC_PTP_TIMEHI", "EMAC_PTP_RXSNAPLO", "EMAC_PTP_RXSNAPHI", 110 "EMAC_PTP_TXSNAPLO", "EMAC_PTP_TXSNAPHI", "EMAC_PTP_ALARMLO", 111 "EMAC_PTP_ALARMHI", "EMAC_PTP_ID_OFF", "EMAC_PTP_ID_SNAP", 112 "EMAC_PTP_PPS_STARTLO", "EMAC_PTP_PPS_STARTHI", "EMAC_PTP_PPS_PERIOD", 113 [mmr_idx (rxc_ok)] = "EMAC_RXC_OK", "EMAC_RXC_FCS", "EMAC_RXC_LIGN", 114 "EMAC_RXC_OCTET", "EMAC_RXC_DMAOVF", "EMAC_RXC_UNICST", "EMAC_RXC_MULTI", 115 "EMAC_RXC_BROAD", "EMAC_RXC_LNERRI", "EMAC_RXC_LNERRO", "EMAC_RXC_LONG", 116 "EMAC_RXC_MACCTL", "EMAC_RXC_OPCODE", "EMAC_RXC_PAUSE", "EMAC_RXC_ALLFRM", 117 "EMAC_RXC_ALLOCT", "EMAC_RXC_TYPED", "EMAC_RXC_SHORT", "EMAC_RXC_EQ64", 118 "EMAC_RXC_LT128", "EMAC_RXC_LT256", "EMAC_RXC_LT512", "EMAC_RXC_LT1024", 119 "EMAC_RXC_GE1024", 120 [mmr_idx (txc_ok)] = "EMAC_TXC_OK", "EMAC_TXC_1COL", "EMAC_TXC_GT1COL", 121 "EMAC_TXC_OCTET", "EMAC_TXC_DEFER", "EMAC_TXC_LATECL", "EMAC_TXC_XS_COL", 122 "EMAC_TXC_DMAUND", "EMAC_TXC_CRSERR", "EMAC_TXC_UNICST", "EMAC_TXC_MULTI", 123 "EMAC_TXC_BROAD", "EMAC_TXC_XS_DFR", "EMAC_TXC_MACCTL", "EMAC_TXC_ALLFRM", 124 "EMAC_TXC_ALLOCT", "EMAC_TXC_EQ64", "EMAC_TXC_LT128", "EMAC_TXC_LT256", 125 "EMAC_TXC_LT512", "EMAC_TXC_LT1024", "EMAC_TXC_GE1024", "EMAC_TXC_ABORT", 126}; 127#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>") 128 129static struct hw * 130mii_find_phy (struct hw *me, bu8 addr) 131{ 132 struct hw *phy = hw_child (me); 133 while (phy && --addr) 134 phy = hw_sibling (phy); 135 return phy; 136} 137 138static void 139mii_write (struct hw *me) 140{ 141 SIM_DESC sd = hw_system (me); 142 struct bfin_emac *emac = hw_data (me); 143 struct hw *phy; 144 bu8 addr = PHYAD (emac->staadd); 145 bu8 reg = REGAD (emac->staadd); 146 bu16 data = emac->stadat; 147 148 phy = mii_find_phy (me, addr); 149 if (!phy) 150 return; 151 sim_hw_io_write_buffer (sd, phy, &data, 1, reg, 2); 152} 153 154static void 155mii_read (struct hw *me) 156{ 157 SIM_DESC sd = hw_system (me); 158 struct bfin_emac *emac = hw_data (me); 159 struct hw *phy; 160 bu8 addr = PHYAD (emac->staadd); 161 bu8 reg = REGAD (emac->staadd); 162 bu16 data; 163 164 phy = mii_find_phy (me, addr); 165 if (!phy || sim_hw_io_read_buffer (sd, phy, &data, 1, reg, 2) != 2) 166 data = 0xffff; 167 168 emac->stadat = data; 169} 170 171static unsigned 172bfin_emac_io_write_buffer (struct hw *me, const void *source, 173 int space, address_word addr, unsigned nr_bytes) 174{ 175 struct bfin_emac *emac = hw_data (me); 176 bu32 mmr_off; 177 bu32 value; 178 bu32 *valuep; 179 180 /* XXX: 16bit accesses are allowed ... */ 181 dv_bfin_mmr_require_32 (me, addr, nr_bytes, true); 182 value = dv_load_4 (source); 183 184 mmr_off = addr - emac->base; 185 valuep = (void *)((unsigned long)emac + mmr_base() + mmr_off); 186 187 HW_TRACE_WRITE (); 188 189 switch (mmr_off) 190 { 191 case mmr_offset(hashlo): 192 case mmr_offset(hashhi): 193 case mmr_offset(stadat): 194 case mmr_offset(flc): 195 case mmr_offset(vlan1): 196 case mmr_offset(vlan2): 197 case mmr_offset(wkup_ffmsk0): 198 case mmr_offset(wkup_ffmsk1): 199 case mmr_offset(wkup_ffmsk2): 200 case mmr_offset(wkup_ffmsk3): 201 case mmr_offset(wkup_ffcmd): 202 case mmr_offset(wkup_ffoff): 203 case mmr_offset(wkup_ffcrc0): 204 case mmr_offset(wkup_ffcrc1): 205 case mmr_offset(sysctl): 206 case mmr_offset(rx_irqe): 207 case mmr_offset(tx_irqe): 208 case mmr_offset(mmc_rirqe): 209 case mmr_offset(mmc_tirqe): 210 *valuep = value; 211 break; 212 case mmr_offset(opmode): 213 if (!(*valuep & RE) && (value & RE)) 214 emac->rx_stat &= ~RX_COMP; 215 if (!(*valuep & TE) && (value & TE)) 216 emac->tx_stat &= ~TX_COMP; 217 *valuep = value; 218 break; 219 case mmr_offset(addrlo): 220 case mmr_offset(addrhi): 221 *valuep = value; 222 break; 223 case mmr_offset(wkup_ctl): 224 dv_w1c_4_partial (valuep, value, 0xf20); 225 break; 226 case mmr_offset(systat): 227 dv_w1c_4 (valuep, value, 0xe1); 228 break; 229 case mmr_offset(staadd): 230 *valuep = value | STABUSY; 231 if (value & STAOP) 232 mii_write (me); 233 else 234 mii_read (me); 235 *valuep &= ~STABUSY; 236 break; 237 case mmr_offset(rx_stat): 238 case mmr_offset(tx_stat): 239 /* Discard writes to these. */ 240 break; 241 case mmr_offset(rx_stky): 242 case mmr_offset(tx_stky): 243 case mmr_offset(mmc_rirqs): 244 case mmr_offset(mmc_tirqs): 245 dv_w1c_4 (valuep, value, -1); 246 break; 247 case mmr_offset(mmc_ctl): 248 /* Writing to bit 0 clears all counters. */ 249 *valuep = value & ~1; 250 if (value & 1) 251 { 252 memset (&emac->rxc_ok, 0, mmr_offset (rxc_ge1024) - mmr_offset (rxc_ok) + 4); 253 memset (&emac->txc_ok, 0, mmr_offset (txc_abort) - mmr_offset (txc_ok) + 4); 254 } 255 break; 256 case mmr_offset(rxc_ok) ... mmr_offset(rxc_ge1024): 257 case mmr_offset(txc_ok) ... mmr_offset(txc_abort): 258 /* XXX: Are these supposed to be read-only ? */ 259 *valuep = value; 260 break; 261 case mmr_offset(ptp_ctl) ... mmr_offset(ptp_pps_period): 262 /* XXX: Only on some models; ignore for now. */ 263 break; 264 default: 265 dv_bfin_mmr_invalid (me, addr, nr_bytes, true); 266 break; 267 } 268 269 return nr_bytes; 270} 271 272static unsigned 273bfin_emac_io_read_buffer (struct hw *me, void *dest, 274 int space, address_word addr, unsigned nr_bytes) 275{ 276 struct bfin_emac *emac = hw_data (me); 277 bu32 mmr_off; 278 bu32 *valuep; 279 280 /* XXX: 16bit accesses are allowed ... */ 281 dv_bfin_mmr_require_32 (me, addr, nr_bytes, false); 282 283 mmr_off = addr - emac->base; 284 valuep = (void *)((unsigned long)emac + mmr_base() + mmr_off); 285 286 HW_TRACE_READ (); 287 288 switch (mmr_off) 289 { 290 case mmr_offset(opmode): 291 case mmr_offset(addrlo): 292 case mmr_offset(addrhi): 293 case mmr_offset(hashlo): 294 case mmr_offset(hashhi): 295 case mmr_offset(staadd): 296 case mmr_offset(stadat): 297 case mmr_offset(flc): 298 case mmr_offset(vlan1): 299 case mmr_offset(vlan2): 300 case mmr_offset(wkup_ctl): 301 case mmr_offset(wkup_ffmsk0): 302 case mmr_offset(wkup_ffmsk1): 303 case mmr_offset(wkup_ffmsk2): 304 case mmr_offset(wkup_ffmsk3): 305 case mmr_offset(wkup_ffcmd): 306 case mmr_offset(wkup_ffoff): 307 case mmr_offset(wkup_ffcrc0): 308 case mmr_offset(wkup_ffcrc1): 309 case mmr_offset(sysctl): 310 case mmr_offset(systat): 311 case mmr_offset(rx_stat): 312 case mmr_offset(rx_stky): 313 case mmr_offset(rx_irqe): 314 case mmr_offset(tx_stat): 315 case mmr_offset(tx_stky): 316 case mmr_offset(tx_irqe): 317 case mmr_offset(mmc_rirqs): 318 case mmr_offset(mmc_rirqe): 319 case mmr_offset(mmc_tirqs): 320 case mmr_offset(mmc_tirqe): 321 case mmr_offset(mmc_ctl): 322 case mmr_offset(rxc_ok) ... mmr_offset(rxc_ge1024): 323 case mmr_offset(txc_ok) ... mmr_offset(txc_abort): 324 dv_store_4 (dest, *valuep); 325 break; 326 case mmr_offset(ptp_ctl) ... mmr_offset(ptp_pps_period): 327 /* XXX: Only on some models; ignore for now. */ 328 break; 329 default: 330 dv_bfin_mmr_invalid (me, addr, nr_bytes, false); 331 break; 332 } 333 334 return nr_bytes; 335} 336 337static void 338attach_bfin_emac_regs (struct hw *me, struct bfin_emac *emac) 339{ 340 address_word attach_address; 341 int attach_space; 342 unsigned attach_size; 343 reg_property_spec reg; 344 345 if (hw_find_property (me, "reg") == NULL) 346 hw_abort (me, "Missing \"reg\" property"); 347 348 if (!hw_find_reg_array_property (me, "reg", 0, ®)) 349 hw_abort (me, "\"reg\" property must contain three addr/size entries"); 350 351 hw_unit_address_to_attach_address (hw_parent (me), 352 ®.address, 353 &attach_space, &attach_address, me); 354 hw_unit_size_to_attach_size (hw_parent (me), ®.size, &attach_size, me); 355 356 if (attach_size != BFIN_MMR_EMAC_SIZE) 357 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_EMAC_SIZE); 358 359 hw_attach_address (hw_parent (me), 360 0, attach_space, attach_address, attach_size, me); 361 362 emac->base = attach_address; 363} 364 365static struct dv_bfin *dma_tx; 366 367static unsigned 368bfin_emac_dma_read_buffer (struct hw *me, void *dest, int space, 369 unsigned_word addr, unsigned nr_bytes) 370{ 371 struct bfin_emac *emac = hw_data (me); 372 struct dv_bfin *dma = hw_data (emac->dma_master); 373 unsigned char *data = dest; 374 static bool flop; /* XXX: This sucks. */ 375 bu16 len; 376 ssize_t ret; 377 378 HW_TRACE_DMA_READ (); 379 380 if (dma_tx == dma) 381 { 382 /* Handle the TX turn around and write the status. */ 383 emac->tx_stat |= TX_OK; 384 emac->tx_stky |= TX_OK; 385 386 memcpy (data, &emac->tx_stat, 4); 387 388 dma->acked = true; 389 return 4; 390 } 391 392 if (!(emac->opmode & RE)) 393 return 0; 394 395 if (!flop) 396 { 397 ssize_t pad_ret; 398 /* Outgoing DMA buffer has 16bit len prepended to it. */ 399 data += 2; 400 401 /* This doesn't seem to work. 402 if (emac->sysctl & RXDWA) 403 { 404 memset (data, 0, 2); 405 data += 2; 406 } */ 407 408 ret = read (emac->tap, data, nr_bytes); 409 if (ret < 0) 410 return 0; 411 ret += 4; /* include crc */ 412 pad_ret = MAX (ret + 4, 64); 413 len = pad_ret; 414 memcpy (dest, &len, 2); 415 416 pad_ret = (pad_ret + 3) & ~3; 417 if (ret < pad_ret) 418 memset (data + ret, 0, pad_ret - ret); 419 pad_ret += 4; 420 421 /* XXX: Need to check -- u-boot doesn't look at this. */ 422 if (emac->sysctl & RXCKS) 423 { 424 pad_ret += 4; 425 emac->rx_crc = 0; 426 } 427 ret = pad_ret; 428 429 /* XXX: Don't support promiscuous yet. */ 430 emac->rx_stat |= RX_ACCEPT; 431 emac->rx_stat = (emac->rx_stat & ~RX_FRLEN) | len; 432 433 emac->rx_stat |= RX_COMP; 434 emac->rx_stky |= RX_COMP; 435 } 436 else 437 { 438 /* Write the RX status and crc info. */ 439 emac->rx_stat |= RX_OK; 440 emac->rx_stky |= RX_OK; 441 442 ret = 4; 443 if (emac->sysctl & RXCKS) 444 { 445 memcpy (data, &emac->rx_crc, 4); 446 data += 4; 447 ret += 4; 448 } 449 memcpy (data, &emac->rx_stat, 4); 450 } 451 452 flop = !flop; 453 dma->acked = true; 454 return ret; 455} 456 457static unsigned 458bfin_emac_dma_write_buffer (struct hw *me, const void *source, 459 int space, unsigned_word addr, 460 unsigned nr_bytes, 461 int violate_read_only_section) 462{ 463 struct bfin_emac *emac = hw_data (me); 464 struct dv_bfin *dma = hw_data (emac->dma_master); 465 const unsigned char *data = source; 466 bu16 len; 467 ssize_t ret; 468 469 HW_TRACE_DMA_WRITE (); 470 471 if (!(emac->opmode & TE)) 472 return 0; 473 474 /* Incoming DMA buffer has 16bit len prepended to it. */ 475 memcpy (&len, data, 2); 476 if (!len) 477 return 0; 478 479 ret = write (emac->tap, data + 2, len); 480 if (ret < 0) 481 return 0; 482 ret += 2; 483 484 emac->tx_stat |= TX_COMP; 485 emac->tx_stky |= TX_COMP; 486 487 dma_tx = dma; 488 dma->acked = true; 489 return ret; 490} 491 492static const struct hw_port_descriptor bfin_emac_ports[] = 493{ 494 { "tx", DV_PORT_TX, 0, output_port, }, 495 { "rx", DV_PORT_RX, 0, output_port, }, 496 { "stat", DV_PORT_STAT, 0, output_port, }, 497 { NULL, 0, 0, 0, }, 498}; 499 500static void 501bfin_emac_attach_address_callback (struct hw *me, 502 int level, 503 int space, 504 address_word addr, 505 address_word nr_bytes, 506 struct hw *client) 507{ 508 const hw_unit *unit = hw_unit_address (client); 509 HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, nr_bytes=%lu, client=%s", 510 level, space, (unsigned long) addr, (unsigned long) nr_bytes, hw_path (client))); 511 /* NOTE: At preset the space is assumed to be zero. Perhaphs the 512 space should be mapped onto something for instance: space0 - 513 unified memory; space1 - IO memory; ... */ 514 sim_core_attach (hw_system (me), 515 NULL, /*cpu*/ 516 level + 10 + unit->cells[unit->nr_cells - 1], 517 access_read_write_exec, 518 space, addr, 519 nr_bytes, 520 0, /* modulo */ 521 client, 522 NULL); 523} 524 525static void 526bfin_emac_delete (struct hw *me) 527{ 528 struct bfin_emac *emac = hw_data (me); 529 close (emac->tap); 530} 531 532static void 533bfin_emac_tap_init (struct hw *me) 534{ 535#if WITH_TUN 536 struct bfin_emac *emac = hw_data (me); 537 const hw_unit *unit; 538 int flags; 539 540 unit = hw_unit_address (me); 541 542 emac->tap = open ("/dev/net/tun", O_RDWR); 543 if (emac->tap == -1) 544 { 545 HW_TRACE ((me, "unable to open /dev/net/tun: %s", strerror (errno))); 546 return; 547 } 548 549 memset (&emac->ifr, 0, sizeof (emac->ifr)); 550 emac->ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 551 strcpy (emac->ifr.ifr_name, "tap-gdb"); 552 553 flags = 1 * 1024 * 1024; 554 if (ioctl (emac->tap, TUNSETIFF, &emac->ifr) < 0 555#ifdef TUNSETNOCSUM 556 || ioctl (emac->tap, TUNSETNOCSUM) < 0 557#endif 558#ifdef TUNSETSNDBUF 559 || ioctl (emac->tap, TUNSETSNDBUF, &flags) < 0 560#endif 561 ) 562 { 563 HW_TRACE ((me, "tap ioctl setup failed: %s", strerror (errno))); 564 close (emac->tap); 565 return; 566 } 567 568 flags = fcntl (emac->tap, F_GETFL); 569 fcntl (emac->tap, F_SETFL, flags | O_NONBLOCK); 570#endif 571} 572 573static void 574bfin_emac_finish (struct hw *me) 575{ 576 struct bfin_emac *emac; 577 578 emac = HW_ZALLOC (me, struct bfin_emac); 579 580 set_hw_data (me, emac); 581 set_hw_io_read_buffer (me, bfin_emac_io_read_buffer); 582 set_hw_io_write_buffer (me, bfin_emac_io_write_buffer); 583 set_hw_dma_read_buffer (me, bfin_emac_dma_read_buffer); 584 set_hw_dma_write_buffer (me, bfin_emac_dma_write_buffer); 585 set_hw_ports (me, bfin_emac_ports); 586 set_hw_attach_address (me, bfin_emac_attach_address_callback); 587 set_hw_delete (me, bfin_emac_delete); 588 589 attach_bfin_emac_regs (me, emac); 590 591 /* Initialize the EMAC. */ 592 emac->addrlo = 0xffffffff; 593 emac->addrhi = 0x0000ffff; 594 emac->vlan1 = 0x0000ffff; 595 emac->vlan2 = 0x0000ffff; 596 emac->sysctl = 0x00003f00; 597 emac->mmc_ctl = 0x0000000a; 598 599 bfin_emac_tap_init (me); 600} 601 602const struct hw_descriptor dv_bfin_emac_descriptor[] = 603{ 604 {"bfin_emac", bfin_emac_finish,}, 605 {NULL, NULL}, 606}; 607