;::::::::::::::::::::::::::::::::::::::::::::::::************************** ; Hard disk routines as implemented for ** Hardware Dependent ** ; SIMH Altair80 ** for exact interface ** ; D-X Designs Pty Ltd P112. ************************** ;-------------------------------------------------------------------------- ; This file uses modifications of the definitions in ICFG-xx to reflect ; Physical and/or logical definitions for HBIOS drives. A controller type of ; 8xH signifies IDE/ATA drives, in which case the Drive byte at HDRVx is: ; 7 6 5 4 3 2 1 0 ; | | | | | | | +- Unit Number (0 = Master, 1 = Slave) ; | | | | +-+-+--- (reserved) ; | | | +--------- 1 = Active, 0 = Inactive ; +-+-+----------- (reserved) ; Additionally, the first byte of the Reduced Write Cylinder word is re- ; defined to be the number of physical/logical Sectors-Per-Track. ; These parameters are used to convert the Track & 16 Sector/Track format ; assumed in the B/P Bios definitions for Hard Drives into Track/Sector/Head ; Sector Number needed for IDE/ATA Data accesses. Direct driver IO routines ; to Select (SELHD), Read (HDREAD) and Write (HDWRIT) are all included here. ;-------------------------------------------------------------------------- ; 1.0 - 26 Aug 01 - Cleaned up source and included fixes from SCSI. HFB ; 0.2 - 28 Jun 97 - Added Home Drive, Retry Disable bit handling. HFB ; 0.1 - 25 Apr 97 - Initial Test Release HFB ;*************************************************************************** IF BANKED COMMON /BANK2/ ELSE CSEG ENDIF ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; Function 0 - Set User Data Area Adress for Direct Disk IO, Return ; Number of Bytes in the driver Command Block (SCSI-"like") ; For IDE, a minimum of 6 Bytes is needed (Comnd,Trk(2),Sctr,Head,Drive) ; Enter: DE = Address of User Data Area ; Exit : A = Number of bytes available in the Command Block ; Uses : A,HL ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: HDVALS: LD (DATADR),DE ; Save the Users Data Area LD A,CMDSIZ RET ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; Function 1 - Set Drive bit Command Block from A ; Enter: A = Drive Byte ; Exit : A = Drive Bit in LSB (00/01H, for Master/Slave) ; Uses : AF ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: HDSLCT: AND 01H ; Strip any garbage LD (hdUnit),A ; save in Command Block RET ;::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; Function 2 - Direct SCSI driver. This routine performs the function ; described by the command in the HD Command Block with Data area ; addressed by DE. At the end of the function, 512 bytes of data are ; transferred from the Bios IO Buffer to the Users Space set by Fcn 0. ; ; Enter: DE = Pointer to User Command Descriptor Block ; HDCOMD contains pre-filled SCSI Command Block ; A = 0 if No Data to be Written, FF if User-supplied data to write ; Exit : H = Message Byte value ; L = Status Byte value ; A = Status byte, Flags set accordingly. ; Uses : AF,BC,DE,HL ; NOTE : Routine assumes the Command Block is properly configured for the ; desired function and device. Errors in phasing result in program ; exit and Warm Boot function, while Timeout returns 0FFH. ; For external access, It assumes the user has used Functions 0 and 1 to ; set the data transfer source/dest address and logical & physical drive. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: HD_RW: CALL PANIC ; NOT IMPLEMENTED!!!! RET ;======================================================================== ; Select Hard Disk (Unit 0/1, Master/Slave) < Internal Bios routine > SELHD: ; SET DEVICE LD A,(SEKPDN) LD (HDSK_DEVICE),A JP SETPARMS ; then set parameters for DPH/DPB ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; Write to Hard Disk Drive < Internal BIOS Routine > ; Writes from HSTBUF using HSTTRK and HSTSEC to build Block Number. ; NOTE: This routine uses physical drive characteristics from ICFG-xx. HDWRIT: XOR A LD (HSTACT),A ; Show no active writes pending JP HDSK_WRITE ; ..continue ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ; Read from Hard Disk Drive < Internal BIOS Routine > ; Reads to HSTBUF using HSTTRK and HSTSEC to build Block Number. ; NOTE: This routine uses physical drive characteristics from ICFG-xx. ; The routine computes a sequential block number (as with SCSI) with ; the algorithm; Trk * 16 + Sector, then computes Head, Sector and Track ; using Physical characteristics (hdHds = Number_of_Heads, ; hdSPT = Sectors_per_Track) according to the algorithm: ; ; Sector := (Block# MOD hdSPT)+1 (* Quotient1 := Block# DIV hdSPT *) ; Head := Quotient1 MOD hdHds (* Quotient2 := Quotient1 DIV hdHds *) ; Track := Quotient2 HDREAD: JP HDSK_READ IF BANKED COMMON /B2RAM/ ELSE DSEG ENDIF HRTrys: DEFS 1 ; Retry counter storage hdUnit: DEFS 1 ; IDE Drive (0 = Master, 1 = Slave) hdTrks: DEFS 2 ; Number of Tracks on IDE Drive hdHds: DEFS 1 ; Number of Heads on IDE Drive hdSPT: DEFS 1 ; Number of Sectors-Per-Track on IDE Drive ; IDE Command Block for User Direct Driver Access hdComd: DEFS 1 ; Command Byte hdBMap: DEFS 1 ; Bit Map (B6..0) of Following Bytes to Set hdHead: DEFS 1 ; Head Number/Number of Heads in B3..0 hdTrkH: DEFS 1 ; Hi-Track (Cylinder) Byte hdTrkL: DEFS 1 ; Lo-Track (Cylinder) Byte hdSec: DEFS 1 ; Sector Number hdSCnt: DEFS 1 ; Sector Count hdErr: DEFS 1 ; Error Reg Value hdDigO: DEFS 1 ; Digital Output Reg Value CMDSIZ EQU $-hdComd ; Size of Command Block DATADR: DEFS 2 ; Pointer to User Buffer Space (user bank) IF NOWAIT ;WTSAVE: DEFS 1 ; Storage for Entry Wait State Setting ENDIF ;======================= End of HARDIDE =========================== IF BANKED COMMON /BANK2/ ELSE CSEG ENDIF ; ;================================================================================================== ; HDSK DISK DRIVER ;================================================================================================== ; ; IO PORT ADDRESSES ; HDSK_IO EQU 0FDH ; HDSK_CMDNONE EQU 0 HDSK_CMDRESET EQU 1 HDSK_CMDREAD EQU 2 HDSK_CMDWRITE EQU 3 HDSK_CMDPARAM EQU 4 ; ; STATUS ; HDSKRC_OK EQU 0 ; ; ; HDSK_READ: ; CALL PRTSTRD ; DEFB '[HDSK READ]$' LD A,HDSK_CMDREAD JR HDSK_RW ; ; ; HDSK_WRITE: ; CALL PRTSTRD ; DEFB '[HDSK WRITE]$' LD A,HDSK_CMDWRITE JR HDSK_RW ; ; ; HDSK_RW: LD (HDSK_CMD),A ; CLEAR RESULTS XOR A ; A = 0 LD (HDSK_RC),A ; CLEAR RETURN CODE ; INIT IF NEEDED LD A,(HDSK_STAT) ; GET CURRENT STATUS OR A ; SET FLAGS CALL NZ,HDSK_RESET ; RESET IF NOT READY ; ; SET SECTOR (IGNORES MSB) ; LD A,(HSTSEC) ; LD (HDSK_SEC),A ; ; SET TRACK ; LD BC,(HSTTRK) ; LD (HDSK_TRK),BC ; BPBIOS DEFINES 16 SECTORS PER TRACK ; CONVERT TO 256 SECTORS PER TRACK FOR SIMH DEFINITION ; FIRST, DIVIDE TRACKS BY 16 SAVING REMAINDER IN TOP NIBBLE OF A LD HL,(HSTTRK) XOR A ; CLEAR A LD B,4 ; ROTATE 4 BITS TO DIVIDE BY 4 HDSK_RW0: SRL H RR L RR A DJNZ HDSK_RW0 LD (HDSK_TRK),HL ; SAVE MODIFIED TRACK FOR HDSK I/O CALL LD HL,HSTSEC ; POINT TO INCOMING SECTOR OR (HL) ; COMBINE WITH SECTOR VALUE PASSED IN LD (HDSK_SEC),A ; SAVE IT FOR HDSK I/O CALL ; SET TRANSFER ADDRESS LD BC,HSTBUF LD (HDSK_DMA),BC ; EXECUTE COMMAND LD B,7 ; SIZE OF PARAMETER BLOCK LD HL,HDSK_PARMBLK ; START ADDRESS OF PARAMETER BLOCK HDSK_RW1: LD A,(HL) ; GET BYTE OF PARAMETER BLOCK OUT (0FDH),A ; SEND IT TO PORT INC HL ; POINT TO NEXT BYTE DJNZ HDSK_RW1 IN A,(0FDH) ; GET RESULT CODE LD (HDSK_RC),A OR A JR Z,HDSK_OK JR HDSK_ERR HDSK_ERR: XOR A DEC A ; A=$FF TO SIGNAL ERROR LD (HDSK_STAT),A ; SAVE IT RET HDSK_OK: XOR A RET ; ; ; HDSK_RESET: LD B,32 LD A,HDSK_CMDRESET HDSK_RESET1: OUT (0FDH),A DJNZ HDSK_RESET1 XOR A ; STATUS = OK LD (HDSK_STAT),A ; SAVE IT RET ; ;================================================================================================== ; HDSK DISK DRIVER - DATA ;================================================================================================== ; IF BANKED COMMON /B2RAM/ ELSE DSEG ENDIF HDSK_STAT DEFB 0 HDSK_RC DEFB 0 ; HDSK_PARMBLK: HDSK_CMD DEFB 0 ; COMMAND (HDSK_READ, HDSK_WRITE, ...) HDSK_DEVICE DEFB 0 ; 0..7, HARD DISK UNIT HDSK_SEC DEFB 0 ; 0..255 SECTOR HDSK_TRK DEFW 0 ; 0..2047 TRACK HDSK_DMA DEFW 0 ; DEFINES WHERE RESULT IS PLACED IN MEMORY