home *** CD-ROM | disk | FTP | other *** search
- LIST NOCOND,NOGEN
- ;
- ;
- PERSCISW: EQU 0 ;ONE IF PERSCI DRIVE
- LARGESW: EQU 0 OR PERSCISW ;ONE IF MAXI DRIVE
- NUMDRIVES: EQU 2 ;ONE TO FOUR (MUST BE SAME TYPE)
- BIGIOSW: EQU 1 ;ZERO IF NO LIST, NO PUNCH
- ;
- BEGINADR: EQU 0E400H ;THIS IS THE START OF 64K CPM
- ;
- ORG 1600H+BEGINADR
- ;
- ; CROMEMCO 4FDC I/O ASSIGNMENTS
- ;
- CSTATPORT: EQU 00H ;3P + S, 4FDC, TU-UART, OR SCC
- CDATAPORT: EQU 01H
- IMODEPORT: EQU 02H ;(3P + S DOESNT HAVE THESE)
- IMASKPORT: EQU 03H
- PARLPORT: EQU 04H ;NOT USED
- ;
- STATPORT: EQU 30H ;4FDC OR CCS 2422 BOARD
- TRAKPORT: EQU 31H
- SECTPORT: EQU 32H
- DATAPORT: EQU 33H
- FLAGPORT: EQU 34H
- ;
- BANKPORT: EQU 40H ;MEMORY BANKING PORT
- ;
- ; 1771/179X EQUATES
- ;
- HEADLOAD: EQU 08H
- VERIFY: EQU 04H
- ;
- IF BIGIOSW = 1
- ;
- ; OTHER DEFINITIONS (OPTIONAL)
- ;
- BAUDRATE: EQU 01H ;110 BAUD FOR READER ?
- RSTATPORT: EQU 20H
- RBAUDPORT: EQU RSTATPORT ;TU-UART BOARD FOR PAPER TAPE
- RDATAPORT: EQU RSTATPORT+1
- PSTATPORT: EQU 20H
- PBAUDPORT: EQU PSTATPORT ;PAPER TAPE PUNCH ALSO
- PDATAPORT: EQU PSTATPORT+1
- LSTATPORT: EQU 54H ;PARALLEL PRINTER POARD
- LDATAPORT: EQU LSTATPORT
- ENDIF
- ;
- ; CPM ENTRY POINTS
- CPMB: EQU 00H+BEGINADR
- BDOS: EQU 806H+BEGINADR
- ;
- ; JUMP VECTOR
- JP CBOOT
- EBOOT:
- JP WBOOT
- JP CONSTAT
- JP CONIN
- JP CONOUT
- JP LIST
- JP PUNCH
- JP READER
- JP HOME
- JP SELDSK
- JP SETTRK
- JP SETSEC
- JP SETDMA
- JP READ
- JP WRITE
- JP LISTAT
- JP SECTRAN
- ;
- ; CP/M 2.2 DISK CONTROL BLOCKS
- ;
- DPBASE:
- DW XLT0,0000
- DW 0000,0000
- DW DIRBUF,DPB0
- DW CSV0,ALV0
- ;
- IF NUMDRIVES > 1
- DW XLT0,0000
- DW 0000,0000
- DW DIRBUF,DPB0
- DW CSV1,ALV1
- ENDIF
- ;
- IF NUMDRIVES > 2
- DW XLT0,0000
- DW 0000,0000
- DW DIRBUF,DPB0
- DW CSV2,ALV2
- ENDIF
- ;
- IF NUMDRIVES > 3
- DW XLT0,0000
- DW 0000,0000
- DW DIRBUF,DPB0
- DW CSV3,ALV3
- ENDIF
- ;
- DPB0:
- ;
- ; disk parameter block, common to all disks
- ; this implements a "standard" CP/M directory
- ; with 64 entries, and 1K blocks.
- ;
- DW 18+LARGESW*8 ;sectors per track
- DB 3 ;block shift factor
- DB 7 ;block mask
- DB 0 ;null mask
- DW 81+LARGESW*161 ;disk size-1
- DW 63 ;directory max
- DB 192 ;alloc 0
- DB 0 ;alloc 1
- DW 16 ;check size
- DW 3-LARGESW ;track offset
- ;
- XLT0:
- ;
- ; sector translate vector
- ;
- IF LARGESW EQ 0
- DB 1,6,11,16 ;sectors 1,2,3,4
- DB 3,8,13,18 ;sectors 5,6,7,8
- DB 5,10,15,2 ;sectors 9,10,11,12
- DB 7,12,17,4 ;sectors 13,14,15,16
- DB 9,14 ;sectors 17,18
- ENDIF
- ;
- ;
- IF LARGESW EQ 1
- DB 1,7,13,19 ;sectors 1,2,3,4
- DB 25,5,11,17 ;sectors 5,6,7,8
- DB 23,3,9,15 ;sectors 9,10,11,12
- DB 21,2,8,14 ;sectors 13,14,15,16
- DB 20,26,6,12 ;sectors 17,18,19,20
- DB 18,24,4,10 ;sectors 21,22,23,24
- DB 16,22 ;sectors 25,26
- ENDIF
- ;
- ;
- SIGNON:
- DEFB 13,10,10
- DEFB '64'
- DEFB 'k CP/M vers 2.2'
- DEFB 13,10,0
- ;
- SELDSK: ;
- LD HL,0
- LD A,C ;C CONTAINS REQUESTED DRIVE NO.
- CP NUMDRIVES
- RET NC ;IGNORE IF TOO HIGH
- LD (CURRDRIVE),A
- LD (DKNUMB),A
- LD L,C ;L=disk number 0,1,2,3
- ADD HL,HL ;*2
- ADD HL,HL ;*4
- ADD HL,HL ;*8
- ADD HL,HL ;*16 (size of each header)
- LD DE,DPBASE
- ADD HL,DE ;HL=.dpbase(diskno*16)
- RET
- ;
- SECTRAN: ;TRANSLATE SECTOR IN C USING TABLE AT DE
- LD B,0
- EX DE,HL ;TABLE ADDR TO HL
- ADD HL,BC ;GET ADDRESS
- LD L,(HL) ;GET BYTE
- LD H,0 ;ANSWER IN HL
- RET
- ;
- SETSEC:
- LD A,C ;JUST SAVE SECTOR NUMBER
- LD (DKSECT),A
- RET
- ;
- SETDMA:
- LD (DKDMA),BC ;JUST SAVE I/O ADDRESS
- RET
- ;
- ;
- ; ERROR CHECKING READ AND WRITE RTNS FOR
- ; CROMEMCO CBIOS
- ;
- READ:
- CALL CLEAR
- RETRYREAD:
- CALL READ4FDC ;READ SECTOR
- RET Z ;SUCCESSFUL READ. RETURN
- CALL ERROR ;INCREMENT RETRYCOUNT
- JR NZ,RETRYREAD ;RETRY 20 TIMES
- OR 01H ;CP/M CONVENTION FOR PERMANENT ERROR
- RET
- ;
- CLEAR:
- XOR A
- LD (TRKERCNT),A ;ZERO OUT TRACK ERROR COUNTER
- LD (RETRYCOUNT),A ;ZERO OUT CRC ERROR COUNTER
- RET
- ;
- WRITE:
- CALL CLEAR
- RETRYWRITE:
- CALL WRIT4FDC ;WRITE SECTOR
- RET Z ;SUCCESSFUL WRITE. RETURN
- CALL ERROR ;INCREMENT RETRYCOUNT
- JR NZ,RETRYWRITE ;RETRY 20 TIMES
- OR 01H ;CP/M CONVENTION FOR PERMANENT ERROR
- RET
- ;
- ERROR:
- PUSH HL
- AND 10H ;CHECK FOR NRF
- JR NZ,TRACKERROR
- LD HL,RETRYCOUNT
- INC (HL) ;INCREMENT RETRYCOUNT
- LD A,(HL)
- POP HL
- SUB 20 ;20 TRIES?
- RET
- ;
- TRACKERROR:
- LD HL,TRKERCNT
- INC (HL) ;INCREMENT NO OF TRACK ERRORS
- LD A,(HL)
- SUB 10D ;ALLOW ONLY 10 TRACK ERRORS
- POP HL
- RET Z ;IF >10, RETURN A FAILURE
- PUSH BC
- CALL HOME ;HOME THE HEAD
- LD A,(DKTRACK)
- LD C,A ;GET TRACK IN C
- CALL SETTRK ;RESEEK TO CORRECT TRACK
- POP BC
- OR 0FFH ;RETRY
- RET
- ;
- ; RESTORE THE DISK TO TRACK ZERO
- ;
- HOME:
- SUB A,A ;ZERO OUT TRACK COUNTER
- LD (DKTRACK),A
- CALL DISKSELECT ;NOW SELECT THE DISK
- OUT FLAGPORT,A
- LD A,02H+HEADLOAD+VERIFY ;USE SLOW STEPPING SPEED FOR ALL DISKS
- OUT STATPORT,A
- RSTI:
- IN A,FLAGPORT ;NOW CHECK STATUS
- RRA
- JR NC,RSTI ;LOOP BACK UNTIL DONE
- JP SEEKTEST
- ;
- ; HERE, ACTUALLY DO THE READ OPERATION
- ;
- READ4FDC:
- PUSH BC
- PUSH HL ;FIRST, SAVE REGS
- PUSH DE
- LD E,88H ;READ COMMAND (VALID FOR 1771, 179X)
- CALL INIT4FDC
- RDI1:
- IN A,FLAGPORT ;NOW CHECK FLAGS
- RRA
- JR C,RDI3 ;IF PREMATURELY DONE, STOP
- INI
- JR NZ,RDI1 ;READ ANOTHER BYTE INTO CORE UNTIL DONE
- RDI2:
- IN A,FLAGPORT ;CHECK FLAGS
- RRA
- JR NC,RDI2 ;LOOP UNTIL READY
- RDI3:
- IN A,STATPORT ;NOW CHECK STATUS
- AND A,9CH
- RDWREND:
- EI
- POP DE ;RESTORE REGS
- POP HL
- POP BC
- RET
- ;
- ; ACTUALLY DO WRITE OPERATION
- ;
- WRIT4FDC:
- PUSH BC
- PUSH HL ;SAVE REGS
- PUSH DE
- LD E,0A8H ;WRITE COMMAND (VALID FOR 1771, 179X)
- CALL INIT4FDC
- WRI1:
- IN A,FLAGPORT ;CHECK FLAGS
- RRA
- JR C,WRI3 ;IF PREMATURELY DONE, STOP
- OUTI
- JR NZ,WRI1 ;WRITE DATA FROM MEMORY TIL DONE
- WRI2:
- IN A,FLAGPORT ;CHECK FLAGS
- RRA
- JR NC,WRI2 ;LOOP TIL DONE WITH WHOLE OPERATION
- WRI3:
- IN A,STATPORT ;NOW CHECK ERROR STATUS
- AND A,0FCH
- JR RDWREND
- ;
- ; SET THE TRACK, AND MOVE DISK ARM THERE
- ;
- SETTRK:
- LD A,C
- LD (DKTRACK),A ;STORE THE TRACK NUMBER
- SUB A,A
- CALL DISKSELECT ;NOW SELECT THE DISK
- OUT FLAGPORT,A
- LD A,C
- OUT DATAPORT,A ;TELL 1771 ABOUT TRACK WANTED
- LD A,(DKSECT)
- OUT SECTPORT,A ;TELL IT ABOUT SECTOR WANTED
- PUSH HL
- PUSH DE
- LD HL,LOGINTAB ;NOW, SEE WHERE DISK ARM IS NOW
- LD A,(DKNUMB)
- LD E,A ;LOOK UP IN TABLE
- LD D,0
- ADD HL,DE ;GET BYTE
- LD A,(HL)
- OUT TRAKPORT,A ;TELL 1771 WHERE ARM IS NOW
- LD A,(HL)
- SUB A,C
- POP DE ;NOW CAN RESTORE THE REGS
- POP HL
- RET Z ;IF ALREADY AT THAT TRACK, QUIT
- LD A,12H-LARGESW*2+HEADLOAD+VERIFY
- OUT STATPORT,A ;PERFORM THE SEEK THAT IS NEEDED
- SKI:
- IN A,FLAGPORT ;CHECK FLAGS
- RRA
- JR NC,SKI ;LOOP UNITL OPERATION DONE
- SEEKTEST:
- IN A,STATPORT ;NOW CHECK ERROR STATUS
- AND A,98H
- RET NZ ;ZERO IS ALL OK
- PUSH DE
- LD D,0 ;UPDATE TRACK TABLE
- LD A,(DKNUMB)
- LD E,A ;WITH NEW POSITION
- IF PERSCISW = 1
- CALL ADDSHIFT ;PERSCI DRIVES HAVE ONE ARM FOR
- BIT 7,E ;TWO DISKS, SO MUST POST BOTH
- LD E,1 ;ENTRIES IN TABLE
- JR Z,ADD2SHFT
- LD DE,-1 ;THIS WAS THE OTHER ONE
- ADD2SHFT:
- CALL ADDSHIFT ;DO THE CORRECTION AND GO
- POP DE
- RET
- ENDIF
- ADDSHIFT: ;IF NOT PERSCI, FALL THRU HERE
- PUSH HL
- LD HL,LOGINTAB ;GET CORRECT ADDRESS OF DISK
- ADD HL,DE
- LD A,(DKTRACK) ;AND GET CURRENT TRACK NUMBER
- LD (HL),A
- SUB A,A ;PUT IT IN
- POP HL
- IF PERSCISW = 0
- POP DE ;AND MISC CLEANUP
- ENDIF
- RET
- ;
- ; INITIALIZE THE 4FDC, BY SELECTING THE DISK AND
- ; TURNING ON THE DISK MOTORS, AND INITIALIZE THE
- ; REGISTERS FOR THE I/O OPERATION
- ;
- INIT4FDC:
- LD A,80H ;FIRST, SELECT THE DISK
- CALL DISKSELECT
- LD HL,(DKDMA) ;INITIALIZE HL AND BC REGS FOR I/O
- LD BC,8000H+DATAPORT ;80H IS 128 BYTE SECTORS
- LD D,A ;SAVE THE A REG
- DI ;DISABLE INTERRUPTS
- LD A,(DKSECT)
- OUT SECTPORT,A ;SET THE SECTOR WANTED
- IN A,FLAGPORT
- CPL ;SEE IF HEAD IS LOADED
- AND A,20H
- JR Z,IN0
- LD A,04 ;THIS IS THE HEAD LOAD BIT
- IN0:
- ADD A,E ;ADD HEAD LOAD BIT TO COMMAND
- LD E,A
- LD A,D ;RESTORE THE A REG
- OUT FLAGPORT,A
- LD A,E
- OUT STATPORT,A ;OUTPUT THE COMMAND
- RET
- ;
- ; FIGURE OUT WHICH DISK TO SELECT AND PUT BIT THERE
- ;
- DISKSELECT:
- PUSH BC ;FIRST, SAVE THIS, ITS NEEDED
- LD C,A
- LD A,(DKNUMB) ;GET DISK NUMBER 0-3
- LD B,A
- INC B ;ADD ONE
- SUB A,A
- SCF ;SET A BIT IN TO BE SHIFTED
- SHIFTBIT:
- RLA ;NOW, ROTATE BITS OVER
- DJNZ SHIFTBIT
- LD B,A ;SAVE THE NEW VALUE
- XOR A
- OR A,20H+LARGESW*10H ;CONDITION 4FDC FOR MOTOR ON AND MAXI
- OR A,B
- OR A,C ;OR IN DRIVE SELECT AND COMMAND WANTED
- POP BC
- RET
- ;
- ; THIS TRAPS THE MISSING MEMORY ERROR, BECAUSE IF A
- ; MEMORY BOARD IS MISSING, THAT WILL GIVE FF'S, AND
- ; THE FF OP-CODE IS THE RST 38H, SO THAT TRAPS HERE
- ;
- MERROR:
- LD SP,80H
- LD HL,ERRMSG ;PRINT OUT THE ERROR AND WARMSTART
- CALL PRMSG
- ;
- ; GETS CONTROL ON A WARM START
- ;
- WBOOT:
- LD A,01H ;FIRST, RESTORE DEFAULT BANKING
- OUT BANKPORT,A
- ;
- LD SP,80H
- LD A,(DKNUMB)
- LD (CURRDRIVE),A ;STORE SELECTED DRIVE
- ;
- STARTBOOT:
- LD C,0
- CALL SELDSK ;SELECT DRIVE A TO REBOOT
- CALL HOME
- LD HL,CPMB-128 ;WILL INCREMENT BY 128 LATER
- LD (DKDMA),HL
- LD BC,44*256+1 ;SECTOR COUNT, FIRST SECTOR-1
- RDSEC:
- LD A,C ;C IS SECTOR NUMBER
- CP 18+LARGESW*8
- JR Z,NXTTRK
- LD DE,128 ;INCREMENT DMA ADDRESS
- LD HL,(DKDMA)
- ADD HL,DE
- LD (DKDMA),HL ;STORE DMA ADDRESS
- INC C ;INCREMENT SECTOR NUMBER
- CALL SETSEC
- CALL READ ;READ THE DATA
- JR NZ,WBOOT ;ON READ FAILURE TRY AGAIN
- DJNZ RDSEC
- JR BOOT ;READ CCP AND BDOS;
- NXTTRK:
- LD A,(DKTRACK)
- CP 2-LARGESW
- JR Z,BOOT ;STOP AT TRACK 2
- LD C,A
- INC C ;SEEK NEXT TRACK IF NOT
- CALL SETTRK
- LD C,0
- JR RDSEC
- ;
- ;
- CBOOT: ;AFTER COLD BOOT
- LD SP,80H ;INITIALIZE STACK FOR ROUTINE
- LD HL,SIGNON
- CALL PRMSG ;PRINT MESSAGE
- BOOT: ;GETS CONTROL AFTER COLD OR WARM BOOT
- DI
- LD A,0C3H ;SET UP PARAMETERS ON PAGE 0
- LD (0),A
- LD HL,EBOOT
- LD (1),HL
- LD (7*8),A ;PRINT ERROR AND BACK TO BOOT
- LD HL,MERROR ; (MAY BE DESTROYED BY DDT
- LD (7*8+1),HL
- LD (5),A
- LD HL,BDOS
- LD (6),HL
- ;
- ; CROMEMCO INITIALIZATION HERE (READER, LIST NOT NEEDED)
- ; NOTE .. THE CONSOLE TUART IS INITIALIZED BY RDOS
- ;
- IF BIGIOSW = 1
- LD A,BAUDRATE
- OUT PBAUDPORT,A
- ENDIF
- LD A,80H ;RST 7
- OUT IMASKPORT,A
- LD A,0CH ;RST7 AND INTA
- OUT IMODEPORT,A
- ;
- LD BC,80H ;SET DEFAULT DMA ADDR
- CALL SETDMA
- ;
- LD A,(CURRDRIVE) ;RESELECT THE DRIVE THAT WAS ACTIVE
- LD C,A ; BEFORE THE WARM START
- EI
- JP CPMB
- ;
- ;
- ERRMSG:
- DEFB 13,10,'?? ERROR ??',13,10,0
- ;
- PRMSG: ;PRINT MESSAGE AT H,L UNTIL 0
- LD A,(HL)
- OR A ;ZERO?
- RET Z
- LD C,A ;GO PRINT CHAR
- CALL CONOUT
- INC HL ;GET NEXT CHAR
- JR PRMSG
- ;
- ;
- ;HARDWARE UART CONSOLE ROUTINES
- ;
- CONSTAT:
- IN A,CSTATPORT ;CHECK CONSOLE STATUS
- AND 40H
- RET Z ;ZERO MEANS NO INPUT BYTE READY
- LD A,0FFH
- RET ;FF MEANS INPUT
- ;
- CONIN:
- CALL CONSTAT ;CHECK STATUS TIL GOT A BYTE
- JR Z,CONIN
- IN A,CDATAPORT ;READ THE BYTE AND KILL OFF 80H
- AND 7FH
- ;
- ; THE FOLLOWING CODE REPLACES THE DEL KEY WITH A CTRL-U,
- ; SO THAT DEL MEANS LINE DELETE. USE BACKSPACE TO DELETE
- ; A SINGLE CHARACTER.
- ;
- ; CP 127 ; DEL
- ; RET NZ
- ; SUB 127-21 ; CTRL-U
- RET
- ;
- ; CONSOLE OUTPUT ROUTINE
- ;
- CONOUT:
- IN A,CSTATPORT ;FIRST, LOOP UNITL TRANSMITTER BUFFER
- AND 80H ;IS EMPTY
- JR Z,CONOUT
- LD A,C ;NOW, OUTPUT CHARACTER TO CONSOLE
- OUT CDATAPORT,A
- RET
- ;
- ; LIST STATUS CHECK FOR CP/M 2.2
- ;
- LISTAT:
- IF BIGIOSW = 1
- IN A,LSTATPORT ;IF LIST TRANSMITTER IS BUSY,
- CPL ;THEN RETURN WITH ZERO
- AND 20H
- RET Z
- OR A,0FFH ;LIST TRANSMITTER BUFFER IS EMPTY
- RET
- ENDIF
- ;
- LIST:
- IF BIGIOSW = 1
- CALL LISTAT ;CHECK IF PRINTER BUSY
- JR Z,LIST
- LD A,C ;NOW OUTPUT CHARACTER
- SET 7,A
- OUT LDATAPORT,A ;WITH HIGH STROBE
- RES 7,A
- OUT LDATAPORT,A ;NOW LOW STROBE
- SET 7,A
- OUT LDATAPORT,A ;NOW HIGH STROBE AGAIN
- RET
- ENDIF
- ;
- PUNCH:
- IF BIGIOSW = 1
- IN A,PSTATPORT ;CHECK IF PUNCH BUFFER EMPTY
- AND 80H
- JR Z,PUNCH ;LOOP UNTIL READY
- LD A,C
- OUT PDATAPORT,A ;OUTPUT CHARACTER
- RET
- ENDIF
- ;
- READER:
- IF BIGIOSW = 1
- IN A,RSTATPORT ;SEE IF READER BUFFER FULL
- AND 40H
- JR Z,READER ;LOOP UNTIL FULL
- IN A,RDATAPORT ;AND READ IT
- RET
- ENDIF
- ;
- IF BIGIOSW NE 1
- XOR A,A ;DUMMY ROUTINE FOR LIST,PUNCH,READER
- RET
- ENDIF
- ;
- DKNUMB: EQU 4 ;THIS IS WHERE THE DISK NUMBER IS
- ; ;KEPT IN NORMAL CP/M
- CURRDRIVE:
- DB 0 ;THE SAVE AREA FOR THE DEFAULT DRIVE
- LOGINTAB:
- DB 2-LARGESW,0,0,0 ;FOUR DRIVES MAX
- DKSECT:
- DB 0 ;SECTOR NUMBER
- DKTRACK:
- DB 0 ;TRACK NUMBER
- DKDMA:
- DW 0 ;DMA ADDRESS
- TRKERCNT:
- DB 0 ;NUMBER OF TRACK ERRORS
- RETRYCOUNT:
- DB 0 ;NUMBER OF READ ERRORS
- ;
- ; FROM HERE ON, THE AREAS ARE INITIALIZED BY CP/M AS NEEDED
- ;
- DIRBUF:
- DS 128 ;SAVE AREA FOR DISK DIRECTORY OPERATIONS
- ;
- ;
- ALV0:
- DS 32
- ;
- IF NUMDRIVES > 1
- ALV1:
- DS 32
- ENDIF
- ;
- IF NUMDRIVES > 2
- ALV2:
- DS 32
- ENDIF
- ;
- IF NUMDRIVES > 3
- ALV3:
- DS 32
- ENDIF
- ;
- CSV0:
- DS 16
- ;
- IF NUMDRIVES > 1
- CSV1:
- DS 16
- ENDIF
- ;
- IF NUMDRIVES > 2
- CSV2:
- DS 16
- ENDIF
- ;
- IF NUMDRIVES > 3
- CSV3:
- DS 16
- ENDIF
- ;
- ; THIS HAD BETTER BE WITHIN YOUR CORE SIZE
- ;
- END
-