gkn@M5.Sdsc.EDU (Gerard K. Newman) (05/26/88)
Well, from what I can tell my RAM disk driver works. It's a lot faster than PDDRIVER, and it's faster than some internal DEC RAM disk driver called FDDRIVER. Assemble & link it thusly: $ Macro RAMDRIVER $ Link/System=0/Header RAMDRIVER No warranty, expressed or implied. Use at your own risk. It doesn't crash systems or corrupt data, or anything like that, but I am in no position to support it or be responsible for pathological cases or configurations. RAMDRIVER doesn't run on VMS V5 systems yet. When I have V5 here it will, and I will post an update. gkn ---------------------------------------- Internet: GKN@SDS.SDSC.EDU Bitnet: GKN@SDSC Span: SDSC::GKN (27.1) MFEnet: GKN@SDS USPS: Gerard K. Newman San Diego Supercomputer Center P.O. Box 85608 San Diego, CA 92138-5608 Phone: 619.534.5076 ....................... Cut between dotted lines and save ...................... $!.............................................................................. $! VAX/VMS archive file created by VMS_SHAR V-5.01 01-Oct-1987 $! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au) $! To unpack, simply save and execute (@) this file. $! $! This archive was created by GKN $! on Thursday 26-MAY-1988 16:30:14.66 $! $! It contains the following 1 file: $! RAMDRIVER.MAR $!============================================================================== $ Set Symbol/Scope=(NoLocal,NoGlobal) $ Version=F$GetSYI("VERSION") ! See what VMS version we have here: $ If Version.ges."V4.4" then goto Version_OK $ Write SYS$Output "Sorry, you are running VMS ",Version, - ", but this procedure requires V4.4 or higher." $ Exit 44 $Version_OK: CR[0,8]=13 $ Pass_or_Failed="failed!,passed." $ Goto Start $Convert_File: $ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd $No_Error1: Define/User_Mode SYS$Output NL: $ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' - VMS_SHAR_DUMMY.DUMMY f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f); o:=Get_Info(Command_Line,"Output_File");Set(Output_File,b,o); Position(Beginning_of(b));Loop x:=Erase_Character(1);Loop ExitIf x<>"V"; Move_Vertical(1);x:=Erase_Character(1);Append_Line; Move_Horizontal(-Current_Offset);EndLoop;Move_Vertical(1); ExitIf Mark(None)=End_of(b) EndLoop;Position(Beginning_of(b));Loop x:=Search("`",Forward,Exact);ExitIf x=0;Position(x);Erase_Character(1); If Current_Character='`' then Move_Horizontal(1);else Copy_Text(ASCII(INT(Erase_Character(3))));EndIf;EndLoop;Exit; $ Delete VMS_SHAR_DUMMY.DUMMY;* $ Checksum 'File_is $ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR $ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd $No_Error2: Return $Start: $ File_is="RAMDRIVER.MAR" $ Check_Sum_is=309999102 $ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY X`009.Title`009RAMDriver`009- RAM disk driver for VAX/VMS X`009.Ident`009/V01.000/ X`009.Enable`009SUP X`009.Default Displacement,Word X`009.Subtitle`009Introduction X X;+ X; X; ----- RAMDriver: RAM disk driver for VAX/VMS X; X; X; Facility: X; X;`009VAX/VMS executive, I/O subsystem. X; X; Abstract: X; X;`009This module implements a RAM disk driver, whereby a collection X;`009of pages from non-paged pool behave as though they were a disk X;`009drive. The driver is $QIO compatible with the DEC supplied X;`009PDDRIVER but is much more efficient since it does all of its X;`009work at IPL$_ASTDEL rather than IPL$_SYNCH (it uses a MUTEX X;`009for synchronization). X; X; Environment: X; X;`009VAX/VMS native mode, VMS V4.4 or later, resident, kernel mode, X;`009IPL$_ASTDEL and above. X; X; X; X; Version:`009V01.000 X; Date:`009`00912-Mar-1988 X; X; Copyright `169 1988 San Diego Supercomputer Center X; X; Gerard K. Newman`00912-Mar-1988 X; San Diego Supercomputer Center X; General Atomics X; P.O. Box 85608 X; San Diego, CA 92138-5608 X; 619.534.5076 X; X; Internet:`009GKN@SDS.SDSC.EDU X; BITNET:`009GKN@SDSC.BITNET X; SPAN:`009`009SDSC::GKN (27.1) X; MFENET:`009GKN@SDS.MFENET X; SDSCNET:`009GKN@SDS.SDSCNET X; X; X; Modifications: X; X; X;- X X`009.Page X`009.Subtitle`009Local definitions X V`009.Link`009 "SYS$SYSTEM:SYS.STB"/Selective_Search`009;Grab the system symbol Xtable X`009.Library "SYS$LIBRARY:LIB.MLB"`009`009`009;Get special macros from here X X`009.NoCross`009`009`009;Save a tree X X`009$ACBDEF`009`009`009`009;AST control block offsets X`009$CRBDEF`009`009`009`009;Controller request block definitions X`009$DCDEF`009`009`009`009;Device class & type definitions X`009$DDBDEF`009`009`009`009;Device data block definitions X`009$DDTDEF`009`009`009`009;Driver dispatch table offsets X`009$DEVDEF`009`009`009`009;Device independent status bits X`009$DPTDEF`009`009`009`009;Driver prologue table offsets X`009$DYNDEF`009`009`009`009;Nonpaged pool data structure type codes X`009$IDBDEF`009`009`009`009;Interrupt dispatch block offsets X`009$IODEF`009`009`009`009;I/O function codes X`009$IPLDEF`009`009`009`009;Interrupt priority levels X`009$IRPDEF`009`009`009`009;I/O request packet definitions X`009$ORBDEF`009`009`009`009;Object rights block definitions X`009$SSDEF`009`009`009`009;System service codes X`009$UCBDEF`009`009`009`009;UCB offsets X`009$VECDEF`009`009`009`009;Interrupt transfer vector offsets X X`009.Cross`009`009`009`009;Turn CREF back on X X X; Local definitions X XRAMD$K_IPL`009=`009IPL$_SYNCH`009;Synchronization IPL X XP1`009`009=`0090`009`009;QIO parameter P1 XP2`009`009=`0094`009`009;QIO parameter P2 X X X; UCB offsets which follow the standard disk UCB. X X$DEFINI`009UCB`009`009`009`009;Start of the UCB offsets X X.`009=`009UCB$K_LCL_DISK_LENGTH`009;Start after the standard disk crap X X$DEF`009UCB$L_RAMD_BUFF`009 .Blkl`009`009;Address of the disk buffer X$DEF`009UCB$L_RAMD_MUTEX .Blkl`009`009;Disk access MUTEX X$DEF`009UCB$K_RAMD_LENG`009`009`009;Length of a RAM disk UCB X X$DEFEND`009UCB`009`009`009`009;End of the UCB offsets X X`009.Page X`009.Subtitle`009Standard device driver tables X X X; Driver prologue table. X X`009DPTAB`009-`009`009`009 ;Driver prologue table X`009`009End`009 = RAMD_END,-`009 ;End of the driver X`009`009Adapter`009 = NULL,-`009 ;No adapter (no hardware) X`009`009MaxUnits = 1,-`009`009 ;Only 1 unit X`009`009Unload`009 = RAMD_UNLOAD,- ;Unload routine X`009`009Name`009 = RAMDRIVER,-`009 ;Driver name X`009`009UCBSize`009 = UCB$K_RAMD_LENG ;UCB size X X X; Initialization table. X X`009DPT_Store INIT`009`009`009;Initialization table X X; Device data block (DDB). X X`009DPT_Store DDB,DDB$L_ACPD,L,<^a/F11/>`009;Default ACP name X`009DPT_Store DDB,DDB$L_ACPD+3,B,DDB$K_SLOW`009;ACP class X X; Unit control block (UCB). X X`009DPT_Store UCB,UCB$B_FIPL,B,RAMD$K_IPL`009;Fork IPL X`009DPT_Store UCB,UCB$B_DIPL,B,RAMD$K_IPL`009;Device IPL X`009DPT_Store UCB,UCB$L_DEVCHAR,L,<-`009;Device characteristics: X`009`009`009DEV$M_FOD!-`009`009; File oriented X`009`009`009DEV$M_DIR!-`009`009; Directory structured X`009`009`009DEV$M_AVL!-`009`009; Available X`009`009`009DEV$M_SHR!-`009`009; Shareable X`009`009`009DEV$M_IDV!-`009`009; Capable of input X`009`009`009DEV$M_ODV!-`009`009; Capable of output X`009`009`009DEV$M_RND>`009`009; Random access X`009DPT_Store UCB,UCB$L_DEVCHAR2,L,<-`009;More device characteristics: X`009`009`009DEV$M_NNM>`009`009; Prefix the name with "node$" X`009DPT_Store UCB,UCB$W_DEVSTS,W,<-`009`009;Device status: X`009`009`009UCB$M_NOCNVRT>`009`009; No LBN conversion X`009DPT_Store UCB,UCB$B_DEVCLASS,B,DC$_DISK`009;It's a disk X`009DPT_Store UCB,UCB$B_DEVTYPE,B,DT$_ML11`009;It's a funny looking disk X`009DPT_Store UCB,UCB$W_DEVBUFSIZ,W,512`009;Buffer size X`009DPT_Store UCB,UCB$B_TRACKS,B,1`009`009;1 track X`009DPT_Store UCB,UCB$B_SECTORS,B,1`009`009;1 sector X X; Reinitialization table. X X`009DPT_Store REINIT`009`009`009;Reinitialization table X X; Controller request block (CRB). X V`009DPT_Store CRB,CRB$L_INTD+VEC$L_INITIAL,D,RAMD_CTRL_INIT`009 ;Controller ini Xtialization V`009DPT_Store CRB,CRB$L_INTD+VEC$L_UNITINIT,D,RAMD_UNIT_INIT ;Unit initializati Xon X X; Device data block (DDB). X X`009DPT_Store DDB,DDB$L_DDT,D,RAMD$DDT`009;Driver dispatch table address X X`009DPT_Store END`009`009`009`009;End of the initialization tables. X X X; Driver dispatch table. X X`009DDTAB`009-`009`009`009 ;Driver dispatch table X`009`009DevNam`009= RAMD,-`009 ;Device name X`009`009Start`009= RAMD_STARTIO,- ;Start I/O V`009`009Unsolic`009= 0,-`009`009 ;No unsolicited interrupt service (no interrup Xts) X`009`009FuncTB`009= RAMD_FUNCTAB,- ;Function decision table address X`009`009Cancel`009= 0,-`009`009 ;No cancel I/O X`009`009RegDmp`009= 0,-`009`009 ;Register dump (no registers!) X`009`009DiagBf`009= 0,-`009`009 ;No diagnostic bufer X`009`009ErlgBf`009= 0`009`009 ;No error logging buffer X X X; Function decision table. X XRAMD_FUNCTAB:`009`009`009`009;Function decision table. X X; Legal functions. X X`009FuncTab`009,<-`009`009`009;Legal functions: X`009`009UNLOAD,-`009`009; Unload X`009`009PACKACK,-`009`009; Pack acknowlege X`009`009AVAILABLE,-`009`009; Drive available X`009`009SENSECHAR,-`009`009; Sense characteristics X`009`009SENSEMODE,-`009`009; Sense mode X`009`009FORMAT,-`009`009; Format (special) X`009`009READVBLK,-`009`009; Read virtual X`009`009READLBLK,-`009`009; Read logical X`009`009READPBLK,-`009`009; Read physical X`009`009WRITEVBLK,-`009`009; Write virtual X`009`009WRITELBLK,-`009`009; Write logical X`009`009WRITEPBLK,-`009`009; Write physical X`009`009ACCESS,-`009`009; Access / lookup X`009`009ACPCONTROL,-`009`009; XQP control, actually X`009`009CREATE,-`009`009; Create / enter X`009`009DEACCESS,-`009`009; Deaccess X`009`009DELETE,-`009`009; Delete X`009`009MODIFY,-`009`009; Modify X`009`009MOUNT>`009`009`009; Mount volume X X; Buffered functions. X X`009FuncTab`009,<-`009`009`009;Buffered functions: X`009`009UNLOAD,-`009`009; Unload X`009`009PACKACK,-`009`009; Pack acknowlege X`009`009AVAILABLE,-`009`009; Drive available X`009`009SENSECHAR,-`009`009; Sense characteristics X`009`009SENSEMODE,-`009`009; Sense mode X`009`009FORMAT,-`009`009; Format (special) X`009`009ACCESS,-`009`009; Access / lookup X`009`009ACPCONTROL,-`009`009; XQP control, actually X`009`009CREATE,-`009`009; Create / enter X`009`009DEACCESS,-`009`009; Deaccess X`009`009DELETE,-`009`009; Delete X`009`009MODIFY,-`009`009; Modify X`009`009MOUNT>`009`009`009; Mount volume X X; Direct functions and FDT mapping. X X`009FuncTab`009RAMD_STASH,<-`009`009;Stash buffer addresss for: X`009`009READVBLK,-`009`009; Read virtual X`009`009READLBLK,-`009`009; Read logical X`009`009READPBLK,-`009`009; Read physical X`009`009WRITEVBLK,-`009`009; Write virtual X`009`009WRITELBLK,-`009`009; Write logical X`009`009WRITEPBLK>`009`009; Write physical X`009FuncTab`009+ACP$READBLK,<-`009`009;Read functions: X`009`009READVBLK,-`009`009; Read virtual X`009`009READLBLK,-`009`009; Read logical X`009`009READPBLK>`009`009; Read physical X`009FuncTab`009+ACP$WRITEBLK,<-`009;Write functions: X`009`009WRITEVBLK,-`009`009; Write virtual X`009`009WRITELBLK,-`009`009; Write logical X`009`009WRITEPBLK>`009`009; Write physical X`009FuncTab`009+ACP$ACCESS,<-`009`009;Access functions: X`009`009ACCESS,-`009`009; Access X`009`009CREATE>`009`009`009; Create X`009FuncTab`009+ACP$DEACCESS,<-`009;Deaccess function: X`009`009DEACCESS>`009`009; Deaccess X`009FuncTab`009+ACP$MODIFY,<-`009`009;Modify functions: X`009`009ACPCONTROL,-`009`009; ACP control X`009`009DELETE,-`009`009; Delete X`009`009MODIFY>`009`009`009; Modify X`009FuncTab`009+ACP$MOUNT,<-`009`009;Mount function: X`009`009MOUNT>`009`009`009; Mount volume X`009FuncTab`009RAMD_PACKACK,<-`009`009;Pack acknowlege function: X`009`009PACKACK>`009`009; Pack acknowlege X`009FuncTab`009RAMD_UNL_AVL,<-`009`009;Unload functions: X`009`009UNLOAD,-`009`009; Unload X`009`009AVAILABLE>`009`009; Available X`009FuncTab`009RAMD_FORMAT,<-`009`009;Format function: X`009`009FORMAT>`009`009`009; Format (special) X`009FuncTab`009+EXE$SENSEMODE,<-`009;Sense functions X`009`009SENSEMODE,-`009`009; Sense mode X`009`009SENSECHAR>`009`009; Sense characteristics X X`009.Page X`009.Subtitle`009RAMD_UNLOAD`009- Driver unload routine X X;+ X; X; ----- RAMD_UNLOAD: Driver unload routine X; X; X; This routine is called in response to the SYSGEN UNLOAD command. X; X; This driver is not unloadable. X; X; Environment: X; X;`009IPL$_POWER, process context. X; X; Inputs: X; X;`009None. X; X; Outputs: X; X;`009None. X; X;- X XRAMD_UNLOAD:`009`009`009`009;Driver unload routine X X`009RSB`009`009`009`009;Driver is not unloadable. X X`009.Page X`009.Subtitle`009RAMD_CTRL_INIT`009- Controller initialization X X;+ X; X; ----- RAMD_CTRL_INIT: Controller initialization X; X; X; This routine is called to perform controller specific initialization X; during the SYSGEN LOAD or RELOAD commands and during power failure X; recovery. Since there isn't a controller this routine doesn't do X; a whole lot. X; X; Environment: X; X;`009IPL$_POWER, system context. X; X; Inputs: X; X;`009R5`009- IDB address X; X; Outputs: X; X;`009Not much. X; X;- X XRAMD_CTRL_INIT:`009`009`009`009;Controller initialization X X`009CLRL`009IDB$L_CSR(R5)`009`009;No CSR X`009RSB`009`009`009`009;Done X X`009.Page X`009.Subtitle`009RAMD_UNIT_INIT`009- Unit initialization X X;+ X; X; ----- RAMD_UNIT_INIT: Unit initialization X; X; X; This routine is called during the SYSGEN LOAD command (but not X; RELOAD) and during power failure recovery. We set the online X; bit in the UCB, initialize the MUTEX and return. X; X; Environment: X; X;`009IPL$_POWER, system context. X; X; Inputs: X; X;`009R5`009- UCB address X; X; Outputs: X; X;`009Unit set online. X; X;- X XRAMD_UNIT_INIT:`009`009`009`009 ;Unit initialization X X`009BISW`009#UCB$M_ONLINE,UCB$W_STS(R5) ;We're on the air X`009MOVL`009#^xFFFF,UCB$L_RAMD_MUTEX(R5) ;Initialize the MUTEX X`009RSB`009`009`009`009 ;Done. X X`009.Page X`009.Subtitle`009RAMD_PACKACK`009- Handle IO$_PACKACK X X;+ X; X; ----- RAMD_PACKACK: Handle IO$_PACKACK X; X; X; This routine is called during FDT processing to handle IO$_PACKACK. X; We set the valid bits in the UCB and return. X; X; Environment: X; X;`009IPL$_ASTDEL, process context. X; X; Inputs: X; X;`009R5`009- UCB address X;`009R3`009- IRP address X; X; Outputs: X; X;`009Volume valid changed. X; X;- X XRAMD_PACKACK:`009`009`009`009;Handle IO$_PACKACK X X`009BBSS`009#UCB$V_LCL_VALID,UCB$L_STS(R5),10$ ;Already valid? X`009BISW`009#UCB$M_VALID,UCB$L_STS(R5)`009 ;No, it is now. X`009INCB`009UCB$B_ONLCNT(R5)`009`009 ;Another system has this one on line X X10$:`009MOVL`009#SS$_NORMAL,R0`009`009;Success! X`009JMP`009G^EXE$FINISHIOC`009`009;Post the I/O request complete X X`009.Page X`009.Subtitle`009RAMD_UNL_AVL`009- Handle IO$_UNLOAD and IO$_AVAILABLE X X;+ X; X; ----- RAMD_UNL_AVL: Handle IO$_UNLOAD and IO$_AVAILABLE X; X; X; This routine is called as an FDT routine for IO$_UNLOAD and IO$_AVAILABLE. X; We clear the volume valid bits and post the I/O request complete. X; X; Environment: X; X;`009IPL$_ASTDEL, process context. X; X; Inputs: X; X;`009R5`009- UCB address X;`009R3`009- IRP address X; X; Outputs: X; X;`009Volume valid cleared. X; X;- X XRAMD_UNL_AVL:`009`009`009`009;Handle IO$_UNLOAD and IO$_AVAILABLE X X`009BBCC`009#UCB$V_LCL_VALID,UCB$L_STS(R5),10$ ;Volume valid? X`009BICW`009#UCB$M_VALID,UCB$W_STS(R5)`009 ;Volume no longer valid X`009DECB`009UCB$B_ONLCNT(R5)`009`009 ;Another system has let go of this one X X10$:`009MOVL`009#SS$_NORMAL,R0`009`009;Success! X`009JMP`009G^EXE$FINISHIOC`009`009;Post the I/O request complete. X X`009.Page X`009.Subtitle`009RAMD_FORMAT`009- Handle IO$_FORMAT X X;+ X; X; ----- RAMD_FORMAT: Handle IO$_FORMAT X; X; X; This routine is called as an FDT routine for IO$_FORMAT, which is X; used to allocate and deallocate nonpaged pool which comprises the X; blocks of the "disk". P1 is the new size of the disk. We first X; deallocate the existing chunk (all data is lost), and allocate a X; chunk of the new size. X; X; Environment: X; X;`009IPL$_ASTDEL, process context. X; X; Inputs: X; X;`009AP`009- Address of P1 X;`009R5`009- UCB address X;`009R3`009- IRP address X; X; Outputs: X; X;`009Disk size changed. X; X;- X XRAMD_FORMAT:`009`009`009`009;Handle IO$_FORMAT X X`009PUSHL`009R3`009`009`009;Keep the IRP safe X X; Lock the disk MUTEX for write access. X X`009MOVAB`009UCB$L_RAMD_MUTEX(R5),R0`009;Address the MUTEX X`009JSB`009G^SCH$LOCKW`009`009;Lock the MUTEX for write access. X X; Ensure that the disk isn't mounted. X X`009MOVL`009#SS$_DEVMOUNT,R0`009`009 ;Presume failure X`009BBS`009#DEV$V_MNT,UCB$L_DEVCHAR(R5),40$ ;Branch if it's mounted. X X; Next deallocate the existing buffer. X X`009MOVL`009UCB$L_RAMD_BUFF(R5),R0`009 ;Grab the existing buffer X`009BEQL`00920$`009`009`009 ;None there, that was easy. X`009MULL3`009#512,UCB$L_MAXBLOCK(R5),R1 ;Grab the size to deallocate X`009BEQL`00910$`009`009`009 ;Eh? X`009JSB`009G^EXE$DEANONPGDSIZ`009 ;Deallocate the block. X X10$:`009CLRL`009UCB$L_RAMD_BUFF(R5)`009;No more buffer. X X; Allocate a new buffer. X X20$:`009MOVL`009#SS$_NORMAL,R0`009`009 ;Presume no new disk to allocate X`009MOVL`009P1(AP),UCB$L_MAXBLOCK(R5) ;New size to allocate X`009BEQL`00940$`009`009`009 ;If EQL that was easy X`009MULL3`009#512,P1(AP),R1`009`009 ;Here's the size we want X`009JSB`009G^EXE$ALONPAGVAR`009 ;Allocate some pool X`009BLBS`009R0,30$`009`009`009 ;Win! X`009MOVZWL`009#SS$_INSFMEM,R0`009`009 ;Lose. X X30$:`009MOVL`009R2,UCB$L_RAMD_BUFF(R5)`009;Stash the block address X X40$:`009MOVW`009UCB$L_MAXBLOCK(R5),UCB$W_CYLINDERS(R5)`009;Cylinders = blocks X`009PUSHL`009R0`009`009`009`009`009;Stash the final status. X`009MOVAB`009UCB$L_RAMD_MUTEX(R5),R0`009`009`009;Address our MUTEX X`009JSB`009G^SCH$UNLOCK`009`009`009`009;Unlock same. X`009POPR`009#^m<R0,R3>`009`009`009`009;Restore the status & IRP X`009JMP`009G^EXE$FINISHIOC`009`009`009`009;Done X X`009.Page X`009.Subtitle`009RAMD_STASH`009- Stash the virtual address of the I/O buffer X X;+ X; X; ----- RAMD_STASH: Stash the virtual address of the I/O buffer X; X; X; This routine is called as an FDT routine to stash the virtual X; address of the user's I/O buffer in the IRP so that RAMD_KAST X; knows where to move data to or from. All of the rest of the X; FDT processing will be done in ACP$READBLK or ACP$WRITEBLK. X; X; Environment: X; X;`009IPL$_ASTDEL, process context. X; X; Inputs: X; X;`009AP`009- Address of the QIO parameter list X;`009R3`009- IRP address X; X; Outputs: X; X;`009P1(AP) stashed in IRP$L_VAL1. X; X;- X XRAMD_STASH:`009`009`009`009;Stash the virtual address of the I/O buffer X X`009MOVL`009P1(AP),IRP$L_VAL1(R3)`009;Stash the buffer's virtual address X`009RSB`009`009`009`009;Back to the FDT dispatcher X X`009.Page X`009.Subtitle`009RAMD_STARTIO`009- Start I/O routine X X;+ X; X; ----- RAMD_STARTIO: Start I/O routine X; X; X; This routine is called as a fork process to start an I/O request. X; The only requests which get here are reads and writes (both logical X; and physical). X; X; Recall that we're at IPL$_SYNCH and do not have process context. X; The only way we can move data to or from user space is to use a X; system virtual page to double map the user's buffer and call X; IOC$MOVxUSER, which is very slow and is doubly bad because it must X; execute at IPL$_SYNCH. This is what DEC's PDDRIVER does (and is X; why that driver may not be a win on a busy system). X; X; A better solution is to execute with process context, where we can X; run at IPL$_ASTDEL and use a MOVC3 instruction to transfer the data X; to user space. Normally one would do this sort of thing in the FDT X; routines and simply bypass the driver start I/O routine. However, X; due to the complex nature of the FDT processing required for file X; oriented devices it is desirable to let DEC's routines do it. Those X; routines (in SYSACPFDT) exit by queueing the IRP to the driver's X; start I/O routine, so we're almost (but not quite) stuck. X; X; So, what we must do is to get back our lost process context. We do X; this by queueing a kernel mode AST back to the requesting process. X; The AST routine (below) will transfer the data and then post the X; I/O request complete. X; X; Since we us a MUTEX for synchronization, we can allow multiple read X; requests to execute in parallel (since we can lock a MUTEX for read X; or write access). In order for this to happen the device must look X; like it is not busy to IOC$INITIATE when it's called to start up an X; I/O request. We do this by clearing the busy bit in the UCB before X; we queue the AST. X; X; Environment: X; X;`009IPL$_SYNCH, fork context. X; X; Inputs: X; X;`009R5`009- UCB address X;`009R3`009- IRP address X; X; Outputs: X; X;`009IRP used as an ACB and a kernel mode AST is queued to the X;`009requesting process to complete the I/O request. X; X;- X XRAMD_STARTIO:`009`009`009`009`009;Start I/O routine X X`009BICW`009#UCB$M_BSY,UCB$W_STS(R5)`009;Device must not look busy X`009MOVL`009IRP$L_WIND(R3),IRP$L_VAL2(R3)`009;Keep the WCB address safe V`009MOVL`009R3,R5`009`009`009`009;Copy the IRP address and make believe it's an X ACB X`009BISB`009#ACB$M_KAST,ACB$B_RMOD(R5)`009;Say we're a kernel AST X`009MOVAB`009RAMD_KAST,ACB$L_KAST(R5)`009;Execute this routine V`009CLRL`009R2`009`009`009`009;No priority increment (could use PRI$_IOCOM, I g Xuess) X`009JMP`009G^SCH$QAST`009`009`009;Queue the AST and return X X; Ok - we're back at IPL$_ASTDEL with (the correct one, even!) process context. X; R0-R5 are available for use, and R5 is the address of the IRP (er, ACB). The X; user's buffer address is in IRP$L_VAL1 (thanks to RAMD_STASH), and the PCB X; address is in R4 (thanks to the AST dispatcher). X XRAMD_KAST:`009`009`009`009;Ref. label X V`009MOVL`009R5,R3`009`009`009;Put the IRP where most everything expects to find X it X`009MOVL`009IRP$L_UCB(R3),R5`009;Address our UCB X X; Decide if it's physical or logical I/O. X X`009MULL3`009#512,IRP$L_MEDIA(R3),R1`009`009;Presume logical I/O X`009BBC`009#IRP$V_PHYSIO,IRP$W_STS(R3),10$`009;Branch if it's physical I/O X V; Physical I/O ... Byte offset = Sector size * ((Sectors per track) * Track + S Xector) X X`009MOVZBL`009UCB$B_SECTORS(R5),R1`009;Grab the sectors/track X`009MULW`009IRP$L_MEDIA+2(R3),R1`009;Multiply by track number X`009ADDW`009IRP$L_MEDIA(R3),R1`009;Add in the sector X`009DECL`009R1`009`009`009;Make it zero based X`009MULL`009#512,R1`009`009`009;Multiply by the sector size X X; Ok - now we have the byte offset into the disk buffer in R1. X V10$:`009ADDL`009UCB$L_RAMD_BUFF(R5),R1`009;Point to the right spot in the disk XbUffer X`009MOVAB`009UCB$L_RAMD_MUTEX(R5),R0`009;Address our MUTEX X`009PUSHR`009#^m<R3,R4,R5>`009`009;Save volitile registers X`009 X; Now lock the MUTEX based on the function type. X X`009BBC`009#IRP$V_FUNC,IRP$W_STS(R3),20$`009 ;Read or write? X X; Read ... disk to user. X X`009JSB`009G^SCH$LOCKR`009`009`009 ;Lock the MUTEX for read access X`009MOVC3`009IRP$L_BCNT(R3),(R1),@IRP$L_VAL1(R3) ;"Read" the data X`009BRB`00930$`009`009`009`009 ;Join common code X X; Write ... user to disk. X X20$:`009JSB`009G^SCH$LOCKW`009`009`009 ;Lock the MUTEX for write access X`009MOVC3`009IRP$L_BCNT(R3),@IRP$L_VAL1(R3),(R1) ;"Write" the data X X; Here to post the I/O request complete. X X30$:`009MOVQ`0094(SP),R4`009`009`009;Restore the PCB and UCB addresses X`009MOVAB`009UCB$L_RAMD_MUTEX(R5),R0`009`009;Address our MUTEX X`009JSB`009G^SCH$UNLOCK`009`009`009;Unlock it. X`009POPR`009#^m<R3,R4,R5>`009`009`009;Restore the IRP, PCB and UCB addresses X`009MOVL`009IRP$L_VAL2(R3),IRP$L_WIND(R3)`009;Restore the window pointer X`009MOVZWL`009IRP$L_BCNT(R3),R0`009`009;Grab the byte count V`009ADDL`009R0,IRP$L_VAL1(R3)`009`009;Update the buffer pointer in case this is X segmented X`009ASHL`009#16,R0,R0`009`009`009;Shift the byte count up to the high word X`009MOVW`009#SS$_NORMAL,R0`009`009`009;Success X`009CLRL`009R1`009`009`009`009;No further status X`009SETIPL`009UCB$B_FIPL(R5)`009`009`009;Up to fork IPL to modify X`009MOVL`009R3,UCB$L_IRP(R5)`009`009; the IRP field in the UCB X`009REQCOM`009`009`009`009`009;Post the request complete and look for more. X X`009.Page X`009.Subtitle`009RAMD_END`009- End of the driver (for SYSGEN) X XRAMD_END:`009`009`009`009;Mark the end of the driver for SYSGEN X X X X X`009.End $ GoSub Convert_File $ Exit
gkn@M5.SDSC.EDU (Gerard K. Newman) (06/02/88)
It's amazing how well a large test group can find bugs :-( ... RAMDRIVER doesn't get along well with the image activator, as I found out... All I ever used it for here was storing temporary files, and the 3 sites I sent it to for testing before distributing it to INFO-VAX apparently did the same. In any case, I will fix it this weekend (I won't have time to do it before then). Sorry for the inconvenience, everyone. gkn -------------------------------- Internet: GKN@SDS.SDSC.EDU BITNET: GKN@SDSC SPAN: SDSC::GKN (27.1) USPS: Gerard K. Newman San Diego Supercomputer Center P.O. Box 85608 San Diego, CA 92138-5608 AT&T: 619.534.5076
newman@lbl-csam.arpa.UUCP (06/04/88)
Yes, there is a bug ... $IMGACT doesn't get along with the RAMDRIVER. Funny, I never bothered to execute images off of it while testing, and neither did the 3 other sites I sent it to for testing before I posted it to Info-VAX. Sigh. I will fix the problem this weekend and post an updated version. I apologize for the BUGCHECKS (and believe me, I *am* embarrased). To the person worried about viriuses --- you have the source code ... gkn SDSC systems
fenster%huha.Huji.AC.IL@CUNYVM.CUNY.EDU (Yaacov Fenster) (06/06/88)
Somebody (Whom i'm sorry to say i deleted his message) asked with regard to the so here is some information: Installing it: $ mc sysgen sysgen> load ramdriver ! After having linked it into sys$system sysgen> connect rma0/driver=ramdriver/noada ! Could be something other than rma0 sysgen> ^Z Now it is time to look in sys$update:stabackit.com which contains a small macro of SETSIZE (SEARCH SETSIZE file_name) which is used to size the Dec PsuedoDisk. Modify it to run on your new device and run. From here on it is a simple matter of init, mount A few notes: a) It is possible to have both this disk and PDA0 online at the same time. b) Before using this disk (Or PDA0) be sure to enlarge your Non-paged dynamic m c) To reclaim the memory resize to 0. d) Don't know about bug-free but it seems virus free. Ack. and thanks to the author of RAMDRIVER, and whoever it was who wrote the rel article in Vax-Pro. Yaacov P.S. I would like to see some discussion of the pro-con of using such a device ( Cc: