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