Subject: port-i386/15261: patches to if_sip.c for SiS 635/735 support
To: None <gnats-bugs@gnats.netbsd.org>
From: None <sdegler@degler.net>
List: netbsd-bugs
Date: 01/15/2002 22:22:04
>Number: 15261
>Category: port-i386
>Synopsis: patches to if_sip.c for SiS 635/735 support
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: port-i386-maintainer
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Jan 15 19:23:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator: Stephen Degler
>Release: NetBSD 1.5ZA
>Organization:
Very little, at best
>Environment:
System: NetBSD bauhaus.degler.net 1.5ZA NetBSD 1.5ZA (BAUHAUS) #1: Tue Jan 15 21:43:19 EST 2002 sdegler@bauhaus.degler.net:/vol1/NetBSD/kernels/BAUHAUS i386
Architecture: i386
Machine: i386
>Description:
Attached is a patch to add support for the integrated ethernet
controller on the SiS 635 and 735 chipsets. This solves two problems.
"master abort" --> apparently caused by initializing the receive
filter too early in the init function.
"oversize packet dropped" --> The SiS chipsets seem to has some
magical internal (not quite pci) bus that the ethernet controller
is attached to. It requires the DMA thresholds to not exceed 64
bytes.
See reports of these problems on the port-i386 mailing list circa
December 20.
Note that I had to refer to the Linux driver as it is the only
source of documentation to be found for the 635/735, and it is
maintained by SIS. No code was borrowed, I wrote what little is
here.
The multicast filter was changed to support at 256 bit hash
table for the 635/735. Finally, changed the crc calculation
as it seemed to be backwards. This needs to be verified. It
is possible that I broke the other supported chips by doing
this. It definitely fixed a problem for me as I was not
receiving NTP multicast packets without it.
>How-To-Repeat:
Boot any SiS 635/735 based system and try to use the integrated
ethernet.
>Fix:
The following 2 patches are against -current:
--------------------------------------------------------------------------
diff -c -r1.8 if_sipreg.h
*** if_sipreg.h 2001/12/20 03:32:31 1.8
--- if_sipreg.h 2002/01/16 03:11:12
***************
*** 249,254 ****
--- 249,257 ----
#else
#define CFG_EUPHCOMP 0x00000100 /* 83810 descriptor compat (83815) */
#endif /* DP83820 */
+ #define CFG_EDBMASTEN 0x00002000 /* 635,900B ?? from linux driver */
+ #define CFG_RNDCNT 0x00000400 /* 635,900B ?? from linux driver */
+ #define CFG_FAIRBO 0x00000200 /* 635,900B ?? from linux driver */
#define CFG_REQALG 0x00000080 /* PCI bus request alg. */
#define CFG_SB 0x00000040 /* single backoff */
#define CFG_POW 0x00000020 /* program out of window timer */
***************
*** 471,476 ****
--- 474,480 ----
#define RXCFG_MXDMA_256 0x00700000 /* 256 bytes */
#endif /* DP83820 */
#define RXCFG_DRTH 0x0000003e
+ /* #define RXCFG_DRTH 14 */
#define RXCFG_DRTH_SHIFT 1
#ifdef DP83820
***************
*** 519,524 ****
--- 523,537 ----
#define RFCR_RFADDR_MC5 0x00090000 /* multicast hash word 5 */
#define RFCR_RFADDR_MC6 0x000a0000 /* multicast hash word 6 */
#define RFCR_RFADDR_MC7 0x000b0000 /* multicast hash word 7 */
+ /* sis900 B and 635/735 only */
+ #define RFCR_RFADDR_MC8 0x000c0000 /* multicast hash word 8 */
+ #define RFCR_RFADDR_MC9 0x000d0000 /* multicast hash word 9 */
+ #define RFCR_RFADDR_MC10 0x000e0000 /* multicast hash word 10 */
+ #define RFCR_RFADDR_MC11 0x000f0000 /* multicast hash word 11 */
+ #define RFCR_RFADDR_MC12 0x00100000 /* multicast hash word 12 */
+ #define RFCR_RFADDR_MC13 0x00110000 /* multicast hash word 13 */
+ #define RFCR_RFADDR_MC14 0x00120000 /* multicast hash word 14 */
+ #define RFCR_RFADDR_MC15 0x00130000 /* multicast hash word 15 */
#define RFCR_NS_RFADDR_PMATCH0 0x0000 /* perfect match octets 1-0 */
#define RFCR_NS_RFADDR_PMATCH2 0x0002 /* perfect match octets 3-2 */
***************
*** 694,699 ****
--- 707,714 ----
#define SIS_REV_630E 0x81
#define SIS_REV_630S 0x82
#define SIS_REV_630EA1 0x83
+ #define SIS_REV_635 0x90 /* same for 735 (745?) */
+ #define SIS_REV_900B 0x03
/*
* Serial EEPROM opcodes, including the start bit.
--------------------------------------------------------------------------
Index: if_sip.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_sip.c,v
retrieving revision 1.44
diff -c -r1.44 if_sip.c
*** if_sip.c 2001/12/20 03:32:31 1.44
--- if_sip.c 2002/01/16 03:13:05
***************
*** 366,371 ****
--- 366,385 ----
SIP_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \
} while (0)
+ #define SIP_CHIP_VERS(sc,vendor,product,rev) \
+ (sc->sc_model->sip_vendor == vendor && \
+ sc->sc_model->sip_product == product && \
+ sc->sc_model->sip_revision == rev )
+
+ #define SIP_CHIP_MODEL(sc,vendor,product) \
+ (sc->sc_model->sip_vendor == vendor && \
+ sc->sc_model->sip_product == product)
+
+ #if !defined(DP83820)
+ #define SIP_SIS900_REV(sc,rev) \
+ (SIP_CHIP_VERS(sc,PCI_VENDOR_SIS,PCI_PRODUCT_SIS_900,rev))
+ #endif
+
#define SIP_TIMEOUT 1000
void SIP_DECL(start)(struct ifnet *);
***************
*** 488,514 ****
const struct sip_product {
pci_vendor_id_t sip_vendor;
pci_product_id_t sip_product;
const char *sip_name;
const struct sip_variant *sip_variant;
} SIP_DECL(products)[] = {
#if defined(DP83820)
! { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83820,
"NatSemi DP83820 Gigabit Ethernet",
&SIP_DECL(variant_dp83820) },
#else
! { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900,
"SiS 900 10/100 Ethernet",
&SIP_DECL(variant_sis900) },
! { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016,
"SiS 7016 10/100 Ethernet",
&SIP_DECL(variant_sis900) },
!
! { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815,
"NatSemi DP83815 10/100 Ethernet",
&SIP_DECL(variant_dp83815) },
#endif /* DP83820 */
!
! { 0, 0,
NULL,
NULL },
};
--- 502,527 ----
const struct sip_product {
pci_vendor_id_t sip_vendor;
pci_product_id_t sip_product;
+ pci_revision_t sip_revision;
const char *sip_name;
const struct sip_variant *sip_variant;
} SIP_DECL(products)[] = {
#if defined(DP83820)
! { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83820, 0,
"NatSemi DP83820 Gigabit Ethernet",
&SIP_DECL(variant_dp83820) },
#else
! { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_900, 0,
"SiS 900 10/100 Ethernet",
&SIP_DECL(variant_sis900) },
! { PCI_VENDOR_SIS, PCI_PRODUCT_SIS_7016, 0,
"SiS 7016 10/100 Ethernet",
&SIP_DECL(variant_sis900) },
! { PCI_VENDOR_NS, PCI_PRODUCT_NS_DP83815, 0,
"NatSemi DP83815 10/100 Ethernet",
&SIP_DECL(variant_dp83815) },
#endif /* DP83820 */
! { 0, 0, 0,
NULL,
NULL },
};
***************
*** 551,557 ****
bus_dma_segment_t seg;
int ioh_valid, memh_valid;
int i, rseg, error;
! const struct sip_product *sip;
pcireg_t pmode;
u_int8_t enaddr[ETHER_ADDR_LEN];
int pmreg;
--- 564,571 ----
bus_dma_segment_t seg;
int ioh_valid, memh_valid;
int i, rseg, error;
! const struct sip_product *sip_template;
! struct sip_product *sip;
pcireg_t pmode;
u_int8_t enaddr[ETHER_ADDR_LEN];
int pmreg;
***************
*** 562,572 ****
callout_init(&sc->sc_tick_ch);
! sip = SIP_DECL(lookup)(pa);
! if (sip == NULL) {
printf("\n");
panic(SIP_STR(attach) ": impossible");
}
printf(": %s\n", sip->sip_name);
--- 576,592 ----
callout_init(&sc->sc_tick_ch);
! sip_template = SIP_DECL(lookup)(pa);
! if (sip_template == NULL) {
printf("\n");
panic(SIP_STR(attach) ": impossible");
}
+ else {
+ sip = (struct sip_product *)
+ malloc(sizeof(struct sip_product), M_DEVBUF, M_NOWAIT);
+ memcpy(sip,sip_template,sizeof(struct sip_product));
+ sip->sip_revision = PCI_REVISION(pa->pa_class);
+ }
printf(": %s\n", sip->sip_name);
***************
*** 611,617 ****
/* Enable bus mastering. */
pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
! pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
PCI_COMMAND_MASTER_ENABLE);
/* Get it out of power save mode if needed. */
--- 631,637 ----
/* Enable bus mastering. */
pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
! pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
PCI_COMMAND_MASTER_ENABLE);
/* Get it out of power save mode if needed. */
***************
*** 728,733 ****
--- 748,759 ----
* in the softc.
*/
sc->sc_cfg = 0;
+
+ #if !defined(DP83820)
+ if ( SIP_SIS900_REV(sc,SIS_REV_635) || SIP_SIS900_REV(sc,SIS_REV_900B))
+ sc->sc_cfg |= (CFG_PESEL | CFG_RNDCNT);
+ #endif /* !defined(DP83820) */
+
(*sip->sip_variant->sipv_read_macaddr)(sc, pa, enaddr);
printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
***************
*** 910,915 ****
--- 936,942 ----
fail_1:
bus_dmamem_free(sc->sc_dmat, &seg, rseg);
fail_0:
+ free((void *)sc->sc_model,M_DEVBUF);
return;
}
***************
*** 1406,1413 ****
PRINTERR(ISR_RMABT, "master abort");
PRINTERR(ISR_RTABT, "target abort");
PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
(void) SIP_DECL(init)(ifp);
- #undef PRINTERR
}
}
--- 1433,1440 ----
PRINTERR(ISR_RMABT, "master abort");
PRINTERR(ISR_RTABT, "target abort");
PRINTERR(ISR_RXSOVR, "receive status FIFO overrun");
+ #undef PRINTERR
(void) SIP_DECL(init)(ifp);
}
}
***************
*** 1913,1918 ****
--- 1940,1948 ----
bus_space_handle_t sh = sc->sc_sh;
int i;
+ bus_space_write_4(st, sh, SIP_IER, 0);
+ bus_space_write_4(st, sh, SIP_IMR, 0);
+ bus_space_write_4(st, sh, SIP_RFCR, 0);
bus_space_write_4(st, sh, SIP_CR, CR_RST);
for (i = 0; i < SIP_TIMEOUT; i++) {
***************
*** 1964,1971 ****
SIP_DECL(reset)(sc);
#if !defined(DP83820)
! if (sc->sc_model->sip_vendor == PCI_VENDOR_NS &&
! sc->sc_model->sip_product == PCI_PRODUCT_NS_DP83815) {
/*
* DP83815 manual, page 78:
* 4.4 Recommended Registers Configuration
--- 1994,2000 ----
SIP_DECL(reset)(sc);
#if !defined(DP83820)
! if (SIP_CHIP_MODEL(sc,PCI_VENDOR_NS,PCI_PRODUCT_NS_DP83815)) {
/*
* DP83815 manual, page 78:
* 4.4 Recommended Registers Configuration
***************
*** 2062,2068 ****
* minimum (32 bytes), and we may be able to
* improve performance by increasing it.
*/
! sc->sc_tx_fill_thresh = 1;
}
if (sc->sc_tx_drain_thresh == 0) {
/*
--- 2091,2097 ----
* minimum (32 bytes), and we may be able to
* improve performance by increasing it.
*/
! sc->sc_tx_fill_thresh = 64/32;
}
if (sc->sc_tx_drain_thresh == 0) {
/*
***************
*** 2075,2089 ****
* may trash the first few outgoing packets if the
* PCI bus is saturated.
*/
! sc->sc_tx_drain_thresh = 512 / 32;
}
/*
* Initialize the prototype TXCFG register.
*/
! sc->sc_txcfg = TXCFG_ATP | TXCFG_MXDMA_512 |
(sc->sc_tx_fill_thresh << TXCFG_FLTH_SHIFT) |
sc->sc_tx_drain_thresh;
bus_space_write_4(st, sh, SIP_TXCFG, sc->sc_txcfg);
/*
--- 2104,2135 ----
* may trash the first few outgoing packets if the
* PCI bus is saturated.
*/
! sc->sc_tx_drain_thresh = 512 / 32;
}
/*
* Initialize the prototype TXCFG register.
*/
!
! #if defined(DP83820)
! sc->sc_txcfg = TXCFG_MXDMA_512;
! sc->sc_rxcfg = RXCFG_MXDMA_512;
! #else
! if ((SIP_SIS900_REV(sc,SIS_REV_635) ||
! SIP_SIS900_REV(sc,SIS_REV_900B)) &&
! (bus_space_read_4(sc->sc_st, sc->sc_sh, SIP_CFG) & CFG_EDBMASTEN)) {
! sc->sc_txcfg = TXCFG_MXDMA_64;
! sc->sc_rxcfg = RXCFG_MXDMA_64;
! } else {
! sc->sc_txcfg = TXCFG_MXDMA_512;
! sc->sc_rxcfg = RXCFG_MXDMA_512;
! }
! #endif /* DP83820 */
!
! sc->sc_txcfg |= TXCFG_ATP |
(sc->sc_tx_fill_thresh << TXCFG_FLTH_SHIFT) |
sc->sc_tx_drain_thresh;
+
bus_space_write_4(st, sh, SIP_TXCFG, sc->sc_txcfg);
/*
***************
*** 2098,2116 ****
* set this value lower than 2; 14 bytes are required to
* filter the packet).
*/
! sc->sc_rx_drain_thresh = RXCFG_DRTH >> RXCFG_DRTH_SHIFT;
}
/*
* Initialize the prototype RXCFG register.
*/
! sc->sc_rxcfg = RXCFG_MXDMA_512 |
! (sc->sc_rx_drain_thresh << RXCFG_DRTH_SHIFT);
bus_space_write_4(st, sh, SIP_RXCFG, sc->sc_rxcfg);
- /* Set up the receive filter. */
- (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
-
#ifdef DP83820
/*
* Initialize the VLAN/IP receive control register.
--- 2144,2159 ----
* set this value lower than 2; 14 bytes are required to
* filter the packet).
*/
! sc->sc_rx_drain_thresh = RXCFG_DRTH >> RXCFG_DRTH_SHIFT ;
! /* sc->sc_rx_drain_thresh = 32/8 ; */
}
/*
* Initialize the prototype RXCFG register.
*/
! sc->sc_rxcfg |= (sc->sc_rx_drain_thresh << RXCFG_DRTH_SHIFT);
bus_space_write_4(st, sh, SIP_RXCFG, sc->sc_rxcfg);
#ifdef DP83820
/*
* Initialize the VLAN/IP receive control register.
***************
*** 2160,2165 ****
--- 2203,2211 ----
ISR_TXURN|ISR_TXDESC|ISR_RXORN|ISR_RXIDLE|ISR_RXDESC;
bus_space_write_4(st, sh, SIP_IMR, sc->sc_imr);
+ /* Set up the receive filter. */
+ (*sc->sc_model->sip_variant->sipv_set_filter)(sc);
+
/*
* Set the current media. Do this after initializing the prototype
* IMR, since sip_mii_statchg() modifies the IMR for 802.3x flow
***************
*** 2418,2424 ****
struct ether_multi *enm;
u_int8_t *cp;
struct ether_multistep step;
! u_int32_t crc, mchash[8];
/*
* Initialize the prototype RFCR.
--- 2464,2470 ----
struct ether_multi *enm;
u_int8_t *cp;
struct ether_multistep step;
! u_int32_t crc, mchash[16];
/*
* Initialize the prototype RFCR.
***************
*** 2456,2465 ****
goto allmulti;
}
! crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
! /* Just want the 7 most significant bits. */
! crc >>= 25;
/* Set the corresponding bit in the hash table. */
mchash[crc >> 4] |= 1 << (crc & 0xf);
--- 2502,2516 ----
goto allmulti;
}
! /* Huh? Hash table must be big endian? */
! crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
! /* Just want the 7 or 8 most significant bits. */
! if ( SIP_SIS900_REV(sc,SIS_REV_635) ||
! SIP_SIS900_REV(sc,SIS_REV_900B))
! crc >>= 24;
! else
! crc >>= 25;
/* Set the corresponding bit in the hash table. */
mchash[crc >> 4] |= 1 << (crc & 0xf);
***************
*** 2501,2506 ****
--- 2552,2568 ----
FILTER_EMIT(RFCR_RFADDR_MC5, mchash[5]);
FILTER_EMIT(RFCR_RFADDR_MC6, mchash[6]);
FILTER_EMIT(RFCR_RFADDR_MC7, mchash[7]);
+ if ( SIP_SIS900_REV(sc,SIS_REV_635) ||
+ SIP_SIS900_REV(sc,SIS_REV_900B)) {
+ FILTER_EMIT(RFCR_RFADDR_MC8, mchash[8]);
+ FILTER_EMIT(RFCR_RFADDR_MC9, mchash[9]);
+ FILTER_EMIT(RFCR_RFADDR_MC10, mchash[10]);
+ FILTER_EMIT(RFCR_RFADDR_MC11, mchash[11]);
+ FILTER_EMIT(RFCR_RFADDR_MC12, mchash[12]);
+ FILTER_EMIT(RFCR_RFADDR_MC13, mchash[13]);
+ FILTER_EMIT(RFCR_RFADDR_MC14, mchash[14]);
+ FILTER_EMIT(RFCR_RFADDR_MC15, mchash[15]);
+ }
}
#undef FILTER_EMIT
***************
*** 2760,2768 ****
/*
* The SiS 900 has only an internal PHY on the MII. Only allow
! * MII address 0.
*/
! if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 && phy != 0)
return (0);
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
--- 2822,2832 ----
/*
* The SiS 900 has only an internal PHY on the MII. Only allow
! * MII address 0. However, the revisions integrated into SiS
! * 635/735 do.
*/
! if (SIP_CHIP_MODEL(sc,PCI_VENDOR_SIS,PCI_PRODUCT_SIS_900) &&
! sc->sc_model->sip_revision < SIS_REV_635 && phy != 0)
return (0);
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
***************
*** 2787,2795 ****
/*
* The SiS 900 has only an internal PHY on the MII. Only allow
! * MII address 0.
*/
! if (sc->sc_model->sip_product == PCI_PRODUCT_SIS_900 && phy != 0)
return;
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
--- 2851,2861 ----
/*
* The SiS 900 has only an internal PHY on the MII. Only allow
! * MII address 0. However, the revisions integrated into SiS
! * 635/735 do.
*/
! if (SIP_CHIP_MODEL(sc,PCI_VENDOR_SIS,PCI_PRODUCT_SIS_900) &&
! sc->sc_model->sip_revision < SIS_REV_635 && phy != 0)
return;
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_ENPHY,
***************
*** 2839,2846 ****
--- 2905,2915 ----
flowctl = 0;
}
+ /* If we have not properly set these values, don't emit them */
+ if ( sc->sc_txcfg & TXCFG_ATP ) {
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_TXCFG, sc->sc_txcfg);
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXCFG, sc->sc_rxcfg);
+ }
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_IMR, sc->sc_imr);
bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_FLOWCTL, flowctl);
}
***************
*** 2992,2997 ****
--- 3061,3067 ----
case SIS_REV_630S:
case SIS_REV_630E:
case SIS_REV_630EA1:
+ case SIS_REV_635:
/*
* The MAC address for the on-board Ethernet of
* the SiS 630 chipset is in the NVRAM. Kick
--------------------------------------------------------------------------
>Release-Note:
>Audit-Trail:
>Unformatted: