Deleted Added
sdiff udiff text old ( 99058 ) new ( 102336 )
full compact
1/*
2 * Copyright (c) 1997, 1998, 1999
3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 15 unchanged lines hidden (view full) ---

24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * $FreeBSD: head/sys/dev/ti/if_ti.c 102336 2002-08-24 00:02:03Z alfred $
33 */
34
35/*
36 * Alteon Networks Tigon PCI gigabit ethernet driver for FreeBSD.
37 * Manuals, sample driver and firmware source kits are available
38 * from http://www.alteon.com/support/openkits.
39 *
40 * Written by Bill Paul <wpaul@ctr.columbia.edu>

--- 106 unchanged lines hidden (view full) ---

147 * BDs.
148 */
149#if defined(TI_JUMBO_HDRSPLIT) && defined(TI_PRIVATE_JUMBOS)
150#error "options TI_JUMBO_HDRSPLIT and TI_PRIVATE_JUMBOS are mutually exclusive"
151#endif /* TI_JUMBO_HDRSPLIT && TI_JUMBO_HDRSPLIT */
152
153#if !defined(lint)
154static const char rcsid[] =
155 "$FreeBSD: head/sys/dev/ti/if_ti.c 102336 2002-08-24 00:02:03Z alfred $";
156#endif
157
158struct ti_softc *tis[8];
159
160typedef enum {
161 TI_SWAP_HTON,
162 TI_SWAP_NTOH
163} ti_swap_type;

--- 261 unchanged lines hidden (view full) ---

425 *dest = byte;
426
427 return(0);
428}
429
430/*
431 * Read a sequence of bytes from the EEPROM.
432 */
433static int
434ti_read_eeprom(sc, dest, off, cnt)
435 struct ti_softc *sc;
436 caddr_t dest;
437 int off;
438 int cnt;
439{
440 int err = 0, i;
441 u_int8_t byte = 0;
442

--- 6 unchanged lines hidden (view full) ---

449
450 return(err ? 1 : 0);
451}
452
453/*
454 * NIC memory access function. Can be used to either clear a section
455 * of NIC local memory or (if buf is non-NULL) copy data into it.
456 */
457static void
458ti_mem(sc, addr, len, buf)
459 struct ti_softc *sc;
460 u_int32_t addr, len;
461 caddr_t buf;
462{
463 int segptr, segsize, cnt;
464 caddr_t ti_winbase, ptr;
465
466 segptr = addr;

--- 354 unchanged lines hidden (view full) ---

821 return(0);
822}
823
824/*
825 * Load firmware image into the NIC. Check that the firmware revision
826 * is acceptable and see if we want the firmware for the Tigon 1 or
827 * Tigon 2.
828 */
829static void
830ti_loadfw(sc)
831 struct ti_softc *sc;
832{
833 switch(sc->ti_hwrev) {
834 case TI_HWREV_TIGON:
835 if (tigonFwReleaseMajor != TI_FIRMWARE_MAJOR ||
836 tigonFwReleaseMinor != TI_FIRMWARE_MINOR ||
837 tigonFwReleaseFix != TI_FIRMWARE_FIX) {
838 printf("ti%d: firmware revision mismatch; want "

--- 41 unchanged lines hidden (view full) ---

880 }
881
882 return;
883}
884
885/*
886 * Send the NIC a command via the command ring.
887 */
888static void
889ti_cmd(sc, cmd)
890 struct ti_softc *sc;
891 struct ti_cmd_desc *cmd;
892{
893 u_int32_t index;
894
895 if (sc->ti_rdata->ti_cmd_ring == NULL)
896 return;
897

--- 5 unchanged lines hidden (view full) ---

903
904 return;
905}
906
907/*
908 * Send the NIC an extended command. The 'len' parameter specifies the
909 * number of command slots to include after the initial command.
910 */
911static void
912ti_cmd_ext(sc, cmd, arg, len)
913 struct ti_softc *sc;
914 struct ti_cmd_desc *cmd;
915 caddr_t arg;
916 int len;
917{
918 u_int32_t index;
919 register int i;
920

--- 12 unchanged lines hidden (view full) ---

933 sc->ti_cmd_saved_prodidx = index;
934
935 return;
936}
937
938/*
939 * Handle events that have triggered interrupts.
940 */
941static void
942ti_handle_events(sc)
943 struct ti_softc *sc;
944{
945 struct ti_event_desc *e;
946
947 if (sc->ti_rdata->ti_event_ring == NULL)
948 return;
949
950 while (sc->ti_ev_saved_considx != sc->ti_ev_prodidx.ti_idx) {

--- 59 unchanged lines hidden (view full) ---

1010 * 256 slots in it, but at 9K per slot than can consume over 2MB of
1011 * RAM. This is a bit much, especially considering we also need
1012 * RAM for the standard ring and mini ring (on the Tigon 2). To
1013 * save space, we only actually allocate enough memory for 64 slots
1014 * by default, which works out to between 500 and 600K. This can
1015 * be tuned by changing a #define in if_tireg.h.
1016 */
1017
1018static int
1019ti_alloc_jumbo_mem(sc)
1020 struct ti_softc *sc;
1021{
1022 caddr_t ptr;
1023 register int i;
1024 struct ti_jpool_entry *entry;
1025
1026 /* Grab a big chunk o' storage. */
1027 sc->ti_cdata.ti_jumbo_buf = contigmalloc(TI_JMEM, M_DEVBUF,

--- 50 unchanged lines hidden (view full) ---

1078 SLIST_REMOVE_HEAD(&sc->ti_jfree_listhead, jpool_entries);
1079 SLIST_INSERT_HEAD(&sc->ti_jinuse_listhead, entry, jpool_entries);
1080 return(sc->ti_cdata.ti_jslots[entry->slot]);
1081}
1082
1083/*
1084 * Release a jumbo buffer.
1085 */
1086static void
1087ti_jfree(buf, args)
1088 void *buf;
1089 void *args;
1090{
1091 struct ti_softc *sc;
1092 int i;
1093 struct ti_jpool_entry *entry;
1094
1095 /* Extract the softc struct pointer. */

--- 19 unchanged lines hidden (view full) ---

1115 return;
1116}
1117
1118#endif /* TI_PRIVATE_JUMBOS */
1119
1120/*
1121 * Intialize a standard receive ring descriptor.
1122 */
1123static int
1124ti_newbuf_std(sc, i, m)
1125 struct ti_softc *sc;
1126 int i;
1127 struct mbuf *m;
1128{
1129 struct mbuf *m_new = NULL;
1130 struct ti_rx_desc *r;
1131
1132 if (m == NULL) {

--- 26 unchanged lines hidden (view full) ---

1159
1160 return(0);
1161}
1162
1163/*
1164 * Intialize a mini receive ring descriptor. This only applies to
1165 * the Tigon 2.
1166 */
1167static int
1168ti_newbuf_mini(sc, i, m)
1169 struct ti_softc *sc;
1170 int i;
1171 struct mbuf *m;
1172{
1173 struct mbuf *m_new = NULL;
1174 struct ti_rx_desc *r;
1175
1176 if (m == NULL) {

--- 23 unchanged lines hidden (view full) ---

1200}
1201
1202#ifdef TI_PRIVATE_JUMBOS
1203
1204/*
1205 * Initialize a jumbo receive ring descriptor. This allocates
1206 * a jumbo buffer from the pool managed internally by the driver.
1207 */
1208static int
1209ti_newbuf_jumbo(sc, i, m)
1210 struct ti_softc *sc;
1211 int i;
1212 struct mbuf *m;
1213{
1214 struct mbuf *m_new = NULL;
1215 struct ti_rx_desc *r;
1216
1217 if (m == NULL) {

--- 188 unchanged lines hidden (view full) ---

1406
1407
1408/*
1409 * The standard receive ring has 512 entries in it. At 2K per mbuf cluster,
1410 * that's 1MB or memory, which is a lot. For now, we fill only the first
1411 * 256 ring entries and hope that our CPU is fast enough to keep up with
1412 * the NIC.
1413 */
1414static int
1415ti_init_rx_ring_std(sc)
1416 struct ti_softc *sc;
1417{
1418 register int i;
1419 struct ti_cmd_desc cmd;
1420
1421 for (i = 0; i < TI_SSLOTS; i++) {
1422 if (ti_newbuf_std(sc, i, NULL) == ENOBUFS)
1423 return(ENOBUFS);
1424 };
1425
1426 TI_UPDATE_STDPROD(sc, i - 1);
1427 sc->ti_std = i - 1;
1428
1429 return(0);
1430}
1431
1432static void
1433ti_free_rx_ring_std(sc)
1434 struct ti_softc *sc;
1435{
1436 register int i;
1437
1438 for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
1439 if (sc->ti_cdata.ti_rx_std_chain[i] != NULL) {
1440 m_freem(sc->ti_cdata.ti_rx_std_chain[i]);
1441 sc->ti_cdata.ti_rx_std_chain[i] = NULL;
1442 }
1443 bzero((char *)&sc->ti_rdata->ti_rx_std_ring[i],
1444 sizeof(struct ti_rx_desc));
1445 }
1446
1447 return;
1448}
1449
1450static int
1451ti_init_rx_ring_jumbo(sc)
1452 struct ti_softc *sc;
1453{
1454 register int i;
1455 struct ti_cmd_desc cmd;
1456
1457 for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
1458 if (ti_newbuf_jumbo(sc, i, NULL) == ENOBUFS)
1459 return(ENOBUFS);
1460 };
1461
1462 TI_UPDATE_JUMBOPROD(sc, i - 1);
1463 sc->ti_jumbo = i - 1;
1464
1465 return(0);
1466}
1467
1468static void
1469ti_free_rx_ring_jumbo(sc)
1470 struct ti_softc *sc;
1471{
1472 register int i;
1473
1474 for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
1475 if (sc->ti_cdata.ti_rx_jumbo_chain[i] != NULL) {
1476 m_freem(sc->ti_cdata.ti_rx_jumbo_chain[i]);
1477 sc->ti_cdata.ti_rx_jumbo_chain[i] = NULL;
1478 }
1479 bzero((char *)&sc->ti_rdata->ti_rx_jumbo_ring[i],
1480 sizeof(struct ti_rx_desc));
1481 }
1482
1483 return;
1484}
1485
1486static int
1487ti_init_rx_ring_mini(sc)
1488 struct ti_softc *sc;
1489{
1490 register int i;
1491
1492 for (i = 0; i < TI_MSLOTS; i++) {
1493 if (ti_newbuf_mini(sc, i, NULL) == ENOBUFS)
1494 return(ENOBUFS);
1495 };
1496
1497 TI_UPDATE_MINIPROD(sc, i - 1);
1498 sc->ti_mini = i - 1;
1499
1500 return(0);
1501}
1502
1503static void
1504ti_free_rx_ring_mini(sc)
1505 struct ti_softc *sc;
1506{
1507 register int i;
1508
1509 for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
1510 if (sc->ti_cdata.ti_rx_mini_chain[i] != NULL) {
1511 m_freem(sc->ti_cdata.ti_rx_mini_chain[i]);
1512 sc->ti_cdata.ti_rx_mini_chain[i] = NULL;
1513 }
1514 bzero((char *)&sc->ti_rdata->ti_rx_mini_ring[i],
1515 sizeof(struct ti_rx_desc));
1516 }
1517
1518 return;
1519}
1520
1521static void
1522ti_free_tx_ring(sc)
1523 struct ti_softc *sc;
1524{
1525 register int i;
1526
1527 if (sc->ti_rdata->ti_tx_ring == NULL)
1528 return;
1529
1530 for (i = 0; i < TI_TX_RING_CNT; i++) {
1531 if (sc->ti_cdata.ti_tx_chain[i] != NULL) {
1532 m_freem(sc->ti_cdata.ti_tx_chain[i]);
1533 sc->ti_cdata.ti_tx_chain[i] = NULL;
1534 }
1535 bzero((char *)&sc->ti_rdata->ti_tx_ring[i],
1536 sizeof(struct ti_tx_desc));
1537 }
1538
1539 return;
1540}
1541
1542static int
1543ti_init_tx_ring(sc)
1544 struct ti_softc *sc;
1545{
1546 sc->ti_txcnt = 0;
1547 sc->ti_tx_saved_considx = 0;
1548 CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, 0);
1549 return(0);
1550}
1551
1552/*
1553 * The Tigon 2 firmware has a new way to add/delete multicast addresses,
1554 * but we have to support the old way too so that Tigon 1 cards will
1555 * work.
1556 */
1557void
1558ti_add_mcast(sc, addr)
1559 struct ti_softc *sc;
1560 struct ether_addr *addr;
1561{
1562 struct ti_cmd_desc cmd;
1563 u_int16_t *m;
1564 u_int32_t ext[2] = {0, 0};
1565
1566 m = (u_int16_t *)&addr->octet[0];

--- 12 unchanged lines hidden (view full) ---

1579 default:
1580 printf("ti%d: unknown hwrev\n", sc->ti_unit);
1581 break;
1582 }
1583
1584 return;
1585}
1586
1587void
1588ti_del_mcast(sc, addr)
1589 struct ti_softc *sc;
1590 struct ether_addr *addr;
1591{
1592 struct ti_cmd_desc cmd;
1593 u_int16_t *m;
1594 u_int32_t ext[2] = {0, 0};
1595
1596 m = (u_int16_t *)&addr->octet[0];

--- 26 unchanged lines hidden (view full) ---

1623 * changes and at that point we only have the current list of addresses:
1624 * we only know the current state, not the previous state, so we don't
1625 * actually know what addresses were removed or added. The firmware has
1626 * state, but we can't get our grubby mits on it, and there is no 'delete
1627 * all multicast addresses' command. Hence, we have to maintain our own
1628 * state so we know what addresses have been programmed into the NIC at
1629 * any given time.
1630 */
1631static void
1632ti_setmulti(sc)
1633 struct ti_softc *sc;
1634{
1635 struct ifnet *ifp;
1636 struct ifmultiaddr *ifma;
1637 struct ti_cmd_desc cmd;
1638 struct ti_mc_entry *mc;
1639 u_int32_t intrs;
1640

--- 61 unchanged lines hidden (view full) ---

1702
1703 return(0);
1704}
1705
1706/*
1707 * Do endian, PCI and DMA initialization. Also check the on-board ROM
1708 * self-test results.
1709 */
1710static int
1711ti_chipinit(sc)
1712 struct ti_softc *sc;
1713{
1714 u_int32_t cacheline;
1715 u_int32_t pci_writemax = 0;
1716 u_int32_t hdrsplit;
1717
1718 /* Initialize link to down state. */
1719 sc->ti_linkstat = TI_EV_CODE_LINK_DOWN;

--- 147 unchanged lines hidden (view full) ---

1867
1868 return(0);
1869}
1870
1871/*
1872 * Initialize the general information block and firmware, and
1873 * start the CPU(s) running.
1874 */
1875static int
1876ti_gibinit(sc)
1877 struct ti_softc *sc;
1878{
1879 struct ti_rcb *rcb;
1880 int i;
1881 struct ifnet *ifp;
1882
1883 ifp = &sc->arpcom.ac_if;
1884

--- 156 unchanged lines hidden (view full) ---

2041
2042 return(0);
2043}
2044
2045/*
2046 * Probe for a Tigon chip. Check the PCI vendor and device IDs
2047 * against our list and return its name if we find a match.
2048 */
2049static int
2050ti_probe(dev)
2051 device_t dev;
2052{
2053 struct ti_type *t;
2054
2055 t = ti_devs;
2056
2057 while(t->ti_name != NULL) {
2058 if ((pci_get_vendor(dev) == t->ti_vid) &&

--- 34 unchanged lines hidden (view full) ---

2093 (int)mbstat.m_msize);
2094 return(EINVAL);
2095 }
2096 return(0);
2097}
2098#endif
2099
2100
2101static int
2102ti_attach(dev)
2103 device_t dev;
2104{
2105 u_int32_t command;
2106 struct ifnet *ifp;
2107 struct ti_softc *sc;
2108 int unit, error = 0, rid;
2109
2110 sc = NULL;

--- 286 unchanged lines hidden (view full) ---

2397 }
2398 /* now we know that there's a vnode in the cache. We hunt it
2399 down and kill it now, before unloading */
2400 vgone(ti_vn);
2401 return(0);
2402}
2403
2404
2405static int
2406ti_detach(dev)
2407 device_t dev;
2408{
2409 struct ti_softc *sc;
2410 struct ifnet *ifp;
2411
2412 if (ti_unref_special(dev))
2413 return EBUSY;
2414

--- 83 unchanged lines hidden (view full) ---

2498 *
2499 * Note: we have to be able to handle three possibilities here:
2500 * 1) the frame is from the mini receive ring (can only happen)
2501 * on Tigon 2 boards)
2502 * 2) the frame is from the jumbo recieve ring
2503 * 3) the frame is from the standard receive ring
2504 */
2505
2506static void
2507ti_rxeof(sc)
2508 struct ti_softc *sc;
2509{
2510 struct ifnet *ifp;
2511 struct ti_cmd_desc cmd;
2512
2513 ifp = &sc->arpcom.ac_if;
2514
2515 while(sc->ti_rx_saved_considx != sc->ti_return_prodidx.ti_idx) {

--- 107 unchanged lines hidden (view full) ---

2623
2624 TI_UPDATE_STDPROD(sc, sc->ti_std);
2625 TI_UPDATE_MINIPROD(sc, sc->ti_mini);
2626 TI_UPDATE_JUMBOPROD(sc, sc->ti_jumbo);
2627
2628 return;
2629}
2630
2631static void
2632ti_txeof(sc)
2633 struct ti_softc *sc;
2634{
2635 struct ti_tx_desc *cur_tx = NULL;
2636 struct ifnet *ifp;
2637
2638 ifp = &sc->arpcom.ac_if;
2639
2640 /*

--- 32 unchanged lines hidden (view full) ---

2673 }
2674
2675 if (cur_tx != NULL)
2676 ifp->if_flags &= ~IFF_OACTIVE;
2677
2678 return;
2679}
2680
2681static void
2682ti_intr(xsc)
2683 void *xsc;
2684{
2685 struct ti_softc *sc;
2686 struct ifnet *ifp;
2687
2688 sc = xsc;
2689 TI_LOCK(sc);
2690 ifp = &sc->arpcom.ac_if;

--- 26 unchanged lines hidden (view full) ---

2717 if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
2718 ti_start(ifp);
2719
2720 TI_UNLOCK(sc);
2721
2722 return;
2723}
2724
2725static void
2726ti_stats_update(sc)
2727 struct ti_softc *sc;
2728{
2729 struct ifnet *ifp;
2730
2731 ifp = &sc->arpcom.ac_if;
2732
2733 ifp->if_collisions +=
2734 (sc->ti_rdata->ti_info.ti_stats.dot3StatsSingleCollisionFrames +

--- 4 unchanged lines hidden (view full) ---

2739
2740 return;
2741}
2742
2743/*
2744 * Encapsulate an mbuf chain in the tx ring by coupling the mbuf data
2745 * pointers to descriptors.
2746 */
2747static int
2748ti_encap(sc, m_head, txidx)
2749 struct ti_softc *sc;
2750 struct mbuf *m_head;
2751 u_int32_t *txidx;
2752{
2753 struct ti_tx_desc *f = NULL;
2754 struct mbuf *m;
2755 u_int32_t frag, cur, cnt = 0;
2756 u_int16_t csum_flags = 0;

--- 83 unchanged lines hidden (view full) ---

2840
2841 return(0);
2842}
2843
2844/*
2845 * Main transmit routine. To avoid having to do mbuf copies, we put pointers
2846 * to the mbuf data regions directly in the transmit descriptors.
2847 */
2848static void
2849ti_start(ifp)
2850 struct ifnet *ifp;
2851{
2852 struct ti_softc *sc;
2853 struct mbuf *m_head = NULL;
2854 u_int32_t prodidx = 0;
2855
2856 sc = ifp->if_softc;
2857 TI_LOCK(sc);

--- 49 unchanged lines hidden (view full) ---

2907 * Set a timeout in case the chip goes out to lunch.
2908 */
2909 ifp->if_timer = 5;
2910 TI_UNLOCK(sc);
2911
2912 return;
2913}
2914
2915static void
2916ti_init(xsc)
2917 void *xsc;
2918{
2919 struct ti_softc *sc = xsc;
2920
2921 /* Cancel pending I/O and flush buffers. */
2922 ti_stop(sc);
2923
2924 TI_LOCK(sc);

--- 92 unchanged lines hidden (view full) ---

3017 ifm->ifm_media = tmp;
3018
3019 return;
3020}
3021
3022/*
3023 * Set media options.
3024 */
3025static int
3026ti_ifmedia_upd(ifp)
3027 struct ifnet *ifp;
3028{
3029 struct ti_softc *sc;
3030 struct ifmedia *ifm;
3031 struct ti_cmd_desc cmd;
3032 u_int32_t flowctl;
3033
3034 sc = ifp->if_softc;

--- 84 unchanged lines hidden (view full) ---

3119 }
3120
3121 return(0);
3122}
3123
3124/*
3125 * Report current media status.
3126 */
3127static void
3128ti_ifmedia_sts(ifp, ifmr)
3129 struct ifnet *ifp;
3130 struct ifmediareq *ifmr;
3131{
3132 struct ti_softc *sc;
3133 u_int32_t media = 0;
3134
3135 sc = ifp->if_softc;
3136

--- 32 unchanged lines hidden (view full) ---

3169 ifmr->ifm_active |= IFM_FDX;
3170 if (media & TI_LNK_HALF_DUPLEX)
3171 ifmr->ifm_active |= IFM_HDX;
3172 }
3173
3174 return;
3175}
3176
3177static int
3178ti_ioctl(ifp, command, data)
3179 struct ifnet *ifp;
3180 u_long command;
3181 caddr_t data;
3182{
3183 struct ti_softc *sc = ifp->if_softc;
3184 struct ifreq *ifr = (struct ifreq *) data;
3185 int mask, error = 0;
3186 struct ti_cmd_desc cmd;

--- 378 unchanged lines hidden (view full) ---

3565 }
3566 default:
3567 error = ENOTTY;
3568 break;
3569 }
3570 return(error);
3571}
3572
3573static void
3574ti_watchdog(ifp)
3575 struct ifnet *ifp;
3576{
3577 struct ti_softc *sc;
3578
3579 sc = ifp->if_softc;
3580 TI_LOCK(sc);
3581
3582 /*

--- 15 unchanged lines hidden (view full) ---

3598
3599 return;
3600}
3601
3602/*
3603 * Stop the adapter and free any mbufs allocated to the
3604 * RX and TX lists.
3605 */
3606static void
3607ti_stop(sc)
3608 struct ti_softc *sc;
3609{
3610 struct ifnet *ifp;
3611 struct ti_cmd_desc cmd;
3612
3613 TI_LOCK(sc);
3614
3615 ifp = &sc->arpcom.ac_if;

--- 32 unchanged lines hidden (view full) ---

3648
3649 return;
3650}
3651
3652/*
3653 * Stop all chip I/O so that the kernel's probe routines don't
3654 * get confused by errant DMAs when rebooting.
3655 */
3656static void
3657ti_shutdown(dev)
3658 device_t dev;
3659{
3660 struct ti_softc *sc;
3661
3662 sc = device_get_softc(dev);
3663 TI_LOCK(sc);
3664 ti_chipinit(sc);
3665 TI_UNLOCK(sc);
3666
3667 return;
3668}