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

1.1     ! root        1: /**************************************************************************
        !             2: *
        !             3: *    mtd80x.c: Etherboot device driver for the mtd80x Ethernet chip.
        !             4: *    Written 2004-2004 by Erdem Güven <[email protected]>
        !             5: *
        !             6: *    This program is free software; you can redistribute it and/or modify
        !             7: *    it under the terms of the GNU General Public License as published by
        !             8: *    the Free Software Foundation; either version 2 of the License, or
        !             9: *    (at your option) any later version.
        !            10: *
        !            11: *    This program is distributed in the hope that it will be useful,
        !            12: *    but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: *    GNU General Public License for more details.
        !            15: *
        !            16: *    You should have received a copy of the GNU General Public License
        !            17: *    along with this program; if not, write to the Free Software
        !            18: *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            19: *
        !            20: *    Portions of this code based on:
        !            21: *               fealnx.c: A Linux device driver for the mtd80x Ethernet chip
        !            22: *               Written 1998-2000 by Donald Becker
        !            23: *
        !            24: ***************************************************************************/
        !            25: 
        !            26: FILE_LICENCE ( GPL2_OR_LATER );
        !            27: 
        !            28: /* to get some global routines like printf */
        !            29: #include "etherboot.h"
        !            30: /* to get the interface to the body of the program */
        !            31: #include "nic.h"
        !            32: /* to get the PCI support functions, if this is a PCI NIC */
        !            33: #include <ipxe/pci.h>
        !            34: #include <ipxe/ethernet.h>
        !            35: #include <mii.h>
        !            36: 
        !            37: /* Condensed operations for readability. */
        !            38: #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
        !            39: #define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
        !            40: #define get_unaligned(ptr) (*(ptr))
        !            41: 
        !            42: 
        !            43: /* Operational parameters that are set at compile time. */
        !            44: 
        !            45: /* Keep the ring sizes a power of two for compile efficiency.           */
        !            46: /* The compiler will convert <unsigned>'%'<2^N> into a bit mask.        */
        !            47: /* Making the Tx ring too large decreases the effectiveness of channel  */
        !            48: /* bonding and packet priority.                                         */
        !            49: /* There are no ill effects from too-large receive rings.               */
        !            50: #define TX_RING_SIZE 2
        !            51: #define TX_QUEUE_LEN 10 /* Limit ring entries actually used.  */
        !            52: #define RX_RING_SIZE 4
        !            53: 
        !            54: /* Operational parameters that usually are not changed. */
        !            55: /* Time in jiffies before concluding the transmitter is hung. */
        !            56: #define HZ 100
        !            57: #define TX_TIME_OUT   (6*HZ)
        !            58: 
        !            59: /* Allocation size of Rx buffers with normal sized Ethernet frames.
        !            60:    Do not change this value without good reason.  This is not a limit,
        !            61:    but a way to keep a consistent allocation size among drivers.
        !            62:  */
        !            63: #define PKT_BUF_SZ 1536
        !            64: 
        !            65: /* for different PHY */
        !            66: enum phy_type_flags {
        !            67:     MysonPHY = 1,
        !            68:     AhdocPHY = 2,
        !            69:     SeeqPHY = 3,
        !            70:     MarvellPHY = 4,
        !            71:     Myson981 = 5,
        !            72:     LevelOnePHY = 6,
        !            73:     OtherPHY = 10,
        !            74: };
        !            75: 
        !            76: /* A chip capabilities table*/
        !            77: enum chip_capability_flags {
        !            78:     HAS_MII_XCVR,
        !            79:     HAS_CHIP_XCVR,
        !            80: };
        !            81: 
        !            82: #if 0 /* not used */
        !            83: static
        !            84: struct chip_info
        !            85: {
        !            86:     u16 dev_id;
        !            87:     int flag;
        !            88: }
        !            89: mtd80x_chips[] = {
        !            90:                      {0x0800, HAS_MII_XCVR},
        !            91:                      {0x0803, HAS_CHIP_XCVR},
        !            92:                      {0x0891, HAS_MII_XCVR}
        !            93:                  };
        !            94: static int chip_cnt = sizeof( mtd80x_chips ) / sizeof( struct chip_info );
        !            95: #endif
        !            96: 
        !            97: /* Offsets to the Command and Status Registers. */
        !            98: enum mtd_offsets {
        !            99:     PAR0 = 0x0,        /* physical address 0-3 */
        !           100:     PAR1 = 0x04,        /* physical address 4-5 */
        !           101:     MAR0 = 0x08,        /* multicast address 0-3 */
        !           102:     MAR1 = 0x0C,        /* multicast address 4-7 */
        !           103:     FAR0 = 0x10,        /* flow-control address 0-3 */
        !           104:     FAR1 = 0x14,        /* flow-control address 4-5 */
        !           105:     TCRRCR = 0x18,        /* receive & transmit configuration */
        !           106:     BCR = 0x1C,        /* bus command */
        !           107:     TXPDR = 0x20,        /* transmit polling demand */
        !           108:     RXPDR = 0x24,        /* receive polling demand */
        !           109:     RXCWP = 0x28,        /* receive current word pointer */
        !           110:     TXLBA = 0x2C,        /* transmit list base address */
        !           111:     RXLBA = 0x30,        /* receive list base address */
        !           112:     ISR = 0x34,        /* interrupt status */
        !           113:     IMR = 0x38,        /* interrupt mask */
        !           114:     FTH = 0x3C,        /* flow control high/low threshold */
        !           115:     MANAGEMENT = 0x40,    /* bootrom/eeprom and mii management */
        !           116:     TALLY = 0x44,        /* tally counters for crc and mpa */
        !           117:     TSR = 0x48,        /* tally counter for transmit status */
        !           118:     BMCRSR = 0x4c,        /* basic mode control and status */
        !           119:     PHYIDENTIFIER = 0x50,    /* phy identifier */
        !           120:     ANARANLPAR = 0x54,    /* auto-negotiation advertisement and link
        !           121:                                                        partner ability */
        !           122:     ANEROCR = 0x58,        /* auto-negotiation expansion and pci conf. */
        !           123:     BPREMRPSR = 0x5c,    /* bypass & receive error mask and phy status */
        !           124: };
        !           125: 
        !           126: /* Bits in the interrupt status/enable registers. */
        !           127: /* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
        !           128: enum intr_status_bits {
        !           129:     RFCON = 0x00020000, /* receive flow control xon packet */
        !           130:     RFCOFF = 0x00010000, /* receive flow control xoff packet */
        !           131:     LSCStatus = 0x00008000, /* link status change */
        !           132:     ANCStatus = 0x00004000, /* autonegotiation completed */
        !           133:     FBE = 0x00002000, /* fatal bus error */
        !           134:     FBEMask = 0x00001800, /* mask bit12-11 */
        !           135:     ParityErr = 0x00000000, /* parity error */
        !           136:     TargetErr = 0x00001000, /* target abort */
        !           137:     MasterErr = 0x00000800, /* master error */
        !           138:     TUNF = 0x00000400, /* transmit underflow */
        !           139:     ROVF = 0x00000200, /* receive overflow */
        !           140:     ETI = 0x00000100, /* transmit early int */
        !           141:     ERI = 0x00000080, /* receive early int */
        !           142:     CNTOVF = 0x00000040, /* counter overflow */
        !           143:     RBU = 0x00000020, /* receive buffer unavailable */
        !           144:     TBU = 0x00000010, /* transmit buffer unavilable */
        !           145:     TI = 0x00000008, /* transmit interrupt */
        !           146:     RI = 0x00000004, /* receive interrupt */
        !           147:     RxErr = 0x00000002, /* receive error */
        !           148: };
        !           149: 
        !           150: /* Bits in the NetworkConfig register. */
        !           151: enum rx_mode_bits {
        !           152:     RxModeMask   = 0xe0,
        !           153:     AcceptAllPhys = 0x80,        /* promiscuous mode */
        !           154:     AcceptBroadcast = 0x40,        /* accept broadcast */
        !           155:     AcceptMulticast = 0x20,        /* accept mutlicast */
        !           156:     AcceptRunt   = 0x08,        /* receive runt pkt */
        !           157:     ALP          = 0x04,        /* receive long pkt */
        !           158:     AcceptErr    = 0x02,        /* receive error pkt */
        !           159: 
        !           160:     AcceptMyPhys = 0x00000000,
        !           161:     RxEnable     = 0x00000001,
        !           162:     RxFlowCtrl   = 0x00002000,
        !           163:     TxEnable     = 0x00040000,
        !           164:     TxModeFDX    = 0x00100000,
        !           165:     TxThreshold  = 0x00e00000,
        !           166: 
        !           167:     PS1000       = 0x00010000,
        !           168:     PS10         = 0x00080000,
        !           169:     FD           = 0x00100000,
        !           170: };
        !           171: 
        !           172: /* Bits in network_desc.status */
        !           173: enum rx_desc_status_bits {
        !           174:     RXOWN = 0x80000000, /* own bit */
        !           175:     FLNGMASK = 0x0fff0000, /* frame length */
        !           176:     FLNGShift = 16,
        !           177:     MARSTATUS = 0x00004000, /* multicast address received */
        !           178:     BARSTATUS = 0x00002000, /* broadcast address received */
        !           179:     PHYSTATUS = 0x00001000, /* physical address received */
        !           180:     RXFSD = 0x00000800, /* first descriptor */
        !           181:     RXLSD = 0x00000400, /* last descriptor */
        !           182:     ErrorSummary = 0x80, /* error summary */
        !           183:     RUNT = 0x40,  /* runt packet received */
        !           184:     LONG = 0x20,  /* long packet received */
        !           185:     FAE = 0x10,  /* frame align error */
        !           186:     CRC = 0x08,  /* crc error */
        !           187:     RXER = 0x04,  /* receive error */
        !           188: };
        !           189: 
        !           190: enum rx_desc_control_bits {
        !           191:     RXIC = 0x00800000, /* interrupt control */
        !           192:     RBSShift = 0,
        !           193: };
        !           194: 
        !           195: enum tx_desc_status_bits {
        !           196:     TXOWN = 0x80000000, /* own bit */
        !           197:     JABTO = 0x00004000, /* jabber timeout */
        !           198:     CSL = 0x00002000, /* carrier sense lost */
        !           199:     LC = 0x00001000, /* late collision */
        !           200:     EC = 0x00000800, /* excessive collision */
        !           201:     UDF = 0x00000400, /* fifo underflow */
        !           202:     DFR = 0x00000200, /* deferred */
        !           203:     HF = 0x00000100, /* heartbeat fail */
        !           204:     NCRMask = 0x000000ff, /* collision retry count */
        !           205:     NCRShift = 0,
        !           206: };
        !           207: 
        !           208: enum tx_desc_control_bits {
        !           209:     TXIC = 0x80000000, /* interrupt control */
        !           210:     ETIControl = 0x40000000, /* early transmit interrupt */
        !           211:     TXLD = 0x20000000, /* last descriptor */
        !           212:     TXFD = 0x10000000, /* first descriptor */
        !           213:     CRCEnable = 0x08000000, /* crc control */
        !           214:     PADEnable = 0x04000000, /* padding control */
        !           215:     RetryTxLC = 0x02000000, /* retry late collision */
        !           216:     PKTSMask = 0x3ff800, /* packet size bit21-11 */
        !           217:     PKTSShift = 11,
        !           218:     TBSMask = 0x000007ff, /* transmit buffer bit 10-0 */
        !           219:     TBSShift = 0,
        !           220: };
        !           221: 
        !           222: /* BootROM/EEPROM/MII Management Register */
        !           223: #define MASK_MIIR_MII_READ       0x00000000
        !           224: #define MASK_MIIR_MII_WRITE      0x00000008
        !           225: #define MASK_MIIR_MII_MDO        0x00000004
        !           226: #define MASK_MIIR_MII_MDI        0x00000002
        !           227: #define MASK_MIIR_MII_MDC        0x00000001
        !           228: 
        !           229: /* ST+OP+PHYAD+REGAD+TA */
        !           230: #define OP_READ             0x6000 /* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */
        !           231: #define OP_WRITE            0x5002 /* ST:01+OP:01+PHYAD+REGAD+TA:10 */
        !           232: 
        !           233: /* ------------------------------------------------------------------------- */
        !           234: /*      Constants for Myson PHY                                              */
        !           235: /* ------------------------------------------------------------------------- */
        !           236: #define MysonPHYID      0xd0000302
        !           237: /* 89-7-27 add, (begin) */
        !           238: #define MysonPHYID0     0x0302
        !           239: #define StatusRegister  18
        !           240: #define SPEED100        0x0400 // bit10
        !           241: #define FULLMODE        0x0800 // bit11
        !           242: /* 89-7-27 add, (end) */
        !           243: 
        !           244: /* ------------------------------------------------------------------------- */
        !           245: /*      Constants for Seeq 80225 PHY                                         */
        !           246: /* ------------------------------------------------------------------------- */
        !           247: #define SeeqPHYID0      0x0016
        !           248: 
        !           249: #define MIIRegister18   18
        !           250: #define SPD_DET_100     0x80
        !           251: #define DPLX_DET_FULL   0x40
        !           252: 
        !           253: /* ------------------------------------------------------------------------- */
        !           254: /*      Constants for Ahdoc 101 PHY                                          */
        !           255: /* ------------------------------------------------------------------------- */
        !           256: #define AhdocPHYID0     0x0022
        !           257: 
        !           258: #define DiagnosticReg   18
        !           259: #define DPLX_FULL       0x0800
        !           260: #define Speed_100       0x0400
        !           261: 
        !           262: /* 89/6/13 add, */
        !           263: /* -------------------------------------------------------------------------- */
        !           264: /*      Constants                                                             */
        !           265: /* -------------------------------------------------------------------------- */
        !           266: #define MarvellPHYID0           0x0141
        !           267: #define LevelOnePHYID0  0x0013
        !           268: 
        !           269: #define MII1000BaseTControlReg  9
        !           270: #define MII1000BaseTStatusReg   10
        !           271: #define SpecificReg  17
        !           272: 
        !           273: /* for 1000BaseT Control Register */
        !           274: #define PHYAbletoPerform1000FullDuplex  0x0200
        !           275: #define PHYAbletoPerform1000HalfDuplex  0x0100
        !           276: #define PHY1000AbilityMask              0x300
        !           277: 
        !           278: // for phy specific status register, marvell phy.
        !           279: #define SpeedMask       0x0c000
        !           280: #define Speed_1000M     0x08000
        !           281: #define Speed_100M      0x4000
        !           282: #define Speed_10M       0
        !           283: #define Full_Duplex     0x2000
        !           284: 
        !           285: // 89/12/29 add, for phy specific status register, levelone phy, (begin)
        !           286: #define LXT1000_100M    0x08000
        !           287: #define LXT1000_1000M   0x0c000
        !           288: #define LXT1000_Full    0x200
        !           289: // 89/12/29 add, for phy specific status register, levelone phy, (end)
        !           290: 
        !           291: #if 0
        !           292: /* for 3-in-1 case */
        !           293: #define PS10            0x00080000
        !           294: #define FD              0x00100000
        !           295: #define PS1000          0x00010000
        !           296: #endif
        !           297: 
        !           298: /* for PHY */
        !           299: #define LinkIsUp        0x0004
        !           300: #define LinkIsUp2 0x00040000
        !           301: 
        !           302: /* Create a static buffer of size PKT_BUF_SZ for each
        !           303: RX and TX Descriptor.  All descriptors point to a
        !           304: part of this buffer */
        !           305: struct {
        !           306:        u8 txb[PKT_BUF_SZ * TX_RING_SIZE] __attribute__ ((aligned(8)));
        !           307:        u8 rxb[PKT_BUF_SZ * RX_RING_SIZE] __attribute__ ((aligned(8)));
        !           308: } mtd80x_bufs __shared;
        !           309: #define txb mtd80x_bufs.txb
        !           310: #define rxb mtd80x_bufs.rxb
        !           311: 
        !           312: /* The Tulip Rx and Tx buffer descriptors. */
        !           313: struct mtd_desc
        !           314: {
        !           315:     s32 status;
        !           316:     s32 control;
        !           317:     u32 buffer;
        !           318:     u32 next_desc;
        !           319:     struct mtd_desc *next_desc_logical;
        !           320:     u8* skbuff;
        !           321:     u32 reserved1;
        !           322:     u32 reserved2;
        !           323: };
        !           324: 
        !           325: struct mtd_private
        !           326: {
        !           327:     struct mtd_desc rx_ring[RX_RING_SIZE];
        !           328:     struct mtd_desc tx_ring[TX_RING_SIZE];
        !           329: 
        !           330:     /* Frequently used values: keep some adjacent for cache effect. */
        !           331:     int flags;
        !           332:     struct pci_dev *pci_dev;
        !           333:     unsigned long crvalue;
        !           334:     unsigned long bcrvalue;
        !           335:     /*unsigned long imrvalue;*/
        !           336:     struct mtd_desc *cur_rx;
        !           337:     struct mtd_desc *lack_rxbuf;
        !           338:     int really_rx_count;
        !           339:     struct mtd_desc *cur_tx;
        !           340:     struct mtd_desc *cur_tx_copy;
        !           341:     int really_tx_count;
        !           342:     int free_tx_count;
        !           343:     unsigned int rx_buf_sz; /* Based on MTU+slack. */
        !           344: 
        !           345:     /* These values are keep track of the transceiver/media in use. */
        !           346:     unsigned int linkok;
        !           347:     unsigned int line_speed;
        !           348:     unsigned int duplexmode;
        !           349:     unsigned int default_port:
        !           350:     4; /* Last dev->if_port value. */
        !           351:     unsigned int PHYType;
        !           352: 
        !           353:     /* MII transceiver section. */
        !           354:     int mii_cnt;  /* MII device addresses. */
        !           355:     unsigned char phys[1]; /* MII device addresses. */
        !           356: 
        !           357:     /*other*/
        !           358:     const char *nic_name;
        !           359:     int ioaddr;
        !           360:     u16 dev_id;
        !           361: };
        !           362: 
        !           363: static struct mtd_private mtdx;
        !           364: 
        !           365: static int mdio_read(struct nic * , int phy_id, int location);
        !           366: static void getlinktype(struct nic * );
        !           367: static void getlinkstatus(struct nic * );
        !           368: static void set_rx_mode(struct nic *);
        !           369: 
        !           370: /**************************************************************************
        !           371:  *  init_ring - setup the tx and rx descriptors
        !           372:  *************************************************************************/
        !           373: static void init_ring(struct nic *nic __unused)
        !           374: {
        !           375:     int i;
        !           376: 
        !           377:     mtdx.cur_rx = &mtdx.rx_ring[0];
        !           378: 
        !           379:     mtdx.rx_buf_sz = PKT_BUF_SZ;
        !           380:     /*mtdx.rx_head_desc = &mtdx.rx_ring[0];*/
        !           381: 
        !           382:     /* Initialize all Rx descriptors. */
        !           383:     /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        !           384:     for (i = 0; i < RX_RING_SIZE; i++)
        !           385:     {
        !           386:         mtdx.rx_ring[i].status = RXOWN;
        !           387:         mtdx.rx_ring[i].control = mtdx.rx_buf_sz << RBSShift;
        !           388:         mtdx.rx_ring[i].next_desc = virt_to_le32desc(&mtdx.rx_ring[i+1]);
        !           389:         mtdx.rx_ring[i].next_desc_logical = &mtdx.rx_ring[i+1];
        !           390:         mtdx.rx_ring[i].buffer = virt_to_le32desc(&rxb[i * PKT_BUF_SZ]);
        !           391:         mtdx.rx_ring[i].skbuff = &rxb[i * PKT_BUF_SZ];
        !           392:     }
        !           393:     /* Mark the last entry as wrapping the ring. */
        !           394:     mtdx.rx_ring[i-1].next_desc = virt_to_le32desc(&mtdx.rx_ring[0]);
        !           395:     mtdx.rx_ring[i-1].next_desc_logical = &mtdx.rx_ring[0];
        !           396: 
        !           397:     /* We only use one transmit buffer, but two
        !           398:      * descriptors so transmit engines have somewhere
        !           399:      * to point should they feel the need */
        !           400:     mtdx.tx_ring[0].status = 0x00000000;
        !           401:     mtdx.tx_ring[0].buffer = virt_to_bus(&txb[0]);
        !           402:     mtdx.tx_ring[0].next_desc = virt_to_le32desc(&mtdx.tx_ring[1]);
        !           403: 
        !           404:     /* This descriptor is never used */
        !           405:     mtdx.tx_ring[1].status = 0x00000000;
        !           406:     mtdx.tx_ring[1].buffer = 0; /*virt_to_bus(&txb[1]); */
        !           407:     mtdx.tx_ring[1].next_desc = virt_to_le32desc(&mtdx.tx_ring[0]);
        !           408: 
        !           409:     return;
        !           410: }
        !           411: 
        !           412: /**************************************************************************
        !           413: RESET - Reset Adapter
        !           414: ***************************************************************************/
        !           415: static void mtd_reset( struct nic *nic )
        !           416: {
        !           417:     /* Reset the chip to erase previous misconfiguration. */
        !           418:     outl(0x00000001, mtdx.ioaddr + BCR);
        !           419: 
        !           420:     init_ring(nic);
        !           421: 
        !           422:     outl(virt_to_bus(mtdx.rx_ring), mtdx.ioaddr + RXLBA);
        !           423:     outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
        !           424: 
        !           425:     /* Initialize other registers. */
        !           426:     /* Configure the PCI bus bursts and FIFO thresholds. */
        !           427:     mtdx.bcrvalue = 0x10; /* little-endian, 8 burst length */
        !           428:     mtdx.crvalue = 0xa00; /* rx 128 burst length */
        !           429: 
        !           430:        if ( mtdx.dev_id == 0x891 ) {
        !           431:                mtdx.bcrvalue |= 0x200; /* set PROG bit */
        !           432:                mtdx.crvalue |= 0x02000000;     /* set enhanced bit */
        !           433:        }
        !           434: 
        !           435:     outl( mtdx.bcrvalue, mtdx.ioaddr + BCR);
        !           436: 
        !           437:     /* Restart Rx engine if stopped. */
        !           438:     outl(0, mtdx.ioaddr + RXPDR);
        !           439: 
        !           440:     getlinkstatus(nic);
        !           441:     if (mtdx.linkok)
        !           442:     {
        !           443:         static const char* texts[]={"half","full","10","100","1000"};
        !           444:         getlinktype(nic);
        !           445:         DBG ( "Link is OK : %s %s\n", texts[mtdx.duplexmode-1], texts[mtdx.line_speed+1] );
        !           446:     } else
        !           447:     {
        !           448:         DBG ( "No link!!!\n" );
        !           449:     }
        !           450: 
        !           451:     mtdx.crvalue |= /*TxEnable |*/ RxEnable | TxThreshold;
        !           452:     set_rx_mode(nic);
        !           453: 
        !           454:     /* Clear interrupts by setting the interrupt mask. */
        !           455:     outl(FBE | TUNF | CNTOVF | RBU | TI | RI, mtdx.ioaddr + ISR);
        !           456:     outl( 0, mtdx.ioaddr + IMR);
        !           457: }
        !           458: 
        !           459: /**************************************************************************
        !           460: POLL - Wait for a frame
        !           461: ***************************************************************************/
        !           462: static int mtd_poll(struct nic *nic, __unused int retrieve)
        !           463: {
        !           464:     s32 rx_status = mtdx.cur_rx->status;
        !           465:     int retval = 0;
        !           466: 
        !           467:     if( ( rx_status & RXOWN ) != 0 )
        !           468:     {
        !           469:         return 0;
        !           470:     }
        !           471: 
        !           472:     if (rx_status & ErrorSummary)
        !           473:     { /* there was a fatal error */
        !           474:         printf( "%s: Receive error, Rx status %8.8x, Error(s) %s%s%s\n",
        !           475:                 mtdx.nic_name, (unsigned int) rx_status,
        !           476:                 (rx_status & (LONG | RUNT)) ? "length_error ":"",
        !           477:                 (rx_status & RXER) ? "frame_error ":"",
        !           478:                 (rx_status & CRC) ? "crc_error ":"" );
        !           479:         retval = 0;
        !           480:     } else if( !((rx_status & RXFSD) && (rx_status & RXLSD)) )
        !           481:     {
        !           482:         /* this pkt is too long, over one rx buffer */
        !           483:         printf("Pkt is too long, over one rx buffer.\n");
        !           484:         retval = 0;
        !           485:     } else
        !           486:     { /* this received pkt is ok */
        !           487:         /* Omit the four octet CRC from the length. */
        !           488:         short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
        !           489: 
        !           490:         DBG ( " netdev_rx() normal Rx pkt length %d"
        !           491:              " status %x.\n", pkt_len, (unsigned int) rx_status );
        !           492: 
        !           493:         nic->packetlen = pkt_len;
        !           494:         memcpy(nic->packet, mtdx.cur_rx->skbuff, pkt_len);
        !           495: 
        !           496:         retval = 1;
        !           497:     }
        !           498: 
        !           499:     while( ( mtdx.cur_rx->status & RXOWN ) == 0 )
        !           500:     {
        !           501:         mtdx.cur_rx->status = RXOWN;
        !           502:         mtdx.cur_rx = mtdx.cur_rx->next_desc_logical;
        !           503:     }
        !           504: 
        !           505:     /* Restart Rx engine if stopped. */
        !           506:     outl(0, mtdx.ioaddr + RXPDR);
        !           507: 
        !           508:     return retval;
        !           509: }
        !           510: 
        !           511: /**************************************************************************
        !           512: TRANSMIT - Transmit a frame
        !           513: ***************************************************************************/
        !           514: static void mtd_transmit(
        !           515:     struct nic *nic,
        !           516:     const char *dest,            /* Destination */
        !           517:     unsigned int type,            /* Type */
        !           518:     unsigned int size,            /* size */
        !           519:     const char *data)            /* Packet */
        !           520: {
        !           521:     u32 to;
        !           522:     u32 tx_status;
        !           523:     unsigned int nstype = htons ( type );
        !           524: 
        !           525:     memcpy( txb, dest, ETH_ALEN );
        !           526:     memcpy( txb + ETH_ALEN, nic->node_addr, ETH_ALEN );
        !           527:     memcpy( txb + 2 * ETH_ALEN, &nstype, 2 );
        !           528:     memcpy( txb + ETH_HLEN, data, size );
        !           529: 
        !           530:     size += ETH_HLEN;
        !           531:     size &= 0x0FFF;
        !           532:     while( size < ETH_ZLEN )
        !           533:     {
        !           534:         txb[size++] = '\0';
        !           535:     }
        !           536: 
        !           537:     mtdx.tx_ring[0].control = TXLD | TXFD | CRCEnable | PADEnable;
        !           538:     mtdx.tx_ring[0].control |= (size << PKTSShift); /* pkt size */
        !           539:     mtdx.tx_ring[0].control |= (size << TBSShift); /* buffer size */
        !           540:     mtdx.tx_ring[0].status = TXOWN;
        !           541: 
        !           542:     /* Point to transmit descriptor */
        !           543:     outl(virt_to_bus(mtdx.tx_ring), mtdx.ioaddr + TXLBA);
        !           544:     /* Enable Tx */
        !           545:     outl( mtdx.crvalue | TxEnable, mtdx.ioaddr + TCRRCR);
        !           546:     /* Wake the potentially-idle transmit channel. */
        !           547:     outl(0, mtdx.ioaddr + TXPDR);
        !           548: 
        !           549:     to = currticks() + TX_TIME_OUT;
        !           550:     while(( mtdx.tx_ring[0].status & TXOWN) && (currticks() < to));
        !           551: 
        !           552:     /* Disable Tx */
        !           553:     outl( mtdx.crvalue & (~TxEnable), mtdx.ioaddr + TCRRCR);
        !           554: 
        !           555:     tx_status = mtdx.tx_ring[0].status;
        !           556:     if (currticks() >= to){
        !           557:         DBG ( "TX Time Out" );
        !           558:     } else if( tx_status & (CSL | LC | EC | UDF | HF)){
        !           559:         printf( "Transmit error: %8.8x %s %s %s %s %s\n",
        !           560:                 (unsigned int) tx_status,
        !           561:                 tx_status & EC ? "abort" : "",
        !           562:                 tx_status & CSL ? "carrier" : "",
        !           563:                 tx_status & LC ? "late" : "",
        !           564:                 tx_status & UDF ? "fifo" : "",
        !           565:                 tx_status & HF ? "heartbeat" : "" );
        !           566:     }
        !           567: 
        !           568:     /*hex_dump( txb, size );*/
        !           569:     /*pause();*/
        !           570: 
        !           571:     DBG ( "TRANSMIT\n" );
        !           572: }
        !           573: 
        !           574: /**************************************************************************
        !           575: DISABLE - Turn off ethernet interface
        !           576: ***************************************************************************/
        !           577: static void mtd_disable ( struct nic *nic ) {
        !           578: 
        !           579:     /* Disable Tx Rx*/
        !           580:     outl( mtdx.crvalue & (~TxEnable) & (~RxEnable), mtdx.ioaddr + TCRRCR );
        !           581: 
        !           582:     /* Reset the chip to erase previous misconfiguration. */
        !           583:     mtd_reset(nic);
        !           584: 
        !           585:     DBG ( "DISABLE\n" );
        !           586: }
        !           587: 
        !           588: static struct nic_operations mtd_operations = {
        !           589:        .connect        = dummy_connect,
        !           590:        .poll           = mtd_poll,
        !           591:        .transmit       = mtd_transmit,
        !           592:        .irq            = dummy_irq,
        !           593: 
        !           594: };
        !           595: 
        !           596: static struct pci_device_id mtd80x_nics[] = {
        !           597:         PCI_ROM(0x1516, 0x0800, "MTD800", "Myson MTD800", 0),
        !           598:         PCI_ROM(0x1516, 0x0803, "MTD803", "Surecom EP-320X", 0),
        !           599:         PCI_ROM(0x1516, 0x0891, "MTD891", "Myson MTD891", 0),
        !           600: };
        !           601: 
        !           602: PCI_DRIVER ( mtd80x_driver, mtd80x_nics, PCI_NO_CLASS );
        !           603: 
        !           604: /**************************************************************************
        !           605: PROBE - Look for an adapter, this routine's visible to the outside
        !           606: ***************************************************************************/
        !           607: 
        !           608: static int mtd_probe ( struct nic *nic, struct pci_device *pci ) {
        !           609: 
        !           610:     int i;
        !           611: 
        !           612:     if (pci->ioaddr == 0)
        !           613:            return 0;
        !           614: 
        !           615:     adjust_pci_device(pci);
        !           616: 
        !           617:     nic->ioaddr = pci->ioaddr;
        !           618:     nic->irqno = 0;
        !           619: 
        !           620:     mtdx.nic_name = pci->id->name;
        !           621:     mtdx.dev_id = pci->device;
        !           622:     mtdx.ioaddr = nic->ioaddr;
        !           623: 
        !           624:     /* read ethernet id */
        !           625:     for (i = 0; i < 6; ++i)
        !           626:     {
        !           627:         nic->node_addr[i] = inb(mtdx.ioaddr + PAR0 + i);
        !           628:     }
        !           629: 
        !           630:     if (memcmp(nic->node_addr, "\0\0\0\0\0\0", 6) == 0)
        !           631:     {
        !           632:         return 0;
        !           633:     }
        !           634: 
        !           635:     DBG ( "%s: ioaddr %4.4x MAC %s\n", mtdx.nic_name, mtdx.ioaddr, eth_ntoa ( nic->node_addr ) );
        !           636: 
        !           637:     /* Reset the chip to erase previous misconfiguration. */
        !           638:     outl(0x00000001, mtdx.ioaddr + BCR);
        !           639: 
        !           640:     /* find the connected MII xcvrs */
        !           641: 
        !           642:     if( mtdx.dev_id != 0x803 )
        !           643:     {
        !           644:         int phy, phy_idx = 0;
        !           645: 
        !           646:         for (phy = 1; phy < 32 && phy_idx < 1; phy++) {
        !           647:             int mii_status = mdio_read(nic, phy, 1);
        !           648: 
        !           649:             if (mii_status != 0xffff && mii_status != 0x0000) {
        !           650:                 mtdx.phys[phy_idx] = phy;
        !           651: 
        !           652:                 DBG ( "%s: MII PHY found at address %d, status "
        !           653:                      "0x%4.4x.\n", mtdx.nic_name, phy, mii_status );
        !           654:                 /* get phy type */
        !           655:                 {
        !           656:                     unsigned int data;
        !           657: 
        !           658:                     data = mdio_read(nic, mtdx.phys[phy_idx], 2);
        !           659:                     if (data == SeeqPHYID0)
        !           660:                         mtdx.PHYType = SeeqPHY;
        !           661:                     else if (data == AhdocPHYID0)
        !           662:                         mtdx.PHYType = AhdocPHY;
        !           663:                     else if (data == MarvellPHYID0)
        !           664:                         mtdx.PHYType = MarvellPHY;
        !           665:                     else if (data == MysonPHYID0)
        !           666:                         mtdx.PHYType = Myson981;
        !           667:                     else if (data == LevelOnePHYID0)
        !           668:                         mtdx.PHYType = LevelOnePHY;
        !           669:                     else
        !           670:                         mtdx.PHYType = OtherPHY;
        !           671:                 }
        !           672:                 phy_idx++;
        !           673:             }
        !           674:         }
        !           675: 
        !           676:         mtdx.mii_cnt = phy_idx;
        !           677:         if (phy_idx == 0) {
        !           678:             printf("%s: MII PHY not found -- this device may "
        !           679:                    "not operate correctly.\n", mtdx.nic_name);
        !           680:         }
        !           681:     } else {
        !           682:         mtdx.phys[0] = 32;
        !           683:         /* get phy type */
        !           684:         if (inl(mtdx.ioaddr + PHYIDENTIFIER) == MysonPHYID ) {
        !           685:             mtdx.PHYType = MysonPHY;
        !           686:             DBG ( "MysonPHY\n" );
        !           687:         } else {
        !           688:             mtdx.PHYType = OtherPHY;
        !           689:             DBG ( "OtherPHY\n" );
        !           690:         }
        !           691:     }
        !           692: 
        !           693:     getlinkstatus(nic);
        !           694:     if( !mtdx.linkok )
        !           695:     {
        !           696:         printf("No link!!!\n");
        !           697:         return 0;
        !           698:     }
        !           699: 
        !           700:     mtd_reset( nic );
        !           701: 
        !           702:     /* point to NIC specific routines */
        !           703:     nic->nic_op        = &mtd_operations;
        !           704:     return 1;
        !           705: }
        !           706: 
        !           707: 
        !           708: /**************************************************************************/
        !           709: static void set_rx_mode(struct nic *nic __unused)
        !           710: {
        !           711:     u32 mc_filter[2];                       /* Multicast hash filter */
        !           712:     u32 rx_mode;
        !           713: 
        !           714:     /* Too many to match, or accept all multicasts. */
        !           715:     mc_filter[1] = mc_filter[0] = ~0;
        !           716:     rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
        !           717: 
        !           718:     outl(mc_filter[0], mtdx.ioaddr + MAR0);
        !           719:     outl(mc_filter[1], mtdx.ioaddr + MAR1);
        !           720: 
        !           721:     mtdx.crvalue = ( mtdx.crvalue & ~RxModeMask ) | rx_mode;
        !           722:     outb( mtdx.crvalue, mtdx.ioaddr + TCRRCR);
        !           723: }
        !           724: /**************************************************************************/
        !           725: static unsigned int m80x_read_tick(void)
        !           726: /* function: Reads the Timer tick count register which decrements by 2 from  */
        !           727: /*           65536 to 0 every 1/36.414 of a second. Each 2 decrements of the */
        !           728: /*           count represents 838 nsec's.                                    */
        !           729: /* input   : none.                                                           */
        !           730: /* output  : none.                                                           */
        !           731: {
        !           732:     unsigned char tmp;
        !           733:     int value;
        !           734: 
        !           735:     outb((char) 0x06, 0x43); // Command 8254 to latch T0's count
        !           736: 
        !           737:     // now read the count.
        !           738:     tmp = (unsigned char) inb(0x40);
        !           739:     value = ((int) tmp) << 8;
        !           740:     tmp = (unsigned char) inb(0x40);
        !           741:     value |= (((int) tmp) & 0xff);
        !           742:     return (value);
        !           743: }
        !           744: 
        !           745: static void m80x_delay(unsigned int interval)
        !           746: /* function: to wait for a specified time.                                   */
        !           747: /* input   : interval ... the specified time.                                */
        !           748: /* output  : none.                                                           */
        !           749: {
        !           750:     unsigned int interval1, interval2, i = 0;
        !           751: 
        !           752:     interval1 = m80x_read_tick(); // get initial value
        !           753:     do
        !           754:     {
        !           755:         interval2 = m80x_read_tick();
        !           756:         if (interval1 < interval2)
        !           757:             interval1 += 65536;
        !           758:         ++i;
        !           759:     } while (((interval1 - interval2) < (u16) interval) && (i < 65535));
        !           760: }
        !           761: 
        !           762: 
        !           763: static u32 m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
        !           764: {
        !           765:     u32 miir;
        !           766:     int i;
        !           767:     unsigned int mask, data;
        !           768: 
        !           769:     /* enable MII output */
        !           770:     miir = (u32) inl(miiport);
        !           771:     miir &= 0xfffffff0;
        !           772: 
        !           773:     miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
        !           774: 
        !           775:     /* send 32 1's preamble */
        !           776:     for (i = 0; i < 32; i++) {
        !           777:         /* low MDC; MDO is already high (miir) */
        !           778:         miir &= ~MASK_MIIR_MII_MDC;
        !           779:         outl(miir, miiport);
        !           780: 
        !           781:         /* high MDC */
        !           782:         miir |= MASK_MIIR_MII_MDC;
        !           783:         outl(miir, miiport);
        !           784:     }
        !           785: 
        !           786:     /* calculate ST+OP+PHYAD+REGAD+TA */
        !           787:     data = opcode | (phyad << 7) | (regad << 2);
        !           788: 
        !           789:     /* sent out */
        !           790:     mask = 0x8000;
        !           791:     while (mask) {
        !           792:         /* low MDC, prepare MDO */
        !           793:         miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
        !           794:         if (mask & data)
        !           795:             miir |= MASK_MIIR_MII_MDO;
        !           796: 
        !           797:         outl(miir, miiport);
        !           798:         /* high MDC */
        !           799:         miir |= MASK_MIIR_MII_MDC;
        !           800:         outl(miir, miiport);
        !           801:         m80x_delay(30);
        !           802: 
        !           803:         /* next */
        !           804:         mask >>= 1;
        !           805:         if (mask == 0x2 && opcode == OP_READ)
        !           806:             miir &= ~MASK_MIIR_MII_WRITE;
        !           807:     }
        !           808:     return miir;
        !           809: }
        !           810: 
        !           811: static int mdio_read(struct nic *nic __unused, int phyad, int regad)
        !           812: {
        !           813:     long miiport = mtdx.ioaddr + MANAGEMENT;
        !           814:     u32 miir;
        !           815:     unsigned int mask, data;
        !           816: 
        !           817:     miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
        !           818: 
        !           819:     /* read data */
        !           820:     mask = 0x8000;
        !           821:     data = 0;
        !           822:     while (mask)
        !           823:     {
        !           824:         /* low MDC */
        !           825:         miir &= ~MASK_MIIR_MII_MDC;
        !           826:         outl(miir, miiport);
        !           827: 
        !           828:         /* read MDI */
        !           829:         miir = inl(miiport);
        !           830:         if (miir & MASK_MIIR_MII_MDI)
        !           831:             data |= mask;
        !           832: 
        !           833:         /* high MDC, and wait */
        !           834:         miir |= MASK_MIIR_MII_MDC;
        !           835:         outl(miir, miiport);
        !           836:         m80x_delay((int) 30);
        !           837: 
        !           838:         /* next */
        !           839:         mask >>= 1;
        !           840:     }
        !           841: 
        !           842:     /* low MDC */
        !           843:     miir &= ~MASK_MIIR_MII_MDC;
        !           844:     outl(miir, miiport);
        !           845: 
        !           846:     return data & 0xffff;
        !           847: }
        !           848: 
        !           849: #if 0 /* not used */
        !           850: static void mdio_write(struct nic *nic __unused, int phyad, int regad,
        !           851:                       int data)
        !           852: {
        !           853:     long miiport = mtdx.ioaddr + MANAGEMENT;
        !           854:     u32 miir;
        !           855:     unsigned int mask;
        !           856: 
        !           857:     miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
        !           858: 
        !           859:     /* write data */
        !           860:     mask = 0x8000;
        !           861:     while (mask)
        !           862:     {
        !           863:         /* low MDC, prepare MDO */
        !           864:         miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
        !           865:         if (mask & data)
        !           866:             miir |= MASK_MIIR_MII_MDO;
        !           867:         outl(miir, miiport);
        !           868: 
        !           869:         /* high MDC */
        !           870:         miir |= MASK_MIIR_MII_MDC;
        !           871:         outl(miir, miiport);
        !           872: 
        !           873:         /* next */
        !           874:         mask >>= 1;
        !           875:     }
        !           876: 
        !           877:     /* low MDC */
        !           878:     miir &= ~MASK_MIIR_MII_MDC;
        !           879:     outl(miir, miiport);
        !           880: 
        !           881:     return;
        !           882: }
        !           883: #endif
        !           884: 
        !           885: static void getlinkstatus(struct nic *nic)
        !           886: /* function: Routine will read MII Status Register to get link status.       */
        !           887: /* input   : dev... pointer to the adapter block.                            */
        !           888: /* output  : none.                                                           */
        !           889: {
        !           890:     unsigned int i, DelayTime = 0x1000;
        !           891: 
        !           892:     mtdx.linkok = 0;
        !           893: 
        !           894:     if (mtdx.PHYType == MysonPHY)
        !           895:     {
        !           896:         for (i = 0; i < DelayTime; ++i) {
        !           897:             if (inl(mtdx.ioaddr + BMCRSR) & LinkIsUp2) {
        !           898:                 mtdx.linkok = 1;
        !           899:                 return;
        !           900:             }
        !           901:             // delay
        !           902:             m80x_delay(100);
        !           903:         }
        !           904:     } else
        !           905:     {
        !           906:         for (i = 0; i < DelayTime; ++i) {
        !           907:             if (mdio_read(nic, mtdx.phys[0], MII_BMSR) & BMSR_LSTATUS) {
        !           908:                 mtdx.linkok = 1;
        !           909:                 return;
        !           910:             }
        !           911:             // delay
        !           912:             m80x_delay(100);
        !           913:         }
        !           914:     }
        !           915: }
        !           916: 
        !           917: 
        !           918: static void getlinktype(struct nic *dev)
        !           919: {
        !           920:     if (mtdx.PHYType == MysonPHY)
        !           921:     { /* 3-in-1 case */
        !           922:         if (inl(mtdx.ioaddr + TCRRCR) & FD)
        !           923:             mtdx.duplexmode = 2; /* full duplex */
        !           924:         else
        !           925:             mtdx.duplexmode = 1; /* half duplex */
        !           926:         if (inl(mtdx.ioaddr + TCRRCR) & PS10)
        !           927:             mtdx.line_speed = 1; /* 10M */
        !           928:         else
        !           929:             mtdx.line_speed = 2; /* 100M */
        !           930:     } else
        !           931:     {
        !           932:         if (mtdx.PHYType == SeeqPHY) { /* this PHY is SEEQ 80225 */
        !           933:             unsigned int data;
        !           934: 
        !           935:             data = mdio_read(dev, mtdx.phys[0], MIIRegister18);
        !           936:             if (data & SPD_DET_100)
        !           937:                 mtdx.line_speed = 2; /* 100M */
        !           938:             else
        !           939:                 mtdx.line_speed = 1; /* 10M */
        !           940:             if (data & DPLX_DET_FULL)
        !           941:                 mtdx.duplexmode = 2; /* full duplex mode */
        !           942:             else
        !           943:                 mtdx.duplexmode = 1; /* half duplex mode */
        !           944:         } else if (mtdx.PHYType == AhdocPHY) {
        !           945:             unsigned int data;
        !           946: 
        !           947:             data = mdio_read(dev, mtdx.phys[0], DiagnosticReg);
        !           948:             if (data & Speed_100)
        !           949:                 mtdx.line_speed = 2; /* 100M */
        !           950:             else
        !           951:                 mtdx.line_speed = 1; /* 10M */
        !           952:             if (data & DPLX_FULL)
        !           953:                 mtdx.duplexmode = 2; /* full duplex mode */
        !           954:             else
        !           955:                 mtdx.duplexmode = 1; /* half duplex mode */
        !           956:         }
        !           957:         /* 89/6/13 add, (begin) */
        !           958:         else if (mtdx.PHYType == MarvellPHY) {
        !           959:             unsigned int data;
        !           960: 
        !           961:             data = mdio_read(dev, mtdx.phys[0], SpecificReg);
        !           962:             if (data & Full_Duplex)
        !           963:                 mtdx.duplexmode = 2; /* full duplex mode */
        !           964:             else
        !           965:                 mtdx.duplexmode = 1; /* half duplex mode */
        !           966:             data &= SpeedMask;
        !           967:             if (data == Speed_1000M)
        !           968:                 mtdx.line_speed = 3; /* 1000M */
        !           969:             else if (data == Speed_100M)
        !           970:                 mtdx.line_speed = 2; /* 100M */
        !           971:             else
        !           972:                 mtdx.line_speed = 1; /* 10M */
        !           973:         }
        !           974:         /* 89/6/13 add, (end) */
        !           975:         /* 89/7/27 add, (begin) */
        !           976:         else if (mtdx.PHYType == Myson981) {
        !           977:             unsigned int data;
        !           978: 
        !           979:             data = mdio_read(dev, mtdx.phys[0], StatusRegister);
        !           980: 
        !           981:             if (data & SPEED100)
        !           982:                 mtdx.line_speed = 2;
        !           983:             else
        !           984:                 mtdx.line_speed = 1;
        !           985: 
        !           986:             if (data & FULLMODE)
        !           987:                 mtdx.duplexmode = 2;
        !           988:             else
        !           989:                 mtdx.duplexmode = 1;
        !           990:         }
        !           991:         /* 89/7/27 add, (end) */
        !           992:         /* 89/12/29 add */
        !           993:         else if (mtdx.PHYType == LevelOnePHY) {
        !           994:             unsigned int data;
        !           995: 
        !           996:             data = mdio_read(dev, mtdx.phys[0], SpecificReg);
        !           997:             if (data & LXT1000_Full)
        !           998:                 mtdx.duplexmode = 2; /* full duplex mode */
        !           999:             else
        !          1000:                 mtdx.duplexmode = 1; /* half duplex mode */
        !          1001:             data &= SpeedMask;
        !          1002:             if (data == LXT1000_1000M)
        !          1003:                 mtdx.line_speed = 3; /* 1000M */
        !          1004:             else if (data == LXT1000_100M)
        !          1005:                 mtdx.line_speed = 2; /* 100M */
        !          1006:             else
        !          1007:                 mtdx.line_speed = 1; /* 10M */
        !          1008:         }
        !          1009:         // chage crvalue
        !          1010:         // mtdx.crvalue&=(~PS10)&(~FD);
        !          1011:         mtdx.crvalue &= (~PS10) & (~FD) & (~PS1000);
        !          1012:         if (mtdx.line_speed == 1)
        !          1013:             mtdx.crvalue |= PS10;
        !          1014:         else if (mtdx.line_speed == 3)
        !          1015:             mtdx.crvalue |= PS1000;
        !          1016:         if (mtdx.duplexmode == 2)
        !          1017:             mtdx.crvalue |= FD;
        !          1018:     }
        !          1019: }
        !          1020: 
        !          1021: DRIVER ( "MTD80X", nic_driver, pci_driver, mtd80x_driver,
        !          1022:         mtd_probe, mtd_disable );

unix.superglobalmegacorp.com

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