1/*
2 * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 2.0 (the
8 * "License").  You may not use this file except in compliance with the
9 * License.  Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23#include <IOKit/assert.h>
24#include <IOKit/IODeviceTreeSupport.h>
25#include <IOKit/IOPlatformExpert.h>
26#include <IOKit/pci/IOPCIPrivate.h>
27#include <IOKit/pci/IOPCIConfigurator.h>
28#if ACPI_SUPPORT
29#include <IOKit/acpi/IOACPIPlatformDevice.h>
30#endif
31#include <libkern/sysctl.h>
32
33__BEGIN_DECLS
34
35#if defined(__i386__) || defined(__x86_64__)
36
37#include <i386/cpuid.h>
38#include <i386/cpu_number.h>
39
40extern void mp_rendezvous_no_intrs(
41               void (*action_func)(void *),
42               void *arg);
43
44#else /* defined(__i386__) || defined(__x86_64__) */
45
46#define NO_RENDEZVOUS_KERNEL    1
47#define cpu_number()    (0)
48
49#define KB		(1024ULL)
50#define MB		(1024ULL*KB)
51#define GB		(1024ULL*MB)
52
53#endif /* ! defined(__i386__) || defined(__x86_64__) */
54
55__END_DECLS
56
57#define PFM64_SIZE    (2ULL*GB)
58#define MAX_BAR_SIZE  (1ULL*GB)
59// NPHYSMAP
60// #define PFM64_MAX     (100ULL*GB)
61
62#define DLOGC(configurator, fmt, args...)                  \
63    do {                                    \
64        if ((configurator->fFlags & kIOPCIConfiguratorIOLog) && !ml_at_interrupt_context())   \
65            IOLog(fmt, ## args);            \
66        if (configurator->fFlags & kIOPCIConfiguratorKPrintf) \
67            kprintf(fmt, ## args);          \
68    } while(0)
69
70
71#define DLOG(fmt, args...)      DLOGC(this, fmt, ## args);
72#define DLOGI(fmt, args...)     do { if (dolog) DLOG(fmt, ## args); } while (0);
73
74#define DLOG_RANGE(name, range) if (range) {                                \
75                DLOG(name": start/size   = 0x%08llx:0x%08llx,0x%08llx\n",  \
76                                        range->start,                       \
77                                        range->size,                        \
78                                        range->proposedSize) }
79
80#define DLOGI_RANGE(name, range)  do { if (dolog) DLOG_RANGE(name, range); } while (0);
81
82static const char * gPCIResourceTypeName[kIOPCIResourceTypeCount] =
83{
84    "MEM", "PFM", "I/O", "BUS"
85};
86
87#define BRN(type)      ((type) + kIOPCIRangeBridgeMemory)
88
89
90#define D() "[i%x]%u:%u:%u(0x%x:0x%x)"
91#define DEVICE_IDENT(device)				\
92		device->id, 						\
93		PCI_ADDRESS_TUPLE(device),			\
94		(device->vendorProduct & 0xffff), 	\
95		(device->vendorProduct >> 16)
96
97#define B() "[i%x]%u:%u:%u(%u:%u)"
98#define BRIDGE_IDENT(bridge)	\
99		bridge->id, PCI_ADDRESS_TUPLE(bridge), bridge->secBusNum, bridge->subBusNum
100
101
102static const IOPCIScalar minBridgeAlignments[kIOPCIResourceTypeCount] = {
103    kPCIBridgeMemoryAlignment, kPCIBridgeMemoryAlignment,
104    kPCIBridgeIOAlignment, kPCIBridgeBusNumberAlignment
105};
106
107static const IOPCIScalar maxBridgeAddressDefault[kIOPCIResourceTypeCount] = {
108    0xFFFFFFFF, 0xFFFFFFFF,
109    0xFFFF, 0xFF
110};
111
112// Never allocate ranges below 1K I/O and 1MB Memory to avoid
113// stomping on legacy ISA, and VGA ranges.
114static const IOPCIScalar minBARAddressDefault[kIOPCIResourceTypeCount] = {
115    kPCIBridgeMemoryAlignment, kPCIBridgeMemoryAlignment,
116    0x400, 0
117};
118
119static UInt8 IOPCIIsHotplugPort(IORegistryEntry * bridgeDevice);
120#if ACPI_SUPPORT
121static IOACPIPlatformDevice * IOPCICopyACPIDevice(IORegistryEntry * device);
122#endif
123
124/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
125
126#define CLASS IOPCIConfigurator
127#define super IOService
128
129OSDefineMetaClassAndStructors( IOPCIConfigurator, IOService )
130
131/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
132
133bool CLASS::init(IOWorkLoop * wl, uint32_t flags)
134{
135    if (!super::init()) return false;
136
137    fWL    = wl;
138    fFlags = flags;
139
140    // Fetch global resources
141    if (!createRoot()) return false;
142
143    return (true);
144}
145
146IOWorkLoop * CLASS::getWorkLoop() const
147{
148    return (fWL);
149}
150
151/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
152
153IOPCIConfigEntry * CLASS::findEntry(IOPCIAddressSpace space)
154{
155    IOPCIConfigEntry * child;
156    IOPCIConfigEntry * entry;
157    IOPCIConfigEntry * next;
158    uint8_t            bus, dev, func;
159
160    bus   = space.s.busNum;
161    dev   = space.s.deviceNum;
162    func  = space.s.functionNum;
163    next  = fRoot;
164    child = NULL;
165
166    while ((entry = next))
167    {
168        next = NULL;
169        for (child = entry->child; child; child = child->peer)
170        {
171            if (bus == entry->secBusNum)
172            {
173                if (dev  != child->space.s.deviceNum)   continue;
174                if (func != child->space.s.functionNum) continue;
175                break;
176            }
177            if (!child->isBridge)            continue;
178            else if (bus < child->secBusNum) continue;
179            else if (bus > child->subBusNum) continue;
180            next = child;
181            break;
182        }
183    }
184
185    return (child);
186}
187/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
188
189IOReturn CLASS::configOp(IOService * device, uintptr_t op, void * arg, void * arg2)
190{
191    IOReturn           ret = kIOReturnUnsupported;
192    IOPCIConfigEntry * entry = NULL;
193    IOPCIDevice *      pciDevice;
194
195    if ((pciDevice = OSDynamicCast(IOPCIDevice, device)))
196        entry = pciDevice->reserved->configEntry;
197
198    switch (op)
199    {
200        case kConfigOpAddHostBridge:
201            ret = addHostBridge(OSDynamicCast(IOPCIBridge, device));
202			return (ret);
203            break;
204
205        case kConfigOpGetState:
206			if (!entry) *((uint32_t *) arg) = kPCIDeviceStateDead;
207			else
208			{
209				*((uint32_t *) arg) = entry->deviceState;
210			}
211			ret = kIOReturnSuccess;
212			return (ret);
213            break;
214
215
216		case kConfigOpFindEntry:
217            entry = findEntry(*((IOPCIAddressSpace *) arg2));
218            *((void **) arg) = NULL;
219            if (!entry || !entry->dtNub) ret = kIOReturnNotFound;
220            else
221            {
222                entry->dtNub->retain();
223                *((void **) arg) = entry->dtNub;
224                ret = kIOReturnSuccess;
225            }
226			return (ret);
227            break;
228    }
229
230	if (!entry) return (kIOReturnBadArgument);
231
232	switch (op)
233    {
234        case kConfigOpNeedsScan:
235			entry->deviceState &= ~kPCIDeviceStateScanned;
236			ret = kIOReturnSuccess;
237            break;
238
239        case kConfigOpShadowed:
240			entry->configShadow = (uint8_t *) arg;
241			ret = kIOReturnSuccess;
242			if (!arg) break;
243			/* fall thru */
244        case kConfigOpPaused:
245			DLOG("kConfigOpPaused%s at "D()"\n",
246				op == kConfigOpShadowed ? "(shadowed)" : "", DEVICE_IDENT(entry));
247
248			if (kPCIDeviceStateRequestPause & entry->deviceState)
249			{
250				entry->deviceState &= ~kPCIDeviceStateRequestPause;
251				entry->deviceState &= ~kPCIDeviceStateAllocated;
252				fWaitingPause--;
253			}
254			if (!(kPCIDeviceStatePaused & entry->deviceState))
255			{
256#if 0
257				uint32_t reg32;
258				reg32 = entry->pausedCommand = configRead16(entry, kIOPCIConfigCommand);
259				reg32 &= ~(kIOPCICommandIOSpace
260					     | kIOPCICommandMemorySpace
261					     | kIOPCICommandBusMaster);
262				reg32  |= kIOPCICommandInterruptDisable;
263				configWrite16(entry, kIOPCIConfigCommand, reg32);
264
265				if (entry->isBridge)
266				{
267					entry->rangeBaseChanges |= (1 << kIOPCIRangeBridgeBusNumber);
268					reg32 = configRead32(entry, kPCI2PCIPrimaryBus);
269					reg32 &= ~0x00ffffff;
270					configWrite32(entry, kPCI2PCIPrimaryBus, reg32);
271				}
272#endif
273				entry->deviceState |= kPCIDeviceStatePaused;
274			}
275			ret = kIOReturnSuccess;
276            break;
277
278        case kConfigOpUnpaused:
279			if (kPCIDeviceStatePaused & entry->deviceState)
280			{
281				DLOG("kConfigOpUnpaused at "D()"\n", DEVICE_IDENT(entry));
282//				configWrite16(entry, kIOPCIConfigCommand, entry->pausedCommand);
283				entry->deviceState &= ~kPCIDeviceStatePaused;
284			}
285			ret = kIOReturnSuccess;
286            break;
287
288        case kConfigOpTestPause:
289			ret = kIOReturnSuccess;
290            break;
291
292        case kConfigOpScan:
293			if (kPCIDeviceStateScanned & entry->deviceState)
294			{
295				*((void **)arg) = NULL;
296				ret = kIOReturnSuccess;
297				return (ret);
298				break;
299			}
300
301			// always reset regs due to hotp interrupt clearing memory ranges
302			entry->rangeBaseChanges |= ((1 << kIOPCIRangeBridgeMemory)
303									  |  (1 << kIOPCIRangeBridgePFMemory));
304
305			// fall thru
306
307        case kConfigOpRealloc:
308
309			DLOG("[ PCI configuration begin ]\n");
310			fChangedServices = OSSet::withCapacity(8);
311			configure(0);
312			DLOG("[ PCI configuration end, bridges %d, devices %d, changed %d, waiting %d ]\n",
313				  fBridgeCount, fDeviceCount, fChangedServices->getCount(), fWaitingPause);
314
315			if (arg)
316			{
317				*((void **)arg) = fChangedServices;
318			}
319			else
320			{
321				fChangedServices->release();
322			}
323			fChangedServices = 0;
324			ret = kIOReturnSuccess;
325			return (ret);
326            break;
327
328
329        case kConfigOpEject:
330			entry->deviceState |= kPCIDeviceStateEjected;
331			ret = kIOReturnSuccess;
332            break;
333
334        case kConfigOpKill:
335			entry->deviceState |= kPCIDeviceStateToKill;
336			ret = kIOReturnSuccess;
337            break;
338
339        case kConfigOpTerminated:
340			DLOG("kConfigOpTerminated at "D()"\n", DEVICE_IDENT(entry));
341
342//			if (0x590111c1 != entry->vendorProduct)
343//          if (!(kPCIDeviceStateEjected & entry->deviceState))
344			{
345				bridgeRemoveChild(entry->parent, entry,
346									kIOPCIRangeAllBarsMask, kIOPCIRangeAllBarsMask, NULL);
347			}
348			ret = kIOReturnSuccess;
349            break;
350
351		case kConfigOpProtect:
352			entry->deviceState = (entry->deviceState & ~(kPCIDeviceStateConfigRProtect|kPCIDeviceStateConfigWProtect))
353								| (*((uint32_t *) arg));
354			DLOG("kConfigOpProtect at "D()" prot %x\n",
355				 DEVICE_IDENT(entry), *((uint32_t *) arg));
356
357			ret = kIOReturnSuccess;
358            break;
359    }
360
361    return (ret);
362}
363
364/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
365
366#if ACPI_SUPPORT
367void CLASS::removeFixedRanges(IORegistryEntry * root)
368{
369	IORegistryIterator * iter;
370	IOService *          service;
371	OSOrderedSet *       all;
372	OSArray *            array;
373	IOMemoryDescriptor * mem;
374	uint32_t             idx, type;
375    IOPCIRange *         range;
376    uint64_t             start, size;
377	bool                 ok;
378
379	range = NULL;
380	iter = IORegistryIterator::iterateOver(root, gIOPCIACPIPlane, kIORegistryIterateRecursively);
381	if (iter)
382	{
383		all = iter->iterateAll();
384		iter->release();
385		if (all)
386		{
387			for ( ; (service = (IOService *) all->getFirstObject()); all->removeObject(service))
388			{
389				array = service->getDeviceMemory();
390				if (!array)
391					continue;
392				for (idx = 0; (mem = (IOMemoryDescriptor *) array->getObject(idx)); idx++)
393				{
394					type  = mem->getTag();
395					start = mem->getPhysicalSegment(0, NULL, kIOMemoryMapperNone);
396					size  = mem->getLength();
397					if (kIOACPIMemoryRange == type)
398						type = kIOPCIResourceTypeMemory;
399					else if (kIOACPIIORange == type)
400					{
401						if (start < 0x1000)
402							continue;
403						if ((start == 0xFFFF) && (size == 0x0001))
404							continue;
405						type = kIOPCIResourceTypeIO;
406					}
407					else
408						continue;
409					if (!range)
410						range = IOPCIRangeAlloc();
411					IOPCIRangeInit(range, type, start, size, 1);
412					ok = IOPCIRangeListAllocateSubRange(fRoot->ranges[BRN(type)], range);
413					DLOG("%s: %sfixed alloc type %d, 0x%llx len 0x%llx\n",
414							service->getName(), ok ? "" : "!", type, start, size);
415					if (ok)
416						range = NULL;
417				}
418			}
419			all->release();
420		}
421	}
422	if (range)
423		IOPCIRangeFree(range);
424}
425#endif
426
427bool CLASS::createRoot(void)
428{
429    IOPCIConfigEntry * root;
430    IOPCIRange *       range;
431    uint64_t           start, size;
432	uint32_t           cpuPhysBits;
433
434    root = IONew(IOPCIConfigEntry, 1);
435    if (!root) return (false);
436
437    memset(root, 0, sizeof(*root));
438
439    root->id           = ++fNextID;
440    root->isHostBridge = true;
441    root->isBridge     = true;
442
443    root->secBusNum    = 0xff;
444
445#if defined(__i386__) || defined(__x86_64__)
446	cpuPhysBits = cpuid_info()->cpuid_address_bits_physical;
447    size  = PFM64_SIZE;
448	if (cpuPhysBits > 44) cpuPhysBits = 44;
449	start = (1ULL << cpuPhysBits);
450//	if (start > PFM64_MAX) start = PFM64_MAX;
451#if PLX8680
452	if (cpuPhysBits >= 36) size *= 16; // 32GB
453#endif
454	start -= size;
455	IOLog("pci (build %s %s), flags 0x%x, pfm64 (%d cpu) 0x%llx, 0x%llx\n",
456			__TIME__, __DATE__, gIOPCIFlags, cpuPhysBits, start, size);
457	kprintf("pci (build %s %s), flags 0x%x, pfm64 (%d cpu) 0x%llx, 0x%llx\n",
458			__TIME__, __DATE__, gIOPCIFlags, cpuPhysBits, start, size);
459	if (cpuPhysBits > 32)
460	{
461		range = IOPCIRangeAlloc();
462		IOPCIRangeInitAlloc(range, kIOPCIResourceTypeMemory, start, size, 1);
463		root->ranges[kIOPCIRangeBridgeMemory] = range;
464	}
465
466#else /* defined(__i386__) || defined(__x86_64__) */
467
468	IOLog  ("pci (build %s %s), flags 0x%x\n", __TIME__, __DATE__, gIOPCIFlags);
469	kprintf("pci (build %s %s), flags 0x%x\n", __TIME__, __DATE__, gIOPCIFlags);
470
471#endif /* !defined(__i386__) || defined(__x86_64__) */
472
473    root->deviceState |= kPCIDeviceStateScanned | kPCIDeviceStateConfigurationDone;
474    fRoot = root;
475
476    return (true);
477}
478
479IOReturn CLASS::addHostBridge(IOPCIBridge * hostBridge)
480{
481    IOPCIConfigEntry * bridge;
482	IOPCIAddressSpace  space;
483    IOPCIRange *       range;
484    uint64_t           start, size;
485
486    bridge = IONew(IOPCIConfigEntry, 1);
487    if (!bridge) return (kIOReturnNoMemory);
488
489    memset(bridge, 0, sizeof(*bridge));
490    bridge->id           = ++fNextID;
491    bridge->classCode    = 0x060000;
492    bridge->headerType   = kPCIHeaderType1;
493    bridge->secBusNum    = hostBridge->firstBusNum();
494    bridge->subBusNum    = hostBridge->lastBusNum();
495//#warning bus52
496//    if (bridge->subBusNum > 250) bridge->subBusNum = 52;
497    bridge->space        = hostBridge->getBridgeSpace();
498
499    bridge->dtNub           = hostBridge->getProvider();
500    bridge->dtEntry         = bridge->dtNub;
501#if ACPI_SUPPORT
502    bridge->acpiDevice      = IOPCICopyACPIDevice(bridge->dtNub);
503#endif
504    bridge->isHostBridge    = true;
505    bridge->isBridge        = true;
506    bridge->supportsHotPlug = false;
507
508    if (OSDynamicCast(IOPCIDevice, bridge->dtNub)) panic("!host bridge");
509
510    // fix - all config cycles use first host bridge
511    if (!fHostBridge)
512	{
513        fHostBridge = hostBridge;
514		space.bits = 0;
515        fRootVendorProduct = configRead32(space, kIOPCIConfigVendorID);
516#if defined(__i386__) || defined(__x86_64__)
517		if ( (0x27A08086 == fRootVendorProduct)
518		  || (0x27AC8086 == fRootVendorProduct)
519		  || (0x25C08086 == fRootVendorProduct)
520	      || (CPUID_FEATURE_VMM & cpuid_features()))
521#endif
522			fFlags &= ~kIOPCIConfiguratorPFM64;
523		DLOG("root id 0x%x, flags 0x%x\n", fRootVendorProduct, (int) fFlags);
524	}
525
526    range = IOPCIRangeAlloc();
527    start = bridge->secBusNum;
528    size  = bridge->subBusNum - bridge->secBusNum + 1;
529
530    DLOG("host bridge acpi bus range 0x%llx len 0x%llx\n", start, size);
531
532    IOPCIRangeInitAlloc(range, kIOPCIResourceTypeBusNumber, start, size, kPCIBridgeBusNumberAlignment);
533    bridge->ranges[kIOPCIRangeBridgeBusNumber] = range;
534
535    DLOG("added(%s) host bridge resource %s 0x%llx len 0x%llx\n",
536        "ok", gPCIResourceTypeName[kIOPCIResourceTypeBusNumber],
537        range->start, range->size);
538
539    for (int type = 0; type < kIOPCIResourceTypeCount; type++)
540    {
541        IOPCIRange * thisRange;
542        for (thisRange = hostBridge->reserved->rangeLists[type];
543			 thisRange;
544			 thisRange = thisRange->next)
545        {
546            bool ok;
547			start = thisRange->start;
548			size  = thisRange->size;
549            DLOG("reported host bridge resource %s 0x%llx len 0x%llx\n",
550                gPCIResourceTypeName[type],
551                start, size);
552            ok = IOPCIRangeListAddRange(&fRoot->ranges[BRN(type)],
553                                        type, start, size);
554            DLOG("added(%s) host bridge resource %s 0x%llx len 0x%llx\n",
555                ok ? "ok" : "!", gPCIResourceTypeName[type],
556                start, size);
557        }
558    }
559
560#if ACPI_SUPPORT
561	if (bridge->acpiDevice)
562		removeFixedRanges(bridge->acpiDevice);
563#endif
564
565    bridge->deviceState |= kPCIDeviceStateConfigurationDone;
566
567    bridgeAddChild(fRoot, bridge);
568
569    configure(kIOPCIConfiguratorBoot);
570
571    return (kIOReturnSuccess);
572}
573
574void CLASS::free( void )
575{
576    super::free();
577}
578
579//---------------------------------------------------------------------------
580
581void CLASS::constructAddressingProperties(IOPCIConfigEntry * device, OSDictionary * propTable)
582{
583    IOPCIRange *         range;
584    IOPCIPhysicalAddress regData;
585    OSString *           string;
586    OSData *             prop;
587    OSData *             regProp;
588    OSData *             assignedProp;
589    OSData *             rangeProp;
590    char                 tuple[64];
591    size_t               len;
592
593    len = snprintf(tuple, sizeof(tuple), "%u:%u:%u", PCI_ADDRESS_TUPLE(device));
594    if (device->isBridge && (len < sizeof(tuple)))
595    {
596        snprintf(&tuple[len], sizeof(tuple) - len, "(%u:%u)", device->secBusNum, device->subBusNum);
597    }
598    string = OSString::withCString(tuple);
599    if (string)
600    {
601        propTable->setObject("pcidebug", string);
602        string->release();
603    }
604
605    assignedProp = OSData::withCapacity(32);
606    regProp      = OSData::withCapacity(32);
607    rangeProp    = OSData::withCapacity(32);
608    if (!assignedProp || !regProp || !rangeProp)
609        return;
610
611    regData.physHi  = device->space;
612    regData.physMid = 0;
613    regData.physLo  = 0;
614    regData.lengthHi  = 0;
615    regData.lengthLo  = 0;
616    regProp->appendBytes(&regData, sizeof(regData));
617
618    for (uint32_t i = 0; i < kIOPCIRangeCount; i++)
619    {
620        static const uint8_t barRegisters[kIOPCIRangeExpansionROM + 1] = {
621            kIOPCIConfigBaseAddress0, kIOPCIConfigBaseAddress1, kIOPCIConfigBaseAddress2,
622            kIOPCIConfigBaseAddress3, kIOPCIConfigBaseAddress4, kIOPCIConfigBaseAddress5,
623            kIOPCIConfigExpansionROMBase
624        };
625
626        range = device->ranges[i];
627        if (!range)
628            continue;
629        if (kIOPCIResourceTypeBusNumber == range->type)
630            continue;
631
632        regData.physHi = device->space;
633        switch (range->type)
634        {
635          case kIOPCIResourceTypeMemory:
636            regData.physHi.s.space    = kIOPCI32BitMemorySpace;
637            break;
638          case kIOPCIResourceTypePrefetchMemory:
639            regData.physHi.s.space    = kIOPCI32BitMemorySpace;
640            regData.physHi.s.prefetch = 1;
641            break;
642
643          case kIOPCIResourceTypeIO:
644            regData.physHi.s.space    = kIOPCIIOSpace;
645            break;
646        }
647
648        regData.physMid  = 0;
649        regData.physLo   = 0;
650        regData.lengthHi = (range->size >> 32ULL);
651        regData.lengthLo = range->size;
652        if (i <= kIOPCIRangeExpansionROM)
653        {
654            regData.physHi.s.registerNum = barRegisters[i];
655            if (range->start)
656            {
657				IOPCIPhysicalAddress assignedData;
658				assignedData = regData;
659                assignedData.physHi.s.reloc = 1;
660                assignedData.physMid = (range->start >> 32ULL);
661                assignedData.physLo  = range->start;
662                assignedProp->appendBytes(&assignedData, sizeof(assignedData));
663            }
664			// reg gets requested length
665			regData.lengthHi             = (range->proposedSize >> 32ULL);
666			regData.lengthLo             = range->proposedSize;
667            regProp->appendBytes(&regData, sizeof(regData));
668        }
669        else
670        {
671            regData.physHi.s.reloc       = 1;
672            regData.physMid              = (range->start >> 32ULL);
673            regData.physLo               = range->start;
674            regData.physHi.s.busNum      = 0;
675            regData.physHi.s.deviceNum   = 0;
676            regData.physHi.s.functionNum = 0;
677            regData.physHi.s.registerNum = 0;
678            rangeProp->appendBytes(&regData, sizeof(regData.physHi) + sizeof(regData.physMid) + sizeof(regData.physLo));
679            rangeProp->appendBytes(&regData, sizeof(regData));
680        }
681    }
682    propTable->setObject("reg", regProp);
683    regProp->release();
684    if (assignedProp->getLength())
685        propTable->setObject("assigned-addresses", assignedProp);
686    assignedProp->release();
687    if (rangeProp->getLength())
688    {
689        propTable->setObject("ranges", rangeProp);
690
691        regData.lengthLo = 3;
692        prop = OSData::withBytes(&regData.lengthLo, sizeof(regData.lengthLo));
693        if (prop)
694        {
695            propTable->setObject("#address-cells", prop );
696            prop->release();
697        }
698        regData.lengthLo = 2;
699        prop = OSData::withBytes(&regData.lengthLo, sizeof(regData.lengthLo));
700        if (prop)
701        {
702            propTable->setObject("#size-cells", prop );
703            prop->release();
704        }
705    }
706    rangeProp->release();
707}
708
709OSDictionary * CLASS::constructProperties(IOPCIConfigEntry * device)
710{
711    OSDictionary *      propTable;
712    uint32_t            value;
713    uint32_t            vendor, product, classCode, revID;
714    uint32_t            subVendor = 0, subProduct = 0;
715    OSData *            prop;
716    const char *        name;
717    const OSSymbol *    nameProp;
718    char                compatBuf[128];
719    char *              out;
720
721    struct IOPCIGenericNames
722    {
723        const char *    name;
724        UInt32          mask;
725        UInt32          classCode;
726    };
727    static const IOPCIGenericNames genericNames[] = {
728                { "display",    0xffffff, 0x000100 },
729                { "scsi",       0xffff00, 0x010000 },
730                { "ethernet",   0xffff00, 0x020000 },
731                { "display",    0xff0000, 0x030000 },
732                { "pci-bridge", 0xffff00, 0x060400 },
733                { 0, 0, 0 }
734            };
735    const IOPCIGenericNames *   nextName;
736
737    propTable = OSDictionary::withCapacity( 8 );
738    if (!propTable)
739        return (NULL);
740
741    constructAddressingProperties(device, propTable);
742
743    value = configRead32( device, kIOPCIConfigVendorID );
744    vendor = value & 0xffff;
745    product = value >> 16;
746
747    prop = OSData::withBytes( &vendor, sizeof(vendor) );
748    if (prop)
749    {
750        propTable->setObject("vendor-id", prop );
751        prop->release();
752    }
753
754    prop = OSData::withBytes( &product, sizeof(product) );
755    if (prop)
756    {
757        propTable->setObject("device-id", prop );
758        prop->release();
759    }
760
761    value = configRead32( device, kIOPCIConfigRevisionID );
762    revID = value & 0xff;
763    prop = OSData::withBytes( &revID, sizeof(revID) );
764    if (prop)
765    {
766        propTable->setObject("revision-id", prop );
767        prop->release();
768    }
769
770    classCode = value >> 8;
771    prop = OSData::withBytes( &classCode, sizeof(classCode) );
772    if (prop)
773    {
774        propTable->setObject("class-code", prop );
775        prop->release();
776    }
777
778    // make generic name
779
780    name = 0;
781    for (nextName = genericNames;
782            (0 == name) && nextName->name;
783            nextName++)
784    {
785        if ((classCode & nextName->mask) == nextName->classCode)
786            name = nextName->name;
787    }
788
789    // or name from IDs
790
791    value = configRead32( device, kIOPCIConfigSubSystemVendorID );
792    if (value)
793    {
794        subVendor = value & 0xffff;
795        subProduct = value >> 16;
796
797        prop = OSData::withBytes( &subVendor, sizeof(subVendor) );
798        if (prop)
799        {
800            propTable->setObject("subsystem-vendor-id", prop );
801            prop->release();
802        }
803        prop = OSData::withBytes( &subProduct, sizeof(subProduct) );
804        if (prop)
805        {
806            propTable->setObject("subsystem-id", prop );
807            prop->release();
808        }
809    }
810
811    out = compatBuf;
812    if ((subVendor || subProduct)
813            && ((subVendor != vendor) || (subProduct != product)))
814        out += snprintf(out, sizeof("pcivvvv,pppp"), "pci%x,%x", subVendor, subProduct) + 1;
815
816    if (0 == name)
817        name = out;
818
819    out += snprintf(out, sizeof("pcivvvv,pppp"), "pci%x,%x", vendor, product) + 1;
820    out += snprintf(out, sizeof("pciclass,cccccc"), "pciclass,%06x", classCode) + 1;
821
822    if (device->dtEntry && ((nameProp = device->dtEntry->copyName())))
823	{
824		out += strlcpy(out, nameProp->getCStringNoCopy(), 31) + 1;
825		nameProp->release();
826	}
827
828    prop = OSData::withBytes( compatBuf, out - compatBuf );
829    if (prop)
830    {
831        propTable->setObject("compatible", prop );
832        prop->release();
833    }
834
835    nameProp = OSSymbol::withCString( name );
836    if (nameProp)
837    {
838        propTable->setObject( gIONameKey, (OSSymbol *) nameProp);
839        nameProp->release();
840    }
841
842    prop = OSData::withBytes( name, strlen(name) + 1 );
843    if (prop)
844    {
845        propTable->setObject("name", prop );
846        prop->release();
847    }
848
849    OSNumber * num;
850	if ((3 == (classCode >> 16))
851	 && (0x8086 == vendor)
852	 && (!(kIOPCIConfiguratorIGIsMapped & fFlags))
853	 && (num = OSNumber::withNumber(kIOMemoryMapperNone, 32)))
854	{
855		propTable->setObject(kIOMemoryDescriptorOptionsKey, num);
856		num->release();
857	}
858
859    if (kPCIHotPlugRoot == device->supportsHotPlug)
860        propTable->setObject(kIOPCIHotPlugKey, kOSBooleanTrue);
861    else if (kPCILinkChange == device->supportsHotPlug)
862        propTable->setObject(kIOPCILinkChangeKey, kOSBooleanTrue);
863
864	if (kPCIHotPlugTunnel == device->parent->supportsHotPlug)
865        propTable->setObject(kIOPCITunnelledKey, kOSBooleanTrue);
866
867	if (device->linkInterrupts)
868        propTable->setObject(kIOPCITunnelLinkChangeKey, kOSBooleanTrue);
869
870	if (device->linkInterrupts || (kPCIHotPlugRoot == device->supportsHotPlug))
871	{
872		bool bootDefer = (kIOPCIConfiguratorBootDefer == (kIOPCIConfiguratorBootDefer & fFlags));
873		if (bootDefer)
874			propTable->setObject(kIOPCITunnelBootDeferKey, kOSBooleanTrue);
875		else if (!(kPCIDeviceStateNoLink & device->deviceState))
876			propTable->setObject(kIOPCIOnlineKey, kOSBooleanTrue);
877	}
878
879#if PLX8680
880    if (device->plxAperture
881        && (num = OSNumber::withNumber(device->plxAperture, 64)))
882	{
883		propTable->setObject("IODMAAddressAperture", num);
884		num->release();
885	}
886#endif /* PLX8680 */
887
888    return (propTable);
889}
890
891//---------------------------------------------------------------------------
892
893#if ACPI_SUPPORT
894
895static IOACPIPlatformDevice * IOPCICopyACPIDevice( IORegistryEntry * device )
896{
897    IOACPIPlatformDevice * acpiDevice = 0;
898    OSString *             acpiPath;
899
900    if (device)
901    {
902        acpiPath = (OSString *) device->copyProperty(kACPIDevicePathKey);
903        if (acpiPath && !OSDynamicCast(OSString, acpiPath))
904        {
905            acpiPath->release();
906            acpiPath = 0;
907        }
908
909        if (acpiPath)
910        {
911            IORegistryEntry * entry;
912
913            entry = IORegistryEntry::fromPath(acpiPath->getCStringNoCopy());
914            acpiPath->release();
915
916            if (entry && entry->metaCast("IOACPIPlatformDevice"))
917                acpiDevice = (IOACPIPlatformDevice *) entry;
918            else if (entry)
919                entry->release();
920        }
921    }
922
923    return (acpiDevice);
924}
925
926#endif /* ACPI_SUPPORT */
927
928//---------------------------------------------------------------------------
929
930static UInt8 IOPCIIsHotplugPort(IORegistryEntry * bridgeDevice)
931{
932    UInt8                  type = kPCIStatic;
933
934#if ACPI_SUPPORT
935
936    IOACPIPlatformDevice * rp;
937    IOACPIPlatformDevice * child;
938
939    rp = IOPCICopyACPIDevice(bridgeDevice);
940    if (rp && gIOPCIACPIPlane)
941    {
942        child = (IOACPIPlatformDevice *) rp->getChildEntry(gIOPCIACPIPlane);
943        if (child)
944        {
945            IOReturn   ret;
946            UInt32     result32 = 0;
947            OSObject * obj;
948
949            ret = child->evaluateInteger("_RMV", &result32);
950            if (kIOReturnSuccess == ret)
951            {
952                if (result32)
953                    type = kPCIHotPlugRoot;
954            }
955            else if ((obj = child->copyProperty(kACPIDevicePropertiesKey)))
956            {
957                OSDictionary * dict;
958                if ((dict = OSDynamicCast(OSDictionary, obj))
959                  && dict->getObject(kACPIPCILinkChangeKey))
960                    type = kPCILinkChange;
961            }
962        }
963    }
964    if (rp)
965        rp->release();
966
967#endif /* ACPI_SUPPORT */
968
969    return (type);
970}
971
972//---------------------------------------------------------------------------
973
974struct MatchDTEntryContext
975{
976    CLASS *     me;
977    IOPCIConfigEntry *   bridge;
978};
979
980void CLASS::matchDTEntry( IORegistryEntry * dtEntry, void * _context )
981{
982    MatchDTEntryContext * context = (MatchDTEntryContext *) _context;
983    IOPCIConfigEntry *    bridge = context->bridge;
984    IOPCIConfigEntry *    match = 0;
985    const OSSymbol *      location;
986
987    assert(bridge);
988    assert(dtEntry);
989
990    if (dtEntry->inPlane(gIOServicePlane)) return;
991
992    location = dtEntry->copyLocation();
993    if (!location)                         return;
994
995    uint32_t devfn = strtoul(location->getCStringNoCopy(), NULL, 16);
996    uint32_t deviceNum   = ((devfn >> 16) & 0x1f);
997    uint32_t functionNum = (devfn & 0x7);
998    bool     functionAll = ((devfn & 0xffff) == 0xffff);
999
1000    FOREACH_CHILD(bridge, child)
1001    {
1002        if (kPCIDeviceStateDead & child->deviceState)
1003            continue;
1004        if (child->space.s.deviceNum == deviceNum &&
1005            (functionAll || (child->space.s.functionNum == functionNum)))
1006        {
1007            match = child;
1008            break;
1009        }
1010    }
1011
1012    if (dtEntry->inPlane(gIOServicePlane))
1013        match = 0;
1014
1015    if (match)
1016    {
1017        if (!match->dtEntry)
1018        {
1019            match->dtEntry = dtEntry;
1020            DLOGC(context->me, "Found PCI device for DT entry [%s] "D()"\n",
1021                 dtEntry->getName(), DEVICE_IDENT(match));
1022        }
1023    }
1024    else
1025    {
1026        DLOGC(context->me, "NOT FOUND: PCI device for DT entry [%s] "D()"\n",
1027                dtEntry->getName(), 0, bridge->secBusNum, deviceNum, functionNum, 0, 0);
1028    }
1029
1030    if (location)
1031        location->release();
1032}
1033
1034#if ACPI_SUPPORT
1035
1036void CLASS::matchACPIEntry( IORegistryEntry * dtEntry, void * _context )
1037{
1038    MatchDTEntryContext * context = (MatchDTEntryContext *) _context;
1039    IOPCIConfigEntry *             bridge = context->bridge;
1040    IOPCIConfigEntry *             match = 0;
1041    OSNumber *            adr;
1042
1043    assert(bridge);
1044    assert(dtEntry);
1045
1046    adr = OSDynamicCast(OSNumber, dtEntry->getProperty("_ADR"));
1047    if (!adr)
1048        return;
1049
1050    uint32_t devfn = adr->unsigned32BitValue();
1051    uint32_t deviceNum = ((devfn >> 16) & 0x1f);
1052    uint32_t functionNum = (devfn & 0x7);
1053    bool     functionAll = ((devfn & 0xffff) == 0xffff);
1054
1055    FOREACH_CHILD( bridge, child )
1056    {
1057        if (kPCIDeviceStateDead & child->deviceState)
1058            continue;
1059        if (child->space.s.deviceNum == deviceNum &&
1060            (functionAll || (child->space.s.functionNum == functionNum)))
1061        {
1062            match = child;
1063            if (!functionAll)
1064                break;
1065        }
1066    }
1067
1068    if (match)
1069    {
1070        if (!match->acpiDevice)
1071        {
1072            match->acpiDevice = dtEntry;
1073            DLOGC(context->me, "Found PCI device for ACPI entry [%s] "D()"\n",
1074                 dtEntry->getName(), DEVICE_IDENT(match));
1075        }
1076    }
1077    else
1078    {
1079        DLOGC(context->me, "NOT FOUND: PCI device for ACPI entry [%s] "D()"\n",
1080                dtEntry->getName(), 0, bridge->secBusNum, deviceNum, functionNum, 0, 0);
1081    }
1082}
1083
1084#endif /* ACPI_SUPPORT */
1085
1086//---------------------------------------------------------------------------
1087
1088void CLASS::bridgeConnectDeviceTree(IOPCIConfigEntry * bridge)
1089{
1090    IORegistryEntry *   dtBridge = bridge->dtEntry;
1091    IOPCIConfigEntry *  parent;
1092	OSObject *          obj;
1093    MatchDTEntryContext context;
1094	IOPCIRange *        childRange;
1095	bool				oneChild;
1096	bool				tbok = (0 == (kIOPCIConfiguratorNoTB & gIOPCIFlags));
1097
1098	if ((kPCIHotPlugTunnel != bridge->supportsHotPlug)
1099	 || (kPCIHotPlugTunnelRoot == bridge->parent->supportsHotPlug))
1100	{
1101		context.me     = this;
1102		context.bridge = bridge;
1103		if (dtBridge)
1104		{
1105			dtBridge->applyToChildren(&matchDTEntry, &context, gIODTPlane);
1106		}
1107#if ACPI_SUPPORT
1108		if (gIOPCIACPIPlane && bridge->acpiDevice)
1109		{
1110			bridge->acpiDevice->applyToChildren(&matchACPIEntry, &context, gIOPCIACPIPlane);
1111		}
1112#endif /* ACPI_SUPPORT */
1113	}
1114
1115	oneChild = (bridge->child && !bridge->child->peer);
1116
1117    FOREACH_CHILD(bridge, child)
1118    {
1119        if (!child->isBridge) continue;
1120		if (kPCIDeviceStateTreeConnected & child->deviceState) continue;
1121//        child->deviceState |= kPCIDeviceStateTreeConnected;
1122		do
1123		{
1124			if ((kPCIHotPlugTunnelRoot == bridge->supportsHotPlug)
1125			 && (child == bridge->child))
1126			{
1127				// assume the first DSB of the TB root is for NHI
1128				bridge->child->supportsHotPlug = kPCIStatic;
1129				bridge->child->linkInterrupts  = false;
1130				DLOG("tunnel controller "D()"\n", DEVICE_IDENT(bridge->child));
1131				continue;
1132			}
1133
1134			if (tbok && child->dtEntry)
1135			{
1136			    if (child->dtEntry->getProperty(gIOPCIThunderboltKey))
1137			    {
1138					child->supportsHotPlug = kPCIHotPlugTunnelRoot;
1139					continue;
1140				}
1141				if ((obj = child->dtEntry->copyProperty(gIOPCIThunderboltKey, gIODTPlane,
1142													   kIORegistryIterateRecursively)))
1143				{
1144					obj->release();
1145					child->supportsHotPlug = kPCIHotPlugTunnelRootParent;
1146					continue;
1147				}
1148			}
1149
1150			if ((kPCIHotPlugTunnelRoot == bridge->supportsHotPlug)
1151			  || (kPCIHotPlugTunnel == bridge->supportsHotPlug))
1152			{
1153				child->supportsHotPlug = kPCIHotPlugTunnel;
1154				continue;
1155			}
1156
1157			if ((kPCIHotPlugRoot == bridge->supportsHotPlug)
1158			  || (kPCIHotPlug == bridge->supportsHotPlug))
1159			{
1160				child->supportsHotPlug = kPCIHotPlug;
1161				continue;
1162			}
1163
1164			if (child->headerType == kPCIHeaderType2)
1165				child->supportsHotPlug = kPCIHotPlugRoot;
1166			else if (child->dtEntry)
1167			{
1168				child->supportsHotPlug = IOPCIIsHotplugPort(child->dtEntry);
1169			}
1170			else
1171				child->supportsHotPlug = kPCIStatic;
1172		}
1173		while (false);
1174    }
1175
1176	bridge->countMaximize = 0;
1177	uint32_t flags = kIOPCIRangeFlagMaximizeRoot | kIOPCIRangeFlagNoCollapse;
1178
1179    FOREACH_CHILD(bridge, child)
1180    {
1181		if ((kPCIHotPlugTunnelRootParent == child->supportsHotPlug)
1182		 || (kPCIHotPlugTunnelRoot == child->supportsHotPlug)) bridge->countMaximize++;
1183	}
1184
1185	for (parent = bridge; parent; parent = parent->parent)
1186	{
1187		if (parent->countMaximize > 1)
1188		{
1189			flags = kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagNoCollapse;
1190			break;
1191		}
1192	}
1193
1194    FOREACH_CHILD(bridge, child)
1195    {
1196        if (!child->isBridge) continue;
1197		if (kPCIDeviceStateTreeConnected & child->deviceState) continue;
1198        child->deviceState |= kPCIDeviceStateTreeConnected;
1199
1200		DLOG("bridge "D()" supportsHotPlug %d, linkInterrupts %d\n",
1201			  DEVICE_IDENT(child),
1202			  child->supportsHotPlug, child->linkInterrupts);
1203
1204        for (int i = kIOPCIRangeBridgeMemory; i < kIOPCIRangeCount; i++)
1205        {
1206            childRange = child->ranges[i];
1207            if (!childRange)
1208                continue;
1209
1210			if (kPCIHotPlugTunnelRootParent == child->supportsHotPlug)
1211			{
1212				childRange->flags |= flags;
1213				child->rangeSizeChanges |= (1 << BRN(childRange->type));
1214			}
1215			else if (kPCIHotPlugTunnelRoot == child->supportsHotPlug)
1216			{
1217				childRange->flags |= flags;
1218				childRange->start = 0;
1219				child->rangeSizeChanges |= (1 << BRN(childRange->type));
1220			}
1221			else if (child->linkInterrupts
1222				&& (kPCIStatic != child->supportsHotPlug)
1223			    && (!(kIOPCIConfiguratorNoSplay & fFlags)))
1224			{
1225				childRange->flags |= kIOPCIRangeFlagSplay;
1226			}
1227		}
1228    }
1229}
1230
1231//---------------------------------------------------------------------------
1232
1233bool CLASS::bridgeConstructDeviceTree(void * unused, IOPCIConfigEntry * bridge)
1234{
1235    IORegistryEntry *   dtBridge = bridge->dtNub;
1236    uint32_t            int32;
1237    bool                ok = true;
1238    IOPCIDevice       * nub;
1239    OSDictionary      * initFrom;
1240
1241//    DLOG("bridgeConstructDeviceTree(%p)\n", bridge);
1242    if (!dtBridge) return (ok);
1243
1244    int32 = 3;
1245    dtBridge->setProperty("#address-cells", &int32, sizeof(int32));
1246    int32 = 2;
1247    dtBridge->setProperty("#size-cells", &int32, sizeof(int32));
1248
1249    // Create missing device-tree entries for any child devices.
1250
1251    FOREACH_CHILD( bridge, child )
1252    {
1253        IOPCIDevice     * pciDevice;
1254		IORegistryEntry * copyReg;
1255        OSDictionary    * propTable;
1256        OSObject        * obj;
1257        const OSSymbol  * sym;
1258		bool              addProps;
1259		bool              initDT;
1260
1261        if (kPCIDeviceStatePropertiesDone & child->deviceState) continue;
1262        child->deviceState |= kPCIDeviceStatePropertiesDone;
1263
1264        DLOG("bridgeConstructDeviceTree at "D()"\n", DEVICE_IDENT(child));
1265
1266        propTable = constructProperties(child);
1267        if (!propTable) continue;
1268
1269#if ACPI_SUPPORT
1270        if (child->acpiDevice)
1271        {
1272            OSObject  *    obj;
1273            OSDictionary * mergeProps;
1274            obj = child->acpiDevice->copyProperty(kACPIDevicePropertiesKey);
1275            if (obj)
1276            {
1277                if ((mergeProps = OSDynamicCast(OSDictionary, obj)))
1278                    propTable->merge(mergeProps);
1279                obj->release();
1280            }
1281        }
1282#endif /* ACPI_SUPPORT */
1283
1284        pciDevice = OSDynamicCast(IOPCIDevice, child->dtNub);
1285        addProps = true;
1286        if (!pciDevice)
1287        {
1288            nub = OSTypeAlloc(IOPCIDevice);
1289            if (!nub) continue;
1290            initFrom = 0;
1291            initDT = false;
1292            ok = false;
1293			if (child->dtEntry)
1294            {
1295#if ACPI_SUPPORT
1296                ok = nub->init(child->dtEntry, gIODTPlane);
1297                child->dtNub = child->dtEntry = 0;
1298                initDT = true;
1299#else  /* !ACPI_SUPPORT */
1300			    initFrom = child->dtEntry->dictionaryWithProperties();
1301#endif /* !ACPI_SUPPORT */
1302            }
1303            if (!initDT)
1304            {
1305                if (!initFrom)
1306                {
1307                    initFrom = propTable;
1308                    initFrom->retain();
1309                    addProps = false;
1310                }
1311                ok = (nub->init(initFrom) && nub->attachToParent(dtBridge, gIODTPlane));
1312                initFrom->release();
1313            }
1314            nub->release();
1315            if (!ok) continue;
1316            nub->reserved->configEntry = child;
1317            child->dtNub = nub;
1318#if ACPI_SUPPORT
1319            child->dtEntry = nub;
1320            copyReg = child->acpiDevice;
1321#else /* !ACPI_SUPPORT */
1322            copyReg = child->dtEntry;
1323#endif /* !ACPI_SUPPORT */
1324
1325            if (!initDT)
1326            {
1327                if (copyReg)
1328                {
1329                    if ((sym = copyReg->copyName()))
1330                    {
1331                        nub->setName(sym);
1332                        sym->release();
1333                    }
1334                }
1335                else if ((sym = OSDynamicCast(OSSymbol, propTable->getObject(gIONameKey))))
1336                    nub->setName(sym);
1337            }
1338        }
1339
1340        if (addProps)
1341        {
1342            // update existing device
1343            OSCollectionIterator * propIter =
1344                OSCollectionIterator::withCollection(propTable);
1345            if (propIter)
1346            {
1347                const OSSymbol * propKey;
1348
1349                child->dtNub->removeProperty("ranges");
1350                child->dtNub->removeProperty("reg");
1351                child->dtNub->removeProperty("assigned-addresses");
1352                child->dtNub->removeProperty("pcidebug");
1353
1354                while ((propKey = (const OSSymbol *)propIter->getNextObject()))
1355                {
1356                    if (child->dtNub->getProperty(propKey)) continue;
1357                    obj = propTable->getObject(propKey);
1358                    child->dtNub->setProperty(propKey, obj);
1359                }
1360                propIter->release();
1361            }
1362        }
1363
1364        if (pciDevice
1365          && (kPCIDeviceStatePaused & child->deviceState)
1366            && pciDevice->getProperty(kIOPCIResourcedKey))
1367        {
1368            // relocate existing device
1369            DLOG("IOPCIDevice::relocate at "D()"\n", DEVICE_IDENT(child));
1370            for (uint32_t idx = 0; idx < kIOPCIRangeCount; idx++)
1371            {
1372                IOPCIRange * range;
1373                range = child->ranges[idx];
1374                if (!range)	continue;
1375                if (range->size < range->proposedSize)
1376                {
1377                    DLOG("  %s ", gPCIResourceTypeName[range->type]);
1378                    DLOG_RANGE("short range", range);
1379                }
1380            }
1381            pciDevice->relocate(true);
1382        }
1383        propTable->release();
1384    }
1385	dtBridge->setProperty(kIOPCIConfiguredKey, kOSBooleanTrue);
1386
1387    return (ok);
1388}
1389
1390//---------------------------------------------------------------------------
1391
1392void CLASS::bridgeScanBus(IOPCIConfigEntry * bridge, uint8_t busNum, uint32_t resetMask)
1393{
1394    IOPCIAddressSpace   space;
1395    IOPCIConfigEntry *  child;
1396    uint32_t		    noLink = 0;
1397    bool     			bootDefer = false;
1398    UInt8               scanDevice, scanFunction, lastFunction;
1399	uint32_t            linkStatus;
1400	enum
1401	{
1402		kLinkCapDataLinkLayerActiveReportingCapable = (1 << 20),
1403		kLinkStatusDataLinkLayerLinkActive 			= (1 << 13)
1404	};
1405
1406	space.bits = 0;
1407	space.s.busNum = busNum;
1408
1409	if (bridge->expressCapBlock) do
1410	{
1411		bootDefer = (bridge->linkInterrupts
1412			&& (kIOPCIConfiguratorBootDefer == (kIOPCIConfiguratorBootDefer & fFlags)));
1413		if (bootDefer)
1414			break;
1415
1416		linkStatus  = configRead16(bridge, bridge->expressCapBlock + 0x12);
1417		if ((kLinkCapDataLinkLayerActiveReportingCapable & bridge->linkCaps)
1418			&& !(kLinkStatusDataLinkLayerLinkActive & linkStatus))
1419		{
1420			noLink = kPCIDeviceStateNoLink;
1421		}
1422
1423		if ((kPCIDeviceStateNoLink & bridge->deviceState) != noLink)
1424		{
1425			bridge->deviceState &= ~kPCIDeviceStateNoLink;
1426			bridge->deviceState |= noLink;
1427			bridge->rangeBaseChanges |= ((1 << kIOPCIRangeBridgeMemory)
1428									  |  (1 << kIOPCIRangeBridgePFMemory));
1429		}
1430
1431		DLOG("bridge "D()" %s%s linkStatus 0x%04x, linkCaps 0x%04x\n",
1432			 DEVICE_IDENT(bridge),
1433			 resetMask ? "reset " : "",
1434			 noLink    ? "nolink " : "",
1435			 linkStatus, bridge->linkCaps);
1436
1437		if (noLink)
1438		{
1439			if (kPCIHotPlugTunnel <= bridge->supportsHotPlug)
1440			{
1441				configWrite32(bridge, kPCI2PCIMemoryRange,         0);
1442				configWrite32(bridge, kPCI2PCIPrefetchMemoryRange, 0);
1443				configWrite32(bridge, kPCI2PCIPrefetchUpperBase,   0);
1444				configWrite32(bridge, kPCI2PCIPrefetchUpperLimit,  0);
1445			}
1446			IOPCIConfigEntry * next;
1447			for (child = bridge->child; child; child = next)
1448			{
1449				next = child->peer;
1450				bridgeDeadChild(bridge, child);
1451			}
1452		}
1453	}
1454	while (false);
1455
1456    if (!bootDefer && !noLink)
1457    {
1458#if 0
1459		static const uint8_t deviceMap[32] = {
1460//		  0,   1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
1461		  0,   1,  3,  2,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
1462		  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 };
1463#endif
1464		// Scan all PCI devices and functions on the secondary bus.
1465		for (scanDevice = 0; scanDevice <= 31; scanDevice++)
1466		{
1467			lastFunction = 0;
1468			for (scanFunction = 0; scanFunction <= lastFunction; scanFunction++)
1469			{
1470				space.s.deviceNum   = scanDevice; // deviceMap[scanDevice];
1471				space.s.functionNum = scanFunction;
1472
1473				bridgeProbeChild(bridge, space, resetMask);
1474
1475				// look in function 0 for multi function flag
1476				if (0 == scanFunction)
1477				{
1478					uint32_t flags = configRead32(space, kIOPCIConfigCacheLineSize);
1479					if ((flags != 0xFFFFFFFF) && (0x00800000 & flags))
1480					{
1481						lastFunction = 7;
1482					}
1483				}
1484			}
1485		}
1486	}
1487}
1488
1489//---------------------------------------------------------------------------
1490
1491void CLASS::markChanged(IOPCIConfigEntry * entry)
1492{
1493    if (fChangedServices)
1494    {
1495        if (entry->dtNub && entry->dtNub->inPlane(gIOServicePlane))
1496            fChangedServices->setObject(entry->dtNub);
1497    }
1498}
1499
1500//---------------------------------------------------------------------------
1501
1502void CLASS::bridgeAddChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * child)
1503{
1504    IOPCIConfigEntry ** prev = &bridge->child;
1505    IOPCIConfigEntry *  next;
1506
1507    // tailq
1508    while ((next = *prev))
1509    {
1510        prev = &next->peer;
1511    }
1512    *prev = child;
1513    child->parent = bridge;
1514
1515    if (child->isBridge)
1516        fBridgeCount++;
1517    else
1518        fDeviceCount++;
1519
1520	bridge->deviceState |= kPCIDeviceStateChildChanged | kPCIDeviceStateChildAdded;
1521}
1522
1523//---------------------------------------------------------------------------
1524
1525bool CLASS::bridgeDeallocateChildRanges(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead,
1526								        uint32_t deallocTypes, uint32_t freeTypes)
1527{
1528	IOPCIRange *        range;
1529	IOPCIRange *        childRange;
1530    bool				ok;
1531    bool				dispose;
1532    bool				didKeep = false;
1533
1534    for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++)
1535	{
1536		childRange = dead->ranges[rangeIndex];
1537		if (!childRange)								continue;
1538		if (!((1 << rangeIndex) & deallocTypes)) 		continue;
1539
1540		if ((kIOPCIRangeBridgeBusNumber == rangeIndex) && dead->busResv.nextSubRange)
1541		{
1542			ok = IOPCIRangeListDeallocateSubRange(childRange, &dead->busResv);
1543			if (!ok) panic("!IOPCIRangeListDeallocateSubRange busResv");
1544		}
1545
1546		dispose = (0 != ((1 << rangeIndex) & freeTypes));
1547
1548		if (childRange->nextSubRange)
1549		{
1550			IOPCIScalar size  = childRange->size;
1551			IOPCIScalar start = childRange->start;
1552
1553			range = bridgeGetRange(bridge, childRange->type);
1554			if (!range) panic("!range");
1555			ok = IOPCIRangeListDeallocateSubRange(range, childRange);
1556			if (!ok) panic("!IOPCIRangeListDeallocateSubRange");
1557            if (rangeIndex <= kIOPCIRangeExpansionROM)
1558            {
1559                childRange->start = start;
1560                childRange->proposedSize = size;
1561            }
1562            else
1563            {
1564                childRange->proposedSize = 0;
1565            }
1566            bridge->haveAllocs |= (1 << childRange->type);
1567			dead->rangeBaseChanges |= (1 << rangeIndex);
1568
1569			didKeep |= !dispose;
1570		}
1571		if (dispose)
1572		{
1573			IOPCIRangeFree(childRange);
1574			dead->ranges[rangeIndex] = NULL;
1575		}
1576	}
1577
1578	return (didKeep);
1579}
1580
1581//---------------------------------------------------------------------------
1582
1583void CLASS::bridgeRemoveChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead,
1584								uint32_t deallocTypes, uint32_t freeTypes,
1585								IOPCIConfigEntry ** childList)
1586{
1587    IOPCIConfigEntry ** prev;
1588    IOPCIConfigEntry *  child;
1589    IOPCIDevice *       pciDevice;
1590    bool				didKeep;
1591
1592	dead->deviceState |= kPCIDeviceStateDead;
1593
1594    while ((child = dead->child))
1595    {
1596        bridgeRemoveChild(dead, child, deallocTypes, freeTypes, childList);
1597    }
1598
1599    DLOG("bridge "B()" removing child %p "D()"\n",
1600         BRIDGE_IDENT(bridge), dead, DEVICE_IDENT(dead));
1601
1602	if (kPCIDeviceStateRequestPause & dead->deviceState)
1603	{
1604		dead->deviceState &= ~kPCIDeviceStateRequestPause;
1605		fWaitingPause--;
1606	}
1607
1608	prev = &bridge->child;
1609	while ((child = *prev))
1610    {
1611        if (dead == child)
1612        {
1613            *prev = child->peer;
1614            break;
1615        }
1616        prev = &child->peer;
1617    }
1618
1619    if (!child) panic("bridgeRemoveChild");
1620
1621	bridge->deviceState |= kPCIDeviceStateChildChanged;
1622	bridge->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated);
1623
1624	didKeep = bridgeDeallocateChildRanges(bridge, dead, deallocTypes, freeTypes);
1625
1626    if (childList && didKeep)
1627	{
1628		dead->parent       = NULL;
1629		dead->peer         = *childList;
1630		*childList         = dead;
1631	}
1632	else
1633    {
1634		if ((pciDevice = OSDynamicCast(IOPCIDevice, dead->dtNub)))
1635		{
1636			pciDevice->reserved->configEntry = NULL;
1637		}
1638		if (dead->isBridge)
1639			fBridgeCount--;
1640		else
1641			fDeviceCount--;
1642
1643//		memset(dead, 0xBB, sizeof(*dead));
1644		IODelete(dead, IOPCIConfigEntry, 1);
1645		DLOG("deleted %p, bridges %d devices %d\n", dead, fBridgeCount, fDeviceCount);
1646	}
1647}
1648
1649//---------------------------------------------------------------------------
1650
1651void CLASS::bridgeMoveChildren(IOPCIConfigEntry * to, IOPCIConfigEntry * list)
1652{
1653	IOPCIConfigEntry * dead;
1654	IOPCIRange *       range;
1655	IOPCIRange *       childRange;
1656	bool		       ok;
1657
1658	while (list)
1659	{
1660		dead = list;
1661		list = list->peer;
1662		for (int rangeIndex = 0; rangeIndex <= kIOPCIRangeExpansionROM; rangeIndex++)
1663		{
1664			childRange = dead->ranges[rangeIndex];
1665			if (!childRange)							continue;
1666			if (!childRange->proposedSize)				continue;
1667			if (!childRange->start)						continue;
1668
1669			range = bridgeGetRange(to, childRange->type);
1670			if (!range) panic("!range");
1671
1672			// reserve the alloc until terminate
1673			if (!dead->parent)
1674			{
1675				// head Q
1676				dead->parent = to;
1677				dead->peer   = to->child;
1678				to->child    = dead;
1679				DLOG("Reserves on ("D()") for ("D()"):\n",
1680						DEVICE_IDENT(to), DEVICE_IDENT(dead));
1681			}
1682			DLOG("  %s: 0x%llx reserve 0x%llx, 0x%llx\n",
1683					gPCIResourceTypeName[childRange->type],
1684					childRange->start, childRange->proposedSize, childRange->totalSize);
1685            if (childRange->nextSubRange) panic("bridgeMoveChildren");
1686//			childRange->proposedSize = childRange->size;
1687			childRange->flags |= kIOPCIRangeFlagReserve;
1688			ok = IOPCIRangeListAllocateSubRange(range, childRange);
1689			if (!ok) panic("!IOPCIRangeListAllocateSubRange");
1690		}
1691	}
1692}
1693
1694//---------------------------------------------------------------------------
1695
1696void CLASS::bridgeDeadChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead)
1697{
1698	IOPCIConfigEntry * pendingList = NULL;
1699
1700    if (kPCIDeviceStateDead & dead->deviceState)
1701        return;
1702
1703    DLOG("bridge %p dead child at "D()"\n", bridge, DEVICE_IDENT(dead));
1704	markChanged(dead);
1705	bridgeRemoveChild(bridge, dead,
1706                        kIOPCIRangeAllMask, kIOPCIRangeAllBridgeMask, &pendingList);
1707	if (pendingList)
1708    {
1709		bridgeMoveChildren(bridge, pendingList);
1710    }
1711}
1712
1713//---------------------------------------------------------------------------
1714
1715void CLASS::bridgeProbeChild( IOPCIConfigEntry * bridge, IOPCIAddressSpace space, uint32_t resetMask )
1716{
1717    IOPCIConfigEntry * child = NULL;
1718    bool      ok = true;
1719    uint32_t  vendorProduct;
1720
1721    vendorProduct = configRead32(space, kIOPCIConfigVendorID);
1722
1723    if ((kPCIStatic != bridge->supportsHotPlug)
1724    	&& ((0 == (vendorProduct & 0xffff)) || (0xffff == (vendorProduct & 0xffff))))
1725	{
1726        configWrite32(space, kIOPCIConfigVendorID, 0);
1727		vendorProduct = configRead32(space, kIOPCIConfigVendorID);
1728	}
1729
1730    for (child = bridge->child; child; child = child->peer)
1731    {
1732        if (kPCIDeviceStateDead & child->deviceState)
1733            continue;
1734        if (space.bits == child->space.bits)
1735        {
1736            DLOG("bridge %p scan existing child at "D()" state 0x%x\n",
1737                 bridge, DEVICE_IDENT(child), child->deviceState);
1738
1739            // check bars?
1740
1741			if (!(kIOPCIConfiguratorNoTerminate & fFlags))
1742			{
1743				if ((vendorProduct != child->vendorProduct)
1744				|| (kPCIDeviceStateEjected & child->deviceState)
1745				|| (kPCIDeviceStateToKill  & child->deviceState))
1746				{
1747					IOPCIConfigEntry * dead = child;
1748					if (!(kPCIDeviceStateEjected & child->deviceState))
1749					{
1750						// create new if present
1751						child = NULL;
1752					}
1753					// may free child
1754					bridgeDeadChild(bridge, dead);
1755				}
1756			}
1757            break;
1758        }
1759    }
1760
1761    if (child)
1762        return;
1763
1764    uint32_t retries = 1;
1765    while ((0 == (vendorProduct & 0xffff)) || (0xffff == (vendorProduct & 0xffff)))
1766    {
1767        if (!--retries)
1768            return;
1769        vendorProduct = configRead32(space, kIOPCIConfigVendorID);
1770    }
1771
1772    child = IONew(IOPCIConfigEntry, 1);
1773    if (!child) return;
1774
1775    memset(child, 0, sizeof(*child));
1776    child->id            = ++fNextID;
1777    child->space         = space;
1778    child->headerType    = configRead8(child, kIOPCIConfigHeaderType) & 0x7f;
1779    child->classCode     = configRead32(child, kIOPCIConfigRevisionID) >> 8;
1780    child->vendorProduct = vendorProduct;
1781
1782    DLOG("Probing type %u device class-code 0x%06x cmd 0x%04x at "D()" [state 0x%x]\n",
1783         child->headerType, child->classCode, configRead16(child, kIOPCIConfigCommand),
1784         DEVICE_IDENT(child),
1785         child->deviceState);
1786
1787    switch (child->headerType)
1788    {
1789        case kPCIHeaderType0:
1790            // skip devices aliased to host bridges
1791            if ((child->classCode & 0xFFFFFF) == 0x060000)
1792                break;
1793
1794            deviceProbeRanges(child, resetMask);
1795            break;
1796
1797        case kPCIHeaderType1:
1798            child->isBridge = true;
1799            bridgeProbeRanges(child, resetMask);
1800            break;
1801
1802        case kPCIHeaderType2:
1803            child->isBridge = true;
1804            cardbusProbeRanges(child, resetMask);
1805            break;
1806
1807        default:
1808            DLOG("  bad PCI header type 0x%x\n", child->headerType);
1809            ok = false;
1810            break;
1811    }
1812
1813    if (!ok)
1814    {
1815        IODelete(child, IOPCIConfigEntry, 1);
1816		return;
1817    }
1818
1819	if (findPCICapability(child, kIOPCIPCIExpressCapability, &child->expressCapBlock))
1820	{
1821		if (child->isBridge)
1822		{
1823			enum
1824			{
1825				kLinkCapDataLinkLayerActiveReportingCapable = (1 << 20),
1826				kLinkStatusDataLinkLayerLinkActive 			= (1 << 13),
1827				kSlotCapHotplug					 			= (1 << 6)
1828			};
1829			uint32_t expressCaps, linkCaps, linkControl, slotCaps = kSlotCapHotplug;
1830
1831			expressCaps = configRead16(child, child->expressCapBlock + 0x02);
1832			linkCaps    = configRead32(child, child->expressCapBlock + 0x0c);
1833			linkControl = configRead16(child, child->expressCapBlock + 0x10);
1834			if (0x100 & expressCaps) slotCaps = configRead32(child, child->expressCapBlock + 0x14);
1835
1836			if ((kPCIHotPlugTunnel <= bridge->supportsHotPlug)
1837				&& (0x60 == (0xf0 & expressCaps))) // downstream port
1838			{
1839				if ((kLinkCapDataLinkLayerActiveReportingCapable & linkCaps)
1840				 && (kSlotCapHotplug & slotCaps))
1841				{
1842					child->linkInterrupts = true;
1843				}
1844			}
1845
1846			child->expressCaps        = expressCaps;
1847			child->linkCaps           = linkCaps;
1848			DLOG("  expressCaps 0x%x, linkControl 0x%x, linkCaps 0x%x, slotCaps 0x%x\n",
1849				 child->expressCaps, linkControl, child->linkCaps, slotCaps);
1850		}
1851		child->expressDeviceCaps1 = configRead32(child, child->expressCapBlock + 0x04);
1852		child->expressMaxPayload  = (child->expressDeviceCaps1 & 7);
1853		DLOG("  expressMaxPayload 0x%x\n", child->expressMaxPayload);
1854	}
1855
1856	bridgeAddChild(bridge, child);
1857	checkCacheLineSize(child);
1858}
1859
1860//---------------------------------------------------------------------------
1861
1862uint32_t CLASS::findPCICapability(IOPCIConfigEntry * device,
1863                                  uint32_t capabilityID, uint32_t * found)
1864{
1865	return(findPCICapability(device->space, capabilityID, found));
1866}
1867
1868//---------------------------------------------------------------------------
1869
1870uint32_t CLASS::findPCICapability(IOPCIAddressSpace space,
1871                                  uint32_t capabilityID, uint32_t * found)
1872{
1873    uint32_t data;
1874    uint32_t offset, expressCap, firstOffset;
1875
1876    data = expressCap = firstOffset = 0;
1877    if (found)
1878    {
1879        firstOffset = *found;
1880        *found = 0;
1881    }
1882
1883    if (0 == ((kIOPCIStatusCapabilities << 16)
1884              & (configRead32(space, kIOPCIConfigCommand))))
1885        return (0);
1886
1887    if (capabilityID >= 0x100)
1888    {
1889        if (!findPCICapability(space, kIOPCIPCIExpressCapability, &expressCap)) return (0);
1890
1891        capabilityID = -capabilityID;
1892        offset = 0x100;
1893        while (offset)
1894        {
1895            data = configRead32(space, offset);
1896            if ((offset > firstOffset) && (capabilityID == (data & 0xffff)))
1897            {
1898                if (found)
1899                    *found = offset;
1900                break;
1901            }
1902            offset = (data >> 20) & 0xfff;
1903            if ((offset < 0x100) || (offset & 3))
1904                offset = 0;
1905        }
1906    }
1907    else
1908    {
1909        offset = (0xff & configRead32(space, kIOPCIConfigCapabilitiesPtr));
1910        if (offset & 3)
1911            offset = 0;
1912        while (offset)
1913        {
1914            data = configRead32(space, offset);
1915            if ((offset > firstOffset) && (capabilityID == (data & 0xff)))
1916            {
1917                if (found)
1918                    *found = offset;
1919                break;
1920            }
1921            offset = (data >> 8) & 0xff;
1922            if (offset & 3)
1923                offset = 0;
1924        }
1925    }
1926
1927    return (offset ? data : 0);
1928}
1929
1930//---------------------------------------------------------------------------
1931
1932struct BARProbeParam {
1933    CLASS *            target;
1934    IOPCIConfigEntry * device;
1935    uint32_t           lastBarNum;
1936    uint32_t           resetMask;
1937};
1938
1939void CLASS::safeProbeCallback( void * refcon )
1940{
1941    BARProbeParam * param = (BARProbeParam *) refcon;
1942    assert(param);
1943
1944    if (cpu_number() == 0)
1945    {
1946        param->target->probeBaseAddressRegister(
1947            param->device, param->lastBarNum, param->resetMask );
1948    }
1949    if (cpu_number() == 99)
1950    {
1951        IOLog("safeProbeCallback() gcc workaround\n");
1952    }
1953}
1954
1955void CLASS::safeProbeBaseAddressRegister(IOPCIConfigEntry * device,
1956										 uint32_t lastBarNum, uint32_t resetMask)
1957{
1958    uint32_t barNum;
1959
1960    for (barNum = 0; barNum <= lastBarNum; barNum++)
1961    {
1962        device->ranges[barNum] = IOPCIRangeAlloc();
1963        IOPCIRangeInit(device->ranges[barNum], 0, 0, 0);
1964    }
1965
1966    {
1967#if NO_RENDEZVOUS_KERNEL
1968        boolean_t       istate;
1969        istate = ml_set_interrupts_enabled(FALSE);
1970        probeBaseAddressRegister(device, lastBarNum, resetMask);
1971        ml_set_interrupts_enabled(istate);
1972#else
1973        BARProbeParam param;
1974
1975        param.target     = this;
1976        param.device     = device;
1977        param.lastBarNum = lastBarNum;
1978        param.resetMask  = resetMask;
1979
1980        mp_rendezvous_no_intrs(&safeProbeCallback, &param);
1981#endif
1982    }
1983
1984#if PLX8680
1985	do
1986	{
1987		IOPCIRange *        range;
1988		uint16_t            command;
1989		volatile uint32_t * regs;
1990		uint32_t            reg32, lut;
1991		IOPCIConfigEntry *  parent;
1992
1993		if (0x868010b5 != device->vendorProduct) break;
1994
1995		command = configRead16(device, kIOPCIConfigCommand);
1996		configWrite16(device, kIOPCIConfigCommand, (command | kIOPCICommandMemorySpace | kIOPCICommandBusMaster));
1997
1998		range = device->ranges[kIOPCIRangeBAR0];
1999		if (!range) break;
2000		if (0x40000 != range->proposedSize) break;
2001		if (kIOPCIResourceTypeMemory != range->type) break;
2002		if (kPCIHeaderType1 != device->headerType) break;
2003
2004		parent = device;
2005		do { regs = parent->plx; } while (!regs && (parent = parent->parent));
2006		if (regs) break;
2007
2008		IOMemoryDescriptor *
2009		md = IOMemoryDescriptor::withAddressRange(range->start, range->proposedSize, kIODirectionOutIn | kIOMemoryMapperNone, TASK_NULL);
2010		if (!md) break;
2011		IOMemoryMap *
2012		map = md->map();
2013		if (!map) break;
2014		regs = (uint32_t *) map->getAddress();
2015
2016		reg32 = regs[0];
2017		IOLog("PLX regs 0x%x, 0x%x\n", (int) range->start, reg32);
2018		if (0x868010b5 != reg32) break;
2019
2020		reg32 = regs[(0x3e000 + 0xd4) / 4];
2021		IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32);
2022		reg32 = regs[(0x3e000 + 0xd8) / 4];
2023		IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32);
2024
2025		for (lut = 0; lut < 8; lut++) regs[((0x3e000 + 0xd94) / 4) + lut] = 0;
2026
2027		regs[(0x3e000 + 0xd4) / 4] = 0x0000000c;
2028		regs[(0x3e000 + 0xd8) / 4] = 0xfffffffc;
2029
2030		regs[(0x3e000 + 0xc3c) / 4] = 0x00000000;
2031		regs[(0x3e000 + 0xc40) / 4] = 0x00000000;
2032
2033		reg32 = regs[(0x3e000 + 0xd4) / 4];
2034		IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32);
2035		reg32 = regs[(0x3e000 + 0xd8) / 4];
2036		IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32);
2037
2038		for (barNum = 0; barNum <= lastBarNum; barNum++)
2039		{
2040			IOPCIRangeInit(device->ranges[barNum], 0, 0, 0);
2041		}
2042
2043		{
2044			BARProbeParam param;
2045			param.target     = this;
2046			param.device     = device;
2047			param.lastBarNum = lastBarNum;
2048			param.resetMask  = resetMask;
2049			mp_rendezvous_no_intrs(&safeProbeCallback, &param);
2050		}
2051
2052		reg32 = regs[(0x3e000 + 0xd4) / 4];
2053		IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32);
2054		reg32 = regs[(0x3e000 + 0xd8) / 4];
2055		IOLog("PLX bar1 0x%x, 0x%x\n", (int) range->start, reg32);
2056		device->plx = regs;
2057	}
2058	while (false);
2059#endif /* PLX8680 */
2060
2061    for (barNum = 0; barNum <= lastBarNum; barNum++)
2062    {
2063        if (!device->ranges[barNum]->proposedSize)
2064        {
2065            IOPCIRangeFree(device->ranges[barNum]);
2066            device->ranges[barNum] = NULL;
2067        }
2068    }
2069}
2070
2071//---------------------------------------------------------------------------
2072
2073void CLASS::probeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask)
2074{
2075    IOPCIRange *    range;
2076    uint32_t        barNum, nextBarNum;
2077    uint32_t        value;
2078    uint64_t        value64, saved, upper, barMask;
2079    uint64_t        start, size;
2080    uint32_t        type;
2081    uint16_t        command;
2082    uint8_t         barOffset;
2083    bool            clean64;
2084
2085    command = disableAccess(device, true);
2086
2087    if (kIOPCIRangeExpansionROM == lastBarNum) do
2088    {
2089        lastBarNum--;
2090
2091        barOffset = kIOPCIConfigExpansionROMBase;
2092        barMask = 0x7FF;
2093
2094        saved = configRead32(device, barOffset);
2095        configWrite32(device, barOffset, 0xFFFFFFFF & ~barMask);
2096        value = configRead32(device, barOffset);
2097        configWrite32(device, barOffset, saved);
2098
2099        // unimplemented BARs are hardwired to zero
2100        if (value == 0) continue;
2101		if (3 != (device->classCode >> 16)) continue;
2102
2103        range = device->ranges[kIOPCIRangeExpansionROM];
2104        start = (resetMask & (1 << kIOPCIResourceTypeMemory)) ? 0 : (saved & ~barMask);
2105        value &= ~barMask;
2106        size  = -value;
2107        IOPCIRangeInit(range, kIOPCIResourceTypeMemory, start, size, size);
2108    }
2109    while (false);
2110
2111    for (barNum = 0; barNum <= lastBarNum; barNum = nextBarNum)
2112    {
2113        barOffset  = kIOPCIConfigBaseAddress0 + barNum * 4;
2114        nextBarNum = barNum + 1;
2115        value64    = (-1LL << 32);
2116
2117        saved = configRead32(device, barOffset);
2118        configWrite32(device, barOffset, 0xFFFFFFFF);
2119        value = configRead32(device, barOffset);
2120        configWrite32(device, barOffset, saved);
2121
2122        // unimplemented BARs are hardwired to zero
2123        if (value == 0) continue;
2124
2125        clean64 = false;
2126        if (value & 1)
2127        {
2128            barMask = 0x3;
2129            type = kIOPCIResourceTypeIO;
2130
2131            // If the upper 16 bits for I/O space
2132            // are all 0, then we should ignore them.
2133            if ((value & 0xFFFF0000) == 0) value |= 0xFFFF0000;
2134        }
2135        else
2136        {
2137            barMask = 0xf;
2138            if (value & 0x8)
2139                type = kIOPCIResourceTypePrefetchMemory;
2140            else
2141                type = kIOPCIResourceTypeMemory;
2142
2143            switch (value & 6)
2144            {
2145                case 2: /* below 1Mb */
2146                case 0: /* 32-bit mem */
2147                case 6: /* reserved  */
2148					type = kIOPCIResourceTypeMemory;
2149                    break;
2150
2151                case 4: /* 64-bit mem */
2152                    clean64 = (kIOPCIResourceTypePrefetchMemory == type);
2153                    if (clean64)
2154                    {
2155                        upper = configRead32(device, barOffset + 4);
2156                        saved |= (upper << 32);
2157                        configWrite32(device, barOffset + 4, 0xFFFFFFFF);
2158                        value64 = configRead32(device, barOffset + 4);
2159						value64 <<= 32;
2160                        configWrite32(device, barOffset + 4, upper);
2161                    }
2162                    nextBarNum = barNum + 2;
2163                    break;
2164            }
2165        }
2166
2167        start    = (resetMask & (1 << type)) ? 0 : (saved & ~barMask);
2168        value   &= ~barMask;
2169		value64 |= value;
2170        size     = -value64;
2171
2172        if (size > MAX_BAR_SIZE)
2173        {
2174            size &= 0xFFFFFFFF;
2175            clean64 = false;
2176            nextBarNum--;
2177        }
2178        if (start == value64)
2179        {
2180            DLOG("  [0x%x] can't probe\n", barOffset);
2181            continue;
2182        }
2183
2184        range = device->ranges[barNum];
2185        IOPCIRangeInit(range, type, start, size, size);
2186        range->minAddress = minBARAddressDefault[type];
2187    	if (clean64 && (kIOPCIConfiguratorPFM64 & fFlags))
2188            range->maxAddress = 0xFFFFFFFFFFFFFFFFULL;
2189#if 0
2190		if ((0x91821b4b == configRead32(device->space, kIOPCIConfigVendorID))
2191		 && (0x18 == barOffset))
2192		{
2193			range->proposedSize = range->totalSize = 0x4000;
2194		}
2195#endif
2196    }
2197
2198    restoreAccess(device, command);
2199}
2200
2201//---------------------------------------------------------------------------
2202
2203void CLASS::deviceProbeRanges( IOPCIConfigEntry * device, uint32_t resetMask )
2204{
2205    uint32_t     idx;
2206    IOPCIRange * range;
2207
2208    // Probe BAR 0 through 5 and ROM
2209    safeProbeBaseAddressRegister(device, kIOPCIRangeExpansionROM, resetMask);
2210
2211    for (idx = kIOPCIRangeBAR0; idx <= kIOPCIRangeExpansionROM; idx++)
2212    {
2213        range = device->ranges[idx];
2214        if (!range)
2215            continue;
2216        DLOG("  [0x%x %s] 0x%llx:0x%llx\n",
2217             (idx == kIOPCIRangeExpansionROM) ?
2218                kIOPCIConfigExpansionROMBase : idx * 4 + kIOPCIConfigBaseAddress0,
2219             gPCIResourceTypeName[range->type], range->start, range->proposedSize);
2220    }
2221}
2222
2223//---------------------------------------------------------------------------
2224
2225void CLASS::bridgeProbeBusRange(IOPCIConfigEntry * bridge, uint32_t resetMask)
2226{
2227    IOPCIRange *    range;
2228    uint64_t        start, size;
2229
2230    // Record the bridge secondary and subordinate bus numbers
2231	if (resetMask & (1 << kIOPCIResourceTypeBusNumber))
2232	{
2233		bridge->secBusNum = 0;
2234		bridge->subBusNum = 0;
2235	}
2236	else
2237	{
2238		bridge->secBusNum = configRead8(bridge, kPCI2PCISecondaryBus);
2239		bridge->subBusNum = configRead8(bridge, kPCI2PCISubordinateBus);
2240	}
2241
2242    range = IOPCIRangeAlloc();
2243    start = bridge->secBusNum;
2244    size  = bridge->subBusNum - bridge->secBusNum + 1;
2245    IOPCIRangeInit(range, kIOPCIResourceTypeBusNumber, start, size, kPCIBridgeBusNumberAlignment);
2246    bridge->ranges[kIOPCIRangeBridgeBusNumber] = range;
2247}
2248
2249//---------------------------------------------------------------------------
2250
2251void CLASS::bridgeProbeRanges( IOPCIConfigEntry * bridge, uint32_t resetMask )
2252{
2253    IOPCIRange *    range;
2254    IOPCIScalar     start, end, upper, size;
2255
2256    bridgeProbeBusRange(bridge, resetMask);
2257
2258    // Probe bridge BAR0 and BAR1
2259	safeProbeBaseAddressRegister(bridge, kIOPCIRangeBAR1, resetMask);
2260
2261#if 0
2262	// test bridge BARs
2263	if ((5 == bridge->space.s.busNum) && (0 == bridge->space.s.deviceNum) && (0 == bridge->space.s.functionNum))
2264	{
2265		for (int barNum = 0; barNum <= kIOPCIRangeBAR1; barNum++)
2266		{
2267			bridge->ranges[barNum] = IOPCIRangeAlloc();
2268			IOPCIRangeInit(bridge->ranges[barNum], kIOPCIResourceTypeMemory, 0, 0x40000, 0x40000);
2269		}
2270	}
2271#endif
2272
2273	DLOG_RANGE("  bridge BAR0", bridge->ranges[kIOPCIRangeBAR0]);
2274	DLOG_RANGE("  bridge BAR1", bridge->ranges[kIOPCIRangeBAR1]);
2275
2276    // Probe memory base and limit
2277
2278    end = configRead32(bridge, kPCI2PCIMemoryRange);
2279
2280    start = (end & 0xfff0) << 16;
2281    end  |= 0x000fffff;
2282    if (start && (end > start))
2283        size = end - start + 1;
2284    else
2285        size = start = 0;
2286	if (resetMask & (1 << kIOPCIResourceTypeMemory)) start = 0;
2287
2288    range = IOPCIRangeAlloc();
2289    IOPCIRangeInit(range, kIOPCIResourceTypeMemory, start, size,
2290                    kPCIBridgeMemoryAlignment);
2291    bridge->ranges[kIOPCIRangeBridgeMemory] = range;
2292
2293    // Probe prefetchable memory base and limit
2294
2295    end = configRead32(bridge, kPCI2PCIPrefetchMemoryRange);
2296
2297    if (true /* should check r/w */)
2298    {
2299        bridge->clean64 = (0x1 == (end & 0xf));
2300        if (bridge->clean64)
2301        {
2302            upper  = configRead32(bridge, kPCI2PCIPrefetchUpperBase);
2303            start |= (upper << 32);
2304            upper  = configRead32(bridge, kPCI2PCIPrefetchUpperLimit);
2305            end   |= (upper << 32);
2306        }
2307
2308        start = (end & 0xfff0) << 16;
2309        end  |= 0x000fffff;
2310        if (start && (end > start))
2311            size = end - start + 1;
2312        else
2313            size = start = 0;
2314		if (resetMask & (1 << kIOPCIResourceTypePrefetchMemory)) start = 0;
2315
2316        range = IOPCIRangeAlloc();
2317        IOPCIRangeInit(range, kIOPCIResourceTypePrefetchMemory, start, size,
2318                        kPCIBridgeMemoryAlignment);
2319		if (bridge->clean64 && (kIOPCIConfiguratorPFM64 & fFlags))
2320            range->maxAddress = 0xFFFFFFFFFFFFFFFFULL;
2321        bridge->ranges[BRN(kIOPCIResourceTypePrefetchMemory)] = range;
2322    }
2323
2324    // Probe I/O base and limit
2325
2326    end = configRead32(bridge, kPCI2PCIIORange);
2327
2328    if ((end & (0x0e0e)) == 0)
2329    {
2330        // I/O Base and Limit register at dword 7 (0x1c).
2331        // If bridge does not implement an I/O address range, then both
2332        // the I/O Base and I/O Limit registers must be implemented as
2333        // read-only registers that return zero when read. The bottom
2334        // and the top of the I/O address range will always be aligned
2335        // to a 4KB boundary.
2336        //
2337        //  I/O Limit  |  I/O  Base
2338        // 7...4 3...0 | 7...4 3...0
2339        //  ^     ^       ^     ^
2340        //  |     |       |     |
2341        //  |     |       |     +- 0 for 16bit decode, 1 for 32-bit decode
2342        //  |     |       |
2343        //  |     |       +-  Upper hex digit of 16-bit or 32-bit I/O range
2344        //  |     |           start address. Read-only field.
2345        //  |     |
2346        //  |     +- 0 for 16bit decode, 1 for 32-bit decode
2347        //  |
2348        //  +- Upper hex digit of 16-bit or 32-bit I/O range end address.
2349        //     Read-write field.
2350
2351        start = (end & 0xf0) << 8;
2352        end   = (end & 0xffff) | 0xfff;
2353
2354        // Limit may be less than the base, when there are no I/O addresses
2355        // on the secondary side of the bridge. Or when BIOS has failed to
2356        // assign I/O resources to devices behind the bridge.
2357
2358        if (start && (end > start))
2359            size = end - start + 1;
2360        else
2361            size = start = 0;
2362		if (resetMask & (1 << kIOPCIResourceTypeIO)) start = 0;
2363
2364        range = IOPCIRangeAlloc();
2365        IOPCIRangeInit(range, kIOPCIResourceTypeIO, start, size,
2366                        kPCIBridgeIOAlignment);
2367        bridge->ranges[kIOPCIRangeBridgeIO] = range;
2368    }
2369
2370    DLOG_RANGE("  BUS", bridge->ranges[kIOPCIRangeBridgeBusNumber]);
2371    DLOG_RANGE("  I/O", bridge->ranges[kIOPCIRangeBridgeIO]);
2372    DLOG_RANGE("  MEM", bridge->ranges[kIOPCIRangeBridgeMemory]);
2373    DLOG_RANGE("  PFM", bridge->ranges[kIOPCIRangeBridgePFMemory]);
2374}
2375
2376//---------------------------------------------------------------------------
2377
2378void CLASS::cardbusProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask)
2379{
2380    IOPCIRange * range;
2381
2382    bridgeProbeBusRange(bridge, resetMask);
2383
2384    // Maximal bus range.
2385
2386    range = bridge->ranges[kIOPCIRangeBridgeBusNumber];
2387    range->flags    |= kIOPCIRangeFlagNoCollapse | kIOPCIRangeFlagPermanent;
2388
2389    // 4K register space
2390
2391    range = IOPCIRangeAlloc();
2392    IOPCIRangeInit(range, kIOPCIResourceTypeMemory, 0, 4096, 4096);
2393    bridge->ranges[kIOPCIRangeBAR0] = range;
2394
2395    // Maximal memory and I/O range.
2396
2397    range = IOPCIRangeAlloc();
2398    IOPCIRangeInit(range, kIOPCIResourceTypeIO, 0, kPCIBridgeIOAlignment, kPCIBridgeIOAlignment);
2399    range->flags     = kIOPCIRangeFlagNoCollapse | kIOPCIRangeFlagPermanent;
2400    bridge->ranges[kIOPCIRangeBridgeIO] = range;
2401
2402    range = IOPCIRangeAlloc();
2403    IOPCIRangeInit(range, kIOPCIResourceTypeMemory, 0, kPCIBridgeMemoryAlignment, kPCIBridgeMemoryAlignment);
2404    range->flags     = kIOPCIRangeFlagNoCollapse | kIOPCIRangeFlagPermanent;
2405    bridge->ranges[kIOPCIRangeBridgeMemory] = range;
2406}
2407
2408
2409//---------------------------------------------------------------------------
2410
2411int32_t CLASS::scanProc(void * ref, IOPCIConfigEntry * bridge)
2412{
2413    int32_t            ok = true;
2414    bool			   bootScan = (NULL != ref);
2415    bool 			   haveBus;
2416	uint32_t           resetMask;
2417
2418    if (kPCIDeviceStateDead & bridge->deviceState) return (ok);
2419
2420    if (!(kPCIDeviceStateScanned & bridge->deviceState))
2421    {
2422		haveBus = ((bridge->secBusNum || bridge->isHostBridge)
2423			    && ((bootScan && bridge->ranges[kIOPCIRangeBridgeBusNumber]->proposedSize)
2424				   || ((!bootScan) && bridge->ranges[kIOPCIRangeBridgeBusNumber]->size)));
2425		if (haveBus)
2426		{
2427			DLOG("scan %s"B()"\n", bootScan ? "(boot) " : "", BRIDGE_IDENT(bridge));
2428			resetMask = 0;
2429			if (kPCIStatic != bridge->supportsHotPlug)
2430			{
2431				resetMask = ((1 << kIOPCIResourceTypeMemory)
2432						   | (1 << kIOPCIResourceTypePrefetchMemory)
2433						   | (1 << kIOPCIResourceTypeIO));
2434				if (!bootScan) resetMask |= (1 << kIOPCIResourceTypeBusNumber);
2435			}
2436			bridgeScanBus(bridge, bridge->secBusNum, resetMask);
2437			bridge->deviceState |= kPCIDeviceStateScanned;
2438			if (kPCIDeviceStateChildChanged & bridge->deviceState)
2439			{
2440				DLOG("bridge "B()" child change\n", BRIDGE_IDENT(bridge));
2441#if 0
2442				IOPCIConfigEntry * parents;
2443				for (parents = bridge;
2444					 parents = parents->parent;
2445					 parents->deviceState &= ~(kPCIDeviceStateTotalled), true) {}
2446#elif 0
2447				bridge->parent->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated);
2448#endif
2449				bridge->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated
2450										| kPCIDeviceStateAllocatedBus);
2451			}
2452		}
2453
2454        // Associate bootrom devices.
2455        bridgeConnectDeviceTree(bridge);
2456    }
2457    if (!bootScan)
2458	{
2459		if (!(kPCIDeviceStateAllocatedBus & bridge->deviceState))
2460		{
2461			FOREACH_CHILD(bridge, child) child->deviceState &= ~kPCIDeviceStateAllocatedBus;
2462			bridge->deviceState &= ~kPCIDeviceStateTotalled;
2463			ok = bridgeTotalResources(bridge, (1 << kIOPCIResourceTypeBusNumber));
2464			if (ok)
2465			{
2466				ok = bridgeAllocateResources(bridge, (1 << kIOPCIResourceTypeBusNumber));
2467				DLOG("bus alloc done (bridge "B()", state 0x%x, ok %d)\n",
2468						BRIDGE_IDENT(bridge), bridge->deviceState, ok);
2469			}
2470			if (ok > 0)	bridge->deviceState |= kPCIDeviceStateAllocatedBus;
2471			else        bridge->parent->deviceState &= ~kPCIDeviceStateAllocatedBus;
2472		}
2473	}
2474    return (ok);
2475}
2476
2477//---------------------------------------------------------------------------
2478
2479int32_t CLASS::bootResetProc(void * ref, IOPCIConfigEntry * bridge)
2480{
2481    bool     ok = true;
2482    uint32_t reg32;
2483
2484	if ((kPCIStatic != bridge->supportsHotPlug)
2485	 && bridge->ranges[kIOPCIRangeBridgeBusNumber]
2486	 && !bridge->ranges[kIOPCIRangeBridgeBusNumber]->nextSubRange)
2487	{
2488        bridge->ranges[kIOPCIRangeBridgeBusNumber]->start        = 0;
2489        bridge->ranges[kIOPCIRangeBridgeBusNumber]->size         = 0;
2490        bridge->ranges[kIOPCIRangeBridgeBusNumber]->totalSize    = 1;
2491        bridge->ranges[kIOPCIRangeBridgeBusNumber]->proposedSize = 1;
2492		if (kPCIHotPlugTunnelRootParent != bridge->supportsHotPlug)
2493		{
2494			DLOG("boot reset "B()"\n", BRIDGE_IDENT(bridge));
2495			reg32 = configRead32(bridge, kPCI2PCIPrimaryBus);
2496			reg32 &= ~0x00ffffff;
2497			configWrite32(bridge, kPCI2PCIPrimaryBus, reg32);
2498	    }
2499    }
2500    return (ok);
2501}
2502
2503//---------------------------------------------------------------------------
2504
2505int32_t CLASS::totalProc(void * ref, IOPCIConfigEntry * bridge)
2506{
2507    bool ok;
2508
2509    if (!(kPCIDeviceStateAllocatedBus & bridge->deviceState)) return (true);
2510    if (kPCIDeviceStateTotalled & bridge->deviceState) return (true);
2511
2512    ok = bridgeTotalResources(bridge,
2513                          (1 << kIOPCIResourceTypeMemory)
2514                        | (1 << kIOPCIResourceTypePrefetchMemory)
2515                        | (1 << kIOPCIResourceTypeIO));
2516
2517	if (!ok) bridge->parent->deviceState &= ~kPCIDeviceStateAllocated;
2518	bridge->deviceState |= kPCIDeviceStateTotalled;
2519
2520    return (true);
2521}
2522
2523//---------------------------------------------------------------------------
2524
2525int32_t CLASS::allocateProc(void * ref, IOPCIConfigEntry * bridge)
2526{
2527    int32_t ok = true;
2528
2529    if (!(kPCIDeviceStateAllocatedBus & bridge->deviceState)) return (ok);
2530    if (kPCIDeviceStateAllocated & bridge->deviceState)       return (ok);
2531
2532	FOREACH_CHILD(bridge, child) child->deviceState &= ~kPCIDeviceStateAllocated;
2533
2534	ok = bridgeAllocateResources(bridge,
2535					  (1 << kIOPCIResourceTypeMemory)
2536					| (1 << kIOPCIResourceTypePrefetchMemory)
2537					| (1 << kIOPCIResourceTypeIO));
2538	DLOG("alloc done (bridge "B()", state 0x%x, ok %d)\n",
2539			BRIDGE_IDENT(bridge), bridge->deviceState, ok);
2540
2541	if (ok > 0) bridge->deviceState |= kPCIDeviceStateAllocated;
2542	else        bridge->parent->deviceState &= ~kPCIDeviceStateAllocated;
2543
2544    return (ok);
2545}
2546
2547//---------------------------------------------------------------------------
2548
2549void CLASS::doConfigure(uint32_t options)
2550{
2551    bool bootConfig = (kIOPCIConfiguratorBoot & options);
2552
2553	fMaxPayload = 5;
2554
2555    if (bootConfig) iterate("boot reset", &CLASS::scanProc,                 &CLASS::bootResetProc, this);
2556					iterate("scan total", &CLASS::scanProc,                 &CLASS::totalProc,     NULL);
2557					iterate("allocate",   &CLASS::allocateProc,             NULL,	    			NULL);
2558					iterate("finalize",   &CLASS::bridgeFinalizeConfigProc, NULL,                  NULL);
2559}
2560
2561//---------------------------------------------------------------------------
2562
2563enum
2564{
2565    kIteratorNew       = 0,
2566    kIteratorCheck     = 1,
2567    kIteratorDidCheck  = 2,
2568    kIteratorDoneCheck = 3,
2569};
2570
2571void CLASS::iterate(const char * what, IterateProc topProc, IterateProc bottomProc, void * ref)
2572{
2573    IOPCIConfigEntry * device;
2574    IOPCIConfigEntry * parent;
2575    int32_t			   ok;
2576	uint32_t           revisits;
2577    bool               didCheck;
2578
2579    device = fRoot;
2580    device->iterator = kIteratorCheck;
2581    revisits = 0;
2582
2583    DLOG("iterate %s: start\n", what);
2584    do
2585    {
2586        parent = device->parent;
2587//        DLOG("iterate(bridge "B()", state 0x%x, parent 0x%x)\n", BRIDGE_IDENT(device), device->iterator, parent ? parent->iterator : 0);
2588        ok = true;
2589        didCheck = false;
2590
2591        if (device->iterator == kIteratorCheck)
2592        {
2593            didCheck = true;
2594            if (topProc)
2595            {
2596                ok = (this->*topProc)(ref, device);
2597            }
2598            device->iterator = kIteratorDidCheck;
2599        }
2600
2601		if (!ok)
2602		{
2603			if (++revisits > (8 * fBridgeCount))
2604			{
2605				DLOG("iterate %s: HUNG?\n", what);
2606				ok = -1;
2607			}
2608		}
2609
2610		if (ok < 0) break;
2611
2612        if (parent && !ok)
2613        {
2614            parent->iterator = kIteratorCheck;
2615            device = parent;
2616        }
2617        else
2618        {
2619            IOPCIConfigEntry * child;
2620            IOPCIConfigEntry * next = NULL;
2621            for (child = device->child; child; child = child->peer)
2622            {
2623                if (!child->isBridge)
2624                    continue;
2625                if (didCheck)
2626                    child->iterator = kIteratorCheck;
2627                if (!next && (child->iterator < kIteratorDidCheck))
2628                    next = child;
2629            }
2630            if (next)
2631            {
2632                device = next;
2633            }
2634            else
2635            {
2636                device->iterator = kIteratorDoneCheck;
2637                if (bottomProc)
2638                {
2639                    (void) (this->*bottomProc)(ref, device);
2640                }
2641                device = parent;
2642            }
2643        }
2644    }
2645    while (device);
2646    DLOG("iterate %s: end(%d)\n", what, revisits);
2647}
2648
2649//---------------------------------------------------------------------------
2650
2651void CLASS::configure(uint32_t options)
2652{
2653    bool bootConfig = (kIOPCIConfiguratorBoot & options);
2654
2655    IOLog("[ PCI configuration begin ]\n");
2656
2657    PE_Video	       consoleInfo;
2658
2659	fFlags |= options;
2660
2661#if defined(__i386__) || defined(__x86_64__)
2662    if (bootConfig)
2663    {
2664        if (!fPFMConsole)
2665        {
2666            IOService::getPlatform()->getConsoleInfo(&consoleInfo);
2667            fPFMConsole  = consoleInfo.v_baseAddr;
2668#ifndef __LP64__
2669            fPFMConsole |= (((uint64_t) consoleInfo.v_baseAddrHigh) << 32);
2670#endif
2671            DLOG("console %ld x %ld @ 0x%qx\n",
2672                consoleInfo.v_width, consoleInfo.v_height, fPFMConsole);
2673        }
2674        fConsoleRange = NULL;
2675        getPlatform()->setConsoleInfo(0, kPEDisableScreen);
2676    }
2677#endif
2678
2679    doConfigure(options);
2680
2681#if defined(__i386__) || defined(__x86_64__)
2682    if (bootConfig)
2683    {
2684        if (fConsoleRange)
2685        {
2686            if (fConsoleRange->start)
2687                fPFMConsole += fConsoleRange->start;
2688            else
2689                fPFMConsole = 0;
2690        }
2691        if (!fPFMConsole)
2692        {
2693            DLOG("!! lost console !!\n");
2694        }
2695        else
2696        {
2697            if (fConsoleRange)
2698            {
2699                consoleInfo.v_baseAddr = (fPFMConsole | 1);
2700#ifdef __LP64__
2701                DLOG("console setting @ %lx\n",
2702                    consoleInfo.v_baseAddr);
2703#else
2704                consoleInfo.v_baseAddrHigh = (fPFMConsole >> 32);
2705                DLOG("console setting 0x%lx:%lx\n",
2706                    consoleInfo.v_baseAddrHigh, consoleInfo.v_baseAddr);
2707#endif
2708                getPlatform()->setConsoleInfo(&consoleInfo, kPEBaseAddressChange);
2709            }
2710            getPlatform()->setConsoleInfo(NULL, kPEEnableScreen);
2711            if (fConsoleRange)
2712                IOLog("console relocated to 0x%llx\n", fPFMConsole);
2713        }
2714    }
2715#endif
2716
2717	fFlags &= ~options;
2718
2719    IOLog("[ PCI configuration end, bridges %d, devices %d ]\n", fBridgeCount, fDeviceCount);
2720}
2721
2722//---------------------------------------------------------------------------
2723
2724IOPCIRange * CLASS::bridgeGetRange(IOPCIConfigEntry * bridge, uint32_t type)
2725{
2726    IOPCIRange * range;
2727
2728    if (bridge->isHostBridge && (type != kIOPCIResourceTypeBusNumber))
2729    {
2730        // use global host ranges
2731        bridge = fRoot;
2732    }
2733    switch (type)
2734    {
2735        case kIOPCIResourceTypePrefetchMemory:
2736            range = bridge->ranges[BRN(kIOPCIResourceTypePrefetchMemory)];
2737            if (range)
2738                break;
2739            /* fall thru */
2740
2741        case kIOPCIResourceTypeMemory:
2742            range = bridge->ranges[BRN(kIOPCIResourceTypeMemory)];
2743            break;
2744
2745        case kIOPCIResourceTypeIO:
2746        case kIOPCIResourceTypeBusNumber:
2747            range = bridge->ranges[BRN(type)];
2748            break;
2749
2750        default:
2751            range = NULL;
2752            break;
2753    }
2754    return (range);
2755}
2756
2757//---------------------------------------------------------------------------
2758
2759void CLASS::logAllocatorRange(IOPCIConfigEntry * device, IOPCIRange * range, char c)
2760{
2761    DLOG("  %s: 0x%llx:0x%llx,0x%llx-0x%llx,0x%llx:0x%llx (at "D()") %s%s%s%s%s%s%c",
2762            gPCIResourceTypeName[range->type],
2763            range->start,
2764            range->size, range->proposedSize,
2765            range->totalSize, range->extendSize,
2766            range->alignment,
2767            DEVICE_IDENT(device),
2768            (NULL != range->nextSubRange)                ? "A" : "a",
2769            (kIOPCIRangeFlagRelocatable  & range->flags) ? "R" : "r",
2770            (kIOPCIRangeFlagSplay        & range->flags) ? "S" : "s",
2771            (kIOPCIRangeFlagMaximizeSize & range->flags) ? "M" : "m",
2772            (kIOPCIRangeFlagMaximizeRoot & range->flags) ? "B" : "b",
2773            (kIOPCIRangeFlagReserve      & range->flags) ? "V" : "v",
2774            c);
2775}
2776
2777//---------------------------------------------------------------------------
2778
2779bool CLASS::bridgeTotalResources(IOPCIConfigEntry * bridge, uint32_t typeMask)
2780{
2781	IOPCIConfigEntry * child;
2782	IOPCIRange *       range;
2783    IOPCIRange *       childRange;
2784    uint32_t           type;
2785	bool		       ok = true;
2786
2787    IOPCIScalar		   totalSize[kIOPCIResourceTypeCount];
2788    IOPCIScalar        maxAlignment[kIOPCIResourceTypeCount];
2789    IOPCIScalar        minAddress[kIOPCIResourceTypeCount];
2790    IOPCIScalar        maxAddress[kIOPCIResourceTypeCount];
2791    IOPCIScalar        countMaximize[kIOPCIResourceTypeCount];
2792
2793	if (bridge == fRoot) 							return (ok);
2794    if (kPCIDeviceStateDead & bridge->deviceState)  return (ok);
2795
2796    DLOG("bridgeTotalResources(bridge "B()", iter 0x%x, state 0x%x, type 0x%x)\n",
2797            BRIDGE_IDENT(bridge), bridge->iterator, bridge->deviceState, typeMask);
2798
2799    bzero(&totalSize[0], sizeof(totalSize));
2800    if (bridge != fRoot) totalSize[kIOPCIResourceTypeBusNumber] = 1;
2801
2802    bcopy(&minBridgeAlignments[0], &maxAlignment[0], sizeof(maxAlignment));
2803
2804    bzero(&minAddress[0], sizeof(minAddress));
2805    bcopy(&maxBridgeAddressDefault[0], &maxAddress[0], sizeof(maxAddress));
2806    if (bridge->clean64 && (kIOPCIConfiguratorPFM64 & fFlags))
2807        maxAddress[kIOPCIResourceTypePrefetchMemory] = 0xFFFFFFFFFFFFFFFFULL;
2808    bzero(&countMaximize[0], sizeof(countMaximize));
2809
2810	if ( ((1 << kIOPCIResourceTypeMemory)
2811		| (1 << kIOPCIResourceTypePrefetchMemory)
2812		| (1 << kIOPCIResourceTypeIO))
2813		& typeMask)
2814	do
2815	{
2816		if (!bridge->child) break;
2817		for (child = bridge->child; child; child = child->peer)
2818		{
2819			if (!(kPCIDeviceStateDead & child->deviceState)) break;
2820		}
2821		if (child) break;
2822		// all children are dead, move reserved allocs to parent & free bridge ranges
2823		IOPCIConfigEntry * pendingList = NULL;
2824		IOPCIConfigEntry * next;
2825		for (child = bridge->child; child; child = next)
2826		{
2827			next = child->peer;
2828			bridgeRemoveChild(bridge, child, kIOPCIRangeAllBarsMask, 0, &pendingList);
2829		}
2830		bridgeDeallocateChildRanges(bridge->parent, bridge,
2831								    kIOPCIRangeAllBridgeMask & ~(1 << kIOPCIRangeBridgeBusNumber), 0);
2832		if (!pendingList) panic("!pendingList");
2833		bridgeMoveChildren(bridge->parent, pendingList);
2834		bridge->parent->deviceState &= ~(kPCIDeviceStateTotalled | kPCIDeviceStateAllocated);
2835	}
2836	while (false);
2837
2838	for (child = bridge->child; child; child = child->peer)
2839    {
2840        for (int i = 0; i < kIOPCIRangeCount; i++)
2841        {
2842            childRange = child->ranges[i];
2843            if (!childRange)										continue;
2844            if (!((1 << childRange->type) & typeMask))				continue;
2845            range = bridgeGetRange(bridge, childRange->type);
2846            if (!range)                                             continue;
2847            type = range->type;
2848            if (kIOPCIRangeFlagMaximizeSize & childRange->flags)    countMaximize[type]++;
2849            if (!(childRange->totalSize + childRange->extendSize))  continue;
2850
2851            logAllocatorRange(child, childRange, '\n');
2852
2853			totalSize[type] += childRange->totalSize + childRange->extendSize;
2854            if (childRange->alignment > maxAlignment[type])
2855                maxAlignment[type] = childRange->alignment;
2856
2857            if (childRange->minAddress < minAddress[type])
2858                minAddress[type] = childRange->minAddress;
2859            if (childRange->maxAddress < maxAddress[type])
2860            {
2861                DLOG("  %s: maxAddr change 0x%llx -> 0x%llx (at "D()")\n",
2862                        gPCIResourceTypeName[type],
2863                        maxAddress[type], childRange->maxAddress, DEVICE_IDENT(child));
2864                maxAddress[type] = childRange->maxAddress;
2865			}
2866
2867			if (childRange->proposedSize
2868			  && child->expressCapBlock
2869			  && ((kIOPCIResourceTypeMemory == childRange->type)
2870			    || (kIOPCIResourceTypePrefetchMemory == childRange->type)))
2871			{
2872				if (child->expressMaxPayload < fMaxPayload)
2873				{
2874					fMaxPayload  = child->expressMaxPayload;
2875				}
2876			}
2877        }
2878    }
2879
2880    for (type = 0; type < kIOPCIResourceTypeCount; type++)
2881    {
2882        if (!((1 << type) & typeMask)) continue;
2883        if (bridge->isHostBridge)      continue;
2884        range = bridgeGetRange(bridge, type);
2885        if (range) do
2886        {
2887			if (((kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagMaximizeRoot) & range->flags)
2888			 && !totalSize[type])            totalSize[type] = minBridgeAlignments[type];
2889            totalSize[type] = IOPCIScalarAlign(totalSize[type], minBridgeAlignments[type]);
2890
2891			if (totalSize[type] != range->totalSize
2892			    && !(kIOPCIRangeFlagPermanent & range->flags))
2893			{
2894				DLOG("  %s: 0x%llx: size change 0x%llx -> 0x%llx\n",
2895					  gPCIResourceTypeName[type],
2896					  range->start, range->proposedSize, totalSize[type]);
2897				range->totalSize = totalSize[type];
2898				if (kIOPCIRangeFlagMaximizeRoot & range->flags) {}
2899				else
2900				{
2901					bridge->rangeSizeChanges    |= (1 << BRN(type));
2902					bridge->rangeRequestChanges |= (1 << type);
2903					ok = false;
2904				}
2905			}
2906			if (!((kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagMaximizeRoot) & range->flags))
2907			{
2908				range->alignment = maxAlignment[type];
2909			}
2910			range->minAddress = minAddress[type];
2911			range->maxAddress = maxAddress[type];
2912
2913			DLOG("  %s: total child reqs 0x%llx of 0x%llx maxalign 0x%llx\n",
2914					gPCIResourceTypeName[type],
2915					range->totalSize, range->size, range->alignment);
2916        }
2917		while (false);
2918    }
2919
2920	return (ok);
2921}
2922
2923bool CLASS::treeInState(IOPCIConfigEntry * entry, uint32_t state, uint32_t mask)
2924{
2925	for (; entry; entry = entry->parent)
2926	{
2927		if (state == (mask & entry->deviceState)) break;
2928	}
2929    return (NULL != entry);
2930}
2931
2932static uint32_t IOPCIRangeStateOrder(IOPCIRange * range)
2933{
2934	uint32_t order = 0;
2935
2936	// order 1st allocated, placed, nonresize or shrink, resize, maximise
2937
2938	if (range->nextSubRange) 											order |= (1 << 31);
2939	if (range->start) 													order |= (1 << 30);
2940	if (/*range->nextSubRange &&*/ (range->proposedSize <= range->size))    order |= (1 << 29);
2941	if (!((kIOPCIRangeFlagMaximizeRoot | kIOPCIRangeFlagMaximizeSize | kIOPCIRangeFlagSplay)
2942		& range->flags)) 												order |= (1 << 28);
2943
2944	return (order);
2945}
2946
2947bool IOPCIRangeAppendSubRange(IOPCIRange ** list, IOPCIRange * newRange)
2948{
2949    IOPCIRange ** prev;
2950    IOPCIRange *  range;
2951	uint32_t      newOrder, oldOrder;
2952
2953    newOrder = IOPCIRangeStateOrder(newRange);
2954    prev = list;
2955    do
2956    {
2957        range = *prev;
2958        if (!range)												          break;
2959		oldOrder = IOPCIRangeStateOrder(range);
2960		if (newOrder > oldOrder) 									      break;
2961		else if (newOrder < oldOrder) 									  continue;
2962		if (newRange->alignment > range->alignment)  					  break;
2963		else if (newRange->alignment < range->alignment)  			      continue;
2964		if (newRange->proposedSize >= range->proposedSize)  			  break;
2965		else if (newRange->proposedSize < range->proposedSize)  	      continue;
2966    }
2967    while (prev = &range->nextToAllocate, true);
2968
2969    *prev = newRange;
2970    newRange->nextToAllocate = range;
2971
2972    return (true);
2973}
2974
2975int32_t CLASS::bridgeAllocateResources(IOPCIConfigEntry * bridge, uint32_t typeMask)
2976{
2977    IOPCIRange * requests[kIOPCIResourceTypeCount];
2978    IOPCIScalar  shortage[kIOPCIResourceTypeCount];
2979	IOPCIScalar  shortageAlignments[kIOPCIResourceTypeCount];
2980    IOPCIRange * range;
2981    IOPCIRange * childRange;
2982    IOPCIScalar  shrink;
2983    uint32_t     type;
2984    uint32_t     haveAllocs = 0;
2985    uint32_t     haveRelocs = 0;
2986    uint32_t     doOptimize = 0;
2987    uint32_t     failTypes  = 0;
2988    int32_t      result;
2989    bool         expressCards = false;
2990    bool         ok;
2991	bool         canRelocate;
2992
2993    DLOG("bridgeAllocateResources(bridge "B()", state 0x%x, type 0x%x)\n",
2994            BRIDGE_IDENT(bridge), bridge->deviceState, typeMask);
2995
2996    if (bridge == fRoot)                           return (true);
2997    if (kPCIDeviceStateDead & bridge->deviceState) return (true);
2998
2999	if (treeInState(bridge, kPCIDeviceStateRequestPause,
3000		(kPCIDeviceStateRequestPause | kPCIDeviceStatePaused))) return (-1);
3001
3002    bzero(requests, sizeof(requests));
3003    bzero(shortage, sizeof(shortage));
3004    bzero(shortageAlignments, sizeof(shortageAlignments));
3005
3006    haveAllocs = bridge->haveAllocs;
3007    bridge->haveAllocs = 0;
3008
3009    // determine kIOPCIRangeFlagRelocatable
3010    FOREACH_CHILD(bridge, child)
3011    {
3012        expressCards |= (kPCIHotPlugRoot == child->supportsHotPlug);
3013        if (kPCIStatic == child->supportsHotPlug)      continue;
3014        for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++)
3015        {
3016            childRange = child->ranges[rangeIndex];
3017            if (!childRange)                           continue;
3018            if (!((1 << childRange->type) & typeMask)) continue;
3019
3020            canRelocate = (kIOPCIConfiguratorBoot & fFlags);
3021            canRelocate |= (0 != (kPCIDeviceStatePaused & child->deviceState));
3022
3023            if ((rangeIndex == kIOPCIRangeBridgeBusNumber) && !canRelocate)
3024            {
3025                // bridges with no i/o allocations are bus relocatable
3026                canRelocate |=
3027                    ((!child->ranges[kIOPCIRangeBridgeMemory]
3028                        || !child->ranges[kIOPCIRangeBridgeMemory]->nextSubRange)
3029                    && (!child->ranges[kIOPCIRangeBridgePFMemory]
3030                        || !child->ranges[kIOPCIRangeBridgePFMemory]->nextSubRange)
3031                    && (!child->ranges[kIOPCIRangeBridgeIO]
3032                        || !child->ranges[kIOPCIRangeBridgeIO]->nextSubRange));
3033            }
3034            if (canRelocate)
3035            {
3036                childRange->flags |= kIOPCIRangeFlagRelocatable;
3037            }
3038            else
3039            {
3040                childRange->flags &= ~kIOPCIRangeFlagRelocatable;
3041            }
3042        }
3043    }
3044
3045	if (((1 << kIOPCIResourceTypeBusNumber) & typeMask)
3046	 && (range = bridgeGetRange(bridge, kIOPCIResourceTypeBusNumber))
3047	 && !bridge->busResv.nextSubRange)
3048	{
3049		IOPCIRangeInit(&bridge->busResv, kIOPCIResourceTypeBusNumber,
3050						bridge->secBusNum, 1, kPCIBridgeBusNumberAlignment);
3051		ok = IOPCIRangeListAllocateSubRange(range, &bridge->busResv);
3052		DLOG("  BUS: reserved(%sok) 0x%llx\n", ok ? "" : "!", bridge->busResv.start);
3053	}
3054
3055    // Do any frees, look for relocs, look for new allocs
3056
3057	FOREACH_CHILD(bridge, child)
3058	{
3059		for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++)
3060		{
3061			childRange = child->ranges[rangeIndex];
3062			if (!childRange)                           continue;
3063			if (!((1 << childRange->type) & typeMask)) continue;
3064			range = bridgeGetRange(bridge, childRange->type);
3065			if (!range)                                continue;
3066
3067			if (!childRange->nextSubRange
3068			 && ((kIOPCIRangeFlagMaximizeRoot | kIOPCIRangeFlagMaximizeSize) & childRange->flags))
3069			{
3070                // minSize
3071                childRange->size = minBridgeAlignments[childRange->type];
3072
3073                // maxSize
3074                if (kIOPCIRangeFlagMaximizeRoot & childRange->flags)
3075                {
3076					if (bridge->isHostBridge && range && expressCards
3077					 && (kIOPCIResourceTypeBusNumber == childRange->type))
3078					{
3079						childRange->proposedSize = (range->size * 240) / 255;
3080					}
3081					else
3082					{
3083						childRange->proposedSize = -1ULL;
3084					}
3085				}
3086				else
3087				{
3088					childRange->proposedSize = childRange->totalSize + childRange->extendSize;
3089                }
3090			}
3091			else
3092			{
3093                // maxSize
3094			    if (!childRange->nextSubRange
3095			     || ((childRange->totalSize + childRange->extendSize) > childRange->size))
3096					childRange->proposedSize = childRange->totalSize + childRange->extendSize;
3097			}
3098            //
3099
3100            logAllocatorRange(child, childRange, '\n');
3101
3102			if (!fConsoleRange
3103				&& fPFMConsole
3104				&& (rangeIndex <= kIOPCIRangeBAR5)
3105				&& (fPFMConsole >= childRange->start)
3106				&& (fPFMConsole < (childRange->start + childRange->proposedSize)))
3107			{
3108				DLOG("  hit console\n");
3109				fPFMConsole -= childRange->start;
3110				fConsoleRange = childRange;
3111			}
3112
3113			if (!range) continue;
3114			type = range->type;
3115
3116			if (bridge->isHostBridge
3117				&& !childRange->nextSubRange
3118				&& (kIOPCIResourceTypeMemory == type)
3119				&& (childRange->maxAddress > 0xFFFFFFFFULL))
3120			{
3121				childRange->minAddress = (1ULL << 32);
3122				childRange->start = 0;
3123			}
3124
3125			if (!childRange->proposedSize)
3126			{
3127				if (childRange->nextSubRange)
3128				{
3129					child->rangeBaseChanges |= (1 << rangeIndex);
3130					ok = IOPCIRangeListDeallocateSubRange(range, childRange);
3131					if (!ok) panic("IOPCIRangeListDeallocateSubRange");
3132					haveAllocs |= (1 << type);
3133				}
3134				childRange->start = 0;
3135				childRange->end   = 0;
3136				childRange->size  = 0;
3137				continue;
3138			}
3139			if (kIOPCIRangeFlagRelocatable & childRange->flags)  haveRelocs |= (1 << type);
3140			if (!childRange->nextSubRange)						 haveAllocs |= (1 << type);
3141			if (childRange->proposedSize != childRange->size)    haveAllocs |= (1 << type);
3142		}
3143	}
3144
3145	// Free anything relocatable if new allocs needed
3146
3147	if (haveAllocs & haveRelocs)
3148	{
3149		FOREACH_CHILD(bridge, child)
3150		{
3151			for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++)
3152			{
3153				childRange = child->ranges[rangeIndex];
3154				if (!childRange)                             continue;
3155				if (!((1 << childRange->type) & haveAllocs)) continue;
3156                if (!childRange->nextSubRange)               continue;
3157
3158                range = bridgeGetRange(bridge, childRange->type);
3159                if (!range) continue;
3160				if (kIOPCIRangeFlagRelocatable & childRange->flags)
3161				{
3162					DLOG("  %s:    free reloc 0x%llx:0x%llx (at "D()")\n",
3163							gPCIResourceTypeName[childRange->type],
3164							childRange->start, childRange->size,
3165							DEVICE_IDENT(child));
3166					child->rangeBaseChanges |= (1 << rangeIndex);
3167					ok = IOPCIRangeListDeallocateSubRange(range, childRange);
3168					if (!ok) panic("IOPCIRangeListDeallocateSubRange");
3169					childRange->start = 0;
3170					childRange->proposedSize = childRange->totalSize + childRange->extendSize;
3171				}
3172			}
3173		}
3174	}
3175
3176	// Apply configuration changes to all children.
3177	FOREACH_CHILD(bridge, child)
3178	{
3179		applyConfiguration(child, typeMask, false);
3180	}
3181
3182    // Find allocations to make
3183
3184	FOREACH_CHILD(bridge, child)
3185	{
3186		for (int rangeIndex = 0; rangeIndex < kIOPCIRangeCount; rangeIndex++)
3187		{
3188			childRange = child->ranges[rangeIndex];
3189			if (!childRange)                           continue;
3190			if (!((1 << childRange->type) & typeMask)) continue;
3191			if (!childRange->proposedSize)			   continue;
3192			if (childRange->nextSubRange && (childRange->proposedSize == childRange->size))  continue;
3193
3194			range = bridgeGetRange(bridge, childRange->type);
3195			if (!range) continue;
3196			type = range->type;
3197
3198			child->rangeBaseChanges |= (1 << rangeIndex);
3199			childRange->device = child;
3200			IOPCIRangeAppendSubRange(&requests[type], childRange);
3201
3202		    if ((kIOPCIRangeFlagSplay | kIOPCIRangeFlagMaximizeSize)
3203		             & childRange->flags)
3204		    {
3205                doOptimize |= (1 << type);
3206                if (!childRange->start) childRange->flags |= kIOPCIRangeFlagRelocatable;
3207		    }
3208		}
3209	}
3210
3211    // Make allocations
3212
3213    for (type = 0; type < kIOPCIResourceTypeCount; type++)
3214    {
3215		if (!(haveAllocs & (1 << type))) continue;
3216        range = bridgeGetRange(bridge, type);
3217        if (!range)                      continue;
3218        while ((childRange = requests[type]))
3219        {
3220            requests[type] = childRange->nextToAllocate;
3221			childRange->nextToAllocate = NULL;
3222
3223			IOPCIScalar placed = childRange->start;
3224            ok = IOPCIRangeListAllocateSubRange(range, childRange);
3225
3226            logAllocatorRange(childRange->device, childRange, ' ');
3227			DLOG("%sok allocated%s\n",
3228                 ok ? " " : "!",
3229                 (ok && (childRange->size != childRange->proposedSize)) ? "(short)" : "");
3230
3231			if (ok && (childRange->size == childRange->proposedSize))  continue;
3232
3233			canRelocate = (0 != (kIOPCIConfiguratorBoot & fFlags));
3234			canRelocate |= (!childRange->nextSubRange);
3235			canRelocate |= (0 != (kIOPCIRangeFlagRelocatable & childRange->flags));
3236
3237			if (canRelocate && placed)
3238			{
3239				if (childRange->nextSubRange)
3240				{
3241					DLOG("  %s:  free 0x%llx:0x%llx\n",
3242								gPCIResourceTypeName[type],
3243								childRange->start, childRange->size);
3244					ok = IOPCIRangeListDeallocateSubRange(range, childRange);
3245					if (!ok) panic("IOPCIRangeListDeallocateSubRange");
3246				}
3247				childRange->start = 0;
3248				IOPCIRangeAppendSubRange(&requests[type], childRange);
3249			}
3250			else
3251			{
3252				shortage[type] += childRange->proposedSize;
3253				if (childRange->nextSubRange) shortage[type] -= childRange->size;
3254				if (childRange->alignment > shortageAlignments[type])
3255					shortageAlignments[type] = childRange->alignment;
3256                if (bridge->isHostBridge)
3257                {
3258                    DLOG("  %s: new host req:\n", gPCIResourceTypeName[type]);
3259                    IOPCIRangeDump(range);
3260                }
3261			}
3262        }
3263
3264        if (bridge->isHostBridge) continue;
3265
3266		if (shortage[type])
3267		{
3268			IOPCIScalar newSize, extendAvail;
3269			extendAvail = IOPCIRangeListLastFree(range, shortageAlignments[type]);
3270			if (shortage[type] > extendAvail)
3271			{
3272				newSize = range->size + shortage[type] - extendAvail;
3273				if (newSize > (range->totalSize + range->extendSize))
3274				{
3275					if (kIOPCIRangeFlagMaximizeRoot & range->flags)	{}
3276					else
3277					{
3278						range->extendSize = IOPCIScalarAlign(newSize - range->totalSize, minBridgeAlignments[type]);;
3279						DLOG("  %s: shortage 0x%llx -> 0x%llx, 0x%llx\n",
3280							   gPCIResourceTypeName[type], range->size, range->totalSize, range->extendSize);
3281						bridge->rangeSizeChanges |= (1 << BRN(type));
3282						bridge->rangeRequestChanges |= (1 << type);
3283					}
3284				}
3285			}
3286			failTypes |= (1 << type);
3287		}
3288		else
3289		{
3290			if ((1 << type) & doOptimize)
3291			{
3292                DLOG("  %s: optimize\n", gPCIResourceTypeName[type]);
3293				IOPCIRangeListOptimize(range);
3294			}
3295			if (!(kIOPCIRangeFlagNoCollapse & range->flags))
3296			{
3297				shrink = IOPCIRangeListCollapse(range, minBridgeAlignments[type]);
3298				if (shrink)
3299				{
3300					DLOG("  %s: shrunk 0x%llx:0x%llx-0x%llx, 0x%llx,0x%llx\n",
3301						   gPCIResourceTypeName[type], range->start,
3302						   range->size, range->proposedSize,
3303						   range->totalSize, range->extendSize);
3304					bridge->rangeSizeChanges    |= (1 << BRN(type));
3305					bridge->rangeRequestChanges |= (1 << type);
3306					failTypes |= (1 << type);
3307				}
3308			}
3309		}
3310    }
3311
3312	result = (0 == failTypes);
3313
3314    if (failTypes && !(bridge->rangeRequestChanges & typeMask))
3315    {
3316        result = true;
3317		FOREACH_CHILD(bridge, child)
3318		{
3319			if (!(kIOPCIConfiguratorUsePause & fFlags))   				  continue;
3320			// no pause for i/o
3321			if ((1 << kIOPCIResourceTypeIO) == failTypes) 				  continue;
3322			if ((kPCIDeviceStateRequestPause | kPCIDeviceStatePaused)
3323				& child->deviceState) 				    				  continue;
3324			if (child->supportsHotPlug < kPCIHotPlug)                     continue;
3325			if (!child->dtNub || !child->dtNub->inPlane(gIOServicePlane)) continue;
3326			if (treeInState(child,
3327				kPCIDeviceStatePaused, kPCIDeviceStatePaused))            continue;
3328
3329			DLOG("Request pause for "D()"\n", DEVICE_IDENT(child));
3330			child->deviceState |= kPCIDeviceStateRequestPause;
3331			markChanged(child);
3332			fWaitingPause++;
3333			result = -1;
3334		}
3335        if (true == result) DLOG("  exhausted\n");
3336    }
3337
3338    if (!result)
3339    {
3340        bridge->rangeRequestChanges &= ~typeMask;
3341    }
3342
3343	// Apply configuration changes to all children.
3344	FOREACH_CHILD(bridge, child)
3345	{
3346		applyConfiguration(child, typeMask, true);
3347	}
3348
3349    return (result);
3350}
3351
3352//---------------------------------------------------------------------------
3353
3354uint16_t CLASS::disableAccess(IOPCIConfigEntry * device, bool disable)
3355{
3356    uint16_t  command;
3357
3358    command = configRead16(device, kIOPCIConfigCommand);
3359    if (disable)
3360    {
3361        configWrite16(device, kIOPCIConfigCommand,
3362                        (command & ~(kIOPCICommandIOSpace | kIOPCICommandMemorySpace)));
3363    }
3364    return (command);
3365}
3366
3367void CLASS::restoreAccess( IOPCIConfigEntry * device, UInt16 command )
3368{
3369    configWrite16(device, kIOPCIConfigCommand, command);
3370}
3371
3372//---------------------------------------------------------------------------
3373
3374void CLASS::applyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog)
3375{
3376    if ((!device->isHostBridge) && !(kPCIDeviceStateDead & device->deviceState))
3377    {
3378        if (device->rangeBaseChanges || device->rangeSizeChanges)
3379        {
3380            switch (device->headerType)
3381            {
3382                case kPCIHeaderType0:
3383                    deviceApplyConfiguration(device, typeMask, dolog);
3384                    break;
3385                case kPCIHeaderType1:
3386                case kPCIHeaderType2:
3387                    bridgeApplyConfiguration(device, typeMask, dolog);
3388                    break;
3389            }
3390            device->deviceState &= ~kPCIDeviceStatePropertiesDone;
3391        }
3392		if (!(kPCIDeviceStatePropertiesDone & device->deviceState))
3393			writeLatencyTimer(device);
3394    }
3395
3396    device->deviceState |= kPCIDeviceStateConfigurationDone;
3397}
3398
3399void CLASS::deviceApplyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog)
3400{
3401    IOPCIScalar start;
3402    IOPCIRange * range;
3403    uint16_t     reg16;
3404
3405    DLOGI("Applying config (bm 0x%x, sm 0x%x) for device "D()"\n",
3406            device->rangeBaseChanges, device->rangeSizeChanges,
3407            DEVICE_IDENT(device));
3408
3409    reg16 = disableAccess(device, true);
3410
3411    for (int rangeIndex = kIOPCIRangeBAR0; rangeIndex <= kIOPCIRangeExpansionROM; rangeIndex++)
3412    {
3413        uint32_t bar;
3414        bool     change;
3415        range = device->ranges[rangeIndex];
3416        if (!range)
3417            continue;
3418        if (!((1 << range->type) & typeMask))
3419            continue;
3420        change = (0 != ((1 << rangeIndex) & device->rangeBaseChanges));
3421        device->rangeBaseChanges &= ~(1 << rangeIndex);
3422        device->rangeSizeChanges &= ~(1 << rangeIndex);
3423        if (change)
3424        {
3425            start = range->start;
3426            if (!start)
3427                continue;
3428            if (rangeIndex <= kIOPCIRangeBAR5)
3429                bar = kIOPCIConfigBaseAddress0 + (rangeIndex * 4);
3430            else
3431                bar = kIOPCIConfigExpansionROMBase;
3432            configWrite32(device, bar, start);
3433            DLOGI("  [0x%x %s] 0x%llx, read 0x%x\n",
3434                bar, gPCIResourceTypeName[range->type],
3435                start & 0xFFFFFFFF, configRead32(device, bar));
3436            if (kIOPCIConfigExpansionROMBase != bar)
3437            {
3438                start >>= 32;
3439                if (start)
3440                {
3441                    rangeIndex++;
3442                    bar += 4;
3443                    configWrite32(device, bar, start);
3444                    DLOGI("  [0x%x %s] 0x%llx, read 0x%x\n",
3445                        bar, gPCIResourceTypeName[range->type],
3446                        start, configRead32(device, bar));
3447                }
3448            }
3449        }
3450    }
3451
3452//    reg16 &= ~(kIOPCICommandIOSpace | kIOPCICommandMemorySpace |
3453//               kIOPCICommandBusMaster | kIOPCICommandMemWrInvalidate);
3454    restoreAccess(device, reg16);
3455
3456    DLOGI("  Device Command = 0x%08x\n", (uint32_t)
3457         configRead32(device, kIOPCIConfigCommand));
3458}
3459
3460void CLASS::bridgeApplyConfiguration(IOPCIConfigEntry * bridge, uint32_t typeMask, bool dolog)
3461{
3462    IOPCIScalar  start;
3463    IOPCIScalar  end;
3464    IOPCIRange * range;
3465    uint16_t     commandReg = 0;
3466    uint32_t     baselim32;
3467    uint16_t     baselim16;
3468    bool         accessDisabled;
3469
3470    enum {
3471        kBridgeCommand = (kIOPCICommandIOSpace | kIOPCICommandMemorySpace | kIOPCICommandBusMaster)
3472    };
3473
3474    do
3475    {
3476        accessDisabled = false;
3477        DLOGI("Applying config for bridge "B()" (disabled %d)\n",
3478                BRIDGE_IDENT(bridge), accessDisabled);
3479
3480        commandReg = disableAccess(bridge, accessDisabled);
3481
3482        // Program bridge BAR0 and BAR1
3483
3484        for (int rangeIndex = kIOPCIRangeBAR0; rangeIndex <= kIOPCIRangeBAR1; rangeIndex++)
3485        {
3486            int thisIndex = rangeIndex;
3487            range = bridge->ranges[rangeIndex];
3488            if (!range)
3489                continue;
3490            if (!((1 << range->type) & typeMask))
3491                continue;
3492            if ((1 << rangeIndex) & bridge->rangeBaseChanges)
3493            {
3494				uint32_t bar;
3495                start = range->start;
3496                bar = kIOPCIConfigBaseAddress0 + (rangeIndex * 4);
3497                configWrite32(bridge, bar, start);
3498				DLOGI("  [0x%x %s] 0x%llx, read 0x%x\n",
3499					bar, gPCIResourceTypeName[range->type],
3500					start & 0xFFFFFFFF, configRead32(bridge, bar));
3501                start >>= 32;
3502                if (start)
3503                {
3504                    rangeIndex++;
3505                    bar += 4;
3506                    configWrite32(bridge, bar, start);
3507                    DLOGI("  [0x%x %s] 0x%llx, read 0x%x\n",
3508                        bar, gPCIResourceTypeName[range->type],
3509                        start, configRead32(bridge, bar));
3510                }
3511            }
3512            bridge->rangeBaseChanges &= ~(1 << thisIndex);
3513            bridge->rangeSizeChanges &= ~(1 << thisIndex);
3514        }
3515
3516        if (((1 << kIOPCIResourceTypeBusNumber) & typeMask)
3517          && ((1 << kIOPCIRangeBridgeBusNumber) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges)))
3518        {
3519			range = bridge->ranges[kIOPCIRangeBridgeBusNumber];
3520            DLOGI_RANGE("  BUS", range);
3521			if (range->start && range->size)
3522			{
3523				bridge->secBusNum = range->start;
3524				bridge->subBusNum = range->start + range->size - 1;
3525			}
3526			else
3527			{
3528				bridge->secBusNum = bridge->subBusNum = 0;
3529			}
3530
3531            // Give children the correct bus
3532
3533            FOREACH_CHILD(bridge, child)
3534            {
3535                child->space.s.busNum = bridge->secBusNum;
3536            	child->deviceState &= ~kPCIDeviceStatePropertiesDone;
3537            }
3538
3539            DLOGI("  OLD: prim/sec/sub = 0x%02x:0x%02x:0x%02x\n",
3540                 configRead8(bridge, kPCI2PCIPrimaryBus),
3541                 configRead8(bridge, kPCI2PCISecondaryBus),
3542                 configRead8(bridge, kPCI2PCISubordinateBus));
3543
3544            // Program bridge bus numbers
3545
3546            uint32_t reg32 = configRead32(bridge, kPCI2PCIPrimaryBus);
3547            reg32 &= ~0x00ffffff;
3548            reg32 |= bridge->space.s.busNum | (bridge->secBusNum << 8) | (bridge->subBusNum << 16);
3549            configWrite32(bridge, kPCI2PCIPrimaryBus, reg32);
3550
3551            DLOGI("  BUS: prim/sec/sub = 0x%02x:0x%02x:0x%02x\n",
3552                 configRead8(bridge, kPCI2PCIPrimaryBus),
3553                 configRead8(bridge, kPCI2PCISecondaryBus),
3554                 configRead8(bridge, kPCI2PCISubordinateBus));
3555
3556            bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgeBusNumber);
3557            bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgeBusNumber);
3558        }
3559
3560        // That's it for cardbus
3561        if (kPCIHeaderType2 == bridge->headerType) break;
3562
3563        if (((1 << kIOPCIResourceTypeIO) & typeMask)
3564          && ((1 << kIOPCIRangeBridgeIO) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges)))
3565        {
3566            // Program I/O base and limit
3567
3568            DLOGI_RANGE("  I/O", bridge->ranges[kIOPCIRangeBridgeIO]);
3569
3570            baselim16 = 0x00f0; // closed range
3571            range = bridge->ranges[kIOPCIRangeBridgeIO];
3572            if (range && range->size)
3573            {
3574                assert(range->start);
3575                assert((range->size  & (4096-1)) == 0);
3576                assert((range->start & (4096-1)) == 0);
3577                assert((range->start & 0xffff0000) == 0);
3578
3579                start = range->start;
3580                end = start + range->size - 1;
3581                baselim16 = ((start >> 8) & 0xf0) | (end & 0xf000);
3582            }
3583            configWrite16(bridge, kPCI2PCIIORange, baselim16);
3584            configWrite32(bridge, kPCI2PCIUpperIORange, 0);
3585
3586            DLOGI("  I/O: base/limit   = 0x%04x\n",
3587                 configRead16(bridge, kPCI2PCIIORange));
3588
3589            bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgeIO);
3590            bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgeIO);
3591        }
3592
3593        if (((1 << kIOPCIResourceTypeMemory) & typeMask)
3594          && ((1 << kIOPCIRangeBridgeMemory) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges)))
3595        {
3596            // Program memory base and limit
3597
3598            DLOGI_RANGE("  MEM", bridge->ranges[kIOPCIRangeBridgeMemory]);
3599
3600            baselim32 = 0x0000FFF0; // closed range
3601            range = bridge->ranges[kIOPCIRangeBridgeMemory];
3602            if (range && range->size && !(kPCIDeviceStateNoLink & bridge->deviceState))
3603            {
3604                assert(range->start);
3605                assert((range->size  & (0x100000-1)) == 0);
3606                assert((range->start & (0x100000-1)) == 0);
3607
3608                start = range->start;
3609                end   = range->start + range->size - 1;
3610                baselim32 = ((start >> 16) & 0xFFF0) | (end & 0xFFF00000);
3611            }
3612            configWrite32(bridge, kPCI2PCIMemoryRange, baselim32);
3613
3614            DLOGI("  MEM: base/limit   = 0x%08x\n", (uint32_t)
3615                 configRead32(bridge, kPCI2PCIMemoryRange));
3616
3617            bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgeMemory);
3618            bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgeMemory);
3619        }
3620
3621        if (((1 << kIOPCIResourceTypePrefetchMemory) & typeMask)
3622          && ((1 << kIOPCIRangeBridgePFMemory) & (bridge->rangeBaseChanges | bridge->rangeSizeChanges)))
3623        {
3624            // Program prefetchable memory base and limit
3625
3626            DLOGI_RANGE("  PFM", bridge->ranges[kIOPCIRangeBridgePFMemory]);
3627
3628            baselim32 = 0x0000FFF0; // closed range
3629            start     = 0;
3630            end       = 0;
3631
3632            if ((1 << kIOPCIRangeBridgePFMemory) & bridge->rangeBaseChanges)
3633			{
3634				configWrite32(bridge, kPCI2PCIPrefetchUpperBase,  -1U);
3635				configWrite32(bridge, kPCI2PCIPrefetchUpperLimit, -1U);
3636				configWrite32(bridge, kPCI2PCIPrefetchMemoryRange, baselim32);
3637			}
3638            range = bridge->ranges[kIOPCIRangeBridgePFMemory];
3639            if (range && range->size && !(kPCIDeviceStateNoLink & bridge->deviceState))
3640            {
3641                assert(range->start);
3642                assert((range->size  & (0x100000-1)) == 0);
3643                assert((range->start & (0x100000-1)) == 0);
3644
3645                start = range->start;
3646                end = range->start + range->size - 1;
3647                baselim32 = ((start >> 16) & 0xFFF0) | (end & 0xFFF00000);
3648            }
3649            configWrite32(bridge, kPCI2PCIPrefetchMemoryRange, baselim32);
3650            configWrite32(bridge, kPCI2PCIPrefetchUpperLimit, (end   >> 32));
3651            configWrite32(bridge, kPCI2PCIPrefetchUpperBase,  (start >> 32));
3652
3653            DLOGI("  PFM: base/limit   = 0x%08x, 0x%08x, 0x%08x\n",
3654                 (uint32_t)configRead32(bridge, kPCI2PCIPrefetchMemoryRange),
3655                 (uint32_t)configRead32(bridge, kPCI2PCIPrefetchUpperBase),
3656                 (uint32_t)configRead32(bridge, kPCI2PCIPrefetchUpperLimit));
3657
3658            bridge->rangeBaseChanges &= ~(1 << kIOPCIRangeBridgePFMemory);
3659            bridge->rangeSizeChanges &= ~(1 << kIOPCIRangeBridgePFMemory);
3660        }
3661    }
3662    while (false);
3663
3664    // Set IOSE, memory enable, Bus Master transaction forwarding
3665
3666    DLOGI("Enabling bridge "B()"\n", BRIDGE_IDENT(bridge));
3667
3668    if (kPCIHeaderType2 == bridge->headerType)
3669    {
3670        commandReg &= ~(kIOPCICommandIOSpace | kIOPCICommandMemorySpace |
3671                   kIOPCICommandBusMaster | kIOPCICommandMemWrInvalidate);
3672    }
3673    else
3674    {
3675        uint16_t bridgeControl;
3676
3677        commandReg |= (kIOPCICommandIOSpace
3678                     | kIOPCICommandMemorySpace
3679//                     | kIOPCICommandSERR
3680                     | kIOPCICommandBusMaster);
3681
3682        // Turn off ISA bit.
3683        bridgeControl = configRead16(bridge, kPCI2PCIBridgeControl);
3684        if (bridgeControl & 0x0004)
3685        {
3686            bridgeControl &= ~0x0004;
3687            configWrite16(bridge, kPCI2PCIBridgeControl, bridgeControl);
3688            DLOGI("  Bridge Control    = 0x%04x\n",
3689                 configRead16(bridge, kPCI2PCIBridgeControl));
3690        }
3691    }
3692
3693    restoreAccess(bridge, commandReg);
3694
3695    DLOGI("  Bridge Command    = 0x%08x\n",
3696         configRead32(bridge, kIOPCIConfigCommand));
3697}
3698
3699//---------------------------------------------------------------------------
3700
3701#ifndef ExtractLSB
3702#define ExtractLSB(x) ((x) & (~((x) - 1)))
3703#endif
3704
3705void CLASS::checkCacheLineSize(IOPCIConfigEntry * device)
3706{
3707    uint8_t cacheLineSize, cls, was;
3708
3709    if (device->isHostBridge)
3710        return;
3711
3712    if (kPCIStatic == device->parent->supportsHotPlug)
3713        return;
3714
3715    if ((kPCIHotPlugTunnelRoot == device->parent->supportsHotPlug)
3716       || (kPCIHotPlugTunnel == device->parent->supportsHotPlug))
3717		cacheLineSize = 0x20;
3718	else
3719		cacheLineSize = 0x40;
3720
3721    cls = configRead8(device, kIOPCIConfigCacheLineSize);
3722    was = cls;
3723
3724    // config looks reasonable, keep original value
3725    if ((cls >= cacheLineSize) && ((cls % cacheLineSize) == 0))
3726        return;
3727
3728    configWrite8(device, kIOPCIConfigCacheLineSize, cacheLineSize);
3729    cls = configRead8(device, kIOPCIConfigCacheLineSize);
3730    if (cls != cacheLineSize)
3731    {
3732        DLOG("  could not set CLS from %u to %u dwords\n", was, cls);
3733        configWrite8(device, kIOPCIConfigCacheLineSize, 0);
3734    }
3735    else
3736    {
3737        DLOG("  changed CLS from %u to %u dwords\n", was, cls);
3738    }
3739}
3740
3741//---------------------------------------------------------------------------
3742
3743void CLASS::writeLatencyTimer(IOPCIConfigEntry * device)
3744{
3745    const uint8_t defaultLT = 0x40;
3746    uint8_t was, now;
3747
3748    if (device == fRoot)
3749        return;
3750
3751    // Nothing fancy here, just set the latency timer to 64 PCI clocks.
3752
3753    was = configRead8(device, kIOPCIConfigLatencyTimer);
3754    configWrite8(device, kIOPCIConfigLatencyTimer, defaultLT);
3755    now = configRead8(device, kIOPCIConfigLatencyTimer);
3756    if (was != now)
3757    {
3758        DLOG("  changed LT %u->%u PCI clocks\n", was, now);
3759    }
3760
3761    // Bridges can act as an initiator on either side of the bridge,
3762    // and there is a separate register for the latency timer on the
3763    // secondary side.
3764
3765    if (device->isBridge)
3766    {
3767        was = configRead8(device, kPCI2PCISecondaryLT);
3768        configWrite8(device, kPCI2PCISecondaryLT, defaultLT);
3769        now = configRead8(device, kPCI2PCISecondaryLT);
3770        if (was != now)
3771        {
3772            DLOG("  changed SEC-LT %u->%u PCI clocks\n", was, now);
3773        }
3774    }
3775}
3776
3777//---------------------------------------------------------------------------
3778
3779int32_t CLASS::bridgeFinalizeConfigProc(void * unused, IOPCIConfigEntry * bridge)
3780{
3781	uint32_t deviceControl, newControl, maxReadReq;
3782
3783    if (!(kPCIDeviceStateAllocated & bridge->deviceState)) return (true);
3784    bridge->deviceState &= ~kPCIDeviceStateChildChanged;
3785
3786#if defined(__i386__) || defined(__x86_64__)
3787	if (bridge->supportsHotPlug >= kPCIHotPlug)
3788#endif
3789	{
3790		FOREACH_CHILD(bridge, child)
3791		{
3792			if (kPCIDeviceStateDead & child->deviceState) 			continue;
3793			if (kPCIDeviceStatePropertiesDone & child->deviceState) continue;
3794			if (!child->expressCapBlock) 							continue;
3795			deviceControl = configRead16(child, child->expressCapBlock + 0x08);
3796			newControl    = deviceControl & ~((7 << 5) | (7 << 12));
3797#if defined(__i386__) || defined(__x86_64__)
3798            maxReadReq    = fMaxPayload;
3799#else
3800            maxReadReq    = 0x05;   // 4096
3801#endif
3802			newControl    |= (fMaxPayload << 5) | (maxReadReq << 12);
3803			if (newControl != deviceControl)
3804			{
3805				configWrite16(child, child->expressCapBlock + 0x08, deviceControl);
3806				DLOG("payload set 0x%08x -> 0x%08x (at "D()"), fMaxPayload 0x%x\n",
3807					  deviceControl, newControl,
3808					  DEVICE_IDENT(child), fMaxPayload);
3809			}
3810		}
3811	}
3812
3813	if ((kPCIDeviceStateChildAdded & bridge->deviceState) && !fWaitingPause)
3814	{
3815		bridge->deviceState &= ~kPCIDeviceStateChildAdded;
3816		markChanged(bridge);
3817	}
3818
3819#if PLX8680
3820	do
3821	{
3822		volatile uint32_t * regs;
3823		uint32_t            reg32, lut;
3824		IOPCIConfigEntry *  parent;
3825
3826		parent = bridge;
3827		do { regs = parent->plx; } while (!regs && (parent = parent->parent));
3828		if (!regs) break;
3829
3830		FOREACH_CHILD(bridge, child)
3831		{
3832		    if (kPCIHeaderType0 != child->headerType) continue;
3833            if (0x868010b5 == child->vendorProduct)   continue;
3834
3835			reg32 = (child->space.s.busNum << 8);
3836//			reg32 |= (child->space.s.deviceNum << 3);
3837//			reg32 |= (child->space.s.functionNum << 0);
3838			reg32 |= 0x80000000;
3839
3840            regs += ((0x3e000 + 0xd98) / 4);
3841			for (lut = 0; lut < 7; lut++)
3842			{
3843				if (reg32 == regs[lut]) break;
3844				if (0x80000000 & regs[lut]) continue;
3845                regs[lut] = reg32;
3846                DLOG("PLX LUT[0x%x] == 0x%x\n", &regs[lut], reg32);
3847                if (lut && parent->ranges[kIOPCIRangeBridgePFMemory])
3848                {
3849                    child->plxAperture = parent->ranges[kIOPCIRangeBridgePFMemory]->start;
3850                }
3851                break;
3852			}
3853		}
3854	}
3855	while (false);
3856#endif /* PLX8680 */
3857
3858	return (bridgeConstructDeviceTree(unused, bridge));
3859}
3860
3861/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3862 *
3863 * Configuration Space Access
3864 *
3865 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3866
3867uint32_t CLASS::configRead32( IOPCIAddressSpace space, uint32_t offset )
3868{
3869	space.es.registerNumExtended = (offset >> 8);
3870    return (fHostBridge->configRead32(space, offset));
3871}
3872
3873void CLASS::configWrite32( IOPCIAddressSpace space, uint32_t offset, uint32_t data )
3874{
3875	space.es.registerNumExtended = (offset >> 8);
3876    fHostBridge->configWrite32(space, offset, data);
3877}
3878
3879/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3880
3881bool CLASS::configAccess(IOPCIConfigEntry * device, bool write)
3882{
3883	bool ok =
3884	(0 == ((write ? kPCIDeviceStateConfigWProtect : kPCIDeviceStateConfigRProtect)
3885			& device->deviceState));
3886	if (!ok)
3887	{
3888		DLOG("config protect fail(1) for device "D()"\n", DEVICE_IDENT(device));
3889		OSReportWithBacktrace("config protect fail(1) for device "D()"\n",
3890								DEVICE_IDENT(device));
3891	}
3892
3893	return (ok);
3894}
3895
3896/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3897
3898enum
3899{
3900   kConfigWrite = 0x00,
3901   kConfigRead  = 0x01,
3902   kConfig32    = (sizeof(uint32_t) << 1),
3903   kConfig16    = (sizeof(uint16_t) << 1),
3904   kConfig8     = (sizeof(uint8_t)  << 1),
3905};
3906
3907void CLASS::configAccess(IOPCIConfigEntry * device, uint32_t access, uint32_t offset, void * data)
3908{
3909	uint8_t * addr;
3910
3911	addr = device->configShadow + offset;
3912	if (kConfigRead & access) bcopy(addr, data, (access >> 1));
3913	else                      bcopy(data, addr, (access >> 1));
3914}
3915
3916/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3917
3918uint32_t CLASS::configRead32( IOPCIConfigEntry * device, uint32_t offset )
3919{
3920	if (device->configShadow)
3921	{
3922		uint32_t data;
3923		configAccess(device, kConfig32|kConfigRead, offset, &data);
3924		return (data);
3925	}
3926
3927	if (!configAccess(device, false)) return (0xFFFFFFFF);
3928
3929	IOPCIAddressSpace space      = device->space;
3930	space.es.registerNumExtended = (offset >> 8);
3931    return (fHostBridge->configRead32(space, offset));
3932}
3933
3934void CLASS::configWrite32( IOPCIConfigEntry * device,
3935                           uint32_t offset, uint32_t data )
3936{
3937	if (device->configShadow)
3938	{
3939		configAccess(device, kConfig32|kConfigWrite, offset, &data);
3940	}
3941
3942	if (!configAccess(device, true)) return;
3943
3944	IOPCIAddressSpace space      = device->space;
3945	space.es.registerNumExtended = (offset >> 8);
3946    fHostBridge->configWrite32(space, offset, data);
3947}
3948
3949uint16_t CLASS::configRead16( IOPCIConfigEntry * device, uint32_t offset )
3950{
3951	if (device->configShadow)
3952	{
3953		uint16_t data;
3954		configAccess(device, kConfig16|kConfigRead, offset, &data);
3955		return (data);
3956	}
3957
3958	if (!configAccess(device, false)) return (0xFFFF);
3959
3960	IOPCIAddressSpace space      = device->space;
3961	space.es.registerNumExtended = (offset >> 8);
3962    return (fHostBridge->configRead16(space, offset));
3963}
3964
3965void CLASS::configWrite16( IOPCIConfigEntry * device,
3966                           uint32_t offset, uint16_t data )
3967{
3968	if (device->configShadow)
3969	{
3970		configAccess(device, kConfig16|kConfigWrite, offset, &data);
3971	}
3972
3973	if (!configAccess(device, true)) return;
3974
3975	IOPCIAddressSpace space      = device->space;
3976	space.es.registerNumExtended = (offset >> 8);
3977    fHostBridge->configWrite16(space, offset, data);
3978}
3979
3980uint8_t CLASS::configRead8( IOPCIConfigEntry * device, uint32_t offset )
3981{
3982	if (device->configShadow)
3983	{
3984		uint8_t data;
3985		configAccess(device, kConfig8|kConfigRead, offset, &data);
3986		return (data);
3987	}
3988
3989	if (!configAccess(device, false)) return (0xFF);
3990
3991	IOPCIAddressSpace space      = device->space;
3992	space.es.registerNumExtended = (offset >> 8);
3993    return (fHostBridge->configRead8(space, offset));
3994}
3995
3996void CLASS::configWrite8( IOPCIConfigEntry * device,
3997                          uint32_t offset, uint8_t data )
3998{
3999	if (device->configShadow)
4000	{
4001		configAccess(device, kConfig8|kConfigWrite, offset, &data);
4002	}
4003
4004	if (!configAccess(device, true)) return;
4005
4006	IOPCIAddressSpace space      = device->space;
4007	space.es.registerNumExtended = (offset >> 8);
4008    fHostBridge->configWrite8(space, offset, data);
4009}
4010/* -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: t -*- */
4011