head	1.3;
access;
symbols
	netbsd-11-0-RC7:1.3
	netbsd-11-0-RC6:1.3
	netbsd-11-0-RC5:1.3
	netbsd-11-0-RC4:1.3
	netbsd-11-0-RC3:1.3
	netbsd-11-0-RC2:1.3
	netbsd-11-0-RC1:1.3
	perseant-exfatfs-base-20250801:1.3
	netbsd-11:1.3.0.12
	netbsd-11-base:1.3
	netbsd-10-1-RELEASE:1.3
	perseant-exfatfs-base-20240630:1.3
	perseant-exfatfs:1.3.0.10
	perseant-exfatfs-base:1.3
	netbsd-9-4-RELEASE:1.2
	netbsd-10-0-RELEASE:1.3
	netbsd-10-0-RC6:1.3
	netbsd-10-0-RC5:1.3
	netbsd-10-0-RC4:1.3
	netbsd-10-0-RC3:1.3
	netbsd-10-0-RC2:1.3
	thorpej-ifq:1.3.0.8
	thorpej-ifq-base:1.3
	thorpej-altq-separation:1.3.0.6
	thorpej-altq-separation-base:1.3
	netbsd-10-0-RC1:1.3
	netbsd-10:1.3.0.4
	netbsd-10-base:1.3
	bouyer-sunxi-drm:1.3.0.2
	bouyer-sunxi-drm-base:1.3
	netbsd-9-3-RELEASE:1.2
	linux-drm-v5-6-rc3:1.1.1.2
	thorpej-i2c-spi-conf2:1.2.0.30
	thorpej-i2c-spi-conf2-base:1.2
	thorpej-futex2:1.2.0.28
	thorpej-futex2-base:1.2
	thorpej-cfargs2:1.2.0.26
	thorpej-cfargs2-base:1.2
	cjep_sun2x-base1:1.2
	cjep_sun2x:1.2.0.24
	cjep_sun2x-base:1.2
	cjep_staticlib_x-base1:1.2
	netbsd-9-2-RELEASE:1.2
	cjep_staticlib_x:1.2.0.22
	cjep_staticlib_x-base:1.2
	thorpej-i2c-spi-conf:1.2.0.20
	thorpej-i2c-spi-conf-base:1.2
	thorpej-cfargs:1.2.0.18
	thorpej-cfargs-base:1.2
	thorpej-futex:1.2.0.16
	thorpej-futex-base:1.2
	netbsd-9-1-RELEASE:1.2
	bouyer-xenpvh-base2:1.2
	phil-wifi-20200421:1.2
	bouyer-xenpvh-base1:1.2
	phil-wifi-20200411:1.2
	bouyer-xenpvh:1.2.0.14
	bouyer-xenpvh-base:1.2
	is-mlppp:1.2.0.12
	is-mlppp-base:1.2
	phil-wifi-20200406:1.2
	ad-namecache-base3:1.2
	netbsd-9-0-RELEASE:1.2
	netbsd-9-0-RC2:1.2
	ad-namecache-base2:1.2
	ad-namecache-base1:1.2
	ad-namecache:1.2.0.10
	ad-namecache-base:1.2
	netbsd-9-0-RC1:1.2
	phil-wifi-20191119:1.2
	netbsd-9:1.2.0.8
	netbsd-9-base:1.2
	phil-wifi:1.2.0.6
	phil-wifi-20190609:1.2
	isaki-audio2:1.2.0.4
	isaki-audio2-base:1.2
	pgoyette-compat-merge-20190127:1.2.2.2
	pgoyette-compat-20190127:1.2
	pgoyette-compat-20190118:1.2
	pgoyette-compat-1226:1.2
	pgoyette-compat-1126:1.2
	pgoyette-compat-1020:1.2
	pgoyette-compat-0930:1.2
	pgoyette-compat:1.2.0.2
	pgoyette-compat-0906:1.2
	linux-drm-v4-4-143:1.1.1.1
	LINUX:1.1.1;
locks; strict;
comment	@# @;


1.3
date	2021.12.18.23.45.41;	author riastradh;	state Exp;
branches;
next	1.2;
commitid	Zzh9v7Bb24ydPblD;

1.2
date	2018.08.27.04.58.35;	author riastradh;	state Exp;
branches
	1.2.2.1
	1.2.6.1;
next	1.1;
commitid	SZZre9lWvwC1sIPA;

1.1
date	2018.08.27.01.34.56;	author riastradh;	state Exp;
branches
	1.1.1.1;
next	;
commitid	J8kFZ57DI7RmkHPA;

1.2.2.1
date	2018.08.27.04.58.35;	author pgoyette;	state dead;
branches;
next	1.2.2.2;
commitid	HCi1bXD317XIK0RA;

1.2.2.2
date	2018.09.06.06.56.30;	author pgoyette;	state Exp;
branches;
next	;
commitid	HCi1bXD317XIK0RA;

1.2.6.1
date	2018.08.27.04.58.35;	author christos;	state dead;
branches;
next	1.2.6.2;
commitid	jtc8rnCzWiEEHGqB;

1.2.6.2
date	2019.06.10.22.08.24;	author christos;	state Exp;
branches;
next	;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.1
date	2018.08.27.01.34.56;	author riastradh;	state Exp;
branches;
next	1.1.1.2;
commitid	J8kFZ57DI7RmkHPA;

1.1.1.2
date	2021.12.18.20.15.42;	author riastradh;	state Exp;
branches;
next	;
commitid	Qm9wp54q2SRJDalD;


desc
@@


1.3
log
@Merge linux-drm-v5-6-rc3
@
text
@/*
 * 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
 */

/******************************************************************************
 * kernel data segment
 *****************************************************************************/
#ifdef INCLUDE_PROC
proc_kern:
process(PROC_KERN, 0, 0)
proc_list_head:
#endif

#ifdef INCLUDE_DATA
proc_list_tail:
time_prev: .b32 0
time_next: .b32 0
#endif

/******************************************************************************
 * kernel code segment
 *****************************************************************************/
#ifdef INCLUDE_CODE
	bra #init

// read nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data (return)
// $r0  - zero
rd32:
	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
	imm32($r13, NV_PPWR_MMIO_CTRL_OP_RD | NV_PPWR_MMIO_CTRL_TRIGGER)
	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
	rd32_wait:
		nv_iord($r13, NV_PPWR_MMIO_CTRL)
		and $r13 NV_PPWR_MMIO_CTRL_STATUS
		bra nz #rd32_wait
	nv_iord($r13, NV_PPWR_MMIO_DATA)
	ret

// write nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data
// $r0  - zero
wr32:
	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
	nv_iowr(NV_PPWR_MMIO_DATA, $r13)
	imm32($r13, NV_PPWR_MMIO_CTRL_OP_WR | NV_PPWR_MMIO_CTRL_MASK_B32_0 | NV_PPWR_MMIO_CTRL_TRIGGER)

#ifdef NVKM_FALCON_MMIO_TRAP
	push $r13
	mov $r13 NV_PPWR_INTR_TRIGGER_USER1
	nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
	wr32_host:
		nv_iord($r13, NV_PPWR_INTR)
		and $r13 NV_PPWR_INTR_USER1
		bra nz #wr32_host
	pop $r13
#endif

	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
	wr32_wait:
		nv_iord($r13, NV_PPWR_MMIO_CTRL)
		and $r13 NV_PPWR_MMIO_CTRL_STATUS
		bra nz #wr32_wait
	ret

// busy-wait for a period of time
//
// $r15 - current
// $r14 - ns
// $r0  - zero
nsec:
	push $r9
	push $r8
	nv_iord($r8, NV_PPWR_TIMER_LOW)
	nsec_loop:
		nv_iord($r9, NV_PPWR_TIMER_LOW)
		sub b32 $r9 $r8
		cmp b32 $r9 $r14
		bra l #nsec_loop
	pop $r8
	pop $r9
	ret

// busy-wait for a period of time
//
// $r15 - current
// $r14 - addr
// $r13 - mask
// $r12 - data
// $r11 - timeout (ns)
// $r0  - zero
wait:
	push $r9
	push $r8
	nv_iord($r8, NV_PPWR_TIMER_LOW)
	wait_loop:
		nv_rd32($r10, $r14)
		and $r10 $r13
		cmp b32 $r10 $r12
		bra e #wait_done
		nv_iord($r9, NV_PPWR_TIMER_LOW)
		sub b32 $r9 $r8
		cmp b32 $r9 $r11
		bra l #wait_loop
	wait_done:
	pop $r8
	pop $r9
	ret

// $r15 - current (kern)
// $r14 - process
// $r8  - NV_PPWR_INTR
intr_watchdog:
	// read process' timer status, skip if not enabled
	ld b32 $r9 D[$r14 + #proc_time]
	cmp b32 $r9 0
	bra z #intr_watchdog_next_proc

	// subtract last timer's value from process' timer,
	// if it's <= 0 then the timer has expired
	ld b32 $r10 D[$r0 + #time_prev]
	sub b32 $r9 $r10
	bra g #intr_watchdog_next_time
		mov $r13 KMSG_ALARM
		call(send_proc)
		clear b32 $r9
		bra #intr_watchdog_next_proc

	// otherwise, update the next timer's value if this
	// process' timer is the soonest
	intr_watchdog_next_time:
		// ... or if there's no next timer yet
		ld b32 $r10 D[$r0 + #time_next]
		cmp b32 $r10 0
		bra z #intr_watchdog_next_time_set

		cmp b32 $r9 $r10
		bra g #intr_watchdog_next_proc
		intr_watchdog_next_time_set:
		st b32 D[$r0 + #time_next] $r9

	// update process' timer status, and advance
	intr_watchdog_next_proc:
	st b32 D[$r14 + #proc_time] $r9
	add b32 $r14 #proc_size
	cmp b32 $r14 #proc_list_tail
	bra ne #intr_watchdog
	ret

intr:
	push $r0
	clear b32 $r0
	push $r8
	push $r9
	push $r10
	push $r11
	push $r12
	push $r13
	push $r14
	push $r15
	mov $r15 #proc_kern
	mov $r8 $flags
	push $r8

	nv_iord($r8, NV_PPWR_DSCRATCH(0))
	add b32 $r8 1
	nv_iowr(NV_PPWR_DSCRATCH(0), $r8)

	nv_iord($r8, NV_PPWR_INTR)
	and $r9 $r8 NV_PPWR_INTR_WATCHDOG
	bra z #intr_skip_watchdog
		st b32 D[$r0 + #time_next] $r0
		mov $r14 #proc_list_head
		call(intr_watchdog)
		ld b32 $r9 D[$r0 + #time_next]
		cmp b32 $r9 0
		bra z #intr_skip_watchdog
			nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9)
			st b32 D[$r0 + #time_prev] $r9

	intr_skip_watchdog:
	and $r9 $r8 NV_PPWR_INTR_SUBINTR
	bra z #intr_skip_subintr
		nv_iord($r9, NV_PPWR_SUBINTR)
		and $r10 $r9 NV_PPWR_SUBINTR_FIFO
		bra z #intr_subintr_skip_fifo
			nv_iord($r12, NV_PPWR_FIFO_INTR)
			push $r12
			imm32($r14, PROC_HOST)
			mov $r13 KMSG_FIFO
			call(send)
			pop $r12
			nv_iowr(NV_PPWR_FIFO_INTR, $r12)
		intr_subintr_skip_fifo:
		nv_iowr(NV_PPWR_SUBINTR, $r9)

	intr_skip_subintr:
	mov $r9 (NV_PPWR_INTR_USER0 | NV_PPWR_INTR_USER1 | NV_PPWR_INTR_PAUSE)
	not b32 $r9
	and $r8 $r9
	nv_iowr(NV_PPWR_INTR_ACK, $r8)

	pop $r8
	mov $flags $r8
	pop $r15
	pop $r14
	pop $r13
	pop $r12
	pop $r11
	pop $r10
	pop $r9
	pop $r8
	pop $r0
	bclr $flags $p0
	iret

// calculate the number of ticks in the specified nanoseconds delay
//
// $r15 - current
// $r14 - ns
// $r14 - ticks (return)
// $r0  - zero
ticks_from_ns:
	push $r12
	push $r11

	/* try not losing precision (multiply then divide) */
	imm32($r13, HW_TICKS_PER_US)
	call(mulu32_32_64)

	/* use an immeditate, it's ok because HW_TICKS_PER_US < 16 bits */
	div $r12 $r12 1000

	/* check if there wasn't any overflow */
	cmpu b32 $r11 0
	bra e #ticks_from_ns_quit

	/* let's divide then multiply, too bad for the precision! */
	div $r14 $r14 1000
	imm32($r13, HW_TICKS_PER_US)
	call(mulu32_32_64)

	/* this cannot overflow as long as HW_TICKS_PER_US < 1000 */

ticks_from_ns_quit:
	mov b32 $r14 $r12
	pop $r11
	pop $r12
	ret

// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - us
// $r14 - ticks (return)
// $r0  - zero
ticks_from_us:
	push $r12
	push $r11

	/* simply multiply $us by HW_TICKS_PER_US */
	imm32($r13, HW_TICKS_PER_US)
	call(mulu32_32_64)
	mov b32 $r14 $r12

	/* check if there wasn't any overflow */
	cmpu b32 $r11 0
	bra e #ticks_from_us_quit

	/* Overflow! */
	clear b32 $r14

ticks_from_us_quit:
	pop $r11
	pop $r12
	ret

// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - ticks
// $r14 - us (return)
// $r0  - zero
ticks_to_us:
	/* simply divide $ticks by HW_TICKS_PER_US */
	imm32($r13, HW_TICKS_PER_US)
	div $r14 $r14 $r13

	ret

// request the current process be sent a message after a timeout expires
//
// $r15 - current
// $r14 - ticks (make sure it is < 2^31 to avoid any possible overflow)
// $r0  - zero
timer:
	push $r9
	push $r8

	// interrupts off to prevent racing with timer isr
	bclr $flags ie0

	// if current process already has a timer set, bail
	ld b32 $r8 D[$r15 + #proc_time]
	cmp b32 $r8 0
	bra g #timer_done

	// halt watchdog timer temporarily
	clear b32 $r8
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)

	// find out how much time elapsed since the last update
	// of the watchdog and add this time to the wanted ticks
	nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
	ld b32 $r9 D[$r0 + #time_prev]
	sub b32 $r9 $r8
	add b32 $r14 $r9
	st b32 D[$r15 + #proc_time] $r14

	// check for a pending interrupt.  if there's one already
	// pending, we can just bail since the timer isr will
	// queue the next soonest right after it's done
	nv_iord($r8, NV_PPWR_INTR)
	and $r8 NV_PPWR_INTR_WATCHDOG
	bra nz #timer_enable

	// update the watchdog if this timer should expire first,
	// or if there's no timeout already set
	nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
	cmp b32 $r14 $r0
	bra e #timer_reset
	cmp b32 $r14 $r8
	bra g #timer_enable
		timer_reset:
		nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14)
		st b32 D[$r0 + #time_prev] $r14

	// re-enable the watchdog timer
	timer_enable:
	mov $r8 1
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)

	// interrupts back on
	timer_done:
	bset $flags ie0

	pop $r8
	pop $r9
	ret

// send message to another process
//
// $r15 - current
// $r14 - process
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0  - zero
send_proc:
	push $r8
	push $r9
	// check for space in queue
	ld b32 $r8 D[$r14 + #proc_qget]
	ld b32 $r9 D[$r14 + #proc_qput]
	xor $r8 #proc_qmaskb
	cmp b32 $r8 $r9
	bra e #send_done

	// enqueue message
	and $r8 $r9 #proc_qmaskp
	shl b32 $r8 $r8 #proc_qlen
	add b32 $r8 #proc_queue
	add b32 $r8 $r14

	ld b32 $r10 D[$r15 + #proc_id]
	st b32 D[$r8 + #msg_process] $r10
	st b32 D[$r8 + #msg_message] $r13
	st b32 D[$r8 + #msg_data0] $r12
	st b32 D[$r8 + #msg_data1] $r11

	// increment PUT
	add b32 $r9 1
	and $r9 #proc_qmaskf
	st b32 D[$r14 + #proc_qput] $r9
	bset $flags $p2
	send_done:
	pop $r9
	pop $r8
	ret

// lookup process structure by its name
//
// $r15 - current
// $r14 - process name
// $r0  - zero
//
// $r14 - process
// $p1  - success
find:
	push $r8
	mov $r8 #proc_list_head
	bset $flags $p1
	find_loop:
		ld b32 $r10 D[$r8 + #proc_id]
		cmp b32 $r10 $r14
		bra e #find_done
		add b32 $r8 #proc_size
		cmp b32 $r8 #proc_list_tail
		bra ne #find_loop
		bclr $flags $p1
	find_done:
	mov b32 $r14 $r8
	pop $r8
	ret

// send message to another process
//
// $r15 - current
// $r14 - process id
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0  - zero
send:
	call(find)
	bra $p1 #send_proc
	ret

// process single message for a given process
//
// $r15 - current
// $r14 - process
// $r0  - zero
recv:
	push $r9
	push $r8

	ld b32 $r8 D[$r14 + #proc_qget]
	ld b32 $r9 D[$r14 + #proc_qput]
	bclr $flags $p1
	cmp b32 $r8 $r9
	bra e #recv_done
		// dequeue message
		and $r9 $r8 #proc_qmaskp
		add b32 $r8 1
		and $r8 #proc_qmaskf
		st b32 D[$r14 + #proc_qget] $r8
		ld b32 $r10 D[$r14 + #proc_recv]

		push $r15
		mov $r15 $flags
		push $r15
		mov b32 $r15 $r14

		shl b32 $r9 $r9 #proc_qlen
		add b32 $r14 $r9
		add b32 $r14 #proc_queue
		ld b32 $r11 D[$r14 + #msg_data1]
		ld b32 $r12 D[$r14 + #msg_data0]
		ld b32 $r13 D[$r14 + #msg_message]
		ld b32 $r14 D[$r14 + #msg_process]

		// process it
		call $r10
		pop $r15
		mov $flags $r15
		bset $flags $p1
		pop $r15
	recv_done:
	pop $r8
	pop $r9
	ret

init:
	// setup stack
	nv_iord($r1, NV_PPWR_CAPS)
	extr $r1 $r1 9:17
	shl b32 $r1 8
	mov $sp $r1

#ifdef NVKM_FALCON_MMIO_UAS
	// somehow allows the magic "access mmio via D[]" stuff that's
	// used by the nv_rd32/nv_wr32 macros to work
	imm32($r1, 0x10 | NV_PPWR_UAS_CONFIG_ENABLE)
	nv_iowrs(NV_PPWR_UAS_CONFIG, $r1)
#endif

	// route all interrupts except user0/1 and pause to fuc
	imm32($r1, 0xe0)
	nv_iowr(NV_PPWR_INTR_ROUTE, $r1)

	// enable watchdog and subintr intrs
	mov $r1 NV_PPWR_INTR_EN_CLR_MASK
	nv_iowr(NV_PPWR_INTR_EN_CLR, $r1)
	mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG
	or $r1 NV_PPWR_INTR_EN_SET_SUBINTR
	nv_iowr(NV_PPWR_INTR_EN_SET, $r1)

	// enable interrupts globally
	imm32($r1, #intr)
	and $r1 0xffff
	mov $iv0 $r1
	bset $flags ie0

	// enable watchdog timer
	mov $r1 1
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1)

	// bootstrap processes, idle process will be last, and not return
	mov $r15 #proc_list_head
	init_proc:
		ld b32 $r1 D[$r15 + #proc_init]
		cmp b32 $r1 0
		bra z #init_proc
		call $r1
		add b32 $r15 #proc_size
		bra #init_proc
#endif
@


1.2
log
@merge linux-drm-v4-4-143
@
text
@d54 1
a54 2
	mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
d72 1
a72 3
	mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
	or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
d215 1
a215 2
			mov $r14 (PROC_HOST & 0x0000ffff)
			sethi $r14 (PROC_HOST & 0xffff0000)
d224 4
a227 8
	and $r9 $r8 NV_PPWR_INTR_PAUSE
	bra z #intr_skip_pause
		and $r10 0xffbf

	intr_skip_pause:
	and $r9 $r8 NV_PPWR_INTR_USER0
	bra z #intr_skip_user0
		and $r10 0xffbf
a228 2
	intr_skip_user0:
	nv_iowr(NV_PPWR_INTR_ACK, $r8)
d255 1
a255 1
	call #mulu32_32_64
d267 1
a267 1
	call #mulu32_32_64
d289 1
a289 1
	call #mulu32_32_64
d510 1
a510 2
	mov $r1 0x0010
	sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE
d515 1
a515 2
	mov $r1 0x00e0
	sethi $r1 0x00000000
d526 2
a527 2
	mov $r1 #intr
	sethi $r1 0x00000000
@


1.2.6.1
log
@file kernel.fuc was added on branch phil-wifi on 2019-06-10 22:08:24 +0000
@
text
@d1 556
@


1.2.6.2
log
@Sync with HEAD
@
text
@a0 556
/*
 * 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
 */

/******************************************************************************
 * kernel data segment
 *****************************************************************************/
#ifdef INCLUDE_PROC
proc_kern:
process(PROC_KERN, 0, 0)
proc_list_head:
#endif

#ifdef INCLUDE_DATA
proc_list_tail:
time_prev: .b32 0
time_next: .b32 0
#endif

/******************************************************************************
 * kernel code segment
 *****************************************************************************/
#ifdef INCLUDE_CODE
	bra #init

// read nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data (return)
// $r0  - zero
rd32:
	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
	mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
	rd32_wait:
		nv_iord($r13, NV_PPWR_MMIO_CTRL)
		and $r13 NV_PPWR_MMIO_CTRL_STATUS
		bra nz #rd32_wait
	nv_iord($r13, NV_PPWR_MMIO_DATA)
	ret

// write nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data
// $r0  - zero
wr32:
	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
	nv_iowr(NV_PPWR_MMIO_DATA, $r13)
	mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
	or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER

#ifdef NVKM_FALCON_MMIO_TRAP
	push $r13
	mov $r13 NV_PPWR_INTR_TRIGGER_USER1
	nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
	wr32_host:
		nv_iord($r13, NV_PPWR_INTR)
		and $r13 NV_PPWR_INTR_USER1
		bra nz #wr32_host
	pop $r13
#endif

	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
	wr32_wait:
		nv_iord($r13, NV_PPWR_MMIO_CTRL)
		and $r13 NV_PPWR_MMIO_CTRL_STATUS
		bra nz #wr32_wait
	ret

// busy-wait for a period of time
//
// $r15 - current
// $r14 - ns
// $r0  - zero
nsec:
	push $r9
	push $r8
	nv_iord($r8, NV_PPWR_TIMER_LOW)
	nsec_loop:
		nv_iord($r9, NV_PPWR_TIMER_LOW)
		sub b32 $r9 $r8
		cmp b32 $r9 $r14
		bra l #nsec_loop
	pop $r8
	pop $r9
	ret

// busy-wait for a period of time
//
// $r15 - current
// $r14 - addr
// $r13 - mask
// $r12 - data
// $r11 - timeout (ns)
// $r0  - zero
wait:
	push $r9
	push $r8
	nv_iord($r8, NV_PPWR_TIMER_LOW)
	wait_loop:
		nv_rd32($r10, $r14)
		and $r10 $r13
		cmp b32 $r10 $r12
		bra e #wait_done
		nv_iord($r9, NV_PPWR_TIMER_LOW)
		sub b32 $r9 $r8
		cmp b32 $r9 $r11
		bra l #wait_loop
	wait_done:
	pop $r8
	pop $r9
	ret

// $r15 - current (kern)
// $r14 - process
// $r8  - NV_PPWR_INTR
intr_watchdog:
	// read process' timer status, skip if not enabled
	ld b32 $r9 D[$r14 + #proc_time]
	cmp b32 $r9 0
	bra z #intr_watchdog_next_proc

	// subtract last timer's value from process' timer,
	// if it's <= 0 then the timer has expired
	ld b32 $r10 D[$r0 + #time_prev]
	sub b32 $r9 $r10
	bra g #intr_watchdog_next_time
		mov $r13 KMSG_ALARM
		call(send_proc)
		clear b32 $r9
		bra #intr_watchdog_next_proc

	// otherwise, update the next timer's value if this
	// process' timer is the soonest
	intr_watchdog_next_time:
		// ... or if there's no next timer yet
		ld b32 $r10 D[$r0 + #time_next]
		cmp b32 $r10 0
		bra z #intr_watchdog_next_time_set

		cmp b32 $r9 $r10
		bra g #intr_watchdog_next_proc
		intr_watchdog_next_time_set:
		st b32 D[$r0 + #time_next] $r9

	// update process' timer status, and advance
	intr_watchdog_next_proc:
	st b32 D[$r14 + #proc_time] $r9
	add b32 $r14 #proc_size
	cmp b32 $r14 #proc_list_tail
	bra ne #intr_watchdog
	ret

intr:
	push $r0
	clear b32 $r0
	push $r8
	push $r9
	push $r10
	push $r11
	push $r12
	push $r13
	push $r14
	push $r15
	mov $r15 #proc_kern
	mov $r8 $flags
	push $r8

	nv_iord($r8, NV_PPWR_DSCRATCH(0))
	add b32 $r8 1
	nv_iowr(NV_PPWR_DSCRATCH(0), $r8)

	nv_iord($r8, NV_PPWR_INTR)
	and $r9 $r8 NV_PPWR_INTR_WATCHDOG
	bra z #intr_skip_watchdog
		st b32 D[$r0 + #time_next] $r0
		mov $r14 #proc_list_head
		call(intr_watchdog)
		ld b32 $r9 D[$r0 + #time_next]
		cmp b32 $r9 0
		bra z #intr_skip_watchdog
			nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9)
			st b32 D[$r0 + #time_prev] $r9

	intr_skip_watchdog:
	and $r9 $r8 NV_PPWR_INTR_SUBINTR
	bra z #intr_skip_subintr
		nv_iord($r9, NV_PPWR_SUBINTR)
		and $r10 $r9 NV_PPWR_SUBINTR_FIFO
		bra z #intr_subintr_skip_fifo
			nv_iord($r12, NV_PPWR_FIFO_INTR)
			push $r12
			mov $r14 (PROC_HOST & 0x0000ffff)
			sethi $r14 (PROC_HOST & 0xffff0000)
			mov $r13 KMSG_FIFO
			call(send)
			pop $r12
			nv_iowr(NV_PPWR_FIFO_INTR, $r12)
		intr_subintr_skip_fifo:
		nv_iowr(NV_PPWR_SUBINTR, $r9)

	intr_skip_subintr:
	and $r9 $r8 NV_PPWR_INTR_PAUSE
	bra z #intr_skip_pause
		and $r10 0xffbf

	intr_skip_pause:
	and $r9 $r8 NV_PPWR_INTR_USER0
	bra z #intr_skip_user0
		and $r10 0xffbf

	intr_skip_user0:
	nv_iowr(NV_PPWR_INTR_ACK, $r8)
	pop $r8
	mov $flags $r8
	pop $r15
	pop $r14
	pop $r13
	pop $r12
	pop $r11
	pop $r10
	pop $r9
	pop $r8
	pop $r0
	bclr $flags $p0
	iret

// calculate the number of ticks in the specified nanoseconds delay
//
// $r15 - current
// $r14 - ns
// $r14 - ticks (return)
// $r0  - zero
ticks_from_ns:
	push $r12
	push $r11

	/* try not losing precision (multiply then divide) */
	imm32($r13, HW_TICKS_PER_US)
	call #mulu32_32_64

	/* use an immeditate, it's ok because HW_TICKS_PER_US < 16 bits */
	div $r12 $r12 1000

	/* check if there wasn't any overflow */
	cmpu b32 $r11 0
	bra e #ticks_from_ns_quit

	/* let's divide then multiply, too bad for the precision! */
	div $r14 $r14 1000
	imm32($r13, HW_TICKS_PER_US)
	call #mulu32_32_64

	/* this cannot overflow as long as HW_TICKS_PER_US < 1000 */

ticks_from_ns_quit:
	mov b32 $r14 $r12
	pop $r11
	pop $r12
	ret

// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - us
// $r14 - ticks (return)
// $r0  - zero
ticks_from_us:
	push $r12
	push $r11

	/* simply multiply $us by HW_TICKS_PER_US */
	imm32($r13, HW_TICKS_PER_US)
	call #mulu32_32_64
	mov b32 $r14 $r12

	/* check if there wasn't any overflow */
	cmpu b32 $r11 0
	bra e #ticks_from_us_quit

	/* Overflow! */
	clear b32 $r14

ticks_from_us_quit:
	pop $r11
	pop $r12
	ret

// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - ticks
// $r14 - us (return)
// $r0  - zero
ticks_to_us:
	/* simply divide $ticks by HW_TICKS_PER_US */
	imm32($r13, HW_TICKS_PER_US)
	div $r14 $r14 $r13

	ret

// request the current process be sent a message after a timeout expires
//
// $r15 - current
// $r14 - ticks (make sure it is < 2^31 to avoid any possible overflow)
// $r0  - zero
timer:
	push $r9
	push $r8

	// interrupts off to prevent racing with timer isr
	bclr $flags ie0

	// if current process already has a timer set, bail
	ld b32 $r8 D[$r15 + #proc_time]
	cmp b32 $r8 0
	bra g #timer_done

	// halt watchdog timer temporarily
	clear b32 $r8
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)

	// find out how much time elapsed since the last update
	// of the watchdog and add this time to the wanted ticks
	nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
	ld b32 $r9 D[$r0 + #time_prev]
	sub b32 $r9 $r8
	add b32 $r14 $r9
	st b32 D[$r15 + #proc_time] $r14

	// check for a pending interrupt.  if there's one already
	// pending, we can just bail since the timer isr will
	// queue the next soonest right after it's done
	nv_iord($r8, NV_PPWR_INTR)
	and $r8 NV_PPWR_INTR_WATCHDOG
	bra nz #timer_enable

	// update the watchdog if this timer should expire first,
	// or if there's no timeout already set
	nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
	cmp b32 $r14 $r0
	bra e #timer_reset
	cmp b32 $r14 $r8
	bra g #timer_enable
		timer_reset:
		nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14)
		st b32 D[$r0 + #time_prev] $r14

	// re-enable the watchdog timer
	timer_enable:
	mov $r8 1
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)

	// interrupts back on
	timer_done:
	bset $flags ie0

	pop $r8
	pop $r9
	ret

// send message to another process
//
// $r15 - current
// $r14 - process
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0  - zero
send_proc:
	push $r8
	push $r9
	// check for space in queue
	ld b32 $r8 D[$r14 + #proc_qget]
	ld b32 $r9 D[$r14 + #proc_qput]
	xor $r8 #proc_qmaskb
	cmp b32 $r8 $r9
	bra e #send_done

	// enqueue message
	and $r8 $r9 #proc_qmaskp
	shl b32 $r8 $r8 #proc_qlen
	add b32 $r8 #proc_queue
	add b32 $r8 $r14

	ld b32 $r10 D[$r15 + #proc_id]
	st b32 D[$r8 + #msg_process] $r10
	st b32 D[$r8 + #msg_message] $r13
	st b32 D[$r8 + #msg_data0] $r12
	st b32 D[$r8 + #msg_data1] $r11

	// increment PUT
	add b32 $r9 1
	and $r9 #proc_qmaskf
	st b32 D[$r14 + #proc_qput] $r9
	bset $flags $p2
	send_done:
	pop $r9
	pop $r8
	ret

// lookup process structure by its name
//
// $r15 - current
// $r14 - process name
// $r0  - zero
//
// $r14 - process
// $p1  - success
find:
	push $r8
	mov $r8 #proc_list_head
	bset $flags $p1
	find_loop:
		ld b32 $r10 D[$r8 + #proc_id]
		cmp b32 $r10 $r14
		bra e #find_done
		add b32 $r8 #proc_size
		cmp b32 $r8 #proc_list_tail
		bra ne #find_loop
		bclr $flags $p1
	find_done:
	mov b32 $r14 $r8
	pop $r8
	ret

// send message to another process
//
// $r15 - current
// $r14 - process id
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0  - zero
send:
	call(find)
	bra $p1 #send_proc
	ret

// process single message for a given process
//
// $r15 - current
// $r14 - process
// $r0  - zero
recv:
	push $r9
	push $r8

	ld b32 $r8 D[$r14 + #proc_qget]
	ld b32 $r9 D[$r14 + #proc_qput]
	bclr $flags $p1
	cmp b32 $r8 $r9
	bra e #recv_done
		// dequeue message
		and $r9 $r8 #proc_qmaskp
		add b32 $r8 1
		and $r8 #proc_qmaskf
		st b32 D[$r14 + #proc_qget] $r8
		ld b32 $r10 D[$r14 + #proc_recv]

		push $r15
		mov $r15 $flags
		push $r15
		mov b32 $r15 $r14

		shl b32 $r9 $r9 #proc_qlen
		add b32 $r14 $r9
		add b32 $r14 #proc_queue
		ld b32 $r11 D[$r14 + #msg_data1]
		ld b32 $r12 D[$r14 + #msg_data0]
		ld b32 $r13 D[$r14 + #msg_message]
		ld b32 $r14 D[$r14 + #msg_process]

		// process it
		call $r10
		pop $r15
		mov $flags $r15
		bset $flags $p1
		pop $r15
	recv_done:
	pop $r8
	pop $r9
	ret

init:
	// setup stack
	nv_iord($r1, NV_PPWR_CAPS)
	extr $r1 $r1 9:17
	shl b32 $r1 8
	mov $sp $r1

#ifdef NVKM_FALCON_MMIO_UAS
	// somehow allows the magic "access mmio via D[]" stuff that's
	// used by the nv_rd32/nv_wr32 macros to work
	mov $r1 0x0010
	sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE
	nv_iowrs(NV_PPWR_UAS_CONFIG, $r1)
#endif

	// route all interrupts except user0/1 and pause to fuc
	mov $r1 0x00e0
	sethi $r1 0x00000000
	nv_iowr(NV_PPWR_INTR_ROUTE, $r1)

	// enable watchdog and subintr intrs
	mov $r1 NV_PPWR_INTR_EN_CLR_MASK
	nv_iowr(NV_PPWR_INTR_EN_CLR, $r1)
	mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG
	or $r1 NV_PPWR_INTR_EN_SET_SUBINTR
	nv_iowr(NV_PPWR_INTR_EN_SET, $r1)

	// enable interrupts globally
	mov $r1 #intr
	sethi $r1 0x00000000
	mov $iv0 $r1
	bset $flags ie0

	// enable watchdog timer
	mov $r1 1
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1)

	// bootstrap processes, idle process will be last, and not return
	mov $r15 #proc_list_head
	init_proc:
		ld b32 $r1 D[$r15 + #proc_init]
		cmp b32 $r1 0
		bra z #init_proc
		call $r1
		add b32 $r15 #proc_size
		bra #init_proc
#endif
@


1.2.2.1
log
@file kernel.fuc was added on branch pgoyette-compat on 2018-09-06 06:56:30 +0000
@
text
@d1 556
@


1.2.2.2
log
@Sync with HEAD

Resolve a couple of conflicts (result of the uimin/uimax changes)
@
text
@a0 556
/*
 * 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
 */

/******************************************************************************
 * kernel data segment
 *****************************************************************************/
#ifdef INCLUDE_PROC
proc_kern:
process(PROC_KERN, 0, 0)
proc_list_head:
#endif

#ifdef INCLUDE_DATA
proc_list_tail:
time_prev: .b32 0
time_next: .b32 0
#endif

/******************************************************************************
 * kernel code segment
 *****************************************************************************/
#ifdef INCLUDE_CODE
	bra #init

// read nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data (return)
// $r0  - zero
rd32:
	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
	mov $r13 NV_PPWR_MMIO_CTRL_OP_RD
	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER
	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
	rd32_wait:
		nv_iord($r13, NV_PPWR_MMIO_CTRL)
		and $r13 NV_PPWR_MMIO_CTRL_STATUS
		bra nz #rd32_wait
	nv_iord($r13, NV_PPWR_MMIO_DATA)
	ret

// write nv register
//
// $r15 - current
// $r14 - addr
// $r13 - data
// $r0  - zero
wr32:
	nv_iowr(NV_PPWR_MMIO_ADDR, $r14)
	nv_iowr(NV_PPWR_MMIO_DATA, $r13)
	mov $r13 NV_PPWR_MMIO_CTRL_OP_WR
	or $r13 NV_PPWR_MMIO_CTRL_MASK_B32_0
	sethi $r13 NV_PPWR_MMIO_CTRL_TRIGGER

#ifdef NVKM_FALCON_MMIO_TRAP
	push $r13
	mov $r13 NV_PPWR_INTR_TRIGGER_USER1
	nv_iowr(NV_PPWR_INTR_TRIGGER, $r13)
	wr32_host:
		nv_iord($r13, NV_PPWR_INTR)
		and $r13 NV_PPWR_INTR_USER1
		bra nz #wr32_host
	pop $r13
#endif

	nv_iowr(NV_PPWR_MMIO_CTRL, $r13)
	wr32_wait:
		nv_iord($r13, NV_PPWR_MMIO_CTRL)
		and $r13 NV_PPWR_MMIO_CTRL_STATUS
		bra nz #wr32_wait
	ret

// busy-wait for a period of time
//
// $r15 - current
// $r14 - ns
// $r0  - zero
nsec:
	push $r9
	push $r8
	nv_iord($r8, NV_PPWR_TIMER_LOW)
	nsec_loop:
		nv_iord($r9, NV_PPWR_TIMER_LOW)
		sub b32 $r9 $r8
		cmp b32 $r9 $r14
		bra l #nsec_loop
	pop $r8
	pop $r9
	ret

// busy-wait for a period of time
//
// $r15 - current
// $r14 - addr
// $r13 - mask
// $r12 - data
// $r11 - timeout (ns)
// $r0  - zero
wait:
	push $r9
	push $r8
	nv_iord($r8, NV_PPWR_TIMER_LOW)
	wait_loop:
		nv_rd32($r10, $r14)
		and $r10 $r13
		cmp b32 $r10 $r12
		bra e #wait_done
		nv_iord($r9, NV_PPWR_TIMER_LOW)
		sub b32 $r9 $r8
		cmp b32 $r9 $r11
		bra l #wait_loop
	wait_done:
	pop $r8
	pop $r9
	ret

// $r15 - current (kern)
// $r14 - process
// $r8  - NV_PPWR_INTR
intr_watchdog:
	// read process' timer status, skip if not enabled
	ld b32 $r9 D[$r14 + #proc_time]
	cmp b32 $r9 0
	bra z #intr_watchdog_next_proc

	// subtract last timer's value from process' timer,
	// if it's <= 0 then the timer has expired
	ld b32 $r10 D[$r0 + #time_prev]
	sub b32 $r9 $r10
	bra g #intr_watchdog_next_time
		mov $r13 KMSG_ALARM
		call(send_proc)
		clear b32 $r9
		bra #intr_watchdog_next_proc

	// otherwise, update the next timer's value if this
	// process' timer is the soonest
	intr_watchdog_next_time:
		// ... or if there's no next timer yet
		ld b32 $r10 D[$r0 + #time_next]
		cmp b32 $r10 0
		bra z #intr_watchdog_next_time_set

		cmp b32 $r9 $r10
		bra g #intr_watchdog_next_proc
		intr_watchdog_next_time_set:
		st b32 D[$r0 + #time_next] $r9

	// update process' timer status, and advance
	intr_watchdog_next_proc:
	st b32 D[$r14 + #proc_time] $r9
	add b32 $r14 #proc_size
	cmp b32 $r14 #proc_list_tail
	bra ne #intr_watchdog
	ret

intr:
	push $r0
	clear b32 $r0
	push $r8
	push $r9
	push $r10
	push $r11
	push $r12
	push $r13
	push $r14
	push $r15
	mov $r15 #proc_kern
	mov $r8 $flags
	push $r8

	nv_iord($r8, NV_PPWR_DSCRATCH(0))
	add b32 $r8 1
	nv_iowr(NV_PPWR_DSCRATCH(0), $r8)

	nv_iord($r8, NV_PPWR_INTR)
	and $r9 $r8 NV_PPWR_INTR_WATCHDOG
	bra z #intr_skip_watchdog
		st b32 D[$r0 + #time_next] $r0
		mov $r14 #proc_list_head
		call(intr_watchdog)
		ld b32 $r9 D[$r0 + #time_next]
		cmp b32 $r9 0
		bra z #intr_skip_watchdog
			nv_iowr(NV_PPWR_WATCHDOG_TIME, $r9)
			st b32 D[$r0 + #time_prev] $r9

	intr_skip_watchdog:
	and $r9 $r8 NV_PPWR_INTR_SUBINTR
	bra z #intr_skip_subintr
		nv_iord($r9, NV_PPWR_SUBINTR)
		and $r10 $r9 NV_PPWR_SUBINTR_FIFO
		bra z #intr_subintr_skip_fifo
			nv_iord($r12, NV_PPWR_FIFO_INTR)
			push $r12
			mov $r14 (PROC_HOST & 0x0000ffff)
			sethi $r14 (PROC_HOST & 0xffff0000)
			mov $r13 KMSG_FIFO
			call(send)
			pop $r12
			nv_iowr(NV_PPWR_FIFO_INTR, $r12)
		intr_subintr_skip_fifo:
		nv_iowr(NV_PPWR_SUBINTR, $r9)

	intr_skip_subintr:
	and $r9 $r8 NV_PPWR_INTR_PAUSE
	bra z #intr_skip_pause
		and $r10 0xffbf

	intr_skip_pause:
	and $r9 $r8 NV_PPWR_INTR_USER0
	bra z #intr_skip_user0
		and $r10 0xffbf

	intr_skip_user0:
	nv_iowr(NV_PPWR_INTR_ACK, $r8)
	pop $r8
	mov $flags $r8
	pop $r15
	pop $r14
	pop $r13
	pop $r12
	pop $r11
	pop $r10
	pop $r9
	pop $r8
	pop $r0
	bclr $flags $p0
	iret

// calculate the number of ticks in the specified nanoseconds delay
//
// $r15 - current
// $r14 - ns
// $r14 - ticks (return)
// $r0  - zero
ticks_from_ns:
	push $r12
	push $r11

	/* try not losing precision (multiply then divide) */
	imm32($r13, HW_TICKS_PER_US)
	call #mulu32_32_64

	/* use an immeditate, it's ok because HW_TICKS_PER_US < 16 bits */
	div $r12 $r12 1000

	/* check if there wasn't any overflow */
	cmpu b32 $r11 0
	bra e #ticks_from_ns_quit

	/* let's divide then multiply, too bad for the precision! */
	div $r14 $r14 1000
	imm32($r13, HW_TICKS_PER_US)
	call #mulu32_32_64

	/* this cannot overflow as long as HW_TICKS_PER_US < 1000 */

ticks_from_ns_quit:
	mov b32 $r14 $r12
	pop $r11
	pop $r12
	ret

// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - us
// $r14 - ticks (return)
// $r0  - zero
ticks_from_us:
	push $r12
	push $r11

	/* simply multiply $us by HW_TICKS_PER_US */
	imm32($r13, HW_TICKS_PER_US)
	call #mulu32_32_64
	mov b32 $r14 $r12

	/* check if there wasn't any overflow */
	cmpu b32 $r11 0
	bra e #ticks_from_us_quit

	/* Overflow! */
	clear b32 $r14

ticks_from_us_quit:
	pop $r11
	pop $r12
	ret

// calculate the number of ticks in the specified microsecond delay
//
// $r15 - current
// $r14 - ticks
// $r14 - us (return)
// $r0  - zero
ticks_to_us:
	/* simply divide $ticks by HW_TICKS_PER_US */
	imm32($r13, HW_TICKS_PER_US)
	div $r14 $r14 $r13

	ret

// request the current process be sent a message after a timeout expires
//
// $r15 - current
// $r14 - ticks (make sure it is < 2^31 to avoid any possible overflow)
// $r0  - zero
timer:
	push $r9
	push $r8

	// interrupts off to prevent racing with timer isr
	bclr $flags ie0

	// if current process already has a timer set, bail
	ld b32 $r8 D[$r15 + #proc_time]
	cmp b32 $r8 0
	bra g #timer_done

	// halt watchdog timer temporarily
	clear b32 $r8
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)

	// find out how much time elapsed since the last update
	// of the watchdog and add this time to the wanted ticks
	nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
	ld b32 $r9 D[$r0 + #time_prev]
	sub b32 $r9 $r8
	add b32 $r14 $r9
	st b32 D[$r15 + #proc_time] $r14

	// check for a pending interrupt.  if there's one already
	// pending, we can just bail since the timer isr will
	// queue the next soonest right after it's done
	nv_iord($r8, NV_PPWR_INTR)
	and $r8 NV_PPWR_INTR_WATCHDOG
	bra nz #timer_enable

	// update the watchdog if this timer should expire first,
	// or if there's no timeout already set
	nv_iord($r8, NV_PPWR_WATCHDOG_TIME)
	cmp b32 $r14 $r0
	bra e #timer_reset
	cmp b32 $r14 $r8
	bra g #timer_enable
		timer_reset:
		nv_iowr(NV_PPWR_WATCHDOG_TIME, $r14)
		st b32 D[$r0 + #time_prev] $r14

	// re-enable the watchdog timer
	timer_enable:
	mov $r8 1
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r8)

	// interrupts back on
	timer_done:
	bset $flags ie0

	pop $r8
	pop $r9
	ret

// send message to another process
//
// $r15 - current
// $r14 - process
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0  - zero
send_proc:
	push $r8
	push $r9
	// check for space in queue
	ld b32 $r8 D[$r14 + #proc_qget]
	ld b32 $r9 D[$r14 + #proc_qput]
	xor $r8 #proc_qmaskb
	cmp b32 $r8 $r9
	bra e #send_done

	// enqueue message
	and $r8 $r9 #proc_qmaskp
	shl b32 $r8 $r8 #proc_qlen
	add b32 $r8 #proc_queue
	add b32 $r8 $r14

	ld b32 $r10 D[$r15 + #proc_id]
	st b32 D[$r8 + #msg_process] $r10
	st b32 D[$r8 + #msg_message] $r13
	st b32 D[$r8 + #msg_data0] $r12
	st b32 D[$r8 + #msg_data1] $r11

	// increment PUT
	add b32 $r9 1
	and $r9 #proc_qmaskf
	st b32 D[$r14 + #proc_qput] $r9
	bset $flags $p2
	send_done:
	pop $r9
	pop $r8
	ret

// lookup process structure by its name
//
// $r15 - current
// $r14 - process name
// $r0  - zero
//
// $r14 - process
// $p1  - success
find:
	push $r8
	mov $r8 #proc_list_head
	bset $flags $p1
	find_loop:
		ld b32 $r10 D[$r8 + #proc_id]
		cmp b32 $r10 $r14
		bra e #find_done
		add b32 $r8 #proc_size
		cmp b32 $r8 #proc_list_tail
		bra ne #find_loop
		bclr $flags $p1
	find_done:
	mov b32 $r14 $r8
	pop $r8
	ret

// send message to another process
//
// $r15 - current
// $r14 - process id
// $r13 - message
// $r12 - message data 0
// $r11 - message data 1
// $r0  - zero
send:
	call(find)
	bra $p1 #send_proc
	ret

// process single message for a given process
//
// $r15 - current
// $r14 - process
// $r0  - zero
recv:
	push $r9
	push $r8

	ld b32 $r8 D[$r14 + #proc_qget]
	ld b32 $r9 D[$r14 + #proc_qput]
	bclr $flags $p1
	cmp b32 $r8 $r9
	bra e #recv_done
		// dequeue message
		and $r9 $r8 #proc_qmaskp
		add b32 $r8 1
		and $r8 #proc_qmaskf
		st b32 D[$r14 + #proc_qget] $r8
		ld b32 $r10 D[$r14 + #proc_recv]

		push $r15
		mov $r15 $flags
		push $r15
		mov b32 $r15 $r14

		shl b32 $r9 $r9 #proc_qlen
		add b32 $r14 $r9
		add b32 $r14 #proc_queue
		ld b32 $r11 D[$r14 + #msg_data1]
		ld b32 $r12 D[$r14 + #msg_data0]
		ld b32 $r13 D[$r14 + #msg_message]
		ld b32 $r14 D[$r14 + #msg_process]

		// process it
		call $r10
		pop $r15
		mov $flags $r15
		bset $flags $p1
		pop $r15
	recv_done:
	pop $r8
	pop $r9
	ret

init:
	// setup stack
	nv_iord($r1, NV_PPWR_CAPS)
	extr $r1 $r1 9:17
	shl b32 $r1 8
	mov $sp $r1

#ifdef NVKM_FALCON_MMIO_UAS
	// somehow allows the magic "access mmio via D[]" stuff that's
	// used by the nv_rd32/nv_wr32 macros to work
	mov $r1 0x0010
	sethi $r1 NV_PPWR_UAS_CONFIG_ENABLE
	nv_iowrs(NV_PPWR_UAS_CONFIG, $r1)
#endif

	// route all interrupts except user0/1 and pause to fuc
	mov $r1 0x00e0
	sethi $r1 0x00000000
	nv_iowr(NV_PPWR_INTR_ROUTE, $r1)

	// enable watchdog and subintr intrs
	mov $r1 NV_PPWR_INTR_EN_CLR_MASK
	nv_iowr(NV_PPWR_INTR_EN_CLR, $r1)
	mov $r1 NV_PPWR_INTR_EN_SET_WATCHDOG
	or $r1 NV_PPWR_INTR_EN_SET_SUBINTR
	nv_iowr(NV_PPWR_INTR_EN_SET, $r1)

	// enable interrupts globally
	mov $r1 #intr
	sethi $r1 0x00000000
	mov $iv0 $r1
	bset $flags ie0

	// enable watchdog timer
	mov $r1 1
	nv_iowr(NV_PPWR_WATCHDOG_ENABLE, $r1)

	// bootstrap processes, idle process will be last, and not return
	mov $r15 #proc_list_head
	init_proc:
		ld b32 $r1 D[$r15 + #proc_init]
		cmp b32 $r1 0
		bra z #init_proc
		call $r1
		add b32 $r15 #proc_size
		bra #init_proc
#endif
@


1.1
log
@Initial revision
@
text
@@


1.1.1.1
log
@Import drm from Linux v4.4.143 (commit a8ea6276d00555387deaaa5eaeb380cd5c17bdc9).

   drivers/gpu/drm      -> sys/external/bsd/drm2/dist/drm
   include/drm          -> sys/external/bsd/drm2/dist/include/drm
   include/uapi/drm     -> sys/external/bsd/drm2/dist/uapi/drm

GPL sources excluded.
@
text
@@


1.1.1.2
log
@Import drm from Linux v5.6-rc3 (commit f8788d86ab28f61f7b46eb6be375f8a726783636)

    drivers/gpu/drm     -> sys/external/bsd/drm2/dist/drm
    include/drm         -> sys/external/bsd/drm2/dist/include/drm
    include/uapi/drm    -> sys/external/bsd/drm2/dist/include/uapi/drm

GPL exclusions in dist/drm:

- amd/amdgpu/amdgpu_atpx_handler.c
- arc/
- arm/
- armada/
- aspeed/
- atmel-hlcdc/
- bochs/
- bridge/
- cirrus/
- drm_dp_cec.c
- drm_dp_mst_topology_internal.h
- drm_edid_load.c
- drm_format_helper.c
- drm_gem_cma_helper.c
- drm_gem_framebuffer_helper.c
- drm_gem_shmem_helper.c
- drm_gem_ttm_helper.c
- drm_gem_vram_helper.c
- drm_hdcp.c
- drm_lease.c
- drm_mipi_dbi.c
- drm_simple_kms_helper.c
- drm_sysfs.c
- drm_trace.h
- drm_vram_helper_common.c
- drm_writeback.c
- etnaviv/
- exynos/
- fsl-dcu/
- gma500/
- hisilicon/
- i2c/tda9950.c
- i2c/tda998x_drv.c
- i915/gt/selftest_context.c
- i915/gt/selftest_engine.c
- i915/gt/selftest_engine.h
- i915/gt/selftest_engine_cs.c
- i915/gt/selftest_engine_pm.c
- i915/i915_trace.h
- i915/selftests/i915_live_selftests.h
- i915/selftests/i915_mock_selftests.h
- i915/selftests/i915_perf_selftests.h
- i915/selftests/lib_sw_fence.h
- imx/
- ingenic/
- lima/
- mcde/
- mediatek/
- meson/
- mgag200/
- msm/
- mxsfb/
- omapdrm/
- panel/
- panfrost/
- pl111/
- radeon/radeon_atpx_handler.c
- rcar-du/
- rockchip/
- selftests/drm_cmdline_selftests.h
- selftests/drm_modeset_selftests.h
- selftests/test-drm_cmdline_parser.c
- selftests/test-drm_damage_helper.c
- selftests/test-drm_dp_mst_helper.c
- selftests/test-drm_format.c
- selftests/test-drm_framebuffer.c
- selftests/test-drm_modeset_common.c
- selftests/test-drm_modeset_common.h
- selftests/test-drm_plane_helper.c
- selftests/test-drm_rect.c
- shmobile/
- sti/
- stm/
- sun4i/
- tegra/
- tilcdc/
- tiny/
- tve200/
- udl/
- v3d/
- vc4/
- virtio/virtgpu_trace.h
- virtio/virtgpu_trace_points.c
- vkms/
- vmwgfx/device_include/vmware_pack_begin.h
- vmwgfx/device_include/vmware_pack_end.h
- zte/

  Exceptions -- these all appear to be files to which someone added
  an SPDX license header automatically by a script that is not aware
  of the default MIT licensing under drivers/gpu/drm:

  - ast/ast_dp501.c
  - ast/ast_dram_tables.h
  - lib/drm_random.c
  - lib/drm_random.h
  - i915/display/intel_acpi.c
  - i915/selftests/mock_gem_device.h
  - i915/selftests/i915_mock_selftests.h
  - i915/selftests/i915_live_selftests.h
  - r128/ati_pcigart.h
  - selftests/drm_mm_selftests.h
  - selftests/test-drm_mm.c
  - vmwgfx/device_include/vm_basic_types.h

GPL exclusions in dist/include/drm:

- bridge
- drm_client.h
- drm_fb_cma_helper.h
- drm_format_helper.h
- drm_gem_cma_helper.h
- drm_gem_shmem_helper.h
- drm_gem_ttm_helper.h
- drm_gem_vram_helper.h
- drm_lease.h
- drm_mipi_dbi.h
- drm_mipi_dsi.h
- drm_of.h
- drm_simple_kms_helper.h
- drm_sysfs.h
- drm_writeback.h
- gma_drm.h
- i2c/tda998x.h
- i915_mei_hdcp_interface.h
- intel-gtt.h

  Exceptions:
  - drm_agpsupport.h - was in original drm; wrong spdx header auto-added

GPL exclusions in dist/include/uapi/drm:

- armada_drm.h
- etnaviv_drm.h
- exynos_drm.h
- lima_drm.h
- omap_drm.h

  Exceptions:
  - i810_drm.h - was in original drm; spdx header is wrong
@
text
@d54 2
a55 1
	imm32($r13, NV_PPWR_MMIO_CTRL_OP_RD | NV_PPWR_MMIO_CTRL_TRIGGER)
d73 3
a75 1
	imm32($r13, NV_PPWR_MMIO_CTRL_OP_WR | NV_PPWR_MMIO_CTRL_MASK_B32_0 | NV_PPWR_MMIO_CTRL_TRIGGER)
d218 2
a219 1
			imm32($r14, PROC_HOST)
d228 10
a237 3
	mov $r9 (NV_PPWR_INTR_USER0 | NV_PPWR_INTR_USER1 | NV_PPWR_INTR_PAUSE)
	not b32 $r9
	and $r8 $r9
a238 1

d265 1
a265 1
	call(mulu32_32_64)
d277 1
a277 1
	call(mulu32_32_64)
d299 1
a299 1
	call(mulu32_32_64)
d520 2
a521 1
	imm32($r1, 0x10 | NV_PPWR_UAS_CONFIG_ENABLE)
d526 2
a527 1
	imm32($r1, 0xe0)
d538 2
a539 2
	imm32($r1, #intr)
	and $r1 0xffff
@

