raw
m_genesis.kv            1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 2 ;; ;;
m_genesis.kv 3 ;; This file is part of 'M', a MIPS system emulator. ;;
m_genesis.kv 4 ;; ;;
m_genesis.kv 5 ;; (C) 2019 Stanislav Datskovskiy ( www.loper-os.org ) ;;
m_genesis.kv 6 ;; http://wot.deedbot.org/17215D118B7239507FAFED98B98228A001ABFFC7.html ;;
m_genesis.kv 7 ;; ;;
m_genesis.kv 8 ;; You do not have, nor can you ever acquire the right to use, copy or ;;
m_genesis.kv 9 ;; distribute this software ; Should you use this software for any purpose, ;;
m_genesis.kv 10 ;; or copy and distribute it to anyone or in any manner, you are breaking ;;
m_genesis.kv 11 ;; the laws of whatever soi-disant jurisdiction, and you promise to ;;
m_genesis.kv 12 ;; continue doing so for the indefinite future. In any case, please ;;
m_genesis.kv 13 ;; always : read and understand any software ; verify any PGP signatures ;;
m_genesis.kv 14 ;; that you use - for any purpose. ;;
m_genesis.kv 15 ;; ;;
m_genesis.kv 16 ;; See also http://trilema.com/2015/a-new-software-licensing-paradigm . ;;
m_genesis.kv 17 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 18
m_genesis.kv 19 ;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 20 ;; UART Console Device ;;
m_genesis.kv 21 ;;;;;;;;;;;;;;;;;;;;;;;;;
m_genesis.kv 22
m_genesis.kv 23 ;-----------------------------------------------------------------------------
m_genesis.kv 24 ; Console UART MMIO:
m_genesis.kv 25 DECLARE_BUS_DEVICE UART, 0x3F8, 0x40C
m_genesis.kv 26 ;-----------------------------------------------------------------------------
m_genesis.kv 27
m_genesis.kv 28 ;-----------------------------------------------------------------------------
m_genesis.kv 29 ; Console UART IRQ:
m_genesis.kv 30 ;-----------------------------------------------------------------------------
m_genesis.kv 31 %define UART0_IRQ 2 ; UART0 Receiver Slave IRQ
m_genesis.kv 32 ;-----------------------------------------------------------------------------
m_genesis.kv 33
m_genesis.kv 34 section .text
m_genesis.kv 35
m_genesis.kv 36 ;-----------------------------------------------------------------------------
m_genesis.kv 37 _PD_Read_Word_UART: ; Word reads from UART: always 0
m_genesis.kv 38 xor eax, eax
m_genesis.kv 39 ret ; Fin.
m_genesis.kv 40 ;-----------------------------------------------------------------------------
m_genesis.kv 41 _PD_Write_Word_UART: ; Word writes to POWER do nothing!
m_genesis.kv 42 ret
m_genesis.kv 43 ;-----------------------------------------------------------------------------
m_genesis.kv 44 _PD_Read_Byte_UART: ; Read Byte from UART
m_genesis.kv 45 call _UART_Read_Reg ; Read this byte from UART
m_genesis.kv 46 mov eax, edx ; Return the resulting byte.
m_genesis.kv 47 ret ; Fin.
m_genesis.kv 48 ;-----------------------------------------------------------------------------
m_genesis.kv 49 _PD_Write_Byte_UART: ; Write Byte to UART
m_genesis.kv 50 call _UART_Write_Reg ; write this byte to UART
m_genesis.kv 51 ret ; Fin.
m_genesis.kv 52 ;-----------------------------------------------------------------------------
m_genesis.kv 53 _Device_Init_UART:
m_genesis.kv 54 call _Cure_TTY ; Cure the tty:
m_genesis.kv 55 call _UART_Reset ; Reset the UART
m_genesis.kv 56 mov rdi, _UART_Slave ; UART Slave
m_genesis.kv 57 call _Create_Thread ; Start the UART Slave Thread
m_genesis.kv 58 ret
m_genesis.kv 59 ;-----------------------------------------------------------------------------
m_genesis.kv 60 _Device_Shutdown_UART: ; Nothing needed
m_genesis.kv 61 mov dword [UART_Die], 0x01 ; Ask (unblocked) slave to die
m_genesis.kv 62 call _Uncure_TTY ; bring back the old tty settings, for clean shell
m_genesis.kv 63 ret
m_genesis.kv 64 ;-----------------------------------------------------------------------------
m_genesis.kv 65
m_genesis.kv 66
m_genesis.kv 67 ;-----------------------------------------------------------------------------
m_genesis.kv 68 ;; UART State
m_genesis.kv 69 ;-----------------------------------------------------------------------------
m_genesis.kv 70 section .bss
m_genesis.kv 71 UART0 resb UART_State_size ; UART-0 State
m_genesis.kv 72 UART_Die resd 1 ; Shutdown Trigger
m_genesis.kv 73 ;-----------------------------------------------------------------------------
m_genesis.kv 74
m_genesis.kv 75 section .text
m_genesis.kv 76
m_genesis.kv 77 ;-----------------------------------------------------------------------------
m_genesis.kv 78 ; Slave Thread which connects UART0 to linux console
m_genesis.kv 79 ;-----------------------------------------------------------------------------
m_genesis.kv 80 _UART_Slave:
m_genesis.kv 81 call _Read_Char_Blocking
m_genesis.kv 82 mov dl, byte [IOBUF]
m_genesis.kv 83 call _UART_Receive_Byte ; put DL in the UART receiver queue
m_genesis.kv 84 SetSlaveIRQ UART0_IRQ ; trigger the slave IRQ
m_genesis.kv 85 cmp dword [UART_Die], 0x01 ; time to die?
m_genesis.kv 86 jne _UART_Slave ; if not, keep going.
m_genesis.kv 87 jmp _exit_thread ; terminate thread
m_genesis.kv 88 ;-----------------------------------------------------------------------------
m_genesis.kv 89
m_genesis.kv 90 ;-----------------------------------------------------------------------------
m_genesis.kv 91 ; UARTism
m_genesis.kv 92 ;-----------------------------------------------------------------------------
m_genesis.kv 93 ;; UART State
m_genesis.kv 94 struc UART_State
m_genesis.kv 95 .LCR resb 1 ; Line Control
m_genesis.kv 96 .LSR resb 1 ; Line Status
m_genesis.kv 97 .MSR resb 1 ; Modem Status
m_genesis.kv 98 .IIR resb 1 ; Interrupt ID
m_genesis.kv 99 .IER resb 1 ; Interrupt Enable
m_genesis.kv 100 .DLL resb 1 ;
m_genesis.kv 101 .DLH resb 1 ;
m_genesis.kv 102 .FCR resb 1 ; FIFO Control
m_genesis.kv 103 .MCR resb 1 ; Modem Control
m_genesis.kv 104 .SCR resb 1 ; Modem Control
m_genesis.kv 105 ;; FIFO:
m_genesis.kv 106 .FIFO resb 32 ; The FIFO itself
m_genesis.kv 107 .FIFO_First resb 1 ; index of 1st byte in the FIFO
m_genesis.kv 108 .FIFO_Last resb 1 ; index of last byte in the FIFO
m_genesis.kv 109 .FIFO_Count resb 1 ; number of bytes in the FIFO
m_genesis.kv 110 endstruc
m_genesis.kv 111 ;-----------------------------------------------------------------------------
m_genesis.kv 112
m_genesis.kv 113 %define UART_LSR_DATA_READY 0x1
m_genesis.kv 114 %define UART_LSR_FIFO_EMPTY 0x20
m_genesis.kv 115 %define UART_LSR_TRANSMITTER_EMPTY 0x40
m_genesis.kv 116
m_genesis.kv 117 ; Enable Transmitter holding register int.
m_genesis.kv 118 %define UART_IER_THRI 0x02
m_genesis.kv 119
m_genesis.kv 120 ; Enable receiver data interrupt
m_genesis.kv 121 %define UART_IER_RDI 0x01
m_genesis.kv 122
m_genesis.kv 123 ; Modem status interrupt (Low priority)
m_genesis.kv 124 %define UART_IIR_MSI 0x00
m_genesis.kv 125
m_genesis.kv 126 %define UART_IIR_NO_INT 0x01
m_genesis.kv 127
m_genesis.kv 128 ; Transmitter holding register empty
m_genesis.kv 129 %define UART_IIR_THRI 0x02
m_genesis.kv 130
m_genesis.kv 131 ; Receiver data interrupt
m_genesis.kv 132 %define UART_IIR_RDI 0x04
m_genesis.kv 133
m_genesis.kv 134 ; Receiver line status interrupt (High p.)
m_genesis.kv 135 %define UART_IIR_RLSI 0x06
m_genesis.kv 136
m_genesis.kv 137 ; Character timeout
m_genesis.kv 138 %define UART_IIR_CTI 0x0c
m_genesis.kv 139
m_genesis.kv 140 ; Divisor latch access bit
m_genesis.kv 141 %define UART_LCR_DLAB 0x80
m_genesis.kv 142
m_genesis.kv 143 ; R/W: Divisor Latch Low, DLAB=1
m_genesis.kv 144 %define UART_DLL 0
m_genesis.kv 145
m_genesis.kv 146 ; R/W: Divisor Latch High, DLAB=1
m_genesis.kv 147 %define UART_DLH 1
m_genesis.kv 148
m_genesis.kv 149 ; R/W: Interrupt Enable Register
m_genesis.kv 150 %define UART_IER 1
m_genesis.kv 151
m_genesis.kv 152 ; R: Interrupt ID Register
m_genesis.kv 153 %define UART_IIR 2
m_genesis.kv 154
m_genesis.kv 155 ; W: FIFO Control Register
m_genesis.kv 156 %define UART_FCR 2
m_genesis.kv 157
m_genesis.kv 158 ; R/W: Line Control Register
m_genesis.kv 159 %define UART_LCR 3
m_genesis.kv 160
m_genesis.kv 161 ; W: Modem Control Register
m_genesis.kv 162 %define UART_MCR 4
m_genesis.kv 163
m_genesis.kv 164 ; R: Line Status Register
m_genesis.kv 165 %define UART_LSR 5
m_genesis.kv 166
m_genesis.kv 167 ; R: Modem Status Register
m_genesis.kv 168 %define UART_MSR 6
m_genesis.kv 169
m_genesis.kv 170 ; R/W:
m_genesis.kv 171 %define UART_SCR 7
m_genesis.kv 172 ;-----------------------------------------------------------------------------
m_genesis.kv 173
m_genesis.kv 174 ;-----------------------------------------------------------------------------
m_genesis.kv 175 ;; Access to UART regs:
m_genesis.kv 176 %define U0r(R) byte [UART0 + UART_State. %+ R]
m_genesis.kv 177 ;-----------------------------------------------------------------------------
m_genesis.kv 178 ;; Clear FIFO
m_genesis.kv 179 ;-----------------------------------------------------------------------------
m_genesis.kv 180 _UART_FIFO_Clear:
m_genesis.kv 181 mov U0r(FIFO_Last), 0
m_genesis.kv 182 mov U0r(FIFO_First), 0
m_genesis.kv 183 mov U0r(FIFO_Count), 0
m_genesis.kv 184 ret
m_genesis.kv 185 ;-----------------------------------------------------------------------------
m_genesis.kv 186
m_genesis.kv 187 ;-----------------------------------------------------------------------------
m_genesis.kv 188 ;; Take a byte from the UART FIFO. Byte will be in DL.
m_genesis.kv 189 ;-----------------------------------------------------------------------------
m_genesis.kv 190 _UART_FIFO_Get:
m_genesis.kv 191 xor edx, edx ; edx := 0
m_genesis.kv 192 cmp U0r(FIFO_Count), 0 ; is FIFO nonempty?
m_genesis.kv 193 je _UART_FIFO_Get_Nope ; ... if empty, skip and return 0
m_genesis.kv 194 ;; if FIFO is nonempty:
m_genesis.kv 195 xor eax, eax ; eax := 0
m_genesis.kv 196 mov al, U0r(FIFO_First) ; al := fifo_first
m_genesis.kv 197 mov dl, U0r(FIFO + eax) ; dl := FIFO[al]
m_genesis.kv 198 inc eax ; eax := eax + 1
m_genesis.kv 199 and eax, 0x1F ; eax := eax & 0x1f
m_genesis.kv 200 mov U0r(FIFO_First), al ; fifo_first := al
m_genesis.kv 201 mov al, U0r(FIFO_Count) ; al := fifo_count
m_genesis.kv 202 test eax, eax ; is al 0 ?
m_genesis.kv 203 jz _UART_FIFO_Get_Nope ; ... if 0, skip and do not update count
m_genesis.kv 204 dec eax ; eax := eax - 1
m_genesis.kv 205 mov U0r(FIFO_Count), al ; fifo_count := al
m_genesis.kv 206 _UART_FIFO_Get_Nope:
m_genesis.kv 207 ret
m_genesis.kv 208 ;-----------------------------------------------------------------------------
m_genesis.kv 209
m_genesis.kv 210 ;-----------------------------------------------------------------------------
m_genesis.kv 211 ;; Reset UART-0
m_genesis.kv 212 ;-----------------------------------------------------------------------------
m_genesis.kv 213 _UART_Reset:
m_genesis.kv 214 mov U0r(LCR), 3
m_genesis.kv 215 mov U0r(LSR), UART_LSR_TRANSMITTER_EMPTY | UART_LSR_FIFO_EMPTY
m_genesis.kv 216 mov U0r(MSR), 0
m_genesis.kv 217 mov U0r(IIR), UART_IIR_NO_INT
m_genesis.kv 218 mov U0r(IER), 0
m_genesis.kv 219 mov U0r(DLL), 0
m_genesis.kv 220 mov U0r(DLH), 0
m_genesis.kv 221 mov U0r(FCR), 0
m_genesis.kv 222 mov U0r(MCR), 0
m_genesis.kv 223 mov U0r(SCR), 0
m_genesis.kv 224 call _UART_FIFO_Clear ; zap the FIFO
m_genesis.kv 225 ret
m_genesis.kv 226 ;-----------------------------------------------------------------------------
m_genesis.kv 227 ;; Update UART IRQ
m_genesis.kv 228 ;-----------------------------------------------------------------------------
m_genesis.kv 229 _UART_IRQ:
m_genesis.kv 230 test U0r(LSR), UART_LSR_DATA_READY
m_genesis.kv 231 jz _UART_IRQ_Not_RDI
m_genesis.kv 232 test U0r(IER), UART_IER_RDI
m_genesis.kv 233 jz _UART_IRQ_Not_RDI
m_genesis.kv 234 _UART_IRQ_RDI:
m_genesis.kv 235 mov U0r(IIR), UART_IIR_RDI ; IIR=UART_IIR_RDI
m_genesis.kv 236 jmp _UART_IRQ_Maybe_Pending ; See if interrupt pending
m_genesis.kv 237 _UART_IRQ_Not_RDI:
m_genesis.kv 238 test U0r(LSR), UART_LSR_FIFO_EMPTY
m_genesis.kv 239 jz _UART_IRQ_Not_THRI
m_genesis.kv 240 test U0r(IER), UART_IER_THRI
m_genesis.kv 241 jz _UART_IRQ_Not_THRI
m_genesis.kv 242 _UART_IRQ_THRI:
m_genesis.kv 243 mov U0r(IIR), UART_IIR_THRI ; IIR=UART_IIR_THRI
m_genesis.kv 244 jmp _UART_IRQ_Maybe_Pending ; See if interrupt pending
m_genesis.kv 245 _UART_IRQ_Not_THRI:
m_genesis.kv 246 mov U0r(IIR), UART_IIR_NO_INT ; IIR=UART_IIR_NO_INT
m_genesis.kv 247 _UART_IRQ_Maybe_Pending: ; See if interrupt pending
m_genesis.kv 248 ;; see if interrupt pending
m_genesis.kv 249 cmp U0r(IIR), UART_IIR_NO_INT ; IIR==UART_IIR_NO_INT ?
m_genesis.kv 250 jne _UART_IRQ_Pending ; if !=, interrupt is pending
m_genesis.kv 251 _UART_IRQ_Not_Pending: ; interrupt is not pending:
m_genesis.kv 252 ClrIRQ UART0_IRQ
m_genesis.kv 253 ret
m_genesis.kv 254 _UART_IRQ_Pending: ; interrupt is pending:
m_genesis.kv 255 SetIRQ UART0_IRQ
m_genesis.kv 256 ret
m_genesis.kv 257 ;-----------------------------------------------------------------------------
m_genesis.kv 258
m_genesis.kv 259 ;-----------------------------------------------------------------------------
m_genesis.kv 260 ;; Place a byte (DL) into the UART's receiver buffer.
m_genesis.kv 261 ; TODO: mutex?
m_genesis.kv 262 ;-----------------------------------------------------------------------------
m_genesis.kv 263 _UART_Receive_Byte:
m_genesis.kv 264 xor eax, eax ; eax := 0
m_genesis.kv 265 mov al, U0r(FIFO_Last) ; al := fifo_last
m_genesis.kv 266 mov U0r(FIFO + eax), dl ; FIFO[al] := dl
m_genesis.kv 267 inc eax ; eax := eax + 1
m_genesis.kv 268 and eax, 0x1F ; eax := eax & 0x1f
m_genesis.kv 269 mov U0r(FIFO_Last), al ; fifo_last := al
m_genesis.kv 270 mov al, U0r(FIFO_Count) ; eax := fifo_count
m_genesis.kv 271 inc eax ; eax := eax + 1
m_genesis.kv 272 mov edx, 32 ; edx := 32
m_genesis.kv 273 cmp eax, edx ; is eax > 32 ?
m_genesis.kv 274 cmovg eax, edx ; ... if yes, eax := 32
m_genesis.kv 275 mov U0r(FIFO_Count), al ; fifo_count := al
m_genesis.kv 276 or U0r(LSR), UART_LSR_DATA_READY ; set the 'ready' flag
m_genesis.kv 277 call _UART_IRQ ; update IRQ
m_genesis.kv 278 ret
m_genesis.kv 279 ;-----------------------------------------------------------------------------
m_genesis.kv 280
m_genesis.kv 281 ;-----------------------------------------------------------------------------
m_genesis.kv 282 ;; Read UART Register. Offset in EAX, result in DL.
m_genesis.kv 283 ;-----------------------------------------------------------------------------
m_genesis.kv 284 _UART_Read_Reg:
m_genesis.kv 285 xor edx, edx ; result := 0
m_genesis.kv 286 sub eax, UART_BASE ; Adjust for base of UART
m_genesis.kv 287 and eax, 0x7 ; Adjusted offset is a 4-bit quantity
m_genesis.kv 288 test U0r(LCR), UART_LCR_DLAB
m_genesis.kv 289 jz _UART_Read_Reg_Not_DLAB
m_genesis.kv 290 _UART_Read_Reg_DLAB:
m_genesis.kv 291 cmp eax, UART_DLL ; offset=DLL?
m_genesis.kv 292 je _UART_Read_Reg_DLAB_DLL
m_genesis.kv 293 cmp eax, UART_DLH ; offset=DLH?
m_genesis.kv 294 je _UART_Read_Reg_DLAB_DLH
m_genesis.kv 295 jmp _UART_Read_Reg_Not_DLAB ; neither of these
m_genesis.kv 296 _UART_Read_Reg_DLAB_DLL:
m_genesis.kv 297 mov dl, U0r(DLL) ; return DLL
m_genesis.kv 298 ret
m_genesis.kv 299 _UART_Read_Reg_DLAB_DLH:
m_genesis.kv 300 mov dl, U0r(DLH) ; return DLH
m_genesis.kv 301 ret
m_genesis.kv 302 _UART_Read_Reg_Not_DLAB:
m_genesis.kv 303 cmp eax, 0 ; offset=0 ?
m_genesis.kv 304 je _UART_Read_Reg_0
m_genesis.kv 305 cmp eax, UART_IER ; offset=IER ?
m_genesis.kv 306 je _UART_Read_Reg_IER
m_genesis.kv 307 cmp eax, UART_MSR ; offset=MSR ?
m_genesis.kv 308 je _UART_Read_Reg_MSR
m_genesis.kv 309 cmp eax, UART_MCR ; offset=MCR ?
m_genesis.kv 310 je _UART_Read_Reg_MCR
m_genesis.kv 311 cmp eax, UART_IIR ; offset=IIR ?
m_genesis.kv 312 je _UART_Read_Reg_IIR
m_genesis.kv 313 cmp eax, UART_LCR ; offset=LCR ?
m_genesis.kv 314 je _UART_Read_Reg_LCR
m_genesis.kv 315 cmp eax, UART_LSR ; offset=LSR ?
m_genesis.kv 316 je _UART_Read_Reg_LSR
m_genesis.kv 317 cmp eax, UART_SCR ; offset=SCR ?
m_genesis.kv 318 je _UART_Read_Reg_SCR
m_genesis.kv 319 ACHTUNG "Bad UART Read Command." ; TODO: print detail
m_genesis.kv 320 ret
m_genesis.kv 321
m_genesis.kv 322 _UART_Read_Reg_0:
m_genesis.kv 323 cmp U0r(FIFO_Count), 0 ; is FIFO nonempty?
m_genesis.kv 324 je _UART_Read_Reg_0_Empty ; ... if empty, skip
m_genesis.kv 325 ;; FIFO is not empty:
m_genesis.kv 326 call _UART_FIFO_Get ; get byte from FIFO
m_genesis.kv 327 and U0r(LSR), ~UART_LSR_DATA_READY ; lower 'ready' flag
m_genesis.kv 328 cmp U0r(FIFO_Count), 0 ; is FIFO still nonempty?
m_genesis.kv 329 je _UART_Read_Reg_0_Empty ; ... if empty, leave 'ready' flag down
m_genesis.kv 330 ;; FIFO still has data:
m_genesis.kv 331 or U0r(LSR), UART_LSR_DATA_READY ; else, raise the 'ready' flag.
m_genesis.kv 332 _UART_Read_Reg_0_Empty:
m_genesis.kv 333 call _UART_IRQ ; update IRQ
m_genesis.kv 334 ret ; return DL
m_genesis.kv 335
m_genesis.kv 336 _UART_Read_Reg_IER:
m_genesis.kv 337 mov dl, U0r(IER)
m_genesis.kv 338 and edx, 0xF
m_genesis.kv 339 ret ; return IER & 0xF
m_genesis.kv 340
m_genesis.kv 341 _UART_Read_Reg_MSR:
m_genesis.kv 342 mov dl, U0r(MSR)
m_genesis.kv 343 ret ; return MSR
m_genesis.kv 344
m_genesis.kv 345 _UART_Read_Reg_MCR:
m_genesis.kv 346 mov dl, U0r(MCR)
m_genesis.kv 347 ret ; return MCR
m_genesis.kv 348
m_genesis.kv 349 _UART_Read_Reg_IIR:
m_genesis.kv 350 mov dl, U0r(IIR)
m_genesis.kv 351 ret ; return IIR
m_genesis.kv 352
m_genesis.kv 353 _UART_Read_Reg_LCR:
m_genesis.kv 354 mov dl, U0r(LCR)
m_genesis.kv 355 ret ; return LCR
m_genesis.kv 356
m_genesis.kv 357 _UART_Read_Reg_LSR:
m_genesis.kv 358 cmp U0r(FIFO_Count), 0 ; is FIFO nonempty?
m_genesis.kv 359 je _UART_Read_Reg_LSR_Empty ; if empty, go to 'empty'
m_genesis.kv 360 ;; FIFO is not empty:
m_genesis.kv 361 or U0r(LSR), UART_LSR_DATA_READY ; raise the 'ready' flag.
m_genesis.kv 362 jmp _UART_Read_Reg_LSR_Done ; return
m_genesis.kv 363 _UART_Read_Reg_LSR_Empty:
m_genesis.kv 364 and U0r(LSR), ~UART_LSR_DATA_READY ; lower the 'ready' flag
m_genesis.kv 365 _UART_Read_Reg_LSR_Done:
m_genesis.kv 366 mov dl, U0r(LSR)
m_genesis.kv 367 ret ; return LSR
m_genesis.kv 368
m_genesis.kv 369 _UART_Read_Reg_SCR:
m_genesis.kv 370 mov dl, U0r(SCR)
m_genesis.kv 371 ret ; return SCR
m_genesis.kv 372 ;-----------------------------------------------------------------------------
m_genesis.kv 373
m_genesis.kv 374 ;-----------------------------------------------------------------------------
m_genesis.kv 375 ;; Write UART Register. Offset in EAX, payload in DL.
m_genesis.kv 376 ;-----------------------------------------------------------------------------
m_genesis.kv 377 _UART_Write_Reg:
m_genesis.kv 378 sub eax, UART_BASE ; Adjust for base of UART
m_genesis.kv 379 and eax, 0x7 ; Adjusted offset is a 4-bit quantity
m_genesis.kv 380 test U0r(LCR), UART_LCR_DLAB
m_genesis.kv 381 jz _UART_Write_Reg_Not_DLAB
m_genesis.kv 382 _UART_Write_Reg_DLAB:
m_genesis.kv 383 cmp eax, UART_DLL ; offset=DLL?
m_genesis.kv 384 je _UART_Write_Reg_DLAB_DLL
m_genesis.kv 385 cmp eax, UART_DLH ; offset=DLH?
m_genesis.kv 386 je _UART_Write_Reg_DLAB_DLH
m_genesis.kv 387 jmp _UART_Write_Reg_Not_DLAB ; neither of these
m_genesis.kv 388 _UART_Write_Reg_DLAB_DLL:
m_genesis.kv 389 mov U0r(DLL), dl ; write DLL
m_genesis.kv 390 ret
m_genesis.kv 391 _UART_Write_Reg_DLAB_DLH:
m_genesis.kv 392 mov U0r(DLH), dl ; write DLH
m_genesis.kv 393 ret
m_genesis.kv 394 _UART_Write_Reg_Not_DLAB:
m_genesis.kv 395 cmp eax, 0 ; offset=0 ?
m_genesis.kv 396 je _UART_Write_Reg_0
m_genesis.kv 397 cmp eax, UART_IER ; offset=IER?
m_genesis.kv 398 je _UART_Write_Reg_IER
m_genesis.kv 399 cmp eax, UART_FCR ; offset=FCR?
m_genesis.kv 400 je _UART_Write_Reg_FCR
m_genesis.kv 401 cmp eax, UART_LCR ; offset=LCR?
m_genesis.kv 402 je _UART_Write_Reg_LCR
m_genesis.kv 403 cmp eax, UART_MCR ; offset=MCR?
m_genesis.kv 404 je _UART_Write_Reg_MCR
m_genesis.kv 405 cmp eax, UART_SCR ; offset=SCR?
m_genesis.kv 406 je _UART_Write_Reg_SCR
m_genesis.kv 407 ACHTUNG "Bad UART Write Command." ; TODO: print detail
m_genesis.kv 408 ret
m_genesis.kv 409
m_genesis.kv 410 _UART_Write_Reg_0:
m_genesis.kv 411 and U0r(LSR), ~UART_LSR_FIFO_EMPTY
m_genesis.kv 412 test U0r(MCR), (1 << 4)
m_genesis.kv 413 jz _UART_Write_Reg_0_Not_Loopback
m_genesis.kv 414 _UART_Write_Reg_0_Loopback:
m_genesis.kv 415 call _UART_Receive_Byte ; put DL in the receiver FIFO
m_genesis.kv 416 jmp _UART_Write_Reg_0_Fin ; wrap up
m_genesis.kv 417 _UART_Write_Reg_0_Not_Loopback: ; if NOT loopback :
m_genesis.kv 418 call _Write_Char ; ... then write char in DL to console
m_genesis.kv 419 _UART_Write_Reg_0_Fin:
m_genesis.kv 420 or U0r(LSR), UART_LSR_FIFO_EMPTY ; mark the send buffer as empty
m_genesis.kv 421 call _UART_IRQ ; refresh IRQ
m_genesis.kv 422 ret ; fin
m_genesis.kv 423
m_genesis.kv 424 _UART_Write_Reg_IER:
m_genesis.kv 425 and edx, 0xF ; 4-bit qty
m_genesis.kv 426 mov U0r(IER), dl ; IER := dl & 0xF
m_genesis.kv 427 call _UART_IRQ ; refresh IRQ
m_genesis.kv 428 ret ; fin
m_genesis.kv 429
m_genesis.kv 430 _UART_Write_Reg_FCR:
m_genesis.kv 431 mov U0r(FCR), dl ; FCR := dl
m_genesis.kv 432 test dl, 0x2 ; if FCR & 2:
m_genesis.kv 433 jz _UART_Write_Reg_FCR_No_Clear
m_genesis.kv 434 call _UART_FIFO_Clear ; ... then zap the FIFO.
m_genesis.kv 435 _UART_Write_Reg_FCR_No_Clear:
m_genesis.kv 436 ret
m_genesis.kv 437
m_genesis.kv 438 _UART_Write_Reg_LCR:
m_genesis.kv 439 mov U0r(LCR), dl ; LCR := dl
m_genesis.kv 440 ret ; fin
m_genesis.kv 441
m_genesis.kv 442 _UART_Write_Reg_MCR:
m_genesis.kv 443 mov U0r(MCR), dl ; MCR := dl
m_genesis.kv 444 ret ; fin
m_genesis.kv 445
m_genesis.kv 446 _UART_Write_Reg_SCR:
m_genesis.kv 447 mov U0r(SCR), dl ; SCR := dl
m_genesis.kv 448 ret ; fin
m_genesis.kv 449 ;-----------------------------------------------------------------------------