// File: /workspace/github_cpp_makefile_star2_O2/CMU-SAFARI[P]MQSim/src/ssd/Host_Interface_NVMe.cpp
// Function: SSD_Components::Input_Stream_Manager_NVMe::Handle_serviced_request(SSD_Components::User_Request*)
inline void Input_Stream_Manager_NVMe::Handle_serviced_request(User_Request *request)
{
	stream_id_type stream_id = request->Stream_id;
	((Input_Stream_NVMe *)input_streams[request->Stream_id])->Waiting_user_requests.remove(request);
	((Input_Stream_NVMe *)input_streams[stream_id])->On_the_fly_requests--;

	DEBUG("** Host Interface: Request #" << request->ID << " from stream #" << request->Stream_id << " is finished")

	//If this is a read request, then the read data should be written to host memory
	if (request->Type == UserRequestType::READ)
	{
		((Host_Interface_NVMe *)host_interface)->request_fetch_unit->Send_read_data(request);
	}

	//there are waiting requests in the submission queue but have not been fetched, due to Queue_fetch_size limit
	if (((Input_Stream_NVMe *)input_streams[stream_id])->Submission_head != ((Input_Stream_NVMe *)input_streams[stream_id])->Submission_tail)
	{
		((Host_Interface_NVMe *)host_interface)->request_fetch_unit->Fetch_next_request(stream_id);
		((Input_Stream_NVMe *)input_streams[stream_id])->On_the_fly_requests++;
		((Input_Stream_NVMe *)input_streams[stream_id])->Submission_head++; //Update submission queue head after starting fetch request
		if (((Input_Stream_NVMe *)input_streams[stream_id])->Submission_head == ((Input_Stream_NVMe *)input_streams[stream_id])->Submission_queue_size)
		{ //Circular queue implementation
			((Input_Stream_NVMe *)input_streams[stream_id])->Submission_head = 0;
		}
	}

	//Check if completion queue is full
	if (((Input_Stream_NVMe *)input_streams[stream_id])->Completion_head > ((Input_Stream_NVMe *)input_streams[stream_id])->Completion_tail)
	{
		//completion queue is full
		if (((Input_Stream_NVMe *)input_streams[stream_id])->Completion_tail + 1 == ((Input_Stream_NVMe *)input_streams[stream_id])->Completion_head)
		{
			((Input_Stream_NVMe *)input_streams[stream_id])->Completed_user_requests.push_back(request); //Wait while the completion queue is full
			return;
		}
	}
	else if (((Input_Stream_NVMe *)input_streams[stream_id])->Completion_tail - ((Input_Stream_NVMe *)input_streams[stream_id])->Completion_head == ((Input_Stream_NVMe *)input_streams[stream_id])->Completion_queue_size - 1)
	{
		((Input_Stream_NVMe *)input_streams[stream_id])->Completed_user_requests.push_back(request); //Wait while the completion queue is full
		return;
	}

	inform_host_request_completed(stream_id, request); //Completion queue is not full, so the device can DMA the completion queue entry to the host
	DELETE_REQUEST_NVME(request);
}

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq %rsp, %r15
movq %rsi, (%r15)
movzwl 0x68(%rsi), %r14d
movq 0x10(%rdi), %rax
movl %r14d, %r12d
shll $0x3, %r12d
movl $0x88, %edi
addq (%rax,%r12), %rdi
movq %r15, %rsi
callq 0x2c194
movq 0x10(%rbx), %rax
movq (%rax,%r12), %rdi
decw 0xd0(%rdi)
movq (%r15), %rsi
cmpl $0x0, 0x64(%rsi)
jne 0x35d42
movq 0x8(%rbx), %rax
movq 0x58(%rax), %rdi
movq (%rdi), %rax
callq *0x20(%rax)
movq 0x10(%rbx), %rax
movq (%rax,%r14,8), %rdi
movzwl 0x7a(%rdi), %eax
cmpw 0x7e(%rdi), %ax
je 0x35d8f
movq 0x8(%rbx), %rax
movq 0x58(%rax), %rdi
movq (%rdi), %rax
movl %r14d, %esi
callq *0x10(%rax)
movq 0x10(%rbx), %rax
leal (,%r14,8), %ecx
movq (%rax,%rcx), %rax
incw 0xd0(%rax)
movzwl 0x7a(%rax), %edx
incl %edx
xorl %esi, %esi
cmpw 0x68(%rax), %dx
cmovnel %edx, %esi
movw %si, 0x7a(%rax)
movq 0x10(%rbx), %rax
movq (%rax,%rcx), %rdi
movzwl 0x80(%rdi), %ecx
movzwl 0x82(%rdi), %eax
cmpw %ax, %cx
jbe 0x35da6
incl %eax
jmp 0x35dae
subl %ecx, %eax
movzwl 0x78(%rdi), %ecx
decl %ecx
cmpl %ecx, %eax
jne 0x35dc3
addq $0xa0, %rdi
movq %rsp, %rsi
callq 0x2ab34
jmp 0x35e1d
movq (%rsp), %rdx
movq %rbx, %rdi
movl %r14d, %esi
callq 0x35e96
movq (%rsp), %rax
movq 0x70(%rax), %rdi
callq 0x7340
callq 0x1f784
movq %rax, %rdi
callq 0x1fb60
movq (%rsp), %rbx
testb %al, %al
je 0x35e06
movq 0x78(%rbx), %rdi
testq %rdi, %rdi
je 0x35e06
callq 0x7430
movq (%rsp), %rbx
cmpq $0x0, 0x50(%rbx)
jne 0x35e29
movq %rbx, %rdi
callq 0x2ab0c
movq %rbx, %rdi
callq 0x7340
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
movq 0x2c1c0(%rip), %rbx     # 0x61ff0
leaq 0xe751(%rip), %rsi      # 0x44588
movq %rbx, %rdi
callq 0x7360
leaq 0x121dc(%rip), %rsi     # 0x48022
movq %rbx, %rdi
callq 0x7360
movq %rax, %rdi
callq 0x71a0
movq 0x2c173(%rip), %rdi     # 0x61fd0
callq 0x73d0
pushq $0x1
popq %rdi
callq 0x73e0