// Code for handling usb attached scsi devices.
//
// only usb 2.0 for now.
//
// once we have xhci driver with usb 3.0 support this must
// be updated to use usb3 streams so booting from usb3
// devices actually works.
//
// Authors:
//  Gerd Hoffmann <kraxel@redhat.com>
//
// based on usb-msc.c which is written by:
//  Kevin O'Connor <kevin@koconnor.net>
//
// This file may be distributed under the terms of the GNU LGPLv3 license.

#include "biosvar.h" // GET_GLOBALFLAT
#include "block.h" // DTYPE_USB
#include "blockcmd.h" // cdb_read
#include "config.h" // CONFIG_USB_UAS
#include "malloc.h" // free
#include "output.h" // dprintf
#include "std/disk.h" // DISK_RET_SUCCESS
#include "string.h" // memset
#include "usb.h" // struct usb_s
#include "usb-uas.h" // usb_uas_init
#include "util.h" // bootprio_find_usb

#define UAS_UI_COMMAND              0x01
#define UAS_UI_SENSE                0x03
#define UAS_UI_RESPONSE             0x04
#define UAS_UI_TASK_MGMT            0x05
#define UAS_UI_READ_READY           0x06
#define UAS_UI_WRITE_READY          0x07

#define UAS_PIPE_ID_COMMAND         0x01
#define UAS_PIPE_ID_STATUS          0x02
#define UAS_PIPE_ID_DATA_IN         0x03
#define UAS_PIPE_ID_DATA_OUT        0x04

typedef struct {
    u8    id;
    u8    reserved;
    u16   tag;
} PACKED  uas_ui_header;

typedef struct {
    u8    prio_taskattr;   /* 6:3 priority, 2:0 task attribute   */
    u8    reserved_1;
    u8    add_cdb_length;  /* 7:2 additional adb length (dwords) */
    u8    reserved_2;
    u8    lun[8];
    u8    cdb[16];
    u8    add_cdb[];
} PACKED  uas_ui_command;

typedef struct {
    u16   status_qualifier;
    u8    status;
    u8    reserved[7];
    u16   sense_length;
    u8    sense_data[18];
} PACKED  uas_ui_sense;

typedef struct {
    u16   add_response_info;
    u8    response_code;
} PACKED  uas_ui_response;

typedef struct {
    u8    function;
    u8    reserved;
    u16   task_tag;
    u8    lun[8];
} PACKED  uas_ui_task_mgmt;

typedef struct {
    uas_ui_header  hdr;
    union {
        uas_ui_command   command;
        uas_ui_sense     sense;
        uas_ui_task_mgmt task;
        uas_ui_response  response;
    };
} PACKED  uas_ui;

struct uasdrive_s {
    struct drive_s drive;
    struct usbdevice_s *usbdev;
    struct usb_pipe *command, *status, *data_in, *data_out;
    u32 lun;
};

int
uas_process_op(struct disk_op_s *op)
{
    if (!CONFIG_USB_UAS)
        return DISK_RET_EBADTRACK;

    struct uasdrive_s *drive_gf = container_of(
        op->drive_fl, struct uasdrive_s, drive);

    uas_ui ui;
    memset(&ui, 0, sizeof(ui));
    ui.hdr.id = UAS_UI_COMMAND;
    ui.hdr.tag = 0xdead;
    ui.command.lun[1] = GET_GLOBALFLAT(drive_gf->lun);
    int blocksize = scsi_fill_cmd(op, ui.command.cdb, sizeof(ui.command.cdb));
    if (blocksize < 0)
        return default_process_op(op);
    int ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->command),
                            USB_DIR_OUT, MAKE_FLATPTR(GET_SEG(SS), &ui),
                            sizeof(ui.hdr) + sizeof(ui.command));
    if (ret) {
        dprintf(1, "uas: command send fail");
        goto fail;
    }

    memset(&ui, 0xff, sizeof(ui));
    ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->status),
                        USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui));
    if (ret) {
        dprintf(1, "uas: status recv fail");
        goto fail;
    }

    switch (ui.hdr.id) {
    case UAS_UI_SENSE:
        goto have_sense;
    case UAS_UI_READ_READY:
        ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->data_in),
                            USB_DIR_IN, op->buf_fl, op->count * blocksize);
        if (ret) {
            dprintf(1, "uas: data read fail");
            goto fail;
        }
        break;
    case UAS_UI_WRITE_READY:
        ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->data_out),
                            USB_DIR_OUT, op->buf_fl, op->count * blocksize);
        if (ret) {
            dprintf(1, "uas: data write fail");
            goto fail;
        }
        break;
    default:
        dprintf(1, "uas: unknown status ui id %d", ui.hdr.id);
        goto fail;
    }

    memset(&ui, 0xff, sizeof(ui));
    ret = usb_send_bulk(GET_GLOBALFLAT(drive_gf->status),
                        USB_DIR_IN, MAKE_FLATPTR(GET_SEG(SS), &ui), sizeof(ui));
    if (ret) {
        dprintf(1, "uas: status recv fail");
        goto fail;
    }
    if (ui.hdr.id != UAS_UI_SENSE) {
        dprintf(1, "uas: expected sense ui, got ui id %d", ui.hdr.id);
        goto fail;
    }

have_sense:
    if (ui.sense.status == 0) {
        return DISK_RET_SUCCESS;
    }

fail:
    return DISK_RET_EBADTRACK;
}

static void
uas_init_lun(struct uasdrive_s *drive, struct usbdevice_s *usbdev,
             struct usb_pipe *command, struct usb_pipe *status,
             struct usb_pipe *data_in, struct usb_pipe *data_out,
             u32 lun)
{
    memset(drive, 0, sizeof(*drive));
    if (usb_32bit_pipe(data_in))
        drive->drive.type = DTYPE_UAS_32;
    else
        drive->drive.type = DTYPE_UAS;
    drive->usbdev = usbdev;
    drive->command = command;
    drive->status = status;
    drive->data_in = data_in;
    drive->data_out = data_out;
    drive->lun = lun;
}

static int
uas_add_lun(u32 lun, struct drive_s *tmpl_drv)
{
    struct uasdrive_s *tmpl_lun =
        container_of(tmpl_drv, struct uasdrive_s, drive);
    struct uasdrive_s *drive = malloc_fseg(sizeof(*drive));
    if (!drive) {
        warn_noalloc();
        return -1;
    }
    uas_init_lun(drive, tmpl_lun->usbdev,
                 tmpl_lun->command, tmpl_lun->status,
                 tmpl_lun->data_in, tmpl_lun->data_out,
                 lun);

    int prio = bootprio_find_usb(drive->usbdev, drive->lun);
    int ret = scsi_drive_setup(&drive->drive, "USB UAS", prio);
    if (ret) {
        free(drive);
        return -1;
    }
    return 0;
}

int
usb_uas_setup(struct usbdevice_s *usbdev)
{
    if (!CONFIG_USB_UAS)
        return -1;

    // Verify right kind of device
    struct usb_interface_descriptor *iface = usbdev->iface;
    if (iface->bInterfaceSubClass != US_SC_SCSI ||
        iface->bInterfaceProtocol != US_PR_UAS) {
        dprintf(1, "Unsupported UAS device (subclass=%02x proto=%02x)\n"
                , iface->bInterfaceSubClass, iface->bInterfaceProtocol);
        return -1;
    }

    /* find & allocate pipes */
    struct usb_endpoint_descriptor *ep = NULL;
    struct usb_pipe *command = NULL;
    struct usb_pipe *status = NULL;
    struct usb_pipe *data_in = NULL;
    struct usb_pipe *data_out = NULL;
    u8 *desc = (u8*)iface;
    while (desc) {
        desc += desc[0];
        switch (desc[1]) {
        case USB_DT_ENDPOINT:
            ep = (void*)desc;
            break;
        case USB_DT_ENDPOINT_COMPANION:
            /* No support (yet) for usb3 streams */
            dprintf(1, "Superspeed UAS devices not supported (yet)\n");
            goto fail;
        case 0x24:
            switch (desc[2]) {
            case UAS_PIPE_ID_COMMAND:
                command = usb_alloc_pipe(usbdev, ep);
                break;
            case UAS_PIPE_ID_STATUS:
                status = usb_alloc_pipe(usbdev, ep);
                break;
            case UAS_PIPE_ID_DATA_IN:
                data_in = usb_alloc_pipe(usbdev, ep);
                break;
            case UAS_PIPE_ID_DATA_OUT:
                data_out = usb_alloc_pipe(usbdev, ep);
                break;
            default:
                goto fail;
            }
            break;
        default:
            desc = NULL;
            break;
        }
    }
    if (!command || !status || !data_in || !data_out)
        goto fail;

    struct uasdrive_s lun0;
    uas_init_lun(&lun0, usbdev, command, status, data_in, data_out, 0);
    int ret = scsi_rep_luns_scan(&lun0.drive, uas_add_lun);
    if (ret <= 0) {
        dprintf(1, "Unable to configure UAS drive.\n");
        goto fail;
    }

    return 0;

fail:
    usb_free_pipe(usbdev, command);
    usb_free_pipe(usbdev, status);
    usb_free_pipe(usbdev, data_in);
    usb_free_pipe(usbdev, data_out);
    return -1;
}
