1/*- 2 * Copyright (c) 1995, David Greenman 3 * Copyright (c) 2001 Jonathan Lemon <jlemon@freebsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 14 unchanged lines hidden (view full) --- 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/fxp/if_fxp.c 185330 2008-11-26 07:36:17Z yongari $"); |
32 33/* 34 * Intel EtherExpress Pro/100B PCI Fast Ethernet driver 35 */ 36 37#ifdef HAVE_KERNEL_OPTION_HEADERS 38#include "opt_device_polling.h" 39#endif --- 574 unchanged lines hidden (view full) --- 614 sc->rfa_size = sizeof (struct fxp_rfa) - FXP_RFAX_LEN; 615 sc->tx_cmd = FXP_CB_COMMAND_XMIT; 616 } 617 618 /* 619 * Allocate DMA tags and DMA safe memory. 620 */ 621 sc->maxtxseg = FXP_NTXSEG; |
622 sc->maxsegsize = MCLBYTES; 623 if (sc->flags & FXP_FLAG_EXT_RFA) { |
624 sc->maxtxseg--; |
625 sc->maxsegsize = FXP_TSO_SEGSIZE; 626 } |
627 error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0, 628 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, |
629 sc->maxsegsize * sc->maxtxseg + sizeof(struct ether_vlan_header), 630 sc->maxtxseg, sc->maxsegsize, 0, |
631 busdma_lock_mutex, &Giant, &sc->fxp_mtag); 632 if (error) { 633 device_printf(dev, "could not allocate dma tag\n"); 634 goto fail; 635 } 636 637 error = bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0, 638 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, --- 140 unchanged lines hidden (view full) --- 779 ifp->if_init = fxp_init; 780 ifp->if_softc = sc; 781 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 782 ifp->if_ioctl = fxp_ioctl; 783 ifp->if_start = fxp_start; 784 785 ifp->if_capabilities = ifp->if_capenable = 0; 786 |
787 /* Enable checksum offload/TSO for 82550 or better chips */ |
788 if (sc->flags & FXP_FLAG_EXT_RFA) { |
789 ifp->if_hwassist = FXP_CSUM_FEATURES | CSUM_TSO; 790 ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4; 791 ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_TSO4; |
792 } 793 794 if (sc->flags & FXP_FLAG_82559_RXCSUM) { 795 ifp->if_capabilities |= IFCAP_RXCSUM; 796 ifp->if_capenable |= IFCAP_RXCSUM; 797 } 798 799#ifdef DEVICE_POLLING --- 474 unchanged lines hidden (view full) --- 1274 1275static int 1276fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) 1277{ 1278 struct ifnet *ifp; 1279 struct mbuf *m; 1280 struct fxp_tx *txp; 1281 struct fxp_cb_tx *cbp; |
1282 struct tcphdr *tcp; |
1283 bus_dma_segment_t segs[FXP_NTXSEG]; |
1284 int error, i, nseg, tcp_payload; |
1285 1286 FXP_LOCK_ASSERT(sc, MA_OWNED); 1287 ifp = sc->ifp; 1288 |
1289 tcp_payload = 0; 1290 tcp = NULL; |
1291 /* 1292 * Get pointer to next available tx desc. 1293 */ 1294 txp = sc->fxp_desc.tx_last->tx_next; 1295 1296 /* 1297 * A note in Appendix B of the Intel 8255x 10/100 Mbps 1298 * Ethernet Controller Family Open Source Software --- 61 unchanged lines hidden (view full) --- 1360 FXP_IPCB_HARDWAREPARSING_ENABLE; 1361 txp->tx_cb->ipcb_ip_schedule |= 1362 FXP_IPCB_IP_CHECKSUM_ENABLE; 1363 } 1364 } 1365#endif 1366 } 1367 |
1368 if (m->m_pkthdr.csum_flags & CSUM_TSO) { 1369 /* 1370 * 82550/82551 requires ethernet/IP/TCP headers must be 1371 * contained in the first active transmit buffer. 1372 */ 1373 struct ether_header *eh; 1374 struct ip *ip; 1375 uint32_t ip_off, poff; 1376 1377 if (M_WRITABLE(*m_head) == 0) { 1378 /* Get a writable copy. */ 1379 m = m_dup(*m_head, M_DONTWAIT); 1380 m_freem(*m_head); 1381 if (m == NULL) { 1382 *m_head = NULL; 1383 return (ENOBUFS); 1384 } 1385 *m_head = m; 1386 } 1387 ip_off = sizeof(struct ether_header); 1388 m = m_pullup(*m_head, ip_off); 1389 if (m == NULL) { 1390 *m_head = NULL; 1391 return (ENOBUFS); 1392 } 1393 eh = mtod(m, struct ether_header *); 1394 /* Check the existence of VLAN tag. */ 1395 if (eh->ether_type == htons(ETHERTYPE_VLAN)) { 1396 ip_off = sizeof(struct ether_vlan_header); 1397 m = m_pullup(m, ip_off); 1398 if (m == NULL) { 1399 *m_head = NULL; 1400 return (ENOBUFS); 1401 } 1402 } 1403 m = m_pullup(m, ip_off + sizeof(struct ip)); 1404 if (m == NULL) { 1405 *m_head = NULL; 1406 return (ENOBUFS); 1407 } 1408 ip = (struct ip *)(mtod(m, char *) + ip_off); 1409 poff = ip_off + (ip->ip_hl << 2); 1410 m = m_pullup(m, poff + sizeof(struct tcphdr)); 1411 if (m == NULL) { 1412 *m_head = NULL; 1413 return (ENOBUFS); 1414 } 1415 tcp = (struct tcphdr *)(mtod(m, char *) + poff); 1416 m = m_pullup(m, poff + sizeof(struct tcphdr) + tcp->th_off); 1417 if (m == NULL) { 1418 *m_head = NULL; 1419 return (ENOBUFS); 1420 } 1421 1422 /* 1423 * Since 82550/82551 doesn't modify IP length and pseudo 1424 * checksum in the first frame driver should compute it. 1425 */ 1426 ip->ip_sum = 0; 1427 ip->ip_len = htons(ifp->if_mtu); 1428 tcp->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, 1429 htons(IPPROTO_TCP + (tcp->th_off << 2) + 1430 m->m_pkthdr.tso_segsz)); 1431 /* Compute total TCP payload. */ 1432 tcp_payload = m->m_pkthdr.len - ip_off - (ip->ip_hl << 2); 1433 tcp_payload -= tcp->th_off << 2; 1434 *m_head = m; 1435 } 1436 |
1437 error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map, *m_head, 1438 segs, &nseg, 0); 1439 if (error == EFBIG) { 1440 m = m_collapse(*m_head, M_DONTWAIT, sc->maxtxseg); 1441 if (m == NULL) { 1442 m_freem(*m_head); 1443 *m_head = NULL; 1444 return (ENOMEM); --- 14 unchanged lines hidden (view full) --- 1459 return (EIO); 1460 } 1461 1462 KASSERT(nseg <= sc->maxtxseg, ("too many DMA segments")); 1463 bus_dmamap_sync(sc->fxp_mtag, txp->tx_map, BUS_DMASYNC_PREWRITE); 1464 1465 cbp = txp->tx_cb; 1466 for (i = 0; i < nseg; i++) { |
1467 /* 1468 * If this is an 82550/82551, then we're using extended 1469 * TxCBs _and_ we're using checksum offload. This means 1470 * that the TxCB is really an IPCB. One major difference 1471 * between the two is that with plain extended TxCBs, 1472 * the bottom half of the TxCB contains two entries from 1473 * the TBD array, whereas IPCBs contain just one entry: 1474 * one entry (8 bytes) has been sacrificed for the TCP/IP 1475 * checksum offload control bits. So to make things work 1476 * right, we have to start filling in the TBD array 1477 * starting from a different place depending on whether 1478 * the chip is an 82550/82551 or not. 1479 */ 1480 if (sc->flags & FXP_FLAG_EXT_RFA) { |
1481 cbp->tbd[i + 2].tb_addr = htole32(segs[i].ds_addr); 1482 cbp->tbd[i + 2].tb_size = htole32(segs[i].ds_len); |
1483 } else { 1484 cbp->tbd[i].tb_addr = htole32(segs[i].ds_addr); 1485 cbp->tbd[i].tb_size = htole32(segs[i].ds_len); 1486 } 1487 } |
1488 if (sc->flags & FXP_FLAG_EXT_RFA) { 1489 /* Configure dynamic TBD for 82550/82551. */ 1490 cbp->tbd_number = 0xFF; 1491 cbp->tbd[nseg + 1].tb_size |= htole32(0x8000); 1492 } else 1493 cbp->tbd_number = nseg; 1494 /* Configure TSO. */ 1495 if (m->m_pkthdr.csum_flags & CSUM_TSO) { 1496 cbp->tbd[-1].tb_size = htole32(m->m_pkthdr.tso_segsz << 16); 1497 cbp->tbd[1].tb_size = htole32(tcp_payload << 16); 1498 cbp->ipcb_ip_schedule |= FXP_IPCB_LARGESEND_ENABLE | 1499 FXP_IPCB_IP_CHECKSUM_ENABLE | 1500 FXP_IPCB_TCP_PACKET | 1501 FXP_IPCB_TCPUDP_CHECKSUM_ENABLE; 1502 } |
1503 1504 txp->tx_mbuf = m; 1505 txp->tx_cb->cb_status = 0; 1506 txp->tx_cb->byte_count = 0; 1507 if (sc->tx_queued != FXP_CXINT_THRESH - 1) 1508 txp->tx_cb->cb_command = 1509 htole16(sc->tx_cmd | FXP_CB_COMMAND_SF | 1510 FXP_CB_COMMAND_S); 1511 else 1512 txp->tx_cb->cb_command = 1513 htole16(sc->tx_cmd | FXP_CB_COMMAND_SF | 1514 FXP_CB_COMMAND_S | FXP_CB_COMMAND_I); |
1515 if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0) 1516 txp->tx_cb->tx_threshold = tx_threshold; |
1517 1518 /* 1519 * Advance the end of list forward. 1520 */ 1521 1522#ifdef __alpha__ 1523 /* 1524 * On platforms which can't access memory in 16-bit --- 657 unchanged lines hidden (view full) --- 2182 cbp->ci_int = 1; /* interrupt on CU idle */ 2183 cbp->ext_txcb_dis = sc->flags & FXP_FLAG_EXT_TXCB ? 0 : 1; 2184 cbp->ext_stats_dis = 1; /* disable extended counters */ 2185 cbp->keep_overrun_rx = 0; /* don't pass overrun frames to host */ 2186 cbp->save_bf = sc->flags & FXP_FLAG_SAVE_BAD ? 1 : prm; 2187 cbp->disc_short_rx = !prm; /* discard short packets */ 2188 cbp->underrun_retry = 1; /* retry mode (once) on DMA underrun */ 2189 cbp->two_frames = 0; /* do not limit FIFO to 2 frames */ |
2190 cbp->dyn_tbd = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; |
2191 cbp->ext_rfa = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; 2192 cbp->mediatype = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 0 : 1; 2193 cbp->csma_dis = 0; /* (don't) disable link */ 2194 cbp->tcp_udp_cksum = ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0 && 2195 (ifp->if_capenable & IFCAP_RXCSUM) != 0) ? 1 : 0; 2196 cbp->vlan_tco = 0; /* (don't) enable vlan wakeup */ 2197 cbp->link_wake_en = 0; /* (don't) assert PME# on link change */ 2198 cbp->arp_wake_en = 0; /* (don't) assert PME# on arp */ --- 475 unchanged lines hidden (view full) --- 2674 ifp->if_hwassist &= ~FXP_CSUM_FEATURES; 2675 } 2676 if ((mask & IFCAP_RXCSUM) != 0 && 2677 (ifp->if_capabilities & IFCAP_RXCSUM) != 0) { 2678 ifp->if_capenable ^= IFCAP_RXCSUM; 2679 if ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0) 2680 reinit++; 2681 } |
2682 if ((mask & IFCAP_TSO4) != 0 && 2683 (ifp->if_capabilities & IFCAP_TSO4) != 0) { 2684 ifp->if_capenable ^= IFCAP_TSO4; 2685 if ((ifp->if_capenable & IFCAP_TSO4) != 0) 2686 ifp->if_hwassist |= CSUM_TSO; 2687 else 2688 ifp->if_hwassist &= ~CSUM_TSO; 2689 } |
2690 if ((mask & IFCAP_VLAN_MTU) != 0 && 2691 (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) { 2692 ifp->if_capenable ^= IFCAP_VLAN_MTU; 2693 if (sc->revision != FXP_REV_82557) 2694 flag = FXP_FLAG_LONG_PKT_EN; 2695 else /* a hack to get long frames on the old chip */ 2696 flag = FXP_FLAG_SAVE_BAD; 2697 sc->flags ^= flag; --- 259 unchanged lines hidden --- |