Changeset 63d8e59 in rtems-libbsd for rtemsbsd/sys
- Timestamp:
- 12/11/13 10:56:37 (10 years ago)
- Branches:
- 4.11, 5, 5-freebsd-12, 6-freebsd-12, freebsd-9.3, master
- Children:
- 90916f1
- Parents:
- 6167dca
- git-author:
- Sebastian Huber <sebastian.huber@…> (12/11/13 10:56:37)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (12/16/13 14:34:46)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
rtemsbsd/sys/dev/ffec/if_ffec_mcf548x.c
r6167dca r63d8e59 42 42 #ifdef __GENMCF548X_BSP_H 43 43 44 #include <rtems/error.h> 45 #include <rtems/rtems_bsdnet.h> 44 #pragma GCC diagnostic ignored "-Wstrict-aliasing" 45 #pragma GCC diagnostic ignored "-Wpointer-sign" 46 47 #include <machine/rtems-bsd-kernel-space.h> 48 46 49 #include <stdio.h> 47 #include <sys/param.h> 50 51 #include <rtems/bsd/sys/param.h> 52 #include <rtems/bsd/sys/types.h> 48 53 #include <sys/mbuf.h> 54 #include <sys/malloc.h> 55 #include <sys/kernel.h> 56 #include <sys/module.h> 49 57 #include <sys/socket.h> 50 58 #include <sys/sockio.h> 59 60 #include <sys/bus.h> 61 #include <machine/bus.h> 62 51 63 #include <net/if.h> 52 #include <netinet/in.h> 53 #include <netinet/if_ether.h> 64 #include <net/ethernet.h> 65 #include <net/if_arp.h> 66 #include <net/if_dl.h> 67 #include <net/if_media.h> 68 #include <net/if_types.h> 54 69 #include <net/if_var.h> 55 70 … … 63 78 #include <mcf548x/mcdma_glue.h> 64 79 80 /* FIXME */ 81 rtems_id 82 rtems_bsdnet_newproc (char *name, int stacksize, void(*entry)(void *), void *arg); 83 #define rtems_panic panic 84 #define SIO_RTEMS_SHOW_STATS _IO('i', 250) 85 86 static void mcf548x_fec_watchdog(void *arg); 87 65 88 /* 66 89 * Number of interfaces supported by this driver … … 70 93 #define FEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */ 71 94 72 #define DMA_BD_RX_NUM 32/* Number of receive buffer descriptors */73 #define DMA_BD_TX_NUM 32/* Number of transmit buffer descriptors */95 #define DMA_BD_RX_NUM 128 /* Number of receive buffer descriptors */ 96 #define DMA_BD_TX_NUM 128 /* Number of transmit buffer descriptors */ 74 97 75 98 #define FEC_EVENT RTEMS_EVENT_0 … … 180 203 */ 181 204 struct mcf548x_enet_struct { 182 struct arpcom arpcom; 183 short padding; 205 device_t dev; 206 struct ifnet *ifp; 207 struct mtx mtx; 184 208 struct mbuf **rxMbuf; 185 209 struct mbuf **txMbuf; … … 193 217 int rxDmaChan; /* dma task */ 194 218 int txDmaChan; /* dma task */ 219 struct callout watchdogCallout; 195 220 rtems_id rxDaemonTid; 196 221 rtems_id txDaemonTid; … … 222 247 }; 223 248 224 static struct mcf548x_enet_struct enet_driver[NIFACES]; 249 #define FEC_LOCK(sc) mtx_lock(&(sc)->mtx) 250 251 #define FEC_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 252 253 static struct mcf548x_enet_struct *fec_vector_to_sc[NIFACES]; 225 254 226 255 static void mcf548x_fec_restart(struct mcf548x_enet_struct *sc, rtems_id otherDaemon); … … 228 257 static void fec_send_event(rtems_id task) 229 258 { 230 rtems_ bsdnet_event_send(task, FEC_EVENT);231 } 232 233 static void fec_wait_for_event( void)259 rtems_event_send(task, FEC_EVENT); 260 } 261 262 static void fec_wait_for_event(struct mcf548x_enet_struct *sc) 234 263 { 235 264 rtems_event_set out; 236 rtems_bsdnet_event_receive( 265 266 FEC_UNLOCK(sc); 267 rtems_event_receive( 237 268 FEC_EVENT, 238 269 RTEMS_EVENT_ANY | RTEMS_WAIT, … … 240 271 &out 241 272 ); 273 FEC_LOCK(sc); 242 274 } 243 275 … … 271 303 * Get the mac address of ethernet controller 272 304 */ 273 mac = (unsigned char *)(&sc->arpcom.ac_enaddr);305 mac = IF_LLADDR(sc->ifp); 274 306 275 307 /* … … 503 535 */ 504 536 for (delay = 0;delay < 16*4;delay++) {}; 537 538 /* Clear and enable MIB counters */ 539 memset( 540 __DEVOLATILE(void *, &MCF548X_FEC_RMON_T_DROP(chan)), 541 0, 542 0xe4 543 ); 544 MCF548X_FEC_MIBC(chan) &= ~MCF548X_FEC_MIBC_MIB_DISABLE; 505 545 } 506 546 … … 593 633 int chan; 594 634 595 sc = &(enet_driver[MCF548X_FEC_VECTOR2CHAN(vector)]);635 sc = fec_vector_to_sc[MCF548X_FEC_VECTOR2CHAN(vector)]; 596 636 chan = sc->chan; 597 637 ievent = MCF548X_FEC_EIR(chan); … … 621 661 if (ievent & (MCF548X_FEC_EIR_RFERR | MCF548X_FEC_EIR_XFERR)) { 622 662 MCF548X_FEC_EIMR(chan) &=~(MCF548X_FEC_EIMR_RFERR | MCF548X_FEC_EIMR_XFERR); 623 printk("fifo\n");624 663 mcf548x_fec_request_restart(sc); 625 664 } … … 764 803 struct mcf548x_enet_struct *sc = ifp->if_softc; 765 804 766 ifp->if_ flags |= IFF_OACTIVE;805 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 767 806 768 807 fec_send_event(sc->txDaemonTid); … … 844 883 fec_send_event(otherDaemon); 845 884 while (sc->state != FEC_STATE_NORMAL) { 846 fec_wait_for_event( );885 fec_wait_for_event(sc); 847 886 } 848 887 } … … 903 942 *isFirst = true; 904 943 } else { 905 ifp->if_ flags &= ~IFF_OACTIVE;944 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 906 945 907 946 return NULL; … … 1024 1063 { 1025 1064 struct mcf548x_enet_struct *sc = arg; 1026 struct ifnet *ifp = &sc->arpcom.ac_if;1065 struct ifnet *ifp = sc->ifp; 1027 1066 int dmaChan = sc->txDmaChan; 1028 1067 int bdIndex = 0; … … 1036 1075 memset(mbufs, 0, bdCount * sizeof(*mbufs)); 1037 1076 1077 FEC_LOCK(sc); 1078 1038 1079 while (true) { 1039 1080 if (bdShortage) { 1040 1081 mcdma_glue_irq_enable(dmaChan); 1041 1082 } 1042 fec_wait_for_event( );1083 fec_wait_for_event(sc); 1043 1084 1044 1085 if (sc->state != FEC_STATE_NORMAL) { … … 1131 1172 1132 1173 static int fec_ether_input( 1174 struct mcf548x_enet_struct *sc, 1133 1175 struct ifnet *ifp, 1134 1176 int dmaChan, … … 1155 1197 n = fec_add_mbuf(0, ifp, bd, bdIsLast); 1156 1198 if (n != NULL) { 1157 int len = bd->length - ETHER_HDR_LEN - ETHER_CRC_LEN; 1158 struct ether_header *eh = mtod(m, struct ether_header *); 1199 int len = bd->length - ETHER_CRC_LEN; 1159 1200 1160 1201 m->m_len = len; 1161 1202 m->m_pkthdr.len = len; 1162 m->m_data = mtod(m, char *) + ETHER_HDR_LEN; 1163 1164 ether_input(ifp, eh, m); 1203 1204 FEC_UNLOCK(sc); 1205 sc->ifp->if_input(sc->ifp, m); 1206 FEC_LOCK(sc); 1165 1207 } else { 1166 1208 n = m; … … 1182 1224 { 1183 1225 struct mcf548x_enet_struct *sc = arg; 1184 struct ifnet *ifp = &sc->arpcom.ac_if;1226 struct ifnet *ifp = sc->ifp; 1185 1227 int dmaChan = sc->rxDmaChan; 1186 1228 int bdIndex = 0; … … 1189 1231 MCD_bufDescFec *bdRing = fec_init_rx_dma(sc->rxBd, ifp, bdCount, mbufs); 1190 1232 1233 FEC_LOCK(sc); 1234 1191 1235 while (true) { 1192 1236 mcdma_glue_irq_enable(dmaChan); 1193 fec_wait_for_event( );1194 1195 bdIndex = fec_ether_input( ifp, dmaChan, bdIndex, bdCount, bdRing, mbufs);1237 fec_wait_for_event(sc); 1238 1239 bdIndex = fec_ether_input(sc, ifp, dmaChan, bdIndex, bdCount, bdRing, mbufs); 1196 1240 1197 1241 if (sc->state != FEC_STATE_NORMAL) { … … 1209 1253 { 1210 1254 struct mcf548x_enet_struct *sc = (struct mcf548x_enet_struct *)arg; 1211 struct ifnet *ifp = &sc->arpcom.ac_if;1255 struct ifnet *ifp = sc->ifp; 1212 1256 int chan = sc->chan; 1213 1257 rtems_isr_entry old_handler; … … 1233 1277 */ 1234 1278 sc->rxMbuf = 1235 malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_ MBUF, M_NOWAIT);1279 malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_TEMP, M_NOWAIT); 1236 1280 sc->txMbuf = 1237 malloc(sc->txBdCount * sizeof *sc->txMbuf, M_ MBUF, M_NOWAIT);1281 malloc(sc->txBdCount * sizeof *sc->txMbuf, M_TEMP, M_NOWAIT); 1238 1282 1239 1283 if(!sc->rxMbuf || !sc->txMbuf) … … 1288 1332 * init timer so the "watchdog function gets called periodically 1289 1333 */ 1290 ifp->if_timer = 1; 1334 callout_reset(&sc->watchdogCallout, hz, mcf548x_fec_watchdog, sc); 1335 1291 1336 /* 1292 1337 * Tell the world that we're running. 1293 1338 */ 1294 ifp->if_ flags |= IFF_RUNNING;1339 ifp->if_drv_flags |= IFF_DRV_RUNNING; 1295 1340 } 1296 1341 … … 1340 1385 rtems_mii_ioctl (&(sc->mdio_info),sc,command,(void *)data); 1341 1386 break; 1342 1343 case SIOCGIFADDR: 1344 case SIOCSIFADDR: 1345 1346 ether_ioctl(ifp, command, data); 1387 case SIO_RTEMS_SHOW_STATS: 1388 1389 enet_stats(sc); 1347 1390 1348 1391 break; 1349 1392 1350 case SIOCADDMULTI: 1351 case SIOCDELMULTI: { 1352 struct ifreq* ifr = (struct ifreq*) data; 1353 error = (command == SIOCADDMULTI) 1354 ? ether_addmulti(ifr, &sc->arpcom) 1355 : ether_delmulti(ifr, &sc->arpcom); 1356 1357 if (error == ENETRESET) { 1358 if (ifp->if_flags & IFF_RUNNING) 1359 error = mcf548x_fec_setMultiFilter(ifp); 1360 else 1361 error = 0; 1362 } 1363 break; 1364 } 1365 1366 case SIOCSIFFLAGS: 1367 1368 switch(ifp->if_flags & (IFF_UP | IFF_RUNNING)) 1369 { 1370 1371 case IFF_RUNNING: 1372 1373 mcf548x_fec_off(sc); 1374 1375 break; 1376 1377 case IFF_UP: 1378 1379 mcf548x_fec_init(sc); 1380 1381 break; 1382 1383 case IFF_UP | IFF_RUNNING: 1384 1385 mcf548x_fec_off(sc); 1386 mcf548x_fec_init(sc); 1387 1388 break; 1389 1390 default: 1391 break; 1392 1393 } 1394 1393 default: 1394 error = ether_ioctl(ifp, command, data); 1395 1395 break; 1396 1397 case SIO_RTEMS_SHOW_STATS:1398 1399 enet_stats(sc);1400 1401 break;1402 1403 /*1404 * FIXME: All sorts of multicast commands need to be added here!1405 */1406 default:1407 1408 error = EINVAL;1409 1410 break;1411 1412 1396 } 1413 1397 … … 1489 1473 * then adjust the FEC settings 1490 1474 */ 1491 static void mcf548x_fec_watchdog( struct ifnet *ifp) 1492 { 1493 mcf548x_fec_mode_adapt(ifp); 1494 ifp->if_timer = FEC_WATCHDOG_TIMEOUT; 1495 } 1475 static void mcf548x_fec_watchdog(void *arg) 1476 { 1477 struct mcf548x_enet_struct *sc = arg; 1478 1479 mcf548x_fec_mode_adapt(sc->ifp); 1480 1481 callout_reset(&sc->watchdogCallout, FEC_WATCHDOG_TIMEOUT * hz, mcf548x_fec_watchdog, sc); 1482 } 1483 1484 static const uint8_t eaddr[NIFACES][ETHER_ADDR_LEN] = { 1485 { 0x0e, 0xb0, 0xba, 0x5e, 0xba, 0x12 }, 1486 { 0x0e, 0xb0, 0xba, 0x5e, 0xba, 0x13 } 1487 }; 1496 1488 1497 1489 /* 1498 1490 * Attach the MCF548X fec driver to the system 1499 1491 */ 1500 int rtems_mcf548x_fec_driver_attach(struct rtems_bsdnet_ifconfig *config)1501 1492 static int fec_attach(device_t dev) 1493 { 1502 1494 struct mcf548x_enet_struct *sc; 1503 1495 struct ifnet *ifp; 1504 int mtu; 1505 int unitNumber; 1506 char *unitName; 1507 1508 /* 1509 * Parse driver name 1510 */ 1511 if((unitNumber = rtems_bsdnet_parse_driver_name(config, &unitName)) < 0) 1512 return 0; 1513 1514 /* 1515 * Is driver free? 1516 */ 1517 if ((unitNumber <= 0) || (unitNumber > NIFACES)) 1518 { 1519 1520 printf ("Bad FEC unit number.\n"); 1521 return 0; 1522 1523 } 1524 1525 sc = &enet_driver[unitNumber - 1]; 1526 sc->chan = unitNumber-1; 1527 ifp = &sc->arpcom.ac_if; 1528 1529 if(ifp->if_softc != NULL) 1530 { 1531 1532 printf ("Driver already in use.\n"); 1533 return 0; 1534 1535 } 1536 1537 /* 1538 * Process options 1539 */ 1540 #if NVRAM_CONFIGURE == 1 1541 1542 /* Configure from NVRAM */ 1543 if(addr = nvram->ipaddr) 1544 { 1545 1546 /* We have a non-zero entry, copy the value */ 1547 if(pAddr = malloc(INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT)) 1548 config->ip_address = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1); 1549 else 1550 rtems_panic("Can't allocate ip_address buffer!\n"); 1551 1552 } 1553 1554 if(addr = nvram->netmask) 1555 { 1556 1557 /* We have a non-zero entry, copy the value */ 1558 if (pAddr = malloc (INET_ADDR_MAX_BUF_SIZE, 0, M_NOWAIT)) 1559 config->ip_netmask = (char *)inet_ntop(AF_INET, &addr, pAddr, INET_ADDR_MAX_BUF_SIZE -1); 1560 else 1561 rtems_panic("Can't allocate ip_netmask buffer!\n"); 1562 1563 } 1564 1565 /* Ethernet address requires special handling -- it must be copied into 1566 * the arpcom struct. The following if construct serves only to give the 1567 * User Area NVRAM parameter the highest priority. 1568 * 1569 * If the ethernet address is specified in NVRAM, go ahead and copy it. 1570 * (ETHER_ADDR_LEN = 6 bytes). 1571 */ 1572 if(nvram->enaddr[0] || nvram->enaddr[1] || nvram->enaddr[2]) 1573 { 1574 1575 /* Anything in the first three bytes indicates a non-zero entry, copy value */ 1576 memcpy((void *)sc->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN); 1577 1578 } 1579 else 1580 if(config->hardware_address) 1581 { 1582 1583 /* There is no entry in NVRAM, but there is in the ifconfig struct, so use it. */ 1584 memcpy((void *)sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); 1585 } 1586 1587 #else /* NVRAM_CONFIGURE != 1 */ 1588 1589 if(config->hardware_address) 1590 { 1591 1592 memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); 1593 1594 } 1595 1596 #endif /* NVRAM_CONFIGURE != 1 */ 1597 #ifdef HAS_UBOOT 1598 if ((sc->arpcom.ac_enaddr[0] == 0) && 1599 (sc->arpcom.ac_enaddr[1] == 0) && 1600 (sc->arpcom.ac_enaddr[2] == 0)) { 1601 memcpy( 1602 (void *)sc->arpcom.ac_enaddr, 1603 bsp_uboot_board_info.bi_enetaddr, 1604 ETHER_ADDR_LEN 1605 ); 1606 } 1607 #endif 1608 #ifdef HAS_DBUG 1609 if ((sc->arpcom.ac_enaddr[0] == 0) && 1610 (sc->arpcom.ac_enaddr[1] == 0) && 1611 (sc->arpcom.ac_enaddr[2] == 0)) { 1612 memcpy( 1613 (void *)sc->arpcom.ac_enaddr, 1614 DBUG_SETTINGS.macaddr, 1615 ETHER_ADDR_LEN 1616 ); 1617 } 1618 #endif 1619 if ((sc->arpcom.ac_enaddr[0] == 0) && 1620 (sc->arpcom.ac_enaddr[1] == 0) && 1621 (sc->arpcom.ac_enaddr[2] == 0)) { 1622 /* There is no ethernet address provided, so it could be read 1623 * from the Ethernet protocol block of SCC1 in DPRAM. 1624 */ 1625 rtems_panic("No Ethernet address specified!\n"); 1626 } 1627 if(config->mtu) 1628 mtu = config->mtu; 1629 else 1630 mtu = ETHERMTU; 1631 1632 if(config->rbuf_count) 1633 sc->rxBdCount = config->rbuf_count; 1634 else 1635 sc->rxBdCount = RX_BUF_COUNT; 1636 1637 if(config->xbuf_count) 1638 sc->txBdCount = config->xbuf_count; 1639 else 1640 sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; 1641 1642 sc->acceptBroadcast = !config->ignore_broadcast; 1496 int unit = device_get_unit(dev); 1497 1498 sc = device_get_softc(dev); 1499 1500 sc->dev = dev; 1501 sc->chan = unit; 1502 sc->ifp = ifp = if_alloc(IFT_ETHER); 1503 1504 mtx_init(&sc->mtx, device_get_nameunit(sc->dev), MTX_NETWORK_LOCK, MTX_DEF); 1505 callout_init_mtx(&sc->watchdogCallout, &sc->mtx, 0); 1506 1507 sc->rxBdCount = RX_BUF_COUNT; 1508 sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; 1509 sc->acceptBroadcast = 1; 1643 1510 1644 1511 /* … … 1653 1520 * like this, this should be more configurable 1654 1521 */ 1655 sc->phy_default = unit Number-1;1522 sc->phy_default = unit; 1656 1523 sc->phy_chan = 0; /* assume all MII accesses are via FEC0 */ 1657 1524 1525 fec_vector_to_sc[unit] = sc; 1526 1658 1527 /* 1659 1528 * Set up network interface values 1660 1529 */ 1661 1530 ifp->if_softc = sc; 1662 ifp->if_unit = unitNumber; 1663 ifp->if_name = unitName; 1664 ifp->if_mtu = mtu; 1531 if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 1665 1532 ifp->if_init = mcf548x_fec_init; 1666 1533 ifp->if_ioctl = mcf548x_fec_ioctl; 1667 1534 ifp->if_start = mcf548x_fec_tx_start; 1668 ifp->if_output = ether_output; 1669 ifp->if_watchdog = mcf548x_fec_watchdog; /* XXX: timer is set in "init" */ 1670 ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST; 1671 /*ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;*/ 1672 1673 if(ifp->if_snd.ifq_maxlen == 0) 1674 ifp->if_snd.ifq_maxlen = ifqmaxlen; 1535 ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX; 1536 IFQ_SET_MAXLEN(&ifp->if_snd, TX_BUF_COUNT - 1); 1537 ifp->if_snd.ifq_drv_maxlen = TX_BUF_COUNT - 1; 1538 IFQ_SET_READY(&ifp->if_snd); 1539 ifp->if_data.ifi_hdrlen = sizeof(struct ether_header); 1675 1540 1676 1541 /* 1677 1542 * Attach the interface 1678 1543 */ 1679 if_attach(ifp); 1680 1681 ether_ifattach(ifp); 1682 1683 return 1; 1684 } 1685 1686 1687 int rtems_mcf548x_fec_driver_attach_detach(struct rtems_bsdnet_ifconfig *config, int attaching) 1688 { 1689 if (attaching) { 1690 return rtems_mcf548x_fec_driver_attach(config); 1691 } 1692 else { 1693 return 0; 1694 } 1695 } 1544 ether_ifattach(ifp, &eaddr[unit][0]); 1545 1546 return 0; 1547 } 1548 1549 static int 1550 fec_probe(device_t dev) 1551 { 1552 int unit = device_get_unit(dev); 1553 int error; 1554 1555 if (unit >= 0 && unit < NIFACES) { 1556 error = BUS_PROBE_DEFAULT; 1557 } else { 1558 error = ENXIO; 1559 } 1560 1561 return (error); 1562 } 1563 1564 static device_method_t fec_methods[] = { 1565 /* Device interface */ 1566 DEVMETHOD(device_probe, fec_probe), 1567 DEVMETHOD(device_attach, fec_attach), 1568 1569 DEVMETHOD_END 1570 }; 1571 1572 static driver_t fec_nexus_driver = { 1573 "fec", 1574 fec_methods, 1575 sizeof(struct mcf548x_enet_struct) 1576 }; 1577 1578 static devclass_t fec_devclass; 1579 DRIVER_MODULE(fec, nexus, fec_nexus_driver, fec_devclass, 0, 0); 1580 MODULE_DEPEND(fec, nexus, 1, 1, 1); 1581 MODULE_DEPEND(fec, ether, 1, 1, 1); 1696 1582 1697 1583 #endif /* __GENMCF548X_BSP_H */
Note: See TracChangeset
for help on using the changeset viewer.