1481c8841SAxel Dörfler /*
29a063f05SAxel Dörfler * Copyright 2008-2010, Axel Dörfler, axeld@pinc-software.de.
3481c8841SAxel Dörfler * Copyright 2004-2006, Rudolf Cornelissen. All rights reserved.
4481c8841SAxel Dörfler *
5481c8841SAxel Dörfler * Distributed under the terms of the MIT License.
6481c8841SAxel Dörfler */
7481c8841SAxel Dörfler
8481c8841SAxel Dörfler // TODO: rethink the AGP interface for more than one bridge/device!
9481c8841SAxel Dörfler // (should be done with the new driver API then)
10481c8841SAxel Dörfler
11481c8841SAxel Dörfler /*
12481c8841SAxel Dörfler Notes:
13481c8841SAxel Dörfler - currently we just setup all found devices with AGP interface to the same
14481c8841SAxel Dörfler highest common mode, we don't distinquish different AGP busses.
15481c8841SAxel Dörfler TODO: it might be a better idea to just setup one instead.
16481c8841SAxel Dörfler
17481c8841SAxel Dörfler - AGP3 defines 'asynchronous request size' and 'calibration cycle' fields
18481c8841SAxel Dörfler in the status and command registers. Currently programming zero's which will
19481c8841SAxel Dörfler make it work, although further optimisation is possible.
20481c8841SAxel Dörfler
21481c8841SAxel Dörfler - AGP3.5 also defines isochronous transfers which are not implemented here:
22481c8841SAxel Dörfler the hardware keeps them disabled by default.
23481c8841SAxel Dörfler */
24481c8841SAxel Dörfler
25481c8841SAxel Dörfler
26481c8841SAxel Dörfler #include <AGP.h>
27481c8841SAxel Dörfler
28481c8841SAxel Dörfler #include <stdlib.h>
29481c8841SAxel Dörfler
30481c8841SAxel Dörfler #include <KernelExport.h>
31481c8841SAxel Dörfler #include <PCI.h>
32481c8841SAxel Dörfler
33481c8841SAxel Dörfler #include <util/OpenHashTable.h>
34481c8841SAxel Dörfler #include <kernel/lock.h>
35e50cf876SIngo Weinhold #include <vm/vm_page.h>
36e50cf876SIngo Weinhold #include <vm/vm_types.h>
37481c8841SAxel Dörfler
38481c8841SAxel Dörfler #include <lock.h>
39481c8841SAxel Dörfler
40481c8841SAxel Dörfler
41481c8841SAxel Dörfler #define TRACE_AGP
42481c8841SAxel Dörfler #ifdef TRACE_AGP
43481c8841SAxel Dörfler # define TRACE(x...) dprintf("\33[36mAGP:\33[0m " x)
44481c8841SAxel Dörfler #else
45481c8841SAxel Dörfler # define TRACE(x...) ;
46481c8841SAxel Dörfler #endif
477d5632a0SJérôme Duval #define ERROR(x...) dprintf("\33[36mAGP:\33[0m " x)
48481c8841SAxel Dörfler
49481c8841SAxel Dörfler
50481c8841SAxel Dörfler #define MAX_DEVICES 8
51481c8841SAxel Dörfler
52481c8841SAxel Dörfler #define AGP_ID(address) (address)
53481c8841SAxel Dörfler #define AGP_STATUS(address) (address + 4)
54481c8841SAxel Dörfler #define AGP_COMMAND(address) (address + 8)
55481c8841SAxel Dörfler
56481c8841SAxel Dörfler /* read and write to PCI config space */
57481c8841SAxel Dörfler #define get_pci_config(info, offset, size) \
58481c8841SAxel Dörfler (sPCI->read_pci_config((info).bus, (info).device, (info).function, \
59481c8841SAxel Dörfler (offset), (size)))
60481c8841SAxel Dörfler #define set_pci_config(info, offset, size, value) \
61481c8841SAxel Dörfler (sPCI->write_pci_config((info).bus, (info).device, (info).function, \
62481c8841SAxel Dörfler (offset), (size), (value)))
63481c8841SAxel Dörfler
64481c8841SAxel Dörfler #define RESERVED_APERTURE 0x80000000
65481c8841SAxel Dörfler #define ALLOCATED_APERTURE 0x40000000
66481c8841SAxel Dörfler #define BIND_APERTURE 0x20000000
67481c8841SAxel Dörfler #define APERTURE_PUBLIC_FLAGS_MASK 0x0000ffff
68481c8841SAxel Dörfler
695147963dSStephan Aßmus struct aperture_memory {
70481c8841SAxel Dörfler aperture_memory *next;
715147963dSStephan Aßmus aperture_memory *hash_link;
72481c8841SAxel Dörfler addr_t base;
73481c8841SAxel Dörfler size_t size;
74481c8841SAxel Dörfler uint32 flags;
7521c87a5dSJérôme Duval #if !defined(GART_TEST)
76481c8841SAxel Dörfler union {
77481c8841SAxel Dörfler vm_page **pages;
78481c8841SAxel Dörfler vm_page *page;
79481c8841SAxel Dörfler };
803cd20943SIngo Weinhold #ifdef DEBUG_PAGE_ACCESS
813cd20943SIngo Weinhold thread_id allocating_thread;
823cd20943SIngo Weinhold #endif
83481c8841SAxel Dörfler #else
84481c8841SAxel Dörfler area_id area;
85481c8841SAxel Dörfler #endif
86481c8841SAxel Dörfler };
87481c8841SAxel Dörfler
88481c8841SAxel Dörfler class Aperture;
89481c8841SAxel Dörfler
90481c8841SAxel Dörfler class MemoryHashDefinition {
91481c8841SAxel Dörfler public:
92481c8841SAxel Dörfler typedef addr_t KeyType;
93481c8841SAxel Dörfler typedef aperture_memory ValueType;
94481c8841SAxel Dörfler
MemoryHashDefinition(aperture_info & info)95481c8841SAxel Dörfler MemoryHashDefinition(aperture_info &info) : fInfo(info) {}
96481c8841SAxel Dörfler
HashKey(const KeyType & base) const97481c8841SAxel Dörfler size_t HashKey(const KeyType &base) const
98481c8841SAxel Dörfler { return (base - fInfo.base) / B_PAGE_SIZE; }
Hash(aperture_memory * memory) const99481c8841SAxel Dörfler size_t Hash(aperture_memory *memory) const
100481c8841SAxel Dörfler { return (memory->base - fInfo.base) / B_PAGE_SIZE; }
Compare(const KeyType & base,aperture_memory * memory) const101481c8841SAxel Dörfler bool Compare(const KeyType &base, aperture_memory *memory) const
102481c8841SAxel Dörfler { return base == memory->base; }
GetLink(aperture_memory * memory) const1035147963dSStephan Aßmus aperture_memory *&GetLink(aperture_memory *memory) const
1045147963dSStephan Aßmus { return memory->hash_link; }
105481c8841SAxel Dörfler
106481c8841SAxel Dörfler private:
107481c8841SAxel Dörfler aperture_info &fInfo;
108481c8841SAxel Dörfler };
109481c8841SAxel Dörfler
1105147963dSStephan Aßmus typedef BOpenHashTable<MemoryHashDefinition> MemoryHashTable;
111481c8841SAxel Dörfler
112481c8841SAxel Dörfler struct agp_device_info {
113481c8841SAxel Dörfler uint8 address; /* location of AGP interface in PCI capabilities */
114481c8841SAxel Dörfler agp_info info;
115481c8841SAxel Dörfler };
116481c8841SAxel Dörfler
1175147963dSStephan Aßmus class Aperture {
118481c8841SAxel Dörfler public:
119481c8841SAxel Dörfler Aperture(agp_gart_bus_module_info *module, void *aperture);
120481c8841SAxel Dörfler ~Aperture();
121481c8841SAxel Dörfler
InitCheck() const122481c8841SAxel Dörfler status_t InitCheck() const { return fLock.sem >= B_OK ? B_OK : fLock.sem; }
123481c8841SAxel Dörfler
124481c8841SAxel Dörfler void DeleteMemory(aperture_memory *memory);
125481c8841SAxel Dörfler aperture_memory *CreateMemory(size_t size, size_t alignment, uint32 flags);
126481c8841SAxel Dörfler
127481c8841SAxel Dörfler status_t AllocateMemory(aperture_memory *memory, uint32 flags);
128481c8841SAxel Dörfler
129481c8841SAxel Dörfler status_t UnbindMemory(aperture_memory *memory);
130103d05f3SAxel Dörfler status_t BindMemory(aperture_memory *memory, addr_t base, size_t size);
131481c8841SAxel Dörfler
132481c8841SAxel Dörfler status_t GetInfo(aperture_info *info);
133481c8841SAxel Dörfler
GetMemory(addr_t base)134481c8841SAxel Dörfler aperture_memory *GetMemory(addr_t base) { return fHashTable.Lookup(base); }
135481c8841SAxel Dörfler
Base() const136481c8841SAxel Dörfler addr_t Base() const { return fInfo.base; }
Size() const137481c8841SAxel Dörfler addr_t Size() const { return fInfo.size; }
ID() const138481c8841SAxel Dörfler int32 ID() const { return fID; }
Lock()139481c8841SAxel Dörfler struct lock &Lock() { return fLock; }
140481c8841SAxel Dörfler
141481c8841SAxel Dörfler private:
1427e6d2343SAxel Dörfler bool _AdaptToReserved(addr_t &base, size_t &size, int32 *_offset = NULL);
143481c8841SAxel Dörfler void _Free(aperture_memory *memory);
144481c8841SAxel Dörfler void _Remove(aperture_memory *memory);
145481c8841SAxel Dörfler status_t _Insert(aperture_memory *memory, size_t size, size_t alignment,
146481c8841SAxel Dörfler uint32 flags);
147481c8841SAxel Dörfler
148481c8841SAxel Dörfler struct lock fLock;
149481c8841SAxel Dörfler agp_gart_bus_module_info *fModule;
150481c8841SAxel Dörfler int32 fID;
151481c8841SAxel Dörfler aperture_info fInfo;
152481c8841SAxel Dörfler MemoryHashTable fHashTable;
153481c8841SAxel Dörfler aperture_memory *fFirstMemory;
154481c8841SAxel Dörfler void *fPrivateAperture;
1555147963dSStephan Aßmus
1565147963dSStephan Aßmus public:
1575147963dSStephan Aßmus Aperture *fNext;
158481c8841SAxel Dörfler };
159481c8841SAxel Dörfler
160481c8841SAxel Dörfler class ApertureHashDefinition {
161481c8841SAxel Dörfler public:
162481c8841SAxel Dörfler typedef int32 KeyType;
163481c8841SAxel Dörfler typedef Aperture ValueType;
164481c8841SAxel Dörfler
HashKey(const KeyType & id) const165481c8841SAxel Dörfler size_t HashKey(const KeyType &id) const
166481c8841SAxel Dörfler { return id; }
Hash(Aperture * aperture) const167481c8841SAxel Dörfler size_t Hash(Aperture *aperture) const
168481c8841SAxel Dörfler { return aperture->ID(); }
Compare(const KeyType & id,Aperture * aperture) const169481c8841SAxel Dörfler bool Compare(const KeyType &id, Aperture *aperture) const
170481c8841SAxel Dörfler { return id == aperture->ID(); }
GetLink(Aperture * aperture) const1715147963dSStephan Aßmus Aperture *&GetLink(Aperture *aperture) const
1725147963dSStephan Aßmus { return aperture->fNext; }
173481c8841SAxel Dörfler };
174481c8841SAxel Dörfler
1755147963dSStephan Aßmus typedef BOpenHashTable<ApertureHashDefinition> ApertureHashTable;
176481c8841SAxel Dörfler
177481c8841SAxel Dörfler
178481c8841SAxel Dörfler static agp_device_info sDeviceInfos[MAX_DEVICES];
179481c8841SAxel Dörfler static uint32 sDeviceCount;
180481c8841SAxel Dörfler static pci_module_info *sPCI;
181481c8841SAxel Dörfler static int32 sAcquired;
182481c8841SAxel Dörfler static ApertureHashTable sApertureHashTable;
183481c8841SAxel Dörfler static int32 sNextApertureID;
184481c8841SAxel Dörfler static struct lock sLock;
185481c8841SAxel Dörfler
186481c8841SAxel Dörfler
187481c8841SAxel Dörfler // #pragma mark - private support functions
188481c8841SAxel Dörfler
189481c8841SAxel Dörfler
190481c8841SAxel Dörfler /*! Makes sure that all bits lower than the maximum supported rate is set. */
191481c8841SAxel Dörfler static uint32
fix_rate_support(uint32 command)192481c8841SAxel Dörfler fix_rate_support(uint32 command)
193481c8841SAxel Dörfler {
194481c8841SAxel Dörfler if ((command & AGP_3_MODE) != 0) {
195481c8841SAxel Dörfler if ((command & AGP_3_8x) != 0)
196481c8841SAxel Dörfler command |= AGP_3_4x;
197481c8841SAxel Dörfler
198481c8841SAxel Dörfler command &= ~AGP_RATE_MASK | AGP_3_8x | AGP_3_4x;
199481c8841SAxel Dörfler command |= AGP_SBA;
200481c8841SAxel Dörfler // SBA is required for AGP3
201481c8841SAxel Dörfler } else {
202481c8841SAxel Dörfler /* AGP 2.0 scheme applies */
203481c8841SAxel Dörfler if ((command & AGP_2_4x) != 0)
204481c8841SAxel Dörfler command |= AGP_2_2x;
205481c8841SAxel Dörfler if ((command & AGP_2_2x) != 0)
206481c8841SAxel Dörfler command |= AGP_2_1x;
207481c8841SAxel Dörfler }
208481c8841SAxel Dörfler
209481c8841SAxel Dörfler return command;
210481c8841SAxel Dörfler }
211481c8841SAxel Dörfler
212481c8841SAxel Dörfler
213481c8841SAxel Dörfler /*! Makes sure that only the highest rate bit is set. */
214481c8841SAxel Dörfler static uint32
fix_rate_command(uint32 command)215481c8841SAxel Dörfler fix_rate_command(uint32 command)
216481c8841SAxel Dörfler {
217481c8841SAxel Dörfler if ((command & AGP_3_MODE) != 0) {
218481c8841SAxel Dörfler if ((command & AGP_3_8x) != 0)
219481c8841SAxel Dörfler command &= ~AGP_3_4x;
220481c8841SAxel Dörfler } else {
221481c8841SAxel Dörfler /* AGP 2.0 scheme applies */
222481c8841SAxel Dörfler if ((command & AGP_2_4x) != 0)
223481c8841SAxel Dörfler command &= ~(AGP_2_2x | AGP_2_1x);
224481c8841SAxel Dörfler if ((command & AGP_2_2x) != 0)
225481c8841SAxel Dörfler command &= ~AGP_2_1x;
226481c8841SAxel Dörfler }
227481c8841SAxel Dörfler
228481c8841SAxel Dörfler return command;
229481c8841SAxel Dörfler }
230481c8841SAxel Dörfler
231481c8841SAxel Dörfler
232481c8841SAxel Dörfler /*! Checks the capabilities of the device, and removes everything from
233481c8841SAxel Dörfler \a command that the device does not support.
234481c8841SAxel Dörfler */
235481c8841SAxel Dörfler static void
check_capabilities(agp_device_info & deviceInfo,uint32 & command)236481c8841SAxel Dörfler check_capabilities(agp_device_info &deviceInfo, uint32 &command)
237481c8841SAxel Dörfler {
238481c8841SAxel Dörfler uint32 agpStatus = deviceInfo.info.interface.status;
239481c8841SAxel Dörfler if (deviceInfo.info.class_base == PCI_bridge) {
240481c8841SAxel Dörfler // make sure the AGP rate support mask is correct
241481c8841SAxel Dörfler // (ie. has the lower bits set)
242481c8841SAxel Dörfler agpStatus = fix_rate_support(agpStatus);
243481c8841SAxel Dörfler }
244481c8841SAxel Dörfler
24582c2deb5SJérôme Duval TRACE("device %u.%u.%u has AGP capabilities %" B_PRIx32 "\n", deviceInfo.info.bus,
246ed7d0f52SAxel Dörfler deviceInfo.info.device, deviceInfo.info.function, agpStatus);
247ed7d0f52SAxel Dörfler
248481c8841SAxel Dörfler // block non-supported AGP modes
249481c8841SAxel Dörfler command &= (agpStatus & (AGP_3_MODE | AGP_RATE_MASK))
250481c8841SAxel Dörfler | ~(AGP_3_MODE | AGP_RATE_MASK);
251481c8841SAxel Dörfler
252481c8841SAxel Dörfler // If no AGP mode is supported at all, nothing remains:
253481c8841SAxel Dörfler // devices exist that have the AGP style connector with AGP style registers,
254481c8841SAxel Dörfler // but not the features!
255481c8841SAxel Dörfler // (confirmed Matrox Millenium II AGP for instance)
256481c8841SAxel Dörfler if ((agpStatus & AGP_RATE_MASK) == 0)
257481c8841SAxel Dörfler command = 0;
258481c8841SAxel Dörfler
259481c8841SAxel Dörfler // block side band adressing if not supported
260481c8841SAxel Dörfler if ((agpStatus & AGP_SBA) == 0)
261481c8841SAxel Dörfler command &= ~AGP_SBA;
262481c8841SAxel Dörfler
263481c8841SAxel Dörfler // block fast writes if not supported
264481c8841SAxel Dörfler if ((agpStatus & AGP_FAST_WRITE) == 0)
265481c8841SAxel Dörfler command &= ~AGP_FAST_WRITE;
266481c8841SAxel Dörfler
267481c8841SAxel Dörfler // adjust maximum request depth to least depth supported
268481c8841SAxel Dörfler // note: this is writable only in the graphics card
269481c8841SAxel Dörfler uint8 requestDepth = ((agpStatus & AGP_REQUEST) >> AGP_REQUEST_SHIFT);
270481c8841SAxel Dörfler if (requestDepth < ((command & AGP_REQUEST) >> AGP_REQUEST_SHIFT)) {
271481c8841SAxel Dörfler command &= ~AGP_REQUEST;
272481c8841SAxel Dörfler command |= (requestDepth << AGP_REQUEST_SHIFT);
273481c8841SAxel Dörfler }
274481c8841SAxel Dörfler }
275481c8841SAxel Dörfler
276481c8841SAxel Dörfler
277481c8841SAxel Dörfler /*! Checks the PCI capabilities if the device is an AGP device
278481c8841SAxel Dörfler */
279481c8841SAxel Dörfler static bool
is_agp_device(pci_info & info,uint8 * _address)280481c8841SAxel Dörfler is_agp_device(pci_info &info, uint8 *_address)
281481c8841SAxel Dörfler {
282481c8841SAxel Dörfler // Check if device implements a list of capabilities
283481c8841SAxel Dörfler if ((get_pci_config(info, PCI_status, 2) & PCI_status_capabilities) == 0)
284481c8841SAxel Dörfler return false;
285481c8841SAxel Dörfler
286481c8841SAxel Dörfler // Get pointer to PCI capabilities list
287481c8841SAxel Dörfler // (AGP devices only, no need to take cardbus into account)
288481c8841SAxel Dörfler uint8 address = get_pci_config(info, PCI_capabilities_ptr, 1);
289481c8841SAxel Dörfler
290481c8841SAxel Dörfler while (true) {
291481c8841SAxel Dörfler uint8 id = get_pci_config(info, address, 1);
292481c8841SAxel Dörfler uint8 next = get_pci_config(info, address + 1, 1) & ~0x3;
293481c8841SAxel Dörfler
294481c8841SAxel Dörfler if (id == PCI_cap_id_agp) {
295481c8841SAxel Dörfler // is an AGP device
296481c8841SAxel Dörfler if (_address != NULL)
297481c8841SAxel Dörfler *_address = address;
298481c8841SAxel Dörfler return true;
299481c8841SAxel Dörfler }
300481c8841SAxel Dörfler if (next == 0) {
301481c8841SAxel Dörfler // end of list
302481c8841SAxel Dörfler break;
303481c8841SAxel Dörfler }
304481c8841SAxel Dörfler
305481c8841SAxel Dörfler address = next;
306481c8841SAxel Dörfler }
307481c8841SAxel Dörfler
308481c8841SAxel Dörfler return false;
309481c8841SAxel Dörfler }
310481c8841SAxel Dörfler
311481c8841SAxel Dörfler
312481c8841SAxel Dörfler static status_t
get_next_agp_device(uint32 * _cookie,pci_info & info,agp_device_info & device)313481c8841SAxel Dörfler get_next_agp_device(uint32 *_cookie, pci_info &info, agp_device_info &device)
314481c8841SAxel Dörfler {
315481c8841SAxel Dörfler uint32 index = *_cookie;
316481c8841SAxel Dörfler
317481c8841SAxel Dörfler // find devices
318481c8841SAxel Dörfler
319481c8841SAxel Dörfler for (; sPCI->get_nth_pci_info(index, &info) == B_OK; index++) {
320481c8841SAxel Dörfler // is it a bridge or a graphics card?
321481c8841SAxel Dörfler if ((info.class_base != PCI_bridge || info.class_sub != PCI_host)
322481c8841SAxel Dörfler && info.class_base != PCI_display)
323481c8841SAxel Dörfler continue;
324481c8841SAxel Dörfler
325481c8841SAxel Dörfler if (is_agp_device(info, &device.address)) {
326481c8841SAxel Dörfler device.info.vendor_id = info.vendor_id;
327481c8841SAxel Dörfler device.info.device_id = info.device_id;
328481c8841SAxel Dörfler device.info.bus = info.bus;
329481c8841SAxel Dörfler device.info.device = info.device;
330481c8841SAxel Dörfler device.info.function = info.function;
331481c8841SAxel Dörfler device.info.class_sub = info.class_sub;
332481c8841SAxel Dörfler device.info.class_base = info.class_base;
333481c8841SAxel Dörfler
334481c8841SAxel Dörfler /* get the contents of the AGP registers from this device */
335481c8841SAxel Dörfler device.info.interface.capability_id = get_pci_config(info,
336481c8841SAxel Dörfler AGP_ID(device.address), 4);
337481c8841SAxel Dörfler device.info.interface.status = get_pci_config(info,
338481c8841SAxel Dörfler AGP_STATUS(device.address), 4);
339481c8841SAxel Dörfler device.info.interface.command = get_pci_config(info,
340481c8841SAxel Dörfler AGP_COMMAND(device.address), 4);
341481c8841SAxel Dörfler
342481c8841SAxel Dörfler *_cookie = index + 1;
343481c8841SAxel Dörfler return B_OK;
344481c8841SAxel Dörfler }
345481c8841SAxel Dörfler }
346481c8841SAxel Dörfler
347481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
348481c8841SAxel Dörfler }
349481c8841SAxel Dörfler
350481c8841SAxel Dörfler
351481c8841SAxel Dörfler static void
set_agp_command(agp_device_info & deviceInfo,uint32 command)352481c8841SAxel Dörfler set_agp_command(agp_device_info &deviceInfo, uint32 command)
353481c8841SAxel Dörfler {
354481c8841SAxel Dörfler set_pci_config(deviceInfo.info, AGP_COMMAND(deviceInfo.address), 4, command);
355481c8841SAxel Dörfler deviceInfo.info.interface.command = get_pci_config(deviceInfo.info,
356481c8841SAxel Dörfler AGP_COMMAND(deviceInfo.address), 4);
357481c8841SAxel Dörfler }
358481c8841SAxel Dörfler
359481c8841SAxel Dörfler
360481c8841SAxel Dörfler static void
set_pci_mode()361481c8841SAxel Dörfler set_pci_mode()
362481c8841SAxel Dörfler {
363ed7d0f52SAxel Dörfler TRACE("set PCI mode on all AGP capable devices.\n");
364ed7d0f52SAxel Dörfler
365481c8841SAxel Dörfler // First program all graphics cards
366481c8841SAxel Dörfler
367481c8841SAxel Dörfler for (uint32 index = 0; index < sDeviceCount; index++) {
368481c8841SAxel Dörfler agp_device_info &deviceInfo = sDeviceInfos[index];
369481c8841SAxel Dörfler if (deviceInfo.info.class_base != PCI_display)
370481c8841SAxel Dörfler continue;
371481c8841SAxel Dörfler
372481c8841SAxel Dörfler set_agp_command(deviceInfo, 0);
373481c8841SAxel Dörfler }
374481c8841SAxel Dörfler
375481c8841SAxel Dörfler // Then program all bridges - it's the other around for AGP mode
376481c8841SAxel Dörfler
377481c8841SAxel Dörfler for (uint32 index = 0; index < sDeviceCount; index++) {
378481c8841SAxel Dörfler agp_device_info &deviceInfo = sDeviceInfos[index];
379481c8841SAxel Dörfler if (deviceInfo.info.class_base != PCI_bridge)
380481c8841SAxel Dörfler continue;
381481c8841SAxel Dörfler
382481c8841SAxel Dörfler set_agp_command(deviceInfo, 0);
383481c8841SAxel Dörfler }
384481c8841SAxel Dörfler
385481c8841SAxel Dörfler // Wait 10mS for the bridges to recover (failsafe!)
386481c8841SAxel Dörfler // Note: some SiS bridge chipsets apparantly require 5mS to recover
387481c8841SAxel Dörfler // or the master (graphics card) cannot be initialized correctly!
388481c8841SAxel Dörfler snooze(10000);
389481c8841SAxel Dörfler }
390481c8841SAxel Dörfler
391481c8841SAxel Dörfler
392103d05f3SAxel Dörfler status_t
get_area_base_and_size(area_id area,addr_t & base,size_t & size)3930148fb2dSAxel Dörfler get_area_base_and_size(area_id area, addr_t &base, size_t &size)
394103d05f3SAxel Dörfler {
395103d05f3SAxel Dörfler area_info info;
396103d05f3SAxel Dörfler status_t status = get_area_info(area, &info);
397103d05f3SAxel Dörfler if (status < B_OK)
398103d05f3SAxel Dörfler return status;
399103d05f3SAxel Dörfler
400103d05f3SAxel Dörfler base = (addr_t)info.address;
401103d05f3SAxel Dörfler size = info.size;
402103d05f3SAxel Dörfler return B_OK;
403103d05f3SAxel Dörfler }
404103d05f3SAxel Dörfler
405103d05f3SAxel Dörfler
406481c8841SAxel Dörfler Aperture *
get_aperture(aperture_id id)407481c8841SAxel Dörfler get_aperture(aperture_id id)
408481c8841SAxel Dörfler {
409481c8841SAxel Dörfler Autolock _(sLock);
410481c8841SAxel Dörfler return sApertureHashTable.Lookup(id);
411481c8841SAxel Dörfler }
412481c8841SAxel Dörfler
413481c8841SAxel Dörfler
414481c8841SAxel Dörfler // #pragma mark - Aperture
415481c8841SAxel Dörfler
416481c8841SAxel Dörfler
Aperture(agp_gart_bus_module_info * module,void * aperture)417481c8841SAxel Dörfler Aperture::Aperture(agp_gart_bus_module_info *module, void *aperture)
418481c8841SAxel Dörfler :
419481c8841SAxel Dörfler fModule(module),
420*555b9ff7SNiels Sascha Reedijk fInfo(),
421481c8841SAxel Dörfler fHashTable(fInfo),
4227e6d2343SAxel Dörfler fFirstMemory(NULL),
423481c8841SAxel Dörfler fPrivateAperture(aperture)
424481c8841SAxel Dörfler {
425481c8841SAxel Dörfler fModule->get_aperture_info(fPrivateAperture, &fInfo);
426481c8841SAxel Dörfler fID = atomic_add(&sNextApertureID, 1);
427481c8841SAxel Dörfler init_lock(&fLock, "aperture");
428481c8841SAxel Dörfler }
429481c8841SAxel Dörfler
430481c8841SAxel Dörfler
~Aperture()431481c8841SAxel Dörfler Aperture::~Aperture()
432481c8841SAxel Dörfler {
4337e6d2343SAxel Dörfler while (fFirstMemory != NULL) {
4347e6d2343SAxel Dörfler DeleteMemory(fFirstMemory);
4357e6d2343SAxel Dörfler }
4367e6d2343SAxel Dörfler
437481c8841SAxel Dörfler fModule->delete_aperture(fPrivateAperture);
438481c8841SAxel Dörfler put_module(fModule->info.name);
439481c8841SAxel Dörfler }
440481c8841SAxel Dörfler
441481c8841SAxel Dörfler
442481c8841SAxel Dörfler status_t
GetInfo(aperture_info * info)443481c8841SAxel Dörfler Aperture::GetInfo(aperture_info *info)
444481c8841SAxel Dörfler {
445481c8841SAxel Dörfler if (info == NULL)
446481c8841SAxel Dörfler return B_BAD_VALUE;
447481c8841SAxel Dörfler
448481c8841SAxel Dörfler *info = fInfo;
449481c8841SAxel Dörfler return B_OK;
450481c8841SAxel Dörfler }
451481c8841SAxel Dörfler
452481c8841SAxel Dörfler
453481c8841SAxel Dörfler void
DeleteMemory(aperture_memory * memory)454481c8841SAxel Dörfler Aperture::DeleteMemory(aperture_memory *memory)
455481c8841SAxel Dörfler {
4567e6d2343SAxel Dörfler TRACE("delete memory %p\n", memory);
4577e6d2343SAxel Dörfler
458481c8841SAxel Dörfler UnbindMemory(memory);
459481c8841SAxel Dörfler _Free(memory);
460481c8841SAxel Dörfler _Remove(memory);
461481c8841SAxel Dörfler fHashTable.Remove(memory);
462481c8841SAxel Dörfler delete memory;
463481c8841SAxel Dörfler }
464481c8841SAxel Dörfler
465481c8841SAxel Dörfler
466481c8841SAxel Dörfler aperture_memory *
CreateMemory(size_t size,size_t alignment,uint32 flags)467481c8841SAxel Dörfler Aperture::CreateMemory(size_t size, size_t alignment, uint32 flags)
468481c8841SAxel Dörfler {
469481c8841SAxel Dörfler aperture_memory *memory = new(std::nothrow) aperture_memory;
470481c8841SAxel Dörfler if (memory == NULL)
471481c8841SAxel Dörfler return NULL;
472481c8841SAxel Dörfler
473481c8841SAxel Dörfler status_t status = _Insert(memory, size, alignment, flags);
474481c8841SAxel Dörfler if (status < B_OK) {
4757d5632a0SJérôme Duval ERROR("Aperture::CreateMemory(): did not find a free space large for "
4767d5632a0SJérôme Duval "this memory object\n");
477481c8841SAxel Dörfler delete memory;
478481c8841SAxel Dörfler return NULL;
479481c8841SAxel Dörfler }
480481c8841SAxel Dörfler
48182c2deb5SJérôme Duval TRACE("create memory %p, base %" B_PRIxADDR ", size %" B_PRIxSIZE
48282c2deb5SJérôme Duval ", flags %" B_PRIx32 "\n", memory, memory->base, memory->size, flags);
4837e6d2343SAxel Dörfler
484481c8841SAxel Dörfler memory->flags = flags;
48521c87a5dSJérôme Duval #if !defined(GART_TEST)
486481c8841SAxel Dörfler memory->pages = NULL;
487481c8841SAxel Dörfler #else
488481c8841SAxel Dörfler memory->area = -1;
489481c8841SAxel Dörfler #endif
490481c8841SAxel Dörfler
491481c8841SAxel Dörfler fHashTable.Insert(memory);
492481c8841SAxel Dörfler return memory;
493481c8841SAxel Dörfler }
494481c8841SAxel Dörfler
495481c8841SAxel Dörfler
4967e6d2343SAxel Dörfler bool
_AdaptToReserved(addr_t & base,size_t & size,int32 * _offset)4977e6d2343SAxel Dörfler Aperture::_AdaptToReserved(addr_t &base, size_t &size, int32 *_offset)
4987e6d2343SAxel Dörfler {
4997e6d2343SAxel Dörfler addr_t reservedEnd = fInfo.base + fInfo.reserved_size;
5007e6d2343SAxel Dörfler if (reservedEnd <= base)
5017e6d2343SAxel Dörfler return false;
5027e6d2343SAxel Dörfler
5037e6d2343SAxel Dörfler if (reservedEnd >= base + size) {
5047e6d2343SAxel Dörfler size = 0;
5057e6d2343SAxel Dörfler return true;
5067e6d2343SAxel Dörfler }
5077e6d2343SAxel Dörfler
5087e6d2343SAxel Dörfler if (_offset != NULL)
5097e6d2343SAxel Dörfler *_offset = reservedEnd - base;
5107e6d2343SAxel Dörfler
5117e6d2343SAxel Dörfler size -= reservedEnd - base;
5127e6d2343SAxel Dörfler base = reservedEnd;
5137e6d2343SAxel Dörfler return true;
5147e6d2343SAxel Dörfler }
5157e6d2343SAxel Dörfler
5167e6d2343SAxel Dörfler
517481c8841SAxel Dörfler status_t
AllocateMemory(aperture_memory * memory,uint32 flags)518481c8841SAxel Dörfler Aperture::AllocateMemory(aperture_memory *memory, uint32 flags)
519481c8841SAxel Dörfler {
5207e6d2343SAxel Dörfler // We don't need to allocate reserved memory - it's
521481c8841SAxel Dörfler // already there for us to use
5227e6d2343SAxel Dörfler addr_t base = memory->base;
523481c8841SAxel Dörfler size_t size = memory->size;
5247e6d2343SAxel Dörfler if (_AdaptToReserved(base, size)) {
5257e6d2343SAxel Dörfler if (size == 0) {
5267e6d2343SAxel Dörfler TRACE("allocation is made of reserved memory\n");
527481c8841SAxel Dörfler return B_OK;
528481c8841SAxel Dörfler }
529481c8841SAxel Dörfler
5307e6d2343SAxel Dörfler memset((void *)memory->base, 0, memory->size - size);
5317e6d2343SAxel Dörfler }
5327e6d2343SAxel Dörfler TRACE("allocate %ld bytes out of %ld\n", size, memory->size);
5337e6d2343SAxel Dörfler
53421c87a5dSJérôme Duval #if !defined(GART_TEST)
535481c8841SAxel Dörfler uint32 count = size / B_PAGE_SIZE;
536481c8841SAxel Dörfler
537481c8841SAxel Dörfler if ((flags & B_APERTURE_NEED_PHYSICAL) != 0) {
538a8ad734fSIngo Weinhold physical_address_restrictions restrictions = {};
539c53724f7SIngo Weinhold #if B_HAIKU_PHYSICAL_BITS > 32
540c53724f7SIngo Weinhold restrictions.high_address = (phys_addr_t)1 << 32;
541c53724f7SIngo Weinhold // TODO: Work-around until intel_gart can deal with physical
542c53724f7SIngo Weinhold // addresses > 4 GB.
543c53724f7SIngo Weinhold #endif
544e65c4002SIngo Weinhold memory->page = vm_page_allocate_page_run(
545a8ad734fSIngo Weinhold PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR, count, &restrictions,
546cff6e9e4SIngo Weinhold VM_PRIORITY_SYSTEM);
5477d5632a0SJérôme Duval if (memory->page == NULL) {
5487d5632a0SJérôme Duval ERROR("Aperture::AllocateMemory(): vm_page_allocate_page_run() "
5497d5632a0SJérôme Duval "failed (with B_APERTURE_NEED_PHYSICAL)\n");
550481c8841SAxel Dörfler return B_NO_MEMORY;
5517d5632a0SJérôme Duval }
552481c8841SAxel Dörfler } else {
553481c8841SAxel Dörfler // Allocate table to hold the pages
554481c8841SAxel Dörfler memory->pages = (vm_page **)malloc(count * sizeof(vm_page *));
555481c8841SAxel Dörfler if (memory->pages == NULL)
556481c8841SAxel Dörfler return B_NO_MEMORY;
557481c8841SAxel Dörfler
558c53724f7SIngo Weinhold #if B_HAIKU_PHYSICAL_BITS > 32
559c53724f7SIngo Weinhold // TODO: Work-around until intel_gart can deal with physical
560c53724f7SIngo Weinhold // addresses > 4 GB.
561c53724f7SIngo Weinhold physical_address_restrictions restrictions = {};
562c53724f7SIngo Weinhold restrictions.high_address = (phys_addr_t)1 << 32;
563c53724f7SIngo Weinhold vm_page* page = vm_page_allocate_page_run(
564c53724f7SIngo Weinhold PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR, count, &restrictions,
565c53724f7SIngo Weinhold VM_PRIORITY_SYSTEM);
5667d5632a0SJérôme Duval if (page == NULL) {
5677d5632a0SJérôme Duval ERROR("Aperture::AllocateMemory(): vm_page_allocate_page_run() "
5687d5632a0SJérôme Duval "failed (without B_APERTURE_NEED_PHYSICAL)\n");
569c53724f7SIngo Weinhold return B_NO_MEMORY;
5707d5632a0SJérôme Duval }
571c53724f7SIngo Weinhold
572c53724f7SIngo Weinhold for (uint32 i = 0; i < count; i++)
573c53724f7SIngo Weinhold memory->pages[i] = page + i;
574c53724f7SIngo Weinhold #else
57540bb9481SIngo Weinhold vm_page_reservation reservation;
57640bb9481SIngo Weinhold vm_page_reserve_pages(&reservation, count, VM_PRIORITY_SYSTEM);
57772382fa6SIngo Weinhold for (uint32 i = 0; i < count; i++) {
57840bb9481SIngo Weinhold memory->pages[i] = vm_page_allocate_page(&reservation,
579e65c4002SIngo Weinhold PAGE_STATE_WIRED | VM_PAGE_ALLOC_CLEAR);
58072382fa6SIngo Weinhold }
58140bb9481SIngo Weinhold vm_page_unreserve_pages(&reservation);
582c53724f7SIngo Weinhold #endif
583481c8841SAxel Dörfler }
5843cd20943SIngo Weinhold
5853cd20943SIngo Weinhold #ifdef DEBUG_PAGE_ACCESS
5863cd20943SIngo Weinhold memory->allocating_thread = find_thread(NULL);
5873cd20943SIngo Weinhold #endif
5883cd20943SIngo Weinhold
58921c87a5dSJérôme Duval #else // GART_TEST
590481c8841SAxel Dörfler void *address;
591481c8841SAxel Dörfler memory->area = create_area("GART memory", &address, B_ANY_KERNEL_ADDRESS,
592481c8841SAxel Dörfler size, B_FULL_LOCK | ((flags & B_APERTURE_NEED_PHYSICAL) != 0
593956f4507STrung Nguyen ? B_CONTIGUOUS : 0), B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
5947d5632a0SJérôme Duval if (memory->area < B_OK) {
5957d5632a0SJérôme Duval ERROR("Aperture::AllocateMemory(): create_area() failed\n");
596481c8841SAxel Dörfler return B_NO_MEMORY;
5977d5632a0SJérôme Duval }
598481c8841SAxel Dörfler #endif
599481c8841SAxel Dörfler
600481c8841SAxel Dörfler memory->flags |= ALLOCATED_APERTURE;
601481c8841SAxel Dörfler return B_OK;
602481c8841SAxel Dörfler }
603481c8841SAxel Dörfler
604481c8841SAxel Dörfler
605481c8841SAxel Dörfler status_t
UnbindMemory(aperture_memory * memory)606481c8841SAxel Dörfler Aperture::UnbindMemory(aperture_memory *memory)
607481c8841SAxel Dörfler {
608481c8841SAxel Dörfler if ((memory->flags & BIND_APERTURE) == 0)
609481c8841SAxel Dörfler return B_BAD_VALUE;
610481c8841SAxel Dörfler
6117e6d2343SAxel Dörfler // We must not unbind reserved memory
6127e6d2343SAxel Dörfler addr_t base = memory->base;
6137e6d2343SAxel Dörfler size_t size = memory->size;
6147e6d2343SAxel Dörfler if (_AdaptToReserved(base, size) && size == 0) {
6157e6d2343SAxel Dörfler memory->flags &= ~BIND_APERTURE;
6167e6d2343SAxel Dörfler return B_OK;
6177e6d2343SAxel Dörfler }
6187e6d2343SAxel Dörfler
6197e6d2343SAxel Dörfler addr_t start = base - Base();
620103d05f3SAxel Dörfler TRACE("unbind %ld bytes at %lx\n", size, start);
621481c8841SAxel Dörfler
622481c8841SAxel Dörfler for (addr_t offset = 0; offset < memory->size; offset += B_PAGE_SIZE) {
623481c8841SAxel Dörfler status_t status = fModule->unbind_page(fPrivateAperture, start + offset);
624481c8841SAxel Dörfler if (status < B_OK)
625481c8841SAxel Dörfler return status;
626481c8841SAxel Dörfler }
627481c8841SAxel Dörfler
628481c8841SAxel Dörfler memory->flags &= ~BIND_APERTURE;
6297e6d2343SAxel Dörfler fModule->flush_tlbs(fPrivateAperture);
630481c8841SAxel Dörfler return B_OK;
631481c8841SAxel Dörfler }
632481c8841SAxel Dörfler
633481c8841SAxel Dörfler
634481c8841SAxel Dörfler status_t
BindMemory(aperture_memory * memory,addr_t address,size_t size)635103d05f3SAxel Dörfler Aperture::BindMemory(aperture_memory *memory, addr_t address, size_t size)
636481c8841SAxel Dörfler {
637103d05f3SAxel Dörfler bool physical = false;
638103d05f3SAxel Dörfler
639103d05f3SAxel Dörfler if ((memory->flags & ALLOCATED_APERTURE) != 0) {
640103d05f3SAxel Dörfler // We allocated this memory, get the base and size from there
641d23e60e7SAxel Dörfler size = memory->size;
642103d05f3SAxel Dörfler physical = true;
643103d05f3SAxel Dörfler }
644103d05f3SAxel Dörfler
6457e6d2343SAxel Dörfler // We don't need to bind reserved memory
6467e6d2343SAxel Dörfler addr_t base = memory->base;
6477e6d2343SAxel Dörfler int32 offset;
6487e6d2343SAxel Dörfler if (_AdaptToReserved(base, size, &offset)) {
6497e6d2343SAxel Dörfler if (size == 0) {
6507e6d2343SAxel Dörfler TRACE("reserved memory already bound\n");
6517e6d2343SAxel Dörfler memory->flags |= BIND_APERTURE;
6527e6d2343SAxel Dörfler return B_OK;
6537e6d2343SAxel Dörfler }
6547e6d2343SAxel Dörfler
6557e6d2343SAxel Dörfler address += offset;
6567e6d2343SAxel Dörfler }
6577e6d2343SAxel Dörfler
6587e6d2343SAxel Dörfler addr_t start = base - Base();
6597e6d2343SAxel Dörfler TRACE("bind %ld bytes at %lx\n", size, base);
660481c8841SAxel Dörfler
661481c8841SAxel Dörfler for (addr_t offset = 0; offset < size; offset += B_PAGE_SIZE) {
66264d79effSIngo Weinhold phys_addr_t physicalAddress = 0;
663481c8841SAxel Dörfler status_t status;
664481c8841SAxel Dörfler
665481c8841SAxel Dörfler if (!physical) {
666481c8841SAxel Dörfler physical_entry entry;
6677e6d2343SAxel Dörfler status = get_memory_map((void *)(address + offset), B_PAGE_SIZE,
668481c8841SAxel Dörfler &entry, 1);
6697d5632a0SJérôme Duval if (status < B_OK) {
6707d5632a0SJérôme Duval ERROR("Aperture::BindMemory(): get_memory_map() failed\n");
671481c8841SAxel Dörfler return status;
6727d5632a0SJérôme Duval }
673481c8841SAxel Dörfler
67464d79effSIngo Weinhold physicalAddress = entry.address;
675103d05f3SAxel Dörfler } else {
676103d05f3SAxel Dörfler uint32 index = offset >> PAGE_SHIFT;
677103d05f3SAxel Dörfler vm_page *page;
678103d05f3SAxel Dörfler if ((memory->flags & B_APERTURE_NEED_PHYSICAL) != 0)
679103d05f3SAxel Dörfler page = memory->page + index;
680103d05f3SAxel Dörfler else
681103d05f3SAxel Dörfler page = memory->pages[index];
682103d05f3SAxel Dörfler
6839a063f05SAxel Dörfler physicalAddress
6849a063f05SAxel Dörfler = (phys_addr_t)page->physical_page_number << PAGE_SHIFT;
685103d05f3SAxel Dörfler }
6867e6d2343SAxel Dörfler
6877e6d2343SAxel Dörfler status = fModule->bind_page(fPrivateAperture, start + offset,
6887e6d2343SAxel Dörfler physicalAddress);
6897d5632a0SJérôme Duval if (status < B_OK) {
6907d5632a0SJérôme Duval ERROR("Aperture::BindMemory(): bind_page() failed\n");
691481c8841SAxel Dörfler return status;
692481c8841SAxel Dörfler }
6937d5632a0SJérôme Duval }
694481c8841SAxel Dörfler
695481c8841SAxel Dörfler memory->flags |= BIND_APERTURE;
6967e6d2343SAxel Dörfler fModule->flush_tlbs(fPrivateAperture);
697481c8841SAxel Dörfler return B_OK;
698481c8841SAxel Dörfler }
699481c8841SAxel Dörfler
700481c8841SAxel Dörfler
701481c8841SAxel Dörfler void
_Free(aperture_memory * memory)702481c8841SAxel Dörfler Aperture::_Free(aperture_memory *memory)
703481c8841SAxel Dörfler {
704481c8841SAxel Dörfler if ((memory->flags & ALLOCATED_APERTURE) == 0)
705481c8841SAxel Dörfler return;
706481c8841SAxel Dörfler
70721c87a5dSJérôme Duval #if !defined(GART_TEST)
708481c8841SAxel Dörfler // Remove the stolen area from the allocation
709481c8841SAxel Dörfler size_t size = memory->size;
710481c8841SAxel Dörfler addr_t reservedEnd = fInfo.base + fInfo.reserved_size;
711481c8841SAxel Dörfler if (memory->base < reservedEnd)
712481c8841SAxel Dörfler size -= reservedEnd - memory->base;
713481c8841SAxel Dörfler
714481c8841SAxel Dörfler // Free previously allocated pages and page table
715481c8841SAxel Dörfler uint32 count = size / B_PAGE_SIZE;
716481c8841SAxel Dörfler
717481c8841SAxel Dörfler if ((memory->flags & B_APERTURE_NEED_PHYSICAL) != 0) {
718481c8841SAxel Dörfler vm_page *page = memory->page;
719481c8841SAxel Dörfler for (uint32 i = 0; i < count; i++, page++) {
7203cd20943SIngo Weinhold DEBUG_PAGE_ACCESS_TRANSFER(page, memory->allocating_thread);
721481c8841SAxel Dörfler vm_page_set_state(page, PAGE_STATE_FREE);
722481c8841SAxel Dörfler }
7237f5c5dc8SAxel Dörfler
7247f5c5dc8SAxel Dörfler memory->page = NULL;
725481c8841SAxel Dörfler } else {
726481c8841SAxel Dörfler for (uint32 i = 0; i < count; i++) {
7273cd20943SIngo Weinhold DEBUG_PAGE_ACCESS_TRANSFER(memory->pages[i],
7283cd20943SIngo Weinhold memory->allocating_thread);
729481c8841SAxel Dörfler vm_page_set_state(memory->pages[i], PAGE_STATE_FREE);
730481c8841SAxel Dörfler }
731481c8841SAxel Dörfler
732481c8841SAxel Dörfler free(memory->pages);
733481c8841SAxel Dörfler memory->pages = NULL;
7347f5c5dc8SAxel Dörfler }
735481c8841SAxel Dörfler #else
736481c8841SAxel Dörfler delete_area(memory->area);
737481c8841SAxel Dörfler memory->area = -1;
738481c8841SAxel Dörfler #endif
739481c8841SAxel Dörfler
740481c8841SAxel Dörfler memory->flags &= ~ALLOCATED_APERTURE;
741481c8841SAxel Dörfler }
742481c8841SAxel Dörfler
743481c8841SAxel Dörfler
744481c8841SAxel Dörfler void
_Remove(aperture_memory * memory)745481c8841SAxel Dörfler Aperture::_Remove(aperture_memory *memory)
746481c8841SAxel Dörfler {
747481c8841SAxel Dörfler aperture_memory *current = fFirstMemory, *last = NULL;
748481c8841SAxel Dörfler
749481c8841SAxel Dörfler while (current != NULL) {
750481c8841SAxel Dörfler if (memory == current) {
751481c8841SAxel Dörfler if (last != NULL) {
752481c8841SAxel Dörfler last->next = current->next;
753481c8841SAxel Dörfler } else {
754481c8841SAxel Dörfler fFirstMemory = current->next;
755481c8841SAxel Dörfler }
756481c8841SAxel Dörfler break;
757481c8841SAxel Dörfler }
758481c8841SAxel Dörfler
759481c8841SAxel Dörfler last = current;
760481c8841SAxel Dörfler current = current->next;
761481c8841SAxel Dörfler }
762481c8841SAxel Dörfler }
763481c8841SAxel Dörfler
764481c8841SAxel Dörfler
765481c8841SAxel Dörfler status_t
_Insert(aperture_memory * memory,size_t size,size_t alignment,uint32 flags)766481c8841SAxel Dörfler Aperture::_Insert(aperture_memory *memory, size_t size, size_t alignment,
767481c8841SAxel Dörfler uint32 flags)
768481c8841SAxel Dörfler {
769481c8841SAxel Dörfler aperture_memory *last = NULL;
770481c8841SAxel Dörfler aperture_memory *next;
771481c8841SAxel Dörfler bool foundSpot = false;
772481c8841SAxel Dörfler
773481c8841SAxel Dörfler // do some sanity checking
774481c8841SAxel Dörfler if (size == 0 || size > fInfo.size)
775481c8841SAxel Dörfler return B_BAD_VALUE;
776481c8841SAxel Dörfler
7777e6d2343SAxel Dörfler if (alignment < B_PAGE_SIZE)
7787e6d2343SAxel Dörfler alignment = B_PAGE_SIZE;
7797e6d2343SAxel Dörfler
780481c8841SAxel Dörfler addr_t start = fInfo.base;
781481c8841SAxel Dörfler if ((flags & (B_APERTURE_NON_RESERVED | B_APERTURE_NEED_PHYSICAL)) != 0)
782481c8841SAxel Dörfler start += fInfo.reserved_size;
783481c8841SAxel Dörfler
784481c8841SAxel Dörfler start = ROUNDUP(start, alignment);
785481c8841SAxel Dörfler if (start > fInfo.base - 1 + fInfo.size || start < fInfo.base)
786481c8841SAxel Dörfler return B_NO_MEMORY;
787481c8841SAxel Dörfler
788481c8841SAxel Dörfler // walk up to the spot where we should start searching
789481c8841SAxel Dörfler
790481c8841SAxel Dörfler next = fFirstMemory;
791481c8841SAxel Dörfler while (next) {
792481c8841SAxel Dörfler if (next->base >= start + size) {
793481c8841SAxel Dörfler // we have a winner
794481c8841SAxel Dörfler break;
795481c8841SAxel Dörfler }
796481c8841SAxel Dörfler last = next;
797481c8841SAxel Dörfler next = next->next;
798481c8841SAxel Dörfler }
799481c8841SAxel Dörfler
800481c8841SAxel Dörfler // find a big enough hole
801481c8841SAxel Dörfler if (last == NULL) {
802481c8841SAxel Dörfler // see if we can build it at the beginning of the virtual map
803481c8841SAxel Dörfler if (next == NULL || (next->base >= ROUNDUP(start, alignment) + size)) {
804481c8841SAxel Dörfler memory->base = ROUNDUP(start, alignment);
805481c8841SAxel Dörfler foundSpot = true;
806481c8841SAxel Dörfler } else {
807481c8841SAxel Dörfler last = next;
808481c8841SAxel Dörfler next = next->next;
809481c8841SAxel Dörfler }
810481c8841SAxel Dörfler }
811481c8841SAxel Dörfler
812481c8841SAxel Dörfler if (!foundSpot) {
813481c8841SAxel Dörfler // keep walking
814481c8841SAxel Dörfler while (next != NULL) {
815481c8841SAxel Dörfler if (next->base >= ROUNDUP(last->base + last->size, alignment) + size) {
816481c8841SAxel Dörfler // we found a spot (it'll be filled up below)
817481c8841SAxel Dörfler break;
818481c8841SAxel Dörfler }
819481c8841SAxel Dörfler last = next;
820481c8841SAxel Dörfler next = next->next;
821481c8841SAxel Dörfler }
822481c8841SAxel Dörfler
823481c8841SAxel Dörfler if ((fInfo.base + (fInfo.size - 1)) >= (ROUNDUP(last->base + last->size,
824481c8841SAxel Dörfler alignment) + (size - 1))) {
825481c8841SAxel Dörfler // got a spot
826481c8841SAxel Dörfler foundSpot = true;
827481c8841SAxel Dörfler memory->base = ROUNDUP(last->base + last->size, alignment);
8287e6d2343SAxel Dörfler if (memory->base < start)
8297e6d2343SAxel Dörfler memory->base = start;
830481c8841SAxel Dörfler }
831481c8841SAxel Dörfler
832481c8841SAxel Dörfler if (!foundSpot)
833481c8841SAxel Dörfler return B_NO_MEMORY;
834481c8841SAxel Dörfler }
835481c8841SAxel Dörfler
836481c8841SAxel Dörfler memory->size = size;
837481c8841SAxel Dörfler if (last) {
838481c8841SAxel Dörfler memory->next = last->next;
839481c8841SAxel Dörfler last->next = memory;
840481c8841SAxel Dörfler } else {
841481c8841SAxel Dörfler memory->next = fFirstMemory;
842481c8841SAxel Dörfler fFirstMemory = memory;
843481c8841SAxel Dörfler }
844481c8841SAxel Dörfler
845481c8841SAxel Dörfler return B_OK;
846481c8841SAxel Dörfler }
847481c8841SAxel Dörfler
848481c8841SAxel Dörfler
849481c8841SAxel Dörfler // #pragma mark - AGP module interface
850481c8841SAxel Dörfler
851481c8841SAxel Dörfler
852481c8841SAxel Dörfler status_t
get_nth_agp_info(uint32 index,agp_info * info)853481c8841SAxel Dörfler get_nth_agp_info(uint32 index, agp_info *info)
854481c8841SAxel Dörfler {
85582c2deb5SJérôme Duval TRACE("get_nth_agp_info(index %" B_PRIu32 ")\n", index);
856481c8841SAxel Dörfler
857481c8841SAxel Dörfler if (index >= sDeviceCount)
858481c8841SAxel Dörfler return B_BAD_VALUE;
859481c8841SAxel Dörfler
860481c8841SAxel Dörfler // refresh from the contents of the AGP registers from this device
861481c8841SAxel Dörfler sDeviceInfos[index].info.interface.status = get_pci_config(
862481c8841SAxel Dörfler sDeviceInfos[index].info, AGP_STATUS(sDeviceInfos[index].address), 4);
863481c8841SAxel Dörfler sDeviceInfos[index].info.interface.command = get_pci_config(
864481c8841SAxel Dörfler sDeviceInfos[index].info, AGP_COMMAND(sDeviceInfos[index].address), 4);
865481c8841SAxel Dörfler
866481c8841SAxel Dörfler *info = sDeviceInfos[index].info;
867481c8841SAxel Dörfler return B_OK;
868481c8841SAxel Dörfler }
869481c8841SAxel Dörfler
870481c8841SAxel Dörfler
871481c8841SAxel Dörfler status_t
acquire_agp(void)872481c8841SAxel Dörfler acquire_agp(void)
873481c8841SAxel Dörfler {
874481c8841SAxel Dörfler if (atomic_or(&sAcquired, 1) == 1)
875481c8841SAxel Dörfler return B_BUSY;
876481c8841SAxel Dörfler
877481c8841SAxel Dörfler return B_OK;
878481c8841SAxel Dörfler }
879481c8841SAxel Dörfler
880481c8841SAxel Dörfler
881481c8841SAxel Dörfler void
release_agp(void)882481c8841SAxel Dörfler release_agp(void)
883481c8841SAxel Dörfler {
884481c8841SAxel Dörfler atomic_and(&sAcquired, 0);
885481c8841SAxel Dörfler }
886481c8841SAxel Dörfler
887481c8841SAxel Dörfler
888481c8841SAxel Dörfler uint32
set_agp_mode(uint32 command)889481c8841SAxel Dörfler set_agp_mode(uint32 command)
890481c8841SAxel Dörfler {
89182c2deb5SJérôme Duval TRACE("set_agp_mode(command %" B_PRIx32 ")\n", command);
892481c8841SAxel Dörfler
893481c8841SAxel Dörfler if ((command & AGP_ENABLE) == 0) {
894481c8841SAxel Dörfler set_pci_mode();
895481c8841SAxel Dörfler return 0;
896481c8841SAxel Dörfler }
897481c8841SAxel Dörfler
898481c8841SAxel Dörfler // Make sure we accept all modes lower than requested one and we
899481c8841SAxel Dörfler // reset reserved bits
900481c8841SAxel Dörfler command = fix_rate_support(command);
901481c8841SAxel Dörfler
902481c8841SAxel Dörfler // iterate through our device list to find the common capabilities supported
903481c8841SAxel Dörfler for (uint32 index = 0; index < sDeviceCount; index++) {
904481c8841SAxel Dörfler agp_device_info &deviceInfo = sDeviceInfos[index];
905481c8841SAxel Dörfler
906481c8841SAxel Dörfler // Refresh from the contents of the AGP capability registers
907481c8841SAxel Dörfler // (note: some graphics driver may have been tweaking, like nvidia)
908481c8841SAxel Dörfler deviceInfo.info.interface.status = get_pci_config(deviceInfo.info,
909481c8841SAxel Dörfler AGP_STATUS(deviceInfo.address), 4);
910481c8841SAxel Dörfler
911481c8841SAxel Dörfler check_capabilities(deviceInfo, command);
912481c8841SAxel Dörfler }
913481c8841SAxel Dörfler
914481c8841SAxel Dörfler command = fix_rate_command(command);
91582c2deb5SJérôme Duval TRACE("set AGP command %" B_PRIx32 " on all capable devices.\n", command);
916481c8841SAxel Dörfler
917481c8841SAxel Dörfler // The order of programming differs for enabling/disabling AGP mode
918481c8841SAxel Dörfler // (see AGP specification)
919481c8841SAxel Dörfler
920481c8841SAxel Dörfler // First program all bridges (master)
921481c8841SAxel Dörfler
922481c8841SAxel Dörfler for (uint32 index = 0; index < sDeviceCount; index++) {
923481c8841SAxel Dörfler agp_device_info &deviceInfo = sDeviceInfos[index];
924481c8841SAxel Dörfler if (deviceInfo.info.class_base != PCI_bridge)
925481c8841SAxel Dörfler continue;
926481c8841SAxel Dörfler
927481c8841SAxel Dörfler set_agp_command(deviceInfo, command);
928481c8841SAxel Dörfler }
929481c8841SAxel Dörfler
930481c8841SAxel Dörfler // Wait 10mS for the bridges to recover (failsafe, see set_pci_mode()!)
931481c8841SAxel Dörfler snooze(10000);
932481c8841SAxel Dörfler
933481c8841SAxel Dörfler // Then all graphics cards (target)
934481c8841SAxel Dörfler
935481c8841SAxel Dörfler for (uint32 index = 0; index < sDeviceCount; index++) {
936481c8841SAxel Dörfler agp_device_info &deviceInfo = sDeviceInfos[index];
937481c8841SAxel Dörfler if (deviceInfo.info.class_base != PCI_display)
938481c8841SAxel Dörfler continue;
939481c8841SAxel Dörfler
940481c8841SAxel Dörfler set_agp_command(deviceInfo, command);
941481c8841SAxel Dörfler }
942481c8841SAxel Dörfler
943481c8841SAxel Dörfler return command;
944481c8841SAxel Dörfler }
945481c8841SAxel Dörfler
946481c8841SAxel Dörfler
947481c8841SAxel Dörfler // #pragma mark - GART module interface
948481c8841SAxel Dörfler
949481c8841SAxel Dörfler
950481c8841SAxel Dörfler static aperture_id
map_aperture(uint8 bus,uint8 device,uint8 function,size_t size,addr_t * _apertureBase)951481c8841SAxel Dörfler map_aperture(uint8 bus, uint8 device, uint8 function, size_t size,
952481c8841SAxel Dörfler addr_t *_apertureBase)
953481c8841SAxel Dörfler {
954481c8841SAxel Dörfler void *iterator = open_module_list("busses/agp_gart");
955481c8841SAxel Dörfler status_t status = B_ENTRY_NOT_FOUND;
956481c8841SAxel Dörfler Aperture *aperture = NULL;
957481c8841SAxel Dörfler
958481c8841SAxel Dörfler Autolock _(sLock);
959481c8841SAxel Dörfler
960481c8841SAxel Dörfler while (true) {
961481c8841SAxel Dörfler char name[256];
962481c8841SAxel Dörfler size_t nameLength = sizeof(name);
963481c8841SAxel Dörfler if (read_next_module_name(iterator, name, &nameLength) != B_OK)
964481c8841SAxel Dörfler break;
965481c8841SAxel Dörfler
966481c8841SAxel Dörfler agp_gart_bus_module_info *module;
967481c8841SAxel Dörfler if (get_module(name, (module_info **)&module) == B_OK) {
968481c8841SAxel Dörfler void *privateAperture;
969481c8841SAxel Dörfler status = module->create_aperture(bus, device, function, size,
970481c8841SAxel Dörfler &privateAperture);
971481c8841SAxel Dörfler if (status < B_OK) {
972481c8841SAxel Dörfler put_module(name);
973481c8841SAxel Dörfler continue;
974481c8841SAxel Dörfler }
975481c8841SAxel Dörfler
976481c8841SAxel Dörfler aperture = new(std::nothrow) Aperture(module, privateAperture);
977481c8841SAxel Dörfler status = aperture->InitCheck();
978481c8841SAxel Dörfler if (status == B_OK) {
979481c8841SAxel Dörfler if (_apertureBase != NULL)
980481c8841SAxel Dörfler *_apertureBase = aperture->Base();
981481c8841SAxel Dörfler
982481c8841SAxel Dörfler sApertureHashTable.Insert(aperture);
983481c8841SAxel Dörfler } else {
984481c8841SAxel Dörfler delete aperture;
985481c8841SAxel Dörfler aperture = NULL;
986481c8841SAxel Dörfler }
987481c8841SAxel Dörfler break;
988481c8841SAxel Dörfler }
989481c8841SAxel Dörfler }
990481c8841SAxel Dörfler
991481c8841SAxel Dörfler close_module_list(iterator);
992481c8841SAxel Dörfler return aperture != NULL ? aperture->ID() : status;
993481c8841SAxel Dörfler }
994481c8841SAxel Dörfler
995481c8841SAxel Dörfler
996481c8841SAxel Dörfler static aperture_id
map_custom_aperture(gart_bus_module_info * module,addr_t * _apertureBase)997481c8841SAxel Dörfler map_custom_aperture(gart_bus_module_info *module, addr_t *_apertureBase)
998481c8841SAxel Dörfler {
999481c8841SAxel Dörfler return B_ERROR;
1000481c8841SAxel Dörfler }
1001481c8841SAxel Dörfler
1002481c8841SAxel Dörfler
1003481c8841SAxel Dörfler static status_t
unmap_aperture(aperture_id id)1004481c8841SAxel Dörfler unmap_aperture(aperture_id id)
1005481c8841SAxel Dörfler {
1006481c8841SAxel Dörfler Autolock _(sLock);
1007481c8841SAxel Dörfler Aperture *aperture = sApertureHashTable.Lookup(id);
1008481c8841SAxel Dörfler if (aperture == NULL)
1009481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1010481c8841SAxel Dörfler
1011481c8841SAxel Dörfler sApertureHashTable.Remove(aperture);
1012481c8841SAxel Dörfler delete aperture;
1013481c8841SAxel Dörfler return B_OK;
1014481c8841SAxel Dörfler }
1015481c8841SAxel Dörfler
1016481c8841SAxel Dörfler
1017481c8841SAxel Dörfler static status_t
get_aperture_info(aperture_id id,aperture_info * info)1018481c8841SAxel Dörfler get_aperture_info(aperture_id id, aperture_info *info)
1019481c8841SAxel Dörfler {
1020481c8841SAxel Dörfler Aperture *aperture = get_aperture(id);
1021481c8841SAxel Dörfler if (aperture == NULL)
1022481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1023481c8841SAxel Dörfler
1024481c8841SAxel Dörfler Autolock _(aperture->Lock());
1025481c8841SAxel Dörfler return aperture->GetInfo(info);
1026481c8841SAxel Dörfler }
1027481c8841SAxel Dörfler
1028481c8841SAxel Dörfler
1029481c8841SAxel Dörfler static status_t
allocate_memory(aperture_id id,size_t size,size_t alignment,uint32 flags,addr_t * _apertureBase,phys_addr_t * _physicalBase)1030481c8841SAxel Dörfler allocate_memory(aperture_id id, size_t size, size_t alignment, uint32 flags,
10319a063f05SAxel Dörfler addr_t *_apertureBase, phys_addr_t *_physicalBase)
1032481c8841SAxel Dörfler {
1033481c8841SAxel Dörfler if ((flags & ~APERTURE_PUBLIC_FLAGS_MASK) != 0 || _apertureBase == NULL)
1034481c8841SAxel Dörfler return B_BAD_VALUE;
1035481c8841SAxel Dörfler
1036481c8841SAxel Dörfler Aperture *aperture = get_aperture(id);
1037481c8841SAxel Dörfler if (aperture == NULL)
1038481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1039481c8841SAxel Dörfler
1040481c8841SAxel Dörfler size = ROUNDUP(size, B_PAGE_SIZE);
1041481c8841SAxel Dörfler
10427e6d2343SAxel Dörfler Autolock _(aperture->Lock());
10437e6d2343SAxel Dörfler
1044481c8841SAxel Dörfler aperture_memory *memory = aperture->CreateMemory(size, alignment, flags);
1045481c8841SAxel Dörfler if (memory == NULL)
1046481c8841SAxel Dörfler return B_NO_MEMORY;
1047481c8841SAxel Dörfler
1048481c8841SAxel Dörfler status_t status = aperture->AllocateMemory(memory, flags);
1049481c8841SAxel Dörfler if (status == B_OK)
1050103d05f3SAxel Dörfler status = aperture->BindMemory(memory, 0, 0);
1051481c8841SAxel Dörfler if (status < B_OK) {
1052481c8841SAxel Dörfler aperture->DeleteMemory(memory);
1053481c8841SAxel Dörfler return status;
1054481c8841SAxel Dörfler }
1055481c8841SAxel Dörfler
1056481c8841SAxel Dörfler if (_physicalBase != NULL && (flags & B_APERTURE_NEED_PHYSICAL) != 0) {
105721c87a5dSJérôme Duval #if !defined(GART_TEST)
10589a063f05SAxel Dörfler *_physicalBase
10599a063f05SAxel Dörfler = (phys_addr_t)memory->page->physical_page_number * B_PAGE_SIZE;
1060481c8841SAxel Dörfler #else
1061481c8841SAxel Dörfler physical_entry entry;
1062481c8841SAxel Dörfler status = get_memory_map((void *)memory->base, B_PAGE_SIZE, &entry, 1);
1063481c8841SAxel Dörfler if (status < B_OK) {
1064481c8841SAxel Dörfler aperture->DeleteMemory(memory);
1065481c8841SAxel Dörfler return status;
1066481c8841SAxel Dörfler }
1067481c8841SAxel Dörfler
106864d79effSIngo Weinhold *_physicalBase = entry.address;
1069481c8841SAxel Dörfler #endif
1070481c8841SAxel Dörfler }
1071481c8841SAxel Dörfler
1072481c8841SAxel Dörfler *_apertureBase = memory->base;
1073481c8841SAxel Dörfler return B_OK;
1074481c8841SAxel Dörfler }
1075481c8841SAxel Dörfler
1076481c8841SAxel Dörfler
1077481c8841SAxel Dörfler static status_t
free_memory(aperture_id id,addr_t base)1078103d05f3SAxel Dörfler free_memory(aperture_id id, addr_t base)
1079481c8841SAxel Dörfler {
1080481c8841SAxel Dörfler Aperture *aperture = get_aperture(id);
1081481c8841SAxel Dörfler if (aperture == NULL)
1082481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1083481c8841SAxel Dörfler
1084481c8841SAxel Dörfler Autolock _(aperture->Lock());
1085481c8841SAxel Dörfler aperture_memory *memory = aperture->GetMemory(base);
1086481c8841SAxel Dörfler if (memory == NULL)
1087481c8841SAxel Dörfler return B_BAD_VALUE;
1088481c8841SAxel Dörfler
1089481c8841SAxel Dörfler aperture->DeleteMemory(memory);
1090481c8841SAxel Dörfler return B_OK;
1091481c8841SAxel Dörfler }
1092481c8841SAxel Dörfler
1093481c8841SAxel Dörfler
1094481c8841SAxel Dörfler static status_t
reserve_aperture(aperture_id id,size_t size,addr_t * _apertureBase)1095481c8841SAxel Dörfler reserve_aperture(aperture_id id, size_t size, addr_t *_apertureBase)
1096481c8841SAxel Dörfler {
1097481c8841SAxel Dörfler Aperture *aperture = get_aperture(id);
1098481c8841SAxel Dörfler if (aperture == NULL)
1099481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1100481c8841SAxel Dörfler
1101481c8841SAxel Dörfler return B_ERROR;
1102481c8841SAxel Dörfler }
1103481c8841SAxel Dörfler
1104481c8841SAxel Dörfler
1105481c8841SAxel Dörfler static status_t
unreserve_aperture(aperture_id id,addr_t apertureBase)1106481c8841SAxel Dörfler unreserve_aperture(aperture_id id, addr_t apertureBase)
1107481c8841SAxel Dörfler {
1108481c8841SAxel Dörfler Aperture *aperture = get_aperture(id);
1109481c8841SAxel Dörfler if (aperture == NULL)
1110481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1111481c8841SAxel Dörfler
1112481c8841SAxel Dörfler return B_ERROR;
1113481c8841SAxel Dörfler }
1114481c8841SAxel Dörfler
1115481c8841SAxel Dörfler
1116481c8841SAxel Dörfler static status_t
bind_aperture(aperture_id id,area_id area,addr_t base,size_t size,size_t alignment,addr_t reservedBase,addr_t * _apertureBase)1117481c8841SAxel Dörfler bind_aperture(aperture_id id, area_id area, addr_t base, size_t size,
1118103d05f3SAxel Dörfler size_t alignment, addr_t reservedBase, addr_t *_apertureBase)
1119481c8841SAxel Dörfler {
1120481c8841SAxel Dörfler Aperture *aperture = get_aperture(id);
1121481c8841SAxel Dörfler if (aperture == NULL)
1122481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1123481c8841SAxel Dörfler
11247e6d2343SAxel Dörfler if (area < 0) {
1125481c8841SAxel Dörfler if (size == 0 || size > aperture->Size()
11267e6d2343SAxel Dörfler || (base & (B_PAGE_SIZE - 1)) != 0
11277e6d2343SAxel Dörfler || base == 0)
1128481c8841SAxel Dörfler return B_BAD_VALUE;
1129481c8841SAxel Dörfler
1130481c8841SAxel Dörfler size = ROUNDUP(size, B_PAGE_SIZE);
11317e6d2343SAxel Dörfler }
1132481c8841SAxel Dörfler
1133481c8841SAxel Dörfler if (area >= 0) {
1134103d05f3SAxel Dörfler status_t status = get_area_base_and_size(area, base, size);
1135481c8841SAxel Dörfler if (status < B_OK)
1136481c8841SAxel Dörfler return status;
1137481c8841SAxel Dörfler }
1138481c8841SAxel Dörfler
1139481c8841SAxel Dörfler Autolock _(aperture->Lock());
1140481c8841SAxel Dörfler aperture_memory *memory = NULL;
1141481c8841SAxel Dörfler if (reservedBase != 0) {
1142481c8841SAxel Dörfler // use reserved aperture to bind the pages
1143481c8841SAxel Dörfler memory = aperture->GetMemory(reservedBase);
1144481c8841SAxel Dörfler if (memory == NULL)
1145481c8841SAxel Dörfler return B_BAD_VALUE;
1146481c8841SAxel Dörfler } else {
1147481c8841SAxel Dörfler // create new memory object
11487e6d2343SAxel Dörfler memory = aperture->CreateMemory(size, alignment,
11497e6d2343SAxel Dörfler B_APERTURE_NON_RESERVED);
1150481c8841SAxel Dörfler if (memory == NULL)
1151481c8841SAxel Dörfler return B_NO_MEMORY;
1152481c8841SAxel Dörfler }
1153481c8841SAxel Dörfler
1154481c8841SAxel Dörfler // just bind the physical pages backing the memory into the GART
1155481c8841SAxel Dörfler
1156103d05f3SAxel Dörfler status_t status = aperture->BindMemory(memory, base, size);
1157481c8841SAxel Dörfler if (status < B_OK) {
115812d046d0SAdrien Destugues if (reservedBase != 0)
1159481c8841SAxel Dörfler aperture->DeleteMemory(memory);
1160481c8841SAxel Dörfler
1161481c8841SAxel Dörfler return status;
1162481c8841SAxel Dörfler }
1163481c8841SAxel Dörfler
1164481c8841SAxel Dörfler if (_apertureBase != NULL)
1165481c8841SAxel Dörfler *_apertureBase = memory->base;
1166481c8841SAxel Dörfler
1167481c8841SAxel Dörfler return B_OK;
1168481c8841SAxel Dörfler }
1169481c8841SAxel Dörfler
1170481c8841SAxel Dörfler
1171481c8841SAxel Dörfler static status_t
unbind_aperture(aperture_id id,addr_t base)1172481c8841SAxel Dörfler unbind_aperture(aperture_id id, addr_t base)
1173481c8841SAxel Dörfler {
1174481c8841SAxel Dörfler Aperture *aperture = get_aperture(id);
1175481c8841SAxel Dörfler if (aperture == NULL)
1176481c8841SAxel Dörfler return B_ENTRY_NOT_FOUND;
1177481c8841SAxel Dörfler
1178481c8841SAxel Dörfler Autolock _(aperture->Lock());
1179481c8841SAxel Dörfler aperture_memory *memory = aperture->GetMemory(base);
1180481c8841SAxel Dörfler if (memory == NULL || (memory->flags & BIND_APERTURE) == 0)
1181481c8841SAxel Dörfler return B_BAD_VALUE;
1182481c8841SAxel Dörfler
1183481c8841SAxel Dörfler if ((memory->flags & ALLOCATED_APERTURE) != 0)
1184481c8841SAxel Dörfler panic("unbind memory %lx (%p) allocated by agp_gart.", base, memory);
1185481c8841SAxel Dörfler
1186481c8841SAxel Dörfler status_t status = aperture->UnbindMemory(memory);
1187481c8841SAxel Dörfler if (status < B_OK)
1188481c8841SAxel Dörfler return status;
1189481c8841SAxel Dörfler
1190481c8841SAxel Dörfler if ((memory->flags & RESERVED_APERTURE) == 0)
1191481c8841SAxel Dörfler aperture->DeleteMemory(memory);
1192481c8841SAxel Dörfler
1193481c8841SAxel Dörfler return B_OK;
1194481c8841SAxel Dörfler }
1195481c8841SAxel Dörfler
1196481c8841SAxel Dörfler
1197481c8841SAxel Dörfler // #pragma mark -
1198481c8841SAxel Dörfler
1199481c8841SAxel Dörfler
1200481c8841SAxel Dörfler static status_t
agp_init(void)1201481c8841SAxel Dörfler agp_init(void)
1202481c8841SAxel Dörfler {
1203481c8841SAxel Dörfler TRACE("bus manager init\n");
1204481c8841SAxel Dörfler
1205481c8841SAxel Dörfler if (get_module(B_PCI_MODULE_NAME, (module_info **)&sPCI) != B_OK)
1206481c8841SAxel Dörfler return B_ERROR;
1207481c8841SAxel Dörfler
1208481c8841SAxel Dörfler uint32 cookie = 0;
1209481c8841SAxel Dörfler sDeviceCount = 0;
1210481c8841SAxel Dörfler pci_info info;
1211481c8841SAxel Dörfler while (get_next_agp_device(&cookie, info, sDeviceInfos[sDeviceCount])
1212481c8841SAxel Dörfler == B_OK) {
1213481c8841SAxel Dörfler sDeviceCount++;
1214481c8841SAxel Dörfler }
1215481c8841SAxel Dörfler
121682c2deb5SJérôme Duval TRACE("found %" B_PRId32 " AGP devices\n", sDeviceCount);
1217481c8841SAxel Dörfler
1218481c8841SAxel Dörfler // Since there can be custom aperture modules (for memory management only),
1219481c8841SAxel Dörfler // we always succeed if we could get the resources we need.
1220481c8841SAxel Dörfler
1221481c8841SAxel Dörfler new(&sApertureHashTable) ApertureHashTable();
1222481c8841SAxel Dörfler return init_lock(&sLock, "agp_gart");
1223481c8841SAxel Dörfler }
1224481c8841SAxel Dörfler
1225481c8841SAxel Dörfler
1226481c8841SAxel Dörfler void
agp_uninit(void)1227481c8841SAxel Dörfler agp_uninit(void)
1228481c8841SAxel Dörfler {
1229481c8841SAxel Dörfler TRACE("bus manager uninit\n");
1230481c8841SAxel Dörfler
1231481c8841SAxel Dörfler ApertureHashTable::Iterator iterator = sApertureHashTable.GetIterator();
1232481c8841SAxel Dörfler while (iterator.HasNext()) {
1233481c8841SAxel Dörfler Aperture *aperture = iterator.Next();
1234481c8841SAxel Dörfler sApertureHashTable.Remove(aperture);
1235481c8841SAxel Dörfler delete aperture;
1236481c8841SAxel Dörfler }
1237481c8841SAxel Dörfler
1238481c8841SAxel Dörfler put_module(B_PCI_MODULE_NAME);
1239481c8841SAxel Dörfler }
1240481c8841SAxel Dörfler
1241481c8841SAxel Dörfler
1242481c8841SAxel Dörfler static int32
agp_std_ops(int32 op,...)1243481c8841SAxel Dörfler agp_std_ops(int32 op, ...)
1244481c8841SAxel Dörfler {
1245481c8841SAxel Dörfler switch (op) {
1246481c8841SAxel Dörfler case B_MODULE_INIT:
1247481c8841SAxel Dörfler return agp_init();
1248481c8841SAxel Dörfler case B_MODULE_UNINIT:
1249481c8841SAxel Dörfler agp_uninit();
1250481c8841SAxel Dörfler return B_OK;
1251481c8841SAxel Dörfler }
1252481c8841SAxel Dörfler
1253481c8841SAxel Dörfler return B_BAD_VALUE;
1254481c8841SAxel Dörfler }
1255481c8841SAxel Dörfler
1256481c8841SAxel Dörfler
1257481c8841SAxel Dörfler static struct agp_gart_module_info sAGPModuleInfo = {
1258481c8841SAxel Dörfler {
1259481c8841SAxel Dörfler {
1260481c8841SAxel Dörfler B_AGP_GART_MODULE_NAME,
1261481c8841SAxel Dörfler B_KEEP_LOADED, // Keep loaded, even if no driver requires it
1262481c8841SAxel Dörfler agp_std_ops
1263481c8841SAxel Dörfler },
1264481c8841SAxel Dörfler NULL // the rescan function
1265481c8841SAxel Dörfler },
1266481c8841SAxel Dörfler get_nth_agp_info,
1267481c8841SAxel Dörfler acquire_agp,
1268481c8841SAxel Dörfler release_agp,
1269481c8841SAxel Dörfler set_agp_mode,
1270481c8841SAxel Dörfler
1271481c8841SAxel Dörfler map_aperture,
1272481c8841SAxel Dörfler map_custom_aperture,
1273481c8841SAxel Dörfler unmap_aperture,
1274481c8841SAxel Dörfler get_aperture_info,
1275481c8841SAxel Dörfler allocate_memory,
1276103d05f3SAxel Dörfler free_memory,
1277481c8841SAxel Dörfler reserve_aperture,
1278481c8841SAxel Dörfler unreserve_aperture,
1279481c8841SAxel Dörfler bind_aperture,
1280481c8841SAxel Dörfler unbind_aperture,
1281481c8841SAxel Dörfler };
1282481c8841SAxel Dörfler
1283481c8841SAxel Dörfler module_info *modules[] = {
1284481c8841SAxel Dörfler (module_info *)&sAGPModuleInfo,
1285481c8841SAxel Dörfler NULL
1286481c8841SAxel Dörfler };
1287