mirror of
https://github.com/qemu/qemu.git
synced 2024-11-24 03:13:44 +08:00
usb: -usbdevice cleanup and un-deprecation.
usb: split usb-storage. usb: misc fixes and cleanups. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEoDKM/7k6F6eZAf59TLbY7tPocTgFAmBPoTQACgkQTLbY7tPo cThrXxAAjAm9UOfcQNWhQZZlyHfZGCO+tx7KQE7XMocpcfsiaccs7t+EhHexzUel 0cjfTYYt0B3Lf9zpYH9kE9vH84cUvkrV7VP+4TtDNDUIMuJrbNCWZ7Wm8x4Q4IR6 YV9FisSZOqHoRU+kzh+jDkRNC+XzZGMFnoLN2cJRNvSOff25PVs8YsUVWeYKYcnU drVE8lYW+z8AB5M5aiHiJlzXVBwIS/bj/UZmF0ddIuWPyRLPMcnYxEVz2iUkSg6P HMjCexacCAJ2Ag48REu5cmHjyWBEOlcGq4Lvt1x84ZbWhb8rKQlajrr1vRDE1kgH OEMhaIzBxOLwdte4cENADpWxr+m2RiG1/OpRbHUmYJCDxvi0rO1uKWfLawd0tQ2j yYCo+cSuLMSwXjt18yu5NM4Cudc/UrOaoP+ZuCBgDbxIoQH/R46j+3ZThF5tayWx S462j1pwDl4Sc95zWPM7bJciiQognKE0aYHWXD950s3poYapLnGono3CU9QeTR8f pDCSDnBo2NZbFkDQxG9ZfodxxghWr3WwNEIw0JCP2AuUlU4Ndjt/fMiYyJUtF5bD zaVjQNd21NdTgwIipmTKaUUJRDMDU95SHHQm18AVv04oTP+qVEj/j2oebx1k0HtO CZrIZXU6ak6qe43ATZFHlOLryWllhbHHvSiis4357eRNEI8oL/o= =yqef -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/usb-20210315-pull-request' into staging usb: -usbdevice cleanup and un-deprecation. usb: split usb-storage. usb: misc fixes and cleanups. # gpg: Signature made Mon 15 Mar 2021 18:02:28 GMT # gpg: using RSA key A0328CFFB93A17A79901FE7D4CB6D8EED3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full] # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" [full] # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full] # Primary key fingerprint: A032 8CFF B93A 17A7 9901 FE7D 4CB6 D8EE D3E8 7138 * remotes/kraxel/tags/usb-20210315-pull-request: usb/storage: clear csw on reset usb/storage: add kconfig symbols usb/storage move usb-storage device to separate source file usb/storage: move usb-bot device to separate source file usb/storage: move declarations to usb/msd.h header hw/usb: Extract VT82C686 UHCI PCI function into a new unit hw/usb/hcd-uhci: Expose generic prototypes to local header hw/southbridge: Add missing Kconfig dependency VT82C686 on USB_UHCI usb: Document the missing -usbdevice options usb: Un-deprecate -usbdevice (except for -usbdevice audio which gets removed) usb: remove '-usbdevice u2f-key' usb: remove support for -usbdevice parameters hw/usb/bus: Remove the "full-path" property Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5b7f5586d1
@ -1180,6 +1180,7 @@ S: Odd Fixes
|
||||
F: hw/mips/fuloong2e.c
|
||||
F: hw/isa/vt82c686.c
|
||||
F: hw/pci-host/bonito.c
|
||||
F: hw/usb/vt82c686-uhci-pci.c
|
||||
F: include/hw/isa/vt82c686.h
|
||||
|
||||
Loongson-3 virtual platforms
|
||||
|
@ -21,15 +21,6 @@ deprecated.
|
||||
System emulator command line arguments
|
||||
--------------------------------------
|
||||
|
||||
``-usbdevice`` (since 2.10.0)
|
||||
'''''''''''''''''''''''''''''
|
||||
|
||||
The ``-usbdevice DEV`` argument is now a synonym for setting
|
||||
the ``-device usb-DEV`` argument instead. The deprecated syntax
|
||||
would automatically enable USB support on the machine type.
|
||||
If using the new syntax, USB support must be explicitly
|
||||
enabled via the ``-machine usb=on`` argument.
|
||||
|
||||
``-drive file=json:{...{'driver':'file'}}`` (since 3.0)
|
||||
'''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
|
@ -38,6 +38,14 @@ or ``-display default,show-cursor=on`` instead.
|
||||
QEMU 5.0 introduced an alternative syntax to specify the size of the translation
|
||||
block cache, ``-accel tcg,tb-size=``.
|
||||
|
||||
``-usbdevice audio`` (removed in 6.0)
|
||||
'''''''''''''''''''''''''''''''''''''
|
||||
|
||||
This option lacked the possibility to specify an audio backend device.
|
||||
Use ``-device usb-audio`` now instead (and specify a corresponding USB
|
||||
host controller or ``-usb`` if necessary).
|
||||
|
||||
|
||||
QEMU Machine Protocol (QMP) commands
|
||||
------------------------------------
|
||||
|
||||
|
@ -47,6 +47,7 @@ config VT82C686
|
||||
select ACPI_SMBUS
|
||||
select SERIAL_ISA
|
||||
select FDC
|
||||
select USB_UHCI
|
||||
|
||||
config SMC37C669
|
||||
bool
|
||||
|
@ -66,11 +66,22 @@ config USB_TABLET_WACOM
|
||||
default y
|
||||
depends on USB
|
||||
|
||||
config USB_STORAGE_CORE
|
||||
bool
|
||||
depends on USB
|
||||
select SCSI
|
||||
|
||||
config USB_STORAGE_CLASSIC
|
||||
bool
|
||||
default y
|
||||
depends on USB
|
||||
select USB_STORAGE_CORE
|
||||
|
||||
config USB_STORAGE_BOT
|
||||
bool
|
||||
default y
|
||||
depends on USB
|
||||
select SCSI
|
||||
select USB_STORAGE_CORE
|
||||
|
||||
config USB_STORAGE_UAS
|
||||
bool
|
||||
|
39
hw/usb/bus.c
39
hw/usb/bus.c
@ -19,8 +19,6 @@ static void usb_qdev_unrealize(DeviceState *qdev);
|
||||
static Property usb_props[] = {
|
||||
DEFINE_PROP_STRING("port", USBDevice, port_path),
|
||||
DEFINE_PROP_STRING("serial", USBDevice, serial),
|
||||
DEFINE_PROP_BIT("full-path", USBDevice, flags,
|
||||
USB_DEV_FLAG_FULL_PATH, true),
|
||||
DEFINE_PROP_BIT("msos-desc", USBDevice, flags,
|
||||
USB_DEV_FLAG_MSOS_DESC_ENABLE, true),
|
||||
DEFINE_PROP_STRING("pcap", USBDevice, pcap_filename),
|
||||
@ -312,13 +310,13 @@ typedef struct LegacyUSBFactory
|
||||
{
|
||||
const char *name;
|
||||
const char *usbdevice_name;
|
||||
USBDevice *(*usbdevice_init)(const char *params);
|
||||
USBDevice *(*usbdevice_init)(void);
|
||||
} LegacyUSBFactory;
|
||||
|
||||
static GSList *legacy_usb_factory;
|
||||
|
||||
void usb_legacy_register(const char *typename, const char *usbdevice_name,
|
||||
USBDevice *(*usbdevice_init)(const char *params))
|
||||
USBDevice *(*usbdevice_init)(void))
|
||||
{
|
||||
if (usbdevice_name) {
|
||||
LegacyUSBFactory *f = g_malloc0(sizeof(*f));
|
||||
@ -596,11 +594,8 @@ static char *usb_get_dev_path(DeviceState *qdev)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(qdev);
|
||||
DeviceState *hcd = qdev->parent_bus->parent;
|
||||
char *id = NULL;
|
||||
char *id = qdev_get_dev_path(hcd);
|
||||
|
||||
if (dev->flags & (1 << USB_DEV_FLAG_FULL_PATH)) {
|
||||
id = qdev_get_dev_path(hcd);
|
||||
}
|
||||
if (id) {
|
||||
char *ret = g_strdup_printf("%s/%s", id, dev->port->path);
|
||||
g_free(id);
|
||||
@ -663,27 +658,17 @@ void hmp_info_usb(Monitor *mon, const QDict *qdict)
|
||||
}
|
||||
|
||||
/* handle legacy -usbdevice cmd line option */
|
||||
USBDevice *usbdevice_create(const char *cmdline)
|
||||
USBDevice *usbdevice_create(const char *driver)
|
||||
{
|
||||
USBBus *bus = usb_bus_find(-1 /* any */);
|
||||
LegacyUSBFactory *f = NULL;
|
||||
Error *err = NULL;
|
||||
GSList *i;
|
||||
char driver[32];
|
||||
const char *params;
|
||||
int len;
|
||||
USBDevice *dev;
|
||||
|
||||
params = strchr(cmdline,':');
|
||||
if (params) {
|
||||
params++;
|
||||
len = params - cmdline;
|
||||
if (len > sizeof(driver))
|
||||
len = sizeof(driver);
|
||||
pstrcpy(driver, len, cmdline);
|
||||
} else {
|
||||
params = "";
|
||||
pstrcpy(driver, sizeof(driver), cmdline);
|
||||
if (strchr(driver, ':')) {
|
||||
error_report("usbdevice parameters are not supported anymore");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = legacy_usb_factory; i; i = i->next) {
|
||||
@ -707,15 +692,7 @@ USBDevice *usbdevice_create(const char *cmdline)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f->usbdevice_init) {
|
||||
dev = f->usbdevice_init(params);
|
||||
} else {
|
||||
if (*params) {
|
||||
error_report("usbdevice %s accepts no params", driver);
|
||||
return NULL;
|
||||
}
|
||||
dev = usb_new(f->name);
|
||||
}
|
||||
dev = f->usbdevice_init ? f->usbdevice_init() : usb_new(f->name);
|
||||
if (!dev) {
|
||||
error_report("Failed to create USB device '%s'", f->name);
|
||||
return NULL;
|
||||
|
@ -1024,7 +1024,6 @@ static const TypeInfo usb_audio_info = {
|
||||
static void usb_audio_register_types(void)
|
||||
{
|
||||
type_register_static(&usb_audio_info);
|
||||
usb_legacy_register(TYPE_USB_AUDIO, "audio", NULL);
|
||||
}
|
||||
|
||||
type_init(usb_audio_register_types)
|
||||
|
@ -614,7 +614,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
|
||||
s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1);
|
||||
}
|
||||
|
||||
static USBDevice *usb_braille_init(const char *unused)
|
||||
static USBDevice *usb_braille_init(void)
|
||||
{
|
||||
USBDevice *dev;
|
||||
Chardev *cdrv;
|
||||
|
63
hw/usb/dev-storage-bot.c
Normal file
63
hw/usb/dev-storage-bot.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* USB Mass Storage Device emulation
|
||||
*
|
||||
* Copyright (c) 2006 CodeSourcery.
|
||||
* Written by Paul Brook
|
||||
*
|
||||
* This code is licensed under the LGPL.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/usb.h"
|
||||
#include "hw/usb/desc.h"
|
||||
#include "hw/usb/msd.h"
|
||||
|
||||
static const struct SCSIBusInfo usb_msd_scsi_info_bot = {
|
||||
.tcq = false,
|
||||
.max_target = 0,
|
||||
.max_lun = 15,
|
||||
|
||||
.transfer_data = usb_msd_transfer_data,
|
||||
.complete = usb_msd_command_complete,
|
||||
.cancel = usb_msd_request_cancelled,
|
||||
.load_request = usb_msd_load_request,
|
||||
};
|
||||
|
||||
static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
|
||||
{
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
DeviceState *d = DEVICE(dev);
|
||||
|
||||
usb_desc_create_serial(dev);
|
||||
usb_desc_init(dev);
|
||||
if (d->hotplugged) {
|
||||
s->dev.auto_attach = 0;
|
||||
}
|
||||
|
||||
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
|
||||
&usb_msd_scsi_info_bot, NULL);
|
||||
usb_msd_handle_reset(dev);
|
||||
}
|
||||
|
||||
static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data)
|
||||
{
|
||||
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||
|
||||
uc->realize = usb_msd_bot_realize;
|
||||
uc->attached_settable = true;
|
||||
}
|
||||
|
||||
static const TypeInfo bot_info = {
|
||||
.name = "usb-bot",
|
||||
.parent = TYPE_USB_STORAGE,
|
||||
.class_init = usb_msd_class_bot_initfn,
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&bot_info);
|
||||
}
|
||||
|
||||
type_init(register_types)
|
156
hw/usb/dev-storage-classic.c
Normal file
156
hw/usb/dev-storage-classic.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* USB Mass Storage Device emulation
|
||||
*
|
||||
* Copyright (c) 2006 CodeSourcery.
|
||||
* Written by Paul Brook
|
||||
*
|
||||
* This code is licensed under the LGPL.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "hw/usb.h"
|
||||
#include "hw/usb/desc.h"
|
||||
#include "hw/usb/msd.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
static const struct SCSIBusInfo usb_msd_scsi_info_storage = {
|
||||
.tcq = false,
|
||||
.max_target = 0,
|
||||
.max_lun = 0,
|
||||
|
||||
.transfer_data = usb_msd_transfer_data,
|
||||
.complete = usb_msd_command_complete,
|
||||
.cancel = usb_msd_request_cancelled,
|
||||
.load_request = usb_msd_load_request,
|
||||
};
|
||||
|
||||
static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
|
||||
{
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
BlockBackend *blk = s->conf.blk;
|
||||
SCSIDevice *scsi_dev;
|
||||
|
||||
if (!blk) {
|
||||
error_setg(errp, "drive property not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blkconf_blocksizes(&s->conf, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blkconf_apply_backend_options(&s->conf, !blk_supports_write_perm(blk),
|
||||
true, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack alert: this pretends to be a block device, but it's really
|
||||
* a SCSI bus that can serve only a single device, which it
|
||||
* creates automatically. But first it needs to detach from its
|
||||
* blockdev, or else scsi_bus_legacy_add_drive() dies when it
|
||||
* attaches again. We also need to take another reference so that
|
||||
* blk_detach_dev() doesn't free blk while we still need it.
|
||||
*
|
||||
* The hack is probably a bad idea.
|
||||
*/
|
||||
blk_ref(blk);
|
||||
blk_detach_dev(blk, DEVICE(s));
|
||||
s->conf.blk = NULL;
|
||||
|
||||
usb_desc_create_serial(dev);
|
||||
usb_desc_init(dev);
|
||||
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
|
||||
&usb_msd_scsi_info_storage, NULL);
|
||||
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
|
||||
s->conf.bootindex, s->conf.share_rw,
|
||||
s->conf.rerror, s->conf.werror,
|
||||
dev->serial,
|
||||
errp);
|
||||
blk_unref(blk);
|
||||
if (!scsi_dev) {
|
||||
return;
|
||||
}
|
||||
usb_msd_handle_reset(dev);
|
||||
s->scsi_dev = scsi_dev;
|
||||
}
|
||||
|
||||
static Property msd_properties[] = {
|
||||
DEFINE_BLOCK_PROPERTIES(MSDState, conf),
|
||||
DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
|
||||
DEFINE_PROP_BOOL("removable", MSDState, removable, false),
|
||||
DEFINE_PROP_BOOL("commandlog", MSDState, commandlog, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||
|
||||
uc->realize = usb_msd_storage_realize;
|
||||
device_class_set_props(dc, msd_properties);
|
||||
}
|
||||
|
||||
static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
|
||||
visit_type_int32(v, name, &s->conf.bootindex, errp);
|
||||
}
|
||||
|
||||
static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
int32_t boot_index;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!visit_type_int32(v, name, &boot_index, errp)) {
|
||||
return;
|
||||
}
|
||||
/* check whether bootindex is present in fw_boot_order list */
|
||||
check_boot_index(boot_index, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* change bootindex to a new one */
|
||||
s->conf.bootindex = boot_index;
|
||||
|
||||
if (s->scsi_dev) {
|
||||
object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index,
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
out:
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static void usb_msd_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "bootindex", "int32",
|
||||
usb_msd_get_bootindex,
|
||||
usb_msd_set_bootindex, NULL, NULL);
|
||||
object_property_set_int(obj, "bootindex", -1, NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo msd_info = {
|
||||
.name = "usb-storage",
|
||||
.parent = TYPE_USB_STORAGE,
|
||||
.class_init = usb_msd_class_storage_initfn,
|
||||
.instance_init = usb_msd_instance_init,
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&msd_info);
|
||||
}
|
||||
|
||||
type_init(register_types)
|
@ -14,13 +14,11 @@
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "hw/usb.h"
|
||||
#include "hw/usb/msd.h"
|
||||
#include "desc.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qom/object.h"
|
||||
#include "trace.h"
|
||||
@ -29,43 +27,6 @@
|
||||
#define MassStorageReset 0xff
|
||||
#define GetMaxLun 0xfe
|
||||
|
||||
enum USBMSDMode {
|
||||
USB_MSDM_CBW, /* Command Block. */
|
||||
USB_MSDM_DATAOUT, /* Transfer data to device. */
|
||||
USB_MSDM_DATAIN, /* Transfer data from device. */
|
||||
USB_MSDM_CSW /* Command Status. */
|
||||
};
|
||||
|
||||
struct usb_msd_csw {
|
||||
uint32_t sig;
|
||||
uint32_t tag;
|
||||
uint32_t residue;
|
||||
uint8_t status;
|
||||
};
|
||||
|
||||
struct MSDState {
|
||||
USBDevice dev;
|
||||
enum USBMSDMode mode;
|
||||
uint32_t scsi_off;
|
||||
uint32_t scsi_len;
|
||||
uint32_t data_len;
|
||||
struct usb_msd_csw csw;
|
||||
SCSIRequest *req;
|
||||
SCSIBus bus;
|
||||
/* For async completion. */
|
||||
USBPacket *packet;
|
||||
/* usb-storage only */
|
||||
BlockConf conf;
|
||||
bool removable;
|
||||
bool commandlog;
|
||||
SCSIDevice *scsi_dev;
|
||||
};
|
||||
typedef struct MSDState MSDState;
|
||||
|
||||
#define TYPE_USB_STORAGE "usb-storage-dev"
|
||||
DECLARE_INSTANCE_CHECKER(MSDState, USB_STORAGE_DEV,
|
||||
TYPE_USB_STORAGE)
|
||||
|
||||
struct usb_msd_cbw {
|
||||
uint32_t sig;
|
||||
uint32_t tag;
|
||||
@ -259,7 +220,7 @@ static void usb_msd_packet_complete(MSDState *s)
|
||||
usb_packet_complete(&s->dev, p);
|
||||
}
|
||||
|
||||
static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
|
||||
void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
|
||||
{
|
||||
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
||||
USBPacket *p = s->packet;
|
||||
@ -277,7 +238,7 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_msd_command_complete(SCSIRequest *req, size_t resid)
|
||||
void usb_msd_command_complete(SCSIRequest *req, size_t resid)
|
||||
{
|
||||
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
||||
USBPacket *p = s->packet;
|
||||
@ -320,7 +281,7 @@ static void usb_msd_command_complete(SCSIRequest *req, size_t resid)
|
||||
s->req = NULL;
|
||||
}
|
||||
|
||||
static void usb_msd_request_cancelled(SCSIRequest *req)
|
||||
void usb_msd_request_cancelled(SCSIRequest *req)
|
||||
{
|
||||
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
||||
|
||||
@ -337,7 +298,7 @@ static void usb_msd_request_cancelled(SCSIRequest *req)
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_msd_handle_reset(USBDevice *dev)
|
||||
void usb_msd_handle_reset(USBDevice *dev)
|
||||
{
|
||||
MSDState *s = (MSDState *)dev;
|
||||
|
||||
@ -352,6 +313,7 @@ static void usb_msd_handle_reset(USBDevice *dev)
|
||||
usb_msd_packet_complete(s);
|
||||
}
|
||||
|
||||
memset(&s->csw, 0, sizeof(s->csw));
|
||||
s->mode = USB_MSDM_CBW;
|
||||
}
|
||||
|
||||
@ -565,7 +527,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
|
||||
}
|
||||
}
|
||||
|
||||
static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
|
||||
void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
|
||||
{
|
||||
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
|
||||
|
||||
@ -576,95 +538,6 @@ static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct SCSIBusInfo usb_msd_scsi_info_storage = {
|
||||
.tcq = false,
|
||||
.max_target = 0,
|
||||
.max_lun = 0,
|
||||
|
||||
.transfer_data = usb_msd_transfer_data,
|
||||
.complete = usb_msd_command_complete,
|
||||
.cancel = usb_msd_request_cancelled,
|
||||
.load_request = usb_msd_load_request,
|
||||
};
|
||||
|
||||
static const struct SCSIBusInfo usb_msd_scsi_info_bot = {
|
||||
.tcq = false,
|
||||
.max_target = 0,
|
||||
.max_lun = 15,
|
||||
|
||||
.transfer_data = usb_msd_transfer_data,
|
||||
.complete = usb_msd_command_complete,
|
||||
.cancel = usb_msd_request_cancelled,
|
||||
.load_request = usb_msd_load_request,
|
||||
};
|
||||
|
||||
static void usb_msd_storage_realize(USBDevice *dev, Error **errp)
|
||||
{
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
BlockBackend *blk = s->conf.blk;
|
||||
SCSIDevice *scsi_dev;
|
||||
|
||||
if (!blk) {
|
||||
error_setg(errp, "drive property not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blkconf_blocksizes(&s->conf, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blkconf_apply_backend_options(&s->conf, !blk_supports_write_perm(blk),
|
||||
true, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack alert: this pretends to be a block device, but it's really
|
||||
* a SCSI bus that can serve only a single device, which it
|
||||
* creates automatically. But first it needs to detach from its
|
||||
* blockdev, or else scsi_bus_legacy_add_drive() dies when it
|
||||
* attaches again. We also need to take another reference so that
|
||||
* blk_detach_dev() doesn't free blk while we still need it.
|
||||
*
|
||||
* The hack is probably a bad idea.
|
||||
*/
|
||||
blk_ref(blk);
|
||||
blk_detach_dev(blk, DEVICE(s));
|
||||
s->conf.blk = NULL;
|
||||
|
||||
usb_desc_create_serial(dev);
|
||||
usb_desc_init(dev);
|
||||
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
|
||||
&usb_msd_scsi_info_storage, NULL);
|
||||
scsi_dev = scsi_bus_legacy_add_drive(&s->bus, blk, 0, !!s->removable,
|
||||
s->conf.bootindex, s->conf.share_rw,
|
||||
s->conf.rerror, s->conf.werror,
|
||||
dev->serial,
|
||||
errp);
|
||||
blk_unref(blk);
|
||||
if (!scsi_dev) {
|
||||
return;
|
||||
}
|
||||
usb_msd_handle_reset(dev);
|
||||
s->scsi_dev = scsi_dev;
|
||||
}
|
||||
|
||||
static void usb_msd_bot_realize(USBDevice *dev, Error **errp)
|
||||
{
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
DeviceState *d = DEVICE(dev);
|
||||
|
||||
usb_desc_create_serial(dev);
|
||||
usb_desc_init(dev);
|
||||
if (d->hotplugged) {
|
||||
s->dev.auto_attach = 0;
|
||||
}
|
||||
|
||||
scsi_bus_new(&s->bus, sizeof(s->bus), DEVICE(dev),
|
||||
&usb_msd_scsi_info_bot, NULL);
|
||||
usb_msd_handle_reset(dev);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_usb_msd = {
|
||||
.name = "usb-storage",
|
||||
.version_id = 1,
|
||||
@ -683,14 +556,6 @@ static const VMStateDescription vmstate_usb_msd = {
|
||||
}
|
||||
};
|
||||
|
||||
static Property msd_properties[] = {
|
||||
DEFINE_BLOCK_PROPERTIES(MSDState, conf),
|
||||
DEFINE_BLOCK_ERROR_PROPERTIES(MSDState, conf),
|
||||
DEFINE_PROP_BOOL("removable", MSDState, removable, false),
|
||||
DEFINE_PROP_BOOL("commandlog", MSDState, commandlog, false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void usb_msd_class_initfn_common(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@ -708,52 +573,6 @@ static void usb_msd_class_initfn_common(ObjectClass *klass, void *data)
|
||||
dc->vmsd = &vmstate_usb_msd;
|
||||
}
|
||||
|
||||
static void usb_msd_class_storage_initfn(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||
|
||||
uc->realize = usb_msd_storage_realize;
|
||||
device_class_set_props(dc, msd_properties);
|
||||
}
|
||||
|
||||
static void usb_msd_get_bootindex(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
|
||||
visit_type_int32(v, name, &s->conf.bootindex, errp);
|
||||
}
|
||||
|
||||
static void usb_msd_set_bootindex(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
USBDevice *dev = USB_DEVICE(obj);
|
||||
MSDState *s = USB_STORAGE_DEV(dev);
|
||||
int32_t boot_index;
|
||||
Error *local_err = NULL;
|
||||
|
||||
if (!visit_type_int32(v, name, &boot_index, errp)) {
|
||||
return;
|
||||
}
|
||||
/* check whether bootindex is present in fw_boot_order list */
|
||||
check_boot_index(boot_index, &local_err);
|
||||
if (local_err) {
|
||||
goto out;
|
||||
}
|
||||
/* change bootindex to a new one */
|
||||
s->conf.bootindex = boot_index;
|
||||
|
||||
if (s->scsi_dev) {
|
||||
object_property_set_int(OBJECT(s->scsi_dev), "bootindex", boot_index,
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
out:
|
||||
error_propagate(errp, local_err);
|
||||
}
|
||||
|
||||
static const TypeInfo usb_storage_dev_type_info = {
|
||||
.name = TYPE_USB_STORAGE,
|
||||
.parent = TYPE_USB_DEVICE,
|
||||
@ -762,40 +581,9 @@ static const TypeInfo usb_storage_dev_type_info = {
|
||||
.class_init = usb_msd_class_initfn_common,
|
||||
};
|
||||
|
||||
static void usb_msd_instance_init(Object *obj)
|
||||
{
|
||||
object_property_add(obj, "bootindex", "int32",
|
||||
usb_msd_get_bootindex,
|
||||
usb_msd_set_bootindex, NULL, NULL);
|
||||
object_property_set_int(obj, "bootindex", -1, NULL);
|
||||
}
|
||||
|
||||
static void usb_msd_class_bot_initfn(ObjectClass *klass, void *data)
|
||||
{
|
||||
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
|
||||
|
||||
uc->realize = usb_msd_bot_realize;
|
||||
uc->attached_settable = true;
|
||||
}
|
||||
|
||||
static const TypeInfo msd_info = {
|
||||
.name = "usb-storage",
|
||||
.parent = TYPE_USB_STORAGE,
|
||||
.class_init = usb_msd_class_storage_initfn,
|
||||
.instance_init = usb_msd_instance_init,
|
||||
};
|
||||
|
||||
static const TypeInfo bot_info = {
|
||||
.name = "usb-bot",
|
||||
.parent = TYPE_USB_STORAGE,
|
||||
.class_init = usb_msd_class_bot_initfn,
|
||||
};
|
||||
|
||||
static void usb_msd_register_types(void)
|
||||
{
|
||||
type_register_static(&usb_storage_dev_type_info);
|
||||
type_register_static(&msd_info);
|
||||
type_register_static(&bot_info);
|
||||
}
|
||||
|
||||
type_init(usb_msd_register_types)
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qom/object.h"
|
||||
#include "hcd-uhci.h"
|
||||
|
||||
#define FRAME_TIMER_FREQ 1000
|
||||
|
||||
@ -50,8 +51,6 @@
|
||||
|
||||
#define MAX_FRAMES_PER_TICK (QH_VALID / 2)
|
||||
|
||||
#define NB_PORTS 2
|
||||
|
||||
enum {
|
||||
TD_RESULT_STOP_FRAME = 10,
|
||||
TD_RESULT_COMPLETE,
|
||||
@ -62,20 +61,8 @@ enum {
|
||||
|
||||
typedef struct UHCIState UHCIState;
|
||||
typedef struct UHCIAsync UHCIAsync;
|
||||
typedef struct UHCIQueue UHCIQueue;
|
||||
typedef struct UHCIInfo UHCIInfo;
|
||||
typedef struct UHCIPCIDeviceClass UHCIPCIDeviceClass;
|
||||
|
||||
struct UHCIInfo {
|
||||
const char *name;
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint8_t revision;
|
||||
uint8_t irq_pin;
|
||||
void (*realize)(PCIDevice *dev, Error **errp);
|
||||
bool unplug;
|
||||
};
|
||||
|
||||
struct UHCIPCIDeviceClass {
|
||||
PCIDeviceClass parent_class;
|
||||
UHCIInfo info;
|
||||
@ -107,43 +94,6 @@ struct UHCIQueue {
|
||||
int8_t valid;
|
||||
};
|
||||
|
||||
typedef struct UHCIPort {
|
||||
USBPort port;
|
||||
uint16_t ctrl;
|
||||
} UHCIPort;
|
||||
|
||||
struct UHCIState {
|
||||
PCIDevice dev;
|
||||
MemoryRegion io_bar;
|
||||
USBBus bus; /* Note unused when we're a companion controller */
|
||||
uint16_t cmd; /* cmd register */
|
||||
uint16_t status;
|
||||
uint16_t intr; /* interrupt enable register */
|
||||
uint16_t frnum; /* frame number */
|
||||
uint32_t fl_base_addr; /* frame list base address */
|
||||
uint8_t sof_timing;
|
||||
uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
|
||||
int64_t expire_time;
|
||||
QEMUTimer *frame_timer;
|
||||
QEMUBH *bh;
|
||||
uint32_t frame_bytes;
|
||||
uint32_t frame_bandwidth;
|
||||
bool completions_only;
|
||||
UHCIPort ports[NB_PORTS];
|
||||
|
||||
/* Interrupts that should be raised at the end of the current frame. */
|
||||
uint32_t pending_int_mask;
|
||||
|
||||
/* Active packets */
|
||||
QTAILQ_HEAD(, UHCIQueue) queues;
|
||||
uint8_t num_ports_vmstate;
|
||||
|
||||
/* Properties */
|
||||
char *masterbus;
|
||||
uint32_t firstport;
|
||||
uint32_t maxframes;
|
||||
};
|
||||
|
||||
typedef struct UHCI_TD {
|
||||
uint32_t link;
|
||||
uint32_t ctrl; /* see TD_CTRL_xxx */
|
||||
@ -160,10 +110,6 @@ static void uhci_async_cancel(UHCIAsync *async);
|
||||
static void uhci_queue_fill(UHCIQueue *q, UHCI_TD *td);
|
||||
static void uhci_resume(void *opaque);
|
||||
|
||||
#define TYPE_UHCI "pci-uhci-usb"
|
||||
DECLARE_INSTANCE_CHECKER(UHCIState, UHCI,
|
||||
TYPE_UHCI)
|
||||
|
||||
static inline int32_t uhci_queue_token(UHCI_TD *td)
|
||||
{
|
||||
if ((td->token & (0xf << 15)) == 0) {
|
||||
@ -1213,7 +1159,7 @@ static USBPortOps uhci_port_ops = {
|
||||
static USBBusOps uhci_bus_ops = {
|
||||
};
|
||||
|
||||
static void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
|
||||
void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
|
||||
@ -1261,21 +1207,6 @@ static void usb_uhci_common_realize(PCIDevice *dev, Error **errp)
|
||||
pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
|
||||
}
|
||||
|
||||
static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
UHCIState *s = UHCI(dev);
|
||||
uint8_t *pci_conf = s->dev.config;
|
||||
|
||||
/* USB misc control 1/2 */
|
||||
pci_set_long(pci_conf + 0x40,0x00001000);
|
||||
/* PM capability */
|
||||
pci_set_long(pci_conf + 0x80,0x00020001);
|
||||
/* USB legacy support */
|
||||
pci_set_long(pci_conf + 0xc0,0x00002000);
|
||||
|
||||
usb_uhci_common_realize(dev, errp);
|
||||
}
|
||||
|
||||
static void usb_uhci_exit(PCIDevice *dev)
|
||||
{
|
||||
UHCIState *s = UHCI(dev);
|
||||
@ -1335,7 +1266,7 @@ static const TypeInfo uhci_pci_type_info = {
|
||||
},
|
||||
};
|
||||
|
||||
static void uhci_data_class_init(ObjectClass *klass, void *data)
|
||||
void uhci_data_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
@ -1372,14 +1303,6 @@ static UHCIInfo uhci_info[] = {
|
||||
.revision = 0x01,
|
||||
.irq_pin = 3,
|
||||
.unplug = true,
|
||||
},{
|
||||
.name = "vt82c686b-usb-uhci",
|
||||
.vendor_id = PCI_VENDOR_ID_VIA,
|
||||
.device_id = PCI_DEVICE_ID_VIA_UHCI,
|
||||
.revision = 0x01,
|
||||
.irq_pin = 3,
|
||||
.realize = usb_uhci_vt82c686b_realize,
|
||||
.unplug = true,
|
||||
},{
|
||||
.name = "ich9-usb-uhci1", /* 00:1d.0 */
|
||||
.vendor_id = PCI_VENDOR_ID_INTEL,
|
||||
|
93
hw/usb/hcd-uhci.h
Normal file
93
hw/usb/hcd-uhci.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* USB UHCI controller emulation
|
||||
*
|
||||
* Copyright (c) 2005 Fabrice Bellard
|
||||
*
|
||||
* Copyright (c) 2008 Max Krasnyansky
|
||||
* Magor rewrite of the UHCI data structures parser and frame processor
|
||||
* Support for fully async operation and multiple outstanding transactions
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef HW_USB_HCD_UHCI_H
|
||||
#define HW_USB_HCD_UHCI_H
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/usb.h"
|
||||
|
||||
typedef struct UHCIQueue UHCIQueue;
|
||||
|
||||
#define NB_PORTS 2
|
||||
|
||||
typedef struct UHCIPort {
|
||||
USBPort port;
|
||||
uint16_t ctrl;
|
||||
} UHCIPort;
|
||||
|
||||
typedef struct UHCIState {
|
||||
PCIDevice dev;
|
||||
MemoryRegion io_bar;
|
||||
USBBus bus; /* Note unused when we're a companion controller */
|
||||
uint16_t cmd; /* cmd register */
|
||||
uint16_t status;
|
||||
uint16_t intr; /* interrupt enable register */
|
||||
uint16_t frnum; /* frame number */
|
||||
uint32_t fl_base_addr; /* frame list base address */
|
||||
uint8_t sof_timing;
|
||||
uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
|
||||
int64_t expire_time;
|
||||
QEMUTimer *frame_timer;
|
||||
QEMUBH *bh;
|
||||
uint32_t frame_bytes;
|
||||
uint32_t frame_bandwidth;
|
||||
bool completions_only;
|
||||
UHCIPort ports[NB_PORTS];
|
||||
|
||||
/* Interrupts that should be raised at the end of the current frame. */
|
||||
uint32_t pending_int_mask;
|
||||
|
||||
/* Active packets */
|
||||
QTAILQ_HEAD(, UHCIQueue) queues;
|
||||
uint8_t num_ports_vmstate;
|
||||
|
||||
/* Properties */
|
||||
char *masterbus;
|
||||
uint32_t firstport;
|
||||
uint32_t maxframes;
|
||||
} UHCIState;
|
||||
|
||||
#define TYPE_UHCI "pci-uhci-usb"
|
||||
DECLARE_INSTANCE_CHECKER(UHCIState, UHCI, TYPE_UHCI)
|
||||
|
||||
typedef struct UHCIInfo {
|
||||
const char *name;
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint8_t revision;
|
||||
uint8_t irq_pin;
|
||||
void (*realize)(PCIDevice *dev, Error **errp);
|
||||
bool unplug;
|
||||
} UHCIInfo;
|
||||
|
||||
void uhci_data_class_init(ObjectClass *klass, void *data);
|
||||
void usb_uhci_common_realize(PCIDevice *dev, Error **errp);
|
||||
|
||||
#endif
|
@ -32,6 +32,7 @@ softmmu_ss.add(when: 'CONFIG_USB_DWC3', if_true: files('hcd-dwc3.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_TUSB6010', if_true: files('tusb6010.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_IMX', if_true: files('chipidea.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_IMX_USBPHY', if_true: files('imx-usb-phy.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_VT82C686', if_true: files('vt82c686-uhci-pci.c'))
|
||||
specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-usb2-ctrl-regs.c'))
|
||||
specific_ss.add(when: 'CONFIG_XLNX_USB_SUBSYS', if_true: files('xlnx-usb-subsystem.c'))
|
||||
|
||||
@ -39,7 +40,9 @@ specific_ss.add(when: 'CONFIG_XLNX_USB_SUBSYS', if_true: files('xlnx-usb-subsyst
|
||||
softmmu_ss.add(when: 'CONFIG_USB', if_true: files('dev-hub.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB', if_true: files('dev-hid.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_TABLET_WACOM', if_true: files('dev-wacom.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_STORAGE_BOT', if_true: files('dev-storage.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_STORAGE_CORE', if_true: files('dev-storage.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_STORAGE_BOT', if_true: files('dev-storage-bot.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_STORAGE_CLASSIC', if_true: files('dev-storage-classic.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_STORAGE_UAS', if_true: files('dev-uas.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_AUDIO', if_true: files('dev-audio.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_USB_SERIAL', if_true: files('dev-serial.c'))
|
||||
|
@ -346,7 +346,6 @@ static const TypeInfo u2f_key_info = {
|
||||
static void u2f_key_register_types(void)
|
||||
{
|
||||
type_register_static(&u2f_key_info);
|
||||
usb_legacy_register(TYPE_U2F_KEY, "u2f-key", NULL);
|
||||
}
|
||||
|
||||
type_init(u2f_key_register_types)
|
||||
|
43
hw/usb/vt82c686-uhci-pci.c
Normal file
43
hw/usb/vt82c686-uhci-pci.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hcd-uhci.h"
|
||||
|
||||
static void usb_uhci_vt82c686b_realize(PCIDevice *dev, Error **errp)
|
||||
{
|
||||
UHCIState *s = UHCI(dev);
|
||||
uint8_t *pci_conf = s->dev.config;
|
||||
|
||||
/* USB misc control 1/2 */
|
||||
pci_set_long(pci_conf + 0x40, 0x00001000);
|
||||
/* PM capability */
|
||||
pci_set_long(pci_conf + 0x80, 0x00020001);
|
||||
/* USB legacy support */
|
||||
pci_set_long(pci_conf + 0xc0, 0x00002000);
|
||||
|
||||
usb_uhci_common_realize(dev, errp);
|
||||
}
|
||||
|
||||
static UHCIInfo uhci_info[] = {
|
||||
{
|
||||
.name = "vt82c686b-usb-uhci",
|
||||
.vendor_id = PCI_VENDOR_ID_VIA,
|
||||
.device_id = PCI_DEVICE_ID_VIA_UHCI,
|
||||
.revision = 0x01,
|
||||
.irq_pin = 3,
|
||||
.realize = usb_uhci_vt82c686b_realize,
|
||||
.unplug = true,
|
||||
}
|
||||
};
|
||||
|
||||
static const TypeInfo vt82c686b_usb_uhci_type_info = {
|
||||
.parent = TYPE_UHCI,
|
||||
.name = "vt82c686b-usb-uhci",
|
||||
.class_init = uhci_data_class_init,
|
||||
.class_data = uhci_info,
|
||||
};
|
||||
|
||||
static void vt82c686b_usb_uhci_register_types(void)
|
||||
{
|
||||
type_register_static(&vt82c686b_usb_uhci_type_info);
|
||||
}
|
||||
|
||||
type_init(vt82c686b_usb_uhci_register_types)
|
@ -216,7 +216,6 @@ struct USBEndpoint {
|
||||
};
|
||||
|
||||
enum USBDeviceFlags {
|
||||
USB_DEV_FLAG_FULL_PATH,
|
||||
USB_DEV_FLAG_IS_HOST,
|
||||
USB_DEV_FLAG_MSOS_DESC_ENABLE,
|
||||
USB_DEV_FLAG_MSOS_DESC_IN_USE,
|
||||
@ -500,7 +499,7 @@ void usb_bus_new(USBBus *bus, size_t bus_size,
|
||||
void usb_bus_release(USBBus *bus);
|
||||
USBBus *usb_bus_find(int busnr);
|
||||
void usb_legacy_register(const char *typename, const char *usbdevice_name,
|
||||
USBDevice *(*usbdevice_init)(const char *params));
|
||||
USBDevice *(*usbdevice_init)(void));
|
||||
USBDevice *usb_new(const char *name);
|
||||
bool usb_realize_and_unref(USBDevice *dev, USBBus *bus, Error **errp);
|
||||
USBDevice *usb_create_simple(USBBus *bus, const char *name);
|
||||
|
54
include/hw/usb/msd.h
Normal file
54
include/hw/usb/msd.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* USB Mass Storage Device emulation
|
||||
*
|
||||
* Copyright (c) 2006 CodeSourcery.
|
||||
* Written by Paul Brook
|
||||
*
|
||||
* This code is licensed under the LGPL.
|
||||
*/
|
||||
|
||||
#include "hw/usb.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
|
||||
enum USBMSDMode {
|
||||
USB_MSDM_CBW, /* Command Block. */
|
||||
USB_MSDM_DATAOUT, /* Transfer data to device. */
|
||||
USB_MSDM_DATAIN, /* Transfer data from device. */
|
||||
USB_MSDM_CSW /* Command Status. */
|
||||
};
|
||||
|
||||
struct usb_msd_csw {
|
||||
uint32_t sig;
|
||||
uint32_t tag;
|
||||
uint32_t residue;
|
||||
uint8_t status;
|
||||
};
|
||||
|
||||
struct MSDState {
|
||||
USBDevice dev;
|
||||
enum USBMSDMode mode;
|
||||
uint32_t scsi_off;
|
||||
uint32_t scsi_len;
|
||||
uint32_t data_len;
|
||||
struct usb_msd_csw csw;
|
||||
SCSIRequest *req;
|
||||
SCSIBus bus;
|
||||
/* For async completion. */
|
||||
USBPacket *packet;
|
||||
/* usb-storage only */
|
||||
BlockConf conf;
|
||||
bool removable;
|
||||
bool commandlog;
|
||||
SCSIDevice *scsi_dev;
|
||||
};
|
||||
|
||||
typedef struct MSDState MSDState;
|
||||
#define TYPE_USB_STORAGE "usb-storage-dev"
|
||||
DECLARE_INSTANCE_CHECKER(MSDState, USB_STORAGE_DEV,
|
||||
TYPE_USB_STORAGE)
|
||||
|
||||
void usb_msd_transfer_data(SCSIRequest *req, uint32_t len);
|
||||
void usb_msd_command_complete(SCSIRequest *req, size_t resid);
|
||||
void usb_msd_request_cancelled(SCSIRequest *req);
|
||||
void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req);
|
||||
void usb_msd_handle_reset(USBDevice *dev);
|
@ -1705,7 +1705,7 @@ ERST
|
||||
|
||||
DEFHEADING()
|
||||
|
||||
DEFHEADING(USB options:)
|
||||
DEFHEADING(USB convenience options:)
|
||||
|
||||
DEF("usb", 0, QEMU_OPTION_usb,
|
||||
"-usb enable on-board USB host controller (if not enabled by default)\n",
|
||||
@ -1723,9 +1723,31 @@ DEF("usbdevice", HAS_ARG, QEMU_OPTION_usbdevice,
|
||||
QEMU_ARCH_ALL)
|
||||
SRST
|
||||
``-usbdevice devname``
|
||||
Add the USB device devname. Note that this option is deprecated,
|
||||
please use ``-device usb-...`` instead. See the chapter about
|
||||
Add the USB device devname, and enable an on-board USB controller
|
||||
if possible and necessary (just like it can be done via
|
||||
``-machine usb=on``). Note that this option is mainly intended for
|
||||
the user's convenience only. More fine-grained control can be
|
||||
achieved by selecting a USB host controller (if necessary) and the
|
||||
desired USB device via the ``-device`` option instead. For example,
|
||||
instead of using ``-usbdevice mouse`` it is possible to use
|
||||
``-device qemu-xhci -device usb-mouse`` to connect the USB mouse
|
||||
to a USB 3.0 controller instead (at least on machines that support
|
||||
PCI and do not have an USB controller enabled by default yet).
|
||||
For more details, see the chapter about
|
||||
:ref:`Connecting USB devices` in the System Emulation Users Guide.
|
||||
Possible devices for devname are:
|
||||
|
||||
``braille``
|
||||
Braille device. This will use BrlAPI to display the braille
|
||||
output on a real or fake device (i.e. it also creates a
|
||||
corresponding ``braille`` chardev automatically beside the
|
||||
``usb-braille`` USB device).
|
||||
|
||||
``ccid``
|
||||
Smartcard reader device
|
||||
|
||||
``keyboard``
|
||||
Standard USB keyboard. Will override the PS/2 keyboard (if present).
|
||||
|
||||
``mouse``
|
||||
Virtual Mouse. This will override the PS/2 mouse emulation when
|
||||
@ -1737,9 +1759,10 @@ SRST
|
||||
position without having to grab the mouse. Also overrides the
|
||||
PS/2 mouse emulation when activated.
|
||||
|
||||
``braille``
|
||||
Braille device. This will use BrlAPI to display the braille
|
||||
output on a real or fake device.
|
||||
``wacom-tablet``
|
||||
Wacom PenPartner USB tablet.
|
||||
|
||||
|
||||
ERST
|
||||
|
||||
DEFHEADING()
|
||||
|
@ -3180,8 +3180,6 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||
qemu_opts_parse_noisily(olist, "usb=on", false);
|
||||
break;
|
||||
case QEMU_OPTION_usbdevice:
|
||||
error_report("'-usbdevice' is deprecated, please use "
|
||||
"'-device usb-...' instead");
|
||||
olist = qemu_find_opts("machine");
|
||||
qemu_opts_parse_noisily(olist, "usb=on", false);
|
||||
add_device_config(DEV_USB, optarg);
|
||||
|
Loading…
Reference in New Issue
Block a user