1/*
2 * Copyright 2005-2008, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3 * Copyright 2003, Marcus Overhagen. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include <device_manager.h>
10#include <PCI.h>
11#include <drivers/ACPI.h>
12#include <drivers/bus/FDT.h>
13
14#include <string.h>
15
16#include <AutoDeleterDrivers.h>
17
18#include "pci_private.h"
19#include "pci.h"
20
21#define CHECK_RET(err) {status_t _err = (err); if (_err < B_OK) return _err;}
22
23
24// name of PCI root module
25#define PCI_ROOT_MODULE_NAME "bus_managers/pci/root/driver_v1"
26
27
28static status_t
29pci_root_register_device(device_node* parent)
30{
31// XXX how do we handle this for PPC?
32// I/O port for PCI config space address
33#define PCI_CONFIG_ADDRESS 0xcf8
34
35	io_resource resources[2] = {
36		{B_IO_PORT, PCI_CONFIG_ADDRESS, 8},
37		{}
38	};
39	device_attr attrs[] = {
40		{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "PCI"}},
41		{B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_KEEP_DRIVER_LOADED}},
42		{}
43	};
44
45	return gDeviceManager->register_node(parent, PCI_ROOT_MODULE_NAME, attrs,
46		resources, NULL);
47}
48
49
50static void
51pci_root_traverse(device_node* node, PCIBus* bus)
52{
53	for (PCIDev* dev = bus->child; dev != NULL; dev = dev->next) {
54		const pci_info& info = dev->info;
55
56		device_attr attrs[] = {
57			// info about device
58			{B_DEVICE_BUS, B_STRING_TYPE, {.string = "pci"}},
59
60			// location on PCI bus
61			{B_PCI_DEVICE_DOMAIN, B_UINT8_TYPE, {.ui8 = dev->domain}},
62			{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {.ui8 = dev->bus}},
63			{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {.ui8 = info.device}},
64			{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {.ui8 = info.function}},
65
66			// info about the device
67			{B_DEVICE_VENDOR_ID, B_UINT16_TYPE, {.ui16 = info.vendor_id}},
68			{B_DEVICE_ID, B_UINT16_TYPE, {.ui16 = info.device_id}},
69
70			{B_DEVICE_TYPE, B_UINT16_TYPE, {.ui16 = info.class_base}},
71			{B_DEVICE_SUB_TYPE, B_UINT16_TYPE, {.ui16 = info.class_sub}},
72			{B_DEVICE_INTERFACE, B_UINT16_TYPE, {.ui16 = info.class_api}},
73
74			{B_DEVICE_FLAGS, B_UINT32_TYPE, {.ui32 = B_FIND_CHILD_ON_DEMAND}},
75			{}
76		};
77
78		gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs, NULL, NULL);
79
80		if (dev->child != NULL)
81			pci_root_traverse(node, dev->child);
82	}
83}
84
85
86static status_t
87pci_root_register_child_devices(void* cookie)
88{
89	domain_data* domainData = (domain_data*)cookie;
90
91	pci_root_traverse(domainData->root_node, domainData->bus);
92
93	return B_OK;
94}
95
96
97static status_t
98pci_root_init(device_node* node, void** _cookie)
99{
100	DeviceNodePutter<&gDeviceManager> pciHostNode(gDeviceManager->get_parent_node(node));
101
102	pci_controller_module_info* pciHostModule;
103	void* pciHostDev;
104	CHECK_RET(gDeviceManager->get_driver(pciHostNode.Get(), (driver_module_info**)&pciHostModule, &pciHostDev));
105
106	module_info *module;
107	status_t res = get_module(B_PCI_MODULE_NAME, &module);
108	if (res < B_OK)
109		return res;
110
111	domain_data* domainData = NULL;
112	CHECK_RET(gPCI->AddController(pciHostModule, pciHostDev, node, &domainData));
113
114	*_cookie = domainData;
115
116	return B_OK;
117}
118
119
120static int32
121pci_root_std_ops(int32 op, ...)
122{
123	switch (op) {
124		case B_MODULE_INIT:
125			return B_OK;
126
127		case B_MODULE_UNINIT:
128			return B_OK;
129	}
130
131	return B_BAD_VALUE;
132}
133
134
135struct pci_root_module_info gPCIRootModule = {
136	{
137		{
138			PCI_ROOT_MODULE_NAME,
139			0,
140			pci_root_std_ops
141		},
142
143		NULL,
144		pci_root_register_device,
145		pci_root_init,
146		NULL,	// uninit
147		pci_root_register_child_devices,
148		NULL,	// rescan devices
149		NULL,	// device removed
150	},
151
152	&pci_read_config,
153	&pci_write_config
154};
155