kern/96743: [sk] [patch] broken 32-bit register operations
Craig Leres
leres at ee.lbl.gov
Thu May 4 02:10:20 UTC 2006
>Number: 96743
>Category: kern
>Synopsis: [sk] [patch] broken 32-bit register operations
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Thu May 04 02:10:19 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Craig Leres
>Release: FreeBSD 6.1-BETA4 i386
>Organization:
Lawrence Berkeley National Laboratory
>Environment:
fox 15 % uname -a
FreeBSD fox.ee.lbl.gov 6.1-BETA4 FreeBSD 6.1-BETA4 #29: Wed May 3 17:45:44 PDT 2006 leres at fox.ee.lbl.gov:/usr/src/6.1-BETA4/sys/i386/compile/LBLSMP i386
SysKonnect SK-9843 gige adapter
>Description:
While attempting to apply a local patch that implements
receive hardware timestamps (nice for research and intrusion
detection applications) with the syskonnect SK-9843, I
noticed that some 32-bit register operations are broken.
Most of the registers, including XM_MODE and XM_TSTAMP_READ,
must be accessed 16-bits at a time. One step in enabling
timestamps is to set the XM_MODE_TIMESTAMP bit in the XM_MODE
register but it was not possible to access the high bytes
of the register.
I developed my timestamp patch with 4.8-RELEASE using version
1.8.2.1 of if_skreg.h which defines SK_XM_READ_4() and
SK_XM_WRITE_4() macros that use sk_win_read_2() and
sk_win_read_2() to read and write 16 bits at a time, as
required by the hardware.
Version 1.8.2.2 of the include file change the macros to
use sk_win_read_4() and sk_win_write_4() which only return
the low order 16-bits.
This problem probably wasn't detected before now because
the current driver only seems to ever access bits in the
low bytes of the registers (e.g. XM_MODE_RX_PROMISC in
XM_MODE).
>How-To-Repeat:
This patch helps demonstrate the problem:
==============================================================================
*** if_sk.c.virgin Wed May 3 17:56:30 2006
--- if_sk.c Wed May 3 17:56:37 2006
***************
*** 2532,2537 ****
--- 2532,2540 ----
/* Save the XMAC II revision */
sc_if->sk_xmac_rev = XM_XMAC_REV(SK_XM_READ_4(sc_if, XM_DEVID));
+ printf("sk%d: XM_DEVID 0x%x (0x%x/0x%x)\n",
+ sc_if->sk_unit, SK_XM_READ_4(sc_if, XM_DEVID),
+ SK_XM_READ_2(sc_if, XM_DEVID_HI), SK_XM_READ_2(sc_if, XM_DEVID_LO));
/*
* Perform additional initialization for external PHYs,
==============================================================================
After applying the patch and building and booting the kernel,
the driver reports:
skc0: <SysKonnect Gigabit Ethernet (V1.0)> port 0x3000-0x30ff mem 0xdd300000-0xd
d303fff irq 48 at device 1.0 on pci3
skc0: SysKonnect SK-NET Gigabit Ethernet Adapter SK-9843 SX rev. (0x0)
sk0: <XaQti Corp. XMAC II> on skc0
sk0: Ethernet address: 00:00:5a:9a:80:18
sk0: XM_DEVID 0xae20 (0xe0/0xae20)
Notice that SK_XM_READ_4() returned the same value as the
low bytes SK_XM_READ_2() and that the high bytes have 0xe0,
not zero.
>Fix:
The appended patch (vs. 1.29.2.1 of if_skreg.h) re-enables
the 2-byte versions if the SK_XM_READ_4() and SK_XM_WRITE_4()
macros. It also protects the SK_XM_WRITE_4() macro.
After booting the new kernel, the debugging printout
shows the complete device id value:
sk0: XM_DEVID 0xe0ae20 (0xe0/0xae20)
It looks like this patch would also apply to the -current
version (1.35).
==============================================================================
*** if_skreg.h.virgin Wed May 3 18:28:19 2006
--- if_skreg.h Wed May 3 18:29:56 2006
***************
*** 1150,1156 ****
#define SK_XMAC_REG(sc, reg) (((reg) * 2) + SK_XMAC1_BASE + \
(((sc)->sk_port) * (SK_XMAC2_BASE - SK_XMAC1_BASE)))
! #if 0
#define SK_XM_READ_4(sc, reg) \
((sk_win_read_2(sc->sk_softc, \
SK_XMAC_REG(sc, reg)) & 0xFFFF) | \
--- 1150,1160 ----
#define SK_XMAC_REG(sc, reg) (((reg) * 2) + SK_XMAC1_BASE + \
(((sc)->sk_port) * (SK_XMAC2_BASE - SK_XMAC1_BASE)))
! /*
! * For at least some registers (e.g. XM_MODE) with at least some
! * boards (e.g. SK-9843) you can only read/write 16 bits at a time.
! */
! #if 1
#define SK_XM_READ_4(sc, reg) \
((sk_win_read_2(sc->sk_softc, \
SK_XMAC_REG(sc, reg)) & 0xFFFF) | \
***************
*** 1158,1167 ****
SK_XMAC_REG(sc, reg + 2)) & 0xFFFF) << 16))
#define SK_XM_WRITE_4(sc, reg, val) \
! sk_win_write_2(sc->sk_softc, SK_XMAC_REG(sc, reg), \
! ((val) & 0xFFFF)); \
! sk_win_write_2(sc->sk_softc, SK_XMAC_REG(sc, reg + 2), \
! ((val) >> 16) & 0xFFFF)
#else
#define SK_XM_READ_4(sc, reg) \
sk_win_read_4(sc->sk_softc, SK_XMAC_REG(sc, reg))
--- 1162,1173 ----
SK_XMAC_REG(sc, reg + 2)) & 0xFFFF) << 16))
#define SK_XM_WRITE_4(sc, reg, val) \
! do { \
! sk_win_write_2(sc->sk_softc, SK_XMAC_REG(sc, reg), \
! ((val) & 0xFFFF)); \
! sk_win_write_2(sc->sk_softc, SK_XMAC_REG(sc, reg + 2), \
! ((val) >> 16) & 0xFFFF); \
! } while (0)
#else
#define SK_XM_READ_4(sc, reg) \
sk_win_read_4(sc->sk_softc, SK_XMAC_REG(sc, reg))
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list