Annotation of qemu/roms/ipxe/src/drivers/net/amd8111e.c, revision 1.1

1.1     ! root        1: /* Advanced  Micro Devices Inc. AMD8111E Linux Network Driver 
        !             2:  * Copyright (C) 2004 Advanced Micro Devices 
        !             3:  * Copyright (C) 2005 Liu Tao <[email protected]> [etherboot port]
        !             4:  * 
        !             5:  * Copyright 2001,2002 Jeff Garzik <[email protected]> [ 8139cp.c,tg3.c ]
        !             6:  * Copyright (C) 2001, 2002 David S. Miller ([email protected])[ tg3.c]
        !             7:  * Copyright 1996-1999 Thomas Bogendoerfer [ pcnet32.c ]
        !             8:  * Derived from the lance driver written 1993,1994,1995 by Donald Becker.
        !             9:  * Copyright 1993 United States Government as represented by the
        !            10:  *     Director, National Security Agency.[ pcnet32.c ]
        !            11:  * Carsten Langgaard, [email protected] [ pcnet32.c ]
        !            12:  * Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
        !            13:  *
        !            14:  * 
        !            15:  * This program is free software; you can redistribute it and/or modify
        !            16:  * it under the terms of the GNU General Public License as published by
        !            17:  * the Free Software Foundation; either version 2 of the License, or
        !            18:  * (at your option) any later version.
        !            19:  *
        !            20:  * This program is distributed in the hope that it will be useful,
        !            21:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            22:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            23:  * GNU General Public License for more details.
        !            24:  *
        !            25:  * You should have received a copy of the GNU General Public License
        !            26:  * along with this program; if not, write to the Free Software
        !            27:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
        !            28:  * USA
        !            29:  */
        !            30: 
        !            31: FILE_LICENCE ( GPL2_OR_LATER );
        !            32: 
        !            33: #include "etherboot.h"
        !            34: #include "nic.h"
        !            35: #include "mii.h"
        !            36: #include <ipxe/pci.h>
        !            37: #include <ipxe/ethernet.h>
        !            38: #include "string.h"
        !            39: #include "stdint.h"
        !            40: #include "amd8111e.h"
        !            41: 
        !            42: 
        !            43: /* driver definitions */
        !            44: #define NUM_TX_SLOTS   2
        !            45: #define NUM_RX_SLOTS   4
        !            46: #define TX_SLOTS_MASK  1
        !            47: #define RX_SLOTS_MASK  3
        !            48: 
        !            49: #define TX_BUF_LEN     1536
        !            50: #define RX_BUF_LEN     1536
        !            51: 
        !            52: #define TX_PKT_LEN_MAX (ETH_FRAME_LEN - ETH_HLEN)
        !            53: #define RX_PKT_LEN_MIN 60
        !            54: #define RX_PKT_LEN_MAX ETH_FRAME_LEN
        !            55: 
        !            56: #define TX_TIMEOUT     3000
        !            57: #define TX_PROCESS_TIME        10
        !            58: #define TX_RETRY       (TX_TIMEOUT / TX_PROCESS_TIME)
        !            59: 
        !            60: #define PHY_RW_RETRY   10
        !            61: 
        !            62: 
        !            63: struct amd8111e_tx_desc {
        !            64:        u16 buf_len;
        !            65:        u16 tx_flags;
        !            66:        u16 tag_ctrl_info;
        !            67:        u16 tag_ctrl_cmd;
        !            68:        u32 buf_phy_addr;
        !            69:        u32 reserved;
        !            70: }; 
        !            71: 
        !            72: struct amd8111e_rx_desc {
        !            73:        u32 reserved;
        !            74:        u16 msg_len;
        !            75:        u16 tag_ctrl_info; 
        !            76:        u16 buf_len;
        !            77:        u16 rx_flags;
        !            78:        u32 buf_phy_addr;
        !            79: };
        !            80: 
        !            81: struct eth_frame {
        !            82:        u8 dst_addr[ETH_ALEN];
        !            83:        u8 src_addr[ETH_ALEN];
        !            84:        u16 type;
        !            85:        u8 data[ETH_FRAME_LEN - ETH_HLEN];
        !            86: } __attribute__((packed));
        !            87: 
        !            88: struct amd8111e_priv {
        !            89:        struct amd8111e_tx_desc tx_ring[NUM_TX_SLOTS];
        !            90:        struct amd8111e_rx_desc rx_ring[NUM_RX_SLOTS];
        !            91:        unsigned char tx_buf[NUM_TX_SLOTS][TX_BUF_LEN];
        !            92:        unsigned char rx_buf[NUM_RX_SLOTS][RX_BUF_LEN];
        !            93:        unsigned long tx_idx, rx_idx;
        !            94:        int tx_consistent;
        !            95: 
        !            96:        char opened;
        !            97:        char link;
        !            98:        char speed;
        !            99:        char duplex;
        !           100:        int ext_phy_addr;
        !           101:        u32 ext_phy_id;
        !           102: 
        !           103:        struct pci_device *pdev;
        !           104:        struct nic *nic;
        !           105:        void *mmio;
        !           106: };
        !           107: 
        !           108: static struct amd8111e_priv amd8111e;
        !           109: 
        !           110: 
        !           111: /********************************************************
        !           112:  *             locale functions                        *
        !           113:  ********************************************************/
        !           114: static void amd8111e_init_hw_default(struct amd8111e_priv *lp);
        !           115: static int amd8111e_start(struct amd8111e_priv *lp);
        !           116: static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val);
        !           117: #if 0
        !           118: static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val);
        !           119: #endif
        !           120: static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp);
        !           121: static void amd8111e_disable_interrupt(struct amd8111e_priv *lp);
        !           122: static void amd8111e_enable_interrupt(struct amd8111e_priv *lp);
        !           123: static void amd8111e_force_interrupt(struct amd8111e_priv *lp);
        !           124: static int amd8111e_get_mac_address(struct amd8111e_priv *lp);
        !           125: static int amd8111e_init_rx_ring(struct amd8111e_priv *lp);
        !           126: static int amd8111e_init_tx_ring(struct amd8111e_priv *lp);
        !           127: static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index);
        !           128: static void amd8111e_wait_link(struct amd8111e_priv *lp);
        !           129: static void amd8111e_poll_link(struct amd8111e_priv *lp);
        !           130: static void amd8111e_restart(struct amd8111e_priv *lp);
        !           131: 
        !           132: 
        !           133: /* 
        !           134:  * This function clears necessary the device registers. 
        !           135:  */    
        !           136: static void amd8111e_init_hw_default(struct amd8111e_priv *lp)
        !           137: {
        !           138:        unsigned int reg_val;
        !           139:        void *mmio = lp->mmio;
        !           140: 
        !           141:         /* stop the chip */
        !           142:        writel(RUN, mmio + CMD0);
        !           143: 
        !           144:        /* Clear RCV_RING_BASE_ADDR */
        !           145:        writel(0, mmio + RCV_RING_BASE_ADDR0);
        !           146: 
        !           147:        /* Clear XMT_RING_BASE_ADDR */
        !           148:        writel(0, mmio + XMT_RING_BASE_ADDR0);
        !           149:        writel(0, mmio + XMT_RING_BASE_ADDR1);
        !           150:        writel(0, mmio + XMT_RING_BASE_ADDR2);
        !           151:        writel(0, mmio + XMT_RING_BASE_ADDR3);
        !           152: 
        !           153:        /* Clear CMD0  */
        !           154:        writel(CMD0_CLEAR, mmio + CMD0);
        !           155:        
        !           156:        /* Clear CMD2 */
        !           157:        writel(CMD2_CLEAR, mmio + CMD2);
        !           158: 
        !           159:        /* Clear CMD7 */
        !           160:        writel(CMD7_CLEAR, mmio + CMD7);
        !           161: 
        !           162:        /* Clear DLY_INT_A and DLY_INT_B */
        !           163:        writel(0x0, mmio + DLY_INT_A);
        !           164:        writel(0x0, mmio + DLY_INT_B);
        !           165: 
        !           166:        /* Clear FLOW_CONTROL */
        !           167:        writel(0x0, mmio + FLOW_CONTROL);
        !           168: 
        !           169:        /* Clear INT0  write 1 to clear register */
        !           170:        reg_val = readl(mmio + INT0);
        !           171:        writel(reg_val, mmio + INT0);
        !           172: 
        !           173:        /* Clear STVAL */
        !           174:        writel(0x0, mmio + STVAL);
        !           175: 
        !           176:        /* Clear INTEN0 */
        !           177:        writel(INTEN0_CLEAR, mmio + INTEN0);
        !           178: 
        !           179:        /* Clear LADRF */
        !           180:        writel(0x0, mmio + LADRF);
        !           181: 
        !           182:        /* Set SRAM_SIZE & SRAM_BOUNDARY registers  */
        !           183:        writel(0x80010, mmio + SRAM_SIZE);
        !           184: 
        !           185:        /* Clear RCV_RING0_LEN */
        !           186:        writel(0x0, mmio +  RCV_RING_LEN0);
        !           187: 
        !           188:        /* Clear XMT_RING0/1/2/3_LEN */
        !           189:        writel(0x0, mmio +  XMT_RING_LEN0);
        !           190:        writel(0x0, mmio +  XMT_RING_LEN1);
        !           191:        writel(0x0, mmio +  XMT_RING_LEN2);
        !           192:        writel(0x0, mmio +  XMT_RING_LEN3);
        !           193: 
        !           194:        /* Clear XMT_RING_LIMIT */
        !           195:        writel(0x0, mmio + XMT_RING_LIMIT);
        !           196: 
        !           197:        /* Clear MIB */
        !           198:        writew(MIB_CLEAR, mmio + MIB_ADDR);
        !           199: 
        !           200:        /* Clear LARF */
        !           201:        writel( 0, mmio + LADRF);
        !           202:        writel( 0, mmio + LADRF + 4);
        !           203: 
        !           204:        /* SRAM_SIZE register */
        !           205:        reg_val = readl(mmio + SRAM_SIZE);
        !           206:        
        !           207:        /* Set default value to CTRL1 Register */
        !           208:        writel(CTRL1_DEFAULT, mmio + CTRL1);
        !           209: 
        !           210:        /* To avoid PCI posting bug */
        !           211:        readl(mmio + CMD2);
        !           212: }
        !           213: 
        !           214: /* 
        !           215:  * This function initializes the device registers  and starts the device.  
        !           216:  */
        !           217: static int amd8111e_start(struct amd8111e_priv *lp)
        !           218: {
        !           219:        struct nic *nic = lp->nic;
        !           220:        void *mmio = lp->mmio;
        !           221:        int i, reg_val;
        !           222: 
        !           223:        /* stop the chip */
        !           224:        writel(RUN, mmio + CMD0);
        !           225: 
        !           226:        /* AUTOPOLL0 Register *//*TBD default value is 8100 in FPS */
        !           227:        writew(0x8100 | lp->ext_phy_addr, mmio + AUTOPOLL0);
        !           228: 
        !           229:        /* enable the port manager and set auto negotiation always */
        !           230:        writel(VAL1 | EN_PMGR, mmio + CMD3 );
        !           231:        writel(XPHYANE | XPHYRST, mmio + CTRL2); 
        !           232: 
        !           233:        /* set control registers */
        !           234:        reg_val = readl(mmio + CTRL1);
        !           235:        reg_val &= ~XMTSP_MASK;
        !           236:        writel(reg_val | XMTSP_128 | CACHE_ALIGN, mmio + CTRL1);
        !           237: 
        !           238:        /* initialize tx and rx ring base addresses */
        !           239:        amd8111e_init_tx_ring(lp);
        !           240:        amd8111e_init_rx_ring(lp);
        !           241:        writel(virt_to_bus(lp->tx_ring), mmio + XMT_RING_BASE_ADDR0);
        !           242:        writel(virt_to_bus(lp->rx_ring), mmio + RCV_RING_BASE_ADDR0);
        !           243:        writew(NUM_TX_SLOTS, mmio + XMT_RING_LEN0);
        !           244:        writew(NUM_RX_SLOTS, mmio + RCV_RING_LEN0);
        !           245:        
        !           246:        /* set default IPG to 96 */
        !           247:        writew(DEFAULT_IPG, mmio + IPG);
        !           248:        writew(DEFAULT_IPG - IFS1_DELTA, mmio + IFS1); 
        !           249: 
        !           250:        /* AutoPAD transmit, Retransmit on Underflow */
        !           251:        writel(VAL0 | APAD_XMT | REX_RTRY | REX_UFLO, mmio + CMD2);
        !           252:        
        !           253:        /* JUMBO disabled */
        !           254:        writel(JUMBO, mmio + CMD3);
        !           255: 
        !           256:        /* Setting the MAC address to the device */
        !           257:        for(i = 0; i < ETH_ALEN; i++)
        !           258:                writeb(nic->node_addr[i], mmio + PADR + i); 
        !           259: 
        !           260:        /* set RUN bit to start the chip, interrupt not enabled */
        !           261:        writel(VAL2 | RDMD0 | VAL0 | RUN, mmio + CMD0);
        !           262:        
        !           263:        /* To avoid PCI posting bug */
        !           264:        readl(mmio + CMD0);
        !           265:        return 0;
        !           266: }
        !           267: 
        !           268: /* 
        !           269: This function will read the PHY registers.
        !           270: */
        !           271: static int amd8111e_read_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 *val)
        !           272: {
        !           273:        void *mmio = lp->mmio;
        !           274:        unsigned int reg_val;
        !           275:        unsigned int retry = PHY_RW_RETRY;
        !           276: 
        !           277:        reg_val = readl(mmio + PHY_ACCESS);
        !           278:        while (reg_val & PHY_CMD_ACTIVE)
        !           279:                reg_val = readl(mmio + PHY_ACCESS);
        !           280: 
        !           281:        writel(PHY_RD_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16),
        !           282:                mmio + PHY_ACCESS);
        !           283:        do {
        !           284:                reg_val = readl(mmio + PHY_ACCESS);
        !           285:                udelay(30);  /* It takes 30 us to read/write data */
        !           286:        } while (--retry && (reg_val & PHY_CMD_ACTIVE));
        !           287: 
        !           288:        if (reg_val & PHY_RD_ERR) {
        !           289:                *val = 0;
        !           290:                return -1;
        !           291:        }
        !           292:        
        !           293:        *val = reg_val & 0xffff;
        !           294:        return 0;
        !           295: }
        !           296: 
        !           297: /* 
        !           298: This function will write into PHY registers. 
        !           299: */
        !           300: #if 0
        !           301: static int amd8111e_write_phy(struct amd8111e_priv *lp, int phy_addr, int reg, u32 val)
        !           302: {
        !           303:        void *mmio = lp->mmio;
        !           304:        unsigned int reg_val;
        !           305:        unsigned int retry = PHY_RW_RETRY;
        !           306: 
        !           307:        reg_val = readl(mmio + PHY_ACCESS);
        !           308:        while (reg_val & PHY_CMD_ACTIVE)
        !           309:                reg_val = readl(mmio + PHY_ACCESS);
        !           310: 
        !           311:        writel(PHY_WR_CMD | ((phy_addr & 0x1f) << 21) | ((reg & 0x1f) << 16) | val,
        !           312:                mmio + PHY_ACCESS);
        !           313:        do {
        !           314:                reg_val = readl(mmio + PHY_ACCESS);
        !           315:                udelay(30);  /* It takes 30 us to read/write the data */
        !           316:        } while (--retry && (reg_val & PHY_CMD_ACTIVE));
        !           317:        
        !           318:        if(reg_val & PHY_RD_ERR)
        !           319:                return -1;
        !           320: 
        !           321:        return 0;
        !           322: }
        !           323: #endif
        !           324: 
        !           325: static void amd8111e_probe_ext_phy(struct amd8111e_priv *lp)
        !           326: {
        !           327:        int i;
        !           328: 
        !           329:        lp->ext_phy_id = 0;
        !           330:        lp->ext_phy_addr = 1;
        !           331:        
        !           332:        for (i = 0x1e; i >= 0; i--) {
        !           333:                u32 id1, id2;
        !           334: 
        !           335:                if (amd8111e_read_phy(lp, i, MII_PHYSID1, &id1))
        !           336:                        continue;
        !           337:                if (amd8111e_read_phy(lp, i, MII_PHYSID2, &id2))
        !           338:                        continue;
        !           339:                lp->ext_phy_id = (id1 << 16) | id2;
        !           340:                lp->ext_phy_addr = i;
        !           341:                break;
        !           342:        }
        !           343: 
        !           344:        if (lp->ext_phy_id)
        !           345:                printf("Found MII PHY ID 0x%08x at address 0x%02x\n",
        !           346:                       (unsigned int) lp->ext_phy_id, lp->ext_phy_addr);
        !           347:        else
        !           348:                printf("Couldn't detect MII PHY, assuming address 0x01\n");
        !           349: }
        !           350: 
        !           351: static void amd8111e_disable_interrupt(struct amd8111e_priv *lp)
        !           352: {
        !           353:        void *mmio = lp->mmio;
        !           354:        unsigned int int0;
        !           355: 
        !           356:        writel(INTREN, mmio + CMD0);
        !           357:        writel(INTEN0_CLEAR, mmio + INTEN0);
        !           358:        int0 = readl(mmio + INT0);
        !           359:        writel(int0, mmio + INT0);
        !           360:        readl(mmio + INT0);
        !           361: }
        !           362: 
        !           363: static void amd8111e_enable_interrupt(struct amd8111e_priv *lp)
        !           364: {
        !           365:        void *mmio = lp->mmio;
        !           366: 
        !           367:        writel(VAL3 | LCINTEN | VAL1 | TINTEN0 | VAL0 | RINTEN0, mmio + INTEN0);
        !           368:        writel(VAL0 | INTREN, mmio + CMD0);
        !           369:        readl(mmio + CMD0);
        !           370: }
        !           371: 
        !           372: static void amd8111e_force_interrupt(struct amd8111e_priv *lp)
        !           373: {
        !           374:        void *mmio = lp->mmio;
        !           375: 
        !           376:        writel(VAL0 | UINTCMD, mmio + CMD0);
        !           377:        readl(mmio + CMD0);
        !           378: }
        !           379: 
        !           380: static int amd8111e_get_mac_address(struct amd8111e_priv *lp)
        !           381: {
        !           382:        struct nic *nic = lp->nic;
        !           383:        void *mmio = lp->mmio;
        !           384:        int i;
        !           385: 
        !           386:        /* BIOS should have set mac address to PADR register,
        !           387:         * so we read PADR to get it.
        !           388:         */
        !           389:        for (i = 0; i < ETH_ALEN; i++)
        !           390:                nic->node_addr[i] = readb(mmio + PADR + i);
        !           391: 
        !           392:        DBG ( "Ethernet addr: %s\n", eth_ntoa ( nic->node_addr ) );
        !           393: 
        !           394:        return 0;
        !           395: }
        !           396: 
        !           397: static int amd8111e_init_rx_ring(struct amd8111e_priv *lp)
        !           398: {
        !           399:        int i;
        !           400: 
        !           401:        lp->rx_idx = 0;
        !           402:        
        !           403:         /* Initilaizing receive descriptors */
        !           404:        for (i = 0; i < NUM_RX_SLOTS; i++) {
        !           405:                lp->rx_ring[i].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[i]));
        !           406:                lp->rx_ring[i].buf_len = cpu_to_le16(RX_BUF_LEN);
        !           407:                wmb();
        !           408:                lp->rx_ring[i].rx_flags = cpu_to_le16(OWN_BIT);
        !           409:        }
        !           410: 
        !           411:        return 0;
        !           412: }
        !           413: 
        !           414: static int amd8111e_init_tx_ring(struct amd8111e_priv *lp)
        !           415: {
        !           416:        int i;
        !           417: 
        !           418:        lp->tx_idx = 0;
        !           419:        lp->tx_consistent = 1;
        !           420:        
        !           421:        /* Initializing transmit descriptors */
        !           422:        for (i = 0; i < NUM_TX_SLOTS; i++) {
        !           423:                lp->tx_ring[i].tx_flags = 0;
        !           424:                lp->tx_ring[i].buf_phy_addr = 0;
        !           425:                lp->tx_ring[i].buf_len = 0;
        !           426:        }
        !           427: 
        !           428:        return 0;
        !           429: }
        !           430: 
        !           431: static int amd8111e_wait_tx_ring(struct amd8111e_priv *lp, unsigned int index)
        !           432: {
        !           433:        volatile u16 status;
        !           434:        int retry = TX_RETRY;
        !           435: 
        !           436:        status = le16_to_cpu(lp->tx_ring[index].tx_flags);
        !           437:        while (--retry && (status & OWN_BIT)) {
        !           438:                mdelay(TX_PROCESS_TIME);
        !           439:                status = le16_to_cpu(lp->tx_ring[index].tx_flags);
        !           440:        }
        !           441:        if (status & OWN_BIT) {
        !           442:                printf("Error: tx slot %d timeout, stat = 0x%x\n", index, status);
        !           443:                amd8111e_restart(lp);
        !           444:                return -1;
        !           445:        }
        !           446: 
        !           447:        return 0;
        !           448: }
        !           449: 
        !           450: static void amd8111e_wait_link(struct amd8111e_priv *lp)
        !           451: {
        !           452:        unsigned int status;
        !           453:        u32 reg_val;
        !           454: 
        !           455:        do {
        !           456:                /* read phy to update STAT0 register */
        !           457:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
        !           458:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
        !           459:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
        !           460:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
        !           461:                status = readl(lp->mmio + STAT0);
        !           462:        } while (!(status & AUTONEG_COMPLETE) || !(status & LINK_STATS));
        !           463: }
        !           464: 
        !           465: static void amd8111e_poll_link(struct amd8111e_priv *lp)
        !           466: {
        !           467:        unsigned int status, speed;
        !           468:        u32 reg_val;
        !           469: 
        !           470:        if (!lp->link) {
        !           471:                /* read phy to update STAT0 register */
        !           472:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMCR, &reg_val);
        !           473:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_BMSR, &reg_val);
        !           474:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_ADVERTISE, &reg_val);
        !           475:                amd8111e_read_phy(lp, lp->ext_phy_addr, MII_LPA, &reg_val);
        !           476:                status = readl(lp->mmio + STAT0);
        !           477: 
        !           478:                if (status & LINK_STATS) {
        !           479:                        lp->link = 1;
        !           480:                        speed = (status & SPEED_MASK) >> 7;
        !           481:                        if (speed == PHY_SPEED_100)
        !           482:                                lp->speed = 1;
        !           483:                        else
        !           484:                                lp->speed = 0;
        !           485:                        if (status & FULL_DPLX)
        !           486:                                lp->duplex = 1;
        !           487:                        else
        !           488:                                lp->duplex = 0;
        !           489: 
        !           490:                        printf("Link is up: %s Mbps %s duplex\n",
        !           491:                                lp->speed ? "100" : "10", lp->duplex ? "full" : "half");
        !           492:                }
        !           493:        } else {
        !           494:                status = readl(lp->mmio + STAT0);
        !           495:                if (!(status & LINK_STATS)) {
        !           496:                        lp->link = 0;
        !           497:                        printf("Link is down\n");
        !           498:                }
        !           499:        }
        !           500: }
        !           501: 
        !           502: static void amd8111e_restart(struct amd8111e_priv *lp)
        !           503: {
        !           504:        printf("\nStarting nic...\n");
        !           505:        amd8111e_disable_interrupt(lp);
        !           506:        amd8111e_init_hw_default(lp);
        !           507:        amd8111e_probe_ext_phy(lp);
        !           508:        amd8111e_get_mac_address(lp);
        !           509:        amd8111e_start(lp);
        !           510: 
        !           511:        printf("Waiting link up...\n");
        !           512:        lp->link = 0;
        !           513:        amd8111e_wait_link(lp);
        !           514:        amd8111e_poll_link(lp);
        !           515: }
        !           516: 
        !           517: 
        !           518: /********************************************************
        !           519:  *             Interface Functions                     *
        !           520:  ********************************************************/
        !           521: 
        !           522: static void amd8111e_transmit(struct nic *nic, const char *dst_addr,
        !           523:                unsigned int type, unsigned int size, const char *packet)
        !           524: {
        !           525:        struct amd8111e_priv *lp = nic->priv_data;
        !           526:        struct eth_frame *frame;
        !           527:        unsigned int index;
        !           528: 
        !           529:        /* check packet size */
        !           530:        if (size > TX_PKT_LEN_MAX) {
        !           531:                printf("amd8111e_transmit(): too large packet, drop\n");
        !           532:                return;
        !           533:        }
        !           534: 
        !           535:        /* get tx slot */
        !           536:        index = lp->tx_idx;
        !           537:        if (amd8111e_wait_tx_ring(lp, index))
        !           538:                return;
        !           539: 
        !           540:        /* fill frame */
        !           541:        frame = (struct eth_frame *)lp->tx_buf[index];
        !           542:        memset(frame->data, 0, TX_PKT_LEN_MAX);
        !           543:        memcpy(frame->dst_addr, dst_addr, ETH_ALEN);
        !           544:        memcpy(frame->src_addr, nic->node_addr, ETH_ALEN);
        !           545:        frame->type = htons(type);
        !           546:        memcpy(frame->data, packet, size);
        !           547: 
        !           548:        /* start xmit */
        !           549:        lp->tx_ring[index].buf_len = cpu_to_le16(ETH_HLEN + size);
        !           550:        lp->tx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(frame));
        !           551:        wmb();
        !           552:        lp->tx_ring[index].tx_flags = 
        !           553:                cpu_to_le16(OWN_BIT | STP_BIT | ENP_BIT | ADD_FCS_BIT | LTINT_BIT);
        !           554:        writel(VAL1 | TDMD0, lp->mmio + CMD0);
        !           555:        readl(lp->mmio + CMD0);
        !           556: 
        !           557:        /* update slot pointer */
        !           558:        lp->tx_idx = (lp->tx_idx + 1) & TX_SLOTS_MASK;
        !           559: }
        !           560: 
        !           561: static int amd8111e_poll(struct nic *nic, int retrieve)
        !           562: {
        !           563:        /* return true if there's an ethernet packet ready to read */
        !           564:        /* nic->packet should contain data on return */
        !           565:        /* nic->packetlen should contain length of data */
        !           566: 
        !           567:        struct amd8111e_priv *lp = nic->priv_data;
        !           568:        u16 status, pkt_len;
        !           569:        unsigned int index, pkt_ok;
        !           570: 
        !           571:        amd8111e_poll_link(lp);
        !           572: 
        !           573:        index = lp->rx_idx;
        !           574:        status = le16_to_cpu(lp->rx_ring[index].rx_flags);
        !           575:        pkt_len = le16_to_cpu(lp->rx_ring[index].msg_len) - 4;  /* remove 4bytes FCS */
        !           576:        
        !           577:        if (status & OWN_BIT)
        !           578:                return 0;
        !           579: 
        !           580:        if (status & ERR_BIT)
        !           581:                pkt_ok = 0;
        !           582:        else if (!(status & STP_BIT))
        !           583:                pkt_ok = 0;
        !           584:        else if (!(status & ENP_BIT))
        !           585:                pkt_ok = 0;
        !           586:        else if (pkt_len < RX_PKT_LEN_MIN)
        !           587:                pkt_ok = 0;
        !           588:        else if (pkt_len > RX_PKT_LEN_MAX)
        !           589:                pkt_ok = 0;
        !           590:        else
        !           591:                pkt_ok = 1;
        !           592: 
        !           593:        if (pkt_ok) {
        !           594:                if (!retrieve)
        !           595:                        return 1;
        !           596:                nic->packetlen = pkt_len;
        !           597:                memcpy(nic->packet, lp->rx_buf[index], nic->packetlen);
        !           598:        }
        !           599: 
        !           600:        lp->rx_ring[index].buf_phy_addr = cpu_to_le32(virt_to_bus(lp->rx_buf[index]));
        !           601:        lp->rx_ring[index].buf_len = cpu_to_le16(RX_BUF_LEN);
        !           602:        wmb();
        !           603:        lp->rx_ring[index].rx_flags = cpu_to_le16(OWN_BIT);
        !           604:        writel(VAL2 | RDMD0, lp->mmio + CMD0);
        !           605:        readl(lp->mmio + CMD0);
        !           606: 
        !           607:        lp->rx_idx = (lp->rx_idx + 1) & RX_SLOTS_MASK;
        !           608:        return pkt_ok;
        !           609: }
        !           610: 
        !           611: static void amd8111e_disable(struct nic *nic)
        !           612: {
        !           613:        struct amd8111e_priv *lp = nic->priv_data;
        !           614: 
        !           615:        /* disable interrupt */
        !           616:        amd8111e_disable_interrupt(lp);
        !           617: 
        !           618:        /* stop chip */
        !           619:        amd8111e_init_hw_default(lp);
        !           620: 
        !           621:        /* unmap mmio */
        !           622:        iounmap(lp->mmio);
        !           623: 
        !           624:        /* update status */
        !           625:        lp->opened = 0;
        !           626: }
        !           627: 
        !           628: static void amd8111e_irq(struct nic *nic, irq_action_t action)
        !           629: {
        !           630:        struct amd8111e_priv *lp = nic->priv_data;
        !           631:                
        !           632:        switch (action) {
        !           633:        case DISABLE:
        !           634:                amd8111e_disable_interrupt(lp);
        !           635:                break;
        !           636:        case ENABLE:
        !           637:                amd8111e_enable_interrupt(lp);
        !           638:                break;
        !           639:        case FORCE:
        !           640:                amd8111e_force_interrupt(lp);
        !           641:                break;
        !           642:        }
        !           643: }
        !           644: 
        !           645: static struct nic_operations amd8111e_operations = {
        !           646:        .connect        = dummy_connect,
        !           647:        .poll           = amd8111e_poll,
        !           648:        .transmit       = amd8111e_transmit,
        !           649:        .irq            = amd8111e_irq,
        !           650: };
        !           651: 
        !           652: static int amd8111e_probe(struct nic *nic, struct pci_device *pdev)
        !           653: {
        !           654:        struct amd8111e_priv *lp = &amd8111e;
        !           655:        unsigned long mmio_start, mmio_len;
        !           656: 
        !           657:         nic->ioaddr = pdev->ioaddr;
        !           658:         nic->irqno  = pdev->irq;
        !           659:        
        !           660:        mmio_start = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
        !           661:        mmio_len = pci_bar_size(pdev, PCI_BASE_ADDRESS_0);
        !           662: 
        !           663:        memset(lp, 0, sizeof(*lp));
        !           664:        lp->pdev = pdev;
        !           665:        lp->nic = nic;
        !           666:        lp->mmio = ioremap(mmio_start, mmio_len);
        !           667:        lp->opened = 1;
        !           668:        adjust_pci_device(pdev);
        !           669: 
        !           670:        nic->priv_data = lp;
        !           671: 
        !           672:        amd8111e_restart(lp);
        !           673: 
        !           674:        nic->nic_op     = &amd8111e_operations;
        !           675:        return 1;
        !           676: }
        !           677: 
        !           678: static struct pci_device_id amd8111e_nics[] = {
        !           679:        PCI_ROM(0x1022, 0x7462, "amd8111e",     "AMD8111E", 0),
        !           680: };
        !           681: 
        !           682: PCI_DRIVER ( amd8111e_driver, amd8111e_nics, PCI_NO_CLASS );
        !           683: 
        !           684: DRIVER ( "AMD8111E", nic_driver, pci_driver, amd8111e_driver,
        !           685:         amd8111e_probe, amd8111e_disable );
        !           686: 
        !           687: /*
        !           688:  * Local variables:
        !           689:  *  c-basic-offset: 8
        !           690:  *  c-indent-level: 8
        !           691:  *  tab-width: 8
        !           692:  * End:
        !           693:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.