pci.c 105 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. pci.c
  5. Abstract:
  6. This module implements the PCI driver.
  7. Author:
  8. Evan Green 16-Sep-2012
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "pci.h"
  16. //
  17. // ---------------------------------------------------------------- Definitions
  18. //
  19. //
  20. // ------------------------------------------------------ Data Type Definitions
  21. //
  22. //
  23. // ----------------------------------------------- Internal Function Prototypes
  24. //
  25. KSTATUS
  26. PciAddDevice (
  27. PVOID Driver,
  28. PSTR DeviceId,
  29. PSTR ClassId,
  30. PSTR CompatibleIds,
  31. PVOID DeviceToken
  32. );
  33. VOID
  34. PciDispatchStateChange (
  35. PIRP Irp,
  36. PVOID DeviceContext,
  37. PVOID IrpContext
  38. );
  39. VOID
  40. PciDispatchSystemControl (
  41. PIRP Irp,
  42. PVOID DeviceContext,
  43. PVOID IrpContext
  44. );
  45. KSTATUS
  46. PcipReportChildren (
  47. PIRP QueryChildrenIrp,
  48. PPCI_DEVICE PciDevice
  49. );
  50. VOID
  51. PcipEnumerateChildren (
  52. PDEVICE Device,
  53. PPCI_DEVICE PciDevice
  54. );
  55. KSTATUS
  56. PcipQueryResourceRequirements (
  57. PDEVICE Device,
  58. PPCI_DEVICE DeviceObject,
  59. PIRP Irp
  60. );
  61. KSTATUS
  62. PcipQueryBridgeResourceRequirements (
  63. PDEVICE Device,
  64. PPCI_DEVICE DeviceObject,
  65. PIRP Irp
  66. );
  67. KSTATUS
  68. PcipSetDeviceResources (
  69. PPCI_DEVICE DeviceContext,
  70. PRESOURCE_ALLOCATION_LIST AllocationList
  71. );
  72. VOID
  73. PcipEnableDevice (
  74. PPCI_DEVICE DeviceContext
  75. );
  76. KSTATUS
  77. PcipSetBridgeDeviceResources (
  78. PPCI_DEVICE DeviceContext,
  79. PRESOURCE_ALLOCATION_LIST AllocationList
  80. );
  81. ULONG
  82. PcipFindDevice (
  83. PPCI_DEVICE ParentBus,
  84. UCHAR Device,
  85. UCHAR Function
  86. );
  87. ULONG
  88. PcipGetNewChildIndex (
  89. PPCI_DEVICE ParentBus
  90. );
  91. KSTATUS
  92. PcipQueryInterface (
  93. PIRP Irp,
  94. PPCI_DEVICE PciDevice
  95. );
  96. KSTATUS
  97. PcipInterfaceReadConfigSpace (
  98. PVOID DeviceToken,
  99. ULONG Offset,
  100. ULONG AccessSize,
  101. PULONGLONG Value
  102. );
  103. KSTATUS
  104. PcipInterfaceWriteConfigSpace (
  105. PVOID DeviceToken,
  106. ULONG Offset,
  107. ULONG AccessSize,
  108. ULONGLONG Value
  109. );
  110. KSTATUS
  111. PcipInterfaceReadSpecificConfigSpace (
  112. PVOID DeviceToken,
  113. ULONG BusNumber,
  114. ULONG DeviceNumber,
  115. ULONG FunctionNumber,
  116. ULONG Offset,
  117. ULONG AccessSize,
  118. PULONGLONG Value
  119. );
  120. KSTATUS
  121. PcipInterfaceWriteSpecificConfigSpace (
  122. PVOID DeviceToken,
  123. ULONG BusNumber,
  124. ULONG DeviceNumber,
  125. ULONG FunctionNumber,
  126. ULONG Offset,
  127. ULONG AccessSize,
  128. ULONGLONG Value
  129. );
  130. KSTATUS
  131. PcipStartBusDevice (
  132. PIRP StartIrp,
  133. PPCI_DEVICE DeviceContext
  134. );
  135. KSTATUS
  136. PcipCreateFunctionInterfaces (
  137. PDEVICE Device,
  138. PPCI_DEVICE PciDevice
  139. );
  140. KSTATUS
  141. PcipCreateBusInterfaces (
  142. PDEVICE Device,
  143. PPCI_DEVICE PciDevice
  144. );
  145. PSTR
  146. PcipGetClassId (
  147. ULONG ClassCode
  148. );
  149. KSTATUS
  150. PcipGetBusDriverDevice (
  151. PDEVICE OsDevice,
  152. PPCI_DEVICE *BusDriverDevice
  153. );
  154. //
  155. // -------------------------------------------------------------------- Globals
  156. //
  157. PDRIVER PciDriver = NULL;
  158. //
  159. // Store the UUID of PCI configuration space access.
  160. //
  161. UUID PciConfigSpaceUuid = UUID_PCI_CONFIG_ACCESS;
  162. //
  163. // Store the UUID of specific PCI configuration space access.
  164. //
  165. UUID PciSpecificConfigSpaceUuid = UUID_PCI_CONFIG_ACCESS_SPECIFIC;
  166. //
  167. // Store the UUID of the PCI MSI and MSI-X access.
  168. //
  169. UUID PciMessageSignaledInterruptsUuid = UUID_PCI_MESSAGE_SIGNALED_INTERRUPTS;
  170. //
  171. // Store the UUID of the ACPI bus number interface.
  172. //
  173. UUID PciAcpiBusAddressUuid = UUID_ACPI_BUS_ADDRESS;
  174. //
  175. // Store the UUID of the internal PCI interface for getting the bus driver's
  176. // PCI device structure.
  177. //
  178. UUID PciBusDriverDeviceUuid =
  179. {{0x73696D6F, 0x74207365, 0x656B206F, 0x61207066}};
  180. //
  181. // ------------------------------------------------------------------ Functions
  182. //
  183. KSTATUS
  184. DriverEntry (
  185. PDRIVER Driver
  186. )
  187. /*++
  188. Routine Description:
  189. This routine is the entry point for the PCI driver. It registers its other
  190. dispatch functions, and performs driver-wide initialization.
  191. Arguments:
  192. Driver - Supplies a pointer to the driver object.
  193. Return Value:
  194. STATUS_SUCCESS on success.
  195. Failure code on error.
  196. --*/
  197. {
  198. DRIVER_FUNCTION_TABLE FunctionTable;
  199. KSTATUS Status;
  200. PciDriver = Driver;
  201. RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
  202. FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
  203. FunctionTable.AddDevice = PciAddDevice;
  204. FunctionTable.DispatchStateChange = PciDispatchStateChange;
  205. FunctionTable.DispatchSystemControl = PciDispatchSystemControl;
  206. Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
  207. return Status;
  208. }
  209. KSTATUS
  210. PciAddDevice (
  211. PVOID Driver,
  212. PSTR DeviceId,
  213. PSTR ClassId,
  214. PSTR CompatibleIds,
  215. PVOID DeviceToken
  216. )
  217. /*++
  218. Routine Description:
  219. This routine is called when a PCI device is detected. PCI will attach
  220. itself to the driver stack.
  221. Arguments:
  222. Driver - Supplies a pointer to the driver being called.
  223. DeviceId - Supplies a pointer to a string with the device ID.
  224. ClassId - Supplies a pointer to a string containing the device's class ID.
  225. CompatibleIds - Supplies a pointer to a string containing device IDs
  226. that would be compatible with this device.
  227. DeviceToken - Supplies an opaque token that the driver can use to identify
  228. the device in the system. This token should be used when attaching to
  229. the stack.
  230. Return Value:
  231. STATUS_SUCCESS on success.
  232. STATUS_UNKNOWN_DEVICE if the device is not recognized by the driver. This
  233. usually a sign of misconfiguration (assigning PCI as a driver for something
  234. it does not own).
  235. Failure code if the driver was unsuccessful in attaching itself.
  236. --*/
  237. {
  238. PPCI_DEVICE Device;
  239. PCI_DEVICE_TYPE DeviceType;
  240. BOOL Match;
  241. KSTATUS Status;
  242. Device = NULL;
  243. DeviceType = PciDeviceInvalid;
  244. Status = STATUS_UNKNOWN_DEVICE;
  245. //
  246. // The PCI driver is the functional driver for the PCI Root device.
  247. //
  248. Match = IoAreDeviceIdsEqual(DeviceId, PCI_BUS_ID);
  249. if (Match == FALSE) {
  250. Match = IoAreDeviceIdsEqual(DeviceId, PCI_EXPRESS_BUS_ID);
  251. }
  252. if (Match != FALSE) {
  253. DeviceType = PciDeviceBus;
  254. } else {
  255. if ((Match == FALSE) && (ClassId != NULL)) {
  256. Match = RtlAreStringsEqual(ClassId,
  257. PCI_BRIDGE_CLASS_ID,
  258. sizeof(PCI_BRIDGE_CLASS_ID));
  259. }
  260. if ((Match == FALSE) && (ClassId != NULL)) {
  261. Match = RtlAreStringsEqual(ClassId,
  262. PCI_SUBTRACTIVE_BRIDGE_CLASS_ID,
  263. sizeof(PCI_SUBTRACTIVE_BRIDGE_CLASS_ID));
  264. }
  265. if (Match != FALSE) {
  266. DeviceType = PciDeviceBridge;
  267. }
  268. }
  269. //
  270. // If the device was not idenfified, then the system was misconfigured to
  271. // have PCI be the driver of some random device.
  272. //
  273. if (Match == FALSE) {
  274. Status = STATUS_UNKNOWN_DEVICE;
  275. goto AddDeviceEnd;
  276. }
  277. ASSERT(DeviceType != PciDeviceInvalid);
  278. Device = MmAllocateNonPagedPool(sizeof(PCI_DEVICE), PCI_ALLOCATION_TAG);
  279. if (Device == NULL) {
  280. Status = STATUS_INSUFFICIENT_RESOURCES;
  281. goto AddDeviceEnd;
  282. }
  283. RtlZeroMemory(Device, sizeof(PCI_DEVICE));
  284. Device->Type = DeviceType;
  285. Device->BusNumber = 0;
  286. if (DeviceType == PciDeviceBus) {
  287. Device->ReadConfig = PcipRootReadConfig;
  288. Device->WriteConfig = PcipRootWriteConfig;
  289. }
  290. Status = IoAttachDriverToDevice(Driver, DeviceToken, Device);
  291. if (!KSUCCESS(Status)) {
  292. goto AddDeviceEnd;
  293. }
  294. AddDeviceEnd:
  295. if (!KSUCCESS(Status)) {
  296. if (Device != NULL) {
  297. MmFreeNonPagedPool(Device);
  298. }
  299. }
  300. return Status;
  301. }
  302. VOID
  303. PciDispatchStateChange (
  304. PIRP Irp,
  305. PVOID DeviceContext,
  306. PVOID IrpContext
  307. )
  308. /*++
  309. Routine Description:
  310. This routine handles State Change IRPs.
  311. Arguments:
  312. Irp - Supplies a pointer to the I/O request packet.
  313. DeviceContext - Supplies the context pointer supplied by the driver when it
  314. attached itself to the driver stack. Presumably this pointer contains
  315. driver-specific device context.
  316. IrpContext - Supplies the context pointer supplied by the driver when
  317. the IRP was created.
  318. Return Value:
  319. None.
  320. --*/
  321. {
  322. PPCI_DEVICE PciDevice;
  323. KSTATUS Status;
  324. ASSERT(Irp->MajorCode == IrpMajorStateChange);
  325. PciDevice = DeviceContext;
  326. //
  327. // The IRP is on its way down the stack. Do most processing here.
  328. //
  329. if (Irp->Direction == IrpDown) {
  330. Status = STATUS_NOT_SUPPORTED;
  331. switch (Irp->MinorCode) {
  332. //
  333. // If the device is a function (therefore PCI is acting as the bus
  334. // driver), then return the device's resources.
  335. //
  336. case IrpMinorQueryResources:
  337. if (PciDevice->Type == PciDeviceFunction) {
  338. if (PciDevice->DeviceIsBridge != FALSE) {
  339. Status = PcipQueryBridgeResourceRequirements(Irp->Device,
  340. PciDevice,
  341. Irp);
  342. } else {
  343. Status = PcipQueryResourceRequirements(Irp->Device,
  344. PciDevice,
  345. Irp);
  346. }
  347. IoCompleteIrp(PciDriver, Irp, Status);
  348. }
  349. break;
  350. //
  351. // Assume the device is already started. Expose the interface for
  352. // interacting with the device's PCI config space.
  353. //
  354. case IrpMinorStartDevice:
  355. if (PciDevice->Type == PciDeviceFunction) {
  356. //
  357. // Set the BARs and enable the device.
  358. //
  359. if (PciDevice->DeviceIsBridge != FALSE) {
  360. Status = PcipSetBridgeDeviceResources(
  361. DeviceContext,
  362. Irp->U.StartDevice.BusLocalResources);
  363. } else {
  364. Status = PcipSetDeviceResources(
  365. DeviceContext,
  366. Irp->U.StartDevice.BusLocalResources);
  367. }
  368. if (!KSUCCESS(Status)) {
  369. IoCompleteIrp(PciDriver, Irp, Status);
  370. break;
  371. }
  372. //
  373. // Enable decoding on the device.
  374. //
  375. if (PciDevice->DeviceIsBridge == FALSE) {
  376. PcipEnableDevice(DeviceContext);
  377. }
  378. //
  379. // As the bus driver of a function, PCI completes the IRP.
  380. //
  381. IoCompleteIrp(PciDriver, Irp, Status);
  382. } else if ((PciDevice->Type == PciDeviceBus) ||
  383. (PciDevice->Type == PciDeviceBridge)) {
  384. Status = PcipStartBusDevice(Irp, PciDevice);
  385. if (!KSUCCESS(Status)) {
  386. IoCompleteIrp(PciDriver, Irp, Status);
  387. }
  388. Status = STATUS_SUCCESS;
  389. }
  390. break;
  391. //
  392. // Enumerate any children on the bus.
  393. //
  394. case IrpMinorQueryChildren:
  395. //
  396. // If the driver is acting as a bus driver for a function, there are
  397. // no children. Complete the IRP.
  398. //
  399. if (PciDevice->Type == PciDeviceFunction) {
  400. IoCompleteIrp(PciDriver, Irp, STATUS_SUCCESS);
  401. //
  402. // If PCI is acting as the functional driver, enumerate the
  403. // children, but don't complete the IRP.
  404. //
  405. } else {
  406. Status = PcipReportChildren(Irp, DeviceContext);
  407. }
  408. break;
  409. //
  410. // Process interface requests.
  411. //
  412. case IrpMinorQueryInterface:
  413. Status = PcipQueryInterface(Irp, DeviceContext);
  414. if (Status != STATUS_NO_INTERFACE) {
  415. IoCompleteIrp(PciDriver, Irp, Status);
  416. }
  417. break;
  418. case IrpMinorIdle:
  419. if (PciDevice->Type == PciDeviceFunction) {
  420. IoCompleteIrp(PciDriver, Irp, STATUS_SUCCESS);
  421. }
  422. break;
  423. case IrpMinorSuspend:
  424. if (PciDevice->Type == PciDeviceFunction) {
  425. IoCompleteIrp(PciDriver, Irp, STATUS_SUCCESS);
  426. }
  427. break;
  428. case IrpMinorResume:
  429. if (PciDevice->Type == PciDeviceFunction) {
  430. IoCompleteIrp(PciDriver, Irp, STATUS_SUCCESS);
  431. }
  432. break;
  433. //
  434. // If the IRP is unknown, don't touch it.
  435. //
  436. default:
  437. break;
  438. }
  439. } else {
  440. ASSERT(Irp->Direction == IrpUp);
  441. }
  442. return;
  443. }
  444. VOID
  445. PciDispatchSystemControl (
  446. PIRP Irp,
  447. PVOID DeviceContext,
  448. PVOID IrpContext
  449. )
  450. /*++
  451. Routine Description:
  452. This routine handles System Control IRPs.
  453. Arguments:
  454. Irp - Supplies a pointer to the I/O request packet.
  455. DeviceContext - Supplies the context pointer supplied by the driver when it
  456. attached itself to the driver stack. Presumably this pointer contains
  457. driver-specific device context.
  458. IrpContext - Supplies the context pointer supplied by the driver when
  459. the IRP was created.
  460. Return Value:
  461. None.
  462. --*/
  463. {
  464. ASSERT(Irp->MajorCode == IrpMajorSystemControl);
  465. if (Irp->Direction == IrpDown) {
  466. IoCompleteIrp(PciDriver, Irp, STATUS_NOT_SUPPORTED);
  467. } else {
  468. ASSERT(Irp->Direction == IrpUp);
  469. }
  470. return;
  471. }
  472. //
  473. // --------------------------------------------------------- Internal Functions
  474. //
  475. KSTATUS
  476. PcipReportChildren (
  477. PIRP QueryChildrenIrp,
  478. PPCI_DEVICE PciDevice
  479. )
  480. /*++
  481. Routine Description:
  482. This routine responds to a Query Children IRP.
  483. Arguments:
  484. QueryChildrenIrp - Supplies a pointer to the I/O request packet.
  485. PciDevice - Supplies a pointer to the PCI device context this IRP relates
  486. to.
  487. Return Value:
  488. STATUS_SUCCESS on success.
  489. STATUS_INSUFFICIENT_RESOURCES if the array could not be allocated for the
  490. children.
  491. --*/
  492. {
  493. PDEVICE *Children;
  494. //
  495. // If the device is not a bus, it has no children.
  496. //
  497. if ((PciDevice->Type != PciDeviceBus) &&
  498. (PciDevice->Type != PciDeviceBridge)) {
  499. QueryChildrenIrp->U.QueryChildren.Children = NULL;
  500. QueryChildrenIrp->U.QueryChildren.ChildCount = 0;
  501. return STATUS_SUCCESS;
  502. }
  503. //
  504. // Scan the bus and pick up any changes.
  505. //
  506. PcipEnumerateChildren(QueryChildrenIrp->Device, PciDevice);
  507. if (PciDevice->ChildCount == 0) {
  508. QueryChildrenIrp->U.QueryChildren.Children = NULL;
  509. QueryChildrenIrp->U.QueryChildren.ChildCount = 0;
  510. return STATUS_SUCCESS;
  511. }
  512. //
  513. // Allocated paged pool for the array to return.
  514. //
  515. Children = MmAllocatePagedPool(sizeof(PDEVICE) * PciDevice->ChildCount,
  516. PCI_ALLOCATION_TAG);
  517. if (Children == NULL) {
  518. return STATUS_INSUFFICIENT_RESOURCES;
  519. }
  520. RtlCopyMemory(Children,
  521. PciDevice->Children,
  522. PciDevice->ChildCount * sizeof(PDEVICE));
  523. QueryChildrenIrp->U.QueryChildren.Children = Children;
  524. QueryChildrenIrp->U.QueryChildren.ChildCount = PciDevice->ChildCount;
  525. return STATUS_SUCCESS;
  526. }
  527. VOID
  528. PcipEnumerateChildren (
  529. PDEVICE Device,
  530. PPCI_DEVICE PciDevice
  531. )
  532. /*++
  533. Routine Description:
  534. This routine scans the given PCI bus, enumerating any new children and
  535. removing any missing ones.
  536. Arguments:
  537. Device - Supplies a pointer to the device.
  538. PciDevice - Supplies a pointer to the PCI device context relating to this
  539. device.
  540. Return Value:
  541. None.
  542. --*/
  543. {
  544. PPCI_CHILD Child;
  545. ULONG ChildIndex;
  546. ULONG ClassCode;
  547. PSTR ClassCodeString;
  548. ULONG DeviceId;
  549. UCHAR DeviceNumber;
  550. UCHAR Function;
  551. ULONG HeaderType;
  552. ULONG Id;
  553. UCHAR MaxFunction;
  554. CHAR NewDeviceId[PCI_DEVICE_ID_SIZE];
  555. PPCI_DEVICE NewPciDevice;
  556. KSTATUS Status;
  557. ULONG VendorId;
  558. //
  559. // If the device is not a bus, it has no children.
  560. //
  561. if ((PciDevice->Type != PciDeviceBus) &&
  562. (PciDevice->Type != PciDeviceBridge)) {
  563. return;
  564. }
  565. //
  566. // Scan through all functions and all devices on this bus.
  567. //
  568. for (DeviceNumber = 0; DeviceNumber < MAX_PCI_DEVICE; DeviceNumber += 1) {
  569. //
  570. // Read configuration space to get the vendor and device ID.
  571. //
  572. Id = (ULONG)PciDevice->ReadConfig(PciDevice->BusNumber,
  573. DeviceNumber,
  574. 0,
  575. PCI_ID_OFFSET,
  576. sizeof(ULONG));
  577. DeviceId = (Id & PCI_DEVICE_ID_MASK) >> PCI_DEVICE_ID_SHIFT;
  578. VendorId = Id & PCI_VENDOR_ID_MASK;
  579. if ((VendorId == 0) || (VendorId == PCI_INVALID_VENDOR_ID)) {
  580. continue;
  581. }
  582. //
  583. // Determine the total number of functions that need to be scanned for
  584. // this device by looking at the header type's multi-function flag.
  585. //
  586. HeaderType = (ULONG)PciDevice->ReadConfig(PciDevice->BusNumber,
  587. DeviceNumber,
  588. 0,
  589. PCI_HEADER_TYPE_OFFSET,
  590. sizeof(ULONG));
  591. HeaderType = (HeaderType & PCI_HEADER_TYPE_MASK) >>
  592. PCI_HEADER_TYPE_SHIFT;
  593. if ((HeaderType & PCI_HEADER_TYPE_FLAG_MULTIPLE_FUNCTIONS) != 0) {
  594. MaxFunction = MAX_PCI_FUNCTION;
  595. } else {
  596. MaxFunction = 0;
  597. }
  598. for (Function = 0; Function <= MaxFunction; Function += 1) {
  599. //
  600. // Read configuration space to get the vendor and device ID if it
  601. // has not already been read.
  602. //
  603. if (Function != 0) {
  604. Id = (ULONG)PciDevice->ReadConfig(PciDevice->BusNumber,
  605. DeviceNumber,
  606. Function,
  607. PCI_ID_OFFSET,
  608. sizeof(ULONG));
  609. DeviceId = (Id & PCI_DEVICE_ID_MASK) >> PCI_DEVICE_ID_SHIFT;
  610. VendorId = Id & PCI_VENDOR_ID_MASK;
  611. }
  612. //
  613. // Attempt to find a previously enumerated child for this device
  614. // and function.
  615. //
  616. ChildIndex = PcipFindDevice(PciDevice, DeviceNumber, Function);
  617. //
  618. // If there was a device here and it seems to have disappeared,
  619. // free the device and swap it out for the last one.
  620. //
  621. if (ChildIndex != MAX_ULONG) {
  622. Child = PciDevice->ChildrenData[ChildIndex];
  623. if ((VendorId == Child->VendorId) &&
  624. (DeviceId == Child->DeviceId)) {
  625. continue;
  626. }
  627. //
  628. // Devices shouldn't just come and go like this. If they really
  629. // do, then completely remove the old device and add a new
  630. // different one in its place, rather than this bizarre
  631. // switcharoo.
  632. //
  633. ASSERT(FALSE);
  634. ASSERT(PciDevice->ChildCount != 0);
  635. PciDevice->Children[ChildIndex] =
  636. PciDevice->Children[PciDevice->ChildCount - 1];
  637. MmFreePagedPool(PciDevice->ChildrenData[ChildIndex]);
  638. PciDevice->ChildrenData[ChildIndex] =
  639. PciDevice->ChildrenData[PciDevice->ChildCount - 1];
  640. PciDevice->Children[PciDevice->ChildCount - 1] = NULL;
  641. PciDevice->ChildrenData[PciDevice->ChildCount - 1] = NULL;
  642. PciDevice->ChildCount -= 1;
  643. //
  644. // There was no child there before.
  645. //
  646. } else {
  647. //
  648. // If the vendor ID is invalid, skip this function.
  649. //
  650. if ((VendorId == 0) || (VendorId == PCI_INVALID_VENDOR_ID)) {
  651. continue;
  652. }
  653. //
  654. // There's a child now where there didn't used to be, kick out
  655. // a new device. Start by getting an index where the child will
  656. // go in the array. This also allocates the new child structure.
  657. //
  658. ChildIndex = PcipGetNewChildIndex(PciDevice);
  659. if (ChildIndex == MAX_ULONG) {
  660. continue;
  661. }
  662. //
  663. // Create the new device ID string. This only needs to be
  664. // temporary, which is why the buffer is stack allocated.
  665. //
  666. RtlPrintToString(NewDeviceId,
  667. PCI_DEVICE_ID_SIZE,
  668. CharacterEncodingDefault,
  669. PCI_DEVICE_ID_FORMAT,
  670. VendorId,
  671. DeviceId);
  672. //
  673. // Read the class code and create a string from it.
  674. //
  675. ClassCode = (ULONG)PciDevice->ReadConfig(PciDevice->BusNumber,
  676. DeviceNumber,
  677. Function,
  678. PCI_CLASS_CODE_OFFSET,
  679. sizeof(ULONG));
  680. ClassCode &= PCI_CLASS_CODE_MASK;
  681. ClassCodeString = PcipGetClassId(ClassCode);
  682. //
  683. // Create the driver context for the new child.
  684. //
  685. NewPciDevice = MmAllocateNonPagedPool(sizeof(PCI_DEVICE),
  686. PCI_ALLOCATION_TAG);
  687. if (NewPciDevice == NULL) {
  688. continue;
  689. }
  690. RtlZeroMemory(NewPciDevice, sizeof(PCI_DEVICE));
  691. NewPciDevice->Type = PciDeviceFunction;
  692. NewPciDevice->BusNumber = PciDevice->BusNumber;
  693. NewPciDevice->DeviceNumber = DeviceNumber;
  694. NewPciDevice->FunctionNumber = Function;
  695. NewPciDevice->ClassCode = ClassCode;
  696. if ((ClassCode == PCI_SUBTRACTIVE_BRIDGE_CLASS_CODE) ||
  697. (ClassCode == PCI_BRIDGE_CLASS_CODE)) {
  698. NewPciDevice->DeviceIsBridge = TRUE;
  699. }
  700. NewPciDevice->ReadConfig = PciDevice->ReadConfig;
  701. NewPciDevice->WriteConfig = PciDevice->WriteConfig;
  702. Status = PcipGetBusDriverDevice(Device,
  703. &(NewPciDevice->Parent));
  704. if (!KSUCCESS(Status)) {
  705. ASSERT(FALSE);
  706. MmFreeNonPagedPool(NewPciDevice);
  707. }
  708. //
  709. // Create the child device and fill out the accounting
  710. // structures.
  711. //
  712. Status = IoCreateDevice(PciDriver,
  713. NewPciDevice,
  714. Device,
  715. NewDeviceId,
  716. ClassCodeString,
  717. NULL,
  718. &(PciDevice->Children[ChildIndex]));
  719. if (!KSUCCESS(Status)) {
  720. MmFreeNonPagedPool(NewPciDevice);
  721. continue;
  722. }
  723. Child = PciDevice->ChildrenData[ChildIndex];
  724. Child->DeviceNumber = DeviceNumber;
  725. Child->Function = Function;
  726. Child->VendorId = VendorId;
  727. Child->DeviceId = DeviceId;
  728. PciDevice->ChildCount += 1;
  729. PcipCreateFunctionInterfaces(PciDevice->Children[ChildIndex],
  730. NewPciDevice);
  731. }
  732. }
  733. }
  734. return;
  735. }
  736. KSTATUS
  737. PcipQueryResourceRequirements (
  738. PDEVICE Device,
  739. PPCI_DEVICE DeviceObject,
  740. PIRP Irp
  741. )
  742. /*++
  743. Routine Description:
  744. This routine determines the resource requirements of the given device.
  745. Arguments:
  746. Device - Supplies a pointer to the device to query.
  747. DeviceObject - Supplies a pointer to the PCI information associated with
  748. the system device.
  749. Irp - Supplies a pointer to the query resources IRP.
  750. Return Value:
  751. Status code.
  752. --*/
  753. {
  754. ULONGLONG AddressDecode;
  755. RESOURCE_ALLOCATION Allocation;
  756. ULONG BarIndex;
  757. ULONGLONG BarLength[PCI_BAR_COUNT];
  758. ULONG BitNumber;
  759. PRESOURCE_ALLOCATION_LIST BootAllocations;
  760. UCHAR Bus;
  761. PRESOURCE_CONFIGURATION_LIST ConfigurationList;
  762. USHORT ControlRegister;
  763. UCHAR DeviceNumber;
  764. UCHAR Function;
  765. ULONG InterruptPin;
  766. ULONGLONG Maximum;
  767. UCHAR Offset;
  768. PPCI_READ_CONFIG ReadConfig;
  769. RESOURCE_REQUIREMENT Requirement;
  770. PRESOURCE_REQUIREMENT_LIST RequirementList;
  771. KSTATUS Status;
  772. ULONG Value;
  773. PPCI_WRITE_CONFIG WriteConfig;
  774. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  775. (Irp->MinorCode == IrpMinorQueryResources));
  776. //
  777. // Bridges are not handled in this function.
  778. //
  779. ASSERT((DeviceObject->Type == PciDeviceFunction) &&
  780. (DeviceObject->DeviceIsBridge == FALSE));
  781. BootAllocations = NULL;
  782. Bus = DeviceObject->BusNumber;
  783. ConfigurationList = NULL;
  784. DeviceNumber = DeviceObject->DeviceNumber;
  785. Function = DeviceObject->FunctionNumber;
  786. ReadConfig = DeviceObject->ReadConfig;
  787. RequirementList = NULL;
  788. WriteConfig = DeviceObject->WriteConfig;
  789. //
  790. // If the BARs have not been read yet from boot, see if the BIOS has
  791. // this device enabled, and read the BARs if so.
  792. //
  793. if (DeviceObject->BarsRead == FALSE) {
  794. DeviceObject->BarsRead = TRUE;
  795. //
  796. // If decoding is enabled, read the BARs.
  797. //
  798. ControlRegister = (USHORT)ReadConfig(Bus,
  799. DeviceNumber,
  800. Function,
  801. PCI_CONTROL_OFFSET,
  802. sizeof(USHORT));
  803. DeviceObject->BootControlRegister = ControlRegister;
  804. if (((ControlRegister & PCI_CONTROL_IO_DECODE_ENABLED) != 0) ||
  805. ((ControlRegister & PCI_CONTROL_MEMORY_DECODE_ENABLED) != 0)) {
  806. for (BarIndex = 0; BarIndex < PCI_BAR_COUNT; BarIndex += 1) {
  807. Offset = PCI_BAR_OFFSET + (BarIndex * sizeof(ULONG));
  808. Value = (ULONG)ReadConfig(Bus,
  809. DeviceNumber,
  810. Function,
  811. Offset,
  812. sizeof(ULONG));
  813. DeviceObject->BootConfiguration.U.Bar32[BarIndex] = Value;
  814. }
  815. }
  816. InterruptPin = (USHORT)ReadConfig(Bus,
  817. DeviceNumber,
  818. Function,
  819. PCI_INTERRUPT_LINE_OFFSET,
  820. sizeof(USHORT));
  821. InterruptPin = (UCHAR)(InterruptPin >> BITS_PER_BYTE);
  822. DeviceObject->InterruptPin = InterruptPin;
  823. if (DeviceObject->InterruptPin > 4) {
  824. ASSERT(FALSE);
  825. DeviceObject->InterruptPin = 0;
  826. }
  827. //
  828. // Disable all decoding in preparation for the BAR test.
  829. //
  830. WriteConfig(Bus,
  831. DeviceNumber,
  832. Function,
  833. PCI_CONTROL_OFFSET,
  834. sizeof(USHORT),
  835. 0);
  836. //
  837. // The technique to determine how many resources a device needs is to
  838. // write all ones to each BAR, and then read them back to see which ones
  839. // stick, and therefore which addresses the device decodes. Write all
  840. // ones here.
  841. //
  842. for (BarIndex = 0; BarIndex < PCI_BAR_COUNT; BarIndex += 1) {
  843. Offset = PCI_BAR_OFFSET + (BarIndex * sizeof(ULONG));
  844. WriteConfig(Bus, DeviceNumber, Function, Offset, sizeof(ULONG), -1);
  845. }
  846. //
  847. // Now read them back.
  848. //
  849. for (BarIndex = 0; BarIndex < PCI_BAR_COUNT; BarIndex += 1) {
  850. Offset = PCI_BAR_OFFSET + (BarIndex * sizeof(ULONG));
  851. Value = (ULONG)ReadConfig(Bus,
  852. DeviceNumber,
  853. Function,
  854. Offset,
  855. sizeof(ULONG));
  856. if (Value != 0) {
  857. DeviceObject->BarCount = BarIndex + 1;
  858. }
  859. DeviceObject->AddressDecodeBits.U.Bar32[BarIndex] = Value;
  860. }
  861. //
  862. // For the safest feeling possible, restore the BARs and control
  863. // register to what it was before.
  864. //
  865. for (BarIndex = 0; BarIndex < PCI_BAR_COUNT; BarIndex += 1) {
  866. Offset = PCI_BAR_OFFSET + (BarIndex * sizeof(ULONG));
  867. Value = DeviceObject->BootConfiguration.U.Bar32[BarIndex];
  868. WriteConfig(Bus,
  869. DeviceNumber,
  870. Function,
  871. Offset,
  872. sizeof(ULONG),
  873. Value);
  874. }
  875. WriteConfig(Bus,
  876. DeviceNumber,
  877. Function,
  878. PCI_CONTROL_OFFSET,
  879. sizeof(USHORT),
  880. ControlRegister);
  881. }
  882. RtlZeroMemory(&Requirement, sizeof(RESOURCE_REQUIREMENT));
  883. //
  884. // Create a new resource requirement list.
  885. //
  886. RequirementList = IoCreateResourceRequirementList();
  887. if (RequirementList == NULL) {
  888. Status = STATUS_INSUFFICIENT_RESOURCES;
  889. goto QueryResourceRequirementsEnd;
  890. }
  891. RtlZeroMemory(BarLength, sizeof(BarLength));
  892. //
  893. // Loop through the BARs to determine the resource requirements.
  894. //
  895. for (BarIndex = 0; BarIndex < DeviceObject->BarCount; BarIndex += 1) {
  896. Value = DeviceObject->AddressDecodeBits.U.Bar32[BarIndex];
  897. //
  898. // Create an I/O or memory space requirement.
  899. //
  900. if ((Value & PCI_BAR_IO_SPACE) != 0) {
  901. Requirement.Type = ResourceTypeIoPort;
  902. Requirement.Flags |= RESOURCE_FLAG_NOT_SHAREABLE;
  903. //
  904. // The value has 1 bit set for everything it decodes. Start from the
  905. // high order bits and find the maximum that it does decode.
  906. //
  907. if ((Value & (~PCI_BAR_IO_FLAGS_MASK)) == 0) {
  908. Maximum = 0;
  909. AddressDecode = 0;
  910. } else {
  911. BitNumber = 31;
  912. Maximum = 1 << BitNumber;
  913. while ((Maximum & Value) == 0) {
  914. BitNumber -= 1;
  915. Maximum = 1 << BitNumber;
  916. }
  917. //
  918. // Back up a smidge, the loop went one too far.
  919. //
  920. BitNumber += 1;
  921. Maximum = 1ULL << BitNumber;
  922. //
  923. // To get the needed size, OR in the empty bits on the right
  924. // (so the whole thing eventually rolls over), then mask off
  925. // the flags bits so they would be zero. Negate the whole
  926. // thing, and add 1 to roll over to a power of 2 that
  927. // represents the required size.
  928. //
  929. AddressDecode =
  930. (~((Value | ~(Maximum - 1)) & ~PCI_BAR_IO_FLAGS_MASK)) + 1;
  931. }
  932. Requirement.Minimum = 0;
  933. Requirement.Maximum = Maximum;
  934. Requirement.Length = AddressDecode;
  935. Requirement.Alignment = AddressDecode;
  936. Requirement.Characteristics = 0;
  937. if ((Value & PCI_BAR_MEMORY_PREFETCHABLE) != 0) {
  938. Requirement.Characteristics |=
  939. MEMORY_CHARACTERISTIC_PREFETCHABLE;
  940. }
  941. BarLength[BarIndex] = AddressDecode;
  942. //
  943. // Create a memory space requirement.
  944. //
  945. } else {
  946. Requirement.Type = ResourceTypePhysicalAddressSpace;
  947. Requirement.Flags |= RESOURCE_FLAG_NOT_SHAREABLE;
  948. AddressDecode = Value & (~PCI_BAR_MEMORY_FLAGS_MASK);
  949. Requirement.Minimum = 0;
  950. //
  951. // Set the minimum and maximum based on the BAR limits.
  952. //
  953. switch (Value & PCI_BAR_MEMORY_SIZE_MASK) {
  954. case PCI_BAR_MEMORY_32_BIT:
  955. BitNumber = 31;
  956. break;
  957. case PCI_BAR_MEMORY_1MB:
  958. BitNumber = 20;
  959. break;
  960. case PCI_BAR_MEMORY_64_BIT:
  961. ASSERT((BarIndex & 0x1) == 0);
  962. AddressDecode =
  963. DeviceObject->AddressDecodeBits.U.Bar64[BarIndex / 2] &
  964. (~PCI_BAR_MEMORY_FLAGS_MASK);
  965. BitNumber = 63;
  966. break;
  967. default:
  968. ASSERT(FALSE);
  969. BitNumber = 0;
  970. break;
  971. }
  972. //
  973. // Just like the I/O bars above, find the unset bits on the left
  974. // to get the maximum address.
  975. //
  976. if ((AddressDecode & (~PCI_BAR_MEMORY_FLAGS_MASK)) == 0) {
  977. Maximum = 0;
  978. AddressDecode = 0;
  979. } else {
  980. Maximum = 1ULL << BitNumber;
  981. while ((Maximum & AddressDecode) == 0) {
  982. BitNumber -= 1;
  983. Maximum = 1ULL << BitNumber;
  984. }
  985. //
  986. // Back up a smidge, the loop went too far.
  987. //
  988. BitNumber += 1;
  989. Maximum = 1ULL << BitNumber;
  990. //
  991. // Get the size needed for this BAR. Again this is done by
  992. // ORing in the unsupported bits on the left masking out the
  993. // flags, negating the whole thing, and adding one. Remember
  994. // that the flags were masked out already above.
  995. //
  996. if (BitNumber == 64) {
  997. AddressDecode = ~AddressDecode + 1;
  998. Maximum = MAX_ULONGLONG;
  999. } else {
  1000. AddressDecode = (~(AddressDecode | ~(Maximum - 1))) + 1;
  1001. }
  1002. }
  1003. Requirement.Length = AddressDecode;
  1004. Requirement.Alignment = AddressDecode;
  1005. Requirement.Maximum = Maximum;
  1006. Requirement.Characteristics = 0;
  1007. BarLength[BarIndex] = AddressDecode;
  1008. //
  1009. // 64 bit BARs take up two of the regular size BARs, so advance
  1010. // past the second one.
  1011. //
  1012. if ((Value & PCI_BAR_MEMORY_SIZE_MASK) == PCI_BAR_MEMORY_64_BIT) {
  1013. BarIndex += 1;
  1014. }
  1015. }
  1016. //
  1017. // Create and add the requirement to the list.
  1018. //
  1019. Status = IoCreateAndAddResourceRequirement(&Requirement,
  1020. RequirementList,
  1021. NULL);
  1022. if (!KSUCCESS(Status)) {
  1023. goto QueryResourceRequirementsEnd;
  1024. }
  1025. }
  1026. //
  1027. // If the interrupt pin is not zero, then request an interrupt line
  1028. // resource as well. By default PCI interrupts are level triggered active
  1029. // low, and shareable.
  1030. //
  1031. InterruptPin = DeviceObject->InterruptPin;
  1032. if (InterruptPin != 0) {
  1033. Requirement.Type = ResourceTypeInterruptLine;
  1034. Requirement.Flags &= ~RESOURCE_FLAG_NOT_SHAREABLE;
  1035. Requirement.Length = 1;
  1036. Requirement.Characteristics = INTERRUPT_LINE_ACTIVE_LOW;
  1037. Requirement.Flags = 0;
  1038. Requirement.Alignment = 1;
  1039. Requirement.Minimum = InterruptPin;
  1040. Requirement.Maximum = InterruptPin + 1;
  1041. Status = IoCreateAndAddResourceRequirement(&Requirement,
  1042. RequirementList,
  1043. NULL);
  1044. if (!KSUCCESS(Status)) {
  1045. goto QueryResourceRequirementsEnd;
  1046. }
  1047. }
  1048. //
  1049. // Create the resource configuration list.
  1050. //
  1051. ConfigurationList = IoCreateResourceConfigurationList(RequirementList);
  1052. if (ConfigurationList == NULL) {
  1053. Status = STATUS_INSUFFICIENT_RESOURCES;
  1054. goto QueryResourceRequirementsEnd;
  1055. }
  1056. RequirementList = NULL;
  1057. //
  1058. // Create the boot configuration.
  1059. //
  1060. BootAllocations = IoCreateResourceAllocationList();
  1061. if (BootAllocations == NULL) {
  1062. Status = STATUS_INSUFFICIENT_RESOURCES;
  1063. goto QueryResourceRequirementsEnd;
  1064. }
  1065. RtlZeroMemory(&Allocation, sizeof(RESOURCE_ALLOCATION));
  1066. for (BarIndex = 0; BarIndex < DeviceObject->BarCount; BarIndex += 1) {
  1067. Value = DeviceObject->BootConfiguration.U.Bar32[BarIndex];
  1068. //
  1069. // Create an I/O or memory space allocation.
  1070. //
  1071. if ((Value & PCI_BAR_IO_SPACE) != 0) {
  1072. Allocation.Type = ResourceTypeIoPort;
  1073. Allocation.Allocation = Value & (~PCI_BAR_IO_FLAGS_MASK);
  1074. Allocation.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1075. Allocation.Length = 0;
  1076. if ((DeviceObject->BootControlRegister &
  1077. PCI_CONTROL_IO_DECODE_ENABLED) != 0) {
  1078. Allocation.Length = BarLength[BarIndex];
  1079. }
  1080. //
  1081. // Create a memory space allocation.
  1082. //
  1083. } else {
  1084. Allocation.Type = ResourceTypePhysicalAddressSpace;
  1085. Allocation.Allocation = Value & (~PCI_BAR_MEMORY_FLAGS_MASK);
  1086. Allocation.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1087. Allocation.Length = 0;
  1088. if ((DeviceObject->BootControlRegister &
  1089. PCI_CONTROL_MEMORY_DECODE_ENABLED) != 0) {
  1090. Allocation.Length = BarLength[BarIndex];
  1091. if ((Value & PCI_BAR_MEMORY_SIZE_MASK) ==
  1092. PCI_BAR_MEMORY_64_BIT) {
  1093. ASSERT((BarIndex & 0x1) == 0);
  1094. Allocation.Allocation =
  1095. DeviceObject->BootConfiguration.U.Bar64[BarIndex / 2] &
  1096. (~PCI_BAR_MEMORY_FLAGS_MASK);
  1097. BarIndex += 1;
  1098. }
  1099. }
  1100. }
  1101. //
  1102. // Create and add the allocation to the list.
  1103. //
  1104. Status = IoCreateAndAddResourceAllocation(&Allocation, BootAllocations);
  1105. if (!KSUCCESS(Status)) {
  1106. goto QueryResourceRequirementsEnd;
  1107. }
  1108. }
  1109. //
  1110. // Add the interrupt pin to the boot configuration.
  1111. //
  1112. if (InterruptPin != 0) {
  1113. Allocation.Type = ResourceTypeInterruptLine;
  1114. Allocation.Allocation = InterruptPin;
  1115. Allocation.Length = 1;
  1116. Allocation.Flags = 0;
  1117. Allocation.Characteristics = INTERRUPT_LINE_ACTIVE_LOW;
  1118. Status = IoCreateAndAddResourceAllocation(&Allocation, BootAllocations);
  1119. if (!KSUCCESS(Status)) {
  1120. goto QueryResourceRequirementsEnd;
  1121. }
  1122. }
  1123. Status = STATUS_SUCCESS;
  1124. QueryResourceRequirementsEnd:
  1125. if (!KSUCCESS(Status)) {
  1126. if (RequirementList != NULL) {
  1127. IoDestroyResourceRequirementList(RequirementList);
  1128. }
  1129. if (ConfigurationList != NULL) {
  1130. IoDestroyResourceConfigurationList(ConfigurationList);
  1131. ConfigurationList = NULL;
  1132. }
  1133. if (BootAllocations != NULL) {
  1134. IoDestroyResourceAllocationList(BootAllocations);
  1135. BootAllocations = NULL;
  1136. }
  1137. }
  1138. Irp->U.QueryResources.ResourceRequirements = ConfigurationList;
  1139. Irp->U.QueryResources.BootAllocation = BootAllocations;
  1140. return Status;
  1141. }
  1142. KSTATUS
  1143. PcipQueryBridgeResourceRequirements (
  1144. PDEVICE Device,
  1145. PPCI_DEVICE DeviceObject,
  1146. PIRP Irp
  1147. )
  1148. /*++
  1149. Routine Description:
  1150. This routine determines the resource requirements of the given PCI bridge.
  1151. For the confused, this routine is called by PCI acting as the bus driver,
  1152. not the function driver.
  1153. Arguments:
  1154. Device - Supplies a pointer to the device to query.
  1155. DeviceObject - Supplies a pointer to the PCI information associated with
  1156. the system device.
  1157. Irp - Supplies a pointer to the query resources IRP.
  1158. Return Value:
  1159. Status code.
  1160. --*/
  1161. {
  1162. RESOURCE_ALLOCATION Allocation;
  1163. BOOL BarsRead;
  1164. PRESOURCE_ALLOCATION_LIST BootAllocations;
  1165. UCHAR Bus;
  1166. PRESOURCE_CONFIGURATION_LIST ConfigurationList;
  1167. UCHAR DeviceNumber;
  1168. UCHAR Function;
  1169. UCHAR InterruptPin;
  1170. ULONG IoDecodeBase;
  1171. ULONG IoDecodeLimit;
  1172. BOOL IoDecodeUpperBaseValid;
  1173. BOOL IoDecodeUpperLimitValid;
  1174. ULONG MemoryDecodeBase;
  1175. ULONG MemoryDecodeLimit;
  1176. ULONGLONG PrefetchableMemoryDecodeBase;
  1177. ULONGLONG PrefetchableMemoryDecodeLimit;
  1178. BOOL PrefetchableMemoryUpperBaseValid;
  1179. BOOL PrefetchableMemoryUpperLimitValid;
  1180. PPCI_READ_CONFIG ReadConfig;
  1181. RESOURCE_REQUIREMENT Requirement;
  1182. PRESOURCE_REQUIREMENT_LIST RequirementList;
  1183. UCHAR SecondaryBusNumber;
  1184. KSTATUS Status;
  1185. ULONG Value;
  1186. ULONG ValueHigh;
  1187. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  1188. (Irp->MinorCode == IrpMinorQueryResources));
  1189. //
  1190. // Only bridges are handled in this function.
  1191. //
  1192. ASSERT((DeviceObject->Type == PciDeviceFunction) &&
  1193. (DeviceObject->DeviceIsBridge != FALSE));
  1194. BarsRead = FALSE;
  1195. BootAllocations = NULL;
  1196. Bus = DeviceObject->BusNumber;
  1197. ConfigurationList = NULL;
  1198. DeviceNumber = DeviceObject->DeviceNumber;
  1199. Function = DeviceObject->FunctionNumber;
  1200. IoDecodeBase = MAX_USHORT;
  1201. IoDecodeLimit = 0;
  1202. MemoryDecodeBase = MAX_ULONG;
  1203. MemoryDecodeLimit = 0;
  1204. PrefetchableMemoryDecodeBase = MAX_ULONGLONG;
  1205. PrefetchableMemoryDecodeLimit = 0;
  1206. ReadConfig = DeviceObject->ReadConfig;
  1207. RequirementList = NULL;
  1208. SecondaryBusNumber = 0xFF;
  1209. //
  1210. // If the BARs have not been read yet from boot, see if the BIOS has
  1211. // this device enabled, and read the BARs if so.
  1212. //
  1213. if (DeviceObject->BarsRead == FALSE) {
  1214. DeviceObject->BarsRead = TRUE;
  1215. BarsRead = TRUE;
  1216. //
  1217. // Read the bus number BAR to see how the BIOS configured it.
  1218. //
  1219. Value = (ULONG)ReadConfig(Bus,
  1220. DeviceNumber,
  1221. Function,
  1222. PCI_BRIDGE_BUS_NUMBERS_OFFSET,
  1223. sizeof(ULONG));
  1224. SecondaryBusNumber = (UCHAR)(Value >> PCI_BRIDGE_SECONDARY_BUS_SHIFT);
  1225. //
  1226. // Read the value set by the BIOS for the I/O decode region.
  1227. //
  1228. IoDecodeUpperBaseValid = FALSE;
  1229. IoDecodeUpperLimitValid = FALSE;
  1230. Value = (USHORT)ReadConfig(Bus,
  1231. DeviceNumber,
  1232. Function,
  1233. PCI_BRIDGE_IO_BAR_OFFSET,
  1234. sizeof(USHORT));
  1235. if ((Value & PCI_BRIDGE_IO_BASE_DECODE_MASK) ==
  1236. PCI_BRIDGE_IO_BASE_DECODE_32_BIT) {
  1237. IoDecodeUpperBaseValid = TRUE;
  1238. }
  1239. if ((Value & PCI_BRIDGE_IO_LIMIT_DECODE_MASK) ==
  1240. PCI_BRIDGE_IO_LIMIT_DECODE_32_BIT) {
  1241. IoDecodeUpperLimitValid = TRUE;
  1242. }
  1243. IoDecodeBase = (Value & PCI_BRIDGE_IO_BASE_MASK) <<
  1244. PCI_BRIDGE_IO_BASE_ADDRESS_SHIFT;
  1245. IoDecodeLimit = Value & PCI_BRIDGE_IO_LIMIT_MASK;
  1246. if ((IoDecodeUpperBaseValid != FALSE) ||
  1247. (IoDecodeUpperLimitValid != FALSE)) {
  1248. ValueHigh = (USHORT)ReadConfig(Bus,
  1249. DeviceNumber,
  1250. Function,
  1251. PCI_BRIDGE_IO_HIGH_BAR_OFFSET,
  1252. sizeof(ULONG));
  1253. if (IoDecodeUpperBaseValid != FALSE) {
  1254. IoDecodeBase |= (ValueHigh &
  1255. PCI_BRIDGE_IO_BASE_HIGH_MASK) <<
  1256. PCI_BRIDGE_IO_BASE_HIGH_ADDRESS_SHIFT;
  1257. }
  1258. if (IoDecodeUpperLimitValid != FALSE) {
  1259. IoDecodeLimit |= ValueHigh & PCI_BRIDGE_IO_LIMIT_HIGH_MASK;
  1260. }
  1261. }
  1262. //
  1263. // Read the value set by the BIOS for the memory decode region.
  1264. //
  1265. Value = (ULONG)ReadConfig(Bus,
  1266. DeviceNumber,
  1267. Function,
  1268. PCI_BRIDGE_MEMORY_BAR_OFFSET,
  1269. sizeof(ULONG));
  1270. MemoryDecodeBase = (Value & PCI_BRIDGE_MEMORY_BASE_MASK) <<
  1271. PCI_BRIDGE_MEMORY_BASE_ADDRESS_SHIFT;
  1272. MemoryDecodeLimit = Value & PCI_BRIDGE_MEMORY_LIMIT_MASK;
  1273. //
  1274. // Read the prefetchable memory range as well.
  1275. //
  1276. PrefetchableMemoryUpperBaseValid = FALSE;
  1277. PrefetchableMemoryUpperLimitValid = FALSE;
  1278. Value = (ULONG)ReadConfig(Bus,
  1279. DeviceNumber,
  1280. Function,
  1281. PCI_BRIDGE_PREFETCHABLE_MEMORY_BAR_OFFSET,
  1282. sizeof(ULONG));
  1283. if ((Value & PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_DECODE_MASK) ==
  1284. PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_DECODE_64_BIT) {
  1285. PrefetchableMemoryUpperBaseValid = TRUE;
  1286. }
  1287. if ((Value & PCI_BRIDGE_PREFETCHABLE_MEMORY_LIMIT_DECODE_MASK) ==
  1288. PCI_BRIDGE_PREFETCHABLE_MEMORY_LIMIT_DECODE_64_BIT) {
  1289. PrefetchableMemoryUpperLimitValid = TRUE;
  1290. }
  1291. PrefetchableMemoryDecodeBase =
  1292. (Value & PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_MASK) <<
  1293. PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_ADDRESS_SHIFT;
  1294. PrefetchableMemoryDecodeLimit =
  1295. Value & PCI_BRIDGE_PREFETCHABLE_MEMORY_LIMIT_MASK;
  1296. if (PrefetchableMemoryUpperBaseValid != FALSE) {
  1297. ValueHigh = (ULONG)ReadConfig(
  1298. Bus,
  1299. DeviceNumber,
  1300. Function,
  1301. PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_HIGH_OFFSET,
  1302. sizeof(ULONG));
  1303. PrefetchableMemoryDecodeBase |=
  1304. (ULONGLONG)ValueHigh <<
  1305. PCI_BRIDGE_PREFETCHABLE_MEMORY_HIGH_ADDRESS_SHIFT;
  1306. }
  1307. if (PrefetchableMemoryUpperLimitValid != FALSE) {
  1308. ValueHigh = (ULONG)ReadConfig(
  1309. Bus,
  1310. DeviceNumber,
  1311. Function,
  1312. PCI_BRIDGE_PREFETCHABLE_MEMORY_LIMIT_HIGH_OFFSET,
  1313. sizeof(ULONG));
  1314. PrefetchableMemoryDecodeLimit |=
  1315. (ULONGLONG)ValueHigh <<
  1316. PCI_BRIDGE_PREFETCHABLE_MEMORY_HIGH_ADDRESS_SHIFT;
  1317. }
  1318. InterruptPin = (USHORT)ReadConfig(Bus,
  1319. DeviceNumber,
  1320. Function,
  1321. PCI_INTERRUPT_LINE_OFFSET,
  1322. sizeof(USHORT));
  1323. InterruptPin = (UCHAR)(InterruptPin >> BITS_PER_BYTE);
  1324. DeviceObject->InterruptPin = InterruptPin;
  1325. if (DeviceObject->InterruptPin > 4) {
  1326. ASSERT(FALSE);
  1327. DeviceObject->InterruptPin = 0;
  1328. }
  1329. }
  1330. RtlZeroMemory(&Requirement, sizeof(RESOURCE_REQUIREMENT));
  1331. //
  1332. // Create a new resource requirement list and add the bus number
  1333. // requirement.
  1334. //
  1335. RequirementList = IoCreateResourceRequirementList();
  1336. if (RequirementList == NULL) {
  1337. Status = STATUS_INSUFFICIENT_RESOURCES;
  1338. goto QueryBridgeResourceRequirementsEnd;
  1339. }
  1340. Requirement.Type = ResourceTypeBusNumber;
  1341. Requirement.Minimum = 0;
  1342. Requirement.Maximum = (UCHAR)-1;
  1343. Requirement.Length = 1;
  1344. Requirement.Characteristics = 0;
  1345. Requirement.Alignment = 0;
  1346. Requirement.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1347. Status = IoCreateAndAddResourceRequirement(&Requirement,
  1348. RequirementList,
  1349. NULL);
  1350. if (!KSUCCESS(Status)) {
  1351. goto QueryBridgeResourceRequirementsEnd;
  1352. }
  1353. //
  1354. // Add empty requirements for the windows.
  1355. //
  1356. Requirement.Type = ResourceTypeIoPort;
  1357. Requirement.Minimum = 0;
  1358. Requirement.Maximum = MAX_ULONG;
  1359. Requirement.Length = 0;
  1360. Requirement.Characteristics = 0;
  1361. Requirement.Alignment = PCI_BRIDGE_IO_GRANULARITY;
  1362. Status = IoCreateAndAddResourceRequirement(&Requirement,
  1363. RequirementList,
  1364. NULL);
  1365. if (!KSUCCESS(Status)) {
  1366. goto QueryBridgeResourceRequirementsEnd;
  1367. }
  1368. Requirement.Type = ResourceTypePhysicalAddressSpace;
  1369. Requirement.Minimum = 0;
  1370. Requirement.Maximum = MAX_ULONG;
  1371. Requirement.Length = 0;
  1372. Requirement.Characteristics = 0;
  1373. Requirement.Alignment = PCI_BRIDGE_MEMORY_GRANULARITY;
  1374. Status = IoCreateAndAddResourceRequirement(&Requirement,
  1375. RequirementList,
  1376. NULL);
  1377. if (!KSUCCESS(Status)) {
  1378. goto QueryBridgeResourceRequirementsEnd;
  1379. }
  1380. //
  1381. // The prefetchable memory window is the same as the MMIO region, but is
  1382. // 64-bit capable.
  1383. //
  1384. Requirement.Maximum = MAX_ULONGLONG;
  1385. Requirement.Characteristics = MEMORY_CHARACTERISTIC_PREFETCHABLE;
  1386. Status = IoCreateAndAddResourceRequirement(&Requirement,
  1387. RequirementList,
  1388. NULL);
  1389. if (!KSUCCESS(Status)) {
  1390. goto QueryBridgeResourceRequirementsEnd;
  1391. }
  1392. //
  1393. // Create the resource configuration list.
  1394. //
  1395. ConfigurationList = IoCreateResourceConfigurationList(RequirementList);
  1396. if (ConfigurationList == NULL) {
  1397. Status = STATUS_INSUFFICIENT_RESOURCES;
  1398. goto QueryBridgeResourceRequirementsEnd;
  1399. }
  1400. RequirementList = NULL;
  1401. //
  1402. // Create the boot configuration.
  1403. //
  1404. BootAllocations = IoCreateResourceAllocationList();
  1405. if (BootAllocations == NULL) {
  1406. Status = STATUS_INSUFFICIENT_RESOURCES;
  1407. goto QueryBridgeResourceRequirementsEnd;
  1408. }
  1409. RtlZeroMemory(&Allocation, sizeof(RESOURCE_ALLOCATION));
  1410. if (BarsRead != FALSE) {
  1411. if (SecondaryBusNumber != 0xFF) {
  1412. Allocation.Type = ResourceTypeBusNumber;
  1413. Allocation.Allocation = SecondaryBusNumber;
  1414. Allocation.Length = 1;
  1415. Allocation.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1416. Status = IoCreateAndAddResourceAllocation(&Allocation,
  1417. BootAllocations);
  1418. if (!KSUCCESS(Status)) {
  1419. goto QueryBridgeResourceRequirementsEnd;
  1420. }
  1421. Allocation.Type = ResourceTypeIoPort;
  1422. Allocation.Allocation = IoDecodeBase;
  1423. if (IoDecodeLimit >= IoDecodeBase) {
  1424. Allocation.Length =
  1425. (IoDecodeLimit + PCI_BRIDGE_IO_GRANULARITY) - IoDecodeBase;
  1426. } else {
  1427. Allocation.Length = 0;
  1428. }
  1429. Allocation.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1430. Status = IoCreateAndAddResourceAllocation(&Allocation,
  1431. BootAllocations);
  1432. if (!KSUCCESS(Status)) {
  1433. goto QueryBridgeResourceRequirementsEnd;
  1434. }
  1435. Allocation.Type = ResourceTypePhysicalAddressSpace;
  1436. Allocation.Allocation = MemoryDecodeBase;
  1437. if (MemoryDecodeLimit >= MemoryDecodeBase) {
  1438. Allocation.Length = (MemoryDecodeLimit +
  1439. PCI_BRIDGE_MEMORY_GRANULARITY) -
  1440. MemoryDecodeBase;
  1441. } else {
  1442. Allocation.Length = 0;
  1443. }
  1444. Allocation.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1445. Status = IoCreateAndAddResourceAllocation(&Allocation,
  1446. BootAllocations);
  1447. if (!KSUCCESS(Status)) {
  1448. goto QueryBridgeResourceRequirementsEnd;
  1449. }
  1450. Allocation.Type = ResourceTypePhysicalAddressSpace;
  1451. Allocation.Allocation = PrefetchableMemoryDecodeBase;
  1452. if (PrefetchableMemoryDecodeLimit >= PrefetchableMemoryDecodeBase) {
  1453. Allocation.Length = (PrefetchableMemoryDecodeLimit +
  1454. PCI_BRIDGE_MEMORY_GRANULARITY) -
  1455. PrefetchableMemoryDecodeBase;
  1456. } else {
  1457. Allocation.Length = 0;
  1458. }
  1459. Allocation.Characteristics = MEMORY_CHARACTERISTIC_PREFETCHABLE;
  1460. Allocation.Flags = RESOURCE_FLAG_NOT_SHAREABLE;
  1461. Status = IoCreateAndAddResourceAllocation(&Allocation,
  1462. BootAllocations);
  1463. if (!KSUCCESS(Status)) {
  1464. goto QueryBridgeResourceRequirementsEnd;
  1465. }
  1466. }
  1467. }
  1468. Status = STATUS_SUCCESS;
  1469. QueryBridgeResourceRequirementsEnd:
  1470. if (!KSUCCESS(Status)) {
  1471. if (RequirementList != NULL) {
  1472. IoDestroyResourceRequirementList(RequirementList);
  1473. }
  1474. if (ConfigurationList != NULL) {
  1475. IoDestroyResourceConfigurationList(ConfigurationList);
  1476. ConfigurationList = NULL;
  1477. }
  1478. if (BootAllocations != NULL) {
  1479. IoDestroyResourceAllocationList(BootAllocations);
  1480. BootAllocations = NULL;
  1481. }
  1482. }
  1483. Irp->U.QueryResources.ResourceRequirements = ConfigurationList;
  1484. Irp->U.QueryResources.BootAllocation = BootAllocations;
  1485. return Status;
  1486. }
  1487. KSTATUS
  1488. PcipSetDeviceResources (
  1489. PPCI_DEVICE DeviceContext,
  1490. PRESOURCE_ALLOCATION_LIST AllocationList
  1491. )
  1492. /*++
  1493. Routine Description:
  1494. This routine sets the assigned resources in the PCI BARs.
  1495. Arguments:
  1496. DeviceContext - Supplies a pointer to the device to set.
  1497. AllocationList - Supplies a pointer to the resource allocation list
  1498. containing the device's resource assignment.
  1499. Return Value:
  1500. Status code.
  1501. --*/
  1502. {
  1503. ULONGLONG AddressDecode;
  1504. PRESOURCE_ALLOCATION Allocation;
  1505. ULONG BarIndex;
  1506. ULONG BarSize;
  1507. UCHAR Bus;
  1508. USHORT ControlRegister;
  1509. UCHAR DeviceNumber;
  1510. UCHAR Function;
  1511. PPCI_MSI_CONTEXT MsiContext;
  1512. UCHAR Offset;
  1513. ULONG PendingArrayIndex;
  1514. ULONG PendingArrayOffset;
  1515. PPCI_READ_CONFIG ReadConfig;
  1516. RESOURCE_TYPE ResourceType;
  1517. KSTATUS Status;
  1518. ULONGLONG Value;
  1519. ULONG VectorTableIndex;
  1520. ULONG VectorTableOffset;
  1521. PPCI_WRITE_CONFIG WriteConfig;
  1522. //
  1523. // This routine only handles functions, not bridges.
  1524. //
  1525. ASSERT((DeviceContext->Type == PciDeviceFunction) &&
  1526. (DeviceContext->DeviceIsBridge == FALSE));
  1527. if (AllocationList == NULL) {
  1528. Status = STATUS_SUCCESS;
  1529. goto SetDeviceResourcesEnd;
  1530. }
  1531. Bus = DeviceContext->BusNumber;
  1532. DeviceNumber = DeviceContext->DeviceNumber;
  1533. Function = DeviceContext->FunctionNumber;
  1534. ReadConfig = DeviceContext->ReadConfig;
  1535. WriteConfig = DeviceContext->WriteConfig;
  1536. //
  1537. // If MSI-X is available on the device then prepare to squirrel away the
  1538. // physical address of the table and pending array.
  1539. //
  1540. MsiContext = DeviceContext->MsiContext;
  1541. if ((MsiContext != NULL) && (MsiContext->MsiXOffset != 0)) {
  1542. PcipGetMsiXBarInformation(DeviceContext,
  1543. &VectorTableIndex,
  1544. &VectorTableOffset,
  1545. &PendingArrayIndex,
  1546. &PendingArrayOffset);
  1547. }
  1548. //
  1549. // Read the control register.
  1550. //
  1551. ControlRegister = (USHORT)ReadConfig(Bus,
  1552. DeviceNumber,
  1553. Function,
  1554. PCI_CONTROL_OFFSET,
  1555. sizeof(USHORT));
  1556. //
  1557. // Disable all decoding in preparation for setting the BARs.
  1558. //
  1559. WriteConfig(Bus,
  1560. DeviceNumber,
  1561. Function,
  1562. PCI_CONTROL_OFFSET,
  1563. sizeof(USHORT),
  1564. 0);
  1565. //
  1566. // Loop through the BARs and assign resources to each one.
  1567. //
  1568. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  1569. for (BarIndex = 0; BarIndex < DeviceContext->BarCount; BarIndex += 1) {
  1570. AddressDecode = DeviceContext->AddressDecodeBits.U.Bar32[BarIndex];
  1571. //
  1572. // Get the resource type for this BAR.
  1573. //
  1574. ResourceType = ResourceTypePhysicalAddressSpace;
  1575. if ((AddressDecode & PCI_BAR_IO_SPACE) != 0) {
  1576. ResourceType = ResourceTypeIoPort;
  1577. }
  1578. //
  1579. // Find the next resource of that type.
  1580. //
  1581. while (Allocation->Type != ResourceType) {
  1582. Allocation =
  1583. IoGetNextResourceAllocation(AllocationList, Allocation);
  1584. if (Allocation == NULL) {
  1585. Status = STATUS_INVALID_CONFIGURATION;
  1586. goto SetDeviceResourcesEnd;
  1587. }
  1588. }
  1589. //
  1590. // Skip it if it's zero length.
  1591. //
  1592. if (AddressDecode == 0) {
  1593. ASSERT(Allocation->Length == 0);
  1594. Allocation = IoGetNextResourceAllocation(AllocationList,
  1595. Allocation);
  1596. continue;
  1597. }
  1598. //
  1599. // See if this is a 64 bit bar.
  1600. //
  1601. BarSize = sizeof(ULONG);
  1602. if ((ResourceType == ResourceTypePhysicalAddressSpace) &&
  1603. ((AddressDecode & PCI_BAR_MEMORY_SIZE_MASK) ==
  1604. PCI_BAR_MEMORY_64_BIT)) {
  1605. BarSize = sizeof(ULONGLONG);
  1606. }
  1607. Value = Allocation->Allocation;
  1608. if (ResourceType == ResourceTypePhysicalAddressSpace) {
  1609. ASSERT((Value & PCI_BAR_MEMORY_FLAGS_MASK) == 0);
  1610. ControlRegister |= PCI_CONTROL_MEMORY_DECODE_ENABLED;
  1611. } else {
  1612. ASSERT(ResourceType == ResourceTypeIoPort);
  1613. ASSERT((Value & PCI_BAR_IO_FLAGS_MASK) == 0);
  1614. ControlRegister |= PCI_CONTROL_IO_DECODE_ENABLED;
  1615. Value |= PCI_BAR_IO_SPACE;
  1616. }
  1617. //
  1618. // Write out the BAR.
  1619. //
  1620. Offset = PCI_BAR_OFFSET + (BarIndex * sizeof(ULONG));
  1621. WriteConfig(Bus, DeviceNumber, Function, Offset, BarSize, Value);
  1622. //
  1623. // If MSI-X is available then check to see if this is the BAR for
  1624. // either the vector table or pending bit array. They could be in the
  1625. // same BAR.
  1626. //
  1627. if ((MsiContext != NULL) && (MsiContext->MsiXOffset != 0)) {
  1628. if (VectorTableIndex == BarIndex) {
  1629. ASSERT(MsiContext->MsiXTablePhysicalAddress ==
  1630. INVALID_PHYSICAL_ADDRESS);
  1631. MsiContext->MsiXTablePhysicalAddress = Value +
  1632. VectorTableOffset;
  1633. }
  1634. if (PendingArrayIndex == BarIndex) {
  1635. ASSERT(MsiContext->MsiXPendingArrayPhysicalAddress ==
  1636. INVALID_PHYSICAL_ADDRESS);
  1637. MsiContext->MsiXPendingArrayPhysicalAddress =
  1638. Value + PendingArrayOffset;
  1639. }
  1640. }
  1641. //
  1642. // Skip over the next BAR if this one was a 64-bit BAR.
  1643. //
  1644. if ((ResourceType == ResourceTypePhysicalAddressSpace) &&
  1645. ((AddressDecode & PCI_BAR_MEMORY_SIZE_MASK) ==
  1646. PCI_BAR_MEMORY_64_BIT)) {
  1647. BarIndex += 1;
  1648. }
  1649. //
  1650. // Move on to the next allocation.
  1651. //
  1652. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  1653. }
  1654. //
  1655. // Write out the control register to enable the device.
  1656. //
  1657. WriteConfig(Bus,
  1658. DeviceNumber,
  1659. Function,
  1660. PCI_CONTROL_OFFSET,
  1661. sizeof(USHORT),
  1662. ControlRegister);
  1663. Status = STATUS_SUCCESS;
  1664. SetDeviceResourcesEnd:
  1665. return Status;
  1666. }
  1667. VOID
  1668. PcipEnableDevice (
  1669. PPCI_DEVICE DeviceContext
  1670. )
  1671. /*++
  1672. Routine Description:
  1673. This routine enables the I/O space, memory space, and Bus master bits in
  1674. the PCI device.
  1675. Arguments:
  1676. DeviceContext - Supplies a pointer to the device to set.
  1677. Return Value:
  1678. None.
  1679. --*/
  1680. {
  1681. UCHAR Bus;
  1682. USHORT CommandRegister;
  1683. UCHAR DeviceNumber;
  1684. UCHAR Function;
  1685. PPCI_READ_CONFIG ReadConfig;
  1686. PPCI_WRITE_CONFIG WriteConfig;
  1687. //
  1688. // This routine only handles functions, not bridges.
  1689. //
  1690. ASSERT((DeviceContext->Type == PciDeviceFunction) &&
  1691. (DeviceContext->DeviceIsBridge == FALSE));
  1692. Bus = DeviceContext->BusNumber;
  1693. DeviceNumber = DeviceContext->DeviceNumber;
  1694. Function = DeviceContext->FunctionNumber;
  1695. ReadConfig = DeviceContext->ReadConfig;
  1696. WriteConfig = DeviceContext->WriteConfig;
  1697. //
  1698. // Read the command register, and enable some bits.
  1699. //
  1700. CommandRegister = (USHORT)ReadConfig(Bus,
  1701. DeviceNumber,
  1702. Function,
  1703. PCI_CONTROL_OFFSET,
  1704. sizeof(USHORT));
  1705. CommandRegister |= PCI_CONTROL_IO_DECODE_ENABLED |
  1706. PCI_CONTROL_MEMORY_DECODE_ENABLED |
  1707. PCI_CONTROL_WRITE_INVALIDATE_ENABLED |
  1708. PCI_CONTROL_BUS_MASTER_ENABLED;
  1709. //
  1710. // Disable all decoding in preparation for setting the BARs.
  1711. //
  1712. WriteConfig(Bus,
  1713. DeviceNumber,
  1714. Function,
  1715. PCI_CONTROL_OFFSET,
  1716. sizeof(USHORT),
  1717. CommandRegister);
  1718. return;
  1719. }
  1720. KSTATUS
  1721. PcipSetBridgeDeviceResources (
  1722. PPCI_DEVICE DeviceContext,
  1723. PRESOURCE_ALLOCATION_LIST AllocationList
  1724. )
  1725. /*++
  1726. Routine Description:
  1727. This routine sets the assigned resource window into the given bridge.
  1728. Arguments:
  1729. DeviceContext - Supplies a pointer to the device to set.
  1730. AllocationList - Supplies a pointer to the resource allocation list
  1731. containing the device's resource assignment.
  1732. Return Value:
  1733. Status code.
  1734. --*/
  1735. {
  1736. PRESOURCE_ALLOCATION Allocation;
  1737. UCHAR Bus;
  1738. ULONG BusRegister;
  1739. USHORT ControlRegister;
  1740. UCHAR DeviceNumber;
  1741. UCHAR Function;
  1742. ULONG IoPortHigh;
  1743. USHORT IoPortRegister;
  1744. ULONGLONG Limit;
  1745. ULONG MemoryRegister;
  1746. UCHAR OriginalSecondaryBusNumber;
  1747. ULONG PrefetchableMemoryBaseHigh;
  1748. ULONG PrefetchableMemoryLimitHigh;
  1749. ULONG PrefetchableMemoryLow;
  1750. UCHAR PrimaryBusNumber;
  1751. PPCI_READ_CONFIG ReadConfig;
  1752. UCHAR SecondaryBusNumber;
  1753. KSTATUS Status;
  1754. UCHAR SubordinateBusNumber;
  1755. PPCI_WRITE_CONFIG WriteConfig;
  1756. //
  1757. // This routine only handles bridges.
  1758. //
  1759. ASSERT((DeviceContext->Type == PciDeviceFunction) &&
  1760. (DeviceContext->DeviceIsBridge != FALSE));
  1761. if (AllocationList == NULL) {
  1762. Status = STATUS_SUCCESS;
  1763. goto SetBridgeDeviceResourcesEnd;
  1764. }
  1765. //
  1766. // Initialize the locals. Set the window registers up so that the base is
  1767. // higher than the limit, a safe default if no resources were given for that
  1768. // window.
  1769. //
  1770. Bus = DeviceContext->BusNumber;
  1771. DeviceNumber = DeviceContext->DeviceNumber;
  1772. Function = DeviceContext->FunctionNumber;
  1773. IoPortRegister = ((MAX_USHORT >> PCI_BRIDGE_IO_BASE_ADDRESS_SHIFT) &
  1774. PCI_BRIDGE_IO_BASE_MASK) |
  1775. (0 & PCI_BRIDGE_IO_LIMIT_MASK);
  1776. IoPortHigh = 0;
  1777. MemoryRegister = ((MAX_ULONG >> PCI_BRIDGE_MEMORY_BASE_ADDRESS_SHIFT) &
  1778. PCI_BRIDGE_MEMORY_BASE_MASK) |
  1779. (0 & PCI_BRIDGE_MEMORY_LIMIT_MASK);
  1780. PrimaryBusNumber = Bus;
  1781. PrefetchableMemoryLow =
  1782. ((MAX_ULONG >> PCI_BRIDGE_MEMORY_BASE_ADDRESS_SHIFT) &
  1783. PCI_BRIDGE_MEMORY_BASE_MASK) |
  1784. (0 & PCI_BRIDGE_MEMORY_LIMIT_MASK);
  1785. PrefetchableMemoryBaseHigh = MAX_ULONG;
  1786. PrefetchableMemoryLimitHigh = 0;
  1787. SecondaryBusNumber = Bus;
  1788. ReadConfig = DeviceContext->ReadConfig;
  1789. WriteConfig = DeviceContext->WriteConfig;
  1790. BusRegister = (ULONG)ReadConfig(Bus,
  1791. DeviceNumber,
  1792. Function,
  1793. PCI_BRIDGE_BUS_NUMBERS_OFFSET,
  1794. sizeof(ULONG));
  1795. //
  1796. // Save the secondary and subordinate bus numbers that were programmed by
  1797. // the firmware. The final secondary bus number will be retrieved from the
  1798. // allocated resources; they should match. The subordinate bus number is
  1799. // the highest bus number underneath this bridge and all bus numbers
  1800. // beneath a given bridge must be contiguous. A depth-first search would
  1801. // need to be performed before the system enumerates the bridges in order
  1802. // to correctly calculate the subordinate bus numbers. For now, rely on the
  1803. // firmware to have done the work.
  1804. //
  1805. OriginalSecondaryBusNumber = (BusRegister &
  1806. PCI_BRIDGE_SECONDARY_BUS_MASK) >>
  1807. PCI_BRIDGE_SECONDARY_BUS_SHIFT;
  1808. SubordinateBusNumber = (BusRegister & PCI_BRIDGE_SUBORDINATE_BUS_MASK) >>
  1809. PCI_BRIDGE_SUBORDINATE_BUS_SHIFT;
  1810. //
  1811. // Read the control register.
  1812. //
  1813. ControlRegister = (USHORT)ReadConfig(Bus,
  1814. DeviceNumber,
  1815. Function,
  1816. PCI_CONTROL_OFFSET,
  1817. sizeof(USHORT));
  1818. ControlRegister |= PCI_CONTROL_BUS_MASTER_ENABLED |
  1819. PCI_CONTROL_SPECIAL_CYCLES_ENABLED |
  1820. PCI_CONTROL_WRITE_INVALIDATE_ENABLED |
  1821. PCI_CONTROL_SERR_ENABLED;
  1822. //
  1823. // Disable all decoding in preparation for setting the BARs.
  1824. //
  1825. WriteConfig(Bus,
  1826. DeviceNumber,
  1827. Function,
  1828. PCI_CONTROL_OFFSET,
  1829. sizeof(USHORT),
  1830. 0);
  1831. //
  1832. // Loop over all the given resources, and extract the necessary items.
  1833. // Don't program anything in until everything's retrieved.
  1834. //
  1835. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  1836. while (Allocation != NULL) {
  1837. //
  1838. // Skip zero length allocations.
  1839. //
  1840. if (Allocation->Length == 0) {
  1841. Allocation = IoGetNextResourceAllocation(AllocationList,
  1842. Allocation);
  1843. continue;
  1844. }
  1845. //
  1846. // Save the bus number.
  1847. //
  1848. if (Allocation->Type == ResourceTypeBusNumber) {
  1849. ASSERT((UCHAR)Allocation->Allocation == Allocation->Allocation);
  1850. ASSERT(Allocation->Length == 1);
  1851. BusRegister &= PCI_BRIDGE_SECONDARY_LATENCY_TIMER_MASK;
  1852. SecondaryBusNumber = (UCHAR)Allocation->Allocation;
  1853. //
  1854. // Save the I/O port window.
  1855. //
  1856. } else if (Allocation->Type == ResourceTypeIoPort) {
  1857. ControlRegister |= PCI_CONTROL_IO_DECODE_ENABLED;
  1858. Limit = Allocation->Allocation + Allocation->Length -
  1859. PCI_BRIDGE_IO_GRANULARITY;
  1860. IoPortRegister = (USHORT)(((Allocation->Allocation >>
  1861. PCI_BRIDGE_IO_BASE_ADDRESS_SHIFT) &
  1862. PCI_BRIDGE_IO_BASE_MASK) |
  1863. (Limit & PCI_BRIDGE_IO_LIMIT_MASK));
  1864. IoPortHigh = (ULONG)((Allocation->Allocation >>
  1865. PCI_BRIDGE_IO_BASE_HIGH_ADDRESS_SHIFT) &
  1866. PCI_BRIDGE_IO_BASE_HIGH_MASK);
  1867. if (IoPortHigh != 0) {
  1868. IoPortRegister |= PCI_BRIDGE_IO_BASE_DECODE_32_BIT;
  1869. }
  1870. if ((ULONG)(Limit & PCI_BRIDGE_IO_LIMIT_HIGH_MASK) != 0) {
  1871. IoPortRegister |= PCI_BRIDGE_IO_LIMIT_DECODE_32_BIT;
  1872. }
  1873. IoPortHigh |= (ULONG)(Limit & PCI_BRIDGE_IO_LIMIT_HIGH_MASK);
  1874. //
  1875. // Save the non-prefetchable (MMIO) memory window.
  1876. //
  1877. } else if ((Allocation->Type == ResourceTypePhysicalAddressSpace) &&
  1878. ((Allocation->Characteristics &
  1879. MEMORY_CHARACTERISTIC_PREFETCHABLE) == 0)) {
  1880. ControlRegister |= PCI_CONTROL_MEMORY_DECODE_ENABLED;
  1881. Limit = Allocation->Allocation + Allocation->Length -
  1882. PCI_BRIDGE_MEMORY_GRANULARITY;
  1883. MemoryRegister = (ULONG)(((Allocation->Allocation >>
  1884. PCI_BRIDGE_MEMORY_BASE_ADDRESS_SHIFT) &
  1885. PCI_BRIDGE_MEMORY_BASE_MASK) |
  1886. (Limit & PCI_BRIDGE_MEMORY_LIMIT_MASK));
  1887. //
  1888. // Save the prefetchable memory window.
  1889. //
  1890. } else if ((Allocation->Type == ResourceTypePhysicalAddressSpace) &&
  1891. ((Allocation->Characteristics &
  1892. MEMORY_CHARACTERISTIC_PREFETCHABLE) != 0)) {
  1893. ControlRegister |= PCI_CONTROL_MEMORY_DECODE_ENABLED;
  1894. Limit = Allocation->Allocation + Allocation->Length -
  1895. PCI_BRIDGE_MEMORY_GRANULARITY;
  1896. PrefetchableMemoryLow =
  1897. (ULONG)(((Allocation->Allocation >>
  1898. PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_ADDRESS_SHIFT) &
  1899. PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_MASK) |
  1900. (Limit & PCI_BRIDGE_PREFETCHABLE_MEMORY_LIMIT_MASK));
  1901. PrefetchableMemoryBaseHigh =
  1902. (ULONG)(Allocation->Allocation >>
  1903. PCI_BRIDGE_PREFETCHABLE_MEMORY_HIGH_ADDRESS_SHIFT);
  1904. if (PrefetchableMemoryBaseHigh != 0) {
  1905. PrefetchableMemoryLow |=
  1906. PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_DECODE_64_BIT;
  1907. }
  1908. PrefetchableMemoryLimitHigh =
  1909. (ULONG)(Limit >>
  1910. PCI_BRIDGE_PREFETCHABLE_MEMORY_HIGH_ADDRESS_SHIFT);
  1911. if (PrefetchableMemoryLimitHigh != 0) {
  1912. PrefetchableMemoryLow |=
  1913. PCI_BRIDGE_PREFETCHABLE_MEMORY_LIMIT_DECODE_64_BIT;
  1914. }
  1915. }
  1916. //
  1917. // Loop on to the next allocation.
  1918. //
  1919. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  1920. }
  1921. //
  1922. // The secondary bus number that was allocated for this bridge should be
  1923. // equal to the number allocated by the firmware at boot. This dependency
  1924. // is taken to avoid doing a depth-first search to determine the correct
  1925. // subordinate bus number for each bridge.
  1926. //
  1927. ASSERT(SecondaryBusNumber == OriginalSecondaryBusNumber);
  1928. //
  1929. // Set up the bus number register value now that the information has been
  1930. // extracted.
  1931. //
  1932. BusRegister |= PrimaryBusNumber |
  1933. (SecondaryBusNumber << PCI_BRIDGE_SECONDARY_BUS_SHIFT) |
  1934. (SubordinateBusNumber << PCI_BRIDGE_SUBORDINATE_BUS_SHIFT);
  1935. //
  1936. // Okay, everything's accounted for. Write the values into the bridge.
  1937. //
  1938. WriteConfig(Bus,
  1939. DeviceNumber,
  1940. Function,
  1941. PCI_BRIDGE_BUS_NUMBERS_OFFSET,
  1942. sizeof(ULONG),
  1943. BusRegister);
  1944. WriteConfig(Bus,
  1945. DeviceNumber,
  1946. Function,
  1947. PCI_BRIDGE_IO_BAR_OFFSET,
  1948. sizeof(USHORT),
  1949. IoPortRegister);
  1950. WriteConfig(Bus,
  1951. DeviceNumber,
  1952. Function,
  1953. PCI_BRIDGE_IO_HIGH_BAR_OFFSET,
  1954. sizeof(ULONG),
  1955. IoPortHigh);
  1956. WriteConfig(Bus,
  1957. DeviceNumber,
  1958. Function,
  1959. PCI_BRIDGE_MEMORY_BAR_OFFSET,
  1960. sizeof(ULONG),
  1961. MemoryRegister);
  1962. WriteConfig(Bus,
  1963. DeviceNumber,
  1964. Function,
  1965. PCI_BRIDGE_PREFETCHABLE_MEMORY_BAR_OFFSET,
  1966. sizeof(ULONG),
  1967. PrefetchableMemoryLow);
  1968. WriteConfig(Bus,
  1969. DeviceNumber,
  1970. Function,
  1971. PCI_BRIDGE_PREFETCHABLE_MEMORY_BASE_HIGH_OFFSET,
  1972. sizeof(ULONG),
  1973. PrefetchableMemoryBaseHigh);
  1974. WriteConfig(Bus,
  1975. DeviceNumber,
  1976. Function,
  1977. PCI_BRIDGE_PREFETCHABLE_MEMORY_LIMIT_HIGH_OFFSET,
  1978. sizeof(ULONG),
  1979. PrefetchableMemoryLimitHigh);
  1980. //
  1981. // Write out the control register to enable address decoding.
  1982. //
  1983. WriteConfig(Bus,
  1984. DeviceNumber,
  1985. Function,
  1986. PCI_CONTROL_OFFSET,
  1987. sizeof(USHORT),
  1988. ControlRegister);
  1989. Status = STATUS_SUCCESS;
  1990. SetBridgeDeviceResourcesEnd:
  1991. return Status;
  1992. }
  1993. ULONG
  1994. PcipFindDevice (
  1995. PPCI_DEVICE ParentBus,
  1996. UCHAR Device,
  1997. UCHAR Function
  1998. )
  1999. /*++
  2000. Routine Description:
  2001. This routine searches for a PCI device matching the given device and
  2002. function in the child list of another device.
  2003. Arguments:
  2004. ParentBus - Supplies a pointer to the PCI device whose children should be
  2005. searched.
  2006. Device - Supplies the PCI device slot number to search for.
  2007. Function - Supplies the function number to search for.
  2008. Return Value:
  2009. Returns the index of the child in the device's child array, or MAX_ULONG
  2010. if the device could not be found.
  2011. --*/
  2012. {
  2013. ULONG ChildIndex;
  2014. for (ChildIndex = 0; ChildIndex < ParentBus->ChildCount; ChildIndex += 1) {
  2015. if ((ParentBus->ChildrenData[ChildIndex]->DeviceNumber == Device) &&
  2016. (ParentBus->ChildrenData[ChildIndex]->Function == Function)) {
  2017. return ChildIndex;
  2018. }
  2019. }
  2020. return MAX_ULONG;
  2021. }
  2022. ULONG
  2023. PcipGetNewChildIndex (
  2024. PPCI_DEVICE ParentBus
  2025. )
  2026. /*++
  2027. Routine Description:
  2028. This routine allocates space in the list of child devices, and also
  2029. allocates space for the child information.
  2030. Arguments:
  2031. ParentBus - Supplies a pointer to the parent bus device where a new device
  2032. is about to be added.
  2033. Return Value:
  2034. Returns an index into the child array where the new child device should be
  2035. placed, and where the child device information buffer is stored.
  2036. MAX_ULONG on error.
  2037. --*/
  2038. {
  2039. ULONG AllocationCount;
  2040. ULONG AllocationSize;
  2041. PDEVICE *NewChildren;
  2042. PPCI_CHILD *NewChildrenData;
  2043. ULONG NewIndex;
  2044. NewChildren = NULL;
  2045. NewChildrenData = NULL;
  2046. NewIndex = MAX_ULONG;
  2047. ASSERT(ParentBus->ChildCount < MAX_PCI_DEVICES);
  2048. if (ParentBus->ChildCount >= MAX_PCI_DEVICES) {
  2049. goto GetNewChildIndexEnd;
  2050. }
  2051. //
  2052. // If there's room in the array, simply use that.
  2053. //
  2054. if (ParentBus->ChildCount < ParentBus->ChildSize) {
  2055. NewIndex = ParentBus->ChildCount;
  2056. //
  2057. // There's no room in the array. Allocate a new array, copy the old
  2058. // contents in, and free the old array.
  2059. //
  2060. } else {
  2061. AllocationCount = ParentBus->ChildSize * 2;
  2062. if (AllocationCount < PCI_INITIAL_CHILD_COUNT) {
  2063. AllocationCount = PCI_INITIAL_CHILD_COUNT;
  2064. }
  2065. if (AllocationCount > MAX_PCI_DEVICES) {
  2066. AllocationCount = MAX_PCI_DEVICES;
  2067. }
  2068. //
  2069. // Allocate the new array.
  2070. //
  2071. AllocationSize = (sizeof(PDEVICE) + sizeof(PPCI_CHILD)) *
  2072. AllocationCount;
  2073. NewChildren = MmAllocatePagedPool(AllocationSize, PCI_ALLOCATION_TAG);
  2074. if (NewChildren == NULL) {
  2075. goto GetNewChildIndexEnd;
  2076. }
  2077. NewChildrenData = (PPCI_CHILD *)(NewChildren + AllocationCount);
  2078. if (ParentBus->Children != NULL) {
  2079. //
  2080. // Copy the old contents over.
  2081. //
  2082. RtlCopyMemory(NewChildren,
  2083. ParentBus->Children,
  2084. sizeof(PDEVICE) * ParentBus->ChildCount);
  2085. RtlCopyMemory(NewChildrenData,
  2086. ParentBus->ChildrenData,
  2087. sizeof(PPCI_DEVICE) * ParentBus->ChildCount);
  2088. //
  2089. // Free the old contents and update the pointers.
  2090. //
  2091. MmFreePagedPool(ParentBus->Children);
  2092. }
  2093. ParentBus->Children = NewChildren;
  2094. ParentBus->ChildrenData = NewChildrenData;
  2095. ParentBus->ChildSize = AllocationCount;
  2096. NewIndex = ParentBus->ChildCount;
  2097. NewChildren = NULL;
  2098. }
  2099. //
  2100. // Allocate a new PCI child structure.
  2101. //
  2102. ParentBus->ChildrenData[NewIndex] =
  2103. MmAllocatePagedPool(sizeof(PCI_CHILD), PCI_ALLOCATION_TAG);
  2104. if (ParentBus->ChildrenData[NewIndex] == NULL) {
  2105. NewIndex = MAX_ULONG;
  2106. goto GetNewChildIndexEnd;
  2107. }
  2108. RtlZeroMemory(ParentBus->ChildrenData[NewIndex], sizeof(PCI_CHILD));
  2109. GetNewChildIndexEnd:
  2110. if (NewChildren != NULL) {
  2111. MmFreePagedPool(NewChildren);
  2112. }
  2113. return NewIndex;
  2114. }
  2115. KSTATUS
  2116. PcipQueryInterface (
  2117. PIRP Irp,
  2118. PPCI_DEVICE PciDevice
  2119. )
  2120. /*++
  2121. Routine Description:
  2122. This routine responds to interface requests.
  2123. Arguments:
  2124. Irp - Supplies a pointer to the Query Interface IRP.
  2125. PciDevice - Supplies a pointer to the PCI device context relating to this
  2126. device.
  2127. Return Value:
  2128. Status code.
  2129. --*/
  2130. {
  2131. PINTERFACE_ACPI_BUS_ADDRESS BusAddressInterface;
  2132. PINTERFACE_PCI_BUS_DEVICE BusDeviceInterface;
  2133. BOOL Match;
  2134. PINTERFACE_PCI_CONFIG_ACCESS PciConfigInterface;
  2135. PINTERFACE_SPECIFIC_PCI_CONFIG_ACCESS SpecificPciConfigInterface;
  2136. KSTATUS Status;
  2137. ASSERT((Irp->MajorCode == IrpMajorStateChange) &&
  2138. (Irp->MinorCode == IrpMinorQueryInterface));
  2139. if (Irp->U.QueryInterface.Interface == NULL) {
  2140. return STATUS_INVALID_PARAMETER;
  2141. }
  2142. Status = STATUS_SUCCESS;
  2143. //
  2144. // Handle PCI config access interface requests.
  2145. //
  2146. Match = RtlAreUuidsEqual(&PciConfigSpaceUuid,
  2147. Irp->U.QueryInterface.Interface);
  2148. if (Match != FALSE) {
  2149. if (Irp->U.QueryInterface.InterfaceBuffer != NULL) {
  2150. //
  2151. // Copy the interface into the buffer, assuming its big enough.
  2152. //
  2153. if (Irp->U.QueryInterface.InterfaceBufferSize !=
  2154. sizeof(INTERFACE_PCI_CONFIG_ACCESS)) {
  2155. Status = STATUS_INCORRECT_BUFFER_SIZE;
  2156. Irp->U.QueryInterface.InterfaceBufferSize =
  2157. sizeof(INTERFACE_PCI_CONFIG_ACCESS);
  2158. goto QueryInterfaceEnd;
  2159. }
  2160. PciConfigInterface = Irp->U.QueryInterface.InterfaceBuffer;
  2161. PciConfigInterface->ReadPciConfig = PcipInterfaceReadConfigSpace;
  2162. PciConfigInterface->WritePciConfig = PcipInterfaceWriteConfigSpace;
  2163. PciConfigInterface->DeviceToken = PciDevice;
  2164. //
  2165. // The buffer is NULL, indicating the caller just wanted to know if the
  2166. // interface was out there. Fill out the size and return success.
  2167. //
  2168. } else {
  2169. Irp->U.QueryInterface.InterfaceBufferSize =
  2170. sizeof(INTERFACE_PCI_CONFIG_ACCESS);
  2171. }
  2172. goto QueryInterfaceEnd;
  2173. }
  2174. //
  2175. // Handle specific PCI config access interface requests.
  2176. //
  2177. Match = RtlAreUuidsEqual(&PciSpecificConfigSpaceUuid,
  2178. Irp->U.QueryInterface.Interface);
  2179. if (Match != FALSE) {
  2180. ASSERT((PciDevice->Type == PciDeviceBus) ||
  2181. (PciDevice->Type == PciDeviceBridge));
  2182. if (Irp->U.QueryInterface.InterfaceBuffer != NULL) {
  2183. //
  2184. // Copy the interface into the buffer, assuming its big enough.
  2185. //
  2186. if (Irp->U.QueryInterface.InterfaceBufferSize !=
  2187. sizeof(INTERFACE_SPECIFIC_PCI_CONFIG_ACCESS)) {
  2188. Status = STATUS_INCORRECT_BUFFER_SIZE;
  2189. Irp->U.QueryInterface.InterfaceBufferSize =
  2190. sizeof(INTERFACE_SPECIFIC_PCI_CONFIG_ACCESS);
  2191. goto QueryInterfaceEnd;
  2192. }
  2193. SpecificPciConfigInterface = Irp->U.QueryInterface.InterfaceBuffer;
  2194. SpecificPciConfigInterface->ReadPciConfig =
  2195. PcipInterfaceReadSpecificConfigSpace;
  2196. SpecificPciConfigInterface->WritePciConfig =
  2197. PcipInterfaceWriteSpecificConfigSpace;
  2198. SpecificPciConfigInterface->DeviceToken = PciDevice;
  2199. //
  2200. // The buffer is NULL, indicating the caller just wanted to know if the
  2201. // interface was out there. Fill out the size and return success.
  2202. //
  2203. } else {
  2204. Irp->U.QueryInterface.InterfaceBufferSize =
  2205. sizeof(INTERFACE_SPECIFIC_PCI_CONFIG_ACCESS);
  2206. }
  2207. goto QueryInterfaceEnd;
  2208. }
  2209. //
  2210. // Handle ACPI bus address interface requests.
  2211. //
  2212. if (PciDevice->Type == PciDeviceFunction) {
  2213. Match = RtlAreUuidsEqual(&PciAcpiBusAddressUuid,
  2214. Irp->U.QueryInterface.Interface);
  2215. if (Match != FALSE) {
  2216. ASSERT(PciDevice->Type == PciDeviceFunction);
  2217. if (Irp->U.QueryInterface.InterfaceBuffer != NULL) {
  2218. //
  2219. // Copy the interface into the buffer, assuming its big enough.
  2220. //
  2221. if (Irp->U.QueryInterface.InterfaceBufferSize !=
  2222. sizeof(INTERFACE_ACPI_BUS_ADDRESS)) {
  2223. Status = STATUS_INCORRECT_BUFFER_SIZE;
  2224. Irp->U.QueryInterface.InterfaceBufferSize =
  2225. sizeof(INTERFACE_ACPI_BUS_ADDRESS);
  2226. goto QueryInterfaceEnd;
  2227. }
  2228. BusAddressInterface = Irp->U.QueryInterface.InterfaceBuffer;
  2229. BusAddressInterface->BusAddress =
  2230. (PciDevice->DeviceNumber << 16) |
  2231. PciDevice->FunctionNumber;
  2232. //
  2233. // The buffer is NULL, indicating the caller just wanted to know if
  2234. // the interface was out there. Fill out the size and return
  2235. // success.
  2236. //
  2237. } else {
  2238. Irp->U.QueryInterface.InterfaceBufferSize =
  2239. sizeof(INTERFACE_ACPI_BUS_ADDRESS);
  2240. }
  2241. goto QueryInterfaceEnd;
  2242. }
  2243. }
  2244. //
  2245. // Handle internal PCI bus driver context requests. The function driver for
  2246. // bridges should not respond to this, leave it for the root bus function
  2247. // driver or a PCI bus driver.
  2248. //
  2249. if ((PciDevice->Type == PciDeviceBus) ||
  2250. (PciDevice->Type == PciDeviceFunction)) {
  2251. Match = RtlAreUuidsEqual(&PciBusDriverDeviceUuid,
  2252. Irp->U.QueryInterface.Interface);
  2253. if (Match != FALSE) {
  2254. if (Irp->U.QueryInterface.InterfaceBuffer != NULL) {
  2255. //
  2256. // Copy the interface into the buffer, assuming its big enough.
  2257. //
  2258. if (Irp->U.QueryInterface.InterfaceBufferSize !=
  2259. sizeof(INTERFACE_PCI_BUS_DEVICE)) {
  2260. ASSERT(FALSE);
  2261. Status = STATUS_INCORRECT_BUFFER_SIZE;
  2262. Irp->U.QueryInterface.InterfaceBufferSize =
  2263. sizeof(INTERFACE_PCI_BUS_DEVICE);
  2264. goto QueryInterfaceEnd;
  2265. }
  2266. BusDeviceInterface = Irp->U.QueryInterface.InterfaceBuffer;
  2267. BusDeviceInterface->BusDevice = PciDevice;
  2268. //
  2269. // The buffer is NULL, indicating the caller just wanted to know if
  2270. // the interface was out there. Fill out the size and return
  2271. // success.
  2272. //
  2273. } else {
  2274. Irp->U.QueryInterface.InterfaceBufferSize =
  2275. sizeof(INTERFACE_PCI_BUS_DEVICE);
  2276. }
  2277. goto QueryInterfaceEnd;
  2278. }
  2279. }
  2280. //
  2281. // The interface is not exposed by this PCI device.
  2282. //
  2283. Status = STATUS_NO_INTERFACE;
  2284. QueryInterfaceEnd:
  2285. return Status;
  2286. }
  2287. KSTATUS
  2288. PcipInterfaceReadConfigSpace (
  2289. PVOID DeviceToken,
  2290. ULONG Offset,
  2291. ULONG AccessSize,
  2292. PULONGLONG Value
  2293. )
  2294. /*++
  2295. Routine Description:
  2296. This routine reads from a device's PCI configuration space.
  2297. Arguments:
  2298. DeviceToken - Supplies the device token supplied when the interface was
  2299. acquired.
  2300. Offset - Supplies the offset in bytes into the PCI configuration space to
  2301. read.
  2302. AccessSize - Supplies the size of the access to make. Valid values are 1,
  2303. 2, 4, and 8.
  2304. Value - Supplies a pointer where the value read from PCI configuration
  2305. space will be returned on success.
  2306. Return Value:
  2307. Status code.
  2308. --*/
  2309. {
  2310. ULONGLONG DataRead;
  2311. PPCI_DEVICE PciDevice;
  2312. if (Offset > 0xFF) {
  2313. return STATUS_NOT_SUPPORTED;
  2314. }
  2315. PciDevice = DeviceToken;
  2316. DataRead = PciDevice->ReadConfig(PciDevice->BusNumber,
  2317. PciDevice->DeviceNumber,
  2318. PciDevice->FunctionNumber,
  2319. Offset,
  2320. AccessSize);
  2321. *Value = DataRead;
  2322. return STATUS_SUCCESS;
  2323. }
  2324. KSTATUS
  2325. PcipInterfaceWriteConfigSpace (
  2326. PVOID DeviceToken,
  2327. ULONG Offset,
  2328. ULONG AccessSize,
  2329. ULONGLONG Value
  2330. )
  2331. /*++
  2332. Routine Description:
  2333. This routine writes to a device's PCI configuration space.
  2334. Arguments:
  2335. DeviceToken - Supplies the device token supplied when the interface was
  2336. acquired.
  2337. AccessSize - Supplies the size of the access to make. Valid values are 1,
  2338. 2, 4, and 8.
  2339. Offset - Supplies the offset in bytes into the PCI configuration space to
  2340. write.
  2341. Value - Supplies the value to write into PCI configuration space.
  2342. Return Value:
  2343. Status code.
  2344. --*/
  2345. {
  2346. PPCI_DEVICE PciDevice;
  2347. if (Offset > 0xFF) {
  2348. return STATUS_NOT_SUPPORTED;
  2349. }
  2350. PciDevice = DeviceToken;
  2351. PciDevice->WriteConfig(PciDevice->BusNumber,
  2352. PciDevice->DeviceNumber,
  2353. PciDevice->FunctionNumber,
  2354. Offset,
  2355. AccessSize,
  2356. Value);
  2357. return STATUS_SUCCESS;
  2358. }
  2359. KSTATUS
  2360. PcipInterfaceReadSpecificConfigSpace (
  2361. PVOID DeviceToken,
  2362. ULONG BusNumber,
  2363. ULONG DeviceNumber,
  2364. ULONG FunctionNumber,
  2365. ULONG Offset,
  2366. ULONG AccessSize,
  2367. PULONGLONG Value
  2368. )
  2369. /*++
  2370. Routine Description:
  2371. This routine reads from a specific device's PCI configuration space.
  2372. Arguments:
  2373. DeviceToken - Supplies the device token supplied when the interface was
  2374. acquired.
  2375. BusNumber - Supplies the bus number of the device whose PCI configuration
  2376. space should be read from.
  2377. DeviceNumber - Supplies the device number of the device whose PCI
  2378. configuration space should be read from.
  2379. FunctionNumber - Supplies the function number of the device whose PCI
  2380. configuration space should be read from.
  2381. Offset - Supplies the offset in bytes into the PCI configuration space to
  2382. read.
  2383. AccessSize - Supplies the size of the access to make. Valid values are 1,
  2384. 2, 4, and 8.
  2385. Value - Supplies a pointer where the value read from PCI configuration
  2386. space will be returned on success.
  2387. Return Value:
  2388. Status code.
  2389. --*/
  2390. {
  2391. ULONGLONG DataRead;
  2392. PPCI_DEVICE PciDevice;
  2393. if (Offset > 0xFF) {
  2394. return STATUS_NOT_SUPPORTED;
  2395. }
  2396. PciDevice = DeviceToken;
  2397. ASSERT((PciDevice->Type == PciDeviceBus) ||
  2398. (PciDevice->Type == PciDeviceBridge));
  2399. DataRead = PciDevice->ReadConfig(BusNumber,
  2400. DeviceNumber,
  2401. FunctionNumber,
  2402. Offset,
  2403. AccessSize);
  2404. *Value = DataRead;
  2405. return STATUS_SUCCESS;
  2406. }
  2407. KSTATUS
  2408. PcipInterfaceWriteSpecificConfigSpace (
  2409. PVOID DeviceToken,
  2410. ULONG BusNumber,
  2411. ULONG DeviceNumber,
  2412. ULONG FunctionNumber,
  2413. ULONG Offset,
  2414. ULONG AccessSize,
  2415. ULONGLONG Value
  2416. )
  2417. /*++
  2418. Routine Description:
  2419. This routine writes to a specific device's PCI configuration space.
  2420. Arguments:
  2421. DeviceToken - Supplies the device token supplied when the interface was
  2422. acquired.
  2423. BusNumber - Supplies the bus number of the device whose PCI configuration
  2424. space should be written to.
  2425. DeviceNumber - Supplies the device number of the device whose PCI
  2426. configuration space should be written to.
  2427. FunctionNumber - Supplies the function number of the device whose PCI
  2428. configuration space should be written to.
  2429. Offset - Supplies the offset in bytes into the PCI configuration space to
  2430. write.
  2431. AccessSize - Supplies the size of the access to make. Valid values are 1,
  2432. 2, 4, and 8.
  2433. Value - Supplies the value to write into PCI configuration space.
  2434. Return Value:
  2435. Status code.
  2436. --*/
  2437. {
  2438. PPCI_DEVICE PciDevice;
  2439. if (Offset > 0xFF) {
  2440. return STATUS_NOT_SUPPORTED;
  2441. }
  2442. PciDevice = DeviceToken;
  2443. ASSERT((PciDevice->Type == PciDeviceBus) ||
  2444. (PciDevice->Type == PciDeviceBridge));
  2445. PciDevice->WriteConfig(BusNumber,
  2446. DeviceNumber,
  2447. FunctionNumber,
  2448. Offset,
  2449. AccessSize,
  2450. Value);
  2451. return STATUS_SUCCESS;
  2452. }
  2453. KSTATUS
  2454. PcipStartBusDevice (
  2455. PIRP StartIrp,
  2456. PPCI_DEVICE DeviceContext
  2457. )
  2458. /*++
  2459. Routine Description:
  2460. This routine starts a PCI bus.
  2461. Arguments:
  2462. StartIrp - Supplies a pointer to the start IRP.
  2463. DeviceContext - Supplies a pointer to the PCI bus or bridge.
  2464. Return Value:
  2465. Status code.
  2466. --*/
  2467. {
  2468. PRESOURCE_ALLOCATION Allocation;
  2469. PRESOURCE_ALLOCATION_LIST AllocationList;
  2470. BOOL BusNumberArbiterCreated;
  2471. BOOL IoPortArbiterCreated;
  2472. BOOL MemoryArbiterCreated;
  2473. PPCI_DEVICE Parent;
  2474. KSTATUS Status;
  2475. ASSERT(StartIrp->MinorCode == IrpMinorStartDevice);
  2476. ASSERT((DeviceContext->Type == PciDeviceBus) ||
  2477. (DeviceContext->Type == PciDeviceBridge));
  2478. //
  2479. // Bridges need to query the interface of the bus driver to get
  2480. // configuration space access.
  2481. //
  2482. if (DeviceContext->ReadConfig == NULL) {
  2483. ASSERT(DeviceContext->Type == PciDeviceBridge);
  2484. Status = PcipGetBusDriverDevice(StartIrp->Device, &Parent);
  2485. if (!KSUCCESS(Status)) {
  2486. goto StartBusDeviceEnd;
  2487. }
  2488. DeviceContext->ReadConfig = Parent->ReadConfig;
  2489. DeviceContext->WriteConfig = Parent->WriteConfig;
  2490. }
  2491. ASSERT((DeviceContext->ReadConfig != NULL) &&
  2492. (DeviceContext->WriteConfig != NULL));
  2493. //
  2494. // Create the "specific PCI Config Space" access interface.
  2495. //
  2496. Status = PcipCreateBusInterfaces(StartIrp->Device, DeviceContext);
  2497. if (!KSUCCESS(Status)) {
  2498. goto StartBusDeviceEnd;
  2499. }
  2500. BusNumberArbiterCreated = FALSE;
  2501. IoPortArbiterCreated = FALSE;
  2502. MemoryArbiterCreated = FALSE;
  2503. Status = STATUS_SUCCESS;
  2504. //
  2505. // Loop through every resource given to the bus/bridge, and expose an
  2506. // arbiter for child devices.
  2507. //
  2508. AllocationList = StartIrp->U.StartDevice.ProcessorLocalResources;
  2509. if (AllocationList == NULL) {
  2510. goto StartBusDeviceEnd;
  2511. }
  2512. Allocation = IoGetNextResourceAllocation(AllocationList, NULL);
  2513. while (Allocation != NULL) {
  2514. //
  2515. // Only create arbiters for expected types.
  2516. //
  2517. switch (Allocation->Type) {
  2518. case ResourceTypeBusNumber:
  2519. //
  2520. // Create a bus number arbiter if one hasn't been created yet and
  2521. // more than one bus number was doled out. Keep the first bus
  2522. // number for this bus itself.
  2523. //
  2524. if (Allocation->Length > 1) {
  2525. ASSERT(Allocation->Allocation == DeviceContext->BusNumber);
  2526. if (BusNumberArbiterCreated == FALSE) {
  2527. Status = IoCreateResourceArbiter(StartIrp->Device,
  2528. Allocation->Type);
  2529. if (!KSUCCESS(Status)) {
  2530. goto StartBusDeviceEnd;
  2531. }
  2532. BusNumberArbiterCreated = TRUE;
  2533. }
  2534. Status = IoAddFreeSpaceToArbiter(StartIrp->Device,
  2535. Allocation->Type,
  2536. Allocation->Allocation + 1,
  2537. Allocation->Length - 1,
  2538. Allocation->Characteristics,
  2539. Allocation,
  2540. 0);
  2541. //
  2542. // If only one bus number was handed out, this must be a bridge.
  2543. // Save that bus number for downstream config accesses later.
  2544. //
  2545. } else {
  2546. ASSERT(Allocation->Length == 1);
  2547. ASSERT((UCHAR)Allocation->Allocation == Allocation->Allocation);
  2548. DeviceContext->BusNumber = (UCHAR)(Allocation->Allocation);
  2549. }
  2550. break;
  2551. case ResourceTypePhysicalAddressSpace:
  2552. //
  2553. // Create an address space arbiter if one hasn't been created yet.
  2554. //
  2555. if (MemoryArbiterCreated == FALSE) {
  2556. Status = IoCreateResourceArbiter(StartIrp->Device,
  2557. Allocation->Type);
  2558. if (!KSUCCESS(Status)) {
  2559. goto StartBusDeviceEnd;
  2560. }
  2561. MemoryArbiterCreated = TRUE;
  2562. }
  2563. Status = IoAddFreeSpaceToArbiter(StartIrp->Device,
  2564. Allocation->Type,
  2565. Allocation->Allocation,
  2566. Allocation->Length,
  2567. Allocation->Characteristics,
  2568. Allocation,
  2569. 0);
  2570. break;
  2571. case ResourceTypeIoPort:
  2572. //
  2573. // Create an I/O port arbiter if one hasn't been created yet.
  2574. //
  2575. if (IoPortArbiterCreated == FALSE) {
  2576. Status = IoCreateResourceArbiter(StartIrp->Device,
  2577. Allocation->Type);
  2578. if (!KSUCCESS(Status)) {
  2579. goto StartBusDeviceEnd;
  2580. }
  2581. IoPortArbiterCreated = TRUE;
  2582. }
  2583. Status = IoAddFreeSpaceToArbiter(StartIrp->Device,
  2584. Allocation->Type,
  2585. Allocation->Allocation,
  2586. Allocation->Length,
  2587. Allocation->Characteristics,
  2588. Allocation,
  2589. 0);
  2590. break;
  2591. default:
  2592. break;
  2593. }
  2594. if (!KSUCCESS(Status)) {
  2595. goto StartBusDeviceEnd;
  2596. }
  2597. Allocation = IoGetNextResourceAllocation(AllocationList, Allocation);
  2598. }
  2599. StartBusDeviceEnd:
  2600. return Status;
  2601. }
  2602. KSTATUS
  2603. PcipCreateFunctionInterfaces (
  2604. PDEVICE Device,
  2605. PPCI_DEVICE PciDevice
  2606. )
  2607. /*++
  2608. Routine Description:
  2609. This routine creates the exposed interfaces for a PCI device.
  2610. Arguments:
  2611. Device - Supplies a pointer to the device to create interfaces for.
  2612. PciDevice - Supplies a pointer to the PCI device context.
  2613. Return Value:
  2614. Status code.
  2615. --*/
  2616. {
  2617. PINTERFACE_ACPI_BUS_ADDRESS BusAddressInterface;
  2618. PINTERFACE_PCI_CONFIG_ACCESS PciConfigInterface;
  2619. KSTATUS Status;
  2620. BusAddressInterface = NULL;
  2621. //
  2622. // Create the PCI config access interface.
  2623. //
  2624. PciConfigInterface = MmAllocateNonPagedPool(
  2625. sizeof(INTERFACE_PCI_CONFIG_ACCESS),
  2626. PCI_ALLOCATION_TAG);
  2627. if (PciConfigInterface == NULL) {
  2628. Status = STATUS_INSUFFICIENT_RESOURCES;
  2629. goto CreateFunctionInterfacesEnd;
  2630. }
  2631. RtlZeroMemory(PciConfigInterface, sizeof(INTERFACE_PCI_CONFIG_ACCESS));
  2632. PciConfigInterface->ReadPciConfig = PcipInterfaceReadConfigSpace;
  2633. PciConfigInterface->WritePciConfig = PcipInterfaceWriteConfigSpace;
  2634. PciConfigInterface->DeviceToken = PciDevice;
  2635. PciDevice->PciConfigInterface = PciConfigInterface;
  2636. //
  2637. // Create the ACPI bus address interface.
  2638. //
  2639. BusAddressInterface = MmAllocateNonPagedPool(
  2640. sizeof(INTERFACE_ACPI_BUS_ADDRESS),
  2641. PCI_ALLOCATION_TAG);
  2642. if (BusAddressInterface == NULL) {
  2643. Status = STATUS_INSUFFICIENT_RESOURCES;
  2644. goto CreateFunctionInterfacesEnd;
  2645. }
  2646. RtlZeroMemory(BusAddressInterface, sizeof(INTERFACE_ACPI_BUS_ADDRESS));
  2647. BusAddressInterface->BusAddress = (PciDevice->DeviceNumber << 16) |
  2648. PciDevice->FunctionNumber;
  2649. PciDevice->AcpiBusAddressInterface = BusAddressInterface;
  2650. //
  2651. // Enumerate the devices to the system.
  2652. //
  2653. Status = IoCreateInterface(&PciConfigSpaceUuid,
  2654. Device,
  2655. PciConfigInterface,
  2656. sizeof(INTERFACE_PCI_CONFIG_ACCESS));
  2657. if (!KSUCCESS(Status)) {
  2658. //
  2659. // Allow this to fail with a duplicate entry if the device is a bridge,
  2660. // as the bridge's functional driver will have already created this
  2661. // interface.
  2662. //
  2663. if ((Status != STATUS_DUPLICATE_ENTRY) ||
  2664. (PciDevice->DeviceIsBridge == FALSE)) {
  2665. goto CreateFunctionInterfacesEnd;
  2666. }
  2667. }
  2668. Status = IoCreateInterface(&PciAcpiBusAddressUuid,
  2669. Device,
  2670. BusAddressInterface,
  2671. sizeof(INTERFACE_ACPI_BUS_ADDRESS));
  2672. if (!KSUCCESS(Status)) {
  2673. IoDestroyInterface(&PciConfigSpaceUuid, Device, PciConfigInterface);
  2674. goto CreateFunctionInterfacesEnd;
  2675. }
  2676. //
  2677. // Attempt to create the MSI/MSI-X context and interface for this function
  2678. // device.
  2679. //
  2680. Status = PcipMsiCreateContextAndInterface(Device, PciDevice);
  2681. if (!KSUCCESS(Status)) {
  2682. IoDestroyInterface(&PciConfigSpaceUuid, Device, PciConfigInterface);
  2683. IoDestroyInterface(&PciAcpiBusAddressUuid, Device, BusAddressInterface);
  2684. goto CreateFunctionInterfacesEnd;
  2685. }
  2686. Status = STATUS_SUCCESS;
  2687. CreateFunctionInterfacesEnd:
  2688. if (!KSUCCESS(Status)) {
  2689. if (PciConfigInterface != NULL) {
  2690. MmFreeNonPagedPool(PciConfigInterface);
  2691. }
  2692. if (BusAddressInterface != NULL) {
  2693. MmFreeNonPagedPool(BusAddressInterface);
  2694. }
  2695. PciDevice->PciConfigInterface = NULL;
  2696. PciDevice->AcpiBusAddressInterface = NULL;
  2697. if (PciDevice->MsiContext != NULL) {
  2698. PcipMsiDestroyContextAndInterface(Device, PciDevice);
  2699. }
  2700. }
  2701. return Status;
  2702. }
  2703. KSTATUS
  2704. PcipCreateBusInterfaces (
  2705. PDEVICE Device,
  2706. PPCI_DEVICE PciDevice
  2707. )
  2708. /*++
  2709. Routine Description:
  2710. This routine creates the exposed interfaces for a PCI device.
  2711. Arguments:
  2712. Device - Supplies a pointer to the device to create interfaces for.
  2713. PciDevice - Supplies a pointer to the PCI device context.
  2714. Return Value:
  2715. Status code.
  2716. --*/
  2717. {
  2718. PINTERFACE_SPECIFIC_PCI_CONFIG_ACCESS SpecificPciConfigInterface;
  2719. KSTATUS Status;
  2720. //
  2721. // Create the specific PCI config access interface.
  2722. //
  2723. SpecificPciConfigInterface = MmAllocateNonPagedPool(
  2724. sizeof(INTERFACE_SPECIFIC_PCI_CONFIG_ACCESS),
  2725. PCI_ALLOCATION_TAG);
  2726. if (SpecificPciConfigInterface == NULL) {
  2727. Status = STATUS_INSUFFICIENT_RESOURCES;
  2728. goto CreateInterfacesEnd;
  2729. }
  2730. RtlZeroMemory(SpecificPciConfigInterface,
  2731. sizeof(INTERFACE_SPECIFIC_PCI_CONFIG_ACCESS));
  2732. SpecificPciConfigInterface->ReadPciConfig =
  2733. PcipInterfaceReadSpecificConfigSpace;
  2734. SpecificPciConfigInterface->WritePciConfig =
  2735. PcipInterfaceWriteSpecificConfigSpace;
  2736. SpecificPciConfigInterface->DeviceToken = PciDevice;
  2737. //
  2738. // Expose the interface to the system.
  2739. //
  2740. Status = IoCreateInterface(&PciSpecificConfigSpaceUuid,
  2741. Device,
  2742. SpecificPciConfigInterface,
  2743. sizeof(INTERFACE_SPECIFIC_PCI_CONFIG_ACCESS));
  2744. if (!KSUCCESS(Status)) {
  2745. goto CreateInterfacesEnd;
  2746. }
  2747. PciDevice->SpecificPciConfigInterface = SpecificPciConfigInterface;
  2748. Status = STATUS_SUCCESS;
  2749. CreateInterfacesEnd:
  2750. if (!KSUCCESS(Status)) {
  2751. if (SpecificPciConfigInterface != NULL) {
  2752. MmFreeNonPagedPool(SpecificPciConfigInterface);
  2753. }
  2754. PciDevice->SpecificPciConfigInterface = NULL;
  2755. }
  2756. return Status;
  2757. }
  2758. PSTR
  2759. PcipGetClassId (
  2760. ULONG ClassCode
  2761. )
  2762. /*++
  2763. Routine Description:
  2764. This routine returns the class string for the given PCI class code.
  2765. Arguments:
  2766. ClassCode - Supplies the class code.
  2767. Return Value:
  2768. Returns a pointer to a string describing the class.
  2769. NULL if no class could be determined.
  2770. --*/
  2771. {
  2772. UCHAR Class;
  2773. USHORT Subclass;
  2774. Class = PCI_CLASS_CODE(ClassCode);
  2775. Subclass = PCI_SUBCLASS_AND_INTERFACE(ClassCode);
  2776. switch (Class) {
  2777. //
  2778. // Unimplemented or unknown class codes.
  2779. //
  2780. case PCI_CLASS_UNKNOWN:
  2781. if (Subclass == PCI_CLASS_UNKNOWN_VGA) {
  2782. return "VGA";
  2783. }
  2784. break;
  2785. case PCI_CLASS_MASS_STORAGE:
  2786. if ((Subclass & PCI_CLASS_MASS_STORAGE_IDE_MASK) ==
  2787. PCI_CLASS_MASS_STORAGE_IDE) {
  2788. return "IDE";
  2789. }
  2790. break;
  2791. case PCI_CLASS_BRIDGE:
  2792. switch (Subclass) {
  2793. case PCI_CLASS_BRIDGE_ISA:
  2794. return "ISA";
  2795. case PCI_CLASS_BRIDGE_PCI:
  2796. return PCI_BRIDGE_CLASS_ID;
  2797. case PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE:
  2798. return PCI_SUBTRACTIVE_BRIDGE_CLASS_ID;
  2799. default:
  2800. break;
  2801. }
  2802. break;
  2803. case PCI_CLASS_SERIAL_BUS:
  2804. switch (Subclass) {
  2805. case PCI_CLASS_SERIAL_BUS_USB_UHCI:
  2806. return "UHCI";
  2807. case PCI_CLASS_SERIAL_BUS_USB_OHCI:
  2808. return "OHCI";
  2809. case PCI_CLASS_SERIAL_BUS_USB_EHCI:
  2810. return "EHCI";
  2811. default:
  2812. break;
  2813. }
  2814. break;
  2815. case PCI_CLASS_NETWORK:
  2816. case PCI_CLASS_DISPLAY:
  2817. case PCI_CLASS_MULTIMEDIA:
  2818. case PCI_CLASS_MEMORY:
  2819. break;
  2820. case PCI_CLASS_SIMPLE_COMMUNICATION:
  2821. switch (Subclass) {
  2822. case PCI_CLASS_SIMPLE_COMMUNICATION_XT_UART:
  2823. case PCI_CLASS_SIMPLE_COMMUNICATION_16450:
  2824. case PCI_CLASS_SIMPLE_COMMUNICATION_16550:
  2825. return "Serial16550";
  2826. }
  2827. break;
  2828. case PCI_CLASS_GENERAL_PERIPHERAL:
  2829. switch (Subclass) {
  2830. case PCI_CLASS_GENERAL_SD_HOST_NO_DMA:
  2831. return "SdHostPio";
  2832. case PCI_CLASS_GENERAL_SD_HOST:
  2833. return "SdHost";
  2834. default:
  2835. break;
  2836. }
  2837. break;
  2838. case PCI_CLASS_INPUT:
  2839. case PCI_CLASS_DOCKING_STATION:
  2840. case PCI_CLASS_PROCESSOR:
  2841. case PCI_CLASS_WIRELESS:
  2842. case PCI_CLASS_INTELLIGENT_IO:
  2843. case PCI_CLASS_SATELLITE_COMMUNICATION:
  2844. case PCI_CLASS_ENCRYPTION:
  2845. case PCI_CLASS_DATA_ACQUISITION:
  2846. case PCI_CLASS_VENDOR:
  2847. break;
  2848. }
  2849. return NULL;
  2850. }
  2851. KSTATUS
  2852. PcipGetBusDriverDevice (
  2853. PDEVICE OsDevice,
  2854. PPCI_DEVICE *BusDriverDevice
  2855. )
  2856. /*++
  2857. Routine Description:
  2858. This routine returns the bus driver's PCI device structure.
  2859. Arguments:
  2860. OsDevice - Supplies a pointer to the OS device.
  2861. BusDriverDevice - Supplies a pointer where a pointer to the bus driver's
  2862. device will be returned on success.
  2863. Return Value:
  2864. Status code.
  2865. --*/
  2866. {
  2867. INTERFACE_PCI_BUS_DEVICE Interface;
  2868. PIRP QueryInterfaceIrp;
  2869. KSTATUS Status;
  2870. *BusDriverDevice = NULL;
  2871. //
  2872. // Allocate and send an IRP to the bus driver requesting access
  2873. // to the PCI config interface.
  2874. //
  2875. QueryInterfaceIrp = IoCreateIrp(OsDevice, IrpMajorStateChange, 0);
  2876. if (QueryInterfaceIrp == NULL) {
  2877. Status = STATUS_INSUFFICIENT_RESOURCES;
  2878. goto GetBusDriverDeviceEnd;
  2879. }
  2880. QueryInterfaceIrp->MinorCode = IrpMinorQueryInterface;
  2881. QueryInterfaceIrp->U.QueryInterface.Interface = &PciBusDriverDeviceUuid;
  2882. QueryInterfaceIrp->U.QueryInterface.InterfaceBuffer = &Interface;
  2883. QueryInterfaceIrp->U.QueryInterface.InterfaceBufferSize =
  2884. sizeof(INTERFACE_PCI_BUS_DEVICE);
  2885. Status = IoSendSynchronousIrp(QueryInterfaceIrp);
  2886. if (!KSUCCESS(Status)) {
  2887. goto GetBusDriverDeviceEnd;
  2888. }
  2889. Status = IoGetIrpStatus(QueryInterfaceIrp);
  2890. if (!KSUCCESS(Status)) {
  2891. goto GetBusDriverDeviceEnd;
  2892. }
  2893. *BusDriverDevice = Interface.BusDevice;
  2894. GetBusDriverDeviceEnd:
  2895. if (QueryInterfaceIrp != NULL) {
  2896. IoDestroyIrp(QueryInterfaceIrp);
  2897. }
  2898. return Status;
  2899. }