]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/virt/pci/vpci.h
update
[l4.git] / l4 / pkg / io / server / src / virt / pci / vpci.h
1 /*
2  * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
3  *          Alexander Warg <warg@os.inf.tu-dresden.de>
4  *     economic rights: Technische Universität Dresden (Germany)
5  *
6  * This file is part of TUD:OS and distributed under the terms of the
7  * GNU General Public License 2.
8  * Please see the COPYING-GPL-2 file for details.
9  */
10 #pragma once
11
12 #include "virt/vdevice.h"
13 #include "pci.h"
14
15 namespace Vi {
16 namespace Pci {
17   typedef Hw::Pci::Config Config;
18 }
19
20 /**
21  * \brief Generic virtual PCI device.
22  * This class provides the basic functionality for a device on a 
23  * virtual PCI bus.  Implementations may provide proxy access to a real PCI
24  * device or a completely virtualized PCI device.
25  */
26 class Pci_dev
27 {
28 private:
29   void operator = (Pci_dev const &);
30   Pci_dev(Pci_dev const &);
31
32 public:
33   typedef Hw::Pci::Cfg_width Cfg_width;
34
35   struct Irq_info
36   {
37     int irq;
38     unsigned char trigger;
39     unsigned char polarity;
40   };
41
42   Pci_dev() {}
43   virtual int cfg_read(int reg, l4_uint32_t *v, Cfg_width) = 0;
44   virtual int cfg_write(int reg, l4_uint32_t v, Cfg_width) = 0;
45   virtual int irq_enable(Irq_info *irq) = 0;
46   virtual bool is_same_device(Pci_dev const *o) const = 0;
47   virtual ~Pci_dev() = 0;
48 };
49
50 inline
51 Pci_dev::~Pci_dev()
52 {}
53
54 /**
55  * \brief A basic really virtualized PCI device.
56  */
57 class Pci_virtual_dev : public Pci_dev, public Dev_feature
58 {
59 public:
60   struct Pci_cfg_header
61   {
62     l4_uint32_t vendor_device;
63     l4_uint16_t cmd;
64     l4_uint16_t status;
65     l4_uint32_t class_rev;
66     l4_uint8_t  cls;
67     l4_uint8_t  lat;
68     l4_uint8_t  hdr_type;
69     l4_uint8_t  bist;
70   } __attribute__((packed));
71
72   Pci_cfg_header *cfg_hdr() { return (Pci_cfg_header*)_h; }
73   Pci_cfg_header const *cfg_hdr() const { return (Pci_cfg_header const *)_h; }
74
75   int cfg_read(int reg, l4_uint32_t *v, Cfg_width);
76   int cfg_write(int reg, l4_uint32_t v, Cfg_width);
77   bool is_same_device(Pci_dev const *o) const { return o == this; }
78
79   ~Pci_virtual_dev() = 0;
80
81   Pci_virtual_dev();
82
83   void set_host(Device *d) { _host = d; }
84   Device *host() const { return _host; }
85
86 protected:
87   Device *_host;
88   unsigned char *_h;
89   unsigned _h_len;
90
91 };
92
93 inline
94 Pci_virtual_dev::~Pci_virtual_dev()
95 {}
96
97
98
99 /**
100  * \brief A virtual PCI proxy for a real PCI device.
101  */
102 class Pci_proxy_dev : public Pci_dev, public virtual Dev_feature
103 {
104 public:
105
106   Pci_proxy_dev(Hw::Pci::If *hwf);
107
108   int cfg_read(int reg, l4_uint32_t *v, Cfg_width);
109   int cfg_write(int reg, l4_uint32_t v, Cfg_width);
110   int irq_enable(Irq_info *irq);
111
112   l4_uint32_t read_bar(int bar);
113   void write_bar(int bar, l4_uint32_t v);
114
115   l4_uint32_t read_rom() const { return _rom; }
116   void write_rom(l4_uint32_t v);
117
118   int vbus_dispatch(l4_umword_t, l4_uint32_t, L4::Ipc::Iostream &)
119   { return -L4_ENOSYS; }
120
121   Hw::Pci::If *hwf() const { return _hwf; }
122
123   void dump() const;
124   bool is_same_device(Pci_dev const *o) const
125   {
126     if (Pci_proxy_dev const *op = dynamic_cast<Pci_proxy_dev const *>(o))
127       return (hwf()->bus_nr() == op->hwf()->bus_nr())
128              && (hwf()->device_nr() == op->hwf()->device_nr());
129     return false;
130   }
131
132   bool match_hw_feature(const Hw::Dev_feature *f) const
133   { return f == _hwf; }
134
135   int dispatch(l4_umword_t, l4_uint32_t, L4::Ipc::Iostream&)
136   { return -L4_ENOSYS; }
137
138   void set_host(Device *d) { _host = d; }
139   Device *host() const { return _host; }
140
141 private:
142   Device *_host;
143   Hw::Pci::If *_hwf;
144
145   l4_uint32_t _vbars[6];
146   l4_uint32_t _rom;
147
148   int _do_status_cmd_write(l4_uint32_t mask, l4_uint32_t value);
149   void _do_cmd_write(unsigned mask,unsigned value);
150
151   int _do_rom_bar_write(l4_uint32_t mask, l4_uint32_t value);
152 };
153
154
155
156 /**
157  * \brief a basic virtual PCI bridge.
158  * This class is the base for virtual Host-to-PCI bridges,
159  * for virtual PCI-to-PCI bridges, and also for this such as
160  * virtual PCI-to-Cardbus brdiges.
161  */
162 class Pci_bridge : public Device
163 {
164 public:
165   class Dev
166   {
167   public:
168     enum { Fns = 8 };
169
170   private:
171     Pci_dev *_fns[Fns];
172
173   public:
174     Dev();
175
176     bool empty() const { return !_fns[0]; }
177     void add_fn(Pci_dev *f);
178     void sort_fns();
179
180     Pci_dev *fn(unsigned f) const { return _fns[f]; }
181     void fn(unsigned f, Pci_dev *fn) { _fns[f] = fn; }
182     bool cmp(Pci_dev const *od) const
183     {
184       if (empty())
185         return false;
186
187       return _fns[0]->is_same_device(od);
188     }
189   };
190
191   class Bus
192   {
193   public:
194     enum { Devs = 32 };
195
196   private:
197     Dev _devs[Devs];
198
199   public:
200     Dev const *dev(unsigned slot) const { return &_devs[slot]; }
201     Dev *dev(unsigned slot) { return &_devs[slot]; }
202
203     void add_fn(Pci_dev *d, int slot = -1);
204   };
205
206   Pci_bridge() : _free_dev(0), _primary(0), _secondary(0), _subordinate(0) {}
207
208 protected:
209   Bus _bus;
210   unsigned _free_dev;
211   union
212   {
213     struct
214     {
215       l4_uint32_t _primary:8;
216       l4_uint32_t _secondary:8;
217       l4_uint32_t _subordinate:8;
218       l4_uint32_t _lat:8;
219     };
220     l4_uint32_t _bus_config;
221   };
222
223 public:
224
225   void primary(unsigned char v) { _primary = v; }
226   void secondary(unsigned char v) { _secondary = v; }
227   void subordinate(unsigned char v) { _subordinate = v; }
228   bool child_dev(unsigned bus, unsigned char dev, unsigned char fn, Pci_dev **rd);
229   void add_child(Device *d);
230   void add_child_fixed(Device *d, Pci_dev *vp, unsigned dn, unsigned fn);
231
232   Pci_bridge *find_bridge(unsigned bus);
233   void setup_bus();
234   void finalize_setup();
235
236 };
237
238 }
239