Advertisement
Ladies_Man

#NUP Intel LAB_2(6) VirtualWire-2 (w/ IOAPIC)

Sep 16th, 2014
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;Инициализировать контроллеры прерываний в Virtual Wire II (с IOAPIC) режиме.
  2. ;Настроить LocalTimer для генерации прерываний с вектором 0x20 на частоте 68Гц.
  3.  
  4. .586
  5. _TEXT   segment byte public 'CODE' use16
  6. assume cs:_TEXT, ds:nothing
  7. org     100h           
  8. start:
  9.         cli    
  10.         lss     SP, dword ptr STKPTR
  11.         sti    
  12.  
  13.     call    init_BIOS
  14.     call    init_PIC
  15.     call    unreal_mode_on
  16.     call    init_IOAPIC
  17.     call    init_LAPIC
  18.     call    stop
  19.  
  20. ;========================================================================
  21. ;---------------------------------init_BIOS-----------------------------
  22. ;========================================================================
  23.  
  24. STKPTR  dw  0FFFEh, 09000h
  25.  
  26. init_BIOS:
  27.     mov     dx, 0C000h
  28.        
  29. cycle:  mov     DS, dx
  30.     mov     ax, 80h        
  31.     cmp     word ptr DS:[0], 0AA55h
  32.     jnz     nxt
  33.        
  34.     call scanbios
  35.  
  36.     movzx   ax, byte ptr DS:[2]
  37.     add     al, 3h     
  38.     and     al, 0FCh
  39.     shl     ax, 5  
  40.          
  41. nxt:    add     dx, ax         
  42.     cmp     dx, 0F000h         
  43.     jb      cycle
  44. ret
  45.  
  46. scanbios proc near
  47.     cld
  48.     xor     si, si
  49.     xor     cx, cx
  50.     mov     ch, DS:[2]     
  51.     xor     bl, bl
  52.  
  53. chcksm: lodsw  
  54.         add     al, ah         
  55.         add     bl, al         
  56.         dec     cx
  57.         jnz     short chcksm
  58.         or      bl, bl 
  59.         jnz     short skip     
  60.  
  61.         pusha
  62.         push    ds
  63.         push    es
  64.         push    fs
  65.         push    gs
  66.         push    CS
  67.         push    offset __ret
  68.         push    DS
  69.         push    3h
  70.         retf
  71. __ret:
  72.         pop     gs
  73.         pop     fs
  74.         pop     es
  75.         pop     ds
  76.         popa
  77. skip:   ret     0
  78. scanbios endp
  79.  
  80. ;========================================================================
  81. ;---------------------------------init_PIC-------------------------------
  82. ;========================================================================
  83.  
  84. init_PIC proc near
  85.  
  86. ;1) начальный сброс (безличный EOI)(запись OCW2 с кодом безличного EOI — 0x20 в чётные порты обоих контроллеров)
  87.  
  88.     mov al, 20h     ;pic0
  89.     out 20h, al
  90.     mov al, 20h     ;pic1
  91.     out 0A0h, al
  92.  
  93. ;2) Загрузка ICW1..ICW4 в оба контроллера
  94. ; ICW1 записывается в чётный порт контроллера, после чего в нечетный порт должны быть немедленно записаны ICW2..ICW4.
  95. ; ICW3 надо указывать только если используется каскадирование (так и есть), а ICW4 только если бит ICW4 в ICW1 установлен.
  96.  
  97.     mov al, 11h     ;pic0
  98.     out 20h, al
  99.     mov al, 11h     ;pic1
  100.     out 0A0h, al
  101.  
  102. ; ICW2 записывается в нечётный порт контроллера и задает номер вектора прерывания ЦПУ, соответствующий нулевой линии запроса прерывания.
  103. ; Линии (1..7) будут отображены на вектора N+1, .., N+7. В реальном режиме это обычно вектора 0x08 для PIC #0 и 0x70 для PIC #1.
  104.  
  105.     mov al, 08h     ;pic0
  106.     out 21h, al
  107.     mov al, 70h     ;pic1
  108.     out 0A1h, al
  109. ; ICW3 записывается в нечётный порт контроллера и задает:
  110. ; для PIC #0 — битовую маску линии запроса, к которой подключен PIC #1 (IRQ2, маска 0b00000100)
  111. ; для PIC #1 — номер уровня ведомого контроллера (обычно 2)
  112.  
  113.     mov al, 04h     ;pic0
  114.     out 21h, al
  115.     mov al, 02h     ;pic1
  116.     out 0A1h, al
  117.  
  118. ;ICW4 записывается в нечётный порт контроллера, если бит ICW4 в ICW1 был установлен.
  119.  
  120.     mov al, 05h     ;pic0
  121.     out 21h, al
  122.     mov al, 01h     ;pic1
  123.     out 0A1h, al
  124.  
  125. ;3) разрешение выбранных IRQ
  126. ; OCW1 чтение/запись в нечётный порт контроллера и задает битовую маску запрещенных линий IRQ. Обычно запрещены линии IRQ 3,4,5,7 на PIC #0 (маска 0xB8) и 8,9,A,B,F на PIC #1 (маска 0x8F)
  127. ;PIC0
  128.     mov al, 0FBh        ;1111 1011
  129.     out 21h, al
  130. ;PIC1
  131.     mov al, 0FFh        ;запретили все
  132.     out 0A1h, al
  133. ret
  134. init_PIC endp
  135.  
  136. ;========================================================================
  137. ;---------------------------------unreal_mode_on-------------------------
  138. ;========================================================================
  139. .586p
  140. unreal_mode_on proc near
  141.         push    ds
  142.         push    es
  143.         push    gs
  144.         push    fs
  145.         push    cx
  146.         push    ax
  147.         push    si
  148.         push    di
  149.  
  150.         mov ax, cs
  151.         mov ds, ax
  152.         mov si, offset _TEXT:unreal_mode_c
  153.  
  154.         mov ax, 9000h
  155.         mov es, ax
  156.         xor di, di
  157.  
  158.         cld
  159.         mov cx, 6
  160.         rep movsd
  161.         lgdt fword ptr _TEXT:unreal_mode_b
  162.  
  163.         mov eax, cr0
  164.         or  eax, 1
  165.         mov cr0, eax
  166.         db  0EAh
  167.         dw  $+4, 8h
  168.  
  169.         mov ax, 10h
  170.         mov ss, ax
  171.         mov ds, ax
  172.         mov es, ax
  173.         mov fs, ax
  174.         mov gs, ax
  175.  
  176.         mov eax, cr0
  177.         and eax, 0FFFFFFFEh
  178.         mov cr0, eax
  179.         db  0EAh
  180.         dw  $+4, 0F000h
  181.  
  182.         mov ax, 9000h
  183.         mov ss, ax
  184.  
  185.         in  al, 92h
  186.         test    al, 2
  187.         jne unreal_mode_d
  188.         or  al, 2
  189.         jmp short $+2
  190.         out 092h, al
  191. unreal_mode_d:
  192.         lgdt fword ptr _TEXT:unreal_mode_a
  193.  
  194.         pop di
  195.         pop si
  196.         pop ax
  197.         pop cx
  198.         pop fs
  199.         pop gs
  200.         pop es
  201.         pop ds
  202.         ret 0
  203. unreal_mode_on endp
  204.  
  205. unreal_mode_a:
  206.     dw  0
  207.     dd  0, 0
  208.  
  209. unreal_mode_b:
  210.     dw  23
  211.     dd  90000h, 0
  212.  
  213. unreal_mode_c:
  214.     dd  0, 0, 0FFFFh, 8F9A0Fh, 0FFFFh, 8F9200h
  215.  
  216. ;========================================================================
  217. ;---------------------------------init_IOAPIC----------------------------
  218. ;========================================================================
  219.  
  220. ;1.IOAPIC обычно отображается на адрес IOAPICBASE 0xFEC00000 (адрес может быть несколько изменен средствами северного моста)
  221. ;2.IOAPIC представлен двумя регистрами: "селектор" (selector) по адресу IOAPICBASE и "окно" (window) по адресу IOAPICBASE+0x10
  222. ;3.При работе с IOAPIC в селектор записывается номер регистра IOAPIC, а из окна производится чтение или запись регистра
  223. ;4.Термин "Reserved", определяющий те или иные биты регистров IOAPIC обозначает не "MBZ", а то, что содержимое этих разрядов нельзя изменять,
  224. ;при необходимости изменить регистр надо сначала прочитать прежнее значение, потом только нужные биты обнулить или установить, а затем записать обратно.
  225. .586p
  226. init_IOAPIC proc near
  227.  
  228.     push    DS
  229.     push    cx
  230.  
  231.     xor ax, ax
  232.     mov DS, ax
  233.  
  234. ;адрес селектора: 0xFEC00000h
  235. ;адрес окна:       0xFEC00010h
  236.  
  237. ;24 пары 32-х разрядных регистров образуют 24 записи, по 64 бита на описание каждого IRQ; порядок little-endian (от 0x10,0x11 до 0x3E,0x3F):
  238. ;линия IOAPIC      |   0   |   1   |  ...  |   22  |   23  |
  239. ;регистр     | 10,11 | 12,13 |  ...  | 3C,3D | 3E,3F |
  240.  
  241. ;линия 0 настраивается отдельно от всех, так как по ней подключен PIC. остальные линии маскируются
  242. ;0 линия, 10 рег
  243.     mov dword ptr DS:[0FEC00000h], 10h      ;номер регистра отвечающего за 0-ю линию -> в адрес селектора (запрос) (0-я линия - 0x10,0x11 рег, 23-я линия - 0x3E,0x3F рег)
  244.     mov     eax, dword ptr DS:[0FEC00010h]      ;работа с регистром в окне (ответ)
  245.     and     eax, 0FFFE60FFh             ;Физическая адресация LAPIC, обнуляем Trigger Mode(15й бит), Pin Polarity(131 бит),
  246.                             ;возбуждение прерывания передним фронтом (состояние 1) т.к. настраиваем линию irq0 - линию по которой подключен PIC
  247.     or  eax, 0700h              ;Delivery Mod = 111 = ExtInt - Causes the processor to respond the intr as if the intr originated in an externally connected intr controller
  248.                             ;прерывания идут в неизменном виде от устройства. Если Delivery Mod = Fixed то они уже были бы заданы и обрабатывались бы заданные, а не полученные прерывания                        
  249.     mov     dword ptr DS:[0FEC00010h], eax      ;настроили маску eax и записали ее обратно
  250.  
  251. ;0 линия, 11 рег
  252.     mov     dword ptr DS:[0FEC00000h], 011h     ;второй регистр 0-й линии
  253.     mov     eax, dword ptr DS:[0FEC00010h] 
  254.     and     eax, 0FFFFFFh               ;Обнулить целевой ID лапика приёмника (0-й lapic единственного процессора) т.к бочс эмулирует лишь 1 процессор
  255.     mov     dword ptr DS:[0FEC00010h], eax 
  256.  
  257. ;на этом 0-я линия настроена, остальные 23 линии маскируем в цикле. начинаем с 1-й линии, 12 регистра
  258.     mov     ecx, 012h                      
  259. loop_masking:
  260.     mov     DS:[0FEC00000h], ecx            ;номер очередного регистра в селектор
  261.     mov     eax, dword ptr DS:[0FEC00010h]      ;работа в окне
  262.     or  eax, 010000h                ;маскирование (16-й бит MASK = 1)
  263.     mov     dword ptr DS:[0FEC00010h], eax      ;записываем обратно
  264.     add     ecx, 2                  ;шаг цикла - через один    т.к бит маскирования(16й) находится в первом (левом) регистре линии (учесть что little-endian)
  265.     cmp     ecx, 040h               ;последний обработанный регистр - 3E. 3Eh + 2h = 40h           
  266.     jnz     loop_masking
  267.  
  268.     pop     cx                             
  269.     pop     DS                         
  270. ret
  271. init_IOAPIC endp
  272.  
  273. ;========================================================================
  274. ;---------------------------------init_LAPIC-----------------------------
  275. ;========================================================================
  276.  
  277. init_LAPIC proc near
  278.  
  279.         push DS
  280.         push cx
  281.  
  282. ;2) Убедиться, что установлен бит разрешения LAPIC(бит номер 0x0B, маска 0x800) в регистре базового адреса LAPIC; регистр базового адреса LAPIC известен как MSR 0x1B (IA32_APPIC_BASE)
  283.  
  284.         mov ecx, 01Bh
  285.         rdmsr
  286.         or  eax, 0800h
  287.         wrmsr
  288.  
  289.         xor     ax, ax
  290.         mov DS, ax
  291.  
  292. ;если во время обработки какого-то прерывания появляется прерывание с повышенным приоритетом, то будет отправлен spurios vector
  293.  
  294.         mov DS:[040h], offset spur_intr         ;обработка фиктивных (spurious) прерываний
  295.         mov DS:[042h], cs               ;аналогично обычным прерываниям далее
  296.  
  297. ;3) Установить бит разрешения LAPIC в дескрипторе вектора фиктивных (spuriouse) прерываний
  298.  
  299.         mov dword ptr DS:[0FEE000F0h], 0110h        ;8-й бит ApicEn = ApicEnabled - включение апика. 4-й бит отвечает за spurious vector (вектор фиктивных прерываний)
  300.  
  301. ;4) Настроить вектора прерываний LINT0, LINT1, локального таймера и т. д.
  302.  
  303.         or dword ptr DS:[0FEE00350h], 010000h       ;маскирование LINT0
  304.         or dword ptr DS:[0FEE00360h], 010000h       ;маскирование LINT1
  305.  
  306. ;обработчик обычных прерываний
  307.         mov DS:[080h], offset interrupt_VANO        ;адрес обработчика в таблице векторов прерываний: 0xVector * 0x4. смещение в сегменте cs в данном случае будет: 0x20 * 4 = 080h
  308.         mov DS:[082h], cs               ;сегмент 082h
  309.  
  310. ;Local Timer: Vector 0x20, Frequency 68 Hz
  311.         mov eax, dword ptr DS:[0FEE00320h]      ;LVT[0] - Timer
  312.         and eax, 06F00h            
  313. ;настройка вектора прерываний
  314.         or  eax, 020020h                ;17-й бит Timer = 1 => таймер периодический. 20h в конце маски - вектор 0x20 из задания
  315.         mov dword ptr DS:[0FEE00320h], eax
  316.  
  317.         or dword ptr DS:[0FEE003E0h], 0Bh       ;Timer Divide Configuration: 1011, d0(0й бит)=1, d1(1й бит)=1, d2(3й бит)=1 => делитель частоты = 1.
  318.                                 ;т.к. частота умещается в отведенные рамки то дополнительно ее не делим (делитель = 1)
  319. ;настройка частоты таймера
  320.         mov dword ptr DS:[0FEE00380h], 123B64Fh     ;Timer Initial Count: 1,3 GHz (частота IPS из bochs) / 68 Hz (частота из задания) = 123B64Fh
  321.  
  322.         mov dword ptr DS:[012300h], 0           ;обнуляем ячейку 12300h (обязательно не из 1-го мб памяти) для последующего накопления там прерываний
  323.  
  324.         pop cx
  325.         pop DS
  326. ret
  327. init_LAPIC endp
  328.  
  329. spur_intr:      ;обработка вектора фиктивных прерываний
  330. iret        ;Ends without EndOfInterrupt! as said in documentation 3A, chapter 10
  331.  
  332. interrupt_VANO: ;обработка прерываний
  333.         push DS
  334.         push ax
  335.  
  336.         xor ax, ax
  337.         mov DS, ax
  338.  
  339.         mov dword ptr DS:[0FEE000B0h], 0    ;EOI
  340.         inc dword ptr DS:[012300h]      ;увеличиваем значение в ячейке куда "накапливаем" прерывания
  341.  
  342.         pop ax
  343.         pop DS
  344. iret
  345.  
  346. ;========================================================================
  347. ;---------------------------------stop-----------------------------------
  348. ;========================================================================
  349.  
  350. stop    proc    near
  351.     ; cli
  352.     hlt
  353.     jmp short stop
  354. stop    endp
  355.  
  356. ;--------------------------------------------------------------------------
  357.  
  358. org 0FFF0h
  359.     db  0EAh        ; JMP FAR
  360.     dw  offset start    ; offset
  361.     dw  0F000h      ; segment
  362.  
  363.  
  364. org 0FFFEh
  365.     dw  99FCh       ; PC
  366.  
  367. _TEXT   ends
  368. end start
  369.  
  370.  
  371. ;P.S. команды бочса (bochsBDG):
  372. ;"c" = continue
  373. ;Ctrl+C = stop
  374. ;Ctrl+C = fullstop
  375. ;"x 0x12300" - проверить ячейку 12300h
  376.  
  377. ;P.P.S. для частоты 68Гц в ячейке 12300h за 5сек накопится значение в ~350d прерываний (15Eh)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement