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)
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.
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.
26 void operator = (Pci_dev const &);
27 Pci_dev(Pci_dev const &);
30 typedef Hw::Pci::Cfg_width Cfg_width;
35 unsigned char trigger;
36 unsigned char polarity;
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;
52 * \brief A basic really virtualized PCI device.
54 class Pci_virtual_dev : public Pci_dev, public Dev_feature
59 l4_uint32_t vendor_device;
62 l4_uint32_t class_rev;
67 } __attribute__((packed));
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; }
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; }
76 ~Pci_virtual_dev() = 0;
80 void set_host(Device *d) { _host = d; }
81 Device *host() const { return _host; }
91 Pci_virtual_dev::~Pci_virtual_dev()
97 * \brief A virtual PCI proxy for a real PCI device.
99 class Pci_proxy_dev : public Pci_dev, public virtual Dev_feature
103 Pci_proxy_dev(Hw::Pci::If *hwf);
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; }
111 int bridge_cfg_write(unsigned, l4_uint32_t, int, l4_uint32_t, Cfg_width)
112 { return -L4_ENODEV; }
114 l4_uint32_t read_bar(int bar);
115 void write_bar(int bar, l4_uint32_t v);
117 l4_uint32_t read_rom() const { return _rom; }
118 void write_rom(l4_uint32_t v);
120 int vbus_dispatch(l4_umword_t, l4_uint32_t, L4::Ipc_iostream &)
121 { return -L4_ENOSYS; }
123 Hw::Pci::If *hwf() const { return _hwf; }
126 bool is_same_device(Pci_dev const *o) const
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));
134 bool match_hw_feature(const Hw::Dev_feature *f) const
135 { return f == _hwf; }
137 int dispatch(l4_umword_t, l4_uint32_t, L4::Ipc_iostream&)
138 { return -L4_ENOSYS; }
140 void set_host(Device *d) { _host = d; }
141 Device *host() const { return _host; }
147 l4_uint32_t _vbars[6];
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.
159 class Pci_bridge : public Device
173 bool empty() const { return !_fns[0]; }
174 void add_fn(Pci_dev *f);
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
184 return _fns[0]->is_same_device(od);
197 Dev const *dev(unsigned slot) const { return &_devs[slot]; }
198 Dev *dev(unsigned slot) { return &_devs[slot]; }
200 void add_fn(Pci_dev *d, int slot = -1);
203 Pci_bridge() : _free_dev(0), _primary(0), _secondary(0), _subordinate(0) {}
212 l4_uint32_t _primary:8;
213 l4_uint32_t _secondary:8;
214 l4_uint32_t _subordinate:8;
217 l4_uint32_t _bus_config;
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);
229 Pci_bridge *find_bridge(unsigned bus);
231 void finalize_setup();