47cd33c88ab1f185477d9b5d31a4f6df520d44cc
[reactos.git] / reactos / hal / halx86 / include / halp.h
1 /*
2 *
3 */
4
5 #ifndef __INTERNAL_HAL_HAL_H
6 #define __INTERNAL_HAL_HAL_H
7
8 #define HAL_APC_REQUEST 0
9 #define HAL_DPC_REQUEST 1
10
11 /* CMOS Registers and Ports */
12 #define CMOS_CONTROL_PORT (PUCHAR)0x70
13 #define CMOS_DATA_PORT (PUCHAR)0x71
14 #define RTC_REGISTER_A 0x0A
15 #define RTC_REGISTER_B 0x0B
16 #define RTC_REG_A_UIP 0x80
17 #define RTC_REGISTER_CENTURY 0x32
18
19 /* Usage flags */
20 #define IDT_REGISTERED 0x01
21 #define IDT_LATCHED 0x02
22 #define IDT_INTERNAL 0x11
23 #define IDT_DEVICE 0x21
24
25 /* Conversion functions */
26 #define BCD_INT(bcd) \
27 (((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F))
28 #define INT_BCD(int) \
29 (UCHAR)(((int / 10) << 4) + (int % 10))
30
31 //
32 // Commonly stated as being 1.19318MHz
33 //
34 // See ISA System Architecture 3rd Edition (Tom Shanley, Don Anderson, John Swindle)
35 // P. 471
36 //
37 // However, the true value is closer to 1.19318181[...]81MHz since this is 1/3rd
38 // of the NTSC color subcarrier frequency which runs at 3.57954545[...]45MHz.
39 //
40 // Note that Windows uses 1.193167MHz which seems to have no basis. However, if
41 // one takes the NTSC color subcarrier frequency as being 3.579545 (trimming the
42 // infinite series) and divides it by three, one obtains 1.19318167.
43 //
44 // It may be that the original NT HAL source code introduced a typo and turned
45 // 119318167 into 1193167 by ommitting the "18". This is very plausible as the
46 // number is quite long.
47 //
48 #define PIT_FREQUENCY 1193182
49
50 //
51 // These ports are controlled by the i8254 Programmable Interrupt Timer (PIT)
52 //
53 #define TIMER_CHANNEL0_DATA_PORT 0x40
54 #define TIMER_CHANNEL1_DATA_PORT 0x41
55 #define TIMER_CHANNEL2_DATA_PORT 0x42
56 #define TIMER_CONTROL_PORT 0x43
57
58 //
59 // Mode 0 - Interrupt On Terminal Count
60 // Mode 1 - Hardware Re-triggerable One-Shot
61 // Mode 2 - Rate Generator
62 // Mode 3 - Square Wave Generator
63 // Mode 4 - Software Triggered Strobe
64 // Mode 5 - Hardware Triggered Strobe
65 //
66 typedef enum _TIMER_OPERATING_MODES
67 {
68 PitOperatingMode0,
69 PitOperatingMode1,
70 PitOperatingMode2,
71 PitOperatingMode3,
72 PitOperatingMode4,
73 PitOperatingMode5,
74 PitOperatingMode2Reserved,
75 PitOperatingMode5Reserved
76 } TIMER_OPERATING_MODES;
77
78 typedef enum _TIMER_ACCESS_MODES
79 {
80 PitAccessModeCounterLatch,
81 PitAccessModeLow,
82 PitAccessModeHigh,
83 PitAccessModeLowHigh
84 } TIMER_ACCESS_MODES;
85
86 typedef enum _TIMER_CHANNELS
87 {
88 PitChannel0,
89 PitChannel1,
90 PitChannel2,
91 PitReadBack
92 } TIMER_CHANNELS;
93
94 typedef union _TIMER_CONTROL_PORT_REGISTER
95 {
96 struct
97 {
98 UCHAR BcdMode:1;
99 TIMER_OPERATING_MODES OperatingMode:3;
100 TIMER_ACCESS_MODES AccessMode:2;
101 TIMER_CHANNELS Channel:2;
102 };
103 UCHAR Bits;
104 } TIMER_CONTROL_PORT_REGISTER, *PTIMER_CONTROL_PORT_REGISTER;
105
106 //
107 // See ISA System Architecture 3rd Edition (Tom Shanley, Don Anderson, John Swindle)
108 // P. 400
109 //
110 // This port is controled by the i8255 Programmable Peripheral Interface (PPI)
111 //
112 #define SYSTEM_CONTROL_PORT_A 0x92
113 #define SYSTEM_CONTROL_PORT_B 0x61
114 typedef union _SYSTEM_CONTROL_PORT_B_REGISTER
115 {
116 struct
117 {
118 UCHAR Timer2GateToSpeaker:1;
119 UCHAR SpeakerDataEnable:1;
120 UCHAR ParityCheckEnable:1;
121 UCHAR ChannelCheckEnable:1;
122 UCHAR RefreshRequest:1;
123 UCHAR Timer2Output:1;
124 UCHAR ChannelCheck:1;
125 UCHAR ParityCheck:1;
126 };
127 UCHAR Bits;
128 } SYSTEM_CONTROL_PORT_B_REGISTER, *PSYSTEM_CONTROL_PORT_B_REGISTER;
129
130 //
131 // See ISA System Architecture 3rd Edition (Tom Shanley, Don Anderson, John Swindle)
132 // P. 396, 397
133 //
134 // These ports are controlled by the i8259 Programmable Interrupt Controller (PIC)
135 //
136 #define PIC1_CONTROL_PORT 0x20
137 #define PIC1_DATA_PORT 0x21
138 #define PIC2_CONTROL_PORT 0xA0
139 #define PIC2_DATA_PORT 0xA1
140
141 //
142 // Definitions for ICW/OCW Bits
143 //
144 typedef enum _I8259_ICW1_OPERATING_MODE
145 {
146 Cascade,
147 Single
148 } I8259_ICW1_OPERATING_MODE;
149
150 typedef enum _I8259_ICW1_INTERRUPT_MODE
151 {
152 EdgeTriggered,
153 LevelTriggered
154 } I8259_ICW1_INTERRUPT_MODE;
155
156 typedef enum _I8259_ICW1_INTERVAL
157 {
158 Interval8,
159 Interval4
160 } I8259_ICW1_INTERVAL;
161
162 typedef enum _I8259_ICW4_SYSTEM_MODE
163 {
164 Mcs8085Mode,
165 New8086Mode
166 } I8259_ICW4_SYSTEM_MODE;
167
168 typedef enum _I8259_ICW4_EOI_MODE
169 {
170 NormalEoi,
171 AutomaticEoi
172 } I8259_ICW4_EOI_MODE;
173
174 typedef enum _I8259_ICW4_BUFFERED_MODE
175 {
176 NonBuffered,
177 NonBuffered2,
178 BufferedSlave,
179 BufferedMaster
180 } I8259_ICW4_BUFFERED_MODE;
181
182 typedef enum _I8259_READ_REQUEST
183 {
184 InvalidRequest,
185 InvalidRequest2,
186 ReadIdr,
187 ReadIsr
188 } I8259_READ_REQUEST;
189
190 typedef enum _I8259_EOI_MODE
191 {
192 RotateAutoEoiClear,
193 NonSpecificEoi,
194 InvalidEoiMode,
195 SpecificEoi,
196 RotateAutoEoiSet,
197 RotateNonSpecific,
198 SetPriority,
199 RotateSpecific
200 } I8259_EOI_MODE;
201
202 //
203 // Definitions for ICW Registers
204 //
205 typedef union _I8259_ICW1
206 {
207 struct
208 {
209 UCHAR NeedIcw4:1;
210 I8259_ICW1_OPERATING_MODE OperatingMode:1;
211 I8259_ICW1_INTERVAL Interval:1;
212 I8259_ICW1_INTERRUPT_MODE InterruptMode:1;
213 UCHAR Init:1;
214 UCHAR InterruptVectorAddress:3;
215 };
216 UCHAR Bits;
217 } I8259_ICW1, *PI8259_ICW1;
218
219 typedef union _I8259_ICW2
220 {
221 struct
222 {
223 UCHAR Sbz:3;
224 UCHAR InterruptVector:5;
225 };
226 UCHAR Bits;
227 } I8259_ICW2, *PI8259_ICW2;
228
229 typedef union _I8259_ICW3
230 {
231 union
232 {
233 struct
234 {
235 UCHAR SlaveIrq0:1;
236 UCHAR SlaveIrq1:1;
237 UCHAR SlaveIrq2:1;
238 UCHAR SlaveIrq3:1;
239 UCHAR SlaveIrq4:1;
240 UCHAR SlaveIrq5:1;
241 UCHAR SlaveIrq6:1;
242 UCHAR SlaveIrq7:1;
243 };
244 struct
245 {
246 UCHAR SlaveId:3;
247 UCHAR Reserved:5;
248 };
249 };
250 UCHAR Bits;
251 } I8259_ICW3, *PI8259_ICW3;
252
253 typedef union _I8259_ICW4
254 {
255 struct
256 {
257 I8259_ICW4_SYSTEM_MODE SystemMode:1;
258 I8259_ICW4_EOI_MODE EoiMode:1;
259 I8259_ICW4_BUFFERED_MODE BufferedMode:2;
260 UCHAR SpecialFullyNestedMode:1;
261 UCHAR Reserved:3;
262 };
263 UCHAR Bits;
264 } I8259_ICW4, *PI8259_ICW4;
265
266 typedef union _I8259_OCW2
267 {
268 struct
269 {
270 UCHAR IrqNumber:3;
271 UCHAR Sbz:2;
272 I8259_EOI_MODE EoiMode:3;
273 };
274 UCHAR Bits;
275 } I8259_OCW2, *PI8259_OCW2;
276
277 typedef union _I8259_OCW3
278 {
279 struct
280 {
281 I8259_READ_REQUEST ReadRequest:2;
282 UCHAR PollCommand:1;
283 UCHAR Sbo:1;
284 UCHAR Sbz:1;
285 UCHAR SpecialMaskMode:2;
286 UCHAR Reserved:1;
287 };
288 UCHAR Bits;
289 } I8259_OCW3, *PI8259_OCW3;
290
291 typedef union _I8259_ISR
292 {
293 union
294 {
295 struct
296 {
297 UCHAR Irq0:1;
298 UCHAR Irq1:1;
299 UCHAR Irq2:1;
300 UCHAR Irq3:1;
301 UCHAR Irq4:1;
302 UCHAR Irq5:1;
303 UCHAR Irq6:1;
304 UCHAR Irq7:1;
305 };
306 };
307 UCHAR Bits;
308 } I8259_ISR, *PI8259_ISR;
309
310 typedef I8259_ISR I8259_IDR, *PI8259_IDR;
311
312 //
313 // See EISA System Architecture 2nd Edition (Tom Shanley, Don Anderson, John Swindle)
314 // P. 34, 35
315 //
316 // These ports are controlled by the i8259A Programmable Interrupt Controller (PIC)
317 //
318 #define EISA_ELCR_MASTER 0x4D0
319 #define EISA_ELCR_SLAVE 0x4D1
320
321 typedef union _EISA_ELCR
322 {
323 struct
324 {
325 struct
326 {
327 UCHAR Irq0Level:1;
328 UCHAR Irq1Level:1;
329 UCHAR Irq2Level:1;
330 UCHAR Irq3Level:1;
331 UCHAR Irq4Level:1;
332 UCHAR Irq5Level:1;
333 UCHAR Irq6Level:1;
334 UCHAR Irq7Level:1;
335 } Master;
336 struct
337 {
338 UCHAR Irq8Level:1;
339 UCHAR Irq9Level:1;
340 UCHAR Irq10Level:1;
341 UCHAR Irq11Level:1;
342 UCHAR Irq12Level:1;
343 UCHAR Irq13Level:1;
344 UCHAR Irq14Level:1;
345 UCHAR Irq15Level:1;
346 } Slave;
347 };
348 USHORT Bits;
349 } EISA_ELCR, *PEISA_ELCR;
350
351 typedef struct _PIC_MASK
352 {
353 union
354 {
355 struct
356 {
357 UCHAR Master;
358 UCHAR Slave;
359 };
360 USHORT Both;
361 };
362 } PIC_MASK, *PPIC_MASK;
363
364 typedef
365 VOID
366 (*PHAL_SW_INTERRUPT_HANDLER)(
367 VOID
368 );
369
370 typedef
371 BOOLEAN
372 __attribute__((regparm(3)))
373 (*PHAL_DISMISS_INTERRUPT)(
374 IN KIRQL Irql,
375 IN ULONG Irq,
376 OUT PKIRQL OldIrql
377 );
378
379 BOOLEAN
380 __attribute__((regparm(3)))
381 HalpDismissIrqGeneric(
382 IN KIRQL Irql,
383 IN ULONG Irq,
384 OUT PKIRQL OldIrql
385 );
386
387 BOOLEAN
388 __attribute__((regparm(3)))
389 HalpDismissIrq15(
390 IN KIRQL Irql,
391 IN ULONG Irq,
392 OUT PKIRQL OldIrql
393 );
394
395 BOOLEAN
396 __attribute__((regparm(3)))
397 HalpDismissIrq13(
398 IN KIRQL Irql,
399 IN ULONG Irq,
400 OUT PKIRQL OldIrql
401 );
402
403 BOOLEAN
404 __attribute__((regparm(3)))
405 HalpDismissIrq07(
406 IN KIRQL Irql,
407 IN ULONG Irq,
408 OUT PKIRQL OldIrql
409 );
410
411 //
412 // Mm PTE/PDE to Hal PTE/PDE
413 //
414 #define HalAddressToPde(x) (PHARDWARE_PTE)MiAddressToPde(x)
415 #define HalAddressToPte(x) (PHARDWARE_PTE)MiAddressToPte(x)
416
417 typedef struct _IDTUsageFlags
418 {
419 UCHAR Flags;
420 } IDTUsageFlags;
421
422 typedef struct
423 {
424 KIRQL Irql;
425 UCHAR BusReleativeVector;
426 } IDTUsage;
427
428 typedef struct _HalAddressUsage
429 {
430 struct _HalAddressUsage *Next;
431 CM_RESOURCE_TYPE Type;
432 UCHAR Flags;
433 struct
434 {
435 ULONG Start;
436 ULONG Length;
437 } Element[];
438 } ADDRESS_USAGE, *PADDRESS_USAGE;
439
440 /* adapter.c */
441 PADAPTER_OBJECT NTAPI HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN IsMaster, BOOLEAN Dma32BitAddresses);
442
443 /* sysinfo.c */
444 VOID
445 NTAPI
446 HalpRegisterVector(IN UCHAR Flags,
447 IN ULONG BusVector,
448 IN ULONG SystemVector,
449 IN KIRQL Irql);
450
451 VOID
452 NTAPI
453 HalpEnableInterruptHandler(IN UCHAR Flags,
454 IN ULONG BusVector,
455 IN ULONG SystemVector,
456 IN KIRQL Irql,
457 IN PVOID Handler,
458 IN KINTERRUPT_MODE Mode);
459
460 /* pic.c */
461 VOID NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts);
462 VOID HalpApcInterrupt(VOID);
463 VOID HalpDispatchInterrupt(VOID);
464
465 /* udelay.c */
466 VOID NTAPI HalpInitializeClock(VOID);
467
468 VOID
469 NTAPI
470 HalpCalibrateStallExecution(VOID);
471
472 /* pci.c */
473 VOID HalpInitPciBus (VOID);
474
475 /* dma.c */
476 VOID HalpInitDma (VOID);
477
478 /* Non-generic initialization */
479 VOID HalpInitPhase0 (PLOADER_PARAMETER_BLOCK LoaderBlock);
480 VOID HalpInitPhase1(VOID);
481 VOID NTAPI HalpClockInterrupt(VOID);
482 VOID NTAPI HalpProfileInterrupt(VOID);
483
484 VOID
485 NTAPI
486 HalpFlushTLB(VOID);
487
488 //
489 // KD Support
490 //
491 VOID
492 NTAPI
493 HalpCheckPowerButton(
494 VOID
495 );
496
497 VOID
498 NTAPI
499 HalpRegisterKdSupportFunctions(
500 VOID
501 );
502
503 NTSTATUS
504 NTAPI
505 HalpSetupPciDeviceForDebugging(
506 IN PVOID LoaderBlock,
507 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
508 );
509
510 NTSTATUS
511 NTAPI
512 HalpReleasePciDeviceForDebugging(
513 IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
514 );
515
516 //
517 // Memory routines
518 //
519 PVOID
520 NTAPI
521 HalpMapPhysicalMemory64(
522 IN PHYSICAL_ADDRESS PhysicalAddress,
523 IN ULONG NumberPage
524 );
525
526 VOID
527 NTAPI
528 HalpUnmapVirtualAddress(
529 IN PVOID VirtualAddress,
530 IN ULONG NumberPages
531 );
532
533 /* sysinfo.c */
534 NTSTATUS
535 NTAPI
536 HaliQuerySystemInformation(
537 IN HAL_QUERY_INFORMATION_CLASS InformationClass,
538 IN ULONG BufferSize,
539 IN OUT PVOID Buffer,
540 OUT PULONG ReturnedLength
541 );
542
543 NTSTATUS
544 NTAPI
545 HaliSetSystemInformation(
546 IN HAL_SET_INFORMATION_CLASS InformationClass,
547 IN ULONG BufferSize,
548 IN OUT PVOID Buffer
549 );
550
551 //
552 // BIOS Routines
553 //
554 BOOLEAN
555 NTAPI
556 HalpBiosDisplayReset(
557 VOID
558 );
559
560 VOID
561 NTAPI
562 HalpBiosCall(
563 VOID
564 );
565
566 VOID
567 NTAPI
568 HalpTrap0D(
569 VOID
570 );
571
572 VOID
573 NTAPI
574 HalpTrap06(
575 VOID
576 );
577
578 //
579 // Processor Halt Routine
580 //
581 VOID
582 NTAPI
583 HaliHaltSystem(
584 VOID
585 );
586
587 //
588 // CMOS initialization
589 //
590 VOID
591 NTAPI
592 HalpInitializeCmos(
593 VOID
594 );
595
596 //
597 // Spinlock for protecting CMOS access
598 //
599 VOID
600 NTAPI
601 HalpAcquireSystemHardwareSpinLock(
602 VOID
603 );
604
605 VOID
606 NTAPI
607 HalpReleaseCmosSpinLock(
608 VOID
609 );
610
611 //
612 // This is duplicated from ke_x.h
613 //
614 #ifdef CONFIG_SMP
615 //
616 // Spinlock Acquisition at IRQL >= DISPATCH_LEVEL
617 //
618 FORCEINLINE
619 VOID
620 KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
621 {
622 /* Make sure that we don't own the lock already */
623 if (((KSPIN_LOCK)KeGetCurrentThread() | 1) == *SpinLock)
624 {
625 /* We do, bugcheck! */
626 KeBugCheckEx(SPIN_LOCK_ALREADY_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
627 }
628
629 for (;;)
630 {
631 /* Try to acquire it */
632 if (InterlockedBitTestAndSet((PLONG)SpinLock, 0))
633 {
634 /* Value changed... wait until it's locked */
635 while (*(volatile KSPIN_LOCK *)SpinLock == 1)
636 {
637 #ifdef DBG
638 /* On debug builds, we use a much slower but useful routine */
639 //Kii386SpinOnSpinLock(SpinLock, 5);
640
641 /* FIXME: Do normal yield for now */
642 YieldProcessor();
643 #else
644 /* Otherwise, just yield and keep looping */
645 YieldProcessor();
646 #endif
647 }
648 }
649 else
650 {
651 #ifdef DBG
652 /* On debug builds, we OR in the KTHREAD */
653 *SpinLock = (KSPIN_LOCK)KeGetCurrentThread() | 1;
654 #endif
655 /* All is well, break out */
656 break;
657 }
658 }
659 }
660
661 //
662 // Spinlock Release at IRQL >= DISPATCH_LEVEL
663 //
664 FORCEINLINE
665 VOID
666 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
667 {
668 #ifdef DBG
669 /* Make sure that the threads match */
670 if (((KSPIN_LOCK)KeGetCurrentThread() | 1) != *SpinLock)
671 {
672 /* They don't, bugcheck */
673 KeBugCheckEx(SPIN_LOCK_NOT_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
674 }
675 #endif
676 /* Clear the lock */
677 InterlockedAnd((PLONG)SpinLock, 0);
678 }
679
680 #else
681
682 //
683 // Spinlock Acquire at IRQL >= DISPATCH_LEVEL
684 //
685 FORCEINLINE
686 VOID
687 KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
688 {
689 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
690 UNREFERENCED_PARAMETER(SpinLock);
691 }
692
693 //
694 // Spinlock Release at IRQL >= DISPATCH_LEVEL
695 //
696 FORCEINLINE
697 VOID
698 KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
699 {
700 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
701 UNREFERENCED_PARAMETER(SpinLock);
702 }
703
704 #endif
705
706 #ifdef _M_AMD64
707 #define KfLowerIrql KeLowerIrql
708 #ifndef CONFIG_SMP
709 /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
710 #define KiAcquireSpinLock(SpinLock)
711 #define KiReleaseSpinLock(SpinLock)
712 #define KfAcquireSpinLock(SpinLock) KfRaiseIrql(DISPATCH_LEVEL);
713 #define KfReleaseSpinLock(SpinLock, OldIrql) KeLowerIrql(OldIrql);
714 #endif // !CONFIG_SMP
715 #endif // _M_AMD64
716
717 extern BOOLEAN HalpNMIInProgress;
718
719 extern PVOID HalpRealModeStart;
720 extern PVOID HalpRealModeEnd;
721
722 extern ADDRESS_USAGE HalpDefaultIoSpace;
723
724 extern KSPIN_LOCK HalpSystemHardwareLock;
725
726 extern PADDRESS_USAGE HalpAddressUsageList;
727
728 #endif /* __INTERNAL_HAL_HAL_H */