|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - download
Length: 11648 (0x2d80) Types: TextFile Names: »LDRBIOS.ASM«
└─⟦b445f10af⟧ Bits:30004389 CP/M Plus Source files └─ ⟦this⟧ »LDRBIOS.ASM«
TITLE 'LOADER MODULE FOR CP/M 3.0 BIOS - DATE:831107' PAGE 43 EXTRN ?XMOVE,?MOVE,?BANK,MA3MIR Extrn @DTBL PUBLIC @ADRV,@RDRV,@TRK,@SECT,@DMA,@DBNK,@CNT,@CBNK PUBLIC ?PMSG,?PDERR,?PDEC ; PUBLIC @ERMDE PUBLIC DSKTMR,MONCNT MACLIB PORTS ; MACLIB Z80 ; MACLIB CPM3 ; if banked ERROR : banked must be equal false endif ;EXTERNAL NAMES FOR BIOS ENTRY POINTS PUBLIC ?BOOT,?WBOOT,?CONST,?CONIN,?CONO,?LIST,?AUXO,?AUXI PUBLIC ?HOME,?SLDSK,?STTRK,?STSEC,?STDMA,?READ,?WRITE PUBLIC ?LISTS,?SCTRN PUBLIC ?CONOS,?AUXIS,?AUXOS,?DVTBL,?DEVIN,?DRTBL PUBLIC ?MLTIO,?FLUSH,?MOV,?TIM,?BNKSL,?STBNK,?XMOV ;BIOS JUMP VECTOR ?BOOT: JMP BOOT ?WBOOT: JMP DUMMY ?CONST: JMP DUMMY ?CONIN: JMP DUMMY ?CONO: JMP CONOUT ?LIST: JMP DUMMY ?AUXO: JMP DUMMY ?AUXI: JMP DUMMY ?HOME: JMP HOME ?SLDSK: JMP SELDSK ?STTRK: JMP SETTRK ?STSEC: JMP SETSEC ?STDMA: JMP SETDMA ?READ: JMP READ ?WRITE: JMP DUMMY ?LISTS: JMP DUMMY ?SCTRN: JMP SECTRN ?CONOS: JMP DUMMY ?AUXIS: JMP DUMMY ?AUXOS: JMP DUMMY ?DVTBL: JMP DEVTBL ?DEVIN: JMP DUMMY ?DRTBL: JMP GETDRV ?MLTIO: JMP MULTIO ?FLUSH: JMP FLUSH ?MOV: JMP ?MOVE ?TIM: JMP DUMMY ?BNKSL: JMP DUMMY ?STBNK: JMP SETBNK ?XMOV: JMP DUMMY JMP 0 JMP 0 JMP 0 BOOT: ;--- SSPD BDOS$SP LXI SP,BOOT$STACK CALL ?INIT LXI B,16*256+0 LXI H,@DTBL D$INIT$LOOP: PUSH B MOV E,M ! INX H ! MOV D,M ! INX H MOV A,E ORA D JZ D$INIT$NEXT PUSH H XCHG DCX H ! DCX H MOV A,M STA @RDRV MOV A,C STA @ADRV DCX H ! MOV D,M ! DCX H ! MOV E,M XCHG CALL IPCHL POP H D$INIT$NEXT: POP B INR C DCR B JNZ D$INIT$LOOP LSPD BDOS$SP RET BDOS$SP: DW 00H DS 64 BOOT$STACK: EQU $ ;*********************************************************************** ; INTERRUPT VECTOR TABLE ;*********************************************************************** DS 1 CTCINT: DW DMYINT DW DMYINT DW TIMER DW DMYINT ;*********************************************************************** ; DEVTBL Return address of character device table devtbl: lxi h,@ctbl ! ret ; GETDRV Return address of drive table getdrv: lxi h,@dtbl ! ret ; CONOUT Console Output. Send character in <C> ; to all selected devices conout: lhld @covec ; fetch console output bit vector jmp out$scan out$scan: mvi b,0 ; start with device 0 co$next: dad h ; shift out next bit jnc not$out$device push h ; save the vector push b ; save the count and character not$out$ready: call coster ! ora a ! jz not$out$ready pop b ! push b ; restore and resave the character and device call ?co ; if device selected, print it pop b ; recover count and character pop h ; recover the rest of the vector not$out$device: inr b ; next device number mov a,h ! ora l ; see if any devices left jnz co$next ; and go find them... ret coster: ; check for output device ready mov l,b ! mvi h,0 ; make device code 16 bits jmp ?cost ; not a xon device, go get output status direct ; Utility Subroutines ipchl: ; vectored CALL point pchl ?pmsg: ; print message @<HL> up to a null ; saves <BC> & <DE> push b push d pmsg$loop: mov a,m ! ora a ! jz pmsg$exit mov c,a ! push h call ?cono ! pop h inx h ! jmp pmsg$loop pmsg$exit: pop d pop b ret ?pdec: ; print binary number 0-65535 from <HL> lxi b,table10! lxi d,-10000 next: mvi a,'0'-1 pdecl: push h! inr a! dad d! jnc stoploop inx sp! inx sp! jmp pdecl stoploop: push d! push b mov c,a! call ?cono pop b! pop d nextdigit: pop h ldax b! mov e,a! inx b ldax b! mov d,a! inx b mov a,e! ora d! jnz next ret table10: dw -1000,-100,-10,-1,0 ?pderr: lxi h,drive$msg ! call ?pmsg ; error header lda @adrv ! adi 'A' ! mov c,a ! call ?cono ; drive code lxi h,track$msg ! call ?pmsg ; track header lhld @trk ! call ?pdec ; track number lxi h,sector$msg ! call ?pmsg ; sector header lhld @sect ! call ?pdec ; sector number ret ; Disk I/O interface routines ; SELDSK Select Disk Drive. Drive code in <C>. ; Invoke login procedure for drive ; if this is first select. Return ; address of disk parameter header ; in <HL> seldsk: mov a,c ! sta @adrv ; save drive select code mov l,c ! mvi h,0 ! dad h ; create index from drive code lxi b,@dtbl ! dad b ; get pointer to dispatch table mov a,m ! inx h ! mov h,m ! mov l,a ; point at disk descriptor ora h ! rz ; if no entry in table, no disk mov a,e ! ani 1 ! jnz not$first$select ; examine login bit push h ! xchg ; put pointer in stack & <DE> lxi h,-2 ! dad d ! mov a,m ! sta @RDRV ; get relative drive lxi h,-6 ! dad d ; find LOGIN addr mov a,m ! inx h ! mov h,m ! mov l,a ; get address of LOGIN routine call ipchl ; call LOGIN pop h ; recover DPH pointer not$first$select: ret ; HOME Home selected drive. Treated as SETTRK(0). home: lxi b,0 ; same as set track zero ; SETTRK Set Track. Saves track address from <BC> ; in @TRK for further operations. settrk: mov l,c ! mov h,b shld @trk ret ; SETSEC Set Sector. Saves sector number from <BC> ; in @sect for further operations. setsec: mov l,c ! mov h,b shld @sect ret ; SETDMA Set Disk Memory Address. Saves DMA address ; from <BC> in @DMA and sets @DBNK to @CBNK ; so that further disk operations take place ; in current bank. setdma: mov l,c ! mov h,b shld @dma lda @cbnk ; default DMA bank is current bank ; fall through to set DMA bank ; SETBNK Set Disk Memory Bank. Saves bank number ; in @DBNK for future disk data ; transfers. setbnk: sta @dbnk ret ; SECTRN Sector Translate. Indexes skew table in <DE> ; with sector in <BC>. Returns physical sector ; in <HL>. If no skew table (<DE>=0) then ; returns physical=logical. sectrn: mov l,c ! mov h,b mov a,d ! ora e ! rz xchg ! dad b ! mov l,m ! mvi h,0 ret ; READ Read physical record from currently selected drive. ; Finds address of proper read routine from ; extended disk parameter header (XDPH). read: lhld @adrv ! mvi h,0 ! dad h ; get drive code and double it lxi d,@dtbl ! dad d ; make address of table entry mov a,m ! inx h ! mov h,m ! mov l,a ; fetch table entry push h ; save address of table lxi d,-8 ! dad d ; point to read routine address jmp rw$common ; use common code rw$common: mov a,m ! inx h ! mov h,m ! mov l,a ; get address of routine pop d ; recover address of table dcx d ! dcx d ; point to relative drive ldax d ! sta @rdrv ; get relative drive code and post it inx d ! inx d ; point to DPH again pchl ; leap to driver ; MULTIO Set multiple sector count. Saves passed count in ; @CNT multio: sta @cnt ! ret ; FLUSH BIOS deblocking buffer flush. Not implemented. flush: xra a ! ret ; return with no error DUMMY: RET ; error message components drive$msg db cr,lf,bell,'BIOS Error on ',0 track$msg db ': T-',0 sector$msg db ', S-',0 ; disk communication data items @adrv ds 1 ; currently selected disk drive @rdrv ds 1 ; controller relative disk drive @trk ds 2 ; current track number @sect ds 2 ; current sector number @dma ds 2 ; current DMA address @cnt db 1 ; record count for multisector transfer @dbnk db 1 ; bank for DMA operations @cbnk db 1 ; bank for processor operations @COVEC DW 0 ; Console Output Redirection ; Vector (word, r/w) @ERMDE DW 0 ; BDOS Error Mode (byte, r/o) ;========================================================================= ?INIT: LXI H,8000H ;ASSIGN CONSOLE TO CRT SHLD @COVEC ; LXI H,0C200H MOV A,L STA 0FFFEH+0AH MOV A,H STA 0FFFEH+0AH+1H LXI H,INIT$TABLE ;SET UP MISC. HARDWARE CALL OUT$BLOCKS ; CALL HW$INIT RET ; OUT$BLOCKS: MOV A,M ;GET COUNT VALUE ORA A ; RZ ; MOV B,A ;GET COUNT VALUE INTO <B> INX H ; MOV C,M ;GET PORT ADDRESS INTO <C> INX H ;<HL> POINTER TO OUTPUT VALUE OUTIR ; JMP OUT$BLOCKS ; INIT$TABLE: DB 1,P$DMA$CLEAR,0 ;CLEAR DMA DB 1,P$DMA$STAT,C$DMA$BYTE ;SET HARDWARE ATTRIBUTES DB 4,P$DMA$MODE,88H,85H,82H,83H ;SET CH.0-3 MODE REG. DB 00H ;TABLE TERMINATOR ;************************************************************************* ; I/O AND HARDWARE INITIALIZATION ROUTINE ;*********************************************************************** HW$INIT: MVI A,0FFH ;DELAY 1/4 SECOND FOR ANY ;UART CHAR IN PROGRESS CALL SDLY DI ; ;INIT TIMER MVI A,03H ;INIT ALSO SOFTWARE TIMER OUT P$DMA$INT ;CH0 RESET OUT P$MFD$INT ;CH1 RESET OUT P$SCI$INT ;CH3 RESET LXI H,CTCINT ; MOV A,L ; OUT P$CTC ; MVI A,0A5H ; OUT P$TIM$INT ;CH2 USED AS SOFTWARE TIMER MVI A,195 ;...AND BUS TIMER OUT P$TIM$INT ;INTERRUPT EVERY 12.5 MILLISECONDS ;INIT CPU MOV A,H ;CTC INTERRUPT VECTOR TABLE ADDRESS STAI ;MOV I,A INITIALIZE CPU PART OF IM2 ;IM 2 INTERRUPT LOGIC EI ; RET ;FINALLY DONE WITH ALL THAT ;*********************************************************************** ; 12.5 MSEC. TIMER INTERRUPT SERVICE ROUTINE ;*********************************************************************** MONCNT: DB 0 DSKTMR: DB 0 TIMER: EXAF MOTCHK: LDA MA3MIR ;CHECK IF MOTORS IS OFF ANI 080H ;MOTENB JZ TIMER1 ; LDA DSKTMR ;TEST IF 2 SEC HAS ELAPSED ANA A ; WITHOUT DISK ACCESS JNZ TIMER1 ; LDA MONCNT ; INR A ; STA MONCNT ; CPI 03H ;HAVE WE BEEN AT THIS FOR SIX SEC YET JNZ NEXT2 ; LDA MA3MIR ;IF SIX SEC HAS ELAPSED ANI 0FH ; STA MA3MIR ; OUT P$MAP3 ;SHUT OFF MINI MOTOR JMP TIMER1 ; NEXT2: MVI A,160 ;160*12.5 mSEC = 2 SEC STA DSKTMR ;SET ANOTHER 2 SEC DELAY TIMER1: LDA DSKTMR ;GET MINI FLOPPY MOTOR ON COUNTER ANA A JZ TEXIT ;IF NOT TIMED OUT DCR A ;COUNT DOWN STA DSKTMR ;OPDATE MEMORY IMAGE TEXIT: EXAF DMYINT: ;DUMMY INTERRUPTS CAN ENTER HERE EI RETI ;---------------------------------------------------------------------- SDLY: MVI L,070H DCR L JNZ $-1 DCR A JNZ SDLY RET ;========================================================================= MAX$DEVICE$NO EQU 01H ;DEVICE 0 ?COST: MOV A,B ;GET DEVICE NUMBER CPI MAX$DEVICE$NO ; JNC NULL$STATUS ; MOV L,B ;MAKE DEVICE NUMBER 16 BITS MVI H,0 ; PUSH H ; LXI D,STAT$PORTS ; DAD D ;MAKE POINTER TO PORT ADDRESS MOV C,M ; MVI A,10H ;RESET EXTERNAL STATUS OUTP A ; INP A ;GET STATUS POP H ;GET DEVICE NUMBER PUSH H ; LXI D,OUT$STAT$MASK ; DAD D ;MAKE POINTER TO MASK MOV C,M ; ANA C ; POP H ; LXI D,OUT$STAT$VALUE; DAD D ;MAKE POINTER TO VALUE MOV C,M ; CMP C ; JNZ NULL$STATUS ; ORI 0FFH ; RET ; ?CO: MOV A,B ;GET DEVICE NUMBER CPI MAX$DEVICE$NO ; JNC NULL$OUTPUT ; MOV A,C ;GET OUTPUT CHARACTER PUSH PSW ;SAVE CHARACTER PUSH B ; COL: CALL ?COST ; JZ COL ; POP B ; MOV L,B ; MVI H,0 ;MAKE DEVICE NUMBER 16 BITS LXI D,DATA$PORTS ; DAD D ;MAKE POINTER TO PORT ADDRESS MOV C,M ; POP PSW ;GET CHARACTER ANI 7FH ;MASK PARITY BIT OUTP A ; NULL$OUTPUT: RET NULL$STATUS: XRA A RET DATA$PORTS: DB P$CRT$DATA ; STAT$PORTS: DB P$CRT$STAT ; OUT$STAT$MASK: DB M$CRT$OUT ; OUT$STAT$VALUE: DB V$CRT$OUT ; @CTBL: DB 'CRT ' ;DEVICE 0 DB MB$IN$OUT+MB$SERIAL+MB$SOFT$BAUD DB BAUD$9600 ; ; DB 0 ;TABLE TERMINATOR END «eof»