/* lun.c - handle LUN allocation */ /* DECUS C , RSX-11M+ flavour */ /*)LIBRARY */ #include #include #include #define IQ_X (1) /* doesn't ANYBODY define this? somewhere? */ #define local #ifdef DOCUMENTATION title LUN Logical Unit Number control index LUN index Lunattach() index Lundetach() index Lunreserve() index Getbit() index Putbit() index Logical Unit Number index Attatchment of LUN index Detachment of LUN usage int lun; /* -ve IE_??? error code or +ve LUN */ char * devstr; /* typically "DDnnn" */ int result; /* -ve IE_??? error, +ve success */ lun = lunattach(devstr); {compute...} result = lundetach(lun); lunreserve(42); /* Lun 42 marked in use */ description This (kludge) module exists to solve a vexing problem. When we use various software libraries in a single task, each library must be told what LUNS it may use. Otherwise different parts of a task "hijack" LUNS from other parts with disasterous consequences. These functions try to keep a "scoreboard" of what LUNS are free and what are in use. RSX seems to have no easy way for a task to know what LUNS are "in use". I would accept "IO.ATTached" as a definition of "in use". If I have missed a trick, PLEASE re-submit this module with your idea of how to find the highest un-attached LUN from a non-priv task. This module clobbers event flag 2. It uses Getbit() and Putbit(). Lunattach() will find an allegedly free LUN, assign it to a given device name, and attach it (with error rather than waiting for it to be free). Lundetach() will IO.DETach a LUN, then mark it on the scoreboard as available for use by a future Lunattach(). If you don't want IO.ATTatchment with Lunattach() then please IO.DET the device yourself. LUNATTACH() 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. LUNDETACH() IO.DETatch a LUN, returning the error code from DSW or I/O status block [0]. A positive return means OK. LUNRESERVE() Mark a Lun as "in use" in the scoreboard. Do NOTHING else. Useful for people who have IO.ATTed in some other way or who just don't want us to mess with that LUN. If this is called first, then it does the right thing by setting up the scoreboard correctly, then marking a Lun as "in use". LUNFIX() Lunfix() is an internal routine that knocks all the "lun in use" bits down in the scoreboard. It is called automagically by the other routines when needed. It only works once then fakes out if it is called again. internal For Lunattach(), 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 the bloody scoreboard says it is. The first time Lunattach() is called we set up the scoreboard by setting up some "used" bits. We can't create this scoreboard at compile time, because until run-time we don't know how many LUNs are available to a task. We also set up the scoreboard if the user calls Lundetach() first, because some fool might one day reasonably want to do this. We find a free LUN by trying every LUN (highest to lowest) until we find one that the scoreboard says is OK to use. This is crude but works. Lunisb[] holds the I/O status block from the last IO.DET or IO.ATT to assist error recovery for particularly curious callers. bugs This is for RSX only. May later evolve for VMS, RSTS, RT, XXDP, UNIX, DOS etc. On any NORMAL device, once you have attached it, then you can't attach it again: you get IO.DAA "device already attached" errors! So programs can't blindly attache anything to any Lun. 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)] */ #define EFN (2) /* event flag to clobber */ local int lunuse[32] /* 256 bits. 1 = in-use. 0 = available */ = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; local BOOL lungo = FALSE; /* TRUE when lunuse[] is valid */ /* also a dummy parameter list to QIO */ int lunisb[2]; /* I/O status block for ATT,DET */ local lunfix() /* internal use: set up lunuse[] if needed */ BEGIN register int i; IF (!lungo) THEN lungo = TRUE; FOR (i=_nluns; i>3; i--) /* LUNS 1:3 are for C */ DO putbit(lunuse,i,0); /* mark as available */ OD /* here with LUN 0 dedicated, but some LUNs free */ FI END lunreserve(Lun) int Lun; BEGIN Luncheck(Lun); Lunfix(); putbit(lunuse,Lun,1); END luncheck(Lun) int Lun; BEGIN IF (Lun&0xFF00) THEN abort(); /* ridiculous LUN */ FI END 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; char result; /* char catches -ve BYTE error codes */ lunfix(); copy(&devnam,devstr,2); devunt = 0; /* assume 0 if sscanf fails */ sscanf(devstr+2,"%o",&devunt); FOR (lun=_nluns; lun; lun--) DO IF (!getbit(lunuse,lun)) THEN putbit(lunuse,lun,1); /* mark as used */ IF (((result=alun(lun,devnam,devunt))&0xFF)==IS_SUC) THEN IF (((result=qiow(IO_ATT|IQ_X,lun,EFN,lunisb,0,&lungo))&0xFF)==IS_SUC) THEN result = lunisb[0]; FI FI break; FI OD IF (result<0) THEN lun = result; /* sign extend to be really -ve */ FI return(lun); END int lundetach(lun) /* detach and mark as free */ int lun; /* LUN */ BEGIN char result; /* sign extends -ve byte errors */ Luncheck(lun); lunfix(); putbit(lunuse,lun,0); /* 0 = available */ IF (((result=qiow(IO_DET,lun,EFN,lunisb,0,&lungo))&0xFF)==IS_SUC) THEN result = lunisb[0]; FI return(result); /* sign extend */ END /* end: lun.c */