Deleted Added
full compact
if_bge.c (136686) if_bge.c (137073)
1/*
2 * Copyright (c) 2001 Wind River Systems
3 * Copyright (c) 1997, 1998, 1999, 2001
4 * Bill Paul <wpaul@windriver.com>. 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:

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

27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
1/*
2 * Copyright (c) 2001 Wind River Systems
3 * Copyright (c) 1997, 1998, 1999, 2001
4 * Bill Paul <wpaul@windriver.com>. 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:

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

27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__FBSDID("$FreeBSD: head/sys/dev/bge/if_bge.c 136686 2004-10-19 02:42:49Z scottl $");
35__FBSDID("$FreeBSD: head/sys/dev/bge/if_bge.c 137073 2004-10-30 14:54:51Z des $");
36
37/*
38 * Broadcom BCM570x family gigabit ethernet driver for FreeBSD.
39 *
40 * The Broadcom BCM5700 is based on technology originally developed by
41 * Alteon Networks as part of the Tigon I and Tigon II gigabit ethernet
42 * MAC chips. The BCM5700, sometimes refered to as the Tigon III, has
43 * two on-board MIPS R4000 CPUs and can have as much as 16MB of external
44 * SSRAM. The BCM5700 supports TCP, UDP and IP checksum offload, jumbo
45 * frames, highly configurable RX filtering, and 16 RX and TX queues
46 * (which, along with RX filter rules, can be used for QOS applications).
47 * Other features, such as TCP segmentation, may be available as part
48 * of value-added firmware updates. Unlike the Tigon I and Tigon II,
49 * firmware images can be stored in hardware and need not be compiled
50 * into the driver.
51 *
52 * The BCM5700 supports the PCI v2.2 and PCI-X v1.0 standards, and will
53 * function in a 32-bit/64-bit 33/66Mhz bus, or a 64-bit/133Mhz bus.
36
37/*
38 * Broadcom BCM570x family gigabit ethernet driver for FreeBSD.
39 *
40 * The Broadcom BCM5700 is based on technology originally developed by
41 * Alteon Networks as part of the Tigon I and Tigon II gigabit ethernet
42 * MAC chips. The BCM5700, sometimes refered to as the Tigon III, has
43 * two on-board MIPS R4000 CPUs and can have as much as 16MB of external
44 * SSRAM. The BCM5700 supports TCP, UDP and IP checksum offload, jumbo
45 * frames, highly configurable RX filtering, and 16 RX and TX queues
46 * (which, along with RX filter rules, can be used for QOS applications).
47 * Other features, such as TCP segmentation, may be available as part
48 * of value-added firmware updates. Unlike the Tigon I and Tigon II,
49 * firmware images can be stored in hardware and need not be compiled
50 * into the driver.
51 *
52 * The BCM5700 supports the PCI v2.2 and PCI-X v1.0 standards, and will
53 * function in a 32-bit/64-bit 33/66Mhz bus, or a 64-bit/133Mhz bus.
54 *
54 *
55 * The BCM5701 is a single-chip solution incorporating both the BCM5700
56 * MAC and a BCM5401 10/100/1000 PHY. Unlike the BCM5700, the BCM5701
57 * does not support external SSRAM.
58 *
59 * Broadcom also produces a variation of the BCM5700 under the "Altima"
60 * brand name, which is functionally similar but lacks PCI-X support.
61 *
62 * Without external SSRAM, you can only have at most 4 TX rings,

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

404 while(1) {
405 d = &ctx->bge_ring[idx];
406 d->bge_addr.bge_addr_lo =
407 htole32(BGE_ADDR_LO(segs[i].ds_addr));
408 d->bge_addr.bge_addr_hi =
409 htole32(BGE_ADDR_HI(segs[i].ds_addr));
410 d->bge_len = htole16(segs[i].ds_len);
411 d->bge_flags = htole16(ctx->bge_flags);
55 * The BCM5701 is a single-chip solution incorporating both the BCM5700
56 * MAC and a BCM5401 10/100/1000 PHY. Unlike the BCM5700, the BCM5701
57 * does not support external SSRAM.
58 *
59 * Broadcom also produces a variation of the BCM5700 under the "Altima"
60 * brand name, which is functionally similar but lacks PCI-X support.
61 *
62 * Without external SSRAM, you can only have at most 4 TX rings,

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

404 while(1) {
405 d = &ctx->bge_ring[idx];
406 d->bge_addr.bge_addr_lo =
407 htole32(BGE_ADDR_LO(segs[i].ds_addr));
408 d->bge_addr.bge_addr_hi =
409 htole32(BGE_ADDR_HI(segs[i].ds_addr));
410 d->bge_len = htole16(segs[i].ds_len);
411 d->bge_flags = htole16(ctx->bge_flags);
412 i++;
412 i++;
413 if (i == nseg)
414 break;
415 BGE_INC(idx, BGE_TX_RING_CNT);
416 }
417
418 d->bge_flags |= htole16(BGE_TXBDFLAG_END);
419 ctx->bge_maxsegs = nseg;
420 ctx->bge_idx = idx;

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

481 sc->bge_vpd_prodname = NULL;
482 sc->bge_vpd_readonly = NULL;
483
484 bge_vpd_read_res(sc, &res, pos);
485
486 if (res.vr_id != VPD_RES_ID) {
487 printf("bge%d: bad VPD resource id: expected %x got %x\n",
488 sc->bge_unit, VPD_RES_ID, res.vr_id);
413 if (i == nseg)
414 break;
415 BGE_INC(idx, BGE_TX_RING_CNT);
416 }
417
418 d->bge_flags |= htole16(BGE_TXBDFLAG_END);
419 ctx->bge_maxsegs = nseg;
420 ctx->bge_idx = idx;

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

481 sc->bge_vpd_prodname = NULL;
482 sc->bge_vpd_readonly = NULL;
483
484 bge_vpd_read_res(sc, &res, pos);
485
486 if (res.vr_id != VPD_RES_ID) {
487 printf("bge%d: bad VPD resource id: expected %x got %x\n",
488 sc->bge_unit, VPD_RES_ID, res.vr_id);
489 return;
490 }
489 return;
490 }
491
492 pos += sizeof(res);
493 sc->bge_vpd_prodname = malloc(res.vr_len + 1, M_DEVBUF, M_NOWAIT);
494 for (i = 0; i < res.vr_len; i++)
495 sc->bge_vpd_prodname[i] = bge_vpd_readbyte(sc, i + pos);
496 sc->bge_vpd_prodname[i] = '\0';
497 pos += i;
498

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

552 if (i == BGE_TIMEOUT) {
553 printf("bge%d: eeprom read timed out\n", sc->bge_unit);
554 return(0);
555 }
556
557 /* Get result. */
558 byte = CSR_READ_4(sc, BGE_EE_DATA);
559
491
492 pos += sizeof(res);
493 sc->bge_vpd_prodname = malloc(res.vr_len + 1, M_DEVBUF, M_NOWAIT);
494 for (i = 0; i < res.vr_len; i++)
495 sc->bge_vpd_prodname[i] = bge_vpd_readbyte(sc, i + pos);
496 sc->bge_vpd_prodname[i] = '\0';
497 pos += i;
498

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

552 if (i == BGE_TIMEOUT) {
553 printf("bge%d: eeprom read timed out\n", sc->bge_unit);
554 return(0);
555 }
556
557 /* Get result. */
558 byte = CSR_READ_4(sc, BGE_EE_DATA);
559
560 *dest = (byte >> ((addr % 4) * 8)) & 0xFF;
560 *dest = (byte >> ((addr % 4) * 8)) & 0xFF;
561
562 return(0);
563}
564
565/*
566 * Read a sequence of bytes from the EEPROM.
567 */
568static int

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

747
748 /* Allocate DMA'able memory for jumbo buffer block */
749
750 error = bus_dmamem_alloc(sc->bge_cdata.bge_jumbo_tag,
751 (void **)&sc->bge_ldata.bge_jumbo_buf, BUS_DMA_NOWAIT,
752 &sc->bge_cdata.bge_jumbo_map);
753
754 if (error)
561
562 return(0);
563}
564
565/*
566 * Read a sequence of bytes from the EEPROM.
567 */
568static int

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

747
748 /* Allocate DMA'able memory for jumbo buffer block */
749
750 error = bus_dmamem_alloc(sc->bge_cdata.bge_jumbo_tag,
751 (void **)&sc->bge_ldata.bge_jumbo_buf, BUS_DMA_NOWAIT,
752 &sc->bge_cdata.bge_jumbo_map);
753
754 if (error)
755 return (ENOMEM);
755 return (ENOMEM);
756
757 SLIST_INIT(&sc->bge_jfree_listhead);
758 SLIST_INIT(&sc->bge_jinuse_listhead);
759
760 /*
761 * Now divide it up into 9K pieces and save the addresses
762 * in an array.
763 */
764 ptr = sc->bge_ldata.bge_jumbo_buf;
765 for (i = 0; i < BGE_JSLOTS; i++) {
766 sc->bge_cdata.bge_jslots[i] = ptr;
767 ptr += BGE_JLEN;
756
757 SLIST_INIT(&sc->bge_jfree_listhead);
758 SLIST_INIT(&sc->bge_jinuse_listhead);
759
760 /*
761 * Now divide it up into 9K pieces and save the addresses
762 * in an array.
763 */
764 ptr = sc->bge_ldata.bge_jumbo_buf;
765 for (i = 0; i < BGE_JSLOTS; i++) {
766 sc->bge_cdata.bge_jslots[i] = ptr;
767 ptr += BGE_JLEN;
768 entry = malloc(sizeof(struct bge_jpool_entry),
768 entry = malloc(sizeof(struct bge_jpool_entry),
769 M_DEVBUF, M_NOWAIT);
770 if (entry == NULL) {
771 bge_free_jumbo_mem(sc);
772 sc->bge_ldata.bge_jumbo_buf = NULL;
773 printf("bge%d: no memory for jumbo "
774 "buffer queue!\n", sc->bge_unit);
775 return(ENOBUFS);
776 }
777 entry->slot = i;
778 SLIST_INSERT_HEAD(&sc->bge_jfree_listhead,
779 entry, jpool_entries);
780 }
781
782 return(0);
783}
784
785static void
786bge_free_jumbo_mem(sc)
769 M_DEVBUF, M_NOWAIT);
770 if (entry == NULL) {
771 bge_free_jumbo_mem(sc);
772 sc->bge_ldata.bge_jumbo_buf = NULL;
773 printf("bge%d: no memory for jumbo "
774 "buffer queue!\n", sc->bge_unit);
775 return(ENOBUFS);
776 }
777 entry->slot = i;
778 SLIST_INSERT_HEAD(&sc->bge_jfree_listhead,
779 entry, jpool_entries);
780 }
781
782 return(0);
783}
784
785static void
786bge_free_jumbo_mem(sc)
787 struct bge_softc *sc;
787 struct bge_softc *sc;
788{
788{
789 int i;
790 struct bge_jpool_entry *entry;
791
789 int i;
790 struct bge_jpool_entry *entry;
791
792 for (i = 0; i < BGE_JSLOTS; i++) {
793 entry = SLIST_FIRST(&sc->bge_jfree_listhead);
794 SLIST_REMOVE_HEAD(&sc->bge_jfree_listhead, jpool_entries);
795 free(entry, M_DEVBUF);
796 }
797
798 /* Destroy jumbo buffer block */
799

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

804
805 if (sc->bge_cdata.bge_rx_jumbo_ring_map)
806 bus_dmamap_destroy(sc->bge_cdata.bge_jumbo_tag,
807 sc->bge_cdata.bge_jumbo_map);
808
809 if (sc->bge_cdata.bge_jumbo_tag)
810 bus_dma_tag_destroy(sc->bge_cdata.bge_jumbo_tag);
811
792 for (i = 0; i < BGE_JSLOTS; i++) {
793 entry = SLIST_FIRST(&sc->bge_jfree_listhead);
794 SLIST_REMOVE_HEAD(&sc->bge_jfree_listhead, jpool_entries);
795 free(entry, M_DEVBUF);
796 }
797
798 /* Destroy jumbo buffer block */
799

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

804
805 if (sc->bge_cdata.bge_rx_jumbo_ring_map)
806 bus_dmamap_destroy(sc->bge_cdata.bge_jumbo_tag,
807 sc->bge_cdata.bge_jumbo_map);
808
809 if (sc->bge_cdata.bge_jumbo_tag)
810 bus_dma_tag_destroy(sc->bge_cdata.bge_jumbo_tag);
811
812 return;
812 return;
813}
814
815/*
816 * Allocate a jumbo buffer.
817 */
818static void *
819bge_jalloc(sc)
820 struct bge_softc *sc;
821{
822 struct bge_jpool_entry *entry;
813}
814
815/*
816 * Allocate a jumbo buffer.
817 */
818static void *
819bge_jalloc(sc)
820 struct bge_softc *sc;
821{
822 struct bge_jpool_entry *entry;
823
823
824 entry = SLIST_FIRST(&sc->bge_jfree_listhead);
824 entry = SLIST_FIRST(&sc->bge_jfree_listhead);
825
825
826 if (entry == NULL) {
827 printf("bge%d: no free jumbo buffers\n", sc->bge_unit);
828 return(NULL);
829 }
830
831 SLIST_REMOVE_HEAD(&sc->bge_jfree_listhead, jpool_entries);
832 SLIST_INSERT_HEAD(&sc->bge_jinuse_listhead, entry, jpool_entries);
833 return(sc->bge_cdata.bge_jslots[entry->slot]);

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

1282 * Disable memory write invalidate. Apparently it is not supported
1283 * properly by these devices.
1284 */
1285 PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD, PCIM_CMD_MWIEN, 4);
1286
1287#ifdef __brokenalpha__
1288 /*
1289 * Must insure that we do not cross an 8K (bytes) boundary
826 if (entry == NULL) {
827 printf("bge%d: no free jumbo buffers\n", sc->bge_unit);
828 return(NULL);
829 }
830
831 SLIST_REMOVE_HEAD(&sc->bge_jfree_listhead, jpool_entries);
832 SLIST_INSERT_HEAD(&sc->bge_jinuse_listhead, entry, jpool_entries);
833 return(sc->bge_cdata.bge_jslots[entry->slot]);

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

1282 * Disable memory write invalidate. Apparently it is not supported
1283 * properly by these devices.
1284 */
1285 PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD, PCIM_CMD_MWIEN, 4);
1286
1287#ifdef __brokenalpha__
1288 /*
1289 * Must insure that we do not cross an 8K (bytes) boundary
1290 * for DMA reads. Our highest limit is 1K bytes. This is a
1291 * restriction on some ALPHA platforms with early revision
1292 * 21174 PCI chipsets, such as the AlphaPC 164lx
1290 * for DMA reads. Our highest limit is 1K bytes. This is a
1291 * restriction on some ALPHA platforms with early revision
1292 * 21174 PCI chipsets, such as the AlphaPC 164lx
1293 */
1294 PCI_SETBIT(sc->bge_dev, BGE_PCI_DMA_RW_CTL,
1295 BGE_PCI_READ_BNDRY_1024BYTES, 4);
1296#endif
1297
1298 /* Set the timer prescaler (always 66Mhz) */
1299 CSR_WRITE_4(sc, BGE_MISC_CFG, 65 << 1/*BGE_32BITTIME_66MHZ*/);
1300

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

1648 /* Turn on DMA completion state machine */
1649 if (sc->bge_asicrev != BGE_ASICREV_BCM5705 &&
1650 sc->bge_asicrev != BGE_ASICREV_BCM5750)
1651 CSR_WRITE_4(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE);
1652
1653 /* Turn on write DMA state machine */
1654 CSR_WRITE_4(sc, BGE_WDMA_MODE,
1655 BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS);
1293 */
1294 PCI_SETBIT(sc->bge_dev, BGE_PCI_DMA_RW_CTL,
1295 BGE_PCI_READ_BNDRY_1024BYTES, 4);
1296#endif
1297
1298 /* Set the timer prescaler (always 66Mhz) */
1299 CSR_WRITE_4(sc, BGE_MISC_CFG, 65 << 1/*BGE_32BITTIME_66MHZ*/);
1300

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

1648 /* Turn on DMA completion state machine */
1649 if (sc->bge_asicrev != BGE_ASICREV_BCM5705 &&
1650 sc->bge_asicrev != BGE_ASICREV_BCM5750)
1651 CSR_WRITE_4(sc, BGE_DMAC_MODE, BGE_DMACMODE_ENABLE);
1652
1653 /* Turn on write DMA state machine */
1654 CSR_WRITE_4(sc, BGE_WDMA_MODE,
1655 BGE_WDMAMODE_ENABLE|BGE_WDMAMODE_ALL_ATTNS);
1656
1656
1657 /* Turn on read DMA state machine */
1658 CSR_WRITE_4(sc, BGE_RDMA_MODE,
1659 BGE_RDMAMODE_ENABLE|BGE_RDMAMODE_ALL_ATTNS);
1660
1661 /* Turn on RX data completion state machine */
1662 CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
1663
1664 /* Turn on RX BD initiator state machine */

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

1695 CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED|
1696 BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE|
1697 BGE_MACSTAT_LINK_CHANGED);
1698 CSR_WRITE_4(sc, BGE_MI_STS, 0);
1699
1700 /* Enable PHY auto polling (for MII/GMII only) */
1701 if (sc->bge_tbi) {
1702 CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK);
1657 /* Turn on read DMA state machine */
1658 CSR_WRITE_4(sc, BGE_RDMA_MODE,
1659 BGE_RDMAMODE_ENABLE|BGE_RDMAMODE_ALL_ATTNS);
1660
1661 /* Turn on RX data completion state machine */
1662 CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
1663
1664 /* Turn on RX BD initiator state machine */

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

1695 CSR_WRITE_4(sc, BGE_MAC_STS, BGE_MACSTAT_SYNC_CHANGED|
1696 BGE_MACSTAT_CFG_CHANGED|BGE_MACSTAT_MI_COMPLETE|
1697 BGE_MACSTAT_LINK_CHANGED);
1698 CSR_WRITE_4(sc, BGE_MI_STS, 0);
1699
1700 /* Enable PHY auto polling (for MII/GMII only) */
1701 if (sc->bge_tbi) {
1702 CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK);
1703 } else {
1703 } else {
1704 BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL|10<<16);
1705 if (sc->bge_asicrev == BGE_ASICREV_BCM5700)
1706 CSR_WRITE_4(sc, BGE_MAC_EVT_ENB,
1707 BGE_EVTENB_MI_INTERRUPT);
1708 }
1709
1710 /* Enable link state change attentions. */
1711 BGE_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED);

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

1922#define BGE_NSEG_NEW 32
1923 error = bus_dma_tag_create(NULL, /* parent */
1924 PAGE_SIZE, 0, /* alignment, boundary */
1925 BUS_SPACE_MAXADDR, /* lowaddr */
1926 BUS_SPACE_MAXADDR_32BIT,/* highaddr */
1927 NULL, NULL, /* filter, filterarg */
1928 MAXBSIZE, BGE_NSEG_NEW, /* maxsize, nsegments */
1929 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
1704 BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL|10<<16);
1705 if (sc->bge_asicrev == BGE_ASICREV_BCM5700)
1706 CSR_WRITE_4(sc, BGE_MAC_EVT_ENB,
1707 BGE_EVTENB_MI_INTERRUPT);
1708 }
1709
1710 /* Enable link state change attentions. */
1711 BGE_SETBIT(sc, BGE_MAC_EVT_ENB, BGE_EVTENB_LINK_CHANGED);

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

1922#define BGE_NSEG_NEW 32
1923 error = bus_dma_tag_create(NULL, /* parent */
1924 PAGE_SIZE, 0, /* alignment, boundary */
1925 BUS_SPACE_MAXADDR, /* lowaddr */
1926 BUS_SPACE_MAXADDR_32BIT,/* highaddr */
1927 NULL, NULL, /* filter, filterarg */
1928 MAXBSIZE, BGE_NSEG_NEW, /* maxsize, nsegments */
1929 BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
1930 BUS_DMA_ALLOCNOW, /* flags */
1930 BUS_DMA_ALLOCNOW, /* flags */
1931 NULL, NULL, /* lockfunc, lockarg */
1932 &sc->bge_cdata.bge_parent_tag);
1933
1934 /*
1935 * Create tag for RX mbufs.
1936 */
1937 nseg = 32;
1938 error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag, 1,

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

1979 return (ENOMEM);
1980 }
1981
1982 /* Allocate DMA'able memory for standard RX ring */
1983
1984 error = bus_dmamem_alloc(sc->bge_cdata.bge_rx_std_ring_tag,
1985 (void **)&sc->bge_ldata.bge_rx_std_ring, BUS_DMA_NOWAIT,
1986 &sc->bge_cdata.bge_rx_std_ring_map);
1931 NULL, NULL, /* lockfunc, lockarg */
1932 &sc->bge_cdata.bge_parent_tag);
1933
1934 /*
1935 * Create tag for RX mbufs.
1936 */
1937 nseg = 32;
1938 error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag, 1,

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

1979 return (ENOMEM);
1980 }
1981
1982 /* Allocate DMA'able memory for standard RX ring */
1983
1984 error = bus_dmamem_alloc(sc->bge_cdata.bge_rx_std_ring_tag,
1985 (void **)&sc->bge_ldata.bge_rx_std_ring, BUS_DMA_NOWAIT,
1986 &sc->bge_cdata.bge_rx_std_ring_map);
1987 if (error)
1988 return (ENOMEM);
1987 if (error)
1988 return (ENOMEM);
1989
1989
1990 bzero((char *)sc->bge_ldata.bge_rx_std_ring, BGE_STD_RX_RING_SZ);
1990 bzero((char *)sc->bge_ldata.bge_rx_std_ring, BGE_STD_RX_RING_SZ);
1991
1992 /* Load the address of the standard RX ring */
1993
1994 ctx.bge_maxsegs = 1;
1995 ctx.sc = sc;
1996
1997 error = bus_dmamap_load(sc->bge_cdata.bge_rx_std_ring_tag,
1998 sc->bge_cdata.bge_rx_std_ring_map, sc->bge_ldata.bge_rx_std_ring,

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

2097 return (ENOMEM);
2098 }
2099
2100 /* Allocate DMA'able memory for RX return ring */
2101
2102 error = bus_dmamem_alloc(sc->bge_cdata.bge_rx_return_ring_tag,
2103 (void **)&sc->bge_ldata.bge_rx_return_ring, BUS_DMA_NOWAIT,
2104 &sc->bge_cdata.bge_rx_return_ring_map);
1991
1992 /* Load the address of the standard RX ring */
1993
1994 ctx.bge_maxsegs = 1;
1995 ctx.sc = sc;
1996
1997 error = bus_dmamap_load(sc->bge_cdata.bge_rx_std_ring_tag,
1998 sc->bge_cdata.bge_rx_std_ring_map, sc->bge_ldata.bge_rx_std_ring,

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

2097 return (ENOMEM);
2098 }
2099
2100 /* Allocate DMA'able memory for RX return ring */
2101
2102 error = bus_dmamem_alloc(sc->bge_cdata.bge_rx_return_ring_tag,
2103 (void **)&sc->bge_ldata.bge_rx_return_ring, BUS_DMA_NOWAIT,
2104 &sc->bge_cdata.bge_rx_return_ring_map);
2105 if (error)
2106 return (ENOMEM);
2105 if (error)
2106 return (ENOMEM);
2107
2107
2108 bzero((char *)sc->bge_ldata.bge_rx_return_ring,
2108 bzero((char *)sc->bge_ldata.bge_rx_return_ring,
2109 BGE_RX_RTN_RING_SZ(sc));
2110
2111 /* Load the address of the RX return ring */
2112
2113 ctx.bge_maxsegs = 1;
2114 ctx.sc = sc;
2115
2116 error = bus_dmamap_load(sc->bge_cdata.bge_rx_return_ring_tag,

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

2135 return (ENOMEM);
2136 }
2137
2138 /* Allocate DMA'able memory for TX ring */
2139
2140 error = bus_dmamem_alloc(sc->bge_cdata.bge_tx_ring_tag,
2141 (void **)&sc->bge_ldata.bge_tx_ring, BUS_DMA_NOWAIT,
2142 &sc->bge_cdata.bge_tx_ring_map);
2109 BGE_RX_RTN_RING_SZ(sc));
2110
2111 /* Load the address of the RX return ring */
2112
2113 ctx.bge_maxsegs = 1;
2114 ctx.sc = sc;
2115
2116 error = bus_dmamap_load(sc->bge_cdata.bge_rx_return_ring_tag,

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

2135 return (ENOMEM);
2136 }
2137
2138 /* Allocate DMA'able memory for TX ring */
2139
2140 error = bus_dmamem_alloc(sc->bge_cdata.bge_tx_ring_tag,
2141 (void **)&sc->bge_ldata.bge_tx_ring, BUS_DMA_NOWAIT,
2142 &sc->bge_cdata.bge_tx_ring_map);
2143 if (error)
2144 return (ENOMEM);
2143 if (error)
2144 return (ENOMEM);
2145
2145
2146 bzero((char *)sc->bge_ldata.bge_tx_ring, BGE_TX_RING_SZ);
2146 bzero((char *)sc->bge_ldata.bge_tx_ring, BGE_TX_RING_SZ);
2147
2148 /* Load the address of the TX ring */
2149
2150 ctx.bge_maxsegs = 1;
2151 ctx.sc = sc;
2152
2153 error = bus_dmamap_load(sc->bge_cdata.bge_tx_ring_tag,
2154 sc->bge_cdata.bge_tx_ring_map, sc->bge_ldata.bge_tx_ring,

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

2171 return (ENOMEM);
2172 }
2173
2174 /* Allocate DMA'able memory for status block */
2175
2176 error = bus_dmamem_alloc(sc->bge_cdata.bge_status_tag,
2177 (void **)&sc->bge_ldata.bge_status_block, BUS_DMA_NOWAIT,
2178 &sc->bge_cdata.bge_status_map);
2147
2148 /* Load the address of the TX ring */
2149
2150 ctx.bge_maxsegs = 1;
2151 ctx.sc = sc;
2152
2153 error = bus_dmamap_load(sc->bge_cdata.bge_tx_ring_tag,
2154 sc->bge_cdata.bge_tx_ring_map, sc->bge_ldata.bge_tx_ring,

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

2171 return (ENOMEM);
2172 }
2173
2174 /* Allocate DMA'able memory for status block */
2175
2176 error = bus_dmamem_alloc(sc->bge_cdata.bge_status_tag,
2177 (void **)&sc->bge_ldata.bge_status_block, BUS_DMA_NOWAIT,
2178 &sc->bge_cdata.bge_status_map);
2179 if (error)
2180 return (ENOMEM);
2179 if (error)
2180 return (ENOMEM);
2181
2181
2182 bzero((char *)sc->bge_ldata.bge_status_block, BGE_STATUS_BLK_SZ);
2182 bzero((char *)sc->bge_ldata.bge_status_block, BGE_STATUS_BLK_SZ);
2183
2184 /* Load the address of the status block */
2185
2186 ctx.sc = sc;
2187 ctx.bge_maxsegs = 1;
2188
2189 error = bus_dmamap_load(sc->bge_cdata.bge_status_tag,
2190 sc->bge_cdata.bge_status_map, sc->bge_ldata.bge_status_block,
2191 BGE_STATUS_BLK_SZ, bge_dma_map_addr, &ctx, BUS_DMA_NOWAIT);
2192
2193 if (error)
2194 return (ENOMEM);
2195
2196 sc->bge_ldata.bge_status_block_paddr = ctx.bge_busaddr;
2197
2198 /* Create tag for statistics block */
2199
2200 error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag,
2201 PAGE_SIZE, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL,
2183
2184 /* Load the address of the status block */
2185
2186 ctx.sc = sc;
2187 ctx.bge_maxsegs = 1;
2188
2189 error = bus_dmamap_load(sc->bge_cdata.bge_status_tag,
2190 sc->bge_cdata.bge_status_map, sc->bge_ldata.bge_status_block,
2191 BGE_STATUS_BLK_SZ, bge_dma_map_addr, &ctx, BUS_DMA_NOWAIT);
2192
2193 if (error)
2194 return (ENOMEM);
2195
2196 sc->bge_ldata.bge_status_block_paddr = ctx.bge_busaddr;
2197
2198 /* Create tag for statistics block */
2199
2200 error = bus_dma_tag_create(sc->bge_cdata.bge_parent_tag,
2201 PAGE_SIZE, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL,
2202 NULL, BGE_STATS_SZ, 1, BGE_STATS_SZ, 0, NULL, NULL,
2202 NULL, BGE_STATS_SZ, 1, BGE_STATS_SZ, 0, NULL, NULL,
2203 &sc->bge_cdata.bge_stats_tag);
2204
2205 if (error) {
2206 device_printf(dev, "could not allocate dma tag\n");
2207 return (ENOMEM);
2208 }
2209
2210 /* Allocate DMA'able memory for statistics block */
2211
2212 error = bus_dmamem_alloc(sc->bge_cdata.bge_stats_tag,
2213 (void **)&sc->bge_ldata.bge_stats, BUS_DMA_NOWAIT,
2214 &sc->bge_cdata.bge_stats_map);
2203 &sc->bge_cdata.bge_stats_tag);
2204
2205 if (error) {
2206 device_printf(dev, "could not allocate dma tag\n");
2207 return (ENOMEM);
2208 }
2209
2210 /* Allocate DMA'able memory for statistics block */
2211
2212 error = bus_dmamem_alloc(sc->bge_cdata.bge_stats_tag,
2213 (void **)&sc->bge_ldata.bge_stats, BUS_DMA_NOWAIT,
2214 &sc->bge_cdata.bge_stats_map);
2215 if (error)
2216 return (ENOMEM);
2215 if (error)
2216 return (ENOMEM);
2217
2217
2218 bzero((char *)sc->bge_ldata.bge_stats, BGE_STATS_SZ);
2218 bzero((char *)sc->bge_ldata.bge_stats, BGE_STATS_SZ);
2219
2220 /* Load the address of the statstics block */
2221
2222 ctx.sc = sc;
2223 ctx.bge_maxsegs = 1;
2224
2225 error = bus_dmamap_load(sc->bge_cdata.bge_stats_tag,
2226 sc->bge_cdata.bge_stats_map, sc->bge_ldata.bge_stats,

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

2265 }
2266
2267 sc->bge_btag = rman_get_bustag(sc->bge_res);
2268 sc->bge_bhandle = rman_get_bushandle(sc->bge_res);
2269 sc->bge_vhandle = (vm_offset_t)rman_get_virtual(sc->bge_res);
2270
2271 /* Allocate interrupt */
2272 rid = 0;
2219
2220 /* Load the address of the statstics block */
2221
2222 ctx.sc = sc;
2223 ctx.bge_maxsegs = 1;
2224
2225 error = bus_dmamap_load(sc->bge_cdata.bge_stats_tag,
2226 sc->bge_cdata.bge_stats_map, sc->bge_ldata.bge_stats,

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

2265 }
2266
2267 sc->bge_btag = rman_get_bustag(sc->bge_res);
2268 sc->bge_bhandle = rman_get_bushandle(sc->bge_res);
2269 sc->bge_vhandle = (vm_offset_t)rman_get_virtual(sc->bge_res);
2270
2271 /* Allocate interrupt */
2272 rid = 0;
2273
2273
2274 sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
2275 RF_SHAREABLE | RF_ACTIVE);
2276
2277 if (sc->bge_irq == NULL) {
2278 printf("bge%d: couldn't map interrupt\n", unit);
2279 error = ENXIO;
2280 goto fail;
2281 }

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

2511
2512 return(0);
2513}
2514
2515static void
2516bge_release_resources(sc)
2517 struct bge_softc *sc;
2518{
2274 sc->bge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
2275 RF_SHAREABLE | RF_ACTIVE);
2276
2277 if (sc->bge_irq == NULL) {
2278 printf("bge%d: couldn't map interrupt\n", unit);
2279 error = ENXIO;
2280 goto fail;
2281 }

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

2511
2512 return(0);
2513}
2514
2515static void
2516bge_release_resources(sc)
2517 struct bge_softc *sc;
2518{
2519 device_t dev;
2519 device_t dev;
2520
2520
2521 dev = sc->bge_dev;
2521 dev = sc->bge_dev;
2522
2523 if (sc->bge_vpd_prodname != NULL)
2524 free(sc->bge_vpd_prodname, M_DEVBUF);
2525
2526 if (sc->bge_vpd_readonly != NULL)
2527 free(sc->bge_vpd_readonly, M_DEVBUF);
2528
2522
2523 if (sc->bge_vpd_prodname != NULL)
2524 free(sc->bge_vpd_prodname, M_DEVBUF);
2525
2526 if (sc->bge_vpd_readonly != NULL)
2527 free(sc->bge_vpd_readonly, M_DEVBUF);
2528
2529 if (sc->bge_intrhand != NULL)
2530 bus_teardown_intr(dev, sc->bge_irq, sc->bge_intrhand);
2529 if (sc->bge_intrhand != NULL)
2530 bus_teardown_intr(dev, sc->bge_irq, sc->bge_intrhand);
2531
2531
2532 if (sc->bge_irq != NULL)
2532 if (sc->bge_irq != NULL)
2533 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->bge_irq);
2534
2533 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->bge_irq);
2534
2535 if (sc->bge_res != NULL)
2535 if (sc->bge_res != NULL)
2536 bus_release_resource(dev, SYS_RES_MEMORY,
2537 BGE_PCI_BAR0, sc->bge_res);
2538
2539 bge_dma_free(sc);
2540
2541 if (mtx_initialized(&sc->bge_mtx)) /* XXX */
2542 BGE_LOCK_DESTROY(sc);
2543
2536 bus_release_resource(dev, SYS_RES_MEMORY,
2537 BGE_PCI_BAR0, sc->bge_res);
2538
2539 bge_dma_free(sc);
2540
2541 if (mtx_initialized(&sc->bge_mtx)) /* XXX */
2542 BGE_LOCK_DESTROY(sc);
2543
2544 return;
2544 return;
2545}
2546
2547static void
2548bge_reset(sc)
2549 struct bge_softc *sc;
2550{
2551 device_t dev;
2552 u_int32_t cachesize, command, pcistate, reset;

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

2570 if (CSR_READ_4(sc, 0x7e2c) == 0x60) /* PCIE 1.0 */
2571 CSR_WRITE_4(sc, 0x7e2c, 0x20);
2572 if (sc->bge_chipid != BGE_CHIPID_BCM5750_A0) {
2573 /* Prevent PCIE link training during global reset */
2574 CSR_WRITE_4(sc, BGE_MISC_CFG, (1<<29));
2575 reset |= (1<<29);
2576 }
2577 }
2545}
2546
2547static void
2548bge_reset(sc)
2549 struct bge_softc *sc;
2550{
2551 device_t dev;
2552 u_int32_t cachesize, command, pcistate, reset;

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

2570 if (CSR_READ_4(sc, 0x7e2c) == 0x60) /* PCIE 1.0 */
2571 CSR_WRITE_4(sc, 0x7e2c, 0x20);
2572 if (sc->bge_chipid != BGE_CHIPID_BCM5750_A0) {
2573 /* Prevent PCIE link training during global reset */
2574 CSR_WRITE_4(sc, BGE_MISC_CFG, (1<<29));
2575 reset |= (1<<29);
2576 }
2577 }
2578
2578
2579 /* Issue global reset */
2580 bge_writereg_ind(sc, BGE_MISC_CFG, reset);
2581
2582 DELAY(1000);
2583
2584 /* XXX: Broadcom Linux driver. */
2585 if (sc->bge_pcie) {
2586 if (sc->bge_chipid == BGE_CHIPID_BCM5750_A0) {

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

2619 * is complete.
2620 */
2621 for (i = 0; i < BGE_TIMEOUT; i++) {
2622 val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM);
2623 if (val == ~BGE_MAGIC_NUMBER)
2624 break;
2625 DELAY(10);
2626 }
2579 /* Issue global reset */
2580 bge_writereg_ind(sc, BGE_MISC_CFG, reset);
2581
2582 DELAY(1000);
2583
2584 /* XXX: Broadcom Linux driver. */
2585 if (sc->bge_pcie) {
2586 if (sc->bge_chipid == BGE_CHIPID_BCM5750_A0) {

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

2619 * is complete.
2620 */
2621 for (i = 0; i < BGE_TIMEOUT; i++) {
2622 val = bge_readmem_ind(sc, BGE_SOFTWARE_GENCOMM);
2623 if (val == ~BGE_MAGIC_NUMBER)
2624 break;
2625 DELAY(10);
2626 }
2627
2627
2628 if (i == BGE_TIMEOUT) {
2629 printf("bge%d: firmware handshake timed out\n", sc->bge_unit);
2630 return;
2631 }
2632
2633 /*
2634 * XXX Wait for the value of the PCISTATE register to
2635 * return to its original pre-reset state. This is a

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

3024 if (ifp->if_snd.ifq_head != NULL)
3025 bge_start_locked(ifp);
3026 }
3027 return;
3028 }
3029
3030 mii = device_get_softc(sc->bge_miibus);
3031 mii_tick(mii);
2628 if (i == BGE_TIMEOUT) {
2629 printf("bge%d: firmware handshake timed out\n", sc->bge_unit);
2630 return;
2631 }
2632
2633 /*
2634 * XXX Wait for the value of the PCISTATE register to
2635 * return to its original pre-reset state. This is a

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

3024 if (ifp->if_snd.ifq_head != NULL)
3025 bge_start_locked(ifp);
3026 }
3027 return;
3028 }
3029
3030 mii = device_get_softc(sc->bge_miibus);
3031 mii_tick(mii);
3032
3032
3033 if (!sc->bge_link && mii->mii_media_status & IFM_ACTIVE &&
3034 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
3035 sc->bge_link++;
3036 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
3037 IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX)
3038 printf("bge%d: gigabit link up\n",
3039 sc->bge_unit);
3040 if (ifp->if_snd.ifq_head != NULL)

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

3212 if (m_head == NULL)
3213 break;
3214
3215 /*
3216 * XXX
3217 * The code inside the if() block is never reached since we
3218 * must mark CSUM_IP_FRAGS in our if_hwassist to start getting
3219 * requests to checksum TCP/UDP in a fragmented packet.
3033 if (!sc->bge_link && mii->mii_media_status & IFM_ACTIVE &&
3034 IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
3035 sc->bge_link++;
3036 if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
3037 IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX)
3038 printf("bge%d: gigabit link up\n",
3039 sc->bge_unit);
3040 if (ifp->if_snd.ifq_head != NULL)

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

3212 if (m_head == NULL)
3213 break;
3214
3215 /*
3216 * XXX
3217 * The code inside the if() block is never reached since we
3218 * must mark CSUM_IP_FRAGS in our if_hwassist to start getting
3219 * requests to checksum TCP/UDP in a fragmented packet.
3220 *
3220 *
3221 * XXX
3222 * safety overkill. If this is a fragmented packet chain
3223 * with delayed TCP/UDP checksums, then only encapsulate
3224 * it if we have enough descriptors to handle the entire
3225 * chain at once.
3226 * (paranoia -- may not actually be needed)
3227 */
3228 if (m_head->m_flags & M_FIRSTFRAG &&

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

3482 if (sc->bge_tbi) {
3483 ifmr->ifm_status = IFM_AVALID;
3484 ifmr->ifm_active = IFM_ETHER;
3485 if (CSR_READ_4(sc, BGE_MAC_STS) &
3486 BGE_MACSTAT_TBI_PCS_SYNCHED)
3487 ifmr->ifm_status |= IFM_ACTIVE;
3488 ifmr->ifm_active |= IFM_1000_SX;
3489 if (CSR_READ_4(sc, BGE_MAC_MODE) & BGE_MACMODE_HALF_DUPLEX)
3221 * XXX
3222 * safety overkill. If this is a fragmented packet chain
3223 * with delayed TCP/UDP checksums, then only encapsulate
3224 * it if we have enough descriptors to handle the entire
3225 * chain at once.
3226 * (paranoia -- may not actually be needed)
3227 */
3228 if (m_head->m_flags & M_FIRSTFRAG &&

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

3482 if (sc->bge_tbi) {
3483 ifmr->ifm_status = IFM_AVALID;
3484 ifmr->ifm_active = IFM_ETHER;
3485 if (CSR_READ_4(sc, BGE_MAC_STS) &
3486 BGE_MACSTAT_TBI_PCS_SYNCHED)
3487 ifmr->ifm_status |= IFM_ACTIVE;
3488 ifmr->ifm_active |= IFM_1000_SX;
3489 if (CSR_READ_4(sc, BGE_MAC_MODE) & BGE_MACMODE_HALF_DUPLEX)
3490 ifmr->ifm_active |= IFM_HDX;
3490 ifmr->ifm_active |= IFM_HDX;
3491 else
3492 ifmr->ifm_active |= IFM_FDX;
3493 return;
3494 }
3495
3496 mii = device_get_softc(sc->bge_miibus);
3497 mii_pollstat(mii);
3498 ifmr->ifm_active = mii->mii_media_active;

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

3572 error = ifmedia_ioctl(ifp, ifr,
3573 &sc->bge_ifmedia, command);
3574 } else {
3575 mii = device_get_softc(sc->bge_miibus);
3576 error = ifmedia_ioctl(ifp, ifr,
3577 &mii->mii_media, command);
3578 }
3579 break;
3491 else
3492 ifmr->ifm_active |= IFM_FDX;
3493 return;
3494 }
3495
3496 mii = device_get_softc(sc->bge_miibus);
3497 mii_pollstat(mii);
3498 ifmr->ifm_active = mii->mii_media_active;

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

3572 error = ifmedia_ioctl(ifp, ifr,
3573 &sc->bge_ifmedia, command);
3574 } else {
3575 mii = device_get_softc(sc->bge_miibus);
3576 error = ifmedia_ioctl(ifp, ifr,
3577 &mii->mii_media, command);
3578 }
3579 break;
3580 case SIOCSIFCAP:
3580 case SIOCSIFCAP:
3581 mask = ifr->ifr_reqcap ^ ifp->if_capenable;
3582 /* NB: the code for RX csum offload is disabled for now */
3583 if (mask & IFCAP_TXCSUM) {
3584 ifp->if_capenable ^= IFCAP_TXCSUM;
3585 if (IFCAP_TXCSUM & ifp->if_capenable)
3586 ifp->if_hwassist = BGE_CSUM_FEATURES;
3587 else
3588 ifp->if_hwassist = 0;

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

3733bge_shutdown(dev)
3734 device_t dev;
3735{
3736 struct bge_softc *sc;
3737
3738 sc = device_get_softc(dev);
3739
3740 BGE_LOCK(sc);
3581 mask = ifr->ifr_reqcap ^ ifp->if_capenable;
3582 /* NB: the code for RX csum offload is disabled for now */
3583 if (mask & IFCAP_TXCSUM) {
3584 ifp->if_capenable ^= IFCAP_TXCSUM;
3585 if (IFCAP_TXCSUM & ifp->if_capenable)
3586 ifp->if_hwassist = BGE_CSUM_FEATURES;
3587 else
3588 ifp->if_hwassist = 0;

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

3733bge_shutdown(dev)
3734 device_t dev;
3735{
3736 struct bge_softc *sc;
3737
3738 sc = device_get_softc(dev);
3739
3740 BGE_LOCK(sc);
3741 bge_stop(sc);
3741 bge_stop(sc);
3742 bge_reset(sc);
3743 BGE_UNLOCK(sc);
3744
3745 return;
3746}
3742 bge_reset(sc);
3743 BGE_UNLOCK(sc);
3744
3745 return;
3746}