Add support for SMC9432FTX card, possibly othe fiber optic SMC9432 family
cards will work too.
This commit is contained in:
parent
e472dcaec2
commit
b3d64495b9
@ -75,6 +75,9 @@
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
#include <dev/mii/miidevs.h>
|
||||
|
||||
#include <dev/mii/lxtphyreg.h>
|
||||
|
||||
#include "miibus_if.h"
|
||||
|
||||
@ -116,6 +119,8 @@
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
#include <dev/mii/miidevs.h>
|
||||
#include <dev/mii/lxtphyreg.h>
|
||||
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
@ -546,7 +551,7 @@ epic_freebsd_attach(dev)
|
||||
if( ' ' == (u_int8_t)tmp ) break;
|
||||
printf("%c",(u_int8_t)tmp);
|
||||
}
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
|
||||
/* Attach to OS's managers */
|
||||
ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
|
||||
@ -779,14 +784,24 @@ epic_common_attach(sc)
|
||||
/* Set defaults */
|
||||
sc->tx_threshold = TRANSMIT_THRESHOLD;
|
||||
sc->txcon = TXCON_DEFAULT;
|
||||
sc->miicfg = MIICFG_SMI_ENABLE;
|
||||
sc->phyid = EPIC_UNKN_PHY;
|
||||
sc->serinst = -1;
|
||||
|
||||
/* Fetch card id */
|
||||
sc->cardvend = pci_read_config(sc->dev, PCIR_SUBVEND_0, 2);
|
||||
sc->cardid = pci_read_config(sc->dev, PCIR_SUBDEV_0, 2);
|
||||
|
||||
if (sc->cardvend != SMC_VENDORID)
|
||||
printf(EPIC_FORMAT ": unknown card vendor 0x%04x\n", EPIC_ARGS(sc), sc->cardvend);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is if_start handler. It takes mbufs from if_snd queue
|
||||
* and quque them for transmit, one by one, until TX ring become full
|
||||
* or quque become empty.
|
||||
* and queue them for transmit, one by one, until TX ring become full
|
||||
* or queue become empty.
|
||||
*/
|
||||
static void
|
||||
epic_ifstart(ifp)
|
||||
@ -1127,39 +1142,124 @@ epic_ifmedia_upd(ifp)
|
||||
epic_softc_t *sc;
|
||||
struct mii_data *mii;
|
||||
struct ifmedia *ifm;
|
||||
struct mii_softc *miisc;
|
||||
int cfg, media;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->miibus);
|
||||
ifm = &mii->mii_media;
|
||||
media = ifm->ifm_cur->ifm_media;
|
||||
|
||||
/* Do not do anything if interface is not up */
|
||||
if(!(ifp->if_flags & IFF_UP))
|
||||
return (0);
|
||||
|
||||
if((IFM_INST(ifm->ifm_cur->ifm_media) == mii->mii_instance) &&
|
||||
(IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_10_2)) {
|
||||
/* Call this, to isolate (and powerdown ?) all PHYs */
|
||||
mii_mediachg(mii);
|
||||
/*
|
||||
* Lookup current selected PHY
|
||||
*/
|
||||
if (IFM_INST(media) == sc->serinst) {
|
||||
sc->phyid = EPIC_SERIAL;
|
||||
sc->physc = NULL;
|
||||
} else {
|
||||
/* If we're not selecting serial interface, select MII mode */
|
||||
sc->miicfg &= ~MIICFG_SERIAL_ENABLE;
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
|
||||
/* Select BNC */
|
||||
CSR_WRITE_4(sc, MIICFG, MIICFG_SERIAL_ENABLE |
|
||||
MIICFG_694_ENABLE | MIICFG_SMI_ENABLE);
|
||||
dprintf((EPIC_FORMAT ": MII selected\n", EPIC_ARGS(sc)));
|
||||
|
||||
/* Update txcon register */
|
||||
epic_miibus_statchg(sc->dev);
|
||||
/* Default to unknown PHY */
|
||||
sc->phyid = EPIC_UNKN_PHY;
|
||||
|
||||
return (0);
|
||||
} else if(IFM_INST(ifm->ifm_cur->ifm_media) < mii->mii_instance) {
|
||||
/* Select MII */
|
||||
CSR_WRITE_4(sc, MIICFG, MIICFG_SMI_ENABLE);
|
||||
/* Lookup selected PHY */
|
||||
for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
|
||||
miisc = LIST_NEXT(miisc, mii_list)) {
|
||||
if (IFM_INST(media) == miisc->mii_inst) {
|
||||
sc->physc = miisc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give it to miibus... */
|
||||
mii_mediachg(mii);
|
||||
/* Identify selected PHY */
|
||||
if (sc->physc) {
|
||||
int id1, id2, model, oui;
|
||||
|
||||
return (0);
|
||||
id1 = PHY_READ(sc->physc, MII_PHYIDR1);
|
||||
id2 = PHY_READ(sc->physc, MII_PHYIDR2);
|
||||
|
||||
oui = MII_OUI(id1, id2);
|
||||
model = MII_MODEL(id2);
|
||||
switch (oui) {
|
||||
case MII_OUI_QUALSEMI:
|
||||
if (model == MII_MODEL_QUALSEMI_QS6612)
|
||||
sc->phyid = EPIC_QS6612_PHY;
|
||||
break;
|
||||
case MII_OUI_xxALTIMA:
|
||||
if (model == MII_MODEL_xxALTIMA_AC101)
|
||||
sc->phyid = EPIC_AC101_PHY;
|
||||
break;
|
||||
case MII_OUI_xxLEVEL1:
|
||||
if (model == MII_MODEL_xxLEVEL1_LXT970)
|
||||
sc->phyid = EPIC_LXT970_PHY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(EINVAL);
|
||||
/*
|
||||
* Do PHY specific card setup
|
||||
*/
|
||||
|
||||
/* Call this, to isolate all not selected PHYs and
|
||||
* set up selected
|
||||
*/
|
||||
mii_mediachg(mii);
|
||||
|
||||
/* Do our own setup */
|
||||
switch (sc->phyid) {
|
||||
case EPIC_QS6612_PHY:
|
||||
break;
|
||||
case EPIC_AC101_PHY:
|
||||
/* We have to powerup fiber tranceivers */
|
||||
if (IFM_SUBTYPE(media) == IFM_100_FX)
|
||||
sc->miicfg |= MIICFG_694_ENABLE;
|
||||
else
|
||||
sc->miicfg &= ~MIICFG_694_ENABLE;
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
|
||||
break;
|
||||
case EPIC_LXT970_PHY:
|
||||
/* We have to powerup fiber tranceivers */
|
||||
cfg = PHY_READ(sc->physc, MII_LXTPHY_CONFIG);
|
||||
if (IFM_SUBTYPE(media) == IFM_100_FX)
|
||||
cfg |= CONFIG_LEDC1 | CONFIG_LEDC0;
|
||||
else
|
||||
cfg &= ~(CONFIG_LEDC1 | CONFIG_LEDC0);
|
||||
PHY_WRITE(sc->physc, MII_LXTPHY_CONFIG, cfg);
|
||||
|
||||
break;
|
||||
case EPIC_SERIAL:
|
||||
/* Select serial PHY, (10base2/BNC usually) */
|
||||
sc->miicfg |= MIICFG_694_ENABLE | MIICFG_SERIAL_ENABLE;
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
|
||||
/* There is no driver to fill this */
|
||||
mii->mii_media_active = media;
|
||||
mii->mii_media_status = 0;
|
||||
|
||||
/* We need to call this manualy as i wasn't called
|
||||
* in mii_mediachg()
|
||||
*/
|
||||
epic_miibus_statchg(sc->dev);
|
||||
|
||||
dprintf((EPIC_FORMAT ": SERIAL selected\n", EPIC_ARGS(sc)));
|
||||
|
||||
break;
|
||||
default:
|
||||
printf(EPIC_FORMAT ": ERROR! Unknown PHY selected\n", EPIC_ARGS(sc));
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1178,6 +1278,7 @@ epic_ifmedia_sts(ifp, ifmr)
|
||||
mii = device_get_softc(sc->miibus);
|
||||
ifm = &mii->mii_media;
|
||||
|
||||
/* Nothing should be selected if interface is down */
|
||||
if(!(ifp->if_flags & IFF_UP)) {
|
||||
ifmr->ifm_active = IFM_NONE;
|
||||
ifmr->ifm_status = 0;
|
||||
@ -1185,18 +1286,13 @@ epic_ifmedia_sts(ifp, ifmr)
|
||||
return;
|
||||
}
|
||||
|
||||
if((IFM_INST(ifm->ifm_cur->ifm_media) == mii->mii_instance) &&
|
||||
(IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_10_2)) {
|
||||
ifmr->ifm_active = ifm->ifm_cur->ifm_media;
|
||||
ifmr->ifm_status = 0;
|
||||
} else if(IFM_INST(ifm->ifm_cur->ifm_media) < mii->mii_instance) {
|
||||
/* Call underlying pollstat, if not serial PHY */
|
||||
if (sc->phyid != EPIC_SERIAL)
|
||||
mii_pollstat(mii);
|
||||
ifmr->ifm_active = mii->mii_media_active;
|
||||
ifmr->ifm_status = mii->mii_media_status;
|
||||
} else {
|
||||
ifmr->ifm_active = IFM_NONE;
|
||||
ifmr->ifm_status = 0;
|
||||
}
|
||||
|
||||
/* Simply copy media info */
|
||||
ifmr->ifm_active = mii->mii_media_active;
|
||||
ifmr->ifm_status = mii->mii_media_status;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1210,20 +1306,34 @@ epic_miibus_statchg(dev)
|
||||
{
|
||||
epic_softc_t *sc;
|
||||
struct mii_data *mii;
|
||||
int media;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mii = device_get_softc(sc->miibus);
|
||||
media = mii->mii_media_active;
|
||||
|
||||
sc->txcon &= ~(TXCON_LOOPBACK_MODE | TXCON_FULL_DUPLEX);
|
||||
|
||||
/*
|
||||
* If we are in full-duplex mode or loopback operation,
|
||||
/* If we are in full-duplex mode or loopback operation,
|
||||
* we need to decouple receiver and transmitter.
|
||||
*/
|
||||
if (mii->mii_media_active & (IFM_FDX | IFM_LOOP))
|
||||
if (IFM_OPTIONS(media) & (IFM_FDX | IFM_LOOP))
|
||||
sc->txcon |= TXCON_FULL_DUPLEX;
|
||||
|
||||
if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX)
|
||||
/* On some cards we need manualy set fullduplex led */
|
||||
if (sc->cardid == SMC9432FTX ||
|
||||
sc->cardid == SMC9432FTX_SC) {
|
||||
if (IFM_OPTIONS(media) & IFM_FDX)
|
||||
sc->miicfg |= MIICFG_694_ENABLE;
|
||||
else
|
||||
sc->miicfg &= ~MIICFG_694_ENABLE;
|
||||
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
}
|
||||
|
||||
/* Update baudrate */
|
||||
if (IFM_SUBTYPE(media) == IFM_100_TX &&
|
||||
IFM_SUBTYPE(media) == IFM_100_FX)
|
||||
sc->sc_if.if_baudrate = 100000000;
|
||||
else
|
||||
sc->sc_if.if_baudrate = 10000000;
|
||||
@ -1233,22 +1343,32 @@ epic_miibus_statchg(dev)
|
||||
return;
|
||||
}
|
||||
|
||||
static void epic_miibus_mediainit(dev)
|
||||
static void
|
||||
epic_miibus_mediainit(dev)
|
||||
device_t dev;
|
||||
{
|
||||
epic_softc_t *sc;
|
||||
struct mii_data *mii;
|
||||
struct ifmedia *ifm;
|
||||
int media;
|
||||
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mii = device_get_softc(sc->miibus);
|
||||
ifm = &mii->mii_media;
|
||||
|
||||
/* Add Serial Media Interface if present, this applies to
|
||||
* SMC9432BTX serie
|
||||
*/
|
||||
if(CSR_READ_4(sc, MIICFG) & MIICFG_PHY_PRESENT) {
|
||||
media = IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, mii->mii_instance);
|
||||
printf(EPIC_FORMAT ": serial PHY detected (10Base2/BNC)\n",EPIC_ARGS(sc));
|
||||
/* Store its instance */
|
||||
sc->serinst = mii->mii_instance++;
|
||||
|
||||
/* Add as 10base2/BNC media */
|
||||
media = IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc->serinst);
|
||||
ifmedia_add(ifm, media, 0, NULL);
|
||||
|
||||
/* Report to user */
|
||||
printf(EPIC_FORMAT ": serial PHY detected (10Base2/BNC)\n",EPIC_ARGS(sc));
|
||||
}
|
||||
|
||||
return;
|
||||
@ -1317,10 +1437,13 @@ epic_init(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_RCC | /* INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE | */
|
||||
/* INTSTAT_TXC | */ INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |
|
||||
INTSTAT_FATAL);
|
||||
|
||||
/* Acknowledge all pending interrupts */
|
||||
CSR_WRITE_4(sc, INTSTAT, CSR_READ_4(sc, INTSTAT));
|
||||
|
||||
/* Enable interrupts, set for PCI read multiple and etc */
|
||||
CSR_WRITE_4( sc, GENCTL,
|
||||
GENCTL_ENABLE_INTERRUPT | GENCTL_MEMORY_READ_MULTIPLE |
|
||||
|
@ -257,6 +257,26 @@ struct epic_tx_buffer {
|
||||
* epic_rx_desc, epic_tx_desc, epic_frag_list - must be aligned on dword
|
||||
*/
|
||||
|
||||
/* PHY, known by tx driver */
|
||||
#define EPIC_UNKN_PHY 0x0000
|
||||
#define EPIC_QS6612_PHY 0x0001
|
||||
#define EPIC_AC101_PHY 0x0002
|
||||
#define EPIC_LXT970_PHY 0x0003
|
||||
#define EPIC_SERIAL 0x0004
|
||||
|
||||
#define SMC9432DMT 0xA010
|
||||
#define SMC9432TX 0xA011
|
||||
#define SMC9032TXM 0xA012
|
||||
#define SMC9032TX 0xA013
|
||||
#define SMC9432TXPWR 0xA014
|
||||
#define SMC9432BTX 0xA015
|
||||
#define SMC9432FTX 0xA016
|
||||
#define SMC9432FTX_SC 0xA017
|
||||
#define SMC9432TX_XG_ADHOC 0xA020
|
||||
#define SMC9434TX_XG_ADHOC 0xA021
|
||||
#define SMC9432FTX_ADHOC 0xA022
|
||||
#define SMC9432BTX1 0xA024
|
||||
|
||||
/* Driver status structure */
|
||||
typedef struct {
|
||||
struct arpcom arpcom;
|
||||
@ -288,11 +308,16 @@ typedef struct {
|
||||
u_int32_t flags;
|
||||
u_int32_t tx_threshold;
|
||||
u_int32_t txcon;
|
||||
u_int32_t phyid;
|
||||
u_int32_t miicfg;
|
||||
u_int32_t cur_tx;
|
||||
u_int32_t cur_rx;
|
||||
u_int32_t dirty_tx;
|
||||
u_int32_t pending_txs;
|
||||
u_int16_t cardvend;
|
||||
u_int16_t cardid;
|
||||
struct mii_softc *physc;
|
||||
u_int32_t phyid;
|
||||
int serinst;
|
||||
void *pool;
|
||||
} epic_softc_t;
|
||||
|
||||
|
@ -257,6 +257,26 @@ struct epic_tx_buffer {
|
||||
* epic_rx_desc, epic_tx_desc, epic_frag_list - must be aligned on dword
|
||||
*/
|
||||
|
||||
/* PHY, known by tx driver */
|
||||
#define EPIC_UNKN_PHY 0x0000
|
||||
#define EPIC_QS6612_PHY 0x0001
|
||||
#define EPIC_AC101_PHY 0x0002
|
||||
#define EPIC_LXT970_PHY 0x0003
|
||||
#define EPIC_SERIAL 0x0004
|
||||
|
||||
#define SMC9432DMT 0xA010
|
||||
#define SMC9432TX 0xA011
|
||||
#define SMC9032TXM 0xA012
|
||||
#define SMC9032TX 0xA013
|
||||
#define SMC9432TXPWR 0xA014
|
||||
#define SMC9432BTX 0xA015
|
||||
#define SMC9432FTX 0xA016
|
||||
#define SMC9432FTX_SC 0xA017
|
||||
#define SMC9432TX_XG_ADHOC 0xA020
|
||||
#define SMC9434TX_XG_ADHOC 0xA021
|
||||
#define SMC9432FTX_ADHOC 0xA022
|
||||
#define SMC9432BTX1 0xA024
|
||||
|
||||
/* Driver status structure */
|
||||
typedef struct {
|
||||
struct arpcom arpcom;
|
||||
@ -288,11 +308,16 @@ typedef struct {
|
||||
u_int32_t flags;
|
||||
u_int32_t tx_threshold;
|
||||
u_int32_t txcon;
|
||||
u_int32_t phyid;
|
||||
u_int32_t miicfg;
|
||||
u_int32_t cur_tx;
|
||||
u_int32_t cur_rx;
|
||||
u_int32_t dirty_tx;
|
||||
u_int32_t pending_txs;
|
||||
u_int16_t cardvend;
|
||||
u_int16_t cardid;
|
||||
struct mii_softc *physc;
|
||||
u_int32_t phyid;
|
||||
int serinst;
|
||||
void *pool;
|
||||
} epic_softc_t;
|
||||
|
||||
|
205
sys/pci/if_tx.c
205
sys/pci/if_tx.c
@ -75,6 +75,9 @@
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
#include <dev/mii/miidevs.h>
|
||||
|
||||
#include <dev/mii/lxtphyreg.h>
|
||||
|
||||
#include "miibus_if.h"
|
||||
|
||||
@ -116,6 +119,8 @@
|
||||
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
#include <dev/mii/miidevs.h>
|
||||
#include <dev/mii/lxtphyreg.h>
|
||||
|
||||
#include <dev/pci/pcivar.h>
|
||||
#include <dev/pci/pcireg.h>
|
||||
@ -546,7 +551,7 @@ epic_freebsd_attach(dev)
|
||||
if( ' ' == (u_int8_t)tmp ) break;
|
||||
printf("%c",(u_int8_t)tmp);
|
||||
}
|
||||
printf ("\n");
|
||||
printf("\n");
|
||||
|
||||
/* Attach to OS's managers */
|
||||
ether_ifattach(ifp, ETHER_BPF_SUPPORTED);
|
||||
@ -779,14 +784,24 @@ epic_common_attach(sc)
|
||||
/* Set defaults */
|
||||
sc->tx_threshold = TRANSMIT_THRESHOLD;
|
||||
sc->txcon = TXCON_DEFAULT;
|
||||
sc->miicfg = MIICFG_SMI_ENABLE;
|
||||
sc->phyid = EPIC_UNKN_PHY;
|
||||
sc->serinst = -1;
|
||||
|
||||
/* Fetch card id */
|
||||
sc->cardvend = pci_read_config(sc->dev, PCIR_SUBVEND_0, 2);
|
||||
sc->cardid = pci_read_config(sc->dev, PCIR_SUBDEV_0, 2);
|
||||
|
||||
if (sc->cardvend != SMC_VENDORID)
|
||||
printf(EPIC_FORMAT ": unknown card vendor 0x%04x\n", EPIC_ARGS(sc), sc->cardvend);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is if_start handler. It takes mbufs from if_snd queue
|
||||
* and quque them for transmit, one by one, until TX ring become full
|
||||
* or quque become empty.
|
||||
* and queue them for transmit, one by one, until TX ring become full
|
||||
* or queue become empty.
|
||||
*/
|
||||
static void
|
||||
epic_ifstart(ifp)
|
||||
@ -1127,39 +1142,124 @@ epic_ifmedia_upd(ifp)
|
||||
epic_softc_t *sc;
|
||||
struct mii_data *mii;
|
||||
struct ifmedia *ifm;
|
||||
struct mii_softc *miisc;
|
||||
int cfg, media;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->miibus);
|
||||
ifm = &mii->mii_media;
|
||||
media = ifm->ifm_cur->ifm_media;
|
||||
|
||||
/* Do not do anything if interface is not up */
|
||||
if(!(ifp->if_flags & IFF_UP))
|
||||
return (0);
|
||||
|
||||
if((IFM_INST(ifm->ifm_cur->ifm_media) == mii->mii_instance) &&
|
||||
(IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_10_2)) {
|
||||
/* Call this, to isolate (and powerdown ?) all PHYs */
|
||||
mii_mediachg(mii);
|
||||
/*
|
||||
* Lookup current selected PHY
|
||||
*/
|
||||
if (IFM_INST(media) == sc->serinst) {
|
||||
sc->phyid = EPIC_SERIAL;
|
||||
sc->physc = NULL;
|
||||
} else {
|
||||
/* If we're not selecting serial interface, select MII mode */
|
||||
sc->miicfg &= ~MIICFG_SERIAL_ENABLE;
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
|
||||
/* Select BNC */
|
||||
CSR_WRITE_4(sc, MIICFG, MIICFG_SERIAL_ENABLE |
|
||||
MIICFG_694_ENABLE | MIICFG_SMI_ENABLE);
|
||||
dprintf((EPIC_FORMAT ": MII selected\n", EPIC_ARGS(sc)));
|
||||
|
||||
/* Update txcon register */
|
||||
epic_miibus_statchg(sc->dev);
|
||||
/* Default to unknown PHY */
|
||||
sc->phyid = EPIC_UNKN_PHY;
|
||||
|
||||
return (0);
|
||||
} else if(IFM_INST(ifm->ifm_cur->ifm_media) < mii->mii_instance) {
|
||||
/* Select MII */
|
||||
CSR_WRITE_4(sc, MIICFG, MIICFG_SMI_ENABLE);
|
||||
/* Lookup selected PHY */
|
||||
for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
|
||||
miisc = LIST_NEXT(miisc, mii_list)) {
|
||||
if (IFM_INST(media) == miisc->mii_inst) {
|
||||
sc->physc = miisc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Give it to miibus... */
|
||||
mii_mediachg(mii);
|
||||
/* Identify selected PHY */
|
||||
if (sc->physc) {
|
||||
int id1, id2, model, oui;
|
||||
|
||||
return (0);
|
||||
id1 = PHY_READ(sc->physc, MII_PHYIDR1);
|
||||
id2 = PHY_READ(sc->physc, MII_PHYIDR2);
|
||||
|
||||
oui = MII_OUI(id1, id2);
|
||||
model = MII_MODEL(id2);
|
||||
switch (oui) {
|
||||
case MII_OUI_QUALSEMI:
|
||||
if (model == MII_MODEL_QUALSEMI_QS6612)
|
||||
sc->phyid = EPIC_QS6612_PHY;
|
||||
break;
|
||||
case MII_OUI_xxALTIMA:
|
||||
if (model == MII_MODEL_xxALTIMA_AC101)
|
||||
sc->phyid = EPIC_AC101_PHY;
|
||||
break;
|
||||
case MII_OUI_xxLEVEL1:
|
||||
if (model == MII_MODEL_xxLEVEL1_LXT970)
|
||||
sc->phyid = EPIC_LXT970_PHY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(EINVAL);
|
||||
/*
|
||||
* Do PHY specific card setup
|
||||
*/
|
||||
|
||||
/* Call this, to isolate all not selected PHYs and
|
||||
* set up selected
|
||||
*/
|
||||
mii_mediachg(mii);
|
||||
|
||||
/* Do our own setup */
|
||||
switch (sc->phyid) {
|
||||
case EPIC_QS6612_PHY:
|
||||
break;
|
||||
case EPIC_AC101_PHY:
|
||||
/* We have to powerup fiber tranceivers */
|
||||
if (IFM_SUBTYPE(media) == IFM_100_FX)
|
||||
sc->miicfg |= MIICFG_694_ENABLE;
|
||||
else
|
||||
sc->miicfg &= ~MIICFG_694_ENABLE;
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
|
||||
break;
|
||||
case EPIC_LXT970_PHY:
|
||||
/* We have to powerup fiber tranceivers */
|
||||
cfg = PHY_READ(sc->physc, MII_LXTPHY_CONFIG);
|
||||
if (IFM_SUBTYPE(media) == IFM_100_FX)
|
||||
cfg |= CONFIG_LEDC1 | CONFIG_LEDC0;
|
||||
else
|
||||
cfg &= ~(CONFIG_LEDC1 | CONFIG_LEDC0);
|
||||
PHY_WRITE(sc->physc, MII_LXTPHY_CONFIG, cfg);
|
||||
|
||||
break;
|
||||
case EPIC_SERIAL:
|
||||
/* Select serial PHY, (10base2/BNC usually) */
|
||||
sc->miicfg |= MIICFG_694_ENABLE | MIICFG_SERIAL_ENABLE;
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
|
||||
/* There is no driver to fill this */
|
||||
mii->mii_media_active = media;
|
||||
mii->mii_media_status = 0;
|
||||
|
||||
/* We need to call this manualy as i wasn't called
|
||||
* in mii_mediachg()
|
||||
*/
|
||||
epic_miibus_statchg(sc->dev);
|
||||
|
||||
dprintf((EPIC_FORMAT ": SERIAL selected\n", EPIC_ARGS(sc)));
|
||||
|
||||
break;
|
||||
default:
|
||||
printf(EPIC_FORMAT ": ERROR! Unknown PHY selected\n", EPIC_ARGS(sc));
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1178,6 +1278,7 @@ epic_ifmedia_sts(ifp, ifmr)
|
||||
mii = device_get_softc(sc->miibus);
|
||||
ifm = &mii->mii_media;
|
||||
|
||||
/* Nothing should be selected if interface is down */
|
||||
if(!(ifp->if_flags & IFF_UP)) {
|
||||
ifmr->ifm_active = IFM_NONE;
|
||||
ifmr->ifm_status = 0;
|
||||
@ -1185,18 +1286,13 @@ epic_ifmedia_sts(ifp, ifmr)
|
||||
return;
|
||||
}
|
||||
|
||||
if((IFM_INST(ifm->ifm_cur->ifm_media) == mii->mii_instance) &&
|
||||
(IFM_SUBTYPE(ifm->ifm_cur->ifm_media) == IFM_10_2)) {
|
||||
ifmr->ifm_active = ifm->ifm_cur->ifm_media;
|
||||
ifmr->ifm_status = 0;
|
||||
} else if(IFM_INST(ifm->ifm_cur->ifm_media) < mii->mii_instance) {
|
||||
/* Call underlying pollstat, if not serial PHY */
|
||||
if (sc->phyid != EPIC_SERIAL)
|
||||
mii_pollstat(mii);
|
||||
ifmr->ifm_active = mii->mii_media_active;
|
||||
ifmr->ifm_status = mii->mii_media_status;
|
||||
} else {
|
||||
ifmr->ifm_active = IFM_NONE;
|
||||
ifmr->ifm_status = 0;
|
||||
}
|
||||
|
||||
/* Simply copy media info */
|
||||
ifmr->ifm_active = mii->mii_media_active;
|
||||
ifmr->ifm_status = mii->mii_media_status;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1210,20 +1306,34 @@ epic_miibus_statchg(dev)
|
||||
{
|
||||
epic_softc_t *sc;
|
||||
struct mii_data *mii;
|
||||
int media;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mii = device_get_softc(sc->miibus);
|
||||
media = mii->mii_media_active;
|
||||
|
||||
sc->txcon &= ~(TXCON_LOOPBACK_MODE | TXCON_FULL_DUPLEX);
|
||||
|
||||
/*
|
||||
* If we are in full-duplex mode or loopback operation,
|
||||
/* If we are in full-duplex mode or loopback operation,
|
||||
* we need to decouple receiver and transmitter.
|
||||
*/
|
||||
if (mii->mii_media_active & (IFM_FDX | IFM_LOOP))
|
||||
if (IFM_OPTIONS(media) & (IFM_FDX | IFM_LOOP))
|
||||
sc->txcon |= TXCON_FULL_DUPLEX;
|
||||
|
||||
if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX)
|
||||
/* On some cards we need manualy set fullduplex led */
|
||||
if (sc->cardid == SMC9432FTX ||
|
||||
sc->cardid == SMC9432FTX_SC) {
|
||||
if (IFM_OPTIONS(media) & IFM_FDX)
|
||||
sc->miicfg |= MIICFG_694_ENABLE;
|
||||
else
|
||||
sc->miicfg &= ~MIICFG_694_ENABLE;
|
||||
|
||||
CSR_WRITE_4(sc, MIICFG, sc->miicfg);
|
||||
}
|
||||
|
||||
/* Update baudrate */
|
||||
if (IFM_SUBTYPE(media) == IFM_100_TX &&
|
||||
IFM_SUBTYPE(media) == IFM_100_FX)
|
||||
sc->sc_if.if_baudrate = 100000000;
|
||||
else
|
||||
sc->sc_if.if_baudrate = 10000000;
|
||||
@ -1233,22 +1343,32 @@ epic_miibus_statchg(dev)
|
||||
return;
|
||||
}
|
||||
|
||||
static void epic_miibus_mediainit(dev)
|
||||
static void
|
||||
epic_miibus_mediainit(dev)
|
||||
device_t dev;
|
||||
{
|
||||
epic_softc_t *sc;
|
||||
struct mii_data *mii;
|
||||
struct ifmedia *ifm;
|
||||
int media;
|
||||
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
mii = device_get_softc(sc->miibus);
|
||||
ifm = &mii->mii_media;
|
||||
|
||||
/* Add Serial Media Interface if present, this applies to
|
||||
* SMC9432BTX serie
|
||||
*/
|
||||
if(CSR_READ_4(sc, MIICFG) & MIICFG_PHY_PRESENT) {
|
||||
media = IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, mii->mii_instance);
|
||||
printf(EPIC_FORMAT ": serial PHY detected (10Base2/BNC)\n",EPIC_ARGS(sc));
|
||||
/* Store its instance */
|
||||
sc->serinst = mii->mii_instance++;
|
||||
|
||||
/* Add as 10base2/BNC media */
|
||||
media = IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0, sc->serinst);
|
||||
ifmedia_add(ifm, media, 0, NULL);
|
||||
|
||||
/* Report to user */
|
||||
printf(EPIC_FORMAT ": serial PHY detected (10Base2/BNC)\n",EPIC_ARGS(sc));
|
||||
}
|
||||
|
||||
return;
|
||||
@ -1317,10 +1437,13 @@ epic_init(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_RCC | /* INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE | */
|
||||
/* INTSTAT_TXC | */ INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |
|
||||
INTSTAT_FATAL);
|
||||
|
||||
/* Acknowledge all pending interrupts */
|
||||
CSR_WRITE_4(sc, INTSTAT, CSR_READ_4(sc, INTSTAT));
|
||||
|
||||
/* Enable interrupts, set for PCI read multiple and etc */
|
||||
CSR_WRITE_4( sc, GENCTL,
|
||||
GENCTL_ENABLE_INTERRUPT | GENCTL_MEMORY_READ_MULTIPLE |
|
||||
|
@ -257,6 +257,26 @@ struct epic_tx_buffer {
|
||||
* epic_rx_desc, epic_tx_desc, epic_frag_list - must be aligned on dword
|
||||
*/
|
||||
|
||||
/* PHY, known by tx driver */
|
||||
#define EPIC_UNKN_PHY 0x0000
|
||||
#define EPIC_QS6612_PHY 0x0001
|
||||
#define EPIC_AC101_PHY 0x0002
|
||||
#define EPIC_LXT970_PHY 0x0003
|
||||
#define EPIC_SERIAL 0x0004
|
||||
|
||||
#define SMC9432DMT 0xA010
|
||||
#define SMC9432TX 0xA011
|
||||
#define SMC9032TXM 0xA012
|
||||
#define SMC9032TX 0xA013
|
||||
#define SMC9432TXPWR 0xA014
|
||||
#define SMC9432BTX 0xA015
|
||||
#define SMC9432FTX 0xA016
|
||||
#define SMC9432FTX_SC 0xA017
|
||||
#define SMC9432TX_XG_ADHOC 0xA020
|
||||
#define SMC9434TX_XG_ADHOC 0xA021
|
||||
#define SMC9432FTX_ADHOC 0xA022
|
||||
#define SMC9432BTX1 0xA024
|
||||
|
||||
/* Driver status structure */
|
||||
typedef struct {
|
||||
struct arpcom arpcom;
|
||||
@ -288,11 +308,16 @@ typedef struct {
|
||||
u_int32_t flags;
|
||||
u_int32_t tx_threshold;
|
||||
u_int32_t txcon;
|
||||
u_int32_t phyid;
|
||||
u_int32_t miicfg;
|
||||
u_int32_t cur_tx;
|
||||
u_int32_t cur_rx;
|
||||
u_int32_t dirty_tx;
|
||||
u_int32_t pending_txs;
|
||||
u_int16_t cardvend;
|
||||
u_int16_t cardid;
|
||||
struct mii_softc *physc;
|
||||
u_int32_t phyid;
|
||||
int serinst;
|
||||
void *pool;
|
||||
} epic_softc_t;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user