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