|
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 - 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»