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