;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Program: load_block_counter.mar ; Author: Bruce Ellis ; Date written: Sometime in January 1986 ; ; Synopsis: This guy prompts for a disk device name ; and looks up it's UCB address. He ; then allocates a chunk of non-paged pool ; and copies the monitoring code into the ; allocated pool. To get the code activated ; he saves the start i/o address from the ; DDT and moves the address of the code ; in pool to the start i/o address in the ; DDT. When the start i/o entry point ; is entered, the code has the address of the ; IRP passed to it in R3. He checks for ;; paging, swapping, and split i/os. He also ; counts the number of read, writes and the ; size of each. ; ; Modifications: ; BAE 9/24/87: Add code to count the split i/os. ; ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .library /sys$library:lib.mlb/ .link /sys$system:sys.stb/ $ddtdef $ucbdef $irpdef header=12 ;12 byte header for the pool devnam: .long 15 ;storagge for the disk device name .address 10$ 10$: .blkb 15 dev_prompt: ;Prompt for device name .ascid /enter disk to be monitored:/ .entry load_block_ctr,^m<> ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Get device name to monitor ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pushal devnam ;pass the length address pushal dev_prompt ;pass the prompt pushal devnam ;address of desc. to store device name calls #3,g^lib$get_input ;Get the device name blbs r0,lab $exit_s r0 ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Load the code to monitor disk activity ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lab: $cmkrnl_s routin=kernel_setup ret ;*********************************************************************** ; Kernel mode setup code ;*********************************************************************** .entry kernel_setup,^m ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Grab a write mutex on the i/o database ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval g^ioc$gl_mutex,r0 ;Grab a write mutex on the jsb g^sch$lockw ; i/o database (Note this code ; assumes that the change mode ; dispatcher has setup R44 to point ; to the PCB) ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Search for ucb address of this device ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval devnam,r1 ;Pass the address of the device name ; descriptor. jsb g^ioc$searchdev ;Search the i/o database for the UCB ; of the device (r1<-UCB address) pushl r1 ;Save the ucb address pushl r0 ;save the device status moval g^ioc$gl_mutex,r0 ;Free up the mutex on the io database movl g^sch$gl_curpcb,r4 ; jsb g^sch$unlock ; popl r0 ;restore the return status blbc r0,dev_error ;If error scram movl #code_len+header,r1 ;else grab a chunk of pool to jsb g^exe$alononpaged ; load the code into blbc r0,pool_error ;on error scram movw r1,8(r2) ;init the size field for deallocation movl r2,g^exe$gl_sitespec ;save the pointer to pool ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Copy the code into pool ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pushr #^m movc3 #code_len,pool_code_start,12(r2) popr #^m ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Assume the highest fork ipl ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ popl r1 ;restore the ucb address setipl ucb$b_fipl(r1) ;Synch with driver at Fork ipl movl ucb$l_ddt(r1),r5 ;get the driver dispatch table address movl ddt$l_start(r5),header(r2) ;save actual start i/o ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; reset the start i/o to point to our code ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ moval get_block_info-pool_code_start+header(r2),ddt$l_start(r5) ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Save the unit number of the disk ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ movzwl ucb$w_unit(r1),unit-pool_code_start+header(r2) setipl #0 movl #ss$_normal,r0 dev_error: pool_error: ret ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Pool code to check each i/o request processed by ; the start i/o routine ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pool_code_start: saved_start: .blkl 1 read_count: .long 0 read_lengths: .long 0[128] write_count: .long 0 write_lengths: .long 0[128] paging_ios: .long 0 swap_ios: .long 0 unit: .long 0 splits: .long 0 get_block_info: pushr #^m cmpw unit,ucb$w_unit(r5) ;this the unit to be monitored? beql ours ; brw exit ;if not scram ours: bbc #irp$v_pagio,irp$w_sts(r3),no_page ;Paging i/o? incl paging_ios ;if so increment count no_page: bbc #irp$v_swapio,irp$w_sts(r3),no_swap ;Swapping i/o? incl swap_ios ;if so increment count no_swap: extzv #io$v_fcode,#io$s_fcode,irp$w_func(r3),r2 ;get function ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Check for reads ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cmpb #io$_readvblk,r2 ;Read virtual? beql handle_reads cmpb #io$_readlblk,r2 ;Read logical? beql handle_reads cmpb #io$_readpblk,r2 ;Read physical? beql handle_reads ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Check for writes ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cmpb #io$_writevblk,r2 ;Write virtual? beql handle_writes cmpb #io$_writelblk,r2 ;Write logical? beql handle_writes cmpb #io$_writepblk,r2 ;Write physical? beql handle_writes brw exit handle_reads: incl read_count ;increment read count movl irp$l_bcnt(r3),r2 ;determine the size divl2 #512,r2 ;Compute the size in blocks cmpl r2,#127 ;if > 127 blocks note in 127 blssu ok1 movl #127,r2 ok1: incl read_lengths[r2] ;increment size counter brw check_splits handle_writes: incl write_count ;increment write count movl irp$l_bcnt(r3),r2 ;determine the size divl2 #512,r2 ;Compute size in blocks cmpl r2,#127 ;if > 127 then set to 127 blssu ok2 movl #127,r2 ok2: incl write_lengths[r2] ;increment write size counter check_splits: ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; If not a virtual i/o then it cannot be a split i/o. ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bbc #irp$v_virtual,irp$w_sts(r3),exit tstl irp$l_abcnt(r3) ;If accumulated byte count ; is 0 this is either not a split ; i/o or it is the first pass ; prior to the split so skip it. beql exit incl splits ; else increment split count exit: popr #^m jmp @saved_start ;Goto driver start i/o routine pool_code_end: code_len = pool_code_end-pool_code_start ;amount of pool to allocate .end load_block_ctr