⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lanc111.c

📁 Contiki是一个开源
💻 C
📖 第 1 页 / 共 3 页
字号:
#define PHYSOR_SPDDET   0x0080  /*!< \ref NIC_PHYSOR bit mask, 100/10 speed detected. */#define PHYSOR_DPLXDET  0x0040  /*!< \ref NIC_PHYSOR bit mask, duplex detected. *//*! * \brief PHY mask register. */#define NIC_PHYMSK      19#define PHYMSK_MINT     0x8000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_INT interrupt. */#define PHYMSK_MLNKFAIL 0x4000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_LNKFAIL interrupt. */#define PHYMSK_MLOSSSYN 0x2000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_LOSSSYNC interrupt. */#define PHYMSK_MCWRD    0x1000  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_CWRD interrupt. */#define PHYMSK_MSSD     0x0800  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_SSD interrupt. */#define PHYMSK_MESD     0x0400  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_ESD interrupt. */#define PHYMSK_MRPOL    0x0200  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_RPOL interrupt. */#define PHYMSK_MJAB     0x0100  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_JAB interrupt. */#define PHYMSK_MSPDDT   0x0080  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_SPDDET interrupt. */#define PHYMSK_MDPLDT   0x0040  /*!< \ref NIC_PHYMSK bit mask, enables \ref PHYSOR_DPLXDET interrupt. */#define MSBV(bit)       (1 << ((bit) - 8))#define nic_outlb(addr, val) (*(volatile u8_t *)(addr) = (val))#define nic_outhb(addr, val) (*(volatile u8_t *)((addr) + 1) = (val))#define nic_outwx(addr, val) (*(volatile u16_t *)(addr) = (val))#define nic_outw(addr, val) { \    *(volatile u8_t *)(addr) = (u8_t)(val); \    *((volatile u8_t *)(addr) + 1) = (u8_t)((val) >> 8); \}#define nic_inlb(addr) (*(volatile u8_t *)(addr))#define nic_inhb(addr) (*(volatile u8_t *)((addr) + 1))#define nic_inw(addr) (*(volatile u16_t *)(addr))#define nic_bs(bank)    nic_outlb(NIC_BSR, bank)/*! * \struct _NICINFO lanc111.h dev/lanc111.h * \brief Network interface controller information structure. *//*@}*//*! * \addtogroup xgNicLanc111 *//*@{*//*! * \brief Select specified PHY register for reading or writing. * * \note NIC interrupts must have been disabled before calling this routine. * * \param reg PHY register number. * \param we  Indicates type of access, 1 for write and 0 for read. * * \return Contents of the PHY interface rgister. */static u8_t NicPhyRegSelect(u8_t reg, u8_t we){    u8_t rs;    u8_t msk;    u8_t i;    nic_bs(3);    rs = (nic_inlb(NIC_MGMT) & ~(MGMT_MCLK | MGMT_MDO)) | MGMT_MDOE;    /* Send idle pattern. */    for (i = 0; i < 33; i++) {        nic_outlb(NIC_MGMT, rs | MGMT_MDO);        nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);    }    /* Send start sequence. */    nic_outlb(NIC_MGMT, rs);    nic_outlb(NIC_MGMT, rs | MGMT_MCLK);    nic_outlb(NIC_MGMT, rs | MGMT_MDO);    nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);    /* Write or read mode. */    if (we) {        nic_outlb(NIC_MGMT, rs);        nic_outlb(NIC_MGMT, rs | MGMT_MCLK);        nic_outlb(NIC_MGMT, rs | MGMT_MDO);        nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);    } else {        nic_outlb(NIC_MGMT, rs | MGMT_MDO);        nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);        nic_outlb(NIC_MGMT, rs);        nic_outlb(NIC_MGMT, rs | MGMT_MCLK);    }    /* Send PHY address. Zero is used for the internal PHY. */    for (i = 0; i < 5; i++) {        nic_outlb(NIC_MGMT, rs);        nic_outlb(NIC_MGMT, rs | MGMT_MCLK);    }    /* Send PHY register number. */    for (msk = 0x10; msk; msk >>= 1) {        if (reg & msk) {            nic_outlb(NIC_MGMT, rs | MGMT_MDO);            nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);        } else {            nic_outlb(NIC_MGMT, rs);            nic_outlb(NIC_MGMT, rs | MGMT_MCLK);        }    }    nic_outlb(NIC_MGMT, rs);    return rs;}/*! * \brief Read contents of PHY register. * * \note NIC interrupts must have been disabled before calling this routine. * * \param reg PHY register number. * * \return Contents of the specified register. */static u16_t NicPhyRead(u8_t reg){    u16_t rc = 0;    u8_t rs;    u8_t i;    /* Select register for reading. */    rs = NicPhyRegSelect(reg, 0);    /* Switch data direction. */    rs &= ~MGMT_MDOE;    nic_outlb(NIC_MGMT, rs);    nic_outlb(NIC_MGMT, rs | MGMT_MCLK);    /* Clock data in. */    for (i = 0; i < 16; i++) {        nic_outlb(NIC_MGMT, rs);        nic_outlb(NIC_MGMT, rs | MGMT_MCLK);        rc <<= 1;        rc |= (nic_inlb(NIC_MGMT) & MGMT_MDI) != 0;    }    /* This will set the clock line to low. */    nic_outlb(NIC_MGMT, rs);    return rc;}/*! * \brief Write value to PHY register. * * \note NIC interrupts must have been disabled before calling this routine. * * \param reg PHY register number. * \param val Value to write. */static void NicPhyWrite(u8_t reg, u16_t val){    u16_t msk;    u8_t rs;    /* Select register for writing. */    rs = NicPhyRegSelect(reg, 1);    /* Switch data direction dummy. */    nic_outlb(NIC_MGMT, rs | MGMT_MDO);    nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);    nic_outlb(NIC_MGMT, rs);    nic_outlb(NIC_MGMT, rs | MGMT_MCLK);    /* Clock data out. */    for (msk = 0x8000; msk; msk >>= 1) {        if (val & msk) {            nic_outlb(NIC_MGMT, rs | MGMT_MDO);            nic_outlb(NIC_MGMT, rs | MGMT_MDO | MGMT_MCLK);        } else {            nic_outlb(NIC_MGMT, rs);            nic_outlb(NIC_MGMT, rs | MGMT_MCLK);        }    }    /* Set clock line low and output line int z-state. */    nic_outlb(NIC_MGMT, rs & ~MGMT_MDOE);}/*! * \brief Configure the internal PHY. * * Reset the PHY and initiate auto-negotiation. */static int NicPhyConfig(void){    u16_t phy_sor;    u16_t phy_sr;    u16_t phy_to;    u16_t mode;    /*      * Reset the PHY and wait until this self clearing bit     * becomes zero. We sleep 63 ms before each poll and     * give up after 3 retries.      */    //printf("Reset PHY..");    NicPhyWrite(NIC_PHYCR, PHYCR_RST);    for (phy_to = 0;; phy_to++) {        NutSleep(63);        if ((NicPhyRead(NIC_PHYCR) & PHYCR_RST) == 0)            break;        if (phy_to > 3)            return -1;    }    //printf("OK\n");    /* Store PHY status output. */    phy_sor = NicPhyRead(NIC_PHYSOR);    /* Enable PHY interrupts. */    NicPhyWrite(NIC_PHYMSK, PHYMSK_MLOSSSYN | PHYMSK_MCWRD | PHYMSK_MSSD |                PHYMSK_MESD | PHYMSK_MRPOL | PHYMSK_MJAB | PHYMSK_MSPDDT | PHYMSK_MDPLDT);    /* Set RPC register. */    mode = RPCR_ANEG | RPCR_LEDA_PAT | RPCR_LEDB_PAT;    nic_bs(0);    nic_outw(NIC_RPCR, mode);#ifdef NIC_FIXED    /* Disable link. */    phy_sr = NicPhyRead(NIC_PHYCFR1);    NicPhyWrite(NIC_PHYCFR1, phy_sr | 0x8000);    NutSleep(63);    /* Set fixed capabilities. */    NicPhyWrite(NIC_PHYCR, NIC_FIXED);    nic_bs(0);    nic_outw(NIC_RPCR, mode);    /* Enable link. */    phy_sr = NicPhyRead(NIC_PHYCFR1);    NicPhyWrite(NIC_PHYCFR1, phy_sr & ~0x8000);    phy_sr = NicPhyRead(NIC_PHYCFR1);#else    /*     * Advertise our capabilities, initiate auto negotiation     * and wait until this has been completed.     */    //printf("Negotiate..");    NicPhyWrite(NIC_PHYANAD, PHYANAD_TX_FDX | PHYANAD_TX_HDX | PHYANAD_10FDX | PHYANAD_10_HDX | PHYANAD_CSMA);    NutSleep(63);    for (phy_to = 0, phy_sr = 0;; phy_to++) {        /* Give up after 10 seconds. */        if (phy_to >= 1024)            return -1;        /* Restart auto negotiation every 4 seconds or on failures. */        if ((phy_to & 127) == 0 /* || (phy_sr & PHYSR_REM_FLT) != 0 */ ) {            NicPhyWrite(NIC_PHYCR, PHYCR_ANEG_EN | PHYCR_ANEG_RST);            //printf("Restart..");            NutSleep(63);        }        /* Check if we are done. */        phy_sr = NicPhyRead(NIC_PHYSR);        //printf("[SR %04X]", phy_sr);        if (phy_sr & PHYSR_ANEG_ACK)            break;        NutSleep(63);    }    //printf("OK\n");#endif    return 0;}/*! * \brief Wait until MMU is ready. * * Poll the MMU command register until \ref MMUCR_BUSY * is cleared. * * \param tmo Timeout in milliseconds. * * \return 0 on success or -1 on timeout. */static INLINE int NicMmuWait(u16_t tmo){    while (tmo--) {        if ((nic_inlb(NIC_MMUCR) & MMUCR_BUSY) == 0)            break;        NutDelay(1);    }    return tmo ? 0 : -1;}/*! * \brief Reset the Ethernet controller. * * \return 0 on success, -1 otherwise. */static int NicReset(void){#ifdef LANC111_RESET_BIT    sbi(LANC111_RESET_DDR, LANC111_RESET_BIT);    sbi(LANC111_RESET_PORT, LANC111_RESET_BIT);    NutDelay(WAIT100);    cbi(LANC111_RESET_PORT, LANC111_RESET_BIT);    NutDelay(WAIT250);    NutDelay(WAIT250);#endif    /* Disable all interrupts. */    nic_outlb(NIC_MSK, 0);    /* MAC and PHY software reset. */    nic_bs(0);    nic_outw(NIC_RCR, RCR_SOFT_RST);    /* Enable Ethernet protocol handler. */    nic_bs(1);    nic_outw(NIC_CR, CR_EPH_EN);    NutDelay(10);    /* Disable transmit and receive. */    nic_bs(0);    nic_outw(NIC_RCR, 0);    nic_outw(NIC_TCR, 0);    /* Enable auto release. */    nic_bs(1);    nic_outw(NIC_CTR, CTR_AUTO_RELEASE);    /* Reset MMU. */    nic_bs(2);    nic_outlb(NIC_MMUCR, MMU_RST);    if (NicMmuWait(1000))        return -1;    return 0;}/* * Fires up the network interface. NIC interrupts * should have been disabled when calling this * function. * * \param mac Six byte unique MAC address. */static int NicStart(CONST u8_t * mac){    u8_t i;    if (NicReset())        return -1;    /* Enable receiver. */    nic_bs(3);    nic_outlb(NIC_ERCV, 7);    nic_bs(0);    nic_outw(NIC_RCR, RCR_RXEN);    /* Enable transmitter and padding. */    nic_outw(NIC_TCR, TCR_PAD_EN | TCR_TXENA);    /* Configure the PHY. */    if (NicPhyConfig())        return -1;    /* Set MAC address. */    //printf("Set MAC %02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);    nic_bs(1);    for (i = 0; i < 6; i++)        nic_outlb(NIC_IAR + i, mac[i]);    //printf("OK\n");    /* Enable interrupts. */    nic_bs(2);    nic_outlb(NIC_MSK, INT_ERCV | INT_RCV | INT_RX_OVRN);    return 0;}/* * NIC interrupt entry. */#if 0static void NicInterrupt(void *arg){    u8_t isr;    u8_t imr;    NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;    ni->ni_interrupts++;    /* Read the interrupt mask and disable all interrupts. */    nic_bs(2);    imr = nic_inlb(NIC_MSK);    nic_outlb(NIC_MSK, 0);    /* Read the interrupt status and acknowledge all interrupts. */    isr = nic_inlb(NIC_IST);    //printf("\n!%02X-%02X ", isr, imr);    isr &= imr;    /*     * If this is a transmit interrupt, then a packet has been sent.      * So we can clear the transmitter busy flag and wake up the      * transmitter thread.     */    if (isr & INT_TX_EMPTY) {        nic_outlb(NIC_ACK, INT_TX_EMPTY);        imr &= ~INT_TX_EMPTY;        NutEventPostFromIrq(&ni->ni_tx_rdy);    }    /* Transmit error. */    else if (isr & INT_TX) {        /* re-enable transmit */        nic_bs(0);        nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA);        nic_bs(2);        nic_outlb(NIC_ACK, INT_TX);        /* kill the packet */        nic_outlb(NIC_MMUCR, MMU_PKT);        NutEventPostFromIrq(&ni->ni_tx_rdy);    }    /*     * If this is a receive interrupt, then wake up the receiver      * thread.     */    if (isr & INT_RX_OVRN) {        nic_outlb(NIC_ACK, INT_RX_OVRN);        //nic_outlb(NIC_MMUCR, MMU_TOP);    }    if (isr & INT_ERCV) {        nic_outlb(NIC_ACK, INT_ERCV);        NutEventPostFromIrq(&ni->ni_rx_rdy);    }    if (isr & INT_RCV) {        nic_outlb(NIC_ACK, INT_RCV);        imr &= ~INT_RCV;        NutEventPostFromIrq(&ni->ni_rx_rdy);    }    if (isr & INT_ALLOC) {        imr &= ~INT_ALLOC;        NutEventPostFromIrq(&maq);    }    //printf(" -%02X-%02X- ", nic_inlb(NIC_IST), inb(PINE) & 0x20);    nic_outlb(NIC_MSK, imr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -