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