// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <dev/interrupt.h>
#include <object/interrupt_dispatcher.h>
#include <object/port_dispatcher.h>
#include <object/process_dispatcher.h>
#include <platform.h>
#include <zircon/syscalls/port.h>

InterruptDispatcher::InterruptDispatcher()
    : timestamp_(0), state_(InterruptState::IDLE) {
    event_init(&event_, false, EVENT_FLAG_AUTOUNSIGNAL);
}

zx_status_t InterruptDispatcher::WaitForInterrupt(zx_time_t* out_timestamp) {
    while (true) {
        {
            Guard<SpinLock, IrqSave> guard{&spinlock_};
            if (port_dispatcher_ || HasVcpu()) {
                return ZX_ERR_BAD_STATE;
            }
            switch (state_) {
            case InterruptState::DESTROYED:
                return ZX_ERR_CANCELED;
            case InterruptState::TRIGGERED:
                state_ = InterruptState::NEEDACK;
                *out_timestamp = timestamp_;
                timestamp_ = 0;
                return event_unsignal(&event_);
            case InterruptState::NEEDACK:
                if (flags_ & INTERRUPT_UNMASK_PREWAIT) {
                    UnmaskInterrupt();
                }
                break;
            case InterruptState::IDLE:
                break;
            default:
                return ZX_ERR_BAD_STATE;
            }
            state_ = InterruptState::WAITING;
        }

        {
            ThreadDispatcher::AutoBlocked by(ThreadDispatcher::Blocked::INTERRUPT);
            zx_status_t status = event_wait_deadline(&event_, ZX_TIME_INFINITE, true);
            if (status != ZX_OK) {
                // The event_wait call was interrupted and we need to retry
                // but before we retry we will set the interrupt state
                // back to IDLE if we are still in the WAITING state
                Guard<SpinLock, IrqSave> guard{&spinlock_};
                if (state_ == InterruptState::WAITING) {
                    state_ = InterruptState::IDLE;
                }
                return status;
            }
        }
    }
}

bool InterruptDispatcher::SendPacketLocked(zx_time_t timestamp) {
    bool status = port_dispatcher_->QueueInterruptPacket(&port_packet_, timestamp);
    if (flags_ & INTERRUPT_MASK_POSTWAIT) {
        MaskInterrupt();
    }
    timestamp_ = 0;
    return status;
}

zx_status_t InterruptDispatcher::Trigger(zx_time_t timestamp) {

    if (!(flags_ & INTERRUPT_VIRTUAL))
        return ZX_ERR_BAD_STATE;

    // Using AutoReschedDisable is necessary for correctness to prevent
    // context-switching to the woken thread while holding spinlock_.
    AutoReschedDisable resched_disable;
    resched_disable.Disable();
    Guard<SpinLock, IrqSave> guard{&spinlock_};

    // only record timestamp if this is the first signal since we started waiting
    if (!timestamp_) {
        timestamp_ = timestamp;
    }
    if (state_ == InterruptState::DESTROYED) {
        return ZX_ERR_CANCELED;
    }
    if (state_ == InterruptState::NEEDACK && port_dispatcher_) {
        // Cannot trigger a interrupt without ACK
        // only record timestamp if this is the first signal since we started waiting
        return ZX_OK;
    }

    if (port_dispatcher_) {
        SendPacketLocked(timestamp);
        state_ = InterruptState::NEEDACK;
    } else {
        Signal();
        state_ = InterruptState::TRIGGERED;
    }
    return ZX_OK;
}

void InterruptDispatcher::InterruptHandler() {
    Guard<SpinLock, IrqSave> guard{&spinlock_};

    // only record timestamp if this is the first IRQ since we started waiting
    if (!timestamp_) {
        timestamp_ = current_time();
    }
    if (state_ == InterruptState::NEEDACK && port_dispatcher_) {
        return;
    }
    if (port_dispatcher_) {
        SendPacketLocked(timestamp_);
        state_ = InterruptState::NEEDACK;
    } else {
        if (flags_ & INTERRUPT_MASK_POSTWAIT) {
            MaskInterrupt();
        }
        Signal();
        state_ = InterruptState::TRIGGERED;
    }
}

zx_status_t InterruptDispatcher::Destroy() {
    // Using AutoReschedDisable is necessary for correctness to prevent
    // context-switching to the woken thread while holding spinlock_.
    AutoReschedDisable resched_disable;
    resched_disable.Disable();
    Guard<SpinLock, IrqSave> guard{&spinlock_};

    MaskInterrupt();
    UnregisterInterruptHandler();

    if (port_dispatcher_) {
        bool packet_was_in_queue = port_dispatcher_->RemoveInterruptPacket(&port_packet_);
        if ((state_ == InterruptState::NEEDACK) &&
            !packet_was_in_queue) {
            state_ = InterruptState::DESTROYED;
            return ZX_ERR_NOT_FOUND;
        }
        if ((state_ == InterruptState::IDLE) ||
            ((state_ == InterruptState::NEEDACK) &&
             packet_was_in_queue)) {
            state_ = InterruptState::DESTROYED;
            return ZX_OK;
        }
    } else {
        state_ = InterruptState::DESTROYED;
        Signal();
    }
    return ZX_OK;
}

zx_status_t InterruptDispatcher::Bind(fbl::RefPtr<PortDispatcher> port_dispatcher, uint64_t key) {
    Guard<SpinLock, IrqSave> guard{&spinlock_};
    if (state_ == InterruptState::DESTROYED) {
        return ZX_ERR_CANCELED;
    } else if (state_ == InterruptState::WAITING) {
        return ZX_ERR_BAD_STATE;
    } else if (port_dispatcher_ || HasVcpu()) {
        return ZX_ERR_ALREADY_BOUND;
    }

    port_dispatcher_ = ktl::move(port_dispatcher);
    port_packet_.key = key;
    return ZX_OK;
}

zx_status_t InterruptDispatcher::Ack() {
    // Using AutoReschedDisable is necessary for correctness to prevent
    // context-switching to the woken thread while holding spinlock_.
    AutoReschedDisable resched_disable;
    resched_disable.Disable();
    Guard<SpinLock, IrqSave> guard{&spinlock_};
    if (port_dispatcher_ == nullptr) {
        return ZX_ERR_BAD_STATE;
    }
    if (state_ == InterruptState::DESTROYED) {
        return ZX_ERR_CANCELED;
    }
    if (state_ == InterruptState::NEEDACK) {
        if (flags_ & INTERRUPT_UNMASK_PREWAIT) {
            UnmaskInterrupt();
        }
        if (timestamp_) {
            if (!SendPacketLocked(timestamp_)) {
                // We cannot queue another packet here.
                // If we reach here it means that the
                // interrupt packet has not been processed,
                // another interrupt has occurred & then the
                // interrupt was ACK'd
                return ZX_ERR_BAD_STATE;
            }
        } else {
            state_ = InterruptState::IDLE;
        }
    }
    return ZX_OK;
}

void InterruptDispatcher::on_zero_handles() {
    Destroy();
}
