summaryrefslogtreecommitdiff
path: root/core/conio.inc
blob: 16c39c651949f52f9fc0a0ab8fe8c9a70f376a0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
;; -----------------------------------------------------------------------
;;
;;   Copyright 1994-2008 H. Peter Anvin - All Rights Reserved
;;   Copyright 2009 Intel Corporation; author: H. Peter Anvin
;;
;;   This program is free software; you can redistribute it and/or modify
;;   it under the terms of the GNU General Public License as published by
;;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
;;   Boston MA 02111-1307, USA; either version 2 of the License, or
;;   (at your option) any later version; incorporated herein by reference.
;;
;; -----------------------------------------------------------------------

;;
;; conio.inc
;;
;; Console I/O code, except:
;;   writechr, writestr_early		- module-dependent
;;   writestr, crlf		- writestr.inc
;;   writehex*			- writehex.inc
;;

;
; loadkeys:	Load a LILO-style keymap; file is open on the top of the
;		getc stack.
;
		section .text

loadkeys:
		mov cx,256
		mov di,trackbuf
		call readc
		jc .done				; EOF already?

		; Make sure we are at EOF now...
		call getc
		jnc .done			; We should be at EOF now!

		; It was okay, we can now move it into the KbdMap
		mov si,trackbuf
		mov di,KbdMap
		mov cx,256 >> 2
		rep movsd

.done:
		call close
		ret

;
; get_msg_file: Load a text file and write its contents to the screen,
;               interpreting color codes.  Call with the file already
;		on the top of the open/getc stack.
;
;		Assumes CS == DS == ES.
;
get_msg_file:
                mov byte [TextAttribute],07h	; Default grey on white
		mov byte [DisplayMask],07h	; Display text in all modes
		call msg_initvars

print_msg_file:
.getc:
		call getc
		jc .done
                cmp al,1Ah                      ; DOS EOF?
		je .done
		movzx cx,byte [UsingVGA]
		and cl,01h
		inc cx				; CL <- 01h = text mode,
						;       02h = graphics mode
                call [NextCharJump]		; Do what shall be done
		jmp .getc
.done:
		jmp close			; Tailcall!

msg_putchar:                                    ; Normal character
                cmp al,0Fh                      ; ^O = color code follows
                je msg_ctrl_o
                cmp al,0Dh                      ; Ignore <CR>
                je msg_ignore
                cmp al,0Ah                      ; <LF> = newline
                je msg_newline
                cmp al,0Ch                      ; <FF> = clear screen
                je msg_formfeed
		cmp al,07h			; <BEL> = beep
		je msg_beep
		cmp al,19h			; <EM> = return to text mode
		je msg_novga
		cmp al,18h			; <CAN> = VGA filename follows
		je msg_vga
		jnb .not_modectl
		cmp al,10h			; 10h to 17h are mode controls
		jae msg_modectl
.not_modectl:

msg_normal:	call write_serial_displaymask	; Write to serial port
		test [DisplayMask],cl
		jz msg_ignore			; Not screen
		test byte [DisplayCon],01h
		jz msg_ignore
                mov bl,[TextAttribute]
		mov bh,[BIOS_page]
                mov ah,09h                      ; Write character/attribute
                mov cx,1                        ; One character only
                int 10h                         ; Write to screen
                mov al,[CursorCol]
                inc ax
                cmp al,[VidCols]
                ja msg_line_wrap		; Screen wraparound
                mov [CursorCol],al

msg_gotoxy:     mov bh,[BIOS_page]
                mov dx,[CursorDX]
                mov ah,02h                      ; Set cursor position
                int 10h
msg_ignore:     ret

msg_beep:	mov ax,0E07h			; Beep
		xor bx,bx
		int 10h
		ret

msg_ctrl_o:                                     ; ^O = color code follows
                mov word [NextCharJump],msg_setbg
                ret
msg_newline:                                    ; Newline char or end of line
		mov si,crlf_msg
		call write_serial_str_displaymask
msg_line_wrap:					; Screen wraparound
		test [DisplayMask],cl
		jz msg_ignore
                mov byte [CursorCol],0
                mov al,[CursorRow]
                inc ax
                cmp al,[VidRows]
                ja msg_scroll
                mov [CursorRow],al
                jmp short msg_gotoxy
msg_scroll:     xor cx,cx                       ; Upper left hand corner
                mov dx,[ScreenSize]
                mov [CursorRow],dh		; New cursor at the bottom
                mov bh,[ScrollAttribute]
                mov ax,0601h                    ; Scroll up one line
                int 10h
                jmp short msg_gotoxy
msg_formfeed:                                   ; Form feed character
		mov si,crff_msg
		call write_serial_str_displaymask
		test [DisplayMask],cl
		jz msg_ignore
                xor cx,cx
                mov [CursorDX],cx		; Upper lefthand corner
                mov dx,[ScreenSize]
                mov bh,[TextAttribute]
                mov ax,0600h                    ; Clear screen region
                int 10h
                jmp msg_gotoxy
msg_setbg:                                      ; Color background character
                call unhexchar
                jc msg_color_bad
                shl al,4
		test [DisplayMask],cl
		jz .dontset
                mov [TextAttribute],al
.dontset:
                mov word [NextCharJump],msg_setfg
                ret
msg_setfg:                                      ; Color foreground character
                call unhexchar
                jc msg_color_bad
		test [DisplayMask],cl
		jz .dontset
                or [TextAttribute],al		; setbg set foreground to 0
.dontset:
		jmp short msg_putcharnext
msg_vga:
		mov word [NextCharJump],msg_filename
		mov di, VGAFileBuf
		jmp short msg_setvgafileptr

msg_color_bad:
                mov byte [TextAttribute],07h	; Default attribute
msg_putcharnext:
                mov word [NextCharJump],msg_putchar
		ret

msg_filename:					; Getting VGA filename
		cmp al,0Ah			; <LF> = end of filename
		je msg_viewimage
		cmp al,' '
		jbe msg_ret			; Ignore space/control char
		mov di,[VGAFilePtr]
		cmp di,VGAFileBufEnd
		jnb msg_ret
		mov [di],al			; Can't use stosb (DS:)
		inc di
msg_setvgafileptr:
		mov [VGAFilePtr],di
msg_ret:	ret

msg_novga:
		call vgaclearmode
		jmp short msg_initvars

msg_viewimage:
		mov si,[VGAFilePtr]
		mov byte [si],0			; Zero-terminate filename
		mov si,VGAFileBuf
		mov di,VGAFileMBuf
		call mangle_name
		call open
		jz msg_putcharnext		; Not there
		call vgadisplayfile
		; Fall through

		; Subroutine to initialize variables, also needed
		; after loading a graphics file
msg_initvars:
                pusha
                mov bh,[BIOS_page]
                mov ah,03h                      ; Read cursor position
                int 10h
                mov [CursorDX],dx
                popa
		jmp short msg_putcharnext	; Initialize state machine

msg_modectl:
		and al,07h
		mov [DisplayMask],al
		jmp short msg_putcharnext

;
; write_serial:	If serial output is enabled, write character on serial port
; write_serial_displaymask: d:o, but ignore if DisplayMask & 04h == 0
;
write_serial_displaymask:
		test byte [DisplayMask], 04h
		jz write_serial.end
write_serial:
		pushfd
		pushad
		mov bx,[SerialPort]
		and bx,bx
		je .noserial
		push ax
		mov ah,[FlowInput]
.waitspace:
		; Wait for space in transmit register
		lea dx,[bx+5]			; DX -> LSR
		in al,dx
		test al,20h
		jz .waitspace

		; Wait for input flow control
		inc dx				; DX -> MSR
		in al,dx
		and al,ah
		cmp al,ah
		jne .waitspace
.no_flow:

		xchg dx,bx			; DX -> THR
		pop ax
		slow_out dx,al			; Send data
.noserial:	popad
		popfd
.end:		ret

;
; write_serial_str: write_serial for strings
; write_serial_str_displaymask: d:o, but ignore if DisplayMask & 04h == 0
;
write_serial_str_displaymask:
		test byte [DisplayMask], 04h
		jz write_serial_str.end

write_serial_str:
.loop		lodsb
		and al,al
		jz .end
		call write_serial
		jmp short .loop
.end:		ret

;
; pollchar: check if we have an input character pending (ZF = 0)
;
pollchar:
		call do_idle
		pushad
		mov ah,11h		; Poll keyboard
		int 16h
		jnz .done		; Keyboard response
		mov dx,[SerialPort]
		and dx,dx
		jz .done		; No serial port -> no input
		mov ax,[SerialTail]	; Already-queued input?
		cli
		cmp ax,[SerialHead]
		jne .done_sti		; If so, return ZF = 0
		add dx,5		; DX -> LSR
		in al,dx
		test al,1		; ZF = 0 if data pending
		jz .done_sti
		inc dx			; DX -> MSR
		mov ah,[FlowIgnore]	; Required status bits
		in al,dx
		and al,ah
		cmp al,ah
		setne al
		dec al			; Set ZF = 0 if equal
.done_sti:	sti
.done:		popad
		ret

;
; getchar: Read a character from keyboard or serial port
;
getchar.sti_again:
		sti
getchar:
.again:
		call do_idle
		mov ah,11h		; Poll keyboard
		int 16h
		jnz .kbd		; Keyboard input?
		mov bx,[SerialPort]
		and bx,bx
		jz .again
		mov ax,[SerialTail]
		cli
		cmp ax,[SerialHead]
		jne .serial_queued
		lea dx,[bx+5]		; DX -> LSR
		in al,dx
		test al,1
		jz .sti_again
		inc dx			; DX -> MSR
		mov ah,[FlowIgnore]
		in al,dx
		and al,ah
		cmp al,ah
		jne .sti_again
.serial:	xor ah,ah		; Avoid confusion
		mov dx,bx		; Data port
		in al,dx		; Read data
		sti
		jmp .done
.serial_queued:
		sti			; We already know we'll consume data
		xchg bx,ax
		push ds
		mov ax,aux_seg + (aux.serial >> 4)
		mov ds,ax
		mov al,[bx]
		pop ds
		inc bx
		and bx,serial_buf_size-1
		mov [SerialTail],bx
		jmp .done

.kbd:		mov ah,10h		; Get keyboard input
		int 16h
		cmp al,0E0h
		jnz .not_ext
		xor al,al
.not_ext:
		and al,al
		jz .func_key
		mov bx,KbdMap		; Convert character sets
		xlatb
.func_key:
.done:
		jmp reset_idle		; Character received

%ifdef DEBUG_TRACERS
;
; debug hack to print a character with minimal code impact
;
debug_tracer:	pushad
		pushfd
		mov bp,sp
		mov bx,[bp+9*4]		; Get return address
		mov al,[cs:bx]		; Get data byte
		inc word [bp+9*4]	; Return to after data byte
		call writechr
		popfd
		popad
		ret
%endif	; DEBUG_TRACERS

		section .data
%if IS_ISOLINUX == 0			; Defined elsewhere for ISOLINUX
crlf_msg	db CR, LF
null_msg	db 0
%endif
crff_msg	db CR, FF, 0

		section .config
		; This is a word to pc_setint16 can set it
DisplayCon	dw 01h			; Console display enabled

ScrollAttribute	db 07h			; Grey on white (normal text color)

		section .bss
		alignb 2
NextCharJump    resw 1			; Routine to interpret next print char
CursorDX        equ $
CursorCol       resb 1			; Cursor column for message file
CursorRow       resb 1			; Cursor row for message file
ScreenSize      equ $
VidCols         resb 1			; Columns on screen-1
VidRows         resb 1			; Rows on screen-1

; Serial console stuff; don't put this in .config becasue we don't want
; loading a new config file to undo this setting.
		section .data
		alignz 4
SerialPort	dw 0			; Serial port base (or 0 for no serial port)
BaudDivisor	dw 115200/9600		; Baud rate divisor
FlowControl	equ $
FlowOutput	db 0			; Outputs to assert for serial flow
FlowInput	db 0			; Input bits for serial flow
FlowIgnore	db 0			; Ignore input unless these bits set
FlowDummy	db 0			; Unused

		section .bss
TextAttribute   resb 1			; Text attribute for message file
DisplayMask	resb 1			; Display modes mask

%include "serirq.inc"