title MORROW 80188 Slave Debugger page 62, 132 .list ;**************************************************************************** ; ; MBUG ; ; MORROW 80188 debugger. ; ; This debugger is written for the MORROW 80188 slave board. The ; debugger will use the serial port attached to the I/O connector ; as the console port. The commands are single letter commands ; and behave as they are described below. Where possible, the ; syntax is kept as close to the 'debug' utility syntax under MSDOS. ; The commands currently supported are: ; ; d - dumps memory in hexadecimal and ascii. ; e - allows modification of memory one byte at a time. ; f - fill memory block with value. ; i - displays value at input port. ; m - move block of memory. ; o - output byte value to output port. ; j - start executing at address. ; ; The debugger is intended to be burned into ROM. For debugging ; purposes, the code was first written to run under MSDOS 2.0. ; The hardware drivers are then replaced with the ones for the ; slave card before burning into ROM. This version of code ; contains the hardware drivers for the Morrow slave card. ; ; The debugger is contained in 2 files. They are MBUG.ASM and ; MFUNCT.ASM. MBUG.ASM contains the main scanner and parser of ; commands and MFUNCT.ASM contains the code for the specific ; functions of the debugger. ; ; The debugger should be assembled and linked as follows for the ; MSDOS version: ; masm mbug; * this generates MBUG.OBJ ; link mbug; * this produces MBUG.EXE ; ; The file MBUG.EXE can then be run under MSDOS for testing. ; ; ; MODIFICATIONS: ; ; 5/7/84 written Raymond Yu ; 5/15/84 V1.0 completed RYU ; tested under MSDOS 2.0 ; 6/4/84 revised for ROM RYU ; renamed 'mbugrom.asm' ; 'mfunct.asm' remains ; ;**************************************************************************** data segment para public 'data' ;********************************************************************** ; ; S100 80188 slave board constant and address definitions ; ;********************************************************************** ; 80188 internal control registers cntrl_base equ 0ff00h ; base addr of 80188 control ports ; in I/O space, this is the default ; addr immediately after a reset umcs equ cntrl_base+0a0h ; addr of upper memory select reg lmcs equ cntrl_base+0a2h ; addr of lower memory select reg mpcs equ cntrl_base+0a8h ; addr of middle memory select reg mmcs equ cntrl_base+0a6h ; addr of middle memory select reg pacs equ cntrl_base+0a4h ; addr of peripheral select reg ; 80188 control register initialization values UMCSVAL equ 0ff38h ; 4K byte block, 0 wait states, ; use external ready LMCSVAL equ 03ff8h ; 256K byte block, 0 wait states, ; use external ready MPCSVAL equ 0a0bfh ; 256K byte block in 64K byte incr, ; 7 PCS lines mapped into I/O space MMCSVAL equ 041f8h ; middle ram starts at 256K, ; 0 wait states, use external ready PACSVAL equ 0003fh ; PCS decoding starts at 0 in ; I/O space, 3 wait states, ; ignore external ready ;********** 8250 UART constant and address definitions **************** uart_base equ 0 ; addr of uart in I/O space ; UART registers uartdata equ uart_base+0 ; data register for uart .. DLAB=0 uartdivisorlow equ uart_base+0 ; clk divisor, low byte .. DLAB=1 uartdivisorhi equ uart_base+1 ; clk divisor, high byte .. DLAB=1 uartinten equ uart_base+1 ; interrupt enable register .. DLAB=0 uartintident equ uart_base+2 ; interrupt identification (read only) uartlinecntrl equ uart_base+3 ; line control register uartmdmcntrl equ uart_base+4 ; modem control register uartlinestatus equ uart_base+5 ; line status register uartmdmstatus equ uart_base+6 ; modem status register ; UART register bit definitions ; interrupt enable register rcvinten equ 01h ; enable data received interrupt bit xmitinten equ 02h ; enable transmitter buffer empty int rcvlineinten equ 04h ; enable receiver line status int bit mdmstatinten equ 010h ; enable modem status interrupt bit ; interrupt identification register (read only) intpending equ 01h ; interrupt pending bit mask intid equ 06h ; interrupt ID mask ( 2 bits ) ; line control register setbreak equ 040h ; set break bit dlab equ 080h ; divisor latch access enable bit ; modem control register dtr equ 01h ; data terminal ready bit rts equ 02h ; request to send bit out1 equ 04h ; output bit 1 out2 equ 08h ; output bit 2 loopcntrl equ 010h ; loop control bit ; line status register dataready equ 01h ; data ready status bit overrunerr equ 02h ; overrun error status bit parityerr equ 04h ; parity error status bit framingerr equ 08h ; framing error status bit breakint equ 010h ; break interrupt status bit thre equ 020h ; transmitter holding register empty tsre equ 040h ; transmitter shift register empty ; modem status register dcts equ 01h ; delta clear to send status bit ddsr equ 02h ; delta data set ready status bit teri equ 04h ; trailing edge ring indicator status drlsd equ 08h ; delta rcv line signal detect status cts equ 010h ; clear to send status read bit dsr equ 020h ; data set ready status read bit ri equ 040h ; ring indicator status read bit rlsd equ 080h ; rcv line signal detect status bit ; initialization values for divisor latch ; divisor values for baud rates using 1.8432Mhz 16X clock baud9600 equ 12 baud4800 equ 24 baud2400 equ 48 baud1200 equ 96 baud300 equ 384 ; initialization values for line control register and ; modem control register LCRVAL equ 07h ; 8 data bits, 2 stop bits, no parity MCRVAL equ 0fh ; DTR, RTS, OUT1, OUT2 set ;****************************************************************** ; ; Debugger constant and string definitions ; ;****************************************************************** PRSTRING equ 09h ; DOS print string function ENDSTRING equ '$' ; string termination char CR equ 0dh ; carriage return char LF equ 0ah ; line feed char BS equ 08h ; backspace char DELETE equ 07fh ; delete char KILL equ 018h ; control-x is kill char SPACE equ 020h ; space char BUFLENGTH equ 128 ; size of command buffer SRC_SEG equ 0 ; init source segment value DEST_SEG equ 0 ; init dest segment value DEF_COUNT equ 128 ; default count of bytes SIGNON db CR,LF db "MORROW DESIGNS 80188 DEBUGGER V1.0 5/7/84" db CR,LF,CR,LF,ENDSTRING NEWLINE db CR,LF,ENDSTRING PROMPT db "MBUG>",ENDSTRING BAD_COMMAND db "COMMAND NOT FOUND",ENDSTRING SYNTAX_MES db "usage: ",ENDSTRING SPACE_2 db " ",ENDSTRING SPACE_3 db " ",ENDSTRING SPACE_4 db " ",ENDSTRING DENTRY db " = ",ENDSTRING syntax label byte S_DUMP db "d
" db CR,LF,ENDSTRING S_ENTER db "e
",CR,LF,ENDSTRING S_FILL db "f
" db CR,LF,ENDSTRING S_INPUT db "i ",CR,LF,ENDSTRING S_MOVE db "m
" db CR,LF,ENDSTRING S_OUTPUT db "o ",CR,LF,ENDSTRING S_JUMP db "j
",CR,LF,ENDSTRING db 0 ; mark end of syntax strings commands label byte ; command table for debugger db 'D' dw offset dump db 'E' dw offset enter db 'F' dw offset fill db 'I' dw offset input db 'M' dw offset move db 'O' dw offset output db 'J' dw offset jump db 'Q' dw offset quit dw 0 segstore label word ; segment value temp storage ; these are used as default dw SRC_SEG ; source segment value dw DEST_SEG ; destination segment value current_src dw 0 ; source address current_dest dw 0 ; destination address current_count dw 40h ; current count current_port dw 0 ; current i/o port buffer db BUFLENGTH dup(?) ; command buffer data_buf db 0 ; count of bytes in data buf db 8 dup(0) ; can fill memory with up to ; 8 byte sequence end_data_seg label byte ; mark end of data segment data ends ;************************************************************** ; CODE STARTS HERE ;************************************************************** code segment para public 'code' assume cs:code, ds:data, es:data begin proc far ; initialize 80188 internal registers mov dx,umcs ; init upper memory chip select mov ax,UMCSVAL ; init value out dx,ax ; output to 80188 control port mov dx,lmcs ; init lower memory chip select mov ax,LMCSVAL ; init value out dx,ax ; output to 80188 control port mov dx,mmcs ; init middle memory chip select mov ax,MMCSVAL ; init value out dx,ax ; output to 80188 control port mov dx,mpcs ; init middle memory chip select mov ax,MPCSVAL ; init value out dx,ax ; output to 80188 control port mov dx,pacs ; init peripheral chip select mov ax,PACSVAL ; init value out dx,ax ; output to 80188 control port ; copy initialized data out of ROM and into RAM mov ax,40h ; data starts after interrupt vectors mov es,ax ; put segment addr into ds reg mov ax,data ; get address of init data in ROM mov ds,ax ; use as source address mov cx,offset end_data_seg xor si,si ; clear pointers mov di,si rep movsb ; copy cx count bytes to RAM mov ax,es ; put new data segment reg addr mov ds,ax ; into ds reg mov ax,offset end_data_seg mov cl,4 ; divide addr by 16 to get segment shr ax,cl inc ax ; point at next paragraph after data add ax,40h ; data seg starts at 400h mov ss,ax ; use as stack pointer mov ax,100h ; give 256 bytes to the stack mov sp,ax mov ax,0ffffh ; push reset address in case of push ax ; return from main loop xor ax,ax ; offset of reset location push ax ; init the console uart mov dx,uartlinecntrl mov al,LCRVAL+dlab ; set DLAB=1 to load divisor out dx,al mov dx,uartdivisorlow mov ax,baud9600 ; init port to 9600 baud out dx,al ; output low byte of divisor mov dx,uartdivisorhi mov al,ah ; get high byte of divisor out dx,al ; output high byte of divisor mov dx,uartlinecntrl mov al,LCRVAL ; init line control register out dx,al mov dx,uartmdmcntrl mov al,MCRVAL ; init modem control register out dx,al ; end of initialization code mov dx,offset SIGNON call prstr ; print sign on message main: ; this is the main loop of ; the debugger mov dx,offset PROMPT ; print the debugger prompt call prstr mov ah,0 ; convert data to upper case call get_command ; get command line into buffer mov al,buffer ; get first char in buffer test al,al ; if zero then no chars entered je main ; get the next command call execute ; execute the command jc main ; routine sets carry to cont ; terminate execution ret begin endp far ;************************************************************** ; COMMAND ENTRY AND PARSE ROUTINES ;************************************************************** ; ; get_command ; ; Get a command line into command buffer. ; ; on entry: ; ah contains 0 if the data should be converted to upper case. ; if ah is not zero then the data is entered as is. ; on return: ; command line is stored at buffer. ; usage: ; call get_command ; get_command proc near ; get command in buffer push ax ; save ax ; clear the buffer mov di,offset buffer ; point to beginning of buffer mov cx,BUFLENGTH ; length of command buffer push es ; need to use es register mov ax,ds ; get segment register mov es,ax ; put in default seg reg xor ax,ax ; fill buffer with zeroes cld ; set dir flag to auto incr rep stosb pop es ; restore segment register xor bx,bx ; clear buffer pointer pop cx ; get param value into cx gc_nextchar: call getc ; get the next input char cmp al,BS ; if backspace char je gc_delete ; then process cmp al,DELETE ; if delete char je gc_delete ; then process cmp al,KILL ; if kill char je gc_kill ; delete entire buffer cmp al,CR ; if CR then done je gc_done cmp al,SPACE ; reject other control chars jl gc_nextchar call putc ; echo char to display test ch,ch ; if param is 0 then convert jne gc_1 ; do not convert to UC cmp al,60h ; if lower case char then jl gc_1 ; else do nothing and al,0dfh ; convert to upper case gc_1: mov buffer[bx],al ; store char away inc bx ; point to next char in buffer cmp bx,BUFLENGTH ; if too many chars jg gc_err ; error exit jmp gc_nextchar gc_kill: mov al,SPACE ; erase to beginning of line call putc mov al,BS ; back up to orig position call putc test bx,bx ; only to beginning of line jz get_command dec bx mov al,BS ; back up one char call putc jmp gc_kill gc_delete: ; delete the previous char test bx,bx ; if at beg of buffer jz gc_nextchar ; do nothing ... otherwise mov al,BS ; back space to prev char call putc mov al,SPACE ; erase char call putc mov al,BS ; fix cursor call putc dec bx ; point at prev char position xor al,al ; clear char in buffer mov buffer[bx],al jmp gc_nextchar ; get next char gc_done: mov dx,offset NEWLINE ; print CR, LF call prstr gc_err: ret get_command endp near ; ; execute ; ; Executes the command line contained in 'buffer'. ; ; on entry: ; the command line is assumed to be in buffer. ; the command table is at 'commands'. ; on exit: ; the carry flag is cleared if the debugger is to terminate. ; usage: ; call execute ; execute proc near ; determine command mov al,buffer ; get 1st char of command line mov bx,offset commands ; point to command table exe_search: mov ah,[bx] ; get command in table test ah,ah ; if zero then reached end of je exe_bad ; table .. bad command cmp al,ah ; if command is found .. je exe_command ; then execute it add bx,3 ; else skip to next command jmp exe_search exe_command: inc bx ; point to addr of routine call word ptr [bx] ; near call to routine ret exe_bad: ; bad command .. print error mov dx,offset BAD_COMMAND ; message call prstr stc ret execute endp near ;************************************************************** ; DEBUGGER FUNCTIONS ;************************************************************** include mfunct.asm ;************************************************************** ; HARDWARE RELATED ROUTINES ;************************************************************** getc proc near ; get a char from console port ; return in al push dx ; save dx register mov dx,uartlinestatus getc_wrdy: in al,dx ; get uart status and al,dataready ; if no char received in uart je getc_wrdy ; wait .. mov dx,uartdata ; get data from uart in al,dx and al,07fh ; get rid of ms bit pop dx ; restore dx ret getc endp near putc proc near ; write a char to console port ; char is in al reg push dx ; save dx register push ax ; save ax register also mov dx,uartlinestatus putc_wrdy: in al,dx and al,thre ; test if xmit holding reg empty je putc_wrdy ; if not empty then again pop ax ; restore ax register and char mov dx,uartdata ; otherwise send data to port out dx,al ; write char to uart pop dx ret putc endp near prstr proc near ; dx pts to string terminated ; by a '$' push bx ; save bx register push ax ; save ax register mov bx,dx ; get string addr prstr1: mov al,[bx] ; get next char in string cmp al,'$' ; see if end of string je prstr_done ; done if so call putc ; else send char to console inc bx ; point at next char jmp prstr1 ; print next char prstr_done: pop ax ; restore ax register pop bx ; restore bx register ret prstr endp near code ends end