Annotation of qemu/roms/SLOF/board-qemu/veth/veth.c, revision 1.1

1.1     ! root        1: /******************************************************************************
        !             2:  * Copyright (c) 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: #include "types.h"
        !            14: #include "netdriver_int.h"
        !            15: #include "libhvcall.h"
        !            16: 
        !            17: static snk_kernel_t     *snk_kernel_interface;
        !            18: static snk_module_t    *snk_module_interface;
        !            19: static unsigned int    g_reg;
        !            20: 
        !            21: #define printk(fmt...)  do { snk_kernel_interface->print(fmt); } while(0)
        !            22: #define malloc(args...) snk_kernel_interface->k_malloc(args)
        !            23: #define malloc_aligned(args...) snk_kernel_interface->k_malloc_aligned(args)
        !            24: #define free(args...)  do { snk_kernel_interface->k_free(args); } while(0)
        !            25: 
        !            26: #define dprintk(fmt...)
        !            27: //#define dprintk(fmt...)      printk(fmt)
        !            28: 
        !            29: /* *** WARNING: We pass our addresses as-is as DMA addresses,
        !            30:  *     we -do- rely on the forth code to have enabled TCE bypass
        !            31:  *     on our device !
        !            32:  */
        !            33: #define vaddr_to_dma(vaddr)    ((u64)vaddr)
        !            34: 
        !            35: struct ibmveth_buf_desc_fields {
        !            36:        u32 flags_len;
        !            37: #define IBMVETH_BUF_VALID      0x80000000
        !            38: #define IBMVETH_BUF_TOGGLE     0x40000000
        !            39: #define IBMVETH_BUF_NO_CSUM    0x02000000
        !            40: #define IBMVETH_BUF_CSUM_GOOD  0x01000000
        !            41: #define IBMVETH_BUF_LEN_MASK   0x00FFFFFF
        !            42:        u32 address;
        !            43: };
        !            44: 
        !            45: union ibmveth_buf_desc {
        !            46:        u64 desc;
        !            47:        struct ibmveth_buf_desc_fields fields;
        !            48: };
        !            49: 
        !            50: struct ibmveth_rx_q_entry {
        !            51:        u32 flags_off;
        !            52: #define IBMVETH_RXQ_TOGGLE             0x80000000
        !            53: #define IBMVETH_RXQ_TOGGLE_SHIFT       31
        !            54: #define IBMVETH_RXQ_VALID              0x40000000
        !            55: #define IBMVETH_RXQ_NO_CSUM            0x02000000
        !            56: #define IBMVETH_RXQ_CSUM_GOOD          0x01000000
        !            57: #define IBMVETH_RXQ_OFF_MASK           0x0000FFFF
        !            58: 
        !            59:        u32 length;
        !            60:        u64 correlator;
        !            61: };
        !            62: 
        !            63: static void *buffer_list; 
        !            64: static void *filter_list; 
        !            65: static u64 *rx_bufs;
        !            66: static u64 *rx_bufs_aligned;
        !            67: static u32 cur_rx_toggle;
        !            68: static u32 cur_rx_index;
        !            69: 
        !            70: #define RX_QUEUE_SIZE  16
        !            71: #define RX_BUF_SIZE    2048
        !            72: #define RX_BUF_MULT    (RX_BUF_SIZE >> 3)
        !            73: 
        !            74: static struct ibmveth_rx_q_entry *rx_queue;
        !            75: 
        !            76: static char * memcpy( char *dest, const char *src, size_t n )
        !            77: {
        !            78:         char *ret = dest;
        !            79:         while( n-- ) {
        !            80:                 *dest++ = *src++;
        !            81:         }
        !            82: 
        !            83:         return( ret );
        !            84: }
        !            85: 
        !            86: static inline u64 *veth_get_rx_buf(unsigned int i)
        !            87: {
        !            88:        return &rx_bufs_aligned[i * RX_BUF_MULT];
        !            89: }
        !            90: 
        !            91: static int veth_init(void)
        !            92: {
        !            93:        char *mac_addr = snk_module_interface->mac_addr;
        !            94:        union ibmveth_buf_desc rxq_desc;
        !            95:        unsigned long rx_queue_len = sizeof(struct ibmveth_rx_q_entry) *
        !            96:                RX_QUEUE_SIZE;
        !            97:        unsigned int i;
        !            98:        long rc;
        !            99: 
        !           100:        dprintk("veth_init(%02x:%02x:%02x:%02x:%02x:%02x)\n",
        !           101:                mac_addr[0], mac_addr[1], mac_addr[2],
        !           102:                mac_addr[3], mac_addr[4], mac_addr[5]);
        !           103: 
        !           104:        if (snk_module_interface->running != 0)
        !           105:                return 0;
        !           106: 
        !           107:        cur_rx_toggle = IBMVETH_RXQ_TOGGLE;
        !           108:        cur_rx_index = 0;
        !           109:        buffer_list = malloc_aligned(8192, 4096);
        !           110:        filter_list = buffer_list + 4096;
        !           111:        rx_queue = malloc_aligned(rx_queue_len, 16);
        !           112:        rx_bufs = malloc(2048 * RX_QUEUE_SIZE + 4);
        !           113:        if (!buffer_list || !filter_list || !rx_queue || !rx_bufs) {
        !           114:                printk("veth: Failed to allocate memory !\n");
        !           115:                goto fail;
        !           116:        }
        !           117:        rx_bufs_aligned = (u64 *)(((u64)rx_bufs | 3) + 1);
        !           118:        rxq_desc.fields.address = vaddr_to_dma(rx_queue);
        !           119:        rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | rx_queue_len;
        !           120: 
        !           121:        rc = h_register_logical_lan(g_reg,
        !           122:                                    vaddr_to_dma(buffer_list),
        !           123:                                    rxq_desc.desc,
        !           124:                                    vaddr_to_dma(filter_list),
        !           125:                                    (*(u64 *)mac_addr) >> 16);
        !           126:        if (rc != H_SUCCESS) {
        !           127:                printk("veth: Error %ld registering interface !\n", rc);
        !           128:                goto fail;
        !           129:        }
        !           130:        for (i = 0; i < RX_QUEUE_SIZE; i++) {
        !           131:                u64 *buf = veth_get_rx_buf(i);
        !           132:                union ibmveth_buf_desc desc;
        !           133:                *buf = (u64)buf;
        !           134:                desc.fields.address = vaddr_to_dma(buf);
        !           135:                desc.fields.flags_len = IBMVETH_BUF_VALID | RX_BUF_SIZE;
        !           136:                h_add_logical_lan_buffer(g_reg, desc.desc);
        !           137:        }
        !           138: 
        !           139:        snk_module_interface->running = 1;
        !           140: 
        !           141:        return 0;
        !           142:  fail:
        !           143:        if (filter_list)
        !           144:                free(filter_list);
        !           145:        if (buffer_list)
        !           146:                free(buffer_list);
        !           147:        if (rx_queue)
        !           148:                free(rx_queue);
        !           149:        if (rx_bufs)
        !           150:                free(rx_bufs);
        !           151:        return -1;
        !           152: }
        !           153: 
        !           154: static int veth_term(void)
        !           155: {
        !           156:        dprintk("veth_term()\n");
        !           157: 
        !           158:        if (snk_module_interface->running == 0)
        !           159:                return 0;
        !           160: 
        !           161:        h_free_logical_lan(g_reg);
        !           162: 
        !           163:        if (filter_list)
        !           164:                free(filter_list);
        !           165:        if (buffer_list)
        !           166:                free(buffer_list);
        !           167:        if (rx_queue)
        !           168:                free(rx_queue);
        !           169:        if (rx_bufs)
        !           170:                free(rx_bufs);
        !           171: 
        !           172:        snk_module_interface->running = 0;
        !           173: 
        !           174:        return 0;
        !           175: }
        !           176: 
        !           177: static int veth_xmit(char *f_buffer_pc, int f_len_i)
        !           178: {
        !           179:        union ibmveth_buf_desc tx_desc;
        !           180:        long rc;
        !           181: 
        !           182:        dprintk("veth_xmit(packet at %p, %d bytes)\n", f_buffer_pc, f_len_i);
        !           183: 
        !           184:        tx_desc.fields.address = vaddr_to_dma(f_buffer_pc);
        !           185:        tx_desc.fields.flags_len = IBMVETH_BUF_VALID | f_len_i;
        !           186: 
        !           187:        rc = hv_send_logical_lan(g_reg, tx_desc.desc, 0, 0, 0, 0, 0);
        !           188:        if (rc != H_SUCCESS) {
        !           189:                printk("veth: Error %ld sending packet !\n", rc);
        !           190:                return -1;
        !           191:        }
        !           192: 
        !           193:        return f_len_i;
        !           194: }
        !           195: 
        !           196: static int veth_receive(char *f_buffer_pc, int f_len_i)
        !           197: {
        !           198:        int packet = 0;
        !           199: 
        !           200:        dprintk("veth_receive()\n");
        !           201: 
        !           202:        while(!packet) {
        !           203:                struct ibmveth_rx_q_entry *desc = &rx_queue[cur_rx_index];
        !           204:                union ibmveth_buf_desc bdesc;
        !           205:                void *buf;
        !           206: 
        !           207:                if ((desc->flags_off & IBMVETH_RXQ_TOGGLE) != cur_rx_toggle)
        !           208:                        break;
        !           209: 
        !           210:                if (!(desc->flags_off & IBMVETH_RXQ_VALID))
        !           211:                        goto recycle;
        !           212:                if (desc->length > f_len_i) {
        !           213:                        printk("veth: Dropping too big packet [%d bytes]\n",
        !           214:                               desc->length);
        !           215:                        goto recycle;
        !           216:                }
        !           217: 
        !           218:                buf = (void *)desc->correlator;
        !           219:                packet = desc->length;
        !           220:                memcpy(f_buffer_pc,
        !           221:                       buf + (desc->flags_off & IBMVETH_RXQ_OFF_MASK), packet);
        !           222:        recycle:
        !           223:                bdesc.fields.address = vaddr_to_dma(buf);
        !           224:                bdesc.fields.flags_len = IBMVETH_BUF_VALID | RX_BUF_SIZE;
        !           225:                h_add_logical_lan_buffer(g_reg, bdesc.desc);
        !           226: 
        !           227:                cur_rx_index = (cur_rx_index + 1) % RX_QUEUE_SIZE;
        !           228:                if (cur_rx_index == 0)
        !           229:                        cur_rx_toggle ^= IBMVETH_RXQ_TOGGLE;
        !           230:        }
        !           231: 
        !           232:        return packet;
        !           233: }
        !           234: 
        !           235: static int veth_ioctl(int request, void* data)
        !           236: {
        !           237:        dprintk("veth_ioctl()\n");
        !           238: 
        !           239:        return 0;
        !           240: }
        !           241: 
        !           242: static snk_module_t veth_interface = {
        !           243:        .version = 1,
        !           244:        .type    = MOD_TYPE_NETWORK,
        !           245:        .running = 0,
        !           246:        .init    = veth_init,
        !           247:        .term    = veth_term,
        !           248:        .write   = veth_xmit,
        !           249:        .read    = veth_receive,
        !           250:        .ioctl   = veth_ioctl
        !           251: };
        !           252: 
        !           253: 
        !           254: static int check_driver(vio_config_t *conf)
        !           255: {
        !           256:        
        !           257:         if (snk_kernel_interface->strcmp(conf->compat, "IBM,l-lan")) {
        !           258:                printk( "veth: netdevice not supported\n" );
        !           259:                return -1;
        !           260:        }
        !           261:        g_reg = conf->reg;
        !           262:        
        !           263:        return 0;
        !           264: }
        !           265: 
        !           266: snk_module_t* veth_module_init(snk_kernel_t *snk_kernel_int, vio_config_t *conf)
        !           267: {
        !           268:        snk_kernel_interface = snk_kernel_int;
        !           269:        snk_module_interface = &veth_interface;
        !           270: 
        !           271:        if (snk_kernel_int->version != snk_module_interface->version)
        !           272:                return 0;
        !           273: 
        !           274:        /* Check if this is the right driver */
        !           275:        if (check_driver(conf) < 0)
        !           276:                return 0;
        !           277: 
        !           278:        snk_module_interface->link_addr = module_init;
        !           279:        return snk_module_interface;
        !           280: }

unix.superglobalmegacorp.com

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