*The purpose of this program is to load the MPX with a routine *which will continuously exercise its DMA. The idea is to run *this routine simulteneously with the DISK1 to make sure that the *DISK1 is exercising its priority properly. This routine will *simply read and write to locations from 10000H to 1FFFFH until it *is told to stop by the sister routine "HOWRYOU.COM". This second *routine places a '0FH' at location 4FH in main memory which tells *the MPX that its time to finish up and tell the system whether *any mistakes have been made in all of its memory accessing. *The main program can make a system call to output to the *terminal but the MPX can't. This was resolved by looking at *location 'IOSPOT' (40h at writing) to see what device is being *used. This is all pretty well explained in the last part of the *program. The bottom line is that I/O1,2,3,4, and Sys Sup's can *all be used by the test as the console (3,4 assume user active). *Written by D.A.Plomgren, 1/83, for Godbout Electronics. fstlnk equ 50h ;first place where MPX goes to get command linkad equ 41h ;after "size" instruction, new link address ;is at this location mpxatn equ 0F1h ;MPX attention port ldcpm equ 00h fdos equ ldcpm+05h mpxcod equ 300h ;this is where the MPX routine is put in ;in main memory to be loaded to the mpx. ;If the program that the main CPU runs grows, ;this address might have to be increased. mpxdst equ 300h ;where code goes in MPX RAM. iospot equ 40h ;the MPX looks here in main memory to find ;out what I/O device is on the bus. (I/O 1-2, ;Sys Sup,I/O 3-4,Bit Bang) org 100h begin: call crlf lxi h,load ;message is 'Loading '. call write lxi h,chksiz lxi d,fstlnk call mpxins ;load mpx command 'checksize' at ;location 'firstlink' out mpxatn ;run 'checksize' on MPX sized: lda fstlnk+1 ;has MPX finished checking size ora a jz sized lda fstlnk+0EH ;result byte 1. ora a ;if FFH then 16K, if 00H then 4K jz wrtfor lxi h,sxtn call write jmp loader ;finished sizing, now load program wrtfor: lxi h,fork call write Š*now the MPX has run the size routine and the CRT either says * "Loading 16K " or "Loading 4K ". *The new Link Address is now 'linkad' *The loader routine now instructs the MPX to load the memory and *DMA test routine form the main memory. loader: lxi h,mormsg ;just more message to the terminal call write lxi h,ldram ;inst to load MPX RAM from sys RAM lxi d,linkad ;second link address call mpxins ;load command bytes from 'linkad' up out mpxatn prgld: lda linkad+1 ;is MPX finished loading ora a jz prgld lxi h,loaded ;finishes loading MPX RAM call write *now the MPX has loaded the its RAM with the program that it *is going to run. Now we only have to tell it to run the program runner: lxi d,linkad lxi h,exram ;instruction to execute a program call mpxins ;load command bytes out mpxatn *now the MPX is running the program to test its DMA. The MPX will *put in the first part of its routine a 'AAH' at location 'linkad+1' *in main memory to signify that it has indeed started running, and *it has found some memory in the second page. If it does not find *any memory in the second page, MPX puts a '55h' at location 'linkad+1' *and writes a nasty messasge to the terminal. finish: lda linkad+1 ;get signal byte ora a jz finish ;MPX has returned something cpi 0AAh ;memory is O.K. jz goodmg cpi 055h ;Memory is not there. jnz finish ;If not aah and not 55h, wait until ;mpx returns one or the other. lxi h,crappy call write ;write a nasty message to the terminal jmp reboot goodmg: lxi h,okmsg call write Š reboot: jmp ldcpm ;re-boot CPM *these next sub's and defines are neeeded by the main program, *but not the mpx. crlf: mvi c,02h ;this routine just sends mvi a,0ah ;a carriage return and line call fdos ;feed to the terminal. mvi c,02h mvi a,0dh call fdos ret *------------------ write: push d push b writ: mov a,m ;this small routine prints chars ora a ;starting at location HL and jz fin ;continues printing until an ;00h is encountered at which mvi c,02h ;time it returns. mov e,a push h call fdos pop h inx h jmp writ fin: pop b pop d ret *---------------- mpxins: push b mvi b,00h insl: mov a,m ;this routine takes information xchg ;from @HL and puts it @DE. a mov m,a ;total of 16 bytes are transferred. xchg ;this is for loading the MPX command. inx d inx h inr b ;check for 16 bytes mvi a,10h cmp b jnz insl pop b ret *----------------- load: db 0dh,0ah,'Loading MPX ',0h sxtn: db '16K ',0h fork: db '4K ',0h mormsg: db 'with routine to test DMA arbitration by accessing' db 0dh,0ah,'system memory from 010000H to 01FFFFH.',0h loaded: db ' Loaded.',0h crappy: db ' at 010000H to 01FFFFH.',0dh,0ah,0h okmsg: db ' Running.',0dh,0ah,0h chksiz: db 06h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h dw linkad db 00h,00h,00h ldram: db 07h,00h dw mpxcod Š db 00h dw mpxcod+1FFh ;the mpx code is less than db 00h ;200H bytes long. dw mpxdst db 00h dw linkad db 00h,00h,00h exram: db 08h,00h dw mpxdst db 00h,00h,00h,00h,00h,00h,00h dw linkad db 00h,00h,00h *==============================================================+ *Below here is the MPX routine which will be loaded and run. *It simply moves through the second page of main memory *looking for an error. It *is always checking location 'linkad+0Fh' for an '0F0H' which *will signal for it to finish its test and return a verdict *on the DMA activity. *============================================================== dmalo equ 8004H dmahi equ 8005H mpxst equ 024FH ;Internal MPX stack pointer. err equ 0260H ;When the MPX gets an error in ;its ramblings, it puts an FFH ;here. mpxres equ 4000H ;this is the beginning of the ;mpx initializtion routine for ;resetting the MPX. secpag equ 01H extwin equ 0C000H org mpxcod ;this address is where the MPX code ;first resides in main memory for the ;mpx to load into its own memory. mpxrou: lxi sp,mpxst ;initialize stack pointer xra a sta mpxst ;clear top of stack. sta err ;clear error location. *now check for memory in second page-10000H to 1FFFFH by looking at *location 010100H and 01FFFFH for some. mvi a,secpag ;high address of second page sta dmahi sta dmalo lxi h,extwin mov a,m ;get byte form main memory cma Š mov b,a ;save mov m,a ;put back in memory mov a,m ;get it back cmp b ;compare it jnz nomem mvi a,0ffh ;now to 01ff00 sta dmalo mov a,m ;this is exactly as above. cma mov b,a mov m,a mov a,m cmp b jnz nomem yesmem: lxi h,mpxis ;write message 'MPX is ' call writem xra a ;place good news ('aah') at sta dmalo ;'linkad+1' in main memory sta dmahi lxi h,extwin+linkad+1 mvi a,0AAh mov m,a ;put aah to memory jmp intd ;now start memory test nomem: lxi h,nommsg call writem ;give first part of bad memory ;message. xra a sta dmalo ;Place bad news '55h' at linkad+1 sta dmahi ;in main memory. lxi h,extwin+linkad+1 mvi a,55h mov m,a ;put 55h to main memory. jmp mpxres ;this goes to the mpx routine which ;initializes the MPX to its power-on ;benign state. *now the routine has checked whether main memory exists or not in the *second page. If it does, the memory tests now starts below. If not, *the MPX jumps to the EPROM for reset. intd: lxi d,0h chkfin: lxi h,extwin+linkad+0fh xra a sta dmalo sta dmahi Š mov a,m ;see if main program wants mpx ;to finish up. If MPX finds a F0h ;at 'linkad+0Fh', it is time to finish cpi 0F0h jnz testm lda err ;now mpx will finish testing, and ora a ;check if its had any errors. jz goodmm lxi h,notsg ;We've had errors, so say so. call writem mvi a,0aah lxi h,extwin+linkad+0Eh mov m,a ;put aah at linkad+0eh for bad news jmp mpxres goodmm: lxi h,verygm ;all tests are good, so say so call writem mvi a,0ffh ;put ffh at linkad+0eh for good news lxi h,extwin+linkad+0Eh mov m,a jmp mpxres *this below is the basic memory test that is to be run. *Register DE contains the actual memory currently under test. It *is initialized once in 'intd' and is incremented every time the loop *below is run. D is moved into dmalo and E into L for the address to *be in M. testm: mvi a,secpag ;MPX keeps on checking. sta dmahi ;The program HOWRYOU.COM places a F0h ;at 'linkad+0fh' to end routine. lxi h,extwin ;MPX address in HL loopt: mov a,d ;put actual address in dmalo sta dmalo mov l,e ;put low byte of actual address to HL mov a,m ;get main memory at (secpag)(D)(E)h mov b,a ;save cma mov c,a ;save. Now original data is in b, and ;complement is in c and a. mov m,a ;put complement to main memory. nop mov a,m ;read complement from main memory. Š cmp c ;compare with stored complement. cnz error ;if they don't match, crap out--but ;continue testing. inr b ;put one greater than last test back mov m,b ;into memory. inx d ;try next memory location. jmp chkfin ;back to check status. error: push psw mvi a,0ffh ;when a memory error occurs, place sta err ;0ffh at the err location. pop psw ret *this prog is needed by the MPX but not the main prog. *This routine goes to location 'iospot' in main memory to find the *I/O device. A 00H indicates a I/O 1-2 (Ports 0,1), a 01H indicates *a bit banger, a 02H says System Support(ports 5ch,5dh), and *a 03H says Interfacer 3 or 4(port 10,11h). The initial address *of the string is @HL and the end is marked with an ascii 00H tbmt equ 01h writem: push b ;WRITE a message to the Console***** push d xchg ;put string address in DE lxi h,extwin+iospot ;what does iospot say the interfacer ;type is. mov a,m cpi 00h jz printm ;00H is already in var 'putchr+1' and ;01h is in 'getstt+1' cpi 02h jz sysup ;use port 5CH cpi 03h jz intr34 ;Interfacer 3 and 4. Use port 10h jmp printm ;if not 0,2,3 use port 0 for lack ;of a better option. sysup: mvi a,5ch ;tell OUT what port sta putchr+1 inr a sta getstt+1 ;tell IN what port jmp printm intr34: mvi a,10H ;as above sta putchr+1 inr a sta getstt+1 *The address of the message is in DE. The equivalent IN and *OUT instructions with the proper port are called in putchr and *getstt. printm: xchg ;get address back in HL wrt: mov a,m ;get next character. ora a jz finis ;a 0h follows all strings. mov b,a ;save data in b. nexstt: call getstt ;use this just like an IN STATUS ani tbmt jz nexstt mov a,b ;get data back. call putchr ;use this just like OUT DATA inx h ;next character. jmp wrt finis: pop d pop b ret *these two below just mimic the IN and OUT assembler instructions *but the port which they access is controlled by what is put in *'putchr+1' and 'getstt+1'. putchr: db 0D3h,00h ;OUT port number ret getstt: db 0DBh,01h ;IN port number ret *these next defines are needed by the mpx, but not the main prog mpxis: db ' MPX is',0h nommsg: db 0dh,0ah,'No System Memory ',0h notsg: db 0dh,0ah,'MPX: Error in Memory Access.',0h verygm: db 0dh,0ah,'MPX: All Memory Access Good.',0h end