Annotation of qemu/roms/SLOF/drivers/e1k/e1k.c, revision 1.1

1.1     ! root        1: /******************************************************************************
        !             2:  * Copyright (c) 2007, 2011 IBM Corporation
        !             3:  * All rights reserved.
        !             4:  * This program and the accompanying materials
        !             5:  * are made available under the terms of the BSD License
        !             6:  * which accompanies this distribution, and is available at
        !             7:  * http://www.opensource.org/licenses/bsd-license.php
        !             8:  *
        !             9:  * Contributors:
        !            10:  *     IBM Corporation - initial implementation
        !            11:  *****************************************************************************/
        !            12: /*
        !            13:  * e1000 Gigabit Ethernet Driver for SLOF
        !            14:  *
        !            15:  * Reference:
        !            16:  *   PCI/PCI-X Family of Gigabit Ethernet Controllers
        !            17:  *   Software Developer's Manual Rev. 3.3, Intel, December 2006
        !            18:  */
        !            19: 
        !            20: #include <stdint.h>
        !            21: #include <string.h>
        !            22: #include <byteorder.h>
        !            23: #include "e1k.h"
        !            24: 
        !            25: 
        !            26: /*
        !            27:  * local defines
        !            28:  ******************************************************************************
        !            29:  */
        !            30: #define E1K_NUM_RX_DESC        128     // do not change
        !            31: #define E1K_NUM_TX_DESC        128     // do not change
        !            32: #define E1K_BUF_SIZE   2096    // do not change
        !            33: 
        !            34: #define NUM_MAC_ADDR   16      // number of mac address register pairs
        !            35: #define EEPROM_MAC_OFFS        0       // position of mac address in eeprom
        !            36: 
        !            37: /*
        !            38:  * local types
        !            39:  ******************************************************************************
        !            40:  */
        !            41: typedef struct {
        !            42:        uint32_t m_dev_u32;
        !            43:        uint64_t m_devmsk_u64;
        !            44:        char *m_name;
        !            45: }      e1k_dev_t;
        !            46: 
        !            47: /*
        !            48:  * e1k common data structures
        !            49:  */
        !            50: 
        !            51: /*
        !            52:  * transmit buffer descriptor
        !            53:  */
        !            54: typedef struct {
        !            55:        uint64_t m_buffer_u64;
        !            56:        uint16_t m_len_u16;
        !            57:        uint8_t m_cso_u08;
        !            58:        uint8_t m_cmd_u08;
        !            59:        uint8_t m_sta_u08;
        !            60:        uint8_t m_css_u08;
        !            61:        uint16_t m_spe_u16;
        !            62: }      __attribute__ ((packed)) e1k_tx_desc_st;
        !            63: 
        !            64: 
        !            65: /*
        !            66:  * receive buffer descriptor
        !            67:  */
        !            68: typedef struct {
        !            69:        uint64_t m_buffer_u64;
        !            70:        uint16_t m_len_u16;
        !            71:        uint16_t m_csm_u16;
        !            72:        uint8_t m_sta_u08;
        !            73:        uint8_t m_err_u08;
        !            74:        uint16_t m_spe_u16;
        !            75: }      __attribute__ ((packed)) e1k_rx_desc_st;
        !            76: 
        !            77: /*
        !            78:  * e1k device structure
        !            79:  */
        !            80: typedef struct {
        !            81:        /*
        !            82:         * device identification mask
        !            83:         */
        !            84:        uint64_t        m_device_u64;
        !            85: 
        !            86:        /*
        !            87:         * memory mapped base address of NIC
        !            88:         */
        !            89:        uint64_t        m_baseaddr_u64;
        !            90: 
        !            91:        /*
        !            92:         * transmit & receive rings
        !            93:         * must be 16 byte aligned
        !            94:         */
        !            95:        e1k_tx_desc_st  m_tx_ring_pst[E1K_NUM_TX_DESC];
        !            96:        e1k_rx_desc_st  m_rx_ring_pst[E1K_NUM_RX_DESC];
        !            97: 
        !            98:        /*
        !            99:         * transmit & receive buffers
        !           100:         * must be 16 byte aligned
        !           101:         */
        !           102:        uint8_t         m_tx_buffer_pu08[E1K_NUM_TX_DESC][E1K_BUF_SIZE];
        !           103:        uint8_t         m_rx_buffer_pu08[E1K_NUM_RX_DESC][E1K_BUF_SIZE];
        !           104: 
        !           105:        /*
        !           106:         * next receive descriptor index
        !           107:         */
        !           108:        uint32_t        m_rx_next_u32;
        !           109: 
        !           110:        /*
        !           111:         * command register storage
        !           112:         */
        !           113:        uint16_t        m_com_r_u16;
        !           114: 
        !           115:        /*
        !           116:         * padding to make the size of the structure a multiple of 16 byte
        !           117:         */
        !           118:        uint16_t        m_pad16_u16;
        !           119:        uint64_t        m_pad64_u32;
        !           120: 
        !           121:        /*
        !           122:         * PCI related data
        !           123:         */
        !           124:        uint64_t        pcicfg_puid;
        !           125:        uint8_t         pcicfg_bus;
        !           126:        uint8_t         pcicfg_devfn;
        !           127: }      __attribute__ ((packed)) e1k_st;
        !           128: 
        !           129: /*
        !           130:  * local constants
        !           131:  ******************************************************************************
        !           132:  */
        !           133: #define E1K_82540      ((uint64_t) 0x1)
        !           134: #define E1K_82541      ((uint64_t) 0x2)
        !           135: #define E1K_82544      ((uint64_t) 0x4)
        !           136: #define E1K_82545      ((uint64_t) 0x8)
        !           137: #define E1K_82546      ((uint64_t) 0x10)
        !           138: #define E1K_82547      ((uint64_t) 0x20)
        !           139: 
        !           140: #define IS_82541       ((m_e1k.m_device_u64 & E1K_82541) != 0)
        !           141: #define IS_82546       ((m_e1k.m_device_u64 & E1K_82546) != 0)
        !           142: #define IS_82547       ((m_e1k.m_device_u64 & E1K_82547) != 0)
        !           143: 
        !           144: static const e1k_dev_t e1k_dev[] = {
        !           145:        { 0x1019, E1K_82547, "82547EI/GI Copper" },
        !           146:        { 0x101A, E1K_82547, "82547EI Mobile" },
        !           147:        { 0x1010, E1K_82546, "52546EB Copper, Dual Port" },
        !           148:        { 0x1012, E1K_82546, "82546EB Fiber, Dual Port" },
        !           149: /*     { 0x101D, E1K_82546, "82546EB Copper, Quad Port" }, */
        !           150:        { 0x1079, E1K_82546, "82546GB Copper, Dual Port" },
        !           151:        { 0x107A, E1K_82546, "82546GB Fiber, Dual Port" },
        !           152:        { 0x107B, E1K_82546, "82546GB SerDes, Dual Port" },
        !           153:        { 0x100F, E1K_82545, "82545EM Copper" },
        !           154:        { 0x1011, E1K_82545, "82545EM Fiber" },
        !           155:        { 0x1026, E1K_82545, "82545GM Copper" },
        !           156:        { 0x1027, E1K_82545, "82545GM Fiber" },
        !           157:        { 0x1028, E1K_82545, "82545GM SerDes" },
        !           158:        { 0x1107, E1K_82544, "82544EI Copper" },
        !           159:        { 0x1112, E1K_82544, "82544GC Copper" },
        !           160:        { 0x1013, E1K_82541, "82541EI Copper" },
        !           161:        { 0x1018, E1K_82541, "82541EI Mobile" },
        !           162:        { 0x1076, E1K_82541, "82541GI Copper" },
        !           163:        { 0x1077, E1K_82541, "82541GI Mobile" },
        !           164:        { 0x1078, E1K_82541, "82541ER Copper" },
        !           165:        { 0x107C, E1K_82541, "82541PI" },
        !           166:        { 0x1015, E1K_82540, "82540EM Mobile" },
        !           167:        { 0x1016, E1K_82540, "82540EP Mobile" },
        !           168:        { 0x1017, E1K_82540, "82540EP Desktop" },
        !           169:        { 0x100E, E1K_82540, "82540EM Desktop" },
        !           170:        { 0     , 0 }
        !           171: };
        !           172: 
        !           173: /*
        !           174:  * local variables
        !           175:  ******************************************************************************
        !           176:  */
        !           177: static e1k_st  m_e1k __attribute__ ((aligned(16)));
        !           178: static long dma_offset;
        !           179: 
        !           180: /*
        !           181:  * global functions
        !           182:  ******************************************************************************
        !           183:  */
        !           184: int
        !           185: check_driver(pci_config_t *pci_conf);
        !           186: 
        !           187: 
        !           188: /*
        !           189:  * snk module interface
        !           190:  ******************************************************************************
        !           191:  */
        !           192: static int e1k_init(void);
        !           193: static int e1k_term(void);
        !           194: static int e1k_xmit(char *f_buffer_pc, int f_len_i);
        !           195: static int e1k_receive(char *f_buffer_pc, int f_len_i);
        !           196: static int e1k_ioctl(int request, void* data);
        !           197: 
        !           198: snk_module_t snk_module_interface = {
        !           199:        .version = 1,
        !           200:        .type    = MOD_TYPE_NETWORK,
        !           201:        .running = 0,
        !           202:        .init    = e1k_init,
        !           203:        .term    = e1k_term,
        !           204:        .write   = e1k_xmit,
        !           205:        .read    = e1k_receive,
        !           206:        .ioctl   = e1k_ioctl
        !           207: };
        !           208: 
        !           209: 
        !           210: /**
        !           211:  * Translate virtual to "physical" address, ie. an address
        !           212:  * which can be used for DMA transfers.
        !           213:  */
        !           214: static uint64_t
        !           215: virt2dma(void *addr)
        !           216: {
        !           217:        return (uint64_t)addr + dma_offset;
        !           218: }
        !           219: 
        !           220: static void *
        !           221: dma2virt(uint64_t addr)
        !           222: {
        !           223:        return (void *)(addr - dma_offset);
        !           224: }
        !           225: 
        !           226: 
        !           227: /*
        !           228:  * local inline functions for e1k register access
        !           229:  ******************************************************************************
        !           230:  */
        !           231: static uint32_t
        !           232: e1k_rd32(uint16_t f_offs_u16)
        !           233: {      // caution: shall only be used after initialization!
        !           234:        return bswap_32(rd32(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16));
        !           235: }
        !           236: 
        !           237: /* not used so far
        !           238: static uint16_t
        !           239: e1k_rd16(uint16_t f_offs_u16)
        !           240: {      // caution: shall only be used after initialization!
        !           241:        return bswap_16(rd16(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16));
        !           242: }*/
        !           243: 
        !           244: /* not used so far
        !           245: static uint8_t
        !           246: e1k_rd08(uint16_t f_offs_u16)
        !           247: {      // caution: shall only be used after initialization!
        !           248:        return rd08(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16);
        !           249: }*/
        !           250: 
        !           251: static void
        !           252: e1k_wr32(uint16_t f_offs_u16, uint32_t f_val_u32)
        !           253: {      // caution: shall only be used after initialization!
        !           254:        wr32(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16, bswap_32(f_val_u32));
        !           255: }
        !           256: 
        !           257: /* not used so far
        !           258: static void
        !           259: e1k_wr16(uint16_t f_offs_u16, uint16_t f_val_u16)
        !           260: {      // caution: shall only be used after initialization!
        !           261:        wr16(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16, bswap_16(f_val_u16));
        !           262: }*/
        !           263: 
        !           264: /* not used so far
        !           265: static void
        !           266: e1k_wr08(uint16_t f_offs_u16, uint8_t f_val_u08)
        !           267: {      // caution: shall only be used after initialization!
        !           268:        wr08(m_e1k.m_baseaddr_u64 + (uint64_t) f_offs_u16, f_val_u08);
        !           269: }*/
        !           270: 
        !           271: static void
        !           272: e1k_setb32(uint16_t f_offs_u16, uint32_t f_mask_u32)
        !           273: {
        !           274:        uint32_t v;
        !           275: 
        !           276:        v  = e1k_rd32(f_offs_u16);
        !           277:        v |= f_mask_u32;
        !           278:        e1k_wr32(f_offs_u16, v);
        !           279: }
        !           280: 
        !           281: /* not used so far
        !           282: static void
        !           283: e1k_setb16(uint16_t f_offs_u16, uint16_t f_mask_u16)
        !           284: {
        !           285:        uint16_t v;
        !           286:        v  = e1k_rd16(f_offs_u16);
        !           287:        v |= f_mask_u16;
        !           288:        e1k_wr16(f_offs_u16, v);
        !           289: }*/
        !           290: 
        !           291: /* not used so far
        !           292: static void
        !           293: e1k_setb08(uint16_t f_offs_u16, uint8_t f_mask_u08)
        !           294: {
        !           295:        uint8_t v;
        !           296:        v  = e1k_rd08(f_offs_u16);
        !           297:        v |= f_mask_u08;
        !           298:        e1k_wr08(f_offs_u16, v);
        !           299: }*/
        !           300: 
        !           301: static void
        !           302: e1k_clrb32(uint16_t f_offs_u16, uint32_t f_mask_u32)
        !           303: {
        !           304:        uint32_t v;
        !           305: 
        !           306:        v  = e1k_rd32(f_offs_u16);
        !           307:        v &= ~f_mask_u32;
        !           308:        e1k_wr32(f_offs_u16, v);
        !           309: }
        !           310: 
        !           311: /* not used so far
        !           312: static void
        !           313: e1k_clrb16(uint16_t f_offs_u16, uint16_t f_mask_u16)
        !           314: {
        !           315:        uint16_t v;
        !           316: 
        !           317:        v  = e1k_rd16(f_offs_u16);
        !           318:        v &= ~f_mask_u16;
        !           319:        e1k_wr16(f_offs_u16, v);
        !           320: }*/
        !           321: 
        !           322: /* not used so far
        !           323: static void
        !           324: e1k_clrb08(uint16_t f_offs_u16, uint8_t f_mask_u08)
        !           325: {
        !           326:        uint8_t v;
        !           327:        v  = e1k_rd08(f_offs_u16);
        !           328:        v &= ~f_mask_u08;
        !           329:        e1k_wr08(f_offs_u16, v);
        !           330: }*/
        !           331: 
        !           332: static int32_t
        !           333: e1k_eep_rd16(uint8_t f_offs_u08, uint16_t *f_data_pu16)
        !           334: {
        !           335:        uint32_t i;
        !           336:        uint32_t v;
        !           337:        int32_t done_shft;
        !           338:        int32_t addr_shft;
        !           339: 
        !           340:        if(IS_82541 || IS_82547) {
        !           341:                addr_shft = 2;
        !           342:                done_shft = 1;
        !           343:        } else {
        !           344:                addr_shft = 8;
        !           345:                done_shft = 4;
        !           346:        }
        !           347: 
        !           348:        /*
        !           349:         * initiate eeprom read
        !           350:         */
        !           351:        e1k_wr32(EERD, ((uint32_t) f_offs_u08 << addr_shft) |   // address
        !           352:                  BIT32(0));                                    // start read
        !           353: 
        !           354:        /*
        !           355:         * wait for read done bit to be set
        !           356:         */
        !           357:        i = 1000;
        !           358:        v = e1k_rd32(EERD);
        !           359:        while ((--i) &&
        !           360:               ((v & BIT32(done_shft)) == 0)) {
        !           361:                ms_delay(1);
        !           362:                v = e1k_rd32(EERD);
        !           363:        }
        !           364: 
        !           365:        /*
        !           366:         * return on error
        !           367:         */
        !           368:        if ((v & BIT32(done_shft)) == 0) {
        !           369:                return -1;
        !           370:        }
        !           371:        
        !           372:        /*
        !           373:         * return data
        !           374:         */
        !           375:        *f_data_pu16 = (uint16_t) ((v >> 16) & 0xffff);
        !           376: 
        !           377:        return 0;
        !           378: }
        !           379: 
        !           380: /*
        !           381:  * ring initialization
        !           382:  */
        !           383: static void
        !           384: e1k_init_receiver(void)
        !           385: {
        !           386:        uint32_t i;
        !           387:        uint64_t addr;
        !           388: 
        !           389:        /*
        !           390:         * disable receiver for initialization
        !           391:         */
        !           392:        e1k_wr32(RCTL, 0);
        !           393: 
        !           394:        /*
        !           395:         * clear receive desciptors and setup buffer pointers
        !           396:         */
        !           397:        for (i = 0; i < E1K_NUM_RX_DESC; i++) {
        !           398:                memset((uint8_t *) &m_e1k.m_rx_ring_pst[i], 0,
        !           399:                        sizeof(e1k_rx_desc_st));
        !           400:                mb();
        !           401: 
        !           402:                m_e1k.m_rx_ring_pst[i].m_buffer_u64 =
        !           403:                        bswap_64(virt2dma(&m_e1k.m_rx_buffer_pu08[i][0]));
        !           404:        }
        !           405: 
        !           406:        /*
        !           407:         * initialize previously received index
        !           408:         */
        !           409:        m_e1k.m_rx_next_u32 = 0;
        !           410: 
        !           411:        /*
        !           412:         * setup the base address and the length of the rx descriptor ring
        !           413:         */
        !           414:        addr = virt2dma(&m_e1k.m_rx_ring_pst[0]);
        !           415:        e1k_wr32(RDBAH, (uint32_t) ((uint64_t) addr >> 32));
        !           416:        e1k_wr32(RDBAL, (uint32_t) ((uint64_t) addr & 0xffffffff));
        !           417:        e1k_wr32(RDLEN, E1K_NUM_RX_DESC * sizeof(e1k_rx_desc_st));
        !           418: 
        !           419:        /*
        !           420:         * setup the rx head and tail descriptor indices
        !           421:         */
        !           422:        e1k_wr32(RDH, 0);
        !           423:        e1k_wr32(RDT, E1K_NUM_RX_DESC - 1);
        !           424: 
        !           425:        /*
        !           426:         * setup the receive delay timer register
        !           427:         */
        !           428:        e1k_wr32(RDTR, 0);
        !           429: 
        !           430:        /*
        !           431:         * setup the receive control register
        !           432:         */
        !           433:        e1k_wr32(RCTL,  BIT32( 1) |     // enable receiver
        !           434:                        BIT32( 4) |     // enable multicast reception
        !           435:                        BIT32(15));     // broadcast accept mode
        !           436:                                        // packet size 2048
        !           437:                                        // no buffer extension
        !           438: }
        !           439: 
        !           440: static void
        !           441: e1k_init_transmitter(void)
        !           442: {
        !           443:        uint32_t i;
        !           444:        uint64_t addr;
        !           445: 
        !           446:        /*
        !           447:         * clear transmit desciptors and setup buffer pointers
        !           448:         */
        !           449:        for (i = 0; i < E1K_NUM_TX_DESC; i++) {
        !           450:                memset((uint8_t *) &m_e1k.m_tx_ring_pst[i], 0,
        !           451:                        sizeof(e1k_tx_desc_st));
        !           452:                mb();
        !           453: 
        !           454:                m_e1k.m_tx_ring_pst[i].m_buffer_u64 =
        !           455:                        bswap_64(virt2dma(&m_e1k.m_tx_buffer_pu08[i][0]));
        !           456:        }
        !           457: 
        !           458:        /*
        !           459:         * setup the base address and the length of the tx descriptor ring
        !           460:         */
        !           461:        addr = virt2dma(&m_e1k.m_tx_ring_pst[0]);
        !           462:        e1k_wr32(TDBAH, (uint32_t) ((uint64_t) addr >> 32));
        !           463:        e1k_wr32(TDBAL, (uint32_t) ((uint64_t) addr & 0xffffffff));
        !           464:        e1k_wr32(TDLEN, E1K_NUM_TX_DESC * sizeof(e1k_tx_desc_st));
        !           465: 
        !           466:        /*
        !           467:         * setup the rx head and tail descriptor indices
        !           468:         */
        !           469:        e1k_wr32(TDH, 0);
        !           470:        e1k_wr32(TDT, 0);
        !           471: 
        !           472:        /*
        !           473:         * initialize the transmit control register
        !           474:         */
        !           475:        e1k_wr32(TCTL, BIT32(1) |                       // enable transmitter
        !           476:                        BIT32(3) |                      // pad short packets
        !           477:                        ((uint32_t) 0x0f <<  4) |       // collision threshhold
        !           478:                        ((uint32_t) 0x40 << 12));       // collision distance
        !           479: }
        !           480: 
        !           481: static int32_t
        !           482: e1k_mac_init(uint8_t *f_mac_pu08)
        !           483: {
        !           484:        uint32_t l_ah_u32;
        !           485:        uint32_t l_al_u32;
        !           486:        uint32_t i;
        !           487:        uint32_t v;
        !           488: 
        !           489:        /*
        !           490:         * Use MAC address from device tree if possible
        !           491:         */
        !           492:        for (i = 0, v = 0; i < 6; i++) {
        !           493:                v += (uint32_t) f_mac_pu08[i];
        !           494:        }
        !           495: 
        !           496:        if (v != 0) {
        !           497:                /*
        !           498:                 * use passed mac address for transmission to nic
        !           499:                 */
        !           500:                l_al_u32  = ((uint32_t) f_mac_pu08[3] << 24);
        !           501:                l_al_u32 |= ((uint32_t) f_mac_pu08[2] << 16);
        !           502:                l_al_u32 |= ((uint32_t) f_mac_pu08[1] <<  8);
        !           503:                l_al_u32 |= ((uint32_t) f_mac_pu08[0] <<  0);
        !           504:                l_ah_u32  = ((uint32_t) f_mac_pu08[5] <<  8);
        !           505:                l_ah_u32 |= ((uint32_t) f_mac_pu08[4] <<  0);
        !           506:        } else {
        !           507:                /*
        !           508:                 * read mac address from eeprom
        !           509:                 */
        !           510:                uint16_t w[3];  // 3 16 bit words from eeprom
        !           511: 
        !           512:                for (i = 0; i < 3; i++) {
        !           513:                        if (e1k_eep_rd16(EEPROM_MAC_OFFS + i, &w[i]) != 0) {
        !           514:                                printk("Failed to read MAC address from EEPROM!\n");
        !           515:                                return -1;
        !           516:                        }
        !           517:                }
        !           518: 
        !           519:                /*
        !           520:                 * invert the least significant bit for 82546 dual port
        !           521:                 * if the second device is in use (remember word is byteswapped)
        !           522:                 */
        !           523:                if ((IS_82546) &&
        !           524:                    ((e1k_rd32(STATUS) & BIT32(2)) != 0)) {
        !           525:                        w[2] ^= (uint16_t) 0x100;
        !           526:                }
        !           527: 
        !           528:                /*
        !           529:                 * store mac address for transmission to nic
        !           530:                 */
        !           531:                l_ah_u32  = ((uint32_t) w[2] <<  0);
        !           532:                l_al_u32  = ((uint32_t) w[1] << 16);
        !           533:                l_al_u32 |= ((uint32_t) w[0] <<  0);
        !           534: 
        !           535:                /*
        !           536:                 * return mac address
        !           537:                 * mac address in eeprom is stored byteswapped
        !           538:                 */
        !           539:                f_mac_pu08[1] = (uint8_t) ((w[0] >> 8) & 0xff);
        !           540:                f_mac_pu08[0] = (uint8_t) ((w[0] >> 0) & 0xff);
        !           541:                f_mac_pu08[3] = (uint8_t) ((w[1] >> 8) & 0xff);
        !           542:                f_mac_pu08[2] = (uint8_t) ((w[1] >> 0) & 0xff);
        !           543:                f_mac_pu08[5] = (uint8_t) ((w[2] >> 8) & 0xff);
        !           544:                f_mac_pu08[4] = (uint8_t) ((w[2] >> 0) & 0xff);
        !           545:        }
        !           546: 
        !           547:        /*
        !           548:         * insert mac address in receive address register
        !           549:         * and set AV bit
        !           550:         */
        !           551:        e1k_wr32(RAL0, l_al_u32);
        !           552:        e1k_wr32(RAH0, l_ah_u32 | BIT32(31));
        !           553: 
        !           554:        /*
        !           555:         * clear remaining receive address registers
        !           556:         */
        !           557:        for (i = 1; i < NUM_MAC_ADDR; i++) {
        !           558:                e1k_wr32(RAL0 + i * sizeof(uint64_t), 0);
        !           559:                e1k_wr32(RAH0 + i * sizeof(uint64_t), 0);
        !           560:        }
        !           561: 
        !           562:        return 0;
        !           563: }
        !           564: 
        !           565: 
        !           566: /*
        !           567:  * interface
        !           568:  ******************************************************************************
        !           569:  */
        !           570:   
        !           571: /*
        !           572:  * e1k_receive
        !           573:  */
        !           574: static int
        !           575: e1k_receive(char *f_buffer_pc, int f_len_i)
        !           576: {
        !           577:        uint32_t        l_rdh_u32 = e1k_rd32(RDH);      // this includes needed dummy read
        !           578:        e1k_rx_desc_st  *rx;
        !           579:        int             l_ret_i;
        !           580: 
        !           581:        #ifdef E1K_DEBUG
        !           582:        #ifdef E1K_SHOW_RCV_DATA
        !           583:        int             i;
        !           584:        #endif
        !           585:        #endif
        !           586: 
        !           587:        /*
        !           588:         * check whether new packets have arrived
        !           589:         */
        !           590:        if (m_e1k.m_rx_next_u32 == l_rdh_u32) {
        !           591:                return 0;
        !           592:        }
        !           593: 
        !           594:        /*
        !           595:         * get a pointer to the next rx descriptor for ease of use
        !           596:         */
        !           597:        rx = &m_e1k.m_rx_ring_pst[m_e1k.m_rx_next_u32];
        !           598: 
        !           599:        /*
        !           600:         * check whether the descriptor done bit is set
        !           601:         */
        !           602:        if ((rx->m_sta_u08 & 0x1) == 0) {
        !           603:                return 0;
        !           604:        }
        !           605: 
        !           606:        /*
        !           607:         * get the length of the packet, throw away checksum
        !           608:         */
        !           609:        l_ret_i = (int) bswap_16(rx->m_len_u16) - (int) 4;
        !           610: 
        !           611:        /*
        !           612:         * copy the data
        !           613:         */
        !           614:        memcpy((uint8_t *) f_buffer_pc, dma2virt(bswap_64(rx->m_buffer_u64)),
        !           615:                (size_t) l_ret_i);
        !           616: 
        !           617:        #ifdef E1K_DEBUG
        !           618:        #if defined(E1K_SHOW_RCV) || defined(E1K_SHOW_RCV_DATA)
        !           619:        printk("e1k: %d bytes received\n", l_ret_i);
        !           620:        #endif
        !           621: 
        !           622:        #ifdef E1K_SHOW_RCV_DATA
        !           623:        for (i = 0; i < l_ret_i; i++) {
        !           624: 
        !           625:                if ((i & 0x1f) == 0) {
        !           626:                        printk("\n       ");
        !           627:                }
        !           628: 
        !           629:                printk("%02X ", f_buffer_pc[i]);
        !           630:        }
        !           631: 
        !           632:        printk("\n\n");
        !           633:        #endif
        !           634:        #endif
        !           635: 
        !           636:        /*
        !           637:         * clear descriptor for reusage, but leave buffer pointer untouched
        !           638:         */
        !           639:        memset((uint8_t *) &rx->m_len_u16, 0,
        !           640:                sizeof(e1k_rx_desc_st) - sizeof(uint64_t));
        !           641:        mb();
        !           642: 
        !           643:        /*
        !           644:         * write new tail pointer
        !           645:         */
        !           646:        e1k_wr32(RDT, m_e1k.m_rx_next_u32);
        !           647: 
        !           648:        /*
        !           649:         * update next receive index
        !           650:         */
        !           651:        m_e1k.m_rx_next_u32 = (m_e1k.m_rx_next_u32 + 1) & (E1K_NUM_RX_DESC - 1);
        !           652: 
        !           653:        return l_ret_i;
        !           654: }
        !           655: 
        !           656: static int
        !           657: e1k_xmit(char *f_buffer_pc, int f_len_i)
        !           658: {
        !           659:        uint32_t        l_tdh_u32 = e1k_rd32(TDH);
        !           660:        uint32_t        l_tdt_u32 = e1k_rd32(TDT);
        !           661:        uint32_t        l_pre_u32 = (l_tdh_u32 + (E1K_NUM_TX_DESC - 1)) &
        !           662:                                    (E1K_NUM_TX_DESC - 1);
        !           663:        e1k_tx_desc_st  *tx;
        !           664:        #if defined(E1K_DEBUG) && defined(E1K_SHOW_XMIT_DATA)
        !           665:        int             i;
        !           666:        #endif
        !           667: 
        !           668:        /*
        !           669:         * check for available buffers
        !           670:         */
        !           671:        if (l_pre_u32 == l_tdt_u32) {
        !           672:                return 0;
        !           673:        }
        !           674: 
        !           675:        /*
        !           676:         * get a pointer to the next tx descriptor for ease of use
        !           677:         */
        !           678:        tx = &m_e1k.m_tx_ring_pst[l_tdt_u32];
        !           679: 
        !           680:        /*
        !           681:         * copy the data
        !           682:         */
        !           683:        memcpy(dma2virt(bswap_64(tx->m_buffer_u64)), (uint8_t *) f_buffer_pc,
        !           684:                (size_t) f_len_i);
        !           685: 
        !           686:        /*
        !           687:         * insert length & command flags
        !           688:         */
        !           689:        tx->m_len_u16 = bswap_16((uint16_t) f_len_i);
        !           690:        tx->m_cmd_u08 = (BIT08(0) |             // EOP
        !           691:                          BIT08(1));            // IFCS
        !           692:        tx->m_sta_u08 = 0;
        !           693:        mb();
        !           694: 
        !           695:        /*
        !           696:         * update tail index
        !           697:         */
        !           698:        l_tdt_u32 = (l_tdt_u32 + 1) & (E1K_NUM_TX_DESC - 1);
        !           699:        e1k_wr32(TDT, l_tdt_u32);
        !           700: 
        !           701:        #ifdef E1K_DEBUG
        !           702:        #if defined(E1K_SHOW_XMIT) || defined(E1K_SHOW_XMIT_DATA)
        !           703:        printk("e1k: %d bytes transmitted\n", bswap_16(tx->m_len_u16));
        !           704:        #endif
        !           705: 
        !           706:        #ifdef E1K_SHOW_XMIT_DATA
        !           707:        for (i = 0; i < bswap_16(tx->m_len_u16); i++) {
        !           708: 
        !           709:                if ((i & 0x1f) == 0) {
        !           710:                        printk("\n       ");
        !           711:                }
        !           712: 
        !           713:                f_buffer_pc = dma2virt(bswap_64(tx->m_buffer_u64));
        !           714:                printk("%02X ", f_buffer_pc[i]);
        !           715:        }
        !           716: 
        !           717:        printk("\n\n");
        !           718:        #endif
        !           719:        #endif
        !           720: 
        !           721:        return f_len_i;
        !           722: }
        !           723: 
        !           724: int
        !           725: check_driver(pci_config_t *pci_conf)
        !           726: {
        !           727:        uint64_t i;
        !           728: 
        !           729:        /*
        !           730:         * checks whether the driver is handling this device
        !           731:         * by verifying vendor & device id
        !           732:         * vendor id 0x8086 == Intel
        !           733:         */
        !           734:        if (pci_conf->vendor_id != 0x8086) {
        !           735:                #ifdef E1K_DEBUG
        !           736:                printk("e1k: netdevice with vendor id %04X not supported\n",
        !           737:                        pci_conf->vendor_id);
        !           738:                #endif
        !           739:                return -1;
        !           740:        }
        !           741: 
        !           742:        for (i = 0; e1k_dev[i].m_dev_u32 != 0; i++) {
        !           743:                if (e1k_dev[i].m_dev_u32 == (uint32_t) pci_conf->device_id) {
        !           744:                        break;
        !           745:                }
        !           746:        }
        !           747: 
        !           748:        if (e1k_dev[i].m_dev_u32 == 0) {
        !           749:                #ifdef E1K_DEBUG
        !           750:                printk("e1k: netdevice with device id %04X not supported\n",
        !           751:                        pci_conf->device_id);
        !           752:                #endif
        !           753:                return -1;
        !           754:        }
        !           755: 
        !           756:        /*
        !           757:         * initialize static variables
        !           758:         */
        !           759:        m_e1k.m_device_u64   = e1k_dev[i].m_devmsk_u64;
        !           760:        m_e1k.m_baseaddr_u64 = 0;
        !           761:        m_e1k.pcicfg_puid    = pci_conf->puid;
        !           762:        m_e1k.pcicfg_bus     = pci_conf->bus;
        !           763:        m_e1k.pcicfg_devfn   = pci_conf->devfn;
        !           764: 
        !           765:        // success
        !           766:        #ifdef E1K_DEBUG
        !           767:        printk("e1k: found device %s\n", e1k_dev[i].m_name);
        !           768:        #endif
        !           769: 
        !           770:        return 0;
        !           771: }
        !           772: 
        !           773: static int
        !           774: e1k_init(void)
        !           775: {
        !           776:        uint32_t i;
        !           777:        uint32_t v;
        !           778:        char *mac_addr = snk_module_interface.mac_addr;
        !           779: 
        !           780:        if (snk_module_interface.running != 0) {
        !           781:                return 0;
        !           782:        }
        !           783: 
        !           784:        #ifdef E1K_DEBUG
        !           785:        printk("\ne1k: initializing\n");
        !           786:        #endif
        !           787: 
        !           788:        dma_offset = snk_kernel_interface->dma_map_in(&m_e1k, sizeof(m_e1k), 0);
        !           789:        #ifdef E1K_DEBUG
        !           790:        printk("e1k: dma offset: %lx - %lx = %lx\n", dma_offset, (long)&m_e1k,
        !           791:                dma_offset - (long)&m_e1k);
        !           792:        #endif
        !           793:        dma_offset = dma_offset - (long)&m_e1k;
        !           794: 
        !           795:        /*
        !           796:         * setup register & memory base addresses of NIC
        !           797:         */
        !           798:        m_e1k.m_baseaddr_u64 = (uint64_t) ((uint32_t) ~0xf & (uint32_t)
        !           799:                snk_kernel_interface->pci_config_read(m_e1k.pcicfg_puid,
        !           800:                                                        4,
        !           801:                                                        m_e1k.pcicfg_bus,
        !           802:                                                        m_e1k.pcicfg_devfn,
        !           803:                                                        PCI_BAR1_R));
        !           804:        #ifdef E1K_DEBUG
        !           805:        printk("e1k: base address register = 0x%lx\n", m_e1k.m_baseaddr_u64);
        !           806:        #endif
        !           807: 
        !           808:        snk_kernel_interface->translate_addr(((void *) &m_e1k.m_baseaddr_u64));
        !           809: 
        !           810: #ifdef E1K_DEBUG
        !           811:        printk("e1k: PCI-Puid  = 0x%llX\n", m_e1k.pcicfg_puid);
        !           812:        printk("e1k: PCI-Bus   = 0x%X\n", m_e1k.pcicfg_bus);
        !           813:        printk("e1k: PCI-DevFn = 0x%X\n", m_e1k.pcicfg_devfn);
        !           814:        printk("e1k: device's register base address = 0x%lx\n",
        !           815:                m_e1k.m_baseaddr_u64);
        !           816: #endif
        !           817: 
        !           818:        /*
        !           819:         * e1k hardware initialization
        !           820:         */
        !           821: 
        !           822:        /*
        !           823:         * save pci command register
        !           824:         */
        !           825:        m_e1k.m_com_r_u16 = (uint16_t)
        !           826:                snk_kernel_interface->pci_config_read(m_e1k.pcicfg_puid,
        !           827:                                                        2,
        !           828:                                                        m_e1k.pcicfg_bus,
        !           829:                                                        m_e1k.pcicfg_devfn,
        !           830:                                                        PCI_COM_R);
        !           831: 
        !           832: /*
        !           833:  * bus mastering does not need to be enabled, it is already set
        !           834:        // enable bus master & memory space in command reg
        !           835:        i = (BIT32(10) | BIT32(2) | BIT32(1));
        !           836:        snk_kernel_interface->pci_config_write(m_e1k.pcicfg_puid,
        !           837:                                                2,
        !           838:                                                m_e1k.pcicfg_bus,
        !           839:                                                m_e1k.pcicfg_devfn,
        !           840:                                                PCI_COM_R,
        !           841:                                                (int) i);
        !           842: */
        !           843: 
        !           844:        /*
        !           845:         * at first disable all interrupts
        !           846:         */
        !           847:        e1k_wr32(IMC, (uint32_t) ~0);
        !           848: 
        !           849:        /*
        !           850:         * check for link up
        !           851:         */
        !           852:        #ifdef E1K_DEBUG
        !           853:        printk("e1k: checking link status..\n");
        !           854:        #endif
        !           855: 
        !           856:        i = 50;
        !           857:        v = e1k_rd32(STATUS);
        !           858:        while ((--i) &&
        !           859:               ((v & BIT32(1)) == 0)) {
        !           860:                ms_delay(100);
        !           861:                v = e1k_rd32(STATUS);
        !           862:        }
        !           863: 
        !           864:        if ((v & BIT32(1)) == 0) {
        !           865:                #ifdef E1K_DEBUG
        !           866:                printk("e1k: link is down.\n");
        !           867:                printk("       terminating.\n");
        !           868:                #endif
        !           869: 
        !           870:                return -1;
        !           871:        }
        !           872: 
        !           873:        #ifdef E1K_DEBUG
        !           874:        printk("e1k: link is up\n");
        !           875: 
        !           876:        switch ((v >> 6) & 0x3) {
        !           877:                case 0: {
        !           878:                        printk("       10 Mb/s\n");
        !           879:                }       break;
        !           880:                case 1: {
        !           881:                        printk("       100 Mb/s\n");
        !           882:                }       break;
        !           883:                case 2:
        !           884:                case 3: {
        !           885:                        printk("       1000 Mb/s\n");
        !           886:                }       break;
        !           887:        }
        !           888: 
        !           889:        if ((v & BIT32(0)) == 0) {
        !           890:                printk("       half-duplex\n");
        !           891:        } else {
        !           892:                printk("       full-duplex\n");
        !           893:        }
        !           894:        #endif
        !           895: 
        !           896:        /*
        !           897:         * initialize mac address
        !           898:         */
        !           899:        #ifdef E1K_DEBUG
        !           900:        printk("e1k: initializing mac address.. ");
        !           901:        #endif
        !           902:        if (e1k_mac_init((uint8_t *)mac_addr) != 0) {
        !           903:                #ifdef E1K_DEBUG
        !           904:                printk("failed.\n");
        !           905:                printk("       terminating.\n");
        !           906:                #endif
        !           907: 
        !           908:                return -1;
        !           909:        }
        !           910: 
        !           911:        #ifdef E1K_DEBUG
        !           912:        printk("done.\n");
        !           913:        printk("       mac address = %02X:%02X:%02X:%02X:%02X:%02X\n",
        !           914:                mac_addr[0], mac_addr[1], mac_addr[2],
        !           915:                mac_addr[3], mac_addr[4], mac_addr[5]);
        !           916:        #endif
        !           917: 
        !           918:        /*
        !           919:         * initialize transmitter
        !           920:         */
        !           921:        #ifdef E1K_DEBUG
        !           922:        printk("e1k: initializing transmitter.. ");
        !           923:        #endif
        !           924:        e1k_init_transmitter();
        !           925:        #ifdef E1K_DEBUG
        !           926:        printk("done.\n");
        !           927:        #endif
        !           928: 
        !           929:        /*
        !           930:         * initialize receiver
        !           931:         */
        !           932:        #ifdef E1K_DEBUG
        !           933:        printk("e1k: initializing receiver.. ");
        !           934:        #endif
        !           935:        e1k_init_receiver();
        !           936:        #ifdef E1K_DEBUG
        !           937:        printk("done.\n");
        !           938:        printk("e1k: initialization complete\n");
        !           939:        #endif
        !           940: 
        !           941:        snk_module_interface.running = 1;
        !           942: 
        !           943:        return 0;
        !           944: }
        !           945: 
        !           946: static int
        !           947: e1k_reset(void)
        !           948: {
        !           949:        /*
        !           950:         * reset the PHY
        !           951:         */
        !           952:        e1k_setb32(CTRL, BIT32(31));
        !           953:        ms_delay(10);
        !           954: 
        !           955:        /*
        !           956:         * reset the MAC
        !           957:         */
        !           958:        e1k_setb32(CTRL, BIT32(26));
        !           959:        ms_delay(10);
        !           960: 
        !           961:        return 0;
        !           962: }
        !           963: 
        !           964: static int 
        !           965: e1k_term(void)
        !           966: {
        !           967:        if (snk_module_interface.running == 0) {
        !           968:                return 0;
        !           969:        }
        !           970: 
        !           971:        #ifdef E1K_DEBUG
        !           972:        printk("e1k: shutdown.. ");
        !           973:        #endif
        !           974: 
        !           975:        /*
        !           976:         * disable receiver & transmitter
        !           977:         */
        !           978:        e1k_wr32(RCTL, 0);
        !           979:        e1k_wr32(TCTL, 0);
        !           980:        ms_delay(10);
        !           981: 
        !           982:        /*
        !           983:         * reset the ring indices
        !           984:         */
        !           985:        e1k_wr32(RDH, 0);
        !           986:        e1k_wr32(RDT, 0);
        !           987:        e1k_wr32(TDH, 0);
        !           988:        e1k_wr32(TDT, 0);
        !           989: 
        !           990:        /*
        !           991:         * disable receive address
        !           992:         */
        !           993:        e1k_clrb32(RAH0, BIT32(31));
        !           994: 
        !           995:        /*
        !           996:         * reset the mac/phy
        !           997:         */
        !           998:        e1k_reset();
        !           999: 
        !          1000:        /*
        !          1001:         * reset pci command register
        !          1002:         */
        !          1003:        snk_kernel_interface->pci_config_write(m_e1k.pcicfg_puid,
        !          1004:                                                2,
        !          1005:                                                m_e1k.pcicfg_bus,
        !          1006:                                                m_e1k.pcicfg_devfn,
        !          1007:                                                PCI_COM_R,
        !          1008:                                                (int) m_e1k.m_com_r_u16);
        !          1009: 
        !          1010:        /*
        !          1011:         * Disable DMA translation
        !          1012:         */
        !          1013:        snk_kernel_interface->dma_map_out(&m_e1k, virt2dma(&m_e1k),
        !          1014:                                          sizeof(m_e1k));
        !          1015: 
        !          1016:        #ifdef E1K_DEBUG
        !          1017:        printk("done.\n");
        !          1018:        #endif
        !          1019: 
        !          1020:        snk_module_interface.running = 0;
        !          1021:        return 0;
        !          1022: }
        !          1023: 
        !          1024: static int
        !          1025: e1k_ioctl(int request, void* data)
        !          1026: {
        !          1027:        return 0;
        !          1028: }

unix.superglobalmegacorp.com

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