vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / kernel / bus_managers / pci / arch / ppc / openfirmware / grackle.cpp
blobb0a98f16d87334f774e05591102dc15e732a0542
1 /*
2 * Copyright 2010 Andreas Färber <andreas.faerber@web.de>
3 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
4 * All rights reserved. Distributed under the terms of the MIT License.
5 */
6 /*-
7 * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <KernelExport.h>
35 #include <platform/openfirmware/devices.h>
36 #include <platform/openfirmware/openfirmware.h>
37 #include <platform/openfirmware/pci.h>
39 #include "pci_controller.h"
40 #include "pci_io.h"
41 #include "pci_openfirmware_priv.h"
44 //#define TRACE_GRACKLE
46 #ifdef TRACE_GRACKLE
47 #define TRACE(fmt...) dprintf(fmt)
48 #else
49 #define TRACE(fmt...) ;
50 #endif
53 struct grackle_range {
54 uint32_t pci_hi;
55 uint32_t pci_mid;
56 uint32_t pci_lo;
57 uint32_t host;
58 uint32_t size_hi;
59 uint32_t size_lo;
63 struct grackle_host_bridge {
64 int device_node;
65 addr_t address_registers;
66 addr_t data_registers;
67 uint32 bus;
68 struct grackle_range ranges[6];
69 int range_count;
73 #define out8rb(address, value) ppc_out8((vuint8*)(address), value)
74 #define out16rb(address, value) ppc_out16_reverse((vuint16*)(address), value)
75 #define out32rb(address, value) ppc_out32_reverse((vuint32*)(address), value)
76 #define in8rb(address) ppc_in8((const vuint8*)(address))
77 #define in16rb(address) ppc_in16_reverse((const vuint16*)(address))
78 #define in32rb(address) ppc_in32_reverse((const vuint32*)(address))
81 static status_t
82 grackle_read_pci_config(void *cookie, uint8 bus, uint8 device, uint8 function,
83 uint16 offset, uint8 size, uint32 *value)
85 grackle_host_bridge *bridge = (grackle_host_bridge*)cookie;
86 TRACE("grackle_read_pci_config(bus=%u, dev=%u, func=%u, offset=%u, "
87 "size=%u)\n", (int)bus, (int)device, (int)function, (int)offset,
88 (int)size);
90 if (offset > 0xff)
91 return B_BAD_VALUE;
93 out32rb(bridge->address_registers, (1 << 31)
94 | (bus << 16) | ((device & 0x1f) << 11) | ((function & 0x7) << 8)
95 | (offset & 0xfc));
97 addr_t dataAddress = bridge->data_registers + (offset & 0x3);
98 switch (size) {
99 case 1:
100 *value = in8rb(dataAddress);
101 break;
102 case 2:
103 *value = in16rb(dataAddress);
104 break;
105 case 4:
106 *value = in32rb(dataAddress);
107 break;
108 default:
109 *value = 0xffffffff;
110 break;
113 out32rb(bridge->address_registers, 0);
115 return B_OK;
119 static status_t
120 grackle_write_pci_config(void *cookie, uint8 bus, uint8 device, uint8 function,
121 uint16 offset, uint8 size, uint32 value)
123 grackle_host_bridge *bridge = (grackle_host_bridge*)cookie;
124 TRACE("grackle_write_pci_config(bus=%u, dev=%u, func=%u, offset=%u, "
125 "size=%u, value=%lu)\n", (int)bus, (int)device, (int)function,
126 (int)offset, (int)size, value);
128 if (offset > 0xff)
129 return B_BAD_VALUE;
131 out32rb(bridge->address_registers, (1 << 31)
132 | (bus << 16) | ((device & 0x1f) << 11) | ((function & 0x7) << 8)
133 | (offset & 0xfc));
135 addr_t dataAddress = bridge->data_registers + (offset & 0x3);
136 switch (size) {
137 case 1:
138 out8rb(dataAddress, (uint8)value);
139 break;
140 case 2:
141 out16rb(dataAddress, (uint16)value);
142 break;
143 case 4:
144 out32rb(dataAddress, value);
145 break;
148 out32rb(bridge->address_registers, 0);
150 return B_OK;
154 static status_t
155 grackle_get_max_bus_devices(void *cookie, int32 *count)
157 *count = 32;
158 return B_OK;
162 static status_t
163 grackle_read_pci_irq(void *cookie, uint8 bus, uint8 device, uint8 function,
164 uint8 pin, uint8 *irq)
166 return B_ERROR;
170 static status_t
171 grackle_write_pci_irq(void *cookie, uint8 bus, uint8 device, uint8 function,
172 uint8 pin, uint8 irq)
174 return B_ERROR;
178 static pci_controller sGracklePCIController = {
179 grackle_read_pci_config,
180 grackle_write_pci_config,
181 grackle_get_max_bus_devices,
182 grackle_read_pci_irq,
183 grackle_write_pci_irq,
187 status_t
188 ppc_openfirmware_probe_grackle(int deviceNode,
189 const StringArrayPropertyValue &compatibleValue)
191 if (!compatibleValue.ContainsElement("grackle"))
192 return B_ERROR;
194 uint32_t busrange[2];
195 if (of_getprop(deviceNode, "bus-range", busrange, sizeof(busrange)) != 8)
196 return B_ERROR;
198 grackle_host_bridge *bridge =
199 (grackle_host_bridge*)malloc(sizeof(grackle_host_bridge));
200 if (bridge == NULL)
201 return B_NO_MEMORY;
203 bridge->device_node = deviceNode;
204 bridge->address_registers = 0xfec00000;
205 bridge->data_registers = 0xfee00000;
206 bridge->bus = busrange[0];
208 memset(bridge->ranges, 0, sizeof(bridge->ranges));
209 int bytesRead = of_getprop(deviceNode, "ranges", bridge->ranges,
210 sizeof(bridge->ranges));
211 if (bytesRead < 0) {
212 dprintf("ppc_openfirmware_probe_grackle: Could not get ranges.\n");
213 free(bridge);
214 return B_ERROR;
216 bridge->range_count = bytesRead / sizeof(grackle_range);
218 grackle_range *ioRange = NULL;
219 grackle_range *memoryRanges[2];
220 int memoryRangeCount = 0;
222 for (int i = 0; i < bridge->range_count; i++) {
223 grackle_range *range = bridge->ranges + i;
224 switch (range->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
225 case OFW_PCI_PHYS_HI_SPACE_CONFIG:
226 break;
227 case OFW_PCI_PHYS_HI_SPACE_IO:
228 ioRange = range;
229 break;
230 case OFW_PCI_PHYS_HI_SPACE_MEM32:
231 memoryRanges[memoryRangeCount++] = range;
232 break;
233 case OFW_PCI_PHYS_HI_SPACE_MEM64:
234 break;
238 if (ioRange == NULL) {
239 dprintf("ppc_openfirmware_probe_grackle: Can't find io range.\n");
240 free(bridge);
241 return B_ERROR;
244 if (memoryRangeCount == 0) {
245 dprintf("ppc_openfirmware_probe_grackle: Can't find mem ranges.\n");
246 free(bridge);
247 return B_ERROR;
250 status_t error = pci_controller_add(&sGracklePCIController, bridge);
251 if (error != B_OK)
252 free(bridge);
253 return error;