Subversion Repositories Kolibri OS

Rev

Rev 8117 | Rev 9715 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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