diff options
author | Pav Lucistnik <pav@FreeBSD.org> | 2006-03-18 21:23:42 +0000 |
---|---|---|
committer | Pav Lucistnik <pav@FreeBSD.org> | 2006-03-18 21:23:42 +0000 |
commit | b56ad1448df9cd4f220225a8c951cde64671f5aa (patch) | |
tree | 6317e394b6fd6ffa40390811446d567021887102 /emulators | |
parent | c3dba571af705f4620ec8808a299a283def99a70 (diff) | |
download | ports-b56ad1448df9cd4f220225a8c951cde64671f5aa.tar.gz ports-b56ad1448df9cd4f220225a8c951cde64671f5aa.zip |
Notes
Diffstat (limited to 'emulators')
26 files changed, 2060 insertions, 2 deletions
diff --git a/emulators/qemu-devel/Makefile b/emulators/qemu-devel/Makefile index 61087cfb7139..28c88772c7a0 100644 --- a/emulators/qemu-devel/Makefile +++ b/emulators/qemu-devel/Makefile @@ -7,7 +7,7 @@ PORTNAME= qemu PORTVERSION= 0.8.0 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= emulators MASTER_SITES= http://www.qemu.org/:release \ http://people.fruitsalad.org/nox/qemu/:snapshot \ diff --git a/emulators/qemu-devel/files/patch-bsdusb.patch b/emulators/qemu-devel/files/patch-bsdusb.patch new file mode 100644 index 000000000000..9a90b930cbea --- /dev/null +++ b/emulators/qemu-devel/files/patch-bsdusb.patch @@ -0,0 +1,741 @@ +Index: qemu/configure +@@ -122,6 +122,7 @@ + *) + oss="yes" + linux="yes" ++usb="linux" + if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then + kqemu="yes" + fi +@@ -131,6 +132,7 @@ + if [ "$bsd" = "yes" ] ; then + if [ ! "$darwin" = "yes" ] ; then + make="gmake" ++ usb="bsd" + fi + fi + +@@ -656,6 +675,19 @@ + echo "#define _BSD 1" >> $config_h + fi + ++# USB host support ++case "$usb" in ++linux) ++ echo "HOST_USB=linux" >> $conig_mak ++;; ++bsd) ++ echo "HOST_USB=bsd" >> $config_mak ++;; ++*) ++ echo "HOST_USB=stub" >> $config_mak ++;; ++esac ++ + for target in $target_list; do + + target_dir="$target" +Index: qemu/Makefile.target +@@ -303,7 +303,7 @@ + endif + + # USB layer +-VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o ++VL_OBJS+= usb.o usb-uhci.o usb-$(HOST_USB).o usb-hid.o + + ifeq ($(TARGET_BASE_ARCH), i386) + # Hardware support +Index: qemu/usb-stub.c +@@ -0,0 +1,11 @@ ++#include "vl.h" ++ ++void usb_host_info(void) ++{ ++ term_printf("USB host devices not supported\n"); ++} ++ ++USBDevice *usb_host_device_open(const char *devname) ++{ ++ return NULL; ++} +Index: qemu/usb-bsd.c +@@ -0,0 +1,592 @@ ++/* ++ * BSD host USB redirector ++ * ++ * Copyright (c) 2005 Lonnie Mendez ++ * Portions of code and concepts borrowed from ++ * usb-linux.c and libusb's bsd.c and are copyright their respective owners. ++ * ++ * 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. ++ */ ++ ++#include "vl.h" ++ ++/* usb.h declares these */ ++#undef USB_SPEED_HIGH ++#undef USB_SPEED_FULL ++#undef USB_SPEED_LOW ++ ++#include <sys/ioctl.h> ++#include <dev/usb/usb.h> ++#include <signal.h> ++ ++/* This value has maximum potential at 16. ++ * You should also set hw.usb.debug to gain ++ * more detailed view. ++ */ ++//#define DEBUG ++#define UGEN_DEBUG_LEVEL 0 ++ ++ ++typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, int speed); ++static int usb_host_find_device(int *pbus_num, int *paddr, ++ const char *devname); ++ ++typedef struct USBHostDevice { ++ USBDevice dev; ++ int ep_fd[USB_MAX_ENDPOINTS]; ++ int devfd; ++ char devpath[32]; ++} USBHostDevice; ++ ++ ++static int ensure_ep_open(USBHostDevice *dev, int ep, int mode) ++{ ++ char buf[32]; ++ int fd; ++ ++ /* Get the address for this endpoint */ ++ ep = UE_GET_ADDR(ep); ++ ++ if (dev->ep_fd[ep] < 0) { ++#if __FreeBSD__ ++ snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep); ++#else ++ snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep); ++#endif ++ /* Try to open it O_RDWR first for those devices which have in and out ++ * endpoints with the same address (eg 0x02 and 0x82) ++ */ ++ fd = open(buf, O_RDWR); ++ if (fd < 0 && errno == ENXIO) ++ fd = open(buf, mode); ++ if (fd < 0) { ++#ifdef DEBUG ++ printf("ensure_ep_open: failed to open device endpoint %s: %s\n", ++ buf, strerror(errno)); ++#endif ++ } ++ dev->ep_fd[ep] = fd; ++ } ++ ++ return dev->ep_fd[ep]; ++} ++ ++static void ensure_eps_closed(USBHostDevice *dev) ++{ ++ int epnum = 1; ++ ++ if (!dev) ++ return; ++ ++ while (epnum < USB_MAX_ENDPOINTS) { ++ if (dev->ep_fd[epnum] >= 0) { ++ close(dev->ep_fd[epnum]); ++ dev->ep_fd[epnum] = -1; ++ } ++ epnum++; ++ } ++} ++ ++static void usb_host_handle_reset(USBDevice *dev) ++{ ++#if 0 ++ USBHostDevice *s = (USBHostDevice *)dev; ++#endif ++} ++ ++/* XXX: ++ * -check device states against transfer requests ++ * and return appropriate response ++ */ ++static int usb_host_handle_control(USBDevice *dev, ++ int request, ++ int value, ++ int index, ++ int length, ++ uint8_t *data) ++{ ++ USBHostDevice *s = (USBHostDevice *)dev; ++ struct usb_ctl_request req; ++ struct usb_alt_interface aiface; ++ int ret, timeout = 50; ++ ++ if ((request >> 8) == UT_WRITE_DEVICE && ++ (request & 0xff) == UR_SET_ADDRESS) { ++ ++ /* specific SET_ADDRESS support */ ++ dev->addr = value; ++ return 0; ++ } else if ((request >> 8) == UT_WRITE_DEVICE && ++ (request & 0xff) == UR_SET_CONFIG) { ++ ++ ensure_eps_closed(s); /* can't do this without all eps closed */ ++ ++ ret = ioctl(s->devfd, USB_SET_CONFIG, &value); ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_control: failed to set configuration - %s\n", ++ strerror(errno)); ++#endif ++ return USB_RET_STALL; ++ } ++ ++ return 0; ++ } else if ((request >> 8) == UT_WRITE_INTERFACE && ++ (request & 0xff) == UR_SET_INTERFACE) { ++ ++ aiface.uai_interface_index = index; ++ aiface.uai_alt_no = value; ++ ++ ensure_eps_closed(s); /* can't do this without all eps closed */ ++ ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface); ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_control: failed to set alternate interface - %s\n", ++ strerror(errno)); ++#endif ++ return USB_RET_STALL; ++ } ++ ++ return 0; ++ } else { ++ req.ucr_request.bmRequestType = request >> 8; ++ req.ucr_request.bRequest = request & 0xff; ++ USETW(req.ucr_request.wValue, value); ++ USETW(req.ucr_request.wIndex, index); ++ USETW(req.ucr_request.wLength, length); ++ req.ucr_data = data; ++ req.ucr_flags = USBD_SHORT_XFER_OK; ++ ++ ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout); ++#if (__NetBSD__ || __OpenBSD__) ++ if (ret < 0 && errno != EINVAL) { ++#else ++ if (ret < 0) { ++#endif ++#ifdef DEBUG ++ printf("handle_control: setting timeout failed - %s\n", ++ strerror(errno)); ++#endif ++ } ++ ++ ret = ioctl(s->devfd, USB_DO_REQUEST, &req); ++ /* ugen returns EIO for usbd_do_request_ no matter what ++ * happens with the transfer */ ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_control: error after request - %s\n", ++ strerror(errno)); ++#endif ++ return USB_RET_NAK; // STALL ++ } else { ++ return req.ucr_actlen; ++ } ++ } ++} ++ ++static int usb_host_handle_data(USBDevice *dev, int pid, ++ uint8_t devep, ++ uint8_t *data, int len) ++{ ++ USBHostDevice *s = (USBHostDevice *)dev; ++ int ret, fd, mode; ++ int one = 1, shortpacket = 0, timeout = 50; ++ sigset_t new_mask, old_mask; ++ ++ /* protect data transfers from SIGALRM signal */ ++ sigemptyset(&new_mask); ++ sigaddset(&new_mask, SIGALRM); ++ sigprocmask(SIG_BLOCK, &new_mask, &old_mask); ++ ++ /* XXX: optimize and handle all data types by looking at the ++ config descriptor */ ++ if (pid == USB_TOKEN_IN) { ++ devep |= 0x80; ++ mode = O_RDONLY; ++ shortpacket = 1; ++ } else { ++ mode = O_WRONLY; ++ } ++ ++ fd = ensure_ep_open(s, devep, mode); ++ if (fd < 0) { ++ sigprocmask(SIG_SETMASK, &old_mask, NULL); ++ return USB_RET_NODEV; ++ } ++ ++ if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) { ++#ifdef DEBUG ++ printf("handle_data: failed to set timeout - %s\n", ++ strerror(errno)); ++#endif ++ } ++ ++ if (shortpacket) { ++ if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) { ++#ifdef DEBUG ++ printf("handle_data: failed to set short xfer mode - %s\n", ++ strerror(errno)); ++#endif ++ sigprocmask(SIG_SETMASK, &old_mask, NULL); ++ } ++ } ++ ++ if (pid == USB_TOKEN_IN) ++ ret = read(fd, data, len); ++ else ++ ret = write(fd, data, len); ++ ++ sigprocmask(SIG_SETMASK, &old_mask, NULL); ++ ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_data: error after %s data - %s\n", ++ pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno)); ++#endif ++ switch(errno) { ++ case ETIMEDOUT: ++ case EINTR: ++ return USB_RET_NAK; ++ default: ++ return USB_RET_STALL; ++ } ++ } else { ++ return ret; ++ } ++} ++ ++USBDevice *usb_host_device_open(const char *devname) ++{ ++ struct usb_device_info bus_info, dev_info; ++ USBHostDevice *dev; ++ char ctlpath[PATH_MAX + 1]; ++ char buspath[PATH_MAX + 1]; ++ int bfd, dfd, bus, address, i; ++ int ugendebug = UGEN_DEBUG_LEVEL; ++ ++ if (usb_host_find_device(&bus, &address, devname) < 0) ++ return NULL; ++ ++ snprintf(buspath, PATH_MAX, "/dev/usb%d", bus); ++ ++ bfd = open(buspath, O_RDWR); ++ if (bfd < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to open usb bus - %s\n", ++ strerror(errno)); ++#endif ++ return NULL; ++ } ++ ++ bus_info.udi_addr = address; ++ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to grab bus information - %s\n", ++ strerror(errno)); ++#endif ++ return NULL; ++ } ++ ++#if __FreeBSD__ ++ snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]); ++#else ++ snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]); ++#endif ++ ++ dfd = open(ctlpath, O_RDWR); ++ if (dfd < 0) { ++ dfd = open(ctlpath, O_RDONLY); ++ if (dfd < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to open usb device %s - %s\n", ++ ctlpath, strerror(errno)); ++#endif ++ } ++ } ++ ++ if (dfd >= 0) { ++ dev = qemu_mallocz(sizeof(USBHostDevice)); ++ if (!dev) ++ goto fail; ++ dev->devfd = dfd; ++ ++ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to grab device info - %s\n", ++ strerror(errno)); ++#endif ++ goto fail; ++ } ++ ++ if (dev_info.udi_speed == 1) ++ dev->dev.speed = USB_SPEED_LOW - 1; ++ else ++ dev->dev.speed = USB_SPEED_FULL - 1; ++ ++ dev->dev.handle_packet = usb_generic_handle_packet; ++ ++ dev->dev.handle_reset = usb_host_handle_reset; ++ dev->dev.handle_control = usb_host_handle_control; ++ dev->dev.handle_data = usb_host_handle_data; ++ ++ strcpy(dev->devpath, "/dev/"); ++ strcat(dev->devpath, dev_info.udi_devnames[0]); ++ ++ /* Mark the endpoints as not yet open */ ++ for (i = 0; i < USB_MAX_ENDPOINTS; i++) ++ dev->ep_fd[i] = -1; ++ ++ ioctl(dfd, USB_SETDEBUG, &ugendebug); ++ ++ return (USBDevice *)dev; ++ } ++ ++fail: ++ return NULL; ++} ++ ++void usb_host_device_close(USBDevice *opaque) ++{ ++ USBHostDevice *s = (USBHostDevice *)opaque; ++ int i; ++ ++ for (i = 0; i < USB_MAX_ENDPOINTS; i++) ++ if (s->ep_fd[i] >= 0) ++ close(s->ep_fd[i]); ++ ++ if (s->devfd < 0) ++ return; ++ ++ close(s->devfd); ++} ++ ++static int usb_host_scan(void *opaque, USBScanFunc *func) ++{ ++ struct usb_device_info bus_info; ++ struct usb_device_info dev_info; ++ uint16_t vendor_id, product_id, class_id, speed; ++ int bfd, dfd, bus, address; ++ char busbuf[20], devbuf[20], product_name[256]; ++ int ret = 0; ++ ++ for (bus = 0; bus < 10; bus++) { ++ ++ snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus); ++ bfd = open(busbuf, O_RDWR); ++ if (bfd < 0) ++ continue; ++ ++ for (address = 1; address < 127; address++) { ++ ++ bus_info.udi_addr = address; ++ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) ++ continue; ++ ++ /* only list devices that can be used by generic layer */ ++ if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0) ++ continue; ++ ++#if __FreeBSD__ ++ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]); ++#else ++ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]); ++#endif ++ ++ dfd = open(devbuf, O_RDONLY); ++ if (dfd < 0) { ++#ifdef DEBUG ++ printf("usb_host_scan: couldn't open device %s - %s\n", devbuf, ++ strerror(errno)); ++#endif ++ continue; ++ } ++ ++ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) ++ printf("usb_host_scan: couldn't get device information for %s - %s\n", ++ devbuf, strerror(errno)); ++ ++ // XXX: might need to fixup endianess of word values before copying over ++ ++ vendor_id = dev_info.udi_vendorNo; ++ product_id = dev_info.udi_productNo; ++ class_id = dev_info.udi_class; ++ speed = dev_info.udi_speed; ++ ++ if (strncmp(dev_info.udi_product, "product", 7) != 0) ++ strcpy(product_name, dev_info.udi_product); ++ else ++ product_name[0] = '\0'; ++ ++ ret = func(opaque, bus, address, class_id, vendor_id, ++ product_id, product_name, speed); ++ ++ close(dfd); ++ ++ if (ret) ++ goto the_end; ++ } ++ ++ close(bfd); ++ } ++ ++the_end: ++ return ret; ++} ++ ++typedef struct FindDeviceState { ++ int vendor_id; ++ int product_id; ++ int bus_num; ++ int addr; ++} FindDeviceState; ++ ++static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, ++ int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, int speed) ++{ ++ FindDeviceState *s = opaque; ++ if (vendor_id == s->vendor_id && ++ product_id == s->product_id) { ++ s->bus_num = bus_num; ++ s->addr = addr; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++ ++/* the syntax is : ++ 'bus.addr' (decimal numbers) or ++ 'vendor_id:product_id' (hexa numbers) */ ++static int usb_host_find_device(int *pbus_num, int *paddr, ++ const char *devname) ++{ ++ const char *p; ++ int ret; ++ FindDeviceState fs; ++ ++ p = strchr(devname, '.'); ++ if (p) { ++ *pbus_num = strtoul(devname, NULL, 0); ++ *paddr = strtoul(p + 1, NULL, 0); ++ return 0; ++ } ++ p = strchr(devname, ':'); ++ if (p) { ++ fs.vendor_id = strtoul(devname, NULL, 16); ++ fs.product_id = strtoul(p + 1, NULL, 16); ++ ret = usb_host_scan(&fs, usb_host_find_device_scan); ++ if (ret) { ++ *pbus_num = fs.bus_num; ++ *paddr = fs.addr; ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++/**********************/ ++/* USB host device info */ ++ ++struct usb_class_info { ++ int class; ++ const char *class_name; ++}; ++ ++static const struct usb_class_info usb_class_info[] = { ++ { USB_CLASS_AUDIO, "Audio"}, ++ { USB_CLASS_COMM, "Communication"}, ++ { USB_CLASS_HID, "HID"}, ++ { USB_CLASS_HUB, "Hub" }, ++ { USB_CLASS_PHYSICAL, "Physical" }, ++ { USB_CLASS_PRINTER, "Printer" }, ++ { USB_CLASS_MASS_STORAGE, "Storage" }, ++ { USB_CLASS_CDC_DATA, "Data" }, ++ { USB_CLASS_APP_SPEC, "Application Specific" }, ++ { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, ++ { USB_CLASS_STILL_IMAGE, "Still Image" }, ++ { USB_CLASS_CSCID, "Smart Card" }, ++ { USB_CLASS_CONTENT_SEC, "Content Security" }, ++ { -1, NULL } ++}; ++ ++static const char *usb_class_str(uint8_t class) ++{ ++ const struct usb_class_info *p; ++ for (p = usb_class_info; p->class != -1; p++) { ++ if (p->class == class) ++ break; ++ } ++ return p->class_name; ++} ++ ++void usb_info_device(int bus_num, int addr, int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, ++ int speed) ++{ ++ const char *class_str, *speed_str; ++ ++ switch(speed) { ++ case USB_SPEED_LOW: ++ speed_str = "1.5"; ++ break; ++ case USB_SPEED_FULL: ++ speed_str = "12"; ++ break; ++ case USB_SPEED_HIGH: ++ speed_str = "480"; ++ break; ++ default: ++ speed_str = "?"; ++ break; ++ } ++ ++ term_printf(" Device %d.%d, speed %s Mb/s\n", ++ bus_num, addr, speed_str); ++ class_str = usb_class_str(class_id); ++ if (class_str) ++ term_printf(" %s:", class_str); ++ else ++ term_printf(" Class %02x:", class_id); ++ term_printf(" USB device %04x:%04x", vendor_id, product_id); ++ if (product_name[0] != '\0') ++ term_printf(", %s", product_name); ++ term_printf("\n"); ++} ++ ++static int usb_host_info_device(void *opaque, int bus_num, int addr, ++ int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, ++ int speed) ++{ ++ usb_info_device(bus_num, addr, class_id, vendor_id, product_id, ++ product_name, speed); ++ return 0; ++} ++ ++void usb_host_info(void) ++{ ++ usb_host_scan(NULL, usb_host_info_device); ++} +Index: qemu/vl.c +@@ -2820,10 +2822,12 @@ + dev = usb_host_device_open(p); + if (!dev) + return -1; ++ dev->isproxied = 1; + } else if (!strcmp(devname, "mouse")) { + dev = usb_mouse_init(); + if (!dev) + return -1; ++ dev->isproxied = 0; + } else { + return -1; + } +@@ -2852,6 +2856,8 @@ + if (dev && dev->addr == addr) + break; + } ++ if (dev && dev->isproxied) ++ usb_host_device_close(dev); + if (i == MAX_VM_USB_PORTS) + return -1; + usb_attach(vm_usb_ports[i], NULL); +Index: qemu/hw/usb.h +@@ -135,6 +146,8 @@ + int setup_state; + int setup_len; + int setup_index; ++ ++ int isproxied; + }; + + /* USB port on which a device can be connected */ +@@ -157,8 +170,9 @@ + /* usb-uhci.c */ + void usb_uhci_init(PCIBus *bus, USBPort **usb_ports); + +-/* usb-linux.c */ ++/* host proxy functions */ + USBDevice *usb_host_device_open(const char *devname); ++void usb_host_device_close(USBDevice *dev); + void usb_host_info(void); + + /* usb-hid.c */ +Index: qemu/usb-linux.c +@@ -23,7 +23,6 @@ + */ + #include "vl.h" + +-#if defined(__linux__) + #include <dirent.h> + #include <sys/ioctl.h> + #include <linux/usbdevice_fs.h> +@@ -255,6 +254,14 @@ + return q - buf; + } + ++void usb_host_device_close(USBDevice *opaque) ++{ ++ USBHostDevice *s = (USBHostDevice *)opaque; ++ ++ if (s->fd >= 0) ++ close(s->fd); ++} ++ + static int usb_host_scan(void *opaque, USBScanFunc *func) + { + FILE *f; +@@ -468,18 +475,3 @@ + { + usb_host_scan(NULL, usb_host_info_device); + } +- +-#else +- +-void usb_host_info(void) +-{ +- term_printf("USB host devices not supported\n"); +-} +- +-/* XXX: modify configure to compile the right host driver */ +-USBDevice *usb_host_device_open(const char *devname) +-{ +- return NULL; +-} +- +-#endif diff --git a/emulators/qemu-devel/files/patch-dyngen.h b/emulators/qemu-devel/files/patch-dyngen.h new file mode 100644 index 000000000000..09ab311dfdf6 --- /dev/null +++ b/emulators/qemu-devel/files/patch-dyngen.h @@ -0,0 +1,11 @@ +# 1.9 +Index: qemu/dyngen.h +@@ -59,7 +59,7 @@ + { + unsigned long p; + +- p = start & ~(MIN_CACHE_LINE_SIZE - 1); ++ start &= ~(MIN_CACHE_LINE_SIZE - 1); + stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); + + for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { diff --git a/emulators/qemu-devel/files/patch-hw-ne2000.c b/emulators/qemu-devel/files/patch-hw-ne2000.c new file mode 100644 index 000000000000..eec4a3f31ccc --- /dev/null +++ b/emulators/qemu-devel/files/patch-hw-ne2000.c @@ -0,0 +1,44 @@ +# 1.19 +Index: qemu/hw/ne2000.c +@@ -648,6 +648,8 @@ + { + NE2000State* s=(NE2000State*)opaque; + ++ qemu_put_8s(f, &s->rxcr); ++ + qemu_put_8s(f, &s->cmd); + qemu_put_be32s(f, &s->start); + qemu_put_be32s(f, &s->stop); +@@ -672,8 +674,13 @@ + { + NE2000State* s=(NE2000State*)opaque; + +- if (version_id != 1) ++ if (version_id == 2) { ++ qemu_get_8s(f, &s->rxcr); ++ } else if (version_id == 1) { ++ s->rxcr = 0x0c; ++ } else { + return -EINVAL; ++ } + + qemu_get_8s(f, &s->cmd); + qemu_get_be32s(f, &s->start); +@@ -732,7 +739,7 @@ + s->macaddr[4], + s->macaddr[5]); + +- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); ++ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); + } + + /***********************************************************/ +@@ -803,7 +810,7 @@ + s->macaddr[5]); + + /* XXX: instance number ? */ +- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); ++ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); + register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, + &d->dev); + } diff --git a/emulators/qemu-devel/files/patch-hw-usb-uhci.c b/emulators/qemu-devel/files/patch-hw-usb-uhci.c new file mode 100644 index 000000000000..c5f3c36629bb --- /dev/null +++ b/emulators/qemu-devel/files/patch-hw-usb-uhci.c @@ -0,0 +1,28 @@ +# 1.6 +Index: qemu/hw/usb-uhci.c +@@ -153,6 +153,7 @@ + switch(addr) { + case 0x0c: + val = s->sof_timing; ++ break; + default: + val = 0xff; + break; +@@ -654,6 +655,7 @@ + pci_conf[0x0b] = 0x0c; + pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x3d] = 4; // interrupt pin 3 ++ pci_conf[0x60] = 0x10; // release number + + for(i = 0; i < NB_PORTS; i++) { + port = &s->ports[i]; +@@ -666,6 +668,8 @@ + + uhci_reset(s); + +- pci_register_io_region(&s->dev, 0, 0x20, ++ /* Use region 4 for consistency with real hardware. BSD guests seem ++ to rely on this. */ ++ pci_register_io_region(&s->dev, 4, 0x20, + PCI_ADDRESS_SPACE_IO, uhci_map); + } diff --git a/emulators/qemu-devel/files/patch-hw-usb.c b/emulators/qemu-devel/files/patch-hw-usb.c new file mode 100644 index 000000000000..50f6fc884a7a --- /dev/null +++ b/emulators/qemu-devel/files/patch-hw-usb.c @@ -0,0 +1,11 @@ +# 1.4 +Index: qemu/hw/usb.c +@@ -183,7 +183,7 @@ + + q = buf; + len = strlen(str); +- *q++ = 2 * len + 1; ++ *q++ = 2 * len + 2; + *q++ = 3; + for(i = 0; i < len; i++) { + *q++ = str[i]; diff --git a/emulators/qemu-devel/files/patch-sdl.c b/emulators/qemu-devel/files/patch-sdl.c new file mode 100644 index 000000000000..2b64583d0a0b --- /dev/null +++ b/emulators/qemu-devel/files/patch-sdl.c @@ -0,0 +1,29 @@ +# 1.24 +Index: qemu/sdl.c +@@ -404,6 +404,7 @@ + mod_state = (ev->key.keysym.mod & gui_grab_code); + if (!mod_state) { + if (gui_key_modifier_pressed) { ++ gui_key_modifier_pressed = 0; + if (gui_keysym == 0) { + /* exit/enter grab if pressing Ctrl-Alt */ + if (!gui_grab) +@@ -415,7 +416,6 @@ + reset_keys(); + break; + } +- gui_key_modifier_pressed = 0; + gui_keysym = 0; + } + } +@@ -456,8 +456,8 @@ + } + break; + case SDL_ACTIVEEVENT: +- if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 && +- !gui_fullscreen_initial_grab) { ++ if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS && ++ !ev->active.gain && !gui_fullscreen_initial_grab) { + sdl_grab_end(); + } + break; diff --git a/emulators/qemu-devel/files/patch-slirp-socket.c b/emulators/qemu-devel/files/patch-slirp-socket.c new file mode 100644 index 000000000000..91b030ae62c3 --- /dev/null +++ b/emulators/qemu-devel/files/patch-slirp-socket.c @@ -0,0 +1,18 @@ +# 1.6 +Index: qemu/slirp/socket.c +@@ -573,6 +573,7 @@ + addr.sin_port = port; + + if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || ++ (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || + (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || + (listen(s,1) < 0)) { + int tmperrno = errno; /* Don't clobber the real reason we failed */ +@@ -587,7 +588,6 @@ + #endif + return NULL; + } +- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); + setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + + getsockname(s,(struct sockaddr *)&addr,&addrlen); diff --git a/emulators/qemu-devel/files/patch-target-i386-translate.c b/emulators/qemu-devel/files/patch-target-i386-translate.c new file mode 100644 index 000000000000..5c9be22401f7 --- /dev/null +++ b/emulators/qemu-devel/files/patch-target-i386-translate.c @@ -0,0 +1,29 @@ +# 1.53 +Index: qemu/target-i386/translate.c +@@ -5803,14 +5803,24 @@ + op = (modrm >> 3) & 7; + switch(op) { + case 0: /* fxsave */ +- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) ++ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || ++ (s->flags & HF_EM_MASK)) + goto illegal_op; ++ if (s->flags & HF_TS_MASK) { ++ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); ++ break; ++ } + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); + gen_op_fxsave_A0((s->dflag == 2)); + break; + case 1: /* fxrstor */ +- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) ++ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || ++ (s->flags & HF_EM_MASK)) + goto illegal_op; ++ if (s->flags & HF_TS_MASK) { ++ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); ++ break; ++ } + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); + gen_op_fxrstor_A0((s->dflag == 2)); + break; diff --git a/emulators/qemu-devel/files/patch-usb-hchalt b/emulators/qemu-devel/files/patch-usb-hchalt new file mode 100644 index 000000000000..360104d5bb25 --- /dev/null +++ b/emulators/qemu-devel/files/patch-usb-hchalt @@ -0,0 +1,10 @@ +Index: qemu/hw/usb-uhci.c +@@ -527,6 +532,8 @@ + + if (!(s->cmd & UHCI_CMD_RS)) { + qemu_del_timer(s->frame_timer); ++ /* set hchalted bit in status - UHCI11D 2.1.2 */ ++ s->status |= UHCI_STS_HCHALTED; + return; + } + frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2); diff --git a/emulators/qemu-devel/files/patch-usb-hubfixups b/emulators/qemu-devel/files/patch-usb-hubfixups new file mode 100644 index 000000000000..17db3bd32806 --- /dev/null +++ b/emulators/qemu-devel/files/patch-usb-hubfixups @@ -0,0 +1,87 @@ +Index: qemu/hw/usb.c +@@ -330,9 +330,9 @@ + 0x0a, /* u16 wHubCharacteristics; */ + 0x00, /* (per-port OC, no power switching) */ + 0x01, /* u8 bPwrOn2pwrGood; 2ms */ +- 0x00, /* u8 bHubContrCurrent; 0 mA */ +- 0x00, /* u8 DeviceRemovable; *** 7 Ports max *** */ +- 0xff /* u8 PortPwrCtrlMask; *** 7 ports max *** */ ++ 0x00 /* u8 bHubContrCurrent; 0 mA */ ++ ++ /* DeviceRemovable and PortPwrCtrlMask patched in later */ + }; + + static void usb_hub_attach(USBPort *port1, USBDevice *dev) +@@ -391,6 +391,12 @@ + } + ret = 0; + break; ++ case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: ++ if (value == 0 && index != 0x81) { /* clear ep halt */ ++ goto fail; ++ } ++ ret = 0; ++ break; + case DeviceOutRequest | USB_REQ_SET_FEATURE: + if (value == USB_DEVICE_REMOTE_WAKEUP) { + dev->remote_wakeup = 1; +@@ -408,6 +414,11 @@ + case USB_DT_DEVICE: + memcpy(data, qemu_hub_dev_descriptor, + sizeof(qemu_hub_dev_descriptor)); ++ ++ /* status change endpoint size based on number ++ * of ports */ ++ data[22] = (s->nb_ports + 1 + 7) / 8; ++ + ret = sizeof(qemu_hub_dev_descriptor); + break; + case USB_DT_CONFIG: +@@ -558,11 +569,29 @@ + } + break; + case GetHubDescriptor: +- memcpy(data, qemu_hub_hub_descriptor, +- sizeof(qemu_hub_hub_descriptor)); +- data[2] = s->nb_ports; +- ret = sizeof(qemu_hub_hub_descriptor); +- break; ++ { ++ unsigned int n, limit, var_hub_size = 0; ++ memcpy(data, qemu_hub_hub_descriptor, ++ sizeof(qemu_hub_hub_descriptor)); ++ data[2] = s->nb_ports; ++ ++ /* fill DeviceRemovable bits */ ++ limit = ((s->nb_ports + 1 + 7) / 8) + 7; ++ for (n = 7; n < limit; n++) { ++ data[n] = 0x00; ++ var_hub_size++; ++ } ++ ++ /* fill PortPwrCtrlMask bits */ ++ limit = limit + ((s->nb_ports + 7) / 8); ++ for (;n < limit; n++) { ++ data[n] = 0xff; ++ var_hub_size++; ++ } ++ ++ ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size; ++ break; ++ } + default: + fail: + ret = USB_RET_STALL; +@@ -584,8 +613,11 @@ + unsigned int status; + int i, n; + n = (s->nb_ports + 1 + 7) / 8; +- if (n > len) ++ if (len == 1) { /* FreeBSD workaround */ ++ n = 1; ++ } else if (n > len) { + return USB_RET_BABBLE; ++ } + status = 0; + for(i = 0; i < s->nb_ports; i++) { + port = &s->ports[i]; diff --git a/emulators/qemu-devel/files/patch-vl.c-nographic b/emulators/qemu-devel/files/patch-vl.c-nographic new file mode 100644 index 000000000000..be2f002c4920 --- /dev/null +++ b/emulators/qemu-devel/files/patch-vl.c-nographic @@ -0,0 +1,9 @@ +Index: qemu/vl.c +@@ -4668,6 +4668,7 @@ + case QEMU_OPTION_nographic: + pstrcpy(monitor_device, sizeof(monitor_device), "stdio"); + pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio"); ++ pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null"); + nographic = 1; + break; + case QEMU_OPTION_kernel: diff --git a/emulators/qemu-devel/pkg-message b/emulators/qemu-devel/pkg-message index 4728b9171ccb..c335f5b3be17 100644 --- a/emulators/qemu-devel/pkg-message +++ b/emulators/qemu-devel/pkg-message @@ -33,4 +33,16 @@ in this message: http://docs.freebsd.org/cgi/mid.cgi?200510131428.21211.jkim (not included in the port since the used VIA VT86C926 PCI ID does not really match the emulated nic exactly, it just `happens' to work with 6.0-RC1's driver.) +- if you want to use usb devices connected to the host in the guest +(usb_add host:... monitor command) you need to make sure the host isn't +claiming them, e.g. for umass devices (like memory sticks or external +harddrives) make sure umass isn't in the kernel (you can then still load it +as a kld when needed), also unless you are running qemu as root you then +need to fix permissions for /dev/ugen* device nodes: if you are on 5.x or +later (devfs) put a rule in /etc/devfs.rules, activate it in /etc/rc.conf +and run /etc/rc.d/devfs restart. example devfs.rules: + [ugen_ruleset=20] + add path 'ugen*' mode 660 group operator +corresponding rc.conf line: + devfs_system_ruleset="ugen_ruleset" ==== diff --git a/emulators/qemu/Makefile b/emulators/qemu/Makefile index 61087cfb7139..28c88772c7a0 100644 --- a/emulators/qemu/Makefile +++ b/emulators/qemu/Makefile @@ -7,7 +7,7 @@ PORTNAME= qemu PORTVERSION= 0.8.0 -PORTREVISION= 3 +PORTREVISION= 4 CATEGORIES= emulators MASTER_SITES= http://www.qemu.org/:release \ http://people.fruitsalad.org/nox/qemu/:snapshot \ diff --git a/emulators/qemu/files/patch-bsdusb.patch b/emulators/qemu/files/patch-bsdusb.patch new file mode 100644 index 000000000000..9a90b930cbea --- /dev/null +++ b/emulators/qemu/files/patch-bsdusb.patch @@ -0,0 +1,741 @@ +Index: qemu/configure +@@ -122,6 +122,7 @@ + *) + oss="yes" + linux="yes" ++usb="linux" + if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then + kqemu="yes" + fi +@@ -131,6 +132,7 @@ + if [ "$bsd" = "yes" ] ; then + if [ ! "$darwin" = "yes" ] ; then + make="gmake" ++ usb="bsd" + fi + fi + +@@ -656,6 +675,19 @@ + echo "#define _BSD 1" >> $config_h + fi + ++# USB host support ++case "$usb" in ++linux) ++ echo "HOST_USB=linux" >> $conig_mak ++;; ++bsd) ++ echo "HOST_USB=bsd" >> $config_mak ++;; ++*) ++ echo "HOST_USB=stub" >> $config_mak ++;; ++esac ++ + for target in $target_list; do + + target_dir="$target" +Index: qemu/Makefile.target +@@ -303,7 +303,7 @@ + endif + + # USB layer +-VL_OBJS+= usb.o usb-uhci.o usb-linux.o usb-hid.o ++VL_OBJS+= usb.o usb-uhci.o usb-$(HOST_USB).o usb-hid.o + + ifeq ($(TARGET_BASE_ARCH), i386) + # Hardware support +Index: qemu/usb-stub.c +@@ -0,0 +1,11 @@ ++#include "vl.h" ++ ++void usb_host_info(void) ++{ ++ term_printf("USB host devices not supported\n"); ++} ++ ++USBDevice *usb_host_device_open(const char *devname) ++{ ++ return NULL; ++} +Index: qemu/usb-bsd.c +@@ -0,0 +1,592 @@ ++/* ++ * BSD host USB redirector ++ * ++ * Copyright (c) 2005 Lonnie Mendez ++ * Portions of code and concepts borrowed from ++ * usb-linux.c and libusb's bsd.c and are copyright their respective owners. ++ * ++ * 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. ++ */ ++ ++#include "vl.h" ++ ++/* usb.h declares these */ ++#undef USB_SPEED_HIGH ++#undef USB_SPEED_FULL ++#undef USB_SPEED_LOW ++ ++#include <sys/ioctl.h> ++#include <dev/usb/usb.h> ++#include <signal.h> ++ ++/* This value has maximum potential at 16. ++ * You should also set hw.usb.debug to gain ++ * more detailed view. ++ */ ++//#define DEBUG ++#define UGEN_DEBUG_LEVEL 0 ++ ++ ++typedef int USBScanFunc(void *opaque, int bus_num, int addr, int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, int speed); ++static int usb_host_find_device(int *pbus_num, int *paddr, ++ const char *devname); ++ ++typedef struct USBHostDevice { ++ USBDevice dev; ++ int ep_fd[USB_MAX_ENDPOINTS]; ++ int devfd; ++ char devpath[32]; ++} USBHostDevice; ++ ++ ++static int ensure_ep_open(USBHostDevice *dev, int ep, int mode) ++{ ++ char buf[32]; ++ int fd; ++ ++ /* Get the address for this endpoint */ ++ ep = UE_GET_ADDR(ep); ++ ++ if (dev->ep_fd[ep] < 0) { ++#if __FreeBSD__ ++ snprintf(buf, sizeof(buf) - 1, "%s.%d", dev->devpath, ep); ++#else ++ snprintf(buf, sizeof(buf) - 1, "%s.%02d", dev->devpath, ep); ++#endif ++ /* Try to open it O_RDWR first for those devices which have in and out ++ * endpoints with the same address (eg 0x02 and 0x82) ++ */ ++ fd = open(buf, O_RDWR); ++ if (fd < 0 && errno == ENXIO) ++ fd = open(buf, mode); ++ if (fd < 0) { ++#ifdef DEBUG ++ printf("ensure_ep_open: failed to open device endpoint %s: %s\n", ++ buf, strerror(errno)); ++#endif ++ } ++ dev->ep_fd[ep] = fd; ++ } ++ ++ return dev->ep_fd[ep]; ++} ++ ++static void ensure_eps_closed(USBHostDevice *dev) ++{ ++ int epnum = 1; ++ ++ if (!dev) ++ return; ++ ++ while (epnum < USB_MAX_ENDPOINTS) { ++ if (dev->ep_fd[epnum] >= 0) { ++ close(dev->ep_fd[epnum]); ++ dev->ep_fd[epnum] = -1; ++ } ++ epnum++; ++ } ++} ++ ++static void usb_host_handle_reset(USBDevice *dev) ++{ ++#if 0 ++ USBHostDevice *s = (USBHostDevice *)dev; ++#endif ++} ++ ++/* XXX: ++ * -check device states against transfer requests ++ * and return appropriate response ++ */ ++static int usb_host_handle_control(USBDevice *dev, ++ int request, ++ int value, ++ int index, ++ int length, ++ uint8_t *data) ++{ ++ USBHostDevice *s = (USBHostDevice *)dev; ++ struct usb_ctl_request req; ++ struct usb_alt_interface aiface; ++ int ret, timeout = 50; ++ ++ if ((request >> 8) == UT_WRITE_DEVICE && ++ (request & 0xff) == UR_SET_ADDRESS) { ++ ++ /* specific SET_ADDRESS support */ ++ dev->addr = value; ++ return 0; ++ } else if ((request >> 8) == UT_WRITE_DEVICE && ++ (request & 0xff) == UR_SET_CONFIG) { ++ ++ ensure_eps_closed(s); /* can't do this without all eps closed */ ++ ++ ret = ioctl(s->devfd, USB_SET_CONFIG, &value); ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_control: failed to set configuration - %s\n", ++ strerror(errno)); ++#endif ++ return USB_RET_STALL; ++ } ++ ++ return 0; ++ } else if ((request >> 8) == UT_WRITE_INTERFACE && ++ (request & 0xff) == UR_SET_INTERFACE) { ++ ++ aiface.uai_interface_index = index; ++ aiface.uai_alt_no = value; ++ ++ ensure_eps_closed(s); /* can't do this without all eps closed */ ++ ret = ioctl(s->devfd, USB_SET_ALTINTERFACE, &aiface); ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_control: failed to set alternate interface - %s\n", ++ strerror(errno)); ++#endif ++ return USB_RET_STALL; ++ } ++ ++ return 0; ++ } else { ++ req.ucr_request.bmRequestType = request >> 8; ++ req.ucr_request.bRequest = request & 0xff; ++ USETW(req.ucr_request.wValue, value); ++ USETW(req.ucr_request.wIndex, index); ++ USETW(req.ucr_request.wLength, length); ++ req.ucr_data = data; ++ req.ucr_flags = USBD_SHORT_XFER_OK; ++ ++ ret = ioctl(s->devfd, USB_SET_TIMEOUT, &timeout); ++#if (__NetBSD__ || __OpenBSD__) ++ if (ret < 0 && errno != EINVAL) { ++#else ++ if (ret < 0) { ++#endif ++#ifdef DEBUG ++ printf("handle_control: setting timeout failed - %s\n", ++ strerror(errno)); ++#endif ++ } ++ ++ ret = ioctl(s->devfd, USB_DO_REQUEST, &req); ++ /* ugen returns EIO for usbd_do_request_ no matter what ++ * happens with the transfer */ ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_control: error after request - %s\n", ++ strerror(errno)); ++#endif ++ return USB_RET_NAK; // STALL ++ } else { ++ return req.ucr_actlen; ++ } ++ } ++} ++ ++static int usb_host_handle_data(USBDevice *dev, int pid, ++ uint8_t devep, ++ uint8_t *data, int len) ++{ ++ USBHostDevice *s = (USBHostDevice *)dev; ++ int ret, fd, mode; ++ int one = 1, shortpacket = 0, timeout = 50; ++ sigset_t new_mask, old_mask; ++ ++ /* protect data transfers from SIGALRM signal */ ++ sigemptyset(&new_mask); ++ sigaddset(&new_mask, SIGALRM); ++ sigprocmask(SIG_BLOCK, &new_mask, &old_mask); ++ ++ /* XXX: optimize and handle all data types by looking at the ++ config descriptor */ ++ if (pid == USB_TOKEN_IN) { ++ devep |= 0x80; ++ mode = O_RDONLY; ++ shortpacket = 1; ++ } else { ++ mode = O_WRONLY; ++ } ++ ++ fd = ensure_ep_open(s, devep, mode); ++ if (fd < 0) { ++ sigprocmask(SIG_SETMASK, &old_mask, NULL); ++ return USB_RET_NODEV; ++ } ++ ++ if (ioctl(fd, USB_SET_TIMEOUT, &timeout) < 0) { ++#ifdef DEBUG ++ printf("handle_data: failed to set timeout - %s\n", ++ strerror(errno)); ++#endif ++ } ++ ++ if (shortpacket) { ++ if (ioctl(fd, USB_SET_SHORT_XFER, &one) < 0) { ++#ifdef DEBUG ++ printf("handle_data: failed to set short xfer mode - %s\n", ++ strerror(errno)); ++#endif ++ sigprocmask(SIG_SETMASK, &old_mask, NULL); ++ } ++ } ++ ++ if (pid == USB_TOKEN_IN) ++ ret = read(fd, data, len); ++ else ++ ret = write(fd, data, len); ++ ++ sigprocmask(SIG_SETMASK, &old_mask, NULL); ++ ++ if (ret < 0) { ++#ifdef DEBUG ++ printf("handle_data: error after %s data - %s\n", ++ pid == USB_TOKEN_IN ? "reading" : "writing", strerror(errno)); ++#endif ++ switch(errno) { ++ case ETIMEDOUT: ++ case EINTR: ++ return USB_RET_NAK; ++ default: ++ return USB_RET_STALL; ++ } ++ } else { ++ return ret; ++ } ++} ++ ++USBDevice *usb_host_device_open(const char *devname) ++{ ++ struct usb_device_info bus_info, dev_info; ++ USBHostDevice *dev; ++ char ctlpath[PATH_MAX + 1]; ++ char buspath[PATH_MAX + 1]; ++ int bfd, dfd, bus, address, i; ++ int ugendebug = UGEN_DEBUG_LEVEL; ++ ++ if (usb_host_find_device(&bus, &address, devname) < 0) ++ return NULL; ++ ++ snprintf(buspath, PATH_MAX, "/dev/usb%d", bus); ++ ++ bfd = open(buspath, O_RDWR); ++ if (bfd < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to open usb bus - %s\n", ++ strerror(errno)); ++#endif ++ return NULL; ++ } ++ ++ bus_info.udi_addr = address; ++ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to grab bus information - %s\n", ++ strerror(errno)); ++#endif ++ return NULL; ++ } ++ ++#if __FreeBSD__ ++ snprintf(ctlpath, PATH_MAX, "/dev/%s", bus_info.udi_devnames[0]); ++#else ++ snprintf(ctlpath, PATH_MAX, "/dev/%s.00", bus_info.udi_devnames[0]); ++#endif ++ ++ dfd = open(ctlpath, O_RDWR); ++ if (dfd < 0) { ++ dfd = open(ctlpath, O_RDONLY); ++ if (dfd < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to open usb device %s - %s\n", ++ ctlpath, strerror(errno)); ++#endif ++ } ++ } ++ ++ if (dfd >= 0) { ++ dev = qemu_mallocz(sizeof(USBHostDevice)); ++ if (!dev) ++ goto fail; ++ dev->devfd = dfd; ++ ++ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) { ++#ifdef DEBUG ++ printf("usb_host_device_open: failed to grab device info - %s\n", ++ strerror(errno)); ++#endif ++ goto fail; ++ } ++ ++ if (dev_info.udi_speed == 1) ++ dev->dev.speed = USB_SPEED_LOW - 1; ++ else ++ dev->dev.speed = USB_SPEED_FULL - 1; ++ ++ dev->dev.handle_packet = usb_generic_handle_packet; ++ ++ dev->dev.handle_reset = usb_host_handle_reset; ++ dev->dev.handle_control = usb_host_handle_control; ++ dev->dev.handle_data = usb_host_handle_data; ++ ++ strcpy(dev->devpath, "/dev/"); ++ strcat(dev->devpath, dev_info.udi_devnames[0]); ++ ++ /* Mark the endpoints as not yet open */ ++ for (i = 0; i < USB_MAX_ENDPOINTS; i++) ++ dev->ep_fd[i] = -1; ++ ++ ioctl(dfd, USB_SETDEBUG, &ugendebug); ++ ++ return (USBDevice *)dev; ++ } ++ ++fail: ++ return NULL; ++} ++ ++void usb_host_device_close(USBDevice *opaque) ++{ ++ USBHostDevice *s = (USBHostDevice *)opaque; ++ int i; ++ ++ for (i = 0; i < USB_MAX_ENDPOINTS; i++) ++ if (s->ep_fd[i] >= 0) ++ close(s->ep_fd[i]); ++ ++ if (s->devfd < 0) ++ return; ++ ++ close(s->devfd); ++} ++ ++static int usb_host_scan(void *opaque, USBScanFunc *func) ++{ ++ struct usb_device_info bus_info; ++ struct usb_device_info dev_info; ++ uint16_t vendor_id, product_id, class_id, speed; ++ int bfd, dfd, bus, address; ++ char busbuf[20], devbuf[20], product_name[256]; ++ int ret = 0; ++ ++ for (bus = 0; bus < 10; bus++) { ++ ++ snprintf(busbuf, sizeof(busbuf) - 1, "/dev/usb%d", bus); ++ bfd = open(busbuf, O_RDWR); ++ if (bfd < 0) ++ continue; ++ ++ for (address = 1; address < 127; address++) { ++ ++ bus_info.udi_addr = address; ++ if (ioctl(bfd, USB_DEVICEINFO, &bus_info) < 0) ++ continue; ++ ++ /* only list devices that can be used by generic layer */ ++ if (strncmp(bus_info.udi_devnames[0], "ugen", 4) != 0) ++ continue; ++ ++#if __FreeBSD__ ++ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s", bus_info.udi_devnames[0]); ++#else ++ snprintf(devbuf, sizeof(devbuf) - 1, "/dev/%s.00", bus_info.udi_devnames[0]); ++#endif ++ ++ dfd = open(devbuf, O_RDONLY); ++ if (dfd < 0) { ++#ifdef DEBUG ++ printf("usb_host_scan: couldn't open device %s - %s\n", devbuf, ++ strerror(errno)); ++#endif ++ continue; ++ } ++ ++ if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) ++ printf("usb_host_scan: couldn't get device information for %s - %s\n", ++ devbuf, strerror(errno)); ++ ++ // XXX: might need to fixup endianess of word values before copying over ++ ++ vendor_id = dev_info.udi_vendorNo; ++ product_id = dev_info.udi_productNo; ++ class_id = dev_info.udi_class; ++ speed = dev_info.udi_speed; ++ ++ if (strncmp(dev_info.udi_product, "product", 7) != 0) ++ strcpy(product_name, dev_info.udi_product); ++ else ++ product_name[0] = '\0'; ++ ++ ret = func(opaque, bus, address, class_id, vendor_id, ++ product_id, product_name, speed); ++ ++ close(dfd); ++ ++ if (ret) ++ goto the_end; ++ } ++ ++ close(bfd); ++ } ++ ++the_end: ++ return ret; ++} ++ ++typedef struct FindDeviceState { ++ int vendor_id; ++ int product_id; ++ int bus_num; ++ int addr; ++} FindDeviceState; ++ ++static int usb_host_find_device_scan(void *opaque, int bus_num, int addr, ++ int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, int speed) ++{ ++ FindDeviceState *s = opaque; ++ if (vendor_id == s->vendor_id && ++ product_id == s->product_id) { ++ s->bus_num = bus_num; ++ s->addr = addr; ++ return 1; ++ } else { ++ return 0; ++ } ++} ++ ++ ++/* the syntax is : ++ 'bus.addr' (decimal numbers) or ++ 'vendor_id:product_id' (hexa numbers) */ ++static int usb_host_find_device(int *pbus_num, int *paddr, ++ const char *devname) ++{ ++ const char *p; ++ int ret; ++ FindDeviceState fs; ++ ++ p = strchr(devname, '.'); ++ if (p) { ++ *pbus_num = strtoul(devname, NULL, 0); ++ *paddr = strtoul(p + 1, NULL, 0); ++ return 0; ++ } ++ p = strchr(devname, ':'); ++ if (p) { ++ fs.vendor_id = strtoul(devname, NULL, 16); ++ fs.product_id = strtoul(p + 1, NULL, 16); ++ ret = usb_host_scan(&fs, usb_host_find_device_scan); ++ if (ret) { ++ *pbus_num = fs.bus_num; ++ *paddr = fs.addr; ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++/**********************/ ++/* USB host device info */ ++ ++struct usb_class_info { ++ int class; ++ const char *class_name; ++}; ++ ++static const struct usb_class_info usb_class_info[] = { ++ { USB_CLASS_AUDIO, "Audio"}, ++ { USB_CLASS_COMM, "Communication"}, ++ { USB_CLASS_HID, "HID"}, ++ { USB_CLASS_HUB, "Hub" }, ++ { USB_CLASS_PHYSICAL, "Physical" }, ++ { USB_CLASS_PRINTER, "Printer" }, ++ { USB_CLASS_MASS_STORAGE, "Storage" }, ++ { USB_CLASS_CDC_DATA, "Data" }, ++ { USB_CLASS_APP_SPEC, "Application Specific" }, ++ { USB_CLASS_VENDOR_SPEC, "Vendor Specific" }, ++ { USB_CLASS_STILL_IMAGE, "Still Image" }, ++ { USB_CLASS_CSCID, "Smart Card" }, ++ { USB_CLASS_CONTENT_SEC, "Content Security" }, ++ { -1, NULL } ++}; ++ ++static const char *usb_class_str(uint8_t class) ++{ ++ const struct usb_class_info *p; ++ for (p = usb_class_info; p->class != -1; p++) { ++ if (p->class == class) ++ break; ++ } ++ return p->class_name; ++} ++ ++void usb_info_device(int bus_num, int addr, int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, ++ int speed) ++{ ++ const char *class_str, *speed_str; ++ ++ switch(speed) { ++ case USB_SPEED_LOW: ++ speed_str = "1.5"; ++ break; ++ case USB_SPEED_FULL: ++ speed_str = "12"; ++ break; ++ case USB_SPEED_HIGH: ++ speed_str = "480"; ++ break; ++ default: ++ speed_str = "?"; ++ break; ++ } ++ ++ term_printf(" Device %d.%d, speed %s Mb/s\n", ++ bus_num, addr, speed_str); ++ class_str = usb_class_str(class_id); ++ if (class_str) ++ term_printf(" %s:", class_str); ++ else ++ term_printf(" Class %02x:", class_id); ++ term_printf(" USB device %04x:%04x", vendor_id, product_id); ++ if (product_name[0] != '\0') ++ term_printf(", %s", product_name); ++ term_printf("\n"); ++} ++ ++static int usb_host_info_device(void *opaque, int bus_num, int addr, ++ int class_id, ++ int vendor_id, int product_id, ++ const char *product_name, ++ int speed) ++{ ++ usb_info_device(bus_num, addr, class_id, vendor_id, product_id, ++ product_name, speed); ++ return 0; ++} ++ ++void usb_host_info(void) ++{ ++ usb_host_scan(NULL, usb_host_info_device); ++} +Index: qemu/vl.c +@@ -2820,10 +2822,12 @@ + dev = usb_host_device_open(p); + if (!dev) + return -1; ++ dev->isproxied = 1; + } else if (!strcmp(devname, "mouse")) { + dev = usb_mouse_init(); + if (!dev) + return -1; ++ dev->isproxied = 0; + } else { + return -1; + } +@@ -2852,6 +2856,8 @@ + if (dev && dev->addr == addr) + break; + } ++ if (dev && dev->isproxied) ++ usb_host_device_close(dev); + if (i == MAX_VM_USB_PORTS) + return -1; + usb_attach(vm_usb_ports[i], NULL); +Index: qemu/hw/usb.h +@@ -135,6 +146,8 @@ + int setup_state; + int setup_len; + int setup_index; ++ ++ int isproxied; + }; + + /* USB port on which a device can be connected */ +@@ -157,8 +170,9 @@ + /* usb-uhci.c */ + void usb_uhci_init(PCIBus *bus, USBPort **usb_ports); + +-/* usb-linux.c */ ++/* host proxy functions */ + USBDevice *usb_host_device_open(const char *devname); ++void usb_host_device_close(USBDevice *dev); + void usb_host_info(void); + + /* usb-hid.c */ +Index: qemu/usb-linux.c +@@ -23,7 +23,6 @@ + */ + #include "vl.h" + +-#if defined(__linux__) + #include <dirent.h> + #include <sys/ioctl.h> + #include <linux/usbdevice_fs.h> +@@ -255,6 +254,14 @@ + return q - buf; + } + ++void usb_host_device_close(USBDevice *opaque) ++{ ++ USBHostDevice *s = (USBHostDevice *)opaque; ++ ++ if (s->fd >= 0) ++ close(s->fd); ++} ++ + static int usb_host_scan(void *opaque, USBScanFunc *func) + { + FILE *f; +@@ -468,18 +475,3 @@ + { + usb_host_scan(NULL, usb_host_info_device); + } +- +-#else +- +-void usb_host_info(void) +-{ +- term_printf("USB host devices not supported\n"); +-} +- +-/* XXX: modify configure to compile the right host driver */ +-USBDevice *usb_host_device_open(const char *devname) +-{ +- return NULL; +-} +- +-#endif diff --git a/emulators/qemu/files/patch-dyngen.h b/emulators/qemu/files/patch-dyngen.h new file mode 100644 index 000000000000..09ab311dfdf6 --- /dev/null +++ b/emulators/qemu/files/patch-dyngen.h @@ -0,0 +1,11 @@ +# 1.9 +Index: qemu/dyngen.h +@@ -59,7 +59,7 @@ + { + unsigned long p; + +- p = start & ~(MIN_CACHE_LINE_SIZE - 1); ++ start &= ~(MIN_CACHE_LINE_SIZE - 1); + stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1); + + for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) { diff --git a/emulators/qemu/files/patch-hw-ne2000.c b/emulators/qemu/files/patch-hw-ne2000.c new file mode 100644 index 000000000000..eec4a3f31ccc --- /dev/null +++ b/emulators/qemu/files/patch-hw-ne2000.c @@ -0,0 +1,44 @@ +# 1.19 +Index: qemu/hw/ne2000.c +@@ -648,6 +648,8 @@ + { + NE2000State* s=(NE2000State*)opaque; + ++ qemu_put_8s(f, &s->rxcr); ++ + qemu_put_8s(f, &s->cmd); + qemu_put_be32s(f, &s->start); + qemu_put_be32s(f, &s->stop); +@@ -672,8 +674,13 @@ + { + NE2000State* s=(NE2000State*)opaque; + +- if (version_id != 1) ++ if (version_id == 2) { ++ qemu_get_8s(f, &s->rxcr); ++ } else if (version_id == 1) { ++ s->rxcr = 0x0c; ++ } else { + return -EINVAL; ++ } + + qemu_get_8s(f, &s->cmd); + qemu_get_be32s(f, &s->start); +@@ -732,7 +739,7 @@ + s->macaddr[4], + s->macaddr[5]); + +- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); ++ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); + } + + /***********************************************************/ +@@ -803,7 +810,7 @@ + s->macaddr[5]); + + /* XXX: instance number ? */ +- register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); ++ register_savevm("ne2000", 0, 2, ne2000_save, ne2000_load, s); + register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, + &d->dev); + } diff --git a/emulators/qemu/files/patch-hw-usb-uhci.c b/emulators/qemu/files/patch-hw-usb-uhci.c new file mode 100644 index 000000000000..c5f3c36629bb --- /dev/null +++ b/emulators/qemu/files/patch-hw-usb-uhci.c @@ -0,0 +1,28 @@ +# 1.6 +Index: qemu/hw/usb-uhci.c +@@ -153,6 +153,7 @@ + switch(addr) { + case 0x0c: + val = s->sof_timing; ++ break; + default: + val = 0xff; + break; +@@ -654,6 +655,7 @@ + pci_conf[0x0b] = 0x0c; + pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x3d] = 4; // interrupt pin 3 ++ pci_conf[0x60] = 0x10; // release number + + for(i = 0; i < NB_PORTS; i++) { + port = &s->ports[i]; +@@ -666,6 +668,8 @@ + + uhci_reset(s); + +- pci_register_io_region(&s->dev, 0, 0x20, ++ /* Use region 4 for consistency with real hardware. BSD guests seem ++ to rely on this. */ ++ pci_register_io_region(&s->dev, 4, 0x20, + PCI_ADDRESS_SPACE_IO, uhci_map); + } diff --git a/emulators/qemu/files/patch-hw-usb.c b/emulators/qemu/files/patch-hw-usb.c new file mode 100644 index 000000000000..50f6fc884a7a --- /dev/null +++ b/emulators/qemu/files/patch-hw-usb.c @@ -0,0 +1,11 @@ +# 1.4 +Index: qemu/hw/usb.c +@@ -183,7 +183,7 @@ + + q = buf; + len = strlen(str); +- *q++ = 2 * len + 1; ++ *q++ = 2 * len + 2; + *q++ = 3; + for(i = 0; i < len; i++) { + *q++ = str[i]; diff --git a/emulators/qemu/files/patch-sdl.c b/emulators/qemu/files/patch-sdl.c new file mode 100644 index 000000000000..2b64583d0a0b --- /dev/null +++ b/emulators/qemu/files/patch-sdl.c @@ -0,0 +1,29 @@ +# 1.24 +Index: qemu/sdl.c +@@ -404,6 +404,7 @@ + mod_state = (ev->key.keysym.mod & gui_grab_code); + if (!mod_state) { + if (gui_key_modifier_pressed) { ++ gui_key_modifier_pressed = 0; + if (gui_keysym == 0) { + /* exit/enter grab if pressing Ctrl-Alt */ + if (!gui_grab) +@@ -415,7 +416,6 @@ + reset_keys(); + break; + } +- gui_key_modifier_pressed = 0; + gui_keysym = 0; + } + } +@@ -456,8 +456,8 @@ + } + break; + case SDL_ACTIVEEVENT: +- if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 && +- !gui_fullscreen_initial_grab) { ++ if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS && ++ !ev->active.gain && !gui_fullscreen_initial_grab) { + sdl_grab_end(); + } + break; diff --git a/emulators/qemu/files/patch-slirp-socket.c b/emulators/qemu/files/patch-slirp-socket.c new file mode 100644 index 000000000000..91b030ae62c3 --- /dev/null +++ b/emulators/qemu/files/patch-slirp-socket.c @@ -0,0 +1,18 @@ +# 1.6 +Index: qemu/slirp/socket.c +@@ -573,6 +573,7 @@ + addr.sin_port = port; + + if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || ++ (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || + (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || + (listen(s,1) < 0)) { + int tmperrno = errno; /* Don't clobber the real reason we failed */ +@@ -587,7 +588,6 @@ + #endif + return NULL; + } +- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); + setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); + + getsockname(s,(struct sockaddr *)&addr,&addrlen); diff --git a/emulators/qemu/files/patch-target-i386-translate.c b/emulators/qemu/files/patch-target-i386-translate.c new file mode 100644 index 000000000000..5c9be22401f7 --- /dev/null +++ b/emulators/qemu/files/patch-target-i386-translate.c @@ -0,0 +1,29 @@ +# 1.53 +Index: qemu/target-i386/translate.c +@@ -5803,14 +5803,24 @@ + op = (modrm >> 3) & 7; + switch(op) { + case 0: /* fxsave */ +- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) ++ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || ++ (s->flags & HF_EM_MASK)) + goto illegal_op; ++ if (s->flags & HF_TS_MASK) { ++ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); ++ break; ++ } + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); + gen_op_fxsave_A0((s->dflag == 2)); + break; + case 1: /* fxrstor */ +- if (mod == 3 || !(s->cpuid_features & CPUID_FXSR)) ++ if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) || ++ (s->flags & HF_EM_MASK)) + goto illegal_op; ++ if (s->flags & HF_TS_MASK) { ++ gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); ++ break; ++ } + gen_lea_modrm(s, modrm, ®_addr, &offset_addr); + gen_op_fxrstor_A0((s->dflag == 2)); + break; diff --git a/emulators/qemu/files/patch-usb-hchalt b/emulators/qemu/files/patch-usb-hchalt new file mode 100644 index 000000000000..360104d5bb25 --- /dev/null +++ b/emulators/qemu/files/patch-usb-hchalt @@ -0,0 +1,10 @@ +Index: qemu/hw/usb-uhci.c +@@ -527,6 +532,8 @@ + + if (!(s->cmd & UHCI_CMD_RS)) { + qemu_del_timer(s->frame_timer); ++ /* set hchalted bit in status - UHCI11D 2.1.2 */ ++ s->status |= UHCI_STS_HCHALTED; + return; + } + frame_addr = s->fl_base_addr + ((s->frnum & 0x3ff) << 2); diff --git a/emulators/qemu/files/patch-usb-hubfixups b/emulators/qemu/files/patch-usb-hubfixups new file mode 100644 index 000000000000..17db3bd32806 --- /dev/null +++ b/emulators/qemu/files/patch-usb-hubfixups @@ -0,0 +1,87 @@ +Index: qemu/hw/usb.c +@@ -330,9 +330,9 @@ + 0x0a, /* u16 wHubCharacteristics; */ + 0x00, /* (per-port OC, no power switching) */ + 0x01, /* u8 bPwrOn2pwrGood; 2ms */ +- 0x00, /* u8 bHubContrCurrent; 0 mA */ +- 0x00, /* u8 DeviceRemovable; *** 7 Ports max *** */ +- 0xff /* u8 PortPwrCtrlMask; *** 7 ports max *** */ ++ 0x00 /* u8 bHubContrCurrent; 0 mA */ ++ ++ /* DeviceRemovable and PortPwrCtrlMask patched in later */ + }; + + static void usb_hub_attach(USBPort *port1, USBDevice *dev) +@@ -391,6 +391,12 @@ + } + ret = 0; + break; ++ case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: ++ if (value == 0 && index != 0x81) { /* clear ep halt */ ++ goto fail; ++ } ++ ret = 0; ++ break; + case DeviceOutRequest | USB_REQ_SET_FEATURE: + if (value == USB_DEVICE_REMOTE_WAKEUP) { + dev->remote_wakeup = 1; +@@ -408,6 +414,11 @@ + case USB_DT_DEVICE: + memcpy(data, qemu_hub_dev_descriptor, + sizeof(qemu_hub_dev_descriptor)); ++ ++ /* status change endpoint size based on number ++ * of ports */ ++ data[22] = (s->nb_ports + 1 + 7) / 8; ++ + ret = sizeof(qemu_hub_dev_descriptor); + break; + case USB_DT_CONFIG: +@@ -558,11 +569,29 @@ + } + break; + case GetHubDescriptor: +- memcpy(data, qemu_hub_hub_descriptor, +- sizeof(qemu_hub_hub_descriptor)); +- data[2] = s->nb_ports; +- ret = sizeof(qemu_hub_hub_descriptor); +- break; ++ { ++ unsigned int n, limit, var_hub_size = 0; ++ memcpy(data, qemu_hub_hub_descriptor, ++ sizeof(qemu_hub_hub_descriptor)); ++ data[2] = s->nb_ports; ++ ++ /* fill DeviceRemovable bits */ ++ limit = ((s->nb_ports + 1 + 7) / 8) + 7; ++ for (n = 7; n < limit; n++) { ++ data[n] = 0x00; ++ var_hub_size++; ++ } ++ ++ /* fill PortPwrCtrlMask bits */ ++ limit = limit + ((s->nb_ports + 7) / 8); ++ for (;n < limit; n++) { ++ data[n] = 0xff; ++ var_hub_size++; ++ } ++ ++ ret = sizeof(qemu_hub_hub_descriptor) + var_hub_size; ++ break; ++ } + default: + fail: + ret = USB_RET_STALL; +@@ -584,8 +613,11 @@ + unsigned int status; + int i, n; + n = (s->nb_ports + 1 + 7) / 8; +- if (n > len) ++ if (len == 1) { /* FreeBSD workaround */ ++ n = 1; ++ } else if (n > len) { + return USB_RET_BABBLE; ++ } + status = 0; + for(i = 0; i < s->nb_ports; i++) { + port = &s->ports[i]; diff --git a/emulators/qemu/files/patch-vl.c-nographic b/emulators/qemu/files/patch-vl.c-nographic new file mode 100644 index 000000000000..be2f002c4920 --- /dev/null +++ b/emulators/qemu/files/patch-vl.c-nographic @@ -0,0 +1,9 @@ +Index: qemu/vl.c +@@ -4668,6 +4668,7 @@ + case QEMU_OPTION_nographic: + pstrcpy(monitor_device, sizeof(monitor_device), "stdio"); + pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio"); ++ pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "null"); + nographic = 1; + break; + case QEMU_OPTION_kernel: diff --git a/emulators/qemu/pkg-message b/emulators/qemu/pkg-message index 4728b9171ccb..c335f5b3be17 100644 --- a/emulators/qemu/pkg-message +++ b/emulators/qemu/pkg-message @@ -33,4 +33,16 @@ in this message: http://docs.freebsd.org/cgi/mid.cgi?200510131428.21211.jkim (not included in the port since the used VIA VT86C926 PCI ID does not really match the emulated nic exactly, it just `happens' to work with 6.0-RC1's driver.) +- if you want to use usb devices connected to the host in the guest +(usb_add host:... monitor command) you need to make sure the host isn't +claiming them, e.g. for umass devices (like memory sticks or external +harddrives) make sure umass isn't in the kernel (you can then still load it +as a kld when needed), also unless you are running qemu as root you then +need to fix permissions for /dev/ugen* device nodes: if you are on 5.x or +later (devfs) put a rule in /etc/devfs.rules, activate it in /etc/rc.conf +and run /etc/rc.d/devfs restart. example devfs.rules: + [ugen_ruleset=20] + add path 'ugen*' mode 660 group operator +corresponding rc.conf line: + devfs_system_ruleset="ugen_ruleset" ==== |