|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 11392 (0x2c80)
Types: TextFile
Names: »HARDDSK.MAC«
└─⟦72577d508⟧ Bits:30003297 Diverse BIOS typer til RC703
└─⟦this⟧ »HARDDSK.MAC«
SUBTTL WINCHESTER DISK DRIVER
;==============================================================================
;= HARD DISK PHYSICAL WRITE (MEMORY => DISK) =
;==============================================================================
;
HWRHST: CALL CHKPOS ; CHECK HEAD POSISTION
CALL NC,STSKFL ; IF: HEAD POSISTION NOT OK
CALL WDCRDY ; THEN: SET UP TASK FILE TO WD1000
RET NC ; ELSE:
LD HL,(FORM) ; IF: WD1000 NOT READY
LD C,(HL) ; THEN: END
INC HL ; ELSE: GET CURRENT FORMAT TABLE ADDRESS
LD B,(HL) ; GET DMA XFER. COUNT
CALL DMA0RD ; SET UP DMA READ (MEM => DISK)
LD A,WRTCMD ;
OUT (HCMDRG),A ; ELSE: ISSUE WRITE COMMAND
CALL WAITHD ; AWAIT COMPLETION
RET ; END
;==============================================================================
;= HARD DISK PHYSICAL READ (DISK => MEMORY) =
;==============================================================================
;
HRDHST: CALL CHKPOS ; CHECK HEAD POSISTION
CALL NC,STSKFL ; IF: HEAD POSISTION NOT OK
CALL WDCRDY ; THEN: SET UP TASK FILE TO WD1000
RET NC ; ELSE:
LD HL,(FORM) ; IF: WD1000 NOT READY
LD C,(HL) ; THEN: END
INC HL ; ELSE: GET CURRENT FORMAT TABLE ADDRESS
LD B,(HL) ; GET DMA XFER. COUNT
CALL DMA0WR ; SET UP DMA READ (DISK => MEM)
LD A,RDCMD ;
OUT (HCMDRG),A ; ELSE: ISSUE READ COMMAND
CALL WAITHD ; AWAIT COMPLETION
RET ; END
PAGE
;==============================================================================
;= CHECK DISK HEAD POSISTION =
;==============================================================================
;
CHKPOS: LD HL,HSTBUF ; INIT. XFER ADR. WITH HOST BUFFER
LD (DSKAD),HL ;
LD A,(HSTDSK) ;
LD HL,LSTDSK ; IF: HOST_DISK:=LAST_DISK
CP (HL) ; THEN:
JP NZ,CHKP10 ;
LD A,(HSTTRK) ;
LD HL,LSTTRK ; IF: HOST_TRACK:=LAST_TRACK
CP (HL) ; THEN: RESET CARRY FLAG
JP NZ,CHKP10 ; END
LD A,(HSTTRK+1) ; ELSE:
INC HL ;
CP (HL) ; ELSE:
JP NZ,CHKP10 ;
AND A ;
RET ;
CHKP10: LD A,(HSTDSK) ;
LD (LSTDSK),A ; LAST_DISK:=HOST_DISK
LD HL,(HSTTRK) ;
LD (LSTTRK),HL ; LAST_TRACK:=HOST_TRACK
CALL STSKFL ; SET UP TASK FILE
CALL HDSEEK ; POSITION HEADS
JP NC,CHKP30 ; IF: SEEK COMMAND ISSUED
CALL WAITHD ; THEN: AWAIT COMPLETION
CHKP20: IN A,(HDSTRG) ; READ STATUS REGISTER
AND 10H ; AWAIT SEEK COMPLETION
JP Z,CHKP20 ;
CHKP30: SCF ; ELSE: SET CARRY FLAG
RET ; END
PAGE
;==============================================================================
;= SET UP TASK FILE TO WD1000 =
;==============================================================================
;
STSKFL: LD HL,(FORM) ; GET CURRENT FORMAT TABLE ADR.
LD DE,-1 ;
EX DE,HL ;
ADD HL,DE ; GET ADR. OF END_OF_PAGE
XOR A ; INIT. HEAD NO.
LD C,(HL) ; GET END_OF_PAGE
LD B,00H ;
LD HL,(HSTSEC) ; GET SECTOR NO.
STSK10: AND A ;
SBC HL,BC ; A:=HEAD_NO:=INT(HOST_SECTOR/END_OF_PAGE)
JP C,STSK20 ;
INC A ; HL:=SECTOR:=HOST_SECTOR-HEAD_N0*END_OF_PAGE
JP STSK10 ;
STSK20: ADD HL,BC ;
LD C,A ; save head_number
LD A,L ;
OUT (HSECNO),A ;
LD HL,(LSTTRK) ; if track_number <> 0 and rodime_202
LD A,H ; then
OR L ; set ecc_flag (error correction)
JR Z,STSK40 ; in sdh-register (size,drive,head)
LD A,(R202_FLG) ;
OR A ;
JR Z,STSK40 ;
SET 7,C ;
STSK40: LD A,C ;
LD HL,5 ;
ADD HL,DE ; GET ADR. OF SECTOR SIZE IN FORMAT TABLE
OR (HL) ; LOGICAL OR SECTOR SIZE ON
OUT (HSZDHD),A ; INIT. SIZE, DISK AND HEAD NO. IN TASK FILE
LD HL,(LSTTRK) ; GET TRACK NO.
LD A,L ;
OUT (HCYLLO),A ; INIT. CYLINDER LOW IN TASK FILE
LD A,H ;
AND 3 ; MASK OF 5 MSB BITS
OUT (HCYLHI),A ; INIT. CYLINDER HIGH IN TASK FILE
LD HL,6 ;
ADD HL,DE ; GET WRITE PRECOMP ADR. IN FORMAT TABLE
LD A,(HL) ;
OUT (HWPCMP),A ; INIT. WRITE PRECOMP IN TASK FILE
RET ; END
PAGE
;==============================================================================
;= HARD DISK SEEK ROUTINE =
;==============================================================================
;
HDSEEK: LD HL,(FORM) ; GET CURRENT FORMAT TABLE ADR.
LD DE,5 ;
ADD HL,DE ; GET ADR. OF DISK STEP RATE
LD A,SEEKCM ; LOGICAL OR SEEK CMD. WITH STEP RATE
OR (HL) ;
CALL WDCRDY ; IF: WD CONTROLLER READY
RET NC ; THEN: END
OUT (HCMDRG),A ; ELSE: ISSUE SEEK COMMAND
SCF ; SET CARRY FLAG
RET ; END.
;==============================================================================
;= WAIT FOR HARD DISK INTERRUPT. RETURN RESULT =
;==============================================================================
; EXIT: A = error flag (0=ok)
; B = copy of wdc error register
; C = copy of wdc status register
WAITHIT:CALL WAITHD ; wait for hard disk interrupt
PUSH HL ;
LD HL,ERFLAG ;
LD A,(HL) ; save error flag in A
LD (HL),0 ; reset error flag
POP HL ;
LD BC,(MHDTSR) ; save wd1001 status and error registers
RET ;
;==============================================================================
;= AWAIT COMPLETION OF HARD DISK OPERATION =
;==============================================================================
;
WAITHD: LD A,(HD_FLG) ; AWAIT HARD DISK INT.
OR A ;
JP Z,WAITHD ;
XOR A ; RESET FLAG
LD (HD_FLG),A ;
RET ; END
PAGE
;==============================================================================
;= CHECK WD1000 FOR READY TO ACCEPT NEW COMMAND =
;==============================================================================
;
WDCRDY: PUSH AF ; SAVE REGISTERS
IN A,(HDSTRG) ; READ WD STATUS REG.
AND 50H ; MASK OF READY,SEEK COMP. AND WRITE FAULT
CP 50H ; TEST FOR READY AND SEEK COMP. IS TRUE
JP Z,WDCR10 ; AND WRITE FAULT IS FALSE
LD A,0BBH ; IF: NOT O.K.
LD (ERFLAG),A ; THEN: SET ERROR FLAG
POP AF ; RESTORE REGISTERS
AND A ; RESET CARRY FLAG TO INDICATE NOT READY
RET ; END
WDCR10: POP AF ; ELSE: RESTORE REGISTERS
SCF ; SET CARRY FLAG TO INDICATE READY
RET ; END
PAGE
;==============================================================================
;= INITIALIZE DMA CHANNEL 0 TO WRITE (DISK => MEMORY) =
;==============================================================================
;
DMA0WR: LD A,04H ;
DI ;
OUT (DMAMAS),A ; SET CHANNEL 0 MASK
LD A,44H ; MODE:=WRITE
JP DMA010 ; GOTO DMA0 LABEL 10
;==============================================================================
;= INITIALIZE DMA CHANNEL 0 TO READ (MEMORY => DISK) =
;==============================================================================
;
DMA0RD: LD A,04H ;
DI ;
OUT (DMAMAS),A ; SET CHANNEL 0 MASK
LD A,48H ; MODE:=READ
DMA010: OUT (DMAMOD),A ; SELECT DMA MODE
OUT (DMACBC),A ; CLEAR BYTE POINTER
LD A,(DSKAD) ;
OUT (DMAAD0),A ; SET LOW ADDRESS
LD A,(DSKAD+1) ;
OUT (DMAAD0),A ; SET HIGH ADDRESS
LD A,C ;
OUT (DMACN0),A ; SET LOW COUNT
LD A,B ;
OUT (DMACN0),A ; SET HIGH COUNT
LD A,00H ;
OUT (DMAMAS),A ; CLEAR CHANNEL 0 MASK
EI ;
RET ; END
PAGE
;==============================================================================
;= WD1000 HARD DISK RESTORE ROUTINE =
;= DESCRIPTION: THE RESTORE ROUTINE PERFORMS A RESTORE OF THE R/W HEADS =
;= (POSITIONS TO TRACK 0) =
;= ENTRY: A:= SIZE/DRIVE/HEAD =
;= B:= STEPPING RATE =
;= =
;= THE ROUTINE IS USED IN THE COLD START. =
;==============================================================================
HRDRST: OUT (HSZDHD),A ; OUTPUT SIZE/DRIVE/HEAD
XOR A ; A=0
OUT (HWPCMP),A ;
OUT (HSECCT),A ;
OUT (HSECNO),A ;
OUT (HCYLLO),A ;
OUT (HCYLHI),A ;
LD A,10H ; RESTORE COMMAND
OR B ; ADD STEPPING RATE
OUT (HCMDRG),A ; OUTPUT RESTORE COMMAND
RET ; RETURN
PAGE
;==============================================================================
;= WD1000 HARD DISK FORMAT ROUTINE. =
;= =
;= DESCRIPTION: THE FORMAT ROUTINE FORMATS ONE TRACK, SPECIFIED BY =
;= THE FOLLOWING PARAMETERS. =
;= =
;= ENTRY: A:= SIZE/DRIVE/HEAD =
;= B:= WRITE PRECOMPRESED =
;= C:= SECTOR COUNT =
;= D:= CYLINDER HIGH =
;= E:= CYLINDER LOW =
;= DMAADR:= POINTER TO FORMAT INFORMATIONS =
;= =
;= EXIT: A:= 0 => FORMAT OK. A:= 1 => FORMAT ERROR =
;= =
;==============================================================================
;
HRDFMT: OUT (HSZDHD),A ; INIT. SIZE/DRIVE/HEAD
LD A,B ;
OUT (HWPCMP),A ; INIT. WRITE PRECOMPRESED
LD A,C ;
OUT (HSECCT),A ; INIT. SECTOR COUNT
LD A,E ;
OUT (HCYLLO),A ; INIT. CYLINDER LOW
LD A,D ;
OUT (HCYLHI),A ; INIT. CYLINDER HIGH
LD HL,(DMAADR) ;
LD (DSKAD),HL ; INIT. DMA XFER ADR.
CALL WDCRDY ; IF: WD1000 READY
JP NC,HRDF10 ; THEN: SET UP DMA0 TO READ (MEM => DISK)
LD BC,511 ; INIT. DMA XFER. COUNT
CALL DMA0RD ;
LD A,FMTCMD ;
OUT (HCMDRG),A ; ISSUE FORMAT COMMAND
CALL WAITHD ; AWAIT COMPLETION
LD A,(ERFLAG) ;
AND A ; IF: FORMAT OK.
RET Z ; THEN: END
HRDF10: XOR A ; ELSE:
LD (ERFLAG),A ; ELSE: RESET ERROR FLAG
LD A,1 ; SIGNAL ERROR TO CALLER
RET
PAGE
;==============================================================================
;= WD1000 HARD DISK CONTROLLER INTERRUPT ROUTINE =
;==============================================================================
;
HDITR: LD (SP_SAV),SP ; SAVE OLD STACK POINTER
LD SP,ISTACK ; INIT. NEW STACK POINTER
PUSH AF ;
PUSH BC ; SAVE REGISTERS
PUSH DE ;
PUSH HL ;
LD A,0FFH ;
LD (HD_FLG),A ; HD_BUSY_FLAG:=FALSE
IN A,(HDSTRG) ; READ STATUS
LD (MHDTSR),A ; UPDATE MIRROW
AND 01H ;
JP Z,HDIT10 ; IF: ERROR
IN A,(HDERRG) ; THEN: READ ERROR REG.
LD (MHDERR),A ; UPDATE MIRROW
LD HL,(HERRCT) ;
INC HL ; ERROR_COUNT:=ERROR_COUNT+1
LD (HERRCT),HL ;
LD A,0BBH ;
LD (ERFLAG),A ; SET ERROR FLAG
HDIT10: POP HL ; ELSE:
POP DE ;
POP BC ; RESTORE REGISTERS
POP AF ;
LD SP,(SP_SAV) ; RESTORE STACK POINTER
EI ;
RETI ; END
PAGE
«eof»