Index: trunk/XTIDE_Universal_BIOS/Inc/BootMenu.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/BootMenu.inc	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Inc/BootMenu.inc	(revision 392)
@@ -30,7 +30,4 @@
 BOOT_MENU_HEIGHT_WITHOUT_ITEMS			EQU	(BOOT_MENU_TITLE_LINES + BOOT_MENU_INFO_LINES + BOOT_MENU_SEPARATOR_LINES_PLUS_SHADOW)
 MENU_SCREEN_BOTTOM_LINES				EQU	1
-
-; Hotkeys
-ROM_BOOT_HOTKEY_SCANCODE				EQU	42h	; F8
 
 
Index: trunk/XTIDE_Universal_BIOS/Inc/BootVars.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/BootVars.inc	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Inc/BootVars.inc	(revision 392)
@@ -30,12 +30,25 @@
 ; Segment is always 0000h, same as BDA segment
 struc BOOTVARS
-					resb	7C00h
-	.rgbAtaInfo:					; 7C00h, ATA Information for drive detection
-	.rgbBootSect	resb 	512		; 7C00h, Boot sector
-					resb	256		; Boot Menu stack
+						resb	7C00h
+	.rgbAtaInfo:						; 7C00h, ATA Information for drive detection
+	.rgbBootSect		resb 	512		; 7C00h, Boot sector
+						resb	256		; Boot Menu stack
 	.rgbMnuStack:
-	.dwPostStack	resb	4		; POST stack pointer when entering INT 19h
-	.rgBootNfo:						; Array containing BOOTNFO structs
+	.dwPostStack		resb	4		; POST stack pointer when entering INT 19h
+	.hotkeyVars			resb	HOTKEYVARS_size
+	.rgBootNfo:							; Array containing BOOTNFO structs
 endstruc
+
+struc HOTKEYVARS
+	.bScancode			resb	1		; Function hotkey scancode
+	.bFlags				resb	1		; Must be just before .bHddLetter! 
+	.wHddAndFddLetters:
+	.bHddLetter			resb	1		; Hard Drive letter hotkey (upper case)
+	.bFddLetter			resb	1		; Floppy Drive letter hotkey (upper case)
+endstruc
+
+; Bit defines for HOTKEYVARS.bFlags
+FLG_HOTKEY_HD_FIRST		EQU		(1<<0)	; First try to boot from HDD, then FDD
+
 
 
Index: trunk/XTIDE_Universal_BIOS/Inc/HotkeyBar.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/HotkeyBar.inc	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Inc/HotkeyBar.inc	(revision 392)
@@ -0,0 +1,32 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Equates and structs used in Hotkey Bar.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;
+
+%ifndef HOTKEYBAR_INC
+%define HOTKEYBAR_INC
+
+; Hotkeys
+BOOT_MENU_HOTKEY_SCANCODE				EQU	3Ch	; F2
+ROM_BOOT_HOTKEY_SCANCODE				EQU	42h	; F8
+
+; Default drives
+DEFAULT_FLOPPY_DRIVE_LETTER				EQU	'A'
+DEFAULT_HARD_DRIVE_LETTER				EQU	'C'
+
+
+%endif ; HOTKEYBAR_INC
Index: trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc
===================================================================
--- trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Inc/RomVars.inc	(revision 392)
@@ -37,5 +37,5 @@
 	.wBootTimeout		resb	2	; Boot Menu selection timeout in system timer ticks
 	.bIdeCnt			resb	1	; Number of available IDE controllers
-	.bBootDrv			resb	1	; Boot Menu default drive
+	.bBootDrv			resb	1	; Default drive to boot from
 	.bMinFddCnt			resb	1	; Minimum number of Floppy Drives
 	.bStealSize			resb	1	; Number of 1kB blocks stolen from 640kB base RAM
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int13h/AH15h_HSize.asm	(revision 392)
@@ -81,8 +81,10 @@
 ;		CX
 ;--------------------------------------------------------------------
+%ifdef MODULE_BOOT_MENU
 AH15h_GetSectorCountFromForeignDriveToDXAX:
 	mov		ah, GET_DRIVE_PARAMETERS
 	call	Int13h_CallPreviousInt13hHandler
 	jmp		SHORT ConvertAH08hReturnValuesToSectorCount
+%endif
 
 AH15h_GetSectorCountToBXDXAX:
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h.asm	(revision 392)
@@ -22,19 +22,4 @@
 
 ;--------------------------------------------------------------------
-; INT 19h handler that properly reboots the computer when
-; INT 19h is called.
-;
-; Int19h_ResetHandler
-;	Parameters:
-;		Nothing
-;	Returns:
-;		Never returns (reboots computer)
-;--------------------------------------------------------------------
-Int19h_ResetHandler:
-	mov		ax, BOOT_FLAG_WARM				; Skip memory tests
-	jmp		Reboot_ComputerWithBootFlagInAX
-
-
-;--------------------------------------------------------------------
 ; Int19h_BootLoaderHandler
 ;	Parameters:
@@ -44,15 +29,16 @@
 ;--------------------------------------------------------------------
 Int19h_BootLoaderHandler:
-	sti
-	; Install INT 19h handler for proper reboot
-	LOAD_BDA_SEGMENT_TO	es, ax
-	mov		al, BIOS_BOOT_LOADER_INTERRUPT_19h	; INT 19h interrupt vector offset
-	mov		si, Int19h_ResetHandler				; INT 19h handler to reboot the system
-	call	Interrupts_InstallHandlerToVectorInALFromCSSI
-	call	Initialize_AndDetectDrives			; Installs new boot menu loader
-	; Fall to .PrepareStackAndSelectDriveFromBootMenu
+	sti											; Allow timer interrupts
+	LOAD_BDA_SEGMENT_TO	es, ax					; Load BDA segment (zero) to ES
+	; Fall to .PrepareBootLoaderStack
+
 
 ;--------------------------------------------------------------------
-; .PrepareStackAndSelectDriveFromBootMenu
+; Drive detection and boot menu use lots of stack so it is
+; wise to relocate stack. Otherwise something important from
+; interrupt vectors are likely corrupted, likely our own DPTs if
+; they are located to 30:0h.
+;
+; .PrepareBootLoaderStack
 ;	Parameters:
 ;		ES:		BDA and interrupt vector segment (zero)
@@ -60,13 +46,14 @@
 ;		Never returns (loads operating system)
 ;--------------------------------------------------------------------
-.PrepareStackAndSelectDriveFromBootMenu:
+.PrepareBootLoaderStack:
 	STORE_POST_STACK_POINTER
 	SWITCH_TO_BOOT_MENU_STACK
 	; Fall to .InitializeDisplay
 
+
 ;--------------------------------------------------------------------
 ; .InitializeDisplay
 ;	Parameters:
-;		Nothing
+;		ES:		BDA and interrupt vector segment (zero)
 ;	Returns:
 ;		Never returns (loads operating system)
@@ -79,57 +66,65 @@
 	int		BIOS_VIDEO_INTERRUPT_10h
 .InitializeDisplayLibrary:
-	call	BootMenuPrint_InitializeDisplayContext
-	; Fall to .SelectDriveToBootFrom
+	call	DetectPrint_InitializeDisplayContext
+	; Fall to .InitializeBiosAndDetectDrives
+
 
 ;--------------------------------------------------------------------
-; .SelectDriveToBootFrom
+; .InitializeBiosAndDetectDrives
 ;	Parameters:
-;		Nothing
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		DS:		RAMVARS segment
+;--------------------------------------------------------------------
+	call	Initialize_AndDetectDrives	
+	; Fall to SelectDriveToBootFrom
+
+
+;--------------------------------------------------------------------
+; SelectDriveToBootFrom
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA and interrupt vector segment (zero)
 ;	Returns:
 ;		Never returns (loads operating system)
 ;--------------------------------------------------------------------
-.SelectDriveToBootFrom:
-	call	RamVars_GetSegmentToDS
+SelectDriveToBootFrom:
+	call	HotkeyBar_UpdateDuringDriveDetection
+
 %ifdef MODULE_BOOT_MENU
-	cmp		WORD [cs:ROMVARS.wfDisplayBootMenu], BYTE 0
-	jne		SHORT ProcessBootMenuSelectionsUntilBootableDriveSelected	; Display boot menu
+	mov		di, BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode
+	cmp		BYTE [es:di], BOOT_MENU_HOTKEY_SCANCODE
+	jne		SHORT .DoNotDisplayBootMenu
+
+	; Stop blinking the Boot Menu hotkey and display menu
+	mov		BYTE [es:di], 0
+	call	HotkeyBar_DrawToTopOfScreen
+	call	BootMenu_DisplayAndStoreSelectionAsHotkey
+.DoNotDisplayBootMenu:
 %endif
-	; Fall to BootFromDriveAthenTryDriveC
+
+	; Check if ROM boot (INT 18h) wanted
+	cmp		BYTE [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode], ROM_BOOT_HOTKEY_SCANCODE
+	je		SHORT JumpToBootSector_or_RomBoot	; CF clear so ROM boot
+
+	; Try to boot from Primary boot drive (00h by default)
+	call	HotkeyBar_GetPrimaryBootDriveNumberToDL
+	call	TryToBootFromPrimaryOrSecondaryBootDevice
+	jc		SHORT JumpToBootSector_or_RomBoot
+
+	; Try to boot from Secondary boot device (80h by default)
+	call	HotkeyBar_GetSecondaryBootDriveNumberToDL
+	call	TryToBootFromPrimaryOrSecondaryBootDevice
+
+%ifdef MODULE_BOOT_MENU
+	; Force Boot Menu hotkey to display boot menu
+	mov		BYTE [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode], BOOT_MENU_HOTKEY_SCANCODE
+	jnc		SHORT SelectDriveToBootFrom
+%endif
+	; Fall to JumpToBootSector_or_RomBoot
+
 
 ;--------------------------------------------------------------------
-; BootFromDriveAthenTryDriveC
-;	Parameters:
-;		DS:		RAMVARS segment
-;	Returns:
-;		Never returns (loads operating system)
-;--------------------------------------------------------------------
-BootFromDriveAthenTryDriveC:
-	xor		dx, dx				; DL = 00h = Floppy Drive A
-	call	BootSector_TryToLoadFromDriveDL
-	jc		SHORT Int19hMenu_JumpToBootSector_or_RomBoot
-	mov		dl, 80h				; DL = 80h = First Hard Drive (usually C)
-	call	BootSector_TryToLoadFromDriveDL
-	jmp		SHORT Int19hMenu_JumpToBootSector_or_RomBoot	; ROM Boot if error
-
-
-%ifdef MODULE_BOOT_MENU
-;--------------------------------------------------------------------
-; ProcessBootMenuSelectionsUntilBootableDriveSelected
-;	Parameters:
-;		DS:		RAMVARS segment
-;	Returns:
-;		Never returns
-;--------------------------------------------------------------------
-ProcessBootMenuSelectionsUntilBootableDriveSelected:
-	call	BootMenu_DisplayAndReturnSelectionInDX
-	call	DriveXlate_ToOrBack											; Translate drive number
-	call	BootSector_TryToLoadFromDriveDL
-	jnc		SHORT ProcessBootMenuSelectionsUntilBootableDriveSelected	; Boot failure, show menu again
-	; Fall to Int19hMenu_JumpToBootSector_or_RomBoot
-	; (CF is set or we wouldn't be here, see "jnc" immediately above)
-%endif
-
-;--------------------------------------------------------------------
-; Int19hMenu_JumpToBootSector_or_RomBoot
+; JumpToBootSector_or_RomBoot
 ;
 ; Switches back to the POST stack, clears the DS and ES registers,
@@ -140,5 +135,5 @@
 ;		DL:		Drive to boot from (translated, 00h or 80h)
 ;       CF:     Set for Boot Sector Boot 
-;               Clear for Rom Boot
+;               Clear for ROM Boot
 ;	   	ES:BX:	(if CF set) Ptr to boot sector
 ;
@@ -146,5 +141,5 @@
 ;		Never returns
 ;--------------------------------------------------------------------
-Int19hMenu_JumpToBootSector_or_RomBoot:
+JumpToBootSector_or_RomBoot:
 	mov		cx, es		; Preserve MBR segment (can't push because of stack change)
 	mov		ax, 0		; NOTE: can't use XOR (LOAD_BDA_SEGMENT_TO) as it impacts CF
@@ -167,3 +162,23 @@
 ; Boot by calling INT 18h (ROM Basic of ROM DOS)
 .romboot:
-	int		BIOS_BOOT_FAILURE_INTERRUPT_18h	; Never returns		
+	int		BIOS_BOOT_FAILURE_INTERRUPT_18h	; Never returns	
+
+
+;--------------------------------------------------------------------
+; TryToBootFromPrimaryOrSecondaryBootDevice
+;	Parameters
+;		DL:		Drive selected as boot device
+;		DS:		RAMVARS segment
+;		ES:		BDA and interrupt vector segment (zero)
+;	Returns:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;       CF:     Set for Boot Sector Boot
+;               Clear for ROM Boot
+;	   	ES:BX:	(if CF set) Ptr to boot sector
+;	Corrupts registers:
+;		AX, CX, DH, SI, DI, (DL if failed to read boot sector)
+;--------------------------------------------------------------------
+TryToBootFromPrimaryOrSecondaryBootDevice:
+	call	DriveXlate_SetDriveToSwap
+	call	DriveXlate_ToOrBack
+	jmp		BootSector_TryToLoadFromDriveDL
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h/BootSector.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h/BootSector.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h/BootSector.asm	(revision 392)
@@ -0,0 +1,121 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Reading and jumping to boot sector.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; BootSector_TryToLoadFromDriveDL
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;		DS:		RAMVARS segment
+;	Returns:
+;		ES:BX:	Ptr to boot sector (if successful)
+;		CF:		Set if boot sector loaded successfully
+;				Cleared if failed to load boot sector
+;	Corrupts registers:
+;		AX, CX, DH, SI, DI, (DL if failed to read boot sector)
+;--------------------------------------------------------------------
+BootSector_TryToLoadFromDriveDL:
+	call	DetectPrint_TryToBootFromDL
+	call	LoadFirstSectorFromDriveDL
+	jc		SHORT .FailedToLoadFirstSector
+
+	test	dl, dl
+	jns		SHORT .AlwaysBootFromFloppyDriveForBooterGames
+	cmp		WORD [es:bx+510], 0AA55h		; Valid boot sector?
+	jne		SHORT .FirstHardDiskSectorNotBootable
+.AlwaysBootFromFloppyDriveForBooterGames:
+	stc
+	ret
+.FailedToLoadFirstSector:
+	call	DetectPrint_FailedToLoadFirstSector
+	clc
+	ret
+.FirstHardDiskSectorNotBootable:
+	mov		si, g_szBootSectorNotFound
+	call	DetectPrint_NullTerminatedStringFromCSSIandSetCF
+	clc
+	ret
+
+;--------------------------------------------------------------------
+; LoadFirstSectorFromDriveDL
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;	Returns:
+;		AH:		INT 13h error code
+;		ES:BX:	Ptr to boot sector (if successful)
+;		CF:		Cleared if read successful
+;				Set if any error
+;	Corrupts registers:
+;		AL, CX, DH, DI
+;--------------------------------------------------------------------
+LoadFirstSectorFromDriveDL:
+	LOAD_BDA_SEGMENT_TO	es, bx				; ES:BX now points to...
+	mov		bx, BOOTVARS.rgbBootSect		; ...boot sector location
+	mov		di, BOOT_READ_RETRY_TIMES		; Initialize retry counter
+
+.ReadRetryLoop:
+	call	.ResetBootDriveFromDL
+	call	.LoadFirstSectorFromDLtoESBX
+	jnc		SHORT .Return
+	dec		di								; Decrement retry counter
+	jnz		SHORT .ReadRetryLoop			; Loop while retries left
+.Return:
+	ret
+
+;--------------------------------------------------------------------
+; .ResetBootDriveFromDL
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;	Returns:
+;		AH:		INT 13h error code
+;		CF:		Cleared if read successful
+;				Set if any error
+;	Corrupts registers:
+;		AL
+;--------------------------------------------------------------------
+.ResetBootDriveFromDL:
+	xor		ax, ax							; AH=0h, Disk Controller Reset
+	test	dl, dl							; Floppy drive?
+	jns		SHORT .SkipAltReset
+	mov		ah, 0Dh							; AH=Dh, Reset Hard Disk (Alternate reset)
+.SkipAltReset:
+	int		BIOS_DISK_INTERRUPT_13h
+	ret
+
+;--------------------------------------------------------------------
+; .LoadFirstSectorFromDLtoESBX
+;	Parameters:
+;		DL:		Drive to boot from (translated, 00h or 80h)
+;		ES:BX:	Destination buffer for boot sector
+;	Returns:
+;		AH:		INT 13h error code
+;		ES:BX:	Ptr to boot sector
+;		CF:		Cleared if read successful
+;				Set if any error
+;	Corrupts registers:
+;		AL, CX, DH
+;--------------------------------------------------------------------
+.LoadFirstSectorFromDLtoESBX:
+	mov		ax, 0201h						; Read 1 sector
+	mov		cx, 1							; Cylinder 0, Sector 1
+	xor		dh, dh							; Head 0
+	int		BIOS_DISK_INTERRUPT_13h
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h/Int19hReset.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h/Int19hReset.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Handlers/Int19h/Int19hReset.asm	(revision 392)
@@ -0,0 +1,35 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Int 19h Handler (Boot Loader).
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; INT 19h handler that properly reboots the computer when
+; INT 19h is called.
+;
+; Int19hReset_Handler
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Never returns (reboots computer)
+;--------------------------------------------------------------------
+Int19hReset_Handler:
+	mov		ax, BOOT_FLAG_WARM				; Skip memory tests
+	jmp		Reboot_ComputerWithBootFlagInAX
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvAtaInit.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvAtaInit.asm	(revision 391)
+++ 	(revision )
@@ -1,139 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	Common functions for initializing different
-;					VLB and PCI IDE Controllers.
-
-;
-; XTIDE Universal BIOS and Associated Tools 
-; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
-;
-; 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; either version 2 of the License, or
-; (at your option) any later version.
-; 
-; This program is distributed in the hope that it will be useful,
-; but WITHOUT ANY WARRANTY; without even the implied warranty of
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-; GNU General Public License for more details.		
-; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-;		
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; AdvAtaInit_DetectControllerForIdeBaseInBX
-;	Parameters:
-;		BX:		IDE Controller base port
-;	Returns:
-;		AX:		ID WORD specific for detected controller
-;				Zero if no controller detected
-;		DX:		Controller base port (not IDE)
-;		CF:		Set if controller detected
-;				Cleared if no controller
-;	Corrupts registers:
-;		BX
-;--------------------------------------------------------------------
-AdvAtaInit_DetectControllerForIdeBaseInBX:
-	call	Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
-	jne		SHORT .NoAdvancedControllerForPortBX
-	call	Vision_DoesIdePortInBXbelongToControllerWithIDinAX
-	jne		SHORT .NoAdvancedControllerForPortBX
-
-	stc		; Advanced Controller found for port BX
-	ret
-
-.NoAdvancedControllerForPortBX:
-	xor		ax, ax
-	ret
-
-
-;--------------------------------------------------------------------
-; AdvAtaInit_GetControllerMaxPioModeToAL
-;	Parameters:
-;		AX:		ID WORD specific for detected controller
-;	Returns:
-;		AL:		Max supported PIO mode
-;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
-;		CF:		Set if PIO limit necessary
-;				Cleared if no need to limit timings
-;	Corrupts registers:
-;		(AX if CF cleared)
-;--------------------------------------------------------------------
-AdvAtaInit_GetControllerMaxPioModeToAL	equ	Vision_GetMaxPioModeToAL
-
-
-;--------------------------------------------------------------------
-; AdvAtaInit_InitializeControllerForDPTinDSDI
-;	Parameters:
-;		DS:DI:	Ptr to DPT for Single or Slave Drive
-;	Returns:
-;		CF:		Cleared if success or no controller to initialize
-;				Set if error
-;	Corrupts registers:
-;		AX, BX, CX, DX
-;--------------------------------------------------------------------
-AdvAtaInit_InitializeControllerForDPTinDSDI:
-	push	bp
-	push	si
-
-	; Call Controller Specific initialization function
-	mov		ax, [di+DPT_ADVANCED_ATA.wControllerID]
-	test	ax, ax
-	jz		SHORT .NoAdvancedController	; Return with CF cleared
-
-	; We only support Vision at the moment so no need to identify ID
-	call	AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
-	call	Vision_InitializeWithIDinAHandConfigInAL
-
-.NoAdvancedController:
-	pop		si
-	pop		bp
-	ret
-
-
-;--------------------------------------------------------------------
-; AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
-;	Parameters:
-;		DS:DI:	Ptr to DPT for Single or Slave Drive
-;	Returns:
-;		DS:DI:	Ptr to DPT for Single or Slave Drive
-;		SI:		Offset to Master DPT if Slave Drive present
-;				Zero if Slave Drive not present
-;	Corrupts registers:
-;		AX
-;--------------------------------------------------------------------
-AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI:
-	; Must be Slave Drive if previous DPT has same IDEVARS offset
-	lea		si, [di-LARGEST_DPT_SIZE]	; DS:SI points to previous DPT
-	mov		al, [di+DPT.bIdevarsOffset]
-	cmp		al, [si+DPT.bIdevarsOffset]
-	je		SHORT .MasterAndSlaveDrivePresent
-
-	; We only have single drive so zero SI
-	xor		si, si
-.MasterAndSlaveDrivePresent:
-	ret
-
-
-;--------------------------------------------------------------------
-; AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
-;	Parameters:
-;		DS:DI:	Ptr to DPT for Single or Slave Drive
-;		SI:		Offset to Master DPT if Slave Drive present
-;				Zero if Slave Drive not present
-;	Returns:
-;		BX:		Best common PIO mode
-;		CX:		Slowest common PIO Cycle Time in nanosecs
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI:
-	eMOVZX	bx, [di+DPT_ADVANCED_ATA.bPioMode]
-	mov		cx, [di+DPT_ADVANCED_ATA.wMinPioCycleTime]
-	test	si, si
-	jz		SHORT .PioTimingsLoadedToAXandCX
-	MIN_U	bl, [si+DPT_ADVANCED_ATA.bPioMode]
-	MAX_U	cx, [si+DPT_ADVANCED_ATA.wMinPioCycleTime]
-.PioTimingsLoadedToAXandCX:
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/AdvAtaInit.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/AdvAtaInit.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/AdvAtaInit.asm	(revision 392)
@@ -0,0 +1,139 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Common functions for initializing different
+;					VLB and PCI IDE Controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; AdvAtaInit_DetectControllerForIdeBaseInBX
+;	Parameters:
+;		BX:		IDE Controller base port
+;	Returns:
+;		AX:		ID WORD specific for detected controller
+;				Zero if no controller detected
+;		DX:		Controller base port (not IDE)
+;		CF:		Set if controller detected
+;				Cleared if no controller
+;	Corrupts registers:
+;		BX
+;--------------------------------------------------------------------
+AdvAtaInit_DetectControllerForIdeBaseInBX:
+	call	Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
+	jne		SHORT .NoAdvancedControllerForPortBX
+	call	Vision_DoesIdePortInBXbelongToControllerWithIDinAX
+	jne		SHORT .NoAdvancedControllerForPortBX
+
+	stc		; Advanced Controller found for port BX
+	ret
+
+.NoAdvancedControllerForPortBX:
+	xor		ax, ax
+	ret
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_GetControllerMaxPioModeToAL
+;	Parameters:
+;		AX:		ID WORD specific for detected controller
+;	Returns:
+;		AL:		Max supported PIO mode
+;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
+;		CF:		Set if PIO limit necessary
+;				Cleared if no need to limit timings
+;	Corrupts registers:
+;		(AX if CF cleared)
+;--------------------------------------------------------------------
+AdvAtaInit_GetControllerMaxPioModeToAL	equ	Vision_GetMaxPioModeToAL
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_InitializeControllerForDPTinDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;	Returns:
+;		CF:		Cleared if success or no controller to initialize
+;				Set if error
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+AdvAtaInit_InitializeControllerForDPTinDSDI:
+	push	bp
+	push	si
+
+	; Call Controller Specific initialization function
+	mov		ax, [di+DPT_ADVANCED_ATA.wControllerID]
+	test	ax, ax
+	jz		SHORT .NoAdvancedController	; Return with CF cleared
+
+	; We only support Vision at the moment so no need to identify ID
+	call	AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
+	call	Vision_InitializeWithIDinAHandConfigInAL
+
+.NoAdvancedController:
+	pop		si
+	pop		bp
+	ret
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;	Returns:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;		SI:		Offset to Master DPT if Slave Drive present
+;				Zero if Slave Drive not present
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+AdvAtaInit_LoadMasterDPTtoDSSIifSlaveInDSDI:
+	; Must be Slave Drive if previous DPT has same IDEVARS offset
+	lea		si, [di-LARGEST_DPT_SIZE]	; DS:SI points to previous DPT
+	mov		al, [di+DPT.bIdevarsOffset]
+	cmp		al, [si+DPT.bIdevarsOffset]
+	je		SHORT .MasterAndSlaveDrivePresent
+
+	; We only have single drive so zero SI
+	xor		si, si
+.MasterAndSlaveDrivePresent:
+	ret
+
+
+;--------------------------------------------------------------------
+; AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
+;	Parameters:
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;		SI:		Offset to Master DPT if Slave Drive present
+;				Zero if Slave Drive not present
+;	Returns:
+;		BX:		Best common PIO mode
+;		CX:		Slowest common PIO Cycle Time in nanosecs
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI:
+	eMOVZX	bx, [di+DPT_ADVANCED_ATA.bPioMode]
+	mov		cx, [di+DPT_ADVANCED_ATA.wMinPioCycleTime]
+	test	si, si
+	jz		SHORT .PioTimingsLoadedToAXandCX
+	MIN_U	bl, [si+DPT_ADVANCED_ATA.bPioMode]
+	MAX_U	cx, [si+DPT_ADVANCED_ATA.wMinPioCycleTime]
+.PioTimingsLoadedToAXandCX:
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/AdvancedAta/Vision.asm	(revision 392)
@@ -0,0 +1,251 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for initializing QDI Vision
+;					QD6500 and QD6580 VLB IDE Controllers.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
+;	Parameters:
+;		Nothing
+;	Returns:
+;		AX:		ID WORD specific for QDI Vision Controllers
+;				(AL = QD65xx Config Register contents)
+;				(AH = QDI Vision Controller ID (bits 4...7))
+;		DX:		Controller port (not IDE port)
+;		ZF:		Set if controller found
+;				Cleared if supported controller not found (AX,DX = undefined)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent:
+	; Check QD65xx base port
+	mov		dx, QD65XX_BASE_PORT
+	in		al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
+	call	IsConfigRegisterWithIDinAL
+	je		SHORT VisionControllerDetected
+
+	; Check QD65xx alternative base port
+	or		dl, QD65XX_ALTERNATIVE_BASE_PORT
+	in		al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
+	; Fall to IsConfigRegisterWithIDinAL
+
+;--------------------------------------------------------------------
+; IsConfigRegisterWithIDinAL
+;	Parameters:
+;		AL:		Possible QD65xx Config Register contents
+;	Returns:
+;		AH		QDI Vision Controller ID or undefined
+;		ZF:		Set if controller found
+;				Cleared if supported controller not found (AH = undefined)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+IsConfigRegisterWithIDinAL:
+	mov		ah, al
+	and		al, MASK_QDCONFIG_CONTROLLER_ID
+	cmp		al, ID_QD6500 << 4
+	je		SHORT VisionControllerDetected
+	cmp		al, ID_QD6580 << 4
+	je		SHORT VisionControllerDetected
+	cmp		al, ID_QD6580_ALTERNATE << 4
+VisionControllerDetected:
+	xchg	ah, al
+	ret
+
+
+;--------------------------------------------------------------------
+; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
+;	Parameters:
+;		AL:		QD65xx Config Register contents
+;		AH:		QDI Vision Controller ID (bits 4...7)
+;		BX:		IDE Base port to check
+;		DX:		Vision Controller port
+;	Returns:
+;		ZF:		Set if port belongs to controller
+;				Cleared if port belongs to another controller
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
+	cmp		ah, ID_QD6500 << 4
+	je		SHORT .DoesIdePortInDXbelongToQD6500
+
+	; QD6580 always have Primary IDE at 1F0h
+	; Secondary IDE at 170h can be enabled or disabled
+	cmp		bx, DEVICE_ATA_DEFAULT_PORT
+	je		SHORT .ReturnResultInZF
+
+	; Check if Secondary IDE channel is enabled
+	push	ax
+	add		dx, BYTE QD6580_CONTROL_REGISTER
+	in		al, dx
+	sub		dx, BYTE QD6580_CONTROL_REGISTER
+	test	al, FLG_QDCONTROL_SECONDARY_DISABLED_in
+	pop		ax
+	jz		SHORT .CompareBXtoSecondaryIDE
+	ret
+
+	; QD6500 has only one IDE channel that can be at 1F0h or 170h
+.DoesIdePortInDXbelongToQD6500:
+	test	al, FLG_QDCONFIG_PRIMARY_IDE
+	jz		SHORT .CompareBXtoSecondaryIDE
+	cmp		bx, DEVICE_ATA_DEFAULT_PORT
+	ret
+
+.CompareBXtoSecondaryIDE:
+	cmp		bx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
+.ReturnResultInZF:
+	ret
+
+
+;--------------------------------------------------------------------
+; Vision_GetMaxPioModeToAL
+;	Parameters:
+;		AL:		QD65xx Config Register contents
+;		AH:		QDI Vision Controller ID (bits 4...7)
+;	Returns:
+;		AL:		Max supported PIO mode
+;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
+;		CF:		Set if PIO limit necessary
+;				Cleared if no need to limit timings
+;	Corrupts registers:
+;		(AX if CF cleared)
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+Vision_GetMaxPioModeToAL:
+	cmp		ah, ID_QD6500 << 4
+	clc
+	jne		SHORT .NoNeedToLimitForQD6580
+
+	mov		ax, 2	; Limit to PIO 2 because QD6500 does not support IORDY
+	stc
+.NoNeedToLimitForQD6580:
+	ret
+
+
+;--------------------------------------------------------------------
+; Vision_InitializeWithIDinAHandConfigInAL
+;	Parameters:
+;		AL:		QD65xx Config Register contents
+;		AH:		QDI Vision Controller ID (bits 4...7)
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;		SI:		Offset to Master DPT if Slave Drive present
+;				Zero if Slave Drive not present
+;	Returns:
+;		CF:		Cleared if success
+;				Set if error
+;	Corrupts registers:
+;		AX, BX, CX, DX, BP
+;--------------------------------------------------------------------
+Vision_InitializeWithIDinAHandConfigInAL:
+	; QD6580 has a Control Register that needs to be programmed
+	mov		dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
+	cmp		ah, ID_QD6500 << 4
+	je		SHORT .CalculateTimingForQD6500
+
+	; Program QD6580 Control Register (not available on QD6500) to
+	; Enable or Disable Read-Ahead and Post-Write Buffer to match
+	; jumper setting on the multi I/O card.
+	xor		ax, ax
+	add		dx, BYTE QD6580_CONTROL_REGISTER
+	in		al, dx									; Read to get ATAPI jumper status
+	test	al, FLG_QDCONTROL_HDONLY_in
+	eCMOVNZ	ah, FLG_QDCONTROL_NONATAPI				; Enable Read-Ahead and Post-Write Buffers
+	or		ah, MASK_QDCONTROL_FLAGS_TO_SET
+	mov		al, ah
+	out		dx, al
+	sub		dx, BYTE QD6580_CONTROL_REGISTER
+
+	; Now we need to determine is the drive connected to the Primary or Secondary channel.
+	; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
+	; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
+	call	AccessDPT_GetIdeBasePortToBX
+	cmp		bx, DEVICE_ATA_DEFAULT_PORT
+	je		SHORT .CalculateTimingTicksForQD6580	; Primary Channel so no need to modify DX
+	times 2 inc dx									; Secondary Channel IDE Timing Register
+
+	; QD6500 and QD6580 require slightly different calculations.
+.CalculateTimingTicksForQD6580:
+	mov		bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)
+	jmp		SHORT .CalculateTimingsForQD65xx
+
+.CalculateTimingForQD6500:
+	mov		bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)
+
+	; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
+.CalculateTimingsForQD65xx:
+	call	AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
+
+	; Calculate Active Time value for QD65xx IDE Timing Register
+	call	AtaID_GetActiveTimeToAXfromPioModeInBX
+	call	ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
+	xchg	bp, ax
+
+	; Calculate Recovery Time value for QD65xx IDE Timing Register
+	call	AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
+	mov		bx, bp						; Active Time value now in BL
+	mov		bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
+	call	ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
+
+	; Merge the values to a single byte to output
+	eSHIFT_IM	al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
+	or		al, bl
+	out		dx, al
+	ret									; Return with CF cleared
+
+
+;--------------------------------------------------------------------
+; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
+;	Parameters:
+;		AX:		Nanosecs to convert
+;		BP:		Low Byte:	Maximum allowed ticks
+;				High Byte:	Minimum allowed ticks
+;		DS:DI:	Ptr to DPT for Single or Slave Drive
+;	Returns:
+;		AL:		Timing value for QD65xx register
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
+	push	cx
+
+	; Get VLB Cycle Time in nanosecs
+	mov		cl, VLB_33MHZ_CYCLE_TIME	; Assume 33 MHz or slower VLB bus
+	test	BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
+	eCMOVZ	cl, VLB_40MHZ_CYCLE_TIME
+
+	; Convert value in AX to VLB ticks
+	div		cl							; AL = VLB ticks
+	inc		ax							; Round up
+
+	; Limit value to QD65xx limits
+	mov		cx, bp
+	MAX_U	al, ch						; Make sure not below minimum
+	MIN_U	al, cl						; Make sure not above maximum
+
+	; Not done yet, we need to invert the ticks since 0 is the slowest
+	; value on the timing register
+	sub		cl, al
+	xchg	ax, cx						; Return in AL
+
+	pop		cx
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectDrives.asm	(revision 392)
@@ -55,5 +55,4 @@
 	jcxz	.AddHardDisks					; Set to zero on .ideVarsSerialAuto iteration (if any)
 %endif
-
 	loop	.DriveDetectLoop
 
@@ -155,4 +154,5 @@
 StartDetectionWithDriveSelectByteInBHandStringInCX:
 	call	DetectPrint_StartDetectWithMasterOrSlaveStringInCXandIdeVarsInCSBP
+	call	HotkeyBar_UpdateDuringDriveDetection
 	; Fall to .ReadAtaInfoFromHardDisk
 
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectPrint.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectPrint.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/DetectPrint.asm	(revision 392)
@@ -22,14 +22,28 @@
 
 ;--------------------------------------------------------------------
-; BootMenuPrint_InitializeDisplayContext
-;	Parameters:
-;		Nothing
-;	Returns:
-;		Nothing
-;	Corrupts registers:
-;		AX, DI
-;--------------------------------------------------------------------
-BootMenuPrint_InitializeDisplayContext:
-	CALL_DISPLAY_LIBRARY InitializeDisplayContext
+; DetectPrint_InitializeDisplayContext
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+DetectPrint_InitializeDisplayContext:
+	CALL_DISPLAY_LIBRARY	InitializeDisplayContext
+	ret
+
+
+;--------------------------------------------------------------------
+; DetectPrint_GetSoftwareCoordinatesToAX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+DetectPrint_GetSoftwareCoordinatesToAX:
+	CALL_DISPLAY_LIBRARY	GetSoftwareCoordinatesToAX
 	ret
 
@@ -186,5 +200,5 @@
 ;		Nothing
 ;	Corrupts registers:
-;		AX, SI, DI
+;		AX, DH, SI, DI
 ;--------------------------------------------------------------------
 DetectPrint_TryToBootFromDL:
@@ -192,15 +206,16 @@
 	mov		bp, sp
 
-	mov		ax, g_szHDD
-	test	dl, dl
-	js		SHORT .NotFDD
-	mov		ax, g_szFDD
-.NotFDD:
-	push	ax
-
-	call	DriveXlate_ToOrBack
-	push	dx					; Push untranslated drive number
-	call	DriveXlate_ToOrBack
-	push	dx					; Push translated drive number
+	call	DriveXlate_ToOrBack	; DL = Untranslated Drive number
+	mov		dh, dl
+	call	DriveXlate_ToOrBack	; DL = Translated Drive number
+
+	call	HotkeyBar_ConvertDriveNumberFromDLtoDriveLetter	; DL = Translated letter
+	xchg	dl, dh
+	call	HotkeyBar_ConvertDriveNumberFromDLtoDriveLetter	; DL = Untranslated letter
+	push	dx
+	xchg	dl, dh
+	push	dx
+
+	call	ConvertDriveLetterInDLtoDriveNumber	; Restore DL
 
 	mov		si, g_szTryToBoot
@@ -226,5 +241,5 @@
 	push	bp
 	mov		bp,sp
-	; Fall to BootMenuPrint_FormatCSSIfromParamsInSSBP
+	; Fall to DetectPrint_FormatCSSIfromParamsInSSBP
 
 ;--------------------------------------------------------------------
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/FloppyDrive.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/FloppyDrive.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/FloppyDrive.asm	(revision 392)
@@ -125,4 +125,5 @@
 ;		AX, CX, DX, DI, ES
 ;--------------------------------------------------------------------
+%ifdef MODULE_BOOT_MENU
 FloppyDrive_GetType:
 	mov		ah, 08h			; Get Drive Parameters
@@ -130,4 +131,5 @@
 	int		BIOS_DISKETTE_INTERRUPT_40h
 	ret
+%endif
 
 
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/Initialize.asm	(revision 392)
@@ -69,7 +69,8 @@
 ;--------------------------------------------------------------------
 Initialize_AndDetectDrives:
-	call	BootMenuPrint_InitializeDisplayContext
+	call	DetectPrint_InitializeDisplayContext
 	call	DetectPrint_RomFoundAtSegment
 	call	RamVars_Initialize
+	call	BootVars_Initialize
 	call	Interrupts_InitializeInterruptVectors
 	call	DetectDrives_FromAllIDEControllers
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Initialization/Interrupts.asm	(revision 392)
@@ -63,4 +63,9 @@
 	mov		si, Int13h_DiskFunctionsHandler		; Interrupt handler offset
 	call	Interrupts_InstallHandlerToVectorInALFromCSSI
+
+	; Install INT 19h handler to properly reset the system
+	mov		al, BIOS_BOOT_LOADER_INTERRUPT_19h	; INT 19h interrupt vector offset
+	mov		si, Int19hReset_Handler				; INT 19h handler to reboot the system
+	call	Interrupts_InstallHandlerToVectorInALFromCSSI
 	; Fall to .InitializeHardwareIrqHandlers
 
Index: trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Initialization/Vision.asm	(revision 391)
+++ 	(revision )
@@ -1,251 +1,0 @@
-; Project name	:	XTIDE Universal BIOS
-; Description	:	Functions for initializing QDI Vision
-;					QD6500 and QD6580 VLB IDE Controllers.
-
-;
-; XTIDE Universal BIOS and Associated Tools 
-; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
-;
-; 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; either version 2 of the License, or
-; (at your option) any later version.
-; 
-; This program is distributed in the hope that it will be useful,
-; but WITHOUT ANY WARRANTY; without even the implied warranty of
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-; GNU General Public License for more details.		
-; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
-;		
-
-; Section containing code
-SECTION .text
-
-;--------------------------------------------------------------------
-; Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent
-;	Parameters:
-;		Nothing
-;	Returns:
-;		AX:		ID WORD specific for QDI Vision Controllers
-;				(AL = QD65xx Config Register contents)
-;				(AH = QDI Vision Controller ID (bits 4...7))
-;		DX:		Controller port (not IDE port)
-;		ZF:		Set if controller found
-;				Cleared if supported controller not found (AX,DX = undefined)
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-Vision_DetectAndReturnIDinAXandPortInDXifControllerPresent:
-	; Check QD65xx base port
-	mov		dx, QD65XX_BASE_PORT
-	in		al, QD65XX_BASE_PORT + QD65XX_CONFIG_REGISTER_in
-	call	IsConfigRegisterWithIDinAL
-	je		SHORT VisionControllerDetected
-
-	; Check QD65xx alternative base port
-	or		dl, QD65XX_ALTERNATIVE_BASE_PORT
-	in		al, QD65XX_ALTERNATIVE_BASE_PORT + QD65XX_CONFIG_REGISTER_in
-	; Fall to IsConfigRegisterWithIDinAL
-
-;--------------------------------------------------------------------
-; IsConfigRegisterWithIDinAL
-;	Parameters:
-;		AL:		Possible QD65xx Config Register contents
-;	Returns:
-;		AH		QDI Vision Controller ID or undefined
-;		ZF:		Set if controller found
-;				Cleared if supported controller not found (AH = undefined)
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-IsConfigRegisterWithIDinAL:
-	mov		ah, al
-	and		al, MASK_QDCONFIG_CONTROLLER_ID
-	cmp		al, ID_QD6500 << 4
-	je		SHORT VisionControllerDetected
-	cmp		al, ID_QD6580 << 4
-	je		SHORT VisionControllerDetected
-	cmp		al, ID_QD6580_ALTERNATE << 4
-VisionControllerDetected:
-	xchg	ah, al
-	ret
-
-
-;--------------------------------------------------------------------
-; Vision_DoesIdePortInBXbelongToControllerWithIDinAX
-;	Parameters:
-;		AL:		QD65xx Config Register contents
-;		AH:		QDI Vision Controller ID (bits 4...7)
-;		BX:		IDE Base port to check
-;		DX:		Vision Controller port
-;	Returns:
-;		ZF:		Set if port belongs to controller
-;				Cleared if port belongs to another controller
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-Vision_DoesIdePortInBXbelongToControllerWithIDinAX:
-	cmp		ah, ID_QD6500 << 4
-	je		SHORT .DoesIdePortInDXbelongToQD6500
-
-	; QD6580 always have Primary IDE at 1F0h
-	; Secondary IDE at 170h can be enabled or disabled
-	cmp		bx, DEVICE_ATA_DEFAULT_PORT
-	je		SHORT .ReturnResultInZF
-
-	; Check if Secondary IDE channel is enabled
-	push	ax
-	add		dx, BYTE QD6580_CONTROL_REGISTER
-	in		al, dx
-	sub		dx, BYTE QD6580_CONTROL_REGISTER
-	test	al, FLG_QDCONTROL_SECONDARY_DISABLED_in
-	pop		ax
-	jz		SHORT .CompareBXtoSecondaryIDE
-	ret
-
-	; QD6500 has only one IDE channel that can be at 1F0h or 170h
-.DoesIdePortInDXbelongToQD6500:
-	test	al, FLG_QDCONFIG_PRIMARY_IDE
-	jz		SHORT .CompareBXtoSecondaryIDE
-	cmp		bx, DEVICE_ATA_DEFAULT_PORT
-	ret
-
-.CompareBXtoSecondaryIDE:
-	cmp		bx, DEVICE_ATA_DEFAULT_SECONDARY_PORT
-.ReturnResultInZF:
-	ret
-
-
-;--------------------------------------------------------------------
-; Vision_GetMaxPioModeToAL
-;	Parameters:
-;		AL:		QD65xx Config Register contents
-;		AH:		QDI Vision Controller ID (bits 4...7)
-;	Returns:
-;		AL:		Max supported PIO mode
-;		AH:		FLGH_DPT_IORDY if IORDY supported, zero otherwise
-;		CF:		Set if PIO limit necessary
-;				Cleared if no need to limit timings
-;	Corrupts registers:
-;		(AX if CF cleared)
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-Vision_GetMaxPioModeToAL:
-	cmp		ah, ID_QD6500 << 4
-	clc
-	jne		SHORT .NoNeedToLimitForQD6580
-
-	mov		ax, 2	; Limit to PIO 2 because QD6500 does not support IORDY
-	stc
-.NoNeedToLimitForQD6580:
-	ret
-
-
-;--------------------------------------------------------------------
-; Vision_InitializeWithIDinAHandConfigInAL
-;	Parameters:
-;		AL:		QD65xx Config Register contents
-;		AH:		QDI Vision Controller ID (bits 4...7)
-;		DS:DI:	Ptr to DPT for Single or Slave Drive
-;		SI:		Offset to Master DPT if Slave Drive present
-;				Zero if Slave Drive not present
-;	Returns:
-;		CF:		Cleared if success
-;				Set if error
-;	Corrupts registers:
-;		AX, BX, CX, DX, BP
-;--------------------------------------------------------------------
-Vision_InitializeWithIDinAHandConfigInAL:
-	; QD6580 has a Control Register that needs to be programmed
-	mov		dx, [di+DPT_ADVANCED_ATA.wControllerBasePort]
-	cmp		ah, ID_QD6500 << 4
-	je		SHORT .CalculateTimingForQD6500
-
-	; Program QD6580 Control Register (not available on QD6500) to
-	; Enable or Disable Read-Ahead and Post-Write Buffer to match
-	; jumper setting on the multi I/O card.
-	xor		ax, ax
-	add		dx, BYTE QD6580_CONTROL_REGISTER
-	in		al, dx									; Read to get ATAPI jumper status
-	test	al, FLG_QDCONTROL_HDONLY_in
-	eCMOVNZ	ah, FLG_QDCONTROL_NONATAPI				; Enable Read-Ahead and Post-Write Buffers
-	or		ah, MASK_QDCONTROL_FLAGS_TO_SET
-	mov		al, ah
-	out		dx, al
-	sub		dx, BYTE QD6580_CONTROL_REGISTER
-
-	; Now we need to determine is the drive connected to the Primary or Secondary channel.
-	; QD6500 has only one channel that can be Primary at 1F0h or Secondary at 170h.
-	; QD6580 always has Primary channel at 1F0h. Secondary channel at 170h can be Enabled or Disabled.
-	call	AccessDPT_GetIdeBasePortToBX
-	cmp		bx, DEVICE_ATA_DEFAULT_PORT
-	je		SHORT .CalculateTimingTicksForQD6580	; Primary Channel so no need to modify DX
-	times 2 inc dx									; Secondary Channel IDE Timing Register
-
-	; QD6500 and QD6580 require slightly different calculations.
-.CalculateTimingTicksForQD6580:
-	mov		bp, QD6580_MAX_ACTIVE_TIME_CLOCKS | (QD6580_MIN_ACTIVE_TIME_CLOCKS << 8)
-	jmp		SHORT .CalculateTimingsForQD65xx
-
-.CalculateTimingForQD6500:
-	mov		bp, QD6500_MAX_ACTIVE_TIME_CLOCKS | (QD6500_MIN_ACTIVE_TIME_CLOCKS << 8)
-
-	; We need the PIO Cycle Time in CX to calculate Active and Recovery Times.
-.CalculateTimingsForQD65xx:
-	call	AdvAtaInit_SelectSlowestCommonPioTimingsToBXandCXfromDSSIandDSDI
-
-	; Calculate Active Time value for QD65xx IDE Timing Register
-	call	AtaID_GetActiveTimeToAXfromPioModeInBX
-	call	ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
-	xchg	bp, ax
-
-	; Calculate Recovery Time value for QD65xx IDE Timing Register
-	call	AtaID_GetRecoveryTimeToAXfromPioModeInBXandCycleTimeInCX
-	mov		bx, bp						; Active Time value now in BL
-	mov		bp, QD65xx_MAX_RECOVERY_TIME_CLOCKS | (QD65xx_MIN_RECOVERY_TIME_CLOCKS << 8)
-	call	ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
-
-	; Merge the values to a single byte to output
-	eSHIFT_IM	al, POSITON_QD65XXIDE_RECOVERY_TIME, shl
-	or		al, bl
-	out		dx, al
-	ret									; Return with CF cleared
-
-
-;--------------------------------------------------------------------
-; ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue
-;	Parameters:
-;		AX:		Nanosecs to convert
-;		BP:		Low Byte:	Maximum allowed ticks
-;				High Byte:	Minimum allowed ticks
-;		DS:DI:	Ptr to DPT for Single or Slave Drive
-;	Returns:
-;		AL:		Timing value for QD65xx register
-;	Corrupts registers:
-;		Nothing
-;--------------------------------------------------------------------
-ConvertNanosecsFromAXwithLimitsInBPtoRegisterValue:
-	push	cx
-
-	; Get VLB Cycle Time in nanosecs
-	mov		cl, VLB_33MHZ_CYCLE_TIME	; Assume 33 MHz or slower VLB bus
-	test	BYTE [di+DPT_ADVANCED_ATA.wControllerID], FLG_QDCONFIG_ID3
-	eCMOVZ	cl, VLB_40MHZ_CYCLE_TIME
-
-	; Convert value in AX to VLB ticks
-	div		cl							; AL = VLB ticks
-	inc		ax							; Round up
-
-	; Limit value to QD65xx limits
-	mov		cx, bp
-	MAX_U	al, ch						; Make sure not below minimum
-	MIN_U	al, cl						; Make sure not above maximum
-
-	; Not done yet, we need to invert the ticks since 0 is the slowest
-	; value on the timing register
-	sub		cl, al
-	xchg	ax, cx						; Return in AL
-
-	pop		cx
-	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Main.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Main.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Main.asm	(revision 392)
@@ -34,9 +34,10 @@
 %define	EXCLUDE_FROM_XTIDE_UNIVERSAL_BIOS	; Exclude unused library functions
 %ifdef MODULE_BOOT_MENU
-	%define MENUEVENT_INLINE_OFFSETS    ; Only one menu required, save space and inline offsets
+	%define MENUEVENT_INLINE_OFFSETS    	; Only one menu required, save space and inline offsets
 	%define INCLUDE_MENU_LIBRARY
 
 %else	; If no boot menu included
 	%define	INCLUDE_DISPLAY_LIBRARY
+	%define INCLUDE_KEYBOARD_LIBRARY
 	%define INCLUDE_TIME_LIBRARY
 %endif
@@ -57,4 +58,5 @@
 	%include "RamVars.inc"			; For RAMVARS struct
 	%include "BootVars.inc"			; For BOOTVARS struct
+	%include "HotkeyBar.inc"		; For Hotkeys
 	%include "BootMenu.inc"			; For Boot Menu
 	%include "IDE_8bit.inc"			; For IDE 8-bit data port macros
@@ -212,4 +214,6 @@
 	%include "Interrupts.asm"		; For Interrupt initialization
 	%include "RamVars.asm"			; For RAMVARS initialization and access
+	%include "BootVars.asm"			; For initializing variabled used during init and boot
+	%include "FloppyDrive.asm"		; Floppy Drive related functions
 	%include "CreateDPT.asm"		; For creating DPTs
 	%include "FindDPT.asm"			; For finding DPTs
@@ -220,4 +224,5 @@
 	%include "DetectDrives.asm"		; For detecting IDE drives
 	%include "DetectPrint.asm"		; For printing drive detection strings
+	%include "HotkeyBar.asm"		; For hotkeys during drive detection and boot menu
 
 	; Boot menu
@@ -232,5 +237,5 @@
 	; Boot loader
 	%include "Int19h.asm"			; For Int 19h, Boot Loader
-	%include "FloppyDrive.asm"		; Floppy Drive related functions
+	%include "Int19hReset.asm"		; INT 19h handler for proper system reset
 	%include "BootSector.asm"		; For loading boot sector
 
Index: trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenu.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenu.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenu.asm	(revision 392)
@@ -0,0 +1,72 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Displays Boot Menu.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html		
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Displays Boot Menu and returns Drive or Function number.
+;
+; BootMenu_DisplayAndReturnSelectionInDX
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing, selected drive is converted to hotkey
+;	Corrupts registers:
+;		All General Purpose Registers
+;--------------------------------------------------------------------
+BootMenu_DisplayAndStoreSelectionAsHotkey:
+	call	DriveXlate_Reset
+
+	mov		bx, BootMenuEvent_Handler
+	CALL_MENU_LIBRARY	DisplayWithHandlerInBXandUserDataInDXAX
+
+	; Clear Boot Menu from screen
+	mov		ax, ' ' | (MONO_NORMAL<<8)
+	CALL_DISPLAY_LIBRARY	ClearScreenWithCharInALandAttrInAH
+	ret
+
+
+;--------------------------------------------------------------------
+; BootMenu_GetDriveToDXforMenuitemInCX
+;	Parameters:
+;		CX:		Index of menuitem selected from Boot Menu
+;	Returns:
+;		DX:		Drive number to be used for booting
+;		DS:		RAMVARS segment
+;       CF:     Set: There is a selected menu item, DL is valid
+;               Clear: There is no selected menu item, DL is not valid
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+BootMenu_GetDriveToDXforMenuitemInCX:
+	cmp		cl, NO_ITEM_HIGHLIGHTED
+	je		SHORT .ReturnFloppyDriveInDX	; Clear CF if branch taken
+
+	mov		dl, cl							; Copy menuitem index to DX
+	call	FloppyDrive_GetCountToAX
+	cmp		dl, al							; Floppy drive?
+	jb		SHORT .ReturnFloppyDriveInDX	; Set CF if branch taken
+	or		al, 80h							; Or 80h into AL before the sub
+											; to cause CF to be set after
+											; and result has high order bit set
+	sub		dl, al							; Remove floppy drives from index
+
+.ReturnFloppyDriveInDX:
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuEvent.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuEvent.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuEvent.asm	(revision 392)
@@ -0,0 +1,344 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Boot Menu event handler for menu library callbacks.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html		
+;		
+
+; Section containing code
+SECTION .text
+
+
+;--------------------------------------------------------------------
+; GetDefaultMenuitemToDL
+;	Parameters:
+;		DL:		Drive number
+;		ES:		Ptr to BDA (zero)
+;	Returns:
+;		DL:		Menuitem index (assuming drive is available)
+;	Corrupts registers:
+;		AX, DH
+;--------------------------------------------------------------------
+GetDefaultMenuitemToDX:
+	mov		dx, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wHddAndFddLetters]
+	test	BYTE [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFlags], FLG_HOTKEY_HD_FIRST
+	eCMOVZ	dl, dh
+	call	IsDriveDLinSystem
+	jnc		SHORT DoNotSetDefaultMenuitem
+	call	DriveXlate_SetDriveToSwap
+	; Fall to GetMenuitemToDXforDriveInDL
+
+
+;--------------------------------------------------------------------
+; GetMenuitemToDXforDriveInDL
+;	Parameters:
+;		DL:		Drive number
+;	Returns:
+;		DX:		Menuitem index (assuming drive is available)
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+GetMenuitemToDXforDriveInDL:
+	xor		dh, dh						; Drive number now in DX
+	test	dl, dl
+	jns		SHORT .ReturnItemIndexInDX	; Return if floppy drive (HD bit not set)
+	call	FloppyDrive_GetCountToAX
+	and		dl, ~80h					; Clear HD bit
+	add		dx, ax
+.ReturnItemIndexInDX:
+	ret
+
+
+;--------------------------------------------------------------------
+; IsDriveDLinSystem
+;	Parameters:
+;		DL:		Drive number
+;		DS:		RAMVARS segment
+;	Returns:
+;		CF:		Set if drive number is valid
+;				Clear if drive is not present in system
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+IsDriveDLinSystem:
+	test	dl, dl								; Floppy drive?
+	jns		SHORT .IsFloppyDriveInSystem
+	call	RamVars_GetHardDiskCountFromBDAtoAX	; Hard Disk count to AX
+	or		al, 80h								; Set Hard Disk bit to AX
+	jmp		SHORT .CompareDriveNumberToDriveCount
+.IsFloppyDriveInSystem:
+	call	FloppyDrive_GetCountToAX
+.CompareDriveNumberToDriveCount:
+	cmp		dl, al								; Set CF when DL is smaller
+	ret
+
+
+;--------------------------------------------------------------------
+; ConvertKeystrokeToAXfromDriveLetterInDL
+;	Parameters:
+;		DL:		Drive Letter ('A'...)
+;	Returns:
+;		AX:		Hotkey keystroke
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+ConvertKeystrokeToAXfromDriveLetterInDL:
+	eMOVZX	ax, dl
+	jmp		Char_ChangeCaseInAL	; Upper case drive letter to lower case keystroke
+
+
+;--------------------------------------------------------------------
+; BootMenuEvent_Handler
+;	Common parameters for all events:
+;		BX:			Menu event (anything from MENUEVENT struct)
+;		SS:BP:		Menu library handle
+;	Common return values for all events:
+;		CF:			Set if event processed
+;					Cleared if event not processed
+;	Corrupts registers:
+;		All
+;--------------------------------------------------------------------
+BootMenuEvent_Handler:
+	LOAD_BDA_SEGMENT_TO	es, di
+	call	RamVars_GetSegmentToDS
+
+%ifdef MENUEVENT_INLINE_OFFSETS
+
+	add		bx, FirstEvent
+	jmp		bx
+
+EventNotHandled:
+DoNotSetDefaultMenuitem:
+	xor		dx, dx		; Clear CF (and menuitem index for DoNotSetDefaultMenuitem)
+	ret
+
+MENUEVENT_InitializeMenuinitFromDSSI equ  (EventInitializeMenuinitFromSSBP - FirstEvent)
+MENUEVENT_ExitMenu equ  (BootMenuEvent_Completed - FirstEvent)
+MENUEVENT_ItemHighlightedFromCX equ (EventItemHighlightedFromCX - FirstEvent)
+MENUEVENT_ItemSelectedFromCX equ (EventItemSelectedFromCX - FirstEvent)
+MENUEVENT_KeyStrokeInAX equ (EventKeyStrokeInAX - FirstEvent)
+MENUEVENT_RefreshTitle equ (BootMenuPrint_TitleStrings - FirstEvent)
+MENUEVENT_RefreshInformation equ (BootMenuPrint_RefreshInformation - FirstEvent)
+MENUEVENT_RefreshItemFromCX equ (BootMenuPrint_RefreshItem - FirstEvent)
+;
+; Note that there is no entry for MENUEVENT_IdleProcessing.  If MENUEVENT_IDLEPROCESSING_ENABLE is not %defined,
+; then the entry point will not be called (saving memory on this end and at the CALL point).
+;
+
+%else
+
+	cmp		bx, BYTE MENUEVENT.RefreshItemFromCX	; Above last supported item?
+	ja		SHORT EventNotHandled
+	jmp		[cs:bx+rgfnEventSpecificHandlers]
+
+EventNotHandled:
+DoNotSetDefaultMenuitem:
+	xor		dx, dx		; Clear CF (and menuitem index for DoNotSetDefaultMenuitem)
+	ret
+
+rgfnEventSpecificHandlers:
+	dw		EventInitializeMenuinitFromSSBP		; MENUEVENT.InitializeMenuinitFromDSSI
+	dw		EventCompleted						; MENUEVENT.ExitMenu
+	dw		EventNotHandled						; MENUEVENT.IdleProcessing
+	dw		EventItemHighlightedFromCX			; MENUEVENT.ItemHighlightedFromCX
+	dw		EventItemSelectedFromCX				; MENUEVENT.ItemSelectedFromCX
+	dw		EventKeyStrokeInAX					; MENUEVENT.KeyStrokeInAX
+	dw		BootMenuPrint_TitleStrings			; MENUEVENT.RefreshTitle
+	dw		BootMenuPrint_RefreshInformation	; MENUEVENT.RefreshInformation
+	dw		BootMenuPrint_RefreshItem			; MENUEVENT.RefreshItemFromCX
+
+%endif
+
+
+;--------------------------------------------------------------------
+; EventInitializeMenuinitFromSSBP
+;	Parameters
+;		DS:		Ptr to RAMVARS
+;		ES:		Ptr to BDA (zero)
+;		SS:BP:	Ptr to MENUINIT struct to initialize
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+FirstEvent:	
+EventInitializeMenuinitFromSSBP:
+	; Store default Menuitem (=default drive to boot from)
+	call	GetDefaultMenuitemToDX
+	mov		[bp+MENUINIT.wHighlightedItem], dx
+
+	; Store number of Menuitems
+	call	RamVars_GetHardDiskCountFromBDAtoAX
+	xchg	ax, cx
+	call	FloppyDrive_GetCountToAX
+	add		ax, cx
+	mov		[bp+MENUINIT.wItems], ax
+
+	; Store menu size
+	mov		WORD [bp+MENUINIT.wTitleAndInfoLines], BOOT_MENU_TITLE_AND_INFO_LINES
+	mov		BYTE [bp+MENUINIT.bWidth], BOOT_MENU_WIDTH
+	add		al, BOOT_MENU_HEIGHT_WITHOUT_ITEMS
+	xchg	cx, ax
+	CALL_DISPLAY_LIBRARY	GetColumnsToALandRowsToAH
+	sub		ah, MENU_SCREEN_BOTTOM_LINES*2	; Leave space for Hotkey Bar
+	MIN_U	ah, cl
+	mov		[bp+MENUINIT.bHeight], ah
+
+	; Store selection timeout
+	mov		ax, [cs:ROMVARS.wBootTimeout]
+	CALL_MENU_LIBRARY StartSelectionTimeoutWithTicksInAX
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; EventItemHighlightedFromCX
+;	Parameters
+;		CX:		Index of new highlighted item
+;		DX:		Index of previously highlighted item or NO_ITEM_HIGHLIGHTED
+;		DS:		Ptr to RAMVARS
+;		ES:		Ptr to BDA (zero)
+;		SS:BP:	Menu library handle
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+EventItemHighlightedFromCX:
+	push	cx
+	call	BootMenu_GetDriveToDXforMenuitemInCX		
+	call	DriveXlate_Reset
+	call	DriveXlate_SetDriveToSwap
+
+	; We need to generate keystroke so selection two drives is possible.
+	; The secondary boot drive is selected by highlighting it using menu keys
+	; and the primary boot drive is selected by pressing drive letter hotkey.
+	call	HotkeyBar_ConvertDriveNumberFromDLtoDriveLetter
+	call	ConvertKeystrokeToAXfromDriveLetterInDL
+	call	HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
+	call	RedrawHotkeyBarFromInsideMenuEventHandler
+
+	; Redraw changes in drive numbers
+	xor		ax, ax	; Update first floppy drive (for translated drive number)
+	CALL_MENU_LIBRARY	RefreshItemFromAX
+	mov		dl, 80h
+	call	GetMenuitemToDXforDriveInDL
+	xchg	ax, dx	; Update first hard disk (for translated drive number)
+	CALL_MENU_LIBRARY	RefreshItemFromAX
+	pop		ax		; Update new item (for translated drive number)
+	CALL_MENU_LIBRARY	RefreshItemFromAX
+	CALL_MENU_LIBRARY	RefreshInformation
+	stc
+	ret
+
+
+;--------------------------------------------------------------------
+; EventItemSelectedFromCX
+;	Parameters
+;		CX:		Index of selected item
+;		DS:		Ptr to RAMVARS
+;		ES:		Ptr to BDA (zero)
+;		SS:BP:	Menu library handle
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+EventItemSelectedFromCX:
+	call	BootMenu_GetDriveToDXforMenuitemInCX
+	jnc		SHORT BootMenuEvent_Completed	; No menuitem selected
+
+	; Convert selected drive to hotkey keystroke
+	call	HotkeyBar_ConvertDriveNumberFromDLtoDriveLetter
+	call	ConvertKeystrokeToAXfromDriveLetterInDL
+	; Fall to EventKeyStrokeInAX
+
+
+;--------------------------------------------------------------------
+; EventKeyStrokeInAX
+;	Parameters
+;		AL:		ASCII character for the key
+;		AH:		Keyboard library scan code for the key
+;		DS:		Ptr to RAMVARS
+;		ES:		Ptr to BDA (zero)
+;		SS:BP:	Menu library handle
+;	Returns:
+;		CF:		Set if event processed
+;				Cleared if event not processed
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+EventKeyStrokeInAX:
+	cmp		ah, BOOT_MENU_HOTKEY_SCANCODE
+	je		SHORT BootMenuEvent_Completed	; Ignore Boot Menu hotkey
+	call	HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
+	jnc		SHORT BootMenuEvent_Completed
+
+	; Hotkey is now stored to BOOTVARS and menu can be closed
+	; Fall to CloseBootMenu
+
+
+;--------------------------------------------------------------------
+; CloseBootMenu
+;	Parameters
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+CloseBootMenu:
+	call	DriveXlate_Reset
+	CALL_MENU_LIBRARY	Close
+	; Fall to RedrawHotkeyBarFromInsideMenuEventHandler
+
+
+;--------------------------------------------------------------------
+; RedrawHotkeyBarFromInsideMenuEventHandler
+;	Parameters
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+RedrawHotkeyBarFromInsideMenuEventHandler:
+	mov		al, MONO_NORMAL
+	CALL_DISPLAY_LIBRARY	SetCharacterAttributeFromAL
+
+	mov		bl, ATTRIBUTES_ARE_USED
+	mov		ax, TELETYPE_OUTPUT_WITH_ATTRIBUTE
+	CALL_DISPLAY_LIBRARY	SetCharOutputFunctionFromAXwithAttribFlagInBL
+	call	HotkeyBar_DrawToTopOfScreen
+	; Fall to BootMenuEvent_Completed
+
+
+;--------------------------------------------------------------------
+; BootMenuEvent_Completed
+;	Parameters
+;		Nothing
+;	Returns:
+;		CF:		Set to exit from menu
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+BootMenuEvent_Completed:
+	stc
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrint.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrint.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrint.asm	(revision 392)
@@ -0,0 +1,219 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for printing boot menu strings.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; BootMenuPrint_RefreshItem
+;
+;	Parameters:
+;		CX:		Index of highlighted item
+;		DS:		RAMVARS segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+BootMenuPrint_RefreshItem:
+	call	BootMenu_GetDriveToDXforMenuitemInCX
+	jnc		BootMenuEvent_Completed					; if no menu item selected, out we go
+
+	push	bp
+	mov		bp, sp
+
+	call	FindDPT_ForDriveNumberInDL
+	jc		.notOurs
+
+	call	BootMenuInfo_ConvertDPTtoBX
+	mov		si, g_szDriveNumBOOTNFO					; special g_szDriveNum that prints from BDA
+	jmp		.go
+
+.notOurs:
+	mov		si,g_szDriveNum
+	mov		bx,g_szForeignHD						; assume a hard disk for the moment
+
+	test	dl, dl
+	js		.go
+	mov		bl,((g_szFloppyDrv)-$$ & 0xff)			; and revisit the earlier assumption...
+
+.go:
+	mov		ax, dx									; preserve DL for the floppy drive letter addition
+	call	DriveXlate_ToOrBack
+	push	dx										; translated drive number
+	push	bx										; sub string
+	add		al, 'A'									; floppy drive letter (we always push this although
+	push	ax										; the hard disks don't ever use it, but it does no harm)
+
+	jmp		SHORT BootMenuPrint_RefreshInformation.FormatRelay
+
+;--------------------------------------------------------------------
+; Prints Boot Menu title strings.
+;
+; BootMenuPrint_TitleStrings
+;	Parameters:
+;		Nothing
+;	Returns:
+;		CF:		Set since menu event handled
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+BootMenuPrint_TitleStrings:
+	mov		si, ROMVARS.szTitle
+	call	DetectPrint_NullTerminatedStringFromCSSIandSetCF
+	CALL_DISPLAY_LIBRARY PrintNewlineCharacters
+	mov		si, ROMVARS.szVersion
+	jmp		DetectPrint_NullTerminatedStringFromCSSIandSetCF
+
+
+;--------------------------------------------------------------------
+; BootMenuPrint_RefreshInformation
+;	Parameters:
+;		CX:		Index of highlighted item
+;		DS:		RAMVARS segment
+;	Returns:
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		Does not matter
+;--------------------------------------------------------------------
+BootMenuPrint_RefreshInformation:
+	CALL_MENU_LIBRARY ClearInformationArea
+
+	call	BootMenu_GetDriveToDXforMenuitemInCX
+	jnc		BootMenuEvent_Completed						; if no menu selection, abort
+
+	push	bp
+	mov		bp, sp
+
+	mov		si, g_szCapacity							; Setup print string now, carries through to print call
+
+	call	FindDPT_ForDriveNumberInDL
+
+	inc		dl											; are we a hard disk?
+	dec		dl											; inc/dec will set SF, without modifying CF or DL
+	js		.HardDiskRefreshInformation
+
+	jnc		.ours										; Based on CF from FindDPT_ForDriveNumberInDL above
+	call	FloppyDrive_GetType							; Get Floppy Drive type to BX
+	jmp		.around
+.ours:
+	call	AH8h_GetDriveParameters
+.around:
+
+	mov		ax, g_szFddSizeOr	        				; .PrintXTFloppyType
+	test	bl, bl										; Two possibilities? (FLOPPY_TYPE_525_OR_35_DD)
+	jz		SHORT .PushAXAndOutput
+
+	mov		al, (g_szFddUnknown - $$) & 0xff	        ; .PrintUnknownFloppyType
+	cmp		bl, FLOPPY_TYPE_35_ED
+	ja		SHORT .PushAXAndOutput
+
+	; Fall to .PrintKnownFloppyType
+
+;--------------------------------------------------------------------
+; .PrintKnownFloppyType
+;	Parameters:
+;		BX:		Floppy drive type
+;	Returns:
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		AX, BX, SI, DI
+;
+; Floppy Drive Types:
+;
+;   0  Handled above
+;   1  FLOPPY_TYPE_525_DD          5 1/4   360K
+;   2  FLOPPY_TYPE_525_HD          5 1/4   1.2M
+;   3  FLOPPY_TYPE_35_DD           3 1/2   720K
+;   4  FLOPPY_TYPE_35_HD           3 1/2   1.44M
+;   5  3.5" ED on some BIOSes      3 1/2   2.88M
+;   6  FLOPPY_TYPE_35_ED		   3 1/2   2.88M
+;   >6 Unknwon, handled above
+;
+;--------------------------------------------------------------------
+.PrintKnownFloppyType:
+	mov		al, (g_szFddSize - $$) & 0xff
+	push	ax
+
+	mov		al, (g_szFddThreeHalf - $$) & 0xff
+	cmp		bl, FLOPPY_TYPE_525_HD
+	ja		.ThreeHalf
+	mov		al, (g_szFddFiveQuarter - $$) & 0xff
+.ThreeHalf:
+	push	ax											; "5 1/4" or "3 1/2"
+
+	mov		al,FloppyTypes.rgbCapacityMultiplier
+	mov		bh, 0
+	mul		byte [cs:bx+FloppyTypes.rgbCapacity - 1]    ; -1 since 0 is handled above and not in the table
+
+.PushAXAndOutput:
+	push	ax
+
+.FormatRelay:
+	jmp		DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; Prints Hard Disk Menuitem information strings.
+;
+; BootMenuPrint_HardDiskMenuitemInformation
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		CF:		Set since menu event was handled successfully
+;	Corrupts registers:
+;		BX, CX, DX, SI, DI, ES
+;--------------------------------------------------------------------
+.HardDiskRefreshInformation:
+	jc		.HardDiskMenuitemInfoForForeignDrive		; Based on CF from FindDPT_ForDriveNumberInDL (way) above
+
+.HardDiskMenuitemInfoForOurDrive:
+	ePUSH_T ax, g_szInformation							; Add substring for our hard disk information
+	call	BootMenuInfo_GetTotalSectorCount			; Get Total LBA Size
+	jmp		.ConvertSectorCountInBXDXAXtoSizeAndPushForFormat
+
+.HardDiskMenuitemInfoForForeignDrive:
+	call	DriveXlate_ToOrBack
+	call	AH15h_GetSectorCountFromForeignDriveToDXAX
+
+.ConvertSectorCountInBXDXAXtoSizeAndPushForFormat:
+	ePUSH_T	cx, g_szCapacityNum		; Push format substring
+	call	Size_ConvertSectorCountInBXDXAXtoKiB
+	mov		cx, BYTE_MULTIPLES.kiB
+	call	Size_GetSizeToAXAndCharToDLfromBXDXAXwithMagnitudeInCX
+	push	ax						; Size in magnitude
+	push	cx						; Tenths
+	push	dx						; Magnitude character
+
+	test	di,di
+	jz		SHORT BootMenuPrint_RefreshInformation.FormatRelay
+
+%include "BootMenuPrintCfg.asm"			; inline of code to fill out remainder of information string
+	jmp		DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+FloppyTypes:
+.rgbCapacityMultiplier equ 20	        ; Multiplier to reduce word sized values to byte size
+.rgbCapacity:
+	db		360   / FloppyTypes.rgbCapacityMultiplier    ;  type 1
+	db		1200  / FloppyTypes.rgbCapacityMultiplier    ;  type 2
+	db		720   / FloppyTypes.rgbCapacityMultiplier    ;  type 3
+	db		1440  / FloppyTypes.rgbCapacityMultiplier    ;  type 4
+	db		2880  / FloppyTypes.rgbCapacityMultiplier    ;  type 5
+	db		2880  / FloppyTypes.rgbCapacityMultiplier    ;  type 6
Index: trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrintCfg.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrintCfg.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Menus/BootMenu/BootMenuPrintCfg.asm	(revision 392)
@@ -0,0 +1,142 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for printing drive configuration
+;					information on Boot Menu.
+; 
+; Included by BootMenuPrint.asm, this routine is to be inserted into
+; BootMenuPrint_HardDiskRefreshInformation.
+;
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;
+				
+; Section containing code
+SECTION .text
+
+;;; fall-into from BootMenuPrint_HardDiskRefreshInformation.
+
+;--------------------------------------------------------------------
+; Prints Hard Disk configuration for drive handled by our BIOS.
+; Cursor is set to configuration header string position.
+;
+; BootMenuPrintCfg_ForOurDrive
+;	Parameters:
+;		DS:DI:		Pointer to DPT
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, BX, CX, DX
+;--------------------------------------------------------------------
+.BootMenuPrintCfg_ForOurDrive:
+	eMOVZX	ax, [di+DPT.bIdevarsOffset]
+	xchg	bx, ax						; CS:BX now points to IDEVARS
+	; Fall to .PushAndFormatCfgString
+
+;--------------------------------------------------------------------
+; PushAddressingMode
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (jumps to next push below)
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+.PushAddressingMode:
+	AccessDPT_GetUnshiftedAddressModeToALZF
+	;;
+	;; This multiply both shifts the addressing mode bits down to low order bits, and
+	;; at the same time multiplies by the size of the string displacement.  The result is in AH,
+	;; with AL clear, and so we exchange AL and AH after the multiply for the final result.
+	;;
+	mov		cl,(1<<(8-ADDRESSING_MODE_FIELD_POSITION)) * g_szAddressingModes_Displacement
+	mul		cl
+	xchg	al,ah
+	add		ax,g_szAddressingModes
+	push	ax
+
+;--------------------------------------------------------------------
+; PushBlockMode
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+.PushBlockMode:
+	mov		ax, 1
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_BLOCK_MODE_SUPPORTED
+	jz		SHORT .PushBlockSizeFromAX
+	mov		al, [di+DPT_ATA.bBlockSize]
+.PushBlockSizeFromAX:
+	push	ax
+
+;--------------------------------------------------------------------
+; PushBusType
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (jumps to next push below)
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+.PushBusType:
+	mov		al,g_szBusTypeValues_Displacement
+	mul		BYTE [cs:bx+IDEVARS.bDevice]
+
+	shr		ax,1			; divide by 2 since IDEVARS.bDevice is multiplied by 2
+
+	add		ax,g_szBusTypeValues
+	push	ax
+
+;--------------------------------------------------------------------
+; PushIRQ
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX, DX
+;--------------------------------------------------------------------
+.PushIRQ:
+	mov		al, [cs:bx+IDEVARS.bIRQ]
+	cbw
+	push	ax
+
+;--------------------------------------------------------------------
+; PushResetStatus
+;	Parameters:
+;		DS:DI:	Ptr to DPT
+;		CS:BX:	Ptr to IDEVARS
+;	Returns:
+;		Nothing (falls to next push below)
+;	Corrupts registers:
+;		AX, BX, DX, ES
+;--------------------------------------------------------------------
+.PushResetStatus:
+	xor		ax, ax
+%ifdef MODULE_SERIAL
+	test	BYTE [di+DPT.bFlagsHigh], FLGH_DPT_SERIAL_DEVICE
+	jnz		SHORT .AlwaysSuccess
+	mov		al, [di+DPT_ATA.bInitError]
+.AlwaysSuccess:
+%endif
+	push	ax
+
+;;; fall-out to BootMenuPrint_HardDiskRefreshInformation.
Index: trunk/XTIDE_Universal_BIOS/Src/Menus/HotkeyBar.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Menus/HotkeyBar.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/Menus/HotkeyBar.asm	(revision 392)
@@ -0,0 +1,473 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Hotkey Bar related functions.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html		
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; HotkeyBar_UpdateDuringDriveDetection
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+HotkeyBar_UpdateDuringDriveDetection:
+	call	ScanHotkeysFromKeyBufferAndStoreToBootvars
+	; Fall to HotkeyBar_DrawToTopOfScreen
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_DrawToTopOfScreen
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+HotkeyBar_DrawToTopOfScreen:
+	; Store current screen coordinates to be restored
+	; when Hotkey Bar is rendered
+	call	DetectPrint_GetSoftwareCoordinatesToAX
+	push	ax
+
+	call	MoveCursorToScreenTopLeftCorner
+	; Fall to .PrintFloppyDriveHotkeys
+
+;--------------------------------------------------------------------
+; .PrintFloppyDriveHotkeys
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.PrintFloppyDriveHotkeys:
+	call	FloppyDrive_GetCountToAX
+	test	ax, ax		; Any Floppy Drives?
+	jz		SHORT .SkipFloppyDriveHotkeys
+
+	mov		di, DEFAULT_FLOPPY_DRIVE_LETTER | (ANGLE_QUOTE_RIGHT<<8)
+	mov		cl, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFddLetter]
+	mov		si, g_szFDD
+	call	FormatDriveHotkeyString
+
+.SkipFloppyDriveHotkeys:
+	; Fall to .PrintHardDriveHotkeys
+
+;--------------------------------------------------------------------
+; .PrintHardDriveHotkeys
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+	call	HotkeyBar_GetLetterForFirstHardDriveToAX
+	mov		ah, ANGLE_QUOTE_RIGHT
+	xchg	di, ax
+	mov		cl, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bHddLetter]
+	mov		si, g_szHDD
+	call	FormatDriveHotkeyString
+	; Fall to .PrintBootMenuHotkey
+
+;--------------------------------------------------------------------
+; .PrintBootMenuHotkey
+;	Parameters:
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.PrintBootMenuHotkey:
+%ifdef MODULE_BOOT_MENU
+	mov		ah, BOOT_MENU_HOTKEY_SCANCODE
+	mov		di, 'F' | ('2'<<8)		; F2
+	mov		si, g_szBootMenu
+	call	FormatFunctionHotkeyString
+%endif
+	; Fall to .PrintRomBootHotkey
+
+;--------------------------------------------------------------------
+; .PrintRomBootHotkey
+;	Parameters:
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+.PrintRomBootHotkey:
+	mov		ah, ROM_BOOT_HOTKEY_SCANCODE
+	mov		di, 'F' | ('8'<<8)		; F8
+	mov		si, g_szRomBoot
+	call	FormatFunctionHotkeyString
+	; Fall to .EndHotkeyBarRendering
+
+;--------------------------------------------------------------------
+; .EndHotkeyBarRendering
+;	Parameters:
+;		Stack:	Screen coordinates before drawing Hotkey Bar
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+.EndHotkeyBarRendering:
+	call	HotkeyBar_ClearRestOfTopRow
+	pop		ax
+	jmp		SHORT HotkeyBar_RestoreCursorCoordinatesFromAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_ClearRestOfTopRow
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+HotkeyBar_ClearRestOfTopRow:
+	CALL_DISPLAY_LIBRARY	GetColumnsToALandRowsToAH
+	eMOVZX	cx, al
+	CALL_DISPLAY_LIBRARY	GetSoftwareCoordinatesToAX
+	sub		cl, al
+	mov		al, ' '
+	CALL_DISPLAY_LIBRARY	PrintRepeatedCharacterFromALwithCountInCX
+	ret
+
+
+;--------------------------------------------------------------------
+; FormatDriveHotkeyString
+;	Parameters:
+;		CL:			Drive letter hotkey from BOOTVARS
+;		DI low:		First character for drive key string
+;		DI high:	Second character for drive key string (ANGLE_QUOTE_RIGHT)
+;		SI:			Offset to hotkey description string
+;		ES:			BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+FormatDriveHotkeyString:
+	ePUSH_T	ax, PushHotkeyParamsAndFormat
+	jmp		SHORT GetNonSelectedHotkeyDescriptionAttributeToDX
+
+
+;--------------------------------------------------------------------
+; FormatFunctionHotkeyString
+;	Parameters:
+;		AH:			Hotkey scancode to compare with BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode
+;		SI:			Offset to hotkey description string
+;		DI low:		First character for drive key string
+;		DI high:	Second character for drive key string
+;		ES:			BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, SI, DI
+;--------------------------------------------------------------------
+FormatFunctionHotkeyString:
+	ePUSH_T	ax, PushHotkeyParamsAndFormat
+	mov		cx, g_szBoot		; Description parameter string
+	cmp		[es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode], ah
+	jne		SHORT GetNonSelectedHotkeyDescriptionAttributeToDX
+	; Fall to GetSelectedHotkeyDescriptionAttributeToDX
+
+
+;--------------------------------------------------------------------
+; GetSelectedHotkeyDescriptionAttributeToDX
+; GetNonSelectedHotkeyDescriptionAttributeToDX
+;	Parameters:
+;		CF:		Set if selected hotkey
+;				Cleared if unselected hotkey
+;	Returns:
+;		DX:		Description Attribute
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+%ifdef MODULE_BOOT_MENU
+GetSelectedHotkeyDescriptionAttributeToDX:
+	push	si
+	mov		si, ATTRIBUTE_CHARS.cHurryTimeout		; Selected hotkey
+	jmp		SHORT GetDescriptionAttributeToDX
+
+GetNonSelectedHotkeyDescriptionAttributeToDX:
+	push	si
+	mov		si, ATTRIBUTE_CHARS.cHighlightedItem	; Unselected hotkey
+
+	; Display Library should not be called like this
+GetDescriptionAttributeToDX:
+	call	MenuAttribute_GetToAXfromTypeInSI
+	pop		si
+	xchg	dx, ax					; DX = Description attribute
+	ret
+
+%else	; No boot menu so use simpler attributes
+
+GetSelectedHotkeyDescriptionAttributeToDX:
+	mov		dl, MONO_REVERSE_BLINK
+	ret
+
+GetNonSelectedHotkeyDescriptionAttributeToDX:
+	mov		dl, MONO_REVERSE
+	ret
+%endif
+
+
+;--------------------------------------------------------------------
+; PushHotkeyParamsAndFormat
+;	Parameters:
+;		DI low:		First character
+;		DI high:	Second character
+;		DX:			Description Attribute
+;		CX:			Description string parameter
+;		CS:SI:		Description string
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, SI, DI
+;--------------------------------------------------------------------
+PushHotkeyParamsAndFormat:
+	push	bp
+	mov		bp, sp
+
+	mov		ax, MONO_BRIGHT
+	push	ax				; Key attribute
+	xchg	ax, di
+	push	ax				; First character
+	xchg	al, ah
+	push	ax				; Second character
+
+	push	dx				; Description attribute
+	push	si				; Description string
+	push	cx				; Description string parameter
+
+	push	di				; Key attribute for last space
+	mov		si, g_szHotkey
+	jmp		DetectPrint_FormatCSSIfromParamsInSSBP
+
+
+;--------------------------------------------------------------------
+; MoveCursorToScreenTopLeftCorner
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+MoveCursorToScreenTopLeftCorner:
+	xor		ax, ax			; Top left corner (0, 0)
+	; Fall to HotkeyBar_RestoreCursorCoordinatesFromAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_RestoreCursorCoordinatesFromAX
+;	Parameters:
+;		Nothing
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, DI
+;--------------------------------------------------------------------
+HotkeyBar_RestoreCursorCoordinatesFromAX:
+	CALL_DISPLAY_LIBRARY	SetCursorCoordinatesFromAX
+	ret
+
+
+;--------------------------------------------------------------------
+; ScanHotkeysFromKeyBufferAndStoreToBootvars
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX
+;--------------------------------------------------------------------
+ScanHotkeysFromKeyBufferAndStoreToBootvars:
+	call	Keyboard_GetKeystrokeToAX
+	jz		SHORT NoHotkeyToProcess
+
+	ePUSH_T	cx, ScanHotkeysFromKeyBufferAndStoreToBootvars
+	; Fall to HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX
+;	Parameters:
+;		AL:		Hotkey ASCII code
+;		AH:		Hotkey Scancode
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		CF:		Set if valid keystroke
+;				Clear if invalid keystroke
+;	Corrupts registers:
+;		AX, CX, DI
+;--------------------------------------------------------------------
+HotkeyBar_StoreHotkeyToBootvarsIfValidKeystrokeInAX:
+	; Boot menu
+%ifdef MODULE_BOOT_MENU
+	cmp		ah, BOOT_MENU_HOTKEY_SCANCODE	; Display Boot Menu?
+	je		SHORT .StoreFunctionHotkeyFromAH
+%endif
+
+	; ROM Boot
+	cmp		ah, ROM_BOOT_HOTKEY_SCANCODE	; ROM Boot?
+	je		SHORT .StoreFunctionHotkeyFromAH
+
+	; Drive letter hotkeys remaining, allow 'a' to 'z'
+	call	Char_IsLowerCaseLetterInAL
+	jnc		SHORT .KeystrokeIsNotValidHotkey
+	call	Char_ChangeCaseInAL		; We want to print upper case letters
+
+	; Clear HD First flag to assume Floppy Drive hotkey
+	mov		di, BOOTVARS.hotkeyVars+HOTKEYVARS.bFlags
+	and		BYTE [es:di], ~FLG_HOTKEY_HD_FIRST
+
+	; Determine if Floppy or Hard Drive hotkey
+	eMOVZX	cx, al					; Clear CH to clear scancode
+	call	HotkeyBar_GetLetterForFirstHardDriveToAX
+	cmp		cl, al
+	jb		SHORT .StoreDriveLetter	; Store Floppy Drive letter
+
+	; Store Hard Drive letter
+	or		BYTE [es:di], FLG_HOTKEY_HD_FIRST
+
+.StoreDriveLetter:
+	adc		di, BYTE 0			; Add 1 if Floppy Drive
+	xchg	ax, cx
+	mov		[es:di+1], al		; AH = zero to clear function hotkey
+
+.StoreFunctionHotkeyFromAH:
+	mov		[es:BOOTVARS.hotkeyVars+HOTKEYVARS.bScancode], ah
+	stc		; Valid hotkey
+
+.KeystrokeIsNotValidHotkey:
+NoHotkeyToProcess:
+	ret
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_GetSecondaryBootDriveNumberToDL
+; HotkeyBar_GetPrimaryBootDriveNumberToDL
+;	Parameters:
+;		DS:		RAMVARS segment
+;		ES:		BDA segment (zero)
+;	Returns:
+;		DL:		Drive selected as boot device
+;	Corrupts registers:
+;		AX, DH
+;--------------------------------------------------------------------
+HotkeyBar_GetSecondaryBootDriveNumberToDL:
+	mov		dx, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wHddAndFddLetters]
+	xchg	dl, dh
+	jmp		SHORT GetBootDriveNumberFromLettersInDX
+
+HotkeyBar_GetPrimaryBootDriveNumberToDL:
+	mov		dx, [es:BOOTVARS.hotkeyVars+HOTKEYVARS.wHddAndFddLetters]
+GetBootDriveNumberFromLettersInDX:
+	test	BYTE [es:BOOTVARS.hotkeyVars+HOTKEYVARS.bFlags], FLG_HOTKEY_HD_FIRST
+	eCMOVZ	dl, dh
+	; Fall to ConvertDriveLetterInDLtoDriveNumber
+
+
+;--------------------------------------------------------------------
+; ConvertDriveLetterInDLtoDriveNumber
+;	Parameters:
+;		DS:		RAMVARS segment
+;		DL:		Drive letter ('A'...)
+;	Returns:
+;		DL:		Drive number (0xh for Floppy Drives, 8xh for Hard Drives)
+;	Corrupts registers:
+;		AX, DH
+;--------------------------------------------------------------------
+ConvertDriveLetterInDLtoDriveNumber:
+	call	HotkeyBar_GetLetterForFirstHardDriveToAX
+	cmp		dl, al
+	jb		SHORT .ConvertLetterInDLtoFloppyDriveNumber
+
+	; Convert letter in DL to Hard Drive number
+	sub		dl, al
+	or		dl, 80h
+	ret
+
+.ConvertLetterInDLtoFloppyDriveNumber:
+	sub		dl, DEFAULT_FLOPPY_DRIVE_LETTER
+	ret
+
+
+;--------------------------------------------------------------------
+; HotkeyBar_ConvertDriveNumberFromDLtoDriveLetter
+;	Parameters:
+;		DL:		Drive number (0xh for Floppy Drives, 8xh for Hard Drives)
+;		DS:		RAMVARS Segment
+;	Returns:
+;		DL:		Drive letter ('A'...)
+;		CF:		Set if Hard Drive
+;				Clear if Floppy Drive
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+HotkeyBar_ConvertDriveNumberFromDLtoDriveLetter:
+	test	dl, dl
+	jns		SHORT .GetDefaultFloppyDrive
+
+	; Store default hard drive to boot from
+	call	HotkeyBar_GetLetterForFirstHardDriveToAX
+	sub		dl, 80h
+	add		dl, al
+	stc
+	ret
+
+.GetDefaultFloppyDrive:
+	add		dl, DEFAULT_FLOPPY_DRIVE_LETTER		; Clears CF
+	ret
+
+
+;--------------------------------------------------------------------
+; Returns letter for first hard disk. Usually it will be 'C' but it
+; can be higher if more than two floppy drives are found.
+;
+; HotkeyBar_GetLetterForFirstHardDriveToAX
+;	Parameters:
+;		DS:		RAMVARS segment
+;	Returns:
+;		AX:		Upper case letter for first hard disk
+;	Corrupts registers:
+;		Nothing
+;--------------------------------------------------------------------
+HotkeyBar_GetLetterForFirstHardDriveToAX:
+	call	FloppyDrive_GetCountToAX
+	add		al, DEFAULT_FLOPPY_DRIVE_LETTER
+	MAX_U	al, DEFAULT_HARD_DRIVE_LETTER
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/Strings.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/Strings.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/Strings.asm	(revision 392)
@@ -73,8 +73,9 @@
 
 ; Boot loader strings
-g_szTryToBoot:			db	"Booting from %s %x",ANGLE_QUOTE_RIGHT,"%x",LF,CR,NULL
+g_szTryToBoot:			db	"Booting %c",ANGLE_QUOTE_RIGHT,"%c",LF,CR,NULL
 g_szBootSectorNotFound:	db	"Boot sector "
 g_szNotFound:			db	"not found",LF,CR,NULL
 g_szReadError:			db	"Error %x!",LF,CR,NULL
+
 
 g_szAddressingModes:
@@ -143,8 +144,10 @@
 
 ; Boot menu bottom of screen strings
-g_szFDD:		db	"FDD     ",NULL
-g_szHDD:		db	"HDD     ",NULL
-g_szRomBoot:	db	"ROM Boot",NULL
-g_szHotkey:		db	"%A%c%c%A%s%A ",NULL
+g_szFDD:		db	"FDD [%c]",NULL			; "FDD [A]"
+g_szHDD:		db	"HDD [%c]",NULL			; "HDD [C]"
+g_szBootMenu:	db	"%sMnu",NULL			; "BootMnu"
+g_szRomBoot:	db	"Rom%s",NULL			; "RomBoot"
+g_szBoot:		db	"Boot",NULL
+g_szHotkey:		db	"%A%c%c%A%s%A ",NULL	; "C»HDD [A] ", "F2BootMnu " or "F8RomBoot "
 
 ; Boot Menu information strings
@@ -227,4 +230,2 @@
 ;
 ;------------------------------------------------------------------------------------------
-
-
Index: trunk/XTIDE_Universal_BIOS/Src/StringsCompressed.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/StringsCompressed.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/StringsCompressed.asm	(revision 392)
@@ -26,5 +26,5 @@
 ; GNU General Public License for more details.
 ; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html		
-;				
+;		
 
 %ifdef MODULE_STRINGS_COMPRESSED_PRECOMPRESS
@@ -128,7 +128,7 @@
 
 ; Boot loader strings
-g_szTryToBoot:			; db	"Booting from %s %x",ANGLE_QUOTE_RIGHT,"%x",LF,CR,NULL
-              			; db	 42h,  6fh,  6fh,  74h,  69h,  6eh,  67h,  20h,  66h,  72h,  6fh,  6dh,  20h,  25h,  73h,  20h,  25h,  78h, 0afh,  25h,  78h,  0ah,  0dh,  00h    ; uncompressed
-              			  db	 48h,  75h,  75h,  7ah,  6fh,  74h, 0edh,  6ch,  78h,  75h, 0f3h,  3eh,  20h,  39h,  24h,  39h,  1bh                                              ; compressed
+g_szTryToBoot:			; db	"Booting %c",ANGLE_QUOTE_RIGHT,"%c",LF,CR,NULL
+              			; db	 42h,  6fh,  6fh,  74h,  69h,  6eh,  67h,  20h,  25h,  63h, 0afh,  25h,  63h,  0ah,  0dh,  00h    ; uncompressed
+              			  db	 48h,  75h,  75h,  7ah,  6fh,  74h, 0edh,  35h,  24h,  35h,  1bh                                  ; compressed
 
 g_szBootSectorNotFound:	; db	"Boot sector "
@@ -143,4 +143,5 @@
               			; db	 45h,  72h,  72h,  6fh,  72h,  20h,  25h,  78h,  21h,  0ah,  0dh,  00h    ; uncompressed
               			  db	 4bh,  78h,  78h,  75h, 0f8h,  39h,  25h,  1bh                            ; compressed
+
 
 
@@ -249,17 +250,25 @@
 
 ; Boot menu bottom of screen strings
-g_szFDD:		; db	"FDD     ",NULL
-        		; db	 46h,  44h,  44h,  20h,  20h,  20h,  20h,  20h,  00h    ; uncompressed
-        		  db	 4ch,  4ah, 0cah,  20h,  20h,  20h,  00h                ; compressed
-
-g_szHDD:		; db	"HDD     ",NULL
-        		; db	 48h,  44h,  44h,  20h,  20h,  20h,  20h,  20h,  00h    ; uncompressed
-        		  db	 4eh,  4ah, 0cah,  20h,  20h,  20h,  00h                ; compressed
-
-g_szRomBoot:	; db	"ROM Boot",NULL
-            	; db	 52h,  4fh,  4dh,  20h,  42h,  6fh,  6fh,  74h,  00h    ; uncompressed
-            	  db	 58h,  55h, 0d3h,  48h,  75h,  75h, 0bah                ; compressed
-
-g_szHotkey:		; db	"%A%c%c%A%s%A ",NULL
+g_szFDD:		; db	"FDD [%c]",NULL			; "FDD [A]"
+        		; db	 46h,  44h,  44h,  20h,  5bh,  25h,  63h,  5dh,  00h    ; uncompressed
+        		  db	 4ch,  4ah, 0cah,  61h,  35h, 0a3h                      ; compressed
+
+g_szHDD:		; db	"HDD [%c]",NULL			; "HDD [C]"
+        		; db	 48h,  44h,  44h,  20h,  5bh,  25h,  63h,  5dh,  00h    ; uncompressed
+        		  db	 4eh,  4ah, 0cah,  61h,  35h, 0a3h                      ; compressed
+
+g_szBootMenu:	; db	"%sMnu",NULL			; "BootMnu"
+             	; db	 25h,  73h,  4dh,  6eh,  75h,  00h    ; uncompressed
+             	  db	 3eh,  53h,  74h, 0bbh                ; compressed
+
+g_szRomBoot:	; db	"Rom%s",NULL			; "RomBoot"
+            	; db	 52h,  6fh,  6dh,  25h,  73h,  00h    ; uncompressed
+            	  db	 58h,  75h,  73h,  1eh                ; compressed
+
+g_szBoot:		; db	"Boot",NULL
+         		; db	 42h,  6fh,  6fh,  74h,  00h    ; uncompressed
+         		  db	 48h,  75h,  75h, 0bah          ; compressed
+
+g_szHotkey:		; db	"%A%c%c%A%s%A ",NULL	; "C»HDD [A] ", "F2BootMnu " or "F8RomBoot "
            		; db	 25h,  41h,  25h,  63h,  25h,  63h,  25h,  41h,  25h,  73h,  25h,  41h,  20h,  00h    ; uncompressed
            		  db	 3dh,  35h,  35h,  3dh,  3eh,  3dh,  00h                                              ; compressed
@@ -371,6 +380,4 @@
 ; End of StringsCompress.pl information
 ;
-;------------------------------------------------------------------------------------------
-
 ;;; end of input stream
 
@@ -455,5 +462,5 @@
 ;; translated usage stats
 ;; 33:1
-;; 32:31
+;; 32:22
 ;; 181:1
 ;; 53:2
@@ -481,10 +488,10 @@
 ;; 2-u:1
 ;; 5-u:2
-;; x:7
-;; s:12
+;; x:5
+;; s:13
 ;; 5-x:1
 ;; nl:8
 ;; 2-I:1
-;; c:5
+;; c:9
 ;; u:6
 ;; z:1
@@ -513,5 +520,5 @@
 ;; 77,M:4
 ;; 78,N:1
-;; 79,O:2
+;; 79,O:1
 ;; 80,P:2
 ;; 81,Q:1
@@ -525,7 +532,7 @@
 ;; 89,Y:
 ;; 90,Z:
-;; 91,[:
+;; 91,[:2
 ;; 92,\:
-;; 93,]:
+;; 93,]:2
 ;; 94,^:
 ;; 95,_:
@@ -536,5 +543,5 @@
 ;; 100,d:6
 ;; 101,e:15
-;; 102,f:2
+;; 102,f:1
 ;; 103,g:2
 ;; 104,h:
@@ -544,17 +551,17 @@
 ;; 108,l:5
 ;; 109,m:1
-;; 110,n:10
+;; 110,n:11
 ;; 111,o:17
 ;; 112,p:3
 ;; 113,q:
-;; 114,r:12
+;; 114,r:11
 ;; 115,s:7
 ;; 116,t:12
-;; 117,u:3
+;; 117,u:4
 ;; 118,v:3
 ;; 119,w:1
 ;; 120,x:
 ;; 121,y:2
-;; alphabet used count: 42
+;; alphabet used count: 44
 %endif ; STRINGSCOMPRESSED_TABLES
 
Index: trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootMenuInfo.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootMenuInfo.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootMenuInfo.asm	(revision 392)
@@ -0,0 +1,101 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for generating and accessing drive
+;					information to be displayed on boot menu.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html				
+;
+				
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; Creates new BOOTMENUINFO struct for detected hard disk.
+;
+; BootMenuInfo_CreateForHardDisk
+;	Parameters:
+;		DL:		Drive number
+;		DS:DI:	Ptr to Disk Parameter Table
+;		ES:SI:	Ptr to 512-byte ATA information read from the drive
+;	Returns:
+;		ES:BX:	Ptr to BOOTMENUINFO (if successful)
+;	Corrupts registers:
+;		AX, BX, CX, DX, DI
+;--------------------------------------------------------------------
+BootMenuInfo_CreateForHardDisk:
+	call	BootMenuInfo_ConvertDPTtoBX			; ES:BX now points to new BOOTMENUINFO
+
+	; Store Drive Name
+	push	ds									; Preserve RAMVARS
+	push	si
+
+	push	es									; ES copied to DS
+	pop		ds
+
+	add		si, BYTE ATA1.strModel				; DS:SI now points drive name
+	lea		di, [bx+BOOTMENUINFO.szDrvName]		; ES:DI now points to name destination
+	mov		cx, MAX_HARD_DISK_NAME_LENGTH / 2	; Max number of WORDs allowed
+.CopyNextWord:
+	lodsw
+	xchg	al, ah								; Change endianness
+	stosw
+	loop	.CopyNextWord
+	xor		ax, ax								; Zero AX and clear CF
+	stosw										; Terminate with NULL
+
+	pop		si
+	pop		ds
+		
+	ret
+
+
+;--------------------------------------------------------------------
+; BootMenuInfo_GetTotalSectorCount
+;	Parameters:
+;		DS:DI:		DPT Pointer
+;	Returns:
+;		BX:DX:AX:	48-bit sector count
+;	Corrupts registers:
+;		CX
+;--------------------------------------------------------------------
+%ifdef MODULE_BOOT_MENU
+BootMenuInfo_GetTotalSectorCount:
+	test	BYTE [di+DPT.bFlagsLow], FLG_DRVNHEAD_LBA
+	jnz		SHORT .ReturnFullCapacity
+	jmp		AH15h_GetSectorCountToBXDXAX
+.ReturnFullCapacity:
+	jmp		AccessDPT_GetLbaSectorCountToBXDXAX
+%endif
+
+
+;--------------------------------------------------------------------
+; Returns offset to BOOTMENUINFO based on DPT pointer.
+;
+; BootMenuInfo_ConvertDPTtoBX
+;	Parameters:
+;		DS:DI:	DPT Pointer
+;	Returns:
+;		BX:		Offset to BOOTMENUINFO struct
+;	Corrupts registers:
+;		AX
+;--------------------------------------------------------------------
+BootMenuInfo_ConvertDPTtoBX:
+	mov		ax, di
+	sub		ax, BYTE RAMVARS_size					; subtract off base of DPTs
+	mov		bl, DPT_BOOTMENUINFO_SIZE_MULTIPLIER	; BOOTMENUINFO's are a whole number multiple of DPT size
+	mul		bl								
+	add		ax, BOOTVARS.rgBootNfo					; add base of BOOTMENUINFO
+	xchg	ax, bx
+	ret	
Index: trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootVars.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootVars.asm	(revision 392)
+++ trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/BootVars.asm	(revision 392)
@@ -0,0 +1,60 @@
+; Project name	:	XTIDE Universal BIOS
+; Description	:	Functions for accessings BOOTVARS.
+
+;
+; XTIDE Universal BIOS and Associated Tools 
+; Copyright (C) 2009-2010 by Tomi Tilli, 2011-2012 by XTIDE Universal BIOS Team.
+;
+; 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; either version 2 of the License, or
+; (at your option) any later version.
+; 
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU General Public License for more details.		
+; Visit http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+;		
+
+; Section containing code
+SECTION .text
+
+;--------------------------------------------------------------------
+; BootVars_Initialize
+;	Parameters:
+;		DS:		RAMVARS Segment
+;		ES:		BDA Segment
+;	Returns:
+;		Nothing
+;	Corrupts registers:
+;		AX, CX, DX, DI
+;--------------------------------------------------------------------
+BootVars_Initialize:
+	; Clear to zero
+	mov		al, BOOTMENUINFO_size
+	mul		BYTE [cs:ROMVARS.bIdeCnt]
+	mov		di, BOOTVARS.hotkeyVars	; We must not initialize anything before this!
+	add		ax, BOOTVARS_size
+	sub		ax, di
+	xchg	cx, ax
+	call	Memory_ZeroESDIwithSizeInCX
+
+	; Store default drives to boot from
+	mov		di, BOOTVARS.hotkeyVars+HOTKEYVARS.wHddAndFddLetters
+	call	HotkeyBar_GetLetterForFirstHardDriveToAX
+	mov		ah, DEFAULT_FLOPPY_DRIVE_LETTER
+	mov		[es:di], ax
+
+	; Check if boot drive is overridden in ROMVARs
+	mov		al, [cs:ROMVARS.bBootDrv]
+	test	al, al
+	js		SHORT .StoreUserHardDiskToBootFrom
+	inc		di
+	jmp		SHORT .AddToDefaultDrive
+
+.StoreUserHardDiskToBootFrom:
+	sub		al, 80h					; Clear HD bit
+.AddToDefaultDrive:
+	add		[es:di], al
+	ret
Index: trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm
===================================================================
--- trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/Src/VariablesAndDPTs/RamVars.asm	(revision 392)
@@ -146,5 +146,5 @@
 ;		CX
 ;--------------------------------------------------------------------
-ALIGN JUMP_ALIGN
+%ifdef MODULE_BOOT_MENU
 RamVars_GetHardDiskCountFromBDAtoAX:
 	call	RamVars_GetCountOfKnownDrivesToAX
@@ -155,4 +155,6 @@
 	pop		ds
 	ret
+%endif
+
 
 ;--------------------------------------------------------------------
Index: trunk/XTIDE_Universal_BIOS/makefile
===================================================================
--- trunk/XTIDE_Universal_BIOS/makefile	(revision 391)
+++ trunk/XTIDE_Universal_BIOS/makefile	(revision 392)
@@ -54,9 +54,9 @@
 HEADERS += Inc/Controllers/
 HEADERS += Src/
-HEADERS += Src/Boot/
 HEADERS += Src/Handlers/
 HEADERS += Src/Handlers/Int13h/
 HEADERS += Src/Handlers/Int13h/EBIOS/
 HEADERS += Src/Handlers/Int13h/Tools/
+HEADERS += Src/Handlers/Int19h/
 HEADERS += Src/Device/
 HEADERS += Src/Device/IDE/
@@ -64,4 +64,7 @@
 HEADERS += Src/Device/Serial/
 HEADERS += Src/Initialization/
+HEADERS += Src/Initialization/AdvancedAta/
+HEADERS += Src/Menus/
+HEADERS += Src/Menus/BootMenu/
 HEADERS += Src/Libraries/
 HEADERS += Src/VariablesAndDPTs/
@@ -86,16 +89,16 @@
 # Assembler preprocessor defines.                               #
 #################################################################
-DEFINES_COMMON = MODULE_BOOT_MENU MODULE_EBIOS MODULE_STRINGS_COMPRESSED
+DEFINES_COMMON = MODULE_STRINGS_COMPRESSED MODULE_EBIOS
 
 DEFINES_XT = ELIMINATE_CGA_SNOW MODULE_SERIAL MODULE_SERIAL_FLOPPY
-DEFINES_XTPLUS = ELIMINATE_CGA_SNOW USE_186 MODULE_SERIAL MODULE_SERIAL_FLOPPY
-DEFINES_AT = USE_286 USE_AT MODULE_SERIAL MODULE_SERIAL_FLOPPY
-
-DEFINES_XT_LARGE = $(DEFINES_XT) MODULE_JRIDE MODULE_ADVANCED_ATA
-DEFINES_XTPLUS_LARGE = $(DEFINES_XTPLUS) MODULE_JRIDE MODULE_ADVANCED_ATA
-DEFINES_AT_LARGE = $(DEFINES_AT) MODULE_JRIDE MODULE_ADVANCED_ATA
+DEFINES_XTPLUS = USE_186 ELIMINATE_CGA_SNOW MODULE_SERIAL MODULE_SERIAL_FLOPPY
+DEFINES_AT = USE_AT USE_286 MODULE_SERIAL MODULE_SERIAL_FLOPPY MODULE_ADVANCED_ATA
+
+DEFINES_XT_LARGE = $(DEFINES_XT) MODULE_BOOT_MENU MODULE_JRIDE MODULE_ADVANCED_ATA
+DEFINES_XTPLUS_LARGE = $(DEFINES_XTPLUS) MODULE_BOOT_MENU MODULE_JRIDE MODULE_ADVANCED_ATA
+DEFINES_AT_LARGE = $(DEFINES_AT) MODULE_BOOT_MENU MODULE_JRIDE MODULE_ADVANCED_ATA
 
 DEFINES_JRIDE_8K = ELIMINATE_CGA_SNOW MODULE_JRIDE
-DEFINES_386_8K = USE_386 USE_AT MODULE_ADVANCED_ATA
+DEFINES_386_8K = USE_AT USE_386 MODULE_ADVANCED_ATA
 
 
