Subversion Repositories Kolibri OS

Rev

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