Annotation of qemu/roms/SLOF/board-qemu/virtio-net/virtio-net.c, revision 1.1.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: /*
                     14:  * This is the implementation for the Virtio network device driver. Details
                     15:  * about the virtio-net interface can be found in Rusty Russel's "Virtio PCI
                     16:  * Card Specification v0.8.10", appendix C, which can be found here:
                     17:  *
                     18:  *        http://ozlabs.org/~rusty/virtio-spec/virtio-spec.pdf
                     19:  */
                     20: 
                     21: #include <stdint.h>
                     22: #include "netdriver_int.h"
                     23: #include <libhvcall.h>
                     24: #include <virtio.h>
                     25: #include <string.h>
                     26: #include "virtio-net.h"
                     27: 
                     28: 
                     29: #define sync()  asm volatile (" sync \n" ::: "memory")
                     30: 
                     31: 
                     32: struct virtio_device virtiodev;
                     33: struct vqs vq[2];     /* Information about virtqueues */
                     34: 
                     35: 
                     36: /* See Virtio Spec, appendix C, "Device Operation" */ 
                     37: struct virtio_net_hdr {
                     38:        uint8_t  flags;
                     39:        uint8_t  gso_type;
                     40:        uint16_t  hdr_len;
                     41:        uint16_t  gso_size;
                     42:        uint16_t  csum_start;
                     43:        uint16_t  csum_offset;
                     44:        // uint16_t  num_buffers;       /* Only if VIRTIO_NET_F_MRG_RXBUF */
                     45: };
                     46: 
                     47: static uint16_t last_rx_idx;   /* Last index in RX "used" ring */
                     48: 
                     49: 
                     50: /**
                     51:  * Initialize the virtio-net device.
                     52:  * See the Virtio Spec, chapter 2.2.1 and Appendix C "Device Initialization"
                     53:  * for details.
                     54:  */
                     55: static int virtionet_init(void)
                     56: {
                     57:        int i;
                     58: 
                     59:        dprintk("virtionet_init(%02x:%02x:%02x:%02x:%02x:%02x)\n",
                     60:                snk_module_interface->mac_addr[0], snk_module_interface->mac_addr[1],
                     61:                snk_module_interface->mac_addr[2], snk_module_interface->mac_addr[3],
                     62:                snk_module_interface->mac_addr[4], snk_module_interface->mac_addr[5]);
                     63: 
                     64:        if (snk_module_interface->running != 0)
                     65:                return 0;
                     66: 
                     67:        /* Tell HV that we know how to drive the device. */
                     68:        virtio_set_status(&virtiodev, VIRTIO_STAT_ACKNOWLEDGE|VIRTIO_STAT_DRIVER);
                     69: 
                     70:        /* Device specific setup - we do not support special features right now */
                     71:        virtio_set_guest_features(&virtiodev,  0);
                     72: 
                     73:        /* Allocate memory for one transmit an multiple receive buffers */
                     74:        vq[VQ_RX].buf_mem = malloc((BUFFER_ENTRY_SIZE+sizeof(struct virtio_net_hdr))
                     75:                                   * RX_QUEUE_SIZE);
                     76:        if (!vq[VQ_RX].buf_mem) {
                     77:                printk("virtionet: Failed to allocate buffers!\n");
                     78:                virtio_set_status(&virtiodev, VIRTIO_STAT_FAILED);
                     79:                return -1;
                     80:        }
                     81: 
                     82:        /* Prepare receive buffer queue */
                     83:        for (i = 0; i < RX_QUEUE_SIZE; i++) {
                     84:                struct vring_desc *desc;
                     85:                /* Descriptor for net_hdr: */
                     86:                desc = &vq[VQ_RX].desc[i*2];
                     87:                desc->addr = (uint64_t)vq[VQ_RX].buf_mem
                     88:                             + i * (BUFFER_ENTRY_SIZE+sizeof(struct virtio_net_hdr));
                     89:                // printk("RX buf %i addr = 0x%llx\n", i, desc->addr);
                     90:                desc->len = sizeof(struct virtio_net_hdr);
                     91:                desc->flags = VRING_DESC_F_NEXT | VRING_DESC_F_WRITE;
                     92:                desc->next = i*2+1;
                     93: 
                     94:                /* Descriptor for data: */
                     95:                desc = &vq[VQ_RX].desc[i*2+1];
                     96:                desc->addr = vq[VQ_RX].desc[i*2].addr + sizeof(struct virtio_net_hdr);
                     97:                desc->len = BUFFER_ENTRY_SIZE;
                     98:                desc->flags = VRING_DESC_F_WRITE;
                     99:                desc->next = 0;
                    100: 
                    101:                vq[VQ_RX].avail->ring[i] = i*2;
                    102:        }
                    103:        sync();
                    104:        vq[VQ_RX].avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
                    105:        vq[VQ_RX].avail->idx = RX_QUEUE_SIZE;
                    106: 
                    107:        last_rx_idx = vq[VQ_RX].used->idx;
                    108: 
                    109:        vq[VQ_TX].avail->flags = VRING_AVAIL_F_NO_INTERRUPT;
                    110:        vq[VQ_TX].avail->idx = 0;
                    111: 
                    112:        /* Tell HV that setup succeeded */
                    113:        virtio_set_status(&virtiodev, VIRTIO_STAT_ACKNOWLEDGE
                    114:                                      |VIRTIO_STAT_DRIVER
                    115:                                      |VIRTIO_STAT_DRIVER_OK);
                    116: 
                    117:        /* Tell HV that RX queues are ready */
                    118:        virtio_queue_notify(&virtiodev, VQ_RX);
                    119: 
                    120:        snk_module_interface->running = 1;
                    121: 
                    122:        return 0;
                    123: }
                    124: 
                    125: 
                    126: /**
                    127:  * Shutdown driver.
                    128:  * We've got to make sure that the hosts stops all transfers since the buffers
                    129:  * in our main memory will become invalid after this module has been terminated.
                    130:  */
                    131: static int virtionet_term(void)
                    132: {
                    133:        dprintk("virtionet_term()\n");
                    134: 
                    135:        if (snk_module_interface->running == 0)
                    136:                return 0;
                    137: 
                    138:        /* Quiesce device */
                    139:        virtio_set_status(&virtiodev, VIRTIO_STAT_FAILED);
                    140: 
                    141:        /* Reset device */
                    142:        virtio_reset_device(&virtiodev);
                    143: 
                    144:        snk_module_interface->running = 0;
                    145: 
                    146:        return 0;
                    147: }
                    148: 
                    149: 
                    150: /**
                    151:  * Transmit a packet
                    152:  */
                    153: static int virtionet_xmit(char *buf, int len)
                    154: {
                    155:        struct vring_desc *desc;
                    156:        int id;
                    157:        static struct virtio_net_hdr nethdr = {
                    158:                0, 0, sizeof(struct virtio_net_hdr),
                    159:                0, 0, 0
                    160:        };
                    161: 
                    162:        if (len > BUFFER_ENTRY_SIZE) {
                    163:                printk("virtionet: Packet too big!\n");
                    164:                return 0;
                    165:        }
                    166: 
                    167:        dprintk("\nvirtionet_xmit(packet at %p, %d bytes)\n", buf, len);
                    168: 
                    169:        /* Determine descriptor index */
                    170:        id = (vq[VQ_TX].avail->idx * 2) % vq[VQ_TX].size;
                    171: 
                    172:        /* Set up virtqueue descriptor for header */
                    173:        desc = &vq[VQ_TX].desc[id];
                    174:        desc->addr = (uint64_t)&nethdr;
                    175:        desc->len = sizeof(struct virtio_net_hdr);
                    176:        desc->flags = VRING_DESC_F_NEXT;
                    177:        desc->next = id + 1;
                    178: 
                    179:        /* Set up virtqueue descriptor for data */
                    180:        desc = &vq[VQ_TX].desc[id+1];
                    181:        desc->addr = (uint64_t)buf;
                    182:        desc->len = len;
                    183:        desc->flags = 0;
                    184:        desc->next = 0;
                    185: 
                    186:        vq[VQ_TX].avail->ring[vq[VQ_TX].avail->idx % vq[VQ_TX].size] = id;
                    187:        sync();
                    188:        vq[VQ_TX].avail->idx += 1;
                    189: 
                    190:        /* Tell HV that TX queue is ready */
                    191:        virtio_queue_notify(&virtiodev, VQ_TX);
                    192: 
                    193:        return len;
                    194: }
                    195: 
                    196: 
                    197: /**
                    198:  * Receive a packet
                    199:  */
                    200: static int virtionet_receive(char *buf, int maxlen)
                    201: {
                    202:        int len = 0;
                    203:        int id;
                    204: 
                    205:        if (last_rx_idx == vq[VQ_RX].used->idx) {
                    206:                /* Nothing received yet */
                    207:                return 0;
                    208:        }
                    209: 
                    210:        id = (vq[VQ_RX].used->ring[last_rx_idx % vq[VQ_RX].size].id + 1)
                    211:             % vq[VQ_RX].size;
                    212:        len = vq[VQ_RX].used->ring[last_rx_idx % vq[VQ_RX].size].len
                    213:              - sizeof(struct virtio_net_hdr);
                    214: 
                    215:        dprintk("virtionet_receive() last_rx_idx=%i, vq[VQ_RX].used->idx=%i,"
                    216:                " id=%i len=%i\n", last_rx_idx, vq[VQ_RX].used->idx, id, len);
                    217: 
                    218:        if (len > maxlen) {
                    219:                printk("virtio-net: Receive buffer not big enough!\n");
                    220:                len = maxlen;
                    221:        }
                    222: 
                    223: #if 0
                    224:        /* Dump packet */
                    225:        printk("\n");
                    226:        int i;
                    227:        for (i=0; i<64; i++) {
                    228:                printk(" %02x", *(uint8_t*)(vq[VQ_RX].desc[id].addr+i));
                    229:                if ((i%16)==15)
                    230:                        printk("\n");
                    231:        }
                    232:        printk("\n");
                    233: #endif
                    234: 
                    235:        /* Copy data to destination buffer */
                    236:        memcpy(buf, (void*)vq[VQ_RX].desc[id].addr, len);
                    237: 
                    238:        /* Move indices to next entries */
                    239:        last_rx_idx = last_rx_idx + 1;
                    240: 
                    241:        vq[VQ_RX].avail->ring[vq[VQ_RX].avail->idx % vq[VQ_RX].size] = id - 1;
                    242:        sync();
                    243:        vq[VQ_RX].avail->idx += 1;
                    244: 
                    245:        /* Tell HV that RX queue entry is ready */
                    246:        virtio_queue_notify(&virtiodev, VQ_RX);
                    247: 
                    248:        return len;
                    249: }
                    250: 
                    251: 
                    252: /**
                    253:  * Network IO control function - not implemented.
                    254:  */
                    255: static int virtionet_ioctl(int request, void* data)
                    256: {
                    257:        dprintk("virtionet_ioctl()\n");
                    258: 
                    259:        return -1;
                    260: }
                    261: 
                    262: 
                    263: /**
                    264:  * Module definition
                    265:  */
                    266: snk_module_t virtionet_interface = {
                    267:        .version = 1,
                    268:        .type    = MOD_TYPE_NETWORK,
                    269:        .running = 0,
                    270:        .init    = virtionet_init,
                    271:        .term    = virtionet_term,
                    272:        .write   = virtionet_xmit,
                    273:        .read    = virtionet_receive,
                    274:        .ioctl   = virtionet_ioctl
                    275: };

unix.superglobalmegacorp.com

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