2 * (c) 2010 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.
11 #include "vpci_pci_bridge.h"
12 #include "vbus_factory.h"
17 * \brief A virtual Host-to-PCI bridge.
19 class Pci_vroot : public Pci_bridge, public Dev_feature
25 int dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc_iostream &ios);
29 char const *hid() const
32 void set_host(Device *d) { _host = d; }
33 Device *host() const { return _host; }
39 int cfg_read(L4::Ipc_iostream &ios);
40 int cfg_write(L4::Ipc_iostream &ios);
41 int irq_enable(L4::Ipc_iostream &ios);
42 bool match_hw_feature(const Hw::Dev_feature*) const
46 // -----------------------------------------------------------------------
47 // Virtual PCI root bridge with identity mapping of phys devices
48 // -----------------------------------------------------------------------
51 class Pci_vroot_id : public Pci_vroot
54 void add_child(Device *d);
60 // -------------------------------------------------------------------
61 // Virtual PCI Root bridge
62 // -------------------------------------------------------------------
64 Pci_vroot::Pci_vroot() : Pci_bridge()
71 Pci_vroot::cfg_read(L4::Ipc_iostream &ios)
76 l4_uint32_t value = 0;
79 ios >> bus >> devfn >> reg >> width;
80 value = ~0U >> (32 - width);
82 //printf("cfg read: %02x:%02x.%1x: reg=%x w=%d\n", bus, devfn >> 16, devfn & 0xffff, reg, width);
84 if ((devfn >> 16) >= 32 || (devfn & 0xffff) >= 8)
91 child_dev(bus, (devfn >> 16), (devfn & 0xffff), &d);
99 int res = d->cfg_read(reg, &value, Hw::Pci::cfg_w_to_o(width));
104 //printf(" value=%x\n", value);
109 Pci_vroot::irq_enable(L4::Ipc_iostream &ios)
116 // printf("irq enable: %02x:%02x.%1x: pin=%d\n", bus, devfn >> 16, devfn & 0xffff, pin);
118 if ((devfn >> 16) >= 32 || (devfn & 0xffff) >= 8)
125 child_dev(bus, (devfn >> 16), (devfn & 0xffff), &d);
126 // printf("dev = %p\n", d);
133 Pci_dev::Irq_info info;
134 int res = d->irq_enable(&info);
141 // printf(" irq = %d\n", info.irq);
142 ios << info.irq << info.trigger << info.polarity;
147 Pci_vroot::cfg_write(L4::Ipc_iostream &ios)
155 ios >> bus >> devfn >> reg >> value >> width;
156 // printf("cfg write: %02x:%02x.%1x: reg=%x w=%x v=%08x\n", bus, devfn >> 16, devfn & 0xffff, reg, width, value);
158 if ((devfn >> 16) >= 32 || (devfn & 0xffff) >= 8)
162 child_dev(bus, (devfn >> 16), (devfn & 0xffff), &d);
167 return d->cfg_write(reg, value, Hw::Pci::cfg_w_to_o(width));
171 Pci_vroot::dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc_iostream &ios)
175 case 0: return cfg_read(ios);
176 case 1: return cfg_write(ios);
177 case 2: return irq_enable(ios);
178 default: return -L4_ENOSYS;
184 Pci_vroot_id::add_child(Device *d)
186 Pci_dev *vp = d->find_feature<Pci_dev>();
188 // hm, also here, drom non PCI devices
192 if (Pci_proxy_dev *proxy = dynamic_cast<Pci_proxy_dev*>(vp))
194 Pci_pci_bridge_basic const *hw_br
195 = dynamic_cast<Pci_pci_bridge_basic const *>(proxy->hwf()->bus());
197 l4_uint32_t hwadr = proxy->hwf()->host()->adr();
198 // printf("VPCI: add proxy PCI device %p (hwbr=%p)\n", proxy, hw_br);
199 unsigned dn = (hwadr >> 16) & (Bus::Devs-1);
200 unsigned fn = hwadr & (Dev::Fns-1);
204 // MUST be a device on the root PCI bus
205 _bus.dev(dn)->fn(fn, vp);
206 Device::add_child(d);
210 Pci_bridge *sw_br = find_bridge(hw_br->num);
213 Pci_to_pci_bridge *b = new Pci_to_pci_bridge();
215 sw_br->primary(hw_br->pri);
216 sw_br->secondary(hw_br->num);
217 sw_br->subordinate(hw_br->subordinate);
219 unsigned dn = (hw_br->host()->adr() >> 16) & (Bus::Devs-1);
220 unsigned fn = hw_br->host()->adr() & (Dev::Fns-1);
221 _bus.dev(dn)->fn(fn, b);
222 Device::add_child(b);
225 sw_br->add_child_fixed(d, vp, dn, fn);
231 Device::add_child(d);
237 static Dev_factory_t<Pci_vroot> __pci_root_factory("PCI_bus");
238 static Dev_factory_t<Pci_vroot_id> __pci_root_id_factory("PCI_bus_ident");