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#ifndef _IOPCICONFIGURATOR_H
24#define _IOPCICONFIGURATOR_H
25
26#if ACPI_SUPPORT
27#define PLX8680		0
28#endif
29
30/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
31
32typedef uint64_t IOPCIScalar;
33
34enum {
35    kIOPCIRangeFlagMaximizeSize  = 0x00000001,
36    kIOPCIRangeFlagNoCollapse    = 0x00000002,
37    kIOPCIRangeFlagMaximizeRoot  = 0x00000004,
38    kIOPCIRangeFlagSplay         = 0x00000008,
39    kIOPCIRangeFlagRelocatable   = 0x00000010,
40    kIOPCIRangeFlagReserve       = 0x00000020,
41    kIOPCIRangeFlagPermanent     = 0x00000040,
42};
43
44struct IOPCIRange
45{
46    IOPCIScalar         start;
47    IOPCIScalar         size;
48    IOPCIScalar         totalSize;
49    IOPCIScalar         extendSize;
50    IOPCIScalar         proposedSize;
51
52    // end marker
53    IOPCIScalar         end;
54    IOPCIScalar         zero;
55
56    IOPCIScalar         alignment;
57    IOPCIScalar         minAddress;
58    IOPCIScalar         maxAddress;
59
60    uint8_t             type;
61    uint8_t             resvB[3];
62    uint32_t            flags;
63    struct IOPCIRange * next;
64    struct IOPCIRange * nextSubRange;
65    struct IOPCIRange * allocations;
66
67    struct IOPCIRange *  nextToAllocate;
68    struct IOPCIConfigEntry * device; 			// debug
69};
70
71IOPCIScalar IOPCIScalarAlign(IOPCIScalar num, IOPCIScalar alignment);
72IOPCIScalar IOPCIScalarTrunc(IOPCIScalar num, IOPCIScalar alignment);
73
74IOPCIRange * IOPCIRangeAlloc(void);
75
76void IOPCIRangeFree(IOPCIRange * range);
77
78void IOPCIRangeInit(IOPCIRange * range, uint32_t type,
79                  IOPCIScalar start, IOPCIScalar size, IOPCIScalar alignment = 0);
80void IOPCIRangeInitAlloc(IOPCIRange * range, uint32_t type,
81                         IOPCIScalar start, IOPCIScalar size, IOPCIScalar alignment = 0);
82
83void IOPCIRangeDump(IOPCIRange * head);
84
85bool IOPCIRangeListAddRange(IOPCIRange ** rangeList,
86                          uint32_t type,
87                          IOPCIScalar start,
88                          IOPCIScalar size,
89                          IOPCIScalar alignment = 1);
90
91bool IOPCIRangeDeallocateSubRange(IOPCIRange * headRange,
92                                IOPCIRange * oldRange);
93
94bool IOPCIRangeListAllocateSubRange(IOPCIRange * headRange,
95                                  IOPCIRange * newRange,
96                                  IOPCIScalar  newStart = 0);
97
98bool IOPCIRangeListDeallocateSubRange(IOPCIRange * headRange,
99                                IOPCIRange * oldRange);
100
101bool IOPCIRangeAppendSubRange(IOPCIRange ** headRange,
102                              IOPCIRange * newRange );
103
104IOPCIScalar IOPCIRangeListCollapse(IOPCIRange * headRange, IOPCIScalar alignment);
105
106IOPCIScalar IOPCIRangeCollapse(IOPCIRange * headRange, IOPCIScalar alignment);
107
108IOPCIScalar IOPCIRangeListLastFree(IOPCIRange * headRange, IOPCIScalar align);
109IOPCIScalar IOPCIRangeLastFree(IOPCIRange * headRange, IOPCIScalar align);
110void        IOPCIRangeListOptimize(IOPCIRange * headRange);
111
112/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
113
114#ifdef KERNEL
115
116#include <IOKit/IOLib.h>
117#include <IOKit/pci/IOPCIBridge.h>
118
119
120#define kPCIBridgeIOAlignment        (4096)
121#define kPCIBridgeMemoryAlignment    (1024*1024)
122#define kPCIBridgeBusNumberAlignment (1)
123
124
125#define FOREACH_CHILD(bridge, child) \
126    for(IOPCIConfigEntry * (child) = (bridge)->child; (child); (child) = (child)->peer)
127
128enum {
129    kIOPCIConfiguratorIOLog          = 0x00000001,
130    kIOPCIConfiguratorKPrintf        = 0x00000002,
131    kIOPCIConfiguratorVTLog          = 0x00000004,
132
133    kIOPCIConfiguratorAER            = 0x00000008,
134    //        = 0x00000010,
135    //        = 0x00000020,
136
137    kIOPCIConfiguratorLogSaveRestore = 0x00000040,
138    kIOPCIConfiguratorDeferHotPlug   = 0x00000080,
139	kIOPCIConfiguratorPanicOnFault   = 0x00000100,
140    kIOPCIConfiguratorNoSplay        = 0x00000200,
141
142    kIOPCIConfiguratorDeepIdle       = 0x00000400,
143    kIOPCIConfiguratorNoTB           = 0x00000800,
144    kIOPCIConfiguratorTBMSIEnable    = 0x00001000,
145
146    kIOPCIConfiguratorPFM64          = 0x00002000,
147    kIOPCIConfiguratorBoot	         = 0x00004000,
148    kIOPCIConfiguratorIGIsMapped     = 0x00008000,
149    kIOPCIConfiguratorReset          = 0x00010000,
150    kIOPCIConfiguratorAllocate       = 0x00020000,
151	kIOPCIConfiguratorUsePause       = 0x00040000,
152
153    kIOPCIConfiguratorCheckTunnel    = 0x00080000,
154    kIOPCIConfiguratorNoTunnelDrv    = 0x00100000,
155    kIOPCIConfiguratorNoTerminate    = 0x00200000,
156
157    kIOPCIConfiguratorBootDefer      = kIOPCIConfiguratorDeferHotPlug | kIOPCIConfiguratorBoot,
158};
159
160enum {
161    kIOPCIRangeBAR0               = 0,
162    kIOPCIRangeBAR1               = 1,
163    kIOPCIRangeBAR2               = 2,
164    kIOPCIRangeBAR3               = 3,
165    kIOPCIRangeBAR4               = 4,
166    kIOPCIRangeBAR5               = 5,
167    kIOPCIRangeExpansionROM       = 6,
168
169    // order matches kIOPCIResourceType*
170    kIOPCIRangeBridgeMemory       = 7,
171    kIOPCIRangeBridgePFMemory     = 8,
172    kIOPCIRangeBridgeIO           = 9,
173    kIOPCIRangeBridgeBusNumber    = 10,
174
175    kIOPCIRangeCount,
176
177	kIOPCIRangeAllMask		  	  = (1 << kIOPCIRangeCount) - 1,
178	kIOPCIRangeAllBarsMask		  = (1 << (kIOPCIRangeExpansionROM + 1)) - 1,
179	kIOPCIRangeAllBridgeMask	  =  (1 << kIOPCIRangeBridgeMemory)
180								   | (1 << kIOPCIRangeBridgePFMemory)
181								   | (1 << kIOPCIRangeBridgeIO)
182								   | (1 << kIOPCIRangeBridgeBusNumber),
183
184
185};
186
187enum {
188//    kPCIDeviceStateResourceAssigned  = 0x00000001,
189    kPCIDeviceStatePropertiesDone    = 0x00000002,
190    kPCIDeviceStateTreeConnected     = 0x00000004,
191    kPCIDeviceStateConfigurationDone = 0x00000008,
192
193    kPCIDeviceStateScanned          = 0x00000010,
194    kPCIDeviceStateAllocatedBus     = 0x00000020,
195    kPCIDeviceStateTotalled         = 0x00000040,
196    kPCIDeviceStateAllocated        = 0x00000080,
197    kPCIDeviceStateChildChanged     = 0x00000100,
198	kPCIDeviceStateChildAdded       = 0x00000200,
199    kPCIDeviceStateNoLink           = 0x00000400,
200
201	kPCIDeviceStateConfigProtectShift = 15,
202	kPCIDeviceStateConfigRProtect	= (VM_PROT_READ  << kPCIDeviceStateConfigProtectShift),
203	kPCIDeviceStateConfigWProtect	= (VM_PROT_WRITE << kPCIDeviceStateConfigProtectShift),
204
205    kPCIDeviceStateDead             = 0x80000000,
206    kPCIDeviceStateEjected          = 0x40000000,
207    kPCIDeviceStateToKill           = 0x20000000,
208    kPCIDeviceStatePaused           = 0x10000000,
209    kPCIDeviceStateRequestPause     = 0x08000000
210};
211
212enum {
213    kPCIHeaderType0 = 0,
214    kPCIHeaderType1 = 1,
215    kPCIHeaderType2 = 2
216};
217
218// value of supportsHotPlug
219enum {
220    kPCIStatic                  = 0,
221    kPCILinkChange              = 1,
222    kPCIHotPlug                 = 2,
223    kPCIHotPlugRoot             = 3,
224    kPCIHotPlugTunnel           = 4,
225    kPCIHotPlugTunnelRoot       = 5,
226    kPCIHotPlugTunnelRootParent = 6,
227};
228
229#define kPCIBridgeMaxCount  256
230
231enum
232{
233    kConfigOpAddHostBridge = 1,
234    kConfigOpScan,
235    kConfigOpRealloc,
236    kConfigOpGetState,
237    kConfigOpNeedsScan,
238    kConfigOpEject,
239    kConfigOpKill,
240    kConfigOpTerminated,
241    kConfigOpProtect,
242    kConfigOpShadowed,
243    kConfigOpPaused,
244    kConfigOpUnpaused,
245    kConfigOpTestPause,
246    kConfigOpFindEntry,
247};
248
249/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
250
251struct IOPCIConfigEntry
252{
253    IOPCIConfigEntry *  parent;
254    IOPCIConfigEntry *  child;
255    IOPCIConfigEntry *  peer;
256    uint32_t			id;
257    uint32_t            classCode;
258    IOPCIAddressSpace   space;
259    uint32_t            vendorProduct;
260
261	uint32_t			expressCapBlock;
262	uint32_t			expressDeviceCaps1;
263
264    IOPCIRange *        ranges[kIOPCIRangeCount];
265    IOPCIRange          busResv;
266    uint32_t            rangeBaseChanges;
267    uint32_t            rangeSizeChanges;
268    uint32_t            rangeRequestChanges;
269    uint32_t            haveAllocs;
270
271    uint32_t            deviceState;
272    uint8_t             iterator;
273
274    uint8_t             headerType;
275    uint8_t             isBridge;
276    uint8_t             countMaximize;
277    uint8_t             isHostBridge;
278    uint8_t             supportsHotPlug;
279    uint8_t				linkInterrupts;
280    uint8_t             clean64;
281    uint8_t             secBusNum;  // bridge only
282    uint8_t             subBusNum;  // bridge only
283
284	uint32_t			linkCaps;
285	uint16_t			expressCaps;
286    uint8_t   			expressMaxPayload;
287    uint8_t   			expressPayloadSetting;
288//	uint16_t            pausedCommand;
289
290    IORegistryEntry *   dtEntry;
291#if ACPI_SUPPORT
292    IORegistryEntry *   acpiDevice;
293#endif
294    IORegistryEntry *   dtNub;
295
296
297	uint8_t *			configShadow;
298
299#if PLX8680
300    volatile uint32_t * plx;
301    IOPCIScalar         plxAperture;
302#endif
303};
304
305/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
306
307class IOPCIConfigurator : public IOService
308{
309    friend class IOPCIBridge;
310    OSDeclareDefaultStructors( IOPCIConfigurator );
311
312    IOWorkLoop *            fWL;
313    IOOptionBits            fFlags;
314    IOPCIBridge *           fHostBridge;
315    IOPCIConfigEntry *      fRoot;
316	uint32_t				fRootVendorProduct;
317
318	uint8_t					fMaxPayload;
319
320    IOPCIRange *            fConsoleRange;
321    IOPCIScalar             fPFMConsole;
322
323    OSSet *                 fChangedServices;
324    uint32_t				fWaitingPause;
325
326    uint32_t                fBridgeCount;
327    uint32_t                fDeviceCount;
328    uint32_t				fNextID;
329
330protected:
331
332    static void safeProbeCallback( void * refcon );
333    static void configProbeCallback( void * refcon );
334
335    static void matchDTEntry( IORegistryEntry * dtEntry, void * _context );
336#if ACPI_SUPPORT
337    static void matchACPIEntry( IORegistryEntry * dtEntry, void * _context );
338	void        removeFixedRanges(IORegistryEntry * root);
339#endif
340
341    typedef int32_t (IOPCIConfigurator::*IterateProc)(void * ref, IOPCIConfigEntry * bridge);
342    void    iterate(const char * what,
343                    IterateProc topProc, IterateProc bottomProc,
344                    void * ref = NULL);
345
346    int32_t scanProc(void * ref, IOPCIConfigEntry * bridge);
347	int32_t bootResetProc(void * ref, IOPCIConfigEntry * bridge);
348    int32_t totalProc(void * ref, IOPCIConfigEntry * bridge);
349    int32_t allocateProc(void * ref, IOPCIConfigEntry * bridge);
350	int32_t bridgeFinalizeConfigProc(void * unused, IOPCIConfigEntry * bridge);
351
352    void    configure(uint32_t options);
353    void    bridgeScanBus(IOPCIConfigEntry * bridge, uint8_t busNum, uint32_t resetMask);
354
355    void    logAllocatorRange(IOPCIConfigEntry * device, IOPCIRange * range, char c);
356    IOPCIRange * bridgeGetRange(IOPCIConfigEntry * bridge, uint32_t type);
357    bool    bridgeTotalResources(IOPCIConfigEntry * bridge, uint32_t typeMask);
358    int32_t bridgeAllocateResources( IOPCIConfigEntry * bridge, uint32_t typeMask );
359
360	bool    bridgeDeallocateChildRanges(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead,
361								        uint32_t deallocTypes, uint32_t freeTypes);
362
363    void    doConfigure(uint32_t options);
364
365    void    applyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog);
366    void    deviceApplyConfiguration(IOPCIConfigEntry * device, uint32_t typeMask, bool dolog);
367    void    bridgeApplyConfiguration(IOPCIConfigEntry * bridge, uint32_t typeMask, bool dolog);
368    uint16_t disableAccess(IOPCIConfigEntry * device, bool disable);
369    void    restoreAccess(IOPCIConfigEntry * device, UInt16 command);
370    void    bridgeAddChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * child);
371    void    bridgeRemoveChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead,
372								uint32_t deallocTypes, uint32_t freeTypes,
373								IOPCIConfigEntry ** childList);
374	void    bridgeMoveChildren(IOPCIConfigEntry * to, IOPCIConfigEntry * list);
375    void    bridgeDeadChild(IOPCIConfigEntry * bridge, IOPCIConfigEntry * dead);
376    void    bridgeProbeChild(IOPCIConfigEntry * bridge, IOPCIAddressSpace space, uint32_t resetMask);
377    void    probeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask);
378    void    safeProbeBaseAddressRegister(IOPCIConfigEntry * device, uint32_t lastBarNum, uint32_t resetMask);
379    void    deviceProbeRanges(IOPCIConfigEntry * device, uint32_t resetMask);
380    void    bridgeProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask);
381    void    cardbusProbeRanges(IOPCIConfigEntry * bridge, uint32_t resetMask);
382    void    bridgeProbeBusRange(IOPCIConfigEntry * bridge, uint32_t resetMask);
383	uint32_t findPCICapability(IOPCIConfigEntry * device,
384                               uint32_t capabilityID, uint32_t * found);
385    void    checkCacheLineSize(IOPCIConfigEntry * device);
386    void    writeLatencyTimer(IOPCIConfigEntry * device);
387
388	bool    treeInState(IOPCIConfigEntry * entry, uint32_t state, uint32_t mask);
389    void    markChanged(IOPCIConfigEntry * entry);
390    void    bridgeConnectDeviceTree(IOPCIConfigEntry * bridge);
391    bool    bridgeConstructDeviceTree(void * unused, IOPCIConfigEntry * bridge);
392    OSDictionary * constructProperties(IOPCIConfigEntry * device);
393    void           constructAddressingProperties(IOPCIConfigEntry * device, OSDictionary * propTable);
394
395    bool     createRoot(void);
396    IOReturn addHostBridge(IOPCIBridge * hostBridge);
397    IOPCIConfigEntry * findEntry(IOPCIAddressSpace space);
398
399	bool     configAccess(IOPCIConfigEntry * device, bool write);
400    void     configAccess(IOPCIConfigEntry * device, uint32_t access, uint32_t offset, void * data);
401
402    uint32_t configRead32( IOPCIAddressSpace space, uint32_t offset);
403	void     configWrite32(IOPCIAddressSpace space, uint32_t offset, uint32_t data);
404	uint32_t findPCICapability(IOPCIAddressSpace space,
405                               uint32_t capabilityID, uint32_t * found);
406
407    uint32_t configRead32( IOPCIConfigEntry * device, uint32_t offset);
408    uint16_t configRead16( IOPCIConfigEntry * device, uint32_t offset);
409    uint8_t  configRead8(  IOPCIConfigEntry * device, uint32_t offset);
410    void     configWrite32(IOPCIConfigEntry * device, uint32_t offset, uint32_t data);
411    void     configWrite16(IOPCIConfigEntry * device, uint32_t offset, uint16_t data);
412    void     configWrite8( IOPCIConfigEntry * device, uint32_t offset, uint8_t  data);
413
414public:
415    bool init(IOWorkLoop * wl, uint32_t flags);
416    virtual IOWorkLoop * getWorkLoop() const;
417    virtual void     free(void);
418
419    IOReturn configOp(IOService * device, uintptr_t op, void * result, void * arg2 = NULL);
420};
421
422#endif /* KERNEL */
423
424#endif /* !_IOPCICONFIGURATOR_H */
425