1 /*
2  * Copyright (c) 2021 Travis Geiseblrecht
3  *
4  * Use of this source code is governed by a MIT-style
5  * license that can be found in the LICENSE file or at
6  * https://opensource.org/licenses/MIT
7  */
8 #pragma once
9 
10 #include <sys/types.h>
11 #include <dev/bus/pci.h>
12 #include <lk/cpp.h>
13 
14 #include "device.h"
15 
16 namespace pci {
17 
18 class bus;
19 
20 // bridge device, holds a list of busses that it is responsible for
21 class bridge : public device {
22 protected:
23     // created via the probe() call
24     bridge(pci_location_t loc, bus *bus);
25 public:
26     ~bridge() override;
27 
28     DISALLOW_COPY_ASSIGN_AND_MOVE(bridge);
29 
30     static status_t probe(pci_location_t loc, bus *parent_bus, bridge **out_bridge);
31 
32     // called when a sub bridge is assigned a new secondary bus.
33     // if this extends our subordinate bus, recursively call the parent bridge.
34     void extend_subordinate_range(uint8_t new_secondary_bus);
35 
36     void assign_bus_numbers(uint8_t primary, uint8_t secondary, uint8_t subordinate_bus);
37 
add_bus(bus * b)38     void add_bus(bus *b) { secondary_bus_ = b; }
39 
40     status_t compute_bar_sizes(bar_sizes *sizes) override;
41     status_t get_bar_alloc_requests(list_node *bar_alloc_requests) override;
42     status_t assign_resource(bar_alloc_request *request, uint64_t address) override;
43     status_t assign_child_resources() override;
44 
45     void dump(size_t indent = 0) override;
46 
47     // config accessors
primary_bus()48     uint8_t primary_bus() const { return config_.type1.primary_bus; }
secondary_bus()49     uint8_t secondary_bus() const { return config_.type1.secondary_bus; }
subordinate_bus()50     uint8_t subordinate_bus() const { return config_.type1.subordinate_bus; }
51 
52     template <typename T>
53     struct range {
54         T base;
55         T limit;
56     };
57 
58     range<uint32_t> io_range();
59     range<uint32_t> mem_range();
60     range<uint64_t> prefetch_range();
61 
62 private:
63     status_t compute_bar_sizes_no_local_bar(bar_sizes *sizes);
64 
65     bus *secondary_bus_ = nullptr;
66 };
67 
68 } // pci
69 
70