$COMPACT(ramdrv -CONST IN CODE- HAS $ ramdrv, $ xram; $ EXPORTS $ ram$init$io, $ ram$finish$io, $ ram$queue$io, $ ram$cancel$io) ramdrv: DO; $include(/rmx386/inc/rmxplm.ext) $include(/rmx386/inc/error.lit) $include(/rmx386/inc/common.lit) $include(/rmx386/inc/io.lit) $include(lddinfo.lit) ram$init$io: PROCEDURE(duib$p,ddata$t$p,status$p) EXTERNAL; DECLARE duib$p POINTER, ddata$t$p POINTER, status$p POINTER; END ram$init$io; ram$finish$io: PROCEDURE(duib$p, ddata$t) EXTERNAL; DECLARE duib$p POINTER, ddata$t TOKEN; END ram$finish$io; ram$cancel$io: PROCEDURE(conn$t, duib$p, ddata$t) EXTERNAL; DECLARE conn$t TOKEN, duib$p POINTER, ddata$t TOKEN; END ram$cancel$io; ram$queue$io: PROCEDURE(iors$t, duib$p, ddata$t) EXTERNAL; DECLARE iors$t TOKEN, duib$p POINTER, ddata$t TOKEN; END ram$queue$io; DECLARE duib DUIB$STRUCT, dinfo LOADABLE$CUSTOM$DINFO, uinfo STRUCTURE( device$address DWORD, write$protect BYTE); DECLARE co$conn$t TOKEN, file$conn$t TOKEN, root$t TOKEN, HI$job$$t TOKEN, parent$job$t TOKEN, input$buff(128) BYTE, status WORD, bytes$read WORD, del BYTE, /* Delimeter returned by get$argument */ disk$size DWORD, file$info STRUCTURE( owner(15) BYTE, length DWORD, type BYTE, owner$access BYTE, world$access BYTE, create$time DWORD, last$mod$time DWORD, reserved(20) BYTE), ram$p POINTER, exception$info STRUCTURE( entry$point POINTER, mode BYTE), MIN$DISK$SIZE LITERALLY '64', NO$BUFFERS LITERALLY '0', RT_PREN LITERALLY '29H', ROOT_JOB LITERALLY '3', PARENT_JOB LITERALLY '1', NO$EXCEPTIONS LITERALLY '00', RAM0(*) BYTE DATA(52H,41H,4DH,30H,20H,20H,20H, 20H,20H,20H,20H,20H,20H,20H), sign$on$msg(*) BYTE DATA(CR,LF, ' iRMX III Loadable RAM Disk Front End',CR,LF,LF), illegal$file$msg(*) BYTE DATA(CR,LF, 'File Size Does Not Match specified RAM Disk Size',CR,LF), badparm$msg(*) BYTE DATA(CR,LF, 'Invalid Command Tail',CR,LF), /* Unknown parameter msg */ illegal$size$msg(*) BYTE DATA(CR,LF, 'Invalid RAM Disk Size Specification',CR,LF), missing$parm$msg(*) BYTE DATA(CR,LF, 'Missing input parameter',CR,LF), /* missing input parm msg */ usage$msg(*) BYTE DATA(CR,LF, 'USAGE: ramdrv( (RAM Disk Size in KBytes(Decimal > 63)),',CR,LF, ' )',CR,LF); $subtitle('CONVERT') convert: PROCEDURE(char$p) DWORD REENTRANT; DECLARE char$p POINTER, char BASED char$p (1) BYTE, value DWORD, i BYTE; value = 0; DO i = 1 to char(0); IF (char(i) < 30H) OR (char(i) > 39H) THEN RETURN 0; value = (value * 10) + (char(i) - 30H); END; RETURN value; END convert; $subtitle('append$string') append$string: PROCEDURE(str1$p, str2$p) REENTRANT; DECLARE str1$p POINTER, str2$p POINTER, str1 BASED str1$p(1) BYTE, str2 BASED str2$p(1) BYTE, i BYTE, j BYTE; j = str1(0); DO i = 1 to str2(0); str1(j+i) = str2(i); END; str1(0) = str1(0) + str2(0); END append$string; $subtitle('Check Exception') check$exception: PROCEDURE(exception, info$p) REENTRANT; DECLARE exception WORD, info$p POINTER, info BASED info$p STRUCTURE( count BYTE, char(1) BYTE), exc$buf STRUCTURE( count BYTE, char(80) BYTE), dummy WORD; IF exception <> E$OK THEN DO; CALL dq$decode$exception(exception, @exc$buf, @dummy); CALL dq$write(co$conn$t, @(CR,LF), 2, @dummy); CALL dq$write(co$conn$t, @exc$buf.char, exc$buf.count, @dummy); CALL dq$write(co$conn$t, @(': '), 2, @dummy); IF info$p <> NIL THEN CALL dq$write(co$conn$t, @info.char, info.count, @dummy); CALL dq$write(co$conn$t, @(CR,LF), 2, @dummy); CALL rq$delete$job (SELECTOR$OF(NIL), @status); CALL rq$suspend$task(SELECTOR$OF(NIL),@status); /* if all else fails */ END; END check$exception; /* * MAIN PROGRAM */ file$conn$t = SELECTOR$OF(NIL); /* * Turn off exceptions */ exception$info.mode = NO$EXCEPTIONS; CALL rq$set$exception$handler( @exception$info, @status); /* * Get the first argument. The first one should be the name * of this program. */ del = dq$get$argument(@input$buff, @status ); /* * Create a log file for the program */ IF status = E$OK THEN DO; /* log file name = .log */ CALL append$string (@input$buff, @(4,'.log')); END; ELSE DO; input$buff(0) = 0; CALL append$string (@input$buff, @(16,'/work/ramdrv.log')); END; /* * Create a connection to log and open it for writing only. */ co$conn$t = dq$create(@input$buff, @status ); CALL dq$open( co$conn$t, WRITE$ONLY, NO$BUFFERS, @status ); CALL dq$write(co$conn$t,@sign$on$msg,LENGTH(sign$on$msg),@status); CALL check$exception(status,NIL); /* * Get the arguments. The first one should be the name * of this program and has already been received. */ /* * If the delimeter is a CR or LF then there are no parameters. * This is an error so print out the usage message. */ IF (del = CR) OR (del = LF) THEN DO; CALL dq$write(co$conn$t,@usage$msg,LENGTH(usage$msg),@status); GOTO exit; END; ELSE DO; /* Get RAM Disk Size argument */ del = dq$get$argument(@input$buff,@status); CALL check$exception(status,NIL); IF (del = CR) OR (del = LF) OR (input$buff(0) = 0) THEN DO; CALL dq$write(co$conn$t,@missing$parm$msg, LENGTH(missing$parm$msg),@status); CALL dq$write(co$conn$t,@usage$msg,LENGTH(usage$msg),@status); GOTO exit; END; ELSE DO; /* Convert ASCII input number to HEX */ disk$size = convert(@input$buff); IF disk$size < MIN$DISK$SIZE THEN DO; CALL dq$write(co$conn$t,@illegal$size$msg, LENGTH(illegal$size$msg),@status); CALL dq$write(co$conn$t,@usage$msg,LENGTH(usage$msg),@status); GOTO exit; END; IF del = RT_PREN THEN GOTO load$driver; /* Get pathname file name argument */ del = dq$get$argument(@input$buff(0),@status); CALL check$exception(status,NIL); IF (del = RT_PREN) AND (input$buff(0) <> 0) THEN DO; /* * Initial Contents File Specified - * Make sure file is valid before any further processing */ /* * Attach and open the configuration file */ file$conn$t = dq$attach( @input$buff, @status ); CALL check$exception(status,@input$buff); CALL dq$open( file$conn$t, READ$ONLY, NO$BUFFERS, @status ); CALL check$exception(status,@input$buff); /* * Get the attributes of the configuration file */ CALL dq$file$info(file$conn$t,NO$BUFFERS,@file$info,@status); CALL check$exception(status,@input$buff); IF (disk$size * 1024) <> file$info.length THEN DO; CALL dq$write(co$conn$t,@illegal$file$msg, LENGTH(illegal$file$msg),@status); CALL dq$write(co$conn$t,@usage$msg,LENGTH(usage$msg), @status); GOTO exit; END; END; ELSE DO; CALL dq$write(co$conn$t,@badparm$msg, LENGTH(badparm$msg),@status); CALL dq$write(co$conn$t,@usage$msg,LENGTH(usage$msg), @status); GOTO exit; END; END; END; load$driver: ram$p = dq$mallocate((disk$size * 1024),@status); CALL check$exception(status,@input$buff); IF file$conn$t <> SELECTOR$OF(NIL) THEN DO; /* * Read the initial contents file into the RAM Disk segment. */ bytes$read = dq$read(file$conn$t,ram$p,file$info.length,@status); CALL check$exception(status,NIL); CALL dq$detach(file$conn$t,@status); CALL check$exception(status,NIL); END; uinfo.write$protect = 0; uinfo.device$address = rqe$get$address(ram$p,@status); CALL check$exception(status,@input$buff); dinfo.far$init$io = @ram$init$io; dinfo.far$finish$io = @ram$finish$io; dinfo.far$queue$io = @ram$queue$io; dinfo.far$cancel$io = @ram$cancel$io; CALL MOVB(@RAM0,@duib.name,14); duib.file$driver = 9; /* Physical, Named */ duib.functs = 0FFH; duib.flags = 0; duib.dev$gran = 64; duib.dev$size = disk$size * 1024; duib.device = 0; duib.unit = 0; duib.dev$unit = 0; duib.init$io = CUSTOM$TYPE; duib.finish$io = CUSTOM$TYPE; duib.queue$io = CUSTOM$TYPE; duib.cancel$io = CUSTOM$TYPE; duib.dinfo$p = @dinfo; duib.uinfo$p = @uinfo; duib.update$timeout = 100; duib.num$buffers = 2; duib.priority = 128; duib.fixed$update = 1; duib.max$buffers = 0FFH; CALL rq$install$duibs(1, @duib, NIL, @status); CALL check$exception(status,NIL); root$t = rq$get$task$tokens(ROOT_JOB,@status); CALL check$exception(status,NIL); HI$job$t = rq$lookup$object(root$t,@(8,'R?HI$JOB'),0,@status); CALL check$exception(status,NIL); parent$job$t = rq$get$task$tokens(PARENT_JOB,@status); CALL check$exception(status,NIL); CALL rq$catalog$object(HI$job$t,parent$job$t, @(10,'RAMDRV_JOB'),@status); IF status = E$CONTEXT THEN DO; CALL rq$uncatalog$object(HI$job$t, @(10,'RAMDRV_JOB'),@status); CALL rq$catalog$object(HI$job$t,parent$job$t, @(10,'RAMDRV_JOB'),@status); END; CALL dq$detach(co$conn$t,@status); /* detach the log file */ CALL rq$suspend$task(SELECTOR$OF(NIL),@status); exit: /* * Clean up. Detach :CO:. */ CALL dq$detach(co$conn$t,@status); CALL rq$delete$job (SELECTOR$OF(NIL), @status); CALL rq$suspend$task(SELECTOR$OF(NIL),@status); /* if all else fails */ END ramdrv;