; ; ; ;* * * DEFINE I/O PORTS ON KONAN SMC-200 DISK CONTROLLER * * * ; ; ; BUSDRA EQU 90H;OUTPUT PORT (BUS DRIVERS - BUSDRA CONTROLS ;THE BUS & SELECT LINES TO THE DISK DRIVE ;(BITS 0,1 = BITS 8,9 OF THE BUS DATA, BIT ;4 = DRIVE ADDRESS AND BIT 7 = POWER SAVE)) ; BUSDRB EQU 91H;OUTPUT PORT (BUS DRIVERS - BUSDRB CONTROLS ;THE BUS DATA LINES TO THE DISK DRIVE (BITS ;0 - 7 = BUS DATA 0 - 7)) ; CMDREG EQU 92H;OUTPUT PORT (COMMAND REGISTER - USED TO IN- ;ITIATE THE FOLLOWING: DMA AND DISK TRANSFERS, ;DISK SELECTION, HEAD SELECTION, SEEKS, AND ;RECOVERY OPERATIONS) ; ;BITS - 0 = DISK WRITE, 1 = DMA WRITE, 2 = DMA READ, 3 = ;DISK READ, 4 = SELECT UNIT, 5 = SET CYLINDER, 6 = SET HEAD, ;7 = FAULT RECOVERY ; SECADP EQU 93H;OUTPUT PORT (SECTOR ADDRESS - SELECTS THE SECTOR ;TO BE USED FOR THE NEXT READ OR WRITE OPERATION (BITS - 0 = ;LSB AND 7 = MSB)) ; SECBFP EQU 94H;INPUT/OUTPUT PORT (SECTOR BUFFER - ALLOWS SOFTWARE ;TO READ AND WRITE THE SECTOR BUFFER (1K OF RAM ;LOGICALLY PLACED BETWEEN THE DISK AND USER'S ;MEMORY. SIZE = BYTES OF USER MEMORY + HEADER BYTES.)) ; STATPT EQU 97H;INPUT/OUTPUT PORT (STATUS - ALLOWS DONE, READY AND ;ERROR STATUS TO BE READ. WRITING TO THIS I/O PORT ;RESETS THE SECTOR BUFFER ADDRESS) ; ;BITS - 0 = SELECTED, 1 = SEEK ERROR, 2 = CHECKSUM ERROR, 3 = BUSY ;OR PROTECTED, 4 = ON CYLINDER, 5 = DISK FAULT, 6 = DISK READY, ;7 = DONE ; ; ; * * * DEFINE SMC-200 LEGAL COMMANDS * * * ; RESETS EQU 0H;(RESETS DONE AND INTERRUPT, NO DATA SET-UP REQUIRED) ; DSKWRT EQU 1H;(WRITES THE CONTENTS OF THE SECTOR BUFFER TO THE DISK) ; ;THE DATA IS WRITTEN ON THE CURRENTLY SELECTED DRIVE, HEAD AND TRACK ;AT THE SECTOR SELECTED BY THE SECTOR ADDRESS REGISTER ; DSKRD EQU 8H;(READS A SECTOR FROM THE DISK INTO THE SECTOR BUFFER) ; ;THE SECTOR READ IS DEFINED BY THE SECTOR REGISTER AND IS TAKEN FROM ;THE CURRENTLY SELECTED DRIVE, HEAD, AND TRACK ; SELUNT EQU 10H;(THIS COMMAND CAUSES THE SELECT TAG LINE TO BE STROBED)) ; ;PRIOR TO ISSUING THIS COMMAND THE ADDRESS OF THE DRIVE TO BE SELECTED ;IS SET INTO THE BUSDRA REGISTER ; SETCYL EQU 20H;(CAUSES THE SELECTED DRIVE TO SEEK TO THE CYLINDER ;SELECTED BY BUS 0 - 9 LINES (SET BY BUSDRA AND BUSDRB)) ; SETHD EQU 40H;(SELECTS THE DISK HEAD IDENTIFIED BY THE BUS LINES ;(SET BY OUT BUSDRB)) ; FLTCLR EQU 80H;(PERFORMS THE FAULT CLEAR FUNCTION IDENTIFIED BY ;THE BUS LINES) ; FLTREC EQU 88H;(READS A SECTOR FROM THE DISK (SAME AS 08H) WITH ;ERROR RECOVERY FUNCTIONS SELECTED BY OUT BUSDRA AND ;BUSDRB) ; SBUFSZ EQU 204H;204 HEX = 516 DEC (512 BYTES FOR SECTOR + 4 HEADER BYTES ; SELECT EQU 01H;SELECT TEST BIT SEEKER EQU 02H;SEEK ERROR TEST BIT CHKSUM EQU 04H;CHECKSUM ERROR TEST BIT BSYWRP EQU 08H;BUSY OR WRITE PROTECTED TEST BIT ONCYL EQU 10H;ON-CYLINDER TEST BIT DSKFLT EQU 20H;DISK FAULT TEST BIT DSKRDY EQU 40H;DISK READY TEST BIT DONE EQU 80H;DONE TEST BIT ; ; ; ORG 0D000H ; JMP 0000H;JUMP TO CPM ; ;FORMAL PARAMETERS (USER LANGUAGE - INTERFACE) ; SUNIT: DB 00H SCYL: DB 00H;MSB OF TRACK ADDRESS DB 00H;LSB OF TRACK ADDRESS ECYL: DB 00H;MSB OF TRACK ADDRESS DB 00H;LSB OF TRACK ADDRESS SHD: DB 00H EHD: DB 00H SSECT: DB 00H ESECT: DB 00H SDATA: DB 00H DB 00H DB 00H DB 00H DB 00H XCYL: DB 00H;MSB OF TRACK ADDRESS DB 00H;LSB OF TRACK ADDRESS XHD: DB 00H XSECT: DB 00H XDATA: DB 00H DB 00H DB 00H DB 00H DB 00H XPRGCNT:DB 00H;SCRATCH - MSB MISC. COUNTER DB 00H;SCRATCH - LSB MISC. COUNTER PRGCMD: DB 00H;PROGRAM COMMAND PRGMOD: DB 00H;MISC. PROGRAM MODIFIERS DATMOD: DB 00H;MISC. DATA MODIFIERS PRGCNT: DB 00H;MSB MISC. COUNTER DB 00H;LSB MISC. COUNTER CBIAS : DB 00H;MSB - COUNTER BIAS DB 00H;LSB - COUNTER BIAS CSTATS: DB 00H;CONTROLLER STATUS PSTATS: DB 00H;PROGRAM STATUS OSBUFF: DS SBUFSZ;OUTPUT SECTOR BUFFER ISBUFF: DS SBUFSZ;INPUT SECTOR BUFFER HDR1 EQU OSBUFF HDR2 EQU OSBUFF + 1 HDR3 EQU OSBUFF + 2 HDR4 EQU OSBUFF + 3 STKPTR: DB 00H;SAVE STACK POINTER DB 00H ; ; ; INITI: LXI H,00H;NEXT 3 INST. SAVES STACK POINTER @ STKPTR: DAD SP SHLD STKPTR MVI A,00H;CLEAR A REG STA CSTATS;CLEAR CONTROLLER STATUS (LAST) STA PSTATS;CLEAR PROGRAM STATUS (LAST) LDA SCYL;INIT STARTING CYLINDER (MSB) STA XCYL LDA SCYL + 1;INIT START CYLINDER (LSB)+ 1 STA XCYL + 1 LDA SHD;INIT STARTING HD STA XHD LDA SSECT;INIT STARTING SECTOR STA XSECT LDA SDATA;INIT STARTING DATA STA XDATA LDA PRGCNT;INIT. MSB MISC. COUNTER STA XPRGCNT LDA PRGCNT + 1;INIT. LSB MISC. COUNTER STA XPRGCNT + 1 JMP GETCMD ; GETCMD: LDA PRGCMD CPI 01H;1 = READ COMMAND JZ RDCMD;IF PRGCMD = 1 THEN DO A READ CPI 02H;2 = WRITE COMMAND JZ WRCMD;IF PRGCMD = 2 THEN DO A WRITE CPI 03H;3 = DO OSCILLATING SEEKS JZ OSCSEK;IF PRGCMD = 3 DO SEEKS CPI 04H;4 = FORMAT JZ FORMAT;IF PRGCMD = 4 DO FORMAT CPI 05H;5 = VERIFY FORMAT JZ VERIFY;IF PRGCMD = 5 DO VERIFY THE FORMAT CPI 06H;6 = WRITE - READ - COMPARE (DONT CHK HDR BEFORE WRITE) JZ WRRDCP;IF PRGCMD = 6 DO WRITE - READ - COMPARE MVI A,06H;6 = BAD COMMAND STA PSTATS JMP BBASIC;BACK TO BASIC ON BAD COMMAND ; BBASIC: LHLD STKPTR;NEXT 2 INST. RESTORES ORIGINAL STACK POINTER SPHL RET;RETURN BACK TO BASIC ; SELEC: LDA SUNIT OUT BUSDRA MVI A,SELUNT OUT CMDREG IN STATPT ANI SELECT JZ SELERR XRA A OUT CMDREG;RESET DONE + INTERRUPT RET ; SELERR: MVI A,01H;SELECT SEQ = 1 STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ; SELHD: LDA XHD OUT BUSDRB STA HDR3 MVI A,SETHD OUT CMDREG RET ; SELCYL: LDA XCYL;MSB OF TRACK ADDRESS OUT BUSDRA STA HDR1 LDA XCYL + 1;LSB OF TRACK ADDRESS OUT BUSDRB STA HDR2 MVI A,SETCYL OUT CMDREG WAITC: IN STATPT ANI DONE JZ WAITC ANI SEEKER RZ MVI A,02H;SEEK SEQ = 2 STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC ; SETSEC: LDA XSECT OUT SECADP STA HDR4 RET ; GDSTWR: IN STATPT ANI 51H;STATUS BITS - RDY,ONCYL,SEL CPI 51H;CHECK FOR RDY,ONCYL,SEL JZ BDSTWR;GO CHECK FOR ANY BAD STATUS BITS MVI A,03H;WRITE SEQ = 3 STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; BDSTWR: IN STATPT;CHECK FOR BAD STATUS ANI 2AH;STATUS BITS - FLT,PROTECTED,SEEK ERR JZ WRDISK;EVERY THING OK - DO WRITE MVI A,04H;WRITE SEQ = 4 STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; WRDISK: OUT STATPT;CLEAR SECTOR BUFFER ADDRESS XRA A;CLEAR THE BUS OUT BUSDRA OUT BUSDRB MVI A,DSKWRT OUT CMDREG WAITB: IN STATPT;WAIT FOR DONE ANI DONE JZ WAITB GSTAWR: IN STATPT ANI 51H;STATUS BITS - RDY,ONCYL,SEL CPI 51H;CHECK FOR GOOD STATUS JZ BSTAWR;JUMP IF GOOD MVI A,07H;WRITE SEQ = 7 STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; BSTAWR: IN STATPT;CHECK FOR BAD STATUSES ANI 2AH;STATUS BITS - FLT,PROTECTED,SEEK ERR RZ;RETURN BACK TO MAIN PROGRAM - OK MVI A,08H STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; GDSTRD: IN STATPT ANI 51H;STATUS BITS - RDY,ONCYL,SEL CPI 51H;CHECK FOR GOOD STATUS JZ BDSTRD MVI A,09H STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; BDSTRD: IN STATPT;CHECK FOR ANY BAD STATUS BITS ANI 22H;STATUS BITS - FLT,SEEK ERR JZ RDDISK;EVERY THING OK,DO READ MVI A,0AH;READ SEQ = A LXI H,PSTATS MOV M,A IN STATPT LXI H,CSTATS MOV M,A INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; RDDISK: XRA A;RESET A REG OUT BUSDRA OUT BUSDRB OUT STATPT;ZERO SECTOR ADDRESS MVI A,DSKRD OUT CMDREG WAITA: IN STATPT;WAIT FOR DONE ANI DONE JZ WAITA GSTARD: IN STATPT;CHECK FOR GOOD STATUSES ANI 51H;STATUS BITS - RDY,ONCYL,SEL CPI 51H;CHECK FOR GOOD STATUS JZ BSTARD;OK - GO LOOK FOR BAD STATUSES MVI A,0BH;READ SEQ = B STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; BSTARD: IN STATPT;CHECK FOR BAD STATUS BITS ANI 26H;STATUS BITS - FLT,CHKSUM ERR,SEEK ERR RZ;RETURN BACK TO MAIN PROGRAM,ALL IS GOOD MVI A,0CH;READ SEQ = C STA PSTATS IN STATPT STA CSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; LDSECB: OUT STATPT;RESET SECTOR BUFFER ADDRESS LXI H,OSBUFF MOV A,M OUT SECBFP;HDR1 INX H MOV A,M OUT SECBFP;HDR2 INX H MOV A,M OUT SECBFP;HDR3 INX H MOV A,M OUT SECBFP;HDR4 LXI D,SBUFSZ - 4 LXI H,XDATA MOV A,M LXI H,OSBUFF + 4;SKIP HEADER BYTES LOOPA: MOV M,A OUT SECBFP INX H DCR E JNZ LOOPA DCR D JNZ LOOPA RET ; UNLDSB: OUT STATPT;ZERO SECTOR BUFFER ADDRESS LXI D,SBUFSZ INR D LXI H,ISBUFF LOOPB: IN SECBFP MOV M,A INX H DCR E JNZ LOOPB DCR D JNZ LOOPB RET ; ;COMPARE SECTOR BUFFERS COMPSB: LXI B,SBUFSZ;CONTROL COUNTER INR B LXI H,ISBUFF LXI D,OSBUFF LOOPC: LDAX D CMP M JNZ CMPERR;COMPARE ERROR INX D INX H DCR C JNZ LOOPC DCR B JNZ LOOPC RET ; CMPERR: MVI A,05;COMPARE ERROR STATUS SET TO 5 STA PSTATS INX SP INX SP JMP BBASIC;BACK TO BASIC ON ERROR ; LDADDO: OUT STATPT;RESET SECTOR BUFFER ADDRESS LXI H,OSBUFF MOV A,M OUT SECBFP;HDR1 INX H MOV A,M OUT SECBFP;HDR2 INX H MOV A,M OUT SECBFP;HDR3 INX H MOV A,M OUT SECBFP;HDR4 RET ; ULDADO: OUT STATPT;RESET SECTOR BUFFER ADDRESS LXI H,ISBUFF IN SECBFP;HDR1 MOV M,A IN SECBFP;HDR2 INX H MOV M,A IN SECBFP;HDR3 INX H MOV M,A IN SECBFP;HDR4 INX H MOV M,A RET ; ;COMPARE HEADERS (4) ONLY (ADDRESS) CPADDO: MVI C,04H LXI H,ISBUFF LXI D,OSBUFF HDRCMP: LDAX D CMP M JNZ CMPERR;COMPARE ERROR INX D INX H DCR C JNZ HDRCMP RET ; INCHD: LDA EHD LXI H,XHD MOV D,M CMP D RZ INR D MOV M,D RET ; INCYL: LDA ECYL LXI H,XCYL MOV D,M INX H MOV E,M CMP D JZ LSCCHK;JMP IF = AND CHK THE LSB DOINCC: INX D MOV M,E DCX H MOV M,D RET LSCCHK: LDA ECYL + 1 CMP E JNZ DOINCC RET ; INSECT: LDA ESECT LXI H,XSECT MOV D,M CMP D RZ INR D MOV M,D RET ; SWAPS: LDA SCYL;MSB STA XCYL;MSB LDA SCYL + 1;LSB STA XCYL + 1;LSB LDA SHD STA XHD LDA SSECT STA XSECT RET ; SWAPE: LDA ECYL;MSB STA XCYL;MSB LDA ECYL + 1;LSB STA XCYL + 1;LSB LDA EHD STA XHD LDA ESECT STA XSECT RET ; ;RE-INITILIZE CYL,HD,SEC,DATA REINIT: LDA SCYL;INIT STARTING CYLINDER (MSB) STA XCYL LDA SCYL + 1;INIT START CYLINDER (LSB) STA XCYL + 1 LDA SHD;INIT STARTING HD STA XHD LDA SSECT;INIT STARTING SECTOR STA XSECT LDA SDATA;INIT STARTING DATA STA XDATA RET ; ; * * * MAIN ROUTINES * * * ; WRCMD: CALL SELEC CALL SELHD CALL SELCYL CALL SETSEC CALL LDSECB CALL GDSTWR JMP BBASIC;BACK TO BASIC WHEN DONE ; RDCMD: CALL SELEC CALL SELHD CALL SELCYL CALL SETSEC CALL GDSTRD CALL UNLDSB JMP BBASIC;BACK TO BASIC WHEN DONE ; WRRDCP: WRITE: CALL SELEC CALL SELHD CALL SELCYL CONTC: CALL SETSEC CALL LDSECB CALL GDSTWR CALL INSECT JNZ CONTC LDA SSECT;RESET SECTOR, NEXT HEAD STA XSECT CALL INCHD JNZ WRITE LDA SSECT;RESET SECTOR, NEXT CYL STA XSECT LDA SHD;RESET HEAD, NEXT CYL STA XHD CALL INCYL JNZ WRITE ; ;RE-INITILIZE STARTING CYL,HD,SEC,DATA (READ VERIFY) CALL REINIT ; READ: CALL SELEC CALL SELHD CALL SELCYL CONTD: CALL SETSEC CALL GDSTRD CALL UNLDSB CALL COMPSB CALL INSECT JNZ CONTD LDA SSECT;RESET SECTOR, NEXT HEAD STA XSECT CALL INCHD JNZ READ LDA SSECT;RESET SECTOR, NEXT CYL STA XSECT LDA SHD;RESET HEAD, NEXT CYL STA XHD CALL INCYL JNZ READ JMP BBASIC;BACK TO BASIC WHEN DONE ; OSCSEK: CALL DOITOS LDA XPRGCNT + 1;LSB OF MISC. COUNTER DCR A STA XPRGCNT + 1;LSB JZ BBASIC;BACK TO BASIC WHEN DONE CALL SWAPE;EXCHANGE STARTING HEADER WITH ENDING HEADER CALL DOITOS LDA XPRGCNT + 1;LSB DCR A STA XPRGCNT + 1;LSB JZ BBASIC;BACK TO BASIC WHEN DONE CALL SWAPS;EXCHANGE ENDING HEADER WITH STARTING HEADER CALL DOITOS JMP OSCSEK DOITOS: CALL SELEC CALL SELHD CALL SELCYL CALL SETSEC CALL GDSTRD CALL ULDADO CALL CPADDO RET ; ;FORMAT FORMAT: FORMWT: CALL SELEC CALL SELHD CALL SELCYL CONTA: CALL SETSEC CALL LDADDO CALL GDSTWR CALL INSECT JNZ CONTA LDA SSECT;RESET SECTOR, NEXT HEAD STA XSECT CALL INCHD JNZ FORMWT LDA SSECT;RESET SECTOR, NEXT CYL STA XSECT LDA SHD;RESET HEAD, NEXT CYL STA XHD CALL INCYL JNZ FORMWT JMP BBASIC;BACK TO BASIC WHEN DONE ; ;VERIFY FORMAT VERIFY: CALL SELEC CALL SELHD CALL SELCYL CONTB: CALL SETSEC CALL LDADDO CALL GDSTRD CALL ULDADO CALL CPADDO CALL INSECT JNZ CONTB LDA SSECT;RESET SECTOR, NEXT HEAD STA XSECT CALL INCHD JNZ VERIFY LDA SSECT;RESET SECTOR, NEXT CYL STA XSECT LDA SHD;RESET HEAD, NEXT CYL STA XHD CALL INCYL JNZ VERIFY JMP BBASIC;BACK TO BASIC WHEN DONE ;