iPXE
Defines | Functions | Variables
sis190.c File Reference
#include "sis190.h"

Go to the source code of this file.

Defines

#define ErrMask   (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)
#define TxErrMask   (WND | TABRT | FIFO | LINK)

Functions

 FILE_LICENCE (GPL_ANY)
static int sis190_isa_bridge_probe (struct pci_device *pdev __unused)
static void sis190_isa_bridge_remove (struct pci_device *pdev __unused)
static void __mdio_cmd (void *ioaddr, u32 ctl)
static void mdio_write (void *ioaddr, int phy_id, int reg, int val)
static int mdio_read (void *ioaddr, int phy_id, int reg)
static void __mdio_write (struct net_device *dev, int phy_id, int reg, int val)
static int __mdio_read (struct net_device *dev, int phy_id, int reg)
static u16 mdio_read_latched (void *ioaddr, int phy_id, int reg)
static u16 sis190_read_eeprom (void *ioaddr, u32 reg)
static void sis190_irq_mask_and_ack (void *ioaddr)
static void sis190_asic_down (void *ioaddr)
static void sis190_mark_as_last_descriptor (struct RxDesc *desc)
static void sis190_give_to_asic (struct RxDesc *desc)
static void sis190_map_to_asic (struct RxDesc *desc, u32 mapping)
static void sis190_make_unusable_by_asic (struct RxDesc *desc)
static struct io_buffersis190_alloc_rx_iob (struct RxDesc *desc)
static u32 sis190_rx_fill (struct sis190_private *tp, u32 start, u32 end)
static int sis190_rx_pkt_err (u32 status)
static int sis190_process_rx (struct sis190_private *tp)
static int sis190_tx_pkt_err (u32 status)
static void sis190_process_tx (struct sis190_private *tp)
static void sis190_poll (struct net_device *dev)
static void sis190_init_ring_indexes (struct sis190_private *tp)
static int sis190_init_ring (struct net_device *dev)
static void sis190_set_rx_mode (struct net_device *dev)
static void sis190_soft_reset (void *ioaddr)
static void sis190_hw_start (struct net_device *dev)
static void sis190_phy_task (struct sis190_private *tp)
static int sis190_open (struct net_device *dev)
static void sis190_down (struct net_device *dev)
static void sis190_free (struct net_device *dev)
static void sis190_close (struct net_device *dev)
static int sis190_transmit (struct net_device *dev, struct io_buffer *iob)
static void sis190_free_phy (struct list_head *first_phy)
static u16 sis190_default_phy (struct sis190_private *tp)
 sis190_default_phy - Select default PHY for sis190 mac.
static void sis190_init_phy (struct sis190_private *tp, struct sis190_phy *phy, unsigned int phy_id, u16 mii_status)
static void sis190_mii_probe_88e1111_fixup (struct sis190_private *tp)
static int sis190_mii_probe (struct net_device *dev)
 sis190_mii_probe - Probe MII PHY for sis190 : the net device to probe for
static void sis190_mii_remove (struct net_device *dev)
static int sis190_init_board (struct pci_device *pdev, struct net_device **netdev)
static void sis190_set_rgmii (struct sis190_private *tp, u8 reg)
static int sis190_get_mac_addr_from_eeprom (struct pci_device *pdev __unused, struct net_device *dev)
static int sis190_get_mac_addr_from_apc (struct pci_device *pdev, struct net_device *dev)
 sis190_get_mac_addr_from_apc - Get MAC address for SiS96x model : PCI device : network device to get address for
static void sis190_init_rxfilter (struct net_device *dev)
 sis190_init_rxfilter - Initialize the Rx filter : network device to initialize
static int sis190_get_mac_addr (struct pci_device *pdev, struct net_device *dev)
static void sis190_set_speed_auto (struct net_device *dev)
static void sis190_irq (struct net_device *dev, int enable)
static int sis190_probe (struct pci_device *pdev)
static void sis190_remove (struct pci_device *pdev)

Variables

static struct pci_device_id sis190_pci_tbl []
static struct pci_device_id sis190_isa_bridge_tbl []
struct pci_driver
sis190_isa_bridge_driver 
__pci_driver
static const u32 sis190_intr_mask
static struct net_device_operations sis190_netdev_ops

Define Documentation

#define ErrMask   (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)

Referenced by sis190_rx_pkt_err().

#define TxErrMask   (WND | TABRT | FIFO | LINK)

Referenced by sis190_tx_pkt_err().


Function Documentation

FILE_LICENCE ( GPL_ANY  )
static int sis190_isa_bridge_probe ( struct pci_device *pdev  __unused) [static]

Definition at line 50 of file sis190.c.

{
        return 0;
}
static void sis190_isa_bridge_remove ( struct pci_device *pdev  __unused) [static]

Definition at line 55 of file sis190.c.

{
        return;
}
static void __mdio_cmd ( void *  ioaddr,
u32  ctl 
) [static]

Definition at line 75 of file sis190.c.

References DBG, EhnMIInotDone, GMIIControl, mdelay(), SIS_R32, and SIS_W32.

Referenced by mdio_read(), and mdio_write().

{
        unsigned int i;

        SIS_W32(GMIIControl, ctl);

        mdelay(1);

        for (i = 0; i < 100; i++) {
                if (!(SIS_R32(GMIIControl) & EhnMIInotDone))
                        break;
                mdelay(1);
        }

        if (i > 99)
                DBG("sis190: PHY command timed out !\n");
}
static void mdio_write ( void *  ioaddr,
int  phy_id,
int  reg,
int  val 
) [static]
static int mdio_read ( void *  ioaddr,
int  phy_id,
int  reg 
) [static]
static void __mdio_write ( struct net_device dev,
int  phy_id,
int  reg,
int  val 
) [static]

Definition at line 108 of file sis190.c.

References mdio_write(), sis190_private::mmio_addr, netdev_priv(), and tp.

Referenced by sis190_mii_probe().

{
        struct sis190_private *tp = netdev_priv(dev);

        mdio_write(tp->mmio_addr, phy_id, reg, val);
}
static int __mdio_read ( struct net_device dev,
int  phy_id,
int  reg 
) [static]

Definition at line 115 of file sis190.c.

References mdio_read(), sis190_private::mmio_addr, netdev_priv(), and tp.

Referenced by sis190_mii_probe().

{
        struct sis190_private *tp = netdev_priv(dev);

        return mdio_read(tp->mmio_addr, phy_id, reg);
}
static u16 mdio_read_latched ( void *  ioaddr,
int  phy_id,
int  reg 
) [static]

Definition at line 122 of file sis190.c.

References mdio_read().

Referenced by sis190_default_phy(), sis190_mii_probe(), and sis190_phy_task().

{
        mdio_read(ioaddr, phy_id, reg);
        return mdio_read(ioaddr, phy_id, reg);
}
static u16 sis190_read_eeprom ( void *  ioaddr,
u32  reg 
) [static]

Definition at line 128 of file sis190.c.

References data, EEREQ, EEROP, mdelay(), ROMControl, ROMInterface, SIS_R32, and SIS_W32.

Referenced by sis190_get_mac_addr_from_eeprom().

{
        u16 data = 0xffff;
        unsigned int i;

        if (!(SIS_R32(ROMControl) & 0x0002))
                return 0;

        SIS_W32(ROMInterface, EEREQ | EEROP | (reg << 10));

        for (i = 0; i < 200; i++) {
                if (!(SIS_R32(ROMInterface) & EEREQ)) {
                        data = (SIS_R32(ROMInterface) & 0xffff0000) >> 16;
                        break;
                }
                mdelay(1);
        }

        return data;
}
static void sis190_irq_mask_and_ack ( void *  ioaddr) [static]

Definition at line 149 of file sis190.c.

References IntrMask, IntrStatus, SIS_PCI_COMMIT, and SIS_W32.

Referenced by sis190_asic_down(), and sis190_init_board().

{
        SIS_W32(IntrMask, 0x00);
        SIS_W32(IntrStatus, 0xffffffff);
        SIS_PCI_COMMIT();
}
static void sis190_asic_down ( void *  ioaddr) [static]

Definition at line 156 of file sis190.c.

References RxControl, sis190_irq_mask_and_ack(), SIS_W32, and TxControl.

Referenced by sis190_down(), and sis190_soft_reset().

{
        /* Stop the chip's Tx and Rx DMA processes. */

        SIS_W32(TxControl, 0x1a00);
        SIS_W32(RxControl, 0x1a00);

        sis190_irq_mask_and_ack(ioaddr);
}
static void sis190_mark_as_last_descriptor ( struct RxDesc desc) [inline, static]

Definition at line 166 of file sis190.c.

References cpu_to_le32, RingEnd, and RxDesc::size.

Referenced by sis190_init_ring().

{
        desc->size |= cpu_to_le32(RingEnd);
}
static void sis190_give_to_asic ( struct RxDesc desc) [inline, static]

Definition at line 171 of file sis190.c.

References cpu_to_le32, INTbit, le32_to_cpu, OWNbit, RxDesc::PSize, RingEnd, RX_BUF_MASK, RX_BUF_SIZE, RxDesc::size, RxDesc::status, and wmb.

Referenced by sis190_map_to_asic(), and sis190_process_rx().

{
        u32 eor = le32_to_cpu(desc->size) & RingEnd;

        desc->PSize = 0x0;
        desc->size = cpu_to_le32((RX_BUF_SIZE & RX_BUF_MASK) | eor);
        wmb();
        desc->status = cpu_to_le32(OWNbit | INTbit);
}
static void sis190_map_to_asic ( struct RxDesc desc,
u32  mapping 
) [inline, static]

Definition at line 181 of file sis190.c.

References RxDesc::addr, cpu_to_le32, and sis190_give_to_asic().

Referenced by sis190_alloc_rx_iob().

{
        desc->addr = cpu_to_le32(mapping);
        sis190_give_to_asic(desc);
}
static void sis190_make_unusable_by_asic ( struct RxDesc desc) [inline, static]

Definition at line 187 of file sis190.c.

References RxDesc::addr, cpu_to_le32, RxDesc::PSize, RingEnd, RxDesc::size, RxDesc::status, and wmb.

Referenced by sis190_alloc_rx_iob(), and sis190_process_rx().

{
        desc->PSize = 0x0;
        desc->addr = cpu_to_le32(0xdeadbeef);
        desc->size &= cpu_to_le32(RingEnd);
        wmb();
        desc->status = 0x0;
}
static struct io_buffer* sis190_alloc_rx_iob ( struct RxDesc desc) [static, read]

Definition at line 196 of file sis190.c.

References alloc_iob(), io_buffer::data, DBG, RX_BUF_SIZE, sis190_make_unusable_by_asic(), sis190_map_to_asic(), and virt_to_bus().

Referenced by sis190_rx_fill().

{
        struct io_buffer *iob;

        iob = alloc_iob(RX_BUF_SIZE);
        if (iob) {
                u32 mapping;

                mapping = virt_to_bus(iob->data);
                sis190_map_to_asic(desc, mapping);
        } else {
                DBG("sis190: alloc_iob failed\n");
                sis190_make_unusable_by_asic(desc);
        }

        return iob;
}
static u32 sis190_rx_fill ( struct sis190_private tp,
u32  start,
u32  end 
) [static]

Definition at line 214 of file sis190.c.

References end, NUM_RX_DESC, sis190_private::Rx_iobuf, sis190_private::RxDescRing, sis190_alloc_rx_iob(), and start.

Referenced by sis190_init_ring(), and sis190_process_rx().

{
        u32 cur;

        for (cur = start; cur < end; cur++) {
                unsigned int i = cur % NUM_RX_DESC;

                if (tp->Rx_iobuf[i])
                        continue;

                tp->Rx_iobuf[i] = sis190_alloc_rx_iob(tp->RxDescRing + i);

                if (!tp->Rx_iobuf[i])
                        break;
        }
        return cur - start;
}
static int sis190_rx_pkt_err ( u32  status) [inline, static]

Definition at line 232 of file sis190.c.

References CRCOK, and ErrMask.

Referenced by sis190_process_rx().

{
#define ErrMask (OVRUN | SHORT | LIMIT | MIIER | NIBON | COLON | ABORT)

        if ((status & CRCOK) && !(status & ErrMask))
                return 0;

        return -1;
}
static int sis190_process_rx ( struct sis190_private tp) [static]

Definition at line 242 of file sis190.c.

References count, cur_rx, sis190_private::cur_rx, io_buffer::data, DBG, DBG2, DBGIO_HD, sis190_private::dev, sis190_private::dirty_rx, entry, iob_put, le32_to_cpu, netdev_rx(), NULL, NUM_RX_DESC, OWNbit, RxDesc::PSize, RX_BUF_SIZE, sis190_private::Rx_iobuf, sis190_private::RxDescRing, RxSizeMask, sis190_give_to_asic(), sis190_make_unusable_by_asic(), sis190_rx_fill(), sis190_rx_pkt_err(), status, and RxDesc::status.

Referenced by sis190_poll().

{
        u32 rx_left, cur_rx = tp->cur_rx;
        u32 delta, count;

        rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;

        for (; rx_left > 0; rx_left--, cur_rx++) {
                unsigned int entry = cur_rx % NUM_RX_DESC;
                struct RxDesc *desc = tp->RxDescRing + entry;
                u32 status;

                if (le32_to_cpu(desc->status) & OWNbit)
                        break;

                status = le32_to_cpu(desc->PSize);

                if (sis190_rx_pkt_err(status) < 0) {
                        sis190_give_to_asic(desc);
                } else {
                        struct io_buffer *iob = tp->Rx_iobuf[entry];
                        unsigned int pkt_size = (status & RxSizeMask) - 4;

                        if (pkt_size > RX_BUF_SIZE) {
                                DBG("sis190: (frag) status = %08x.\n", status);
                                sis190_give_to_asic(desc);
                                continue;
                        }

                        sis190_make_unusable_by_asic(desc);

                        iob_put(iob, pkt_size);

                        DBG2("sis190: received packet. len: %d\n", pkt_size);
                        netdev_rx(tp->dev, iob);
                        DBGIO_HD(iob->data, 60);
                        tp->Rx_iobuf[entry] = NULL;
                }
        }
        count = cur_rx - tp->cur_rx;
        tp->cur_rx = cur_rx;

        delta = sis190_rx_fill(tp, tp->dirty_rx, tp->cur_rx);
        if (!delta && count)
                DBG("sis190: no Rx buffer allocated.\n");
        tp->dirty_rx += delta;

        if (((tp->dirty_rx + NUM_RX_DESC) == tp->cur_rx))
                DBG("sis190: Rx buffers exhausted.\n");

        return count;
}
static int sis190_tx_pkt_err ( u32  status) [inline, static]

Definition at line 295 of file sis190.c.

References TxErrMask.

Referenced by sis190_process_tx().

{
#define TxErrMask (WND | TABRT | FIFO | LINK)

        if (!(status & TxErrMask))
                return 0;

        return -1;
}
static void sis190_process_tx ( struct sis190_private tp) [static]

Definition at line 305 of file sis190.c.

References sis190_private::cur_tx, DBG, DBG2, sis190_private::dev, sis190_private::dirty_tx, EINVAL, entry, le32_to_cpu, netdev_tx_complete(), netdev_tx_complete_err(), NULL, NUM_TX_DESC, OWNbit, pending, sis190_tx_pkt_err(), status, TxDesc::status, sis190_private::Tx_iobuf, txd, and sis190_private::TxDescRing.

Referenced by sis190_poll().

{
        u32 pending, dirty_tx = tp->dirty_tx;

        pending = tp->cur_tx - dirty_tx;

        for (; pending; pending--, dirty_tx++) {
                unsigned int entry = dirty_tx % NUM_TX_DESC;
                struct TxDesc *txd = tp->TxDescRing + entry;
                u32 status = le32_to_cpu(txd->status);
                struct io_buffer *iob;

                if (status & OWNbit)
                        break;

                iob = tp->Tx_iobuf[entry];

                if (!iob)
                        break;

                if (sis190_tx_pkt_err(status) == 0) {
                        DBG2("sis190: Transmitted packet: %#08x\n", status);
                        netdev_tx_complete(tp->dev, iob);
                } else {
                        DBG("sis190: Transmit error: %#08x\n", status);
                        netdev_tx_complete_err(tp->dev, iob, -EINVAL);
                }

                tp->Tx_iobuf[entry] = NULL;
        }

        if (tp->dirty_tx != dirty_tx)
                tp->dirty_tx = dirty_tx;
}
static void sis190_poll ( struct net_device dev) [static]

Definition at line 344 of file sis190.c.

References IntrStatus, ioaddr, LinkChange, sis190_private::mmio_addr, netdev_link_ok(), netdev_priv(), RxQInt, sis190_phy_task(), sis190_process_rx(), sis190_process_tx(), SIS_R32, SIS_W32, status, tp, and TxQ0Int.

{
        struct sis190_private *tp = netdev_priv(dev);
        void  *ioaddr = tp->mmio_addr;
        u32 status;

        status = SIS_R32(IntrStatus);

        if ((status == 0xffffffff) || !status)
                return;

        SIS_W32(IntrStatus, status);

        /* sis190_phy_task() needs to be called in event of a LinkChange and
         * after auto-negotiation is finished. Finishing auto-neg won't generate
         * any indication, hence we call it every time if the link is bad. */
        if ((status & LinkChange) || !netdev_link_ok(dev))
                sis190_phy_task(tp);

        if (status & RxQInt)
                sis190_process_rx(tp);

        if (status & TxQ0Int)
                sis190_process_tx(tp);
}
static void sis190_init_ring_indexes ( struct sis190_private tp) [inline, static]

Definition at line 370 of file sis190.c.

References sis190_private::cur_rx, sis190_private::cur_tx, sis190_private::dirty_rx, and sis190_private::dirty_tx.

Referenced by sis190_init_ring().

{
        tp->dirty_tx = tp->dirty_rx = tp->cur_tx = tp->cur_rx = 0;
}
static int sis190_init_ring ( struct net_device dev) [static]
static void sis190_set_rx_mode ( struct net_device dev) [static]

Definition at line 396 of file sis190.c.

References AcceptBroadcast, AcceptMulticast, AcceptMyPhys, ioaddr, sis190_private::mmio_addr, netdev_priv(), RxHashTable, RxMacControl, SIS_W16, SIS_W32, and tp.

Referenced by sis190_hw_start().

{
        struct sis190_private *tp = netdev_priv(dev);
        void *ioaddr = tp->mmio_addr;
        u32 mc_filter[2];       /* Multicast hash filter */
        u16 rx_mode;

        rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
        mc_filter[1] = mc_filter[0] = 0xffffffff;

        SIS_W16(RxMacControl, rx_mode | 0x2);
        SIS_W32(RxHashTable, mc_filter[0]);
        SIS_W32(RxHashTable + 4, mc_filter[1]);

}
static void sis190_soft_reset ( void *  ioaddr) [static]
static void sis190_hw_start ( struct net_device dev) [static]
static void sis190_phy_task ( struct sis190_private tp) [static]

Definition at line 448 of file sis190.c.

References ADVERTISE_1000FULL, ADVERTISE_1000HALF, BMCR_RESET, BMSR_ANEGCOMPLETE, DBG, sis190_private::dev, net_device::dev, EXPANSION_NWAY, F_HAS_RGMII, F_PHY_BCM5461, sis190_private::features, ioaddr, LPA_1000FULL, LPA_1000HALF, LPA_100FULL, LPA_100HALF, LPA_10FULL, LPA_10HALF, LPA_NPAGE, mdelay(), mdio_read(), mdio_read_latched(), mdio_write(), MII_ADVERTISE, MII_BMCR, MII_BMSR, MII_CTRL1000, MII_EXPANSION, sis190_private::mii_if, MII_LPA, MII_STAT1000, sis190_private::mmio_addr, msg(), netdev_link_down(), netdev_link_up(), NULL, mii_if_info::phy_id, RGDelay, SIS_R32, SIS_W32, StationControl, udelay(), and val.

Referenced by sis190_poll(), and sis190_probe().

{
        struct net_device *dev = tp->dev;
        void *ioaddr = tp->mmio_addr;
        int phy_id = tp->mii_if.phy_id;
        int cnt = 0;
        u16 val;

        val = mdio_read(ioaddr, phy_id, MII_BMCR);

        /* 100ms timeout is completely arbitrary. I have no datasheet to
         * check whether that's a sensible value or not.
         */
        while ((val & BMCR_RESET) && (cnt < 100)) {
                val = mdio_read(ioaddr, phy_id, MII_BMCR);
                mdelay(1);
                cnt++;
        }

        if (cnt > 99) {
                DBG("sis190: BMCR_RESET timeout\n");
                return;
        }

        if (!(mdio_read_latched(ioaddr, phy_id, MII_BMSR) &
                     BMSR_ANEGCOMPLETE)) {
                DBG("sis190: auto-negotiating...\n");
                netdev_link_down(dev);
        } else {
                /* Rejoice ! */
                struct {
                        int val;
                        u32 ctl;
                        const char *msg;
                } reg31[] = {
                        { LPA_1000FULL, 0x07000c00 | 0x00001000,
                                "1000 Mbps Full Duplex" },
                        { LPA_1000HALF, 0x07000c00,
                                "1000 Mbps Half Duplex" },
                        { LPA_100FULL, 0x04000800 | 0x00001000,
                                "100 Mbps Full Duplex" },
                        { LPA_100HALF, 0x04000800,
                                "100 Mbps Half Duplex" },
                        { LPA_10FULL, 0x04000400 | 0x00001000,
                                "10 Mbps Full Duplex" },
                        { LPA_10HALF, 0x04000400,
                                "10 Mbps Half Duplex" },
                        { 0, 0x04000400, "unknown" }
                }, *p = NULL;
                u16 adv, autoexp, gigadv, gigrec;

                val = mdio_read(ioaddr, phy_id, 0x1f);

                val = mdio_read(ioaddr, phy_id, MII_LPA);
                adv = mdio_read(ioaddr, phy_id, MII_ADVERTISE);

                autoexp = mdio_read(ioaddr, phy_id, MII_EXPANSION);

                if (val & LPA_NPAGE && autoexp & EXPANSION_NWAY) {
                        /* check for gigabit speed */
                        gigadv = mdio_read(ioaddr, phy_id, MII_CTRL1000);
                        gigrec = mdio_read(ioaddr, phy_id, MII_STAT1000);
                        val = (gigadv & (gigrec >> 2));
                        if (val & ADVERTISE_1000FULL)
                                p = reg31;
                        else if (val & ADVERTISE_1000HALF)
                                p = reg31 + 1;
                }

                if (!p) {
                        val &= adv;

                        for (p = reg31; p->val; p++) {
                                if ((val & p->val) == p->val)
                                        break;
                        }
                }

                p->ctl |= SIS_R32(StationControl) & ~0x0f001c00;

                if ((tp->features & F_HAS_RGMII) &&
                    (tp->features & F_PHY_BCM5461)) {
                        // Set Tx Delay in RGMII mode.
                        mdio_write(ioaddr, phy_id, 0x18, 0xf1c7);
                        udelay(200);
                        mdio_write(ioaddr, phy_id, 0x1c, 0x8c00);
                        p->ctl |= 0x03000000;
                }

                SIS_W32(StationControl, p->ctl);

                if (tp->features & F_HAS_RGMII) {
                        SIS_W32(RGDelay, 0x0441);
                        SIS_W32(RGDelay, 0x0440);
                }

                DBG("sis190: link on %s mode.\n", p->msg);
                netdev_link_up(dev);
        }
}
static int sis190_open ( struct net_device dev) [static]

Definition at line 549 of file sis190.c.

References cpu_to_le32, DBG, ENOMEM, error, malloc_dma(), netdev_priv(), out, rc, RING_ALIGNMENT, sis190_private::rx_dma, RX_RING_BYTES, sis190_private::RxDescRing, sis190_free(), sis190_hw_start(), sis190_init_ring(), sis190_init_rxfilter(), tp, sis190_private::tx_dma, TX_RING_BYTES, sis190_private::TxDescRing, and virt_to_bus().

{
        struct sis190_private *tp = netdev_priv(dev);
        int rc;

        /* Allocate TX ring */
        tp->TxDescRing = malloc_dma(TX_RING_BYTES, RING_ALIGNMENT);
        if (!tp->TxDescRing) {
                DBG("sis190: TX ring allocation failed\n");
                rc = -ENOMEM;
                goto out;
        }
        tp->tx_dma = cpu_to_le32(virt_to_bus(tp->TxDescRing));

        /* Allocate RX ring */
        tp->RxDescRing = malloc_dma(RX_RING_BYTES, RING_ALIGNMENT);
        if (!tp->RxDescRing) {
                DBG("sis190: RX ring allocation failed\n");
                rc = -ENOMEM;
                goto error;
        }
        tp->rx_dma = cpu_to_le32(virt_to_bus(tp->RxDescRing));

        rc = sis190_init_ring(dev);
        if (rc < 0)
                goto error;

        /* init rx filter, also program MAC address to card */
        sis190_init_rxfilter(dev);

        sis190_hw_start(dev);
out:
        return rc;

error:
        sis190_free(dev);
        goto out;
}
static void sis190_down ( struct net_device dev) [static]

Definition at line 588 of file sis190.c.

References IntrMask, ioaddr, sis190_private::mmio_addr, netdev_priv(), sis190_asic_down(), SIS_R32, and tp.

Referenced by sis190_close().

{
        struct sis190_private *tp = netdev_priv(dev);
        void  *ioaddr = tp->mmio_addr;

        do {
                sis190_asic_down(ioaddr);
        } while (SIS_R32(IntrMask));
}
static void sis190_free ( struct net_device dev) [static]
static void sis190_close ( struct net_device dev) [static]

Definition at line 625 of file sis190.c.

References sis190_down(), and sis190_free().

{
        sis190_down(dev);
        sis190_free(dev);
}
static int sis190_transmit ( struct net_device dev,
struct io_buffer iob 
) [static]

Definition at line 631 of file sis190.c.

References TxDesc::addr, CmdReset, CmdTxEnb, cpu_to_le32, CRCbit, sis190_private::cur_tx, io_buffer::data, DBG, DEFbit, EINVAL, entry, ETH_ZLEN, INTbit, ioaddr, iob_len(), iob_pad(), le32_to_cpu, len, sis190_private::mmio_addr, netdev_priv(), NUM_TX_DESC, OWNbit, PADbit, TxDesc::PSize, RingEnd, SIS_W32, TxDesc::size, TxDesc::status, tp, sis190_private::Tx_iobuf, TxControl, sis190_private::TxDescRing, virt_to_bus(), and wmb.

{
        struct sis190_private *tp = netdev_priv(dev);
        void  *ioaddr = tp->mmio_addr;
        u32 len, entry;
        struct TxDesc *desc;

        len = iob_len(iob);
        if (len < ETH_ZLEN) {
                iob_pad(iob, ETH_ZLEN);
                len = ETH_ZLEN;
        }

        entry = tp->cur_tx % NUM_TX_DESC;
        desc = tp->TxDescRing + entry;

        if (le32_to_cpu(desc->status) & OWNbit) {
                DBG("sis190: Tx Ring full\n");
                return -EINVAL;
        }

        tp->Tx_iobuf[entry] = iob;

        desc->PSize = cpu_to_le32(len);
        desc->addr = cpu_to_le32(virt_to_bus(iob->data));

        desc->size = cpu_to_le32(len);
        if (entry == (NUM_TX_DESC - 1))
                desc->size |= cpu_to_le32(RingEnd);

        wmb();

        desc->status = cpu_to_le32(OWNbit | INTbit | DEFbit | CRCbit | PADbit);

        tp->cur_tx++;

        SIS_W32(TxControl, 0x1a00 | CmdReset | CmdTxEnb);

        return 0;
}
static void sis190_free_phy ( struct list_head first_phy) [static]

Definition at line 672 of file sis190.c.

References free, sis190_phy::list, list_for_each_entry_safe, and next.

Referenced by sis190_mii_probe(), and sis190_mii_remove().

{
        struct sis190_phy *cur, *next;

        list_for_each_entry_safe(cur, next, first_phy, list) {
                free(cur);
        }
}
static u16 sis190_default_phy ( struct sis190_private tp) [static]

sis190_default_phy - Select default PHY for sis190 mac.

: the net device to probe for

Select first detected PHY with link as default. If no one is link on, select PHY whose types is HOME as default. If HOME doesn't exist, select LAN.

Definition at line 689 of file sis190.c.

References BMCR_ANENABLE, BMCR_ISOLATE, BMSR_LSTATUS, DBG, sis190_private::first_phy, HOME, ioaddr, LAN, list_entry, list_for_each_entry, mdio_read(), mdio_read_latched(), mdio_write(), MII_BMCR, MII_BMSR, sis190_private::mii_if, sis190_private::mmio_addr, NULL, phy, mii_if_info::phy_id, sis190_phy::phy_id, status, sis190_phy::type, and UNKNOWN.

Referenced by sis190_mii_probe().

{
        struct sis190_phy *phy, *phy_home, *phy_default, *phy_lan;
        struct mii_if_info *mii_if = &tp->mii_if;
        void  *ioaddr = tp->mmio_addr;
        u16 status;

        phy_home = phy_default = phy_lan = NULL;

        list_for_each_entry(phy, &tp->first_phy, list) {
                status = mdio_read_latched(ioaddr, phy->phy_id, MII_BMSR);

                // Link ON & Not select default PHY & not ghost PHY.
                if ((status & BMSR_LSTATUS) &&
                    !phy_default &&
                    (phy->type != UNKNOWN)) {
                        phy_default = phy;
                } else {
                        status = mdio_read(ioaddr, phy->phy_id, MII_BMCR);
                        mdio_write(ioaddr, phy->phy_id, MII_BMCR,
                                   status | BMCR_ANENABLE | BMCR_ISOLATE);
                        if (phy->type == HOME)
                                phy_home = phy;
                        else if (phy->type == LAN)
                                phy_lan = phy;
                }
        }

        if (!phy_default) {
                if (phy_home)
                        phy_default = phy_home;
                else if (phy_lan)
                        phy_default = phy_lan;
                else
                        phy_default = list_entry(&tp->first_phy,
                                                 struct sis190_phy, list);
        }

        if (mii_if->phy_id != phy_default->phy_id) {
                mii_if->phy_id = phy_default->phy_id;
                DBG("sis190: Using transceiver at address %d as default.\n",
                     mii_if->phy_id);
        }

        status = mdio_read(ioaddr, mii_if->phy_id, MII_BMCR);
        status &= (~BMCR_ISOLATE);

        mdio_write(ioaddr, mii_if->phy_id, MII_BMCR, status);
        status = mdio_read_latched(ioaddr, mii_if->phy_id, MII_BMSR);

        return status;
}
static void sis190_init_phy ( struct sis190_private tp,
struct sis190_phy phy,
unsigned int  phy_id,
u16  mii_status 
) [static]

Definition at line 742 of file sis190.c.

References BMSR_100FULL, BMSR_100HALF, DBG, mii_chip_info::feature, sis190_private::features, HOME, sis190_phy::id, mii_chip_info::id, INIT_LIST_HEAD, ioaddr, LAN, sis190_phy::list, mdio_read(), mii_chip_table, MII_PHYSID1, MII_PHYSID2, MIX, sis190_private::mmio_addr, mii_chip_info::name, sis190_phy::phy_id, sis190_phy::status, sis190_phy::type, mii_chip_info::type, and UNKNOWN.

Referenced by sis190_mii_probe().

{
        void *ioaddr = tp->mmio_addr;
        struct mii_chip_info *p;

        INIT_LIST_HEAD(&phy->list);
        phy->status = mii_status;
        phy->phy_id = phy_id;

        phy->id[0] = mdio_read(ioaddr, phy_id, MII_PHYSID1);
        phy->id[1] = mdio_read(ioaddr, phy_id, MII_PHYSID2);

        for (p = mii_chip_table; p->type; p++) {
                if ((p->id[0] == phy->id[0]) &&
                    (p->id[1] == (phy->id[1] & 0xfff0))) {
                        break;
                }
        }

        if (p->id[1]) {
                phy->type = (p->type == MIX) ?
                        ((mii_status & (BMSR_100FULL | BMSR_100HALF)) ?
                                LAN : HOME) : p->type;
                tp->features |= p->feature;

                DBG("sis190: %s transceiver at address %d.\n", p->name, phy_id);
        } else {
                phy->type = UNKNOWN;

                DBG("sis190: unknown PHY 0x%x:0x%x transceiver at address %d\n",
                    phy->id[0], (phy->id[1] & 0xfff0), phy_id);
        }
}
static void sis190_mii_probe_88e1111_fixup ( struct sis190_private tp) [static]

Definition at line 778 of file sis190.c.

References F_HAS_RGMII, F_PHY_88E1111, sis190_private::features, ioaddr, mdio_write(), sis190_private::mii_if, sis190_private::mmio_addr, mii_if_info::phy_id, reg, and udelay().

Referenced by sis190_mii_probe().

{
        if (tp->features & F_PHY_88E1111) {
                void *ioaddr = tp->mmio_addr;
                int phy_id = tp->mii_if.phy_id;
                u16 reg[2][2] = {
                        { 0x808b, 0x0ce1 },
                        { 0x808f, 0x0c60 }
                }, *p;

                p = (tp->features & F_HAS_RGMII) ? reg[0] : reg[1];

                mdio_write(ioaddr, phy_id, 0x1b, p[0]);
                udelay(200);
                mdio_write(ioaddr, phy_id, 0x14, p[1]);
                udelay(200);
        }
}
static int sis190_mii_probe ( struct net_device dev) [static]

sis190_mii_probe - Probe MII PHY for sis190 : the net device to probe for

Search for total of 32 possible mii phy addresses. Identify and set current phy if found one, return error if it failed to found.

Definition at line 805 of file sis190.c.

References __mdio_read(), __mdio_write(), DBG, mii_if_info::dev, EIO, ENOMEM, sis190_private::first_phy, INIT_LIST_HEAD, ioaddr, sis190_phy::list, list_add, list_empty, mii_if_info::mdio_read, mdio_read_latched(), mii_if_info::mdio_write, MII_BMSR, sis190_private::mii_if, MII_REG_ANY, sis190_private::mmio_addr, netdev_priv(), out, phy, mii_if_info::phy_id, PHY_ID_ANY, mii_if_info::phy_id_mask, PHY_MAX_ADDR, rc, mii_if_info::reg_num_mask, sis190_default_phy(), sis190_free_phy(), sis190_init_phy(), sis190_mii_probe_88e1111_fixup(), status, tp, and zalloc().

Referenced by sis190_probe().

{
        struct sis190_private *tp = netdev_priv(dev);
        struct mii_if_info *mii_if = &tp->mii_if;
        void *ioaddr = tp->mmio_addr;
        int phy_id;
        int rc = 0;

        INIT_LIST_HEAD(&tp->first_phy);

        for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) {
                struct sis190_phy *phy;
                u16 status;

                status = mdio_read_latched(ioaddr, phy_id, MII_BMSR);

                // Try next mii if the current one is not accessible.
                if (status == 0xffff || status == 0x0000)
                        continue;

                phy = zalloc(sizeof(*phy));
                if (!phy) {
                        sis190_free_phy(&tp->first_phy);
                        rc = -ENOMEM;
                        goto out;
                }

                DBG("sis190: found PHY\n");

                sis190_init_phy(tp, phy, phy_id, status);

                list_add(&tp->first_phy, &phy->list);
        }

        if (list_empty(&tp->first_phy)) {
                DBG("sis190: No MII transceivers found!\n");
                rc = -EIO;
                goto out;
        }

        /* Select default PHY for mac */
        sis190_default_phy(tp);

        sis190_mii_probe_88e1111_fixup(tp);

        mii_if->dev = dev;
        mii_if->mdio_read = __mdio_read;
        mii_if->mdio_write = __mdio_write;
        mii_if->phy_id_mask = PHY_ID_ANY;
        mii_if->reg_num_mask = MII_REG_ANY;
out:
        return rc;
}
static void sis190_mii_remove ( struct net_device dev) [static]

Definition at line 859 of file sis190.c.

References sis190_private::first_phy, netdev_priv(), sis190_free_phy(), and tp.

Referenced by sis190_probe(), and sis190_remove().

static int sis190_init_board ( struct pci_device pdev,
struct net_device **  netdev 
) [static]

Definition at line 866 of file sis190.c.

References adjust_pci_device(), alloc_etherdev(), DBG, pci_device::dev, sis190_private::dev, net_device::dev, EIO, ENOMEM, ioaddr, ioremap(), pci_device::membase, memset(), sis190_private::mmio_addr, netdev_priv(), sis190_private::pci_device, rc, sis190_irq_mask_and_ack(), SIS190_REGS_SIZE, sis190_soft_reset(), and tp.

Referenced by sis190_probe().

{
        struct sis190_private *tp;
        struct net_device *dev;
        void *ioaddr;
        int rc;

        dev = alloc_etherdev(sizeof(*tp));
        if (!dev) {
                DBG("sis190: unable to alloc new etherdev\n");
                rc = -ENOMEM;
                goto err;
        }

        dev->dev = &pdev->dev;

        tp = netdev_priv(dev);
        memset(tp, 0, sizeof(*tp));

        tp->dev = dev;

        adjust_pci_device(pdev);

        ioaddr = ioremap(pdev->membase, SIS190_REGS_SIZE);
        if (!ioaddr) {
                DBG("sis190: cannot remap MMIO, aborting\n");
                rc = -EIO;
                goto err;
        }

        tp->pci_device = pdev;
        tp->mmio_addr = ioaddr;

        sis190_irq_mask_and_ack(ioaddr);

        sis190_soft_reset(ioaddr);

        *netdev = dev;

        return 0;

err:
        return rc;
}
static void sis190_set_rgmii ( struct sis190_private tp,
u8  reg 
) [static]

Definition at line 911 of file sis190.c.

References F_HAS_RGMII, and sis190_private::features.

Referenced by sis190_get_mac_addr_from_apc(), and sis190_get_mac_addr_from_eeprom().

{
        tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
}
static int sis190_get_mac_addr_from_eeprom ( struct pci_device *pdev  __unused,
struct net_device dev 
) [static]

Definition at line 916 of file sis190.c.

References cpu_to_le16, DBG, EEPROMInfo, EEPROMMACAddr, EEPROMSignature, EIO, ETH_ALEN, net_device::hw_addr, ioaddr, sis190_private::mmio_addr, netdev_priv(), sig, sis190_read_eeprom(), sis190_set_rgmii(), tp, and u16.

Referenced by sis190_get_mac_addr().

{
        struct sis190_private *tp = netdev_priv(dev);
        void *ioaddr = tp->mmio_addr;
        u16 sig;
        int i;

        DBG("sis190: Read MAC address from EEPROM\n");

        /* Check to see if there is a sane EEPROM */
        sig = (u16) sis190_read_eeprom(ioaddr, EEPROMSignature);

        if ((sig == 0xffff) || (sig == 0x0000)) {
                DBG("sis190: Error EEPROM read.\n");
                return -EIO;
        }

        /* Get MAC address from EEPROM */
        for (i = 0; i < ETH_ALEN / 2; i++) {
                u16 w = sis190_read_eeprom(ioaddr, EEPROMMACAddr + i);

                ((u16 *)dev->hw_addr)[i] = cpu_to_le16(w);
        }

        sis190_set_rgmii(tp, sis190_read_eeprom(ioaddr, EEPROMInfo));

        return 0;
}
static int sis190_get_mac_addr_from_apc ( struct pci_device pdev,
struct net_device dev 
) [static]

sis190_get_mac_addr_from_apc - Get MAC address for SiS96x model : PCI device : network device to get address for

SiS96x model, use APC CMOS RAM to store MAC address. APC CMOS RAM is accessed through ISA bridge. MAC address is read into ->dev_addr.

Definition at line 955 of file sis190.c.

References container_of, DBG, pci_device::dev, pci_device::device, EIO, ETH_ALEN, net_device::hw_addr, inb(), list_for_each_entry, netdev_priv(), NULL, outb(), pci_read_config_byte(), pci_write_config_byte(), reg, device::siblings, sis190_set_rgmii(), tp, udelay(), and pci_device::vendor.

Referenced by sis190_get_mac_addr().

{
        struct sis190_private *tp = netdev_priv(dev);
        struct pci_device *isa_bridge = NULL;
        struct device *d;
        u8 reg, tmp8;
        unsigned int i;

        DBG("sis190: Read MAC address from APC.\n");

        list_for_each_entry(d, &(pdev->dev.siblings), siblings) {
                unsigned int i;
                for(i = 0; i < sis190_isa_bridge_driver.id_count; i++) {
                        isa_bridge = container_of(d, struct pci_device, dev);
                        if(isa_bridge->vendor ==
                             sis190_isa_bridge_driver.ids[i].vendor
                             && isa_bridge->device ==
                             sis190_isa_bridge_driver.ids[i].device) {
                                DBG("sis190: ISA bridge found\n");
                                break;
                        } else {
                                isa_bridge = NULL;
                        }
                }
                if(isa_bridge)
                        break;
        }

        if (!isa_bridge) {
                DBG("sis190: Can not find ISA bridge.\n");
                return -EIO;
        }

        /* Enable port 78h & 79h to access APC Registers. */
        pci_read_config_byte(isa_bridge, 0x48, &tmp8);
        reg = (tmp8 & ~0x02);
        pci_write_config_byte(isa_bridge, 0x48, reg);
        udelay(50);
        pci_read_config_byte(isa_bridge, 0x48, &reg);

        for (i = 0; i < ETH_ALEN; i++) {
                outb(0x9 + i, 0x78);
                dev->hw_addr[i] = inb(0x79);
        }

        outb(0x12, 0x78);
        reg = inb(0x79);

        sis190_set_rgmii(tp, reg);

        /* Restore the value to ISA Bridge */
        pci_write_config_byte(isa_bridge, 0x48, tmp8);

        return 0;
}
static void sis190_init_rxfilter ( struct net_device dev) [inline, static]

sis190_init_rxfilter - Initialize the Rx filter : network device to initialize

Set receive filter address to our MAC address and enable packet filtering.

Definition at line 1019 of file sis190.c.

References ETH_ALEN, ioaddr, net_device::ll_addr, sis190_private::mmio_addr, netdev_priv(), RxMacAddr, RxMacControl, SIS_PCI_COMMIT, SIS_R16, SIS_W16, SIS_W8, and tp.

Referenced by sis190_open().

{
        struct sis190_private *tp = netdev_priv(dev);
        void *ioaddr = tp->mmio_addr;
        u16 ctl;
        int i;

        ctl = SIS_R16(RxMacControl);
        /*
         * Disable packet filtering before setting filter.
         * Note: SiS's driver writes 32 bits but RxMacControl is 16 bits
         * only and followed by RxMacAddr (6 bytes). Strange. -- FR
         */
        SIS_W16(RxMacControl, ctl & ~0x0f00);

        for (i = 0; i < ETH_ALEN; i++)
                SIS_W8(RxMacAddr + i, dev->ll_addr[i]);

        SIS_W16(RxMacControl, ctl);
        SIS_PCI_COMMIT();
}
static int sis190_get_mac_addr ( struct pci_device pdev,
struct net_device dev 
) [static]

Definition at line 1041 of file sis190.c.

References pci_read_config_byte(), rc, reg, sis190_get_mac_addr_from_apc(), and sis190_get_mac_addr_from_eeprom().

Referenced by sis190_probe().

{
        int rc;

        rc = sis190_get_mac_addr_from_eeprom(pdev, dev);
        if (rc < 0) {
                u8 reg;

                pci_read_config_byte(pdev, 0x73, &reg);

                if (reg & 0x00000001)
                        rc = sis190_get_mac_addr_from_apc(pdev, dev);
        }
        return rc;
}
static void sis190_set_speed_auto ( struct net_device dev) [static]

Definition at line 1058 of file sis190.c.

References ADVERTISE_1000FULL, ADVERTISE_100FULL, ADVERTISE_100HALF, ADVERTISE_10FULL, ADVERTISE_10HALF, ADVERTISE_SLCT, BMCR_ANENABLE, BMCR_ANRESTART, BMCR_RESET, DBG, ioaddr, mdio_read(), mdio_write(), MII_ADVERTISE, MII_BMCR, MII_CTRL1000, sis190_private::mii_if, sis190_private::mmio_addr, netdev_priv(), mii_if_info::phy_id, tp, and val.

Referenced by sis190_probe().

{
        struct sis190_private *tp = netdev_priv(dev);
        void *ioaddr = tp->mmio_addr;
        int phy_id = tp->mii_if.phy_id;
        int val;

        DBG("sis190: Enabling Auto-negotiation.\n");

        val = mdio_read(ioaddr, phy_id, MII_ADVERTISE);

        // Enable 10/100 Full/Half Mode, leave MII_ADVERTISE bit4:0
        // unchanged.
        mdio_write(ioaddr, phy_id, MII_ADVERTISE, (val & ADVERTISE_SLCT) |
                   ADVERTISE_100FULL | ADVERTISE_10FULL |
                   ADVERTISE_100HALF | ADVERTISE_10HALF);

        // Enable 1000 Full Mode.
        mdio_write(ioaddr, phy_id, MII_CTRL1000, ADVERTISE_1000FULL);

        // Enable auto-negotiation and restart auto-negotiation.
        mdio_write(ioaddr, phy_id, MII_BMCR,
                   BMCR_ANENABLE | BMCR_ANRESTART | BMCR_RESET);
}
static void sis190_irq ( struct net_device dev,
int  enable 
) [static]

Definition at line 1083 of file sis190.c.

References IntrMask, IntrStatus, ioaddr, sis190_private::mmio_addr, netdev_priv(), SIS_PCI_COMMIT, SIS_W32, and tp.

{
        struct sis190_private *tp = netdev_priv(dev);
        void *ioaddr = tp->mmio_addr;

        SIS_W32(IntrStatus, 0xffffffff);

        if (enable == 0)
                SIS_W32(IntrMask, 0x00);
        else
                SIS_W32(IntrMask, sis190_intr_mask);

        SIS_PCI_COMMIT();
}
static int sis190_probe ( struct pci_device pdev) [static]

Definition at line 1106 of file sis190.c.

References net_device::dev, iounmap(), sis190_private::mmio_addr, netdev_init(), netdev_priv(), out, pci_set_drvdata(), rc, register_netdev(), sis190_get_mac_addr(), sis190_init_board(), sis190_mii_probe(), sis190_mii_remove(), sis190_phy_task(), sis190_set_speed_auto(), and tp.

{
        struct sis190_private *tp;
        struct net_device *dev;
        int rc;

        rc = sis190_init_board(pdev, &dev);
        if (rc < 0)
                goto out;
        netdev_init(dev, &sis190_netdev_ops);

        pci_set_drvdata(pdev, dev);

        tp = netdev_priv(dev);

        rc = sis190_get_mac_addr(pdev, dev);
        if (rc < 0)
                goto err;

        rc = sis190_mii_probe(dev);
        if (rc < 0)
                goto err;

        rc = register_netdev(dev);
        if (rc < 0)
                goto err;

        sis190_set_speed_auto(dev);
        sis190_phy_task(tp);

out:
        return rc;

err:
        sis190_mii_remove(dev);
        iounmap(tp->mmio_addr);
        goto out;
}
static void sis190_remove ( struct pci_device pdev) [static]

Variable Documentation

struct pci_device_id sis190_pci_tbl[] [static]
Initial value:
 {
        PCI_ROM (0x1039, 0x0190, "sis190", "sis190", 0),
        PCI_ROM (0x1039, 0x0191, "sis191", "sis191", 0),
}

Definition at line 28 of file sis190.c.

Initial value:
 {
        PCI_ID (0x1039, 0x0965, "", "", 0),
        PCI_ID (0x1039, 0x0966, "", "", 0),
        PCI_ID (0x1039, 0x0968, "", "", 0),
}

Definition at line 44 of file sis190.c.

struct pci_driver sis190_pci_driver __pci_driver
Initial value:
 {
        .ids            = sis190_isa_bridge_tbl,
        .id_count       = (sizeof(sis190_isa_bridge_tbl) /
                           sizeof(sis190_isa_bridge_tbl[0])),
        .probe          = sis190_isa_bridge_probe,
        .remove         = sis190_isa_bridge_remove,
}

Definition at line 60 of file sis190.c.

const u32 sis190_intr_mask [static]
Initial value:

Definition at line 72 of file sis190.c.

Initial value:
 {
        .open = sis190_open,
        .close = sis190_close,
        .poll = sis190_poll,
        .transmit = sis190_transmit,
        .irq = sis190_irq,
}

Definition at line 1098 of file sis190.c.