Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 8 kB image not shown  

Quelle  memx.fuc   Sprache: unbekannt

 
/*
 * 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 , 0x0000, 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)
handler(VBLANK, 0x0001, 0x0000, #memx_func_wait_vblank)
handler(TRAIN , 0x0000, 0x0000, #memx_func_train)
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_ts_start:
.b32 0
memx_ts_end:
.b32 0

memx_data_head:
.skip 0x0800
memx_data_tail:

memx_train_head:
.skip 0x0100
memx_train_tail:
#endif

/******************************************************************************
 * MEMX code segment
 *****************************************************************************/
#ifdef INCLUDE_CODE
// description
//
// $r15 - current (memx)
// $r4  - packet length
// $r3  - opcode desciption
// $r0  - zero
memx_func_enter:
#if NVKM_PPWR_CHIPSET == GT215
 mov $r8 0x1610
 nv_rd32($r7, $r8)
 imm32($r6, 0xfffffffc)
 and $r7 $r6
 mov $r6 0x2
 or $r7 $r6
 nv_wr32($r8, $r7)
#else
 mov $r6 0x001620
 imm32($r7, ~0x00000aa2);
 nv_rd32($r8, $r6)
 and $r8 $r7
 nv_wr32($r6, $r8)

 imm32($r7, ~0x00000001)
 nv_rd32($r8, $r6)
 and $r8 $r7
 nv_wr32($r6, $r8)

 mov $r6 0x0026f0
 nv_rd32($r8, $r6)
 and $r8 $r7
 nv_wr32($r6, $r8)
#endif

 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

 nv_iord($r6, NV_PPWR_TIMER_LOW)
 st b32 D[$r0 + #memx_ts_start] $r6
 ret

// description
//
// $r15 - current (memx)
// $r4  - packet length
// $r3  - opcode desciption
// $r0  - zero
memx_func_leave:
 nv_iord($r6, NV_PPWR_TIMER_LOW)
 st b32 D[$r0 + #memx_ts_end] $r6

 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

#if NVKM_PPWR_CHIPSET == GT215
 mov $r8 0x1610
 nv_rd32($r7, $r8)
 imm32($r6, 0xffffffcc)
 and $r7 $r6
 nv_wr32($r8, $r7)
#else
 mov $r6 0x0026f0
 imm32($r7, 0x00000001)
 nv_rd32($r8, $r6)
 or $r8 $r7
 nv_wr32($r6, $r8)

 mov $r6 0x001620
 nv_rd32($r8, $r6)
 or $r8 $r7
 nv_wr32($r6, $r8)

 imm32($r7, 0x00000aa2);
 nv_rd32($r8, $r6)
 or $r8 $r7
 nv_wr32($r6, $r8)
#endif
 ret

#if NVKM_PPWR_CHIPSET < GF119
// description
//
// $r15 - current (memx)
// $r4  - packet length
// +00: head to wait for vblank on
// $r3  - opcode desciption
// $r0  - zero
memx_func_wait_vblank:
 ld b32 $r6 D[$r1 + 0x00]
 cmp b32 $r6 0x0
 bra z #memx_func_wait_vblank_head0
 cmp b32 $r6 0x1
 bra z #memx_func_wait_vblank_head1
 bra #memx_func_wait_vblank_fini

 memx_func_wait_vblank_head1:
 mov $r7 0x20
 bra #memx_func_wait_vblank_0

 memx_func_wait_vblank_head0:
 mov $r7 0x8

 memx_func_wait_vblank_0:
  nv_iord($r6, NV_PPWR_INPUT)
  and $r6 $r7
  bra nz #memx_func_wait_vblank_0

 memx_func_wait_vblank_1:
  nv_iord($r6, NV_PPWR_INPUT)
  and $r6 $r7
  bra z #memx_func_wait_vblank_1

 memx_func_wait_vblank_fini:
 add b32 $r1 0x4
 ret

#else

// XXX: currently no-op
//
// $r15 - current (memx)
// $r4  - packet length
// +00: head to wait for vblank on
// $r3  - opcode desciption
// $r0  - zero
memx_func_wait_vblank:
 add b32 $r1 0x4
 ret

#endif

// 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)
// $r4  - packet length
// $r3  - opcode desciption
// $r0  - zero
memx_func_train:
#if NVKM_PPWR_CHIPSET == GT215
// $r5 - outer loop counter
// $r6 - inner loop counter
// $r7 - entry counter (#memx_train_head + $r7)
 mov $r5 0x3
 mov $r7 0x0

// Read random memory to wake up... things
 imm32($r9, 0x700000)
 nv_rd32($r8,$r9)
 mov $r14 0x2710
 call(nsec)

 memx_func_train_loop_outer:
  mulu $r8 $r5 0x101
  sethi $r8 0x02000000
  imm32($r9, 0x1111e0)
  nv_wr32($r9, $r8)
  push $r5

  mov $r6 0x0
  memx_func_train_loop_inner:
   mov $r8 0x1111
   mulu $r9 $r6 $r8
   shl b32 $r8 $r9 0x10
   or $r8 $r9
   imm32($r9, 0x100720)
   nv_wr32($r9, $r8)

   imm32($r9, 0x100080)
   nv_rd32($r8, $r9)
   or $r8 $r8 0x20
   nv_wr32($r9, $r8)

   imm32($r9, 0x10053c)
   imm32($r8, 0x80003002)
   nv_wr32($r9, $r8)

   imm32($r14, 0x100560)
   imm32($r13, 0x80000000)
   add b32 $r12 $r13 0
   imm32($r11, 0x001e8480)
   call(wait)

   // $r5 - inner inner loop counter
   // $r9 - result
   mov $r5 0
   imm32($r9, 0x8300ffff)
   memx_func_train_loop_4x:
    imm32($r10, 0x100080)
    nv_rd32($r8, $r10)
    imm32($r11, 0xffffffdf)
    and $r8 $r11
    nv_wr32($r10, $r8)

    imm32($r10, 0x10053c)
    imm32($r8, 0x80003002)
    nv_wr32($r10, $r8)

    imm32($r14, 0x100560)
    imm32($r13, 0x80000000)
    mov b32 $r12 $r13
    imm32($r11, 0x00002710)
    call(wait)

    nv_rd32($r13, $r14)
    and $r9 $r9 $r13

    add b32 $r5 1
    cmp b16 $r5 0x4
    bra l #memx_func_train_loop_4x

   add b32 $r10 $r7 #memx_train_head
   st b32 D[$r10 + 0] $r9
   add b32 $r6 1
   add b32 $r7 4

   cmp b16 $r6 0x10
   bra l #memx_func_train_loop_inner

  pop $r5
  add b32 $r5 1
  cmp b16 $r5 7
  bra l #memx_func_train_loop_outer

#endif
 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
  ld b32 $r3 D[$r1]
  add b32 $r1 4
  extr $r4 $r3 16:31
  extr $r3 $r3 0:15

  // execute the opcode handler
  sub b32 $r3 1
  mulu $r3 #memx_func_size
  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
 ld b32 $r11 D[$r0 + #memx_ts_start]
 ld b32 $r12 D[$r0 + #memx_ts_end]
 sub b32 $r12 $r11
 nv_iord($r11, NV_PPWR_INPUT)
 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:
 cmp b16 $r12 0x1
 bra e #memx_info_train

 memx_info_data:
 mov $r12 #memx_data_head
 mov $r11 #memx_data_tail - #memx_data_head
 bra #memx_info_send

 memx_info_train:
 mov $r12 #memx_train_head
 mov $r11 #memx_train_tail - #memx_train_head

 memx_info_send:
 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

[ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ]