Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

225 lines
6.0 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;****************************************************************
;* *
;* 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