]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/io/server/src/vpci.h
bab65502eb0d117e7fbf93c3091e22eaa21b94e7
[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 protected:
81   unsigned char *_h;
82   unsigned _h_len;
83
84 };
85
86 inline
87 Pci_virtual_dev::~Pci_virtual_dev()
88 {}
89
90
91
92 /**
93  * \brief A virtual PCI proxy for a real PCI device.
94  */
95 class Pci_proxy_dev : public Pci_dev, public virtual Dev_feature
96 {
97 public:
98
99   Pci_proxy_dev(Hw::Pci::If *hwf);
100
101   int cfg_read(int reg, l4_uint32_t *v, Cfg_width);
102   int cfg_write(int reg, l4_uint32_t v, Cfg_width);
103   int irq_enable(Irq_info *irq);
104   int bridge_cfg_read(unsigned, l4_uint32_t, int, l4_uint32_t *, Cfg_width)
105   { return -L4_ENODEV; }
106
107   int bridge_cfg_write(unsigned, l4_uint32_t, int, l4_uint32_t, Cfg_width)
108   { return -L4_ENODEV; }
109
110   l4_uint32_t read_bar(int bar);
111   void write_bar(int bar, l4_uint32_t v);
112
113   l4_uint32_t read_rom() const { return _rom; }
114   void write_rom(l4_uint32_t v);
115
116   int vbus_dispatch(l4_umword_t, l4_uint32_t, L4::Ipc_iostream &)
117   { return -L4_ENOSYS; }
118
119   Hw::Pci::If *hwf() const { return _hwf; }
120
121   void dump() const;
122   bool is_same_device(Pci_dev const *o) const
123   {
124     if (Pci_proxy_dev const *op = dynamic_cast<Pci_proxy_dev const *>(o))
125       return (hwf()->bus_nr() == op->hwf()->bus_nr())
126              && ((hwf()->host()->adr() >> 16) == (op->hwf()->host()->adr() >> 16));
127     return false;
128   }
129
130   bool match_hw_feature(const Hw::Dev_feature *f) const
131   { return f == _hwf; }
132
133   int dispatch(l4_umword_t, l4_uint32_t, L4::Ipc_iostream&)
134   { return -L4_ENOSYS; }
135
136 private:
137   Hw::Pci::If *_hwf;
138
139   l4_uint32_t _vbars[6];
140   l4_uint32_t _rom;
141 };
142
143
144
145 /**
146  * \brief a basic virtual PCI bridge.
147  * This class is the base for virtual Host-to-PCI bridges,
148  * for virtual PCI-to-PCI bridges, and also for this such as
149  * virtual PCI-to-Cardbus brdiges.
150  */
151 class Pci_bridge : public Device
152 {
153 public:
154   class Dev
155   {
156   public:
157     enum { Fns = 8 };
158
159   private:
160     Pci_dev *_fns[Fns];
161
162   public:
163     Dev();
164
165     bool empty() const { return !_fns[0]; }
166     void add_fn(Pci_dev *f);
167     void sort_fns();
168
169     Pci_dev *fn(unsigned f) const { return _fns[f]; }
170     void fn(unsigned f, Pci_dev *fn) { _fns[f] = fn; }
171     bool cmp(Pci_dev const *od) const
172     {
173       if (empty())
174         return false;
175
176       return _fns[0]->is_same_device(od);
177     }
178   };
179
180   class Bus
181   {
182   public:
183     enum { Devs = 32 };
184
185   private:
186     Dev _devs[Devs];
187
188   public:
189     Dev const *dev(unsigned slot) const { return &_devs[slot]; }
190     Dev *dev(unsigned slot) { return &_devs[slot]; }
191
192     void add_fn(Pci_dev *d, int slot = -1);
193   };
194
195   Pci_bridge() : _free_dev(0), _primary(0), _secondary(0), _subordinate(0) {}
196
197 protected:
198   Bus _bus;
199   unsigned _free_dev;
200   union
201   {
202     struct
203     {
204       l4_uint32_t _primary:8;
205       l4_uint32_t _secondary:8;
206       l4_uint32_t _subordinate:8;
207       l4_uint32_t _lat:8;
208     };
209     l4_uint32_t _bus_config;
210   };
211
212 public:
213
214   void primary(unsigned char v) { _primary = v; }
215   void secondary(unsigned char v) { _secondary = v; }
216   void subordinate(unsigned char v) { _subordinate = v; }
217   bool child_dev(unsigned bus, unsigned char dev, unsigned char fn, Pci_dev **rd);
218   void add_child(Device *d);
219   void add_child_fixed(Device *d, Pci_dev *vp, unsigned dn, unsigned fn);
220
221   Pci_bridge *find_bridge(unsigned bus);
222   void setup_bus();
223   void finalize_setup();
224
225 };
226
227 }
228