/* lunattach.c - manage LUNs for DECUS C RSX11M+ */

#include <algol68.h>
#include <cx.h>

#define local

#ifdef	DOCUMENTATION
title	Lunattach	Logical Unit Number control
index	LUN
index	Lunattach
index	Logical Unit Number
index	Attatchment of LUN
usage
	 
	 int	lun;	/* -ve IE_??? error code or +ve LUN */
	 char *	devstr;	/* typically "DDnnn" */
	 
	 lun = lunattach(devstr);
	 
description
	Assign,
	then attach, a LUN (previously not in use by your task) to the
	device named in devstr. Devstr does not require ':'. Beware
	that a device name with node name will be misinterpreted viz.
	"MYNODE::LB42:MUMBLE.UPU;6" will be interpreted as device MY0:
	because the rules are: first two characters are device name
	and any characters starting at third character that can be
	interpreted as an octal number form the device number.

	Return the LUN number (positive) if we suceeded.
	This means that we could assign the LUN to the device and
	also attach it.

	Return an RSX error code if we failed.
	Return IE.ULN (Unassigned LUN) if we had no available LUNs
	for this task, right now.

	Unfortunately the only way we can detect a free LUN is if the
	LUN is attached. Mere LUN assignment to a legal device is
	not easily detectable, and it appears hard to "unassign"
	a LUN. So after lunassign() gives you a LUN, IO.ATT it to
	dedicate the LUN and IO.DET it to free it for another
	lunassign().
internal
	Distinguish two ideas: (1) how we determine a LUN is eligible
	for assignment; (2) which order we try to assign LUNs.

	A LUN is available if and only if it is not attached. So if
	you want to re-use a LUN please IO.DET the LUN.

	We find a free LUN by trying every LUN (highest to lowest)
	until we find one that RSX will accept. This is crude but works.
	If you have a better way to assign LUNs without annoying
	other people's run-time systems, please submit it to DECUS.
bugs
	This is for RSX only. May later evolve for
	VMS, RSTS, RT, XXDP, UNIX, DOS etc.

	Lets make it understand node names one day, and skip past
	them to the device name, or even get the right device at the
	right node assigned to the lun.
#endif

extern int _nluns;	/* RSX11M taskbuilder: LUNs are [1:(.nluns)]	*/

int	lunattach	(devstr)
char *	devstr;		/* string defining device			*/
			/* for RSX: we expect exactly 2 letters, then	*/
			/* an OCTAL unit number.			*/
BEGIN
/*
 *	We expect to use RSX error codes if the device string is ill
 *	conditioned. So we assume it is OK and RSX detects all the
 *	bad news.
 */
int	devnam;
int	devunt;
int	lun;
int	junk[6];		/* 6 is magic number of words returned */
char	result;

	copy(&devnam,devstr,2);
	devunt = 0;			/* assume 0 if sscanf fails */
	sscanf(devstr+2,"%o",&devunt);
	FOR	(lun=_nluns;  lun;  lun--)
	DO	IF	((glun(lun,junk)&0xFF)==IE_ULN)
		THEN	/* we have a usable lun */
			IF	(alun(lun,devnam,devunt)==IS_SUC)
			THEN	return(lun);
			FI
		FI
	OD
	result = IE_ULN;	/* sign extend so it really is -ve */
	return(result);		/* no LUNs available - caller loses */
END

/* end: lun.c */
