8b0626fe384d0f5d35c3ec9ba65f038ef60226a3
[reactos.git] / reactos / hal / halx86 / generic / pci.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/hal/x86/pci.c
6 * PURPOSE: Interfaces to the PCI bus
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * Eric Kohl (ekohl@rz-online.de)
9 * UPDATE HISTORY:
10 * 05/06/1998: Created
11 * 17/08/2000: Added preliminary pci bus scanner
12 * 13/06/2001: Implemented access to pci configuration space
13 */
14
15 /*
16 * NOTES: Sections copied from the Linux pci support
17 */
18
19 /* INCLUDES *****************************************************************/
20
21 #include <hal.h>
22 #define NDEBUG
23 #include <debug.h>
24
25
26 /* MACROS ******************************************************************/
27
28 /* FIXME These are also defined in drivers/bus/pci/pcidef.h.
29 Maybe put PCI definitions in a central include file??? */
30
31 /* access type 1 macros */
32 #define CONFIG_CMD(bus, dev_fn, where) \
33 (0x80000000 | (((ULONG)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3))
34
35 /* access type 2 macros */
36 #define IOADDR(dev_fn, where) \
37 (0xC000 | (((dev_fn) & 0x1F) << 8) | (where))
38 #define FUNC(dev_fn) \
39 ((((dev_fn) & 0xE0) >> 4) | 0xf0)
40
41 #define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
42 #define PCI_BASE_ADDRESS_SPACE_IO 0x01
43 #define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
44 #define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
45 #define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
46 #define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
47 #define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
48 #define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
49 #define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
50 #define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
51 /* bit 1 is reserved if address_space = 1 */
52
53
54 /* GLOBALS ******************************************************************/
55
56 #define TAG_PCI TAG('P', 'C', 'I', 'H')
57
58 static ULONG BusConfigType = 0; /* undetermined config type */
59 static KSPIN_LOCK PciLock;
60
61 /* FUNCTIONS ****************************************************************/
62
63 static NTSTATUS
64 ReadPciConfigUchar(UCHAR Bus,
65 UCHAR Slot,
66 UCHAR Offset,
67 PUCHAR Value)
68 {
69 KIRQL oldIrql;
70
71 switch (BusConfigType)
72 {
73 case 1:
74 KeAcquireSpinLock(&PciLock, &oldIrql);
75 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
76 *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3));
77 KeReleaseSpinLock(&PciLock, oldIrql);
78 return STATUS_SUCCESS;
79
80 case 2:
81 KeAcquireSpinLock(&PciLock, &oldIrql);
82 WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
83 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
84 *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset)));
85 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
86 KeReleaseSpinLock(&PciLock, oldIrql);
87 return STATUS_SUCCESS;
88 }
89 return STATUS_UNSUCCESSFUL;
90 }
91
92
93 static NTSTATUS
94 ReadPciConfigUshort(UCHAR Bus,
95 UCHAR Slot,
96 UCHAR Offset,
97 PUSHORT Value)
98 {
99 KIRQL oldIrql;
100
101 if ((Offset & 1) != 0)
102 {
103 return STATUS_INVALID_PARAMETER;
104 }
105
106 switch (BusConfigType)
107 {
108 case 1:
109 KeAcquireSpinLock(&PciLock, &oldIrql);
110 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
111 *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2));
112 KeReleaseSpinLock(&PciLock, oldIrql);
113 return STATUS_SUCCESS;
114
115 case 2:
116 KeAcquireSpinLock(&PciLock, &oldIrql);
117 WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
118 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
119 *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)));
120 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
121 KeReleaseSpinLock(&PciLock, oldIrql);
122 return STATUS_SUCCESS;
123 }
124 return STATUS_UNSUCCESSFUL;
125 }
126
127
128 static NTSTATUS
129 ReadPciConfigUlong(UCHAR Bus,
130 UCHAR Slot,
131 UCHAR Offset,
132 PULONG Value)
133 {
134 KIRQL oldIrql;
135
136 if ((Offset & 3) != 0)
137 {
138 return STATUS_INVALID_PARAMETER;
139 }
140
141 switch (BusConfigType)
142 {
143 case 1:
144 KeAcquireSpinLock(&PciLock, &oldIrql);
145 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
146 *Value = READ_PORT_ULONG((PULONG)0xCFC);
147 KeReleaseSpinLock(&PciLock, oldIrql);
148 return STATUS_SUCCESS;
149
150 case 2:
151 KeAcquireSpinLock(&PciLock, &oldIrql);
152 WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
153 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
154 *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)));
155 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
156 KeReleaseSpinLock(&PciLock, oldIrql);
157 return STATUS_SUCCESS;
158 }
159 return STATUS_UNSUCCESSFUL;
160 }
161
162
163 static NTSTATUS
164 WritePciConfigUchar(UCHAR Bus,
165 UCHAR Slot,
166 UCHAR Offset,
167 UCHAR Value)
168 {
169 KIRQL oldIrql;
170
171 switch (BusConfigType)
172 {
173 case 1:
174 KeAcquireSpinLock(&PciLock, &oldIrql);
175 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
176 WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value);
177 KeReleaseSpinLock(&PciLock, oldIrql);
178 return STATUS_SUCCESS;
179
180 case 2:
181 KeAcquireSpinLock(&PciLock, &oldIrql);
182 WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
183 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
184 WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value);
185 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
186 KeReleaseSpinLock(&PciLock, oldIrql);
187 return STATUS_SUCCESS;
188 }
189 return STATUS_UNSUCCESSFUL;
190 }
191
192
193 static NTSTATUS
194 WritePciConfigUshort(UCHAR Bus,
195 UCHAR Slot,
196 UCHAR Offset,
197 USHORT Value)
198 {
199 KIRQL oldIrql;
200
201 if ((Offset & 1) != 0)
202 {
203 return STATUS_INVALID_PARAMETER;
204 }
205
206 switch (BusConfigType)
207 {
208 case 1:
209 KeAcquireSpinLock(&PciLock, &oldIrql);
210 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
211 WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2), Value);
212 KeReleaseSpinLock(&PciLock, oldIrql);
213 return STATUS_SUCCESS;
214
215 case 2:
216 KeAcquireSpinLock(&PciLock, &oldIrql);
217 WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
218 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
219 WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value);
220 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
221 KeReleaseSpinLock(&PciLock, oldIrql);
222 return STATUS_SUCCESS;
223 }
224 return STATUS_UNSUCCESSFUL;
225 }
226
227
228 static NTSTATUS
229 WritePciConfigUlong(UCHAR Bus,
230 UCHAR Slot,
231 UCHAR Offset,
232 ULONG Value)
233 {
234 KIRQL oldIrql;
235
236 if ((Offset & 3) != 0)
237 {
238 return STATUS_INVALID_PARAMETER;
239 }
240
241 switch (BusConfigType)
242 {
243 case 1:
244 KeAcquireSpinLock(&PciLock, &oldIrql);
245 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
246 WRITE_PORT_ULONG((PULONG)0xCFC, Value);
247 KeReleaseSpinLock(&PciLock, oldIrql);
248 return STATUS_SUCCESS;
249
250 case 2:
251 KeAcquireSpinLock(&PciLock, &oldIrql);
252 WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
253 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
254 WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value);
255 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
256 KeReleaseSpinLock(&PciLock, oldIrql);
257 return STATUS_SUCCESS;
258 }
259 return STATUS_UNSUCCESSFUL;
260 }
261
262
263 static ULONG STDCALL
264 HalpGetPciData(PBUS_HANDLER BusHandler,
265 ULONG BusNumber,
266 ULONG SlotNumber,
267 PVOID Buffer,
268 ULONG Offset,
269 ULONG Length)
270 {
271 PVOID Ptr = Buffer;
272 ULONG Address = Offset;
273 ULONG Len = Length;
274 ULONG Vendor;
275 UCHAR HeaderType;
276
277 DPRINT("HalpGetPciData() called.\n");
278 DPRINT(" BusNumber %lu\n", BusNumber);
279 DPRINT(" SlotNumber %lu\n", SlotNumber);
280 DPRINT(" Offset 0x%lx\n", Offset);
281 DPRINT(" Length 0x%lx\n", Length);
282
283 if ((Length == 0) || (BusConfigType == 0))
284 return 0;
285
286 ReadPciConfigUlong((UCHAR)BusNumber,
287 (UCHAR)(SlotNumber & 0x1F),
288 0x00,
289 &Vendor);
290 /* some broken boards return 0 if a slot is empty: */
291 if (Vendor == 0xFFFFFFFF || Vendor == 0)
292 {
293 if (BusNumber == 0 && Offset == 0 && Length >= 2)
294 {
295 *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
296 return 2;
297 }
298 return 0;
299 }
300
301 /* 0E=PCI_HEADER_TYPE */
302 ReadPciConfigUchar((UCHAR)BusNumber,
303 (UCHAR)(SlotNumber & 0x1F),
304 0x0E,
305 &HeaderType);
306 if (((HeaderType & PCI_MULTIFUNCTION) == 0) && ((SlotNumber & 0xE0) != 0))
307 {
308 if (Offset == 0 && Length >= 2)
309 {
310 *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
311 return 2;
312 }
313 return 0;
314 }
315 ReadPciConfigUlong((UCHAR)BusNumber,
316 (UCHAR)SlotNumber,
317 0x00,
318 &Vendor);
319 /* some broken boards return 0 if a slot is empty: */
320 if (Vendor == 0xFFFFFFFF || Vendor == 0)
321 {
322 if (BusNumber == 0 && Offset == 0 && Length >= 2)
323 {
324 *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
325 return 2;
326 }
327 return 0;
328 }
329
330 if ((Address & 1) && (Len >= 1))
331 {
332 ReadPciConfigUchar((UCHAR)BusNumber,
333 (UCHAR)SlotNumber,
334 (UCHAR)Address,
335 Ptr);
336 Ptr = (char*)Ptr + 1;
337 Address++;
338 Len--;
339 }
340
341 if ((Address & 2) && (Len >= 2))
342 {
343 ReadPciConfigUshort((UCHAR)BusNumber,
344 (UCHAR)SlotNumber,
345 (UCHAR)Address,
346 Ptr);
347 Ptr = (char*)Ptr + 2;
348 Address += 2;
349 Len -= 2;
350 }
351
352 while (Len >= 4)
353 {
354 ReadPciConfigUlong((UCHAR)BusNumber,
355 (UCHAR)SlotNumber,
356 (UCHAR)Address,
357 Ptr);
358 Ptr = (char*)Ptr + 4;
359 Address += 4;
360 Len -= 4;
361 }
362
363 if (Len >= 2)
364 {
365 ReadPciConfigUshort((UCHAR)BusNumber,
366 (UCHAR)SlotNumber,
367 (UCHAR)Address,
368 Ptr);
369 Ptr = (char*)Ptr + 2;
370 Address += 2;
371 Len -= 2;
372 }
373
374 if (Len >= 1)
375 {
376 ReadPciConfigUchar((UCHAR)BusNumber,
377 (UCHAR)SlotNumber,
378 (UCHAR)Address,
379 Ptr);
380 Ptr = (char*)Ptr + 1;
381 Address++;
382 Len--;
383 }
384
385 return Length - Len;
386 }
387
388
389 static ULONG STDCALL
390 HalpSetPciData(PBUS_HANDLER BusHandler,
391 ULONG BusNumber,
392 ULONG SlotNumber,
393 PVOID Buffer,
394 ULONG Offset,
395 ULONG Length)
396 {
397 PVOID Ptr = Buffer;
398 ULONG Address = Offset;
399 ULONG Len = Length;
400 ULONG Vendor;
401 UCHAR HeaderType;
402
403 DPRINT("HalpSetPciData() called.\n");
404 DPRINT(" BusNumber %lu\n", BusNumber);
405 DPRINT(" SlotNumber %lu\n", SlotNumber);
406 DPRINT(" Offset 0x%lx\n", Offset);
407 DPRINT(" Length 0x%lx\n", Length);
408
409 if ((Length == 0) || (BusConfigType == 0))
410 return 0;
411
412 ReadPciConfigUlong((UCHAR)BusNumber,
413 (UCHAR)(SlotNumber & 0x1F),
414 0x00,
415 &Vendor);
416 /* some broken boards return 0 if a slot is empty: */
417 if (Vendor == 0xFFFFFFFF || Vendor == 0)
418 return 0;
419
420
421 /* 0E=PCI_HEADER_TYPE */
422 ReadPciConfigUchar((UCHAR)BusNumber,
423 (UCHAR)(SlotNumber & 0x1F),
424 0x0E,
425 &HeaderType);
426 if (((HeaderType & PCI_MULTIFUNCTION) == 0) && ((SlotNumber & 0xE0) != 0))
427 return 0;
428
429 ReadPciConfigUlong((UCHAR)BusNumber,
430 (UCHAR)SlotNumber,
431 0x00,
432 &Vendor);
433 /* some broken boards return 0 if a slot is empty: */
434 if (Vendor == 0xFFFFFFFF || Vendor == 0)
435 return 0;
436
437 if ((Address & 1) && (Len >= 1))
438 {
439 WritePciConfigUchar((UCHAR)BusNumber,
440 (UCHAR)SlotNumber,
441 (UCHAR)Address,
442 *(PUCHAR)Ptr);
443 Ptr = (char*)Ptr + 1;
444 Address++;
445 Len--;
446 }
447
448 if ((Address & 2) && (Len >= 2))
449 {
450 WritePciConfigUshort((UCHAR)BusNumber,
451 (UCHAR)SlotNumber,
452 (UCHAR)Address,
453 *(PUSHORT)Ptr);
454 Ptr = (char*)Ptr + 2;
455 Address += 2;
456 Len -= 2;
457 }
458
459 while (Len >= 4)
460 {
461 WritePciConfigUlong((UCHAR)BusNumber,
462 (UCHAR)SlotNumber,
463 (UCHAR)Address,
464 *(PULONG)Ptr);
465 Ptr = (char*)Ptr + 4;
466 Address += 4;
467 Len -= 4;
468 }
469
470 if (Len >= 2)
471 {
472 WritePciConfigUshort((UCHAR)BusNumber,
473 (UCHAR)SlotNumber,
474 (UCHAR)Address,
475 *(PUSHORT)Ptr);
476 Ptr = (char*)Ptr + 2;
477 Address += 2;
478 Len -= 2;
479 }
480
481 if (Len >= 1)
482 {
483 WritePciConfigUchar((UCHAR)BusNumber,
484 (UCHAR)SlotNumber,
485 (UCHAR)Address,
486 *(PUCHAR)Ptr);
487 Ptr = (char*)Ptr + 1;
488 Address++;
489 Len--;
490 }
491
492 return Length - Len;
493 }
494
495
496 static ULONG
497 GetBusConfigType(VOID)
498 {
499 ULONG Value;
500 KIRQL oldIrql;
501
502 DPRINT("GetBusConfigType() called\n");
503
504 KeAcquireSpinLock(&PciLock, &oldIrql);
505
506 DPRINT("Checking configuration type 1:");
507 WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01);
508 Value = READ_PORT_ULONG((PULONG)0xCF8);
509 WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000);
510 if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000)
511 {
512 WRITE_PORT_ULONG((PULONG)0xCF8, Value);
513 KeReleaseSpinLock(&PciLock, oldIrql);
514 DPRINT(" Success!\n");
515 return 1;
516 }
517 WRITE_PORT_ULONG((PULONG)0xCF8, Value);
518 DPRINT(" Unsuccessful!\n");
519
520 DPRINT("Checking configuration type 2:");
521 WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00);
522 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00);
523 WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00);
524 if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 &&
525 READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00)
526 {
527 KeReleaseSpinLock(&PciLock, oldIrql);
528 DPRINT(" Success!\n");
529 return 2;
530 }
531 KeReleaseSpinLock(&PciLock, oldIrql);
532 DPRINT(" Unsuccessful!\n");
533
534 DPRINT("No pci bus found!\n");
535 return 0;
536 }
537
538
539 static ULONG STDCALL
540 HalpGetPciInterruptVector(PVOID BusHandler,
541 ULONG BusNumber,
542 ULONG BusInterruptLevel,
543 ULONG BusInterruptVector,
544 PKIRQL Irql,
545 PKAFFINITY Affinity)
546 {
547 ULONG Vector = IRQ2VECTOR(BusInterruptVector);
548 *Irql = VECTOR2IRQL(Vector);
549 *Affinity = 0xFFFFFFFF;
550 return Vector;
551 }
552
553 static BOOLEAN STDCALL
554 HalpTranslatePciAddress(PBUS_HANDLER BusHandler,
555 ULONG BusNumber,
556 PHYSICAL_ADDRESS BusAddress,
557 PULONG AddressSpace,
558 PPHYSICAL_ADDRESS TranslatedAddress)
559 {
560 if (*AddressSpace == 0)
561 {
562 /* memory space */
563
564 }
565 else if (*AddressSpace == 1)
566 {
567 /* io space */
568
569 }
570 else
571 {
572 /* other */
573 return FALSE;
574 }
575
576 TranslatedAddress->QuadPart = BusAddress.QuadPart;
577
578 return TRUE;
579 }
580
581 /*
582 * Find the extent of a PCI decode..
583 */
584 static ULONG STDCALL
585 PciSize(ULONG Base, ULONG Mask)
586 {
587 ULONG Size = Mask & Base; /* Find the significant bits */
588 Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */
589 return Size;
590 }
591
592 static NTSTATUS STDCALL
593 HalpAssignPciSlotResources(IN PBUS_HANDLER BusHandler,
594 IN ULONG BusNumber,
595 IN PUNICODE_STRING RegistryPath,
596 IN PUNICODE_STRING DriverClassName,
597 IN PDRIVER_OBJECT DriverObject,
598 IN PDEVICE_OBJECT DeviceObject,
599 IN ULONG SlotNumber,
600 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
601 {
602 ULONG DataSize;
603 PCI_COMMON_CONFIG PciConfig;
604 UINT Address;
605 UINT ResourceCount;
606 ULONG Size[PCI_TYPE0_ADDRESSES];
607 NTSTATUS Status = STATUS_SUCCESS;
608 UCHAR Offset;
609 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
610
611 /* FIXME: Should handle 64-bit addresses */
612
613 DataSize = HalpGetPciData(BusHandler,
614 BusNumber,
615 SlotNumber,
616 &PciConfig,
617 0,
618 PCI_COMMON_HDR_LENGTH);
619 if (PCI_COMMON_HDR_LENGTH != DataSize)
620 {
621 return STATUS_UNSUCCESSFUL;
622 }
623
624 /* Read the PCI configuration space for the device and store base address and
625 size information in temporary storage. Count the number of valid base addresses */
626 ResourceCount = 0;
627 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
628 {
629 if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address])
630 {
631 PciConfig.u.type0.BaseAddresses[Address] = 0;
632 }
633 if (0 != PciConfig.u.type0.BaseAddresses[Address])
634 {
635 ResourceCount++;
636 Offset = FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);
637 Status = WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset, 0xffffffff);
638 if (! NT_SUCCESS(Status))
639 {
640 WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset,
641 PciConfig.u.type0.BaseAddresses[Address]);
642 return Status;
643 }
644 Status = ReadPciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber,
645 Offset, Size + Address);
646 if (! NT_SUCCESS(Status))
647 {
648 WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset,
649 PciConfig.u.type0.BaseAddresses[Address]);
650 return Status;
651 }
652 Status = WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset,
653 PciConfig.u.type0.BaseAddresses[Address]);
654 if (! NT_SUCCESS(Status))
655 {
656 return Status;
657 }
658 }
659 }
660
661 if (0 != PciConfig.u.type0.InterruptLine)
662 {
663 ResourceCount++;
664 }
665
666 /* Allocate output buffer and initialize */
667 *AllocatedResources = ExAllocatePoolWithTag(PagedPool,
668 sizeof(CM_RESOURCE_LIST) +
669 (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
670 TAG_PCI);
671 if (NULL == *AllocatedResources)
672 {
673 return STATUS_NO_MEMORY;
674 }
675 (*AllocatedResources)->Count = 1;
676 (*AllocatedResources)->List[0].InterfaceType = PCIBus;
677 (*AllocatedResources)->List[0].BusNumber = BusNumber;
678 (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
679 (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
680 (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount;
681 Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
682
683 /* Store configuration information */
684 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
685 {
686 if (0 != PciConfig.u.type0.BaseAddresses[Address])
687 {
688 if (PCI_BASE_ADDRESS_SPACE_MEMORY ==
689 (PciConfig.u.type0.BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
690 {
691 Descriptor->Type = CmResourceTypeMemory;
692 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
693 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; /* FIXME Just a guess */
694 Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_BASE_ADDRESS_MEM_MASK);
695 Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_MEM_MASK);
696 }
697 else if (PCI_BASE_ADDRESS_SPACE_IO ==
698 (PciConfig.u.type0.BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
699 {
700 Descriptor->Type = CmResourceTypePort;
701 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
702 Descriptor->Flags = CM_RESOURCE_PORT_IO; /* FIXME Just a guess */
703 Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_BASE_ADDRESS_IO_MASK;
704 Descriptor->u.Port.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_IO_MASK & 0xffff);
705 }
706 else
707 {
708 ASSERT(FALSE);
709 return STATUS_UNSUCCESSFUL;
710 }
711 Descriptor++;
712 }
713 }
714
715 if (0 != PciConfig.u.type0.InterruptLine)
716 {
717 Descriptor->Type = CmResourceTypeInterrupt;
718 Descriptor->ShareDisposition = CmResourceShareShared; /* FIXME Just a guess */
719 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; /* FIXME Just a guess */
720 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
721 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
722 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
723
724 Descriptor++;
725 }
726
727 ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount);
728
729 /* FIXME: Should store the resources in the registry resource map */
730
731 return Status;
732 }
733
734
735 VOID
736 HalpInitPciBus(VOID)
737 {
738 PBUS_HANDLER BusHandler;
739
740 DPRINT("HalpInitPciBus() called.\n");
741
742 KeInitializeSpinLock (&PciLock);
743
744 BusConfigType = GetBusConfigType();
745 if (BusConfigType == 0)
746 return;
747
748 DPRINT("Bus configuration %lu used\n", BusConfigType);
749
750 /* pci bus (bus 0) handler */
751 BusHandler = HalpAllocateBusHandler(PCIBus,
752 PCIConfiguration,
753 0);
754 BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
755 BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
756 BusHandler->GetInterruptVector =
757 (pGetInterruptVector)HalpGetPciInterruptVector;
758 BusHandler->TranslateBusAddress =
759 (pTranslateBusAddress)HalpTranslatePciAddress;
760 // BusHandler->AdjustResourceList =
761 // (pGetSetBusData)HalpAdjustPciResourceList;
762 BusHandler->AssignSlotResources =
763 (pAssignSlotResources)HalpAssignPciSlotResources;
764 if (NULL != HalpHooks.InitPciBus)
765 {
766 HalpHooks.InitPciBus(0, BusHandler);
767 }
768
769
770 /* agp bus (bus 1) handler */
771 BusHandler = HalpAllocateBusHandler(PCIBus,
772 PCIConfiguration,
773 1);
774 BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
775 BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
776 BusHandler->GetInterruptVector =
777 (pGetInterruptVector)HalpGetPciInterruptVector;
778 BusHandler->TranslateBusAddress =
779 (pTranslateBusAddress)HalpTranslatePciAddress;
780 // BusHandler->AdjustResourceList =
781 // (pGetSetBusData)HalpAdjustPciResourceList;
782 BusHandler->AssignSlotResources =
783 (pAssignSlotResources)HalpAssignPciSlotResources;
784 if (NULL != HalpHooks.InitPciBus)
785 {
786 HalpHooks.InitPciBus(1, BusHandler);
787 }
788
789
790 /* PCI bus (bus 2) handler */
791 BusHandler = HalpAllocateBusHandler(PCIBus,
792 PCIConfiguration,
793 2);
794 BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
795 BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
796 BusHandler->GetInterruptVector =
797 (pGetInterruptVector)HalpGetPciInterruptVector;
798 BusHandler->TranslateBusAddress =
799 (pTranslateBusAddress)HalpTranslatePciAddress;
800 // BusHandler->AdjustResourceList =
801 // (pGetSetBusData)HalpAdjustPciResourceList;
802 BusHandler->AssignSlotResources =
803 (pAssignSlotResources)HalpAssignPciSlotResources;
804 if (NULL != HalpHooks.InitPciBus)
805 {
806 HalpHooks.InitPciBus(2, BusHandler);
807 }
808
809 DPRINT("HalpInitPciBus() finished.\n");
810 }
811
812 /* EOF */