Subversion Repositories Kolibri OS

Rev

Rev 9958 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2288 clevermous 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
9715 Doczom 3
;; Copyright (C) KolibriOS team 2004-2022. All rights reserved. ;;
2288 clevermous 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
4850 mario79 8
$Revision: 9977 $
2288 clevermous 9
 
7733 dunkaist 10
MAX_IOAPICS = 2
4850 mario79 11
 
2288 clevermous 12
uglobal
7733 dunkaist 13
IRQ_COUNT    rd  MAX_IOAPICS
14
irq_mode     rd  1              ; PIC/(IO)APIC
15
IOAPIC_base  rd  MAX_IOAPICS
16
ioapic_gsi_base rd MAX_IOAPICS  ; zero-based, i.e. not vector
17
ioapic_cnt   dd  ?              ; from MADT aka APIC table
18
ioapic_cur   dd  ?
2288 clevermous 19
LAPIC_BASE   rd  1
20
endg
21
 
7136 dunkaist 22
APIC_ID         = 0x20
23
APIC_TPR        = 0x80
24
APIC_EOI        = 0xb0
25
APIC_LDR        = 0xd0
26
APIC_DFR        = 0xe0
27
APIC_SVR        = 0xf0
28
APIC_ISR        = 0x100
29
APIC_ESR        = 0x280
30
APIC_ICRL       = 0x300
31
APIC_ICRH       = 0x310
32
APIC_LVT_LINT0  = 0x350
33
APIC_LVT_LINT1  = 0x360
34
APIC_LVT_err    = 0x370
2288 clevermous 35
 
36
; APIC timer
7136 dunkaist 37
APIC_LVT_timer  = 0x320
38
APIC_timer_div  = 0x3e0
39
APIC_timer_init = 0x380
40
APIC_timer_cur  = 0x390
2288 clevermous 41
; IOAPIC
7136 dunkaist 42
IOAPIC_ID       = 0x0
43
IOAPIC_VER      = 0x1
44
IOAPIC_ARB      = 0x2
45
IOAPIC_REDTBL   = 0x10
2288 clevermous 46
 
47
align 4
48
APIC_init:
7733 dunkaist 49
        push    ebx
2288 clevermous 50
        mov     [irq_mode], IRQ_PIC
51
 
52
        cmp     [acpi_ioapic_base], 0
53
        jz      .no_apic
54
 
55
        cmp     [acpi_lapic_base], 0
56
        jz      .no_apic
57
 
9958 dunkaist 58
; non-UEFI loaders don't load DEVICES.DAT but they zero out [acpi_dev_size]
8092 dunkaist 59
        cmp     [acpi_dev_size], 0
60
        jz      @f
61
        stdcall map_io_mem, [acpi_dev_data], [acpi_dev_size], PG_SWR
62
        mov     [acpi_dev_data], eax
63
        jmp     .loaded
64
@@:
65
 
2288 clevermous 66
        stdcall load_file, dev_data_path
67
        test    eax, eax
68
        jz      .no_apic
69
 
70
        mov     [acpi_dev_data], eax
71
        mov     [acpi_dev_size], ebx
8092 dunkaist 72
.loaded:
2288 clevermous 73
 
74
; IOAPIC init
7733 dunkaist 75
        xor     ebx, ebx
76
@@:
9715 Doczom 77
        stdcall map_io_mem, [acpi_ioapic_base + ebx*4], 0x20, PG_GLOBAL + PG_NOCACHE + PG_SWR
78
        mov     [IOAPIC_base + ebx*4], eax
7733 dunkaist 79
        inc     ebx
80
        cmp     ebx, [ioapic_cnt]
81
        jnz     @b
2288 clevermous 82
 
7733 dunkaist 83
        call    IRQ_mask_all
84
        mov     [ioapic_cur], 0
85
.next_ioapic:
86
        mov     edx, [ioapic_cur]
2288 clevermous 87
        mov     eax, IOAPIC_VER
88
        call    IOAPIC_read
89
        shr     eax, 16
90
        inc     al
91
        movzx   eax, al
9715 Doczom 92
        mov     ecx, [ioapic_gsi_base + edx*4]
7733 dunkaist 93
        cmp     ecx, IRQ_RESERVED
94
        jae     .lapic_init
95
        add     ecx, eax
96
        sub     ecx, IRQ_RESERVED
2288 clevermous 97
        jbe     @f
7733 dunkaist 98
        sub     eax, ecx
2288 clevermous 99
@@:
9715 Doczom 100
        mov     [IRQ_COUNT + edx*4], eax
2288 clevermous 101
 
102
        ; Reroute IOAPIC & mask all interrupts
103
        xor     ecx, ecx
104
        mov     eax, IOAPIC_REDTBL
7733 dunkaist 105
.next_irq:
2288 clevermous 106
        mov     ebx, eax
107
        call    IOAPIC_read
3751 Serge 108
        mov     ah, 0x08; Delivery Mode: Fixed, Destination Mode: Logical
2288 clevermous 109
        mov     al, cl
110
        add     al, 0x20; vector
9715 Doczom 111
        add     eax, [ioapic_gsi_base + edx*4]
7733 dunkaist 112
        or      eax, 0x1a000; Mask Interrupt, level-triggered active-low
113
        cmp     [ioapic_cur], 0
114
        jnz     @f
2288 clevermous 115
        cmp     ecx, 16
7733 dunkaist 116
        jae     @f
117
        and     eax, NOT 0xa000 ; edge-triggered active-high for IRQ0-15
118
@@:
2288 clevermous 119
        xchg    eax, ebx
120
        call    IOAPIC_write
121
        inc     eax
122
        mov     ebx, eax
123
        call    IOAPIC_read
124
        or      eax, 0xff000000; Destination Field
125
        xchg    eax, ebx
126
        call    IOAPIC_write
127
        inc     eax
128
        inc     ecx
9715 Doczom 129
        cmp     ecx, [IRQ_COUNT + edx*4]
7733 dunkaist 130
        jb      .next_irq
2288 clevermous 131
 
7733 dunkaist 132
        inc     [ioapic_cur]
133
        inc     edx
134
        cmp     edx, [ioapic_cnt]
135
        jnz     .next_ioapic
136
 
137
.lapic_init:
2288 clevermous 138
        call    LAPIC_init
139
 
140
        mov     [irq_mode], IRQ_APIC
141
 
142
        mov     al, 0x70
143
        out     0x22, al
144
        mov     al, 1
145
        out     0x23, al
146
 
147
        call    pci_irq_fixup
148
.no_apic:
7733 dunkaist 149
        pop     ebx
2288 clevermous 150
        ret
151
 
152
;===========================================================
153
align 4
154
LAPIC_init:
155
 
8120 dunkaist 156
        mov     eax, [LAPIC_BASE]
157
        test    eax, eax
158
        jnz     @f
9715 Doczom 159
        stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_GLOBAL + PG_NOCACHE + PG_SWR
2288 clevermous 160
        mov     [LAPIC_BASE], eax
8120 dunkaist 161
@@:
2288 clevermous 162
        mov     esi, eax
163
 
164
        ; Program Destination Format Register for Flat mode.
165
        mov     eax, [esi + APIC_DFR]
166
        or      eax, 0xf0000000
167
        mov     [esi + APIC_DFR], eax
168
 
169
        ; Program Logical Destination Register.
170
        mov     eax, [esi + APIC_LDR]
171
        ;and  eax, 0xff000000
172
        and     eax, 0x00ffffff
173
        or      eax, 0x01000000;!!!!!!!!!!!!
174
        mov     [esi + APIC_LDR], eax
175
 
176
        ; Task Priority Register initialization.
177
        mov     eax, [esi + APIC_TPR]
178
        and     eax, 0xffffff00
179
        mov     [esi + APIC_TPR], eax
180
 
181
        ; Flush the queue
9977 rgimad 182
        xor     edx, edx
2288 clevermous 183
.nxt2:
184
        mov     ecx, 32
185
        mov     eax, [esi + APIC_ISR + edx]
186
.nxt:
187
        shr     eax, 1
188
        jnc     @f
189
        mov     dword [esi + APIC_EOI], 0; EOI
190
@@:
191
        loop    .nxt
192
 
193
        add     edx, 0x10
194
        cmp     edx, 0x170
195
        jbe     .nxt2
196
 
197
        ; Spurious-Interrupt Vector Register initialization.
198
        mov     eax, [esi + APIC_SVR]
199
        or      eax, 0x1ff
200
        and     eax, 0xfffffdff
201
        mov     [esi + APIC_SVR], eax
202
 
203
        ; Initialize LVT LINT0 register. (INTR)
204
        mov     eax, 0x00700
205
        ; mov eax, 0x10700
206
        mov     [esi + APIC_LVT_LINT0], eax
207
 
208
        ; Initialize LVT LINT1 register. (NMI)
209
        mov     eax, 0x00400
210
        mov     [esi + APIC_LVT_LINT1], eax
211
 
212
        ; Initialize LVT Error register.
213
        mov     eax, [esi + APIC_LVT_err]
214
        or      eax, 0x10000; bit 16
215
        mov     [esi + APIC_LVT_err], eax
216
 
217
        ; LAPIC timer
218
        ; pre init
219
        mov     dword[esi + APIC_timer_div], 1011b; 1
220
        mov     dword[esi + APIC_timer_init], 0xffffffff; max val
221
        push    esi
222
        mov     esi, 640    ; wait 0.64 sec
223
        call    delay_ms
224
        pop     esi
225
        mov     eax, [esi + APIC_timer_cur]; read current tick couner
226
        xor     eax, 0xffffffff   ; eax = 0xffffffff - eax
227
        shr     eax, 6      ; eax /= 64; APIC ticks per 0.01 sec
228
 
229
        ; Start (every 0.01 sec)
230
        mov     dword[esi + APIC_LVT_timer], 0x30020; periodic int 0x20
231
        mov     dword[esi + APIC_timer_init], eax
2443 Serge 232
 
233
.done:
2288 clevermous 234
        ret
235
 
236
;===========================================================
237
; IOAPIC implementation
238
align 4
239
IOAPIC_read:
240
; in : EAX - IOAPIC register
241
; out: EAX - readed value
242
        push    esi
7733 dunkaist 243
        mov     esi, [ioapic_cur]
9715 Doczom 244
        mov     esi, [IOAPIC_base + esi*4]
2288 clevermous 245
        mov     [esi], eax
246
        mov     eax, [esi + 0x10]
247
        pop     esi
248
        ret
249
 
250
align 4
251
IOAPIC_write:
252
; in :  EAX - IOAPIC register
253
;       EBX - value
254
; out:  none
255
        push    esi
7733 dunkaist 256
        mov     esi, [ioapic_cur]
9715 Doczom 257
        mov     esi, [IOAPIC_base + esi*4]
2288 clevermous 258
        mov     [esi], eax
259
        mov     [esi + 0x10], ebx
260
        pop     esi
261
        ret
262
;===========================================================
263
; Remap all IRQ to 0x20+ Vectors
264
; IRQ0 to vector 0x20, IRQ1 to vector 0x21....
265
align 4
266
PIC_init:
7733 dunkaist 267
        mov     [IRQ_COUNT], 16
2288 clevermous 268
        cli
269
        mov     al, 0x11        ;  icw4, edge triggered
270
        out     0x20, al
271
        out     0xA0, al
272
 
273
        mov     al, 0x20        ;  generate 0x20 +
274
        out     0x21, al
275
        mov     al, 0x28        ;  generate 0x28 +
276
        out     0xA1, al
277
 
278
        mov     al, 0x04        ;  slave at irq2
279
        out     0x21, al
280
        mov     al, 0x02        ;  at irq9
281
        out     0xA1, al
282
 
283
        mov     al, 0x01        ;  8086 mode
284
        out     0x21, al
285
        out     0xA1, al
286
 
287
        call    IRQ_mask_all
288
        ret
289
 
290
; -----------------------------------------
291
; TIMER SET TO 1/100 S
292
align 4
293
PIT_init:
294
        mov     al, 0x34   ; set to 100Hz
295
        out     0x43, al
296
        mov     al, 0x9b   ; lsb    1193180 / 1193
297
        out     0x40, al
298
        mov     al, 0x2e   ; msb
299
        out     0x40, al
300
        ret
301
 
302
; -----------------------------------------
303
align 4
304
unmask_timer:
305
        cmp     [irq_mode], IRQ_APIC
306
        je      @f
307
 
308
        stdcall enable_irq, 0
309
        ret
310
@@:
311
        ; use PIT
312
        ; in some systems PIT no connected to IOAPIC
313
        ; mov   eax, 0x14
314
        ; call  IOAPIC_read
315
        ; mov   ah, 0x09                ; Delivery Mode: Lowest Priority, Destination Mode: Logical
316
        ; mov   al, 0x20
317
        ; or    eax, 0x10000            ; Mask Interrupt
318
        ; mov   ebx, eax
319
        ; mov   eax, 0x14
320
        ; call  IOAPIC_write
321
        ; stdcall enable_irq, 2
322
        ; ret
323
 
324
        ; use LAPIC timer
325
        mov     esi, [LAPIC_BASE]
326
        mov     eax, [esi + APIC_LVT_timer]
327
        and     eax, 0xfffeffff
328
        mov     [esi + APIC_LVT_timer], eax
329
        ret
330
 
331
; -----------------------------------------
332
; Disable all IRQ
333
align 4
334
IRQ_mask_all:
335
        cmp     [irq_mode], IRQ_APIC
336
        je      .APIC
337
 
338
        mov     al, 0xFF
339
        out     0x21, al
340
        out     0xA1, al
341
        mov     ecx, 0x1000
342
        ret
343
.APIC:
7733 dunkaist 344
        cmp     [IOAPIC_base], 0
345
        jz      .done
346
        mov     [ioapic_cur], 0
347
.next_ioapic:
348
        mov     edx, [ioapic_cur]
9715 Doczom 349
        mov     ecx, [IRQ_COUNT + edx*4]
2288 clevermous 350
        mov     eax, 0x10
351
@@:
352
        mov     ebx, eax
353
        call    IOAPIC_read
354
        or      eax, 0x10000; bit 16
355
        xchg    eax, ebx
356
        call    IOAPIC_write
357
        inc     eax
358
        inc     eax
359
        loop    @b
7733 dunkaist 360
 
361
        inc     [ioapic_cur]
362
        inc     edx
363
        cmp     edx, [ioapic_cnt]
364
        jnz     .next_ioapic
365
.done:
2288 clevermous 366
        ret
367
 
368
; -----------------------------------------
369
; End Of Interrupt
370
; cl - IRQ number
371
align 4
372
irq_eoi:         ; __fastcall
373
        cmp     [irq_mode], IRQ_APIC
374
        je      .APIC
375
 
376
        cmp     cl, 8
377
        mov     al, 0x20
378
        jb      @f
379
        out     0xa0, al
380
@@:
381
        out     0x20, al
382
        ret
383
 
384
.APIC:
385
        mov     eax, [LAPIC_BASE]
386
        mov     dword [eax + APIC_EOI], 0; EOI
387
        ret
388
 
389
; -----------------------------------------
390
; from dll.inc
391
align 4
392
proc enable_irq stdcall, irq_line:dword
393
        mov     ebx, [irq_line]
394
        cmp     [irq_mode], IRQ_APIC
395
        je      .APIC
396
 
397
        mov     edx, 0x21
398
        cmp     ebx, 8
399
        jb      @F
400
 
401
        mov     edx, 0xA1
402
        sub     ebx, 8
403
@@:
404
        in      al, dx
405
        btr     eax, ebx
406
        out     dx, al
407
        ret
408
.APIC:
7733 dunkaist 409
        push    [ioapic_cur]
410
        xor     eax, eax
411
.next_ioapic:
412
        mov     ecx, [ioapic_gsi_base+eax*4]
413
        add     ecx, [IRQ_COUNT+eax*4]
414
        cmp     ebx, ecx
415
        jb      .found
416
        inc     eax
417
        cmp     eax, [ioapic_cnt]
418
        jnz     .next_ioapic
419
        jmp     .done
420
.found:
421
        mov     [ioapic_cur], eax
422
        sub     ebx, [ioapic_gsi_base+eax*4]
2288 clevermous 423
        shl     ebx, 1
424
        add     ebx, 0x10
425
        mov     eax, ebx
426
        call    IOAPIC_read
427
        and     eax, 0xfffeffff; bit 16
428
        xchg    eax, ebx
429
        call    IOAPIC_write
7733 dunkaist 430
.done:
431
        pop     [ioapic_cur]
2288 clevermous 432
        ret
433
endp
434
 
3320 clevermous 435
proc disable_irq stdcall, irq_line:dword
436
        mov     ebx, [irq_line]
437
        cmp     [irq_mode], IRQ_APIC
438
        je      .APIC
439
 
440
        mov     edx, 0x21
441
        cmp     ebx, 8
442
        jb      @F
443
 
444
        mov     edx, 0xA1
445
        sub     ebx, 8
446
@@:
447
        in      al, dx
448
        bts     eax, ebx
449
        out     dx, al
450
        ret
451
.APIC:
7733 dunkaist 452
        push    [ioapic_cur]
453
        xor     eax, eax
454
.next_ioapic:
9715 Doczom 455
        mov     ecx, [ioapic_gsi_base + eax*4]
456
        add     ecx, [IRQ_COUNT + eax*4]
7733 dunkaist 457
        cmp     ebx, ecx
458
        jae     .found
459
        inc     eax
460
        cmp     eax, [ioapic_cnt]
461
        jnz     .next_ioapic
462
        jmp     .done
463
.found:
464
        mov     [ioapic_cur], eax
465
        sub     ebx, [ioapic_gsi_base+eax*4]
3320 clevermous 466
        shl     ebx, 1
467
        add     ebx, 0x10
468
        mov     eax, ebx
469
        call    IOAPIC_read
470
        or      eax, 0x10000; bit 16
471
        xchg    eax, ebx
472
        call    IOAPIC_write
7733 dunkaist 473
.done:
474
        pop     [ioapic_cur]
3320 clevermous 475
        ret
476
endp
477
 
2288 clevermous 478
align 4
479
pci_irq_fixup:
480
 
481
        push    ebp
482
 
483
        mov     esi, [acpi_dev_data]
484
        mov     ebx, [acpi_dev_size]
485
 
9715 Doczom 486
        lea     edi, [esi + ebx]
2288 clevermous 487
 
488
.iterate:
489
 
490
        cmp     esi, edi
491
        jae     .done
492
 
493
        mov     eax, [esi]
494
 
495
        cmp     eax, -1
496
        je      .done
497
 
498
        movzx   ebx, al
499
        movzx   ebp, ah
500
 
501
        stdcall pci_read32, ebp, ebx, 0
502
 
503
        cmp     eax, [esi+4]
504
        jne     .skip
505
 
506
        mov     eax, [esi+8]
507
        stdcall pci_write8, ebp, ebx, 0x3C, eax
508
.skip:
509
        add     esi, 16
510
        jmp     .iterate
511
 
512
.done:
513
.fail:
514
        pop     ebp
515
        ret
516
 
5787 serge 517
align 4
518
get_clock_ns:
2288 clevermous 519
 
5787 serge 520
        mov     eax, [hpet_base]
521
        test    eax, eax
522
        jz      .old_tics
2288 clevermous 523
 
5787 serge 524
        push    ebx
5791 serge 525
        push    esi
5787 serge 526
        pushfd
527
        cli
2288 clevermous 528
 
5787 serge 529
        mov     ebx, eax
530
@@:
531
        mov     edx, [ebx+0xF4]
532
        mov     eax, [ebx+0xF0]
533
        mov     ecx, [ebx+0xF4]
534
        cmp     ecx, edx
5791 serge 535
        jne     @B
6941 serge 536
        popfd
2288 clevermous 537
 
6942 serge 538
;96-bit arithmetic
539
;ebx - low dword
540
;esi - medium dword
541
;edx - high dword
542
 
5791 serge 543
        mul     [hpet_period]
544
        mov     ebx, eax
545
        mov     esi, edx
546
 
547
        mov     eax, ecx
548
        mul     [hpet_period]
6942 serge 549
        add     esi, eax
550
        adc     edx, 0
6941 serge 551
        mov     eax, ebx
6942 serge 552
        mov     ebx, esi
553
        shrd    eax, ebx, 10
554
        shrd    esi, edx, 10
555
        mov     edx, esi
5791 serge 556
 
557
        pop     esi
5787 serge 558
        pop     ebx
559
        ret
560
 
561
.old_tics:
562
        mov     eax, [timer_ticks]
563
        mov     edx, 10000000
564
        mul     edx
565
        ret