Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 727e639 in mainline


Ignore:
Timestamp:
2014-06-30T21:08:06Z (7 years ago)
Author:
Agnieszka Tabaka <nufcia@…>
Branches:
lfn, master
Children:
ca652eb
Parents:
91e057c
Message:

Add functions to access RTL8169's PHY (rtl8169_mii_read and rtl8169_mii_write)
and fill most of existing stubs of nic_iface_t functions.

Location:
uspace/drv/nic/rtl8169
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/nic/rtl8169/defs.h

    r91e057c r727e639  
    110110};
    111111
     112enum rtl8169_mii_registers {
     113        MII_BMCR = 0x00,
     114        MII_BMSR = 0x01,
     115        MII_ANAR = 0x04,
     116};
     117
    112118/** Command register bits */
    113119enum rtl8169_cr {
     
    266272};
    267273
     274enum rtl8169_phyar {
     275        PHYAR_RW_SHIFT = 31, /**< Read (0) or write (1) command */
     276        PHYAR_RW_READ = (0 << PHYAR_RW_SHIFT),
     277        PHYAR_RW_WRITE = (1 << PHYAR_RW_SHIFT),
     278        PHYAR_ADDR_SHIFT = 15,
     279        PHYAR_ADDR_MASK = 0x1f,
     280        PHYAR_DATA_MASK = 0xffff
     281};
     282
     283enum rtl8169_bmcr {
     284        BMCR_RESET = (1 << 15), /**< Software reset */
     285        BMCR_SPD_100 = (1 << 13), /**< 100 MBit mode set */
     286        BMCR_AN_ENABLE = (1 << 12), /**< Autonegotion enable */
     287        BMCR_AN_RESTART = (1 << 9), /**< Restart autonegotion */
     288        BMCR_DUPLEX = (1 << 8), /**< Duplex mode: 1=full duplex */
     289        BMCR_SPD_1000 = (1 << 6), /**< 1000 Mbit mode set */
     290};
     291
    268292enum rtl8169_descr_control {
    269293        CONTROL_OWN = (1 << 31), /**< Descriptor ownership */
  • uspace/drv/nic/rtl8169/driver.c

    r91e057c r727e639  
    9292static int rtl8169_broadcast_set(nic_t *nic_data, nic_broadcast_mode_t mode);
    9393
     94static uint16_t rtl8169_mii_read(rtl8169_t *rtl8169, uint8_t addr);
     95static void rtl8169_mii_write(rtl8169_t *rtl8169, uint8_t addr, uint16_t value);
    9496static void rtl8169_rx_ring_refill(rtl8169_t *rtl8169, unsigned int first,
    9597    unsigned int last);
     
    494496    nic_channel_mode_t *duplex, nic_role_t *role)
    495497{
     498        rtl8169_t *rtl8169 = nic_get_specific(nic_get_from_ddf_fun(fun));
     499        uint8_t phystatus = pio_read_8(rtl8169->regs + PHYSTATUS);
     500
     501        *duplex = phystatus & PHYSTATUS_FDX
     502            ? NIC_CM_FULL_DUPLEX : NIC_CM_HALF_DUPLEX;
     503
     504        if (phystatus & PHYSTATUS_10M)
     505                *speed = 10;
     506
     507        if (phystatus & PHYSTATUS_100M)
     508                *speed = 100;
     509
     510        if (phystatus & PHYSTATUS_1000M)
     511                *speed = 1000;
     512
     513        *role = NIC_ROLE_UNKNOWN;
    496514        return EOK;
    497515}
     
    500518    nic_channel_mode_t duplex, nic_role_t role)
    501519{
     520        rtl8169_t *rtl8169 = nic_get_specific(nic_get_from_ddf_fun(fun));
     521        uint16_t bmcr;
     522
     523        if (speed != 10 && speed != 100 && speed != 1000)
     524                return EINVAL;
     525
     526        if (duplex != NIC_CM_HALF_DUPLEX && duplex != NIC_CM_FULL_DUPLEX)
     527                return EINVAL;
     528
     529        bmcr = rtl8169_mii_read(rtl8169, MII_BMCR);
     530        bmcr &= ~(BMCR_DUPLEX | BMCR_SPD_100 | BMCR_SPD_1000);
     531       
     532        if (duplex == NIC_CM_FULL_DUPLEX)
     533                bmcr |= BMCR_DUPLEX;
     534
     535        if (speed == 100)
     536                bmcr |= BMCR_SPD_100;
     537
     538        if (speed == 1000)
     539                bmcr |= BMCR_SPD_1000;
     540
     541        rtl8169_mii_write(rtl8169, MII_BMCR, bmcr);
    502542        return EOK;
    503543}
     
    517557static int rtl8169_autoneg_enable(ddf_fun_t *fun, uint32_t advertisement)
    518558{
     559        rtl8169_t *rtl8169 = nic_get_specific(nic_get_from_ddf_fun(fun));
     560        uint16_t bmcr = rtl8169_mii_read(rtl8169, MII_BMCR);
     561        uint16_t anar = ANAR_SELECTOR;
     562
     563        if (advertisement & ETH_AUTONEG_10BASE_T_FULL)
     564                anar |= ANAR_10_FD;
     565        if (advertisement & ETH_AUTONEG_10BASE_T_HALF)
     566                anar |= ANAR_10_HD;
     567        if (advertisement & ETH_AUTONEG_100BASE_TX_FULL)
     568                anar |= ANAR_100TX_FD;
     569        if (advertisement & ETH_AUTONEG_100BASE_TX_HALF)
     570                anar |= ANAR_100TX_HD;
     571        if (advertisement & ETH_AUTONEG_PAUSE_SYMETRIC)
     572                anar |= ANAR_PAUSE;
     573
     574        bmcr |= BMCR_AN_ENABLE;
     575        rtl8169_mii_write(rtl8169, MII_BMCR, bmcr);
     576        rtl8169_mii_write(rtl8169, MII_ANAR, anar);
     577
    519578        return EOK;
    520579}
     
    522581static int rtl8169_autoneg_disable(ddf_fun_t *fun)
    523582{
     583        rtl8169_t *rtl8169 = nic_get_specific(nic_get_from_ddf_fun(fun));
     584        uint16_t bmcr = rtl8169_mii_read(rtl8169, MII_BMCR);
     585
     586        bmcr &= ~BMCR_AN_ENABLE;
     587        rtl8169_mii_write(rtl8169, MII_BMCR, bmcr);
     588
    524589        return EOK;
    525590}
     
    910975}
    911976
     977static uint16_t rtl8169_mii_read(rtl8169_t *rtl8169, uint8_t addr)
     978{
     979        uint32_t phyar;
     980
     981        phyar = PHYAR_RW_READ
     982            | ((addr & PHYAR_ADDR_MASK) << PHYAR_ADDR_SHIFT);
     983
     984        pio_write_32(rtl8169->regs + PHYAR, phyar);
     985
     986        do {
     987                phyar = pio_read_32(rtl8169->regs + PHYAR);
     988                usleep(20);
     989        } while ((phyar & PHYAR_RW_WRITE) == 0);
     990
     991        return phyar & PHYAR_DATA_MASK;
     992}
     993
     994static void rtl8169_mii_write(rtl8169_t *rtl8169, uint8_t addr, uint16_t value)
     995{
     996        uint32_t phyar;
     997
     998        phyar = PHYAR_RW_WRITE
     999            | ((addr & PHYAR_ADDR_MASK) << PHYAR_ADDR_SHIFT)
     1000            | (value & PHYAR_DATA_MASK);
     1001
     1002        pio_write_32(rtl8169->regs + PHYAR, phyar);
     1003
     1004        do {
     1005                phyar = pio_read_32(rtl8169->regs + PHYAR);
     1006                usleep(20);
     1007        } while ((phyar & PHYAR_RW_WRITE) != 0);
     1008
     1009        usleep(20);
     1010}
     1011
    9121012/** Main function of RTL8169 driver
    9131013*
Note: See TracChangeset for help on using the changeset viewer.