Annotation of qemu/roms/ipxe/src/drivers/net/mtd80x.c, revision 1.1.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.