home *** CD-ROM | disk | FTP | other *** search
- PAGE 62
- ;P2BIOS.ASM aka ACIBS1K.ASM
- ;ALSPA COMPUTER, INC. Double Density Floppy Disk BIOS P2DOS/CPM2.2
- ;******************************************************
- ;EDIT HISTORY
- ; DATE: REL: MOD:
- ;01/11/82 - 02/01/82 1.8 ACIBS modified to 61K CPM, Blocking added
- ;02/01/82 - 02/02/82 Track mechanism fixed, side A:/B: code removed
- ;02/03/82 - 02/04/82 Diskswap fixed
- ;02/08/82 - 02/09/82 2.0 B: Logon fixed, sign-on 'glitch' fixed
- ;02/18/82 - 02/18/82 RCLOCK/WCLOCK timing fix, PIP/Density fixed
- ;02/25/82 2.1*SELDSK modified to delay disk change till R/W/SEEK
- ;03/02/82 2.2 Disk chg (dbl-sd PIP[V]) problem fixed
- ;03/05/82 D B: (rev A) problem fixed
- ;03/08/82 IBM format on B: option supported (rev xI)
- ;03/15/82 SYSFMT generated from IOBYTE, IOBYTE corrected
- ;03/16/82 - 03/25/82 2.3 Clock routines updated, IO routines re-done
- ;04/19/82 - 04/26/82 IOBYTE select, Coldboot in buffer, Autostart done.
- ;04/27/82 - 05/05/82 2.4 Add Motor on/off, User#/JumpTable saved in Wboot.
- ;05/07/82 2.5 System speed optimized.
- ;05/10/82 2.6 Wboot select error fixed.
- ;05/19/82 - 05/20/82 Select problem (when no Home after SELDSK) fixed.
- ;05/21/82 2.7*Select C:+ problem (drive# in Wboot) fixed.
- ;05/22/82 2.8*Tandon Motor-On speed mod.
- ;05/24/82 2.9 Motor-On mod improved (spindle-speed test added).
- ;08/23/82 - 08/25/82 3.0 1 Drive Side-select(B:dbl1/A:sngl0) bug fixed.
- ;10/27/82 - 11/02/82 Type-ahead buffer added (WordStar users rejoice).
- ;11/10/82 Density flag clear in HOME added (for JBS drives).
- ;11/10/82 - 11/11/82 Flush buffer on CONIN added.
- ;12/09/82 - 12/21/82 Autoswitch IOBYTE option added, Warmboot CCP only.
- ;12/21/82 - 01/17/83 3.1 Code for self-load of ACIDOS.COM file added.
- ;03/03/85 - 03/03/85 3.2%Added USER0 code
- ;09/18/87 3.3%Added USER0 warning (USER0 kills ZCPR3 & FCOPY)
- ;10/30/87 - 11/09/87 Added P2DOS support.
- ;11/10/87 - 11/12/87 made rev A code optional, to save a few bytes,
- ;11/15/87 Added 2-drive only flag and p2dos time function.
- ;11/17/87 Added clear of mem above BIOS on coldboot.
- ;11/21/87 Added ZCPR3 definitions.
- ;11/24/87 - 11/26/87 Added ZCPR3/P2DOS overlays and data areas.
- ;11/28/87 - 11/29/87 3.4%Added fix for motor-on problem.
- ;01/12/88 3.5%Upgraded for P2DOS v. 23
- ;01/27/89 3.6%Added parallel printer status
- ;09/19/89 - 09/20/89 3.7%Modified to NOT use DIRBUF for scratch area.
- ; possible improvement - flush on nnnn*CONST (if no char is input)??
- ; * Unreleased/Limited Release versions
- ; % Special version - Custom by W.O.S.
- ;******************************************************
- MO EQU 09 ;LAST EDIT DATE
- DA EQU 20
- YR EQU 89
-
- REVNO EQU 37 ;REVISION #
-
- TRUE EQU 0FFFFH
- FALSE EQU NOT TRUE
-
- VER36 EQU FALSE ;Version3.6 code option (for restore after testing 3.7)
- ;************************************************************
- ;* USER-SELECTED ASSEMBLY-TIME OPTIONS *
- ;************************************************************
- IBMB EQU FALSE ;Set to true if IBM disk compatibility is desired.
- ;This will cause the system to use 'diskette' density
- ;when reading Track 1 of disks B:,C:,... (i.e. not A:).
- ;ALSPA disks always use double-density
- ;on track 1 to hold the system, even if disk density
- ;is single-d. Since the system on B: is not likely
- ;to be read (except, maybe, by 'Disk Editor' utilities)
- ;This should not affect normal operation. If an IBM-CPM
- ;translation utility is used, this option MUST be
- ;selected.
- LL EQU 0 ;DEFAULT PRINTER OPTION: (0,1,2,or 3)
- ;0=Parallel printer interface
- ;1=(console output)
- ;2=Serial interface, ETX/ACK protocol
- ;3=Serial interface, X-ON/X-OFF(or NO) protocol
- DD EQU 2 ;# OF PHYSICAL FLOPPY DISK DRIVES: (1 or 2)
- AA EQU 1 ;AUTOSWITCH OPTION: (0 OR 1)
- ;0=Autoswitch enabled
- ;1=Autoswitch disabled
- ;The Autoswitch option runs the Modem and Console ports
- ;in parallel, i.e. any character input from either
- ;port is accepted as console input, and is echoed to
- ;both Console and Modem output ports.
- SS SET 0 ;AUTOSTART OPTION: (0 OR 1)
- ;0=Autostart enabled (both Cold/Warmboot)
- ;1=Autostart disabled (Coldboot only)
- ;The Autostart option allows the user to insert a
- ;command in the CCP to be executed upon either coldboot
- ;or warmboot. If the option is disabled, the command in
- ;the CCP buffer will be ignored on warmboot, but
- ;executed upon coldboot(power-on or reset).
- ;Autostart MUST be ENABLED for ZCPR3!
- QSIZE EQU 25 ;Type-ahead buffer size (maximum: 255 characters)
- TYPEAHEAD EQU TRUE ;TYPE-AHEAD Option = TRUE or FALSE
- USER0 SET FALSE ;Add USER 0 = Public capability (patch CCP).
- ;USER0 MUST be FALSE for ZCPR3!
- P2DOS EQU FALSE ;TRUE if this is a P2DOS BIOS, FALSE for CP/M.
- ZCPR3 EQU TRUE ;TRUE if this BIOS is to be use with ZCPR3.
- DEBUG EQU FALSE ;Add debugging code - watch ENDDISK parameter!
- ;G = GoCPM dnn = drive# tnn = track#
- ;snn = sector# r = read w = write
- ;R = real read W = real write H = real home
- ;* = warmboot xnn = xlat sector
- NOREVA EQU TRUE ;If true, BIOS handles Alspa rev B boards only.
- ONLY2 EQU TRUE ;TRUE for 2-drive only version (saves code space).
- ;*******************************************************************
- if ZCPR3
- SS SET 0
- USER0 SET FALSE
- endif
-
- MSIZE EQU 61 ;MEMORY SIZE
- if not NOREVA
- REVA EQU 'A' ;VALUE OF CPU-BOARD=REV.A FLAG
- REVB EQU 'B' ;VALUE OF CPU-BOARD=REV.B FLAG
- endif
-
- ;SERIAL I/O PORTS (8251)
- MSTAT EQU 5 ;MODEM STATUS PORT
- MDATA EQU 4 ;MODEM DATA PORT
- CSTAT EQU 3 ;CONSOLE STATUS PORT
- CDATA EQU 2 ;CONSOLE DATA PORT
- LSTAT EQU 1 ;LIST STATUS PORT
- LDATA EQU 0 ;LIST DATA PORT
-
- ;PARALLEL I/O PORTS (8255 - REV B ONLY)
- PPORTA EQU 0D0H ;8255 PORT A
- PPORTB EQU PPORTA+1 ;8255 PORT B
- PPORTC EQU PPORTA+2 ;8255 PORT C
- PPCMD EQU PPORTA+3 ;8255 COMMAND PORT
- PPINIT EQU 91H ;A MODE0 IN, C HI OUT; B MODE0 OUT, C LO IN
-
- ;**********************************************************
- ;* SYSTEM CONFIGURATION: *
- ;* Both IOBYTE and SYSFMT are initialized from 'IOBYTA': *
- ;* IOBYTE=(IOBYTA AND IOBMSK) OR (DFTSY SHR 2 AND 1) *
- ;* SYSFMT=(IOBYTA AND SYSMSK) OR DFTSY *
- ;* This is done for continuity with earlier systems which *
- ;* used IOBYTE for all the system configuration functions.*
- ;**********************************************************
- IOBYTE EQU 0003H ;I/O BYTE: <llpprrcc> (Reserved Memory location)
- ;IOBYTE assignments: (Default = '*', optional defaults = '-')
- ;------------------------------------------------
- ;ll: prn protocol pp: punch device
- ;-00 PARALLEL TTY: -00 PARALLEL PRN TTY:
- ;-01 (CONSOLE OUT) CRT: -01 (not used) PUN:
- ;-10 ETX/ACK LPT: *10 MODEM OUT UP1:
- ;*11 XON/XOFF(or NO) UL1: -11 CLOCK WRITE UP2:
- ; --------------------------------------
- ;rr: reader device cc: console device
- ;-00 (not used) TTY: *00 CONSOLE TTY:
- ; 01 (not used) RDR: 01 CONSOLE/MODEM CRT: (autoswitch)
- ;*10 MODEM IN UR1: -10 MODEM I/O BAT:
- ; 11 CLOCK READ UR2: 11 CLOCK R/W UC1:
- ;------------------------------------------------
- ;SYSFMT Sytem format byte: <---s-a-d>
- ;s: autostart mode a: autoswitch mode d: #drives
- ; 0 on (cold/warm) 0 on(modem&console) 0 2-drives
- ;*1 off (cold) *1 off(console only) *1 1-drive
- ;------------------------------------------------
- SYSMSK EQU 05H ;(Mask for bits used in SYSFMT from IOBYTA)
- IOBMSK EQU (NOT SYSMSK) AND 0FFH ;(Mask for bits used in IOBYTE from IOBYTA)
- DFTIO EQU ((LL shl 6 or 28H) and iobmsk) ;Default IOBYTE
- DFTSY EQU (AA*4+(not (DD-1) and 1)+(SS*10H and 10H)) ;Default SYSFMT
- DFLTIOB EQU DFTIO or (DFTSY AND SYSMSK) ;Default IOBYTA
- ;********************************************************
- CDISC EQU 0004H ;CP/M Reserved memory location - current disk
-
- ;DOUBLE DENSITY TEST CODE FLAG
- ;NOTE: FOR A DISK TO BE CONSIDERED DOUBLE DENSITY
- ;CODE3 MUST BE ALREADY ON THE DISK AT TRACK 0
- ;SECTOR 1, BYTE 7F (LAST BYTE)
- ;CODE4 FOR DOUBLE DENSITY DOUBLE SIDE
- CODE3 EQU 0DDH
- CODE4 EQU 0D0H
- SINGL EQU 2 ;LOGDEN VALUE FOR SINGLE DENS. DISK
-
- ;BLOCKING/DEBLOCKING PARAMETERS
- WRALL EQU 0 ;WRITE TO ALLOCATED SECTOR*BDOS
- WRDIR EQU 1 ;WRITE TO DIRECTORY *CONSTANTS
- WRUAL EQU 2 ;WRITE TO UNALLOCATED SEC.*
- HSTSIZ EQU 1024 ;PHYSICAL SECTOR SIZE
- HSTSPT EQU 8 ;HOST SECTORS PER TRACK
- HSTBLK EQU HSTSIZ/128 ;CPM SECTORS/HOST SECTOR
-
-
- ;DISK IO PORTS
- DISK EQU 0F8H ;DISK BASE ADDRESS.
- DCOM EQU DISK ;DISK COMMAND PORT.
- DSTAT EQU DISK ;DISK STATUS PORT.
- TRACK EQU DISK+1 ;DISK TRACK PORT
- SECTP EQU DISK+2 ;DISK SECTOR PORT.
- DDATA EQU DISK+3 ;DISK DATA PORT.
- DSEL EQU DISK+5 ;DENSITY SELECT/MOTOR CONTROL PORT:
- ; CODE: | 01/02 | 04/08 |
- ; |density=dble/single|motor=on/off(revB)|
- DCONT EQU DISK+4 ;DISK CONTROL PORT:
- ; CODE: | 01/02 | 04/08 |
- ;REV B: |disk=B/A |side=1/0 |
- ;REV A: |disk/side| n/a |
-
- ;CPM PARAMETERS
- RTCNT EQU 10 ;RETRY COUNT
- BIAS EQU (MSIZE-20)*1024 ;BIAS FOR LARGER THAN 17K.
- CCP EQU BIAS+3400H ;START OF CPM.
- OFFSET EQU 980H-CCP ;OFFSET USED WITH DDT IN SYSTEM CONFIGURATION
- BDOS EQU CCP+806H ;BASE OF BDOS
- BIOS EQU CCP+1600H ;BASE OF BIOS
- CPML EQU BDOS-CCP ;LENGTH OF CPM CCP (re-loaded in warmboot).
- NSECTS EQU (CPML+127)/128 ;NUMBER OF CPM SECTORS IN IT.
- NPSECTS EQU (HSTSIZ-1+NSECTS*128)/HSTSIZ ;# OF PHYSICAL SECTORS
- MAXDRV EQU 1 ;DRIVES 0 - 1 VALID
- CCCONOT EQU CCP+8CH ;CCP: OUTPUT A TO CONSOLE
- CCGTUSR EQU CCP+113H ; GET USER NUMBER
- CCSTUSR EQU CCP+115H ; SET USER NUMBER
- CCOPFCB EQU CCP+0D0H ; CCP OPEN FILE (CPMFCB$)
- CCATTR EQU CCP+7D6H ; ATTRIBUTE FIELD IN CPMFCB$
- CCDSK EQU CCP+7F0H ; DISK GIVEN IN COMMAND STRING
- CCERR EQU CCP+76BH ; TYPE ERROR STRING
- CCLOAD EQU CCP+6DEH ; IF FILE OPENS, GO HERE
-
- ;Character Equates
- CR EQU 0DH
- LF EQU 0AH
- ESC EQU 1BH
- BELL EQU 7
-
- ;Z80 OPCODE EQUATES
- JR EQU 18H ;JR XX
- JRNZ EQU 20H ;JR NZ,XX
- JRZ EQU 28H ;JR Z,XX
- JRNC EQU 30H ;JR NC,XX
- JRC EQU 38H ;JR C,XX
- RRCB EQU 08CBH ;RRC B
- LDIR EQU 0B0EDH ;LDIR
- SRLA EQU 2FCBH ;SRL A
- DJNZ EQU 10H ;DJNZ XX
- PUSHIX EQU 0E5DDH ;PUSH IX
- LDIX EQU 21DDH ;LD IX,XXXX
- POPIX EQU 0E1DDH ;POP IX
- INI EQU 0A2EDH ;INI
- JPIX EQU 0E9DDH ;JP (IX)
- OUTI EQU 0A3EDH ;OUTI
- OUTCA EQU 79EDH ;OUT (C),A
- INAC EQU 78EDH ;IN A,(C)
- SBCHLDE EQU 52EDH ;SBC HL,DE
- RES2HL EQU 96CBH ;RES 2,(HL)
- RES3HL EQU 9ECBH ;RES 3,(HL)
-
- ;***********ACIDOS.COM PREFACE CODE****************
- ;This code allows the ACIDOS.COM to be executed. If run
- ;(by mistake), it merely brings up the new operating system.
- ORG 0100H-OFFSET
- LXI H,CCP+OFFSET ;COPY (image in ram from .COM file)
- LXI D,CCP ; TO (executable address)
- LXI B,ENDISK-CCP ; (# of bytes of image)
- DW LDIR
- JMP BIOS ;COLDSTART (image at executable address)
- DB ' no copyright message here '
- ;***************************************************
-
- if USER0
- ;***********USER0 PATCHES ON THE CCP****************
- ;This code patches the CCP to look first on the A: drive, then in USER 0
- ;for command files requested but not found in the current user number.
- ;It makes a call on a routine assembled intp the BIOS.
- ORG CCP+6DBH ;Replace 'jz ccerr' with 'jz patch'
- JZ CCPATCH ;Patch is called if file isn't found
- ;in current user.
- ORG CCP+7F2H ;Patch is placed in area of CCP occupied
- CCPATCH: ;by unused NOPs.
- LXI H,CCDSK ;Get drive spec'd in command
- ORA M ;If explicit drive given, look in USER0
- JNZ CHKUSR0
- INR M ;Else set A (was 0 on entry) to A:
- LXI D,CCATTR ; and retry (re-enter CCP)
- JMP CCP+6CDH
- ;***************************************************
- endif
-
- ; I/O JUMP VECTOR
- ; THIS IS WHERE CPM CALLS WHENEVER IT NEEDS
- ; TO DO ANY INPUT/OUTPUT OPERATION.
- ; USER PROGRAMS MAY USE THESE ENTRY POINTS
-
- ORG BIOS
-
- JMP CBOOT ;FROM COLD START LOADER.
- WBOOTE: JMP WBOOT
- JMP LCONST
- JMP LCONIN
- JMP LCONOUT
- JMP LLIST
- JMP LPUNCH
- JMP LREADER
- JMP HOME
- JMP SELDSK
- JMP SETTRK
- JMP SETSEC ;SET SECTOR NUMBER.
- JMP SETDMA ;SET DISK STARTING ADR.
- JMP READ ;READ SELECTED RECORD
- JMP WRITE ;WRITE SELECTED RECORD
- JMP LLISTST ;RETURN LIST STATUS
- JMP SECTRAN ;SECTOR TRANSLATE
- ; this must be after 17th JUMP address
- DFLAGS: DB 0,0,0,0 ;DENSITY FLAGS *do
- CALL BLDPTR ;DENSITY SETTING ROUTINE*not
- CALL DENSITY ;FOR FCOPY PROGRAM *move
- RET ; *or
- IOBYTA: DB DFLTIOB ;DEFAULT I/O BYTE *change
- SYSFMT: DB DFTSY and IOBMSK ; *
- if not P2DOS
- DB 'Reserve';FOR FUTURE USE *
- endif
- if P2DOS
- JMP BTIME ;BIOS TIME ROUTINES *
- DB 'free' ;FOR FUTURE USE *
- endif
- UARTT: DB 0CEH ;USART MODE SELECT *
- UARTP: DB 0CEH ;CODES *
- UARTM: DB 0CEH ; *
-
- ;FIXED DATA TABLES FOR TWO-DRIVE STANDARD
- ;IBM-COMPATIBLE 8" DISKS (MODIFIED IN 'DENSITY').
- ; DISK PARAMETER HEADER FOR DISK 00 -SNGL D
- DPBASE: DW TRANS,0000H
- DW 0000H,0000H
- DW DIRBF,DPSDBK
- DW CHK00,ALL00
- ; DISK PARAMETER HEADER FOR DISK 01 -SNGL D
- DW TRANS,0000H
- DW 0000H,0000H
- DW DIRBF,DPSDBK
- DW CHK01,ALL01
-
- ; SINGLE DENSITY SECTOR TRANSLATE VECTOR
- TRANS: 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
-
- ; DOUBLE DENSITY SECTOR TRANSLATE VECTOR
- TRANSD: EQU 0 ;NO SECTOR TRANSLATION
-
- DPDDBK: ;DOUBLE DENSITY PARAMETER BLOCK
- DW 64 ;SECTORS PER TRACK - SPT
- DB 4 ;BLOCK SHIFT FACTOR - BSH
- DB 15 ;BLOCK MASK - BLM
- DB 0 ;NULL MASK - EXM
- DW 300-1 ;DISK SIZE IN BLOCKS - DSM
- DW 128-1 ;DIRECTORY MAX ENTRIES - DLM
- DB 0C0H ;DIR. ALLOC. MASK - AL0
- DB 0 ;DIR. ALLOC. MASK - AL1
- DW 128/4 ;DIR. CHECK SIZE - CKS
- DW 2 ;TRACK OFFSET - OFF
- DB 16 ;BLOCKSIZE/128 ****************
- DB 7 ;SECMASK *BLOCKING PARMS*
- DB 3+1 ;SECSHF * DO NOT MOVE *
- DB 64 ;CPMSPT ****************
- DPDDBK1: ;DOUBLE DENSITY PARAMETER BLOCK (2 side)
- DW 64 ;SECTORS PER TRACK - SPT
- DB 5 ;BLOCK SHIFT FACTOR - BSH
- DB 31 ;BLOCK MASK - BLM
- DB 1 ;NULL MASK - EXM
- DW 304-1 ;DISK SIZE IN BLOCKS - DSM
- DW 128-1 ;DIRECTORY MAX ENTRIES - DLM
- DB 80H ;DIR. ALLOC. MASK - AL0
- DB 0 ;DIR. ALLOC. MASK - AL1
- DW 128/4 ;DIR. CHECK SIZE - CKS
- DW 2 ;TRACK OFFSET - OFF
- DB 32 ;BLOCKSIZE/128 *BLOCKING PARMS *
- DB 7 ;SECMASK * =HSTSIZ/128-1 *
- DB 3+1 ;SECSHF *=LG2(SCMSK+1)+1*
- DB 64 ;CPMSPT *=HSTBLK*HSTSPT *
- DPSDBK: ;DISK PARAMETER BLOCK, SINGLE DENSITY
- DW 26 ;SECTORS PER TRACK
- DB 3 ;BLOCK SHIFT FACTOR
- DB 7 ;BLOCK MASK
- DB 0 ;NULL MASK
- DW 242 ;DISK SIZE-1
- DW 63 ;DIRECTORY MAX
- DB 192 ;ALLOC 0
- DB 0 ;ALLOC 1
- DW 16 ;CHECK SIZE
- DW 2 ;TRACK OFFSET
- DB 8 ;BLOCKSIZE/128 ****************
- DB 0 ;SECMASK *BLOCKING PARMS*
- DB 0+1 ;SECSHF * DO NOT MOVE *
- DB 26 ;CPMSPT ****************
-
- ;******** END OF FIXED TABLES **************************************
-
- ;*******************
- ; COLDBOOT: STARTUP
- ;*******************
- DB MO,DA,YR;THIS MUST PRECEDE CBOOT
- CBOOT: JMP BOOT ;BOOT CHANGES THIS TO WBOOT
-
-
- ;***************************************************************
- ; WARM-BOOT: READ CCP AND PART OF BDOS BACK IN, THEN JUMP TO CCP.
- ;****************************************************************
- ;*** THIS CODE BYTE MUST BE ALWAYS BE THE BYTE BEFORE LABEL WBOOT: ***
- DB 0DDH ;*** DO NOT MOVE OR REMOVE ***
-
- WBOOT:
- if DEBUG
- MVI A,'*'
- CALL CONOUTA
- endif
- LXI SP,80H ;SET STACK POINTER.
- LDA SEKDSK ;SAVE DISK NUMBER.
- PUSH PSW ;
- XRA A ;CLEAR BLOCKING FLAGS
- STA HSTACT ; -HOSTBUFFER INACTIVE
- STA UNACNT ; -UNALLOC CT=0
- STA HSTWRT ; -NO PENDING WRITE
- STA SEKDSK ;SET DISK=0 (A:)
- CALL CLRDFLGS;CLEAR DENSITY FLAGS
- CALL CHKSD ;SELECT A:
- MVI A,1 ;
- CALL SEEK ;SET TRACK=1
- MVI A,1 ;SECTOR=E=1
- OUT SECTP ;
- MOV E,A ;
- LXI H,CCP ;HL -> CCP
- MVI C,DDATA ;C -> DATAPORT(1793)
- MVI A,8CH ;A=(READ W/15MS DELAY)COMMAND
- WBOOT2: CALL RLOOP ; READ SECTOR(E) => (HL)
- IN DSTAT ; IF (ERROR) THEN EXIT(RDERR)
- ANI 9DH ;
- DB JRNZ,BTERR-$-1
- INR E ; INCREMENT SECTOR
- MOV A,E ; IF (SECTOR=NPSECTS) THEN EXIT(DONE)
- CPI NPSECTS+1 ;
- DB JRZ,WBOOT3-$-1
- OUT SECTP ; SET SECTOR(E)
- MVI A,88H ; A=(READ W/NO DELAY)COMMAND
- DB JR,WBOOT2-$+0FFH ; END
-
- WBOOT3: POP PSW ;RESTORE DISK NUMBER.
- STA SEKDSK ;
- if not P2DOS
- LDA SYSFMT ;IF (AUTOSTART OFF) DISABLE CCP COMMAND
- ANI 10H
- DB JRZ,GOCPM-$-1
- XRA A
- STA CCP+7
- endif
-
- GOCPM: if DEBUG
- MVI A,'G'
- CALL CONOUTA
- endif
- MVI A,0C3H ;PUT JMP TO WBOOT
- STA 0 ;ADR AT ZERO.
- LXI H,WBOOTE
- SHLD 1
- STA 5
- LXI H,BDOS ;PUT JUMP TO BDOS
- SHLD 6 ;AT ADR 5,6,7.
- LXI H,80H ;SET DEFAULT DMA ADR.
- SHLD DMAADD
- LDA SEKDSK ;GET LAST REQUESTED DISK#
- MOV C,A
- PUSH B
- CALL CHKDS1 ;SET UP DRIVE
- POP B
- LDA CDISC
- ANI 0F0H ;GET USER# (if c:+ requested, cdisc is wrong)
- ORA C ;GET (REAL) DRIVE #
- MOV C,A
- if P2DOS and ZCPR3
- JMP P2CWBT ;Do extra ZCPR3 warmboot stuff (reinit Submit FCB).
- endif
- if (not P2DOS) or (not ZCPR3)
- JMP CCP ;JUMP TO CCP.
- endif
-
-
- BTERR: LXI H,BTMSG ;GET ADDRESS OF "BOOT ERROR".
- CALL ERMSG ;PRINT IT.
- CALL LCONIN ;READ A CHAR FROM CONSOLE.
- JMP WBOOT ;DO A WARM BOOT.
-
- CLRDFLGS:
- LXI H,0 ;CLEAR DENSITY FLAGS
- SHLD DFLAGS ;
- SHLD DFLAGS+2;
- RET
-
- ;****************************************************************
- ;SELDSK: SELECT DISK NUMBER ACCORDING TO REGISTER C.
- ;BLDPTR: BUILD POINTER (IN HL) TO DISK PARM BLK HEADER
- ;****************************************************************
- SELDSK:
- if DEBUG
- MVI A,'d'
- CALL CONOUTA
- MOV A,C
- CALL PHEX
- endif
- LDA SEKDSK ;SAME AS LAST DRIVE REQUESTED?
- CMP C ;
- DB JRZ,BLDPTR-$-1; YES, JUST BUILD DRIVE HEADER POINTER.
- MOV A,C ;
- CPI MAXDRV+1;SEE IF DRIVE NO. IS VALID
- LXI H,0 ; (IF INVALID, RETURN HL=0)
- RNC ;ERROR - RETURN IF OUT OF RANGE
- PUSH PSW ;IF WRITE PENDING THEN
- CALL FLUSH ; FLUSH BUFFER
- POP PSW ;
- STA SEKDSK ;SEKDSK=NEW DRIVE SELECTED
- MOV C,A ;BUILD DPB HEADER POINTER
- CALL BLDPTR ;
- JMP DENSITY ;GET DENSITY PARMS
-
- BLDPTR: ;COMPUTE SEL. DRIVE HEADER VECTOR
- MOV L,C ;DISK NO.
- MVI H,0 ;AS 16 BIT QTY.
- DAD H ;*2 (BUILD 16-BYTE OFFSET)
- DAD H ;*4
- DAD H ;*8
- DAD H ;*16
- LXI D,DPBASE;TABLE BASE
- DAD D ;EFFECTIVE ADDRESS OF VECTOR
- RET ;
-
- ;****************************************************
- ;CHKSD: CHECK THAT CURRENT DISK=SELECTED DISK &
- ;CHKDSK: CHECK THAT DISK (C) =SELECTED DISK &
- ; & SELECT IF NOT
- ;****************************************************
- CHKSD: LDA SEKDSK ;C=SEKDSK
- CHKDSA: MOV C,A
- CHKDSK: LDA CURDSK ;A=CURDSK
- CMP C ;IF (A=C) THEN RETURN(&TURN MOTORS ON)
- JZ MTRON ;
- CHKDS1: ;/******* ENTRY FOR BOOT (A=C=0)*******/
- ;/*FROM HERE ON, C=DISK TO BE SELECTED*/
- MOV E,A ;HL => TRACKTABLE(LASTDRIVE)
- MVI D,0 ;
- LXI H,TRTAB ;
- DAD D ;
- IN TRACK ;A = 1793 TRACK REGISTER (ADJUSTED)
- CALL INTRK ;
- MOV M,A ;M(HL) = A
- MOV E,C ;HL => TRACKTABLE(NEWDRIVE)
- LXI H,TRTAB ;
- DAD D ;
- MOV A,M ;
- CALL OUTRK ;
- OUT TRACK ;1793 TRACK REG = TRKTBL(NWDR) (ADJUSTED)
- if not ONLY2
- LDA SYSFMT ;IF (1 DRIVE SYSTEM) THEN DO
- MOV B,A ;
- RAR ;
- DB JRNC,TWODR-$-1;SWAP DISKS:
- PUSH H ;THE FOLLOWING IS SINGLE DRIVE
- PUSH B ;DISK SWAP CODE
- LDA CURDSK ;
- CMP C ;CHECK IF CHANGE IN DISK &
- DB JRZ,CHKDS2-$-1 ;
- MOV A,C ;PUT DISK REFERENCE IN MESSAGE
- ADI 'A' ;
- STA SWDSK ;
- LXI H,SWMSG ;PROMPT FOR DISK SWAP
- CALL PMSG ;
- CALL LCONIN ;WAIT FOR KEY TO BE HIT
- CALL PCRLF ;PRINT CRLF
- CHKDS2: POP B ;
- POP H ;
- DB JR,CHKDS4-$-1 ;
- endif
- TWODR: MOV A,C ;ELSE CHANGE DRIVE
- INR A ;
- CMA ;
- ANI 3 ;
- OUT DCONT ;
- CHKDS4: MOV A,M ;IF (TRACK=0FFH) DO
- INR A ;
- DB JRNZ,CHKDS6-$-1
- if not NOREVA
- LDA CPUREV ; IF (REV.B) OR (REV.A AND 2DRIVE SYSTEM) DO
- CPI 'B'
- DB JRZ,CHKDS5-$-1
- MOV A,B
- RAR
- DB JRNC,CHKDS6-$-1
- endif
- CHKDS5: PUSH B ; /*This is the 1st time this disk is*/
- CALL OUTRK ; SET SIDE 0 /*accessed. We don't know where the*/
- OUT TRACK ; /*head is, so we HOME it. */
- CALL HOME1 ; HOME DRIVE
- POP B ; ENDIF
- CHKDS6: CALL MTRON ;WAIT FOR DRIVE READY(TURN MOTOR ON, ALSO)
- MOV A,C ;SET CURDSK=SELECTED DRIVE
- STA CURDSK ;
- CALL BLDPTR ;BUILD POINTER TO PARM. HDR.
- ;SET DENSITY PARMS FOR DISK (C).
- ;***********************************************
- ;DENSITY: SET DRIVE PARMS FOR DRIVE # (C)
- ; C: DRIVE # (0-3)
- ; HL: -> DISK PARAMETER HEADER (IN DPBASE:)
- ; KILLS: A,BC,DE,FLAGS
- ;DETERMINE DENSITY OF NEW DISK, SELECT TRANSLATE TABLE
- ;AND DISK PARM BLOCK, IN DPBASE
- ;***********************************************
- DENSITY:
- PUSH H ;SAVE DISKPARM HEADER PTR
- LXI H,DFLAGS;HL -> DENSITY FLAGS
- MVI B,0 ;
- DAD B ;
- MOV A,M ;
- ORA A ;GET DENSITY FLAG(C)
- JM LOGED ;SKIP IF LOGGED IN BEFORE
- PUSH H ; SAVE DENSITYFLAGPTR
- CALL CHKDSK ; CHECK IF SELECTED ALREADY, DO SO IF NOT.
- IF VER36
- LDA SEKSEC ; SAVE SECTOR
- PUSH PSW ;
- LHLD DMAADD ; SAVE DMAADD
- PUSH H ;
- CALL HOME1 ; DENSITYFLAG=F(TRACK0,SECTOR1,BYTE7FH)
- MVI C,1
- CALL SETSEC
- LXI B,DIRBF
- CALL SETDMA
- CALL READ
- POP H ; RESTORE DMADD
- SHLD DMAADD
- POP PSW ; RESTORE SECTOR
- STA SEKSEC
- POP H ; RESTORE DENSITYFLAGPTR
- LDA DIRBF+07FH;(DENSITYFLAG BYTE)
- ENDIF
- IF NOT VER36
- CALL HOME1
- LXI H,ERCNT
- MVI M,RTCNT
- DENS1: MVI A,0D0H ;FORCE INTERRUPT
- OUT DCOM
- XTHL ;KILL TIME
- XTHL
- XTHL
- XTHL
- MVI A,1 ;SET SECTOR
- OUT SECTP
- IN DSTAT ;LOOK AT HEAD LOAD BIT
- ANI 20H
- MVI A,8CH ;READ WITH HEAD LOAD DELAY
- DB JRZ,DENS2-$-1
- MVI A,88H ; READ WITH NO HEAD LOAD DELAY
- DENS2: DW PUSHIX
- CALL XRLOOP ;READ SECTOR AND REATIN (ONLY) LAST BYTE
- DW POPIX
- MOV B,A
- IN DSTAT ;CHECK FOR ERRORS
- ANI 9DH
- DB JRZ,DENS3-$-1 ;NONE FOUND
- DCR M ;ERROR FOUND - DECREMENT ERRORCOUNT
- DB JRNZ,DENS1-$+0FFH ;RETRY
- CALL ERMSG0 ;PRINT ERRMSGS (RETURNS 0 WHICH WE USE FOR SSSD)
- DENS3: POP H ;RESTORE PTR TO DENSITY FLAG
- MOV A,B
- ENDIF
- CPI 0DDH ;CODE3
- DB JRZ,LOGDD-$-1
- CPI 0D0H ;CODE4
- DB JRZ,LOGD0-$-1
-
- LOG00: MVI A,82H ;LOGGED DISK IS SINGLE DENSITY
- LXI B,TRANS ;
- LXI D,DPSDBK;
- DB JR,LOGDRV-$-1
-
- LOGED: CPI 081H ;TEST PREVIOUSLY LOGGED DRIVE PARM
- DB JRZ,LOGDD-$-1 ;AND BRANCH APPROPRIATELY
- CPI 085H ;
- DB JRNZ,LOG00-$+0FFH
-
- LOGD0: MVI A,85H ;LOGGED DISK IS DBL SIDE, DBL DENSITY
- LXI B,TRANSD;
- LXI D,DPDDBK1;
- DB JR,LOGDRV-$-1
-
- LOGDD: MVI A,81H ;LOGGED DISK IS SNGL SIDE, DBL DENSITY
- LXI B,TRANSD;
- LXI D,DPDDBK;
-
- LOGDRV: MOV M,A ;SAVE DISKTYPE IN DENSITY FLAGS
- ANI 3 ;STRIP OFF LOGGED IN BIT
- STA LOGDEN ;SAVE DENSITY OF LOGGED IN DRIVE
- OUT DSEL ;SET IT
- POP H ;GET DISKPARMHDR PTR
- PUSH H ;SAVE IT FOR RETURN
- MOV M,C ;SET UP TRANSLATE TABLE PTR IN BLOCK
- INX H
- MOV M,B ;
- LXI B,9 ;SET UP DISK PARM PTR IN BLOCK
- DAD B ;
- MOV M,E ;
- INX H ;
- MOV M,D ;
- LXI H,15 ;LET HL->BLOCKING PARMS (SET BLKG PRMS FOR DISK)
- DAD D ;
- LXI D,CPMSPB;LET DE->LOGGEDDRIVE BLOCKINGPARM AREA
- LXI B,4 ;LET BC=#ITEMS TO MOVE
- DW LDIR ;(MOVE (HL)=>(DE),BC ITEMS)
- POP H ;RETURN DISKPARMHDR POINTER
- RET ;
-
- XRLOOP: DW LDIX,XRL1
- OUT DCOM
- EI
- XRL1: HLT ;WAIT FOR F/D CONTROLLER TO START AGAIN...
- IN DDATA
- EI
- DW JPIX
-
- ;****************************************************************
- ; SET TRACK NUMBER TO REGISTER C.
- ;****************************************************************
- SETTRK:
- if DEBUG
- MVI A,'t'
- CALL CONOUTA
- MOV A,C
- CALL PHEX
- endif
- MVI H,0 ;SAVE TRACK NUMBER
- MOV L,C
- SHLD SEKTRK
- RET
-
- ;****************************************************************
- ; SET DISK SECTOR NUMBER.
- ;****************************************************************
- SETSEC:
- if DEBUG
- MVI A,'s'
- CALL CONOUTA
- MOV A,C
- CALL PHEX
- endif
- MOV A,C ;GET SECTOR NUMBER.
- STA SEKSEC
- RET ;RETURN FROM SETSEC.
-
- ;****************************************************************
- ; SET DISK DMA ADDRESS.
- ;****************************************************************
- SETDMA: MOV H,B ;MOVE B&C TO H&L.
- MOV L,C
- SHLD DMAADD ;PUT AT DMA ADR ADDRESS.
- RET ;RETURN FROM SETDMA.
-
- ;****************************************************************
- ;TRANSLATE SECTOR IN BC TO HL USING TABLE POINTED AT BY DE.
- ;****************************************************************
- SECTRAN:
- if DEBUG
- MVI A,'x'
- CALL CONOUTA
- MOV A,B
- CALL PHEX
- MOV A,C
- CALL PHEX
- endif
- MOV A,E ;TEST IF TABLE TRANSLATION IS REQUESTED
- ORA D ; (I.E. DE<>0)
- DB JRNZ,SECTR1-$-1 ; YES, DO IT
- MOV L,C ; NO, LET HL=BC+1
- MOV H,B ;
- INX H ;
- RET ;
- SECTR1: XCHG ;GET TABLE ADDR IN HL
- DAD B ;INDEX INTO TABLE
- MOV L,M ;HL=M(BC+DE)
- MVI H,0 ;
- RET ;
-
-
- ;*****************************************************
- ;* Read CPM sector (record) from SEKDSK, *
- ;* SEKTRK,SEKSEC, to M(DMAADD). *
- ;*****************************************************
- READ:
- if DEBUG
- MVI A,'r'
- CALL CONOUTA
- endif
- XRA A
- STA UNACNT
- INR A
- STA READOP ;read operation
- STA RSFLAG ;must read data
- MVI A,WRUAL
- STA WRTYPE ;treat as unalloc
- DB JR,RWOPER-$-1 ;to perform the read
-
- ;*****************************************************
- ;* Write CPM sector (record) from M(DMAADD) *
- ;* to SEKDSK,SEKTRK,SEKSEC. *
- ;*****************************************************
- WRITE:
- if DEBUG
- MVI A,'w'
- CALL CONOUTA
- endif
- XRA A ;0 to accumulator
- STA READOP ;not a read operation
- MOV A,C ;write type in c
- STA WRTYPE
- LDA LOGDEN ;IF (SD), NEVER RD BEFORE WR
- CPI SINGL ;
- DB JRZ,NOOVF-$-1 ;
- MOV A,C ;
- CPI WRUAL ;write unallocated?
- DB JRNZ,CHKUNA-$-1 ;check for unalloc
- ;write to unallocated, set parameters
- LDA CPMSPB ;next unalloc recs
- STA UNACNT
- LXI H,SEKDSK ;Copy SEEK parms to UNALLOC parms
- LXI D,UNADSK
- LXI B,5
- DW LDIR
- CHKUNA: ;check for write to unallocated sector
- LDA UNACNT ;any unalloc remain?
- ORA A
- DB JRZ,ALLOC-$-1 ;skip if not
- ;more unallocated records remain
- DCR A ;unacnt = unacnt-1
- STA UNACNT
- LDA SEKDSK ;same disk?
- LXI H,UNADSK
- CMP M ;sekdsk = unadsk?
- DB JRNZ,ALLOC-$-1 ;skip if not
- ;disks are the same
- LHLD UNATRK
- CALL SEKTRKCMP ;sektrk = unatrk?
- DB JRNZ,ALLOC-$-1 ;skip if not
- ;tracks are the same
- LDA SEKSEC ;same sector?
- LXI H,UNASEC
- CMP M ;seksec = unasec?
- DB JRNZ,ALLOC-$-1 ;skip if not
- ;match, move to next sector for future ref
- INR M ;unasec = unasec+1
- LDA CPMSPT ;end of track?
- CMP M ;count CP/M sectors
- DB JRNC,NOOVF-$-1 ;skip if no overflow
- ;overflow to next track
- MVI M,1 ;unasec = 1
- LHLD UNATRK
- INX H
- SHLD UNATRK ;unatrk = unatrk+1
- NOOVF: ;match found, mark as unnecessary read
- XRA A
- STA RSFLAG ;rsflag = 0
- DB JR,RWOPER-$-1 ;to perform the write
-
- ALLOC: ;not an unallocated record, requires pre-read
- XRA A
- STA UNACNT ;unacnt = 0
- INR A
- STA RSFLAG ;rsflag = 1
- ;*****************************************************
- ;* *
- ;* Common code for READ and WRITE follows *
- ;* *
- ;*****************************************************
- RWOPER: if TYPEAHEAD
- CALL TESTI ;(TEST CONSOLE INPUT)
- endif
- LDA SECSHF ;COMPUTE HOST SECTOR
- MOV B,A
- LDA SEKSEC ;HOSTSECTOR=((SEEKSECTOR)-1 SHR SEKSHF)+1
- DCR A
- DB JR,RWOPR2-$-1
- RWOPR1: DW SRLA
- RWOPR2: DB DJNZ,RWOPR1-$+0FFH
- INR A
- STA SEKHST ;host sector to seek
- ;active host sector?
- LXI H,HSTACT ;host active flag
- MOV A,M
- MVI M,1 ;always becomes 1
- ORA A ;was it already?
- DB JRZ,FILHST-$-1 ;fill host if not
- ;host buffer active, same as seek buffer?
- LDA SEKDSK
- LXI H,HSTDSK
- CMP M ;sekdsk = hstdsk?
- DB JRNZ,NOMATCH-$-1
- LHLD HSTTRK
- CALL SEKTRKCMP ;sektrk = hsttrk?
- DB JRNZ,NOMATCH-$-1
- LDA SEKHST
- LXI H,HSTSEC ;sekhst = hstsec?
- CMP M
- DB JRZ,MATCH-$-1 ;skip if match
- NOMATCH: ;not correct sector
- CALL FLUSH ;flush buffer
- STA ERFLAG ;REPORT ANY ERRORS
- FILHST: ;fill the host buffer
- LXI H,SEKDSK ;Copy SEEK parms to HOSTBUFFER parms
- LXI D,HSTDSK
- LXI B,5
- DW LDIR
- LDA RSFLAG ;need to read?
- ORA A
- CNZ READHST ;yes, if 1
- LXI H,ERFLAG ;REPORT ANY ERRORS
- ORA M
- MOV M,A
- XRA A
- STA HSTWRT ;no pending write
- MATCH: ;copy data to or from buffer
- LDA SEKSEC ;mask buffer number
- DCR A ; HL=((SEKSEC-1) AND SECMSK) SHL 7
- MOV L,A
- LDA SECMSK
- ANA L
- RAR
- MOV H,A
- MVI A,0
- RAR
- MOV L,A ; HL has relative host buffer address
- LXI D,HSTBUF
- DAD D ;hl = host address
- XCHG ;now in DE
- LHLD DMAADD ;get/put CP/M data
- XCHG
- LXI B,128 ;length of move
- LDA READOP ;which way?
- ORA A
- DB JRNZ,RWMOVE-$-1 ;skip if read
- ;write operation, mark and switch direction
- MVI A,1
- STA HSTWRT ;hstwrt = 1
- XCHG ;source/dest swap
- RWMOVE: DW LDIR ;BC initially 128, HL is source, DE is dest
- ;data has been moved to/from host buffer
- LDA WRTYPE ;write type
- CPI WRDIR ;to directory?
- LDA ERFLAG ;IF NOT THEN EXIT WITH FLAG
- RNZ
- ;clear host buffer for directory write
- ORA A ;errors?
- CZ WRITEHST;IF NOT, WRITE BUFFER
- RET
-
- ;*****************************************************
- ;* Compare M(HL)=SEKTRK, 16-bit compare *
- ;*****************************************************
- SEKTRKCMP: ;HL = .unatrk or .hsttrk, compare with sektrk
- XCHG
- LHLD SEKTRK
- ORA A ;(clear carry)
- DW SBCHLDE ;SBC HL,DE set Z/NZ on compare
- RET
-
- ;****************************************************************
- ; READ THE SECTOR AT HSTSEC, HSTTRK, HSTDSK.
- ; USE HOSTBUFFER.
- ;****************************************************************
- READHST:
- if DEBUG
- MVI A,'R'
- CALL CONOUTA
- endif
- LDA HSTDSK
- CALL CHKDSA ;SELECT HOST DISK
- CALL CHKTRK ;CHECK FOR CORRECT CURRENT TRACK, & MOVE
- MVI A,RTCNT ;GET RETRY COUNT.
- RRETRY: STA ERCNT ;STORE IN ERROR CTR.
- if TYPEAHEAD
- CALL TESTI
- endif
- LXI H,HSTBUF;GET STARTING ADR.
- MVI A,0D0H ;CAUSE INTERRUPT.
- OUT DCOM
- XTHL ;SOME DELAY.
- XTHL
- XTHL
- XTHL
- LDA HSTSEC ;GET SECTOR NUMBER.
- OUT SECTP ;SET SECTOR INTO 1793.
- IN DSTAT ;READ STATUS.
- ANI 20H ;LOOK AT HLD BIT.
- MVI A,8CH ;READ WITH HEAD LOAD DELAY
- DB JRZ,READ3-$-1 ;HEAD NOT LOADED.
- MVI A,88H ;CODE FOR READ W/O HD LD DELAY
- READ3: MVI C,DDATA ;SEND COMMAND TO 1793
- DW PUSHIX
- CALL RLOOP
- DW POPIX
- IN DSTAT ;DONE: READ DISK STATUS.
- ANI 9DH ;LOOK AT ERROR BITS.
- JZ MTROFF ;IF NO ERROR THEN RETURN (&TURN MOTOR OFF)
- CALL ERCHK ;CHECK FOR SEEK ERROR.
- LXI H,RECNT ;GET RD ERR COUNT ADDR.
- INR M ;ONE MORE ERROR.
- LDA ERCNT ;GET ERROR COUNT.
- DCR A ;DECREMENT COUNT.
- DB JRNZ,RRETRY-$+0FFH ;TRY TO READ AGAIN.
- ERMSG0: LXI H,RDMSG ;PRINT "READ ".
- ERMSG: CALL PMSG ;PRINT ORIGIN MESSAGE.
- ERMSG1:
- MOV A,D ;GET ERROR BITS.
- RAL ;IF BIT 7 HIGH,
- LXI H,NRMSG ;"NOT READY".
- DB JRC,ERMSG2-$-1
- MOV A,D ;GET ERROR BITS.
- ANI 10H ;IF BIT 4 IS HIGH,
- LXI H,RNMSG ;PRINT "RECORD NOT FOUND"
- CNZ PMSG
- MOV A,D ;GET ERROR BITS.
- ANI 8H ;IF BIT 3 IS HIGH,
- LXI H,CRCMSG ;PRINT "CRC ERROR".
- CNZ PMSG
- MOV A,D ;GET ERROR BITS.
- ANI 4H ;IF BIT 2 IS HIGH,
- LXI H,LDMSG ;PRINT "LOST DATA".
- CNZ PMSG
- MOV A,D ;GET ERROR BITS.
- RAR ;IF BIT 1 IS HIGH,
- LXI H,BSYMSG;PRINT "BUSY".
- CC PMSG
- PERMSG: LXI H,ERRMSG ;PRINT "ERROR."
- ERMSG2: CALL PMSG
- MVI A,1 ;SET FOR BDOS ERR.
- ORA A
- JMP MTROFF ;TURN MOTOR OFF
-
- RLOOP: DW LDIX,RL1
- OUT DCOM ;
- EI ;
- RL1: HLT ;
- DW INI ;
- EI ;
- DW JPIX ;
-
- ; ERCHK - CHECK FOR RECORD NOT FOUND ERROR.
- ERCHK: MOV D,A ;SAVE ERROR BITS IN D.
- ANI 10H ;IF RECORD NOT FOUND,
- CNZ CHKSK ;DO A CHECK ON SEEK.
- MOV A,D ;RESTORE BITS
- ORA A ;SET FLAGS,
- RET ;AND RETURN.
-
- ;CHECK FOR SEEK TO CORRECT TRACK,
- ;AND CHANGE IF NECESSARY.
- CHKSK: PUSH H ;
- MVI A,0C4H ;COMMAND TO READ ADDRESS
- MVI C,DDATA ;
- LXI H,ADDRBF ;
- DW PUSHIX
- CALL RLOOP ;
- DW POPIX
- LDA ADDRBF ;
- MOV B,A ;
- POP H ;DMAADD: TRK,SIDE,SECTOR,SECL,CRC,CRC
- CHKS3: IN DSTAT ;READ DISK STATUS.
- ORA A ;SET FLAGS.
- DB JRZ,CHKS4-$-1 ;READ ADR OK IF 0.
- CALL HOME1 ;OTHERWISE, HOME FIRST.
- DB JR,CHKTRK-$-1
- CHKS4:
- MOV A,B ;UPDATE TRACK REGISTER.
- CALL OUTRK ;ADJUST IF 2SIDE
- OUT TRACK ;
- ;*********************************************
- ;CHKTRK: IF CURRENT TRACK <> HOST TRACK, GOTO HOSTTRACK
- ;*********************************************
- CHKTRK: IN TRACK
- CALL INTRK
- LXI H,HSTTRK
- CMP M
- RZ ;TRACKS ARE THE SAME, RETURN
- MOV A,M ;TRACKS NOT SAME, CORRECT
- JMP SEEK ;
-
- ;****************************************************************
- ; FLUSH THE BUFFER IF A WRITE OPERATION IS PENDING
- ;****************************************************************
- FLUSH: LDA HSTWRT ;
- ORA A ;
- RZ
- ;****************************************************************
- ; WRITE THE SECTOR AT HSTSEC, HSTTRK, HSTDSK.
- ; USE HOST BUFFER.
- ;****************************************************************
- WRITEHST:
- if DEBUG
- MVI A,'W'
- CALL CONOUTA
- endif
- LDA HSTDSK ;CHECK FOR CORRECT DISK, AND SELECT
- CALL CHKDSA ;
- CALL CHKTRK ;GO TO CORRECT TRACK
- MVI A,RTCNT ;GET RETRY COUNT.
- WRETRY: STA ERCNT ;STORE IN ERROR COUNTER.
- if TYPEAHEAD
- CALL TESTI
- endif
- LXI H,HSTBUF ;GET STARTING ADR.
- MVI A,0D0H ;STATUS INTERUPT FOR 1793.
- OUT DCOM ;COMMAND 1793.
- XTHL
- XTHL
- XTHL
- XTHL
- LDA HSTSEC ;GET SECTOR NUMBER.
- OUT SECTP ;SET THE SECTOR INTO 1793.
- IN DSTAT ;GET 1793 STATUS.
- ANI 20H ;CHECK FOR HEAD LOAD.
- MVI A,0ACH ;SET UP 1793 FOR WRITE.
- DB JRZ,WRITE2-$-1 ;HEAD IS NOT LOADED.
- MVI A,0A8H ;CODE FOR WRITE W/O HD LD.
- WRITE2: MVI C,DDATA
- DW PUSHIX
- CALL WLOOP
- DW POPIX
- IN DSTAT ;DONE: READ DISK STATUS.
- ANI 0FDH ;LOOK AT THESE BITS.
- STA HSTWRT ;CLEAR PENDINGWRITEFLAG IF NO ERROR
- JZ MTROFF ;RETURN IF NO ERROR (&TURN MOTOR OFF).
- CALL ERCHK ;CHECK/CORRECT SEEK ERR.
- LXI H,WECNT ;GET ADR OF WRITE ERR CTR.
- INR M ;ONE MORE WRITE ERROR.
- LDA ERCNT ;GET ERROR COUNT.
- DCR A ;DECREMENT COUNT.
- DB JRNZ,WRETRY-$+0FFH ;TRY TO WRITE AGAIN.
- LXI H,WTMSG ;PRINT "WRITE ".
- CALL PMSG
- MOV A,D ;GET ERROR BITS.
- ANI 40H ;LOOK AT BIT 6.
- LXI H,WPMSG ;PRINT "PROTECT ".
- CNZ PMSG
- MOV A,D ;GET ERROR BITS.
- ANI 20H ;LOOK AT BIT 5.
- LXI H,WFMSG ;PRINT "FAULT ".
- CNZ PMSG
- JMP ERMSG1 ;DO COMMON MESSAGES.
-
- WLOOP: DW LDIX,WL1
- OUT DCOM
- EI
- WL1: HLT
- DW OUTI
- EI
- DW JPIX
-
- ;****************************************************************
- ; HOME DISK DRIVE (RETURN TO TRACK 0)
- ;****************************************************************
- HOME:
- if DEBUG
- MVI A,'H'
- CALL CONOUTA
- endif
- CALL FLUSH ;IF (BUFFER WRITE PENDING) THEN WRITE BUFFER
- ; (SPEEDS UP SAVE & PIP)
- CALL CLRDFLGS;CLEAR DENSITY FLAGS
- CALL CHKSD ;CHECK FOR SEKDSK AND SELECT IF NECESSARY
- HOME1: MVI A,2
- OUT DSEL ;SINGLE DENSITY
- MVI C,0
- CALL SETTRK
- CALL MTRON ;TURN MOTOR ON
- XRA A
- OUT DDATA ;TRACK # 0
- MVI A,1CH ;3MS SEEK W/ HEAD LOAD & VERIFY
- CALL DCOMM
- IN DSTAT ;READ STATUS.
- ANI 91H ;LOOK AT BITS.
- RZ ;OK IF ZERO.
- MVI A,9 ;6MS RESTORE W/BEGIN HEAD LOAD
- CALL DCOMM ;
- IN DSTAT
- ANI 91H
- DB JRZ,HOME2-$-1 ;IF NOT OK, SEEK TRACK 0
- XRA A
- CALL SEEK
- HOME2: JMP MTROFF ;RETURN (&TURN MOTOR OFF)
-
- ;****************************************************************
- ;SEEK: MOVE THE HEAD TO THE TRACK IN REGISTER A (= 0-153).
- ;****************************************************************
- SEEK: PUSH B ;SAVE B&C.
- PUSH PSW ;
- CALL MTRON ;(TURN MOTOR ON)
- POP PSW ;
- MOV B,A ;SAVE DESTINATION TRACK.
- XRA A ;
- STA SECNT ;CLEAR SEEK ERROR CTR
- MOV A,B ;
- ORA A ; IF (TK 0) THEN
- MVI A,2 ; SET UP FOR SINGLE DENS
- DB JRZ,SEEK1-$-1
- MVI A,1 ; IF (TK 1) THEN
- CMP B ; SET UP FOR DOUBLE DENSITY
- if not IBMB
- DB JRZ,SEEK1-$-1
- endif
- if IBMB
- DB JRNZ,SEEK0-$-1; (UNLESS NOT A: AND IBM OPTION SELECTED)
- LDA CURDSK ; (IN WHICH CASE, TRK1 DENSITY=LOGDEN)
- ORA A ;
- MVI A,1 ;
- DB JRZ,SEEK1-$-1
- SEEK0: ;
- endif
- LDA LOGDEN ;ELSE GET DENSITY OF LOGGED DRIVE.
- SEEK1: OUT DSEL ;SET DENSITY IN 1793
- MVI A,RTCNT ;GET RETRY COUNT.
- SRETRY: STA SERCNT ;STORE IN ERROR COUNTER.
- IN TRACK ;READ PRESENT TRACK NO.
- CALL INTRK ;ADJUST IF 2SIDE
- MOV C,A ;SAVE IN C. (CURR TK)
- CMP B ;SAME AS SEEK TRACK NO.? (A IS CURR TK)
- MOV A,B ;RESTORE A FROM B. (MAKE A DESIRED TK)
- DB JRZ,THERE-$-1 ;IF (THERE) THEN EXIT
- MVI A,0D0H ;TERMINATE COMMAND AND/OR BUSY
- OUT DCOM ;
- XTHL ;WASTE
- XTHL ;TIME
- MOV A,B ;GET TRACK
- CALL OUTRK ;ADJUST FOR 2-SIDE
- OUT DDATA ;OUTPUT (SEEK TRACK #)
- MVI A,1CH ;3MS SEEK W/ HEAD LOAD & VERIFY
- CALL DCOMM ;
- IN DSTAT ;READ STATUS.
- ANI 91H ;LOOK AT BITS.
- DB JRZ,THERE-$-1 ;OK IF ZERO.
- MOV B,A ;SAVE STATUS IN B
- LDA SECNT ;
- INR A ;
- STA SECNT ;ADD 1 TO SEEK ERR CTR
- LDA SERCNT ;GET ERROR COUNT.
- DCR A ;DECREMENT COUNT.
- DB JRNZ,SRETRY-$+0FFH ;RETRY SEK.
- MOV D,B ;RESTORE STATUS TO D REG
- POP B ;RESTORE B&C.
- LXI H,SKMSG ;PRINT "SEEK ".
- JMP ERMSG ;DO COMMON ERR MESSAGES.
-
- THERE: POP B
- RET
-
-
- DCOMM: OUT DCOM
- EI
- HLT ;INTERUPT CAUSES RETURN
- RET ;WHEN COMMAND COMPLETE
-
- ;*****************************************************
- ; INTRK/OUTRK ADJUST TRACK NUMBERS IF >77
- ;*****************************************************
- INTRK: ;TRACK # IN A INCREASED BY 77 IF SIDEFLG NON-ZERO
- PUSH PSW
- LDA SIDEFLG
- ORA A ;Z:=(TRACK<77)
- DB JRZ,INTRK1-$-1
- POP PSW
- ADI 77
- RET
-
- OUTRK: ;TRACK # IN A REDUCED BY 77 IF >76 AND SET SIDEFLG NON-ZERO
- PUSH PSW
- CPI 77
- if not NOREVA
- LDA CPUREV ;A=CPU BD REV
- endif
- DB JRC,OUTRK1-$-1
- if not NOREVA
- CPI REVB ; (>=T77)
- endif
- MVI A,4 ; (REV B)
- if not NOREVA
- DB JRZ,OUTRK0-$-1
- MVI A,1 ; (REV A)
- endif
- OUTRK0: STA SIDEFLG
- OUT DCONT
- POP PSW
- SUI 77
- RET
-
- OUTRK1: if not NOREVA
- CPI REVB ; (<T77)
- endif
- MVI A,8 ; (REV B)
- if not NOREVA
- DB JRZ,OUTRK2-$-1
- LDA SEKDSK ; (REV A) IF NOT(DRIVE A) THEN DON'T SET SIDE
- ORA A ;
- DB JRNZ,OUTRK3-$-1
- MVI A,2 ; (REV A AND DRIVE A)
- endif
- OUTRK2: OUT DCONT
- OUTRK3: XRA A
- STA SIDEFLG
- INTRK1: POP PSW
- RET
-
- ;****************************************
- ; DRIVE MOTOR CONTROL ON/OFF
- ;****************************************
- MTRON:
- IN TRACK ;SET SIDE 0
- CALL OUTRK
- MVI A,8 ;TURN DRIVE MOTOR ON
- OUT DSEL
- MVI A,0D0H ;1793 FORCE INTERRUPT COMMAND
- OUT DCOM
- IN DSTAT ;IF (READY) THEN RETURN
- RAL
- RNC
- MTRON1: IN DSTAT ;ELSE DO
- RAL ; REPEAT
- DB JRC,MTRON1-$+0FFH; UNTIL (READY)
- PUSH H ; /*Check spindle speed*/
- PUSH B
- CALL SPIN
- POP B
- POP H
- RET
-
- SPIN: CALL SPIN1 ;Check spindle speed twice
- SPIN1: LXI B,-13544; REPEAT
- SPIN2: LXI H,0 ; HL=0
- SPIN3: ; REPEAT
- if TYPEAHEAD
- CALL TESTI
- endif
- IN DSTAT
- ANI 2
- DB JRZ,SPIN3-$+0FFH; UNTIL (INDEX PULSE)
- SPIN4: IN DSTAT ; REPEAT
- ANI 2
- DB JRNZ,SPIN4-$+0FFH; UNTIL (NO INDEX PULSE)
- SPIN5: INX H ; REPEAT
- MOV A,H ; IF (HL++ == 0) start over
- ORA L
- DB JRZ,SPIN2-$+0FFH
- IN DSTAT
- ANI 2
- JZ SPIN5 ; UNTIL (INDEX PULSE)
- DAD B ; UNTIL (HL<13544)
- JC SPIN2
- RET
-
- MTROFF:
- PUSH PSW ;TURN DRIVE MOTOR OFF
- MVI A,4 ;(DRIVE STOPS ~20 SECS AFTER COMMAND)
- OUT DSEL
- POP PSW
- RET
-
- ;****************************************************************
- ; I/O Routines
- ;****************************************************************
-
- PCRLF: LXI H,CRLF ;PRINT CRLF
- PMSG: MOV A,M ;GET A CHARACTER.
- CALL CONOUTA ;PRINT IT.
- ORA M ;GET AGAIN, SET FLAGS
- RM ;IF MSB SET, RETURN
- INX H ;INCREMENT H&L, AND GET ANOTHER.
- DB JR,PMSG-$+0FFH
-
- if DEBUG
- PHEX: PUSH PSW ;Print ACC in Hex (destroys acc)
- RRC
- RRC
- RRC
- RRC
- CALL PHEX1
- POP PSW
- PHEX1: ANI 0FH
- ADI 90H
- DAA
- ACI 40H
- DAA
- ;fall through to CONOUTA
- endif
-
- CONOUTA: ;print acc
- PUSH B
- ANI 7FH
- MOV C,A
- CALL LCONOUT
- POP B
- RET
-
-
- ;**************************************************
- ;* I/O DEVICE DRIVERS *
- ;* See IOBYTE description at beginning of listing *
- ;**************************************************
-
- LCONST: PUSH D ;LOGICAL CONSOLE INPUT DEVICE STATUS
- CALL DISPATCH0
- DW CONST ;00=Console
- DW AUTST ;01=Console & Modem in parallel (Autoswitch mode)
- DW MODST ;10=Modem
- DW NULLRDY ;11=Clock (Always ready)
-
- LCONIN: PUSH D ;LOGICAL CONSOLE INPUT DEVICE
- CALL DISPATCH0
- DW CONIN ;00=Console
- DW AUTIN ;01=Console & Modem
- DW MODEMIN ;10=Modem
- DW RCLOCK ;11=Clock
-
- LCONOUT:PUSH D ;LOGICAL CONSOLE OUTPUT DEVICE
- CALL DISPATCH0
- DW CONOUT ;00=Console
- DW AUTOUT ;01=Console & Modem
- DW MODEMO ;10=Modem
- DW WCLOCK ;11=Clock
-
- LREADER:PUSH D ;LOGICAL READER DEVICE
- MVI E,2
- CALL DISPATCH
- DW NULLIN ;00= not used
- DW NULLIN ;01= not used
- DW MODEMIN ;10=Modem
- DW RCLOCK ;11=Clock
-
- LPUNCH: PUSH D ;LOGICAL PUNCH DEVICE
- MVI E,4
- CALL DISPATCH
- DW PLLPRN ;00=Parallel printer
- DW NULLOUT ;01= not used
- DW MODEMO ;10=Modem
- DW WCLOCK ;11=Clock
-
- LLISTST: PUSH D ;LOGICAL LIST DEVICE STATUS
- MVI E,6
- CALL DISPATCH
- DW PLLRDY ;00=Parallel printer
- DW NULLRDY ;01=Console
- DW NULLRDY ;10=Serial, ETX/ACK
- DW NULLRDY ;11=Serial, XON/XOFF
- NULLRDY:XRA A ;RETURN STATUS (0 IF NOT-READY SEZ D.R.I.?)
- RET
-
- LLIST: PUSH D ;LOGICAL LIST DEVICE
- MVI E,6
- CALL DISPATCH
- DW PLLPRN ;00=Parallel printer
- DW CONOUT ;01=Console
- DW ETXACK ;10=Serial, ETX/ACK protocol
- DW XONXOFF ;11=Serial, XON/XOFF protocol
-
- DISPATCH0:
- MVI E,8
- DISPATCH:
- LDA IOBYTE ;Get byte from IOBYTE
- DISP1: RRC ;Rotate bits of interest into lsb
- DCR E
- DB JRNZ,DISP1-$+0FFH
- ANI 3 ;Mask for desired bits
- XTHL ;Push HL, Pop (Table Address)
- MOV E,A
- MVI D,0 ;HL -> Table Item
- DAD D
- DAD D
- MOV E,M ;HL = Table Item
- INX H
- MOV D,M
- XCHG
- PUSH B ;Push B (TOS=Caller's HL,DE)
- LXI D,DISP2 ;Push return address
- PUSH D
- if TYPEAHEAD
- CALL TESTI ;Test console input
- endif
- PCHL ;GOTO TABLE ROUTINE
- DISP2: POP B ;Restore caller's regs (except psw)
- POP H
- POP D
- RET
-
- CONST: ;IF(CONSOLE RDY) THEN RETURN (NZ)
- if TYPEAHEAD
- LDA ICOUNT
- ORA A
- endif
- if not TYPEAHEAD
- IN CSTAT ;IF (RX CHAR RDY) DO
- ANI 2
- endif
- DB JRNZ,CONST1-$-1
- RET
-
- AUTST: CALL CONST
- RNZ
- MODST: IN MSTAT ;RETURN (MODEM STATUS)
- ANI 2
- RZ
- CONST1: ORI 0FFH
- RET
-
- CONIN: CALL FLUSH ;FLUSH BUFFER
- if TYPEAHEAD
- CALL TESTI
- LXI H,ICOUNT ;IF (CON CHAR NOT RDY) GOTO CONIN
- MOV A,M
- ORA A
- DB JRZ,CONIN-$+0FFH
- DCR M
- LXI H,ICHARQ+1; ELSE DO
- LXI D,ICHARQ
- MOV C,A
- MVI B,0
- LDAX D ; A=CHAR
- DW LDIR ; DROP QUEUE
- endif
- if not TYPEAHEAD
- IN CSTAT ;IF (CON CHAR NOT RDY) GOTO CONIN
- ANI 2
- DB JRZ,CONIN-$+0FFH
- IN CDATA ;ELSE RETURN (A=CHAR AND 7FH)
- endif
- ANI 7FH
- RET
-
- if TYPEAHEAD
- TESTI: IN CSTAT ;IF (RX CHAR RDY) DO
- ANI 2
- RZ
- LDA ICOUNT ; IF (QUEUE<QSIZE) DO
- CPI QSIZE
- RNC
- INR A ; QUEUE.COUNT++
- STA ICOUNT
- PUSH H ; QUEUE||RX CHAR
- LXI H,ICHARQ-1
- ADD L
- MOV L,A
- DB JRNC,TEST0-$-1
- INR H
- TEST0: IN CDATA
- MOV M,A
- POP H
- RET
- endif
-
- AUTIN: CALL FLUSH
- AUTIN1:
- if TYPEAHEAD
- CALL TESTI
- endif
- CALL CONST
- DB JRNZ,CONIN-$+0FFH
- CALL MODST
- DB JRZ,AUTIN1-$+0FFH
- MODEMIN:CALL FLUSH
- IN MSTAT
- ANI 02H
- DB JRZ,MODEMIN-$+0FFH
- IN MDATA
- RET
-
- CONOUT: IN CSTAT ;OUTPUT (C) TO CONSOLE
- RAR
- DB JRNC,CONOUT-$+0FFH
- MOV A,C
- OUT CDATA
- RET
-
- AUTOUT: CALL CONOUT
- MODEMO: IN MSTAT ;OUTPUT TO MODEM
- RAR
- DB JRNC,MODEMO-$+0FFH
- MOV A,C
- OUT MDATA
- RET
-
-
- XONXOFF: ;START OF X-ON X-OFF
- IN LDATA
- ANI 1FH ;MASK MSB'S
- CPI 13H ;CHECK FOR X-OFF
- DB JRNZ,XONX2-$-1 ;IF NOT THEN OUTPUT CHAR
- XONX1: ;IF SENT THEN WAIT FOR X-ON
- IN LDATA
- ANI 1FH ;MASK MSB'S
- CPI 11H ;X-ON CHAR ?
- DB JRNZ,XONX1-$+0FFH;IF NOT GOBACK
- XONX2: IN LSTAT
- ANI 81H ;SEND CHAR
- CPI 81H
- DB JRNZ,XONX2-$+0FFH
- MOV A,C
- OUT LDATA
- RET
-
- PLLPRN: ;PARALLEL PORT DRIVER
- MVI A,81H
- OUT 0D3H ;8255 CONTROL PORT
- PLLP1: CALL PLLRDY
- DB JRNZ,PLLP1-$+0FFH;LOOP UNTIL READY
- MOV A,C
- OUT 0D1H ;OUTPUT DATA TO PORT B
- MVI A,0BH
- OUT 0D3H ;STROBE
- DCR A
- OUT 0D3H
- RET
-
- PLLRDY: IN 0D2H ;Parallel Printer Ready
- ANI 4 ;04H==busy, 00=ready
- RZ ;Return 0==ready
- ORI 0FFH
- RET ;Return 0FFH==not ready
-
- ETXACK: IN LSTAT
- RAR
- DB JRNC,ETXACK-$+0FFH
- MOV A,C
- OUT LDATA
- LXI H,PCOUNT
- DCR M
- RP
- MVI M,80H
- MVI C,3
- CALL ETXACK
- ACKCHK: IN LSTAT
- ANI 2
- DB JRZ,ACKCHK-$+0FFH
- IN LDATA
- ANI 7FH
- CPI 6
- DB JRNZ,ACKCHK-$+0FFH
- RET
-
- NULLIN: MVI A,1AH ;NULL INPUT DEVICE - RETURN CONTROL-Z
- NULLOUT:RET ;NULL OUTPUT DEVICE
-
-
-
- ;*****************************************************************
- ;CLOCK READ/WRITE ROUTINES
- ;*****************************************************************
- RCLOCK: LXI H,PASSADD
- DCR M ;DECREMENT PASS COUNTER(RANGE:15H-0-0FDH)
- MOV A,M
- CPI 0DH ;CHECK TO SEE IF AT BEGINNING
- JM RCLOC1
- MVI A,' ' ;IF NOT, RET WITH A SPACE
- RET
-
- RCLOC1: ORA A ;CHECK TO SEE IF ALL PASSES
- JP RCLOC2 ; COMPLETED
- CPI 0FEH
- MVI A,' ' ;(RETURN {'.',' ',CR} AFTER STRING)
- RZ ; (2ND CHAR AFTER)
- MVI A,'.'
- RNC ; (1ST CHAR AFTER)
- MVI M,15H
- MVI A,0DH ; (3RD CHAR AFTER)
- RET
-
-
- RCLOC2: MVI A,40H
- OUT 0CCH ;TURN ON CLOCK
- MVI B,78H
- RCLOC3: DB DJNZ,RCLOC3-$+0FFH ;WAIT
- MOV A,M
- ;CONVERT PTR=(12-0) TO (10,9,8,7,12,11,6-0)
- CPI 7 ;THIS MAKES DATA ORDER=MMDDYYwHHMMSS
- DB JRC,RCLOC4-$-1 ;MUCH MORE CONVENIENT TO USE
- SUI 2 ;
- CPI 7 ;
- DB JRNC,RCLOC4-$-1
- ADI 6 ;
- RCLOC4: ORI 0C0H ;CONVERT TO CLOCK CHIP I/O PORT#
- MOV C,A ;SET UP OUTPUT ADDRESS
- MVI A,50H
- DW OUTCA ;TOGGLE CLOCK
- DW INAC
- CALL SWAP ;FLIP THE BITS
- ADI 30H
- PUSH PSW
- XRA A
- OUT 0C0H ;RESET CLOCK
- POP PSW ;RETURN WITH DATA IN ACC.
- RET
-
-
- WCLOCK: LXI H,CLKDIR
- MOV A,C ;IF (CHAR < '0') THEN RETURN
- ANI 07FH
- SUI '0'
- RC
- CPI 9+1+1 ;IF (CHAR < '9'+1) THEN DO
- DB JRNC,WCLK2-$-1 ; (NOTE: '9'+1=':', NEEDED FOR 24 HR MODE SET)
- CALL SWAP
- MOV B,A
- MOV A,M ;IF ('DIRECTOR' < 'A') THEN RETURN
- CPI 'A'-40H
- RC
- CPI 'M'+1-40H;IF ('DIRECTOR' > 'M') THEN RETURN
- RNC
- DCR A
- CPI 6
- DB JRNC,WCLOC0-$-1
- ADI 2
- CPI 6
- DB JRC,WCLOC0-$-1
- SUI 6
- WCLOC0: INR A
- MOV C,A
- MVI A,40H
- OUT 0C0H ;ISSUE HOLD COMMAND
- MVI A,0BFH+14;PORT BASE ADDRESS
- SUB C ;ADD ADDRESS TO BASE PORT
- MOV C,A ;('A'=13, 'M'=1)
- MOV A,B
- MVI B,62+6 ;HOLD 200uS (+10% MARGIN)
- TIML1: DB DJNZ,TIML1-$+0FFH
- ADI 40H ;SET UP ADDRESS
- DW OUTCA ;OUT (C),A
- XTHL
- XTHL ;DELAY
- ORI 20H ;TURN ON WRITE
- DW OUTCA
- XTHL
- XTHL ;DELAY
- ANI 4FH ;TURN OFF WRITE
- DW OUTCA
- XRA A
- OUT 0C0H ;TURN OFF CLOCK
- INR M ;RESET DIRECTOR
- RET
-
- WCLK2: CPI 'A'-'0'
- RC ;RETURN IF < ASCII "A"
- CPI 'M'-'0'+1
- RNC ;RETURN IF > ASCII "M"
- ANI 0FH ;STRIP OFF ASCII
- MOV M,A ;STORE DIRECTOR
- RET
-
- SWAP: MOV B,A
- XRA A ;SWAP BITS 0-4,1-3
- CALL SWAP1
- SWAP1: DW RRCB
- RAL
- DW RRCB
- RAL
- RET
-
- if P2DOS
- ;Set Time c==0FFH, de == &buffer:
- ; NDAYS: DW 0 ;(binary count) #days since 1/1/1978
- ; HOURS: DB 0 ;(in BCD) 0000H<=ndays<=0FFFFH,
- ; MINUTE: DB 0 ;(in BCD) i.e. only 1978-2157,
- ; SECOND: DB 0 ;(in BCD) 179 years.
- ;Get Time c==00H; return hl == &buffer
- ;Note: calls to rclock return mmddyyWhhmmss
- ; pm: hx D2==1, 24: hx D3==1, leap: dx= D2==1
- BTIME: INR C
- RC ;Cannot set time (yet?)
- GTIME: MVI A,0DH ;synchronise rclock
- STA PASSADD
- LXI D,TBUFMO ;read clock information into buffer
- MVI B,13
- GTIME2: PUSH B
- CALL RCLOCK
- POP B
- ANI 0FH
- STAX D
- INX D
- DB djnz,GTIME2-$+0FFH
- GTIME3: MVI A,15H ;reset rclock
- STA PASSADD
- ;days = day_of_month-1;
- LXI H,TBUFYR ;for(yr -= 1978; yr>0; --y)
- CALL PAKBIN ; days += 365 + leap(yr);
- SUI 78 ;(We assume 1900s here, subtract just 0078)
- MOV B,A ;(b = p2dos year)
- PUSH B ;(save b for later calculations)
- LXI H,TBUFDY
- DW res2hl ;(clear "leap year" bit from clock chip)
- CALL PAKBIN ;(init hl = day of month - 1)
- DCX H
- LXI D,365
- GTIME4: DCR B
- JM GTIME5
- DAD D
- CALL LEAP
- DB jrnz,GTIME4-$+0FFH
- INX H
- DB jr,GTIME4-$+0FFH
- GTIME5: POP B ;(restore b=year#)
- XCHG ; m = mon-1; while (m-- > 0)
- LXI H,TBUFMO ; day += md[m] + (m == 1 && leap (y));
- CALL PAKBIN
- DCR A
- MOV C,A ;(b=year,c=month,de=day,hl->md[m])
- LXI H,MD-1
- ADD L
- MOV L,A
- DB jrnc,GTIME6-$-1
- INR H
- GTIME6: DCR C
- JM GTIME9
- MOV A,M
- DCX H
- ADD E
- MOV E,A
- DB jrnc,GTIME7-$-1
- INR D
- GTIME7: MOV A,C ;(is month == 1?)
- DCR A
- DB jrnz,GTIME6-$+0FFH
- CALL LEAP ;(yes, now is it a leap year?)
- DB jrnz,GTIME6-$+0FFH
- INX D ;(yup, increment #days by 1)
- DB jr,GTIME6-$+0FFH
- GTIME9: ;Save number of days since 1/1/1978
- XCHG
- SHLD P2NDAY
-
- LXI D,P2HR
- LXI H,TBUFHR
- DW res3hl
- DW res2hl
- CALL PAKBCD
- CALL PAKBCD
- CALL PAKBCD
- LXI H,P2NDAY
- RET
-
- PAKBCD: MOV A,M ;Pack two successive bcd bytes into bcd byte
- RLC
- RLC
- RLC
- RLC
- INX H
- ADD M
- INX H
- STAX D
- INX D
- RET
-
- ;leap - Return Z if p2dos year is a leap year, NZ otherwise.
- ; year 1978 = p2dos year 0, and maximum p2dos year = 2157
- LEAP: MOV A,B ;B = years since 1978
- ; CPI 122 ; if (y = 122) return (NZ) /*year 2100*/
- ; DB jrz,LEAP1-$-1
- ADI 2 ;correction needed: year 2 is leap year, year 0 is not
- LEAP1: ANI 3 ; return (y % 4)
- RET
-
- MD: DB 31,28,31,30,31,30,31,31,30,31,30 ;Don't need December
-
- ;Pack two successive bytes into binary word
- PAKBIN: MOV A,M
- RLC
- RLC
- ADD M
- RLC
- INX H
- ADD M
- MOV L,A
- MVI H,0
- RET
- endif
-
- ;*************************************************************
- ; End of I/O routines
- ;*************************************************************
-
- RNMSG: DB 'ID NOT FOUN','D'+80H
- CRCMSG: DB 'CR','C'+80H
- LDMSG: DB 'LOST DAT','A'+80H
- BSYMSG: DB 'BUS','Y'+80H
- WPMSG: DB 'PROTEC','T'+80H
- WFMSG: DB 'FAUL','T'+80H
-
- NRMSG: DB 'READY'
- ERRMSG: DB ' ERRO','R'+80H
-
- BTMSG: DB 'BOOT',' '+80H
- RDMSG: DB 0DH,0AH,'READ',' '+80H
- WTMSG: DB 0DH,0AH,'WRITE',' '+80H
- SKMSG: DB 0DH,0AH,'SEEK',' '+80H
- HEMSG: DB 0DH,0AH,'HOME',' '+80H
- if not ONLY2
- SWMSG: DB 0DH,0AH,'insert '
- SWDSK: DB '?: disk then key retur','n'+80H
- endif
-
-
- ;********************************************************
- ;PRE-INITIALIZED DATA VARIABLES:
- ; These items are set to initial values when loaded
- ; during cold-load.
- ;********************************************************
- ; Error counts. These locations keep track of the number
- ; of errors occurring during Read, Write, or Seek.
- RECNT: DB 0 ;READ ERROR COUNT.
- WECNT: DB 0 ;WRITE ERROR COUNT.
- SECNT: DB 0 ;SEEK ERROR COUNT.
- ERFLAG: DB 0 ;CPM BLOCKING ERROR FLAG
-
- SIDEFLG: DB 0 ;HEAD 2 SELECT FLAG (0=SIDE 1, NZ=SIDE 2)
- TRTAB: DB 0FFH,0FFH,0FFH,0FFH ;TRACK TABLE: PRESENT HEAD POSITION
- ;FOR FOUR DRIVES.
-
- PASSADD:DB 15H ;PASS COUNT & CLOCK REG PTR
- CLKDIR: DB 00H ;CLOCK DIGIT 'DIRECTOR'
-
- CURDSK: DB 0 ;Currently Selected Disk (Init=A:)
- UNACNT: DB 0 ;Blocking - Unallocated Record count
- HSTACT: DB 0 ; - Hostbuffer Active flag
- HSTWRT: DB 0 ; - Hostbuffer Write Pending flag
-
- if TYPEAHEAD
- ICOUNT: DB 0 ;INPUT QUEUE - number of characters
- endif
-
- if USER0
- CHKUSR0: CALL CCGTUSR ;Get current user number
- ORA A
- JZ CCERR ;If already 0, print error message
- MOV E,A ;Save user number
- PUSH D
- MVI E,0 ;Set user = 0
- CALL CCSTUSR
- CALL CCOPFCB ;Try to open file
- POP D
- PUSH PSW ;Restore user number
- CALL CCSTUSR
- POP PSW
- JNZ CCLOAD ;If file found, get it
- JMP CCERR ;Else print error
- endif
-
- ;********************************************************
- HSTBUF: ;Start of Host-Buffer (For 1 physical sector) *
- ;Reserve HSTSIZ bytes *
- ;The Cold-Boot routine here will be overwritten *
- ;********************************************************
- BOOT: LXI H,WBOOT ;RE-DIRECT CBOOT TO WBOOT
- SHLD CBOOT+1
- LXI SP,7FH ;SET STACK POINTER.
- MVI A,0A6H ;INIT 8251 I/O PORTS
- CALL INITSIO
- MVI A,40H
- CALL INITSIO
- LDA UARTT
- OUT CSTAT
- LDA UARTP
- OUT LSTAT
- LDA UARTM
- OUT MSTAT
- MVI A,27H
- CALL INITSIO
- MVI A,PPINIT;INIT 8255
- OUT PPCMD
- if not NOREVA
- MVI A,41H ;TEST IF 8255 IS PRESENT
- CALL TESTB ;IF SO, THIS IS REV B BOARD
- CMA ;(TEST TWICE, TO BE SURE)
- CALL TESTB ;
- endif
- XRA A ;SET DISK SELECT TO A: & USER# TO 0
- STA SEKDSK
- STA CDISC
- LXI H,SYSFMT;INIT IOBYTE &SYSFMT
- MOV A,M
- ANI 4
- RAR
- RAR
- MOV C,A
- LDA IOBYTA
- MOV B,A
- ANI IOBMSK
- ORA C
- STA IOBYTE
- MOV A,B
- ANI SYSMSK
- ORA M
- MOV M,A
- LXI H,SMSG ;PRINT OPENING MESSAGE.
- CALL PMSG
- LDA 07FH ;DISK OPTIONS: (temp addr. of density flag)
- LXI H,VDD ; DBL-D
- CPI 0DDH
- DB JRZ,DEN1-$-1
- LXI H,VDSD ; DBL-SD (always DBL-D)
- CPI 0D0H
- DB JRZ,DEN1-$-1
- LXI H,VSD ; SINGL-D
- DEN1: CALL PMSG
- if not ONLY2
- MOV A,B
- ANI 1 ;DRIVE OPTIONS:
- endif
- LXI H,V2D ; 2DRIVE
- if not ONLY2
- DB JRZ,STAT2-$-1
- LXI H,V1D ; 1DRIVE
- endif
- STAT2: CALL PMSG
- MOV A,B ;PRINTER OPTIONS:
- ANI 0C0H
- LXI H,VPLL ; PARALLEL
- DB JRZ,STAT5-$-1
- CPI 80H
- LXI H,VEA ; ETX-ACK
- DB JRZ,STAT6-$-1
- LXI H,VXO ; XON/XOFF OR NO
- DB JRC,STAT7-$-1; CONSOLE, SAY NOTHING
- STAT5: CALL PMSG
- LXI H,PROTCL;'PRINTER PROTOCOL'
- STAT6: CALL PMSG
- if ZCPR3
- LXI H,ENDISK-1 ;Clear rest of memory
- LXI D,ENDISK
- LXI B,0FFFFH-ENDISK+1
- DW LDIR
- endif
- STAT7:
- if P2DOS and ZCPR3
- JMP P2CBT ;Do extra initialisation for P2DOS/ZCPR3
- endif
- if (not P2DOS) or (not ZCPR3)
- JMP GOCPM
- endif
-
- INITSIO:
- OUT CSTAT
- OUT LSTAT
- OUT MSTAT
- RET
-
- if not NOREVA
- TESTB: MOV B,A ;TEST 8255 PORT B WITH BYTE IN A:
- OUT PPORTB ; OUTPUT BYTE TO PORT.
- IN PPORTB ; READ BACK IN.
- CMP B ; IF SAME, TEST PASSES, RETURN.
- RZ ;
- MVI A,REVA ; ELSE CHANGE FLAG TO 'A' AND RETURN.
- STA CPUREV ; (NOTE: FLAG IS IN SIGN-ON MESSAGE)
- RET
- endif
-
- SMSG: DB CR, LF, LF, 'ACI '
- DB MSIZE/10+'0', MSIZE MOD 10 +'0', 'K '
- if P2DOS
- DB 'P2DOS'
- endif
- if not P2DOS
- DB 'CP/M'
- endif
- DB ' v'
- DB REVNO/10+'0', '.', REVNO MOD 10 +'0'
- if not NOREVA
- CPUREV: DB 'B'
- endif
- if IBMB
- DB 'I'
- endif
- if USER0
- DB 'U'
- endif
- CRLF: DB CR,LF+80H
-
-
- if not ONLY2
- V2D: DB '2 drive,',' '+80H ;DRIVE OPTIONS
- V1D: DB '1 drive,',' '+80H ;
- endif
- if ONLY2
- V2D: DB '2 drive only,',' '+80H ;
- endif
- VPLL: DB 'PARALLE','L'+80H ;PRINTER OPTIONS
- VXO: DB 'XON/XOFF(or NO',')'+80H ;
- VEA: DB 'ETX/ACK' ;
- PROTCL: DB ' printe','r'+80H ;
- VSD: DB 'Single density,',' '+80H ;DISK OPTIONS
- VDD: DB 'Double density,',' '+80H ;
- VDSD: DB 'Double side,',' '+80H ;
- if ZCPR3
- DB 0 ;byte to clear mem to.
- endif
- ENDISK: ;End of CP/M image required to be stored on disk.
- ;************************************************************************
- if not ((HSTSIZ-($-HSTBUF)) SHR 15)*TRUE ;If not enough *
- DS (HSTSIZ-($-HSTBUF)) ;space is used, *
- endif ;reserve it *
- ;************************************************************************
-
-
- ;****************************************************************
- ; THE REMAINDER OF THE CBIOS IS RESERVED UNINITIALIZED
- ; DATA AREA, AND DOES NOT NEED TO BE A PART OF THE
- ; SYSTEM MEMORY IMAGE (THE SPACE MUST BE AVAILABLE,
- ; HOWEVER AS SCRATCH RAM AREA FOR BDOS USE). INITIALIZATION
- ; IS DONE FOR 'CONVENIENCE', AND IS SET TO PROBABLY
- ; CORRECT VALUES (FOR SINGLE-DENSITY DISKS).
- ;****************************************************************
- ERCNT: DB 0 ;ERROR COUNT FOR RETRIES.
- SERCNT: DB 0 ;SEEK RETRY COUNTER.
-
-
- SEKDSK: DB 0 ;CURRENTLY REQUESTED DISK. *DON'T
- SEKTRK: DW 0 ;CURRENTLY REQUESTED TRACK. *RE-ARRANGE
- SEKHST: DB 1 ;CURRENTLY REQUESTED HOST SECTOR*
- SEKSEC: DB 1 ;CURRENTLY REQUESTED SECTOR. *
-
- HSTDSK: DB 0FFH ;HOSTBUFFER DISK. *DON'T
- HSTTRK: DW 0FFFFH ;HOSTBUFFER TRACK. *RE-ARRANGE
- HSTSEC: DB 0FFH ;HOSTBUFFER SECTOR. *
- DB 0FFH ;not used, reserved *
-
- UNADSK: DB 0 ;LAST UNALLOCATED DISK. *DON'T
- UNATRK: DW 0 ;LAST UNALLOCATED TRACK. *RE-ARRANGE
- DB 0 ;not used, reserved *
- UNASEC: DB 0 ;LAST UNALLOCATED SECTOR. *
-
-
- CPMSPB: DB 8 ;BLOCKSIZE/128 *******BLOCKING PARMS********
- SECMSK: DB 0 ;HSTSIZ/128-1 ** DON'T RE-ARRANGE **
- SECSHF: DB 0+1 ;LOG2(HSTSIZ/128)+1 **PARMS ARE FOR LOGGED DISK**
- CPMSPT: DB 26 ;TRACKSIZE/128 *****************************
- LOGDEN: DB 2 ;DENSITY OF LOGGED DRIVE (2=SGL,1=DBL)
-
- RSFLAG: DB 0 ;READ SECTOR FLAG
- READOP: DB 0 ;READ OPERATION FLAG
- WRTYPE: DB 0 ;WRITE OPERATION TYPE
-
- DMAADD: DW 0080H ;CURRENT READ/WRITE ADDRESS.
-
- PCOUNT: DB 80H ;COUNTER FOR ETXACK:
-
- if TYPEAHEAD
- ICHARQ: DS QSIZE ;INPUT CHARACTER QUEUE
- endif
-
- DIRBF: DS 128 ;SCRATCH DIRECTORY AREA
- ALL00: DS 39 ;ALLOCATION VECTOR 0
- ALL01: DS 39 ;ALLOCATION VECTOR 1
- CHK00: DS 128/4 ;CHECK VECTOR 0
- CHK01: DS 128/4 ;CHECK VECTOR 1
-
- ADDRBF: DS 7 ;READ ADDRESS BUFFER (1 EXTRA BYTE RESERVED)
-
- if P2DOS
- ;data buffer for P2DOS time function - doesn't need initialization
- TBUFMO: DB 0,1 ;month
- TBUFDY: DB 0,1 ;day
- TBUFYR: DB 7,8 ;year
- DB 0 ;day of week (Sunday)
- TBUFHR: DB 0,0 ;hours 12-1-11 am, 52-41-51 pm
- TBUFMI: DB 0,0 ;minutes
- TBUFSC: DB 0,0 ;seconds
-
- P2NDAY: DW 0 ;#days since 1/1/78
- P2HR: DB 0 ;bcd hours
- P2MIN: DB 0 ;bcd minutes
- P2SEC: DB 0 ;bcd seconds
- endif ;P2DOS
-
- if ZCPR3
-
- ;This area needs to be cleared to all zeros on coldboot, with exceptions
- ;noted (and initialized by CBOOT. ZCPR3 must have these addresses defined
- ;in Z3BASE.HDR, exactly as they appear here.
-
- ;ZCPR3 Shell Stack
- SHSTK: DS 4*32
-
- ;ZCPR3 Message Buffer
- Z3MSG: DS 80
-
-
- ;80 byte command buffer for ZCPR3. Set Z3CL and Z3CLS (=80) in Z3BASE.HDR.
- Z3CL: DW 0 ;(Must be initialized to Z3BF by CBOOT)
- Z3SIZ: DB 0 ;(Must be initialized to 80 by CBOOT)
- Z3CT: DB 0
- Z3BF: DS 80
-
- ;Named directory buffer for ZCPR3. Set Z3NDIR and Z3NDIRS (=14) in Z3BASE.
- Z3NDIR: DS 14*18 + 1
-
- ;External Stack for ZCPR3. Set EXTSTK in Z3BASE. Always uses 48 bytes.
- EXTSTK: DS 48
-
- ;External FCB for ZCPR3. Set EXTFCB in Z3BASe. Always uses 36 byes.
- EXTFCB: DS 36 ;(Could this be put in the end of P2DOS also?)
-
- endif ;endif ZCPR3
-
- if P2DOS
- ;External Stack for P2DOS. Set P2STK in P2DOS.MAC. Uses 62 bytes (v23)
- P2STK: DS 62
- endif ;endif P2DOS
-
- if ZCPR3
-
- ORG 0FF00H
-
- ;External ZCPR3 Environment
- ;Because this holds the pointers to the other data areas, this gets fixed
- ;at top of memory. It is initialized by the loader LDR.
- Z3ENV: DS 2*128
-
- endif ;endif ZCPR3
-
- ORG BIOS-115 ;Overlay code on top of P2DOS blank area
- ;Only 115 bytes are available in P2DOS v23.
- ;Note: P2DOS MUST have external stack.
-
-
- if P2DOS and ZCPR3
-
- ;ZCPR3 External Command Executive Name (CMDRUN option)
- EXTRUN: DB 0 ;(A0:?)
- DB 'CMDRUN '
- DB 'COM'
-
- ;ZCPR3 External Search Path
- EXTPATH: DB '$$' ;This drive, this user#
- DB '$',0 ;This drive, user 0
- DB 1,0 ;Drive A: user 0
- DB 0
-
- ;ZCPR3 External Submit File FCB:
- ;EXTSUB in Z3BASE.LIB must be set either to the value given here for SUBFCB,
- ;or to zero. BE VERY SURE you aren't using this area for the ZCPR stack. The
- ;part of this that is commented out does not need to be initialised, there-
- ;fore it overlays the cold-boot code that may follow.
- P2CWBT: LXI H,0 ;Clear Submit FCB
- SHLD SUBEXT
- JMP CCP
-
- EXTSUB: DB 1 ;Default Drive A:
- DB '$$$ ' ;Submit filename
- DB 'SUB' ;Submit filetype
- SUBEXT:
- endif ;P2DOS and ZCPR3
- if FALSE ;(force it to overlay)
- DB 0 ;Extent number - clear this on warmboot
- DB 0 ;s1
- SUBFS2: DB 0 ;s2
- SUBFRC: DB 0 ;record count
- DS 16 ;Disk Group Map
- SUBFCR: DS 1 ;Current Record Number
- endif ;FALSE
-
- if P2DOS and ZCPR3
- ;ZCPR3 Command Line Initialisation:
- ;Because this code is used during coldboot only, which precedes the use of
- ;either the Submit facility or ZCPR3, this code will be overlayed by the
- ;Submit FCB area from below, and possibly by the ZCPR3 Stack from above.
- P2CBT: LXI H,Z3CNIT
- LXI D,Z3CL
- LXI B,P2CBTE-Z3CNIT
- DW LDIR
- JMP GOCPM ;Resume coldboot initialisation
-
- Z3CNIT: DW Z3BF ;Command Line image, must be same size as Z3CL
- DB 80 ;80 characters
- DB 0 ;Character count
- DB 'LDR SYS.ENV,SYS.NDR' ;coldboot command
- P2CBTE:
- endif ;ZCPR3 and P2DOS
-
-
- ACIDOS EQU (ENDISK+OFFSET+0FFH)/100H ;'SAVE xx ACIDOS.COM'
- END
-
-