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