if_fxp.c (185329) | if_fxp.c (185330) |
---|---|
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> | 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 185329 2008-11-26 06:36:53Z yongari $"); | 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; | 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 if (sc->flags & FXP_FLAG_EXT_RFA) | 622 sc->maxsegsize = MCLBYTES; 623 if (sc->flags & FXP_FLAG_EXT_RFA) { |
623 sc->maxtxseg--; | 624 sc->maxtxseg--; |
625 sc->maxsegsize = FXP_TSO_SEGSIZE; 626 } |
|
624 error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0, 625 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, | 627 error = bus_dma_tag_create(bus_get_dma_tag(dev), 2, 0, 628 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, |
626 MCLBYTES * sc->maxtxseg, sc->maxtxseg, MCLBYTES, 0, | 629 sc->maxsegsize * sc->maxtxseg + sizeof(struct ether_vlan_header), 630 sc->maxtxseg, sc->maxsegsize, 0, |
627 busdma_lock_mutex, &Giant, &sc->fxp_mtag); 628 if (error) { 629 device_printf(dev, "could not allocate dma tag\n"); 630 goto fail; 631 } 632 633 error = bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0, 634 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, --- 140 unchanged lines hidden (view full) --- 775 ifp->if_init = fxp_init; 776 ifp->if_softc = sc; 777 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 778 ifp->if_ioctl = fxp_ioctl; 779 ifp->if_start = fxp_start; 780 781 ifp->if_capabilities = ifp->if_capenable = 0; 782 | 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 |
783 /* Enable checksum offload for 82550 or better chips */ | 787 /* Enable checksum offload/TSO for 82550 or better chips */ |
784 if (sc->flags & FXP_FLAG_EXT_RFA) { | 788 if (sc->flags & FXP_FLAG_EXT_RFA) { |
785 ifp->if_hwassist = FXP_CSUM_FEATURES; 786 ifp->if_capabilities |= IFCAP_HWCSUM; 787 ifp->if_capenable |= IFCAP_HWCSUM; | 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; |
788 } 789 790 if (sc->flags & FXP_FLAG_82559_RXCSUM) { 791 ifp->if_capabilities |= IFCAP_RXCSUM; 792 ifp->if_capenable |= IFCAP_RXCSUM; 793 } 794 795#ifdef DEVICE_POLLING --- 474 unchanged lines hidden (view full) --- 1270 1271static int 1272fxp_encap(struct fxp_softc *sc, struct mbuf **m_head) 1273{ 1274 struct ifnet *ifp; 1275 struct mbuf *m; 1276 struct fxp_tx *txp; 1277 struct fxp_cb_tx *cbp; | 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; |
|
1278 bus_dma_segment_t segs[FXP_NTXSEG]; | 1283 bus_dma_segment_t segs[FXP_NTXSEG]; |
1279 int error, i, nseg; | 1284 int error, i, nseg, tcp_payload; |
1280 1281 FXP_LOCK_ASSERT(sc, MA_OWNED); 1282 ifp = sc->ifp; 1283 | 1285 1286 FXP_LOCK_ASSERT(sc, MA_OWNED); 1287 ifp = sc->ifp; 1288 |
1289 tcp_payload = 0; 1290 tcp = NULL; |
|
1284 /* 1285 * Get pointer to next available tx desc. 1286 */ 1287 txp = sc->fxp_desc.tx_last->tx_next; 1288 1289 /* 1290 * A note in Appendix B of the Intel 8255x 10/100 Mbps 1291 * Ethernet Controller Family Open Source Software --- 61 unchanged lines hidden (view full) --- 1353 FXP_IPCB_HARDWAREPARSING_ENABLE; 1354 txp->tx_cb->ipcb_ip_schedule |= 1355 FXP_IPCB_IP_CHECKSUM_ENABLE; 1356 } 1357 } 1358#endif 1359 } 1360 | 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 |
|
1361 error = bus_dmamap_load_mbuf_sg(sc->fxp_mtag, txp->tx_map, *m_head, 1362 segs, &nseg, 0); 1363 if (error == EFBIG) { 1364 m = m_collapse(*m_head, M_DONTWAIT, sc->maxtxseg); 1365 if (m == NULL) { 1366 m_freem(*m_head); 1367 *m_head = NULL; 1368 return (ENOMEM); --- 14 unchanged lines hidden (view full) --- 1383 return (EIO); 1384 } 1385 1386 KASSERT(nseg <= sc->maxtxseg, ("too many DMA segments")); 1387 bus_dmamap_sync(sc->fxp_mtag, txp->tx_map, BUS_DMASYNC_PREWRITE); 1388 1389 cbp = txp->tx_cb; 1390 for (i = 0; i < nseg; i++) { | 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++) { |
1391 KASSERT(segs[i].ds_len <= MCLBYTES, ("segment size too large")); | |
1392 /* 1393 * If this is an 82550/82551, then we're using extended 1394 * TxCBs _and_ we're using checksum offload. This means 1395 * that the TxCB is really an IPCB. One major difference 1396 * between the two is that with plain extended TxCBs, 1397 * the bottom half of the TxCB contains two entries from 1398 * the TBD array, whereas IPCBs contain just one entry: 1399 * one entry (8 bytes) has been sacrificed for the TCP/IP 1400 * checksum offload control bits. So to make things work 1401 * right, we have to start filling in the TBD array 1402 * starting from a different place depending on whether 1403 * the chip is an 82550/82551 or not. 1404 */ 1405 if (sc->flags & FXP_FLAG_EXT_RFA) { | 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) { |
1406 cbp->tbd[i + 1].tb_addr = htole32(segs[i].ds_addr); 1407 cbp->tbd[i + 1].tb_size = htole32(segs[i].ds_len); | 1481 cbp->tbd[i + 2].tb_addr = htole32(segs[i].ds_addr); 1482 cbp->tbd[i + 2].tb_size = htole32(segs[i].ds_len); |
1408 } else { 1409 cbp->tbd[i].tb_addr = htole32(segs[i].ds_addr); 1410 cbp->tbd[i].tb_size = htole32(segs[i].ds_len); 1411 } 1412 } | 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 } |
1413 cbp->tbd_number = nseg; | 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 } |
1414 1415 txp->tx_mbuf = m; 1416 txp->tx_cb->cb_status = 0; 1417 txp->tx_cb->byte_count = 0; 1418 if (sc->tx_queued != FXP_CXINT_THRESH - 1) 1419 txp->tx_cb->cb_command = 1420 htole16(sc->tx_cmd | FXP_CB_COMMAND_SF | 1421 FXP_CB_COMMAND_S); 1422 else 1423 txp->tx_cb->cb_command = 1424 htole16(sc->tx_cmd | FXP_CB_COMMAND_SF | 1425 FXP_CB_COMMAND_S | FXP_CB_COMMAND_I); | 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); |
1426 txp->tx_cb->tx_threshold = tx_threshold; | 1515 if ((m->m_pkthdr.csum_flags & CSUM_TSO) == 0) 1516 txp->tx_cb->tx_threshold = tx_threshold; |
1427 1428 /* 1429 * Advance the end of list forward. 1430 */ 1431 1432#ifdef __alpha__ 1433 /* 1434 * On platforms which can't access memory in 16-bit --- 657 unchanged lines hidden (view full) --- 2092 cbp->ci_int = 1; /* interrupt on CU idle */ 2093 cbp->ext_txcb_dis = sc->flags & FXP_FLAG_EXT_TXCB ? 0 : 1; 2094 cbp->ext_stats_dis = 1; /* disable extended counters */ 2095 cbp->keep_overrun_rx = 0; /* don't pass overrun frames to host */ 2096 cbp->save_bf = sc->flags & FXP_FLAG_SAVE_BAD ? 1 : prm; 2097 cbp->disc_short_rx = !prm; /* discard short packets */ 2098 cbp->underrun_retry = 1; /* retry mode (once) on DMA underrun */ 2099 cbp->two_frames = 0; /* do not limit FIFO to 2 frames */ | 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 */ |
2100 cbp->dyn_tbd = 0; /* (no) dynamic TBD mode */ | 2190 cbp->dyn_tbd = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; |
2101 cbp->ext_rfa = sc->flags & FXP_FLAG_EXT_RFA ? 1 : 0; 2102 cbp->mediatype = sc->flags & FXP_FLAG_SERIAL_MEDIA ? 0 : 1; 2103 cbp->csma_dis = 0; /* (don't) disable link */ 2104 cbp->tcp_udp_cksum = ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0 && 2105 (ifp->if_capenable & IFCAP_RXCSUM) != 0) ? 1 : 0; 2106 cbp->vlan_tco = 0; /* (don't) enable vlan wakeup */ 2107 cbp->link_wake_en = 0; /* (don't) assert PME# on link change */ 2108 cbp->arp_wake_en = 0; /* (don't) assert PME# on arp */ --- 475 unchanged lines hidden (view full) --- 2584 ifp->if_hwassist &= ~FXP_CSUM_FEATURES; 2585 } 2586 if ((mask & IFCAP_RXCSUM) != 0 && 2587 (ifp->if_capabilities & IFCAP_RXCSUM) != 0) { 2588 ifp->if_capenable ^= IFCAP_RXCSUM; 2589 if ((sc->flags & FXP_FLAG_82559_RXCSUM) != 0) 2590 reinit++; 2591 } | 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 } |
|
2592 if ((mask & IFCAP_VLAN_MTU) != 0 && 2593 (ifp->if_capabilities & IFCAP_VLAN_MTU) != 0) { 2594 ifp->if_capenable ^= IFCAP_VLAN_MTU; 2595 if (sc->revision != FXP_REV_82557) 2596 flag = FXP_FLAG_LONG_PKT_EN; 2597 else /* a hack to get long frames on the old chip */ 2598 flag = FXP_FLAG_SAVE_BAD; 2599 sc->flags ^= flag; --- 259 unchanged lines hidden --- | 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 --- |