Fixed warnings and errors so ReactOS can be compiled with GCC 3.2.
[reactos.git] / reactos / drivers / bus / pci / pci.c
1 /* $Id: pci.c,v 1.2 2002/05/05 14:57:45 chorns Exp $
2 *
3 * PROJECT: ReactOS PCI Bus driver
4 * FILE: pci.c
5 * PURPOSE: Driver entry
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * UPDATE HISTORY:
8 * 10-09-2001 CSH Created
9 */
10 #include <pci.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15
16 #ifdef ALLOC_PRAGMA
17
18 // Make the initialization routines discardable, so that they
19 // don't waste space
20
21 #pragma alloc_text(init, DriverEntry)
22
23 #endif /* ALLOC_PRAGMA */
24
25 /*** PUBLIC ******************************************************************/
26
27 PCI_BUS_TYPE PciBusConfigType = pbtUnknown;
28
29
30 /*** PRIVATE *****************************************************************/
31
32 static NTSTATUS
33 PciReadConfigUchar(UCHAR Bus,
34 UCHAR Slot,
35 UCHAR Offset,
36 PUCHAR Value)
37 {
38 switch (PciBusConfigType)
39 {
40 case pbtType1:
41 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
42 *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3));
43 return STATUS_SUCCESS;
44
45 case pbtType2:
46 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
47 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
48 *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset)));
49 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
50 return STATUS_SUCCESS;
51 }
52 return STATUS_UNSUCCESSFUL;
53 }
54
55
56 static NTSTATUS
57 PciReadConfigUshort(UCHAR Bus,
58 UCHAR Slot,
59 UCHAR Offset,
60 PUSHORT Value)
61 {
62 if ((Offset & 1) != 0)
63 {
64 return STATUS_INVALID_PARAMETER;
65 }
66
67 switch (PciBusConfigType)
68 {
69 case pbtType1:
70 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
71 *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1));
72 return STATUS_SUCCESS;
73
74 case pbtType2:
75 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
76 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
77 *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)));
78 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
79 return STATUS_SUCCESS;
80 }
81 return STATUS_UNSUCCESSFUL;
82 }
83
84
85 static NTSTATUS
86 PciReadConfigUlong(UCHAR Bus,
87 UCHAR Slot,
88 UCHAR Offset,
89 PULONG Value)
90 {
91 if ((Offset & 3) != 0)
92 {
93 return STATUS_INVALID_PARAMETER;
94 }
95
96 switch (PciBusConfigType)
97 {
98 case pbtType1:
99 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
100 *Value = READ_PORT_ULONG((PULONG)0xCFC);
101 return STATUS_SUCCESS;
102
103 case pbtType2:
104 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
105 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
106 *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)));
107 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
108 return STATUS_SUCCESS;
109 }
110 return STATUS_UNSUCCESSFUL;
111 }
112
113
114 static NTSTATUS
115 PciWriteConfigUchar(UCHAR Bus,
116 UCHAR Slot,
117 UCHAR Offset,
118 UCHAR Value)
119 {
120 switch (PciBusConfigType)
121 {
122 case pbtType1:
123 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
124 WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value);
125 return STATUS_SUCCESS;
126
127 case pbtType2:
128 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
129 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
130 WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value);
131 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
132 return STATUS_SUCCESS;
133 }
134 return STATUS_UNSUCCESSFUL;
135 }
136
137
138 static NTSTATUS
139 PciWriteConfigUshort(UCHAR Bus,
140 UCHAR Slot,
141 UCHAR Offset,
142 USHORT Value)
143 {
144 if ((Offset & 1) != 0)
145 {
146 return STATUS_INVALID_PARAMETER;
147 }
148
149 switch (PciBusConfigType)
150 {
151 case pbtType1:
152 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
153 WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1), Value);
154 return STATUS_SUCCESS;
155
156 case pbtType2:
157 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
158 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
159 WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value);
160 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
161 return STATUS_SUCCESS;
162 }
163 return STATUS_UNSUCCESSFUL;
164 }
165
166
167 static NTSTATUS
168 PciWriteConfigUlong(UCHAR Bus,
169 UCHAR Slot,
170 UCHAR Offset,
171 ULONG Value)
172 {
173 if ((Offset & 3) != 0)
174 {
175 return STATUS_INVALID_PARAMETER;
176 }
177
178 switch (PciBusConfigType)
179 {
180 case pbtType1:
181 WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
182 WRITE_PORT_ULONG((PULONG)0xCFC, Value);
183 return STATUS_SUCCESS;
184
185 case pbtType2:
186 WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
187 WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
188 WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value);
189 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
190 return STATUS_SUCCESS;
191 }
192 return STATUS_UNSUCCESSFUL;
193 }
194
195
196 ULONG
197 PciGetBusData(ULONG BusNumber,
198 ULONG SlotNumber,
199 PVOID Buffer,
200 ULONG Offset,
201 ULONG Length)
202 {
203 PVOID Ptr = Buffer;
204 ULONG Address = Offset;
205 ULONG Len = Length;
206 ULONG Vendor;
207 UCHAR HeaderType;
208
209 #if 0
210 DPRINT(" BusNumber %lu\n", BusNumber);
211 DPRINT(" SlotNumber %lu\n", SlotNumber);
212 DPRINT(" Offset 0x%lx\n", Offset);
213 DPRINT(" Length 0x%lx\n", Length);
214 #endif
215
216 if ((Length == 0) || (PciBusConfigType == 0))
217 return 0;
218
219 /* 0E=PCI_HEADER_TYPE */
220 PciReadConfigUchar(BusNumber,
221 SlotNumber & 0xF8,
222 0x0E,
223 &HeaderType);
224 if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
225 return 0;
226
227 PciReadConfigUlong(BusNumber,
228 SlotNumber,
229 0x00,
230 &Vendor);
231 /* some broken boards return 0 if a slot is empty: */
232 if (Vendor == 0xFFFFFFFF || Vendor == 0)
233 return 0;
234
235 if ((Address & 1) && (Len >= 1))
236 {
237 PciReadConfigUchar(BusNumber,
238 SlotNumber,
239 Address,
240 Ptr);
241 Ptr = Ptr + 1;
242 Address++;
243 Len--;
244 }
245
246 if ((Address & 2) && (Len >= 2))
247 {
248 PciReadConfigUshort(BusNumber,
249 SlotNumber,
250 Address,
251 Ptr);
252 Ptr = Ptr + 2;
253 Address += 2;
254 Len -= 2;
255 }
256
257 while (Len >= 4)
258 {
259 PciReadConfigUlong(BusNumber,
260 SlotNumber,
261 Address,
262 Ptr);
263 Ptr = Ptr + 4;
264 Address += 4;
265 Len -= 4;
266 }
267
268 if (Len >= 2)
269 {
270 PciReadConfigUshort(BusNumber,
271 SlotNumber,
272 Address,
273 Ptr);
274 Ptr = Ptr + 2;
275 Address += 2;
276 Len -= 2;
277 }
278
279 if (Len >= 1)
280 {
281 PciReadConfigUchar(BusNumber,
282 SlotNumber,
283 Address,
284 Ptr);
285 Ptr = Ptr + 1;
286 Address++;
287 Len--;
288 }
289
290 return Length - Len;
291 }
292
293
294 ULONG
295 PciSetBusData(ULONG BusNumber,
296 ULONG SlotNumber,
297 PVOID Buffer,
298 ULONG Offset,
299 ULONG Length)
300 {
301 PVOID Ptr = Buffer;
302 ULONG Address = Offset;
303 ULONG Len = Length;
304 ULONG Vendor;
305 UCHAR HeaderType;
306
307 #if 0
308 DPRINT(" BusNumber %lu\n", BusNumber);
309 DPRINT(" SlotNumber %lu\n", SlotNumber);
310 DPRINT(" Offset 0x%lx\n", Offset);
311 DPRINT(" Length 0x%lx\n", Length);
312 #endif
313
314 if ((Length == 0) || (PciBusConfigType == 0))
315 return 0;
316
317 /* 0E=PCI_HEADER_TYPE */
318 PciReadConfigUchar(BusNumber,
319 SlotNumber & 0xF8,
320 0x0E,
321 &HeaderType);
322 if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
323 return 0;
324
325 PciReadConfigUlong(BusNumber,
326 SlotNumber,
327 0x00,
328 &Vendor);
329 /* some broken boards return 0 if a slot is empty: */
330 if (Vendor == 0xFFFFFFFF || Vendor == 0)
331 return 0;
332
333 if ((Address & 1) && (Len >= 1))
334 {
335 PciWriteConfigUchar(BusNumber,
336 SlotNumber,
337 Address,
338 *(PUCHAR)Ptr);
339 Ptr = Ptr + 1;
340 Address++;
341 Len--;
342 }
343
344 if ((Address & 2) && (Len >= 2))
345 {
346 PciWriteConfigUshort(BusNumber,
347 SlotNumber,
348 Address,
349 *(PUSHORT)Ptr);
350 Ptr = Ptr + 2;
351 Address += 2;
352 Len -= 2;
353 }
354
355 while (Len >= 4)
356 {
357 PciWriteConfigUlong(BusNumber,
358 SlotNumber,
359 Address,
360 *(PULONG)Ptr);
361 Ptr = Ptr + 4;
362 Address += 4;
363 Len -= 4;
364 }
365
366 if (Len >= 2)
367 {
368 PciWriteConfigUshort(BusNumber,
369 SlotNumber,
370 Address,
371 *(PUSHORT)Ptr);
372 Ptr = Ptr + 2;
373 Address += 2;
374 Len -= 2;
375 }
376
377 if (Len >= 1)
378 {
379 PciWriteConfigUchar(BusNumber,
380 SlotNumber,
381 Address,
382 *(PUCHAR)Ptr);
383 Ptr = Ptr + 1;
384 Address++;
385 Len--;
386 }
387
388 return Length - Len;
389 }
390
391
392 PCI_BUS_TYPE
393 PciGetBusConfigType(VOID)
394 {
395 ULONG Value;
396
397 DPRINT("Called\n");
398
399 DPRINT("Checking configuration type 1:\n");
400 WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01);
401 Value = READ_PORT_ULONG((PULONG)0xCF8);
402 WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000);
403 if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000)
404 {
405 WRITE_PORT_ULONG((PULONG)0xCF8, Value);
406 DPRINT(" Success!\n");
407 return pbtType1;
408 }
409 WRITE_PORT_ULONG((PULONG)0xCF8, Value);
410 DPRINT(" Unsuccessful!\n");
411
412 DPRINT("Checking configuration type 2:\n");
413 WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00);
414 WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00);
415 WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00);
416 if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 &&
417 READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00)
418 {
419 DPRINT(" Success!\n");
420 return pbtType2;
421 }
422 DPRINT(" Unsuccessful!\n");
423
424 DPRINT("No pci bus found!\n");
425 return pbtUnknown;
426 }
427
428
429 NTSTATUS
430 STDCALL
431 PciDispatchDeviceControl(
432 IN PDEVICE_OBJECT DeviceObject,
433 IN PIRP Irp)
434 {
435 PIO_STACK_LOCATION IrpSp;
436 NTSTATUS Status;
437
438 DPRINT("Called. IRP is at (0x%X)\n", Irp);
439
440 Irp->IoStatus.Information = 0;
441
442 IrpSp = IoGetCurrentIrpStackLocation(Irp);
443 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
444 default:
445 DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
446 Status = STATUS_NOT_IMPLEMENTED;
447 break;
448 }
449
450 if (Status != STATUS_PENDING) {
451 Irp->IoStatus.Status = Status;
452
453 DPRINT("Completing IRP at 0x%X\n", Irp);
454
455 IoCompleteRequest(Irp, IO_NO_INCREMENT);
456 }
457
458 DPRINT("Leaving. Status 0x%X\n", Status);
459
460 return Status;
461 }
462
463
464 NTSTATUS
465 STDCALL
466 PciPnpControl(
467 IN PDEVICE_OBJECT DeviceObject,
468 IN PIRP Irp)
469 /*
470 * FUNCTION: Handle Plug and Play IRPs
471 * ARGUMENTS:
472 * DeviceObject = Pointer to PDO or FDO
473 * Irp = Pointer to IRP that should be handled
474 * RETURNS:
475 * Status
476 */
477 {
478 PCOMMON_DEVICE_EXTENSION DeviceExtension;
479 NTSTATUS Status;
480
481 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
482
483 DPRINT("IsFDO %d\n", DeviceExtension->IsFDO);
484
485 if (DeviceExtension->IsFDO) {
486 Status = FdoPnpControl(DeviceObject, Irp);
487 } else {
488 Status = PdoPnpControl(DeviceObject, Irp);
489 }
490
491 return Status;
492 }
493
494
495 NTSTATUS
496 STDCALL
497 PciPowerControl(
498 IN PDEVICE_OBJECT DeviceObject,
499 IN PIRP Irp)
500 /*
501 * FUNCTION: Handle power management IRPs
502 * ARGUMENTS:
503 * DeviceObject = Pointer to PDO or FDO
504 * Irp = Pointer to IRP that should be handled
505 * RETURNS:
506 * Status
507 */
508 {
509 PCOMMON_DEVICE_EXTENSION DeviceExtension;
510 NTSTATUS Status;
511
512 DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
513
514 if (DeviceExtension->IsFDO) {
515 Status = FdoPowerControl(DeviceObject, Irp);
516 } else {
517 Status = PdoPowerControl(DeviceObject, Irp);
518 }
519
520 return Status;
521 }
522
523
524 NTSTATUS
525 STDCALL
526 PciAddDevice(
527 IN PDRIVER_OBJECT DriverObject,
528 IN PDEVICE_OBJECT PhysicalDeviceObject)
529 {
530 PFDO_DEVICE_EXTENSION DeviceExtension;
531 PDEVICE_OBJECT Fdo;
532 NTSTATUS Status;
533
534 DPRINT("Called\n");
535
536 Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION),
537 NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
538 if (!NT_SUCCESS(Status)) {
539 DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
540 return Status;
541 }
542
543 DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
544
545 RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
546
547 DeviceExtension->Common.IsFDO = TRUE;
548
549 DeviceExtension->Ldo =
550 IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
551
552 DeviceExtension->State = dsStopped;
553
554 Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
555
556 //Fdo->Flags |= DO_POWER_PAGABLE;
557
558 DPRINT("Done AddDevice\n");
559
560 return STATUS_SUCCESS;
561 }
562
563
564 NTSTATUS
565 STDCALL
566 DriverEntry(
567 IN PDRIVER_OBJECT DriverObject,
568 IN PUNICODE_STRING RegistryPath)
569 {
570 DbgPrint("Peripheral Component Interconnect Bus Driver\n");
571
572 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH) PciDispatchDeviceControl;
573 DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH) PciPnpControl;
574 DriverObject->MajorFunction[IRP_MJ_POWER] = (PDRIVER_DISPATCH) PciPowerControl;
575 DriverObject->DriverExtension->AddDevice = PciAddDevice;
576
577 return STATUS_SUCCESS;
578 }
579
580
581 BOOLEAN
582 PciCreateUnicodeString(
583 PUNICODE_STRING Destination,
584 PWSTR Source,
585 POOL_TYPE PoolType)
586 {
587 ULONG Length;
588
589 if (!Source)
590 {
591 RtlInitUnicodeString(Destination, NULL);
592 return TRUE;
593 }
594
595 Length = (wcslen(Source) + 1) * sizeof(WCHAR);
596
597 Destination->Buffer = ExAllocatePool(PoolType, Length);
598
599 if (Destination->Buffer == NULL)
600 {
601 return FALSE;
602 }
603
604 RtlCopyMemory(Destination->Buffer, Source, Length);
605
606 Destination->MaximumLength = Length;
607
608 Destination->Length = Length - sizeof(WCHAR);
609
610 return TRUE;
611 }
612
613 /* EOF */