dv-bfin_emac.c 17 KB

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