⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb-msd.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * USB Mass Storage Device emulation * * Copyright (c) 2006 CodeSourcery. * Written by Paul Brook * * This code is licenced under the LGPL. */#include "vl.h"//#define DEBUG_MSD#ifdef DEBUG_MSD#define DPRINTF(fmt, args...) \do { printf("usb-msd: " fmt , ##args); } while (0)#else#define DPRINTF(fmt, args...) do {} while(0)#endif/* USB requests.  */#define MassStorageReset  0xff#define GetMaxLun         0xfeenum USBMSDMode {    USB_MSDM_CBW, /* Command Block.  */    USB_MSDM_DATAOUT, /* Tranfer data to device.  */    USB_MSDM_DATAIN, /* Transfer data from device.  */    USB_MSDM_CSW /* Command Status.  */};typedef struct {    USBDevice dev;    enum USBMSDMode mode;    uint32_t scsi_len;    uint8_t *scsi_buf;    uint32_t usb_len;    uint8_t *usb_buf;    uint32_t data_len;    uint32_t residue;    uint32_t tag;    BlockDriverState *bs;    SCSIDevice *scsi_dev;    int result;    /* For async completion.  */    USBPacket *packet;} MSDState;struct usb_msd_cbw {    uint32_t sig;    uint32_t tag;    uint32_t data_len;    uint8_t flags;    uint8_t lun;    uint8_t cmd_len;    uint8_t cmd[16];};struct usb_msd_csw {    uint32_t sig;    uint32_t tag;    uint32_t residue;    uint8_t status;};static const uint8_t qemu_msd_dev_descriptor[] = {	0x12,       /*  u8 bLength; */	0x01,       /*  u8 bDescriptorType; Device */	0x10, 0x00, /*  u16 bcdUSB; v1.0 */	0x00,	    /*  u8  bDeviceClass; */	0x00,	    /*  u8  bDeviceSubClass; */	0x00,       /*  u8  bDeviceProtocol; [ low/full speeds only ] */	0x08,       /*  u8  bMaxPacketSize0; 8 Bytes */        /* Vendor and product id are arbitrary.  */	0x00, 0x00, /*  u16 idVendor; */ 	0x00, 0x00, /*  u16 idProduct; */	0x00, 0x00, /*  u16 bcdDevice */	0x01,       /*  u8  iManufacturer; */	0x02,       /*  u8  iProduct; */	0x03,       /*  u8  iSerialNumber; */	0x01        /*  u8  bNumConfigurations; */};static const uint8_t qemu_msd_config_descriptor[] = {	/* one configuration */	0x09,       /*  u8  bLength; */	0x02,       /*  u8  bDescriptorType; Configuration */	0x20, 0x00, /*  u16 wTotalLength; */	0x01,       /*  u8  bNumInterfaces; (1) */	0x01,       /*  u8  bConfigurationValue; */	0x00,       /*  u8  iConfiguration; */	0xc0,       /*  u8  bmAttributes; 				 Bit 7: must be set,				     6: Self-powered,				     5: Remote wakeup,				     4..0: resvd */	0x00,       /*  u8  MaxPower; */      	/* one interface */	0x09,       /*  u8  if_bLength; */	0x04,       /*  u8  if_bDescriptorType; Interface */	0x00,       /*  u8  if_bInterfaceNumber; */	0x00,       /*  u8  if_bAlternateSetting; */	0x02,       /*  u8  if_bNumEndpoints; */	0x08,       /*  u8  if_bInterfaceClass; MASS STORAGE */	0x06,       /*  u8  if_bInterfaceSubClass; SCSI */	0x50,       /*  u8  if_bInterfaceProtocol; Bulk Only */	0x00,       /*  u8  if_iInterface; */     	/* Bulk-In endpoint */	0x07,       /*  u8  ep_bLength; */	0x05,       /*  u8  ep_bDescriptorType; Endpoint */	0x81,       /*  u8  ep_bEndpointAddress; IN Endpoint 1 */ 	0x02,       /*  u8  ep_bmAttributes; Bulk */ 	0x40, 0x00, /*  u16 ep_wMaxPacketSize; */	0x00,       /*  u8  ep_bInterval; */	/* Bulk-Out endpoint */	0x07,       /*  u8  ep_bLength; */	0x05,       /*  u8  ep_bDescriptorType; Endpoint */	0x02,       /*  u8  ep_bEndpointAddress; OUT Endpoint 2 */ 	0x02,       /*  u8  ep_bmAttributes; Bulk */ 	0x40, 0x00, /*  u16 ep_wMaxPacketSize; */	0x00        /*  u8  ep_bInterval; */};static void usb_msd_copy_data(MSDState *s){    uint32_t len;    len = s->usb_len;    if (len > s->scsi_len)        len = s->scsi_len;    if (s->mode == USB_MSDM_DATAIN) {        memcpy(s->usb_buf, s->scsi_buf, len);    } else {        memcpy(s->scsi_buf, s->usb_buf, len);    }    s->usb_len -= len;    s->scsi_len -= len;    s->usb_buf += len;    s->scsi_buf += len;    s->data_len -= len;    if (s->scsi_len == 0) {        if (s->mode == USB_MSDM_DATAIN) {            scsi_read_data(s->scsi_dev, s->tag);        } else if (s->mode == USB_MSDM_DATAOUT) {            scsi_write_data(s->scsi_dev, s->tag);        }    }}static void usb_msd_send_status(MSDState *s){    struct usb_msd_csw csw;    csw.sig = cpu_to_le32(0x53425355);    csw.tag = cpu_to_le32(s->tag);    csw.residue = s->residue;    csw.status = s->result;    memcpy(s->usb_buf, &csw, 13);}static void usb_msd_command_complete(void *opaque, int reason, uint32_t tag,                                     uint32_t arg){    MSDState *s = (MSDState *)opaque;    USBPacket *p = s->packet;    if (tag != s->tag) {        fprintf(stderr, "usb-msd: Unexpected SCSI Tag 0x%x\n", tag);    }    if (reason == SCSI_REASON_DONE) {        DPRINTF("Command complete %d\n", arg);        s->residue = s->data_len;        s->result = arg != 0;        if (s->packet) {            if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {                /* A deferred packet with no write data remaining must be                   the status read packet.  */                usb_msd_send_status(s);                s->mode = USB_MSDM_CBW;            } else {                if (s->data_len) {                    s->data_len -= s->usb_len;                    if (s->mode == USB_MSDM_DATAIN)                        memset(s->usb_buf, 0, s->usb_len);                    s->usb_len = 0;                }                if (s->data_len == 0)                    s->mode = USB_MSDM_CSW;            }            s->packet = NULL;            usb_packet_complete(p);        } else if (s->data_len == 0) {            s->mode = USB_MSDM_CSW;        }        return;    }    s->scsi_len = arg;    s->scsi_buf = scsi_get_buf(s->scsi_dev, tag);    if (p) {        usb_msd_copy_data(s);        if (s->usb_len == 0) {            /* Set s->packet to NULL before calling usb_packet_complete               because annother request may be issued before               usb_packet_complete returns.  */            DPRINTF("Packet complete %p\n", p);            s->packet = NULL;            usb_packet_complete(p);        }    }}static void usb_msd_handle_reset(USBDevice *dev){    MSDState *s = (MSDState *)dev;    DPRINTF("Reset\n");    s->mode = USB_MSDM_CBW;}static int usb_msd_handle_control(USBDevice *dev, int request, int value,                                  int index, int length, uint8_t *data){    MSDState *s = (MSDState *)dev;    int ret = 0;    switch (request) {    case DeviceRequest | USB_REQ_GET_STATUS:        data[0] = (1 << USB_DEVICE_SELF_POWERED) |            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);        data[1] = 0x00;        ret = 2;        break;    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:        if (value == USB_DEVICE_REMOTE_WAKEUP) {            dev->remote_wakeup = 0;        } else {            goto fail;        }        ret = 0;        break;    case DeviceOutRequest | USB_REQ_SET_FEATURE:        if (value == USB_DEVICE_REMOTE_WAKEUP) {            dev->remote_wakeup = 1;        } else {            goto fail;        }        ret = 0;        break;    case DeviceOutRequest | USB_REQ_SET_ADDRESS:        dev->addr = value;        ret = 0;        break;    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:        switch(value >> 8) {        case USB_DT_DEVICE:            memcpy(data, qemu_msd_dev_descriptor,                    sizeof(qemu_msd_dev_descriptor));            ret = sizeof(qemu_msd_dev_descriptor);            break;        case USB_DT_CONFIG:            memcpy(data, qemu_msd_config_descriptor,                    sizeof(qemu_msd_config_descriptor));            ret = sizeof(qemu_msd_config_descriptor);            break;        case USB_DT_STRING:            switch(value & 0xff) {            case 0:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -