version 1.7, 2007/10/14 12:06:17 |
version 1.7.2.2, 2007/11/18 19:35:33 |
Line 46 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 46 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/queue.h> |
#include <sys/queue.h> |
|
|
#include <machine/endian.h> |
#include <machine/endian.h> |
#include <machine/bus.h> |
#include <sys/bus.h> |
#include <machine/intr.h> |
#include <sys/intr.h> |
|
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_media.h> |
#include <net/if_media.h> |
Line 87 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 87 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define GRR 0x216 /* global reset */ |
#define GRR 0x216 /* global reset */ |
#define CIDR 0x400 /* chip ID and enable */ |
#define CIDR 0x400 /* chip ID and enable */ |
#define CGCR 0x40a /* chip global control */ |
#define CGCR 0x40a /* chip global control */ |
|
#define IACR 0x4a0 /* indirect access control */ |
|
#define IADR1 0x4a2 /* indirect access data 66:63 */ |
|
#define IADR2 0x4a4 /* indirect access data 47:32 */ |
|
#define IADR3 0x4a6 /* indirect access data 63:48 */ |
|
#define IADR4 0x4a8 /* indirect access data 15:0 */ |
|
#define IADR5 0x4aa /* indirect access data 31:16 */ |
#define P1CR4 0x512 /* port 1 control 4 */ |
#define P1CR4 0x512 /* port 1 control 4 */ |
#define P1SR 0x514 /* port 1 status */ |
#define P1SR 0x514 /* port 1 status */ |
|
#define P2CR4 0x532 /* port 2 control 4 */ |
|
#define P2SR 0x534 /* port 2 status */ |
|
|
#define TXC_BS_MSK 0x3f000000 /* burst size */ |
#define TXC_BS_MSK 0x3f000000 /* burst size */ |
#define TXC_BS_SFT (24) /* 1,2,4,8,16,32 or 0 for unlimited */ |
#define TXC_BS_SFT (24) /* 1,2,4,8,16,32 or 0 for unlimited */ |
Line 150 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 158 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define T1_TBS_MASK 0x7ff /* segment size 10:0 */ |
#define T1_TBS_MASK 0x7ff /* segment size 10:0 */ |
|
|
#define R1_RER (1U<<25) /* end of ring */ |
#define R1_RER (1U<<25) /* end of ring */ |
#define R1_RBS_MASK 0x7fd /* segment size 10:0 */ |
#define R1_RBS_MASK 0x7fc /* segment size 10:0 */ |
|
|
#define KSE_NTXSEGS 16 |
#define KSE_NTXSEGS 16 |
#define KSE_TXQUEUELEN 64 |
#define KSE_TXQUEUELEN 64 |
Line 205 struct kse_softc { |
|
Line 213 struct kse_softc { |
|
struct ifmedia sc_media; /* ifmedia information */ |
struct ifmedia sc_media; /* ifmedia information */ |
int sc_media_status; /* PHY */ |
int sc_media_status; /* PHY */ |
int sc_media_active; /* PHY */ |
int sc_media_active; /* PHY */ |
callout_t sc_callout; /* tick callout */ |
callout_t sc_callout; /* MII tick callout */ |
|
callout_t sc_stat_ch; /* statistics counter callout */ |
|
|
bus_dmamap_t sc_cddmamap; /* control data DMA map */ |
bus_dmamap_t sc_cddmamap; /* control data DMA map */ |
#define sc_cddma sc_cddmamap->dm_segs[0].ds_addr |
#define sc_cddma sc_cddmamap->dm_segs[0].ds_addr |
|
|
struct kse_control_data *sc_control_data; |
struct kse_control_data *sc_control_data; |
#define sc_txdescs sc_control_data->kcd_txdescs |
#define sc_txdescs sc_control_data->kcd_txdescs |
#define sc_rxdescs sc_control_data->kcd_rxdescs |
#define sc_rxdescs sc_control_data->kcd_rxdescs |
|
|
struct kse_txsoft sc_txsoft[KSE_TXQUEUELEN]; |
struct kse_txsoft sc_txsoft[KSE_TXQUEUELEN]; |
struct kse_rxsoft sc_rxsoft[KSE_NRXDESC]; |
struct kse_rxsoft sc_rxsoft[KSE_NRXDESC]; |
Line 226 struct kse_softc { |
|
Line 235 struct kse_softc { |
|
uint32_t sc_txc, sc_rxc; |
uint32_t sc_txc, sc_rxc; |
uint32_t sc_t1csum; |
uint32_t sc_t1csum; |
int sc_mcsum; |
int sc_mcsum; |
|
uint32_t sc_inten; |
|
|
uint32_t sc_chip; |
uint32_t sc_chip; |
|
uint8_t sc_altmac[16][ETHER_ADDR_LEN]; |
|
uint16_t sc_vlan[16]; |
|
|
|
#ifdef KSE_EVENT_COUNTERS |
|
struct ksext { |
|
char evcntname[3][8]; |
|
struct evcnt pev[3][34]; |
|
} sc_ext; /* switch statistics */ |
|
#endif |
}; |
}; |
|
|
#define KSE_CDTXADDR(sc, x) ((sc)->sc_cddma + KSE_CDTXOFF((x))) |
#define KSE_CDTXADDR(sc, x) ((sc)->sc_cddma + KSE_CDTXOFF((x))) |
|
|
KSE_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \ |
KSE_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); \ |
} while (/*CONSTCOND*/0) |
} while (/*CONSTCOND*/0) |
|
|
u_int kse_burstsize = 16; /* DMA burst length tuning knob */ |
u_int kse_burstsize = 8; /* DMA burst length tuning knob */ |
|
|
#ifdef KSEDIAGNOSTIC |
#ifdef KSEDIAGNOSTIC |
u_int kse_monitor_rxintr; /* fragmented UDP csum HW bug hook */ |
u_int kse_monitor_rxintr; /* fragmented UDP csum HW bug hook */ |
Line 300 static void lnkchg(struct kse_softc *); |
|
Line 320 static void lnkchg(struct kse_softc *); |
|
static int ifmedia_upd(struct ifnet *); |
static int ifmedia_upd(struct ifnet *); |
static void ifmedia_sts(struct ifnet *, struct ifmediareq *); |
static void ifmedia_sts(struct ifnet *, struct ifmediareq *); |
static void phy_tick(void *); |
static void phy_tick(void *); |
|
static int ifmedia2_upd(struct ifnet *); |
|
static void ifmedia2_sts(struct ifnet *, struct ifmediareq *); |
|
#ifdef KSE_EVENT_COUNTERS |
|
static void stat_tick(void *); |
|
static void zerostats(struct kse_softc *); |
|
#endif |
|
|
static int |
static int |
kse_match(struct device *parent, struct cfdata *match, void *aux) |
kse_match(struct device *parent, struct cfdata *match, void *aux) |
Line 324 kse_attach(struct device *parent, struct |
|
Line 350 kse_attach(struct device *parent, struct |
|
pci_intr_handle_t ih; |
pci_intr_handle_t ih; |
const char *intrstr; |
const char *intrstr; |
struct ifnet *ifp; |
struct ifnet *ifp; |
|
struct ifmedia *ifm; |
uint8_t enaddr[ETHER_ADDR_LEN]; |
uint8_t enaddr[ETHER_ADDR_LEN]; |
bus_dma_segment_t seg; |
bus_dma_segment_t seg; |
int error, i, nseg; |
int i, p, error, nseg; |
pcireg_t pmode; |
pcireg_t pmode; |
int pmreg; |
int pmreg; |
|
|
Line 459 kse_attach(struct device *parent, struct |
|
Line 486 kse_attach(struct device *parent, struct |
|
} |
} |
|
|
callout_init(&sc->sc_callout, 0); |
callout_init(&sc->sc_callout, 0); |
|
callout_init(&sc->sc_stat_ch, 0); |
|
|
ifmedia_init(&sc->sc_media, 0, ifmedia_upd, ifmedia_sts); |
ifm = &sc->sc_media; |
ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T, 0, NULL); |
if (sc->sc_chip == 0x8841) { |
ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); |
ifmedia_init(ifm, 0, ifmedia_upd, ifmedia_sts); |
ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_100_TX, 0, NULL); |
ifmedia_add(ifm, IFM_ETHER|IFM_10_T, 0, NULL); |
ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); |
ifmedia_add(ifm, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); |
ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_AUTO, 0, NULL); |
ifmedia_add(ifm, IFM_ETHER|IFM_100_TX, 0, NULL); |
ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO); |
ifmedia_add(ifm, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); |
|
ifmedia_add(ifm, IFM_ETHER|IFM_AUTO, 0, NULL); |
|
ifmedia_set(ifm, IFM_ETHER|IFM_AUTO); |
|
} |
|
else { |
|
ifmedia_init(ifm, 0, ifmedia2_upd, ifmedia2_sts); |
|
ifmedia_add(ifm, IFM_ETHER|IFM_AUTO, 0, NULL); |
|
ifmedia_set(ifm, IFM_ETHER|IFM_AUTO); |
|
} |
|
|
printf("%s: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto\n", |
printf("%s: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto\n", |
sc->sc_dev.dv_xname); |
sc->sc_dev.dv_xname); |
Line 494 kse_attach(struct device *parent, struct |
|
Line 530 kse_attach(struct device *parent, struct |
|
|
|
if_attach(ifp); |
if_attach(ifp); |
ether_ifattach(ifp, enaddr); |
ether_ifattach(ifp, enaddr); |
|
|
|
p = (sc->sc_chip == 0x8842) ? 3 : 1; |
|
#ifdef KSE_EVENT_COUNTERS |
|
for (i = 0; i < p; i++) { |
|
struct ksext *ee = &sc->sc_ext; |
|
sprintf(ee->evcntname[i], "%s.%d", sc->sc_dev.dv_xname, i+1); |
|
evcnt_attach_dynamic(&ee->pev[i][0], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxLoPriotyByte"); |
|
evcnt_attach_dynamic(&ee->pev[i][1], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxHiPriotyByte"); |
|
evcnt_attach_dynamic(&ee->pev[i][2], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxUndersizePkt"); |
|
evcnt_attach_dynamic(&ee->pev[i][3], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxFragments"); |
|
evcnt_attach_dynamic(&ee->pev[i][4], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxOversize"); |
|
evcnt_attach_dynamic(&ee->pev[i][5], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxJabbers"); |
|
evcnt_attach_dynamic(&ee->pev[i][6], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxSymbolError"); |
|
evcnt_attach_dynamic(&ee->pev[i][7], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxCRCError"); |
|
evcnt_attach_dynamic(&ee->pev[i][8], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxAlignmentError"); |
|
evcnt_attach_dynamic(&ee->pev[i][9], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxControl8808Pkts"); |
|
evcnt_attach_dynamic(&ee->pev[i][10], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxPausePkts"); |
|
evcnt_attach_dynamic(&ee->pev[i][11], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxBroadcast"); |
|
evcnt_attach_dynamic(&ee->pev[i][12], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxMulticast"); |
|
evcnt_attach_dynamic(&ee->pev[i][13], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxUnicast"); |
|
evcnt_attach_dynamic(&ee->pev[i][14], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "Rx64Octets"); |
|
evcnt_attach_dynamic(&ee->pev[i][15], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "Rx65To127Octets"); |
|
evcnt_attach_dynamic(&ee->pev[i][16], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "Rx128To255Octets"); |
|
evcnt_attach_dynamic(&ee->pev[i][17], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "Rx255To511Octets"); |
|
evcnt_attach_dynamic(&ee->pev[i][18], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "Rx512To1023Octets"); |
|
evcnt_attach_dynamic(&ee->pev[i][19], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "Rx1024To1522Octets"); |
|
evcnt_attach_dynamic(&ee->pev[i][20], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxLoPriotyByte"); |
|
evcnt_attach_dynamic(&ee->pev[i][21], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxHiPriotyByte"); |
|
evcnt_attach_dynamic(&ee->pev[i][22], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxLateCollision"); |
|
evcnt_attach_dynamic(&ee->pev[i][23], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxPausePkts"); |
|
evcnt_attach_dynamic(&ee->pev[i][24], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxBroadcastPkts"); |
|
evcnt_attach_dynamic(&ee->pev[i][25], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxMulticastPkts"); |
|
evcnt_attach_dynamic(&ee->pev[i][26], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxUnicastPkts"); |
|
evcnt_attach_dynamic(&ee->pev[i][27], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxDeferred"); |
|
evcnt_attach_dynamic(&ee->pev[i][28], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxTotalCollision"); |
|
evcnt_attach_dynamic(&ee->pev[i][29], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxExcessiveCollision"); |
|
evcnt_attach_dynamic(&ee->pev[i][30], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxSingleCollision"); |
|
evcnt_attach_dynamic(&ee->pev[i][31], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxMultipleCollision"); |
|
evcnt_attach_dynamic(&ee->pev[i][32], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "TxDropPkts"); |
|
evcnt_attach_dynamic(&ee->pev[i][33], EVCNT_TYPE_MISC, |
|
NULL, ee->evcntname[i], "RxDropPkts"); |
|
} |
|
#endif |
return; |
return; |
|
|
fail_5: |
fail_5: |
Line 555 kse_ioctl(struct ifnet *ifp, u_long cmd, |
|
Line 667 kse_ioctl(struct ifnet *ifp, u_long cmd, |
|
return error; |
return error; |
} |
} |
|
|
#define KSE_INTRS (INT_DMLCS|INT_DMTS|INT_DMRS|INT_DMRBUS) |
|
|
|
static int |
static int |
kse_init(struct ifnet *ifp) |
kse_init(struct ifnet *ifp) |
{ |
{ |
Line 660 kse_init(struct ifnet *ifp) |
|
Line 770 kse_init(struct ifnet *ifp) |
|
CSR_WRITE_4(sc, MDRSC, 1); |
CSR_WRITE_4(sc, MDRSC, 1); |
|
|
/* enable interrupts */ |
/* enable interrupts */ |
|
sc->sc_inten = INT_DMTS|INT_DMRS|INT_DMRBUS; |
|
if (sc->sc_chip == 0x8841) |
|
sc->sc_inten |= INT_DMLCS; |
CSR_WRITE_4(sc, INTST, ~0); |
CSR_WRITE_4(sc, INTST, ~0); |
CSR_WRITE_4(sc, INTEN, KSE_INTRS); |
CSR_WRITE_4(sc, INTEN, sc->sc_inten); |
|
|
ifp->if_flags |= IFF_RUNNING; |
ifp->if_flags |= IFF_RUNNING; |
ifp->if_flags &= ~IFF_OACTIVE; |
ifp->if_flags &= ~IFF_OACTIVE; |
|
|
/* start one second timer */ |
if (sc->sc_chip == 0x8841) { |
callout_reset(&sc->sc_callout, hz, phy_tick, sc); |
/* start one second timer */ |
|
callout_reset(&sc->sc_callout, hz, phy_tick, sc); |
|
} |
|
#ifdef KSE_EVENT_COUNTERS |
|
/* start statistics gather 1 minute timer */ |
|
zerostats(sc); |
|
callout_reset(&sc->sc_stat_ch, hz * 60, stat_tick, sc); |
|
#endif |
|
|
out: |
out: |
if (error) { |
if (error) { |
Line 685 kse_stop(struct ifnet *ifp, int disable) |
|
Line 805 kse_stop(struct ifnet *ifp, int disable) |
|
struct kse_txsoft *txs; |
struct kse_txsoft *txs; |
int i; |
int i; |
|
|
callout_stop(&sc->sc_callout); |
if (sc->sc_chip == 0x8841) |
|
callout_stop(&sc->sc_callout); |
|
callout_stop(&sc->sc_stat_ch); |
|
|
sc->sc_txc &= ~TXC_TEN; |
sc->sc_txc &= ~TXC_TEN; |
sc->sc_rxc &= ~RXC_REN; |
sc->sc_rxc &= ~RXC_REN; |
|
|
kse_start(struct ifnet *ifp) |
kse_start(struct ifnet *ifp) |
{ |
{ |
struct kse_softc *sc = ifp->if_softc; |
struct kse_softc *sc = ifp->if_softc; |
struct mbuf *m0; |
struct mbuf *m0, *m; |
struct kse_txsoft *txs; |
struct kse_txsoft *txs; |
bus_dmamap_t dmamap; |
bus_dmamap_t dmamap; |
int error, nexttx, lasttx, ofree, seg; |
int error, nexttx, lasttx, ofree, seg; |
Line 838 kse_start(struct ifnet *ifp) |
|
Line 960 kse_start(struct ifnet *ifp) |
|
tdes0 |= T0_OWN; |
tdes0 |= T0_OWN; |
lasttx = nexttx; |
lasttx = nexttx; |
} |
} |
#if 0 |
|
/* |
|
* T1_IC bit could schedule Tx frame done interrupt here, |
|
* but this driver takes a "shoot away" Tx strategy. |
|
*/ |
|
#else |
|
{ |
|
/* |
/* |
* Outgoing NFS mbuf must be unloaded when Tx completed. |
* Outgoing NFS mbuf must be unloaded when Tx completed. |
* Without T1_IC NFS mbuf is left unack'ed for excessive |
* Without T1_IC NFS mbuf is left unack'ed for excessive |
Line 853 kse_start(struct ifnet *ifp) |
|
Line 969 kse_start(struct ifnet *ifp) |
|
* It's painful to traverse every mbuf chain to determine |
* It's painful to traverse every mbuf chain to determine |
* whether someone is waiting for Tx completion. |
* whether someone is waiting for Tx completion. |
*/ |
*/ |
struct mbuf *m = m0; |
m = m0; |
do { |
do { |
if ((m->m_flags & M_EXT) && m->m_ext.ext_free) { |
if ((m->m_flags & M_EXT) && m->m_ext.ext_free) { |
sc->sc_txdescs[lasttx].t1 |= T1_IC; |
sc->sc_txdescs[lasttx].t1 |= T1_IC; |
break; |
break; |
} |
} |
} while ((m = m->m_next) != NULL); |
} while ((m = m->m_next) != NULL); |
} |
|
#endif |
|
|
|
/* write last T0_OWN bit of the 1st segment */ |
/* write last T0_OWN bit of the 1st segment */ |
sc->sc_txdescs[lasttx].t1 |= T1_LS; |
sc->sc_txdescs[lasttx].t1 |= T1_LS; |
Line 1244 phy_tick(void *arg) |
|
Line 1358 phy_tick(void *arg) |
|
|
|
callout_reset(&sc->sc_callout, hz, phy_tick, sc); |
callout_reset(&sc->sc_callout, hz, phy_tick, sc); |
} |
} |
|
|
|
static int |
|
ifmedia2_upd(struct ifnet *ifp) |
|
{ |
|
struct kse_softc *sc = ifp->if_softc; |
|
|
|
sc->sc_media_status = IFM_AVALID; |
|
sc->sc_media_active = IFM_NONE; |
|
return 0; |
|
} |
|
|
|
static void |
|
ifmedia2_sts(struct ifnet *ifp, struct ifmediareq *ifmr) |
|
{ |
|
struct kse_softc *sc = ifp->if_softc; |
|
int p1sts, p2sts; |
|
|
|
ifmr->ifm_status = IFM_AVALID; |
|
ifmr->ifm_active = IFM_ETHER; |
|
p1sts = CSR_READ_2(sc, P1SR); |
|
p2sts = CSR_READ_2(sc, P2SR); |
|
if (((p1sts | p2sts) & (1U << 5)) == 0) |
|
ifmr->ifm_active |= IFM_NONE; |
|
else { |
|
ifmr->ifm_status |= IFM_ACTIVE; |
|
ifmr->ifm_active |= IFM_100_TX|IFM_FDX; |
|
ifmr->ifm_active |= IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE; |
|
} |
|
sc->sc_media_status = ifmr->ifm_status; |
|
sc->sc_media_active = ifmr->ifm_active; |
|
} |
|
|
|
#ifdef KSE_EVENT_COUNTERS |
|
static void |
|
stat_tick(arg) |
|
void *arg; |
|
{ |
|
struct kse_softc *sc = arg; |
|
struct ksext *ee = &sc->sc_ext; |
|
int nport, p, i, val; |
|
|
|
nport = (sc->sc_chip == 0x8842) ? 3 : 1; |
|
for (p = 0; p < nport; p++) { |
|
for (i = 0; i < 32; i++) { |
|
val = 0x1c00 | (p * 0x20 + i); |
|
CSR_WRITE_2(sc, IACR, val); |
|
do { |
|
val = CSR_READ_2(sc, IADR5) << 16; |
|
} while ((val & (1U << 30)) == 0); |
|
if (val & (1U << 31)) { |
|
(void)CSR_READ_2(sc, IADR4); |
|
val = 0x3fffffff; /* has made overflow */ |
|
} |
|
else { |
|
val &= 0x3fff0000; /* 29:16 */ |
|
val |= CSR_READ_2(sc, IADR4); /* 15:0 */ |
|
} |
|
ee->pev[p][i].ev_count += val; /* i (0-31) */ |
|
} |
|
CSR_WRITE_2(sc, IACR, 0x1c00 + 0x100 + p); |
|
ee->pev[p][32].ev_count = CSR_READ_2(sc, IADR4); /* 32 */ |
|
CSR_WRITE_2(sc, IACR, 0x1c00 + 0x100 + p * 3 + 1); |
|
ee->pev[p][33].ev_count = CSR_READ_2(sc, IADR4); /* 33 */ |
|
} |
|
callout_reset(&sc->sc_stat_ch, hz * 60, stat_tick, arg); |
|
} |
|
|
|
static void |
|
zerostats(struct kse_softc *sc) |
|
{ |
|
struct ksext *ee = &sc->sc_ext; |
|
int nport, p, i, val; |
|
|
|
/* make sure all the HW counters get zero */ |
|
nport = (sc->sc_chip == 0x8842) ? 3 : 1; |
|
for (p = 0; p < nport; p++) { |
|
for (i = 0; i < 31; i++) { |
|
val = 0x1c00 | (p * 0x20 + i); |
|
CSR_WRITE_2(sc, IACR, val); |
|
do { |
|
val = CSR_READ_2(sc, IADR5) << 16; |
|
} while ((val & (1U << 30)) == 0); |
|
(void)CSR_READ_2(sc, IADR4); |
|
ee->pev[p][i].ev_count = 0; |
|
} |
|
} |
|
} |
|
#endif |