LIST OFF LIST NOCOND FALSE EQU 0 TRUE EQU NOT FALSE INCLUD EQU FALSE LIST ON IF INCLUD EQ TRUE SUBTITLE DCM MODULE ELSE TITLE DISK CONTROLLER MODULE ENDIF ;************************************************************* ; ; DISK CONTROLLER MODULE (DCM) ; ; Algorithm property of: Jade Computer Products Inc. ; 4901 W. Rosecrans Blvd. ; Hawthorne, CA 90250 ; ; Ver. 2.2 for 8" drives by Girvin Herr ; ; The disk controller module (DCM) resides internal to the ; Jade Double D Disk Controller board. This program provides ; a facility to read/write diskette sectors & format diskette ; tracks (in single & double density). This DCM sets the ; parameters for each drive during the "LOG-ON" operation. ; The FORMAT program (not in this module) writes an ident- ; ification sector (0,0) which provides the needed information. ; If this identity sector is not present on the diskette, it ; is assumed to be a standard 8" IBM 3740 format. This program ; contains a 6 word timing block which should be patched to ; match the user's disk drives. ; This has normally been set for Shugart SA800/801 drives. ; ;************************************************************* ; FORM ;************************************************************ IF INCLUDE EQ FALSE ENTRY DCMMOD,DBUFR ; ;************************************************************ ENDIF ; ; THE FOLLOWING IS A LIST OF THE INTERNAL I/O ADDRESS ; ASSIGNMENTS. ; THESE PORTS AND CONTROLS CAN ONLY BE USED BY THE ONBOARD Z80. ; ; CONTROLLER PORT ASSIGNMENTS: ; BLSTS: EQU 0 ;BOARD STATUS PORT BLCTL: EQU 0 ;BOARD CONTROL PORT WDCMD: EQU 4 ;1791 COMMAND REGISTER WDSTS: EQU 4 ;1791 STATUS REGISTER WDTRK: EQU 5 ;1791 TRACK REGISTER WDSEC: EQU 6 ;1791 SECTOR REGISTER WDDTA: EQU 7 ;1791 DATA REGISTER ; ; CONTROLLER FUNCTION ASSIGNMENTS ; XPSTP: EQU 8H ;ISSUE STEP PULSE XPMTO: EQU 10H ;MOTOR TURN OFF XPIRR: EQU 20H ;S100 INT-REQ RESET XPMTX: EQU 40H ;MOTOR TIME EXTEND XPDSH: EQU 80H ;DATA SYNC HOLD ; ; THE FOLLOWING ASSIGNS EACH BIT POSITION & FUNCTION OF THE ; BOARD CONTROL PORT (BLCTL). ; ; BIT ASSIGNMENTS ; BCDSA: EQU 00000001B ;DRIVE SELECT A (2*0) BCDSB: EQU 00000010B ;DRIVE SELECT B (2*1) BCDSE: EQU 00000100B ;DRIVE SELECT ENABLE BCEIA: EQU 00001000B ;EIA SIGNAL LEVEL OUT BCDDE: EQU 00010000B ;DOUBLE DENSITY ENABLE BCDAS: EQU 00100000B ;DIRECTION (& SIDE) BCPCA: EQU 01000000B ;PRECOMP SELECT A BCPCB: EQU 10000000B ;PRECOMP SELECT B ; ; FUNCTION ASSIGNMENTS ; BCDSN: EQU BCDSA+BCDSB ;DRIVE # MASK BCSDS: EQU 0 ;SINGLE DENSITY BCDDS: EQU BCDDE ;DOUBLE DENSITY BCPCH: EQU BCPCA ;PRECOMP. - HEAVY BCPCM: EQU BCPCB ;PRECOMP. - MEDIUM BCPCL: EQU BCPCA+BCPCB ;PRECOMP. - LIGHT BCPCZ: EQU 0 ;PRECOMP. - OFF ; ; THE FOLLOWING DEFINES EACH BIT & FUNCTION OF THE BOARD ; STATUS PORT (BLSTS). ; BSUS0: EQU 00000001B ;USER SWITCH 0 = 179X DATA ; INVERT "1" BSUS1: EQU 00000010B ;USER SWITCH 1 (NOT USED YET) BSTST: EQU 00000100B ;TEST MODE SWITCH BSINT: EQU 00001000B ;HOST INTERRUPT REQUEST BSEIA: EQU 00010000B ;EIA SIGNAL LEVEL INPUT BSMOF: EQU 00100000B ;MOTOR OFF INDICATOR BSTSD: EQU 01000000B ;TWO SIDED DRIVE FLAG BSDCN: EQU 10000000B ;DISK CHANGE INDICATOR ; ; FOLLOWING IS A LIST OF COMMAND CODES ISSUED TO THE 179X ; DISK CONTROLLER ; DCHDL: EQU 00011000B ;SEEK/LOAD HEAD DCHDU: EQU 00010000B ;SEEK/UNLOAD HEAD DCRDS: EQU 10000000B ;READ SECTOR DCWRS: EQU 10100000B ;WRITE SECTOR DCWRT: EQU 11110000B ;WRITE TRACK FORMAT DCRDA: EQU 11000000B ;READ TRACK ADDRESS DCSTS: EQU 11010000B ;SET TYPE 1 STATUS OR ABORT ; CMD WITHOUT INT. DCIFI: EQU 11011000B ;FORCED INTERRUPT (NOT USED) ; ; STATUS BIT DEFINITIONS: ; ; TYPE I: ; CSDNR: EQU 10000000B ;DRIVE NOT READY CSWRP: EQU 01000000B ;WRITE PROTECTED CSHLD: EQU 00100000B ;HEAD LOADED CSSKE: EQU 00010000B ;SEEK ERROR CSCRC: EQU 00001000B ;CRC ERROR CSTK0: EQU 00000100B ;TRACK 0 CSINDX: EQU 00000010B ;INDEX CSBSY: EQU 00000001B ;BUSY ; ; TYPE II & III: ; CSTYPE: EQU 00100000B ;RECORD TYPE CSWFLT: EQU 00100000B ;WRITE FAULT CSRNF: EQU 00010000B ;RECORD NOT FOUND CSLDE: EQU 00000100B ;LOST DATA ERROR CSDRQ: EQU 00000010B ;DATA REQUEST ; ; FOLLOWING CONTAINS ALL THE MASKS USED TO TEST THE 1791 ; STATUS CODE PORT WDSTS ; DMRER: EQU 10011101B ;READ ERROR TEST DMWER: EQU 11111101B ;WRITE ERROR TEST DMFER: EQU 11100100B ;FORMAT ERROR TEST DMTK0: EQU 00000100B ;TRACK 0 TEST DMHDL: EQU 00100000B ;HEAD LOAD TEST DMDNR: EQU 10000000B ;DRIVE NOT READY DMLDE: EQU 00000100B ;LOST DATA ERROR ; ; BASE ADDR FOR DCM ; BASE: EQU 1000H ;BASE ADDR ; ; MEMORY BANKS ; BANK0: EQU BASE+0 ;DEFINE BANK 0 BANKL: EQU 400H ;BANK LENGTH BANK1: EQU BANK0+BANKL ; ; RESTART VECTORS ; RST0: EQU BANK0+0 RST1: EQU BANK0+8H RST2: EQU BANK0+10H RST3: EQU BANK0+18H RST4: EQU BANK0+20H RST5: EQU BANK0+28H RST6: EQU BANK0+30H RST7: EQU BANK0+38H ; ; INTERRUPT VECTORS ; HRINT: EQU RST7 ;MASKABLE NMINT: EQU BANK0+66H ;NON-MASKABLE ; ; I/O COMMUNICATION ; IOBLK: EQU BANK0+370H ;I/O BLOCK BEGIN TPSTK: EQU IOBLK+0 ;TOP OF STACK CMDBK: EQU IOBLK+0 ;COMMAND BLOCK BUFBG: EQU IOBLK+10H ;SECTOR BUFFER FMTBG: EQU BANK1+300H ;FORMAT BUFFER FMTPS: EQU FMTBG+8H ;FORMAT PROGRAM ; ; TIMING CONSTANTS ; TMRFC: EQU 19H ;TIMING CONSTANT, 1ST PASS TMRNC: EQU 1CH ;TIMING CONSTANT, NORMAL PASS ; ; RETRY VALUES ; RTYSK: EQU 5 ;REPOSITION HEAD ON RETRY RTYLS: EQU 9D ;LAST REPEATED RETRY ; FORM ;************************************************************* ; ; THE FOLLOWING AREA IS THE INITIAL START JUMP TABLE. ; THE 1ST JUMP IS EXECUTED WHEN THE ONBOARD Z80 IS RESET. ; THE SECOND JUMP IS THE DCM ENTRY FROM A BOOTSTRAP LOADER. ; THIS ENTRY ASSUMES DCM HAS BEEN LOADED INTO DD BANK 1 BY THE ; LOADER ROUTINE. THE LAST 2 BYTES HOLD THE JUMP ADDRESS USED ; BY RESTART INTERRUPT ROUTINE @ BANK 0 + 380H. ; ; IF INCLUDE EQ FALSE DATA ;PUT IN DATA SEGMENT ELSE ORG BASE ENDIF START: ; JP CLEAR ;RESET & RE-INITIALIZE Z-80 REGS JP INITB+BANKL ;INIT - BOOTSTRAPPED HRVEC: DW XCUTE ;BUS INTERRUPT VECTOR ; ; THIS SUBROUTINE IS THE ENTRY POINT FOR THE DISK CONTROLLER ; TIMING MODULE. THIS MODULE PROVIDES DELAYS WHICH ARE ; MULTIPLES OF 100 us. THE CONTENTS OF DE DETERMINES THE TOTAL ; PERIOD. (DELAY=(DE)*100 us). ; LD B,TMRFC ;SET CONSTANT DJNZ $ JP TICKE ;GOTO TICK ENTRY ; ; INITIALIZE Z-80 REGS AFTER RESET & HALT FOR CMD ; CLEAR: LD SP,TPSTK IM 1 LD C,0 ;IF NOT INVERTED DATA SELECT THEN ; CONTINUE IN A,BLSTS AND BSUS0 JR NZ,STOP LD C,0FFH ;ELSE SET UP INVERT MASK STOP: LD IX,DTDED ;SET DRIVE TABLE PTR EI HALT ; ; RESTART SPARES ; DS RST7-$ ; ; MASKABLE INTERRUPT ROUTINE - EXECUTED WHEN RESTARTING THE ; Z80 FROM A HALT. THE FUNCTIONS ARE; RESET THE DD INT REQ ; FLOP, PUT THE INTERRUPTED ADDR IN DE & JUMP ADDR @ HRVEC. ; IN A,XPIRR ;RESET INT REQ POP DE ;PURGE INTERRUPTED ADDR LD HL,(HRVEC) ;GET RETURN ADDR JP (HL) ; ; END OF SEQUENCE HALT - DURING THIS TIME, THE HOST SYSTEM ; CAN SWITCH THE CONTROLLER MEMORY INTO THE S100 BUS FOR ; STATUS CHECK, SETTING COMMAND BLOCK, & SECTOR DATA XFERS. ; FETCH: EI ;ENABLE INTERRUPT RESTART HALT ; ; THIS GETS CONTROL AFTER THE DISK CONTROLLER IS INTERRUPTED ; FROM THE HALT CONDITION. IT BRANCHES TO THE INDIVIDUAL ; COMMAND ROUTINES. ; XCUTE: CALL EXSTS ;GET 179X'S ATTENTION FOR CMDS LD A,(CBCMD) ;GET HOST CMD AND MASK ;LIMIT OPTIONS ADD A ;2*VALUE LD D,0 LD E,A ;SET UP OFFSET LD HL,CMDT ;SET TABLE PTR ADD HL,DE LD E,(HL) INC HL LD D,(HL) EX DE,HL JP (HL) ;GOTO COMMAND ; CMDT: EQU $ ;COMMAND TABLE CM0A: DW LGON ;LOG-ON DRIVE CM1A: DW READ ;READ SECTOR CM2A: DW WRIT ;WRITE SECTOR CM3A: DW FORM ;FORMAT TRACK CM4A: DW ADDR ;READ ADDRESS CM5A: DW SPAR ;SPARES CM6A: DW SPAR CM7A: DW IDLE ;BACKGROUND MASK: EQU 7 ;COMMAND MASK ; ; THIS IS THE NON-MASKABLE INTERRUPT ROUTINE ; UPON 1791 COMMAND TERMINATION, THE Z80 RECEIVES A NMI. THE ; STATUS PORT IS INTERROGATED & SAVED (SVSTS). IY HAS RETURN ; ADDR. ; DS NMINT-$ ; WDINT: IN A,WDSTS ;GET 1791 STATUS & RESET INT. XOR C LD (SVSTS),A EX (SP),IY ;PUT RETURN ADDR ON STACK RETN ; ; REMAINDER OF TIMING SECTION FROM RESTART 1 ; TICKR: LD B,TMRNC ;SET NORMAL CONSTANT DJNZ $ TICKE: DEC DE ;COUNT -1 LD A,D OR E ;IF COUNT NOT 0 THEN REPEAT NOP NOP JR NZ,TICKR RET ;ELSE RETURN ; ; READ SECTOR COMMAND ; READ: CALL SELECT ;SELECT DRIVE JP NZ,FETCH ;IF DRIVE NOT READY THEN EXIT CALL SEEK ;SEEK TRACK & SET CTLS CALL RDSEC ;READ A SECTOR JP FETCH ;GET NEXT COMMAND ; ; WRITE SECTOR COMMAND ; WRIT: CALL SELECT JP NZ,FETCH CALL SEEK CALL WRSEC JP FETCH ; ; FORMAT TRACK COMMAND ; FORM: CALL SELECT JP NZ,FETCH LD A,(CBSEC) ;GET FORMAT FLAGS LD (IX+DVFLG),A ;RESET DRIVE FLAGS CALL SEEK CALL WRTRK ;WRITE DISK TRACK JP FETCH ; ; DRIVE LOG-ON COMMAND ; LGON: CALL SELECT JP NZ,FETCH XOR A ;SET TRACK=0 LD (CBTRK),A INC A ;SET SECTOR =1 LD (CBSEC),A CALL SEEK JP NZ,FETCH ;IF ERROR THEN EXIT CALL RDSEC ;READ ID SECTOR CALL LOGON ;LOG ON DISK DRIVE JP FETCH ; ; READ ADDRESS COMMAND ; ADDR: JP FETCH ;NOT IMPLEMENTED ; ; SPARE COMMAND ; SPAR: JP FETCH ; ; IDLE COMMAND ; IDLE: IN A,BLSTS ;IF NO HOST INTERRUPT THEN WAIT AND BSINT JR Z,IDLE IN A,XPIRR ;ELSE RESET INTERRUPT REQUEST & EXIT JP FETCH ; ; THIS SUBROUTINE IS RESPONSIBLE FOR SELECTING THE COMMAND ; REQUESTED DRIVE #. BEFORE DRIVE SELECTION, THE DRIVE MOTOR ; STATE IS TESTED AND IF NEEDED, THEY ARE TURNED ON. IX IS SET ; TO POINT TO THE NEW SELECTED DRIVE TABLE. ; SELECT: IN A,BLSTS ;GET BOARD LEVEL STATUS AND BSMOF ;IF MOTOR ON THEN CHECK DRIVE JR Z,CKDV IN A,XPMTX ;ELSE ISSUE MOTOR START LD DE,(TMMTO) RST 8H CKDV: IN A,XPMTX ;EXTEND MOTOR TIME LD A,(SVDRV) ;INSURE 179X INTRQ ENABLED FOR ; LATER OR BCDSE ;CMDS OUT BLCTL,A LD A,(CBDRV) ;IF THIS DRIVE = OLD DRIVE THEN ; OK CP (IX+DVNBR) JR Z,DVOK CALL EXHDU ;ELSE UNLOAD HEAD, LD A,(SVDRV) ;DESELECT CURRENT DRIVE, AND [NOT BCDSE] OUT BLCTL,A LD A,(CBDRV) ;SELECT DESIRED DRIVE, AND BCDSN OUT BLCTL,A OR BCDSE OUT BLCTL,A LD (SVDRV),A AND BCDSN ;SELECT DRIVE TABLE FOR DRIVE LD IX,DVTBL LD DE,DVDES ;DRIVE TABLE ARRAY SIZE NEXT: DEC A ;IF DRIVE = 0 THEN EXIT WITH POINTER SET JP M,SLED ADD IX,DE ;ELSE POINT TO NEXT ARRAY & REPEAT JR NEXT ; SLED: CALL EXSTS ;SET FLAGS PER DRIVE READY AND DMDNR LD (CBSTS),A DVOK: RET ; ; HOMED SUBROUTINE STEPS THE DISK DRIVE HEAD OUTWARD UNTIL ; TRACK 0 FLAG IS TRUE OR 255 STEPS HAVE BEEN ISSUED ; HOMED: LD L,255D ;SET MAX COUNT STEP: CALL EXSTS ;IF ON TRACK 0 THEN EXIT AND DMTK0 JR NZ,EXIT DEC L ;IF STEPS = 255 THEN ERROR JR Z,EROR IN A,XPSTP ;ISSUE STEP PULSE LD DE,(TMSTP) ;SET DELAY RST 8H JR STEP ; ; DRIVE IS RESTORED ; EXIT: LD DE,(TMALS) ;WAIT A BIT AFTER LAST STEP RST 8H LD A,0 ;SET COMPLETE FLAG LD (IX+DVTRK),A ;SET TRACK VALUE AND A ;SET RETURN FLAGS RET ; ; TRACK 0 NOT FOUND ; EROR: LD A,0FFH ;SET FAILURE FLAG AND A RET ; ; LOGON SUBROUTINE READS THE IDENTITY SECTOR FROM THE ; DISKETTE AND MAKES THE NEEDED ENTRYS INTO THE DRIVE TABLE. ; THE SECTOR DATA IS ALSO LEFT IN THE SECTOR BUFFER FOR BIOS ; TO FINISH THE LOG-ON OPERATION. ; LOGON: LD DE,JADEID ;SET STRING PTR LD HL,IDLB ;SET SECTOR BUFFER PTR TO COMPARE LD B,IDSZE ;SET ID LENGTH CKJI: LD A,(DE) ;IF ID NOT=JADE THEN 3740 CP (HL) JR NZ,I3740 INC HL ;ELSE INC PTRS INC DE DJNZ CKJI ;IF NOT DONE THEN REPEAT LD A,(IDSPT) ;SET TRACK SECTOR COUNT LD (IX+DVSPT),A LD A,(IDSTG) ;SET STAGGER # LD (IX+DVSTG),A LD A,(IDFLG) ;SET SIDES & DENSITIES LD (IX+DVFLG),A JP FETCH ; ; ASSUME 3740 FORMAT ; I3740: LD A,26D ;SECTORS/TRK=26D LD (IX+DVSPT),A LD A,1 ;STAGGER=1 LD (IX+DVSTG),A LD A,IDFLD ;SIDE & DENSITIES FLAGS=0 LD (IX+DVFLG),A JP FETCH ; ; TRACK SEEK SUBROUTINE ; EXIT - DENSITY & PRE-COMP CONTROLS SET ; SEEK: CALL EXSTS ;IF HEAD ALREADY LOADED THE BYPASS AND DMHDL JR NZ,HLDD CALL EXHDL ;ELSE LOAD HEAD LD DE,(TMHLD) RST 8H HLDD: LD A,(CBTRK) ;IF CURRENT TRACK=REQUESTED ; TRACK THEN EXIT SUB (IX+DVTRK) JR NZ,DSET LD A,(IX+DVCTL) ;ELSE GET PREVIOUS CTLS & ; RETURN JP EXITS ; ; SET DIRECTION & STEP COUNT ; DSET: PUSH AF LD DE,(TMSAW) ;DELAY FOR STEP AFTER WRITE RST 8H POP AF JR C,SOUT ;CARRY=STEP OUT SIN: LD L,A LD A,(SVDRV) OR BCDAS OUT BLCTL,A JR STEPS ; SOUT: NEG ;COMPLEMENT OFFSET JP M,HOME LD L,A LD A,(SVDRV) OUT BLCTL,A STEPS: IN A,XPSTP ;ISSUE STEP PULSE LD DE,(TMSTP) RST 8H DEC L ;IF STEPS-1 NOT 0 THEN STEP AGAIN JR NZ,STEPS LD DE,(TMALS) ;ELSE EXTEND LAST PULSE RST 8H ; ; TRACK SECTION DISTRIBUTE ; LD A,(CBTRK) ;IF TRACK 0 THEN GOTO TRK0 CP 1 JR C,TRK0 JR Z,TRK1 ;ELSE IF TRACK 1 THEN GOTO TRK1 CP 26D ;ELSE IF