mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-24 17:04:19 +00:00
225 lines
6.0 KiB
Plaintext
225 lines
6.0 KiB
Plaintext
;****************************************************************
|
||
;* *
|
||
;* Queue system subroutines: Q System must be owned *
|
||
;* before calling any of the following routines *
|
||
;* *
|
||
;****************************************************************
|
||
|
||
queverify: ; check QLR for existence of QD address
|
||
;--------- ---------------------------------------
|
||
; entry: U_WRKSEG:DX = offset of QPB
|
||
; exit: CX = 0 if queue is found
|
||
; CX = E_NO_QUEUE error code, if not
|
||
; BX=SI=QD offset
|
||
; ES,DX preserved
|
||
|
||
push es ;save UDA
|
||
mov es,u_wrkseg
|
||
mov bx,dx ;ES:BX->QPB
|
||
mov bx,es:qpb_qaddr[bx] ;get QD from user's QPB
|
||
pop es ;restore UDA
|
||
lea si,qlr-q_link
|
||
qv_nxt:
|
||
mov si,q_link[si] ;SI addresses of valid QDs
|
||
test si,si ! jz qv_nqf
|
||
cmp bx,si ! jne qv_nxt
|
||
xor cx,cx ! ret ;BX=SI=QD offset, return success
|
||
qv_nqf:
|
||
mov cx,e_no_queue ;couldn't find the queue
|
||
ret
|
||
|
||
getqdaddr:
|
||
;----------
|
||
; entry: DX = offset of QD in U_WRKSEG
|
||
; exit: DI = offset of QD in SYSDAT
|
||
;
|
||
; If QD address is within SYSDAT use it.
|
||
; Else get a QD from QDUL and set QF_TABLE flag.
|
||
; If Q_NMSGS=0 in QD then return error.
|
||
; If 0 length buffer needed, zero the Q_BUF field.
|
||
; If buffer space is within SYSDAT use it. Else get buffer
|
||
; from QMAU. Return the QD address within SYSDAT.
|
||
|
||
push dx ;save QD offset
|
||
mov bx,qdlen
|
||
call sysdat_chk
|
||
jcxz g_qul ;CX=0 if not within SYSDAT
|
||
mov ax,u_wrkseg ;# of paragraphs to U_WRKSEG
|
||
mov bx,ds
|
||
sub ax,bx ;from SYSDAT
|
||
mov cl,4 ! shl ax,cl ;make into # of bytes
|
||
pop di ;DI=QD in U_WRKSEG
|
||
add di,ax ;make QD relative to SYSDAT
|
||
jmps g_qd
|
||
g_qul:
|
||
mov di,qul ;get QD from QUL
|
||
test di,di ;DI=unused QD
|
||
jnz g_gotqd
|
||
pop dx
|
||
mov cx,e_no_qd ;no QD available
|
||
ret
|
||
g_gotqd:
|
||
mov ax,q_link[di]
|
||
mov qul,ax
|
||
pop si ;SI=QD in U_WRKSEG
|
||
push di ;save SYSDAT QD
|
||
mov cx,qdlen/2
|
||
; ES=UDA, DS=SYSDAT
|
||
mov ax,ds
|
||
mov ds,u_wrkseg ; DS:SI = QD in U_WRKSEG
|
||
push es ! mov es,ax ; ES:DI = QD in SYSDAT
|
||
rep movsw ; copy QD into QD in SYSDAT
|
||
mov ax,es ! mov ds,ax
|
||
pop es ; ES=UDA, DS=SYSDAT
|
||
pop di ; SYSDAT:DI -> New QD
|
||
or q_flags[di],qf_table ; Set "from table" flag
|
||
|
||
g_qd: ;DI=QD in SYSDAT
|
||
xor cx,cx ;CX=0
|
||
cmp q_nmsgs[di],cx ;must have one or more msgs
|
||
jne g_buflen ;or illegal queue
|
||
mov cx,e_no_qbuf
|
||
jmps g_qdfree
|
||
g_buflen: ;if MX or buffer length is zero
|
||
test q_flags[di],qf_mx ;0 Q_BUF field and return
|
||
jnz g_mx ;CX=0 to indicate success
|
||
cmp q_msglen[di],cx
|
||
jne g_getbuf
|
||
g_mx:
|
||
mov q_buf[di],cx
|
||
ret
|
||
g_getbuf: ;non 0 length buffer needed
|
||
cmp q_buf[di],0 ;is there a buffer specified?
|
||
je g_buf
|
||
mov ax,q_msglen[di] ;yes make sure it fits in SYSDAT
|
||
mul q_nmsgs[di] ;AX=needed buffer space
|
||
mov bx,ax
|
||
mov dx,q_buf[di]
|
||
call sysdat_chk
|
||
jcxz g_buf ;CX=0 not within SYSDAT
|
||
mov ax,u_wrkseg ;# of paragraphs to U_WRKSEG
|
||
mov bx,ds
|
||
sub ax,bx ;from SYSDAT
|
||
mov cl,4 ! shl ax,cl ;make into # of bytes
|
||
add q_buf[di],ax ;make buffer relative to SYSDAT
|
||
xor cx,cx ;indicate success
|
||
ret
|
||
|
||
g_buf: ;allocate buffer space to queue
|
||
call qspace
|
||
jcxz g_ret
|
||
mov cx,e_no_qbuf ;no buffer space
|
||
g_qdfree:
|
||
mov ax,qul ;error return QD to QUL
|
||
mov q_link[di],ax
|
||
mov qul,di ;CX = error code
|
||
g_ret:
|
||
ret
|
||
|
||
|
||
sysdat_chk:
|
||
;----------
|
||
; entry: DX = offset of data structure to check
|
||
; relative to U_WRKSEG
|
||
; BX = length of data structure
|
||
; exit: CX <> 0 if within SYSDAT
|
||
; or wrap around
|
||
; CX = 0 if not within SYSDAT
|
||
; SI,DI preserved
|
||
|
||
; Check data structure for being within SYSDAT
|
||
; Also check that data structure doesn't wrap
|
||
; around at 64K, or 1 megabyte.
|
||
|
||
add dx,bx ;find end of data structure
|
||
jc sc_no ;check for 64K wrap around
|
||
add dx,0fh
|
||
mov cl,4 ;round up to next paragraph
|
||
shr dx,cl ;1st paragraph after struct relative
|
||
add dx,u_wrkseg ;to U_WRKSEG
|
||
jc sc_no ;next paragraph after struct
|
||
;check for 1 MB wrap around
|
||
mov ax,sysdat
|
||
cmp dx,ax ;check for below SYSDAT
|
||
jb sc_no
|
||
add ax,1000h ;check for above SYSDAT
|
||
cmp ax,endseg ;must be within 64k and ENDSEG
|
||
jb sc_end ;(use the smaller of the 2)
|
||
mov ax,endseg
|
||
sc_end:
|
||
cmp dx,ax ;DX=next paragraph,
|
||
ja sc_no
|
||
mov cl,1 ;indicate within SYSDAT
|
||
ret
|
||
sc_no:
|
||
xor cx,cx
|
||
ret
|
||
|
||
qspace:
|
||
;------
|
||
; entry: DI = QD address
|
||
; exit: CX = 0 if ok else error code
|
||
; DI preserved
|
||
; Allocate buffer space for QD
|
||
; The QMAU describes the Memory Allocation Unit
|
||
; for the queues. QMAU is set up by GENCCPM or GENSYS.
|
||
|
||
mov ax,q_msglen[di] ;compute size of buffer
|
||
mul q_nmsgs[di] ;AX=size of request
|
||
xor cx,cx
|
||
push cx ! push cx ! push ax ;call MALLOC
|
||
push ax ! push cx ;with MPB on stack
|
||
mov dx,sp ! mov ax,ss
|
||
mov ds,ax
|
||
mov bx,offset qmau
|
||
push di ;save QD
|
||
mov cx,f_maualloc ;go through OSIF to
|
||
call osif ;get U_WRKSEG=SS
|
||
pop di ;DI=QD
|
||
mov ds,sysdat
|
||
cmp cx,0 ! jne qspace_ret
|
||
mov bp,sp
|
||
mov ax,mpb_start[bp]
|
||
mov q_buf[di],ax ;address of buffer
|
||
|
||
qspace_ret:
|
||
add sp,10 ;pop MPB from stack
|
||
ret
|
||
|
||
remqd:
|
||
;-----
|
||
; Place QD on queue unused list
|
||
; entry: DS:DI = QD address
|
||
; exit: none
|
||
|
||
mov ax,q_flags[di]
|
||
and ax,qf_table ! jz rqd_exit
|
||
mov ax,qul ! mov q_link[di],ax
|
||
mov qul,di
|
||
jmps qrelease
|
||
rqd_exit:
|
||
ret
|
||
|
||
|
||
qrelease:
|
||
;--------
|
||
; entry: DI = QD address
|
||
; exit : none
|
||
;
|
||
; Release buffer space for QD.
|
||
; If the released space is ajacent to another
|
||
; free area, they are joined in the SAT table.
|
||
; The QMAU describes the Memory Allocation Unit
|
||
; for the queues. QMAU is set up by GENCCPM or GENSYS.
|
||
|
||
|
||
mov ax,q_buf[di]
|
||
mov cx,offset qmau
|
||
push ax ! push ax ! push cx ;MFPB on stack
|
||
mov cx,f_maufree
|
||
mov dx,sp ! mov ax,ss ! mov ds,ax
|
||
call osif
|
||
add sp,6 ;pop MFPB from stack
|
||
mov ds,cs:sysdat ;DS=SYSDAT
|
||
ret
|
||
|