title 'Initial Program Loader and Generator V1.1" name ('iplgen') ; date 21-Jun-83 ; ; .z80 ; Z-80 coding is used ; ; aseg ; ; *** ASCII Constants *** ; cr equ 0dh lf equ 0ah bell equ 07h eom equ '$' retry equ 10 ; ; ; ; ; *** Port Assignments *** ; SCSI$base equ 0050h ; SCSI Interface board base QUAD$eia equ 0010h ; Base port for QUAD. eia board crtstatus equ QUAD$eia+4 ; Status port for console crtdata equ QUAD$eia+5 ; Data port for console ; txrdy equ 0001h ; Tx. Ready bit in 8251 usart rxrdy equ 0002h ; Rx. Ready bit in 8251 usart ; ; *** SCSI Port assignments *** ; ; * bit,byte and port assigments for * ; * SCSI host interface adaptor * ; datai equ SCSI$base ; data in register datao equ SCSI$base+2 ; data out register bstat equ SCSI$base+1 ; bus status selport equ SCSI$base ; select port adr. clrint equ SCSI$base+1 ; clr. intrrupt port dmaport equ SCSI$base+3 ; dma address port cparity equ SCSI$base+4 ; clear parity port busy equ 80h ; controler busy bit cd equ 40h ; command/data bit direc equ 20h ; directon bit req equ 10h ; request bit msg equ 08h ; end message bit perr equ 04h ; perr error bit bdack equ 02h ; board ack. signal lint equ 01h ; interupte bit ; ; cseg ; start:: ld sp,stack ; set up the stack pointer call txout .xlist defb cr,lf defb 'IPLGEN00 -- Initial Program Booter and' defb ' System Generator V1.1' defb cr,lf,lf defb 'For 60k Systems',cr,lf,lf,lf defb 'L)oad or M)ake System Track --->',eom call ci ; get answer cp 'M' ; see if make system jp z,make$system ; brif so cp 'L' ; see if load system jp z,load$system ; brif so call txout defb cr,lf,lf defb 'ERROR: Please Type "M" or "L"' defb cr,lf,lf,eom jp start ;* ;** ;* ;+ txout:: ;- ex (sp),hl ; hl @ data ld a,(hl) ; a = data inc hl ; put back pointer ex (sp),hl ; cp eom ; end of message??? ret z ; return if so ld e,a ; else e = character ld c,2 ; console output code call 0005h ; do the bdos stuff jp txout ; and repeat ;* ;** ;* ;+ ci:: ;- ld c,1 call 0005h ret ;* ;** ;* ;+ make$system:: ;- call txout .xlist defb cr,lf,lf defb 'Please Enter Name of GEN''ed CP/M System --->',eom .list ld hl,line$buffer ; hl @ line buffer ld (hl),80 ; max. line size = 80 characters ex de,hl ; de @ line buffer ld c,10 ; read console buffer call 0005h ; ld hl,fcb ; clear out fcb ld de,fcb+1 ; ld bc,33 ; ld (hl),00 ; prime the routine ldir ; perform the operation ld de,fcb+1 ; de @ filename ld hl,line$buffer+1 ; hl @ filename line ld c,(hl) ; c = size of line inc hl ; point to data part of line ld b,8 ; b = size of filename ms010:: ld a,(hl) ; a = data from line cp '.' ; is it a dot?? jp z,ms020 ; brif so ld (de),a ; else stuff to fcb inc hl ; inc de ; increment pointers djnz ms010 ; ms030:: ld a,(hl) ; skip past '.' cp '.' ; jp z,ms020 ; brif found inc hl ; jp ms030 ; and countine ;* ms020:: inc hl ; point past '.' ld a,b ; see if all filename is filed or a ; jp z,ms040 ; brif so ms050:: ld a,' ' ; pad with spaces ld (de),a ; inc de ; djnz ms050 ; ms040:: ld bc,3 ; ldir ; trnsfr rest of file name ld de,fcb ; try to open ld c,15 ; call 0005h ; cp 0ffh ; check for error jp nz,ms060 ; brif ok call txout ; defb cr,lf,lf defb 'ERROR: Cannot Open File ',eom ld de,(line$buffer+1) ld hl,line$buffer+2 ld d,0 add hl,de ld (hl),'$' ld de,line$buffer+2 ld c,9 call 0005h jp make$system ;* ms060:: call txout defb cr,lf defb 'Loading File ...',eom ld hl,buffer ms070:: ex de,hl ; de @ dma buffer push de ; save ld c,26 ; set dma call 0005h ; ld de,fcb ; de @ fcb ld c,20 ; go read a record call 0005h ; perform the read or a ; check for errors jp nz,ms080 ; brif done pop hl ; increment dma ld de,128 ; add hl,de ; jp ms070 ; ;* ms080:: call txout ; defb cr,lf,'OK',cr,lf,eom call get$drive ; go get the proper drive code ld hl,buffer+0880h ; start = buffer ld (begin),hl ; pop hl ; end = last dma ld (last),hl ; ld a,03 ; command is write ld (command),a ; call doio ; and do the i/o call txout defb cr,lf,lf defb 'Operation Completed',cr,lf,eom jp 0000 ;* ;** ;* ;+ get$drive: ;- call txout defb cr,lf defb 'Enter 0 (Drive #0) or 1 (Drive #1) -->',eom call ci cp '0' jp z,gd99 cp '1' jp nz,gd010 ld a,20h ld (drive),a gd99: call txout defb cr,lf defb 'OK',cr,lf,eom ret ;* gd010: call txout defb cr,lf defb 'ERROR: Please Enter Either 0 or 1',cr,lf,eom jp get$drive ;* ;** ;* ;+ load$system:: ;- call txout defb cr,lf,lf defb 'Load System Function Selected',cr,lf,eom call get$drive ld hl,0d400h ld (begin),hl ld hl,0f700h ld (last),hl ld a,1 ld (command),a call txout defb cr,lf,lf defb 'Loading System ...',eom call doio jp 0ea00h ;* ;** ;* ;+ doio:: ;- ld hl,command ld a,(drive) or (hl) ld (hl),a ld de,(begin) ld (dma),de ld a,1 ld (command+2),a ld (command+4),a doio10:: ld hl,command call docmd jr z,doio20 call txout defb cr,lf,lf defb 'ERROR: Disk I/O Error Detected, Operation Aborted' defb cr,lf,eom jp 0000 ;* doio20:: ld hl,command+2 inc (hl) ld hl,dma+1 inc (hl) ld hl,(dma) ld de,(last) or a sbc hl,de jp c,doio10 ret ;* ;** ;* ; ;* start of protocal handling routnes * ; ;+ docmd: ;-op: issue command to SCSI host adaptor ;-pp: hl @ command bytes to send ;- @actsec & @rpntr are valid ;-rc: no - zero : error in command (a = error bits) ;- zero : command was executed successfully ;- ld (lcmd@),hl ; save command @ ld a,retry ; get retry count ld (trycntr),a ; reset counter out (cparity),a ; reset parity error dcmd1: push bc ; save counter call ?putdma ; set dma address call ?select ; go select controler pop bc ; recover bc ; wait: ; ;* here we must wait for execution * ; in a,(bstat) ; a <--- buss status and cd+req ; check for data jr nz,wait ; brif still data in a,(datai) ; a <-- completion status push af ; save ending status wait1: in a,(bstat) ; wait for req. and msg. and req+msg ; jr nz,wait1 ; in a,(datai) ; get byte of zero pop af ; recover status and 00011111b ; mask out errors jr nz,wait4 ; brif not ok in a,(bstat) ; check for parity and perr ; out (clrint),a ; clear interrupt ld a,0ffh ; jr nz,wait4 ; brif error xor a ; exit with zero ret ; and exit ;* ;* wait7: pop af ; clear out stack wait4: bit 2,a ; hardware busy?? jr z,wait6 ; brif not call txout defb cr defb 'Please Wait, Drive is Spining Up',eom jr wait5 ; and continue ;* wait6: ld hl,trycntr ; see if retry up dec (hl) ; jr z,wait2 ; brif retry is up wait5: ld hl,(lcmd@) ; recover last command jp dcmd1 ; and try again ;* wait2: out (clrint),a ; clear interrupt or a ; exit with non-zero ret ; and exit ;* ;** ;* ;+ ?putdma: ;-op: send dma address to host adapter ;-pp: rpntr has dma address ;- ld a,(hidma) ; set hi-byte out (dmaport),a ; high byte always zero ld de,(dma) ; de @ dma address ld a,d out (dmaport),a ; send byte 1 ld a,e out (dmaport),a ; send byte 2 ret ; and exit ;* ;** ;* ;+ ?select: ;-op: select controler ;- in a,(bstat) ; is controler busy?? and busy ; wait for not busy jr z,?select ; wait if so sel2: ld a,01h ; select controler #1 out (datao),a ; out (selport),a ; and select controler sel1: in a,(bstat) ; wait for req and req ; jr nz,sel1 ; ld d,a ; d=0, mark first command ; ;* now fall on thru to output command bytes * ; ;+ ?outcmd: ;-op: issue command bytes to host adaptor ;-pp: hl @ command bytes ;- in a,(bstat) ; grab buss status ld c,a ; save status and cd ; see if data ret nz ; exit if data ld a,c ; check for direc and direc ; ret z ; exit if input ld a,req+bdack ; bit 0,d ; see if first cmd. jr nz,?oc5 ; brif not ld a,req ; else just check for req. ?oc5: and c ; check for ready jr nz,?outcmd ; brif not (1.75/1.17) ?oc1: ld a,(hl) ; get command byte (1.75/1.17) out (datao),a ; send to controler (2.75/1.83) inc hl ; point next (1.5/1.0) ld d,1 ; mark not first command jr ?outcmd ; and do it again! ;* ;** ;* ; ; dseg line$buffer:: defs 80+2 last:: defw 00 begin:: defw 00 hidma:: defw 00 drive:: defw 00 dma:: defw 00 lcmd@:: defw 00 trycntr:: defw 00 command:: defw 00,00,00,00 fcb:: defs 36 defw 100 stack:: buffer:: end