/* * Copyright 2013 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Ben Skeggs */ #ifdef INCLUDE_PROC process(PROC_MEMX, #memx_init, #memx_recv) #endif /****************************************************************************** * MEMX data segment *****************************************************************************/ #ifdef INCLUDE_DATA .equ #memx_opcode 0 .equ #memx_header 2 .equ #memx_length 4 .equ #memx_func 8 #define handler(cmd,hdr,len,func) /* */ .b16 MEMX_##cmd /* */ .b16 hdr /* */ .b16 len /* */ .b16 0 /* */ .b32 func memx_func_head: handler(ENTER , 0x0001, 0x0000, #memx_func_enter) memx_func_next: handler(LEAVE , 0x0000, 0x0000, #memx_func_leave) handler(WR32 , 0x0000, 0x0002, #memx_func_wr32) handler(WAIT , 0x0004, 0x0000, #memx_func_wait) handler(DELAY , 0x0001, 0x0000, #memx_func_delay) memx_func_tail: .equ #memx_func_size #memx_func_next - #memx_func_head .equ #memx_func_num (#memx_func_tail - #memx_func_head) / #memx_func_size memx_data_head: .skip 0x0800 memx_data_tail: #endif /****************************************************************************** * MEMX code segment *****************************************************************************/ #ifdef INCLUDE_CODE // description // // $r15 - current (memx) // $r4 - packet length // +00: bitmask of heads to wait for vblank on // $r3 - opcode desciption // $r0 - zero memx_func_enter: mov $r6 NV_PPWR_OUTPUT_SET_FB_PAUSE nv_iowr(NV_PPWR_OUTPUT_SET, $r6) memx_func_enter_wait: nv_iord($r6, NV_PPWR_OUTPUT) and $r6 NV_PPWR_OUTPUT_FB_PAUSE bra z #memx_func_enter_wait //XXX: TODO ld b32 $r6 D[$r1 + 0x00] add b32 $r1 0x04 ret // description // // $r15 - current (memx) // $r4 - packet length // $r3 - opcode desciption // $r0 - zero memx_func_leave: mov $r6 NV_PPWR_OUTPUT_CLR_FB_PAUSE nv_iowr(NV_PPWR_OUTPUT_CLR, $r6) memx_func_leave_wait: nv_iord($r6, NV_PPWR_OUTPUT) and $r6 NV_PPWR_OUTPUT_FB_PAUSE bra nz #memx_func_leave_wait ret // description // // $r15 - current (memx) // $r4 - packet length // +00*n: addr // +04*n: data // $r3 - opcode desciption // $r0 - zero memx_func_wr32: ld b32 $r6 D[$r1 + 0x00] ld b32 $r5 D[$r1 + 0x04] add b32 $r1 0x08 nv_wr32($r6, $r5) sub b32 $r4 0x02 bra nz #memx_func_wr32 ret // description // // $r15 - current (memx) // $r4 - packet length // +00: addr // +04: mask // +08: data // +0c: timeout (ns) // $r3 - opcode desciption // $r0 - zero memx_func_wait: nv_iord($r8, NV_PPWR_TIMER_LOW) ld b32 $r14 D[$r1 + 0x00] ld b32 $r13 D[$r1 + 0x04] ld b32 $r12 D[$r1 + 0x08] ld b32 $r11 D[$r1 + 0x0c] add b32 $r1 0x10 call(wait) ret // description // // $r15 - current (memx) // $r4 - packet length // +00: time (ns) // $r3 - opcode desciption // $r0 - zero memx_func_delay: ld b32 $r14 D[$r1 + 0x00] add b32 $r1 0x04 call(nsec) ret // description // // $r15 - current (memx) // $r14 - sender process name // $r13 - message (exec) // $r12 - head of script // $r11 - tail of script // $r0 - zero memx_exec: push $r14 push $r13 mov b32 $r1 $r12 mov b32 $r2 $r11 memx_exec_next: // fetch the packet header, and locate opcode info ld b32 $r3 D[$r1] add b32 $r1 4 shr b32 $r4 $r3 16 mulu $r3 #memx_func_size // execute the opcode handler ld b32 $r5 D[$r3 + #memx_func_head + #memx_func] call $r5 // keep going, if we haven't reached the end cmp b32 $r1 $r2 bra l #memx_exec_next // send completion reply pop $r13 pop $r14 call(send) ret // description // // $r15 - current (memx) // $r14 - sender process name // $r13 - message // $r12 - data0 // $r11 - data1 // $r0 - zero memx_info: mov $r12 #memx_data_head mov $r11 #memx_data_tail - #memx_data_head call(send) ret // description // // $r15 - current (memx) // $r14 - sender process name // $r13 - message // $r12 - data0 // $r11 - data1 // $r0 - zero memx_recv: cmp b32 $r13 MEMX_MSG_EXEC bra e #memx_exec cmp b32 $r13 MEMX_MSG_INFO bra e #memx_info ret // description // // $r15 - current (memx) // $r0 - zero memx_init: ret #endif