.MCALL	.MODULE
.MODULE	INDDEV,VERSION=05,COMMENT=<General Device Table Search>

; Copyright (c) 1998 by Mentec, Inc., Nashua, NH.
; All rights reserved
;
; This software is furnished under a license for use only on a
; single computer system and  may  be  copied  only  with  the
; inclusion of the above copyright notice.  This software,  or
; any other copies thereof, may not be provided  or  otherwise
; made available to any other person except for  use  on  such
; system and to one who agrees to these license  terms.  Title
; to  and  ownership of the software shall at all times remain
; in Mentec, Inc.
;
; The information in this document is subject to change without
; notice and should not be construed as a commitment by Digital
; Equipment Corporation, or Mentec, Inc.
;
; Digital and Mentec  assume  no  responsibility for the use or
; reliability of its software on equipment which is not supplied
; by Digital  or Mentec,  and listed  in the  Software  Product
; Description.

	.ENABL	GBL,LC

;+
; This module contains a general use routine to scan the UNAM and PNAME
; tables in RMON and return the physical device name of a logical device.
;
;	R1 ->	FDB  (F$DNAM CAN BE A LOGICAL DEVICE NAME)
;
; Rewritten for RT-11 V5.5 to accomodate extended unit devices.
;
; This routine is called as a last-ditch attempt to get a physical device
; name when .TESTDEVICE (in INDUTL) cannot .FETCH the requested handler.
; It crawls through the $PNAM* and $UNAM* tables in RMON, and generates
; every possible device/unit combination until a match is found.
;
; This will become much more simple when/if RT-11 provides a device
; name translation service.  .DSTATUS doesn't return enough information.
;-

	.SBTTL	System macros

;+
;External macros.
;-

	.MCALL	GCLDF$, DEFIN$, FDBDF$, FERDF$, RT5DF$
	.MCALL	.GVAL

DEFIN$				;Definitions for IND files
GCLDF$				;Define GCML block offsets and symbols
FDBDF$				;Define FDB offsets
FERDF$				;Define file service error codes
RT5DF$				;RT11 definitions

	.GLOBL	SYSPTR,$PNPTR

	.SBTTL	Definitions

$CNFG3	=: 466			; Configuration word 3
	CF3.64 =: 000400	; Extended Unit support


	OPSECT	INDDEV


	.SBTTL	INDDEV - Code
	.ENABL	LSB

INDDEV::
	CALL	$SAVAL			; Save all registers
;+
; Determine the address and size of the device tables.
;-
	.GVAL	#EMTBLK,#$CNFG3		; Get config word 3
	BIC	#^C<CF3.64>,R0		; mask out unneeded bits,
	MOV	R0,EXTUNI		; save extended unitness of RMON

	.GVAL	#EMTBLK,#$PNPTR
	MOV	@#SYSPTR,R5		; R5 -> RMON.
	MOV	R0,R4			; R4 = offset from RMON to $PNAME.
	ADD	R5,R4			; R4 -> $PNAME.
	MOV	R4,R3			; R3 -> $PNAME.
	MOV	R4,$PNAMA		; Save it.

10$:	CMP	(R3)+,#-1		; Search for end of $ENTRY table.
	BNE	10$			; Keep going.
	TST	-(R3)			; R3 -> first word above $ENTRY.
	SUB	R4,R3			; R3 = bytes in combined tables.

	ASR	R3			; Make it bytes per $UNAM(1,2) table.
	MOV	R3,R0			; Copy it. (DK/SY slot NOT included).
					; R0 contains $SLOT*2
	MOV	R4,R2			; R2 -> $PNAME.
	SUB	R0,R2			; R2 -> $UNAM2+4.
	CMP	-(R2),-(R2)		; R2 -> $UNAM2.
	MOV	R2,R3			; Save the pointer to $UNAM2

	SUB	R0,R2			; R2 -> $UNAM1+4.
	CMP	-(R2),-(R2)		; R2 -> $UNAM1.

; R0 = $SLOT*2
; R1 = address of FDB
; R2 -> $UNAM1
; R3 -> $UNAM2
;
; Search through the UNAM2 table to see if the device name is a LOGICAL 
; name.  If so, put the equivalent physical name in the F$DNAM location.

	ASR	R0			; change $SLOT*2 to $SLOT*1
	MOV	R0,SLOTS		; save it that way
	BITB	(R0)+,(R0)+		; add 2 to counter for SY & DK
	ADD	#F$DNAM,R1		; point to FDB's device name field
20$:	CMP	(R3)+,@R1		; is this logical the one?
	BNE	30$			; branch if not
	MOV	@R2,@R1			; substitute physical name
	BR	40$			;  and use it.

30$:	TST	(R2)+			; bump phys name pointer
	DEC	R0
	BGT	20$			; keep looking...

;+
; For each PNAME entry, create all possible device name forms.  Compare 
; them one by one against the physical device name, and return it if 
; found.  Calculate the address of the $PNAM2 table (whether it exists 
; or not).
;-

40$:	MOV	$PNAMA,R2		; point to permanent names
	MOV	SLOTS,R5		; start calculating $PNAM2's adrs
	MOV	R5,R4			; keep a copy to count with
	ASL	R5			; $SLOT*2
	ASL	R5			; $SLOT*4
	MOV	R5,-(SP)
	ASL	R5			; $SLOT*8
	ADD	(SP)+,R5		; $SLOT*12.
	ADD	R2,R5			; add $PNAME entry address
50$:	TST	(R5)+			; allow for extra word in $ENTRY
					;  or advance to next $PNAM2 entry
	CLR	R3			; potential unit number here

; Try forms XX and XXn

	MOV	@R2,R0			; Get the PNAME entry
	BEQ	100$			; if blank, go to next.
	CMP	R0,@R1			; is it just XX?
	BEQ	120$			; Yes!  Oh wow, I can't believe it!
	ADD	#^R  0,R0
60$:	CMP	R0,@R1			; is it XXn?
	BEQ	120$			; Yes.  Use it.
	INC	R0			; next RAD50 unit,
	INC	R3			; next integer unit
	CMP	R3,#7			; over the limit in this format?
	BLOS	60$			; no, try some more.

; If running on an extended-unit monitor, try forms X, Xn, and Xnn

	TST	EXTUNI			; Is RMON supporting 64-units?
	BEQ	100$			; If not, done checking this PNAME

; R5 now points to the corresponding $PNAM2 entry

	CMP	@R5,@R2			; Does this device do extended units?
	BEQ	100$			; branch if not.
	CLR	R3			; reset potential unit number
	MOV	@R5,R0			; Get the single-letter name
	CMP	R0,@R1			; Did user pass X?
	BEQ	120$
	ADD	#^R 0 ,R0		; try Xn
70$:	CMP	R0,@R1			; Did user pass Xn?
	BEQ	120$
	ADD	#50,R0			; next RAD50 value in Xn series
	INC	R3			; next unit number
	CMP	R3,#7			; last in range?
	BLOS	70$

;+
; Ok.  Nothing yet.  Try all of the Xnn forms.
;
; R0 is our test name,
; R1 points to the FDB's device name,
; R2 holds the $PNAME entry pointer,
; R3 holds a unit number/counter
; R4 counts down PNAME entries
; R5 holds the $PNAM2 entry pointer,
; That's all.  'Gotta use the stack.
;-
	CLR	R3			; reset unit number
	MOV	@R5,R0			; Get the single-letter name
	ADD	#^R 00,R0		; Begin with X00
	MOV	#8.,-(SP)		; for each octade,
80$:	MOV	#8.,-(SP)		;  for each unit within octade,
90$:	CMP	R0,@R1			; Did user pass Xnn?
	BEQ	110$			; That's it. Fix stack and make name.
	INC	R0			; next RAD50 value in Xnn series
	INC	R3			; next unit number
	DEC	@SP			; last in octade?
	BGT	90$			; loop if not.
	TST	(SP)+
	ADD	#<^rX10-^rX08>,R0	; carry RAD50 digit
	DEC	@SP			; done?
	BGT	80$			; no, do another octade
	TST	(SP)+			; Not found.  Drop through.

; Not found yet.  Try next PNAME entry.

100$:	TST	(R2)+			; point to next PNAME entry
	DEC	R4			; count them
	BGT	50$			; look at next PNAME entry
	SEC				; Indicate NOT FOUND
	RETURN
;	......

; Success on Xnn format.  Fix stack and get 1-letter name for DEVTR.

110$:	TST	(SP)+			; give up unit counter
	CMP	(SP)+,#8.		; was unit in first octade? (X0n?)
	BEQ	120$			; If so, use 2-letter name
	MOV	R5,R2			; point to $PNAM2's 1-letter name

;+
; We have a good device name and unit number.  Convert the name to the 
; preferred format, DDn or Dnn.  Extract the unit number, get the 1-letter 
; or 2-letter $PNAM* name, and call $DEVTR to get the preferred name.
;-

120$:	MOV	R1,-(SP)		; save FDB pointer,
	MOV	@R2,R0			; get handler name,
	MOV	R3,R1			; get unit number
	CALL	$DEVTR			; Use SYSLIB routine for name,
	MOV	(SP)+,R1		; restore FDB pointer
	MOV	R0,@R1			; Store result
	CLC
	RETURN				; through coroutine

	.DSABL	LSB

; Local data

$PNAMA:	.WORD	0
SLOTS:	.WORD	0
EXTUNI:	.WORD	0

	ROUNDUP				; Check for overflow and round-up

	.END
.rem %

	.mcall	.print, .exit
;+
; Test program for INDDEV
;-
	.nlist	MEB,BEX

sysptr =: 54
$pnptr =: 404

emtblk:	.blkw	6
args:	.word	3
	.word	count
	.word	dev
	.word	dnam

fdb:	.word	0			; phony channel no.
dev:	.rad50	/DK /

count:	.word	3			; no. of characters
msg0:	.asciz	/INDDEV test/
msg1:	.ascii	/Device name is /
dnam:	.ascii	/   /
	.asciz	/:/

	.even

test:	.print	#msg0	
	mov	#fdb,r1
	call	INDDEV
	mov	#R50ASC,R0
	mov	#args,R5
	call	CALL$F
	.print	#msg1
	.exit

	.end	test
%
