2 * (c) 2013-2014 Alexander Warg <warg@os.inf.tu-dresden.de>
3 * economic rights: Technische Universität Dresden (Germany)
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU General Public License 2.
7 * Please see the COPYING-GPL-2 file for details.
10 * Copyright (C) 2015 Kernkonzept GmbH.
11 * Author(s): Sarah Hoffmann <sarah.hoffmann@kernkonzept.com>
13 * This file is distributed under the terms of the GNU General Public
14 * License, version 2. Please see the COPYING-GPL-2 file for details.
18 #include <l4/l4virtio/virtio.h>
19 #include <l4/l4virtio/server/virtio>
25 class Virtqueue : public L4virtio::Svr::Virtqueue
28 typedef l4virtio_config_queue_t Queue_config;
32 void init_queue(void *base)
33 { setup(config.num, config.align, base); }
41 typedef L4virtio::Svr::Dev_status Status;
42 typedef L4virtio::Svr::Dev_features Features;
47 l4_uint32_t _irq_status;
49 l4_uint32_t _guest_features[8];
54 Dev(Vmm::Vm_ram *iommu, l4_uint32_t vendor, l4_uint32_t device)
55 : _vendor(vendor), _device(device), _irq_status(0), _status(0),
58 memset(_guest_features, 0, sizeof(_guest_features));
61 virtual l4_uint32_t read_config(unsigned /*reg*/) { return 0; }
62 virtual void write_config(unsigned /*reg*/, l4_uint32_t /*value*/) {}
63 virtual void kick() = 0;
64 virtual l4_uint32_t host_feature(unsigned /*id*/) { return 0; }
65 virtual Virtqueue *queue(unsigned idx) = 0;
66 virtual void reset() {}
68 l4_uint32_t vendor() const noexcept
71 l4_uint32_t device() const noexcept
74 l4_uint32_t irq_status()
76 // hack: we have always a queue IRQ
80 l4_uint32_t tmp = _irq_status;
86 Status dev_status() const noexcept
89 void set_dev_status(l4_uint32_t status)
96 l4_uint32_t guest_feature(unsigned idx) noexcept
97 { return (idx < 8) ? _guest_features[idx] : 0; }
99 void set_guest_feature(unsigned idx, l4_uint32_t value) noexcept
102 _guest_features[idx] = value;
106 T *devaddr_to_virt(l4_addr_t devaddr) const
107 { return _iommu->access(L4virtio::Ptr<T>(devaddr)); }
111 template<typename DEV>
115 l4_uint32_t read(unsigned reg, char /*size*/, unsigned)
118 return dev()->read_config(reg - 0x100);
122 case 0: return *reinterpret_cast<l4_uint32_t const *>("virt");
124 case 2: return dev()->device();
125 case 3: return dev()->vendor();
126 case 4: return dev()->host_feature(_current_host_feat);
127 case 13: return _current_q ? _current_q->config.num_max : 0;
128 case 16: return _current_q ? _current_q->config.pfn : 0;
129 case 24: return dev()->irq_status();
130 case 28: return dev()->dev_status().raw;
135 void write(unsigned reg, char /*size*/, l4_uint32_t value, unsigned)
139 dev()->write_config(reg - 0x100, value);
146 _current_host_feat = value;
150 dev()->set_guest_feature(_current_guest_feat, value);
154 _current_guest_feat = value;
162 _current_q = dev()->queue(value);
167 _current_q->config.num = _current_q->config.num_max >= value
169 : _current_q->config.num_max;
174 _current_q->config.align = value;
180 _current_q->config.pfn = value;
181 _current_q->init_queue(dev()->template devaddr_to_virt<void>(value * _page_size));
193 dev()->set_dev_status(value);
200 { return static_cast<DEV *>(this); }
202 Virtqueue *_current_q = 0;
203 unsigned _current_host_feat = 0;
204 unsigned _current_guest_feat = 0;
205 l4_uint32_t _page_size = 1 << 12;