// File: chenhn123[P]wdt_util_src/wdt_ct/w8790_funcs.cpp
// Function: wh_w8790_dev_send_commands(WdtDevice*, int, unsigned int)
int wh_w8790_dev_send_commands(WDT_DEV* pdev, int cmd, UINT32 value)
{
	int ret = 0;
	switch (cmd)
	{
	case 	WH_CMD_RESET:
		/** 
         	 * Hard reset doesn't make OSC back to default. So we need this workaround to set OSC to default.
         	 * If not, the OSC clock for ROM code is too high and might cause booting fails.
        	 */
        	ret = wh_w8790_dev_write_register(pdev, 0x00801408, 0x47);

		ret = wh_w8790_dev_reboot(pdev);
		break;
	case 	WH_CMD_SET_DEV_MODE: {
		ret =  wh_w8790_dev_set_n_check_device_mode(pdev, value, 0, 0);
		break;
	}
	case	WH_CMD_FLASH_ERASE4K:
		ret = wh_w8790_dev_flash_erase(pdev, value, 0x1000);
		break;
	case	WH_CMD_FLASH_ERASE32K:
		ret = wh_w8790_dev_flash_erase(pdev, value, 0x8000);
		break;
	case	WH_CMD_FLASH_ERASE64K:
		ret = wh_w8790_dev_flash_erase(pdev, value, 0x10000);
		break;

	case	WH_CMD_FLASH_LOCK:
	case	WH_CMD_FLASH_PROTECTION_ON:
		ret = wh_w8790_dev_protect_flash(pdev, W8790_ProtectAll512k);
		break;
	case	WH_CMD_FLASH_UNLOCK: {
		ret = wh_w8790_dev_set_n_check_device_mode(pdev, W8790_MODE_FLASH_PROGRAM, 0, 0);
		break;
	}
	case	WH_CMD_FLASH_PROTECTION_OFF:
	{
		// address align to 0x100
		UINT32 addr = ((value & 0xFFFF0000) >> 8);

		// size align to 0x100
		UINT32 size = ((value & 0xFFFF) << 8) + 0x100;
		if (addr < 128 * 1024 && addr + size <= 128 * 1024)
			ret = wh_w8790_dev_protect_flash(pdev, W8790_UnprotectLower128k);
		else if (addr < 256 * 1024 && addr + size <= 256 * 1024)
			ret = wh_w8790_dev_protect_flash(pdev, W8790_UnprotectLower256k);
		else if (addr < 384 * 1024 && addr + size <= 384 * 1024)
			ret = wh_w8790_dev_protect_flash(pdev, W8790_UnprotectLower384k);
		else if (addr < 508 * 1024 && addr + size <= 508 * 1024)
			ret = wh_w8790_dev_protect_flash(pdev, W8790_UnprotectLower508k);
	}
	break;
	case 	WH_CMD_ALGO_STOP: 
		ret =  wh_w8790_dev_set_n_check_device_mode(pdev, W8790_MODE_COMMAND, 0, 0);
		break;
	case 	WH_CMD_ALGO_START:
		ret = wh_w8790_dev_set_n_check_device_mode(pdev, W8790_MODE_SENSING, 0, 0);
		break;
	default:
		ret = 0;
		break;
	}
	return ret;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movl -0xc(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x28(%rbp)
subl $0x16, %eax
ja 0x83d7
movq -0x28(%rbp), %rax
leaq 0x78c4(%rip), %rcx      # 0xfadc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rdi
movl $0x801408, %esi         # imm = 0x801408
movl $0x47, %edx
callq 0x84d0
movl %eax, -0x14(%rbp)
movq -0x8(%rbp), %rdi
callq 0x77b0
movl %eax, -0x14(%rbp)
jmp 0x83de
movq -0x8(%rbp), %rdi
movl -0x10(%rbp), %eax
xorl %ecx, %ecx
movzbl %al, %esi
movl %ecx, %edx
callq 0x7160
movl %eax, -0x14(%rbp)
jmp 0x83de
movq -0x8(%rbp), %rdi
movl -0x10(%rbp), %esi
movl $0x1000, %edx           # imm = 0x1000
callq 0x8480
movl %eax, -0x14(%rbp)
jmp 0x83de
movq -0x8(%rbp), %rdi
movl -0x10(%rbp), %esi
movl $0x8000, %edx           # imm = 0x8000
callq 0x8480
movl %eax, -0x14(%rbp)
jmp 0x83de
movq -0x8(%rbp), %rdi
movl -0x10(%rbp), %esi
movl $0x10000, %edx          # imm = 0x10000
callq 0x8480
movl %eax, -0x14(%rbp)
jmp 0x83de
movq -0x8(%rbp), %rdi
movl $0x7c, %esi
callq 0x7c20
movl %eax, -0x14(%rbp)
jmp 0x83de
movq -0x8(%rbp), %rdi
movl $0x96, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x7160
movl %eax, -0x14(%rbp)
jmp 0x83de
movl -0x10(%rbp), %eax
andl $0xffff0000, %eax       # imm = 0xFFFF0000
shrl $0x8, %eax
movl %eax, -0x18(%rbp)
movl -0x10(%rbp), %eax
andl $0xffff, %eax           # imm = 0xFFFF
shll $0x8, %eax
addl $0x100, %eax            # imm = 0x100
movl %eax, -0x1c(%rbp)
cmpl $0x20000, -0x18(%rbp)   # imm = 0x20000
jae 0x8328
movl -0x18(%rbp), %eax
addl -0x1c(%rbp), %eax
cmpl $0x20000, %eax          # imm = 0x20000
ja 0x8328
movq -0x8(%rbp), %rdi
movl $0x4028, %esi           # imm = 0x4028
callq 0x7c20
movl %eax, -0x14(%rbp)
jmp 0x83a7
cmpl $0x40000, -0x18(%rbp)   # imm = 0x40000
jae 0x8351
movl -0x18(%rbp), %eax
addl -0x1c(%rbp), %eax
cmpl $0x40000, %eax          # imm = 0x40000
ja 0x8351
movq -0x8(%rbp), %rdi
movl $0xc, %esi
callq 0x7c20
movl %eax, -0x14(%rbp)
jmp 0x83a5
cmpl $0x60000, -0x18(%rbp)   # imm = 0x60000
jae 0x837a
movl -0x18(%rbp), %eax
addl -0x1c(%rbp), %eax
cmpl $0x60000, %eax          # imm = 0x60000
ja 0x837a
movq -0x8(%rbp), %rdi
movl $0x8, %esi
callq 0x7c20
movl %eax, -0x14(%rbp)
jmp 0x83a3
cmpl $0x7f000, -0x18(%rbp)   # imm = 0x7F000
jae 0x83a1
movl -0x18(%rbp), %eax
addl -0x1c(%rbp), %eax
cmpl $0x7f000, %eax          # imm = 0x7F000
ja 0x83a1
movq -0x8(%rbp), %rdi
movl $0x44, %esi
callq 0x7c20
movl %eax, -0x14(%rbp)
jmp 0x83a3
jmp 0x83a5
jmp 0x83a7
jmp 0x83de
movq -0x8(%rbp), %rdi
movl $0x90, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x7160
movl %eax, -0x14(%rbp)
jmp 0x83de
movq -0x8(%rbp), %rdi
movl $0x1, %esi
xorl %ecx, %ecx
movl %ecx, %edx
callq 0x7160
movl %eax, -0x14(%rbp)
jmp 0x83de
movl $0x0, -0x14(%rbp)
movl -0x14(%rbp), %eax
addq $0x30, %rsp
popq %rbp
retq
nopw (%rax,%rax)