home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Complete Bookshop
/
CompleteWorkshop.iso
/
compute
/
dosdev2
/
stkdev.asm
< prev
next >
Wrap
Assembly Source File
|
1986-03-08
|
8KB
|
259 lines
; Listing 2 - STKDEV.ASM
;** PC-DOS Device Driver - Reconfigurable Stack for Structures ( 1-32K bytes)
;
; Bruce Bordner, 1985
;
;
CSEG SEGMENT PARA PUBLIC 'CODE'
;
yell macro char
push es
push di
push ax
mov ax,'&char'
les di,CS:bugout
stos byte ptr [di]
inc di
mov word ptr CS:bugout,di
pop ax
pop di
pop es
endm
;
XSTK PROC FAR
ASSUME CS:CSEG,DS:CSEG,ES:CSEG
BEGIN:
START EQU $
; Header for DOS Device Drivers
NEXT_DEV DD -1 ; fake pointer to next device driver
ATTRIBUTE DW 0C000H ;character device with IOCTL capability
STRATEGY DW XSTK_STRAT ;pointer to function which queues request header
FUNC_CALL DW XSTK_FUNC ;pointer to operating functions switch
DEV_NAME DB 'XSTK ' ;8-byte device name field
;
; Pointer to function request from DOS
RH_OFF DW ?
RH_SEG DW ?
;
; Function Address Table for DOS Requests
FUNTAB LABEL BYTE
DW INIT ; initialize device
DW MEDIA_CHECK ; do a media check (block dev only)
DW BUILD_BPB ; build BPB " " "
DW IOCTL_IN ; IOCTL input
DW INPUT ; normal input (read device)
DW ND_INPUT ; non-destructive input no wait
DW IN_STAT ; report input status
DW IN_FLUSH ; flush input
DW OUTPUT ; output (write to device)
DW OUT_VERIFY ; output with verify
DW OUT_STAT ; report output status
DW OUT_FLUSH ; flush output
DW IOCTL_OUT ; IOCTL output
;
bugout dd 0B8000000h ; screen address for yell macro
;
; Internal Data
BOTMEM DW ? ; start of stack storage space
TOPMEM DW ? ; end of storage (BOTMEM + 32K)
RECSIZE DW ? ; size of each structure to store, in bytes
CURRENT DW ? ; address after current "top of stack" - free spot
NUM2READ DW 0 ; number of bytes left to read to make full recsize
NUM2WRITE DW 0 ; number left to write
; *end local data
;
;
;
; Device Strategy - set pointer to request header from DOS
XSTK_STRAT: MOV CS:RH_SEG,ES
MOV CS:RH_OFF,BX
RET
;
; Device Interrupt Handler
XSTK_FUNC: ;preserve machine state
PUSHF
CLD
PUSH DS
PUSH ES
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
; Set DS to CS value
PUSH CS
POP DS
; Load ES and BX with RH_SEG and RH_OFF
LES BX,DWORD PTR CS:RH_OFF
; Branch to correct function in FUNTAB based on function code from DOS
MOV AL,ES:[BX+2] ; get function code byte
XOR AH,AH
SHL AL,1 ; make it into offset into FUNTAB
LEA DI,FUNTAB ; get address of FUNTAB base
ADD DI,AX
JMP WORD PTR[DI] ; jump to function code
;
;
;
; Functions not supported:
;
MEDIA_CHECK:
BUILD_BPB:
ND_INPUT:
OUT_VERIFY:
MOV ES:WORD PTR [BX+3],0100H ; set status DONE, NOERROR
JMP EXIT
;************************************************************
;
; Device Initialization
INIT: MOV AX,OFFSET STORAGE
MOV BOTMEM,AX ; set lower limit
MOV CURRENT,AX ; set current record address
ADD AX,32768 ; add 32K for top limit
MOV TOPMEM,AX
MOV ES:[BX+14],AX ; return end of XSTK space
MOV ES:[BX+16],CS ; and segment into request hdr
MOV RECSIZE,1 ; default recsize = 1 byte
MOV WORD PTR ES:[BX+3],0100H ;set status word to DONE, NOERROR
JMP EXIT
;
;************************************************************
;
IOCTL_IN: ; report record size
MOV CX,WORD PTR ES:[BX+18] ; get #bytes requested
LEA SI,RECSIZE
LES DI,DWORD PTR ES:[BX+14]
REP MOVSB
LES BX,DWORD PTR CS:RH_OFF
MOV ES:WORD PTR [BX+3],0100H ; set status DONE, NOERROR
JMP EXIT
;************************************************************
IOCTL_OUT: ; change record size
MOV CX,WORD PTR ES:[BX+18]
LEA DI,RECSIZE
PUSH DS
LDS SI,DWORD PTR ES:[BX+14]
POP ES
REP MOVSB
LES BX,DWORD PTR CS:RH_OFF
MOV ES:WORD PTR [BX+3],0100H ; set status DONE, NOERROR
JMP EXIT
;************************************************************
;
IN_STAT:
OUT_STAT: ; BUSY if any records stacked, DONE if empty?
MOV ES:WORD PTR [BX+3],0100H ; set status DONE, NOERROR
JMP EXIT
;************************************************************
;
IN_FLUSH:
OUT_FLUSH: ; empty stack
MOV ES:WORD PTR [BX+3],0100H ; set status DONE, NOERROR
JMP EXIT
;************************************************************
; Primary I/O Functions
;
; ES:[BX]+14 = offset of buffer in calling program
; ES:[BX]+16 = segment of buffer
; ES:[BX]+18 = size of buffer
;
;
;
INPUT: ; pop record from stack to calling program's buffer
yell R
CMP NUM2WRITE,0
JE CHKRED
MOV AX,NUM2WRITE ;OUTPUT didn't push full record - adj CURRENT
ADD CURRENT,AX ; set to record boundary, end of last rec writ
CHKRED: MOV SI,CURRENT ; set SI to next byte position
CMP NUM2READ,0 ; any bytes left to read to fill RECSIZE?
JG PULLIT
yell n
MOV AX,RECSIZE ; starting a new record
MOV NUM2READ,AX
SUB SI,RECSIZE ; sub record size from CURRENT
CMP SI,BOTMEM ; make sure full record can be pulled
JGE PULLIT
MOV WORD PTR ES:[BX+3],8130H ; else error 30H, stack empty
MOV WORD PTR ES:[BX+18],0 ; no bytes transferred
yell e
JMP EXIT
PULLIT: MOV CX,WORD PTR ES:[BX+18] ; #bytes to move(ALWAYS 1,DOS 2.0)
SUB NUM2READ,CX
MOV DI,WORD PTR ES:[BX+14] ; get buffer offset + seg
MOV AX,WORD PTR ES:[BX+16]
MOV ES,AX
REP MOVSB ; copy record to program buffer from stack at SI
CMP NUM2READ,0 ; are we done with a record
JG NEWPTR
SUB SI,CS:RECSIZE ; reset to record start
yell d
NEWPTR: MOV CS:CURRENT,SI ; SI has been incr by CX in MOVSB
LES BX,DWORD PTR CS:RH_OFF ; reset to DOS request header
MOV WORD PTR ES:[BX+3],0100H ; set DONE, NOERROR
JMP EXIT
;*************************************************************
;
OUTPUT: ; push record from calling program buffer onto stack storage
yell W
CMP NUM2READ,0
JE CHKWRIT
MOV AX,RECSIZE ; INPUT didn't take full record - adj CURRENT
SUB AX,NUM2READ
SUB CURRENT,AX ; set to record boundary
CHKWRIT: MOV DI,CURRENT ; set DI to next byte position
CMP NUM2WRITE,0 ; any bytes left to write to fill RECSIZE?
JG STUFFIT
yell n
MOV AX,RECSIZE ; starting a new record
MOV NUM2WRITE,AX
MOV DX,DI
ADD DX,RECSIZE ; add record size to CURRENT
CMP TOPMEM,DX ; make sure full record can be stored
JNG STUFFIT
MOV WORD PTR ES:[BX+3],8120H ; else error 20H, stack full
MOV WORD PTR ES:[BX+18],0 ; no bytes transferred
yell f
JMP EXIT
STUFFIT: MOV CX,WORD PTR ES:[BX+18] ; #bytes to move(ALWAYS 1,DOS 2.0)
SUB NUM2WRITE,CX
PUSH DS ; need this for ES later
LDS SI,DWORD PTR ES:[BX+14] ; get buffer offset + seg
POP ES ; set to old DS value to reference stack space
REP MOVSB ; copy record from program buffer to stack at DI
MOV CS:CURRENT,DI ; DI has been incr by CX in MOVSB
LES BX,DWORD PTR CS:RH_OFF ; reset to DOS request header
MOV WORD PTR ES:[BX+3],0100H ; set DONE, NOERROR
JMP EXIT
;*********************************************************
;
; Restore registers and exit
EXIT: POP SI
POP DI
POP DX
POP CX
POP BX
POP AX
POP ES
POP DS
POPF
RET
;
;
; Align stack storage to start on a paragraph boundary - fits all storage types
if ($-START) MOD 16
ORG ($-START)+16-(($-START) MOD 16)
endif
;
STORAGE EQU $ ; start of stack storage space
;
XSTK ENDP
CSEG ENDS
END BEGIN
T)+16-(($-START) MOD 16)
endif
;
STORAGE EQU $ ; start of stack storage space
;
X