
;*****************************************************
;*
;*	Queue Routines
;*
;*****************************************************

;===========		=======================
makeq_entry:		; Create a System Queue
;===========		=======================
;	input : DX = address of QD in u_wrkseg
;		u_wrkseg = segment of QD
;	output: BX = 0 if okay , 0ffffh if error
;		CX = Error Code

	call getqdaddr ! mov di,dx	;DI->QD addr
	cmp cx,0 ! je qm_chk
	    mov bx,0ffffh ! ret
		;Make sure this queue doesn't already exist
qm_chk:	pushf ! cli
	push es ! mov es,sysdat
	mov si,(offset qlr)-q_link
qm_nxt:	mov si,q_link[si]
	cmp si,0 ! je qm_go
	    push di ! push si ! mov cx,qnamsiz/2
	    add di,q_name ! add si,q_name
	    repe cmpsw
	    pop si ! pop di ! jne qm_nxt
			;Names match
		mov bx,0ffffh ! mov cx,e_q_inuse
		pop es ! popf ! ret
qm_go:	pop es
		;We have a QD initialize it
	mov dx,0 ! mov q_dq[di],dx
	mov q_nq[di],dx ! mov q_msgcnt[di],dx
	mov q_msgout[di],dx
		;put it on QLR
	mov ax,qlr ! mov q_link[di],ax
	mov qlr,di ! sub bx,bx
	mov cx,bx ! popf ! ret

;===========		======================
openq_entry:		; Find an active Queue
;===========		======================
;	input:	DX = address of QPB
;		     segment is u_wrkseg
;	output:	Fills QPB with appropriate info
;		BX = 0 if okay, 0ffffh if not
;		CX = Error Code

	pushf ! cli
	push es ! mov es,u_wrkseg
	mov si,(offset qlr)-q_link ! mov di,dx
qo_nqd:	mov si,q_link[si]
	cmp si,0 ! je qo_noq
	    push di ! push si ! mov cx,qnamsiz/2
	    add si,q_name ! add di,qpb_name
	    repe cmpsw
	    pop si ! pop di ! jne qo_nqd
			;Names match
		mov es:qpb_qaddr[di],si
		sub bx,bx ! mov cx,bx
		pop es ! popf ! ret
qo_noq:			;No name matches
	mov cx,e_no_queue ! mov bx,0ffffh
	pop es ! popf ! ret

;=============		=======================
deleteq_entry:		; Delete a System Queue
;=============		=======================
; Takes a qd off the qlr and places it in the qul.
;	input:	DX = offset of QPB
;			in u_wrkseg
;	output:	BX = 0 if ok, 0ffffh if bad
;		CX = Error Code

	pushf ! cli
	push es ! mov es,u_wrkseg
	mov di,dx ! add di,qpb_qaddr
	mov di,es:[di]
	mov ax,q_dq[di] ! mov dx,q_nq[di]
	add dx,ax ! jnz qd_use
	    mov bx,(offset qlr)-q_link
qd_nqd:	    mov si,q_link[bx]
	    cmp si,0 ! jz qd_noq
		cmp si,di ! jne qd_neq
		    mov ax,q_link[si]!mov q_link[bx],ax
		    call remqd
		    mov bx,0 ! mov cx,bx
		    pop es ! jmps qd_e
qd_neq:		mov bx,si ! jmps qd_nqd
qd_noq:	    mov cx,e_q_notactive ! jmps qd_be
qd_use:	pop ax ! mov cx,e_q_inuse
qd_be:	mov bx,0ffffh
qd_e:	popf ! ret

;===========		============
readq_entry:		; Read Queue
;===========		============
	mov ax,0 ! jmps readq

;============
creadq_entry:		; Conditional Read Queue
;============
	mov ax,0ffffh
	; jmps readq

readq:		; Read message from queue
;-----		-------------------------
; If no buffer is available, the process is placed into the DQ list
; of the queue and waits until another process writes into the queue.
;	input:	DX = address of qpb in u_wrkseg
;		AX = 0ffffh if conditional
;		     0 if not
;	output:	BX = 0 if okay
;		     0ffffh if error
;		CX = Error Code

	push ax ! call queverify ! pop ax
	cmp cx,0 ! je qr_ver
	    mov bx,0ffffh ! ret
qr_ver:	push es ! mov es,u_wrkseg
	mov si,dx			;es:[si]->QPB
	mov bx,es:qpb_qaddr[si]		;bx->QD
	mov di,es:qpb_buffptr[si]	;es:[di]->buff
	pushf ! cli
	mov cx,q_msgcnt[bx]
	cmp cx,0 ! jne qr_gmsg
	    inc ax ! jnz qr_wait
		mov bx,0ffffh ! mov cx,e_q_empty
		popf ! pop es ! jmps qr_exit
qr_wait:    lea dx,q_dq[bx]		;DX=addr of DQ List
	    mov bx,rlr ! mov p_stat[bx],ps_dq	;status=DQ
	    popf ! pop es ! push si
	    mov cx,f_sleep ! call mpmif		;Sleep on DQ List
	    pop dx ! jmps qr_ver
qr_gmsg:mov cx,q_msglen[bx]
	cmp cx,0 ! jne qr_lmsg
	    mov cx,q_flags[bx]	; msglen=0
	    and cx,qf_mx ! jz qr_finish
		mov ax,rlr		;Its a MX queue
		mov q_buf[bx],ax	;BUF = PD addr (owner)
		jmps qr_finish
qr_lmsg:			; msglen > 0
	mov ax,q_msgout[bx] ! push ax
	mul cx ! add ax,q_buf[bx]
	mov si,ax ! rep movsb
	pop ax ! inc ax
	cmp ax,q_nmsgs[bx] ! jne qr_nend
	    mov ax,0
qr_nend:mov q_msgout[bx],ax
qr_finish:
	dec q_msgcnt[bx] ! popf
	mov si,bx ! pop es
	lea dx,q_nq[si]			;DX = NQ List
	mov cx,f_wakeup			;Wakeup a process
	call mpmif			; waiting to write
	mov cx,0 ! mov bx,cx
qr_exit:ret

;============		=============
writeq_entry:		; Write Queue
;============		=============
	mov ax,0 ! jmps writeq

;=============		=========================
cwriteq_entry:		; conditional Write Queue
;=============		=========================
	mov ax,0ffffh
	;jmps writeq

writeq:		; Write message into queue
;------		--------------------------
; If no buffer is available, the process is placed into the NQ list
; of the queue and waits until another process reads from the queue.
;	input:	DX = address of qpb in u_wrkseg
;		BX = pd address
;		AX = 0ffffh if conditional
;		     0 if not
;	output:	BX = 0 if okay
;		     0ffffh if error
;		CX = Error Code

	push ax ! call queverify ! pop ax
	cmp cx,0 ! je qw_ver
	    mov bx,0ffffh ! ret
qw_ver:	push es ! mov es,u_wrkseg
	mov di,dx			; es:[di]->QPB
	mov bx,es:qpb_qaddr[di]		; bx -> QD
	mov si,es:qpb_buffptr[di]	; es:[si]->QPB.buff
	pushf ! cli
	mov cx,q_msgcnt[bx]
	cmp cx,q_nmsgs[bx] ! jne qw_gbuf
	    inc ax ! jnz qw_wait
		popf ! pop es ! mov bx,0ffffh
		mov cx,e_q_full ! jmps qw_exit
qw_wait:    lea dx,q_nq[bx]			;DX = NQ List
	    mov bx,rlr ! mov p_stat[bx],ps_nq	;status=NQ
	    popf ! pop es ! push si
	    mov cx,f_sleep ! call mpmif		;Sleep on NQ List
	    pop dx ! jmps qw_ver		;try again
qw_gbuf:mov cx,q_msglen[bx]			;there is a buffer
	cmp cx,0 ! je qw_fin
	    mov ax,q_msgout[bx] ! add ax,q_msgcnt[bx]
	    cmp ax,q_nmsgs[bx] ! jb qw_move
		sub ax,q_nmsgs[bx]
qw_move:    mul cx ! add ax,q_buf[bx]
	    mov di,ax				;DI=start of new msg
	    push ds ! push es ! pop ds ! pop es
	    rep movsb				; copy message
	    push ds ! push es ! pop ds ! pop es
qw_fin:	inc q_msgcnt[bx]
	mov cx,q_flags[bx] ! and cx,qf_mx
	jz qw_nomx
	    mov q_buf[bx],0		;an MX queue,no owner
qw_nomx:mov si,bx ! popf ! pop es
	lea dx,q_dq[si]			;DX = DQ List
	mov cx,f_wakeup			;Wakeup a process trying
	call mpmif			; to read a message
	sub bx,bx ! mov cx,bx
qw_exit:ret


queverify:		; check QLR for existence of QD address
;---------		---------------------------------------
;	input:	DX = offset of QPB
;	output:	CX = error code

	push ds ! mov ds,u_wrkseg
	mov bx,dx ! mov si,qpb_qaddr[bx] ! pop ds
	mov bx,offset qlr
qv_nxt:	mov bx,q_link[bx]
	cmp bx,0 ! jne qv_chk
	    mov cx,e_no_queue ! ret
qv_chk:	cmp bx,si ! je qv_fnd
	    jmps qv_nxt
qv_fnd:	mov cx,0 ! ret
