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