source: mainline/uspace/drv/nic/virtio-net/virtio-net.c@ 0180c67

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0180c67 was 0180c67, checked in by Jakub Jermar <jakub@…>, 8 years ago

Separate buffers from virtqueues

  • Property mode set to 100644
File size: 4.5 KB
Line 
1/*
2 * Copyright (c) 2018 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "virtio-net.h"
30
31#include <stdio.h>
32#include <stdint.h>
33
34#include <ddf/driver.h>
35#include <ddf/log.h>
36#include <ops/nic.h>
37#include <pci_dev_iface.h>
38
39#include <nic.h>
40
41#include <virtio-pci.h>
42
43#define NAME "virtio-net"
44
45#define VIRTIO_NET_NUM_QUEUES 3
46
47#define RECVQ1 0
48#define TRANSQ1 1
49#define CTRLQ1 2
50
51#define RECVQ_SIZE 8
52#define TRANSQ_SIZE 8
53#define CTRLQ_SIZE 4
54
55static errno_t virtio_net_initialize(ddf_dev_t *dev)
56{
57 nic_t *nic_data = nic_create_and_bind(dev);
58 if (!nic_data)
59 return ENOMEM;
60
61 virtio_net_t *virtio_net = calloc(1, sizeof(virtio_net_t));
62 if (!virtio_net) {
63 nic_unbind_and_destroy(dev);
64 return ENOMEM;
65 }
66
67 nic_set_specific(nic_data, virtio_net);
68
69 errno_t rc = virtio_pci_dev_initialize(dev, &virtio_net->virtio_dev);
70 if (rc != EOK)
71 return rc;
72
73 virtio_dev_t *vdev = &virtio_net->virtio_dev;
74 virtio_pci_common_cfg_t *cfg = virtio_net->virtio_dev.common_cfg;
75 virtio_net_cfg_t *netcfg = virtio_net->virtio_dev.device_cfg;
76
77 /* Reset the device and negotiate the feature bits */
78 rc = virtio_device_setup_start(vdev,
79 VIRTIO_NET_F_MAC | VIRTIO_NET_F_CTRL_VQ);
80 if (rc != EOK)
81 goto fail;
82
83 /* Perform device-specific setup */
84
85 /*
86 * Discover and configure the virtqueues
87 */
88 uint16_t num_queues = pio_read_16(&cfg->num_queues);
89 if (num_queues != VIRTIO_NET_NUM_QUEUES) {
90 ddf_msg(LVL_NOTE, "Unsupported number of virtqueues: %u",
91 num_queues);
92 goto fail;
93 }
94
95 vdev->queues = calloc(sizeof(virtq_t), num_queues);
96 if (!vdev->queues) {
97 rc = ENOMEM;
98 goto fail;
99 }
100
101 rc = virtio_virtq_setup(vdev, RECVQ1, RECVQ_SIZE);
102 if (rc != EOK)
103 goto fail;
104 rc = virtio_virtq_setup(vdev, TRANSQ1, TRANSQ_SIZE);
105 if (rc != EOK)
106 goto fail;
107 rc = virtio_virtq_setup(vdev, CTRLQ1, CTRLQ_SIZE);
108 if (rc != EOK)
109 goto fail;
110
111 /*
112 * Read the MAC address
113 */
114 nic_address_t nic_addr;
115 for (unsigned i = 0; i < 6; i++)
116 nic_addr.address[i] = pio_read_8(&netcfg->mac[i]);
117 rc = nic_report_address(nic_data, &nic_addr);
118 if (rc != EOK)
119 goto fail;
120
121 ddf_msg(LVL_NOTE, "MAC address: %02x:%02x:%02x:%02x:%02x:%02x",
122 nic_addr.address[0], nic_addr.address[1], nic_addr.address[2],
123 nic_addr.address[3], nic_addr.address[4], nic_addr.address[5]);
124
125 /* Go live */
126 virtio_device_setup_finalize(vdev);
127
128 return EOK;
129
130fail:
131 virtio_device_setup_fail(vdev);
132 virtio_pci_dev_cleanup(vdev);
133 return rc;
134}
135
136static errno_t virtio_net_dev_add(ddf_dev_t *dev)
137{
138 ddf_msg(LVL_NOTE, "%s %s (handle = %zu)", __func__,
139 ddf_dev_get_name(dev), ddf_dev_get_handle(dev));
140
141 errno_t rc = virtio_net_initialize(dev);
142 if (rc != EOK)
143 return rc;
144
145 return ENOTSUP;
146}
147
148static ddf_dev_ops_t virtio_net_dev_ops;
149
150static driver_ops_t virtio_net_driver_ops = {
151 .dev_add = virtio_net_dev_add
152};
153
154static driver_t virtio_net_driver = {
155 .name = NAME,
156 .driver_ops = &virtio_net_driver_ops
157};
158
159static nic_iface_t virtio_net_nic_iface;
160
161int main(void)
162{
163 printf("%s: HelenOS virtio-net driver\n", NAME);
164
165 if (nic_driver_init(NAME) != EOK)
166 return 1;
167
168 nic_driver_implement(&virtio_net_driver_ops, &virtio_net_dev_ops,
169 &virtio_net_nic_iface);
170
171 (void) ddf_log_init(NAME);
172 return ddf_driver_main(&virtio_net_driver);
173}
Note: See TracBrowser for help on using the repository browser.