* Shuffler: fix bug in real-mode entry. This affected a
number of modules, probably in relatively unimportant ways,
but it completely broke linux.c32.
+ * Improved performance.
+ * Attempt to halt the processor while idle. This can cause
+ bad reponsiveness when using a serial console especially for
+ automated input; if that ends up being a problem, use the
+ new "NOHALT 1" configuration command.
Changes in 3.80:
* New shuffler mechanism and API.
;
; INT 28h - DOS idle
;
-%ifdef HAVE_IDLE
comboot_int28:
cli
cld
- pushad
- xor ax,ax
- push ds
- push es
- mov ds,ax
- mov es,ax
- DO_IDLE
- pop es
- pop ds
- popad
+ call do_idle
iret
-%else
-comboot_int28 equ comboot_iret
-%endif
;
; INT 29h - DOS fast write character
;
; INT 22h AX=0013h Idle call
;
-;
-; *** FIX THIS ***
-; The idle call seems to have detrimental effects on some machines when
-; called from a COM32 context (WHY?) -- disable it for now.
-; *** IS THIS STILL TRUE? ***
-;
-%ifdef HAVE_IDLE
comapi_idle:
- DO_IDLE
+ call do_idle
clc
ret
-%else
-comapi_idle equ comapi_err
-%endif
-
;
; INT 22h AX=0014h Local boot
;
; in pxe_detect_nic_type
;
feature_flags:
- db 3 ; Have local boot, idle is noop
+ db 1 ; Have local boot, idle is not noop
feature_flags_len equ ($-feature_flags)
err_notdos db ': attempted DOS system call INT ',0
;
pollchar:
pushad
- DO_IDLE
+ call do_idle
mov ah,11h ; Poll keyboard
int 16h
jnz .done ; Keyboard response
;
getchar:
.again:
- DO_IDLE
+ call do_idle
mov ah,11h ; Poll keyboard
int 16h
jnz .kbd ; Keyboard input?
cmp al,ah
jne .again
.serial: xor ah,ah ; Avoid confusion
- xchg dx,bx ; Data port
+ mov dx,bx ; Data port
in al,dx
+ lea dx,[bx+2] ; DX -> IIR
+ in al,dx ; Read IIR to discard any IRQ bits
ret
.kbd: mov ah,10h ; Get keyboard input
int 16h
mov bx,KbdMap ; Convert character sets
xlatb
.func_key:
- RESET_IDLE ; Character received
+ call reset_idle ; Character received
ret
%ifdef DEBUG_TRACERS
FlowOutput resb 1 ; Outputs to assert for serial flow
FlowInput resb 1 ; Input bits for serial flow
FlowIgnore resb 1 ; Ignore input unless these bits set
+FlowDummy resb 1 ; Unused
TextAttribute resb 1 ; Text attribute for message file
DisplayMask resb 1 ; Display modes mask
CUR_DIR_DWORD equ 0x00002F2E
;
-; This is what we need to do when idle
-;
-%macro RESET_IDLE 0
- ; Nothing
-%endmacro
-%macro DO_IDLE 0
- ; Nothing
-%endmacro
-
-;
; The following structure is used for "virtual kernels"; i.e. LILO-style
; option labels. The options we permit here are `kernel' and `append
; Since there is no room in the bottom 64K for all of these, we
%include "strcpy.inc" ; strcpy()
%include "strecpy.inc" ; strcpy with end pointer check
%include "cache.inc" ; Metadata disk cache
+%include "idle.inc" ; Idle handling
%include "adv.inc" ; Auxillary Data Vector
%include "localboot.inc" ; Disk-based local boot
--- /dev/null
+;; -*- fundamental -*- ---------------------------------------------------
+;;
+;; Copyright 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., 51 Franklin St, Fifth Floor,
+;; Boston MA 02110-1301, USA; either version 2 of the License, or
+;; (at your option) any later version; incorporated herein by reference.
+;;
+;; -----------------------------------------------------------------------
+
+ section .text
+TICKS_TO_IDLE equ 4
+
+reset_idle:
+ push ax
+ mov ax,[cs:BIOS_timer]
+ mov [cs:IdleTimer],ax
+ pop ax
+ ret
+
+do_idle:
+ push ax
+ push ds
+ push es
+ mov ax,cs
+ mov ds,ax
+ mov es,ax
+ mov ax,[BIOS_timer]
+ sub ax,[IdleTimer]
+ cmp ax,TICKS_TO_IDLE
+ jb .done
+ call [IdleHook]
+ cmp word [NoHalt],0
+ jne .done
+ hlt
+.done:
+ pop es
+ pop ds
+ pop ax
+.ret: ret
+
+ section .data
+NoHalt dw 0
+IdleHook dw do_idle.ret
+
+ section .bss
+IdleTimer resw 1
ROOT_DIR_WORD equ 0x002F
;
-; This is what we need to do when idle
-;
-%macro RESET_IDLE 0
- ; Nothing
-%endmacro
-%macro DO_IDLE 0
- ; Nothing
-%endmacro
-
-;
; The following structure is used for "virtual kernels"; i.e. LILO-style
; option labels. The options we permit here are `kernel' and `append
; Since there is no room in the bottom 64K for all of these, we
%include "highmem.inc" ; High memory sizing
%include "strcpy.inc" ; strcpy()
%include "rawcon.inc" ; Console I/O w/o using the console functions
+%include "idle.inc" ; Idle handling
%include "adv.inc" ; Auxillary Data Vector
%include "localboot.inc" ; Disk-based local boot
onerror
noescape
nocomplete
+nohalt
f0
f1
f2
keyword allowoptions, pc_setint16, AllowOptions
keyword noescape, pc_setint16, NoEscape
keyword nocomplete, pc_setint16, NoComplete
+ keyword nohalt, pc_setint16, NoHalt
keyword f1, pc_filename, FKeyN(1)
keyword f2, pc_filename, FKeyN(2)
keyword f3, pc_filename, FKeyN(3)
ROOT_DIR_WORD equ 0x002F
;
-; This is what we need to do when idle
-;
-%macro RESET_IDLE 0
- ; Nothing
-%endmacro
-%macro DO_IDLE 0
- ; Nothing
-%endmacro
-
-;
; The following structure is used for "virtual kernels"; i.e. LILO-style
; option labels. The options we permit here are `kernel' and `append
; Since there is no room in the bottom 64K for all of these, we
%include "highmem.inc" ; High memory sizing
%include "strcpy.inc" ; strcpy()
%include "cache.inc" ; Metadata disk cache
+%include "idle.inc" ; Idle handling
%include "adv.inc" ; Auxillary Data Vector
%include "localboot.inc" ; Disk-based local boot
pc_serial: call getint
jc .err
push bx ; Serial port #
- xor ax,ax
- mov [FlowControl],ax ; Default to no flow control
- mov [FlowIgnore],al
+ xor eax,eax
+ mov [FlowControl],eax ; Default to no flow control
call skipspace
jc .nobaud
call ungetc
shl bh,4
mov [FlowIgnore],bh
mov bh,bl
- and bx,0F003h ; Valid bits
+ and bx,0F00Bh ; Valid bits
mov [FlowControl],bx
pop ebx ; Baud rate
jmp short .parse_baud
jne .err ; Assume serial port busted
dec dx
dec dx ; DX -> IER
- xor al,al ; IRQ disable
+ test byte [FlowOutput],8
+ setnz al ; Bit 0 -> input available IRQ
call slow_out
inc dx ; DX -> FCR/IIR
inc dx
inc dx ; DX -> MCR
- in al,dx
- or al,[FlowOutput] ; Assert bits
+ mov al,[FlowOutput] ; Assert bits
call slow_out
; Show some life
;; -*- fundamental -*- ---------------------------------------------------
;;
;; Copyright 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
ret
.found_device:
- and byte [feature_flags],~2
+ mov word [IdleHook],check_for_arp
jmp .done
;;
.sdid: resw 1
section .text
+;
+; Call the receive loop while idle. This is done mostly so we can respond to
+; ARP messages, but perhaps in the future this can be used to do network
+; console.
+;
+; hpa sez: people using automatic control on the serial port get very
+; unhappy if we poll for ARP too often (the PXE stack is pretty slow,
+; typically.) Therefore, only poll if at least 4 BIOS timer ticks have
+; passed since the last poll, and reset this when a character is
+; received (call reset_idle).
+;
+; Note: we only do this if pxe_detect_nic_type has set the IdleHook
+; to point to this routine.
+;
+check_for_arp:
+ pushad
+ mov di,packet_buf
+ mov [pxe_udp_read_pkt.buffer],di
+ mov [pxe_udp_read_pkt.buffer+2],ds
+ mov word [pxe_udp_read_pkt.buffersize],packet_buf_size
+ mov eax,[MyIP]
+ mov [pxe_udp_read_pkt.dip],eax
+ mov word [pxe_udp_read_pkt.lport],htons(9) ; discard port
+ mov di,pxe_udp_read_pkt
+ mov bx,PXENV_UDP_READ
+ call pxenv
+ ; Ignore result...
+ pop es
+ pop ds
+ popad
+ ret
SECTOR_SHIFT equ TFTP_BLOCKSIZE_LG2
SECTOR_SIZE equ TFTP_BLOCKSIZE
-%define HAVE_IDLE 1 ; idle is not a noop
-
-%if HAVE_IDLE
-%macro RESET_IDLE 0
- call reset_idle
-%endmacro
-%macro DO_IDLE 0
- call check_for_arp
-%endmacro
-%else
-%macro RESET_IDLE 0
- ; Nothing
-%endmacro
-%macro DO_IDLE 0
- ; Nothing
-%endmacro
-%endif
-
;
; TFTP operation codes
;
RebootTime resd 1 ; Reboot timeout, if set by option
StrucPtr resd 1 ; Pointer to PXENV+ or !PXE structure
APIVer resw 1 ; PXE API version found
-IdleTimer resw 1 ; Time to check for ARP?
LocalBootType resw 1 ; Local boot return code
RealBaseMem resw 1 ; Amount of DOS memory after freeing
OverLoad resb 1 ; Set if DHCP packet uses "overloading"
; Detect NIC type and initialize the idle mechanism
;
call pxe_detect_nic_type
- RESET_IDLE
+ call reset_idle
;
; Now we're all set to start with our *real* business. First load the
popad
ret
-;
-; Call the receive loop while idle. This is done mostly so we can respond to
-; ARP messages, but perhaps in the future this can be used to do network
-; console.
-;
-; hpa sez: people using automatic control on the serial port get very
-; unhappy if we poll for ARP too often (the PXE stack is pretty slow,
-; typically.) Therefore, only poll if at least 4 BIOS timer ticks have
-; passed since the last poll, and reset this when a character is
-; received (RESET_IDLE).
-;
-; Note: we only do this if pxe_detect_nic_type has cleared the
-; "idle is noop" bit in feature_flags.
-;
-%if HAVE_IDLE
-
-reset_idle:
- push ax
- mov ax,[cs:BIOS_timer]
- mov [cs:IdleTimer],ax
- pop ax
- ret
-
-check_for_arp:
- test byte [cs:feature_flags],2
- jnz .ret
- push ax
- mov ax,[cs:BIOS_timer]
- sub ax,[cs:IdleTimer]
- cmp ax,4
- pop ax
- jae .need_poll
-.ret: ret
-.need_poll: pushad
- push ds
- push es
- mov ax,cs
- mov ds,ax
- mov es,ax
- mov di,packet_buf
- mov [pxe_udp_read_pkt.buffer],di
- mov [pxe_udp_read_pkt.buffer+2],ds
- mov word [pxe_udp_read_pkt.buffersize],packet_buf_size
- mov eax,[MyIP]
- mov [pxe_udp_read_pkt.dip],eax
- mov word [pxe_udp_read_pkt.lport],htons(9) ; discard port
- mov di,pxe_udp_read_pkt
- mov bx,PXENV_UDP_READ
- call pxenv
- ; Ignore result...
- pop es
- pop ds
- popad
- RESET_IDLE
- ret
-
-%endif ; HAVE_IDLE
-
; -----------------------------------------------------------------------------
; Common modules
; -----------------------------------------------------------------------------
%include "strcpy.inc" ; strcpy()
%include "rawcon.inc" ; Console I/O w/o using the console functions
%include "dnsresolv.inc" ; DNS resolver
-%include "pxeidle.inc" ; Idle mechanism
+%include "idle.inc" ; Idle handling
+%include "pxeidle.inc" ; PXE-specific idle mechanism
%include "adv.inc" ; Auxillary Data Vector
; -----------------------------------------------------------------------------
;
getchar_timeout:
call vgashowcursor
- RESET_IDLE
+ call reset_idle
.loop:
push word [BIOS_timer]
pop ax
cmp ax,[BIOS_timer] ; Has the timer advanced?
je .loop
- DO_IDLE
+ call do_idle
dec dword [ThisKbdTo]
jz .timeout
"flowcontrol" is a combination of the following bits:
0x001 - Assert DTR
0x002 - Assert RTS
+ 0x008 - Enable interrupts
0x010 - Wait for CTS assertion
0x020 - Wait for DSR assertion
0x040 - Wait for RI assertion
ports detected by the BIOS. They may or may not correspond to
the legacy port values 0x3F8, 0x2F8, 0x3E8, 0x2E8.
+ Enabling interrupts (setting the 0x008 bit) may give better
+ responsiveness without setting the NOHALT option, but could
+ potentially cause problems with buggy BIOSes.
+
+NOHALT flag_val
+ If flag_val is 1, don't halt the processor while idle.
+ Halting the processor while idle significantly reduces the
+ power consumption, but can cause poor responsiveness to the
+ serial console, especially when using scripts to drive the
+ serial console, as opposed to human interaction.
+
CONSOLE flag_val
If flag_val is 0, disable output to the normal video console.
If flag_val is 1, enable output to the video console (this is