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