mirror of
https://github.com/microsoft/MS-DOS.git
synced 2024-11-29 09:05:46 +00:00
1377 lines
44 KiB
NASM
1377 lines
44 KiB
NASM
|
TITLE IO.SYS for the ALTOS ACS-86C.
|
|||
|
|
|||
|
; I/O system for Version 2.x of MSDOS.
|
|||
|
|
|||
|
;This BIOS designed to be linked with the SYSINIT module provided by
|
|||
|
;Microsoft
|
|||
|
|
|||
|
BIOSIZ EQU 4096 ;Size of BIOS in bytes.
|
|||
|
BIOSIZS EQU 100H ;Size of BIOS in Paragraphs.
|
|||
|
ANSI EQU 0 ;Ansi switch.
|
|||
|
|
|||
|
;Additional Information for the ALTOS machine.
|
|||
|
|
|||
|
QSIZE EQU 100 ;Input queue size.
|
|||
|
BIOSSEG EQU 0C0H ;I/O system segment.
|
|||
|
MAX_MEM EQU 4000H ;Memory size in paragraphs.
|
|||
|
|
|||
|
; Constants for commands in Altos ROM.
|
|||
|
|
|||
|
ROM_CONSTA EQU 01 ;Return status AL of console selected in CX.
|
|||
|
ROM_CONIN EQU 02 ;Get char. from console in CX to AL
|
|||
|
ROM_CONOUT EQU 03 ;Write char. in DL to console in CX.
|
|||
|
ROM_PMSG EQU 07 ;Write string ES:DX to console in CX.
|
|||
|
ROM_DISKIO EQU 08 ;Perform disk I/O from IOPB in ES:CX.
|
|||
|
ROM_INIT EQU 10 ;Returns boot console and top memory ES:DX.
|
|||
|
|
|||
|
;Things needed to communicate with SYSINIT
|
|||
|
|
|||
|
EXTRN SYSINIT:FAR ;The entry point of SYSINIT
|
|||
|
EXTRN CURRENT_DOS_LOCATION:WORD ;Where the DOS is when SYSINIT called
|
|||
|
EXTRN FINAL_DOS_LOCATION:WORD ;Where I want SYSINIT to put the DOS
|
|||
|
EXTRN DEVICE_LIST:DWORD ;Pointer to the DEVICE list.
|
|||
|
EXTRN MEMORY_SIZE:WORD ;Size in paragraphs of Physical memory.
|
|||
|
EXTRN DEFAULT_DRIVE:BYTE ;Default Drive to use when system booted
|
|||
|
EXTRN BUFFERS:BYTE ;Number of default buffers.
|
|||
|
; Leave as is and SYSINIT uses only 2.
|
|||
|
|
|||
|
CODE SEGMENT
|
|||
|
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
|
|||
|
|
|||
|
ORG 0 ;Starts at an offset of zero.
|
|||
|
|
|||
|
INIT: JMP HWINIT
|
|||
|
|
|||
|
PAGE
|
|||
|
|
|||
|
SUBTTL Device driver tables.
|
|||
|
|
|||
|
;-----------------------------------------------+
|
|||
|
; DWORD pointer to next device | 1 word offset.
|
|||
|
; (-1,-1 if last device) | 1 word segement.
|
|||
|
;-----------------------------------------------+
|
|||
|
; Device attribute WORD ; 1 word.
|
|||
|
; Bit 15 = 1 for chacter devices. ;
|
|||
|
; 0 for Block devices. ;
|
|||
|
; ;
|
|||
|
; Charcter devices. (Bit 15=1) ;
|
|||
|
; Bit 0 = 1 current sti device. ;
|
|||
|
; Bit 1 = 1 current sto device. ;
|
|||
|
; Bit 2 = 1 current NUL device. ;
|
|||
|
; Bit 3 = 1 current Clock device. ;
|
|||
|
; ;
|
|||
|
; Bit 13 = 1 for non IBM machines. ;
|
|||
|
; 0 for IBM machines only. ;
|
|||
|
; Bit 14 = 1 IOCTL control bit. ;
|
|||
|
;-----------------------------------------------+
|
|||
|
; Device strategy pointer. ; 1 word offset.
|
|||
|
;-----------------------------------------------+
|
|||
|
; Device interrupt pointer. ; 1 word offset.
|
|||
|
;-----------------------------------------------+
|
|||
|
; Device name field. ; 8 bytes.
|
|||
|
; Character devices are any valid name ;
|
|||
|
; left justified, in a space filled ;
|
|||
|
; field. ;
|
|||
|
; Block devices contain # of units in ;
|
|||
|
; the first byte. ;
|
|||
|
;-----------------------------------------------+
|
|||
|
|
|||
|
DEVSTART LABEL WORD
|
|||
|
CONDEV: ;Header for device CON
|
|||
|
DW AUXDEV,BIOSSEG ;Link to next device
|
|||
|
DW 8003H ;Attributes - console input, output device
|
|||
|
DW STRATEGY ;Srategy entry point
|
|||
|
DW CON_INT ;Interrupt entry point
|
|||
|
DB "CON " ;Device name
|
|||
|
|
|||
|
AUXDEV: ;Header for device AUX
|
|||
|
DW PRNDEV,BIOSSEG
|
|||
|
DW 8000H
|
|||
|
DW STRATEGY
|
|||
|
DW AUX_INT
|
|||
|
DB "AUX "
|
|||
|
|
|||
|
PRNDEV: ;Header for device PRN
|
|||
|
DW TIMDEV,BIOSSEG
|
|||
|
DW 8000H
|
|||
|
DW STRATEGY
|
|||
|
DW PRN_INT
|
|||
|
DB "PRN "
|
|||
|
|
|||
|
TIMDEV: ;Header for device CLOCK
|
|||
|
DW DSKDEV,BIOSSEG
|
|||
|
DW 8008H
|
|||
|
DW STRATEGY
|
|||
|
DW TIM_INT
|
|||
|
DB "CLOCK "
|
|||
|
|
|||
|
DSKDEV: ;Header for disk devices
|
|||
|
DW -1,-1 ;Last device
|
|||
|
DW 2000H ;Is a block device
|
|||
|
DW STRATEGY
|
|||
|
DW DSK_INT
|
|||
|
DRVMAX DB 1 ;Number of Units
|
|||
|
DB 7 DUP (?)
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Dispatch tables for each device.
|
|||
|
|
|||
|
DSKTBL: DW DSK_INIT ;0 - Initialize Driver.
|
|||
|
DW MEDIAC ;1 - Return current media code.
|
|||
|
DW GET_BPB ;2 - Get Bios Parameter Block.
|
|||
|
DW CMDERR ;3 - Reserved. (currently returns error)
|
|||
|
DW DSK_RED ;4 - Block read.
|
|||
|
DW BUS_EXIT ;5 - (Not used, return busy flag)
|
|||
|
DW EXIT ;6 - Return status. (Not used)
|
|||
|
DW EXIT ;7 - Flush input buffer. (Not used.)
|
|||
|
DW DSK_WRT ;8 - Block write.
|
|||
|
DW DSK_WRV ;9 - Block write with verify.
|
|||
|
DW EXIT ;10 - Return output status.
|
|||
|
DW EXIT ;11 - Flush output buffer. (Not used.)
|
|||
|
DW EXIT ;12 - IO Control.
|
|||
|
|
|||
|
CONTBL: DW EXIT ;0 - Init. (Not used)
|
|||
|
DW EXIT ;1 - Media check (Not used)
|
|||
|
DW EXIT ;2 - Get Bios Parameter Block (Not used)
|
|||
|
DW CMDERR ;3 - Reserved. (Currently returns error)
|
|||
|
DW CON_READ ;4 - Character read. (Destructive)
|
|||
|
DW CON_RDND ;5 - Character read. (Non-destructive)
|
|||
|
DW EXIT ;6 - Return status. (Not used)
|
|||
|
DW CON_FLSH ;7 - Flush Input buffer.
|
|||
|
DW CON_WRIT ;8 - Character write.
|
|||
|
DW CON_WRIT ;9 - Character write with Verify.
|
|||
|
DW CON_WRST ;10 - Character write status.
|
|||
|
DW EXIT ;11 - Flush output buffer. (Not used.)
|
|||
|
DW EXIT ;12 - IO Control.
|
|||
|
|
|||
|
AUXTBL: DW EXIT ;0 - Init. (Not used)
|
|||
|
DW EXIT ;1 - Media check (Not used)
|
|||
|
DW EXIT ;2 - Get Bios Parameter Block (Not used)
|
|||
|
DW CMDERR ;3 - Reserved. (Returns an error)
|
|||
|
DW AUX_READ ;4 - Character read. (Destructive)
|
|||
|
DW AUX_RDND ;5 - Character read. (Non-destructive)
|
|||
|
DW EXIT ;6 - Return status. (Not used)
|
|||
|
DW AUX_CLR ;7 - Flush Input buffer.
|
|||
|
DW AUX_WRIT ;8 - Character write.
|
|||
|
DW AUX_WRIT ;9 - Character write with verify.
|
|||
|
DW AUX_WRST ;10 - Character write status.
|
|||
|
DW EXIT ;11 - Flush output buffer. (Not used.)
|
|||
|
DW EXIT ;12 - IO Control.
|
|||
|
|
|||
|
TIMTBL: DW EXIT ;0 - Init. (Not used)
|
|||
|
DW EXIT ;1 - Media check (Not used)
|
|||
|
DW EXIT ;2 - Get Bios Parameter Block (Not used)
|
|||
|
DW CMDERR ;3 - Reserved. (Currently returns an error)
|
|||
|
DW TIM_RED ;4 - Character read. (Destructive)
|
|||
|
DW BUS_EXIT ;5 - (Not used, returns busy flag.)
|
|||
|
DW EXIT ;6 - Return status. (Not used)
|
|||
|
DW EXIT ;7 - Flush Input buffer. (Not used)
|
|||
|
DW TIM_WRT ;8 - Character write.
|
|||
|
DW TIM_WRT ;9 - Character write with verify.
|
|||
|
DW EXIT ;10 - Character write status. (Not used)
|
|||
|
DW EXIT ;11 - Flush output buffer. (Not used)
|
|||
|
DW EXIT ;12 - IO Control.
|
|||
|
|
|||
|
PRNTBL: DW EXIT ;0 - (Not used)
|
|||
|
DW EXIT ;1 - (Not used)
|
|||
|
DW EXIT ;2 - Block (Not used)
|
|||
|
DW CMDERR ;3 - Reserved. (currently returns error)
|
|||
|
DW EXIT ;4 - (Not used)
|
|||
|
DW BUS_EXIT ;5 - (Not used, returns busy flag.)
|
|||
|
DW EXIT ;6 - (Not used)
|
|||
|
DW EXIT ;7 - (Not used)
|
|||
|
DW PRN_WRT ;8 - Character write.
|
|||
|
DW PRN_WRT ;9 - Character write with verify.
|
|||
|
DW PRN_STA ;10 - Character write status.
|
|||
|
DW EXIT ;11 - (Not used.)
|
|||
|
DW EXIT ;12 - IO Control.
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Strategy and Software Interrupt routines.
|
|||
|
|
|||
|
;Define offsets for io data packet
|
|||
|
|
|||
|
IODAT STRUC
|
|||
|
CMDLEN DB ? ;LENGTH OF THIS COMMAND
|
|||
|
UNIT DB ? ;SUB UNIT SPECIFIER
|
|||
|
CMD DB ? ;COMMAND CODE
|
|||
|
STATUS DW ? ;STATUS
|
|||
|
DB 8 DUP (?)
|
|||
|
MEDIA DB ? ;MEDIA DESCRIPTOR
|
|||
|
TRANS DD ? ;TRANSFER ADDRESS
|
|||
|
COUNT DW ? ;COUNT OF BLOCKS OR CHARACTERS
|
|||
|
START DW ? ;FIRST BLOCK TO TRANSFER
|
|||
|
IODAT ENDS
|
|||
|
|
|||
|
PTRSAV DD 0 ;Strategy pointer save.
|
|||
|
|
|||
|
;
|
|||
|
; Simplistic Strategy routine for non-multi-Tasking system.
|
|||
|
;
|
|||
|
; Currently just saves I/O packet pointers in PTRSAV for
|
|||
|
; later processing by the individual interrupt routines.
|
|||
|
;
|
|||
|
|
|||
|
STRATP PROC FAR
|
|||
|
|
|||
|
STRATEGY:
|
|||
|
MOV WORD PTR CS:[PTRSAV],BX
|
|||
|
MOV WORD PTR CS:[PTRSAV+2],ES
|
|||
|
RET
|
|||
|
|
|||
|
STRATP ENDP
|
|||
|
|
|||
|
;
|
|||
|
; Console interrupt routine for processing I/O packets.
|
|||
|
;
|
|||
|
|
|||
|
CON_INT:
|
|||
|
PUSH SI
|
|||
|
MOV SI,OFFSET CONTBL
|
|||
|
JMP SHORT ENTRY
|
|||
|
|
|||
|
;
|
|||
|
; Auxilary interrupt routine for processing I/O packets.
|
|||
|
;
|
|||
|
|
|||
|
AUX_INT:
|
|||
|
PUSH SI
|
|||
|
MOV SI,OFFSET AUXTBL
|
|||
|
JMP SHORT ENTRY
|
|||
|
|
|||
|
;
|
|||
|
; Printer interrupt routine for processing I/O packets.
|
|||
|
;
|
|||
|
|
|||
|
PRN_INT:
|
|||
|
PUSH SI
|
|||
|
MOV SI,OFFSET PRNTBL
|
|||
|
JMP SHORT ENTRY
|
|||
|
|
|||
|
;
|
|||
|
; Clock interrupt routine for processing I/O packets.
|
|||
|
;
|
|||
|
|
|||
|
TIM_INT:
|
|||
|
PUSH SI
|
|||
|
MOV SI,OFFSET TIMTBL
|
|||
|
JMP SHORT ENTRY
|
|||
|
|
|||
|
;
|
|||
|
; Disk interrupt routine for processing I/O packets.
|
|||
|
;
|
|||
|
|
|||
|
DSK_INT:
|
|||
|
PUSH SI
|
|||
|
MOV SI,OFFSET DSKTBL
|
|||
|
|
|||
|
;
|
|||
|
; Common program for handling the simplistic I/O packet
|
|||
|
; processing scheme in MSDOS 2.0
|
|||
|
;
|
|||
|
|
|||
|
ENTRY: PUSH AX ;Save all nessacary registers.
|
|||
|
PUSH CX
|
|||
|
PUSH DX
|
|||
|
PUSH DI
|
|||
|
PUSH BP
|
|||
|
PUSH DS
|
|||
|
PUSH ES
|
|||
|
PUSH BX
|
|||
|
|
|||
|
LDS BX,CS:[PTRSAV] ;Retrieve pointer to I/O Packet.
|
|||
|
|
|||
|
MOV AL,[BX.UNIT] ;AL = Unit code.
|
|||
|
MOV AH,[BX.MEDIA] ;AH = Media descriptor.
|
|||
|
MOV CX,[BX.COUNT] ;CX = Contains byte/sector count.
|
|||
|
MOV DX,[BX.START] ;DX = Starting Logical sector.
|
|||
|
|
|||
|
XCHG DI,AX ;Move Unit & Media into DI temporarily.
|
|||
|
MOV AL,[BX.CMD] ;Retrieve Command type. (1 => 11)
|
|||
|
XOR AH,AH ;Clear upper half of AX for calculation.
|
|||
|
ADD SI,AX ;Compute entry pointer in dispatch table.
|
|||
|
ADD SI,AX
|
|||
|
CMP AL,11 ;Verify that not more than 11 commands.
|
|||
|
JA CMDERR ;Ah, well, error out.
|
|||
|
XCHG AX,DI ;Move Unit & Media back where they belong.
|
|||
|
LES DI,[BX.TRANS] ;DI contains addess of Transfer address.
|
|||
|
;ES contains segment.
|
|||
|
PUSH CS
|
|||
|
POP DS ;Data segment same as Code segment.
|
|||
|
JMP [SI] ;Perform I/O packet command.
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Common error and exit points.
|
|||
|
|
|||
|
BUS_EXIT: ;Device busy exit.
|
|||
|
MOV AH,00000011B ;Set busy and done bits.
|
|||
|
JMP SHORT EXIT1
|
|||
|
|
|||
|
CMDERR: MOV AL,3 ;Set unknown command error #.
|
|||
|
|
|||
|
;
|
|||
|
; Common error processing routine.
|
|||
|
; AL contains actual error code.
|
|||
|
;
|
|||
|
; Error # 0 = Write Protect violation.
|
|||
|
; 1 = Unkown unit.
|
|||
|
; 2 = Drive not ready.
|
|||
|
; 3 = Unknown command in I/O packet.
|
|||
|
; 4 = CRC error.
|
|||
|
; 5 = Bad drive request structure length.
|
|||
|
; 6 = Seek error.
|
|||
|
; 7 = Unknown media discovered.
|
|||
|
; 8 = Sector not found.
|
|||
|
; 9 = Printer out of paper.
|
|||
|
; 10 = Write fault.
|
|||
|
; 11 = Read fault.
|
|||
|
; 12 = General failure.
|
|||
|
;
|
|||
|
|
|||
|
ERR_EXIT:
|
|||
|
MOV AH,10000001B ;Set error and done bits.
|
|||
|
STC ;Set carry bit also.
|
|||
|
JMP SHORT EXIT1 ;Quick way out.
|
|||
|
|
|||
|
EXITP PROC FAR ;Normal exit for device drivers.
|
|||
|
|
|||
|
EXIT: MOV AH,00000001B ;Set done bit for MSDOS.
|
|||
|
EXIT1: LDS BX,CS:[PTRSAV]
|
|||
|
MOV [BX.STATUS],AX ;Save operation compete and status.
|
|||
|
|
|||
|
POP BX ;Restore registers.
|
|||
|
POP ES
|
|||
|
POP DS
|
|||
|
POP BP
|
|||
|
POP DI
|
|||
|
POP DX
|
|||
|
POP CX
|
|||
|
POP AX
|
|||
|
POP SI
|
|||
|
RET ;RESTORE REGS AND RETURN
|
|||
|
EXITP ENDP
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Main console I/O section.
|
|||
|
|
|||
|
MCON DW 0001H
|
|||
|
PCON DW 0002H
|
|||
|
ACON DW 0003H
|
|||
|
|
|||
|
CHAR DB ? ;Small typeahead buffer for now.
|
|||
|
|
|||
|
;
|
|||
|
; Console keyboard handler.
|
|||
|
;
|
|||
|
|
|||
|
CISTAT: PUSH CX ;Save CX pair.
|
|||
|
MOV AL,[CHAR]
|
|||
|
OR AL,AL
|
|||
|
JNZ CISTA9 ;Character still in buffer.
|
|||
|
CISTA1: MOV BX,ROM_CONSTA
|
|||
|
MOV CX,[MCON]
|
|||
|
CALL ROM_CALL ;See if character waiting.
|
|||
|
TEST AL,AL
|
|||
|
JZ CISTA9
|
|||
|
MOV BX,ROM_CONIN
|
|||
|
MOV CX,[MCON]
|
|||
|
CALL ROM_CALL ;Get character from Rom.
|
|||
|
OR AL,AL
|
|||
|
JZ CISTA1 ;Got a null character.
|
|||
|
MOV [CHAR],AL
|
|||
|
CISTA9: POP CX ;Can't lose CX pair.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; Get a character from the buffer queue.
|
|||
|
;
|
|||
|
|
|||
|
CINP: CALL CISTAT ;Check for character ready in queue.
|
|||
|
JZ CINP ;Cycle until one ready.
|
|||
|
MOV [CHAR],0 ;We have character in AL, clear type a head.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; Console read non-destructive.
|
|||
|
;
|
|||
|
|
|||
|
CON_RDND:
|
|||
|
CALL CISTAT ;See if character ready.
|
|||
|
JZ CON_RDN2 ;No, return busy signal.
|
|||
|
CON_RDN1:
|
|||
|
LDS BX,CS:[PTRSAV]
|
|||
|
MOV [BX.MEDIA],AL
|
|||
|
JMP EXIT
|
|||
|
CON_RDN2:
|
|||
|
JMP BUS_EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Console destructive read.
|
|||
|
;
|
|||
|
|
|||
|
CON_READ:
|
|||
|
CALL CINP ;Get character.
|
|||
|
STOSB ;Save it in users buffer.
|
|||
|
LOOP CON_READ ;Loop until CX is exhausted.
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Console flush routine. (ctrl-c, ctrl-f, or ctrl-s inspired)
|
|||
|
;
|
|||
|
|
|||
|
CON_FLSH:
|
|||
|
MOV [CHAR],0 ;Clear small type a head buffer.
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Console output status routine.
|
|||
|
;
|
|||
|
|
|||
|
CON_WRST:
|
|||
|
JMP EXIT ;Yes, normal exit.
|
|||
|
|
|||
|
;
|
|||
|
; Console output routine.
|
|||
|
;
|
|||
|
|
|||
|
CON_WRIT:
|
|||
|
MOV SI,DI ;Get destination to source.
|
|||
|
CON_WRI1:
|
|||
|
LODS BYTE PTR ES:[SI]
|
|||
|
PUSH CX
|
|||
|
IF ANSI
|
|||
|
CALL CONOUT ;Call ansi driver.
|
|||
|
ENDIF
|
|||
|
IFE ANSI
|
|||
|
CALL OUTCHR
|
|||
|
ENDIF
|
|||
|
POP CX
|
|||
|
LOOP CON_WRI1 ;Keep going until user buffer through.
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Console character output routine.
|
|||
|
;
|
|||
|
|
|||
|
OUTCHR: MOV BX,ROM_CONOUT
|
|||
|
MOV CX,[MCON] ;Get current console port.
|
|||
|
MOV DL,AL
|
|||
|
CALL ROM_CALL
|
|||
|
RET
|
|||
|
|
|||
|
PAGE
|
|||
|
|
|||
|
IF ANSI
|
|||
|
|
|||
|
SUBTTL ANSI interface section.
|
|||
|
|
|||
|
;
|
|||
|
;ANSI Info and routines. ANSI driver implemented as a finite state automata
|
|||
|
;This ANSI driver translates the ANSI standard escape sequences into the
|
|||
|
; Zenith Escape sequences used on the Zenith(Heath) Z(H)-19 terminal.
|
|||
|
;This is not a full implementation of ANSI, but rather a minimal implementation
|
|||
|
; which implements all of the necessary ANSI functions.
|
|||
|
;
|
|||
|
|
|||
|
ESC EQU 1BH ;Escape character used in this implementation.
|
|||
|
STATE DW ST1 ;Current ANSI character state.
|
|||
|
PRMPNT DW PARMS ;Current parameter pointer.
|
|||
|
PARMS DB 0,0,0,0,0,0,0 ;Allow for up to eight parameters.
|
|||
|
LASTPRM DB 0 ;With this being the eight one.
|
|||
|
|
|||
|
CMDTABL DB 'A' ;Cursor up. "esc","[",#,"A"
|
|||
|
DW CUU
|
|||
|
DB 'B' ;Cursor down. "esc","[",#,"B"
|
|||
|
DW CUD
|
|||
|
DB 'C' ;Cursor forward. "esc","[",#,"C"
|
|||
|
DW CUF
|
|||
|
DB 'D' ;Cursor back. "esc","[",#,"D"
|
|||
|
DW CUB
|
|||
|
DB 'H' ;Direct cursor posit. "esc","[",x,y,"H"
|
|||
|
DW CUP
|
|||
|
DB 'J' ;Erase. "esc","[",code,"J"
|
|||
|
DW ED
|
|||
|
DB 'K' ;Erase in line. "esc","[",code,"K"
|
|||
|
DW EL
|
|||
|
DB 'f' ;Direct cursor posit. "esc","[",x,y,"f"
|
|||
|
DW CUP
|
|||
|
DB 'm' ;Special video mode. "esc","[",code,"m"
|
|||
|
DW SGR
|
|||
|
DB 's' ;Save cursor posit. "esc","[","s"
|
|||
|
DW PSCP
|
|||
|
DB 'u' ;Move cursor to saved. "esc","[","u"
|
|||
|
DW PRCP
|
|||
|
DB 00 ;End of table.
|
|||
|
|
|||
|
;
|
|||
|
; ANSI console output driver.
|
|||
|
;
|
|||
|
|
|||
|
CONOUT: MOV DI,OFFSET STATE ;Retrieve current ansi state.
|
|||
|
JMP [DI] ;Jump to it.
|
|||
|
|
|||
|
;
|
|||
|
; State one (1).
|
|||
|
; Looks for an Escape character.
|
|||
|
;
|
|||
|
|
|||
|
ST1: CMP AL,ESC ;See if this the first character is ESC.
|
|||
|
JNZ OUTCHR ;No, treat as regular character output.
|
|||
|
MOV WORD PTR [DI],OFFSET ST2 ;Yes, setup state two.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; State two (2).
|
|||
|
; Looks for the "[" character.
|
|||
|
;
|
|||
|
|
|||
|
ST2: CMP AL,'[' ;See if a valide state two.
|
|||
|
JNZ OUTCHR ;No, treat as regular charcter
|
|||
|
MOV BX,OFFSET PARMS ;Yes, get parameter pointer.
|
|||
|
MOV WORD PTR [PRMPNT],BX ;Setup in pointer index.
|
|||
|
MOV WORD PTR [BX],0 ;Clear first entry.
|
|||
|
MOV WORD PTR [DI],OFFSET ST3;Setup for state three.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; State three (3).
|
|||
|
; Entered one or more times for parameter passing.
|
|||
|
;
|
|||
|
|
|||
|
ST3: CMP AL,';' ;Look for decimal # seperator.
|
|||
|
JNZ ST3A ;No check phase A.
|
|||
|
INC WORD PTR [PRMPNT] ;Yes, incr. pointer to next param.
|
|||
|
MOV AX,OFFSET LASTPRM ;Check for outside parameter list.
|
|||
|
CMP [PRMPNT],AX
|
|||
|
JBE RETST3 ;Yes, proceed with next parameter.
|
|||
|
MOV [PRMPNT],AX ;No, treat as extentsion to old.
|
|||
|
RETST3: MOV DI,[PRMPNT] ;Setup for next parameter.
|
|||
|
MOV BYTE PTR [DI],0 ;Pre-Initialize it to zero.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; State three A (3A).
|
|||
|
; Check for a ascii digit.
|
|||
|
;
|
|||
|
|
|||
|
ST3A: CMP AL,'0' ;Check for ASCII digit.
|
|||
|
JB ST3B ;No, check for seconday command character.
|
|||
|
CMP AL,'9' ;Still checking for ASCII digit.
|
|||
|
JA ST3B ;No, it must be a secondary.
|
|||
|
SUB AL,'0' ;Convert to binary.
|
|||
|
MOV DI,[PRMPNT] ;Get the current parameter pointer.
|
|||
|
XCHG [DI],AL ;Get existing #.
|
|||
|
MOV AH,10 ;Scale by 10.
|
|||
|
MUL AH
|
|||
|
ADD [DI],AL ;Add to new digit.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; State three B (3B).
|
|||
|
; Wasn't a ascii digit, so check for secondary command.
|
|||
|
;
|
|||
|
|
|||
|
ST3B: MOV [DI],OFFSET ST1 ;Preset STATE to state 1 just in case.
|
|||
|
MOV DI,OFFSET PARMS-1 ;Get pointer to start of parameters.
|
|||
|
MOV [PRMPNT],DI ;Save it in Parameter pointer.
|
|||
|
MOV DI,OFFSET CMDTABL-3 ;Get start of Secondary command table.
|
|||
|
|
|||
|
ST3B1: ADD DI,3 ;Update Command table pointer.
|
|||
|
CMP BYTE PTR [DI],0 ;Check for end of table.
|
|||
|
JNZ ST3B2 ;No, continue processing.
|
|||
|
JMP OUTCHR ;Yes, treat as regular character.
|
|||
|
ST3B2: CMP AL,[DI] ;Check for valid. command.
|
|||
|
JNZ ST3B1 ;No, keep checking.
|
|||
|
JMP [DI+1] ;Yes, transfer to that secondary command.
|
|||
|
|
|||
|
;
|
|||
|
; Get binary parameter from storage and return a one if = 0
|
|||
|
;
|
|||
|
|
|||
|
GETONE: CALL GETPARM ;Get parameter form list.
|
|||
|
OR AL,AL ;Verify for non-zero.
|
|||
|
JNZ GETRET ;Good, then return to caller.
|
|||
|
INC AL ;Bad, make it at least a one.
|
|||
|
GETRET: CBW ;Sign extend AL.
|
|||
|
MOV CX,AX ;Copy of it to CX.
|
|||
|
RET
|
|||
|
|
|||
|
GETPARM:INC WORD PTR [PRMPNT] ;Increment parameter pointer.
|
|||
|
GOTPARM:MOV DI,[PRMPNT] ;Get parameter pointer.
|
|||
|
MOV AL,[DI] ;Get parameter value.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; Send escape, character sequence.
|
|||
|
;
|
|||
|
|
|||
|
OUTESC: MOV AL,ESC ;Send escape character.
|
|||
|
CALL OUTCHR
|
|||
|
MOV AL,BL ;Send follow character.
|
|||
|
JMP OUTCHR
|
|||
|
|
|||
|
;
|
|||
|
; Cursor Positioning routines.
|
|||
|
;
|
|||
|
|
|||
|
CUU: MOV BL,'A' ;Cursor up.
|
|||
|
JMP SHORT CURPOS
|
|||
|
CUD: MOV BL,'B' ;Cursor down.
|
|||
|
JMP SHORT CURPOS
|
|||
|
CUF: MOV BL,'C' ;Cursor forward.
|
|||
|
JMP SHORT CURPOS
|
|||
|
CUB: MOV BL,'D' ;Cursor back.
|
|||
|
|
|||
|
CURPOS: CALL GETONE ;Get number of positions to move into CX.
|
|||
|
MOVCUR: CALL OUTESC ;Send escape, command characters.
|
|||
|
LOOP MOVCUR ;Keep moving until done.
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; Direct cursor positioning routine.
|
|||
|
;
|
|||
|
|
|||
|
CUP: CALL GETONE ;Get X position.
|
|||
|
MOV DX,AX ;Save in DX.
|
|||
|
CALL GETONE ;Get Y position.
|
|||
|
MOV BL,'Y'
|
|||
|
CALL OUTESC ;Send escape, "Y" sequence.
|
|||
|
MOV AL,DL
|
|||
|
ADD AL,' '-1 ;Convert binary to Character.
|
|||
|
CALL OUTCHR ;Send X posit.
|
|||
|
MOV AL,CL
|
|||
|
ADD AL,' '-1 ;Convert binary to Character.
|
|||
|
JMP OUTCHR ;Send Y posit.
|
|||
|
|
|||
|
;
|
|||
|
; Erase all/part of screen.
|
|||
|
;
|
|||
|
|
|||
|
ED: CALL GETPARM ;Get trinary command type.
|
|||
|
MOV BL,'b'
|
|||
|
DEC AL ;See if erase from begining of screen.
|
|||
|
JZ ED1 ;Yes, perform ZDS function.
|
|||
|
MOV BL,'E'
|
|||
|
DEC AL ;See if erase from end of screen.
|
|||
|
JZ ED1 ;Yes, perform ZDS function.
|
|||
|
MOV BL,'J' ;Now we assume erase whole screen.
|
|||
|
ED1: JMP OUTESC
|
|||
|
|
|||
|
;
|
|||
|
; Erase all/part of a line.
|
|||
|
;
|
|||
|
|
|||
|
EL: CALL GETPARM ;Get trinary command type.
|
|||
|
MOV BL,'o'
|
|||
|
DEC AL ;See if erase from begining of line.
|
|||
|
JZ EL1 ;Yes, perform ZDS function.
|
|||
|
MOV BL,'l'
|
|||
|
DEC AL ;See if erase whole line.
|
|||
|
JZ EL1 ;Yes, perform ZDS function.
|
|||
|
MOV BL,'K' ;Now we assume erase to end of line.
|
|||
|
EL1: JMP OUTESC
|
|||
|
|
|||
|
;
|
|||
|
; Special video modes.
|
|||
|
;
|
|||
|
|
|||
|
SGR: CALL GETPARM ;Get trinary command type.
|
|||
|
MOV BL,'p'
|
|||
|
CMP AL,7 ;See if enter reverse video mode.
|
|||
|
JZ SGR2 ;Yes, perform ZDS function.
|
|||
|
MOV BL,'q'
|
|||
|
OR AL,AL ;See if exit reverse video mode.
|
|||
|
JNZ SGR3 ;No, ignore.
|
|||
|
SGR2: CALL OUTESC
|
|||
|
SGR3: RET
|
|||
|
|
|||
|
;
|
|||
|
; Save / restore cursor position.
|
|||
|
;
|
|||
|
|
|||
|
PSCP: MOV BL,'j' ;Set save cursor posit. mode.
|
|||
|
JMP OUTESC
|
|||
|
|
|||
|
PRCP: MOV BL,'k' ;Restore last cursor save.
|
|||
|
JMP OUTESC
|
|||
|
|
|||
|
ENDIF
|
|||
|
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Printer buffer handler.
|
|||
|
|
|||
|
;
|
|||
|
; Printer status routine.
|
|||
|
;
|
|||
|
|
|||
|
PRN_STA:
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Printer write routine.
|
|||
|
;
|
|||
|
|
|||
|
PRN_WRT:MOV SI,DI ;Set source = destination index.
|
|||
|
|
|||
|
PRN_WR1:LODS BYTE PTR ES:[SI];Get a data byte.
|
|||
|
PUSH CX
|
|||
|
MOV CX,[PCON]
|
|||
|
MOV BX,ROM_CONOUT
|
|||
|
MOV DL,AL
|
|||
|
CALL ROM_CALL
|
|||
|
POP CX
|
|||
|
LOOP PRN_WR1
|
|||
|
RET
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Auxilary I/O routines.
|
|||
|
|
|||
|
AUXCHAR DB 0 ;Temporary AUX ahead storage.
|
|||
|
|
|||
|
;
|
|||
|
; Status routine for Auxilary port.
|
|||
|
;
|
|||
|
|
|||
|
AISTAT: MOV AL,[AUXCHAR]
|
|||
|
TEST AL,AL
|
|||
|
JNZ AISTA9 ;Character already waiting.
|
|||
|
MOV CX,[ACON]
|
|||
|
MOV BX,ROM_CONSTA
|
|||
|
CALL ROM_CALL
|
|||
|
TEST AL,AL
|
|||
|
JZ AISTA9 ;Still none waiting.
|
|||
|
MOV CX,[ACON]
|
|||
|
MOV BX,ROM_CONIN
|
|||
|
CALL ROM_CALL
|
|||
|
AISTA9: MOV [AUXCHAR],AL
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; Auxilary port read.
|
|||
|
;
|
|||
|
|
|||
|
AIN: CALL AISTAT ;Get status and/or char.
|
|||
|
JZ AIN ;Cycle until one is ready.
|
|||
|
MOV [AUXCHAR],0
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; Write routine for Auxilary port.
|
|||
|
;
|
|||
|
|
|||
|
AOUT: MOV CX,[ACON]
|
|||
|
MOV BX,ROM_CONOUT
|
|||
|
MOV DL,AL
|
|||
|
CALL ROM_CALL
|
|||
|
RET
|
|||
|
|
|||
|
;
|
|||
|
; Non-Destructive Auxilary read routine.
|
|||
|
;
|
|||
|
|
|||
|
AUX_RDND:
|
|||
|
CALL AISTAT ;Get status and copy of char. waiting if any.
|
|||
|
JZ AUX_RDN2 ;No character waiting, exit.
|
|||
|
JMP CON_RDN1
|
|||
|
AUX_RDN2:
|
|||
|
JMP BUS_EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Destructive Auxilary read routine.
|
|||
|
;
|
|||
|
|
|||
|
AUX_READ:
|
|||
|
CALL AIN ;Get data character.
|
|||
|
STOSB ;Save it through DI.
|
|||
|
LOOP AUX_READ ;Cycle until user buffer full.
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Auxilary clear type a head.
|
|||
|
;
|
|||
|
|
|||
|
AUX_CLR:
|
|||
|
MOV [AUXCHAR],0
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Auxilary write port status.
|
|||
|
;
|
|||
|
|
|||
|
AUX_WRST:
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Auxilary write.
|
|||
|
;
|
|||
|
|
|||
|
AUX_WRIT:
|
|||
|
MOV SI,DI
|
|||
|
AUX_WRI1:
|
|||
|
LODS BYTE PTR ES:[SI] ;Get char. from users buffer.
|
|||
|
CALL AOUT ;Send it to device.
|
|||
|
LOOP AUX_WRI1 ;Cycle until all done.
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Date/Time Routines.
|
|||
|
|
|||
|
TIM_DAYS: DB 2 DUP (?) ;Number of days since 1-1-80.
|
|||
|
TIM_MINS: DB ? ;Minutes.
|
|||
|
TIM_HRS: DB ? ;Hours.
|
|||
|
TIM_HSEC: DB ? ;Hundreths of a second.
|
|||
|
TIM_SECS: DB ? ;Seconds.
|
|||
|
|
|||
|
;
|
|||
|
; Time write routine.
|
|||
|
;
|
|||
|
|
|||
|
TIM_WRT:
|
|||
|
MOV SI,OFFSET TIM_DAYS
|
|||
|
XCHG SI,DI
|
|||
|
PUSH ES
|
|||
|
MOV AX,DS
|
|||
|
POP DS
|
|||
|
MOV ES,AX
|
|||
|
MOV CX,6
|
|||
|
REP MOVSB
|
|||
|
MOV AL,0
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
;
|
|||
|
; Time read routine.
|
|||
|
;
|
|||
|
|
|||
|
TIM_RED:
|
|||
|
MOV SI,OFFSET TIM_DAYS
|
|||
|
MOV CX,6
|
|||
|
REP MOVSB
|
|||
|
MOV AL,0
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL 8089 Monitor structure.
|
|||
|
|
|||
|
;
|
|||
|
; Structure to reference 8089 and ROM command table.
|
|||
|
;
|
|||
|
|
|||
|
SIOPB STRUC
|
|||
|
DB 4 DUP (?) ;Monitor Use Only
|
|||
|
OPCODE DB ? ;I/O operation code.
|
|||
|
DRIVE DB ? ;Logical drive spec.
|
|||
|
TRACK DW ? ;Logical track number.
|
|||
|
HEAD DB ? ;Logical head number.
|
|||
|
SECTOR DB ? ;Logical sector to start with.
|
|||
|
SCOUNT DB ? ;Number of logical sectors in buffer.
|
|||
|
RETCODE DB ? ;Error code after masking.
|
|||
|
RETMASK DB ? ;Error mask.
|
|||
|
RETRIES DB ? ;Number of retries before error exit.
|
|||
|
DMAOFF DW ? ;Buffer offset address.
|
|||
|
DMASEG DW ? ;Buffer segment.
|
|||
|
SECLENG DW ? ;Sector Length.
|
|||
|
DB 6 DUP (?) ;8089 use only.
|
|||
|
SIOPB ENDS
|
|||
|
|
|||
|
IOPB SIOPB <,00H,0,0,0,0,0,0,000H,0,0,0,0,>
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Drive Tables.
|
|||
|
|
|||
|
|
|||
|
;
|
|||
|
; MSDOS drive initialization tables and other what not.
|
|||
|
;
|
|||
|
; Drive 0 is:
|
|||
|
; Single sided, Single density, 77 track with 26
|
|||
|
; 128 byte sectors per track. One sector for
|
|||
|
; boot and header. (256,128 bytes free, old style).
|
|||
|
; or
|
|||
|
; Single sided, Single density, 77 track with 26
|
|||
|
; 128 byte sectors per track. Four sectors for
|
|||
|
; boot and header. (255,744 bytes free).
|
|||
|
; or
|
|||
|
; Single sided, Double Density, 75 track with 12
|
|||
|
; 512 byte sectors per track.
|
|||
|
; (460,800 bytes)
|
|||
|
; Two hidden single density tracks.
|
|||
|
;
|
|||
|
|
|||
|
DBP STRUC
|
|||
|
|
|||
|
JMPNEAR DB 3 DUP (?) ;Jmp Near xxxx for boot.
|
|||
|
NAMEVER DB 8 DUP (?) ;Name / Version of OS.
|
|||
|
|
|||
|
;------- Start of Drive Parameter Block.
|
|||
|
|
|||
|
SECSIZE DW ? ;Sector size in bytes. (dpb)
|
|||
|
ALLOC DB ? ;Number of sectors per alloc. block. (dpb)
|
|||
|
RESSEC DW ? ;Reserved sectors. (dpb)
|
|||
|
FATS DB ? ;Number of FAT's. (dpb)
|
|||
|
MAXDIR DW ? ;Number of root directory entries. (dpb)
|
|||
|
SECTORS DW ? ;Number of sectors per diskette. (dpb)
|
|||
|
MEDIAID DB ? ;Media byte ID. (dpb)
|
|||
|
FATSEC DW ? ;Number of FAT Sectors. (dpb)
|
|||
|
|
|||
|
;------- End of Drive Parameter Block.
|
|||
|
|
|||
|
SECTRK DW ? ;Number of Sectors per track.
|
|||
|
|
|||
|
DBP ENDS
|
|||
|
|
|||
|
LSDRIV1 DBP <,,128,4,1,2,68,2002,0FEH,6,26>
|
|||
|
|
|||
|
LSDRIV2 DBP <,,128,4,4,2,68,2002,0FDH,6,26>
|
|||
|
|
|||
|
LDDRIV1 DBP <,,512,1,24,2,128,924,0F8H,3,12>
|
|||
|
|
|||
|
LDDRIV2 DBP <,,1024,1,16,2,128,616,0F9H,1,8>
|
|||
|
|
|||
|
DSK_INIT:
|
|||
|
MOV AX,1
|
|||
|
MOV SI,OFFSET INITTAB
|
|||
|
JMP GET_BP5
|
|||
|
|
|||
|
INITTAB:
|
|||
|
DW LDDRIV2.SECSIZE
|
|||
|
|
|||
|
DSTAT EQU 41H ;1793 status port.
|
|||
|
DTRACK EQU 43H ;1793 track port.
|
|||
|
DSECTOR EQU 45H ;1793 sector port.
|
|||
|
DDATA EQU 47H ;1793 data I/O port.
|
|||
|
|
|||
|
DDENS EQU 55H ;Density select port.
|
|||
|
DDBIT EQU 04H ;Density select bit.
|
|||
|
DSELECT EQU 53H ;Drive select port.
|
|||
|
|
|||
|
CURDRV DB 0
|
|||
|
DRVTAB DB 0EH,0DH,0BH,07H
|
|||
|
TRKPT DB 0,1,2,3
|
|||
|
TRKTAB DB -1,-1,-1,-1
|
|||
|
PREDENS DB 0,0,0,0
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Media check routine
|
|||
|
|
|||
|
;
|
|||
|
; Media check routine.
|
|||
|
; On entry:
|
|||
|
; AL = disk unit number.
|
|||
|
; AH = media byte
|
|||
|
; On exit:
|
|||
|
;
|
|||
|
; [MEDIA FLAG] = -1 (FF hex) if disk is changed.
|
|||
|
; [MEDIA FLAG] = 0 if don't know.
|
|||
|
; [MEDIA FLAG] = 1 if not changed.
|
|||
|
;
|
|||
|
; [MEDIA] = 0FEH for Standard single density.
|
|||
|
; [MEDIA] = 0FDH for Altos single density.
|
|||
|
; [MEDIA] = 0F4H for Altos double density.
|
|||
|
;
|
|||
|
|
|||
|
MEDIAS STRUC
|
|||
|
DB 13 DUP(?) ;Static request header.
|
|||
|
MEDIAS1 DB ? ;Media byte.
|
|||
|
MEDIAS2 DB ? ;Media status byte flag.
|
|||
|
MEDIAS ENDS
|
|||
|
|
|||
|
MEDIAC:
|
|||
|
AND AL,03H ;Clear any extraneous bits.
|
|||
|
PUSH AX ;Save drive number requested.
|
|||
|
MOV AL,0D0H ;Terminate with no interrupt.
|
|||
|
CALL DCOM
|
|||
|
AND AL,20H ;See if head load bit set.
|
|||
|
POP AX
|
|||
|
JZ MEDIA2 ;Head not loaded, so see if media changed.
|
|||
|
MOV AH,1 ; AH = 1, disk not changed.
|
|||
|
JMP SHORT MEDIA1
|
|||
|
|
|||
|
MEDIA1A:MOV [PREDENS],DL ;Save last density used for read.
|
|||
|
|
|||
|
MEDIA1: LDS BX,[PTRSAV] ;Udate media section of data block.
|
|||
|
MOV [BX.MEDIAS2],AH
|
|||
|
MOV AL,0
|
|||
|
JMP EXIT
|
|||
|
|
|||
|
MEDIA2: CALL MEDIA4 ;Unload head if selecting new drive.
|
|||
|
MOV CX,2 ;Try each density once.
|
|||
|
MOV BX,OFFSET DRVTAB
|
|||
|
XLAT ;Convert from drive # to select code.
|
|||
|
OUT DSELECT,AL ;Select disk
|
|||
|
MOV AH,0 ;Assume that we don't know.
|
|||
|
MOV DL,[PREDENS] ;Get last density.
|
|||
|
AND DL,DDBIT ;Be sure only Density bit set/clr.
|
|||
|
MEDIA3: IN AL,DDENS
|
|||
|
AND AL,0FBH ;Clear density bit.
|
|||
|
OR AL,DL ;Set/clear density bit.
|
|||
|
OUT DDENS,AL ;Select density.
|
|||
|
MOV AL,0C4H ;READ ADDRESS command
|
|||
|
CALL DCOM
|
|||
|
AND AL,98H
|
|||
|
IN AL,DDATA ;Eat last byte to reset DRQ
|
|||
|
JZ MEDIA1A ;Jump if no error in reading address.
|
|||
|
MOV AH,0FFH ; AH = -1 (disk changed) if new density works.
|
|||
|
XOR DL,DDBIT ;Flip density bit.
|
|||
|
LOOP MEDIA3
|
|||
|
MOV AX,2 ;Couldn't read disk at all, AH = 0 for don't
|
|||
|
JMP ERR_EXIT ; know if disk changed, AL = error code 2 -
|
|||
|
|
|||
|
MEDIA4: MOV AH,AL ;Save disk drive number in AH.
|
|||
|
XCHG AL,[CURDRV] ;make new drive current, AL = previous
|
|||
|
CMP AL,AH ;Changing drives?
|
|||
|
JZ MEDIA5 ;No, return to caller.
|
|||
|
;
|
|||
|
; If changing drives, unload head so the head load delay one-shot
|
|||
|
; will fire again. Do it by seeking to same track with the H bit reset.
|
|||
|
;
|
|||
|
IN AL,DTRACK ;Get current track number
|
|||
|
OUT DDATA,AL ;Make it the track to seek to
|
|||
|
MOV AL,10H ;Seek and unload head
|
|||
|
CALL DCOM
|
|||
|
MOV AL,AH ;Restore current drive number
|
|||
|
MEDIA5: RET
|
|||
|
|
|||
|
;
|
|||
|
; Short routine to send a command to 1793 diskette controller chip and
|
|||
|
; wait for 1793 to complete the command.
|
|||
|
;
|
|||
|
|
|||
|
DCOM: OUT 41H,AL ;Send command to 1793.
|
|||
|
MOV CX,10H
|
|||
|
DCOM1: LOOP DCOM1 ;Wait a short time for 1793 to digest it.
|
|||
|
|
|||
|
DCOM2: IN AL,41H ;Get 1793's status.
|
|||
|
AND AL,1 ;See if busy.
|
|||
|
JNZ DCOM2 ;Yes, keep checking.
|
|||
|
IN AL,41H ;Get 1793's status for return
|
|||
|
RET
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Build and return Bios Parameter Block for a diskette.
|
|||
|
|
|||
|
;
|
|||
|
; Build Bios Parameter Blocks.
|
|||
|
;
|
|||
|
; On entry: ES:DI contains the address of a scratch sector buffer.
|
|||
|
; AL = Unit number.
|
|||
|
; AH = Current media byte.
|
|||
|
;
|
|||
|
; On exit: Return a DWORD pointer to the associated BPB
|
|||
|
; in the Request packet.
|
|||
|
;
|
|||
|
|
|||
|
BPBS STRUC
|
|||
|
DB 13 DUP(?) ;Static request header.
|
|||
|
BPB1 DB ? ;Media byte.
|
|||
|
BPB2 DW ? ;DWORD transfer address.
|
|||
|
DW ?
|
|||
|
BPB3 DW ? ;DWORD pointer to BPB
|
|||
|
DW ?
|
|||
|
BPBS ENDS
|
|||
|
|
|||
|
GET_BPB:
|
|||
|
PUSH ES
|
|||
|
PUSH DI
|
|||
|
MOV [IOPB.DMASEG],ES
|
|||
|
MOV [IOPB.DMAOFF],DI
|
|||
|
MOV BYTE PTR[IOPB.SECTOR],1
|
|||
|
MOV BYTE PTR[IOPB.SCOUNT],1
|
|||
|
MOV BYTE PTR[IOPB.OPCODE],088H
|
|||
|
MOV BYTE PTR[IOPB.RETRIES],1
|
|||
|
MOV BYTE PTR[IOPB.DRIVE],0
|
|||
|
MOV [IOPB.TRACK],0
|
|||
|
MOV BYTE PTR[IOPB.HEAD],1
|
|||
|
MOV BYTE PTR[IOPB.RETMASK],0DCH
|
|||
|
MOV [IOPB.SECLENG],128
|
|||
|
MOV BX,ROM_DISKIO
|
|||
|
MOV CX,OFFSET IOPB
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
CALL ROM_CALL ;Read sector zero for information.
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
POP DI
|
|||
|
POP ES
|
|||
|
MOV AH,[IOPB.RETCODE]
|
|||
|
OR AH,AH
|
|||
|
JNZ GET_BP3 ;Disk error, assume old single density.
|
|||
|
|
|||
|
GET_BP1:MOV AL,ES:[DI.MEDIAID] ;Get diskettes media ID.
|
|||
|
MOV SI,OFFSET LSDRIV2
|
|||
|
CMP AL,[SI.MEDIAID]
|
|||
|
JZ GET_BP4
|
|||
|
MOV SI,OFFSET LDDRIV1
|
|||
|
CMP AL,[SI.MEDIAID]
|
|||
|
JZ GET_BP4
|
|||
|
MOV SI,OFFSET LDDRIV2
|
|||
|
CMP AL,[SI.MEDIAID]
|
|||
|
JZ GET_BP4
|
|||
|
|
|||
|
GET_BP3:MOV SI,OFFSET LSDRIV1 ;No compares, assume old style for now.
|
|||
|
|
|||
|
GET_BP4:MOV AL,[SI.MEDIAID]
|
|||
|
ADD SI,11 ;Convert to DPB pointer
|
|||
|
|
|||
|
GET_BP5:LDS BX,[PTRSAV] ;Update I/O data packet.
|
|||
|
MOV [BX.BPB1],AL ;Media byte.
|
|||
|
MOV [BX.BPB3],SI ;DPB pointer.
|
|||
|
MOV [BX.BPB3+2],CS ;Code segment.
|
|||
|
OR AH,AH
|
|||
|
JNZ GET_BP6
|
|||
|
MOV AL,0
|
|||
|
JMP EXIT
|
|||
|
GET_BP6:MOV AX,7
|
|||
|
JMP ERR_EXIT
|
|||
|
|
|||
|
PAGE
|
|||
|
|
|||
|
SUBTTL Disk I/O equates.
|
|||
|
|
|||
|
; Floppy drives
|
|||
|
|
|||
|
; --------------------------
|
|||
|
; Hardware command def.
|
|||
|
; --------------------------
|
|||
|
;
|
|||
|
; Read command = 88 hex.
|
|||
|
; Write command = A8 hex.
|
|||
|
; Format command = F0 hex.
|
|||
|
; Seek command = 1E hex.
|
|||
|
; Recal command = 0A hex.
|
|||
|
; Set DD mode = 80 hex.
|
|||
|
;
|
|||
|
; --------------------------
|
|||
|
; Status bits:
|
|||
|
; --------------------------
|
|||
|
;
|
|||
|
; Busy = 01 hex.
|
|||
|
; (not used) = 02 hex.
|
|||
|
; TK0(seek) = 04 hex.
|
|||
|
; Lost Data = 04 hex.
|
|||
|
; CRC error = 08 hex.
|
|||
|
; Seek error = 10 hex.
|
|||
|
; Not found = 10 hex.
|
|||
|
; Write fault = 20 hex.
|
|||
|
; Write protect = 40 hex.
|
|||
|
; Not ready = 80 hex.
|
|||
|
;
|
|||
|
; --------------------------
|
|||
|
|
|||
|
F_READ EQU 088H ;Floppy read command.
|
|||
|
F_WRIT EQU 0A8H ;Floppy write command.
|
|||
|
F_FMT EQU 0F0H ;Floppy format command.
|
|||
|
F_SEEK EQU 01EH ;Floppy seek command.
|
|||
|
F_RECAL EQU 00AH ;Floppy recal. command.
|
|||
|
F_DD EQU 080H ;Set Drive double density bit.
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL MSDOS 2.x Disk I/O drivers.
|
|||
|
|
|||
|
;
|
|||
|
; Disk READ/WRITE functions.
|
|||
|
;
|
|||
|
; On entry:
|
|||
|
; AL = Disk I/O driver number
|
|||
|
; AH = Media byte.
|
|||
|
; ES = Disk transfer segment.
|
|||
|
; DI = Disk transfer offset in ES.
|
|||
|
; CX = Number of sectors to transfer
|
|||
|
; DX = Logical starting sector.
|
|||
|
;
|
|||
|
; On exit:
|
|||
|
; Normal exit through common exit routine.
|
|||
|
;
|
|||
|
; Abnormal exit through common error routine.
|
|||
|
;
|
|||
|
|
|||
|
DSK_RED:
|
|||
|
MOV BX,0DC88H ;Set read mode and Error mask.
|
|||
|
JMP SHORT DSK_COM
|
|||
|
DSK_WRV:
|
|||
|
DSK_WRT:MOV BX,0FCA8H ;Set write mode and Error mask.
|
|||
|
|
|||
|
DSK_COM:MOV SI,OFFSET LSDRIV1
|
|||
|
CMP AH,[SI.MEDIAID]
|
|||
|
JE DSK_CO3
|
|||
|
MOV SI,OFFSET LSDRIV2
|
|||
|
CMP AH,[SI.MEDIAID]
|
|||
|
JE DSK_CO3
|
|||
|
MOV SI,OFFSET LDDRIV1
|
|||
|
CMP AH,[SI.MEDIAID]
|
|||
|
JE DSK_CO2
|
|||
|
MOV SI,OFFSET LDDRIV2
|
|||
|
CMP AH,[SI.MEDIAID]
|
|||
|
JE DSK_CO2
|
|||
|
MOV AL,7
|
|||
|
JMP ERR_EXIT
|
|||
|
|
|||
|
DSK_CO2:OR AL,F_DD ;Set double density mode.
|
|||
|
|
|||
|
DSK_CO3:MOV [IOPB.DMASEG],ES ;Setup Buffer segment.
|
|||
|
MOV [IOPB.DMAOFF],DI ;Setup buffer offset.
|
|||
|
MOV DI,[SI.SECSIZE] ;Get sector size.
|
|||
|
MOV [IOPB.SECLENG],DI
|
|||
|
MOV [IOPB.RETRIES],1 ;Setup number of retries.
|
|||
|
MOV [IOPB.RETMASK],BH ;Operation error mask.
|
|||
|
MOV [IOPB.OPCODE],BL ;R/W opcode.
|
|||
|
MOV [IOPB.DRIVE],AL ;Drive with density select.
|
|||
|
MOV [IOPB.HEAD],1 ;Only one head on floppy drive.
|
|||
|
MOV BP,CX ;Save number of sectors to R/W
|
|||
|
DSK_CO4:PUSH DX ;Save starting sector.
|
|||
|
MOV AX,DX
|
|||
|
MOV DX,0 ;32 bit divide coming up.
|
|||
|
MOV CX,[SI.SECTRK]
|
|||
|
DIV CX ;Get track+head and start sector.
|
|||
|
INC DL
|
|||
|
MOV [IOPB.SECTOR],DL ;Starting sector.
|
|||
|
MOV BL,DL ;Save starting sector for later.
|
|||
|
MOV [IOPB.TRACK],AX ;Track to read/write.
|
|||
|
MOV AX,[SI.SECTRK] ;Now see how many sectors
|
|||
|
INC AL ; we can burst read.
|
|||
|
SUB AL,BL ;BL is the starting sector.
|
|||
|
MOV AH,0
|
|||
|
POP DX ;Retrieve logical sector start.
|
|||
|
CMP AX,BP ;See if on last partial track+head.
|
|||
|
JG DSK_CO5 ;Yes, on last track+head.
|
|||
|
SUB BP,AX ;No, update number of sectors left.
|
|||
|
ADD DX,AX ;Update next starting sector.
|
|||
|
JMP SHORT DSK_CO6
|
|||
|
DSK_CO5:MOV AX,BP ;Only read enough of sector
|
|||
|
MOV BP,0 ;to finish buffer and clear # left.
|
|||
|
DSK_CO6:MOV [IOPB.SCOUNT],AL
|
|||
|
MOV DI,AX ;Save number sectors for later.
|
|||
|
MOV BX,ROM_DISKIO
|
|||
|
MOV CX,OFFSET IOPB
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
CALL ROM_CALL ;Do disk operation.
|
|||
|
MOV AL,[IOPB.RETCODE] ;Get error code.
|
|||
|
OR AL,AL
|
|||
|
JNZ DERROR
|
|||
|
MOV AX,DI ;Retrieve number of sectors read.
|
|||
|
MOV CX,[SI.SECSIZE] ;Number of bytes per sector.
|
|||
|
PUSH DX
|
|||
|
MUL CX
|
|||
|
POP DX
|
|||
|
TEST AL,0FH ;Make sure no strange sizes.
|
|||
|
JNZ DSK_CO7 ;Illegal sector size found.
|
|||
|
MOV CL,4
|
|||
|
SHR AX,CL ;Convert number of bytes to para.
|
|||
|
ADD AX,[IOPB.DMASEG]
|
|||
|
MOV [IOPB.DMASEG],AX
|
|||
|
OR BP,BP
|
|||
|
JNZ DSK_CO4 ;Still more to do.
|
|||
|
MOV AL,0
|
|||
|
JMP EXIT ;All done.
|
|||
|
DSK_CO7:MOV AL,12
|
|||
|
JMP ERR_EXIT
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Disk Error processing.
|
|||
|
|
|||
|
;
|
|||
|
; Disk error routine.
|
|||
|
;
|
|||
|
|
|||
|
DERROR: LDS BX,CS:[PTRSAV]
|
|||
|
MOV [BX.COUNT],0
|
|||
|
PUSH CS
|
|||
|
POP DS
|
|||
|
|
|||
|
MOV BL,-1
|
|||
|
MOV AH,AL
|
|||
|
MOV BH,14 ;Lenght of table.
|
|||
|
MOV SI,OFFSET DERRTAB
|
|||
|
DERROR2:INC BL ;Increment to next error code.
|
|||
|
LODS BYTE PTR CS:[SI]
|
|||
|
CMP AH,AL ;See if error code matches disk status.
|
|||
|
JZ DERROR3 ;Got the right error, exit.
|
|||
|
DEC BH
|
|||
|
JNZ DERROR2 ;Keep checking table.
|
|||
|
MOV BL,12 ;Set general type of error.
|
|||
|
DERROR3:MOV AL,BL ;Now we've got the code.
|
|||
|
RET
|
|||
|
|
|||
|
DERRTAB DB 40H ; 0. Write protect error
|
|||
|
DB 00H ; 1. Unknown unit.
|
|||
|
DB 80H ; 2. Not ready error.
|
|||
|
DB 0FFH ; 3. Unknown command.
|
|||
|
DB 08H ; 4. CRC error
|
|||
|
DB 00H ; 5. Bad drive request.
|
|||
|
DB 02H ; 6. Seek error
|
|||
|
DB 00H ; 7. Unknown media.
|
|||
|
DB 10H ; 8. Sector not found
|
|||
|
DB 00H ; 9. (Not used.)
|
|||
|
DB 20H ;10. Write fault.
|
|||
|
DB 04H ;11. Read fault.
|
|||
|
DB 07H ;12. General type of failure.
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Common ROM call routine.
|
|||
|
|
|||
|
;
|
|||
|
; Save all registers except CX, BX and AX.
|
|||
|
|
|||
|
ROMRTN DD 0FE000000H ;Main ROM entry point.
|
|||
|
|
|||
|
ROM_CALL:
|
|||
|
PUSH DI
|
|||
|
PUSH SI
|
|||
|
PUSH BP
|
|||
|
PUSH DX
|
|||
|
PUSH ES
|
|||
|
CALL CS:DWORD PTR [ROMRTN]
|
|||
|
POP ES
|
|||
|
POP DX
|
|||
|
POP BP
|
|||
|
POP SI
|
|||
|
POP DI
|
|||
|
RET
|
|||
|
|
|||
|
PAGE
|
|||
|
SUBTTL Initalization code and temporary work areas.
|
|||
|
|
|||
|
;
|
|||
|
; Overlayed by MSDOS by SYSINIT.
|
|||
|
;
|
|||
|
|
|||
|
WRKSTK LABEL WORD
|
|||
|
DB 100 DUP (?)
|
|||
|
|
|||
|
|
|||
|
HWINIT: XOR BP,BP
|
|||
|
MOV SS,BP
|
|||
|
MOV SP,OFFSET WRKSTK+98 ;Some nice area for stack.
|
|||
|
|
|||
|
PUSH CS
|
|||
|
POP ES
|
|||
|
|
|||
|
MOV BX,ROM_INIT
|
|||
|
CALL ROM_CALL
|
|||
|
MOV AH,0
|
|||
|
MOV MCON,AX
|
|||
|
|
|||
|
MOV AX,SEG SYSINIT
|
|||
|
MOV DS,AX
|
|||
|
|
|||
|
ASSUME DS:SEG SYSINIT
|
|||
|
|
|||
|
MOV AX,CS
|
|||
|
ADD AX,BIOSIZS
|
|||
|
MOV DS:[CURRENT_DOS_LOCATION],AX
|
|||
|
MOV DS:[MEMORY_SIZE],MAX_MEM
|
|||
|
MOV AX,CS
|
|||
|
MOV WORD PTR DS:[DEVICE_LIST+2],AX
|
|||
|
MOV WORD PTR DS:[DEVICE_LIST],OFFSET DEVSTART
|
|||
|
MOV AX,CS
|
|||
|
ADD AX,((OFFSET WRKSTK - OFFSET INIT)+50) /16
|
|||
|
MOV DS:[FINAL_DOS_LOCATION],AX
|
|||
|
JMP SYSINIT
|
|||
|
|
|||
|
DOSSPOT LABEL WORD
|
|||
|
|
|||
|
CODE ENDS
|
|||
|
|
|||
|
END
|
|||
|
|