;       SCCSID = @(#)debugdd.asm	6.1 90/11/17
PAGE	,132
TITLE	Debugger Device Driver for MSDOS
NAME	DEBUGDD
.286p

;***	DEBUGDD - Debugger Device Driver for MSDOS
;
;	SCCSID = @(#)debugdd.asm	13.6 90/04/17
;
;	Copyright (C) Microsoft Corp. 1982, 1983, 1984, 1985

PMDEBUG	equ	1

	include	basemaca.inc
	include dosseg.inc
	include	devsym.inc
	include	debseg.inc
	include	debmac.inc
	include	debequ.inc
	include debinit.inc

	extrn	_Debug_Entry:far

DATA		segment

		public	ABIOS_present
ABIOS_present	db	0

		public	state_A20
state_A20	db	0

DATA		ends


DataSegmentStart

Static	ExtCmdTable, LABEL, BYTE
	db	'?'
	dw	codeOFFSET Help

	db	'B'
	dw	codeOFFSET SetBaudCmd

	db	'R'
	dw	codeOFFSET RebootCmd

	db	0
	dw	perr

Static	HelpMsg, LABEL, BYTE
	db	"B <baud rate> [<port addr>] - set COM baud rate/port addr (1 = COM1, 2 = COM2)"
	db	CR,LF
	db	"REBOOT - reboots machine"
	db	CR,LF
	db	0

DD_mesg DB	"--- Installing DEBUG Device Driver v8.05 ---", 13, 10, '$'

InitData	DebugInit <DBGCODE, DBGDATA, 0, 0, 0, 0, 0, 0, (INIT_REALFLAG + INIT_CTRLCFLAG), ' ', 0, 0, 8, 0000000001111111b, 0, 0, DebCallOutRoutine>

DataSegmentEnd


CodeSegmentStart

Extern	CmdBreak, NEAR
Extern	perr, NEAR
Extern	OEMInitCom, NEAR
Extern	OEMOutputChar, NEAR
Extern	OEMScanChar, NEAR
Extern	OEMEnableNMI, NEAR
Extern	OEMEnableA20, NEAR
Extern	OEMRestoreA20, NEAR
Extern	OEMBreakChk, NEAR
Extern	OEMBeep, NEAR
Extern	SetBaudCmd, NEAR
Extern	RebootCmd, NEAR

;***	Device Driver Header
;

DD_Start	EQU	$

DevHeader	dw	0FFFFh,0FFFFh
		dw	DEV_CHAR_DEV
		dw	DDStrategy
		dw	DDInterrupt
		db	"$DEBUGDD"


;------------------------------------------------------------------------
;	Device Data Area

DevHlp		dd	?		; pointer to dos "helper" functions

;	Command dispatch table

DDTable		dw	1		; Highest function allowed
		dw	DevInit		;  0  Initialization
;	end of device functions
		dw	CmdErr		; 13  Command Error Routine

;------------------------------------------------------------------------
;	Device Entry Points

;***	DDInterrupt - Device Driver "Interrupt" Entry point
;
;	Not Used

DDInterrupt PROC FAR
	ret
DDInterrupt ENDP


;***	DDStrategy - Device Driver "Strategy" Entry point
;
;	Handles the common "setup" code for the device driver entry
;	points.  It saves the necessary registers and fill them with
;	various useful values and addresses.  Finally, it dispatches
;	throught the dispatch table.
;
;	ENTRY	ES:BX	points to Request packet
;	EXIT
;	USES	AX, SI
;

DDStrategy PROC FAR
	push	cx
	push	dx
	push	di
	push	bp
	push	ds
	push	es
	push	bx

	mov	si,codeOFFSET DDTable	; (CS:SI) = address of dispatch table
	push	es
	pop	ds			; DS:BX also points to packet

	mov	al,ds:[bx].PktCmd	; Get device command
	xor	ah,ah
	cmp	ax,cs:[si]		; check command against table limit
	jbe	dds_cmdok		; command is valid
	mov	ax,cs:[si]		; last command is an error handler
dds_cmdok:
	inc	ax			; don't dispatch to limit value!
	shl	ax,1
	add	si,ax			; (CS:SI) = address of handler addr
	mov	al,ds:[bx].PktUnit	;AL = Unit code
	mov	ah,ds:[bx].IOmedia	;AH = Media descriptor
	mov	cx,ds:[bx].IOcount	;CX = Count
	mov	dx,ds:[bx].IOstart	;DX = Start sector
	les	di,dword ptr ds:[bx].IOpData	; ES:DI = buffer addr

;	AL	  Unit code from packet
;	AH	  Media descriptor from packet
;	CX	  Count from packet
;	DX	  Start sector from packet
;	ES:DI	Buffer address from packet
;	DS:BX	Packet address
;	SS	  TaskArea segment( from DOS call )
;
	call	word ptr cs:[si]	; Do request

	pop	bx
	pop	es
	mov	es:word ptr [bx].PktStatus,ax	 ;mark operation complete
	pop	ds
	pop	bp
	pop	di
	pop	dx
	pop	cx
	ret				;restore regs and return
DDStrategy ENDP


CmdErr PROC NEAR			; Bad device command number
	xor	ax,ax
	mov	[bx].IOcount,ax		; No chars transfered
	mov	al,3			; Unknown command error
	mov	ah,(STDON+STERR)/256	; Done + Error
	ret
CmdErr ENDP


;***	DevInit - Initialization Function 0
;
;	ENTRY	DS:BX = pointer to Request Packet
;		ES:DI = Dos DevHlp function entry point address
;
;	EXIT	Request Packet filled in
;
;	USES

DevInit PROC NEAR
	mov	word ptr DevHlp,di
	mov	word ptr DevHlp + 2,es
	mov	word ptr ds:[bx].InitpEnd,offset DOSGROUP:DD_End
	mov	word ptr ds:[bx].InitpEnd + 2,DBGCODE
	mov	ax,DBGDATA
	mov	ds,ax
	mov	es,ax
	mov	dx,dataOFFSET DD_mesg
	mov	ah,9
	int	21h
	Pcall	CpuID
	mov	di,dataOFFSET InitData
	sidt	[di].RealIDTaddr
	call	_Debug_Entry
	mov	ax, STDON		; Done
	ret
DevInit ENDP


CallOutTable	label	word
	.errnz	DEB_CALLOUT_INIT_COM-0
	dw	codeOFFSET OEMInitCom

	.errnz	DEB_CALLOUT_OUTPUT_CHAR-1
	dw	codeOFFSET OEMOutputChar

	.errnz	DEB_CALLOUT_SCAN_CHAR-2
	dw	codeOFFSET OEMScanChar

	.errnz	DEB_CALLOUT_ENABLE_NMI-3
	dw	codeOFFSET OEMEnableNMI

	.errnz	DEB_CALLOUT_ENABLE_A20-4
	dw	codeOFFSET OEMEnableA20

	.errnz	DEB_CALLOUT_RESTORE_A20-5
	dw	codeOFFSET OEMRestoreA20

	.errnz	DEB_CALLOUT_EXTCMD-6
	dw	codeOFFSET ExtCmdRoutine

	.errnz	DEB_CALLOUT_DEBENTRY-7
	dw	codeOFFSET NullRoutine

	.errnz	DEB_CALLOUT_DEBEXIT-8
	dw	codeOFFSET NullRoutine

	.errnz	DEB_CALLOUT_DEBINIT-9
	dw	codeOFFSET NullRoutine

	.errnz	DEB_CALLOUT_DEBEND-10
	dw	codeOFFSET NullRoutine

	.errnz	DEB_CALLOUT_GETCURRTASK-11
	dw	codeOFFSET NullRoutine

	.errnz	DEB_CALLOUT_GETDESCINFO-12
	dw	codeOFFSET DebGetDescInfo

	.errnz	DEB_CALLOUT_BREAK-13
	dw	codeOFFSET OEMBreakChk

	.errnz	DEB_CALLOUT_BEEP-14
	dw	codeOFFSET OEMBeep

	.errnz	DEB_CALLOUT_MAX + 1 - (($ - CallOutTable)/2)

;***	DebCallOutRoutine
;
;	ENTRY:	(FuncCode)
;
;	EXIT:	Depends on function code
;
;	USES:	Depends on function code
;
	ASSUME	DS:NOTHING, ES:NOTHING, SS:NOTHING

DefProc DebCallOutRoutine,FAR,LOCAL

ArgVar	FuncCode,WORD

BeginProc
	push	bx
	mov	bx,FuncCode
	shl	bx,1
	mov	bx,CallOutTable[bx]
	mov	FuncCode,bx
	pop	bx
	call	FuncCode
EndProc

;***	NullRoutine
;

DefProc	NullRoutine,NEAR,LOCAL
EndProc

;***	DebGetDescInfo
;

DefProc	DebGetDescInfo
	xor	ax,ax
	stc
EndProc

;***	ExtCmdRoutine
;
;	This routine executes the external debugger commands.
;
;	ENTRY:	NONE
;
;	EXIT:	NONE
;
;	USES:	ALL
;

DefProc ExtCmdRoutine, NEAR, PUBLIC
	Pcall	GetChrI				; (AL) = command letter
	jnz	ecr1
	jmp	perr

ecr1:	mov	si,dataOFFSET ExtCmdTable	; (SI) = address of cmd table
	Pcall	ExecSubr			; execute command
EndProc


;***	Help
;
;	This prints the help menu.
;
;	ENTRY:	NONE
;
;	EXIT:	NONE
;
;	USES:	ALL
;

DefProc Help, NEAR, LOCAL
	mov	dx,dataOFFSET HelpMsg
	Pcall	rprbuf
EndProc


DefProc	Xreboot, NEAR, PUBLIC
EndProc

DefProc KDPObjInfo, NEAR, C
EndProc

;***	CpuID - Set processor type (386 vs. 8088/86/286).
;
;	This routine relies on Intel-approved code that takes advantage
;	of the documented behavior of the high nibble of the flag word
;	in the REAL MODE of the various processors.  The MSB (bit 15)
;	is always a one on the 8086 and 8088 and a zero on the 286 and
;	386.  Bit 14 (NT flag) and bits 13/12 (IOPL bit field) are
;	always zero on the 286, but can be set on the 386.
;
;	For future compatibility of this test, it is strongly recommended
;	that this specific instruction sequence be used.  The exit codes
;	can of course be changed to fit a particular need.
;
;	CALLABLE FROM REAL MODE ONLY
;
;	ENTRY:	NONE
;
;	EXIT:	NONE
;
;	USES:	AX, DS
;
	ASSUME DS:DBGDATA, ES:DBGDATA, SS:NOTHING

DefProc	CpuID,NEAR,LOCAL
	pushf				; save flags during cpu test

	xor	ax,ax			; 0000 into AX
	push	ax			; push immediate is bad op-code on 8086
	POPFF				; try to put that in the flags

	pushf
	pop	ax			; look at what really went into flags

	and	ah,0f0h			; mask off high flag bits
	cmp	ah,0f0h			; Q: was high nibble all ones ?
	jz	cidx			;   Y: 8086 - InternalError

	push	0f000h			;   N: try to set the high bits
	POPFF				;      ... in the flags

	pushf
	pop	ax			; look at actual flags

	and	ah,0f0h			; Q: any high bits set ?
	jz	cidx			;   N: 80286 - exit w/ Z flag set
					;   Y: 80386 - Z flag reset
	or	InitData.InitFlag,INIT_CPU386

cidx:	POPFF				; restore flags after cpu test

EndProc

ENDHIGH3CODE SEGMENT

DD_End	equ	$

ENDHIGH3CODE ENDS

CodeSegmentEnd

	END
