From: SMTP%"MACRO32@WKUVX1.WKU.EDU" 15-JAN-1994 09:56:47.17 To: EVERHART CC: Subj: Light diddlers for uVAX II X-Listname: "VMS Internals, MACRO, & BLISS Discussions" Warnings-To: <> Errors-To: MacroMan@WKUVX1.WKU.EDU Sender: MacroMan@WKUVX1.WKU.EDU Date: Sat, 15 Jan 94 16:15:32 +1300 Message-Id: <0097894A369DB740.0000008E@toyvax.zl2tnm.gen.nz> From: "Don Stokes" Reply-To: MACRO32@WKUVX1.WKU.EDU Subject: Light diddlers for uVAX II To: MACRO32@WKUVX1.WKU.EDU X-Vms-Mail-To: MACRO32@WKUVX1.WKU.EDU X-Vms-Mail-Cc: DON Here's the third version of the uVAX II LED diddler. This does what the previous one did, ie display idle time on the LED at 1 sec intevals, but this one doesn't occupy a process slot. Rather, it runs as a system subroutine using a repeating TQE, mapping the page directly instead of using $CRMPSC. Enjoy. Don Stokes, Network Manager, Victoria University of Wellington, New Zealand. don@zl2tnm.gen.nz(home) don@vuw.ac.nz(work) +64 4 495-5052 Fax+64 4 471-5386 .title IDLE_LED Display idle time on uVAX II rear panel ; ; This little ditty displays the idle time on the KA630 panel insert LED ; display by diddling the Boot & Diagnostic Register located at physical ; address ^x20080000. This is done from nonpaged pool using a repeating ; system subroutine TQE to run it at one second intervals. The program ; does not require a process slot after loading the into pool. ; ; Accessing the BDR is done by requesting a system page table entry and ; mapping it onto the BDR page. ; ; This has only been tested on the KA630 (MicroVAX II). It may work with ; other KA6xx processors if they use the same BDR format. On the other ; hand, it may crash other processors. It also does kernel stuff. You've ; been warned. I'd like to hear of mods to make it work on other systems. ; ; Privileges required: CMKRNL. ; ; Don Stokes , 15 January 1994. ; This program is in the public domain. No warranties expressed or implied. ; .library "SYS$LIBRARY:LIB.MLB" .link "SYS$SYSTEM:SYS.STB"/selective_search .library "MACROS" $PRTDEF $PTEDEF $TQEDEF $IPLDEF $IRPDEF $CPUDEF PHY_BDR = ^x20080000 ; Phy address of Boot & Diagnostic Reg BDR_PTE = PTE$M_VALID!!PTE$M_WINDOW! ; PTE to map BDR, valid, window, KW .psect IDLE_LED_RE, long,exe,shr,nowrt .entry idle_led, ^M<> $CMKRNL_S routin=install_krnl ; Who needs user-mode code? ret .entry install_krnl, ^M ; ; Map page onto BDR ; movl #1, R2 ; R2=PTE count jsb g^LDR$ALLOC_PT ; Get PTE blbc R0, 99$ ; OK? movl #BDR_PTE, (R1) ; Map page, R1=PTE adr, R2=count subl3 g^LDR$GL_SPTBASE, R1, R7 ; R7=PTE number*4 ashl #7, R7, R7 ; R7=offset to VA bisl #^x80000000, R7 ; R7=abs VA of page ; ; Allocate some nonpaged pool and put code into it ; movl #krnl_size+12, R1 jsb g^EXE$ALONONPAGED ; Allocate some nonpaged pool blbc R0, 99$ ; R2=pool address, R1=len movzwl R1, IRP$W_SIZE(R2) ; save length of pool packet movab 12(R2), R6 ; R6=pool code entry address movc3 #krnl_size, krnl_base, (R6); Copy code into pool ; ; Allocate a TQE and set it up ; jsb g^EXE$ALLOCTQE ; R2=TQE address blbs R0, 98$ movab -12(R6), R1 jsb g^EXE$DEANONPAGED 99$: ret 98$: movl R2, R5 ; EXE$INSTIMQ wants TQE in R5 movb #TQE$C_SSREPT, TQE$B_RQTYPE(R5) ; repeated TQE... movq #10000000, TQE$Q_DELTA(R5) ; ... at 1sec intervals movl R6, TQE$L_FPC(R5) ; AST routine addr movl R7, TQE$L_FR3(R5) ; Use BDR addr as R3 in TQE clrl TQE$L_FR4(R5) ; R4 is last timer ; ; Now queue the TQE. This is done at IPL$_TIMER to protect against accidents. ; Note that this uses poor man's lockdown; this isn't intended for SMP systems! ; dsbint ipl=10$, environ=uniprocessor ; Shields up! movq g^EXE$GQ_SYSTIME, R0 ; TQE will fire on next tick jsb g^EXE$INSTIMQ ; insert it into queue enbint ; Shields down. movl #SS$_NORMAL, R0 ret 10$: .long IPL$_TIMER ; ; Code to get idle time and place in LED display, run from TQE in nonpaged ; pool at IPL$_TIMER at one second intervals. ; This is aggressively non-SMP code and only measures idle time on CPU 0. ; Idle time is converted to a busy time fingure in the range 0..9. ; On entry: R3 VA of mapped BDR (from TQE$L_FR3) ; R4 Last value of CPU$L_NULLCPU (from TQE$L_FR4) ; R5 address of TQE ; On exit: TQE$L_FR4 Current value of CPU$L_NULLCPU ; R5 Must contain address of TQE ; R0 Trashed ; krnl_base: movl g^SMP$GL_CPU_DATA, R0 ; R0=address of CPU 0's counters movl CPU$L_NULLCPU(R0), R0 ; R0=absolute idle time on CPU 0 movl R0, TQE$L_FR4(R5) ; save absolute idle time subl R4, R0 ; R0=delta idle time in 10ms ticks divl #10, R0 ; R0=idle time in 100ms ticks subl3 R0, #9, R0 ; R0=busy time, 0..9 bgeq 1$ ; Underflow? clrl R0 ; Correct underflow (timer slew etc) 1$: movw R0, (R3) ; Place in BDR rsb krnl_size = . - krnl_base .end idle_led