OBS User unknown 2007-10-02 23:09:38 +00:00 committed by Git OBS Bridge
parent 47490e3dd4
commit 9116357c8b
12 changed files with 2948 additions and 5 deletions

20
qemu-cvs-cache-info.patch Normal file
View File

@ -0,0 +1,20 @@
Index: target-i386/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-i386/helper.c,v
retrieving revision 1.84
diff -u -r1.84 helper.c
--- target-i386/helper.c 26 Jun 2007 08:35:18 -0000 1.84
+++ target-i386/helper.c 8 Sep 2007 16:07:23 -0000
@@ -1657,10 +1657,10 @@
break;
case 2:
/* cache info: needed for Pentium Pro compatibility */
- EAX = 0x410601;
+ EAX = 1;
EBX = 0;
ECX = 0;
- EDX = 0;
+ EDX = 0x2c307d;
break;
case 0x80000000:
EAX = env->cpuid_xlevel;

View File

@ -0,0 +1,26 @@
Index: eepro100.c
===================================================================
RCS file: /sources/qemu/qemu/hw/eepro100.c,v
retrieving revision 1.3
diff -u -r1.3 eepro100.c
--- hw/eepro100.c 2 Jul 2007 13:38:46 -0000 1.3
+++ hw/eepro100.c 10 Sep 2007 08:38:51 -0000
@@ -140,6 +140,7 @@
SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
SCBCtrlMDI = 16, /* MDI interface control. */
SCBEarlyRx = 20, /* Early receive byte count. */
+ SCBFlow = 24
};
/* A speedo3 transmit buffer descriptor with two buffers... */
@@ -1256,6 +1257,10 @@
eepro100_interrupt(s, 0);
break;
case SCBPort + 3:
+ case SCBFlow:
+ case SCBFlow + 1:
+ case SCBFlow + 2:
+ case SCBFlow + 3:
logout("addr=%s val=0x%02x\n", regname(addr), val);
break;
case SCBeeprom:

16
qemu-cvs-fdc.patch Normal file
View File

@ -0,0 +1,16 @@
--- qemu-orig/hw/fdc.c Mon Aug 20 19:51:42 2007
+++ qemu/hw/fdc.c Tue Aug 28 15:46:31 2007
@@ -1843,5 +1843,13 @@
static void fdctrl_result_timer(void *opaque)
{
fdctrl_t *fdctrl = opaque;
+ fdrive_t *cur_drv = get_cur_drv(fdctrl);
+ /* Pretend we are spinning.
+ * This is needed for Coherent, which uses READ ID to check for
+ * sector interleaving.
+ */
+ if (cur_drv->last_sect != 0) {
+ cur_drv->sect = (cur_drv->sect % cur_drv->last_sect) + 1;
+ }
fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
}

View File

@ -0,0 +1,29 @@
diff -r 106bc46793ca hw/ide.c
--- a/hw/ide.c Mon Aug 27 16:20:33 2007 -0400
+++ b/hw/ide.c Mon Aug 27 16:27:28 2007 -0400
@@ -1914,6 +1914,8 @@ static void ide_ioport_write(void *opaqu
case 0x67: /* NOP */
case 0x96: /* NOP */
case 0x9a: /* NOP */
+ case 0x42: /* enable Automatic Acoustic Mode */
+ case 0xc2: /* disable Automatic Acoustic Mode */
s->status = READY_STAT | SEEK_STAT;
ide_set_irq(s);
break;
@@ -1952,12 +1954,16 @@ static void ide_ioport_write(void *opaqu
s->status = READY_STAT;
ide_set_irq(s);
break;
+ case WIN_STANDBY:
+ case WIN_STANDBY2:
case WIN_STANDBYNOW1:
case WIN_STANDBYNOW2:
case WIN_IDLEIMMEDIATE:
case CFA_IDLEIMMEDIATE:
case WIN_SETIDLE1:
case WIN_SETIDLE2:
+ case WIN_SLEEPNOW1:
+ case WIN_SLEEPNOW2:
s->status = READY_STAT;
ide_set_irq(s);
break;

121
qemu-cvs-ide-dvd.patch Normal file
View File

@ -0,0 +1,121 @@
Index: hw/ide.c
===================================================================
RCS file: /sources/qemu/qemu/hw/ide.c,v
retrieving revision 1.65
diff -u -r1.65 ide.c
--- hw/ide.c 26 Aug 2007 17:42:20 -0000 1.65
+++ hw/ide.c 8 Sep 2007 16:05:27 -0000
@@ -261,6 +261,7 @@
* older drives only.
*/
#define GPCMD_GET_MEDIA_STATUS 0xda
+#define GPCMD_MODE_SENSE_6 0x1a
/* Mode page codes for mode sense/set */
#define GPMODE_R_W_ERROR_PAGE 0x01
@@ -1329,10 +1330,14 @@
ASC_MEDIUM_NOT_PRESENT);
}
break;
+ case GPCMD_MODE_SENSE_6:
case GPCMD_MODE_SENSE_10:
{
int action, code;
- max_len = ube16_to_cpu(packet + 7);
+ if (packet[0] == GPCMD_MODE_SENSE_10)
+ max_len = ube16_to_cpu(packet + 7);
+ else
+ max_len = packet[4];
action = packet[2] >> 6;
code = packet[2] & 0x3f;
switch(action) {
@@ -1368,7 +1373,7 @@
buf[8] = 0x2a;
buf[9] = 0x12;
- buf[10] = 0x00;
+ buf[10] = 0x08;
buf[11] = 0x00;
buf[12] = 0x70;
@@ -1582,6 +1587,50 @@
ide_atapi_cmd_reply(s, 8, 8);
}
break;
+ case GPCMD_READ_DVD_STRUCTURE:
+ {
+ int media = packet[1];
+ int layer = packet[6];
+ int format = packet[2];
+ int64_t total_sectors;
+
+ if (media != 0 || layer != 0)
+ {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ }
+
+ switch (format) {
+ case 0:
+ bdrv_get_geometry(s->bs, &total_sectors);
+ total_sectors >>= 2;
+
+ memset(buf, 0, 2052);
+
+ buf[4] = 1; // DVD-ROM, part version 1
+ buf[5] = 0xf; // 120mm disc, maximum rate unspecified
+ buf[6] = 0; // one layer, embossed data
+ buf[7] = 0;
+
+ cpu_to_ube32(buf + 8, 0);
+ cpu_to_ube32(buf + 12, total_sectors - 1);
+ cpu_to_ube32(buf + 16, total_sectors - 1);
+
+ cpu_to_be16wu((uint16_t *)buf, 2048 + 4);
+
+ ide_atapi_cmd_reply(s, 2048 + 3, 2048 + 4);
+ break;
+
+ default:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ break;
+ }
+ }
+ break;
+ case GPCMD_SET_SPEED:
+ ide_atapi_cmd_ok(s);
+ break;
case GPCMD_INQUIRY:
max_len = packet[4];
buf[0] = 0x05; /* CD-ROM */
@@ -1597,6 +1646,29 @@
padstr8(buf + 32, 4, QEMU_VERSION);
ide_atapi_cmd_reply(s, 36, max_len);
break;
+ case GPCMD_GET_CONFIGURATION:
+ {
+ int64_t total_sectors;
+
+ /* only feature 0 is supported */
+ if (packet[2] != 0 || packet[3] != 0) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ break;
+ }
+ memset(buf, 0, 32);
+ bdrv_get_geometry(s->bs, &total_sectors);
+ buf[3] = 16;
+ buf[7] = total_sectors <= 1433600 ? 0x08 : 0x10; /* current profile */
+ buf[10] = 0x10 | 0x1;
+ buf[11] = 0x08; /* size of profile list */
+ buf[13] = 0x10; /* DVD-ROM profile */
+ buf[14] = buf[7] == 0x10; /* (in)active */
+ buf[17] = 0x08; /* CD-ROM profile */
+ buf[18] = buf[7] == 0x08; /* (in)active */
+ ide_atapi_cmd_reply(s, 32, 32);
+ break;
+ }
default:
ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
ASC_ILLEGAL_OPCODE);

View File

@ -0,0 +1,134 @@
diff -r 808c4b54209f block-raw.c
--- a/block-raw.c Fri Aug 10 16:30:38 2007 -0400
+++ b/block-raw.c Fri Aug 10 16:30:38 2007 -0400
@@ -59,6 +59,13 @@
//#define DEBUG_FLOPPY
+#define DEBUG_BLOCK
+#ifdef DEBUG_BLOCK
+#define DEBUG_BLOCK_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, ##args ); fflush( logfile )
+#else
+#define DEBUG_BLOCK_PRINT( formatCstr, args... )
+#endif
+
#define FTYPE_FILE 0
#define FTYPE_CD 1
#define FTYPE_FD 2
@@ -70,6 +77,7 @@ typedef struct BDRVRawState {
typedef struct BDRVRawState {
int fd;
int type;
+ unsigned int lseek_err_cnt;
#if defined(__linux__)
/* linux floppy specific */
int fd_open_flags;
@@ -87,6 +95,8 @@ static int raw_open(BlockDriverState *bs
BDRVRawState *s = bs->opaque;
int fd, open_flags, ret;
+ s->lseek_err_cnt = 0;
+
open_flags = O_BINARY;
if ((flags & BDRV_O_ACCESS) == O_RDWR) {
open_flags |= O_RDWR;
@@ -137,8 +147,58 @@ static int raw_pread(BlockDriverState *b
if (ret < 0)
return ret;
- lseek(s->fd, offset, SEEK_SET);
+ if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+ ++(s->lseek_err_cnt);
+ if(s->lseek_err_cnt <= 10) {
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %ld, %p, %d) [%ld] lseek failed : %d = %s\n",
+ s->fd,
+ bs->filename,
+ offset,
+ buf,
+ count,
+ bs->total_sectors, errno, strerror(errno) );
+ }
+ return -1;
+ }
+ s->lseek_err_cnt=0;
+
ret = read(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_read__success;
+
+ DEBUG_BLOCK_PRINT("raw_read(%d:%s, %ld, %p, %d) [%ld] read failed %d : %d = %s\n",
+ s->fd,
+ bs->filename,
+ offset,
+ buf,
+ count,
+ bs->total_sectors,
+ ret, errno, strerror(errno) );
+
+ if (bs->type == BDRV_TYPE_CDROM) { // Try harder for CDrom
+ lseek(s->fd, offset, SEEK_SET);
+ ret = read(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_read__success;
+ lseek(s->fd, offset, SEEK_SET);
+ ret = read(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_read__success;
+
+ DEBUG_BLOCK_PRINT("raw_read(%d:%s, %ld, %p, %d) [%ld] retry read failed %d : %d = %s\n",
+ s->fd,
+ bs->filename,
+ offset,
+ buf,
+ count,
+ bs->total_sectors,
+ ret, errno, strerror(errno) );
+ }
+
+ return -1;
+
+label__raw_read__success:
+
return ret;
}
@@ -152,8 +212,38 @@ static int raw_pwrite(BlockDriverState *
if (ret < 0)
return ret;
- lseek(s->fd, offset, SEEK_SET);
+ if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+ ++(s->lseek_err_cnt);
+ if(s->lseek_err_cnt) {
+ DEBUG_BLOCK_PRINT("raw_write(%d:%s, %ld, %p, %d) [%ld] lseek failed : %d = %s\n",
+ s->fd,
+ bs->filename,
+ offset,
+ buf,
+ count,
+ bs->total_sectors, errno, strerror(errno) );
+ }
+ return -1;
+ }
+ s->lseek_err_cnt = 0;
+
ret = write(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_write__success;
+
+ DEBUG_BLOCK_PRINT("raw_write(%d:%s, %ld, %p, %d) [%ld] write failed %d : %d = %s\n",
+ s->fd,
+ bs->filename,
+ offset,
+ buf,
+ count,
+ bs->total_sectors,
+ ret, errno, strerror(errno) );
+
+ return -1;
+
+label__raw_write__success:
+
return ret;
}

1812
qemu-cvs-svm.patch Normal file

File diff suppressed because it is too large Load Diff

71
qemu-cvs-svm2.patch Normal file
View File

@ -0,0 +1,71 @@
Index: qemu/cpu-exec.c
===================================================================
--- qemu.orig/cpu-exec.c
+++ qemu/cpu-exec.c
@@ -408,7 +408,7 @@ int cpu_exec(CPUState *env1)
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
svm_check_intercept(SVM_EXIT_INTR);
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
intno = cpu_get_pic_interrupt(env);
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
@@ -427,12 +427,13 @@ int cpu_exec(CPUState *env1)
int intno;
/* FIXME: this should respect TPR */
env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
- stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
- ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
+ svm_check_intercept(SVM_EXIT_VINTR);
intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
if (loglevel & CPU_LOG_TB_IN_ASM)
fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
do_interrupt(intno, 0, 0, -1, 1);
+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
+ ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
Index: qemu/target-i386/helper.c
===================================================================
--- qemu.orig/target-i386/helper.c
+++ qemu/target-i386/helper.c
@@ -4120,8 +4122,9 @@ void helper_vmrun(target_ulong addr)
if (loglevel & CPU_LOG_TB_IN_ASM)
fprintf(logfile, " %#x %#x\n", env->exception_index, env->error_code);
}
- if (int_ctl & V_IRQ_MASK)
+ if ((int_ctl & V_IRQ_MASK) || (env->intercept & INTERCEPT_VINTR)) {
env->interrupt_request |= CPU_INTERRUPT_VIRQ;
+ }
cpu_loop_exit();
}
@@ -4283,6 +4291,13 @@ void vmexit(uint64_t exit_code, uint64_t
ldq_phys(env->vm_vmcb + offsetof(struct vmcb, control.exit_info_2)),
EIP);
+ if(env->hflags & HF_INHIBIT_IRQ_MASK) {
+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), SVM_INTERRUPT_SHADOW_MASK);
+ env->hflags &= ~HF_INHIBIT_IRQ_MASK;
+ } else {
+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_state), 0);
+ }
+
/* Save the VM state in the vmcb */
SVM_SAVE_SEG(env->vm_vmcb, segs[R_ES], es);
SVM_SAVE_SEG(env->vm_vmcb, segs[R_CS], cs);
Index: qemu/target-i386/translate.c
===================================================================
--- qemu.orig/target-i386/translate.c
+++ qemu/target-i386/translate.c
@@ -5551,8 +5551,6 @@ static target_ulong disas_insn(DisasCont
gen_op_set_inhibit_irq();
/* give a chance to handle pending irqs */
gen_jmp_im(s->pc - s->cs_base);
- if (gen_svm_check_intercept(s, pc_start, SVM_EXIT_VINTR))
- break;
gen_eob(s);
} else {
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);

660
qemu-cvs-usb-isoch.patch Normal file
View File

@ -0,0 +1,660 @@
diff --git a/qemu/usb-linux.c b/qemu/usb-linux.c
old mode 100644
new mode 100755
index 50386ea..e790f00
--- a/qemu/usb-linux.c
+++ b/qemu/usb-linux.c
@@ -28,6 +28,7 @@
#include <sys/ioctl.h>
#include <linux/usbdevice_fs.h>
#include <linux/version.h>
+#include <signal.h>
/* We redefine it to avoid version problems */
struct usb_ctrltransfer {
@@ -48,15 +49,152 @@ static int usb_host_find_device(int *pbus_num, int *paddr,
const char *devname);
//#define DEBUG
+//#define DEBUG_ISOCH
+//#define USE_ASYNCIO
#define USBDEVFS_PATH "/dev/bus/usb"
#define PRODUCT_NAME_SZ 32
+#define SIG_ISOCOMPLETE (SIGRTMIN+7)
+#define MAX_ENDPOINTS 16
+
+struct sigaction sigact;
+
+// endpoint association data
+struct endp_data {
+ uint8_t type;
+};
typedef struct USBHostDevice {
USBDevice dev;
int fd;
+ struct usbdevfs_urb *urb;
+ USBPacket *packet;
+ QEMUBH *bh;
+ int status;
+ struct endp_data endp_table[MAX_ENDPOINTS];
+ int configuration;
+ uint8_t descr[1024];
+ int descr_len;
} USBHostDevice;
+typedef struct PendingURB {
+ struct usbdevfs_urb *urb;
+ struct PendingURB *next;
+} PendingURB;
+
+PendingURB *pending_urbs = NULL;
+
+int add_pending_urb(struct usbdevfs_urb *urb)
+{
+ PendingURB *purb = qemu_mallocz(sizeof(PendingURB));
+ if (purb) {
+ purb->urb = urb;
+ purb->next = pending_urbs;
+ pending_urbs = purb;
+ return 1;
+ }
+ return 0;
+}
+
+int del_pending_urb(struct usbdevfs_urb *urb)
+{
+ PendingURB *purb = pending_urbs;
+ PendingURB *prev = NULL;
+
+ while (purb && purb->urb != urb) {
+ prev = purb;
+ purb = purb->next;
+ }
+
+ if (purb && purb->urb == urb) {
+ if (prev) {
+ prev->next = purb->next;
+ } else {
+ pending_urbs = purb->next;
+ }
+ qemu_free(purb);
+ return 1;
+ }
+ return 0;
+}
+
+static int usb_host_update_interfaces(USBHostDevice *dev, int configuration)
+{
+ int dev_descr_len, config_descr_len;
+ int interface, nb_interfaces, nb_configurations;
+ int ret, i;
+
+ if (configuration == 0) // address state - ignore
+ return 1;
+
+ i = 0;
+ dev_descr_len = dev->descr[0];
+ if (dev_descr_len > dev->descr_len)
+ goto fail;
+ nb_configurations = dev->descr[17];
+
+ i += dev_descr_len;
+ while (i < dev->descr_len) {
+#ifdef DEBUG
+ printf("i is %d, descr_len is %d, dl %d, dt %d\n", i, dev->descr_len,
+ dev->descr[i], dev->descr[i+1]);
+#endif
+ if (dev->descr[i+1] != USB_DT_CONFIG) {
+ i += dev->descr[i];
+ continue;
+ }
+ config_descr_len = dev->descr[i];
+
+ if (configuration == dev->descr[i + 5])
+ break;
+
+ i += config_descr_len;
+ }
+
+ if (i >= dev->descr_len) {
+ printf("usb_host: error - device has no matching configuration\n");
+ goto fail;
+ }
+ nb_interfaces = dev->descr[i + 4];
+
+#ifdef USBDEVFS_DISCONNECT
+ /* earlier Linux 2.4 do not support that */
+ {
+ struct usbdevfs_ioctl ctrl;
+ for (interface = 0; interface < nb_interfaces; interface++) {
+ ctrl.ioctl_code = USBDEVFS_DISCONNECT;
+ ctrl.ifno = interface;
+ ret = ioctl(dev->fd, USBDEVFS_IOCTL, &ctrl);
+ if (ret < 0 && errno != ENODATA) {
+ perror("USBDEVFS_DISCONNECT");
+ goto fail;
+ }
+ }
+ }
+#endif
+
+ /* XXX: only grab if all interfaces are free */
+ for (interface = 0; interface < nb_interfaces; interface++) {
+ ret = ioctl(dev->fd, USBDEVFS_CLAIMINTERFACE, &interface);
+ if (ret < 0) {
+ if (errno == EBUSY) {
+ fprintf(stderr, "usb_host: warning - device already grabbed\n");
+ } else {
+ perror("USBDEVFS_CLAIMINTERFACE");
+ }
+ fail:
+ return 0;
+ }
+ }
+
+#ifdef DEBUG
+ printf("usb_host: %d interfaces claimed for configuration %d\n", nb_interfaces,
+ configuration);
+#endif
+
+ return 1;
+}
+
static void usb_host_handle_reset(USBDevice *dev)
{
#if 0
@@ -76,6 +214,8 @@ static void usb_host_handle_destroy(USBDevice *dev)
qemu_free(s);
}
+static int usb_linux_update_endp_table(USBHostDevice *s);
+
static int usb_host_handle_control(USBDevice *dev,
int request,
int value,
@@ -85,13 +225,32 @@ static int usb_host_handle_control(USBDevice *dev,
{
USBHostDevice *s = (USBHostDevice *)dev;
struct usb_ctrltransfer ct;
+ struct usbdevfs_setinterface si;
+ int intf_update_required = 0;
int ret;
if (request == (DeviceOutRequest | USB_REQ_SET_ADDRESS)) {
/* specific SET_ADDRESS support */
dev->addr = value;
return 0;
+ } else if (request == ((USB_RECIP_INTERFACE << 8) | USB_REQ_SET_INTERFACE)) {
+ /* set alternate setting for the interface */
+ si.interface = index;
+ si.altsetting = value;
+ ret = ioctl(s->fd, USBDEVFS_SETINTERFACE, &si);
+ usb_linux_update_endp_table(dev);
+ } else if (request == (DeviceOutRequest | USB_REQ_SET_CONFIGURATION)) {
+#ifdef DEBUG
+ printf("usb_host_handle_control: SET_CONFIGURATION request - config %d\n",
+ value & 0xff);
+#endif
+ if (s->configuration != (value & 0xff)) {
+ s->configuration = (value & 0xff);
+ intf_update_required = 1;
+ }
+ goto do_request;
} else {
+ do_request:
ct.bRequestType = request >> 8;
ct.bRequest = request;
ct.wValue = value;
@@ -100,19 +259,28 @@ static int usb_host_handle_control(USBDevice *dev,
ct.timeout = 50;
ct.data = data;
ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
- if (ret < 0) {
- switch(errno) {
- case ETIMEDOUT:
- return USB_RET_NAK;
- default:
- return USB_RET_STALL;
- }
- } else {
- return ret;
+ }
+
+ if (ret < 0) {
+ switch(errno) {
+ case ETIMEDOUT:
+ return USB_RET_NAK;
+ default:
+ return USB_RET_STALL;
+ }
+ } else {
+ if (intf_update_required) {
+#ifdef DEBUG
+ printf("usb_host_handle_control: updating interfaces\n");
+#endif
+ usb_host_update_interfaces(s, value & 0xff);
}
- }
+ return ret;
+ }
}
+static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p);
+
static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
{
USBHostDevice *s = (USBHostDevice *)dev;
@@ -120,6 +288,10 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
int ret;
uint8_t devep = p->devep;
+ if (s->endp_table[p->devep - 1].type == USBDEVFS_URB_TYPE_ISO) {
+ return usb_host_handle_isoch(dev, p);
+ }
+
/* XXX: optimize and handle all data types by looking at the
config descriptor */
if (p->pid == USB_TOKEN_IN)
@@ -145,18 +317,268 @@ static int usb_host_handle_data(USBDevice *dev, USBPacket *p)
}
}
+void isoch_done(int signum, siginfo_t *info, void *context) {
+ struct usbdevfs_urb *urb = (struct usbdevfs_urb *)info->si_addr;
+ USBHostDevice *s = (USBHostDevice *)urb->usercontext;
+
+ if (info->si_code != SI_ASYNCIO ||
+ info->si_signo != SIG_ISOCOMPLETE) {
+ return;
+ }
+
+ s->status = info->si_errno;
+ qemu_bh_schedule(s->bh);
+}
+
+static int usb_host_handle_isoch(USBDevice *dev, USBPacket *p)
+{
+ USBHostDevice *s = (USBHostDevice *)dev;
+ struct usbdevfs_urb *urb, *purb = NULL;
+ int ret;
+ uint8_t devep = p->devep;
+
+ if (p->pid == USB_TOKEN_IN)
+ devep |= 0x80;
+
+ urb = qemu_mallocz(sizeof(struct usbdevfs_urb) +
+ sizeof(struct usbdevfs_iso_packet_desc));
+ if (!urb) {
+ printf("usb_host_handle_isoch: malloc failed\n");
+ return 0;
+ }
+
+ urb->type = USBDEVFS_URB_TYPE_ISO;
+ urb->endpoint = devep;
+ urb->status = 0;
+ urb->flags = USBDEVFS_URB_ISO_ASAP;
+ urb->buffer = p->data;
+ urb->buffer_length = p->len;
+ urb->actual_length = 0;
+ urb->start_frame = 0;
+ urb->error_count = 0;
+#ifdef USE_ASYNCIO
+ urb->signr = SIG_ISOCOMPLETE;
+#else
+ urb->signr = 0;
+#endif
+ urb->usercontext = s;
+ urb->number_of_packets = 1;
+ urb->iso_frame_desc[0].length = p->len;
+ urb->iso_frame_desc[0].actual_length = 0;
+ urb->iso_frame_desc[0].status = 0;
+ ret = ioctl(s->fd, USBDEVFS_SUBMITURB, urb);
+ if (ret == 0) {
+ if (!add_pending_urb(urb)) {
+ printf("usb_host_handle_isoch: add_pending_urb failed %p\n", urb);
+ }
+ } else {
+ printf("usb_host_handle_isoch: SUBMITURB ioctl=%d errno=%d\n", ret, errno);
+ qemu_free(urb);
+ switch(errno) {
+ case ETIMEDOUT:
+ return USB_RET_NAK;
+ case EPIPE:
+ default:
+ return USB_RET_STALL;
+ }
+ }
+#ifdef USE_ASYNCIO
+ s->urb = urb;
+ s->packet = p;
+ return USB_RET_ASYNC;
+#else
+ ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
+ if (ret == 0) {
+ if (del_pending_urb(purb)) {
+ ret = purb->actual_length;
+ qemu_free(purb);
+ } else {
+ printf("usb_host_handle_isoch: del_pending_urb failed %p\n", purb);
+ }
+ } else {
+#ifdef DEBUG_ISOCH
+ printf("usb_host_handle_isoch: REAPURBNDELAY ioctl=%d errno=%d\n", ret, errno);
+#endif
+ }
+ return ret;
+#endif
+}
+
+static void usb_linux_bh_cb(void *opaque)
+{
+ USBHostDevice *s = (USBHostDevice *)opaque;
+ struct usbdevfs_urb *purb = NULL;
+ USBPacket *p = s->packet;
+ int ret;
+
+ if (!s || !p)
+ return;
+
+#ifdef DEBUG_ISOCH
+ printf("completion: devaddr %d - devep 0x%02x\n", p->devaddr, p->devep);
+#endif
+
+ ret = ioctl(s->fd, USBDEVFS_REAPURBNDELAY, &purb);
+ if (ret < 0) {
+ perror("USBDEVFS_REAPURBNDELAY");
+ return;
+ }
+
+ /* FIXME: handle s->status */
+ if (del_pending_urb(purb)) {
+ p->len = purb->actual_length;
+ qemu_free(purb);
+ s->packet = NULL;
+ usb_packet_complete(p);
+ } else {
+ printf("usb_linux_bh_cb: purb NOT found %p\n", purb);
+ qemu_free(purb);
+ s->packet = NULL;
+ }
+}
+
+// returns 1 on problem encountered or 0 for success
+static int usb_linux_update_endp_table(USBHostDevice *s)
+{
+ uint8_t descriptors[1024];
+ uint8_t data, devep, type;
+ struct usb_ctrltransfer ct;
+ int configuration, interface, alt_interface;
+ int ret, length, i;
+
+ ct.bRequestType = USB_DIR_IN;
+ ct.bRequest = USB_REQ_GET_CONFIGURATION;
+ ct.wValue = 0;
+ ct.wIndex = 0;
+ ct.wLength = 1;
+ ct.data = &data;
+ ct.timeout = 50;
+
+ ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
+ if (ret < 0) {
+ perror("usb_linux_update_endp_table");
+ return 1;
+ }
+ configuration = data;
+
+ // in address state
+ if (configuration == 0)
+ return 1;
+
+ /* get the desired configuration, interface, and endpoint
+ * descriptors in one shot - could also re-read all data from
+ * open file descriptor, go through sysfs entries, etc.
+ */
+ ct.bRequestType = USB_DIR_IN;
+ ct.bRequest = USB_REQ_GET_DESCRIPTOR;
+ ct.wValue = (USB_DT_CONFIG << 8) | (configuration - 1);
+ ct.wIndex = 0;
+ ct.wLength = 1024;
+ ct.data = descriptors;
+ ct.timeout = 50;
+
+ ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
+ if (ret < 0) {
+ perror("usb_linux_update_endp_table");
+ return 1;
+ }
+
+ length = ret;
+ i = 0;
+
+ if (descriptors[i + 1] != USB_DT_CONFIG ||
+ descriptors[i + 5] != configuration) {
+ printf("invalid descriptor data - configuration\n");
+ return 1;
+ }
+ i += descriptors[i];
+
+ while (i < length) {
+ if (descriptors[i + 1] != USB_DT_INTERFACE ||
+ (descriptors[i + 1] == USB_DT_INTERFACE &&
+ descriptors[i + 4] == 0)) {
+ i += descriptors[i];
+ continue;
+ }
+
+ interface = descriptors[i + 2];
+
+ ct.bRequestType = USB_DIR_IN | USB_RECIP_INTERFACE;
+ ct.bRequest = USB_REQ_GET_INTERFACE;
+ ct.wValue = 0;
+ ct.wIndex = interface;
+ ct.wLength = 1;
+ ct.data = &data;
+ ct.timeout = 50;
+
+ ret = ioctl(s->fd, USBDEVFS_CONTROL, &ct);
+ if (ret < 0) {
+ perror("usb_linux_update_endp_table");
+ return 1;
+ }
+ alt_interface = data;
+
+ // the current interface descriptor is the active interface
+ // and has endpoints
+ if (descriptors[i + 3] != alt_interface) {
+ i += descriptors[i];
+ continue;
+ }
+
+ // advance to the endpoints
+ while (i < length && descriptors[i +1] != USB_DT_ENDPOINT)
+ i += descriptors[i];
+
+ if (i >= length)
+ break;
+
+ while (i < length) {
+ if (descriptors[i + 1] != USB_DT_ENDPOINT)
+ break;
+
+ devep = descriptors[i + 2];
+ switch (descriptors[i + 3] & 0x3) {
+ case 0x00:
+ type = USBDEVFS_URB_TYPE_CONTROL;
+ break;
+ case 0x01:
+ type = USBDEVFS_URB_TYPE_ISO;
+ break;
+ case 0x02:
+ type = USBDEVFS_URB_TYPE_BULK;
+ break;
+ case 0x03:
+ type = USBDEVFS_URB_TYPE_INTERRUPT;
+ break;
+ default:
+ printf("usb_host: malformed endpoint type\n");
+ type = USBDEVFS_URB_TYPE_BULK;
+ }
+ s->endp_table[(devep & 0xf) - 1].type = type;
+
+ i += descriptors[i];
+ }
+ }
+ return 0;
+}
+
/* XXX: exclude high speed devices or implement EHCI */
USBDevice *usb_host_device_open(const char *devname)
{
- int fd, interface, ret, i;
- USBHostDevice *dev;
+ int fd = -1, ret;
+ USBHostDevice *dev = NULL;
struct usbdevfs_connectinfo ci;
- uint8_t descr[1024];
char buf[1024];
- int descr_len, dev_descr_len, config_descr_len, nb_interfaces;
int bus_num, addr;
char product_name[PRODUCT_NAME_SZ];
+ dev = qemu_mallocz(sizeof(USBHostDevice));
+ if (!dev)
+ goto fail;
+
+#ifdef DEBUG_ISOCH
+ printf("usb_host_device_open %s\n", devname);
+#endif
if (usb_host_find_device(&bus_num, &addr,
product_name, sizeof(product_name),
devname) < 0)
@@ -164,61 +586,35 @@ USBDevice *usb_host_device_open(const char *devname)
snprintf(buf, sizeof(buf), USBDEVFS_PATH "/%03d/%03d",
bus_num, addr);
- fd = open(buf, O_RDWR);
+ fd = open(buf, O_RDWR | O_NONBLOCK);
if (fd < 0) {
perror(buf);
return NULL;
}
- /* read the config description */
- descr_len = read(fd, descr, sizeof(descr));
- if (descr_len <= 0) {
- perror("read descr");
- goto fail;
- }
-
- i = 0;
- dev_descr_len = descr[0];
- if (dev_descr_len > descr_len)
- goto fail;
- i += dev_descr_len;
- config_descr_len = descr[i];
- if (i + config_descr_len > descr_len)
- goto fail;
- nb_interfaces = descr[i + 4];
- if (nb_interfaces != 1) {
- /* NOTE: currently we grab only one interface */
- fprintf(stderr, "usb_host: only one interface supported\n");
+ /* read the device description */
+ dev->descr_len = read(fd, dev->descr, sizeof(dev->descr));
+ if (dev->descr_len <= 0) {
+ perror("usb_host_update_interfaces: reading device data failed");
goto fail;
}
-#ifdef USBDEVFS_DISCONNECT
- /* earlier Linux 2.4 do not support that */
+#ifdef DEBUG
{
- struct usbdevfs_ioctl ctrl;
- ctrl.ioctl_code = USBDEVFS_DISCONNECT;
- ctrl.ifno = 0;
- ret = ioctl(fd, USBDEVFS_IOCTL, &ctrl);
- if (ret < 0 && errno != ENODATA) {
- perror("USBDEVFS_DISCONNECT");
- goto fail;
- }
+ int x;
+ printf("=== begin dumping device descriptor data ===\n");
+ for (x = 0; x < dev->descr_len; x++)
+ printf("%02x ", dev->descr[x]);
+ printf("\n=== end dumping device descriptor data ===\n");
}
#endif
- /* XXX: only grab if all interfaces are free */
- interface = 0;
- ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &interface);
- if (ret < 0) {
- if (errno == EBUSY) {
- fprintf(stderr, "usb_host: device already grabbed\n");
- } else {
- perror("USBDEVFS_CLAIMINTERFACE");
- }
- fail:
- close(fd);
- return NULL;
- }
+ dev->fd = fd;
+ dev->configuration = 1;
+
+ // XXX - do something about initial configuration
+ if (!usb_host_update_interfaces(dev, 1))
+ goto fail;
ret = ioctl(fd, USBDEVFS_CONNECTINFO, &ci);
if (ret < 0) {
@@ -230,10 +626,20 @@ USBDevice *usb_host_device_open(const char *devname)
printf("host USB device %d.%d grabbed\n", bus_num, addr);
#endif
- dev = qemu_mallocz(sizeof(USBHostDevice));
- if (!dev)
+ ret = usb_linux_update_endp_table(dev);
+ if (ret) {
+ qemu_free(dev);
goto fail;
- dev->fd = fd;
+ }
+
+#ifdef USE_ASYNCIO
+ dev->bh = qemu_bh_new(usb_linux_bh_cb, dev);
+ if (!dev->bh) {
+ qemu_free(dev);
+ goto fail;
+ }
+#endif
+
if (ci.slow)
dev->dev.speed = USB_SPEED_LOW;
else
@@ -252,7 +658,24 @@ USBDevice *usb_host_device_open(const char *devname)
pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
product_name);
+#ifdef USE_ASYNCIO
+ /* set up the signal handlers */
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_sigaction = isoch_done;
+ sigact.sa_flags = SA_SIGINFO;
+ sigact.sa_restorer = 0;
+ ret = sigaction(SIG_ISOCOMPLETE, &sigact, NULL);
+ if (ret < 0) {
+ printf("sigaction SIG_ISOCOMPLETE=%d errno=%d\n", ret, errno);
+ }
+#endif
+
return (USBDevice *)dev;
+fail:
+ if (dev)
+ qemu_free(dev);
+ close(fd);
+ return NULL;
}
static int get_tag_value(char *buf, int buf_size,

View File

@ -71,6 +71,19 @@
#elif defined(__alpha__) #elif defined(__alpha__)
#define EXIT_TB() asm volatile ("ret") #define EXIT_TB() asm volatile ("ret")
#elif defined(__ia64__) #elif defined(__ia64__)
--- qemu-0.9.0.cvs/dyngen.c
+++ qemu-0.9.0.cvs/dyngen.c
@@ -1495,8 +1495,8 @@
p = (void *)(p_end - 2);
if (p == p_start)
error("empty code for %s", name);
- if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)
- error("br %%r14 expected at the end of %s", name);
+ if ((get16((uint16_t *)p) & 0xfff0) != 0x07f0)
+ error("br %%rX expected at the end of %s", name);
copy_size = p - p_start;
}
#elif defined(HOST_ALPHA)
--- qemu-0.9.0.cvs/exec-all.h --- qemu-0.9.0.cvs/exec-all.h
+++ qemu-0.9.0.cvs/exec-all.h +++ qemu-0.9.0.cvs/exec-all.h
@@ -340,6 +340,24 @@ @@ -340,6 +340,24 @@

View File

@ -1,3 +1,18 @@
-------------------------------------------------------------------
Thu Sep 28 14:45:41 CEST 2007 - agraf@suse.de
- fix SVM support (Alexander Graf)
-------------------------------------------------------------------
Thu Sep 13 13:37:41 CEST 2007 - agraf@suse.de
- add SVM emulation support (Alexander Graf)
- fix a misassumption in the s390 fix (uli)
- allow more IDE power management (Ben Guthro)
- log any I/O error and perform automatic read retry for CDrom (Ben Guthro)
- fix Coherent guest support (Jan Jezabek)
- fix several Darwin guest issues (Filip Navara)
------------------------------------------------------------------- -------------------------------------------------------------------
Mon Aug 20 11:05:39 CEST 2007 - agraf@suse.de Mon Aug 20 11:05:39 CEST 2007 - agraf@suse.de

View File

@ -12,12 +12,12 @@
Name: qemu Name: qemu
BuildRequires: SDL-devel bison e2fsprogs-devel BuildRequires: SDL-devel bison e2fsprogs-devel
URL: http://fabrice.bellard.free.fr/qemu/ Url: http://fabrice.bellard.free.fr/qemu/
License: BSD 3-Clause, GPL v2 or later License: BSD 3-Clause; GPL v2 or later; LGPL v2 or later; X11/MIT
Group: System/Emulators/PC Group: System/Emulators/PC
Summary: Universal CPU emulator Summary: Universal CPU emulator
Version: 0.9.0.cvs Version: 0.9.0.cvs
Release: 21 Release: 36
Source: %name-%version.tar.bz2 Source: %name-%version.tar.bz2
#Patch400: qemu-0.7.0-gcc4-dot-syms.patch #Patch400: qemu-0.7.0-gcc4-dot-syms.patch
#Patch401: qemu-0.8.0-gcc4-hacks.patch #Patch401: qemu-0.8.0-gcc4-hacks.patch
@ -59,6 +59,15 @@ Patch69: qemu-cvs-ia64.patch
Patch70: qemu-m68k.diff Patch70: qemu-m68k.diff
Patch71: qemu-s390.patch Patch71: qemu-s390.patch
Patch72: qemu-cvs-atapi.patch Patch72: qemu-cvs-atapi.patch
Patch73: qemu-cvs-svm.patch
Patch74: qemu-cvs-cache-info.patch
Patch76: qemu-cvs-eepro100-flow-control.patch
Patch77: qemu-cvs-fdc.patch
Patch78: qemu-cvs-ide-allow-more-powermgmt.patch
Patch79: qemu-cvs-ide-dvd.patch
Patch80: qemu-cvs-raw-io-reliability.patch
Patch81: qemu-cvs-usb-isoch.patch
Patch82: qemu-cvs-svm2.patch
Source200: kvm_bios.bin Source200: kvm_bios.bin
Source201: zx-rom.bin Source201: zx-rom.bin
Source202: COPYING.zx-rom Source202: COPYING.zx-rom
@ -103,7 +112,7 @@ Patch701: gcc-3.3.5.dif
# this is to make lint happy # this is to make lint happy
Source300: rpmlintrc Source300: rpmlintrc
BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRoot: %{_tmppath}/%{name}-%{version}-build
ExclusiveArch: %ix86 ppc sparc x86_64 ia64 s390 ExclusiveArch: %ix86 ppc sparc x86_64 ia64 s390
%description %description
QEMU is an extremely well-performing CPU emulator that allows you to QEMU is an extremely well-performing CPU emulator that allows you to
@ -159,6 +168,15 @@ Authors:
%patch70 %patch70
%patch71 -p1 %patch71 -p1
%patch72 -p1 %patch72 -p1
%patch73 -p1
%patch74
%patch76
# needs fixing
%patch77 -p1
%patch78 -p1
%patch79
%patch80 -p1
%patch81 -p2
%ifarch ia64 ppc64 %ifarch ia64 ppc64
#this is the dyngen for gcc4 patch (does not work on x86) #this is the dyngen for gcc4 patch (does not work on x86)
%patch68 -p1 %patch68 -p1
@ -309,8 +327,16 @@ rm -rf %{gcc33tmp}
%ifnarch %ix86 x86_64 ia64 %ifnarch %ix86 x86_64 ia64
%dir /emul/ia32-linux %dir /emul/ia32-linux
%endif %endif
%changelog %changelog
* Fri Sep 28 2007 - agraf@suse.de
- fix SVM support (Alexander Graf)
* Thu Sep 13 2007 - agraf@suse.de
- add SVM emulation support (Alexander Graf)
- fix a misassumption in the s390 fix (uli)
- allow more IDE power management (Ben Guthro)
- log any I/O error and perform automatic read retry for CDrom (Ben Guthro)
- fix Coherent guest support (Jan Jezabek)
- fix several Darwin guest issues (Filip Navara)
* Mon Aug 20 2007 - agraf@suse.de * Mon Aug 20 2007 - agraf@suse.de
- fix ATAPI bug when using libata (Brandon Philips) (#291775) - fix ATAPI bug when using libata (Brandon Philips) (#291775)
* Sat Aug 11 2007 - olh@suse.de * Sat Aug 11 2007 - olh@suse.de