| /* |
| * 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 |