Date: Tue, 5 May 1998 18:43:40 +0700 (NSS) From: Ustimenko Semen <semen@iclub.nsu.ru> To: Adam McDougall <mcdougall@ameritech.net> Cc: Andrew <andrew@iaccess.com.au>, freebsd-current@FreeBSD.ORG, Jaroslav Klaus <J.Klaus@sh.cvut.cz> Subject: Re: ethernet card Problems Message-ID: <Pine.BSF.3.96.980505183656.13866C-200000@iclub.nsu.ru> In-Reply-To: <35495353.62F9852D@ameritech.net>
next in thread | previous in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Hello!
On Fri, 1 May 1998, Adam McDougall wrote:
> Andrew wrote:
>
> > >Hi,
> > >
> > >I'm having some ethernet crad problems. The card i'm using is a SMC8216
> > >10/100Mbps
> > >I'm running it on 100Mbps.
> > >I'm running ipfilter with transproxy and squid on a 14 Gig cache on
> > >freebsd3.0-current, divertin all packets comin in on port 80 to transproxy.
> > >This is what messages tells me just before the whole thing crashes:
> > >
At last, i have done something, i added some debug output
if any errors occured, fixed epic_stop() to properly stop TX DMA and
changed tx queuing policy a little.
I don't want to commit it to FreeBSD-current, just
would You be so please to try it with EPIC_DEBUG enabled in if_tx.c.
Patch is attached.
Have You used previous versions? What was the best?
Thank you.
[-- Attachment #2 --]
*** if_tx.c.orig Tue May 5 18:21:38 1998
--- if_tx.c Tue May 5 18:24:42 1998
***************
*** 51,56 ****
--- 51,64 ----
#define TX_FRAG_LIST 1 /* Transmit directly from mbuf enstead */
/* of collecting mbuf's frags to one */
/* static allocated place */
+ /*#define EARLY_RX 1*/
+ /*#define EARLY_TX 1*/
+
+ #if defined(EPIC_DEBUG)
+ #define dprintf(a) printf a
+ #else
+ #define dprintf(a)
+ #endif
#include "pci.h"
#if NPCI > 0
***************
*** 85,91 ****
* Global variables
*/
static u_long epic_pci_count;
- static epic_softc_t * epics[EPIC_MAX_DEVICES];
static struct pci_device txdevice = {
"tx",
epic_pci_probe,
--- 93,98 ----
***************
*** 225,231 ****
m0 = m;
#if defined(TX_FRAG_LIST)
! if( buf->mbuf ) m_freem( buf->mbuf );
buf->mbuf = m;
flist->numfrags = 0;
--- 232,241 ----
m0 = m;
#if defined(TX_FRAG_LIST)
! if( buf->mbuf ) {
! dprintf(("tx%d: mbuf not freed in ifstart\n",sc->unit));
! m_freem( buf->mbuf );
! }
buf->mbuf = m;
flist->numfrags = 0;
***************
*** 238,243 ****
--- 248,254 ----
}
if( NULL != m0 ){
+ dprintf(("tx%d: mbuf too fragmented\n",sc->unit));
/* Copy packet to new allocated mbuf */
MGETHDR(m0,M_DONTWAIT,MT_DATA);
if( NULL == m0 ) {
***************
*** 255,282 ****
continue;
}
! for (len = 0; m != 0; m = m->m_next) {
! bcopy( mtod(m, caddr_t), mtod(m0, caddr_t) + len, m->m_len);
! len += m->m_len;
! }
!
! m_freem(buf->mbuf);
! buf->mbuf = m0;
flist->numfrags = 1;
flist->frag[0].fraglen = len;
flist->frag[0].fragaddr = vtophys( mtod(m0, caddr_t) );
}
/* Does not generate TXC unless ring is full more then a half */
! desc->control = (sc->pending_txs>TX_RING_SIZE/2)?0x05:0x01;
#else
! for (len = 0; m0 != 0; m0 = m0->m_next) {
! bcopy(mtod(m0, caddr_t), buf->data + len, m0->m_len);
! len += m0->m_len;
! }
/* Does not generate TXC unless ring is full more then a half */
! desc->control = (sc->pending_txs>TX_RING_SIZE/2)?0x14:0x10;
#endif
/* Packet should be at least ETHER_MIN_LEN */
--- 266,294 ----
continue;
}
! len = m->m_pkthdr.len;
! m_copydata( m, 0, len, mtod(m0,caddr_t) );
! m0->m_pkthdr.len = len;
! m0->m_pkthdr.rcvif = &sc->epic_if;
! m0->m_len = len;
!
! m_freem(m);
! buf->mbuf = m = m0;
flist->numfrags = 1;
flist->frag[0].fraglen = len;
flist->frag[0].fragaddr = vtophys( mtod(m0, caddr_t) );
}
/* Does not generate TXC unless ring is full more then a half */
! /*desc->control = (sc->pending_txs>TX_RING_SIZE/2)?0x05:0x01; */
! desc->control = 0x01;
#else
! len = m->m_pkthdr.len;
! m_copydata( m, 0, len, buf->data );
/* Does not generate TXC unless ring is full more then a half */
! /*desc->control = (sc->pending_txs>TX_RING_SIZE/2)?0x14:0x10;*/
! desc->control = 0x10;
#endif
/* Packet should be at least ETHER_MIN_LEN */
***************
*** 285,290 ****
--- 297,305 ----
/* Pass ownership to the chip */
desc->status = 0x8000;
+ /* Trigger an immediate transmit demand. */
+ CSR_WRITE_4( sc, COMMAND, COMMAND_TXQUEUED );
+
/* Set watchdog timer */
ifp->if_timer = 2;
***************
*** 296,303 ****
/* We don't need mbuf anyway */
m_freem( m );
#endif
- /* Trigger an immediate transmit demand. */
- CSR_WRITE_4( sc, COMMAND, COMMAND_TXQUEUED );
/* Packet queued successful */
sc->pending_txs++;
--- 311,316 ----
***************
*** 313,319 ****
}
/*
! * IFWATCHDOG function
*
* splimp() invoked here
*/
--- 326,333 ----
}
/*
! * Synopsis: This one is called if packets wasn't transmitted
! * during timeout.
*
* splimp() invoked here
*/
***************
*** 330,335 ****
--- 344,357 ----
printf("tx%d: device timeout %d packets\n",
sc->unit,sc->pending_txs);
+ #if defined(EPIC_DEBUG)
+ printf("tx%d: dirty_tx: %d, cur_tx: %d\n",sc->unit,sc->dirty_tx,sc->cur_tx);
+ printf("tx%d: not transmitted descs: ",sc->unit);
+ for(i=0;i<TX_RING_SIZE;i++)
+ if( sc->tx_desc[i].status & 0x8000 ) printf("%d ",i);
+ printf("\n");
+ #endif
+
ifp->if_oerrors+=sc->pending_txs;
epic_stop(sc);
***************
*** 370,375 ****
--- 392,398 ----
/* Check for errors */
if( !(desc->status & 1) ) {
+ dprintf(("tx%d: receive error, status: %x\n",sc->unit,desc->status));
sc->epic_if.if_ierrors++;
goto rxerror;
}
***************
*** 477,483 ****
int coll;
u_int16_t stt;
! while( i++ < TX_RING_SIZE ){
struct epic_tx_buffer *buf = sc->tx_buffer + sc->dirty_tx;
struct epic_tx_desc *desc = sc->tx_desc + sc->dirty_tx;
#if defined(TX_FRAG_LIST)
--- 500,506 ----
int coll;
u_int16_t stt;
! while( sc->pending_txs > 0 ){
struct epic_tx_buffer *buf = sc->tx_buffer + sc->dirty_tx;
struct epic_tx_desc *desc = sc->tx_desc + sc->dirty_tx;
#if defined(TX_FRAG_LIST)
***************
*** 566,600 ****
epic_softc_t * sc = (epic_softc_t *) arg;
int status;
! status = CSR_READ_4( sc, INTSTAT);
CSR_WRITE_4( sc, INTSTAT, status & (
! INTSTAT_RQE|INTSTAT_HCC|INTSTAT_RCC|
INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE|
INTSTAT_FATAL|INTSTAT_GP2|
INTSTAT_CNT|INTSTAT_TXU|INTSTAT_OVW|INTSTAT_RXE ) );
! if( status & (INTSTAT_RQE|INTSTAT_HCC|INTSTAT_RCC) ) {
epic_rx_done( sc );
! if( status & INTSTAT_RQE )
CSR_WRITE_4( sc, COMMAND, COMMAND_RXQUEUED );
}
if( status & (INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE) )
epic_tx_done( sc );
- if( (status & INTSTAT_TQE) && !(sc->epic_if.if_flags & IFF_OACTIVE) )
- epic_ifstart( &sc->epic_if );
-
if( (status & INTSTAT_GP2) && (QS6612_OUI == sc->phyid) ) {
u_int32_t status;
status = epic_read_phy_register( sc, QS6612_INTSTAT );
! if( (status & INTSTAT_AN_COMPLETE) &&
! (epic_autoneg(sc) == EPIC_FULL_DUPLEX) ) {
status = BMCR_FULL_DUPLEX | epic_read_phy_register( sc, DP83840_BMCR );
! CSR_WRITE_4( sc, TXCON,
! TXCON_LOOPBACK_MODE_FULL_DUPLEX|TXCON_DEFAULT );
} else {
status = ~BMCR_FULL_DUPLEX & epic_read_phy_register( sc, DP83840_BMCR );
CSR_WRITE_4( sc, TXCON, TXCON_DEFAULT );
--- 589,636 ----
epic_softc_t * sc = (epic_softc_t *) arg;
int status;
! intloop:
! status = CSR_READ_4( sc, INTSTAT );
!
! #if defined(EPIC_DEBUG)
! if( (status & INTSTAT_TQE) && (sc->epic_if.if_flags & IFF_DEBUG) ){
! printf("tx%d: TQE occured, forced epic_stop() - epic_init()\n",sc->unit);
! epic_stop( sc );
! epic_init( sc );
! }
! #endif
!
CSR_WRITE_4( sc, INTSTAT, status & (
! INTSTAT_RQE|INTSTAT_RCC|
INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE|
INTSTAT_FATAL|INTSTAT_GP2|
INTSTAT_CNT|INTSTAT_TXU|INTSTAT_OVW|INTSTAT_RXE ) );
! if( status & (INTSTAT_RQE|INTSTAT_RCC|INTSTAT_OVW) ) {
epic_rx_done( sc );
! if( status & INTSTAT_RQE ) {
! dprintf(("tx%d: Rx FIFO overflowed, restarting receiver\n",sc->unit));
CSR_WRITE_4( sc, COMMAND, COMMAND_RXQUEUED );
+ sc->epic_if.if_ierrors++;
+ }
+ if( status & INTSTAT_OVW ) {
+ dprintf(("tx%d: onchip Rx buffer overflowed, restarting receiver\n",sc->unit));
+ CSR_WRITE_4( sc, COMMAND, COMMAND_RXQUEUED );
+ sc->epic_if.if_ierrors++;
+ }
}
if( status & (INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE) )
epic_tx_done( sc );
if( (status & INTSTAT_GP2) && (QS6612_OUI == sc->phyid) ) {
u_int32_t status;
status = epic_read_phy_register( sc, QS6612_INTSTAT );
! if( (status & INTSTAT_AN_COMPLETE) && (epic_autoneg(sc) == EPIC_FULL_DUPLEX) ) {
status = BMCR_FULL_DUPLEX | epic_read_phy_register( sc, DP83840_BMCR );
! CSR_WRITE_4( sc, TXCON, TXCON_FULL_DUPLEX | TXCON_DEFAULT );
} else {
status = ~BMCR_FULL_DUPLEX & epic_read_phy_register( sc, DP83840_BMCR );
CSR_WRITE_4( sc, TXCON, TXCON_DEFAULT );
***************
*** 603,617 ****
/* There is apparently QS6612 chip bug: */
/* BMCR_FULL_DUPLEX flag is not updated by */
/* autonegotiation process, so update it by hands */
! epic_write_phy_register( sc, DP83840_BMCR, status);
/* We should clear GP2 int again after we clear it on PHY */
CSR_WRITE_4( sc, INTSTAT, INTSTAT_GP2 );
}
if( status & (INTSTAT_FATAL|INTSTAT_PMA|INTSTAT_PTA|INTSTAT_APE|INTSTAT_DPE) ){
int j;
! struct epic_tx_desc *desc;
printf("tx%d: PCI fatal error occured (%s%s%s%s)\n",
sc->unit,
--- 639,656 ----
/* There is apparently QS6612 chip bug: */
/* BMCR_FULL_DUPLEX flag is not updated by */
/* autonegotiation process, so update it by hands */
! epic_write_phy_register(sc, DP83840_BMCR, status);
/* We should clear GP2 int again after we clear it on PHY */
CSR_WRITE_4( sc, INTSTAT, INTSTAT_GP2 );
}
if( status & (INTSTAT_FATAL|INTSTAT_PMA|INTSTAT_PTA|INTSTAT_APE|INTSTAT_DPE) ){
+ #if defined(EPIC_DEBUG)
int j;
! struct epic_tx_desc *tdesc;
! struct epic_rx_desc *rdesc;
! #endif
printf("tx%d: PCI fatal error occured (%s%s%s%s)\n",
sc->unit,
***************
*** 621,635 ****
(status&INTSTAT_DPE)?" DPE":"");
#if defined(EPIC_DEBUG)
! printf("tx%d: dumping descriptors\n",sc->unit);
for(j=0;j<TX_RING_SIZE;j++){
! desc = sc->tx_desc + j;
! printf("desc%d: %d %04x, %08x, %04x %d, %08x\n",
j,
! desc->txlength,desc->status,
! desc->bufaddr,
! desc->control,desc->buflength,
! desc->next
);
}
#endif
--- 660,686 ----
(status&INTSTAT_DPE)?" DPE":"");
#if defined(EPIC_DEBUG)
! printf("tx%d: PRCDAR: 0x%08x, PTCDAR: 0x%08x\n",sc->unit,CSR_READ_4(sc,PRCDAR),CSR_READ_4(sc,PTCDAR));
! printf("tx%d: dumping tx descriptors\n",sc->unit);
for(j=0;j<TX_RING_SIZE;j++){
! tdesc = sc->tx_desc + j;
! printf("desc%d: %4d 0x%04x, 0x%08x, 0x%04x %4d, 0x%08x\n",
j,
! tdesc->txlength,tdesc->status,
! tdesc->bufaddr,
! tdesc->control,tdesc->buflength,
! tdesc->next
! );
! }
! printf("tx%d: dumping rx descriptors\n",sc->unit);
! for(j=0;j<RX_RING_SIZE;j++){
! rdesc = sc->rx_desc + j;
! printf("desc%d: %4d 0x%04x, 0x%08x, %4d, 0x%08x\n",
! j,
! rdesc->rxlength,rdesc->status,
! rdesc->bufaddr,
! rdesc->buflength,
! rdesc->next
);
}
#endif
***************
*** 640,667 ****
}
/* UPDATE statistics */
! if (status & (INTSTAT_CNT | INTSTAT_TXU | INTSTAT_OVW | INTSTAT_RXE)) {
/* update dot3 Rx statistics */
! sc->dot3stats.dot3StatsMissedFrames += CSR_READ_1( sc, MPCNT);
! sc->dot3stats.dot3StatsFrameTooLongs += CSR_READ_1( sc, ALICNT);
! sc->dot3stats.dot3StatsFCSErrors += CSR_READ_1( sc, CRCCNT);
/* Update if Rx statistics */
! if (status & (INTSTAT_OVW | INTSTAT_RXE))
sc->epic_if.if_ierrors++;
/* Tx FIFO underflow. */
if (status & INTSTAT_TXU) {
/* Inc. counters */
sc->dot3stats.dot3StatsInternalMacTransmitErrors++;
sc->epic_if.if_oerrors++;
/* Restart the transmit process. */
! CSR_WRITE_4(sc, COMMAND, COMMAND_TXUGO);
}
}
/* If no packets are pending, thus no timeouts */
if( sc->pending_txs == 0 )
sc->epic_if.if_timer = 0;
--- 691,723 ----
}
/* UPDATE statistics */
! if (status & (INTSTAT_CNT | INTSTAT_TXU | INTSTAT_RXE)) {
/* update dot3 Rx statistics */
! sc->dot3stats.dot3StatsMissedFrames += CSR_READ_1(sc, MPCNT);
! sc->dot3stats.dot3StatsFrameTooLongs += CSR_READ_1(sc, ALICNT);
! sc->dot3stats.dot3StatsFCSErrors += CSR_READ_1(sc, CRCCNT);
/* Update if Rx statistics */
! if (status & INTSTAT_RXE) {
! dprintf(("tx%d: CRC/Alignment error\n",sc->unit));
sc->epic_if.if_ierrors++;
+ }
/* Tx FIFO underflow. */
if (status & INTSTAT_TXU) {
+ dprintf(("tx%d: Tx underrun error, restarting tranciever\n",sc->unit));
/* Inc. counters */
sc->dot3stats.dot3StatsInternalMacTransmitErrors++;
sc->epic_if.if_oerrors++;
/* Restart the transmit process. */
! CSR_WRITE_4(sc, COMMAND, COMMAND_TXUGO | COMMAND_TXQUEUED);
}
}
+ if( CSR_READ_4( sc, INTSTAT ) & INTSTAT_INT_ACTV ) goto intloop;
+
/* If no packets are pending, thus no timeouts */
if( sc->pending_txs == 0 )
sc->epic_if.if_timer = 0;
***************
*** 724,741 ****
/* Preinitialize softc structure */
bzero(sc, sizeof(epic_softc_t));
- epics[ unit ] = sc;
sc->unit = unit;
/* Get iobase or membase */
#if defined(EPIC_USEIOSPACE)
if (!pci_map_port(config_id, PCI_CBIO,(u_short *) &(sc->iobase))) {
printf("tx%d: cannot map port\n",unit);
return;
}
#else
if (!pci_map_mem(config_id, PCI_CBMA,(vm_offset_t *) &(sc->csr),(vm_offset_t *) &pmembase)) {
printf("tx%d: cannot map memory\n",unit);
return;
}
#endif
--- 780,798 ----
/* Preinitialize softc structure */
bzero(sc, sizeof(epic_softc_t));
sc->unit = unit;
/* Get iobase or membase */
#if defined(EPIC_USEIOSPACE)
if (!pci_map_port(config_id, PCI_CBIO,(u_short *) &(sc->iobase))) {
printf("tx%d: cannot map port\n",unit);
+ free(sc, M_DEVBUF);
return;
}
#else
if (!pci_map_mem(config_id, PCI_CBMA,(vm_offset_t *) &(sc->csr),(vm_offset_t *) &pmembase)) {
printf("tx%d: cannot map memory\n",unit);
+ free(sc, M_DEVBUF);
return;
}
#endif
***************
*** 764,776 ****
sc->epic_macaddr[0],sc->epic_macaddr[1],sc->epic_macaddr[2],
sc->epic_macaddr[3],sc->epic_macaddr[4],sc->epic_macaddr[5]);
-
s = splimp();
/* Map interrupt */
if( !pci_map_int(config_id, epic_intr_normal, (void*)sc, &net_imask) ) {
printf("tx%d: couldn't map interrupt\n",unit);
- epics[ unit ] = NULL;
free(sc, M_DEVBUF);
return;
}
--- 821,831 ----
***************
*** 867,876 ****
--- 922,934 ----
/* init ifmedia interface */
ifmedia_init(&sc->ifmedia,0,epic_ifmedia_change,epic_ifmedia_status);
ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_10_T,0,NULL);
+ ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_10_T|IFM_LOOP,0,NULL);
ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_10_T|IFM_FDX,0,NULL);
ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_100_TX,0,NULL);
+ ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_100_TX|IFM_LOOP,0,NULL);
ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_100_TX|IFM_FDX,0,NULL);
ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_AUTO,0,NULL);
+ ifmedia_add(&sc->ifmedia,IFM_ETHER|IFM_LOOP,0,NULL);
ifmedia_set(&sc->ifmedia, media);
#endif
***************
*** 884,892 ****
/* Set shut down routine to stop DMA processes on reboot */
at_shutdown(epic_shutdown, sc, SHUTDOWN_POST_SYNC);
! /*
! * Attach to if manager
! */
if_attach(ifp);
ether_ifattach(ifp);
--- 942,948 ----
/* Set shut down routine to stop DMA processes on reboot */
at_shutdown(epic_shutdown, sc, SHUTDOWN_POST_SYNC);
! /* Attach to if manager */
if_attach(ifp);
ether_ifattach(ifp);
***************
*** 937,947 ****
ifmr->ifm_status |= IFM_ACTIVE;
ifmr->ifm_active |= (bmcr&BMCR_100MBPS)?IFM_100_TX:IFM_10_T;
ifmr->ifm_active |= (bmcr&BMCR_FULL_DUPLEX)?IFM_FDX:0;
}
#endif
/*
! * IFINIT function
*
* splimp() invoked here
*/
--- 993,1004 ----
ifmr->ifm_status |= IFM_ACTIVE;
ifmr->ifm_active |= (bmcr&BMCR_100MBPS)?IFM_100_TX:IFM_10_T;
ifmr->ifm_active |= (bmcr&BMCR_FULL_DUPLEX)?IFM_FDX:0;
+ ifmr->ifm_active |= ((CSR_READ_4(sc,TXCON)&TXCON_LOOPBACK_MODE)==TXCON_LOOPBACK_MODE_INT)?IFM_LOOP:0;
}
#endif
/*
! * Reset chip, PHY, allocate rings
*
* splimp() invoked here
*/
***************
*** 979,986 ****
CSR_WRITE_4( sc, LAN1, ((u_int16_t *)sc->epic_macaddr)[1] );
CSR_WRITE_4( sc, LAN2, ((u_int16_t *)sc->epic_macaddr)[2] );
/* Set transmit threshold */
! CSR_WRITE_4( sc, ETXTHR, 0x40 );
/* Compute and set RXCON. */
epic_set_rx_mode( sc );
--- 1036,1045 ----
CSR_WRITE_4( sc, LAN1, ((u_int16_t *)sc->epic_macaddr)[1] );
CSR_WRITE_4( sc, LAN2, ((u_int16_t *)sc->epic_macaddr)[2] );
+ #if defined(EARLY_TX)
/* Set transmit threshold */
! CSR_WRITE_4( sc, ETXTHR, TRANSMIT_THRESHOLD );
! #endif
/* Compute and set RXCON. */
epic_set_rx_mode( sc );
***************
*** 993,1011 ****
epic_set_mc_table( sc );
/* Enable interrupts by setting the interrupt mask. */
! if( QS6612_OUI == sc->phyid ) {
! CSR_WRITE_4( sc, INTMASK,
! INTSTAT_RCC | INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE |
! INTSTAT_TXC | INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |
! INTSTAT_CNT | INTSTAT_GP2 | INTSTAT_FATAL |
! INTSTAT_PTA | INTSTAT_PMA | INTSTAT_APE | INTSTAT_DPE );
! } else {
! CSR_WRITE_4( sc, INTMASK,
! INTSTAT_RCC | INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE |
! INTSTAT_TXC | INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |
! INTSTAT_CNT | INTSTAT_FATAL |
! INTSTAT_PTA | INTSTAT_PMA | INTSTAT_APE | INTSTAT_DPE );
! }
/* Enable interrupts, set for PCI read multiple and etc */
CSR_WRITE_4( sc, GENCTL,
--- 1052,1062 ----
epic_set_mc_table( sc );
/* Enable interrupts by setting the interrupt mask. */
! CSR_WRITE_4( sc, INTMASK,
! INTSTAT_RCC | INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE |
! INTSTAT_TXC | INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |
! INTSTAT_CNT | INTSTAT_FATAL |
! ((QS6612_OUI == sc->phyid)?INTSTAT_GP2:0) );
/* Enable interrupts, set for PCI read multiple and etc */
CSR_WRITE_4( sc, GENCTL,
***************
*** 1027,1057 ****
}
/*
! * This function should set EPIC's registers according IFF_* flags
*/
static void
epic_set_rx_mode(
epic_softc_t * sc)
{
! struct ifnet *ifp = &sc->epic_if;
! u_int16_t rxcon = 0;
! #if NBPFILTER > 0
! if( sc->epic_if.if_flags & IFF_PROMISC )
! rxcon |= RXCON_PROMISCUOUS_MODE;
! #endif
!
! if( sc->epic_if.if_flags & IFF_BROADCAST )
! rxcon |= RXCON_RECEIVE_BROADCAST_FRAMES;
!
! if( sc->epic_if.if_flags & IFF_MULTICAST )
! rxcon |= RXCON_RECEIVE_MULTICAST_FRAMES;
CSR_WRITE_4( sc, RXCON, rxcon );
return;
}
static void
epic_init_phy __P((
epic_softc_t * sc))
--- 1078,1102 ----
}
/*
! * Synopsis: calculate and set Rx mode
*/
static void
epic_set_rx_mode(
epic_softc_t * sc)
{
! u_int32_t flags = sc->epic_if.if_flags;
! u_int32_t rxcon = RXCON_DEFAULT | RXCON_RECEIVE_MULTICAST_FRAMES | RXCON_RECEIVE_BROADCAST_FRAMES;
! rxcon |= (flags & IFF_PROMISC)?RXCON_PROMISCUOUS_MODE:0;
CSR_WRITE_4( sc, RXCON, rxcon );
return;
}
+ /*
+ * Synopsis: Reset PHY and do PHY-special initialization:
+ */
static void
epic_init_phy __P((
epic_softc_t * sc))
***************
*** 1073,1079 ****
CSR_WRITE_4( sc, NVCTL, NVCTL_GP1_OUTPUT_ENABLE );
epic_read_phy_register( sc, QS6612_INTSTAT );
epic_write_phy_register( sc, QS6612_INTMASK,
! INTMASK_THUNDERLAN|INTSTAT_AN_COMPLETE );
break;
default:
break;
--- 1118,1128 ----
CSR_WRITE_4( sc, NVCTL, NVCTL_GP1_OUTPUT_ENABLE );
epic_read_phy_register( sc, QS6612_INTSTAT );
epic_write_phy_register( sc, QS6612_INTMASK,
! INTMASK_THUNDERLAN | INTSTAT_AN_COMPLETE );
!
! /* Enable QS6612 extended cable length capabilites */
! epic_write_phy_register( sc, QS6612_MCTL, epic_read_phy_register( sc,QS6612_MCTL ) | MCTL_BTEXT );
!
break;
default:
break;
***************
*** 1081,1087 ****
}
/*
! * This function should set MII to mode specified by IFF_LINK* flags or
* ifmedia structure.
*/
static void
--- 1130,1136 ----
}
/*
! * Synopsis: Set PHY to media type specified by IFF_LINK* flags or
* ifmedia structure.
*/
static void
***************
*** 1108,1114 ****
epic_write_phy_register( sc, DP83840_BMCR, media );
! CSR_WRITE_4( sc, TXCON,(tgtmedia&IFM_FDX)?TXCON_LOOPBACK_MODE_FULL_DUPLEX|TXCON_DEFAULT:TXCON_DEFAULT );
}
#else
if( ifp->if_flags & IFF_LINK0 ) {
--- 1157,1167 ----
epic_write_phy_register( sc, DP83840_BMCR, media );
! media = TXCON_DEFAULT;
! if( tgtmedia & IFM_FDX ) media |= TXCON_FULL_DUPLEX;
! else if( tgtmedia & IFM_LOOP ) media |= TXCON_LOOPBACK_MODE_INT;
!
! CSR_WRITE_4( sc, TXCON, media );
}
#else
if( ifp->if_flags & IFF_LINK0 ) {
***************
*** 1121,1127 ****
epic_write_phy_register( sc, DP83840_BMCR, media );
! CSR_WRITE_4( sc, TXCON, (ifp->if_flags & IFF_LINK2) ? TXCON_LOOPBACK_MODE_FULL_DUPLEX|TXCON_DEFAULT : TXCON_DEFAULT );
}
#endif
else {
--- 1174,1183 ----
epic_write_phy_register( sc, DP83840_BMCR, media );
! media = TXCON_DEFAULT;
! media |= (ifp->if_flags&IFF_LINK2)?TXCON_FULL_DUPLEX:0;
!
! CSR_WRITE_4( sc, TXCON, media );
}
#endif
else {
***************
*** 1142,1149 ****
DELAY(3000000);
if( epic_autoneg(sc) == EPIC_FULL_DUPLEX )
! CSR_WRITE_4( sc, TXCON,
! TXCON_LOOPBACK_MODE_FULL_DUPLEX|TXCON_DEFAULT);
}
/* Else it will be done when GP2 int occured */
}
--- 1198,1204 ----
DELAY(3000000);
if( epic_autoneg(sc) == EPIC_FULL_DUPLEX )
! CSR_WRITE_4( sc, TXCON, TXCON_FULL_DUPLEX|TXCON_DEFAULT);
}
/* Else it will be done when GP2 int occured */
}
***************
*** 1258,1264 ****
}
/*
! * This function should completely stop rx and tx processes
*
* splimp() invoked here
*/
--- 1313,1320 ----
}
/*
! * Synopsis: Completely stop Rx and Tx processes, and deallocate rings. If
! * TQE is set, additional packet needs to be queued to stop Tx DMA.
*
* splimp() invoked here
*/
***************
*** 1268,1305 ****
{
int i,s;
s = splimp();
sc->epic_if.if_timer = 0;
! /* Disable interrupts, stop processes */
CSR_WRITE_4( sc, INTMASK, 0 );
CSR_WRITE_4( sc, GENCTL, 0 );
- CSR_WRITE_4( sc, COMMAND,
- COMMAND_STOP_RX | COMMAND_STOP_RDMA | COMMAND_STOP_TDMA );
! /* Wait RX and TX DMA to stop */
! for(i=0;i<0x100000;i++){
! if( (CSR_READ_4(sc,INTSTAT)&(INTSTAT_RXIDLE|INTSTAT_TXIDLE)) ==
! (INTSTAT_RXIDLE|INTSTAT_TXIDLE) ) break;
! }
!
! if( !(CSR_READ_4(sc,INTSTAT)&INTSTAT_RXIDLE) )
printf("tx%d: can't stop RX DMA\n",sc->unit);
! if( !(CSR_READ_4(sc,INTSTAT)&INTSTAT_TXIDLE) )
! printf("tx%d: can't stop TX DMA\n",sc->unit);
! /* Reset chip and phy */
CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET );
/* Need to wait for 15 pci ticks to pass before accessing again*/
DELAY(1);
/* Free memory allocated for rings */
epic_free_rings( sc );
splx(s);
}
/*
--- 1324,1392 ----
{
int i,s;
+ dprintf(("tx%d: epic_stop(): enter\n",sc->unit));
+
s = splimp();
sc->epic_if.if_timer = 0;
! /* Disable interrupts */
CSR_WRITE_4( sc, INTMASK, 0 );
CSR_WRITE_4( sc, GENCTL, 0 );
! /* Stop Tx and Rx DMA */
! CSR_WRITE_4( sc, COMMAND, COMMAND_STOP_RX | COMMAND_STOP_RDMA | COMMAND_STOP_TDMA);
!
! dprintf(("tx%d: waiting Rx DMA to stop\n",sc->unit));
! /* Wait only Rx DMA */
! for(i=0;i<0x100000;i++)
! if( (CSR_READ_4(sc,INTSTAT)&INTSTAT_RXIDLE) == INTSTAT_RXIDLE ) break;
!
! if( !(CSR_READ_4(sc,INTSTAT)&INTSTAT_RXIDLE) )
printf("tx%d: can't stop RX DMA\n",sc->unit);
+ else
+ dprintf(("tx%d: Rx DMA stoped\n",sc->unit));
+
+ /* May need to queue one more packet if TQE */
+ if( (CSR_READ_4( sc, INTSTAT ) & INTSTAT_TQE) &&
+ !(CSR_READ_4( sc, INTSTAT ) & INTSTAT_TXIDLE) ){
+ dprintf(("tx%d: epic_stop(): queue last packet\n",sc->unit));
+
+ /* Turn it to loopback mode */
+ CSR_WRITE_4( sc, TXCON, TXCON_DEFAULT | TXCON_LOOPBACK_MODE_INT );
+
+ sc->tx_desc[sc->cur_tx].bufaddr = vtophys( sc );
+ sc->tx_desc[sc->cur_tx].buflength = ETHER_MIN_LEN-ETHER_CRC_LEN;
+ sc->tx_desc[sc->cur_tx].control = 0x14;
+ sc->tx_desc[sc->cur_tx].txlength = ETHER_MIN_LEN-ETHER_CRC_LEN;
+ sc->tx_desc[sc->cur_tx].status = 0x8000;
+
+ CSR_WRITE_4( sc, COMMAND, COMMAND_TXQUEUED );
! dprintf(("tx%d: waiting Tx DMA to stop\n",sc->unit));
! /* Wait TX DMA to stop */
! for(i=0;i<0x100000;i++)
! if( (CSR_READ_4(sc,INTSTAT)&INTSTAT_TXIDLE) == INTSTAT_TXIDLE ) break;
! if( !(CSR_READ_4(sc,INTSTAT)&INTSTAT_TXIDLE) )
! printf("tx%d: can't stop TX DMA\n",sc->unit);
! else
! dprintf(("tx%d: Tx DMA stoped\n",sc->unit));
! } else
! dprintf(("tx%d: Tx DMA stoped\n",sc->unit));
!
! /* Reset chip */
CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET );
/* Need to wait for 15 pci ticks to pass before accessing again*/
DELAY(1);
+ dprintf(("tx%d: deallocate rings\n",sc->unit));
/* Free memory allocated for rings */
epic_free_rings( sc );
splx(s);
+ dprintf(("tx%d: epic_stop(): done\n",sc->unit));
}
/*
***************
*** 1312,1317 ****
--- 1399,1406 ----
epic_free_rings(epic_softc_t * sc){
int i;
+ dprintf(("tx%d: epic_free_rings(): enter\n",sc->unit));
+
for(i=0;i<RX_RING_SIZE;i++){
struct epic_rx_buffer *buf = sc->rx_buffer + i;
struct epic_rx_desc *desc = sc->rx_desc + i;
***************
*** 1345,1350 ****
--- 1434,1441 ----
buf->data = NULL;
#endif
}
+
+ dprintf(("tx%d: epic_free_rings(): done\n",sc->unit));
}
/*
***************
*** 1382,1388 ****
if( NULL == (buf->mbuf->m_flags & M_EXT) ) return -1;
desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) );
#else
! buf->data = malloc(ETHER_MAX_FRAME_LEN, M_DEVBUF, M_NOWAIT);
if( buf->data == NULL ) return -1;
desc->bufaddr = vtophys( buf->data );
#endif
--- 1473,1479 ----
if( NULL == (buf->mbuf->m_flags & M_EXT) ) return -1;
desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) );
#else
! buf->data = malloc( ETHER_MAX_FRAME_LEN, M_DEVBUF, M_NOWAIT);
if( buf->data == NULL ) return -1;
desc->bufaddr = vtophys( buf->data );
#endif
*** smc83c170.h.orig Tue May 5 18:21:30 1998
--- smc83c170.h Tue May 5 18:10:43 1998
***************
*** 180,190 ****
#define TXCON_LOOPBACK_DISABLE 0x00000000
#define TXCON_LOOPBACK_MODE_INT 0x00000002
#define TXCON_LOOPBACK_MODE_PHY 0x00000004
! #define TXCON_LOOPBACK_MODE_FULL_DUPLEX 0x00000006
#define TXCON_SLOT_TIME 0x00000078
! #define TXCON_DEFAULT (TXCON_SLOT_TIME|TXCON_EARLY_TRANSMIT_ENABLE)
!
/*
* National Semiconductor's DP83840A Registers and bits
*/
--- 180,200 ----
#define TXCON_LOOPBACK_DISABLE 0x00000000
#define TXCON_LOOPBACK_MODE_INT 0x00000002
#define TXCON_LOOPBACK_MODE_PHY 0x00000004
! #define TXCON_LOOPBACK_MODE 0x00000006
! #define TXCON_FULL_DUPLEX 0x00000006
#define TXCON_SLOT_TIME 0x00000078
! #if defined(EARLY_TX)
! #define TXCON_DEFAULT (TXCON_SLOT_TIME | TXCON_EARLY_TRANSMIT_ENABLE)
! #define TRANSMIT_THRESHOLD 0x40
! #else
! #define TXCON_DEFAULT (TXCON_SLOT_TIME)
! #endif
! #if defined(EARLY_RX)
! #define RXCON_DEFAULT (RXCON_EARLY_RECEIVE_ENABLE | RXCON_SAVE_ERRORED_PACKETS)
! #else
! #define RXCON_DEFAULT (0)
! #endif
/*
* National Semiconductor's DP83840A Registers and bits
*/
***************
*** 228,236 ****
--- 238,252 ----
* Quality Semiconductor's QS6612 registers and bits
*/
#define QS6612_OUI 0x006051
+ #define QS6612_MCTL 17
#define QS6612_INTSTAT 29
#define QS6612_INTMASK 30
+ #define MCTL_T4_PRESENT 0x1000 /* External T4 Enabled, ignored */
+ /* if AutoNeg is enabled */
+ #define MCTL_BTEXT 0x0800 /* Reduces 10baset squelch level */
+ /* for extended cable length */
+
#define INTSTAT_AN_COMPLETE 0x40 /* Autonegotiation complete */
#define INTSTAT_RF_DETECTED 0x20 /* Remote Fault detected */
#define INTSTAT_LINK_STATUS 0x10 /* Link status changed */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.980505183656.13866C-200000>
