subttl '(c) 1981 Morrow Designs' title 'WB I/O test EPROM' .z80 ;**************************************************************** ;* * ;* Decision one CPU firmware, for the Morrow Designs / Thinker * ;* Toys Decision one computer. The monitor routine looks for * ;* the power on jump addresses on CPU switches which determine * ;* address to begin execution (top 5 switches). I/O is through * ;* the Wunderbus I/O motherboard UART 1. Base address of the * ;* I/O is assumed to be standard (beginning at port 48H). * ;* If top five switches are 'On', a hard disk is assumed to be * ;* the disk device and Boothd is executed. * ;* * ;* Bobby Dale Gifford and Bob Groppo * ;* 10/20/81 * ;* * ;**************************************************************** org 0 ;Local Ram in task zero nop equ 0 jmpop equ 0c3h ;Jump unstruction op-code callop equ 0cdh ;z80 call instruction opcode t1mask equ 2bh ;unlimited mask... no traps enabled t0mask equ 2bh ;unlimited mask ssmode equ 036h ;single step mode mask hstrap equ 1Ah ;allow traps on halts and stops, interrupts ;- masked out in task 0 (temporary) window equ 01h ;task 0 window at location 10000 ACR equ 0Dh ;carriage return ALF equ 0Ah ;line feed ASP equ ' ' ;space AFF equ 0Ch ;form feed BEl equ 07H ;bell BSP equ 08H ;backspace mskofst equ 19h ;offset to get to user's mask reg. contents spofst equ 17h ;offset to stack pointer of user afofst equ 15h ;offset to user Af register hlofst equ 13h ;offset to user h,l register deofst equ 11h ;offset to d,e bcofst equ 0Fh ;offset to b,c pcofst equ 0Dh ;offset to the users pc register nxtbyte equ 076h ;byte after a halt ;**************************************************************** ;* * ;* Wunderbus I/O equates: * ;* * ;**************************************************************** base equ 048h ;I/O base address of wunderbus ports group0 equ 00h group1 equ 01h ;serial port 1 group2 equ 02h ;serial port 2 Šgroup3 equ 03h ;serial port 3 grpctl equ base+7 ;I/O group select port ; UART equates dll equ base ;divisor latch lsb dlm equ base+1 ;divisor latch msb ier equ base+1 ;interupt enable register lcr equ base+3 ;line control register mcr equ base+4 ;modem control register lsr equ base+5 ;line status register rbr equ base ;read data buffer thr equ base ;transmitter data buffer dlab equ 80h ;divisor latch access bit thre equ 20h ;status line TBE dr equ 01 ;line status DR bit wls0 equ 01 ;word length select bit 0 wls1 equ 02 ;word length select bit 1 (for 8 bit word) stb equ 04 ;stop bit count (2 stop bits) imask equ 00 ;non interupt mode loop equ 010h ;UART loop mode ; PIC equates init equ 010h ;bit high to initialize the PIC icw1 equ base + 4 ;PIC initialization control word 1 icw2 equ base + 5 ;PIC initialization control word 2 icw3 equ base + 5 ;PIC initialization control word 3 icw4 equ base + 5 ;PIC initialization control word 4 ocw1 equ base + 5 ;PIC interrupt mask register ocw2 equ base + 4 ;PIC EOI register picmask equ 0ffh ;mask to turn all interrupts off ltim equ 08h ;level triggered mode adi4 equ 04h ;call address intervals = 4 adi8 equ 00h ;call address intervals = 8 sngl equ 02 ;sole system PIC ic4 equ 01h ;icw4 access bit lovect equ 0 ;call vectors begin at 0 hivect equ 0 ;call vectors begin at 0 normal equ 0 ;Master/Reg. nest/unbuffered/no AEOI/8085 ; -normal setting of OCW4 for Morrow Software eoi equ 20h ;non-specific EOI constant ;**************************************************************** ;* * ;* HDC Winchester controller equates * ;* * ;**************************************************************** revnum equ 13 ioaddr equ 120Q contrl equ ioaddr status equ ioaddr data equ ioaddr+3 functn equ ioaddr+2 commd equ ioaddr+1 Šsecstat equ ioaddr+1 dread equ 1 sector equ 1 opdone equ 2 complt equ 4 header equ 10Q drenbl equ 5 dskrun equ 7 ready equ 40Q system equ 200Q stepo equ 370Q drivea equ 374Q trk0 equ 1 ;**************************************************************** ;* * ;* DJ-DMA Equates * ;* * ;**************************************************************** djstat equ 104ah ;adjusted channel address of status byte ;**************************************************************** ;* * ;* DMA Winchester Controller Equates * ;* * ;**************************************************************** cyl equ 153 ;number cylinders for Seagate ST-506 heads equ 4 ;number heads for Seagate ST-506 stpdly equ 01eh ;15 msec for Seagate ST-506 hdsetl equ 0C8h ;20 msec for Seagate ST-506 secsiz equ 7 ;1024 byte sectors for CPM readat equ 0 ;DMA controller read sector opcode write equ 1 ;DMA controller write sector opcode rhead equ 2 ;DMA controller read header opcode format equ 3 ;DMA controller format track opcode const equ 4 ;load drive constants command sense equ 5 ;return drive status command noop equ 6 ;command used when seeking dmarst equ 54h ;DMA controller reset port attn equ 55h ;DMA controller Attention port stepout equ 10h ;Step direction to track 0 stepin equ 0 ;Step direction away from track 0 track0 equ 1 ;track 0 status wfault equ 2 ;write fault condition from drive dready equ 4 ;drive ready status sekcmp equ 8 ;seek complete status hdspt equ 17 ;number of sectors per track iopb equ 1050h ;pointer to the channel chan equ 1080h ;actual channel select equ chan + 3 ;select byte in channel dmaddr equ chan + 4 ;24 bit dma address location arg equ chan + 7 ;beginning of four arguments to commands cmmd equ chan + 11 ;actual command location statis equ chan + 12 ;controller return status location Šlink equ chan + 13 ;link field address for next command bootad equ 1100h ;dma address for first sector from hddma good equ 0ffh ;good status result ;**************************************************************** ;* * ;* Decision One Ram variables, visible only to task 0. * ;* * ;**************************************************************** ram equ $ ;Local RAM, visible only to task 0 ;**************************************************************** ;* * ;* Supervisor entry point, this jump must be inserted into the * ;* CPU's ram by the supervisor for subsequent entry to the * ;* supervisor when traps occur. * ;* * ;**************************************************************** super: jp super ;Supervisor entry point user: jp user ;(7) User entry point ctask: db 0 ;Current task cmask: db 0 ;Current mask contents ;**************************************************************** ;* * ;* Task save areas. Each of the tasks 1-15 have one of these * ;* structures associated with it. When tskbase returns, HL * ;* will point to u.ir for that task + 0 offset. * ;* * ;* offset * ;* u.ir +0 Interrupt register (1 byte) * ;* u.ix +1 Index registers (2 bytes) * ;* u.iy +3 (2 bytes) * ;* u.abc +5 Alternate registers (2 bytes) * ;* u.ade +7 (2 bytes) * ;* u.ahl +9 (2 bytes) * ;* u.aaf +B (2 bytes) * ;* u.pc +D Task PC (2 bytes) * ;* u.bc +F Task registers (2 bytes) * ;* u.de +11 (2 bytes) * ;* u.hl +13 (2 bytes) * ;* u.af +15 (2 bytes) * ;* u.sp +17 Stack pointer (2 bytes) * ;* u.mask +19 Mask register contents. (1 bytes) * ;* * ;**************************************************************** tasksiz equ 26 tasks: ds tasksiz ;Task 1 ds tasksiz ;Task 2 ds tasksiz ;Task 3 ds tasksiz ;Task 4 Š ds tasksiz ;Task 5 ds tasksiz ;Task 6 ds tasksiz ;Task 7 ds tasksiz ;Task 8 ds tasksiz ;Task 9 ds tasksiz ;Task 10 ds tasksiz ;Task 11 ds tasksiz ;Task 12 ds tasksiz ;Task 13 ds tasksiz ;Task 14 ds tasksiz ;Task 15 u.save: db 0 ;Start of user save area u.ir: db 0 ;Temporary user interrupt reg. save dw 0,0,0,0,0,0 ;ix,iy,bc',de',hl',af' u.pc: dw 0 ;Temporary user pc storage dw 0,0,0 ;bc,de,hl u.af: dw 0 ;Temporary user af storage u.sp: dw 0 ;temporary user stack storage u.mask: dw 0 ;temporary mask storage gobuff equ $ ds 14 ;task boot buffer ersav equ $ ds 200h-(ersav-ram);Fill out the ram stack equ $ ;End of local ram ;**************************************************************** ;* * ;* The following map is used to hold an image of the current * ;* memory map for all tasks. * ;* * ;**************************************************************** map: ds 200h ;Task Memory map image ;**************************************************************** ;* * ;* Decision One local I/O map, the following registers are * ;* memory mapped into task 0, and are always visible to task * ;* zero only. * ;* * ;**************************************************************** locio equ $ ;Local I/O, visible only to task 0 trpadd: ds 0 ;Trapp address register (read) dspseg: ds 1 ;Display segment register (write) keybd: ds 0 ;Key board register (read) dspcol: ds 1 ;Display column register (write) switch: ds 0 ;CPU switch port (read) task: ds 1 ;Task register (write) stats: ds 0 ;Trap status register (read) mask: ds 1 ;Task mask register (write) elocio equ $ ;End of local I/O Š ds 200h-(elocio-locio) ;Fill out local I/O ;**************************************************************** ;* * ;* The following ram is the actual memory map, it can only be * ;* written into, so an image is kept in the local ram. * ;* * ;**************************************************************** mapram: ds 200h ;Memory Map RAM, visible only to task 0 ;**************************************************************** ;* * ;* Decision One prom routines, usable by the supervisor task * ;* only after a reset but not accessible by any other tasks. * ;* * ;**************************************************************** rom0 equ $ ;Local ROM, visible only to task 0 ;and is visible only during RESET ;**************************************************************** ;* * ;* Reset is executed only once. Currently, reset forms an * ;* identity map for task zero to occupy the first 64K of main * ;* memory, allows task 0 to have unlimited priviledges. Task1 * ;* occupies the first 64K, unlimited access and the traps are * ;* set for halts or a stop. All other task maps are initialized * ;* starting at bank 2 to bank 15. (e.g. task 15 has bank 15). * ;* If swithches are set with S1 through S7 off and S8 on, the * ;* power on jump address will be F800. If switch 6 is on, the * ;* program will jump to the monitor regardless of the state * ;* of the other switches. If S1 - S5 are all 'ON' a MORROW * ;* hard disk is assumed and the 'Boothd' program is executed. * ;* If pin 2 of 15D is lifted, the diag nostic mode is entered. * ;* * ;**************************************************************** ; Check all the readable registers regrd: out (0ffh),a ;sync ld hl,trpadd ld a,(hl) ;read trap address reg @ 400h inc hl ld a,(hl) ;read keyboard reg @ 401h inc hl ld a,(hl) ;read switch reg @ 402h inc hl ld a,(hl) ;read trap status reg @ 403h jr getsw Š; Check all the writable registers regwr: xor a ;loop till switch not 00 regwr1: out (0ffh),a ;sync ld (mask),a ;write to the mask register ld (dspcol),a ;write to the display column register ld (keybd),a ;write to the display segment reg. cpl cp 0ffh jr z,regwr1 jr getsw ; Check the Map RAMs tmap: xor a ;write to map ram / protection ram ld hl,mapram out (0ffh),a ;sync ld (hl),a ;write location 600,0 inc hl ld (hl),a ;write 601,0 cpl ld (hl),a ;write 601,0ffh dec hl ld (hl),a ;write 600,0ffh ld hl,mapram + 01feh ld (hl),a ;write 7fe,0ff inc hl ld (hl),a ;write 7ff,0ff cpl ld (hl),a ;write 7ff,00 dec hl ld (hl),a ;write 7fe,00 jr getsw ; Check the R/W RAMs tram: ld hl,0000h ;write to read/write ram out (0ffh),a tram1: xor a ld (hl),a ;write a 00 to ram cp (hl) ;read it back cpl ld (hl),a ;write an ffh to ram cp (hl) ;read it back bit 0,h jr nz,getsw ld hl,03ffh jr tram1 ;write to 3ffh a ffh ; Check the Floating Point Processor Š tfpp: xor a ;check FPP out (0ffh),a ;sync ld (0c00h),a ;write a 00 to location C00h ld (0c08h),a ;write a 00 to location C08h ld a,(0c00h) ;read c00h getsw: ld a,(keybd) bit 1,a reset: jp z,reset0 ;go to the montior if low ld a,(switch) bit 2,a jp z,reset0 ;go to the monitor if S6 is on and 070h ;strip insignificant bits rrc a ;4 byte offset rrc a ld hl,jtable ;point to beginning of table add a,l ld l,a jp (hl) ; Check the S-100 bus addr and data lines tbus: ld a,0f0h ld (task),a ;force upper task bits high ld a,0ffh ;init the T0 map ld (61eh),a ld a,03 ld (61fh),a ld (603h),a xor a ld (602h),a out (0ffh),a ;sync ld (0ffffh),a ;write - bus addresses A0-23 are high ld (task),a ;upper task bits low ld (1000h),a ;write - bus addresses A0-23 are low ld a,0f0h ld (task),a ;force upper task bits high ld a,(0ffffh) ;read - bus addresses A0-23 are high xor a ld (task),a ;force upper task bits low ld a,(1000h) ;read - bus addresses A0-23 are low jr getsw ntbus: ld a,0A0h ld (task),a ;force upper task bits high ld a,0aah ;init the T0 map ld (61eh),a ld a,03 ld (61fh),a ld (603h),a ld a,55h Š ld (602h),a out (0ffh),a ;sync ld a,0aah ld (0faaah),a ;write - bus addresses A0-23 = AAAAAA ld a,50h ld (task),a ;upper task bits low = 5 ld a,55h ld (1555h),a ;write - bus addresses A0-23 are low ld a,0A0h ld (task),a ;force upper task bits high ld a,(0faaah) ;read - bus addresses A0-23 are high ld a,050h ld (task),a ;force upper task bits low ld a,(1555h) ;read - bus addresses A0-23 are low jp getsw ; Initialize the maps and jump vectors reset0: call reset1 jp uartst reset1: ld hl,super ;initialize 'super' to the monitor... settle: dec hl ;wait for the hardware to settle down ld a,l or h jr nz,settle ld (hl),jmpop ;- this will be overwritten by the inc hl ;- supervisor but all traps in the ld (hl),012h ;- meantime will fall into the monitor. inc hl ld (hl),08h reslop: xor a ld c,3 ;New access priviledges reslp2: ld b,a ;New allocation = segment # call rstmap ;Allocate it inc a ;Next segment # and 0fh ;Check if all done jr nz,reslp2 ;Continue until done LD A,10h ;write new task and segment LD B,0 ;TASK 1 gets first 64K of memory reslp1: call rstmap ;Give TASK 1 a full 64k of space inc B inc A cp 20h jr nz,reslp1 fmap: ld b,a ;fill all the tasks' maps call rstmap inc a cp 0h jr nz,fmap ;****************************ll restore Task 0's map with its old * ;* values. This assumes that if the map for task 0 * ;* has been changed, that vectors = restart locations. * ;* * ;**************************************************************** picset: xor a out (grpctl),a ld a,lovect + hivect + init + ltim + adi8 + sngl + icw4 out (icw1),a ;initialize the first word ld a,hivect out (icw2),a ;initialize the second word ld a,normal out (icw4),a ;initialize the forth word ld a,picmask out (ocw1),a ;mask all interrupts ld a,eoi ;send PIC an End of Interrupt word out (ocw2),a ;clear the master interrupt requests out (ocw2),a ;clear the slaves interrupt requests ret ;**************************************************************** ;* * ;* Rstmap writes the tasks memory allocation vectors. Upon * ;* entry the registers must contain: * ;* a = task number / task segment number to update * ;* high nibble = task # low nibble = segment # * ;* b = New allocation vector * ;* c = New allocation access * ;* * ;* Routine calculates the expression 600+(Accumulator) x 2 * ;* where accumulator contents are as listed above. All arit- * ;* hmetic and numbers are in Hex * ;* * ;**************************************************************** rstmap: ld l,a ;Get task and segment numbers ld h,0h add hl,hl ;multiply times 2 ex de,hl ;save calculated offset in D,E ld hl,mapram ;point to beginning of ram map call rstmxx ld hl,map ;point to image map at 200 rstmxx: add hl,de ;add offset to selected map ld (hl),b ;write the allocation vector to ram inc hl ;point to access ram ld (hl),c ;write access attributes to ram ret ;******************************************************** ;* * ;* The following code intitializes the I/O for * ;* the Decision 1 Motherboard and the Mult I/O. * ;* * ;******************************************************** Š uartst: ld d,3 ;start with uart 3 uarts0: ld a,d out (grpctl),a xor a out (lsr),a ;clear line status register out (ier),a ;initialialize interupt mask (off) dec d jr nz,uarts0 out (grpctl),a ;select sense switch port in a,(base+1) rlca rlca rlca and 07h ;mask insignificant bits cp 07h ;all off? ld d,0 jr z,default ;default if all off ld hl,btable ;point to baud rate table add a,a ld e,a add hl,de ;offset to selected baud rate ld c,(hl) inc hl ld b,(hl) ;bc = baud rate divisor value (D) jr setit default: ld bc,12 ;default baud rate is 9600 setit: inc d ld a,d cp 04h ;all UARTS initialized?? jr z,uartest out (grpctl),a ld a,dlab+wls1+wls0+stb out (lcr),a ;divisor access bit is on ld a,b out (dlm),a ;load high divisor register ld a,c out (dll),a ;load low divisor register ld a,wls1+wls0+stb out (lcr),a ;divisor access bit is off ld a,03h out (ier),a ;enable the interrupts jr setit ;loop till all UARTS initialized uartest: ld c,3 utest1: ld a,c ld b,'0' ;start with ascii zero out (grpctl),a ;select uart utest2: call lsrtst ;print it inc b ld a,b cp 'z' + 1 jr nz,utest2 dec c jr nz,utest1 ;next uart jr uartst ;do it over again lsrtst: ld d,0h ;retry count lsrt1: dec d ret z ;keep trying (255 times) in a,(lsr) and thre jr z,lsrt1 conout: in a,(rbr) ;clear receiver interrupt ld a,b out (thr),a ;send char./clear interrupt ret ; Baud rate selection table for Mult I/o or WB I/O btable: dw 1047 ;110 baud 0 0 0 dw 384 ;300 baud 0 0 1 dw 96 ;1200 baud 0 1 0 dw 48 ;2400 baud 0 1 1 dw 24 ;4800 baud 1 0 0 dw 12 ;9600 baud 1 0 1 dw 6 ;19200 baud 1 1 0 ; Load constants command for the DMA Winchester controller bootbl: db 0 ;select db 0 ;low steps db 0 ;high steps db 0 ;select db 0 ;low dma address db 01 ;high dma address db 0 ;extended dma address db 0 ;argument 0 db stpdly ;argument 1 db hdsetl ;argument 2 db secsiz ;argument 3 db const ;load constants opcode db 0 ;clear status byte db 80h ;low link address db 0 ;high link address db 0 ;extended link address endboot equ $ Š ; Read sector 1, head 0, cyl 0 command for the HD-DMA: rdtbl: db 0 ;no seek db 0 db 0 db 07ch ;select drive 0, head 0 db 0 ;dma address of 100h db 1 db 0 db 0 ;low byte cylinder db 0 ;high byte cylinder db 0 ;head 0 db 0 ;sector 1 db 0 ;read command db 0 ;clear status endrd equ $ ; Dispatch table for the on-board diagnostic routines jtable equ $ jp regrd ;test all the readable registers db 0 jp regwr ;check all the writable registers but ; -task register db 0 jp tmap ;check map rams db 0 jp tram ;check read/write ram db 0 jp tfpp ;check fpp db 0 jp tbus ;check bus read/write addresses db 0 jp ntbus ;R/W bus with 055h and 0aah db 0 jp start ;yet to be defined ecode0 equ $ ;End of reset prom code ds 3f0h-(ecode0-rom0) ;Fill out the prom ; Code begins executing here on a reset ld hl,djstat ld a,0 ld (mapram + 2),a inc a start: ld sp,map jp getsw nop end