;    File              : $Workfile: SERPAR.ASM$
;
;    Description       :
;
;    Original Author   : DIGITAL RESEARCH
;
;    Last Edited By    : $CALDERA$
;
;-----------------------------------------------------------------------;
;    Copyright Work of Caldera, Inc. All Rights Reserved.
;      
;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
;    CIVIL LIABILITY.
;-----------------------------------------------------------------------;
;
;    *** Current Edit History ***
;    *** End of Current Edit History ***
;
;    $Log$
;    SERPAR.ASM 1.7 93/07/22 19:44:27
;    switch over to REQUEST.EQU
;    SERPAR.ASM 1.6 93/07/19 18:57:59
;    Add header
;
;    ENDLOG

	include BIOSGRPS.EQU
	include	DRMACROS.EQU		; standard DR macros
	include	IBMROS.EQU		; ROM BIOS equates
	include	REQUEST.EQU		; request header equates
	include	DRIVER.EQU		; device driver equates

page
CGROUP	group	CODE, RCODE, ICODE

CG	equ	offset CGROUP

	Assume	CS:CGROUP, DS:CGROUP, ES:CGROUP, SS:CGROUP

CODE	segment 'CODE'

	extrn	endbios:word		; for device driver INIT function
	extrn	serparFlag:byte
	extrn	serparChar:byte

CODE	ends

RCODE	segment 'RCODE'

	Public	SerParCommonTable

SerParCommonTable:
	db	19			; Last supported function
	dw	CG:dd_init		; 0-initialize driver
	dw	CG:dd_error		; 1-media change check (disks only)
	dw	CG:dd_error		; 2-build BPB (disks only)
	dw	CG:dd_error		; 3-IOCTL string input
	dw	CG:dd_input		; 4-input
	dw	CG:dd_poll		; 5-nondestructive input (char only)
	dw	CG:dd_instat		; 6-input status (char only)
	dw	CG:dd_inflush		; 7-input flush
	dw	CG:dd_output		; 8-output
	dw	CG:dd_output		; 9-output with verify
	dw	CG:dd_outstat		; 10-output status (char only)
	dw	CG:dd_outflush		; 11-output flush (char only)
	dw	CG:dd_error		; 12-IOCTL string output
	dw	CG:dd_open		; 13-device open
	dw	CG:dd_close		; 14-device close
	dw	CG:dd_error		; 15-removable media check (disks only)
	dw	CG:dd_error		; 16-n/a
	dw	CG:dd_error		; 17-n/a
	dw	CG:dd_error		; 18-n/a
	dw	CG:dd_genioctl		; 19-generic IOCTL


	Assume	DS:CGROUP, ES:Nothing, SS:Nothing

page
driver	proc	near

dd_error:	; used for all unsupported driver functions
;--------
	mov	ax,RHS_ERROR+3		; "invalid command" error
	ret

	page

poll_char:
;---------
;	exit:	ZF = 1  =>  no character ready
;		ZF = 0  =>  AL = character

	cmp	serparFlag[si],TRUE	; do we have local character?
	 jne	poll_c2			; skip if not
	mov	al,serparChar[si]	; get the local charcater
	jmps	poll_c4			;    and return it
poll_c2:				; need to check ROS keyboard status
	mov	ah,3			; get serial status status
	int	ASYNC_INT		; read serial status
	test	ah,1			; test "received data" bit
	 jz	poll_c9			; skip if no character there
	mov	ah,2			; read the character
	int	ASYNC_INT		; character returned in AL
	mov	serparChar[si],al	; save it for look ahead
	mov	serparFlag[si],TRUE	; we've got a local character
poll_c4:				; return the character in AL
	or	ah,TRUE			; indicate "ready" status
	ret
poll_c9:
	sub	ax,ax			; indicate "not-ready" status
	ret				; (driver is busy)


char_read:
;---------
    xor ax,ax 
	cmp	serparFlag[si],TRUE	; do we have local character?
	 jne	rdchr1
	mov	serparFlag[si],FALSE	; tell them buffer is invalid
	mov	al,serparChar[si]	; get the local character
	ret				;    and return it
rdchr1:
	mov	ah,2			; read character from serial port
	int	ASYNC_INT		; call the ROM BIOS
	and	ah,0eh			; only worry about these error bits
	ret				; and return the character

	page
dd_input:	; 4-input
;--------
	push	es			; save ES (-> request header!)
	mov	cx,es:RH4_COUNT[bx]	; get # of characters to output
	 jcxz	input9			; return if nothing to input
	sub	dx,3			; convert to serial port #
	 jb	input9			; return none read if parallel port
	mov	si,dx			; SI = serial port index
	les	di,es:RH4_BUFFER[bx]	; get address of string to input
input2:
	call	char_read		; read 8-bit character
	test	ah,ah			; did we read OK ?
	 jnz	input9			; if we have an error stop now
	stosb				; store it in input buffer
	loop	input2			; repeat for all characters
input9:
	pop	es
	sub	es:RH4_COUNT[bx],cx	; update to actual number xfered
	sub	ax,ax
	ret

dd_poll:	; 5-nondestructive input (console only)
;-------
	cmp	dx,3			; check if a parallel port
	 jb	poll_busy		;  they are never ready
	sub	dx,3
	mov	si,dx			; SI = serial port index
	call	poll_char		; check keyboard status
	 jz	poll_busy
	mov	es:RH5_CHAR[bx],al	; return the character
	sub	ax,ax
	ret
poll_busy:
	mov	ax,RHS_BUSY		; indicate no character waiting
	ret

dd_instat:	; 6-input status (char only)
;---------
	cmp	dx,3			; check if a parallel port
	 jb	poll_busy		;  if so it's always busy
	sub	dx,3
	mov	si,dx			; SI = serial port index
	call	poll_char		; check keyboard status
	 jz	poll_busy
	sub	ax,ax			; indicate "not ready" status
	ret

dd_inflush:	; 7-input flush
;---------
	cmp	dx,3			; check if a parallel port
	 jae	inflsh1			; skip if serial port
	mov	ax,RHS_ERROR+11		; return "read error" if attempting
	ret				;  to read from the parallel port
inflsh1:
	sub	dx,3
	mov	si,dx			; SI = serial port index
inflsh2:
	call	poll_char		; check keyboard status
	 jz	inflsh_ret		; skip if not ready
	call	char_read		; else read next character
	jmps	inflsh2			; repeat until buffer empty
inflsh_ret:				; keyboard buffer empty
	sub	ax,ax			; return success
	ret

dd_output:	; 8-output
;---------
	mov	cx,es:RH4_COUNT[bx]	; get # of characters to output
	 jcxz	output5			; return if nothing to output
	push	es			; save ES (-> request header!)
	les	si,es:RH4_BUFFER[bx]	; get address of string to output
	sub	dx,3			; test if parallel port
	 jae	output2			; skip if serial port
	add	dx,3			; back to parallel port number
output1:
	lods	es:byte ptr [si]	; get next character to output
	mov	ah,0			; output AL to parallel port
	int	PRINTER_INT		; output to parallel port
	mov	al,2			; "not ready" error
	test	ah,PRN_TIMEOUT		; printer not ready?
	 jnz	output4			;  yes, return error
	mov	al,9			; "printer out of paper" error
	test	ah,PRN_PAPER		; printer out paper?
	 jnz	output4			;  yes, return error
	inc	ax			; "write fault" error
	test	ah,PRN_ERROR		; test if other errors
	 jnz	output4			; skip if any errors occurred
	loop	output1			; else repeat for all characters
	jmps	output4			; return successfully when done

output2:				; output is for serial port
	lods	es:byte ptr [si]	; get next character to output
	mov	ah,1			; output AL to serial port
	int	ASYNC_INT		; output to serial port
	mov	al,2			; "not ready" error
	test	ah,AUX_ERROR		; test if time out etc.
	 jnz	output4			; skip if any errors occurred
	loop	output2			; else repeat for all characters
output4:
	mov	ah,RHS_ERROR shr 8	; assume an error code
	pop	es
	sub	es:RH4_COUNT[bx],cx	; update to actual number xfered
	 jz	output6			; none xfered is an error
output5:
	sub	ax,ax			; return successfully when done
output6:
	ret



dd_outstat:	; 10-output status (char only)
;----------
	cmp	dx,3			; test if parallel port
	 jae	outstat1
	mov	ah,2			; read parallel port status
	int	PRINTER_INT		; call the ROM BIOS
	test	ah,80h			; test "not busy" bit
	 jnz	outstat_ready		; if not busy then ready for output
	jmps	outstat_busy		;    else we must be still busy
outstat1:
	sub	dx,3
	mov	ah,3			; get status for serial port
	int	ASYNC_INT
	test	ah,20h			; transmit buffer register emmpty?
	 jz	outstat_busy
	test	al,20h			; data set ready?
	 jz	outstat_busy
outstat_ready:
	sub	ax,ax			; always ready, return no busy
	ret
outstat_busy:
	mov	ax,RHS_BUSY
	ret

dd_outflush:	; 11-output flush (char only)
;-----------
	sub	ax,ax			; unbuffered, perform no operation
	ret


	page
dd_open:	; 13-device open
;-------
	sub	ax,ax			; no operation
	ret


dd_close:	; 14-device close
;--------
	sub	ax,ax			; no operation
	ret


	page
dd_genioctl:	; 19-generic IOCTL
;-----------
    sub ax,ax           
	ret

driver	endp

RCODE	ends				; end of device driver code

page

ICODE	segment 'ICODE'			; initialization code

dd_init:	; 0-initialize driver
;-------
	cmp	dx,3			; check if serial or parallel
	 jae	init1			; skip if serial port setup
	mov	ah,1			; initialize parallel port
	int	PRINTER_INT		; call the ROM BIOS
	jmps	init2
init1:
	sub	dx,3
	mov	ah,0			; initialize serial port
	mov	al,0A3h			; 2400 Bd, no parity, 8 data, 1 stop
	int	ASYNC_INT		; call the ROM BIOS
init2:
	les	bx,REQUEST[bp]		; ES:BX -> request header

	mov	ax,endbios
	mov	es:RH0_RESIDENT[bx],ax	; set end of device driver
	mov	es:RH0_RESIDENT+2[bx],ds

	sub	ax,ax			; initialization succeeded
	ret				; (BIOS init always does...)

ICODE	ends

	end
