diff -Nur kvm-76/Makefile kvm-userspace/Makefile
--- kvm-76/Makefile	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/Makefile	2008-10-12 09:38:23.000000000 +0200
@@ -23,7 +23,7 @@
 ifneq '$(filter $(ARCH), i386 x86_64)' ''
     qemu: extboot
 endif
-ifneq '$(filter $(ARCH), powerpc, ia64)' ''
+ifneq '$(filter $(ARCH), powerpc ia64)' ''
     qemu: libfdt
 endif
 user: libkvm
diff -Nur kvm-76/SOURCES kvm-userspace/SOURCES
--- kvm-76/SOURCES	2008-09-28 20:38:01.000000000 +0200
+++ kvm-userspace/SOURCES	1970-01-01 01:00:00.000000000 +0100
@@ -1,2 +0,0 @@
-kernel:    ac8e90a2b855305d7459fd6e40966e09bff38cb5
-userspace: 0795a0b426419c3539355b0aeeb17f6c5e0474a8
diff -Nur kvm-76/bios/acpi-dsdt.dsl kvm-userspace/bios/acpi-dsdt.dsl
--- kvm-76/bios/acpi-dsdt.dsl	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/bios/acpi-dsdt.dsl	2008-10-12 09:38:23.000000000 +0200
@@ -224,7 +224,7 @@
                     0x00000000,         // Address Translation Offset
                     0x00020000,         // Address Length
                     ,, , AddressRangeMemory, TypeStatic)
-                DWordMemory (ResourceProducer, PosDecode, MinNotFixed, MaxFixed, NonCacheable, ReadWrite,
+                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
                     0x00000000,         // Address Space Granularity
                     0xE0000000,         // Address Range Minimum
                     0xFEBFFFFF,         // Address Range Maximum
diff -Nur kvm-76/bios/rombios.c kvm-userspace/bios/rombios.c
--- kvm-76/bios/rombios.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/bios/rombios.c	2008-10-12 09:38:23.000000000 +0200
@@ -175,6 +175,7 @@
 #define IPL_TABLE_ENTRIES    8
 #define IPL_COUNT_OFFSET     0x0080  /* u16: number of valid table entries */
 #define IPL_SEQUENCE_OFFSET  0x0082  /* u16: next boot device */
+#define IPL_BOOTFIRST_OFFSET 0x0084  /* u16: user selected device */
 #define IPL_SIZE             0xff
 #define IPL_TYPE_FLOPPY      0x01
 #define IPL_TYPE_HARDDISK    0x02
@@ -665,7 +666,8 @@
     chs_t  lchs;         // Logical CHS
     chs_t  pchs;         // Physical CHS
 
-    Bit32u sectors;      // Total sectors count
+    Bit32u sectors_low;  // Total sectors count
+    Bit32u sectors_high;
     } ata_device_t;
 
   typedef struct {
@@ -712,8 +714,8 @@
   //     The EBDA structure should conform to
   //     http://www.frontiernet.net/~fys/rombios.htm document
   //     I made the ata and cdemu structs begin at 0x121 in the EBDA seg
-  // EBDA must be at most 768 bytes; it lives at 0x9fc00, and the boot
-  // device tables are at 0x9ff00 -- 0x9ffff
+  // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot
+  // device tables are at IPL_SEG
   typedef struct {
     unsigned char filler1[0x3D];
 
@@ -901,7 +903,10 @@
 static void           keyboard_panic();
 static void           shutdown_status_panic();
 static void           nmi_handler_msg();
+static void           delay_ticks();
+static void           delay_ticks_and_check_for_keystroke();
 
+static void           interactive_bootkey();
 static void           print_bios_banner();
 static void           print_boot_device();
 static void           print_boot_failure();
@@ -1515,17 +1520,94 @@
   send(action, val - (nval * 10) + '0');
 }
 
-void put_str(action, s)
+void put_str(action, segment, offset)
   Bit16u action;
-  Bit8u *s;
+  Bit16u segment;
+  Bit16u offset;
 {
   Bit8u c;
-  if (!s)
-    s = "<NULL>";
 
-  while (c = read_byte(get_CS(), s)) {
+  while (c = read_byte(segment, offset)) {
     send(action, c);
-    s++;
+    offset++;
+  }
+}
+
+  void
+delay_ticks(ticks)
+  Bit16u ticks;
+{
+  long ticks_to_wait, delta;
+  Bit32u prev_ticks, t;
+
+   /*
+    * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
+    * We also have to be careful about interrupt storms.
+    */
+ASM_START
+  pushf
+  sti
+ASM_END
+  ticks_to_wait = ticks;
+  prev_ticks = read_dword(0x0, 0x46c);
+  do
+  {
+ASM_START
+    hlt
+ASM_END
+    t = read_dword(0x0, 0x46c);
+    if (t > prev_ticks)
+    {
+      delta = t - prev_ticks;     /* The temp var is required or bcc screws up. */
+      ticks_to_wait -= delta;
+    }
+    else if (t < prev_ticks)
+    {
+      ticks_to_wait -= t;         /* wrapped */
+    }
+
+    prev_ticks = t;
+  } while (ticks_to_wait > 0);
+ASM_START
+  cli
+  popf
+ASM_END
+}
+
+  Bit8u
+check_for_keystroke()
+{
+ASM_START
+  mov  ax, #0x100
+  int  #0x16
+  jz   no_key
+  mov  al, #1
+  jmp  done
+no_key:
+  xor  al, al
+done:
+ASM_END
+}
+
+  Bit8u
+get_keystroke()
+{
+ASM_START
+  mov  ax, #0x0
+  int  #0x16
+  xchg ah, al
+ASM_END
+}
+
+  void
+delay_ticks_and_check_for_keystroke(ticks, count)
+  Bit16u ticks, count;
+{
+  Bit16u i;
+  for (i = 1; i <= count; i++) {
+    delay_ticks(ticks);
+    if (check_for_keystroke())
+      break;
   }
 }
 
@@ -1534,7 +1616,7 @@
 //   A compact variable argument printf function.
 //
 //   Supports %[format_width][length]format
-//   where format can be x,X,u,d,s,c
+//   where format can be x,X,u,d,s,S,c
 //   and the optional length modifier is l (ell)
 //--------------------------------------------------------------------------
   void
@@ -1623,7 +1705,13 @@
             put_int(action, arg, format_width, 0);
           }
         else if (c == 's') {
-          put_str(action, arg);
+          put_str(action, get_CS(), arg);
+          }
+        else if (c == 'S') {
+          hibyte = arg;
+          arg_ptr++;
+          arg = read_word(arg_seg, arg_ptr);
+          put_str(action, hibyte, arg);
           }
         else if (c == 'c') {
           send(action, arg);
@@ -1869,6 +1957,7 @@
 // http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm
 //--------------------------------------------------------------------------
 
+static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
 
 static void
 init_boot_vectors()
@@ -1880,6 +1969,9 @@
   /* Clear out the IPL table. */
   memsetb(IPL_SEG, IPL_TABLE_OFFSET, 0, IPL_SIZE);
 
+  /* User selected device not set */
+  write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF);
+
   /* Floppy drive */
   e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0;
   memcpyb(IPL_SEG, IPL_TABLE_OFFSET + count * sizeof (e), ss, &e, sizeof (e));
@@ -1917,22 +2009,106 @@
   return 1;
 }
 
+#if BX_ELTORITO_BOOT
+  void
+interactive_bootkey()
+{
+  ipl_entry_t e;
+  Bit16u count;
+  char description[33];
+  Bit8u scan_code;
+  Bit8u i;
+  Bit16u ss = get_SS();
+  Bit16u valid_choice = 0;
+
+  while (check_for_keystroke())
+    get_keystroke();
+
+  printf("Press F12 for boot menu.\n\n");
+
+  delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */
+  if (check_for_keystroke())
+  {
+    scan_code = get_keystroke();
+    if (scan_code == 0x58) /* F12 */
+    {
+      while (check_for_keystroke())
+        get_keystroke();
+
+      printf("Select boot device:\n\n");
+
+      count = read_word(IPL_SEG, IPL_COUNT_OFFSET);
+      for (i = 0; i < count; i++)
+      {
+        memcpyb(ss, &e, IPL_SEG, IPL_TABLE_OFFSET + i * sizeof (e), sizeof (e));
+        printf("%d. ", i+1);
+        switch(e.type)
+        {
+          case IPL_TYPE_FLOPPY:
+          case IPL_TYPE_HARDDISK:
+          case IPL_TYPE_CDROM:
+            printf("%s\n", drivetypes[e.type]);
+            break;
+          case IPL_TYPE_BEV:
+            printf("%s", drivetypes[4]);
+            if (e.description != 0)
+            {
+              memcpyb(ss, &description, (Bit16u)(e.description >> 16), (Bit16u)(e.description & 0xffff), 32);
+              description[32] = 0;
+              printf(" [%S]", ss, description);
+           }
+           printf("\n");
+           break;
+        }
+      }
+
+      count++;
+      while (!valid_choice) {
+        scan_code = get_keystroke();
+        if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */
+        {
+          valid_choice = 1;
+        }
+        else if (scan_code <= count)
+        {
+          valid_choice = 1;
+          scan_code -= 1;
+          /* Set user selected device */
+          write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, scan_code);
+        }
+      }
+    printf("\n");
+    }
+  }
+}
+#endif // BX_ELTORITO_BOOT
 
 //--------------------------------------------------------------------------
 // print_boot_device
 //   displays the boot device
 //--------------------------------------------------------------------------
 
-static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"};
-
 void
-print_boot_device(type)
-  Bit16u type;
+print_boot_device(e)
+  ipl_entry_t *e;
 {
+  Bit16u type;
+  char description[33];
+  Bit16u ss = get_SS();
+  type = e->type;
   /* NIC appears as type 0x80 */
   if (type == IPL_TYPE_BEV) type = 0x4;
   if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n");
-  printf("Booting from %s...\n", drivetypes[type]);
+  printf("Booting from %s", drivetypes[type]);
+  /* print product string if BEV */
+  if (type == 4 && e->description != 0) {
+    /* first 32 bytes are significant */
+    memcpyb(ss, &description, (Bit16u)(e->description >> 16), (Bit16u)(e->description & 0xffff), 32);
+    /* terminate string */
+    description[32] = 0;
+    printf(" [%S]", ss, description);
+  }
+  printf("...\n");
 }
 
 //--------------------------------------------------------------------------
@@ -1945,15 +2121,15 @@
 {
   if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n");
 
-  printf("Boot from %s failed", drivetypes[type]);
+  printf("Boot failed");
   if (type < 4) {
     /* Report the reason too */
-  if (reason==0)
-    printf(": not a bootable disk");
-  else
-    printf(": could not read the boot disk");
+    if (reason==0)
+      printf(": not a bootable disk");
+    else
+      printf(": could not read the boot disk");
   }
-  printf("\n");
+  printf("\n\n");
 }
 
 //--------------------------------------------------------------------------
@@ -2197,7 +2373,8 @@
     write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders,0);
     write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt,0);
 
-    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors,0L);
+    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low,0L);
+    write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high,0L);
     }
 
   // hdidmap  and cdidmap init.
@@ -2359,7 +2536,7 @@
 
     // Now we send a IDENTIFY command to ATA device
     if(type == ATA_TYPE_ATA) {
-      Bit32u sectors;
+      Bit32u sectors_low, sectors_high;
       Bit16u cylinders, heads, spt, blksize;
       Bit8u  translation, removable, mode;
 
@@ -2367,7 +2544,7 @@
       write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
       write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
 
-      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, get_SS(),buffer) !=0 )
+      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) !=0 )
         BX_PANIC("ata-detect: Failed to detect ATA device\n");
 
       removable = (read_byte(get_SS(),buffer+0) & 0x80) ? 1 : 0;
@@ -2378,7 +2555,13 @@
       heads     = read_word(get_SS(),buffer+(3*2)); // word 3
       spt       = read_word(get_SS(),buffer+(6*2)); // word 6
 
-      sectors   = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
+      if (read_word(get_SS(),buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 support
+        sectors_low  = read_dword(get_SS(),buffer+(100*2)); // word 100 and word 101
+        sectors_high = read_dword(get_SS(),buffer+(102*2)); // word 102 and word 103
+      } else {
+        sectors_low = read_dword(get_SS(),buffer+(60*2)); // word 60 and word 61
+        sectors_high = 0;
+      }
 
       write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_HD);
       write_byte(ebda_seg,&EbdaData->ata.devices[device].removable, removable);
@@ -2387,7 +2570,8 @@
       write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.heads, heads);
       write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.cylinders, cylinders);
       write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt);
-      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors);
+      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors_low);
+      write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high, sectors_high);
       BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt);
 
       translation = inb_cmos(0x39 + channel/2);
@@ -2415,14 +2599,14 @@
           break;
         case ATA_TRANSLATION_LBA:
           spt = 63;
-          sectors /= 63;
-          heads = sectors / 1024;
+          sectors_low /= 63;
+          heads = sectors_low / 1024;
           if (heads>128) heads = 255;
           else if (heads>64) heads = 128;
           else if (heads>32) heads = 64;
           else if (heads>16) heads = 32;
           else heads=16;
-          cylinders = sectors / heads;
+          cylinders = sectors_low / heads;
           break;
         case ATA_TRANSLATION_RECHS:
           // Take care not to overflow
@@ -2465,7 +2649,7 @@
       write_byte(ebda_seg,&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM);
       write_byte(ebda_seg,&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16);
 
-      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, get_SS(),buffer) != 0)
+      if (ata_cmd_data_in(device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) != 0)
         BX_PANIC("ata-detect: Failed to detect ATAPI device\n");
 
       type      = read_byte(get_SS(),buffer+1) & 0x1f;
@@ -2490,8 +2674,8 @@
 
       switch (type) {
         case ATA_TYPE_ATA:
-          sizeinmb = read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors);
-          sizeinmb >>= 11;
+          sizeinmb = (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_high) << 21)
+            | (read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low) >> 11);
         case ATA_TYPE_ATAPI:
           // Read ATA/ATAPI version
           ataversion=((Bit16u)(read_byte(get_SS(),buffer+161))<<8)|read_byte(get_SS(),buffer+160);
@@ -2504,7 +2688,7 @@
           for(i=0;i<20;i++){
             write_byte(get_SS(),model+(i*2),read_byte(get_SS(),buffer+(i*2)+54+1));
             write_byte(get_SS(),model+(i*2)+1,read_byte(get_SS(),buffer+(i*2)+54));
-            }
+          }
 
           // Reformat
           write_byte(get_SS(),model+40,0x00);
@@ -2512,7 +2696,13 @@
             if(read_byte(get_SS(),model+i)==0x20)
               write_byte(get_SS(),model+i,0x00);
             else break;
+          }
+          if (i>36) {
+            write_byte(get_SS(),model+36,0x00);
+            for(i=35;i>32;i--){
+              write_byte(get_SS(),model+i,0x2E);
             }
+          }
           break;
         }
 
@@ -2628,9 +2818,9 @@
       // 5 : more sectors to read/verify
       // 6 : no sectors left to write
       // 7 : more sectors to write
-Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba, segment, offset)
+Bit16u ata_cmd_data_in(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
 Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
+Bit32u lba_low, lba_high;
 {
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit16u iobase1, iobase2, blksize;
@@ -2659,19 +2849,19 @@
 
   // sector will be 0 only on lba access. Convert to lba-chs
   if (sector == 0) {
-    if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
+    if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
       outb(iobase1 + ATA_CB_FR, 0x00);
       outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
-      outb(iobase1 + ATA_CB_SN, lba >> 24);
-      outb(iobase1 + ATA_CB_CL, 0);
-      outb(iobase1 + ATA_CB_CH, 0);
+      outb(iobase1 + ATA_CB_SN, lba_low >> 24);
+      outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
+      outb(iobase1 + ATA_CB_CH, lba_high >> 8);
       command |= 0x04;
       count &= (1UL << 8) - 1;
-      lba &= (1UL << 24) - 1;
+      lba_low &= (1UL << 24) - 1;
       }
-    sector = (Bit16u) (lba & 0x000000ffL);
-    cylinder = (Bit16u) ((lba>>8) & 0x0000ffffL);
-    head = ((Bit16u) ((lba>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+    sector = (Bit16u) (lba_low & 0x000000ffL);
+    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
   }
 
   outb(iobase1 + ATA_CB_FR, 0x00);
@@ -2779,9 +2969,9 @@
       // 5 : more sectors to read/verify
       // 6 : no sectors left to write
       // 7 : more sectors to write
-Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba, segment, offset)
+Bit16u ata_cmd_data_out(device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset)
 Bit16u device, command, count, cylinder, head, sector, segment, offset;
-Bit32u lba;
+Bit32u lba_low, lba_high;
 {
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit16u iobase1, iobase2, blksize;
@@ -2810,19 +3000,19 @@
 
   // sector will be 0 only on lba access. Convert to lba-chs
   if (sector == 0) {
-    if ((count >= 1 << 8) || (lba + count >= 1UL << 28)) {
+    if ((count >= 1 << 8) || lba_high || (lba_low + count >= 1UL << 28)) {
       outb(iobase1 + ATA_CB_FR, 0x00);
       outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff);
-      outb(iobase1 + ATA_CB_SN, lba >> 24);
-      outb(iobase1 + ATA_CB_CL, 0);
-      outb(iobase1 + ATA_CB_CH, 0);
+      outb(iobase1 + ATA_CB_SN, lba_low >> 24);
+      outb(iobase1 + ATA_CB_CL, lba_high & 0xff);
+      outb(iobase1 + ATA_CB_CH, lba_high >> 8);
       command |= 0x04;
       count &= (1UL << 8) - 1;
-      lba &= (1UL << 24) - 1;
+      lba_low &= (1UL << 24) - 1;
       }
-    sector = (Bit16u) (lba & 0x000000ffL);
-    cylinder = (Bit16u) ((lba>>8) & 0x0000ffffL);
-    head = ((Bit16u) ((lba>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
+    sector = (Bit16u) (lba_low & 0x000000ffL);
+    cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL);
+    head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA;
   }
 
   outb(iobase1 + ATA_CB_FR, 0x00);
@@ -3299,9 +3489,9 @@
   BX_DEBUG_ATA("sectors=%u\n", sectors);
   if (block_len == 2048)
     sectors <<= 2; /* # of sectors in 512-byte "soft" sector */
-  if (sectors != read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors))
+  if (sectors != read_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low))
     printf("%dMB medium detected\n", sectors>>(20-9));
-  write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors);
+  write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors_low, sectors);
   return 0;
 }
 
@@ -4214,7 +4404,7 @@
       break;
     }
 }
-#endif
+#endif // BX_USE_PS2_MOUSE
 
 
 void set_e820_range(ES, DI, start, end, extra_start, extra_end, type)
@@ -4321,6 +4511,7 @@
                     extended_memory_size <<= 8;
                     extended_memory_size |= inb_cmos(0x30);
                     extended_memory_size *= 1024;
+                    extended_memory_size += (1L * 1024 * 1024);
                 }
 
                 extra_lowbits_memory_size = inb_cmos(0x5c);
@@ -4360,10 +4551,17 @@
                         return;
                         break;
                     case 3:
+#if BX_ROMBIOS32
                         set_e820_range(ES, regs.u.r16.di,
                                        0x00100000L,
                                        extended_memory_size - ACPI_DATA_SIZE ,0, 0, 1);
                         regs.u.r32.ebx = 4;
+#else
+                        set_e820_range(ES, regs.u.r16.di,
+                                       0x00100000L,
+                                       extended_memory_size, 1);
+                        regs.u.r32.ebx = 5;
+#endif
                         regs.u.r32.eax = 0x534D4150;
                         regs.u.r32.ecx = 0x14;
                         CLEAR_CF();
@@ -5011,7 +5209,7 @@
 int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS)
   Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS;
 {
-  Bit32u lba;
+  Bit32u lba_low, lba_high;
   Bit16u ebda_seg=read_word(0x0040,0x000E);
   Bit16u cylinder, head, sector;
   Bit16u segment, offset;
@@ -5090,14 +5288,15 @@
 
       // if needed, translate lchs to lba, and execute command
       if ( (nph != nlh) || (npspt != nlspt)) {
-        lba = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
+        lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1;
+        lba_high = 0;
         sector = 0; // this forces the command to be lba
         }
 
       if ( GET_AH() == 0x02 )
-        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba, segment, offset);
+        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
       else
-        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba, segment, offset);
+        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset);
 
       // Set nb of sector transferred
       SET_AL(read_word(ebda_seg, &EbdaData->ata.trsfsectors));
@@ -5159,9 +5358,9 @@
       nlspt = read_word(ebda_seg, &EbdaData->ata.devices[device].lchs.spt);
 
       // Compute sector count seen by int13
-      lba = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt;
-      CX = lba >> 16;
-      DX = lba & 0xffff;
+      lba_low = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt;
+      CX = lba_low >> 16;
+      DX = lba_low & 0xffff;
 
       SET_AH(3);  // hard disk accessible
       goto int13_success_noah;
@@ -5183,16 +5382,17 @@
       segment=read_word(DS, SI+(Bit16u)&Int13Ext->segment);
       offset=read_word(DS, SI+(Bit16u)&Int13Ext->offset);
 
-      // Can't use 64 bits lba
-      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
-      if (lba != 0L) {
-        BX_PANIC("int13_harddisk: function %02x. Can't use 64bits lba\n",GET_AH());
+      // Get 32 msb lba and check
+      lba_high=read_dword(DS, SI+(Bit16u)&Int13Ext->lba2);
+      if (lba_high > read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high) ) {
+        BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
         goto int13_fail;
         }
 
-      // Get 32 bits lba and check
-      lba=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
-      if (lba >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors) ) {
+      // Get 32 lsb lba and check
+      lba_low=read_dword(DS, SI+(Bit16u)&Int13Ext->lba1);
+      if (lba_high == read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high)
+          && lba_low >= read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low) ) {
         BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH());
         goto int13_fail;
         }
@@ -5203,9 +5403,9 @@
 
       // Execute the command
       if ( GET_AH() == 0x42 )
-        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba, segment, offset);
+        status=ata_cmd_data_in(device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
       else
-        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba, segment, offset);
+        status=ata_cmd_data_out(device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset);
 
       count=read_word(ebda_seg, &EbdaData->ata.trsfsectors);
       write_word(DS, SI+(Bit16u)&Int13Ext->count, count);
@@ -5243,11 +5443,12 @@
         npc     = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.cylinders);
         nph     = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.heads);
         npspt   = read_word(ebda_seg, &EbdaData->ata.devices[device].pchs.spt);
-        lba     = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors);
+        lba_low = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_low);
+        lba_high = read_dword(ebda_seg, &EbdaData->ata.devices[device].sectors_high);
         blksize = read_word(ebda_seg, &EbdaData->ata.devices[device].blksize);
 
         write_word(DS, SI+(Bit16u)&Int13DPT->size, 0x1a);
-        if ((lba/npspt)/nph > 0x3fff)
+        if (lba_high || (lba_low/npspt)/nph > 0x3fff)
         {
           write_word(DS, SI+(Bit16u)&Int13DPT->infos, 0x00); // geometry is invalid
           write_dword(DS, SI+(Bit16u)&Int13DPT->cylinders, 0x3fff);
@@ -5259,8 +5460,8 @@
         }
         write_dword(DS, SI+(Bit16u)&Int13DPT->heads, (Bit32u)nph);
         write_dword(DS, SI+(Bit16u)&Int13DPT->spt, (Bit32u)npspt);
-        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba);  // FIXME should be Bit64
-        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, 0L);
+        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count1, lba_low);
+        write_dword(DS, SI+(Bit16u)&Int13DPT->sector_count2, lba_high);
         write_word(DS, SI+(Bit16u)&Int13DPT->blksize, blksize);
         }
 
@@ -7779,6 +7980,7 @@
   Bit16u bootseg;
   Bit16u bootip;
   Bit16u status;
+  Bit16u bootfirst;
 
   ipl_entry_t e;
 
@@ -7806,7 +8008,16 @@
   bootdev |= ((inb_cmos(0x38) & 0xf0) << 4);
   bootdev >>= 4 * seq_nr;
   bootdev &= 0xf;
-  if (bootdev == 0) BX_PANIC("No bootable device.\n");
+
+  /* Read user selected device */
+  bootfirst = read_word(IPL_SEG, IPL_BOOTFIRST_OFFSET);
+  if (bootfirst != 0xFFFF) {
+    bootdev = bootfirst;
+    /* User selected device not set */
+    write_word(IPL_SEG, IPL_BOOTFIRST_OFFSET, 0xFFFF);
+    /* Reset boot sequence */
+    write_word(IPL_SEG, IPL_SEQUENCE_OFFSET, 0xFFFF);
+  } else if (bootdev == 0) BX_PANIC("No bootable device.\n");
 
   /* Translate from CMOS runes to an IPL table offset by subtracting 1 */
   bootdev -= 1;
@@ -7827,7 +8038,7 @@
 
   /* Do the loading, and set up vector as a far pointer to the boot
    * address, and bootdrv as the boot drive */
-  print_boot_device(e.type);
+  print_boot_device(&e);
 
   switch(e.type) {
   case IPL_TYPE_FLOPPY: /* FDD */
@@ -7899,9 +8110,7 @@
 
     bootdrv = (Bit8u)(status>>8);
     bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment);
-    /* Canonicalize bootseg:bootip */
-    bootip = (bootseg & 0x0fff) << 4;
-    bootseg &= 0xf000;
+    bootip = 0;
     break;
 #endif
 
@@ -7919,6 +8128,8 @@
   /* Jump to the boot vector */
 ASM_START
     mov  bp, sp
+    push cs
+    push #int18_handler
     ;; Build an iret stack frame that will take us to the boot vector.
     ;; iret pops ip, then cs, then flags, so push them in the opposite order.
     pushf
@@ -8874,13 +9085,33 @@
 ;--------------------
 ; relocated here because the primary POST area isnt big enough.
 eoi_jmp_post:
-  call eoi_both_pics
+  mov   al, #0x20
+  out   #0xA0, al ;; slave  PIC EOI
+  mov   al, #0x20
+  out   #0x20, al ;; master PIC EOI
 
+jmp_post_0x467:
   xor ax, ax
   mov ds, ax
 
   jmp far ptr [0x467]
 
+iret_post_0x467:
+  xor ax, ax
+  mov ds, ax
+
+  mov sp, [0x467]
+  mov ss, [0x469]
+  iret
+
+retf_post_0x467:
+  xor ax, ax
+  mov ds, ax
+
+  mov sp, [0x467]
+  mov ss, [0x469]
+  retf
+
 
 ;--------------------
 eoi_both_pics:
@@ -9447,10 +9678,10 @@
   db 0x08 ;; PCI interrupt router DevFunc
   dw 0x0000 ;; PCI exclusive IRQs
   dw 0x8086 ;; compatible PCI interrupt router vendor ID
-  dw 0x7000 ;; compatible PCI interrupt router device ID
+  dw 0x122e ;; compatible PCI interrupt router device ID
   dw 0,0 ;; Miniport data
   db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved
-  db 0x07 ;; checksum
+  db 0x37 ;; checksum
 pci_routing_table_structure_start:
   ;; first slot entry PCI-to-ISA (embedded)
   db 0 ;; pci bus number
@@ -9752,7 +9983,7 @@
   pop  bp
   pop  ds
   ret
-#endif // BX_ROMBIOS32
+#endif // !BX_ROMBIOS32
 #endif // BX_PCIBIOS
 
 #if BX_ROMBIOS32
@@ -9872,7 +10103,7 @@
   dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18)
   dw 0xffff, 0, 0x9b0f, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff
   dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff
-#endif
+#endif // BX_ROMBIOS32
 
 
 ; parallel port detection: base address in DX, index in BX, timeout in CL
@@ -10056,10 +10287,12 @@
   mov  ds, ax
   ret
 
-;; for 'C' strings and other data, insert them here with
-;; a the following hack:
-;; DATA_SEG_DEFS_HERE
-
+post_enable_cache:
+  ;; enable cache
+  mov eax, cr0
+  and eax, #0x9fffffff
+  mov cr0, eax
+  jmp post_enable_cache_done
 
 ;; the following area can be used to write dynamically generated tables
   .align 16
@@ -10067,16 +10300,15 @@
   dd 0xaafb4442
   dd bios_table_area_end - bios_table_area_start - 8;
 
+
 ;--------
 ;- POST -
 ;--------
 .org 0xe05b ; POST Entry Point
 post:
-  ;; enable cache
-  mov eax, cr0
-  and eax, #0x9fffffff
-  mov cr0, eax
-
+  jmp post_enable_cache ; hack: we have limited space before next .org,
+	                ;       so take this bit out-of-line
+post_enable_cache_done:
   xor ax, ax
 
   ;; first reset the DMA controllers
@@ -10118,8 +10350,20 @@
   cmp al, #0x05
   je  eoi_jmp_post
 
+  ;; 0x0A = jmp via [0x40:0x67] jump
+  cmp al, #0x0a
+  je  jmp_post_0x467
+
+  ;; 0x0B = iret via [0x40:0x67]
+  cmp al, #0x0b
+  je  iret_post_0x467
+
+  ;; 0x0C = retf via [0x40:0x67]
+  cmp al, #0x0c
+  je  retf_post_0x467
+
   ;; Examine CMOS shutdown status.
-  ;;  0x01,0x02,0x03,0x04,0x06,0x07,0x08, 0x0a, 0x0b, 0x0c = Unimplemented shutdown status.
+  ;;  0x01,0x02,0x03,0x04,0x06,0x07,0x08 = Unimplemented shutdown status.
   push bx
   call _shutdown_status_panic
 
@@ -10356,25 +10600,19 @@
   ;;
   call floppy_drive_post
 
-#if BX_USE_ATADRV
-
   ;;
   ;; Hard Drive setup
   ;;
   call hard_drive_post
 
+#if BX_USE_ATADRV
+
   ;;
   ;; ATA/ATAPI driver setup
   ;;
   call _ata_init
   call _ata_detect
   ;;
-#else // BX_USE_ATADRV
-
-  ;;
-  ;; Hard Drive setup
-  ;;
-  call hard_drive_post
 
 #endif // BX_USE_ATADRV
 
@@ -10392,6 +10630,10 @@
   mov  ax, #0xe000
   call rom_scan
 
+#if BX_ELTORITO_BOOT
+  call _interactive_bootkey
+#endif // BX_ELTORITO_BOOT
+
   sti        ;; enable interrupts
   int  #0x19
 
diff -Nur kvm-76/bios/rombios32.c kvm-userspace/bios/rombios32.c
--- kvm-76/bios/rombios32.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/bios/rombios32.c	2008-10-12 09:38:23.000000000 +0200
@@ -416,7 +416,7 @@
 uint32_t cpuid_features;
 uint32_t cpuid_ext_features;
 unsigned long ram_size;
-uint64_t above4g_ram_size;
+uint64_t ram_end;
 uint8_t bios_uuid[16];
 #ifdef BX_USE_EBDA_TABLES
 unsigned long ebda_cur_addr;
@@ -452,7 +452,7 @@
     // check if backdoor port exists
     asm volatile ("outl %%eax, %%dx"
         : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
-        : "a" (0x564d5868), "c" (0xa), "d" (0x5658));
+        : "a" (0x564d5868), "b" (0), "c" (0xa), "d" (0x5658));
     if (ebx == 0x564d5868) {
         uint32_t *uuid_ptr = (uint32_t *)bios_uuid;
         // get uuid
@@ -494,7 +494,6 @@
         uint8_t valb[8];
         uint64_t val;
     } u;
-    uint64_t vbase, vmask;
 
     mtrr_cap = rdmsr(MSR_MTRRcap);
     vcnt = mtrr_cap & 0xff;
@@ -521,25 +520,10 @@
     wrmsr_smp(MSR_MTRRfix4K_E8000, 0);
     wrmsr_smp(MSR_MTRRfix4K_F0000, 0);
     wrmsr_smp(MSR_MTRRfix4K_F8000, 0);
-    vbase = 0;
-    --vcnt; /* leave one mtrr for VRAM */
-    for (i = 0; i < vcnt && vbase < ram_size; ++i) {
-        vmask = (1ull << 40) - 1;
-        while (vbase + vmask + 1 > ram_size)
-            vmask >>= 1;
-        wrmsr_smp(MTRRphysBase_MSR(i), vbase | 6);
-        wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
-        vbase += vmask + 1;
-    }
-    for (vbase = 1ull << 32; i < vcnt && vbase < above4g_ram_size; ++i) {
-        vmask = (1ull << 40) - 1;
-        while (vbase + vmask + 1 > above4g_ram_size)
-            vmask >>= 1;
-        wrmsr_smp(MTRRphysBase_MSR(i), vbase | 6);
-        wrmsr_smp(MTRRphysMask_MSR(i), (~vmask & 0xfffffff000ull) | 0x800);
-        vbase += vmask + 1;
-    }
-    wrmsr_smp(MSR_MTRRdefType, 0xc00);
+    /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
+    wrmsr_smp(MTRRphysBase_MSR(0), 0xe0000000ull | 0);
+    wrmsr_smp(MTRRphysMask_MSR(0), ~(0x20000000ull - 1) | 0x800);
+    wrmsr_smp(MSR_MTRRdefType, 0xc06);
 }
 
 void ram_probe(void)
@@ -551,17 +535,19 @@
     ram_size = (cmos_readb(0x17) | (cmos_readb(0x18) << 8)) * 1024;
 
   if (cmos_readb(0x5b) | cmos_readb(0x5c) | cmos_readb(0x5d))
-    above4g_ram_size = ((uint64_t)cmos_readb(0x5b) << 16) |
-        ((uint64_t)cmos_readb(0x5c) << 24) | ((uint64_t)cmos_readb(0x5d) << 32);
+    ram_end = (((uint64_t)cmos_readb(0x5b) << 16) |
+               ((uint64_t)cmos_readb(0x5c) << 24) |
+               ((uint64_t)cmos_readb(0x5d) << 32)) + (1ull << 32);
+  else
+    ram_end = ram_size;
 
-  if (above4g_ram_size)
-    above4g_ram_size += 1ull << 32;
+  BX_INFO("end of ram=%ldMB\n", ram_end >> 20);
 
+  BX_INFO("ram_size=0x%08lx\n", ram_size);
 #ifdef BX_USE_EBDA_TABLES
-    ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
+  ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x380;
+  BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr);
 #endif
-    BX_INFO("ram_size=0x%08lx\n", ram_size);
-    BX_INFO("top of ram %ldMB\n", above4g_ram_size >> 20);
   setup_mtrr();
 }
 
@@ -635,6 +621,17 @@
 #define PCI_MIN_GNT		0x3e	/* 8 bits */
 #define PCI_MAX_LAT		0x3f	/* 8 bits */
 
+#define PCI_VENDOR_ID_INTEL             0x8086
+#define PCI_DEVICE_ID_INTEL_82441       0x1237
+#define PCI_DEVICE_ID_INTEL_82371SB_0   0x7000
+#define PCI_DEVICE_ID_INTEL_82371SB_1   0x7010
+#define PCI_DEVICE_ID_INTEL_82371AB_0   0x7110
+#define PCI_DEVICE_ID_INTEL_82371AB     0x7111
+#define PCI_DEVICE_ID_INTEL_82371AB_3   0x7113
+
+#define PCI_VENDOR_ID_IBM               0x1014
+#define PCI_VENDOR_ID_APPLE             0x106b
+
 typedef struct PCIDevice {
     int bus;
     int devfn;
@@ -773,11 +770,13 @@
     vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
     device_id = pci_config_readw(d, PCI_DEVICE_ID);
 
-    if (vendor_id == 0x8086 && device_id == 0x7000) {
+    if (vendor_id == PCI_VENDOR_ID_INTEL &&
+       (device_id == PCI_DEVICE_ID_INTEL_82371SB_0 ||
+        device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
         int i, irq;
         uint8_t elcr[2];
 
-        /* PIIX3 bridge */
+        /* PIIX3/PIIX4 PCI to ISA bridge */
 
         elcr[0] = 0x00;
         elcr[1] = 0x00;
@@ -790,9 +789,9 @@
         }
         outb(0x4d0, elcr[0]);
         outb(0x4d1, elcr[1]);
-        BX_INFO("PIIX3 init: elcr=%02x %02x\n",
+        BX_INFO("PIIX3/PIIX4 init: elcr=%02x %02x\n",
                 elcr[0], elcr[1]);
-    } else if (vendor_id == 0x8086 && device_id == 0x1237) {
+    } else if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441) {
         /* i440 PCI bridge */
         bios_shadow_init(d);
     }
@@ -853,8 +852,10 @@
             d->bus, d->devfn, vendor_id, device_id);
     switch(class) {
     case 0x0101:
-        if (vendor_id == 0x8086 && device_id == 0x7010) {
-            /* PIIX3 IDE */
+        if (vendor_id == PCI_VENDOR_ID_INTEL &&
+           (device_id == PCI_DEVICE_ID_INTEL_82371SB_1 ||
+            device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
+            /* PIIX3/PIIX4 IDE */
             pci_config_writew(d, 0x40, 0x8000); // enable IDE0
             pci_config_writew(d, 0x42, 0x8000); // enable IDE1
             goto default_map;
@@ -874,7 +875,7 @@
         break;
     case 0x0800:
         /* PIC */
-        if (vendor_id == 0x1014) {
+        if (vendor_id == PCI_VENDOR_ID_IBM) {
             /* IBM */
             if (device_id == 0x0046 || device_id == 0xFFFF) {
                 /* MPIC & MPIC2 */
@@ -883,7 +884,7 @@
         }
         break;
     case 0xff00:
-        if (vendor_id == 0x0106b &&
+        if (vendor_id == PCI_VENDOR_ID_APPLE &&
             (device_id == 0x0017 || device_id == 0x0022)) {
             /* macio bridge */
             pci_set_io_region_addr(d, 0, 0x80800000);
@@ -926,7 +927,7 @@
         pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
     }
 
-    if (vendor_id == 0x8086 && device_id == 0x7113) {
+    if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
         /* PIIX4 Power Management device (for ACPI) */
 
         // acpi sci is hardwired to 9
@@ -1494,8 +1495,8 @@
     fadt->pm1_evt_len = 4;
     fadt->pm1_cnt_len = 2;
     fadt->pm_tmr_len = 4;
-    fadt->plvl2_lat = cpu_to_le16(0x0fff); // C2 state not supported
-    fadt->plvl3_lat = cpu_to_le16(0x0fff); // C3 state not supported
+    fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
+    fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
     fadt->gpe0_blk = cpu_to_le32(0xafe0);
     fadt->gpe0_blk_len = 4;
     /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
@@ -1650,6 +1651,9 @@
 	uint16_t current_speed;
 	uint8_t status;
 	uint8_t processor_upgrade;
+        uint16_t l1_cache_handle;
+        uint16_t l2_cache_handle;
+        uint16_t l3_cache_handle;
 } __attribute__((__packed__));
 
 /* SMBIOS type 16 - Physical Memory Array
@@ -1772,8 +1776,8 @@
     p->bios_release_date_str = 2;
     p->bios_rom_size = 0; /* FIXME */
 
-    memset(p->bios_characteristics, 0, 7);
-    p->bios_characteristics[7] = 0x08; /* BIOS characteristics not supported */
+    memset(p->bios_characteristics, 0, 8);
+    p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
     p->bios_characteristics_extension_bytes[0] = 0;
     p->bios_characteristics_extension_bytes[1] = 0;
 
@@ -1876,6 +1880,10 @@
     p->status = 0x41; /* socket populated, CPU enabled */
     p->processor_upgrade = 0x01; /* other */
 
+    p->l1_cache_handle = 0xffff; /* cache information structure not provided */
+    p->l2_cache_handle = 0xffff;
+    p->l3_cache_handle = 0xffff;
+
     start += sizeof(struct smbios_type_4);
 
     memcpy((char *)start, "CPU  " "\0" "" "\0" "", 7);
@@ -1949,7 +1957,7 @@
     p->header.handle = 0x1300;
 
     p->starting_address = 0;
-    p->ending_address = (memory_size_mb-1) * 1024;
+    p->ending_address = (memory_size_mb * 1024) - 1;
     p->memory_array_handle = 0x1000;
     p->partition_width = 1;
 
@@ -1970,7 +1978,7 @@
     p->header.handle = 0x1400;
 
     p->starting_address = 0;
-    p->ending_address = (memory_size_mb-1)*1024;
+    p->ending_address = (memory_size_mb * 1024) - 1;
     p->memory_device_handle = 0x1100;
     p->memory_array_mapped_address_handle = 0x1300;
     p->partition_row_position = 1;
@@ -2021,7 +2029,8 @@
 {
     unsigned cpu_num, nr_structs = 0, max_struct_size = 0;
     char *start, *p, *q;
-    int memsize = ram_size / (1024 * 1024);
+    int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) :
+                  (ram_end - (1ull << 32) + ram_size) / (1024 * 1024);
 
 #ifdef BX_USE_EBDA_TABLES
     ebda_cur_addr = align(ebda_cur_addr, 16);
@@ -2048,8 +2057,8 @@
         add_struct(smbios_type_4_init(p, cpu_num));
     add_struct(smbios_type_16_init(p, memsize));
     add_struct(smbios_type_17_init(p, memsize));
-    add_struct(smbios_type_19_init(p, memsize));
-    add_struct(smbios_type_20_init(p, memsize));
+    add_struct(smbios_type_19_init(p, ram_end / (1024 * 1024)));
+    add_struct(smbios_type_20_init(p, ram_end / (1024 * 1024)));
     add_struct(smbios_type_32_init(p));
     add_struct(smbios_type_127_init(p));
 
@@ -2082,14 +2091,14 @@
 
     smp_probe();
 
-    uuid_probe();
-
     pci_bios_init();
 
     if (bios_table_cur_addr != 0) {
 
         mptable_init();
 
+        uuid_probe();
+
         smbios_init();
 
         if (acpi_enabled)
diff -Nur kvm-76/bios/rombios32start.S kvm-userspace/bios/rombios32start.S
--- kvm-76/bios/rombios32start.S	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/bios/rombios32start.S	2008-10-12 09:38:23.000000000 +0200
@@ -60,7 +60,7 @@
   jmp 11b
 12:
 
-  incw CPU_COUNT_ADDR
+  lock incw CPU_COUNT_ADDR
   ljmp $0xe000, $(1f-_start)
 1:
   hlt
diff -Nur kvm-76/configure kvm-userspace/configure
--- kvm-76/configure	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/configure	2008-10-12 09:38:23.000000000 +0200
@@ -1,6 +1,7 @@
 #!/bin/bash
 
 prefix=/usr/local
+kernelsourcedir=
 kerneldir=/lib/modules/$(uname -r)/build
 cc=gcc
 ld=ld
@@ -107,6 +108,11 @@
     qemu_ldflags="$qemu_ldflags -L $PWD/libfdt"
 fi
 
+# see if we have split build and source directories
+if [ -d "$kerneldir/include2" ]; then
+    kernelsourcedir=${kerneldir%/*}/source
+fi
+
 #configure user dir
 (cd user; ./configure --prefix="$prefix" --kerneldir="$libkvm_kerneldir" \
           --arch="$arch" \
@@ -129,6 +135,7 @@
 ARCH=$arch
 PREFIX=$prefix
 KERNELDIR=$kerneldir
+KERNELSOURCEDIR=$kernelsourcedir
 LIBKVM_KERNELDIR=$libkvm_kerneldir
 WANT_MODULE=$want_module
 CROSS_COMPILE=$cross_prefix
diff -Nur kvm-76/kernel/Makefile kvm-userspace/kernel/Makefile
--- kvm-76/kernel/Makefile	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/kernel/Makefile	2008-10-12 09:38:23.000000000 +0200
@@ -41,7 +41,9 @@
 all:: header-link prerequisite
 #	include header priority 1) $LINUX 2) $KERNELDIR 3) include-compat
 	$(MAKE) -C $(KERNELDIR) M=`pwd` \
-		LINUXINCLUDE="-I`pwd`/include -Iinclude -Iarch/${ARCH_DIR}/include -I`pwd`/include-compat \
+		LINUXINCLUDE="-I`pwd`/include -Iinclude \
+		$(if $(KERNELSOURCEDIR),-Iinclude2 -I$(KERNELSOURCEDIR)/include) \
+		-Iarch/${ARCH_DIR}/include -I`pwd`/include-compat \
 		-include include/linux/autoconf.h \
 		-include `pwd`/$(ARCH_DIR)/external-module-compat.h $(module_defines)"
 		"$$@"
diff -Nur kvm-76/kernel/ia64/Kbuild kvm-userspace/kernel/ia64/Kbuild
--- kvm-76/kernel/ia64/Kbuild	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/kernel/ia64/Kbuild	2008-10-12 09:38:23.000000000 +0200
@@ -1,7 +1,7 @@
 obj-m := kvm.o kvm-intel.o
 
 kvm-objs := kvm_main.o ioapic.o coalesced_mmio.o kvm-ia64.o kvm_fw.o \
-	../anon_inodes.o ../external-module-compat.o
+	irq_comm.o ../anon_inodes.o ../external-module-compat.o
 
 EXTRA_CFLAGS_vcpu.o += -mfixed-range=f2-f5,f12-f127
 kvm-intel-objs := vmm.o vmm_ivt.o trampoline.o vcpu.o optvfault.o mmio.o \
diff -Nur kvm-76/libkvm/libkvm-powerpc.c kvm-userspace/libkvm/libkvm-powerpc.c
--- kvm-76/libkvm/libkvm-powerpc.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/libkvm/libkvm-powerpc.c	2008-10-12 09:38:23.000000000 +0200
@@ -1,10 +1,7 @@
 /*
- * This header is for functions & variables that will ONLY be
- * used inside libkvm for x86.
- * THESE ARE NOT EXPOSED TO THE USER AND ARE ONLY FOR USE
- * WITHIN LIBKVM.
- *
- * derived from libkvm.c
+ * This file contains the powerpc specific implementation for the
+ * architecture dependent functions defined in kvm-common.h and
+ * libkvm.h
  *
  * Copyright (C) 2006 Qumranet, Inc.
  *
@@ -12,12 +9,11 @@
  *      Avi Kivity   <avi@qumranet.com>
  *      Yaniv Kamay  <yaniv@qumranet.com>
  *
- * Copyright 2007 IBM Corporation.
- * Added by & Authors:
+ * Copyright IBM Corp. 2007,2008
+ * Authors:
  * 	Jerone Young <jyoung5@us.ibm.com>
  * 	Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
  *
- *
  * This work is licensed under the GNU LGPL license, version 2.
  */
 
diff -Nur kvm-76/libkvm/libkvm.c kvm-userspace/libkvm/libkvm.c
--- kvm-76/libkvm/libkvm.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/libkvm/libkvm.c	2008-10-12 09:38:23.000000000 +0200
@@ -34,6 +34,7 @@
 #include <string.h>
 #include <errno.h>
 #include <sys/ioctl.h>
+#include <inttypes.h>
 #include "libkvm.h"
 
 #if defined(__x86_64__) || defined(__i386__)
@@ -69,6 +70,7 @@
 	unsigned long len;
 	unsigned long userspace_addr;
 	unsigned flags;
+	int logging_count;
 };
 
 struct slot_info slots[KVM_MAX_NUM_MEM_REGIONS];
@@ -120,6 +122,7 @@
 void free_slot(int slot)
 {
 	slots[slot].len = 0;
+	slots[slot].logging_count = 0;
 }
 
 int get_slot(unsigned long phys_addr)
@@ -158,17 +161,23 @@
 /* 
  * dirty pages logging control 
  */
-static int kvm_dirty_pages_log_change(kvm_context_t kvm, unsigned long phys_addr
-				      , __u32 flag)
+static int kvm_dirty_pages_log_change(kvm_context_t kvm,
+				      unsigned long phys_addr,
+				      unsigned flags,
+				      unsigned mask)
 {
 	int r = -1;
 	int slot = get_slot(phys_addr);
+
 	if (slot == -1) {
 		fprintf(stderr, "BUG: %s: invalid parameters\n", __FUNCTION__);
 		return 1;
 	}
 
-	flag |= slots[slot].flags;
+	flags = (slots[slot].flags & ~mask) | flags;
+	if (flags == slots[slot].flags)
+		return 0;
+	slots[slot].flags = flags;
 
 	{
 		struct kvm_userspace_memory_region mem = {
@@ -176,11 +185,15 @@
 			.memory_size = slots[slot].len,
 			.guest_phys_addr = slots[slot].phys_addr,
 			.userspace_addr = slots[slot].userspace_addr,
-			.flags = flag,
+			.flags = slots[slot].flags,
 		};
 
 
-
+		DPRINTF("slot %d start %llx len %llx flags %x\n",
+			mem.slot,
+			mem.guest_phys_addr,
+			mem.memory_size,
+			mem.flags);
 		r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &mem);
 		if (r == -1)
 			fprintf(stderr, "%s: %m\n", __FUNCTION__);
@@ -188,18 +201,59 @@
 	return r;
 }
 
-static int kvm_dirty_pages_log_change_all(kvm_context_t kvm, __u32 flag)
+static int kvm_dirty_pages_log_change_all(kvm_context_t kvm,
+					  int (*change)(kvm_context_t kvm,
+							uint64_t start,
+							uint64_t len))
 {
 	int i, r;
 
 	for (i=r=0; i<KVM_MAX_NUM_MEM_REGIONS && r==0; i++) {
 		if (slots[i].len)
-			r = kvm_dirty_pages_log_change(kvm, slots[i].phys_addr,
-						       flag);
+			r = change(kvm, slots[i].phys_addr, slots[i].len);
 	}
 	return r;
 }
 
+int kvm_dirty_pages_log_enable_slot(kvm_context_t kvm,
+				    uint64_t phys_addr,
+				    uint64_t len)
+{
+	int slot = get_slot(phys_addr);
+
+	DPRINTF("start %"PRIx64" len %"PRIx64"\n", phys_addr, len);
+	if (slot == -1) {
+		fprintf(stderr, "BUG: %s: invalid parameters\n", __func__);
+		return -EINVAL;
+	}
+
+	if (slots[slot].logging_count++)
+		return 0;
+
+	return kvm_dirty_pages_log_change(kvm, slots[slot].phys_addr,
+					  KVM_MEM_LOG_DIRTY_PAGES,
+					  KVM_MEM_LOG_DIRTY_PAGES);
+}
+
+int kvm_dirty_pages_log_disable_slot(kvm_context_t kvm,
+				     uint64_t phys_addr,
+				     uint64_t len)
+{
+	int slot = get_slot(phys_addr);
+
+	if (slot == -1) {
+		fprintf(stderr, "BUG: %s: invalid parameters\n", __func__);
+		return -EINVAL;
+	}
+
+	if (--slots[slot].logging_count)
+		return 0;
+
+	return kvm_dirty_pages_log_change(kvm, slots[slot].phys_addr,
+					  0,
+					  KVM_MEM_LOG_DIRTY_PAGES);
+}
+
 /**
  * Enable dirty page logging for all memory regions
  */
@@ -208,7 +262,8 @@
 	if (kvm->dirty_pages_log_all)
 		return 0;
 	kvm->dirty_pages_log_all = 1;
-	return kvm_dirty_pages_log_change_all(kvm, KVM_MEM_LOG_DIRTY_PAGES);
+	return kvm_dirty_pages_log_change_all(kvm,
+					      kvm_dirty_pages_log_enable_slot);
 }
 
 /**
@@ -220,7 +275,8 @@
 	if (!kvm->dirty_pages_log_all)
 		return 0;
 	kvm->dirty_pages_log_all = 0;
-	return kvm_dirty_pages_log_change_all(kvm, 0);
+	return kvm_dirty_pages_log_change_all(kvm,
+					      kvm_dirty_pages_log_disable_slot);
 }
 
 
@@ -430,6 +486,11 @@
 
 	memory.userspace_addr = (unsigned long)ptr;
 	memory.slot = get_free_slot(kvm);
+	DPRINTF("slot %d start %llx len %llx flags %x\n",
+		memory.slot,
+		memory.guest_phys_addr,
+		memory.memory_size,
+		memory.flags);
 	r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &memory);
 	if (r == -1) {
 		fprintf(stderr, "%s: %s", __func__, strerror(errno));
@@ -499,6 +560,11 @@
 	}
 
 	memory.slot = slot;
+	DPRINTF("slot %d start %llx len %llx flags %x\n",
+		memory.slot,
+		memory.guest_phys_addr,
+		memory.memory_size,
+		memory.flags);
 	r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &memory);
 	if (r == -1) {
 		fprintf(stderr, "destroy_userspace_phys_mem: %s",
@@ -766,6 +832,11 @@
 	return kvm->callbacks->try_push_interrupts(kvm->opaque);
 }
 
+int try_push_nmi(kvm_context_t kvm)
+{
+	return kvm->callbacks->try_push_nmi(kvm->opaque);
+}
+
 void post_kvm_run(kvm_context_t kvm, int vcpu)
 {
 	kvm->callbacks->post_kvm_run(kvm->opaque, vcpu);
@@ -790,6 +861,17 @@
 	return run->ready_for_interrupt_injection;
 }
 
+int kvm_is_ready_for_nmi_injection(kvm_context_t kvm, int vcpu)
+{
+#ifdef KVM_CAP_NMI
+	struct kvm_run *run = kvm->run[vcpu];
+
+	return run->ready_for_nmi_injection;
+#else
+	return 0;
+#endif
+}
+
 int kvm_run(kvm_context_t kvm, int vcpu)
 {
 	int r;
@@ -797,6 +879,9 @@
 	struct kvm_run *run = kvm->run[vcpu];
 
 again:
+#ifdef KVM_CAP_NMI
+	run->request_nmi_window = try_push_nmi(kvm);
+#endif
 #if !defined(__s390__)
 	if (!kvm->irqchip_in_kernel)
 		run->request_interrupt_window = try_push_interrupts(kvm);
@@ -872,6 +957,9 @@
 			r = handle_halt(kvm, vcpu);
 			break;
 		case KVM_EXIT_IRQ_WINDOW_OPEN:
+#ifdef KVM_CAP_NMI
+		case KVM_EXIT_NMI_WINDOW_OPEN:
+#endif
 			break;
 		case KVM_EXIT_SHUTDOWN:
 			r = handle_shutdown(kvm, vcpu);
@@ -956,6 +1044,15 @@
         return r;
 }
 
+int kvm_inject_nmi(kvm_context_t kvm, int vcpu)
+{
+#ifdef KVM_CAP_NMI
+	return ioctl(kvm->vcpu_fd[vcpu], KVM_NMI);
+#else
+	return -ENOSYS;
+#endif
+}
+
 int kvm_init_coalesced_mmio(kvm_context_t kvm)
 {
 	int r = 0;
diff -Nur kvm-76/libkvm/libkvm.h kvm-userspace/libkvm/libkvm.h
--- kvm-76/libkvm/libkvm.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/libkvm/libkvm.h	2008-10-12 09:38:23.000000000 +0200
@@ -66,6 +66,7 @@
     int (*shutdown)(void *opaque, int vcpu);
     int (*io_window)(void *opaque);
     int (*try_push_interrupts)(void *opaque);
+    int (*try_push_nmi)(void *opaque);
     void (*post_kvm_run)(void *opaque, int vcpu);
     int (*pre_kvm_run)(void *opaque, int vcpu);
     int (*tpr_access)(void *opaque, int vcpu, uint64_t rip, int is_write);
@@ -216,6 +217,17 @@
 int kvm_is_ready_for_interrupt_injection(kvm_context_t kvm, int vcpu);
 
 /*!
+ * \brief Check if a vcpu is ready for NMI injection
+ *
+ * This checks if vcpu is not already running in NMI context.
+ *
+ * \param kvm Pointer to the current kvm_context
+ * \param vcpu Which virtual CPU should get dumped
+ * \return boolean indicating NMI injection readiness
+ */
+int kvm_is_ready_for_nmi_injection(kvm_context_t kvm, int vcpu);
+
+/*!
  * \brief Read VCPU registers
  *
  * This gets the GP registers from the VCPU and outputs them
@@ -503,6 +515,12 @@
 				     void* bitmap, void* opaque));
 int kvm_set_irq_level(kvm_context_t kvm, int irq, int level);
 
+int kvm_dirty_pages_log_enable_slot(kvm_context_t kvm,
+				    uint64_t phys_start,
+				    uint64_t len);
+int kvm_dirty_pages_log_disable_slot(kvm_context_t kvm,
+				     uint64_t phys_start,
+				     uint64_t len);
 /*!
  * \brief Enable dirty-pages-logging for all memory regions
  *
@@ -578,6 +596,17 @@
 
 #endif
 
+/*!
+ * \brief Simulate an NMI
+ *
+ * This allows you to simulate a non-maskable interrupt.
+ *
+ * \param kvm Pointer to the current kvm_context
+ * \param vcpu Which virtual CPU should get dumped
+ * \return 0 on success
+ */
+int kvm_inject_nmi(kvm_context_t kvm, int vcpu);
+
 #endif
 
 /*!
diff -Nur kvm-76/patches/origin kvm-userspace/patches/origin
--- kvm-76/patches/origin	2008-09-28 20:38:11.000000000 +0200
+++ kvm-userspace/patches/origin	1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-v2.6.27-rc7-106-g6ef190c
diff -Nur kvm-76/qemu/Makefile kvm-userspace/qemu/Makefile
--- kvm-76/qemu/Makefile	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/Makefile	2008-10-12 09:38:23.000000000 +0200
@@ -81,6 +81,7 @@
 OBJS+=usb.o usb-hub.o usb-linux.o usb-hid.o usb-msd.o usb-wacom.o
 OBJS+=usb-serial.o usb-net.o
 OBJS+=sd.o ssi-sd.o
+OBJS+=bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
 
 ifdef CONFIG_BRLAPI
 OBJS+= baum.o
@@ -165,6 +166,9 @@
 curses.o: curses.c keymaps.c curses_keys.h
 	$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
+bt-host.o: bt-host.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(CONFIG_BLUEZ_CFLAGS) -c -o $@ $<
+
 audio/sdlaudio.o: audio/sdlaudio.c
 	$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) -c -o $@ $<
 
@@ -260,7 +264,7 @@
 
 cscope:
 	rm -f ./cscope.*
-	find . -name "*.[ch]" -print > ./cscope.files
+	find . -name "*.[ch]" -print | sed 's,^\./,,' > ./cscope.files
 	cscope -b
 
 # documentation
diff -Nur kvm-76/qemu/Makefile.target kvm-userspace/qemu/Makefile.target
--- kvm-76/qemu/Makefile.target	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/Makefile.target	2008-10-12 09:38:23.000000000 +0200
@@ -214,7 +214,7 @@
 endif
 
 ifeq ($(USE_KVM), 1)
-LIBOBJS+=qemu-kvm.o kvm-compatfd.o
+LIBOBJS+=qemu-kvm.o
 endif
 ifdef CONFIG_SOFTFLOAT
 LIBOBJS+=fpu/softfloat.o
@@ -586,9 +586,13 @@
 LIBS += $(CONFIG_VNC_TLS_LIBS)
 endif
 
+ifdef CONFIG_BLUEZ
+LIBS += $(CONFIG_BLUEZ_LIBS)
+endif
+
 ifdef CONFIG_LIBFDT
 LIBS += -lfdt
-DEPLIBS += libfdt.a
+DEPLIBS += ../libfdt/libfdt.a
 endif
 
 # SCSI layer
@@ -696,7 +700,7 @@
 OBJS+= omap2.o omap_dss.o soc_dma.o
 OBJS+= palm.o tsc210x.o
 OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o
-OBJS+= tsc2005.o
+OBJS+= tsc2005.o bt-hci-csr.o
 OBJS+= mst_fpga.o mainstone.o
 OBJS+= musicpal.o pflash_cfi02.o
 CPPFLAGS += -DHAS_AUDIO
diff -Nur kvm-76/qemu/audio/alsaaudio.c kvm-userspace/qemu/audio/alsaaudio.c
--- kvm-76/qemu/audio/alsaaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/alsaaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -917,7 +917,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-static struct audio_pcm_ops alsa_pcm_ops = {
+static const struct audio_pcm_ops alsa_pcm_ops = {
     alsa_init_out,
     alsa_fini_out,
     alsa_run_out,
diff -Nur kvm-76/qemu/audio/audio.c kvm-userspace/qemu/audio/audio.c
--- kvm-76/qemu/audio/audio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/audio.c	2008-10-12 09:38:23.000000000 +0200
@@ -212,7 +212,7 @@
         char *u = r + sizeof (qemu_prefix) - 1;
 
         pstrcpy (r, len + sizeof (qemu_prefix), qemu_prefix);
-        pstrcat (r, len, s);
+        pstrcat (r, len + sizeof (qemu_prefix), s);
 
         for (i = 0; i < len; ++i) {
             u[i] = toupper (u[i]);
@@ -467,16 +467,13 @@
         }
 
         pstrcpy (optname, optlen, qemu_prefix);
-        optlen -= preflen;
 
         /* copy while upper-casing, including trailing zero */
         for (i = 0; i <= preflen; ++i) {
             optname[i + sizeof (qemu_prefix) - 1] = toupper (prefix[i]);
         }
         pstrcat (optname, optlen, "_");
-        optlen--;
         pstrcat (optname, optlen, opt->name);
-        optlen -= len;
 
         def = 1;
         switch (opt->tag) {
diff -Nur kvm-76/qemu/audio/audio.h kvm-userspace/qemu/audio/audio.h
--- kvm-76/qemu/audio/audio.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/audio.h	2008-10-12 09:38:23.000000000 +0200
@@ -170,4 +170,7 @@
 #define audio_MAX(a, b) ((a)<(b)?(b):(a))
 #endif
 
+int wav_start_capture (CaptureState *s, const char *path, int freq,
+                       int bits, int nchannels);
+
 #endif  /* audio.h */
diff -Nur kvm-76/qemu/audio/audio_int.h kvm-userspace/qemu/audio/audio_int.h
--- kvm-76/qemu/audio/audio_int.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/audio_int.h	2008-10-12 09:38:23.000000000 +0200
@@ -81,7 +81,7 @@
     int samples;
     LIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head;
     LIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head;
-    struct audio_pcm_ops *pcm_ops;
+    const struct audio_pcm_ops *pcm_ops;
     LIST_ENTRY (HWVoiceOut) entries;
 } HWVoiceOut;
 
@@ -99,7 +99,7 @@
 
     int samples;
     LIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head;
-    struct audio_pcm_ops *pcm_ops;
+    const struct audio_pcm_ops *pcm_ops;
     LIST_ENTRY (HWVoiceIn) entries;
 } HWVoiceIn;
 
@@ -140,7 +140,7 @@
     struct audio_option *options;
     void *(*init) (void);
     void (*fini) (void *);
-    struct audio_pcm_ops *pcm_ops;
+    const struct audio_pcm_ops *pcm_ops;
     int can_be_default;
     int max_voices_out;
     int max_voices_in;
diff -Nur kvm-76/qemu/audio/coreaudio.c kvm-userspace/qemu/audio/coreaudio.c
--- kvm-76/qemu/audio/coreaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/coreaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -520,7 +520,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-static struct audio_pcm_ops coreaudio_pcm_ops = {
+static const struct audio_pcm_ops coreaudio_pcm_ops = {
     coreaudio_init_out,
     coreaudio_fini_out,
     coreaudio_run_out,
diff -Nur kvm-76/qemu/audio/dsoundaudio.c kvm-userspace/qemu/audio/dsoundaudio.c
--- kvm-76/qemu/audio/dsoundaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/dsoundaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -1057,7 +1057,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-static struct audio_pcm_ops dsound_pcm_ops = {
+static const struct audio_pcm_ops dsound_pcm_ops = {
     dsound_init_out,
     dsound_fini_out,
     dsound_run_out,
diff -Nur kvm-76/qemu/audio/esdaudio.c kvm-userspace/qemu/audio/esdaudio.c
--- kvm-76/qemu/audio/esdaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/esdaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -566,7 +566,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-struct audio_pcm_ops qesd_pcm_ops = {
+static const struct audio_pcm_ops qesd_pcm_ops = {
     qesd_init_out,
     qesd_fini_out,
     qesd_run_out,
diff -Nur kvm-76/qemu/audio/fmodaudio.c kvm-userspace/qemu/audio/fmodaudio.c
--- kvm-76/qemu/audio/fmodaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/fmodaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -657,7 +657,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-static struct audio_pcm_ops fmod_pcm_ops = {
+static const struct audio_pcm_ops fmod_pcm_ops = {
     fmod_init_out,
     fmod_fini_out,
     fmod_run_out,
diff -Nur kvm-76/qemu/audio/noaudio.c kvm-userspace/qemu/audio/noaudio.c
--- kvm-76/qemu/audio/noaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/noaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -145,7 +145,7 @@
     (void) opaque;
 }
 
-static struct audio_pcm_ops no_pcm_ops = {
+static const struct audio_pcm_ops no_pcm_ops = {
     no_init_out,
     no_fini_out,
     no_run_out,
diff -Nur kvm-76/qemu/audio/ossaudio.c kvm-userspace/qemu/audio/ossaudio.c
--- kvm-76/qemu/audio/ossaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/ossaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -751,7 +751,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-static struct audio_pcm_ops oss_pcm_ops = {
+static const struct audio_pcm_ops oss_pcm_ops = {
     oss_init_out,
     oss_fini_out,
     oss_run_out,
diff -Nur kvm-76/qemu/audio/paaudio.c kvm-userspace/qemu/audio/paaudio.c
--- kvm-76/qemu/audio/paaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/paaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -487,7 +487,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-struct audio_pcm_ops qpa_pcm_ops = {
+static const struct audio_pcm_ops qpa_pcm_ops = {
     qpa_init_out,
     qpa_fini_out,
     qpa_run_out,
diff -Nur kvm-76/qemu/audio/sdlaudio.c kvm-userspace/qemu/audio/sdlaudio.c
--- kvm-76/qemu/audio/sdlaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/sdlaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -423,7 +423,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-static struct audio_pcm_ops sdl_pcm_ops = {
+static const struct audio_pcm_ops sdl_pcm_ops = {
     sdl_init_out,
     sdl_fini_out,
     sdl_run_out,
diff -Nur kvm-76/qemu/audio/wavaudio.c kvm-userspace/qemu/audio/wavaudio.c
--- kvm-76/qemu/audio/wavaudio.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/wavaudio.c	2008-10-12 09:38:23.000000000 +0200
@@ -159,7 +159,7 @@
     le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
     le_store (hdr + 32, 1 << (bits16 + stereo), 2);
 
-    wav->f = qemu_fopen_file (conf.wav_path, "wb");
+    wav->f = qemu_fopen (conf.wav_path, "wb");
     if (!wav->f) {
         dolog ("Failed to open wave file `%s'\nReason: %s\n",
                conf.wav_path, strerror (errno));
@@ -218,7 +218,7 @@
     ldebug ("wav_fini");
 }
 
-struct audio_option wav_options[] = {
+static struct audio_option wav_options[] = {
     {"FREQUENCY", AUD_OPT_INT, &conf.settings.freq,
      "Frequency", NULL, 0},
 
@@ -233,7 +233,7 @@
     {NULL, 0, NULL, NULL, NULL, 0}
 };
 
-struct audio_pcm_ops wav_pcm_ops = {
+static const struct audio_pcm_ops wav_pcm_ops = {
     wav_init_out,
     wav_fini_out,
     wav_run_out,
diff -Nur kvm-76/qemu/audio/wavcapture.c kvm-userspace/qemu/audio/wavcapture.c
--- kvm-76/qemu/audio/wavcapture.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/audio/wavcapture.c	2008-10-12 09:38:23.000000000 +0200
@@ -134,7 +134,7 @@
     le_store (hdr + 28, freq << shift, 4);
     le_store (hdr + 32, 1 << shift, 2);
 
-    wav->f = qemu_fopen_file (path, "wb");
+    wav->f = qemu_fopen (path, "wb");
     if (!wav->f) {
         term_printf ("Failed to open wave file `%s'\nReason: %s\n",
                      path, strerror (errno));
diff -Nur kvm-76/qemu/block-raw-posix.c kvm-userspace/qemu/block-raw-posix.c
--- kvm-76/qemu/block-raw-posix.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/block-raw-posix.c	2008-10-12 09:38:23.000000000 +0200
@@ -84,10 +84,16 @@
    reopen it to see if the disk has been changed */
 #define FD_OPEN_TIMEOUT 1000
 
+/* posix-aio doesn't allow multiple outstanding requests to a single file
+ * descriptor.  we implement a pool of dup()'d file descriptors to work
+ * around this */
+#define RAW_FD_POOL_SIZE	64
+
 typedef struct BDRVRawState {
     int fd;
     int type;
     unsigned int lseek_err_cnt;
+    int fd_pool[RAW_FD_POOL_SIZE];
 #if defined(__linux__)
     /* linux floppy specific */
     int fd_open_flags;
@@ -109,6 +115,7 @@
 {
     BDRVRawState *s = bs->opaque;
     int fd, open_flags, ret;
+    int i;
 
     posix_aio_init();
 
@@ -138,6 +145,8 @@
         return ret;
     }
     s->fd = fd;
+    for (i = 0; i < RAW_FD_POOL_SIZE; i++)
+        s->fd_pool[i] = -1;
 #if defined(O_DIRECT)
     s->aligned_buf = NULL;
     if (flags & BDRV_O_DIRECT) {
@@ -436,6 +445,7 @@
 
 typedef struct RawAIOCB {
     BlockDriverAIOCB common;
+    int fd;
     struct aiocb aiocb;
     struct RawAIOCB *next;
     int ret;
@@ -447,6 +457,38 @@
     RawAIOCB *first_aio;
 } PosixAioState;
 
+static int raw_fd_pool_get(BDRVRawState *s)
+{
+    int i;
+
+    for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
+        /* already in use */
+        if (s->fd_pool[i] != -1)
+            continue;
+
+        /* try to dup file descriptor */
+        s->fd_pool[i] = dup(s->fd);
+        if (s->fd_pool[i] != -1)
+            return s->fd_pool[i];
+    }
+
+    /* we couldn't dup the file descriptor so just use the main one */
+    return s->fd;
+}
+
+static void raw_fd_pool_put(RawAIOCB *acb)
+{
+    BDRVRawState *s = acb->common.bs->opaque;
+    int i;
+
+    for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
+        if (s->fd_pool[i] == acb->fd) {
+            close(s->fd_pool[i]);
+            s->fd_pool[i] = -1;
+        }
+    }
+}
+
 static void posix_aio_read(void *opaque)
 {
     PosixAioState *s = opaque;
@@ -487,6 +529,7 @@
             if (ret == ECANCELED) {
                 /* remove the request */
                 *pacb = acb->next;
+                raw_fd_pool_put(acb);
                 qemu_aio_release(acb);
             } else if (ret != EINPROGRESS) {
                 /* end of aio */
@@ -503,6 +546,7 @@
                 *pacb = acb->next;
                 /* call the callback */
                 acb->common.cb(acb->common.opaque, ret);
+                raw_fd_pool_put(acb);
                 qemu_aio_release(acb);
                 break;
             } else {
@@ -540,20 +584,30 @@
     
     s->first_aio = NULL;
     s->fd = qemu_signalfd(&mask);
+    if (s->fd == -1) {
+        fprintf(stderr, "failed to create signalfd\n");
+        return -errno;
+    }
 
     fcntl(s->fd, F_SETFL, O_NONBLOCK);
 
     qemu_aio_set_fd_handler(s->fd, posix_aio_read, NULL, posix_aio_flush, s);
 
-#if defined(__linux__) && defined(__GLIBC_PREREQ) && !__GLIBC_PREREQ(2, 4)
+#if defined(__linux__)
     {
-        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
-           seems to fix the problem. */
         struct aioinit ai;
+
         memset(&ai, 0, sizeof(ai));
+#if defined(__GLIBC_PREREQ) && __GLIBC_PREREQ(2, 4)
+        ai.aio_threads = 64;
+        ai.aio_num = 64;
+#else
+        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
+           seems to fix the problem. */
         ai.aio_threads = 1;
         ai.aio_num = 1;
         ai.aio_idle_time = 365 * 100000;
+#endif
         aio_init(&ai);
     }
 #endif
@@ -575,7 +629,8 @@
     acb = qemu_aio_get(bs, cb, opaque);
     if (!acb)
         return NULL;
-    acb->aiocb.aio_fildes = s->fd;
+    acb->fd = raw_fd_pool_get(s);
+    acb->aiocb.aio_fildes = acb->fd;
     acb->aiocb.aio_sigevent.sigev_signo = SIGUSR2;
     acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
     acb->aiocb.aio_buf = buf;
@@ -682,6 +737,7 @@
             break;
         } else if (*pacb == acb) {
             *pacb = acb->next;
+            raw_fd_pool_put(acb);
             qemu_aio_release(acb);
             break;
         }
@@ -692,9 +748,22 @@
 #else /* CONFIG_AIO */
 static int posix_aio_init(void)
 {
+    return 0;
 }
 #endif /* CONFIG_AIO */
 
+static void raw_close_fd_pool(BDRVRawState *s)
+{
+    int i;
+
+    for (i = 0; i < RAW_FD_POOL_SIZE; i++) {
+        if (s->fd_pool[i] != -1) {
+            close(s->fd_pool[i]);
+            s->fd_pool[i] = -1;
+        }
+    }
+}
+
 static void raw_close(BlockDriverState *bs)
 {
     BDRVRawState *s = bs->opaque;
@@ -706,6 +775,7 @@
             qemu_free(s->aligned_buf);
 #endif
     }
+    raw_close_fd_pool(s);
 }
 
 static int raw_truncate(BlockDriverState *bs, int64_t offset)
@@ -896,7 +966,7 @@
 static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVRawState *s = bs->opaque;
-    int fd, open_flags, ret;
+    int fd, open_flags, ret, i;
 
     posix_aio_init();
 
@@ -961,6 +1031,8 @@
         return ret;
     }
     s->fd = fd;
+    for (i = 0; i < RAW_FD_POOL_SIZE; i++)
+        s->fd_pool[i] = -1;
 #if defined(__linux__)
     /* close fd so that we can reopen it as needed */
     if (s->type == FTYPE_FD) {
@@ -973,7 +1045,6 @@
 }
 
 #if defined(__linux__)
-
 /* Note: we do not have a reliable method to detect if the floppy is
    present. The current method is to try to open the floppy at every
    I/O and to keep it opened during a few hundreds of ms. */
@@ -989,6 +1060,7 @@
         (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
         close(s->fd);
         s->fd = -1;
+        raw_close_fd_pool(s);
 #ifdef DEBUG_FLOPPY
         printf("Floppy closed\n");
 #endif
@@ -1089,6 +1161,7 @@
             if (s->fd >= 0) {
                 close(s->fd);
                 s->fd = -1;
+                raw_close_fd_pool(s);
             }
             fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
             if (fd >= 0) {
diff -Nur kvm-76/qemu/block-vmdk.c kvm-userspace/qemu/block-vmdk.c
--- kvm-76/qemu/block-vmdk.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/block-vmdk.c	2008-10-12 09:38:23.000000000 +0200
@@ -709,13 +709,13 @@
         "createType=\"monolithicSparse\"\n"
         "\n"
         "# Extent description\n"
-        "RW %lu SPARSE \"%s\"\n"
+        "RW %" PRId64 " SPARSE \"%s\"\n"
         "\n"
         "# The Disk Data Base \n"
         "#DDB\n"
         "\n"
         "ddb.virtualHWVersion = \"%d\"\n"
-        "ddb.geometry.cylinders = \"%lu\"\n"
+        "ddb.geometry.cylinders = \"%" PRId64 "\"\n"
         "ddb.geometry.heads = \"16\"\n"
         "ddb.geometry.sectors = \"63\"\n"
         "ddb.adapterType = \"ide\"\n";
@@ -791,8 +791,9 @@
     if ((temp_str = strrchr(real_filename, ':')) != NULL)
         real_filename = temp_str + 1;
     snprintf(desc, sizeof(desc), desc_template, (unsigned int)time(NULL),
-             (unsigned long)total_size, real_filename,
-             (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), total_size / (63 * 16));
+             total_size, real_filename,
+             (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4),
+             total_size / (int64_t)(63 * 16));
 
     /* write the descriptor */
     lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET);
diff -Nur kvm-76/qemu/bt-host.c kvm-userspace/qemu/bt-host.c
--- kvm-76/qemu/bt-host.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/bt-host.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,207 @@
+/*
+ * Wrap a host Bluetooth HCI socket in a struct HCIInfo.
+ *
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+#include "net.h"
+
+#ifndef _WIN32
+# include <errno.h>
+# include <sys/ioctl.h>
+# include <sys/uio.h>
+# ifdef CONFIG_BLUEZ
+#  include <bluetooth/bluetooth.h>
+#  include <bluetooth/hci.h>
+#  include <bluetooth/hci_lib.h>
+# else
+#  include "hw/bt.h"
+#  define HCI_MAX_FRAME_SIZE	1028
+# endif
+
+struct bt_host_hci_s {
+    struct HCIInfo hci;
+    int fd;
+
+    uint8_t hdr[HCI_MAX_FRAME_SIZE];
+    int len;
+};
+
+static void bt_host_send(struct HCIInfo *hci,
+                int type, const uint8_t *data, int len)
+{
+    struct bt_host_hci_s *s = (struct bt_host_hci_s *) hci;
+    uint8_t pkt = type;
+    struct iovec iv[2];
+    int ret;
+
+    iv[0].iov_base = &pkt;
+    iv[0].iov_len  = 1;
+    iv[1].iov_base = (void *) data;
+    iv[1].iov_len  = len;
+
+    while ((ret = writev(s->fd, iv, 2)) < 0)
+        if (errno != EAGAIN && errno != EINTR) {
+            fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
+                            errno);
+            return;
+        }
+}
+
+static void bt_host_cmd(struct HCIInfo *hci, const uint8_t *data, int len)
+{
+    bt_host_send(hci, HCI_COMMAND_PKT, data, len);
+}
+
+static void bt_host_acl(struct HCIInfo *hci, const uint8_t *data, int len)
+{
+    bt_host_send(hci, HCI_ACLDATA_PKT, data, len);
+}
+
+static void bt_host_sco(struct HCIInfo *hci, const uint8_t *data, int len)
+{
+    bt_host_send(hci, HCI_SCODATA_PKT, data, len);
+}
+
+static int bt_host_read_poll(void *opaque)
+{
+    struct bt_host_hci_s *s = (struct bt_host_hci_s *) opaque;
+
+    return !!s->hci.evt_recv;
+}
+
+static void bt_host_read(void *opaque)
+{
+    struct bt_host_hci_s *s = (struct bt_host_hci_s *) opaque;
+    uint8_t *pkt;
+    int pktlen;
+
+    /* Seems that we can't read only the header first and then the amount
+     * of data indicated in the header because Linux will discard everything
+     * that's not been read in one go.  */
+    s->len = read(s->fd, s->hdr, sizeof(s->hdr));
+
+    if (s->len < 0) {
+        fprintf(stderr, "qemu: error %i reading HCI frame\n", errno);
+        return;
+    }
+
+    pkt = s->hdr;
+    while (s->len --)
+        switch (*pkt ++) {
+        case HCI_EVENT_PKT:
+            if (s->len < 2)
+                goto bad_pkt;
+
+            pktlen = MIN(pkt[1] + 2, s->len);
+            s->hci.evt_recv(s->hci.opaque, pkt, pktlen);
+            s->len -= pktlen;
+            pkt += pktlen;
+
+            /* TODO: if this is an Inquiry Result event, it's also
+             * interpreted by Linux kernel before we received it, possibly
+             * we should clean the kernel Inquiry cache through
+             * ioctl(s->fd, HCI_INQUIRY, ...).  */
+            break;
+
+        case HCI_ACLDATA_PKT:
+            if (s->len < 4)
+                goto bad_pkt;
+
+            pktlen = MIN(((pkt[3] << 8) | pkt[2]) + 4, s->len);
+            s->hci.acl_recv(s->hci.opaque, pkt, pktlen);
+            s->len -= pktlen;
+            pkt += pktlen;
+            break;
+
+        case HCI_SCODATA_PKT:
+            if (s->len < 3)
+                goto bad_pkt;
+
+            pktlen = MIN(pkt[2] + 3, s->len);
+            s->len -= pktlen;
+            pkt += pktlen;
+
+        default:
+        bad_pkt:
+            fprintf(stderr, "qemu: bad HCI packet type %02x\n", pkt[-1]);
+        }
+}
+
+static int bt_host_bdaddr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
+{
+    return -ENOTSUP;
+}
+
+struct HCIInfo *bt_host_hci(const char *id)
+{
+    struct bt_host_hci_s *s;
+    int fd = -1;
+# ifdef CONFIG_BLUEZ
+    int dev_id = hci_devid(id);
+    struct hci_filter flt;
+
+    if (dev_id < 0) {
+        fprintf(stderr, "qemu: `%s' not available\n", id);
+        return 0;
+    }
+
+    fd = hci_open_dev(dev_id);
+
+    /* XXX: can we ensure nobody else has the device opened?  */
+# endif
+
+    if (fd < 0) {
+        fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
+                        id, strerror(errno), errno);
+        return 0;
+    }
+
+# ifdef CONFIG_BLUEZ
+    hci_filter_clear(&flt);
+    hci_filter_all_ptypes(&flt);
+    hci_filter_all_events(&flt);
+
+    if (setsockopt(fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
+        fprintf(stderr, "qemu: Can't set HCI filter on socket (%i)\n", errno);
+        return 0;
+    }
+# endif
+
+    s = qemu_mallocz(sizeof(struct bt_host_hci_s));
+    s->fd = fd;
+    s->hci.cmd_send = bt_host_cmd;
+    s->hci.sco_send = bt_host_sco;
+    s->hci.acl_send = bt_host_acl;
+    s->hci.bdaddr_set = bt_host_bdaddr_set;
+
+    qemu_set_fd_handler2(s->fd, bt_host_read_poll, bt_host_read, 0, s);
+
+    return &s->hci;
+}
+#else
+struct HCIInfo *bt_host_hci(const char *id)
+{
+    fprintf(stderr, "qemu: bluetooth passthrough not supported (yet)\n", errno);
+
+    return 0;
+}
+#endif
diff -Nur kvm-76/qemu/bt-vhci.c kvm-userspace/qemu/bt-vhci.c
--- kvm-76/qemu/bt-vhci.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/bt-vhci.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,170 @@
+/*
+ * Support for host VHCIs inside qemu scatternets.
+ *
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+#include "net.h"
+#include "hw/bt.h"
+
+#define VHCI_DEV	"/dev/vhci"
+#define VHCI_UDEV	"/dev/hci_vhci"
+
+struct bt_vhci_s {
+    int fd;
+    struct HCIInfo *info;
+
+    uint8_t hdr[4096];
+    int len;
+};
+
+static void vhci_read(void *opaque)
+{
+    struct bt_vhci_s *s = (struct bt_vhci_s *) opaque;
+    uint8_t *pkt;
+    int pktlen;
+
+    /* Seems that we can't read only the header first and then the amount
+     * of data indicated in the header because Linux will discard everything
+     * that's not been read in one go.  */
+    s->len = read(s->fd, s->hdr, sizeof(s->hdr));
+
+    if (s->len < 0) {
+        fprintf(stderr, "qemu: error %i reading the PDU\n", errno);
+        return;
+    }
+
+    pkt = s->hdr;
+    while (s->len --)
+        switch (*pkt ++) {
+        case HCI_COMMAND_PKT:
+            if (s->len < 3)
+                goto bad_pkt;
+
+            pktlen = MIN(pkt[2] + 3, s->len);
+            s->info->cmd_send(s->info, pkt, pktlen);
+            s->len -= pktlen;
+            pkt += pktlen;
+            break;
+
+        case HCI_ACLDATA_PKT:
+            if (s->len < 4)
+                goto bad_pkt;
+
+            pktlen = MIN(((pkt[3] << 8) | pkt[2]) + 4, s->len);
+            s->info->acl_send(s->info, pkt, pktlen);
+            s->len -= pktlen;
+            pkt += pktlen;
+            break;
+
+        case HCI_SCODATA_PKT:
+            if (s->len < 3)
+                goto bad_pkt;
+
+            pktlen = MIN(pkt[2] + 3, s->len);
+            s->info->sco_send(s->info, pkt, pktlen);
+            s->len -= pktlen;
+            pkt += pktlen;
+            break;
+
+        default:
+        bad_pkt:
+            fprintf(stderr, "qemu: bad HCI packet type %02x\n", pkt[-1]);
+        }
+}
+
+static void vhci_host_send(void *opaque,
+                int type, const uint8_t *data, int len)
+{
+    struct bt_vhci_s *s = (struct bt_vhci_s *) opaque;
+#if 0
+    uint8_t pkt = type;
+    struct iovec iv[2];
+
+    iv[0].iov_base = &pkt;
+    iv[0].iov_len  = 1;
+    iv[1].iov_base = (void *) data;
+    iv[1].iov_len  = len;
+
+    while (writev(s->fd, iv, 2) < 0)
+        if (errno != EAGAIN && errno != EINTR) {
+            fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
+                            errno);
+            return;
+        }
+#else
+    /* Apparently VHCI wants us to write everything in one chunk :-(  */
+    static uint8_t buf[4096];
+
+    buf[0] = type;
+    memcpy(buf + 1, data, len);
+
+    while (write(s->fd, buf, len + 1) < 0)
+        if (errno != EAGAIN && errno != EINTR) {
+            fprintf(stderr, "qemu: error %i writing bluetooth packet.\n",
+                            errno);
+            return;
+        }
+#endif
+}
+
+static void vhci_out_hci_packet_event(void *opaque,
+                const uint8_t *data, int len)
+{
+    vhci_host_send(opaque, HCI_EVENT_PKT, data, len);
+}
+
+static void vhci_out_hci_packet_acl(void *opaque,
+                const uint8_t *data, int len)
+{
+    vhci_host_send(opaque, HCI_ACLDATA_PKT, data, len);
+}
+
+void bt_vhci_init(struct HCIInfo *info)
+{
+    struct bt_vhci_s *s;
+    int err[2];
+    int fd;
+
+    fd = open(VHCI_DEV, O_RDWR);
+    err[0] = errno;
+    if (fd < 0) {
+        fd = open(VHCI_UDEV, O_RDWR);
+        err[1] = errno;
+    }
+
+    if (fd < 0) {
+        fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
+                        VHCI_DEV, strerror(err[0]), err[0]);
+        fprintf(stderr, "qemu: Can't open `%s': %s (%i)\n",
+                        VHCI_UDEV, strerror(err[1]), err[1]);
+        exit(-1);
+    }
+
+    s = qemu_mallocz(sizeof(struct bt_vhci_s));
+    s->fd = fd;
+    s->info = info ?: qemu_next_hci();
+    s->info->opaque = s;
+    s->info->evt_recv = vhci_out_hci_packet_event;
+    s->info->acl_recv = vhci_out_hci_packet_acl;
+
+    qemu_set_fd_handler(s->fd, vhci_read, 0, s);
+}
diff -Nur kvm-76/qemu/compatfd.c kvm-userspace/qemu/compatfd.c
--- kvm-76/qemu/compatfd.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/compatfd.c	2008-10-12 09:38:23.000000000 +0200
@@ -33,35 +33,35 @@
     sigprocmask(SIG_BLOCK, &all, NULL);
 
     do {
-	siginfo_t siginfo;
+        siginfo_t siginfo;
 
-	err = sigwaitinfo(&info->mask, &siginfo);
-	if (err == -1 && errno == EINTR) {
+        err = sigwaitinfo(&info->mask, &siginfo);
+        if (err == -1 && errno == EINTR) {
             err = 0;
             continue;
         }
 
-	if (err > 0) {
-	    char buffer[128];
-	    size_t offset = 0;
-
-	    memcpy(buffer, &err, sizeof(err));
-	    while (offset < sizeof(buffer)) {
-		ssize_t len;
-
-		len = write(info->fd, buffer + offset,
-			    sizeof(buffer) - offset);
-		if (len == -1 && errno == EINTR)
-		    continue;
-
-		if (len <= 0) {
-		    err = -1;
-		    break;
-		}
-
-		offset += len;
-	    }
-	}
+        if (err > 0) {
+            char buffer[128];
+            size_t offset = 0;
+
+            memcpy(buffer, &err, sizeof(err));
+            while (offset < sizeof(buffer)) {
+                ssize_t len;
+
+                len = write(info->fd, buffer + offset,
+                            sizeof(buffer) - offset);
+                if (len == -1 && errno == EINTR)
+                    continue;
+
+                if (len <= 0) {
+                    err = -1;
+                    break;
+                }
+
+                offset += len;
+            }
+        }
     } while (err >= 0);
 
     return NULL;
@@ -76,13 +76,13 @@
 
     info = malloc(sizeof(*info));
     if (info == NULL) {
-	errno = ENOMEM;
-	return -1;
+        errno = ENOMEM;
+        return -1;
     }
 
     if (pipe(fds) == -1) {
-	free(info);
-	return -1;
+        free(info);
+        return -1;
     }
 
     memcpy(&info->mask, mask, sizeof(*mask));
@@ -100,12 +100,12 @@
 
 int qemu_signalfd(const sigset_t *mask)
 {
-#if defined(SYS_signalfd)
+#if defined(CONFIG_signalfd)
     int ret;
 
     ret = syscall(SYS_signalfd, -1, mask, _NSIG / 8);
-    if (!(ret == -1 && errno == ENOSYS))
-	return ret;
+    if (ret != -1)
+        return ret;
 #endif
 
     return qemu_signalfd_compat(mask);
@@ -113,15 +113,14 @@
 
 int qemu_eventfd(int *fds)
 {
-#if defined(SYS_eventfd)
+#if defined(CONFIG_eventfd)
     int ret;
 
     ret = syscall(SYS_eventfd, 0);
     if (ret >= 0) {
-	fds[0] = fds[1] = ret;
-	return 0;
-    } else if (!(ret == -1 && errno == ENOSYS))
-	return ret;
+        fds[0] = fds[1] = ret;
+        return 0;
+    }
 #endif
 
     return pipe(fds);
diff -Nur kvm-76/qemu/configure kvm-userspace/qemu/configure
--- kvm-76/qemu/configure	2008-09-28 20:38:17.000000000 +0200
+++ kvm-userspace/qemu/configure	2008-10-12 09:38:23.000000000 +0200
@@ -15,6 +15,7 @@
 TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
 TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}"
 TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S"
+TMPI="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.i"
 
 # default parameters
 prefix=""
@@ -113,6 +114,9 @@
 aio="yes"
 nptl="yes"
 mixemu="no"
+bluez="yes"
+signalfd="no"
+eventfd="no"
 cpu_emulation="yes"
 device_tree_support=""
 
@@ -309,6 +313,8 @@
   ;;
   --disable-brlapi) brlapi="no"
   ;;
+  --disable-bluez) bluez="no"
+  ;;
   --enable-profiler) profiler="yes"
   ;;
   --kernel-path=*) kernel_path="$optarg"
@@ -453,6 +459,7 @@
 echo "  --disable-brlapi         disable BrlAPI"
 echo "  --disable-vnc-tls        disable TLS encryption for VNC server"
 echo "  --disable-curses         disable curses output"
+echo "  --disable-bluez          disable bluez stack connectivity"
 echo "  --disable-nptl           disable usermode NPTL support"
 echo "  --enable-system          enable all system emulation targets"
 echo "  --disable-system         disable all system emulation targets"
@@ -510,8 +517,10 @@
     linux_user="no"
 fi
 
-if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
+if [ "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
     AIOLIBS=
+elif [ "$bsd" = "yes" ]; then
+    AIOLIBS="-lpthread"
 else
     # Some Linux architectures (e.g. s390) don't imply -lpthread automatically.
     AIOLIBS="-lrt -lpthread"
@@ -693,17 +702,8 @@
 
 # ppc specific hostlongbits selection
 if test "$cpu" = "powerpc" ; then
-    cat > $TMPC <<EOF
-int main(void){return sizeof(long);}
-EOF
-
-    if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null; then
-        $TMPE
-        case $? in
-            4) hostlongbits="32";;
-            8) hostlongbits="64";;
-            *) echo "Couldn't determine bits per long value"; exit 1;;
-        esac
+    if $cc $ARCH_CFLAGS -dM -E - -o $TMPI 2>/dev/null </dev/null; then
+        grep -q __powerpc64__ $TMPI && hostlongbits=64
     else
         echo hostlongbits test failed
         exit 1
@@ -931,6 +931,26 @@
 fi # test "$curses"
 
 ##########################################
+# bluez support probe
+if test "$bluez" = "yes" ; then
+  `pkg-config bluez` || bluez="no"
+fi
+if test "$bluez" = "yes" ; then
+  cat > $TMPC << EOF
+#include <bluetooth/bluetooth.h>
+int main(void) { return bt_error(0); }
+EOF
+  bluez_cflags=`pkg-config --cflags bluez`
+  bluez_libs=`pkg-config --libs bluez`
+  if $cc $ARCH_CFLAGS -o $TMPE ${OS_FLAGS} $bluez_cflags $TMPC \
+      $bluez_libs 2> /dev/null ; then
+    :
+  else
+    bluez="no"
+  fi
+fi
+
+##########################################
 # AIO probe
 if test "$aio" = "yes" ; then
   aio=no
@@ -943,6 +963,33 @@
   fi
 fi
 
+##########################################
+# signalfd probe
+cat > $TMPC << EOF
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <signal.h>
+int main(void) { return syscall(SYS_signalfd, -1, NULL, _NSIG / 8); }
+EOF
+
+if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
+  signalfd=yes
+fi
+
+##########################################
+# eventfd probe
+cat > $TMPC << EOF
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+int main(void) { return syscall(SYS_eventfd, 0); }
+EOF
+
+if $cc $ARCH_CFLAGS -o $TMPE $TMPC 2> /dev/null ; then
+  eventfd=yes
+fi
+
 # Check if tools are available to build documentation.
 if [ -x "`which texi2html 2>/dev/null`" ] && \
    [ -x "`which pod2man 2>/dev/null`" ]; then
@@ -1255,7 +1302,7 @@
 qemu_version=`head $source_path/VERSION`
 echo "VERSION=$qemu_version" >>$config_mak
 echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
-echo "#define KVM_VERSION \"kvm-76\"" >> $config_h
+echo "#define KVM_VERSION \"kvm-devel\"" >> $config_h
 
 echo "SRC_PATH=$source_path" >> $config_mak
 if [ "$source_path_used" = "yes" ]; then
@@ -1298,10 +1345,22 @@
   echo "#define CONFIG_BRLAPI 1" >> $config_h
   echo "BRLAPI_LIBS=-lbrlapi" >> $config_mak
 fi
+if test "$bluez" = "yes" ; then
+  echo "CONFIG_BLUEZ=yes" >> $config_mak
+  echo "CONFIG_BLUEZ_CFLAGS=$bluez_cflags" >> $config_mak
+  echo "CONFIG_BLUEZ_LIBS=$bluez_libs" >> $config_mak
+  echo "#define CONFIG_BLUEZ 1" >> $config_h
+fi
 if test "$aio" = "yes" ; then
   echo "#define CONFIG_AIO 1" >> $config_h
   echo "CONFIG_AIO=yes" >> $config_mak
 fi
+if test "$signalfd" = "yes" ; then
+  echo "#define CONFIG_signalfd 1" >> $config_h
+fi
+if test "$eventfd" = "yes" ; then
+  echo "#define CONFIG_eventfd 1" >> $config_h
+fi
 
 # XXX: suppress that
 if [ "$bsd" = "yes" ] ; then
@@ -1462,10 +1521,8 @@
   ;;
   alpha)
     echo "TARGET_ARCH=alpha" >> $config_mak
-    echo "CONFIG_DYNGEN_OP=yes" >> $config_mak
     echo "#define TARGET_ARCH \"alpha\"" >> $config_h
     echo "#define TARGET_ALPHA 1" >> $config_h
-    echo "#define CONFIG_DYNGEN_OP 1" >> $config_h
   ;;
   arm|armeb)
     echo "TARGET_ARCH=arm" >> $config_mak
@@ -1648,4 +1705,4 @@
     done
 fi
 
-rm -f $TMPO $TMPC $TMPE $TMPS
+rm -f $TMPO $TMPC $TMPE $TMPS $TMPI
diff -Nur kvm-76/qemu/cpu-all.h kvm-userspace/qemu/cpu-all.h
--- kvm-76/qemu/cpu-all.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/cpu-all.h	2008-10-12 09:38:23.000000000 +0200
@@ -797,7 +797,7 @@
     const char *help;
 } CPULogItem;
 
-extern CPULogItem cpu_log_items[];
+extern const CPULogItem cpu_log_items[];
 
 void cpu_set_log(int log_flags);
 void cpu_set_log_filename(const char *filename);
diff -Nur kvm-76/qemu/curses_keys.h kvm-userspace/qemu/curses_keys.h
--- kvm-76/qemu/curses_keys.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/curses_keys.h	2008-10-12 09:38:23.000000000 +0200
@@ -37,7 +37,7 @@
 
 #define CURSES_KEYS         KEY_MAX     /* KEY_MAX defined in <curses.h> */
 
-int curses2keycode[CURSES_KEYS] = {
+static const int curses2keycode[CURSES_KEYS] = {
     [0 ... (CURSES_KEYS - 1)] = -1,
 
     [0x01b] = 1, /* Escape */
@@ -216,7 +216,7 @@
 
 };
 
-int curses2keysym[CURSES_KEYS] = {
+static const int curses2keysym[CURSES_KEYS] = {
     [0 ... (CURSES_KEYS - 1)] = -1,
 
     ['\n'] = '\n',
@@ -244,7 +244,7 @@
 	int keysym;
 } name2keysym_t;
 
-static name2keysym_t name2keysym[] = {
+static const name2keysym_t name2keysym[] = {
     /* Plain ASCII */
     { "space", 0x020 },
     { "exclam", 0x021 },
diff -Nur kvm-76/qemu/darwin-user/qemu.h kvm-userspace/qemu/darwin-user/qemu.h
--- kvm-76/qemu/darwin-user/qemu.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/darwin-user/qemu.h	2008-10-12 09:38:23.000000000 +0200
@@ -109,8 +109,7 @@
 void init_paths(const char *prefix);
 const char *path(const char *pathname);
 
-extern int loglevel;
-extern FILE *logfile;
+#include "qemu-log.h"
 
 /* commpage.c */
 void commpage_init(void);
diff -Nur kvm-76/qemu/darwin-user/syscall.c kvm-userspace/qemu/darwin-user/syscall.c
--- kvm-76/qemu/darwin-user/syscall.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/darwin-user/syscall.c	2008-10-12 09:38:23.000000000 +0200
@@ -654,7 +654,7 @@
 
 #define MAX_STRUCT_SIZE 4096
 
-IOCTLEntry ioctl_entries[] = {
+static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, types...) \
     { cmd, cmd, #cmd, access, { types } },
 #include "ioctls.h"
diff -Nur kvm-76/qemu/exec.c kvm-userspace/qemu/exec.c
--- kvm-76/qemu/exec.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/exec.c	2008-10-12 09:38:23.000000000 +0200
@@ -89,10 +89,10 @@
 #define TARGET_PHYS_ADDR_SPACE_BITS 32
 #endif
 
-TranslationBlock *tbs;
+static TranslationBlock *tbs;
 int code_gen_max_blocks;
 TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
-int nb_tbs;
+static int nb_tbs;
 /* any access to the tbs or the page table must use this lock */
 spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
 
@@ -109,10 +109,10 @@
 #endif
 
 uint8_t code_gen_prologue[1024] code_gen_section;
-uint8_t *code_gen_buffer;
-unsigned long code_gen_buffer_size;
+static uint8_t *code_gen_buffer;
+static unsigned long code_gen_buffer_size;
 /* threshold to flush the translated code buffer */
-unsigned long code_gen_buffer_max_size; 
+static unsigned long code_gen_buffer_max_size;
 uint8_t *code_gen_ptr;
 
 #if !defined(CONFIG_USER_ONLY)
@@ -175,7 +175,7 @@
 
 /* XXX: for system emulation, it could just be an array */
 static PageDesc *l1_map[L1_SIZE];
-PhysPageDesc **l1_phys_map;
+static PhysPageDesc **l1_phys_map;
 
 #if !defined(CONFIG_USER_ONLY)
 static void io_mem_init(void);
@@ -189,7 +189,7 @@
 #endif
 
 /* log support */
-const char *logfilename = "/tmp/qemu.log";
+static const char *logfilename = "/tmp/qemu.log";
 FILE *logfile;
 int loglevel;
 static int log_append = 0;
@@ -455,6 +455,28 @@
             exit(1);
         }
     }
+#elif defined(__FreeBSD__)
+    {
+        int flags;
+        void *addr = NULL;
+        flags = MAP_PRIVATE | MAP_ANONYMOUS;
+#if defined(__x86_64__)
+        /* FreeBSD doesn't have MAP_32BIT, use MAP_FIXED and assume
+         * 0x40000000 is free */
+        flags |= MAP_FIXED;
+        addr = (void *)0x40000000;
+        /* Cannot map more than that */
+        if (code_gen_buffer_size > (800 * 1024 * 1024))
+            code_gen_buffer_size = (800 * 1024 * 1024);
+#endif
+        code_gen_buffer = mmap(addr, code_gen_buffer_size,
+                               PROT_WRITE | PROT_READ | PROT_EXEC, 
+                               flags, -1, 0);
+        if (code_gen_buffer == MAP_FAILED) {
+            fprintf(stderr, "Could not allocate dynamic translator buffer\n");
+            exit(1);
+        }
+    }
 #else
     code_gen_buffer = qemu_malloc(code_gen_buffer_size);
     if (!code_gen_buffer) {
@@ -632,7 +654,7 @@
     }
 }
 
-void tb_jmp_check(TranslationBlock *tb)
+static void tb_jmp_check(TranslationBlock *tb)
 {
     TranslationBlock *tb1;
     unsigned int n1;
@@ -1516,7 +1538,7 @@
     env->interrupt_request &= ~mask;
 }
 
-CPULogItem cpu_log_items[] = {
+const CPULogItem cpu_log_items[] = {
     { CPU_LOG_TB_OUT_ASM, "out_asm",
       "show generated host assembly code for each compiled TB" },
     { CPU_LOG_TB_IN_ASM, "in_asm",
@@ -1556,7 +1578,7 @@
 /* takes a comma separated list of log masks. Return 0 if error. */
 int cpu_str_to_log_mask(const char *str)
 {
-    CPULogItem *item;
+    const CPULogItem *item;
     int mask;
     const char *p, *p1;
 
@@ -2296,7 +2318,7 @@
 {
     ram_addr_t addr;
     if ((phys_ram_alloc_offset + size) > phys_ram_size) {
-        fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 "\n",
+        fprintf(stderr, "Not enough memory (requested_size = %" PRIu64 ", max memory = %" PRIu64 ")\n",
                 (uint64_t)size, (uint64_t)phys_ram_size);
         abort();
     }
diff -Nur kvm-76/qemu/hw/acpi.c kvm-userspace/qemu/hw/acpi.c
--- kvm-76/qemu/hw/acpi.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/acpi.c	2008-10-12 09:38:23.000000000 +0200
@@ -726,7 +726,11 @@
 {
     CPUState *env;
 
-    if ((state) && (!qemu_kvm_cpu_env(cpu))) {
+    if (state
+#ifdef USE_KVM
+        && (!qemu_kvm_cpu_env(cpu))
+#endif
+    ) {
         env = pc_new_cpu(cpu, model, 1);
         if (!env) {
             fprintf(stderr, "cpu %d creation failed\n", cpu);
diff -Nur kvm-76/qemu/hw/apic.c kvm-userspace/qemu/hw/apic.c
--- kvm-76/qemu/hw/apic.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/apic.c	2008-10-12 09:38:23.000000000 +0200
@@ -114,7 +114,7 @@
 {
     unsigned int ret = 0;
 
-#if defined(HOST_I386)
+#if defined(HOST_I386) || defined(HOST_X86_64)
     __asm__ __volatile__ ("bsr %1, %0\n" : "+r" (ret) : "rm" (value));
     return ret;
 #else
@@ -135,7 +135,7 @@
 {
     unsigned int ret = 0;
 
-#if defined(HOST_I386)
+#if defined(HOST_I386) || defined(HOST_X86_64)
     __asm__ __volatile__ ("bsf %1, %0\n" : "+r" (ret) : "rm" (value));
     return ret;
 #else
@@ -467,6 +467,11 @@
     s->initial_count_load_time = 0;
     s->next_time = 0;
 
+    cpu_reset(s->cpu_env);
+
+    if (!(s->apicbase & MSR_IA32_APICBASE_BSP))
+        s->cpu_env->halted = 1;
+
     if (kvm_enabled() && !qemu_kvm_irqchip_in_kernel())
 	if (s->cpu_env)
 	    kvm_apic_init(s->cpu_env);
diff -Nur kvm-76/qemu/hw/boards.h kvm-userspace/qemu/hw/boards.h
--- kvm-76/qemu/hw/boards.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/boards.h	2008-10-12 09:38:23.000000000 +0200
@@ -17,6 +17,7 @@
 #define RAMSIZE_FIXED	(1 << 0)
     ram_addr_t ram_require;
     int nodisk_ok;
+    int use_scsi;
     struct QEMUMachine *next;
 } QEMUMachine;
 
@@ -69,6 +70,7 @@
 /* sun4u.c */
 extern QEMUMachine sun4u_machine;
 extern QEMUMachine sun4v_machine;
+extern QEMUMachine niagara_machine;
 
 /* integratorcp.c */
 extern QEMUMachine integratorcp_machine;
diff -Nur kvm-76/qemu/hw/bt-hci-csr.c kvm-userspace/qemu/hw/bt-hci-csr.c
--- kvm-76/qemu/hw/bt-hci-csr.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/bt-hci-csr.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,456 @@
+/*
+ * Bluetooth serial HCI transport.
+ * CSR41814 HCI with H4p vendor extensions.
+ *
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "qemu-char.h"
+#include "qemu-timer.h"
+#include "irq.h"
+#include "sysemu.h"
+#include "net.h"
+#include "bt.h"
+
+struct csrhci_s {
+    int enable;
+    qemu_irq *pins;
+    int pin_state;
+    int modem_state;
+    CharDriverState chr;
+#define FIFO_LEN	4096
+    int out_start;
+    int out_len;
+    int out_size;
+    uint8_t outfifo[FIFO_LEN * 2];
+    uint8_t inpkt[FIFO_LEN];
+    int in_len;
+    int in_hdr;
+    int in_data;
+    QEMUTimer *out_tm;
+    int64_t baud_delay;
+
+    bdaddr_t bd_addr;
+    struct HCIInfo *hci;
+};
+
+/* H4+ packet types */
+enum {
+    H4_CMD_PKT   = 1,
+    H4_ACL_PKT   = 2,
+    H4_SCO_PKT   = 3,
+    H4_EVT_PKT   = 4,
+    H4_NEG_PKT   = 6,
+    H4_ALIVE_PKT = 7,
+};
+
+/* CSR41814 negotiation start magic packet */
+static const uint8_t csrhci_neg_packet[] = {
+    H4_NEG_PKT, 10,
+    0x00, 0xa0, 0x01, 0x00, 0x00,
+    0x4c, 0x00, 0x96, 0x00, 0x00,
+};
+
+/* CSR41814 vendor-specific command OCFs */
+enum {
+    OCF_CSR_SEND_FIRMWARE = 0x000,
+};
+
+static inline void csrhci_fifo_wake(struct csrhci_s *s)
+{
+    if (!s->enable || !s->out_len)
+        return;
+
+    /* XXX: Should wait for s->modem_state & CHR_TIOCM_RTS? */
+    if (s->chr.chr_can_read && s->chr.chr_can_read(s->chr.handler_opaque) &&
+                    s->chr.chr_read) {
+        s->chr.chr_read(s->chr.handler_opaque,
+                        s->outfifo + s->out_start ++, 1);
+        s->out_len --;
+        if (s->out_start >= s->out_size) {
+            s->out_start = 0;
+            s->out_size = FIFO_LEN;
+        }
+    }
+
+    if (s->out_len)
+        qemu_mod_timer(s->out_tm, qemu_get_clock(vm_clock) + s->baud_delay);
+}
+
+#define csrhci_out_packetz(s, len) memset(csrhci_out_packet(s, len), 0, len)
+static uint8_t *csrhci_out_packet(struct csrhci_s *s, int len)
+{
+    int off = s->out_start + s->out_len;
+
+    /* TODO: do the padding here, i.e. align len */
+    s->out_len += len;
+
+    if (off < FIFO_LEN) {
+        if (off + len > FIFO_LEN && (s->out_size = off + len) > FIFO_LEN * 2) {
+            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
+            exit(-1);
+        }
+        return s->outfifo + off;
+    }
+
+    if (s->out_len > s->out_size) {
+        fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
+        exit(-1);
+    }
+
+    return s->outfifo + off - s->out_size;
+}
+
+static inline uint8_t *csrhci_out_packet_csr(struct csrhci_s *s,
+                int type, int len)
+{
+    uint8_t *ret = csrhci_out_packetz(s, len + 2);
+
+    *ret ++ = type;
+    *ret ++ = len;
+
+    return ret;
+}
+
+static inline uint8_t *csrhci_out_packet_event(struct csrhci_s *s,
+                int evt, int len)
+{
+    uint8_t *ret = csrhci_out_packetz(s,
+                    len + 1 + sizeof(struct hci_event_hdr));
+
+    *ret ++ = H4_EVT_PKT;
+    ((struct hci_event_hdr *) ret)->evt = evt;
+    ((struct hci_event_hdr *) ret)->plen = len;
+
+    return ret + sizeof(struct hci_event_hdr);
+}
+
+static void csrhci_in_packet_vendor(struct csrhci_s *s, int ocf,
+                uint8_t *data, int len)
+{
+    int offset;
+    uint8_t *rpkt;
+
+    switch (ocf) {
+    case OCF_CSR_SEND_FIRMWARE:
+        /* Check if this is the bd_address packet */
+        if (len >= 18 + 8 && data[12] == 0x01 && data[13] == 0x00) {
+            offset = 18;
+            s->bd_addr.b[0] = data[offset + 7];	/* Beyond cmd packet end(!?) */
+            s->bd_addr.b[1] = data[offset + 6];
+            s->bd_addr.b[2] = data[offset + 4];
+            s->bd_addr.b[3] = data[offset + 0];
+            s->bd_addr.b[4] = data[offset + 3];
+            s->bd_addr.b[5] = data[offset + 2];
+
+            s->hci->bdaddr_set(s->hci, s->bd_addr.b);
+            fprintf(stderr, "%s: bd_address loaded from firmware: "
+                            "%02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__,
+                            s->bd_addr.b[0], s->bd_addr.b[1], s->bd_addr.b[2],
+                            s->bd_addr.b[3], s->bd_addr.b[4], s->bd_addr.b[5]);
+        }
+
+        rpkt = csrhci_out_packet_event(s, EVT_VENDOR, 11);
+        /* Status bytes: no error */
+        rpkt[9] = 0x00;
+        rpkt[10] = 0x00;
+        break;
+
+    default:
+        fprintf(stderr, "%s: got a bad CMD packet\n", __FUNCTION__);
+        return;
+    }
+
+    csrhci_fifo_wake(s);
+}
+
+static void csrhci_in_packet(struct csrhci_s *s, uint8_t *pkt)
+{
+    uint8_t *rpkt;
+    int opc;
+
+    switch (*pkt ++) {
+    case H4_CMD_PKT:
+        opc = le16_to_cpu(((struct hci_command_hdr *) pkt)->opcode);
+        if (cmd_opcode_ogf(opc) == OGF_VENDOR_CMD) {
+            csrhci_in_packet_vendor(s, cmd_opcode_ocf(opc),
+                            pkt + sizeof(struct hci_command_hdr),
+                            s->in_len - sizeof(struct hci_command_hdr) - 1);
+            return;
+        }
+
+        /* TODO: if the command is OCF_READ_LOCAL_COMMANDS or the likes,
+         * we need to send it to the HCI layer and then add our supported
+         * commands to the returned mask (such as OGF_VENDOR_CMD).  With
+         * bt-hci.c we could just have hooks for this kind of commands but
+         * we can't with bt-host.c.  */
+
+        s->hci->cmd_send(s->hci, pkt, s->in_len - 1);
+        break;
+
+    case H4_EVT_PKT:
+        goto bad_pkt;
+
+    case H4_ACL_PKT:
+        s->hci->acl_send(s->hci, pkt, s->in_len - 1);
+        break;
+
+    case H4_SCO_PKT:
+        s->hci->sco_send(s->hci, pkt, s->in_len - 1);
+        break;
+
+    case H4_NEG_PKT:
+        if (s->in_hdr != sizeof(csrhci_neg_packet) ||
+                        memcmp(pkt - 1, csrhci_neg_packet, s->in_hdr)) {
+            fprintf(stderr, "%s: got a bad NEG packet\n", __FUNCTION__);
+            return;
+        }
+        pkt += 2;
+
+        rpkt = csrhci_out_packet_csr(s, H4_NEG_PKT, 10);
+
+        *rpkt ++ = 0x20;	/* Operational settings negotation Ok */
+        memcpy(rpkt, pkt, 7); rpkt += 7;
+        *rpkt ++ = 0xff;
+        *rpkt ++ = 0xff;
+        break;
+
+    case H4_ALIVE_PKT:
+        if (s->in_hdr != 4 || pkt[1] != 0x55 || pkt[2] != 0x00) {
+            fprintf(stderr, "%s: got a bad ALIVE packet\n", __FUNCTION__);
+            return;
+        }
+
+        rpkt = csrhci_out_packet_csr(s, H4_ALIVE_PKT, 2);
+
+        *rpkt ++ = 0xcc;
+        *rpkt ++ = 0x00;
+        break;
+
+    default:
+    bad_pkt:
+        /* TODO: error out */
+        fprintf(stderr, "%s: got a bad packet\n", __FUNCTION__);
+        break;
+    }
+
+    csrhci_fifo_wake(s);
+}
+
+static int csrhci_header_len(const uint8_t *pkt)
+{
+    switch (pkt[0]) {
+    case H4_CMD_PKT:
+        return HCI_COMMAND_HDR_SIZE;
+    case H4_EVT_PKT:
+        return HCI_EVENT_HDR_SIZE;
+    case H4_ACL_PKT:
+        return HCI_ACL_HDR_SIZE;
+    case H4_SCO_PKT:
+        return HCI_SCO_HDR_SIZE;
+    case H4_NEG_PKT:
+        return pkt[1] + 1;
+    case H4_ALIVE_PKT:
+        return 3;
+    }
+
+    exit(-1);
+}
+
+static int csrhci_data_len(const uint8_t *pkt)
+{
+    switch (*pkt ++) {
+    case H4_CMD_PKT:
+        /* It seems that vendor-specific command packets for H4+ are all
+         * one byte longer than indicated in the standard header.  */
+        if (le16_to_cpu(((struct hci_command_hdr *) pkt)->opcode) == 0xfc00)
+            return (((struct hci_command_hdr *) pkt)->plen + 1) & ~1;
+
+        return ((struct hci_command_hdr *) pkt)->plen;
+    case H4_EVT_PKT:
+        return ((struct hci_event_hdr *) pkt)->plen;
+    case H4_ACL_PKT:
+        return le16_to_cpu(((struct hci_acl_hdr *) pkt)->dlen);
+    case H4_SCO_PKT:
+        return ((struct hci_sco_hdr *) pkt)->dlen;
+    case H4_NEG_PKT:
+    case H4_ALIVE_PKT:
+        return 0;
+    }
+
+    exit(-1);
+}
+
+static int csrhci_write(struct CharDriverState *chr,
+                const uint8_t *buf, int len)
+{
+    struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
+    int plen = s->in_len;
+
+    if (!s->enable)
+        return 0;
+
+    s->in_len += len;
+    memcpy(s->inpkt + plen, buf, len);
+
+    while (1) {
+        if (s->in_len >= 2 && plen < 2)
+            s->in_hdr = csrhci_header_len(s->inpkt) + 1;
+
+        if (s->in_len >= s->in_hdr && plen < s->in_hdr)
+            s->in_data = csrhci_data_len(s->inpkt) + s->in_hdr;
+
+        if (s->in_len >= s->in_data) {
+            csrhci_in_packet(s, s->inpkt);
+
+            memmove(s->inpkt, s->inpkt + s->in_len, s->in_len - s->in_data);
+            s->in_len -= s->in_data;
+            s->in_hdr = INT_MAX;
+            s->in_data = INT_MAX;
+            plen = 0;
+        } else
+            break;
+    }
+
+    return len;
+}
+
+static void csrhci_out_hci_packet_event(void *opaque,
+                const uint8_t *data, int len)
+{
+    struct csrhci_s *s = (struct csrhci_s *) opaque;
+    uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1);	/* Align */
+
+    *pkt ++ = H4_EVT_PKT;
+    memcpy(pkt, data, len);
+
+    csrhci_fifo_wake(s);
+}
+
+static void csrhci_out_hci_packet_acl(void *opaque,
+                const uint8_t *data, int len)
+{
+    struct csrhci_s *s = (struct csrhci_s *) opaque;
+    uint8_t *pkt = csrhci_out_packet(s, (len + 2) & ~1);	/* Align */
+
+    *pkt ++ = H4_ACL_PKT;
+    pkt[len & ~1] = 0;
+    memcpy(pkt, data, len);
+
+    csrhci_fifo_wake(s);
+}
+
+static int csrhci_ioctl(struct CharDriverState *chr, int cmd, void *arg)
+{
+    QEMUSerialSetParams *ssp;
+    struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
+    int prev_state = s->modem_state;
+
+    switch (cmd) {
+    case CHR_IOCTL_SERIAL_SET_PARAMS:
+        ssp = (QEMUSerialSetParams *) arg;
+        s->baud_delay = ticks_per_sec / ssp->speed;
+        /* Moments later... (but shorter than 100ms) */
+        s->modem_state |= CHR_TIOCM_CTS;
+        break;
+
+    case CHR_IOCTL_SERIAL_GET_TIOCM:
+        *(int *) arg = s->modem_state;
+        break;
+
+    case CHR_IOCTL_SERIAL_SET_TIOCM:
+        s->modem_state = *(int *) arg;
+        if (~s->modem_state & prev_state & CHR_TIOCM_RTS)
+            s->modem_state &= ~CHR_TIOCM_CTS;
+        break;
+
+    default:
+        return -ENOTSUP;
+    }
+    return 0;
+}
+
+static void csrhci_reset(struct csrhci_s *s)
+{
+    s->out_len = 0;
+    s->out_size = FIFO_LEN;
+    s->in_len = 0;
+    s->baud_delay = ticks_per_sec;
+    s->enable = 0;
+    s->in_hdr = INT_MAX;
+    s->in_data = INT_MAX;
+
+    s->modem_state = 0;
+    /* After a while... (but sooner than 10ms) */
+    s->modem_state |= CHR_TIOCM_CTS;
+
+    memset(&s->bd_addr, 0, sizeof(bdaddr_t));
+}
+
+static void csrhci_out_tick(void *opaque)
+{
+    csrhci_fifo_wake((struct csrhci_s *) opaque);
+}
+
+static void csrhci_pins(void *opaque, int line, int level)
+{
+    struct csrhci_s *s = (struct csrhci_s *) opaque;
+    int state = s->pin_state;
+
+    s->pin_state &= ~(1 << line);
+    s->pin_state |= (!!level) << line;
+
+    if ((state & ~s->pin_state) & (1 << csrhci_pin_reset)) {
+        /* TODO: Disappear from lower layers */
+        csrhci_reset(s);
+    }
+
+    if (s->pin_state == 3 && state != 3) {
+        s->enable = 1;
+        /* TODO: Wake lower layers up */
+    }
+}
+
+qemu_irq *csrhci_pins_get(CharDriverState *chr)
+{
+    struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
+
+    return s->pins;
+}
+
+CharDriverState *uart_hci_init(qemu_irq wakeup)
+{
+    struct csrhci_s *s = (struct csrhci_s *)
+            qemu_mallocz(sizeof(struct csrhci_s));
+
+    s->chr.opaque = s;
+    s->chr.chr_write = csrhci_write;
+    s->chr.chr_ioctl = csrhci_ioctl;
+
+    s->hci = qemu_next_hci();
+    s->hci->opaque = s;
+    s->hci->evt_recv = csrhci_out_hci_packet_event;
+    s->hci->acl_recv = csrhci_out_hci_packet_acl;
+
+    s->out_tm = qemu_new_timer(vm_clock, csrhci_out_tick, s);
+    s->pins = qemu_allocate_irqs(csrhci_pins, s, __csrhci_pins);
+    csrhci_reset(s);
+
+    return &s->chr;
+}
diff -Nur kvm-76/qemu/hw/bt-hci.c kvm-userspace/qemu/hw/bt-hci.c
--- kvm-76/qemu/hw/bt-hci.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/bt-hci.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,2220 @@
+/*
+ * QEMU Bluetooth HCI logic.
+ *
+ * Copyright (C) 2007 OpenMoko, Inc.
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA  02110-1301  USA
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "usb.h"
+#include "net.h"
+#include "bt.h"
+
+struct bt_hci_s {
+    uint8_t *(*evt_packet)(void *opaque);
+    void (*evt_submit)(void *opaque, int len);
+    void *opaque;
+    uint8_t evt_buf[256];
+
+    uint8_t acl_buf[4096];
+    int acl_len;
+
+    uint16_t asb_handle;
+    uint16_t psb_handle;
+
+    int last_cmd;	/* Note: Always little-endian */
+
+    struct bt_device_s *conn_req_host;
+
+    struct {
+        int inquire;
+        int periodic;
+        int responses_left;
+        int responses;
+        QEMUTimer *inquiry_done;
+        QEMUTimer *inquiry_next;
+        int inquiry_length;
+        int inquiry_period;
+        int inquiry_mode;
+
+#define HCI_HANDLE_OFFSET	0x20
+#define HCI_HANDLES_MAX		0x10
+        struct bt_hci_master_link_s {
+            struct bt_link_s *link;
+            void (*lmp_acl_data)(struct bt_link_s *link,
+                            const uint8_t *data, int start, int len);
+            QEMUTimer *acl_mode_timer;
+        } handle[HCI_HANDLES_MAX];
+        uint32_t role_bmp;
+        int last_handle;
+        int connecting;
+        bdaddr_t awaiting_bdaddr[HCI_HANDLES_MAX];
+    } lm;
+
+    uint8_t event_mask[8];
+    uint16_t voice_setting;	/* Notw: Always little-endian */
+    uint16_t conn_accept_tout;
+    QEMUTimer *conn_accept_timer;
+
+    struct HCIInfo info;
+    struct bt_device_s device;
+};
+
+#define DEFAULT_RSSI_DBM	20
+
+#define hci_from_info(ptr)	container_of((ptr), struct bt_hci_s, info)
+#define hci_from_device(ptr)	container_of((ptr), struct bt_hci_s, device)
+
+struct bt_hci_link_s {
+    struct bt_link_s btlink;
+    uint16_t handle;	/* Local */
+};
+
+/* LMP layer emulation */
+static void bt_submit_lmp(struct bt_device_s *bt, int length, uint8_t *data)
+{
+    int resp, resplen, error, op, tr;
+    uint8_t respdata[17];
+
+    if (length < 1)
+        return;
+
+    tr = *data & 1;
+    op = *(data ++) >> 1;
+    resp = LMP_ACCEPTED;
+    resplen = 2;
+    respdata[1] = op;
+    error = 0;
+    length --;
+
+    if (op >= 0x7c) {	/* Extended opcode */
+        op |= *(data ++) << 8;
+        resp = LMP_ACCEPTED_EXT;
+        resplen = 4;
+        respdata[0] = op >> 8;
+        respdata[1] = op & 0xff;
+        length --;
+    }
+
+    switch (op) {
+    case LMP_ACCEPTED:
+        /* data[0]	Op code
+         */
+        if (length < 1) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        resp = 0;
+        break;
+
+    case LMP_ACCEPTED_EXT:
+        /* data[0]	Escape op code
+         * data[1]	Extended op code
+         */
+        if (length < 2) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        resp = 0;
+        break;
+
+    case LMP_NOT_ACCEPTED:
+        /* data[0]	Op code
+         * data[1]	Error code
+         */
+        if (length < 2) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        resp = 0;
+        break;
+
+    case LMP_NOT_ACCEPTED_EXT:
+        /* data[0]	Op code
+         * data[1]	Extended op code
+         * data[2]	Error code
+         */
+        if (length < 3) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        resp = 0;
+        break;
+
+    case LMP_HOST_CONNECTION_REQ:
+        break;
+
+    case LMP_SETUP_COMPLETE:
+        resp = LMP_SETUP_COMPLETE;
+        resplen = 1;
+        bt->setup = 1;
+        break;
+
+    case LMP_DETACH:
+        /* data[0]	Error code
+         */
+        if (length < 1) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        bt->setup = 0;
+        resp = 0;
+        break;
+
+    case LMP_SUPERVISION_TIMEOUT:
+        /* data[0,1]	Supervision timeout
+         */
+        if (length < 2) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        resp = 0;
+        break;
+
+    case LMP_QUALITY_OF_SERVICE:
+        resp = 0;
+        /* Fall through */
+    case LMP_QOS_REQ:
+        /* data[0,1]	Poll interval
+         * data[2]	N(BC)
+         */
+        if (length < 3) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        break;
+
+    case LMP_MAX_SLOT:
+        resp = 0;
+        /* Fall through */
+    case LMP_MAX_SLOT_REQ:
+        /* data[0]	Max slots
+         */
+        if (length < 1) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        break;
+
+    case LMP_AU_RAND:
+    case LMP_IN_RAND:
+    case LMP_COMB_KEY:
+        /* data[0-15]	Random number
+         */
+        if (length < 16) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        if (op == LMP_AU_RAND) {
+            if (bt->key_present) {
+                resp = LMP_SRES;
+                resplen = 5;
+                /* XXX: [Part H] Section 6.1 on page 801 */
+            } else {
+                error = HCI_PIN_OR_KEY_MISSING;
+                goto not_accepted;
+            }
+        } else if (op == LMP_IN_RAND) {
+            error = HCI_PAIRING_NOT_ALLOWED;
+            goto not_accepted;
+        } else {
+            /* XXX: [Part H] Section 3.2 on page 779 */
+            resp = LMP_UNIT_KEY;
+            resplen = 17;
+            memcpy(respdata + 1, bt->key, 16);
+
+            error = HCI_UNIT_LINK_KEY_USED;
+            goto not_accepted;
+        }
+        break;
+
+    case LMP_UNIT_KEY:
+        /* data[0-15]	Key
+         */
+        if (length < 16) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        memcpy(bt->key, data, 16);
+        bt->key_present = 1;
+        break;
+
+    case LMP_SRES:
+        /* data[0-3]	Authentication response
+         */
+        if (length < 4) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        break;
+
+    case LMP_CLKOFFSET_REQ:
+        resp = LMP_CLKOFFSET_RES;
+        resplen = 3;
+        respdata[1] = 0x33;
+        respdata[2] = 0x33;
+        break;
+
+    case LMP_CLKOFFSET_RES:
+        /* data[0,1]	Clock offset
+         * (Slave to master only)
+         */
+        if (length < 2) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        break;
+
+    case LMP_VERSION_REQ:
+    case LMP_VERSION_RES:
+        /* data[0]	VersNr
+         * data[1,2]	CompId
+         * data[3,4]	SubVersNr
+         */
+        if (length < 5) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        if (op == LMP_VERSION_REQ) {
+            resp = LMP_VERSION_RES;
+            resplen = 6;
+            respdata[1] = 0x20;
+            respdata[2] = 0xff;
+            respdata[3] = 0xff;
+            respdata[4] = 0xff;
+            respdata[5] = 0xff;
+        } else
+            resp = 0;
+        break;
+
+    case LMP_FEATURES_REQ:
+    case LMP_FEATURES_RES:
+        /* data[0-7]	Features
+         */
+        if (length < 8) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        if (op == LMP_FEATURES_REQ) {
+            resp = LMP_FEATURES_RES;
+            resplen = 9;
+            respdata[1] = (bt->lmp_caps >> 0) & 0xff;
+            respdata[2] = (bt->lmp_caps >> 8) & 0xff;
+            respdata[3] = (bt->lmp_caps >> 16) & 0xff;
+            respdata[4] = (bt->lmp_caps >> 24) & 0xff;
+            respdata[5] = (bt->lmp_caps >> 32) & 0xff;
+            respdata[6] = (bt->lmp_caps >> 40) & 0xff;
+            respdata[7] = (bt->lmp_caps >> 48) & 0xff;
+            respdata[8] = (bt->lmp_caps >> 56) & 0xff;
+        } else
+            resp = 0;
+        break;
+
+    case LMP_NAME_REQ:
+        /* data[0]	Name offset
+         */
+        if (length < 1) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        resp = LMP_NAME_RES;
+        resplen = 17;
+        respdata[1] = data[0];
+        respdata[2] = strlen(bt->lmp_name);
+        memset(respdata + 3, 0x00, 14);
+        if (respdata[2] > respdata[1])
+            memcpy(respdata + 3, bt->lmp_name + respdata[1],
+                            respdata[2] - respdata[1]);
+        break;
+
+    case LMP_NAME_RES:
+        /* data[0]	Name offset
+         * data[1]	Name length
+         * data[2-15]	Name fragment
+         */
+        if (length < 16) {
+            error = HCI_UNSUPPORTED_LMP_PARAMETER_VALUE;
+            goto not_accepted;
+        }
+        resp = 0;
+        break;
+
+    default:
+        error = HCI_UNKNOWN_LMP_PDU;
+        /* Fall through */
+    not_accepted:
+        if (op >> 8) {
+            resp = LMP_NOT_ACCEPTED_EXT;
+            resplen = 5;
+            respdata[0] = op >> 8;
+            respdata[1] = op & 0xff;
+            respdata[2] = error;
+        } else {
+            resp = LMP_NOT_ACCEPTED;
+            resplen = 3;
+            respdata[0] = op & 0xff;
+            respdata[1] = error;
+        }
+    }
+
+    if (resp == 0)
+        return;
+
+    if (resp >> 8) {
+        respdata[0] = resp >> 8;
+        respdata[1] = resp & 0xff;
+    } else
+        respdata[0] = resp & 0xff;
+
+    respdata[0] <<= 1;
+    respdata[0] |= tr;
+}
+
+void bt_submit_raw_acl(struct bt_piconet_s *net, int length, uint8_t *data)
+{
+    struct bt_device_s *slave;
+    if (length < 1)
+        return;
+
+    slave = 0;
+#if 0
+    slave = net->slave;
+#endif
+
+    switch (data[0] & 3) {
+    case LLID_ACLC:
+        bt_submit_lmp(slave, length - 1, data + 1);
+        break;
+    case LLID_ACLU_START:
+#if 0
+        bt_sumbit_l2cap(slave, length - 1, data + 1, (data[0] >> 2) & 1);
+        breka;
+#endif
+    default:
+    case LLID_ACLU_CONT:
+        break;
+    }
+}
+
+/* HCI layer emulation */
+
+/* Note: we could ignore endiannes because unswapped handles will still
+ * be valid as connection identifiers for the guest - they don't have to
+ * be continuously allocated.  We do it though, to preserve similar
+ * behaviour between hosts.  Some things, like the BD_ADDR cannot be
+ * preserved though (for example if a real hci is used).  */
+#ifdef WORDS_BIGENDIAN
+# define HNDL(raw)	bswap16(raw)
+#else
+# define HNDL(raw)	(raw)
+#endif
+
+static const uint8_t bt_event_reserved_mask[8] = {
+    0xff, 0x9f, 0xfb, 0xff, 0x07, 0x18, 0x00, 0x00,
+};
+
+static inline uint8_t *bt_hci_event_start(struct bt_hci_s *hci,
+                int evt, int len)
+{
+    uint8_t *packet, mask;
+    int mask_byte;
+
+    if (len > 255) {
+        fprintf(stderr, "%s: HCI event params too long (%ib)\n",
+                        __FUNCTION__, len);
+        exit(-1);
+    }
+
+    mask_byte = (evt - 1) >> 3;
+    mask = 1 << ((evt - 1) & 3);
+    if (mask & bt_event_reserved_mask[mask_byte] & ~hci->event_mask[mask_byte])
+        return 0;
+
+    packet = hci->evt_packet(hci->opaque);
+    packet[0] = evt;
+    packet[1] = len;
+
+    return &packet[2];
+}
+
+static inline void bt_hci_event(struct bt_hci_s *hci, int evt,
+                void *params, int len)
+{
+    uint8_t *packet = bt_hci_event_start(hci, evt, len);
+
+    if (!packet)
+        return;
+
+    if (len)
+        memcpy(packet, params, len);
+
+    hci->evt_submit(hci->opaque, len + 2);
+}
+
+static inline void bt_hci_event_status(struct bt_hci_s *hci, int status)
+{
+    evt_cmd_status params = {
+        .status	= status,
+        .ncmd	= 1,
+        .opcode	= hci->last_cmd,
+    };
+
+    bt_hci_event(hci, EVT_CMD_STATUS, &params, EVT_CMD_STATUS_SIZE);
+}
+
+static inline void bt_hci_event_complete(struct bt_hci_s *hci,
+                void *ret, int len)
+{
+    uint8_t *packet = bt_hci_event_start(hci, EVT_CMD_COMPLETE,
+                    len + EVT_CMD_COMPLETE_SIZE);
+    evt_cmd_complete *params = (evt_cmd_complete *) packet;
+
+    if (!packet)
+        return;
+
+    params->ncmd	= 1;
+    params->opcode	= hci->last_cmd;
+    if (len)
+        memcpy(&packet[EVT_CMD_COMPLETE_SIZE], ret, len);
+
+    hci->evt_submit(hci->opaque, len + EVT_CMD_COMPLETE_SIZE + 2);
+}
+
+static void bt_hci_inquiry_done(void *opaque)
+{
+    struct bt_hci_s *hci = (struct bt_hci_s *) opaque;
+    uint8_t status = HCI_SUCCESS;
+
+    if (!hci->lm.periodic)
+        hci->lm.inquire = 0;
+
+    /* The specification is inconsistent about this one.  Page 565 reads
+     * "The event parameters of Inquiry Complete event will have a summary
+     * of the result from the Inquiry process, which reports the number of
+     * nearby Bluetooth devices that responded [so hci->responses].", but
+     * Event Parameters (see page 729) has only Status.  */
+    bt_hci_event(hci, EVT_INQUIRY_COMPLETE, &status, 1);
+}
+
+static void bt_hci_inquiry_result_standard(struct bt_hci_s *hci,
+                struct bt_device_s *slave)
+{
+    inquiry_info params = {
+        .num_responses		= 1,
+        .bdaddr			= BAINIT(&slave->bd_addr),
+        .pscan_rep_mode		= 0x00,	/* R0 */
+        .pscan_period_mode	= 0x00,	/* P0 - deprecated */
+        .pscan_mode		= 0x00,	/* Standard scan - deprecated */
+        .dev_class[0]		= slave->class[0],
+        .dev_class[1]		= slave->class[1],
+        .dev_class[2]		= slave->class[2],
+        /* TODO: return the clkoff *differenece* */
+        .clock_offset		= slave->clkoff,	/* Note: no swapping */
+    };
+
+    bt_hci_event(hci, EVT_INQUIRY_RESULT, &params, INQUIRY_INFO_SIZE);
+}
+
+static void bt_hci_inquiry_result_with_rssi(struct bt_hci_s *hci,
+                struct bt_device_s *slave)
+{
+    inquiry_info_with_rssi params = {
+        .num_responses		= 1,
+        .bdaddr			= BAINIT(&slave->bd_addr),
+        .pscan_rep_mode		= 0x00,	/* R0 */
+        .pscan_period_mode	= 0x00,	/* P0 - deprecated */
+        .dev_class[0]		= slave->class[0],
+        .dev_class[1]		= slave->class[1],
+        .dev_class[2]		= slave->class[2],
+        /* TODO: return the clkoff *differenece* */
+        .clock_offset		= slave->clkoff,	/* Note: no swapping */
+        .rssi			= DEFAULT_RSSI_DBM,
+    };
+
+    bt_hci_event(hci, EVT_INQUIRY_RESULT_WITH_RSSI,
+                    &params, INQUIRY_INFO_WITH_RSSI_SIZE);
+}
+
+static void bt_hci_inquiry_result(struct bt_hci_s *hci,
+                struct bt_device_s *slave)
+{
+    if (!slave->inquiry_scan || !hci->lm.responses_left)
+        return;
+
+    hci->lm.responses_left --;
+    hci->lm.responses ++;
+
+    switch (hci->lm.inquiry_mode) {
+    case 0x00:
+        return bt_hci_inquiry_result_standard(hci, slave);
+    case 0x01:
+        return bt_hci_inquiry_result_with_rssi(hci, slave);
+    default:
+        fprintf(stderr, "%s: bad inquiry mode %02x\n", __FUNCTION__,
+                        hci->lm.inquiry_mode);
+        exit(-1);
+    }
+}
+
+static void bt_hci_mod_timer_1280ms(QEMUTimer *timer, int period)
+{
+    qemu_mod_timer(timer, qemu_get_clock(vm_clock) +
+                    muldiv64(period << 7, ticks_per_sec, 100));
+}
+
+static void bt_hci_inquiry_start(struct bt_hci_s *hci, int length)
+{
+    struct bt_device_s *slave;
+
+    hci->lm.inquiry_length = length;
+    for (slave = hci->device.net->slave; slave; slave = slave->next)
+        /* Don't uncover ourselves.  */
+        if (slave != &hci->device)
+            bt_hci_inquiry_result(hci, slave);
+
+    /* TODO: register for a callback on a new device's addition to the
+     * scatternet so that if it's added before inquiry_length expires,
+     * an Inquiry Result is generated immediately.  Alternatively re-loop
+     * through the devices on the inquiry_length expiration and report
+     * devices not seen before.  */
+    if (hci->lm.responses_left)
+        bt_hci_mod_timer_1280ms(hci->lm.inquiry_done, hci->lm.inquiry_length);
+    else
+        bt_hci_inquiry_done(hci);
+
+    if (hci->lm.periodic)
+        bt_hci_mod_timer_1280ms(hci->lm.inquiry_next, hci->lm.inquiry_period);
+}
+
+static void bt_hci_inquiry_next(void *opaque)
+{
+    struct bt_hci_s *hci = (struct bt_hci_s *) opaque;
+
+    hci->lm.responses_left += hci->lm.responses;
+    hci->lm.responses = 0;
+    bt_hci_inquiry_start(hci,  hci->lm.inquiry_length);
+}
+
+static inline int bt_hci_handle_bad(struct bt_hci_s *hci, uint16_t handle)
+{
+    return !(handle & HCI_HANDLE_OFFSET) ||
+            handle >= (HCI_HANDLE_OFFSET | HCI_HANDLES_MAX) ||
+            !hci->lm.handle[handle & ~HCI_HANDLE_OFFSET].link;
+}
+
+static inline int bt_hci_role_master(struct bt_hci_s *hci, uint16_t handle)
+{
+    return !!(hci->lm.role_bmp & (1 << (handle & ~HCI_HANDLE_OFFSET)));
+}
+
+static inline struct bt_device_s *bt_hci_remote_dev(struct bt_hci_s *hci,
+                uint16_t handle)
+{
+    struct bt_link_s *link = hci->lm.handle[handle & ~HCI_HANDLE_OFFSET].link;
+
+    return bt_hci_role_master(hci, handle) ? link->slave : link->host;
+}
+
+static void bt_hci_mode_tick(void *opaque);
+static void bt_hci_lmp_link_establish(struct bt_hci_s *hci,
+                struct bt_link_s *link, int master)
+{
+    hci->lm.handle[hci->lm.last_handle].link = link;
+
+    if (master) {
+        /* We are the master side of an ACL link */
+        hci->lm.role_bmp |= 1 << hci->lm.last_handle;
+
+        hci->lm.handle[hci->lm.last_handle].lmp_acl_data =
+                link->slave->lmp_acl_data;
+    } else {
+        /* We are the slave side of an ACL link */
+        hci->lm.role_bmp &= ~(1 << hci->lm.last_handle);
+
+        hci->lm.handle[hci->lm.last_handle].lmp_acl_data =
+                link->host->lmp_acl_resp;
+    }
+
+    /* Mode */
+    if (master) {
+        link->acl_mode = acl_active;
+        hci->lm.handle[hci->lm.last_handle].acl_mode_timer =
+                qemu_new_timer(vm_clock, bt_hci_mode_tick, link);
+    }
+}
+
+static void bt_hci_lmp_link_teardown(struct bt_hci_s *hci, uint16_t handle)
+{
+    handle &= ~HCI_HANDLE_OFFSET;
+    hci->lm.handle[handle].link = 0;
+
+    if (bt_hci_role_master(hci, handle)) {
+        qemu_del_timer(hci->lm.handle[handle].acl_mode_timer);
+        qemu_free_timer(hci->lm.handle[handle].acl_mode_timer);
+    }
+}
+
+static int bt_hci_connect(struct bt_hci_s *hci, bdaddr_t *bdaddr)
+{
+    struct bt_device_s *slave;
+    struct bt_link_s link;
+
+    for (slave = hci->device.net->slave; slave; slave = slave->next)
+        if (slave->page_scan && !bacmp(&slave->bd_addr, bdaddr))
+            break;
+    if (!slave || slave == &hci->device)
+        return -ENODEV;
+
+    bacpy(&hci->lm.awaiting_bdaddr[hci->lm.connecting ++], &slave->bd_addr);
+
+    link.slave = slave;
+    link.host = &hci->device;
+    link.slave->lmp_connection_request(&link);	/* Always last */
+
+    return 0;
+}
+
+static void bt_hci_connection_reject(struct bt_hci_s *hci,
+                struct bt_device_s *host, uint8_t because)
+{
+    struct bt_link_s link = {
+        .slave	= &hci->device,
+        .host	= host,
+        /* Rest uninitialised */
+    };
+
+    host->reject_reason = because;
+    host->lmp_connection_complete(&link);
+}
+
+static void bt_hci_connection_reject_event(struct bt_hci_s *hci,
+                bdaddr_t *bdaddr)
+{
+    evt_conn_complete params;
+
+    params.status	= HCI_NO_CONNECTION;
+    params.handle	= 0;
+    bacpy(&params.bdaddr, bdaddr);
+    params.link_type	= ACL_LINK;
+    params.encr_mode	= 0x00;		/* Encryption not required */
+    bt_hci_event(hci, EVT_CONN_COMPLETE, &params, EVT_CONN_COMPLETE_SIZE);
+}
+
+static void bt_hci_connection_accept(struct bt_hci_s *hci,
+                struct bt_device_s *host)
+{
+    struct bt_hci_link_s *link = qemu_mallocz(sizeof(struct bt_hci_link_s));
+    evt_conn_complete params;
+    uint16_t handle;
+    uint8_t status = HCI_SUCCESS;
+    int tries = HCI_HANDLES_MAX;
+
+    /* Make a connection handle */
+    do {
+        while (hci->lm.handle[++ hci->lm.last_handle].link && -- tries)
+            hci->lm.last_handle &= HCI_HANDLES_MAX - 1;
+        handle = hci->lm.last_handle | HCI_HANDLE_OFFSET;
+    } while ((handle == hci->asb_handle || handle == hci->psb_handle) &&
+            tries);
+
+    if (!tries) {
+        qemu_free(link);
+        bt_hci_connection_reject(hci, host, HCI_REJECTED_LIMITED_RESOURCES);
+        status = HCI_NO_CONNECTION;
+        goto complete;
+    }
+
+    link->btlink.slave	= &hci->device;
+    link->btlink.host	= host;
+    link->handle = handle;
+
+    /* Link established */
+    bt_hci_lmp_link_establish(hci, &link->btlink, 0);
+
+complete:
+    params.status	= status;
+    params.handle	= HNDL(handle);
+    bacpy(&params.bdaddr, &host->bd_addr);
+    params.link_type	= ACL_LINK;
+    params.encr_mode	= 0x00;		/* Encryption not required */
+    bt_hci_event(hci, EVT_CONN_COMPLETE, &params, EVT_CONN_COMPLETE_SIZE);
+
+    /* Neets to be done at the very end because it can trigger a (nested)
+     * disconnected, in case the other and had cancelled the request
+     * locally.  */
+    if (status == HCI_SUCCESS) {
+        host->reject_reason = 0;
+        host->lmp_connection_complete(&link->btlink);
+    }
+}
+
+static void bt_hci_lmp_connection_request(struct bt_link_s *link)
+{
+    struct bt_hci_s *hci = hci_from_device(link->slave);
+    evt_conn_request params;
+
+    if (hci->conn_req_host)
+        return bt_hci_connection_reject(hci, link->host,
+                        HCI_REJECTED_LIMITED_RESOURCES);
+    hci->conn_req_host = link->host;
+    /* TODO: if masked and auto-accept, then auto-accept,
+     * if masked and not auto-accept, then auto-reject */
+    /* TODO: kick the hci->conn_accept_timer, timeout after
+     * hci->conn_accept_tout * 0.625 msec */
+
+    bacpy(&params.bdaddr, &link->host->bd_addr);
+    memcpy(&params.dev_class, &link->host->class, sizeof(params.dev_class));
+    params.link_type	= ACL_LINK;
+    bt_hci_event(hci, EVT_CONN_REQUEST, &params, EVT_CONN_REQUEST_SIZE);
+    return;
+}
+
+static void bt_hci_conn_accept_timeout(void *opaque)
+{
+    struct bt_hci_s *hci = (struct bt_hci_s *) opaque;
+
+    if (!hci->conn_req_host)
+        /* Already accepted or rejected.  If the other end cancelled the
+         * connection request then we still have to reject or accept it
+         * and then we'll get a disconnect.  */
+        return;
+
+    /* TODO */
+}
+
+/* Remove from the list of devices which we wanted to connect to and
+ * are awaiting a response from.  If the callback sees a response from
+ * a device which is not on the list it will assume it's a connection
+ * that's been cancelled by the host in the meantime and immediately
+ * try to detach the link and send a Connection Complete.  */
+static int bt_hci_lmp_connection_ready(struct bt_hci_s *hci,
+                bdaddr_t *bdaddr)
+{
+    int i;
+
+    for (i = 0; i < hci->lm.connecting; i ++)
+        if (!bacmp(&hci->lm.awaiting_bdaddr[i], bdaddr)) {
+            if (i < -- hci->lm.connecting)
+                bacpy(&hci->lm.awaiting_bdaddr[i],
+                                &hci->lm.awaiting_bdaddr[hci->lm.connecting]);
+            return 0;
+        }
+
+    return 1;
+}
+
+static void bt_hci_lmp_connection_complete(struct bt_link_s *link)
+{
+    struct bt_hci_s *hci = hci_from_device(link->host);
+    evt_conn_complete params;
+    uint16_t handle;
+    uint8_t status = HCI_SUCCESS;
+    int tries = HCI_HANDLES_MAX;
+
+    if (bt_hci_lmp_connection_ready(hci, &link->slave->bd_addr)) {
+        if (!hci->device.reject_reason)
+            link->slave->lmp_disconnect_slave(link);
+        handle = 0;
+        status = HCI_NO_CONNECTION;
+        goto complete;
+    }
+
+    if (hci->device.reject_reason) {
+        handle = 0;
+        status = hci->device.reject_reason;
+        goto complete;
+    }
+
+    /* Make a connection handle */
+    do {
+        while (hci->lm.handle[++ hci->lm.last_handle].link && -- tries)
+            hci->lm.last_handle &= HCI_HANDLES_MAX - 1;
+        handle = hci->lm.last_handle | HCI_HANDLE_OFFSET;
+    } while ((handle == hci->asb_handle || handle == hci->psb_handle) &&
+            tries);
+
+    if (!tries) {
+        link->slave->lmp_disconnect_slave(link);
+        status = HCI_NO_CONNECTION;
+        goto complete;
+    }
+
+    /* Link established */
+    link->handle = handle;
+    bt_hci_lmp_link_establish(hci, link, 1);
+
+complete:
+    params.status	= status;
+    params.handle	= HNDL(handle);
+    params.link_type	= ACL_LINK;
+    bacpy(&params.bdaddr, &link->slave->bd_addr);
+    params.encr_mode	= 0x00;		/* Encryption not required */
+    bt_hci_event(hci, EVT_CONN_COMPLETE, &params, EVT_CONN_COMPLETE_SIZE);
+}
+
+static void bt_hci_disconnect(struct bt_hci_s *hci,
+                uint16_t handle, int reason)
+{
+    struct bt_link_s *btlink =
+            hci->lm.handle[handle & ~HCI_HANDLE_OFFSET].link;
+    struct bt_hci_link_s *link;
+    evt_disconn_complete params;
+
+    if (bt_hci_role_master(hci, handle)) {
+        btlink->slave->reject_reason = reason;
+        btlink->slave->lmp_disconnect_slave(btlink);
+        /* The link pointer is invalid from now on */
+
+        goto complete;
+    }
+
+    btlink->host->reject_reason = reason;
+    btlink->host->lmp_disconnect_master(btlink);
+
+    /* We are the slave, we get to clean this burden */
+    link = (struct bt_hci_link_s *) btlink;
+    qemu_free(link);
+
+complete:
+    bt_hci_lmp_link_teardown(hci, handle);
+
+    params.status	= HCI_SUCCESS;
+    params.handle	= HNDL(handle);
+    params.reason	= HCI_CONNECTION_TERMINATED;
+    bt_hci_event(hci, EVT_DISCONN_COMPLETE,
+                    &params, EVT_DISCONN_COMPLETE_SIZE);
+}
+
+/* TODO: use only one function */
+static void bt_hci_lmp_disconnect_host(struct bt_link_s *link)
+{
+    struct bt_hci_s *hci = hci_from_device(link->host);
+    uint16_t handle = link->handle;
+    evt_disconn_complete params;
+
+    bt_hci_lmp_link_teardown(hci, handle);
+
+    params.status	= HCI_SUCCESS;
+    params.handle	= HNDL(handle);
+    params.reason	= hci->device.reject_reason;
+    bt_hci_event(hci, EVT_DISCONN_COMPLETE,
+                    &params, EVT_DISCONN_COMPLETE_SIZE);
+}
+
+static void bt_hci_lmp_disconnect_slave(struct bt_link_s *btlink)
+{
+    struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
+    struct bt_hci_s *hci = hci_from_device(btlink->slave);
+    uint16_t handle = link->handle;
+    evt_disconn_complete params;
+
+    qemu_free(link);
+
+    bt_hci_lmp_link_teardown(hci, handle);
+
+    params.status	= HCI_SUCCESS;
+    params.handle	= HNDL(handle);
+    params.reason	= hci->device.reject_reason;
+    bt_hci_event(hci, EVT_DISCONN_COMPLETE,
+                    &params, EVT_DISCONN_COMPLETE_SIZE);
+}
+
+static int bt_hci_name_req(struct bt_hci_s *hci, bdaddr_t *bdaddr)
+{
+    struct bt_device_s *slave;
+    evt_remote_name_req_complete params;
+    int len;
+
+    for (slave = hci->device.net->slave; slave; slave = slave->next)
+        if (slave->page_scan && !bacmp(&slave->bd_addr, bdaddr))
+            break;
+    if (!slave)
+        return -ENODEV;
+
+    bt_hci_event_status(hci, HCI_SUCCESS);
+
+    params.status       = HCI_SUCCESS;
+    bacpy(&params.bdaddr, &slave->bd_addr);
+    len = snprintf(params.name, sizeof(params.name),
+                    "%s", slave->lmp_name ?: "");
+    memset(params.name + len, 0, sizeof(params.name) - len);
+    bt_hci_event(hci, EVT_REMOTE_NAME_REQ_COMPLETE,
+                    &params, EVT_REMOTE_NAME_REQ_COMPLETE_SIZE);
+
+    return 0;
+}
+
+static int bt_hci_features_req(struct bt_hci_s *hci, uint16_t handle)
+{
+    struct bt_device_s *slave;
+    evt_read_remote_features_complete params;
+
+    if (bt_hci_handle_bad(hci, handle))
+        return -ENODEV;
+
+    slave = bt_hci_remote_dev(hci, handle);
+
+    bt_hci_event_status(hci, HCI_SUCCESS);
+
+    params.status	= HCI_SUCCESS;
+    params.handle	= HNDL(handle);
+    params.features[0]	= (slave->lmp_caps >>  0) & 0xff;
+    params.features[1]	= (slave->lmp_caps >>  8) & 0xff;
+    params.features[2]	= (slave->lmp_caps >> 16) & 0xff;
+    params.features[3]	= (slave->lmp_caps >> 24) & 0xff;
+    params.features[4]	= (slave->lmp_caps >> 32) & 0xff;
+    params.features[5]	= (slave->lmp_caps >> 40) & 0xff;
+    params.features[6]	= (slave->lmp_caps >> 48) & 0xff;
+    params.features[7]	= (slave->lmp_caps >> 56) & 0xff;
+    bt_hci_event(hci, EVT_READ_REMOTE_FEATURES_COMPLETE,
+                    &params, EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE);
+
+    return 0;
+}
+
+static int bt_hci_version_req(struct bt_hci_s *hci, uint16_t handle)
+{
+    struct bt_device_s *slave;
+    evt_read_remote_version_complete params;
+
+    if (bt_hci_handle_bad(hci, handle))
+        return -ENODEV;
+
+    slave = bt_hci_remote_dev(hci, handle);
+
+    bt_hci_event_status(hci, HCI_SUCCESS);
+
+    params.status	= HCI_SUCCESS;
+    params.handle	= HNDL(handle);
+    params.lmp_ver	= 0x03;
+    params.manufacturer	= cpu_to_le16(0xa000);
+    params.lmp_subver	= cpu_to_le16(0xa607);
+    bt_hci_event(hci, EVT_READ_REMOTE_VERSION_COMPLETE,
+                    &params, EVT_READ_REMOTE_VERSION_COMPLETE_SIZE);
+
+    return 0;
+}
+
+static int bt_hci_clkoffset_req(struct bt_hci_s *hci, uint16_t handle)
+{
+    struct bt_device_s *slave;
+    evt_read_clock_offset_complete params;
+
+    if (bt_hci_handle_bad(hci, handle))
+        return -ENODEV;
+
+    slave = bt_hci_remote_dev(hci, handle);
+
+    bt_hci_event_status(hci, HCI_SUCCESS);
+
+    params.status	= HCI_SUCCESS;
+    params.handle	= HNDL(handle);
+    /* TODO: return the clkoff *differenece* */
+    params.clock_offset	= slave->clkoff;	/* Note: no swapping */
+    bt_hci_event(hci, EVT_READ_CLOCK_OFFSET_COMPLETE,
+                    &params, EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE);
+
+    return 0;
+}
+
+static void bt_hci_event_mode(struct bt_hci_s *hci, struct bt_link_s *link,
+                uint16_t handle)
+{
+    evt_mode_change params = {
+        .status		= HCI_SUCCESS,
+        .handle		= HNDL(handle),
+        .mode		= link->acl_mode,
+        .interval	= cpu_to_le16(link->acl_interval),
+    };
+
+    bt_hci_event(hci, EVT_MODE_CHANGE, &params, EVT_MODE_CHANGE_SIZE);
+}
+
+static void bt_hci_lmp_mode_change_master(struct bt_hci_s *hci,
+                struct bt_link_s *link, int mode, uint16_t interval)
+{
+    link->acl_mode = mode;
+    link->acl_interval = interval;
+
+    bt_hci_event_mode(hci, link, link->handle);
+
+    link->slave->lmp_mode_change(link);
+}
+
+static void bt_hci_lmp_mode_change_slave(struct bt_link_s *btlink)
+{
+    struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
+    struct bt_hci_s *hci = hci_from_device(btlink->slave);
+
+    bt_hci_event_mode(hci, btlink, link->handle);
+}
+
+static int bt_hci_mode_change(struct bt_hci_s *hci, uint16_t handle,
+                int interval, int mode)
+{
+    struct bt_hci_master_link_s *link;
+
+    if (bt_hci_handle_bad(hci, handle) || !bt_hci_role_master(hci, handle))
+        return -ENODEV;
+
+    link = &hci->lm.handle[handle & ~HCI_HANDLE_OFFSET];
+    if (link->link->acl_mode != acl_active) {
+        bt_hci_event_status(hci, HCI_COMMAND_DISALLOWED);
+        return 0;
+    }
+
+    bt_hci_event_status(hci, HCI_SUCCESS);
+
+    qemu_mod_timer(link->acl_mode_timer, qemu_get_clock(vm_clock) +
+                            muldiv64(interval * 625, ticks_per_sec, 1000000));
+    bt_hci_lmp_mode_change_master(hci, link->link, mode, interval);
+
+    return 0;
+}
+
+static int bt_hci_mode_cancel(struct bt_hci_s *hci, uint16_t handle, int mode)
+{
+    struct bt_hci_master_link_s *link;
+
+    if (bt_hci_handle_bad(hci, handle) || !bt_hci_role_master(hci, handle))
+        return -ENODEV;
+
+    link = &hci->lm.handle[handle & ~HCI_HANDLE_OFFSET];
+    if (link->link->acl_mode != mode) {
+        bt_hci_event_status(hci, HCI_COMMAND_DISALLOWED);
+
+        return 0;
+    }
+
+    bt_hci_event_status(hci, HCI_SUCCESS);
+
+    qemu_del_timer(link->acl_mode_timer);
+    bt_hci_lmp_mode_change_master(hci, link->link, acl_active, 0);
+
+    return 0;
+}
+
+static void bt_hci_mode_tick(void *opaque)
+{
+    struct bt_link_s *link = opaque;
+    struct bt_hci_s *hci = hci_from_device(link->host);
+
+    bt_hci_lmp_mode_change_master(hci, link, acl_active, 0);
+}
+
+void bt_hci_reset(struct bt_hci_s *hci)
+{
+    hci->acl_len = 0;
+    hci->last_cmd = 0;
+    hci->lm.connecting = 0;
+
+    hci->event_mask[0] = 0xff;
+    hci->event_mask[1] = 0xff;
+    hci->event_mask[2] = 0xff;
+    hci->event_mask[3] = 0xff;
+    hci->event_mask[4] = 0xff;
+    hci->event_mask[5] = 0x1f;
+    hci->event_mask[6] = 0x00;
+    hci->event_mask[7] = 0x00;
+    hci->device.inquiry_scan = 0;
+    hci->device.page_scan = 0;
+    if (hci->device.lmp_name)
+        free((void *) hci->device.lmp_name);
+    hci->device.lmp_name = 0;
+    hci->device.class[0] = 0x00;
+    hci->device.class[1] = 0x00;
+    hci->device.class[2] = 0x00;
+    hci->voice_setting = 0x0000;
+    hci->conn_accept_tout = 0x1f40;
+    hci->lm.inquiry_mode = 0x00;
+
+    hci->psb_handle = 0x000;
+    hci->asb_handle = 0x000;
+
+    /* XXX: qemu_del_timer(sl->acl_mode_timer); for all links */
+    qemu_del_timer(hci->lm.inquiry_done);
+    qemu_del_timer(hci->lm.inquiry_next);
+    qemu_del_timer(hci->conn_accept_timer);
+}
+
+static void bt_hci_read_local_version_rp(struct bt_hci_s *hci)
+{
+    read_local_version_rp lv = {
+        .status		= HCI_SUCCESS,
+        .hci_ver	= 0x03,
+        .hci_rev	= cpu_to_le16(0xa607),
+        .lmp_ver	= 0x03,
+        .manufacturer	= cpu_to_le16(0xa000),
+        .lmp_subver	= cpu_to_le16(0xa607),
+    };
+
+    bt_hci_event_complete(hci, &lv, READ_LOCAL_VERSION_RP_SIZE);
+}
+
+static void bt_hci_read_local_commands_rp(struct bt_hci_s *hci)
+{
+    read_local_commands_rp lc = {
+        .status		= HCI_SUCCESS,
+        .commands	= {
+            /* Keep updated! */
+            /* Also, keep in sync with hci->device.lmp_caps in bt_new_hci */
+            0xbf, 0x80, 0xf9, 0x03, 0xb2, 0xc0, 0x03, 0xc3,
+            0x00, 0x0f, 0x80, 0x00, 0xc0, 0x00, 0xe8, 0x13,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        },
+    };
+
+    bt_hci_event_complete(hci, &lc, READ_LOCAL_COMMANDS_RP_SIZE);
+}
+
+static void bt_hci_read_local_features_rp(struct bt_hci_s *hci)
+{
+    read_local_features_rp lf = {
+        .status		= HCI_SUCCESS,
+        .features	= {
+            (hci->device.lmp_caps >>  0) & 0xff,
+            (hci->device.lmp_caps >>  8) & 0xff,
+            (hci->device.lmp_caps >> 16) & 0xff,
+            (hci->device.lmp_caps >> 24) & 0xff,
+            (hci->device.lmp_caps >> 32) & 0xff,
+            (hci->device.lmp_caps >> 40) & 0xff,
+            (hci->device.lmp_caps >> 48) & 0xff,
+            (hci->device.lmp_caps >> 56) & 0xff,
+        },
+    };
+
+    bt_hci_event_complete(hci, &lf, READ_LOCAL_FEATURES_RP_SIZE);
+}
+
+static void bt_hci_read_local_ext_features_rp(struct bt_hci_s *hci, int page)
+{
+    read_local_ext_features_rp lef = {
+        .status		= HCI_SUCCESS,
+        .page_num	= page,
+        .max_page_num	= 0x00,
+        .features	= {
+            /* Keep updated! */
+            0x5f, 0x35, 0x85, 0x7e, 0x9b, 0x19, 0x00, 0x80,
+        },
+    };
+    if (page)
+        memset(lef.features, 0, sizeof(lef.features));
+
+    bt_hci_event_complete(hci, &lef, READ_LOCAL_EXT_FEATURES_RP_SIZE);
+}
+
+static void bt_hci_read_buffer_size_rp(struct bt_hci_s *hci)
+{
+    read_buffer_size_rp bs = {
+        /* This can be made configurable, for one standard USB dongle HCI
+         * the four values are cpu_to_le16(0x0180), 0x40,
+         * cpu_to_le16(0x0008), cpu_to_le16(0x0008).  */
+        .status		= HCI_SUCCESS,
+        .acl_mtu	= cpu_to_le16(0x0200),
+        .sco_mtu	= 0,
+        .acl_max_pkt	= cpu_to_le16(0x0001),
+        .sco_max_pkt	= cpu_to_le16(0x0000),
+    };
+
+    bt_hci_event_complete(hci, &bs, READ_BUFFER_SIZE_RP_SIZE);
+}
+
+/* Deprecated in V2.0 (page 661) */
+static void bt_hci_read_country_code_rp(struct bt_hci_s *hci)
+{
+    read_country_code_rp cc ={
+        .status		= HCI_SUCCESS,
+        .country_code	= 0x00,	/* North America & Europe^1 and Japan */
+    };
+
+    bt_hci_event_complete(hci, &cc, READ_COUNTRY_CODE_RP_SIZE);
+
+    /* ^1. Except France, sorry */
+}
+
+static void bt_hci_read_bd_addr_rp(struct bt_hci_s *hci)
+{
+    read_bd_addr_rp ba = {
+        .status = HCI_SUCCESS,
+        .bdaddr = BAINIT(&hci->device.bd_addr),
+    };
+
+    bt_hci_event_complete(hci, &ba, READ_BD_ADDR_RP_SIZE);
+}
+
+static int bt_hci_link_quality_rp(struct bt_hci_s *hci, uint16_t handle)
+{
+    read_link_quality_rp lq = {
+        .status		= HCI_SUCCESS,
+        .handle		= HNDL(handle),
+        .link_quality	= 0xff,
+    };
+
+    if (bt_hci_handle_bad(hci, handle))
+        lq.status = HCI_NO_CONNECTION;
+
+    bt_hci_event_complete(hci, &lq, READ_LINK_QUALITY_RP_SIZE);
+    return 0;
+}
+
+/* Generate a Command Complete event with only the Status parameter */
+static inline void bt_hci_event_complete_status(struct bt_hci_s *hci,
+                uint8_t status)
+{
+    bt_hci_event_complete(hci, &status, 1);
+}
+
+static inline void bt_hci_event_complete_conn_cancel(struct bt_hci_s *hci,
+                uint8_t status, bdaddr_t *bd_addr)
+{
+    create_conn_cancel_rp params = {
+        .status = status,
+        .bdaddr = BAINIT(bd_addr),
+    };
+
+    bt_hci_event_complete(hci, &params, CREATE_CONN_CANCEL_RP_SIZE);
+}
+
+static inline void bt_hci_event_auth_complete(struct bt_hci_s *hci,
+                uint16_t handle)
+{
+    evt_auth_complete params = {
+        .status = HCI_SUCCESS,
+        .handle = HNDL(handle),
+    };
+
+    bt_hci_event(hci, EVT_AUTH_COMPLETE, &params, EVT_AUTH_COMPLETE_SIZE);
+}
+
+static inline void bt_hci_event_encrypt_change(struct bt_hci_s *hci,
+                uint16_t handle, uint8_t mode)
+{
+    evt_encrypt_change params = {
+        .status		= HCI_SUCCESS,
+        .handle		= HNDL(handle),
+        .encrypt	= mode,
+    };
+
+    bt_hci_event(hci, EVT_ENCRYPT_CHANGE, &params, EVT_ENCRYPT_CHANGE_SIZE);
+}
+
+static inline void bt_hci_event_complete_name_cancel(struct bt_hci_s *hci,
+                bdaddr_t *bd_addr)
+{
+    remote_name_req_cancel_rp params = {
+        .status = HCI_INVALID_PARAMETERS,
+        .bdaddr = BAINIT(bd_addr),
+    };
+
+    bt_hci_event_complete(hci, &params, REMOTE_NAME_REQ_CANCEL_RP_SIZE);
+}
+
+static inline void bt_hci_event_read_remote_ext_features(struct bt_hci_s *hci,
+                uint16_t handle)
+{
+    evt_read_remote_ext_features_complete params = {
+        .status = HCI_UNSUPPORTED_FEATURE,
+        .handle = HNDL(handle),
+        /* Rest uninitialised */
+    };
+
+    bt_hci_event(hci, EVT_READ_REMOTE_EXT_FEATURES_COMPLETE,
+                    &params, EVT_READ_REMOTE_EXT_FEATURES_COMPLETE_SIZE);
+}
+
+static inline void bt_hci_event_complete_lmp_handle(struct bt_hci_s *hci,
+                uint16_t handle)
+{
+    read_lmp_handle_rp params = {
+        .status		= HCI_NO_CONNECTION,
+        .handle		= HNDL(handle),
+        .reserved	= 0,
+        /* Rest uninitialised */
+    };
+
+    bt_hci_event_complete(hci, &params, READ_LMP_HANDLE_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_role_discovery(struct bt_hci_s *hci,
+                int status, uint16_t handle, int master)
+{
+    role_discovery_rp params = {
+        .status		= status,
+        .handle		= HNDL(handle),
+        .role		= master ? 0x00 : 0x01,
+    };
+
+    bt_hci_event_complete(hci, &params, ROLE_DISCOVERY_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_flush(struct bt_hci_s *hci,
+                int status, uint16_t handle)
+{
+    flush_rp params = {
+        .status		= status,
+        .handle		= HNDL(handle),
+    };
+
+    bt_hci_event_complete(hci, &params, FLUSH_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_read_local_name(struct bt_hci_s *hci)
+{
+    read_local_name_rp params;
+    params.status = HCI_SUCCESS;
+    memset(params.name, 0, sizeof(params.name));
+    if (hci->device.lmp_name)
+        strncpy(params.name, hci->device.lmp_name, sizeof(params.name));
+
+    bt_hci_event_complete(hci, &params, READ_LOCAL_NAME_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_read_conn_accept_timeout(
+                struct bt_hci_s *hci)
+{
+    read_conn_accept_timeout_rp params = {
+        .status		= HCI_SUCCESS,
+        .timeout	= cpu_to_le16(hci->conn_accept_tout),
+    };
+
+    bt_hci_event_complete(hci, &params, READ_CONN_ACCEPT_TIMEOUT_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_read_scan_enable(struct bt_hci_s *hci)
+{
+    read_scan_enable_rp params = {
+        .status = HCI_SUCCESS,
+        .enable =
+                (hci->device.inquiry_scan ? SCAN_INQUIRY : 0) |
+                (hci->device.page_scan ? SCAN_PAGE : 0),
+    };
+
+    bt_hci_event_complete(hci, &params, READ_SCAN_ENABLE_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_read_local_class(struct bt_hci_s *hci)
+{
+    read_class_of_dev_rp params;
+
+    params.status = HCI_SUCCESS;
+    memcpy(params.dev_class, hci->device.class, sizeof(params.dev_class));
+
+    bt_hci_event_complete(hci, &params, READ_CLASS_OF_DEV_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_voice_setting(struct bt_hci_s *hci)
+{
+    read_voice_setting_rp params = {
+        .status		= HCI_SUCCESS,
+        .voice_setting	= hci->voice_setting,	/* Note: no swapping */
+    };
+
+    bt_hci_event_complete(hci, &params, READ_VOICE_SETTING_RP_SIZE);
+}
+
+static inline void bt_hci_event_complete_read_inquiry_mode(
+                struct bt_hci_s *hci)
+{
+    read_inquiry_mode_rp params = {
+        .status		= HCI_SUCCESS,
+        .mode		= hci->lm.inquiry_mode,
+    };
+
+    bt_hci_event_complete(hci, &params, READ_INQUIRY_MODE_RP_SIZE);
+}
+
+static inline void bt_hci_event_num_comp_pkts(struct bt_hci_s *hci,
+                uint16_t handle, int packets)
+{
+    uint16_t buf[EVT_NUM_COMP_PKTS_SIZE(1) / 2 + 1];
+    evt_num_comp_pkts *params = (void *) ((uint8_t *) buf + 1);
+
+    params->num_hndl			= 1;
+    params->connection->handle		= HNDL(handle);
+    params->connection->num_packets	= cpu_to_le16(packets);
+
+    bt_hci_event(hci, EVT_NUM_COMP_PKTS, params, EVT_NUM_COMP_PKTS_SIZE(1));
+}
+
+static void bt_submit_hci(struct HCIInfo *info,
+                const uint8_t *data, int length)
+{
+    struct bt_hci_s *hci = hci_from_info(info);
+    uint16_t cmd;
+    int paramlen, i;
+
+    if (length < HCI_COMMAND_HDR_SIZE)
+        goto short_hci;
+
+    memcpy(&hci->last_cmd, data, 2);
+
+    cmd = (data[1] << 8) | data[0];
+    paramlen = data[2];
+    if (cmd_opcode_ogf(cmd) == 0 || cmd_opcode_ocf(cmd) == 0)	/* NOP */
+        return;
+
+    data += HCI_COMMAND_HDR_SIZE;
+    length -= HCI_COMMAND_HDR_SIZE;
+
+    if (paramlen > length)
+        return;
+
+#define PARAM(cmd, param)	(((cmd##_cp *) data)->param)
+#define PARAM16(cmd, param)	le16_to_cpup(&PARAM(cmd, param))
+#define PARAMHANDLE(cmd)	HNDL(PARAM(cmd, handle))
+#define LENGTH_CHECK(cmd)	if (length < sizeof(cmd##_cp)) goto short_hci
+    /* Note: the supported commands bitmask in bt_hci_read_local_commands_rp
+     * needs to be updated every time a command is implemented here!  */
+    switch (cmd) {
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY):
+        LENGTH_CHECK(inquiry);
+
+        if (PARAM(inquiry, length) < 1) {
+            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        hci->lm.inquire = 1;
+        hci->lm.periodic = 0;
+        hci->lm.responses_left = PARAM(inquiry, num_rsp) ?: INT_MAX;
+        hci->lm.responses = 0;
+        bt_hci_event_status(hci, HCI_SUCCESS);
+        bt_hci_inquiry_start(hci, PARAM(inquiry, length));
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_INQUIRY_CANCEL):
+        if (!hci->lm.inquire || hci->lm.periodic) {
+            fprintf(stderr, "%s: Inquiry Cancel should only be issued after "
+                            "the Inquiry command has been issued, a Command "
+                            "Status event has been received for the Inquiry "
+                            "command, and before the Inquiry Complete event "
+                            "occurs", __FUNCTION__);
+            bt_hci_event_complete_status(hci, HCI_COMMAND_DISALLOWED);
+            break;
+        }
+
+        hci->lm.inquire = 0;
+        qemu_del_timer(hci->lm.inquiry_done);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_PERIODIC_INQUIRY):
+        LENGTH_CHECK(periodic_inquiry);
+
+        if (!(PARAM(periodic_inquiry, length) <
+                                PARAM16(periodic_inquiry, min_period) &&
+                                PARAM16(periodic_inquiry, min_period) <
+                                PARAM16(periodic_inquiry, max_period)) ||
+                        PARAM(periodic_inquiry, length) < 1 ||
+                        PARAM16(periodic_inquiry, min_period) < 2 ||
+                        PARAM16(periodic_inquiry, max_period) < 3) {
+            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        hci->lm.inquire = 1;
+        hci->lm.periodic = 1;
+        hci->lm.responses_left = PARAM(periodic_inquiry, num_rsp);
+        hci->lm.responses = 0;
+        hci->lm.inquiry_period = PARAM16(periodic_inquiry, max_period);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        bt_hci_inquiry_start(hci, PARAM(periodic_inquiry, length));
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_EXIT_PERIODIC_INQUIRY):
+        if (!hci->lm.inquire || !hci->lm.periodic) {
+            fprintf(stderr, "%s: Inquiry Cancel should only be issued after "
+                            "the Inquiry command has been issued, a Command "
+                            "Status event has been received for the Inquiry "
+                            "command, and before the Inquiry Complete event "
+                            "occurs", __FUNCTION__);
+            bt_hci_event_complete_status(hci, HCI_COMMAND_DISALLOWED);
+            break;
+        }
+        hci->lm.inquire = 0;
+        qemu_del_timer(hci->lm.inquiry_done);
+        qemu_del_timer(hci->lm.inquiry_next);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_CREATE_CONN):
+        LENGTH_CHECK(create_conn);
+
+        if (hci->lm.connecting >= HCI_HANDLES_MAX) {
+            bt_hci_event_status(hci, HCI_REJECTED_LIMITED_RESOURCES);
+            break;
+        }
+        bt_hci_event_status(hci, HCI_SUCCESS);
+
+        if (bt_hci_connect(hci, &PARAM(create_conn, bdaddr)))
+            bt_hci_connection_reject_event(hci, &PARAM(create_conn, bdaddr));
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_DISCONNECT):
+        LENGTH_CHECK(disconnect);
+
+        if (bt_hci_handle_bad(hci, PARAMHANDLE(disconnect))) {
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+            break;
+        }
+
+        bt_hci_event_status(hci, HCI_SUCCESS);
+        bt_hci_disconnect(hci, PARAMHANDLE(disconnect),
+                        PARAM(disconnect, reason));
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_CREATE_CONN_CANCEL):
+        LENGTH_CHECK(create_conn_cancel);
+
+        if (bt_hci_lmp_connection_ready(hci,
+                                &PARAM(create_conn_cancel, bdaddr))) {
+            for (i = 0; i < HCI_HANDLES_MAX; i ++)
+                if (bt_hci_role_master(hci, i) && hci->lm.handle[i].link &&
+                                !bacmp(&hci->lm.handle[i].link->slave->bd_addr,
+                                        &PARAM(create_conn_cancel, bdaddr)))
+                   break;
+
+            bt_hci_event_complete_conn_cancel(hci, i < HCI_HANDLES_MAX ?
+                            HCI_ACL_CONNECTION_EXISTS : HCI_NO_CONNECTION,
+                            &PARAM(create_conn_cancel, bdaddr));
+        } else
+            bt_hci_event_complete_conn_cancel(hci, HCI_SUCCESS,
+                            &PARAM(create_conn_cancel, bdaddr));
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_ACCEPT_CONN_REQ):
+        LENGTH_CHECK(accept_conn_req);
+
+        if (!hci->conn_req_host ||
+                        bacmp(&PARAM(accept_conn_req, bdaddr),
+                                &hci->conn_req_host->bd_addr)) {
+            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        bt_hci_event_status(hci, HCI_SUCCESS);
+        bt_hci_connection_accept(hci, hci->conn_req_host);
+        hci->conn_req_host = 0;
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_REJECT_CONN_REQ):
+        LENGTH_CHECK(reject_conn_req);
+
+        if (!hci->conn_req_host ||
+                        bacmp(&PARAM(reject_conn_req, bdaddr),
+                                &hci->conn_req_host->bd_addr)) {
+            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        bt_hci_event_status(hci, HCI_SUCCESS);
+        bt_hci_connection_reject(hci, hci->conn_req_host,
+                        PARAM(reject_conn_req, reason));
+        bt_hci_connection_reject_event(hci, &hci->conn_req_host->bd_addr);
+        hci->conn_req_host = 0;
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_AUTH_REQUESTED):
+        LENGTH_CHECK(auth_requested);
+
+        if (bt_hci_handle_bad(hci, PARAMHANDLE(auth_requested)))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        else {
+            bt_hci_event_status(hci, HCI_SUCCESS);
+            bt_hci_event_auth_complete(hci, PARAMHANDLE(auth_requested));
+        }
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_SET_CONN_ENCRYPT):
+        LENGTH_CHECK(set_conn_encrypt);
+
+        if (bt_hci_handle_bad(hci, PARAMHANDLE(set_conn_encrypt)))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        else {
+            bt_hci_event_status(hci, HCI_SUCCESS);
+            bt_hci_event_encrypt_change(hci,
+                            PARAMHANDLE(set_conn_encrypt),
+                            PARAM(set_conn_encrypt, encrypt));
+        }
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_REMOTE_NAME_REQ):
+        LENGTH_CHECK(remote_name_req);
+
+        if (bt_hci_name_req(hci, &PARAM(remote_name_req, bdaddr)))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_REMOTE_NAME_REQ_CANCEL):
+        LENGTH_CHECK(remote_name_req_cancel);
+
+        bt_hci_event_complete_name_cancel(hci,
+                        &PARAM(remote_name_req_cancel, bdaddr));
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_REMOTE_FEATURES):
+        LENGTH_CHECK(read_remote_features);
+
+        if (bt_hci_features_req(hci, PARAMHANDLE(read_remote_features)))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_REMOTE_EXT_FEATURES):
+        LENGTH_CHECK(read_remote_ext_features);
+
+        if (bt_hci_handle_bad(hci, PARAMHANDLE(read_remote_ext_features)))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        else {
+            bt_hci_event_status(hci, HCI_SUCCESS);
+            bt_hci_event_read_remote_ext_features(hci,
+                            PARAMHANDLE(read_remote_ext_features));
+        }
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_REMOTE_VERSION):
+        LENGTH_CHECK(read_remote_version);
+
+        if (bt_hci_version_req(hci, PARAMHANDLE(read_remote_version)))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_CLOCK_OFFSET):
+        LENGTH_CHECK(read_clock_offset);
+
+        if (bt_hci_clkoffset_req(hci, PARAMHANDLE(read_clock_offset)))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_CTL, OCF_READ_LMP_HANDLE):
+        LENGTH_CHECK(read_lmp_handle);
+
+        /* TODO: */
+        bt_hci_event_complete_lmp_handle(hci, PARAMHANDLE(read_lmp_handle));
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_HOLD_MODE):
+        LENGTH_CHECK(hold_mode);
+
+        if (PARAM16(hold_mode, min_interval) >
+                        PARAM16(hold_mode, max_interval) ||
+                        PARAM16(hold_mode, min_interval) < 0x0002 ||
+                        PARAM16(hold_mode, max_interval) > 0xff00 ||
+                        (PARAM16(hold_mode, min_interval) & 1) ||
+                        (PARAM16(hold_mode, max_interval) & 1)) {
+            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        if (bt_hci_mode_change(hci, PARAMHANDLE(hold_mode),
+                                PARAM16(hold_mode, max_interval),
+                                acl_hold))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_PARK_MODE):
+        LENGTH_CHECK(park_mode);
+
+        if (PARAM16(park_mode, min_interval) >
+                        PARAM16(park_mode, max_interval) ||
+                        PARAM16(park_mode, min_interval) < 0x000e ||
+                        (PARAM16(park_mode, min_interval) & 1) ||
+                        (PARAM16(park_mode, max_interval) & 1)) {
+            bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        if (bt_hci_mode_change(hci, PARAMHANDLE(park_mode),
+                                PARAM16(park_mode, max_interval),
+                                acl_parked))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_EXIT_PARK_MODE):
+        LENGTH_CHECK(exit_park_mode);
+
+        if (bt_hci_mode_cancel(hci, PARAMHANDLE(exit_park_mode),
+                                acl_parked))
+            bt_hci_event_status(hci, HCI_NO_CONNECTION);
+        break;
+
+    case cmd_opcode_pack(OGF_LINK_POLICY, OCF_ROLE_DISCOVERY):
+        LENGTH_CHECK(role_discovery);
+
+        if (bt_hci_handle_bad(hci, PARAMHANDLE(role_discovery)))
+            bt_hci_event_complete_role_discovery(hci,
+                            HCI_NO_CONNECTION, PARAMHANDLE(role_discovery), 0);
+        else
+            bt_hci_event_complete_role_discovery(hci,
+                            HCI_SUCCESS, PARAMHANDLE(role_discovery),
+                            bt_hci_role_master(hci,
+                                    PARAMHANDLE(role_discovery)));
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_SET_EVENT_MASK):
+        LENGTH_CHECK(set_event_mask);
+
+        memcpy(hci->event_mask, PARAM(set_event_mask, mask), 8);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_RESET):
+        bt_hci_reset(hci);
+        bt_hci_event_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_SET_EVENT_FLT):
+        if (length >= 1 && PARAM(set_event_flt, flt_type) == FLT_CLEAR_ALL)
+            /* No length check */;
+        else
+            LENGTH_CHECK(set_event_flt);
+
+        /* Filters are not implemented */
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_FLUSH):
+        LENGTH_CHECK(flush);
+
+        if (bt_hci_handle_bad(hci, PARAMHANDLE(flush)))
+            bt_hci_event_complete_flush(hci,
+                            HCI_NO_CONNECTION, PARAMHANDLE(flush));
+        else {
+            /* TODO: ordering? */
+            bt_hci_event(hci, EVT_FLUSH_OCCURRED,
+                            &PARAM(flush, handle),
+                            EVT_FLUSH_OCCURRED_SIZE);
+            bt_hci_event_complete_flush(hci,
+                            HCI_SUCCESS, PARAMHANDLE(flush));
+        }
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_CHANGE_LOCAL_NAME):
+        LENGTH_CHECK(change_local_name);
+
+        if (hci->device.lmp_name)
+            free((void *) hci->device.lmp_name);
+        hci->device.lmp_name = strndup(PARAM(change_local_name, name),
+                        sizeof(PARAM(change_local_name, name)));
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_LOCAL_NAME):
+        bt_hci_event_complete_read_local_name(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_CONN_ACCEPT_TIMEOUT):
+        bt_hci_event_complete_read_conn_accept_timeout(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CONN_ACCEPT_TIMEOUT):
+        /* TODO */
+        LENGTH_CHECK(write_conn_accept_timeout);
+
+        if (PARAM16(write_conn_accept_timeout, timeout) < 0x0001 ||
+                        PARAM16(write_conn_accept_timeout, timeout) > 0xb540) {
+            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        hci->conn_accept_tout = PARAM16(write_conn_accept_timeout, timeout);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_SCAN_ENABLE):
+        bt_hci_event_complete_read_scan_enable(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_SCAN_ENABLE):
+        LENGTH_CHECK(write_scan_enable);
+
+        /* TODO: check that the remaining bits are all 0 */
+        hci->device.inquiry_scan =
+                !!(PARAM(write_scan_enable, scan_enable) & SCAN_INQUIRY);
+        hci->device.page_scan =
+                !!(PARAM(write_scan_enable, scan_enable) & SCAN_PAGE);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_CLASS_OF_DEV):
+        bt_hci_event_complete_read_local_class(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_CLASS_OF_DEV):
+        LENGTH_CHECK(write_class_of_dev);
+
+        memcpy(hci->device.class, PARAM(write_class_of_dev, dev_class),
+                        sizeof(PARAM(write_class_of_dev, dev_class)));
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_VOICE_SETTING):
+        bt_hci_event_complete_voice_setting(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_VOICE_SETTING):
+        LENGTH_CHECK(write_voice_setting);
+
+        hci->voice_setting = PARAM(write_voice_setting, voice_setting);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_HOST_NUMBER_OF_COMPLETED_PACKETS):
+        if (length < data[0] * 2 + 1)
+            goto short_hci;
+
+        for (i = 0; i < data[0]; i ++)
+            if (bt_hci_handle_bad(hci,
+                                    data[i * 2 + 1] | (data[i * 2 + 2] << 8)))
+                bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_READ_INQUIRY_MODE):
+        /* Only if (local_features[3] & 0x40) && (local_commands[12] & 0x40)
+         * else
+         *     goto unknown_command */
+        bt_hci_event_complete_read_inquiry_mode(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_HOST_CTL, OCF_WRITE_INQUIRY_MODE):
+        /* Only if (local_features[3] & 0x40) && (local_commands[12] & 0x80)
+         * else
+         *     goto unknown_command */
+        LENGTH_CHECK(write_inquiry_mode);
+
+        if (PARAM(write_inquiry_mode, mode) > 0x01) {
+            bt_hci_event_complete_status(hci, HCI_INVALID_PARAMETERS);
+            break;
+        }
+
+        hci->lm.inquiry_mode = PARAM(write_inquiry_mode, mode);
+        bt_hci_event_complete_status(hci, HCI_SUCCESS);
+        break;
+
+    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_VERSION):
+        bt_hci_read_local_version_rp(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_COMMANDS):
+        bt_hci_read_local_commands_rp(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_FEATURES):
+        bt_hci_read_local_features_rp(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_LOCAL_EXT_FEATURES):
+        LENGTH_CHECK(read_local_ext_features);
+
+        bt_hci_read_local_ext_features_rp(hci,
+                        PARAM(read_local_ext_features, page_num));
+        break;
+
+    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BUFFER_SIZE):
+        bt_hci_read_buffer_size_rp(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_COUNTRY_CODE):
+        bt_hci_read_country_code_rp(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_INFO_PARAM, OCF_READ_BD_ADDR):
+        bt_hci_read_bd_addr_rp(hci);
+        break;
+
+    case cmd_opcode_pack(OGF_STATUS_PARAM, OCF_READ_LINK_QUALITY):
+        LENGTH_CHECK(read_link_quality);
+
+        bt_hci_link_quality_rp(hci, PARAMHANDLE(read_link_quality));
+        break;
+
+    default:
+        bt_hci_event_status(hci, HCI_UNKNOWN_COMMAND);
+        break;
+
+    short_hci:
+        fprintf(stderr, "%s: HCI packet too short (%iB)\n",
+                        __FUNCTION__, length);
+        bt_hci_event_status(hci, HCI_INVALID_PARAMETERS);
+        break;
+    }
+}
+
+/* We could perform fragmentation here, we can't do "recombination" because
+ * at this layer the length of the payload is not know ahead, so we only
+ * know that a packet contained the last fragment of the SDU when the next
+ * SDU starts.  */
+static inline void bt_hci_lmp_acl_data(struct bt_hci_s *hci, uint16_t handle,
+                const uint8_t *data, int start, int len)
+{
+    struct hci_acl_hdr *pkt = (void *) hci->acl_buf;
+
+    /* TODO: packet flags */
+    /* TODO: avoid memcpy'ing */
+
+    if (len + HCI_ACL_HDR_SIZE > sizeof(hci->acl_buf)) {
+        fprintf(stderr, "%s: can't take ACL packets %i bytes long\n",
+                        __FUNCTION__, len);
+        return;
+    }
+    memcpy(hci->acl_buf + HCI_ACL_HDR_SIZE, data, len);
+
+    pkt->handle = cpu_to_le16(
+                    acl_handle_pack(handle, start ? ACL_START : ACL_CONT));
+    pkt->dlen = cpu_to_le16(len);
+    hci->info.acl_recv(hci->info.opaque,
+                    hci->acl_buf, len + HCI_ACL_HDR_SIZE);
+}
+
+static void bt_hci_lmp_acl_data_slave(struct bt_link_s *btlink,
+                const uint8_t *data, int start, int len)
+{
+    struct bt_hci_link_s *link = (struct bt_hci_link_s *) btlink;
+
+    bt_hci_lmp_acl_data(hci_from_device(btlink->slave),
+                    link->handle, data, start, len);
+}
+
+static void bt_hci_lmp_acl_data_host(struct bt_link_s *link,
+                const uint8_t *data, int start, int len)
+{
+    bt_hci_lmp_acl_data(hci_from_device(link->host),
+                    link->handle, data, start, len);
+}
+
+static void bt_submit_acl(struct HCIInfo *info,
+                const uint8_t *data, int length)
+{
+    struct bt_hci_s *hci = hci_from_info(info);
+    uint16_t handle;
+    int datalen, flags;
+    struct bt_link_s *link;
+
+    if (length < HCI_ACL_HDR_SIZE) {
+        fprintf(stderr, "%s: ACL packet too short (%iB)\n",
+                        __FUNCTION__, length);
+        return;
+    }
+
+    handle = acl_handle((data[1] << 8) | data[0]);
+    flags = acl_flags((data[1] << 8) | data[0]);
+    datalen = (data[3] << 8) | data[2];
+    data += HCI_ACL_HDR_SIZE;
+    length -= HCI_ACL_HDR_SIZE;
+
+    if (bt_hci_handle_bad(hci, handle)) {
+        fprintf(stderr, "%s: invalid ACL handle %03x\n",
+                        __FUNCTION__, handle);
+        /* TODO: signal an error */
+        return;
+    }
+    handle &= ~HCI_HANDLE_OFFSET;
+
+    if (datalen > length) {
+        fprintf(stderr, "%s: ACL packet too short (%iB < %iB)\n",
+                        __FUNCTION__, length, datalen);
+        return;
+    }
+
+    link = hci->lm.handle[handle].link;
+
+    if ((flags & ~3) == ACL_ACTIVE_BCAST) {
+        if (!hci->asb_handle)
+            hci->asb_handle = handle;
+        else if (handle != hci->asb_handle) {
+            fprintf(stderr, "%s: Bad handle %03x in Active Slave Broadcast\n",
+                            __FUNCTION__, handle);
+            /* TODO: signal an error */
+            return;
+        }
+
+        /* TODO */
+    }
+
+    if ((flags & ~3) == ACL_PICO_BCAST) {
+        if (!hci->psb_handle)
+            hci->psb_handle = handle;
+        else if (handle != hci->psb_handle) {
+            fprintf(stderr, "%s: Bad handle %03x in Parked Slave Broadcast\n",
+                            __FUNCTION__, handle);
+            /* TODO: signal an error */
+            return;
+        }
+
+        /* TODO */
+    }
+
+    /* TODO: increase counter and send EVT_NUM_COMP_PKTS */
+    bt_hci_event_num_comp_pkts(hci, handle | HCI_HANDLE_OFFSET, 1);
+
+    /* Do this last as it can trigger further events even in this HCI */
+    hci->lm.handle[handle].lmp_acl_data(link, data,
+                    (flags & 3) == ACL_START, length);
+}
+
+static void bt_submit_sco(struct HCIInfo *info,
+                const uint8_t *data, int length)
+{
+    struct bt_hci_s *hci = hci_from_info(info);
+    struct bt_link_s *link;
+    uint16_t handle;
+    int datalen;
+
+    if (length < 3)
+        return;
+
+    handle = acl_handle((data[1] << 8) | data[0]);
+    datalen = data[2];
+    data += 3;
+    length -= 3;
+
+    if (bt_hci_handle_bad(hci, handle)) {
+        fprintf(stderr, "%s: invalid SCO handle %03x\n",
+                        __FUNCTION__, handle);
+        return;
+    }
+    handle &= ~HCI_HANDLE_OFFSET;
+
+    if (datalen > length) {
+        fprintf(stderr, "%s: SCO packet too short (%iB < %iB)\n",
+                        __FUNCTION__, length, datalen);
+        return;
+    }
+
+    link = hci->lm.handle[handle].link;
+    /* TODO */
+
+    /* TODO: increase counter and send EVT_NUM_COMP_PKTS if synchronous
+     * Flow Control is enabled.
+     * (See Read/Write_Synchronous_Flow_Control_Enable on page 513 and
+     * page 514.)  */
+}
+
+static uint8_t *bt_hci_evt_packet(void *opaque)
+{
+    /* TODO: allocate a packet from upper layer */
+    struct bt_hci_s *s = opaque;
+
+    return s->evt_buf;
+}
+
+static void bt_hci_evt_submit(void *opaque, int len)
+{
+    /* TODO: notify upper layer */
+    struct bt_hci_s *s = opaque;
+
+    return s->info.evt_recv(s->info.opaque, s->evt_buf, len);
+}
+
+static int bt_hci_bdaddr_set(struct HCIInfo *info, const uint8_t *bd_addr)
+{
+    struct bt_hci_s *hci = hci_from_info(info);
+
+    bacpy(&hci->device.bd_addr, (const bdaddr_t *) bd_addr);
+    return 0;
+}
+
+static void bt_hci_done(struct HCIInfo *info);
+static void bt_hci_destroy(struct bt_device_s *dev)
+{
+    struct bt_hci_s *hci = hci_from_device(dev);
+
+    return bt_hci_done(&hci->info);
+}
+
+struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net)
+{
+    struct bt_hci_s *s = qemu_mallocz(sizeof(struct bt_hci_s));
+
+    s->lm.inquiry_done = qemu_new_timer(vm_clock, bt_hci_inquiry_done, s);
+    s->lm.inquiry_next = qemu_new_timer(vm_clock, bt_hci_inquiry_next, s);
+    s->conn_accept_timer =
+            qemu_new_timer(vm_clock, bt_hci_conn_accept_timeout, s);
+
+    s->evt_packet = bt_hci_evt_packet;
+    s->evt_submit = bt_hci_evt_submit;
+    s->opaque = s;
+
+    bt_device_init(&s->device, net);
+    s->device.lmp_connection_request = bt_hci_lmp_connection_request;
+    s->device.lmp_connection_complete = bt_hci_lmp_connection_complete;
+    s->device.lmp_disconnect_master = bt_hci_lmp_disconnect_host;
+    s->device.lmp_disconnect_slave = bt_hci_lmp_disconnect_slave;
+    s->device.lmp_acl_data = bt_hci_lmp_acl_data_slave;
+    s->device.lmp_acl_resp = bt_hci_lmp_acl_data_host;
+    s->device.lmp_mode_change = bt_hci_lmp_mode_change_slave;
+
+    /* Keep updated! */
+    /* Also keep in sync with supported commands bitmask in
+     * bt_hci_read_local_commands_rp */
+    s->device.lmp_caps = 0x8000199b7e85355fll;
+
+    bt_hci_reset(s);
+
+    s->info.cmd_send = bt_submit_hci;
+    s->info.sco_send = bt_submit_sco;
+    s->info.acl_send = bt_submit_acl;
+    s->info.bdaddr_set = bt_hci_bdaddr_set;
+
+    s->device.handle_destroy = bt_hci_destroy;
+
+    return &s->info;
+}
+
+static void bt_hci_done(struct HCIInfo *info)
+{
+    struct bt_hci_s *hci = hci_from_info(info);
+    int handle;
+
+    bt_device_done(&hci->device);
+
+    if (hci->device.lmp_name)
+        free((void *) hci->device.lmp_name);
+
+    /* Be gentle and send DISCONNECT to all connected peers and those
+     * currently waiting for us to accept or reject a connection request.
+     * This frees the links.  */
+    if (hci->conn_req_host)
+        return bt_hci_connection_reject(hci,
+                        hci->conn_req_host, HCI_OE_POWER_OFF);
+
+    for (handle = HCI_HANDLE_OFFSET;
+                    handle < (HCI_HANDLE_OFFSET | HCI_HANDLES_MAX); handle ++)
+        if (!bt_hci_handle_bad(hci, handle))
+            bt_hci_disconnect(hci, handle, HCI_OE_POWER_OFF);
+
+    /* TODO: this is not enough actually, there may be slaves from whom
+     * we have requested a connection who will soon (or not) respond with
+     * an accept or a reject, so we should also check if hci->lm.connecting
+     * is non-zero and if so, avoid freeing the hci but otherwise disappear
+     * from all qemu social life (e.g. stop scanning and request to be
+     * removed from s->device.net) and arrange for
+     * s->device.lmp_connection_complete to free the remaining bits once
+     * hci->lm.awaiting_bdaddr[] is empty.  */
+
+    qemu_free_timer(hci->lm.inquiry_done);
+    qemu_free_timer(hci->lm.inquiry_next);
+    qemu_free_timer(hci->conn_accept_timer);
+
+    qemu_free(hci);
+}
diff -Nur kvm-76/qemu/hw/bt-hid.c kvm-userspace/qemu/hw/bt-hid.c
--- kvm-76/qemu/hw/bt-hid.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/bt-hid.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,571 @@
+/*
+ * QEMU Bluetooth HID Profile wrapper for USB HID.
+ *
+ * Copyright (C) 2007-2008 OpenMoko, Inc.
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "usb.h"
+#include "bt.h"
+
+enum hid_transaction_req {
+    BT_HANDSHAKE			= 0x0,
+    BT_HID_CONTROL			= 0x1,
+    BT_GET_REPORT			= 0x4,
+    BT_SET_REPORT			= 0x5,
+    BT_GET_PROTOCOL			= 0x6,
+    BT_SET_PROTOCOL			= 0x7,
+    BT_GET_IDLE				= 0x8,
+    BT_SET_IDLE				= 0x9,
+    BT_DATA				= 0xa,
+    BT_DATC				= 0xb,
+};
+
+enum hid_transaction_handshake {
+    BT_HS_SUCCESSFUL			= 0x0,
+    BT_HS_NOT_READY			= 0x1,
+    BT_HS_ERR_INVALID_REPORT_ID		= 0x2,
+    BT_HS_ERR_UNSUPPORTED_REQUEST	= 0x3,
+    BT_HS_ERR_INVALID_PARAMETER		= 0x4,
+    BT_HS_ERR_UNKNOWN			= 0xe,
+    BT_HS_ERR_FATAL			= 0xf,
+};
+
+enum hid_transaction_control {
+    BT_HC_NOP				= 0x0,
+    BT_HC_HARD_RESET			= 0x1,
+    BT_HC_SOFT_RESET			= 0x2,
+    BT_HC_SUSPEND			= 0x3,
+    BT_HC_EXIT_SUSPEND			= 0x4,
+    BT_HC_VIRTUAL_CABLE_UNPLUG		= 0x5,
+};
+
+enum hid_protocol {
+    BT_HID_PROTO_BOOT			= 0,
+    BT_HID_PROTO_REPORT			= 1,
+};
+
+enum hid_boot_reportid {
+    BT_HID_BOOT_INVALID			= 0,
+    BT_HID_BOOT_KEYBOARD,
+    BT_HID_BOOT_MOUSE,
+};
+
+enum hid_data_pkt {
+    BT_DATA_OTHER			= 0,
+    BT_DATA_INPUT,
+    BT_DATA_OUTPUT,
+    BT_DATA_FEATURE,
+};
+
+#define BT_HID_MTU			48
+
+/* HID interface requests */
+#define GET_REPORT			0xa101
+#define GET_IDLE			0xa102
+#define GET_PROTOCOL			0xa103
+#define SET_REPORT			0x2109
+#define SET_IDLE			0x210a
+#define SET_PROTOCOL			0x210b
+
+struct bt_hid_device_s {
+    struct bt_l2cap_device_s btdev;
+    struct bt_l2cap_conn_params_s *control;
+    struct bt_l2cap_conn_params_s *interrupt;
+    USBDevice *usbdev;
+
+    int proto;
+    int connected;
+    int data_type;
+    int intr_state;
+    struct {
+        int len;
+        uint8_t buffer[1024];
+    } dataother, datain, dataout, feature, intrdataout;
+    enum {
+        bt_state_ready,
+        bt_state_transaction,
+        bt_state_suspend,
+    } state;
+};
+
+static void bt_hid_reset(struct bt_hid_device_s *s)
+{
+    struct bt_scatternet_s *net = s->btdev.device.net;
+
+    /* Go as far as... */
+    bt_l2cap_device_done(&s->btdev);
+    bt_l2cap_device_init(&s->btdev, net);
+
+    s->usbdev->handle_reset(s->usbdev);
+    s->proto = BT_HID_PROTO_REPORT;
+    s->state = bt_state_ready;
+    s->dataother.len = 0;
+    s->datain.len = 0;
+    s->dataout.len = 0;
+    s->feature.len = 0;
+    s->intrdataout.len = 0;
+    s->intr_state = 0;
+}
+
+static int bt_hid_out(struct bt_hid_device_s *s)
+{
+    USBPacket p;
+
+    if (s->data_type == BT_DATA_OUTPUT) {
+        p.pid = USB_TOKEN_OUT;
+        p.devep = 1;
+        p.data = s->dataout.buffer;
+        p.len = s->dataout.len;
+        s->dataout.len = s->usbdev->handle_data(s->usbdev, &p);
+
+        return s->dataout.len;
+    }
+
+    if (s->data_type == BT_DATA_FEATURE) {
+        /* XXX:
+         * does this send a USB_REQ_CLEAR_FEATURE/USB_REQ_SET_FEATURE
+         * or a SET_REPORT? */
+        p.devep = 0;
+    }
+
+    return -1;
+}
+
+static int bt_hid_in(struct bt_hid_device_s *s)
+{
+    USBPacket p;
+
+    p.pid = USB_TOKEN_IN;
+    p.devep = 1;
+    p.data = s->datain.buffer;
+    p.len = sizeof(s->datain.buffer);
+    s->datain.len = s->usbdev->handle_data(s->usbdev, &p);
+
+    return s->datain.len;
+}
+
+static void bt_hid_send_handshake(struct bt_hid_device_s *s, int result)
+{
+    *s->control->sdu_out(s->control, 1) =
+            (BT_HANDSHAKE << 4) | result;
+    s->control->sdu_submit(s->control);
+}
+
+static void bt_hid_send_control(struct bt_hid_device_s *s, int operation)
+{
+    *s->control->sdu_out(s->control, 1) =
+            (BT_HID_CONTROL << 4) | operation;
+    s->control->sdu_submit(s->control);
+}
+
+static void bt_hid_disconnect(struct bt_hid_device_s *s)
+{
+    /* Disconnect s->control and s->interrupt */
+}
+
+static void bt_hid_send_data(struct bt_l2cap_conn_params_s *ch, int type,
+                const uint8_t *data, int len)
+{
+    uint8_t *pkt, hdr = (BT_DATA << 4) | type;
+    int plen;
+
+    do {
+        plen = MIN(len, ch->remote_mtu - 1);
+        pkt = ch->sdu_out(ch, plen + 1);
+
+        pkt[0] = hdr;
+        if (plen)
+            memcpy(pkt + 1, data, plen);
+        ch->sdu_submit(ch);
+
+        len -= plen;
+        data += plen;
+        hdr = (BT_DATC << 4) | type;
+    } while (plen == ch->remote_mtu - 1);
+}
+
+static void bt_hid_control_transaction(struct bt_hid_device_s *s,
+                const uint8_t *data, int len)
+{
+    uint8_t type, parameter;
+    int rlen, ret = -1;
+    if (len < 1)
+        return;
+
+    type = data[0] >> 4;
+    parameter = data[0] & 0xf;
+
+    switch (type) {
+    case BT_HANDSHAKE:
+    case BT_DATA:
+        switch (parameter) {
+        default:
+            /* These are not expected to be sent this direction.  */
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+        }
+        break;
+
+    case BT_HID_CONTROL:
+        if (len != 1 || (parameter != BT_HC_VIRTUAL_CABLE_UNPLUG &&
+                                s->state == bt_state_transaction)) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+        switch (parameter) {
+        case BT_HC_NOP:
+            break;
+        case BT_HC_HARD_RESET:
+        case BT_HC_SOFT_RESET:
+            bt_hid_reset(s);
+            break;
+        case BT_HC_SUSPEND:
+            if (s->state == bt_state_ready)
+                s->state = bt_state_suspend;
+            else
+                ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        case BT_HC_EXIT_SUSPEND:
+            if (s->state == bt_state_suspend)
+                s->state = bt_state_ready;
+            else
+                ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        case BT_HC_VIRTUAL_CABLE_UNPLUG:
+            bt_hid_disconnect(s);
+            break;
+        default:
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+        }
+        break;
+
+    case BT_GET_REPORT:
+        /* No ReportIDs declared.  */
+        if (((parameter & 8) && len != 3) ||
+                        (!(parameter & 8) && len != 1) ||
+                        s->state != bt_state_ready) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (parameter & 8)
+            rlen = data[2] | (data[3] << 8);
+        else
+            rlen = INT_MAX;
+        switch (parameter & 3) {
+        case BT_DATA_OTHER:
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        case BT_DATA_INPUT:
+            /* Here we can as well poll s->usbdev */
+            bt_hid_send_data(s->control, BT_DATA_INPUT,
+                            s->datain.buffer, MIN(rlen, s->datain.len));
+            break;
+        case BT_DATA_OUTPUT:
+            bt_hid_send_data(s->control, BT_DATA_OUTPUT,
+                            s->dataout.buffer, MIN(rlen, s->dataout.len));
+            break;
+        case BT_DATA_FEATURE:
+            bt_hid_send_data(s->control, BT_DATA_FEATURE,
+                            s->feature.buffer, MIN(rlen, s->feature.len));
+            break;
+        }
+        break;
+
+    case BT_SET_REPORT:
+        if (len < 2 || len > BT_HID_MTU || s->state != bt_state_ready ||
+                        (parameter & 3) == BT_DATA_OTHER ||
+                        (parameter & 3) == BT_DATA_INPUT) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+        s->data_type = parameter & 3;
+        if (s->data_type == BT_DATA_OUTPUT) {
+            s->dataout.len = len - 1;
+            memcpy(s->dataout.buffer, data + 1, s->dataout.len);
+        } else {
+            s->feature.len = len - 1;
+            memcpy(s->feature.buffer, data + 1, s->feature.len);
+        }
+        if (len == BT_HID_MTU)
+            s->state = bt_state_transaction;
+        else
+            bt_hid_out(s);
+        break;
+
+    case BT_GET_PROTOCOL:
+        if (len != 1 || s->state == bt_state_transaction) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+        *s->control->sdu_out(s->control, 1) = s->proto;
+        s->control->sdu_submit(s->control);
+        break;
+
+    case BT_SET_PROTOCOL:
+        if (len != 1 || s->state == bt_state_transaction ||
+                        (parameter != BT_HID_PROTO_BOOT &&
+                         parameter != BT_HID_PROTO_REPORT)) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+        s->proto = parameter;
+        s->usbdev->handle_control(s->usbdev, SET_PROTOCOL, s->proto, 0, 0, 0);
+        ret = BT_HS_SUCCESSFUL;
+        break;
+
+    case BT_GET_IDLE:
+        if (len != 1 || s->state == bt_state_transaction) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+        s->usbdev->handle_control(s->usbdev, GET_IDLE, 0, 0, 1,
+                        s->control->sdu_out(s->control, 1));
+        s->control->sdu_submit(s->control);
+        break;
+
+    case BT_SET_IDLE:
+        if (len != 2 || s->state == bt_state_transaction) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+
+        /* We don't need to know about the Idle Rate here really,
+         * so just pass it on to the device.  */
+        ret = s->usbdev->handle_control(s->usbdev,
+                        SET_IDLE, data[1], 0, 0, 0) ?
+                BT_HS_SUCCESSFUL : BT_HS_ERR_INVALID_PARAMETER;
+        /* XXX: Does this generate a handshake? */
+        break;
+
+    case BT_DATC:
+        if (len > BT_HID_MTU || s->state != bt_state_transaction) {
+            ret = BT_HS_ERR_INVALID_PARAMETER;
+            break;
+        }
+        if (s->data_type == BT_DATA_OUTPUT) {
+            memcpy(s->dataout.buffer + s->dataout.len, data + 1, len - 1);
+            s->dataout.len += len - 1;
+        } else {
+            memcpy(s->feature.buffer + s->feature.len, data + 1, len - 1);
+            s->feature.len += len - 1;
+        }
+        if (len < BT_HID_MTU) {
+            bt_hid_out(s);
+            s->state = bt_state_ready;
+        }
+        break;
+
+    default:
+        ret = BT_HS_ERR_UNSUPPORTED_REQUEST;
+    }
+
+    if (ret != -1)
+        bt_hid_send_handshake(s, ret);
+}
+
+static void bt_hid_control_sdu(void *opaque, const uint8_t *data, int len)
+{
+    struct bt_hid_device_s *hid = opaque;
+
+    return bt_hid_control_transaction(hid, data, len);
+}
+
+static void bt_hid_datain(void *opaque)
+{
+    struct bt_hid_device_s *hid = opaque;
+
+    /* If suspended, wake-up and send a wake-up event first.  We might
+     * want to also inspect the input report and ignore event like
+     * mouse movements until a button event occurs.  */
+    if (hid->state == bt_state_suspend) {
+        hid->state = bt_state_ready;
+    }
+
+    if (bt_hid_in(hid) > 0)
+        /* TODO: when in boot-mode precede any Input reports with the ReportID
+         * byte, here and in GetReport/SetReport on the Control channel.  */
+        bt_hid_send_data(hid->interrupt, BT_DATA_INPUT,
+                        hid->datain.buffer, hid->datain.len);
+}
+
+static void bt_hid_interrupt_sdu(void *opaque, const uint8_t *data, int len)
+{
+    struct bt_hid_device_s *hid = opaque;
+
+    if (len > BT_HID_MTU || len < 1)
+        goto bad;
+    if ((data[0] & 3) != BT_DATA_OUTPUT)
+        goto bad;
+    if ((data[0] >> 4) == BT_DATA) {
+        if (hid->intr_state)
+            goto bad;
+
+        hid->data_type = BT_DATA_OUTPUT;
+        hid->intrdataout.len = 0;
+    } else if ((data[0] >> 4) == BT_DATC) {
+        if (!hid->intr_state)
+            goto bad;
+    } else
+        goto bad;
+
+    memcpy(hid->intrdataout.buffer + hid->intrdataout.len, data + 1, len - 1);
+    hid->intrdataout.len += len - 1;
+    hid->intr_state = (len == BT_HID_MTU);
+    if (!hid->intr_state) {
+        memcpy(hid->dataout.buffer, hid->intrdataout.buffer,
+                        hid->dataout.len = hid->intrdataout.len);
+        bt_hid_out(hid);
+    }
+
+    return;
+bad:
+    fprintf(stderr, "%s: bad transaction on Interrupt channel.\n",
+                    __FUNCTION__);
+}
+
+/* "Virtual cable" plug/unplug event.  */
+static void bt_hid_connected_update(struct bt_hid_device_s *hid)
+{
+    int prev = hid->connected;
+
+    hid->connected = hid->control && hid->interrupt;
+
+    /* Stop page-/inquiry-scanning when a host is connected.  */
+    hid->btdev.device.page_scan = !hid->connected;
+    hid->btdev.device.inquiry_scan = !hid->connected;
+
+    if (hid->connected && !prev) {
+        hid->usbdev->handle_reset(hid->usbdev);
+        hid->proto = BT_HID_PROTO_REPORT;
+    }
+
+    /* Should set HIDVirtualCable in SDP (possibly need to check that SDP
+     * isn't destroyed yet, in case we're being called from handle_destroy) */
+}
+
+static void bt_hid_close_control(void *opaque)
+{
+    struct bt_hid_device_s *hid = opaque;
+
+    hid->control = 0;
+    bt_hid_connected_update(hid);
+}
+
+static void bt_hid_close_interrupt(void *opaque)
+{
+    struct bt_hid_device_s *hid = opaque;
+
+    hid->interrupt = 0;
+    bt_hid_connected_update(hid);
+}
+
+static int bt_hid_new_control_ch(struct bt_l2cap_device_s *dev,
+                struct bt_l2cap_conn_params_s *params)
+{
+    struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
+
+    if (hid->control)
+        return 1;
+
+    hid->control = params;
+    hid->control->opaque = hid;
+    hid->control->close = bt_hid_close_control;
+    hid->control->sdu_in = bt_hid_control_sdu;
+
+    bt_hid_connected_update(hid);
+
+    return 0;
+}
+
+static int bt_hid_new_interrupt_ch(struct bt_l2cap_device_s *dev,
+                struct bt_l2cap_conn_params_s *params)
+{
+    struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
+
+    if (hid->interrupt)
+        return 1;
+
+    hid->interrupt = params;
+    hid->interrupt->opaque = hid;
+    hid->interrupt->close = bt_hid_close_interrupt;
+    hid->interrupt->sdu_in = bt_hid_interrupt_sdu;
+
+    bt_hid_connected_update(hid);
+
+    return 0;
+}
+
+static void bt_hid_destroy(struct bt_device_s *dev)
+{
+    struct bt_hid_device_s *hid = (struct bt_hid_device_s *) dev;
+
+    if (hid->connected)
+        bt_hid_send_control(hid, BT_HC_VIRTUAL_CABLE_UNPLUG);
+    bt_l2cap_device_done(&hid->btdev);
+
+    hid->usbdev->handle_destroy(hid->usbdev);
+
+    qemu_free(hid);
+}
+
+enum peripheral_minor_class {
+    class_other		= 0 << 4,
+    class_keyboard	= 1 << 4,
+    class_pointing	= 2 << 4,
+    class_combo		= 3 << 4,
+};
+
+static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
+                USBDevice *dev, enum peripheral_minor_class minor)
+{
+    struct bt_hid_device_s *s = qemu_mallocz(sizeof(*s));
+    uint32_t class =
+            /* Format type */
+            (0 << 0) |
+            /* Device class */
+            (minor << 2) |
+            (5 << 8) |  /* "Peripheral" */
+            /* Service classes */
+            (1 << 13) | /* Limited discoverable mode */
+            (1 << 19);  /* Capturing device (?) */
+
+    bt_l2cap_device_init(&s->btdev, net);
+    bt_l2cap_sdp_init(&s->btdev);
+    bt_l2cap_psm_register(&s->btdev, BT_PSM_HID_CTRL,
+                    BT_HID_MTU, bt_hid_new_control_ch);
+    bt_l2cap_psm_register(&s->btdev, BT_PSM_HID_INTR,
+                    BT_HID_MTU, bt_hid_new_interrupt_ch);
+
+    s->usbdev = dev;
+    s->btdev.device.lmp_name = s->usbdev->devname;
+    usb_hid_datain_cb(s->usbdev, s, bt_hid_datain);
+
+    s->btdev.device.handle_destroy = bt_hid_destroy;
+
+    s->btdev.device.class[0] = (class >>  0) & 0xff;
+    s->btdev.device.class[1] = (class >>  8) & 0xff;
+    s->btdev.device.class[2] = (class >> 16) & 0xff;
+
+    return &s->btdev.device;
+}
+
+struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
+{
+    return bt_hid_init(net, usb_keyboard_init(), class_keyboard);
+}
diff -Nur kvm-76/qemu/hw/bt-l2cap.c kvm-userspace/qemu/hw/bt-l2cap.c
--- kvm-76/qemu/hw/bt-l2cap.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/bt-l2cap.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,1364 @@
+/*
+ * QEMU Bluetooth L2CAP logic.
+ *
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA  02110-1301  USA
+ */
+
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "bt.h"
+
+#define L2CAP_CID_MAX	0x100	/* Between 0x40 and 0x10000 */
+
+struct l2cap_instance_s {
+    struct bt_link_s *link;
+    struct bt_l2cap_device_s *dev;
+    int role;
+
+    uint8_t frame_in[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4)));
+    int frame_in_len;
+
+    uint8_t frame_out[65535 + L2CAP_HDR_SIZE] __attribute__ ((aligned (4)));
+    int frame_out_len;
+
+    /* Signalling channel timers.  They exist per-request but we can make
+     * sure we have no more than one outstanding request at any time.  */
+    QEMUTimer *rtx;
+    QEMUTimer *ertx;
+
+    int last_id;
+    int next_id;
+
+    struct l2cap_chan_s {
+        struct bt_l2cap_conn_params_s params;
+
+        void (*frame_in)(struct l2cap_chan_s *chan, uint16_t cid,
+                        const l2cap_hdr *hdr, int len);
+        int mps;
+        int min_mtu;
+
+        struct l2cap_instance_s *l2cap;
+
+        /* Only allocated channels */
+        uint16_t remote_cid;
+#define L2CAP_CFG_INIT	2
+#define L2CAP_CFG_ACC	1
+        int config_req_id; /* TODO: handle outgoing requests generically */
+        int config;
+
+        /* Only connection-oriented channels.  Note: if we allow the tx and
+         * rx traffic to be in different modes at any time, we need two.  */
+        int mode;
+
+        /* Only flow-controlled, connection-oriented channels */
+        uint8_t sdu[65536]; /* TODO: dynamically allocate */
+        int len_cur, len_total;
+        int rexmit;
+        int monitor_timeout;
+        QEMUTimer *monitor_timer;
+        QEMUTimer *retransmission_timer;
+    } *cid[L2CAP_CID_MAX];
+    /* The channel state machine states map as following:
+     * CLOSED           -> !cid[N]
+     * WAIT_CONNECT     -> never occurs
+     * WAIT_CONNECT_RSP -> never occurs
+     * CONFIG           -> cid[N] && config < 3
+     *   WAIT_CONFIG         -> never occurs, cid[N] && config == 0 && !config_r
+     *   WAIT_SEND_CONFIG    -> never occurs, cid[N] && config == 1 && !config_r
+     *   WAIT_CONFIG_REQ_RSP -> cid[N] && config == 0 && config_req_id
+     *   WAIT_CONFIG_RSP     -> cid[N] && config == 1 && config_req_id
+     *   WAIT_CONFIG_REQ     -> cid[N] && config == 2
+     * OPEN             -> cid[N] && config == 3
+     * WAIT_DISCONNECT  -> never occurs
+     */
+
+    struct l2cap_chan_s signalling_ch;
+    struct l2cap_chan_s group_ch;
+};
+
+struct slave_l2cap_instance_s {
+    struct bt_link_s link;	/* Underlying logical link (ACL) */
+    struct l2cap_instance_s l2cap;
+};
+
+struct bt_l2cap_psm_s {
+    int psm;
+    int min_mtu;
+    int (*new_channel)(struct bt_l2cap_device_s *device,
+                    struct bt_l2cap_conn_params_s *params);
+    struct bt_l2cap_psm_s *next;
+};
+
+static const uint16_t l2cap_fcs16_table[256] = {
+    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
+    0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
+    0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
+    0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
+    0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
+    0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
+    0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
+    0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
+    0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
+    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
+    0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
+    0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
+    0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
+    0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
+    0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
+    0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
+    0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
+    0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
+    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
+    0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
+    0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
+    0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
+    0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
+    0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
+    0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
+    0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
+    0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
+    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
+    0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
+    0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
+    0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
+    0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040,
+};
+
+static uint16_t l2cap_fcs16(const uint8_t *message, int len)
+{
+    uint16_t fcs = 0x0000;
+
+    while (len --)
+#if 0
+    {
+        int i;
+
+        fcs ^= *message ++;
+        for (i = 8; i; -- i)
+            if (fcs & 1)
+                fcs = (fcs >> 1) ^ 0xa001;
+            else
+                fcs = (fcs >> 1);
+    }
+#else
+        fcs = (fcs >> 8) ^ l2cap_fcs16_table[(fcs ^ *message ++) & 0xff];
+#endif
+
+    return fcs;
+}
+
+/* L2CAP layer logic (protocol) */
+
+static void l2cap_retransmission_timer_update(struct l2cap_chan_s *ch)
+{
+#if 0
+    if (ch->mode != L2CAP_MODE_BASIC && ch->rexmit)
+        qemu_mod_timer(ch->retransmission_timer);
+    else
+        qemu_del_timer(ch->retransmission_timer);
+#endif
+}
+
+static void l2cap_monitor_timer_update(struct l2cap_chan_s *ch)
+{
+#if 0
+    if (ch->mode != L2CAP_MODE_BASIC && !ch->rexmit)
+        qemu_mod_timer(ch->monitor_timer);
+    else
+        qemu_del_timer(ch->monitor_timer);
+#endif
+}
+
+static void l2cap_command_reject(struct l2cap_instance_s *l2cap, int id,
+                uint16_t reason, const void *data, int plen)
+{
+    uint8_t *pkt;
+    l2cap_cmd_hdr *hdr;
+    l2cap_cmd_rej *params;
+    uint16_t len;
+
+    reason = cpu_to_le16(reason);
+    len = cpu_to_le16(L2CAP_CMD_REJ_SIZE + plen);
+
+    pkt = l2cap->signalling_ch.params.sdu_out(&l2cap->signalling_ch.params,
+                    L2CAP_CMD_HDR_SIZE + L2CAP_CMD_REJ_SIZE + plen);
+    hdr = (void *) (pkt + 0);
+    params = (void *) (pkt + L2CAP_CMD_HDR_SIZE);
+
+    hdr->code = L2CAP_COMMAND_REJ;
+    hdr->ident = id;
+    memcpy(&hdr->len, &len, sizeof(hdr->len));
+    memcpy(&params->reason, &reason, sizeof(reason));
+    if (plen)
+       memcpy(pkt + L2CAP_CMD_HDR_SIZE + L2CAP_CMD_REJ_SIZE, data, plen);
+
+    l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
+}
+
+static void l2cap_command_reject_cid(struct l2cap_instance_s *l2cap, int id,
+                uint16_t reason, uint16_t dcid, uint16_t scid)
+{
+    l2cap_cmd_rej_cid params = {
+        .dcid = dcid,
+        .scid = scid,
+    };
+
+    l2cap_command_reject(l2cap, id, reason, &params, L2CAP_CMD_REJ_CID_SIZE);
+}
+
+static void l2cap_connection_response(struct l2cap_instance_s *l2cap,
+                int dcid, int scid, int result, int status)
+{
+    uint8_t *pkt;
+    l2cap_cmd_hdr *hdr;
+    l2cap_conn_rsp *params;
+
+    pkt = l2cap->signalling_ch.params.sdu_out(&l2cap->signalling_ch.params,
+                    L2CAP_CMD_HDR_SIZE + L2CAP_CONN_RSP_SIZE);
+    hdr = (void *) (pkt + 0);
+    params = (void *) (pkt + L2CAP_CMD_HDR_SIZE);
+
+    hdr->code = L2CAP_CONN_RSP;
+    hdr->ident = l2cap->last_id;
+    hdr->len = cpu_to_le16(L2CAP_CONN_RSP_SIZE);
+
+    params->dcid = cpu_to_le16(dcid);
+    params->scid = cpu_to_le16(scid);
+    params->result = cpu_to_le16(result);
+    params->status = cpu_to_le16(status);
+
+    l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
+}
+
+static void l2cap_configuration_request(struct l2cap_instance_s *l2cap,
+                int dcid, int flag, const uint8_t *data, int len)
+{
+    uint8_t *pkt;
+    l2cap_cmd_hdr *hdr;
+    l2cap_conf_req *params;
+
+    pkt = l2cap->signalling_ch.params.sdu_out(&l2cap->signalling_ch.params,
+                    L2CAP_CMD_HDR_SIZE + L2CAP_CONF_REQ_SIZE(len));
+    hdr = (void *) (pkt + 0);
+    params = (void *) (pkt + L2CAP_CMD_HDR_SIZE);
+
+    /* TODO: unify the id sequencing */
+    l2cap->last_id = l2cap->next_id;
+    l2cap->next_id = l2cap->next_id == 255 ? 1 : l2cap->next_id + 1;
+
+    hdr->code = L2CAP_CONF_REQ;
+    hdr->ident = l2cap->last_id;
+    hdr->len = cpu_to_le16(L2CAP_CONF_REQ_SIZE(len));
+
+    params->dcid = cpu_to_le16(dcid);
+    params->flags = cpu_to_le16(flag);
+    if (len)
+        memcpy(params->data, data, len);
+
+    l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
+}
+
+static void l2cap_configuration_response(struct l2cap_instance_s *l2cap,
+                int scid, int flag, int result, const uint8_t *data, int len)
+{
+    uint8_t *pkt;
+    l2cap_cmd_hdr *hdr;
+    l2cap_conf_rsp *params;
+
+    pkt = l2cap->signalling_ch.params.sdu_out(&l2cap->signalling_ch.params,
+                    L2CAP_CMD_HDR_SIZE + L2CAP_CONF_RSP_SIZE(len));
+    hdr = (void *) (pkt + 0);
+    params = (void *) (pkt + L2CAP_CMD_HDR_SIZE);
+
+    hdr->code = L2CAP_CONF_RSP;
+    hdr->ident = l2cap->last_id;
+    hdr->len = cpu_to_le16(L2CAP_CONF_RSP_SIZE(len));
+
+    params->scid = cpu_to_le16(scid);
+    params->flags = cpu_to_le16(flag);
+    params->result = cpu_to_le16(result);
+    if (len)
+        memcpy(params->data, data, len);
+
+    l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
+}
+
+static void l2cap_disconnection_response(struct l2cap_instance_s *l2cap,
+                int dcid, int scid)
+{
+    uint8_t *pkt;
+    l2cap_cmd_hdr *hdr;
+    l2cap_disconn_rsp *params;
+
+    pkt = l2cap->signalling_ch.params.sdu_out(&l2cap->signalling_ch.params,
+                    L2CAP_CMD_HDR_SIZE + L2CAP_DISCONN_RSP_SIZE);
+    hdr = (void *) (pkt + 0);
+    params = (void *) (pkt + L2CAP_CMD_HDR_SIZE);
+
+    hdr->code = L2CAP_DISCONN_RSP;
+    hdr->ident = l2cap->last_id;
+    hdr->len = cpu_to_le16(L2CAP_DISCONN_RSP_SIZE);
+
+    params->dcid = cpu_to_le16(dcid);
+    params->scid = cpu_to_le16(scid);
+
+    l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
+}
+
+static void l2cap_echo_response(struct l2cap_instance_s *l2cap,
+                const uint8_t *data, int len)
+{
+    uint8_t *pkt;
+    l2cap_cmd_hdr *hdr;
+    uint8_t *params;
+
+    pkt = l2cap->signalling_ch.params.sdu_out(&l2cap->signalling_ch.params,
+                    L2CAP_CMD_HDR_SIZE + len);
+    hdr = (void *) (pkt + 0);
+    params = (void *) (pkt + L2CAP_CMD_HDR_SIZE);
+
+    hdr->code = L2CAP_ECHO_RSP;
+    hdr->ident = l2cap->last_id;
+    hdr->len = cpu_to_le16(len);
+
+    memcpy(params, data, len);
+
+    l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
+}
+
+static void l2cap_info_response(struct l2cap_instance_s *l2cap, int type,
+                int result, const uint8_t *data, int len)
+{
+    uint8_t *pkt;
+    l2cap_cmd_hdr *hdr;
+    l2cap_info_rsp *params;
+
+    pkt = l2cap->signalling_ch.params.sdu_out(&l2cap->signalling_ch.params,
+                    L2CAP_CMD_HDR_SIZE + L2CAP_INFO_RSP_SIZE + len);
+    hdr = (void *) (pkt + 0);
+    params = (void *) (pkt + L2CAP_CMD_HDR_SIZE);
+
+    hdr->code = L2CAP_INFO_RSP;
+    hdr->ident = l2cap->last_id;
+    hdr->len = cpu_to_le16(L2CAP_INFO_RSP_SIZE + len);
+
+    params->type = cpu_to_le16(type);
+    params->result = cpu_to_le16(result);
+    if (len)
+       memcpy(params->data, data, len);
+
+    l2cap->signalling_ch.params.sdu_submit(&l2cap->signalling_ch.params);
+}
+
+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len);
+static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms);
+#if 0
+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len);
+static void l2cap_iframe_submit(struct bt_l2cap_conn_params_s *parm);
+#endif
+static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
+                const l2cap_hdr *hdr, int len);
+static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
+                const l2cap_hdr *hdr, int len);
+
+static int l2cap_cid_new(struct l2cap_instance_s *l2cap)
+{
+    int i;
+
+    for (i = L2CAP_CID_ALLOC; i < L2CAP_CID_MAX; i ++)
+        if (!l2cap->cid[i])
+            return i;
+
+    return L2CAP_CID_INVALID;
+}
+
+static inline struct bt_l2cap_psm_s *l2cap_psm(
+                struct bt_l2cap_device_s *device, int psm)
+{
+    struct bt_l2cap_psm_s *ret = device->first_psm;
+
+    while (ret && ret->psm != psm)
+        ret = ret->next;
+
+    return ret;
+}
+
+static struct l2cap_chan_s *l2cap_channel_open(struct l2cap_instance_s *l2cap,
+                int psm, int source_cid)
+{
+    struct l2cap_chan_s *ch = 0;
+    struct bt_l2cap_psm_s *psm_info;
+    int result, status;
+    int cid = l2cap_cid_new(l2cap);
+
+    if (cid) {
+        /* See what the channel is to be used for.. */
+        psm_info = l2cap_psm(l2cap->dev, psm);
+
+        if (psm_info) {
+            /* Device supports this use-case.  */
+            ch = qemu_mallocz(sizeof(*ch));
+            ch->params.sdu_out = l2cap_bframe_out;
+            ch->params.sdu_submit = l2cap_bframe_submit;
+            ch->frame_in = l2cap_bframe_in;
+            ch->mps = 65536;
+            ch->min_mtu = MAX(48, psm_info->min_mtu);
+            ch->params.remote_mtu = MAX(672, ch->min_mtu);
+            ch->remote_cid = source_cid;
+            ch->mode = L2CAP_MODE_BASIC;
+            ch->l2cap = l2cap;
+
+            /* Does it feel like opening yet another channel though?  */
+            if (!psm_info->new_channel(l2cap->dev, &ch->params)) {
+                l2cap->cid[cid] = ch;
+
+                result = L2CAP_CR_SUCCESS;
+                status = L2CAP_CS_NO_INFO;
+            } else {
+                qemu_free(ch);
+
+                result = L2CAP_CR_NO_MEM;
+                status = L2CAP_CS_NO_INFO;
+            }
+        } else {
+            result = L2CAP_CR_BAD_PSM;
+            status = L2CAP_CS_NO_INFO;
+        }
+    } else {
+        result = L2CAP_CR_NO_MEM;
+        status = L2CAP_CS_NO_INFO;
+    }
+
+    l2cap_connection_response(l2cap, cid, source_cid, result, status);
+
+    return ch;
+}
+
+static void l2cap_channel_close(struct l2cap_instance_s *l2cap,
+                int cid, int source_cid)
+{
+    struct l2cap_chan_s *ch = 0;
+
+    /* According to Volume 3, section 6.1.1, pg 1048 of BT Core V2.0, a
+     * connection in CLOSED state still responds with a L2CAP_DisconnectRsp
+     * message on an L2CAP_DisconnectReq event.  */
+    if (unlikely(cid < L2CAP_CID_ALLOC)) {
+        l2cap_command_reject_cid(l2cap, l2cap->last_id, L2CAP_REJ_CID_INVAL,
+                        cid, source_cid);
+        return;
+    }
+    if (likely(cid >= L2CAP_CID_ALLOC && cid < L2CAP_CID_MAX))
+        ch = l2cap->cid[cid];
+
+    if (likely(ch)) {
+        if (ch->remote_cid != source_cid) {
+            fprintf(stderr, "%s: Ignoring a Disconnection Request with the "
+                            "invalid SCID %04x.\n", __FUNCTION__, source_cid);
+            return;
+        }
+
+        l2cap->cid[cid] = 0;
+
+        ch->params.close(ch->params.opaque);
+        qemu_free(ch);
+    }
+
+    l2cap_disconnection_response(l2cap, cid, source_cid);
+}
+
+static void l2cap_channel_config_null(struct l2cap_instance_s *l2cap,
+                struct l2cap_chan_s *ch)
+{
+    l2cap_configuration_request(l2cap, ch->remote_cid, 0, 0, 0);
+    ch->config_req_id = l2cap->last_id;
+    ch->config &= ~L2CAP_CFG_INIT;
+}
+
+static void l2cap_channel_config_req_event(struct l2cap_instance_s *l2cap,
+                struct l2cap_chan_s *ch)
+{
+    /* Use all default channel options and terminate negotiation.  */
+    l2cap_channel_config_null(l2cap, ch);
+}
+
+static int l2cap_channel_config(struct l2cap_instance_s *l2cap,
+                struct l2cap_chan_s *ch, int flag,
+                const uint8_t *data, int len)
+{
+    l2cap_conf_opt *opt;
+    l2cap_conf_opt_qos *qos;
+    uint32_t val;
+    uint8_t rsp[len];
+    int result = L2CAP_CONF_SUCCESS;
+
+    data = memcpy(rsp, data, len);
+    while (len) {
+        opt = (void *) data;
+
+        if (len < L2CAP_CONF_OPT_SIZE ||
+                        len < L2CAP_CONF_OPT_SIZE + opt->len) {
+            result = L2CAP_CONF_REJECT;
+            break;
+        }
+        data += L2CAP_CONF_OPT_SIZE + opt->len;
+        len -= L2CAP_CONF_OPT_SIZE + opt->len;
+
+        switch (opt->type & 0x7f) {
+        case L2CAP_CONF_MTU:
+            if (opt->len != 2) {
+                result = L2CAP_CONF_REJECT;
+                break;
+            }
+
+            /* MTU */
+            val = le16_to_cpup((void *) opt->val);
+            if (val < ch->min_mtu) {
+                cpu_to_le16w((void *) opt->val, ch->min_mtu);
+                result = L2CAP_CONF_UNACCEPT;
+                break;
+            }
+
+            ch->params.remote_mtu = val;
+            break;
+
+        case L2CAP_CONF_FLUSH_TO:
+            if (opt->len != 2) {
+                result = L2CAP_CONF_REJECT;
+                break;
+            }
+
+            /* Flush Timeout */
+            val = le16_to_cpup((void *) opt->val);
+            if (val < 0x0001) {
+                opt->val[0] = 0xff;
+                opt->val[1] = 0xff;
+                result = L2CAP_CONF_UNACCEPT;
+                break;
+            }
+            break;
+
+        case L2CAP_CONF_QOS:
+            if (opt->len != L2CAP_CONF_OPT_QOS_SIZE) {
+                result = L2CAP_CONF_REJECT;
+                break;
+            }
+            qos = (void *) opt->val;
+
+            /* Flags */
+            val = qos->flags;
+            if (val) {
+                qos->flags = 0;
+                result = L2CAP_CONF_UNACCEPT;
+            }
+
+            /* Service type */
+            val = qos->service_type;
+            if (val != L2CAP_CONF_QOS_BEST_EFFORT &&
+                            val != L2CAP_CONF_QOS_NO_TRAFFIC) {
+                qos->service_type = L2CAP_CONF_QOS_BEST_EFFORT;
+                result = L2CAP_CONF_UNACCEPT;
+            }
+
+            if (val != L2CAP_CONF_QOS_NO_TRAFFIC) {
+                /* XXX: These values should possibly be calculated
+                 * based on LM / baseband properties also.  */
+
+                /* Token rate */
+                val = le32_to_cpu(qos->token_rate);
+                if (val == L2CAP_CONF_QOS_WILDCARD)
+                    qos->token_rate = cpu_to_le32(0x100000);
+
+                /* Token bucket size */
+                val = le32_to_cpu(qos->token_bucket_size);
+                if (val == L2CAP_CONF_QOS_WILDCARD)
+                    qos->token_bucket_size = cpu_to_le32(65500);
+
+                /* Any Peak bandwidth value is correct to return as-is */
+                /* Any Access latency value is correct to return as-is */
+                /* Any Delay variation value is correct to return as-is */
+            }
+            break;
+
+        case L2CAP_CONF_RFC:
+            if (opt->len != 9) {
+                result = L2CAP_CONF_REJECT;
+                break;
+            }
+
+            /* Mode */
+            val = opt->val[0];
+            switch (val) {
+            case L2CAP_MODE_BASIC:
+                ch->mode = val;
+                ch->frame_in = l2cap_bframe_in;
+
+                /* All other parameters shall be ignored */
+                break;
+
+            case L2CAP_MODE_RETRANS:
+            case L2CAP_MODE_FLOWCTL:
+                ch->mode = val;
+                ch->frame_in = l2cap_iframe_in;
+                /* Note: most of these parameters refer to incoming traffic
+                 * so we don't need to save them as long as we can accept
+                 * incoming PDUs at any values of the parameters.  */
+
+                /* TxWindow size */
+                val = opt->val[1];
+                if (val < 1 || val > 32) {
+                    opt->val[1] = 32;
+                    result = L2CAP_CONF_UNACCEPT;
+                    break;
+                }
+
+                /* MaxTransmit */
+                val = opt->val[2];
+                if (val < 1) {
+                    opt->val[2] = 1;
+                    result = L2CAP_CONF_UNACCEPT;
+                    break;
+                }
+
+                /* Remote Retransmission time-out shouldn't affect local
+                 * operation (?) */
+
+                /* The Monitor time-out drives the local Monitor timer (?),
+                 * so save the value.  */
+                val = (opt->val[6] << 8) | opt->val[5];
+                if (val < 30) {
+                    opt->val[5] = 100 & 0xff;
+                    opt->val[6] = 100 >> 8;
+                    result = L2CAP_CONF_UNACCEPT;
+                    break;
+                }
+                ch->monitor_timeout = val;
+                l2cap_monitor_timer_update(ch);
+
+                /* MPS */
+                val = (opt->val[8] << 8) | opt->val[7];
+                if (val < ch->min_mtu) {
+                    opt->val[7] = ch->min_mtu & 0xff;
+                    opt->val[8] = ch->min_mtu >> 8;
+                    result = L2CAP_CONF_UNACCEPT;
+                    break;
+                }
+                ch->mps = val;
+                break;
+
+            default:
+                result = L2CAP_CONF_UNACCEPT;
+                break;
+            }
+            break;
+
+        default:
+            if (!(opt->type >> 7))
+                result = L2CAP_CONF_UNKNOWN;
+            break;
+        }
+
+        if (result != L2CAP_CONF_SUCCESS)
+            break;	/* XXX: should continue? */
+    }
+
+    l2cap_configuration_response(l2cap, ch->remote_cid,
+                    flag, result, rsp, len);
+
+    return result == L2CAP_CONF_SUCCESS && !flag;
+}
+
+static void l2cap_channel_config_req_msg(struct l2cap_instance_s *l2cap,
+                int flag, int cid, const uint8_t *data, int len)
+{
+    struct l2cap_chan_s *ch;
+
+    if (unlikely(cid >= L2CAP_CID_MAX || !l2cap->cid[cid])) {
+        l2cap_command_reject_cid(l2cap, l2cap->last_id, L2CAP_REJ_CID_INVAL,
+                        cid, 0x0000);
+        return;
+    }
+    ch = l2cap->cid[cid];
+
+    /* From OPEN go to WAIT_CONFIG_REQ and from WAIT_CONFIG_REQ_RSP to
+     * WAIT_CONFIG_REQ_RSP.  This is assuming the transition chart for OPEN
+     * on pg 1053, section 6.1.5, volume 3 of BT Core V2.0 has a mistake
+     * and on options-acceptable we go back to OPEN and otherwise to
+     * WAIT_CONFIG_REQ and not the other way.  */
+    ch->config &= ~L2CAP_CFG_ACC;
+
+    if (l2cap_channel_config(l2cap, ch, flag, data, len))
+        /* Go to OPEN or WAIT_CONFIG_RSP */
+        ch->config |= L2CAP_CFG_ACC;
+
+    /* TODO: if the incoming traffic flow control or retransmission mode
+     * changed then we probably need to also generate the
+     * ConfigureChannel_Req event and set the outgoing traffic to the same
+     * mode.  */
+    if (!(ch->config & L2CAP_CFG_INIT) && (ch->config & L2CAP_CFG_ACC) &&
+                    !ch->config_req_id)
+        l2cap_channel_config_req_event(l2cap, ch);
+}
+
+static int l2cap_channel_config_rsp_msg(struct l2cap_instance_s *l2cap,
+                int result, int flag, int cid, const uint8_t *data, int len)
+{
+    struct l2cap_chan_s *ch;
+
+    if (unlikely(cid >= L2CAP_CID_MAX || !l2cap->cid[cid])) {
+        l2cap_command_reject_cid(l2cap, l2cap->last_id, L2CAP_REJ_CID_INVAL,
+                        cid, 0x0000);
+        return 0;
+    }
+    ch = l2cap->cid[cid];
+
+    if (ch->config_req_id != l2cap->last_id)
+        return 1;
+    ch->config_req_id = 0;
+
+    if (result == L2CAP_CONF_SUCCESS) {
+        if (!flag)
+            ch->config |= L2CAP_CFG_INIT;
+        else
+            l2cap_channel_config_null(l2cap, ch);
+    } else
+        /* Retry until we succeed */
+        l2cap_channel_config_req_event(l2cap, ch);
+
+    return 0;
+}
+
+static void l2cap_channel_open_req_msg(struct l2cap_instance_s *l2cap,
+                int psm, int source_cid)
+{
+    struct l2cap_chan_s *ch = l2cap_channel_open(l2cap, psm, source_cid);
+
+    if (!ch)
+        return;
+
+    /* Optional */
+    if (!(ch->config & L2CAP_CFG_INIT) && !ch->config_req_id)
+        l2cap_channel_config_req_event(l2cap, ch);
+}
+
+static void l2cap_info(struct l2cap_instance_s *l2cap, int type)
+{
+    uint8_t data[4];
+    int len = 0;
+    int result = L2CAP_IR_SUCCESS;
+
+    switch (type) {
+    case L2CAP_IT_CL_MTU:
+        data[len ++] = l2cap->group_ch.mps & 0xff;
+        data[len ++] = l2cap->group_ch.mps >> 8;
+        break;
+
+    case L2CAP_IT_FEAT_MASK:
+        /* (Prematurely) report Flow control and Retransmission modes.  */
+        data[len ++] = 0x03;
+        data[len ++] = 0x00;
+        data[len ++] = 0x00;
+        data[len ++] = 0x00;
+        break;
+
+    default:
+        result = L2CAP_IR_NOTSUPP;
+    }
+
+    l2cap_info_response(l2cap, type, result, data, len);
+}
+
+static void l2cap_command(struct l2cap_instance_s *l2cap, int code, int id,
+                const uint8_t *params, int len)
+{
+    int err;
+
+#if 0
+    /* TODO: do the IDs really have to be in sequence?  */
+    if (!id || (id != l2cap->last_id && id != l2cap->next_id)) {
+        fprintf(stderr, "%s: out of sequence command packet ignored.\n",
+                        __FUNCTION__);
+        return;
+    }
+#else
+    l2cap->next_id = id;
+#endif
+    if (id == l2cap->next_id) {
+        l2cap->last_id = l2cap->next_id;
+        l2cap->next_id = l2cap->next_id == 255 ? 1 : l2cap->next_id + 1;
+    } else {
+        /* TODO: Need to re-send the same response, without re-executing
+         * the corresponding command!  */
+    }
+
+    switch (code) {
+    case L2CAP_COMMAND_REJ:
+        if (unlikely(len != 2 && len != 4 && len != 6)) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        /* We never issue commands other than Command Reject currently.  */
+        fprintf(stderr, "%s: stray Command Reject (%02x, %04x) "
+                        "packet, ignoring.\n", __FUNCTION__, id,
+                        le16_to_cpu(((l2cap_cmd_rej *) params)->reason));
+        break;
+
+    case L2CAP_CONN_REQ:
+        if (unlikely(len != L2CAP_CONN_REQ_SIZE)) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        l2cap_channel_open_req_msg(l2cap,
+                        le16_to_cpu(((l2cap_conn_req *) params)->psm),
+                        le16_to_cpu(((l2cap_conn_req *) params)->scid));
+        break;
+
+    case L2CAP_CONN_RSP:
+        if (unlikely(len != L2CAP_CONN_RSP_SIZE)) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        /* We never issue Connection Requests currently. TODO  */
+        fprintf(stderr, "%s: unexpected Connection Response (%02x) "
+                        "packet, ignoring.\n", __FUNCTION__, id);
+        break;
+
+    case L2CAP_CONF_REQ:
+        if (unlikely(len < L2CAP_CONF_REQ_SIZE(0))) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        l2cap_channel_config_req_msg(l2cap,
+                        le16_to_cpu(((l2cap_conf_req *) params)->flags) & 1,
+                        le16_to_cpu(((l2cap_conf_req *) params)->dcid),
+                        ((l2cap_conf_req *) params)->data,
+                        len - L2CAP_CONF_REQ_SIZE(0));
+        break;
+
+    case L2CAP_CONF_RSP:
+        if (unlikely(len < L2CAP_CONF_RSP_SIZE(0))) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        if (l2cap_channel_config_rsp_msg(l2cap,
+                        le16_to_cpu(((l2cap_conf_rsp *) params)->result),
+                        le16_to_cpu(((l2cap_conf_rsp *) params)->flags) & 1,
+                        le16_to_cpu(((l2cap_conf_rsp *) params)->scid),
+                        ((l2cap_conf_rsp *) params)->data,
+                        len - L2CAP_CONF_RSP_SIZE(0)))
+            fprintf(stderr, "%s: unexpected Configure Response (%02x) "
+                            "packet, ignoring.\n", __FUNCTION__, id);
+        break;
+
+    case L2CAP_DISCONN_REQ:
+        if (unlikely(len != L2CAP_DISCONN_REQ_SIZE)) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        l2cap_channel_close(l2cap,
+                        le16_to_cpu(((l2cap_disconn_req *) params)->dcid),
+                        le16_to_cpu(((l2cap_disconn_req *) params)->scid));
+        break;
+
+    case L2CAP_DISCONN_RSP:
+        if (unlikely(len != L2CAP_DISCONN_RSP_SIZE)) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        /* We never issue Disconnection Requests currently. TODO  */
+        fprintf(stderr, "%s: unexpected Disconnection Response (%02x) "
+                        "packet, ignoring.\n", __FUNCTION__, id);
+        break;
+
+    case L2CAP_ECHO_REQ:
+        l2cap_echo_response(l2cap, params, len);
+        break;
+
+    case L2CAP_ECHO_RSP:
+        /* We never issue Echo Requests currently. TODO  */
+        fprintf(stderr, "%s: unexpected Echo Response (%02x) "
+                        "packet, ignoring.\n", __FUNCTION__, id);
+        break;
+
+    case L2CAP_INFO_REQ:
+        if (unlikely(len != L2CAP_INFO_REQ_SIZE)) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        l2cap_info(l2cap, le16_to_cpu(((l2cap_info_req *) params)->type));
+        break;
+
+    case L2CAP_INFO_RSP:
+        if (unlikely(len != L2CAP_INFO_RSP_SIZE)) {
+            err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+            goto reject;
+        }
+
+        /* We never issue Information Requests currently. TODO  */
+        fprintf(stderr, "%s: unexpected Information Response (%02x) "
+                        "packet, ignoring.\n", __FUNCTION__, id);
+        break;
+
+    default:
+        err = L2CAP_REJ_CMD_NOT_UNDERSTOOD;
+    reject:
+        l2cap_command_reject(l2cap, id, err, 0, 0);
+        break;
+    }
+}
+
+static void l2cap_rexmit_enable(struct l2cap_chan_s *ch, int enable)
+{
+    ch->rexmit = enable;
+
+    l2cap_retransmission_timer_update(ch);
+    l2cap_monitor_timer_update(ch);
+}
+
+/* Command frame SDU */
+static void l2cap_cframe_in(void *opaque, const uint8_t *data, int len)
+{
+    struct l2cap_instance_s *l2cap = opaque;
+    const l2cap_cmd_hdr *hdr;
+    int clen;
+
+    while (len) {
+        hdr = (void *) data;
+        if (len < L2CAP_CMD_HDR_SIZE)
+            /* TODO: signal an error */
+            return;
+        len -= L2CAP_CMD_HDR_SIZE;
+        data += L2CAP_CMD_HDR_SIZE;
+
+        clen = le16_to_cpu(hdr->len);
+        if (len < clen) {
+            l2cap_command_reject(l2cap, hdr->ident,
+                            L2CAP_REJ_CMD_NOT_UNDERSTOOD, 0, 0);
+            break;
+        }
+
+        l2cap_command(l2cap, hdr->code, hdr->ident, data, clen);
+        len -= clen;
+        data += clen;
+    }
+}
+
+/* Group frame SDU */
+static void l2cap_gframe_in(void *opaque, const uint8_t *data, int len)
+{
+}
+
+/* Supervisory frame */
+static void l2cap_sframe_in(struct l2cap_chan_s *ch, uint16_t ctrl)
+{
+}
+
+/* Basic L2CAP mode Information frame */
+static void l2cap_bframe_in(struct l2cap_chan_s *ch, uint16_t cid,
+                const l2cap_hdr *hdr, int len)
+{
+    /* We have a full SDU, no further processing */
+    ch->params.sdu_in(ch->params.opaque, hdr->data, len);
+}
+
+/* Flow Control and Retransmission mode frame */
+static void l2cap_iframe_in(struct l2cap_chan_s *ch, uint16_t cid,
+                const l2cap_hdr *hdr, int len)
+{
+    uint16_t fcs = le16_to_cpup((void *) (hdr->data + len - 2));
+
+    if (len < 4)
+        goto len_error;
+    if (l2cap_fcs16((const uint8_t *) hdr, L2CAP_HDR_SIZE + len - 2) != fcs)
+        goto fcs_error;
+
+    if ((hdr->data[0] >> 7) == ch->rexmit)
+        l2cap_rexmit_enable(ch, !(hdr->data[0] >> 7));
+
+    if (hdr->data[0] & 1) {
+        if (len != 4)
+            /* TODO: Signal an error? */;
+            return;
+
+        return l2cap_sframe_in(ch, le16_to_cpup((void *) hdr->data));
+    }
+
+    switch (hdr->data[1] >> 6) {	/* SAR */
+    case L2CAP_SAR_NO_SEG:
+        if (ch->len_total)
+            goto seg_error;
+        if (len - 4 > ch->mps)
+            goto len_error;
+
+        return ch->params.sdu_in(ch->params.opaque, hdr->data + 2, len - 4);
+
+    case L2CAP_SAR_START:
+        if (ch->len_total || len < 6)
+            goto seg_error;
+        if (len - 6 > ch->mps)
+            goto len_error;
+
+        ch->len_total = le16_to_cpup((void *) (hdr->data + 2));
+        if (len >= 6 + ch->len_total)
+            goto seg_error;
+
+        ch->len_cur = len - 6;
+        memcpy(ch->sdu, hdr->data + 4, ch->len_cur);
+        break;
+
+    case L2CAP_SAR_END:
+        if (!ch->len_total || ch->len_cur + len - 4 < ch->len_total)
+            goto seg_error;
+        if (len - 4 > ch->mps)
+            goto len_error;
+
+        memcpy(ch->sdu + ch->len_cur, hdr->data + 2, len - 4);
+        return ch->params.sdu_in(ch->params.opaque, ch->sdu, ch->len_total);
+
+    case L2CAP_SAR_CONT:
+        if (!ch->len_total || ch->len_cur + len - 4 >= ch->len_total)
+            goto seg_error;
+        if (len - 4 > ch->mps)
+            goto len_error;
+
+        memcpy(ch->sdu + ch->len_cur, hdr->data + 2, len - 4);
+        ch->len_cur += len - 4;
+        break;
+
+    seg_error:
+    len_error:	/* TODO */
+    fcs_error:	/* TODO */
+        ch->len_cur = 0;
+        ch->len_total = 0;
+        break;
+    }
+}
+
+static void l2cap_frame_in(struct l2cap_instance_s *l2cap,
+                const l2cap_hdr *frame)
+{
+    uint16_t cid = le16_to_cpu(frame->cid);
+    uint16_t len = le16_to_cpu(frame->len);
+
+    if (unlikely(cid >= L2CAP_CID_MAX || !l2cap->cid[cid])) {
+        fprintf(stderr, "%s: frame addressed to a non-existent L2CAP "
+                        "channel %04x received.\n", __FUNCTION__, cid);
+        return;
+    }
+
+    l2cap->cid[cid]->frame_in(l2cap->cid[cid], cid, frame, len);
+}
+
+/* "Recombination" */
+static void l2cap_pdu_in(struct l2cap_instance_s *l2cap,
+                const uint8_t *data, int len)
+{
+    const l2cap_hdr *hdr = (void *) l2cap->frame_in;
+
+    if (unlikely(len + l2cap->frame_in_len > sizeof(l2cap->frame_in))) {
+        if (l2cap->frame_in_len < sizeof(l2cap->frame_in)) {
+            memcpy(l2cap->frame_in + l2cap->frame_in_len, data,
+                            sizeof(l2cap->frame_in) - l2cap->frame_in_len);
+            l2cap->frame_in_len = sizeof(l2cap->frame_in);
+            /* TODO: truncate */
+            l2cap_frame_in(l2cap, hdr);
+        }
+
+        return;
+    }
+
+    memcpy(l2cap->frame_in + l2cap->frame_in_len, data, len);
+    l2cap->frame_in_len += len;
+
+    if (len >= L2CAP_HDR_SIZE)
+        if (len >= L2CAP_HDR_SIZE + le16_to_cpu(hdr->len))
+            l2cap_frame_in(l2cap, hdr);
+            /* There is never a start of a new PDU in the same ACL packet, so
+             * no need to memmove the remaining payload and loop.  */
+}
+
+static inline uint8_t *l2cap_pdu_out(struct l2cap_instance_s *l2cap,
+                uint16_t cid, uint16_t len)
+{
+    l2cap_hdr *hdr = (void *) l2cap->frame_out;
+
+    l2cap->frame_out_len = len + L2CAP_HDR_SIZE;
+
+    hdr->cid = cpu_to_le16(cid);
+    hdr->len = cpu_to_le16(len);
+
+    return l2cap->frame_out + L2CAP_HDR_SIZE;
+}
+
+static inline void l2cap_pdu_submit(struct l2cap_instance_s *l2cap)
+{
+    /* TODO: Fragmentation */
+    (l2cap->role ?
+     l2cap->link->slave->lmp_acl_data : l2cap->link->host->lmp_acl_resp)
+            (l2cap->link, l2cap->frame_out, 1, l2cap->frame_out_len);
+}
+
+static uint8_t *l2cap_bframe_out(struct bt_l2cap_conn_params_s *parm, int len)
+{
+    struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm;
+
+    if (len > chan->params.remote_mtu) {
+        fprintf(stderr, "%s: B-Frame for CID %04x longer than %i octets.\n",
+                        __FUNCTION__,
+                        chan->remote_cid, chan->params.remote_mtu);
+        exit(-1);
+    }
+
+    return l2cap_pdu_out(chan->l2cap, chan->remote_cid, len);
+}
+
+static void l2cap_bframe_submit(struct bt_l2cap_conn_params_s *parms)
+{
+    struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parms;
+
+    return l2cap_pdu_submit(chan->l2cap);
+}
+
+#if 0
+/* Stub: Only used if an emulated device requests outgoing flow control */
+static uint8_t *l2cap_iframe_out(struct bt_l2cap_conn_params_s *parm, int len)
+{
+    struct l2cap_chan_s *chan = (struct l2cap_chan_s *) parm;
+
+    if (len > chan->params.remote_mtu) {
+        /* TODO: slice into segments and queue each segment as a separate
+         * I-Frame in a FIFO of I-Frames, local to the CID.  */
+    } else {
+        /* TODO: add to the FIFO of I-Frames, local to the CID.  */
+        /* Possibly we need to return a pointer to a contiguous buffer
+         * for now and then memcpy from it into FIFOs in l2cap_iframe_submit
+         * while segmenting at the same time.  */
+    }
+    return 0;
+}
+
+static void l2cap_iframe_submit(struct bt_l2cap_conn_params_s *parm)
+{
+    /* TODO: If flow control indicates clear to send, start submitting the
+     * invidual I-Frames from the FIFO, but don't remove them from there.
+     * Kick the appropriate timer until we get an S-Frame, and only then
+     * remove from FIFO or resubmit and re-kick the timer if the timer
+     * expired.  */
+}
+#endif
+
+static void l2cap_init(struct l2cap_instance_s *l2cap,
+                struct bt_link_s *link, int role)
+{
+    l2cap->link = link;
+    l2cap->role = role;
+    l2cap->dev = (struct bt_l2cap_device_s *)
+            (role ? link->host : link->slave);
+
+    l2cap->next_id = 1;
+
+    /* Establish the signalling channel */
+    l2cap->signalling_ch.params.sdu_in = l2cap_cframe_in;
+    l2cap->signalling_ch.params.sdu_out = l2cap_bframe_out;
+    l2cap->signalling_ch.params.sdu_submit = l2cap_bframe_submit;
+    l2cap->signalling_ch.params.opaque = l2cap;
+    l2cap->signalling_ch.params.remote_mtu = 48;
+    l2cap->signalling_ch.remote_cid = L2CAP_CID_SIGNALLING;
+    l2cap->signalling_ch.frame_in = l2cap_bframe_in;
+    l2cap->signalling_ch.mps = 65536;
+    l2cap->signalling_ch.min_mtu = 48;
+    l2cap->signalling_ch.mode = L2CAP_MODE_BASIC;
+    l2cap->signalling_ch.l2cap = l2cap;
+    l2cap->cid[L2CAP_CID_SIGNALLING] = &l2cap->signalling_ch;
+
+    /* Establish the connection-less data channel */
+    l2cap->group_ch.params.sdu_in = l2cap_gframe_in;
+    l2cap->group_ch.params.opaque = l2cap;
+    l2cap->group_ch.frame_in = l2cap_bframe_in;
+    l2cap->group_ch.mps = 65533;
+    l2cap->group_ch.l2cap = l2cap;
+    l2cap->group_ch.remote_cid = L2CAP_CID_INVALID;
+    l2cap->cid[L2CAP_CID_GROUP] = &l2cap->group_ch;
+}
+
+static void l2cap_teardown(struct l2cap_instance_s *l2cap, int send_disconnect)
+{
+    int cid;
+
+    /* Don't send DISCONNECT if we are currently handling a DISCONNECT
+     * sent from the other side.  */
+    if (send_disconnect) {
+        if (l2cap->role)
+            l2cap->dev->device.lmp_disconnect_slave(l2cap->link);
+            /* l2cap->link is invalid from now on.  */
+        else
+            l2cap->dev->device.lmp_disconnect_master(l2cap->link);
+    }
+
+    for (cid = L2CAP_CID_ALLOC; cid < L2CAP_CID_MAX; cid ++)
+        if (l2cap->cid[cid]) {
+            l2cap->cid[cid]->params.close(l2cap->cid[cid]->params.opaque);
+            free(l2cap->cid[cid]);
+        }
+
+    if (l2cap->role)
+        qemu_free(l2cap);
+    else
+        qemu_free(l2cap->link);
+}
+
+/* L2CAP glue to lower layers in bluetooth stack (LMP) */
+
+static void l2cap_lmp_connection_request(struct bt_link_s *link)
+{
+    struct bt_l2cap_device_s *dev = (struct bt_l2cap_device_s *) link->slave;
+    struct slave_l2cap_instance_s *l2cap;
+
+    /* Always accept - we only get called if (dev->device->page_scan).  */
+
+    l2cap = qemu_mallocz(sizeof(struct slave_l2cap_instance_s));
+    l2cap->link.slave = &dev->device;
+    l2cap->link.host = link->host;
+    l2cap_init(&l2cap->l2cap, &l2cap->link, 0);
+
+    /* Always at the end */
+    link->host->reject_reason = 0;
+    link->host->lmp_connection_complete(&l2cap->link);
+}
+
+/* Stub */
+static void l2cap_lmp_connection_complete(struct bt_link_s *link)
+{
+    struct bt_l2cap_device_s *dev = (struct bt_l2cap_device_s *) link->host;
+    struct l2cap_instance_s *l2cap;
+
+    if (dev->device.reject_reason) {
+        /* Signal to upper layer */
+        return;
+    }
+
+    l2cap = qemu_mallocz(sizeof(struct l2cap_instance_s));
+    l2cap_init(l2cap, link, 1);
+
+    link->acl_mode = acl_active;
+
+    /* Signal to upper layer */
+}
+
+/* Stub */
+static void l2cap_lmp_disconnect_host(struct bt_link_s *link)
+{
+    struct bt_l2cap_device_s *dev = (struct bt_l2cap_device_s *) link->host;
+    struct l2cap_instance_s *l2cap =
+            /* TODO: Retrieve from upper layer */ (void *) dev;
+
+    /* Signal to upper layer */
+
+    l2cap_teardown(l2cap, 0);
+}
+
+static void l2cap_lmp_disconnect_slave(struct bt_link_s *link)
+{
+    struct slave_l2cap_instance_s *l2cap =
+            (struct slave_l2cap_instance_s *) link;
+
+    l2cap_teardown(&l2cap->l2cap, 0);
+}
+
+static void l2cap_lmp_acl_data_slave(struct bt_link_s *link,
+                const uint8_t *data, int start, int len)
+{
+    struct slave_l2cap_instance_s *l2cap =
+            (struct slave_l2cap_instance_s *) link;
+
+    if (start)
+        l2cap->l2cap.frame_in_len = 0;
+
+    l2cap_pdu_in(&l2cap->l2cap, data, len);
+}
+
+/* Stub */
+static void l2cap_lmp_acl_data_host(struct bt_link_s *link,
+                const uint8_t *data, int start, int len)
+{
+    struct bt_l2cap_device_s *dev = (struct bt_l2cap_device_s *) link->host;
+    struct l2cap_instance_s *l2cap =
+            /* TODO: Retrieve from upper layer */ (void *) dev;
+
+    if (start)
+        l2cap->frame_in_len = 0;
+
+    l2cap_pdu_in(l2cap, data, len);
+}
+
+static void l2cap_dummy_destroy(struct bt_device_s *dev)
+{
+    struct bt_l2cap_device_s *l2cap_dev = (struct bt_l2cap_device_s *) dev;
+
+    bt_l2cap_device_done(l2cap_dev);
+}
+
+void bt_l2cap_device_init(struct bt_l2cap_device_s *dev,
+                struct bt_scatternet_s *net)
+{
+    bt_device_init(&dev->device, net);
+
+    dev->device.lmp_connection_request = l2cap_lmp_connection_request;
+    dev->device.lmp_connection_complete = l2cap_lmp_connection_complete;
+    dev->device.lmp_disconnect_master = l2cap_lmp_disconnect_host;
+    dev->device.lmp_disconnect_slave = l2cap_lmp_disconnect_slave;
+    dev->device.lmp_acl_data = l2cap_lmp_acl_data_slave;
+    dev->device.lmp_acl_resp = l2cap_lmp_acl_data_host;
+
+    dev->device.handle_destroy = l2cap_dummy_destroy;
+}
+
+void bt_l2cap_device_done(struct bt_l2cap_device_s *dev)
+{
+    bt_device_done(&dev->device);
+
+    /* Should keep a list of all instances and go through it and
+     * invoke l2cap_teardown() for each.  */
+}
+
+void bt_l2cap_psm_register(struct bt_l2cap_device_s *dev, int psm, int min_mtu,
+                int (*new_channel)(struct bt_l2cap_device_s *dev,
+                        struct bt_l2cap_conn_params_s *params))
+{
+    struct bt_l2cap_psm_s *new_psm = l2cap_psm(dev, psm);
+
+    if (new_psm) {
+        fprintf(stderr, "%s: PSM %04x already registered for device `%s'.\n",
+                        __FUNCTION__, psm, dev->device.lmp_name);
+        exit(-1);
+    }
+
+    new_psm = qemu_mallocz(sizeof(*new_psm));
+    new_psm->psm = psm;
+    new_psm->min_mtu = min_mtu;
+    new_psm->new_channel = new_channel;
+    new_psm->next = dev->first_psm;
+    dev->first_psm = new_psm;
+}
diff -Nur kvm-76/qemu/hw/bt-sdp.c kvm-userspace/qemu/hw/bt-sdp.c
--- kvm-76/qemu/hw/bt-sdp.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/bt-sdp.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,969 @@
+/*
+ * Service Discover Protocol server for QEMU L2CAP devices
+ *
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "bt.h"
+
+struct bt_l2cap_sdp_state_s {
+    struct bt_l2cap_conn_params_s *channel;
+
+    struct sdp_service_record_s {
+        int match;
+
+        int *uuid;
+        int uuids;
+        struct sdp_service_attribute_s {
+            int match;
+
+            int attribute_id;
+            int len;
+            void *pair;
+        } *attribute_list;
+        int attributes;
+    } *service_list;
+    int services;
+};
+
+static ssize_t sdp_datalen(const uint8_t **element, ssize_t *left)
+{
+    size_t len = *(*element) ++ & SDP_DSIZE_MASK;
+
+    if (!*left)
+        return -1;
+    (*left) --;
+
+    if (len < SDP_DSIZE_NEXT1)
+        return 1 << len;
+    else if (len == SDP_DSIZE_NEXT1) {
+        if (*left < 1)
+            return -1;
+        (*left) --;
+
+        return *(*element) ++;
+    } else if (len == SDP_DSIZE_NEXT2) {
+        if (*left < 2)
+            return -1;
+        (*left) -= 2;
+
+        len = (*(*element) ++) << 8;
+        return len | (*(*element) ++);
+    } else {
+        if (*left < 4)
+            return -1;
+        (*left) -= 4;
+
+        len = (*(*element) ++) << 24;
+        len |= (*(*element) ++) << 16;
+        len |= (*(*element) ++) << 8;
+        return len | (*(*element) ++);
+    }
+}
+
+static const uint8_t bt_base_uuid[12] = {
+    0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb,
+};
+
+static int sdp_uuid_match(struct sdp_service_record_s *record,
+                const uint8_t *uuid, ssize_t datalen)
+{
+    int *lo, hi, val;
+
+    if (datalen == 16 || datalen == 4) {
+        if (datalen == 16 && memcmp(uuid + 4, bt_base_uuid, 12))
+            return 0;
+
+        if (uuid[0] | uuid[1])
+            return 0;
+        uuid += 2;
+    }
+
+    val = (uuid[0] << 8) | uuid[1];
+    lo = record->uuid;
+    hi = record->uuids;
+    while (hi >>= 1)
+        if (lo[hi] <= val)
+            lo += hi;
+
+    return *lo == val;
+}
+
+#define CONTINUATION_PARAM_SIZE	(1 + sizeof(int))
+#define MAX_PDU_OUT_SIZE	96	/* Arbitrary */
+#define PDU_HEADER_SIZE		5
+#define MAX_RSP_PARAM_SIZE	(MAX_PDU_OUT_SIZE - PDU_HEADER_SIZE - \
+                CONTINUATION_PARAM_SIZE)
+
+static int sdp_svc_match(struct bt_l2cap_sdp_state_s *sdp,
+                const uint8_t **req, ssize_t *len)
+{
+    size_t datalen;
+    int i;
+
+    if ((**req & ~SDP_DSIZE_MASK) != SDP_DTYPE_UUID)
+        return 1;
+
+    datalen = sdp_datalen(req, len);
+    if (datalen != 2 && datalen != 4 && datalen != 16)
+        return 1;
+
+    for (i = 0; i < sdp->services; i ++)
+        if (sdp_uuid_match(&sdp->service_list[i], *req, datalen))
+            sdp->service_list[i].match = 1;
+
+    (*req) += datalen;
+    (*len) -= datalen;
+
+    return 0;
+}
+
+static ssize_t sdp_svc_search(struct bt_l2cap_sdp_state_s *sdp,
+                uint8_t *rsp, const uint8_t *req, ssize_t len)
+{
+    ssize_t seqlen;
+    int i, count, start, end, max;
+    int32_t handle;
+
+    /* Perform the search */
+    for (i = 0; i < sdp->services; i ++)
+        sdp->service_list[i].match = 0;
+
+    if (len < 1)
+        return -SDP_INVALID_SYNTAX;
+    if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
+        seqlen = sdp_datalen(&req, &len);
+        if (seqlen < 3 || len < seqlen)
+            return -SDP_INVALID_SYNTAX;
+        len -= seqlen;
+
+        while (seqlen)
+            if (sdp_svc_match(sdp, &req, &seqlen))
+                return -SDP_INVALID_SYNTAX;
+    } else if (sdp_svc_match(sdp, &req, &seqlen))
+        return -SDP_INVALID_SYNTAX;
+
+    if (len < 3)
+        return -SDP_INVALID_SYNTAX;
+    end = (req[0] << 8) | req[1];
+    req += 2;
+    len -= 2;
+
+    if (*req) {
+        if (len <= sizeof(int))
+            return -SDP_INVALID_SYNTAX;
+        len -= sizeof(int);
+        memcpy(&start, req + 1, sizeof(int));
+    } else
+        start = 0;
+
+    if (len > 1);
+        return -SDP_INVALID_SYNTAX;
+
+    /* Output the results */
+    len = 4;
+    count = 0;
+    end = start;
+    for (i = 0; i < sdp->services; i ++)
+        if (sdp->service_list[i].match) {
+            if (count >= start && count < max && len + 4 < MAX_RSP_PARAM_SIZE) {
+                handle = i;
+                memcpy(rsp + len, &handle, 4);
+                len += 4;
+                end = count + 1;
+            }
+
+            count ++;
+        }
+
+    rsp[0] = count >> 8;
+    rsp[1] = count & 0xff;
+    rsp[2] = (end - start) >> 8;
+    rsp[3] = (end - start) & 0xff;
+
+    if (end < count) {
+        rsp[len ++] = sizeof(int);
+        memcpy(rsp + len, &end, sizeof(int));
+        len += 4;
+    } else
+        rsp[len ++] = 0;
+
+    return len;
+}
+
+static int sdp_attr_match(struct sdp_service_record_s *record,
+                const uint8_t **req, ssize_t *len)
+{
+    int i, start, end;
+
+    if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_2)) {
+        (*req) ++;
+        if (*len < 3)
+            return 1;
+
+        start = (*(*req) ++) << 8;
+        start |= *(*req) ++;
+        end = start;
+        *len -= 3;
+    } else if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_4)) {
+        (*req) ++;
+        if (*len < 5)
+            return 1;
+
+        start = (*(*req) ++) << 8;
+        start |= *(*req) ++;
+        end = (*(*req) ++) << 8;
+        end |= *(*req) ++;
+        *len -= 5;
+    } else
+        return 1;
+
+    for (i = 0; i < record->attributes; i ++)
+        if (record->attribute_list[i].attribute_id >= start &&
+                        record->attribute_list[i].attribute_id <= end)
+            record->attribute_list[i].match = 1;
+
+    return 0;
+}
+
+static ssize_t sdp_attr_get(struct bt_l2cap_sdp_state_s *sdp,
+                uint8_t *rsp, const uint8_t *req, ssize_t len)
+{
+    ssize_t seqlen;
+    int i, start, end, max;
+    int32_t handle;
+    struct sdp_service_record_s *record;
+    uint8_t *lst;
+
+    /* Perform the search */
+    if (len < 7)
+        return -SDP_INVALID_SYNTAX;
+    memcpy(&handle, req, 6);
+    req += 4;
+    len -= 4;
+
+    if (handle < 0 || handle > sdp->services)
+        return -SDP_INVALID_RECORD_HANDLE;
+    record = &sdp->service_list[handle];
+
+    for (i = 0; i < record->attributes; i ++)
+        record->attribute_list[i].match = 0;
+
+    max = (req[0] << 8) | req[1];
+    req += 2;
+    len -= 2;
+    if (max < 0x0007)
+        return -SDP_INVALID_SYNTAX;
+
+    if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
+        seqlen = sdp_datalen(&req, &len);
+        if (seqlen < 3 || len < seqlen)
+            return -SDP_INVALID_SYNTAX;
+        len -= seqlen;
+
+        while (seqlen)
+            if (sdp_attr_match(record, &req, &seqlen))
+                return -SDP_INVALID_SYNTAX;
+    } else if (sdp_attr_match(record, &req, &seqlen))
+        return -SDP_INVALID_SYNTAX;
+
+    if (len < 1)
+        return -SDP_INVALID_SYNTAX;
+
+    if (*req) {
+        if (len <= sizeof(int))
+            return -SDP_INVALID_SYNTAX;
+        len -= sizeof(int);
+        memcpy(&start, req + 1, sizeof(int));
+    } else
+        start = 0;
+
+    if (len > 1)
+        return -SDP_INVALID_SYNTAX;
+
+    /* Output the results */
+    lst = rsp + 2;
+    max = MIN(max, MAX_RSP_PARAM_SIZE);
+    len = 3 - start;
+    end = 0;
+    for (i = 0; i < record->attributes; i ++)
+        if (record->attribute_list[i].match) {
+            if (len >= 0 && len + record->attribute_list[i].len < max) {
+                memcpy(lst + len, record->attribute_list[i].pair,
+                                record->attribute_list[i].len);
+                end = len + record->attribute_list[i].len;
+            }
+            len += record->attribute_list[i].len;
+        }
+    if (0 >= start) {
+       lst[0] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
+       lst[1] = (len + start - 3) >> 8;
+       lst[2] = (len + start - 3) & 0xff;
+    }
+
+    rsp[0] = end >> 8;
+    rsp[1] = end & 0xff;
+
+    if (end < len) {
+        len = end + start;
+        lst[end ++] = sizeof(int);
+        memcpy(lst + end, &len, sizeof(int));
+        end += sizeof(int);
+    } else
+        lst[end ++] = 0;
+
+    return end + 2;
+}
+
+static int sdp_svc_attr_match(struct bt_l2cap_sdp_state_s *sdp,
+                const uint8_t **req, ssize_t *len)
+{
+    int i, j, start, end;
+    struct sdp_service_record_s *record;
+
+    if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_2)) {
+        (*req) ++;
+        if (*len < 3)
+            return 1;
+
+        start = (*(*req) ++) << 8;
+        start |= *(*req) ++;
+        end = start;
+        *len -= 3;
+    } else if (**req == (SDP_DTYPE_UINT | SDP_DSIZE_4)) {
+        (*req) ++;
+        if (*len < 5)
+            return 1;
+
+        start = (*(*req) ++) << 8;
+        start |= *(*req) ++;
+        end = (*(*req) ++) << 8;
+        end |= *(*req) ++;
+        *len -= 5;
+    } else
+        return 1;
+
+    for (i = 0; i < sdp->services; i ++)
+        if ((record = &sdp->service_list[i])->match)
+            for (j = 0; j < record->attributes; j ++)
+                if (record->attribute_list[j].attribute_id >= start &&
+                                record->attribute_list[j].attribute_id <= end)
+                    record->attribute_list[j].match = 1;
+
+    return 0;
+}
+
+static ssize_t sdp_svc_search_attr_get(struct bt_l2cap_sdp_state_s *sdp,
+                uint8_t *rsp, const uint8_t *req, ssize_t len)
+{
+    ssize_t seqlen;
+    int i, j, start, end, max;
+    struct sdp_service_record_s *record;
+    uint8_t *lst;
+
+    /* Perform the search */
+    for (i = 0; i < sdp->services; i ++) {
+        sdp->service_list[i].match = 0;
+            for (j = 0; j < sdp->service_list[i].attributes; j ++)
+                sdp->service_list[i].attribute_list[j].match = 0;
+    }
+
+    if (len < 1)
+        return -SDP_INVALID_SYNTAX;
+    if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
+        seqlen = sdp_datalen(&req, &len);
+        if (seqlen < 3 || len < seqlen)
+            return -SDP_INVALID_SYNTAX;
+        len -= seqlen;
+
+        while (seqlen)
+            if (sdp_svc_match(sdp, &req, &seqlen))
+                return -SDP_INVALID_SYNTAX;
+    } else if (sdp_svc_match(sdp, &req, &seqlen))
+        return -SDP_INVALID_SYNTAX;
+
+    if (len < 3)
+        return -SDP_INVALID_SYNTAX;
+    max = (req[0] << 8) | req[1];
+    req += 2;
+    len -= 2;
+    if (max < 0x0007)
+        return -SDP_INVALID_SYNTAX;
+
+    if ((*req & ~SDP_DSIZE_MASK) == SDP_DTYPE_SEQ) {
+        seqlen = sdp_datalen(&req, &len);
+        if (seqlen < 3 || len < seqlen)
+            return -SDP_INVALID_SYNTAX;
+        len -= seqlen;
+
+        while (seqlen)
+            if (sdp_svc_attr_match(sdp, &req, &seqlen))
+                return -SDP_INVALID_SYNTAX;
+    } else if (sdp_svc_attr_match(sdp, &req, &seqlen))
+        return -SDP_INVALID_SYNTAX;
+
+    if (len < 1)
+        return -SDP_INVALID_SYNTAX;
+
+    if (*req) {
+        if (len <= sizeof(int))
+            return -SDP_INVALID_SYNTAX;
+        len -= sizeof(int);
+        memcpy(&start, req + 1, sizeof(int));
+    } else
+        start = 0;
+
+    if (len > 1)
+        return -SDP_INVALID_SYNTAX;
+
+    /* Output the results */
+    /* This assumes empty attribute lists are never to be returned even
+     * for matching Service Records.  In practice this shouldn't happen
+     * as the requestor will usually include the always present
+     * ServiceRecordHandle AttributeID in AttributeIDList.  */
+    lst = rsp + 2;
+    max = MIN(max, MAX_RSP_PARAM_SIZE);
+    len = 3 - start;
+    end = 0;
+    for (i = 0; i < sdp->services; i ++)
+        if ((record = &sdp->service_list[i])->match) {
+            len += 3;
+            seqlen = len;
+            for (j = 0; j < record->attributes; j ++)
+                if (record->attribute_list[j].match) {
+                    if (len >= 0)
+                        if (len + record->attribute_list[j].len < max) {
+                            memcpy(lst + len, record->attribute_list[j].pair,
+                                            record->attribute_list[j].len);
+                            end = len + record->attribute_list[j].len;
+                        }
+                    len += record->attribute_list[j].len;
+                }
+            if (seqlen == len)
+                len -= 3;
+            else if (seqlen >= 3 && seqlen < max) {
+                lst[seqlen - 3] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
+                lst[seqlen - 2] = (len - seqlen) >> 8;
+                lst[seqlen - 1] = (len - seqlen) & 0xff;
+            }
+        }
+    if (len == 3 - start)
+        len -= 3;
+    else if (0 >= start) {
+       lst[0] = SDP_DTYPE_SEQ | SDP_DSIZE_NEXT2;
+       lst[1] = (len + start - 3) >> 8;
+       lst[2] = (len + start - 3) & 0xff;
+    }
+
+    rsp[0] = end >> 8;
+    rsp[1] = end & 0xff;
+
+    if (end < len) {
+        len = end + start;
+        lst[end ++] = sizeof(int);
+        memcpy(lst + end, &len, sizeof(int));
+        end += sizeof(int);
+    } else
+        lst[end ++] = 0;
+
+    return end + 2;
+}
+
+static void bt_l2cap_sdp_sdu_in(void *opaque, const uint8_t *data, int len)
+{
+    struct bt_l2cap_sdp_state_s *sdp = opaque;
+    enum bt_sdp_cmd pdu_id;
+    uint8_t rsp[MAX_PDU_OUT_SIZE - PDU_HEADER_SIZE], *sdu_out;
+    int transaction_id, plen;
+    int err = 0;
+    int rsp_len = 0;
+
+    if (len < 5) {
+        fprintf(stderr, "%s: short SDP PDU (%iB).\n", __FUNCTION__, len);
+        return;
+    }
+
+    pdu_id = *data ++;
+    transaction_id = (data[0] << 8) | data[1];
+    plen = (data[2] << 8) | data[3];
+    data += 4;
+    len -= 5;
+
+    if (len != plen) {
+        fprintf(stderr, "%s: wrong SDP PDU length (%iB != %iB).\n",
+                        __FUNCTION__, plen, len);
+        err = SDP_INVALID_PDU_SIZE;
+        goto respond;
+    }
+
+    switch (pdu_id) {
+    case SDP_SVC_SEARCH_REQ:
+        rsp_len = sdp_svc_search(sdp, rsp, data, len);
+        pdu_id = SDP_SVC_SEARCH_RSP;
+        break;
+
+    case SDP_SVC_ATTR_REQ:
+        rsp_len = sdp_attr_get(sdp, rsp, data, len);
+        pdu_id = SDP_SVC_ATTR_RSP;
+        break;
+
+    case SDP_SVC_SEARCH_ATTR_REQ:
+        rsp_len = sdp_svc_search_attr_get(sdp, rsp, data, len);
+        pdu_id = SDP_SVC_SEARCH_ATTR_RSP;
+        break;
+
+    case SDP_ERROR_RSP:
+    case SDP_SVC_ATTR_RSP:
+    case SDP_SVC_SEARCH_RSP:
+    case SDP_SVC_SEARCH_ATTR_RSP:
+    default:
+        fprintf(stderr, "%s: unexpected SDP PDU ID %02x.\n",
+                        __FUNCTION__, pdu_id);
+        err = SDP_INVALID_SYNTAX;
+        break;
+    }
+
+    if (rsp_len < 0) {
+        err = -rsp_len;
+        rsp_len = 0;
+    }
+
+respond:
+    if (err) {
+        pdu_id = SDP_ERROR_RSP;
+        rsp[rsp_len ++] = err >> 8;
+        rsp[rsp_len ++] = err & 0xff;
+    }
+
+    sdu_out = sdp->channel->sdu_out(sdp->channel, rsp_len + PDU_HEADER_SIZE);
+
+    sdu_out[0] = pdu_id;
+    sdu_out[1] = transaction_id >> 8;
+    sdu_out[2] = transaction_id & 0xff;
+    sdu_out[3] = rsp_len >> 8;
+    sdu_out[4] = rsp_len & 0xff;
+    memcpy(sdu_out + PDU_HEADER_SIZE, rsp, rsp_len);
+
+    sdp->channel->sdu_submit(sdp->channel);
+}
+
+static void bt_l2cap_sdp_close_ch(void *opaque)
+{
+    struct bt_l2cap_sdp_state_s *sdp = opaque;
+    int i;
+
+    for (i = 0; i < sdp->services; i ++) {
+        qemu_free(sdp->service_list[i].attribute_list->pair);
+        qemu_free(sdp->service_list[i].attribute_list);
+        qemu_free(sdp->service_list[i].uuid);
+    }
+    qemu_free(sdp->service_list);
+    qemu_free(sdp);
+}
+
+struct sdp_def_service_s {
+    uint16_t class_uuid;
+    struct sdp_def_attribute_s {
+        uint16_t id;
+        struct sdp_def_data_element_s {
+            uint8_t type;
+            union {
+                uint32_t uint;
+                const char *str;
+                struct sdp_def_data_element_s *list;
+            } value;
+        } data;
+    } attributes[];
+};
+
+/* Calculate a safe byte count to allocate that will store the given
+ * element, at the same time count elements of a UUID type.  */
+static int sdp_attr_max_size(struct sdp_def_data_element_s *element,
+                int *uuids)
+{
+    int type = element->type & ~SDP_DSIZE_MASK;
+    int len;
+
+    if (type == SDP_DTYPE_UINT || type == SDP_DTYPE_UUID ||
+                    type == SDP_DTYPE_BOOL) {
+        if (type == SDP_DTYPE_UUID)
+            (*uuids) ++;
+        return 1 + (1 << (element->type & SDP_DSIZE_MASK));
+    }
+
+    if (type == SDP_DTYPE_STRING || type == SDP_DTYPE_URL) {
+        if (element->type & SDP_DSIZE_MASK) {
+            for (len = 0; element->value.str[len] |
+                            element->value.str[len + 1]; len ++);
+            return len;
+        } else
+            return 2 + strlen(element->value.str);
+    }
+
+    if (type != SDP_DTYPE_SEQ)
+        exit(-1);
+    len = 2;
+    element = element->value.list;
+    while (element->type)
+        len += sdp_attr_max_size(element ++, uuids);
+    if (len > 255)
+        exit (-1);
+
+    return len;
+}
+
+static int sdp_attr_write(uint8_t *data,
+                struct sdp_def_data_element_s *element, int **uuid)
+{
+    int type = element->type & ~SDP_DSIZE_MASK;
+    int len = 0;
+
+    if (type == SDP_DTYPE_UINT || type == SDP_DTYPE_BOOL) {
+        data[len ++] = element->type;
+        if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_1)
+            data[len ++] = (element->value.uint >>  0) & 0xff;
+        else if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_2) {
+            data[len ++] = (element->value.uint >>  8) & 0xff;
+            data[len ++] = (element->value.uint >>  0) & 0xff;
+        } else if ((element->type & SDP_DSIZE_MASK) == SDP_DSIZE_4) {
+            data[len ++] = (element->value.uint >>  24) & 0xff;
+            data[len ++] = (element->value.uint >>  16) & 0xff;
+            data[len ++] = (element->value.uint >>  8) & 0xff;
+            data[len ++] = (element->value.uint >>  0) & 0xff;
+        }
+
+        return len;
+    }
+
+    if (type == SDP_DTYPE_UUID) {
+        *(*uuid) ++ = element->value.uint;
+
+        data[len ++] = element->type;
+        data[len ++] = (element->value.uint >>  24) & 0xff;
+        data[len ++] = (element->value.uint >>  16) & 0xff;
+        data[len ++] = (element->value.uint >>  8) & 0xff;
+        data[len ++] = (element->value.uint >>  0) & 0xff;
+        memcpy(data + len, bt_base_uuid, 12);
+
+        return len + 12;
+    }
+
+    data[0] = type | SDP_DSIZE_NEXT1;
+    if (type == SDP_DTYPE_STRING || type == SDP_DTYPE_URL) {
+        if (element->type & SDP_DSIZE_MASK)
+            for (len = 0; element->value.str[len] |
+                            element->value.str[len + 1]; len ++);
+        else
+            len = strlen(element->value.str);
+        memcpy(data + 2, element->value.str, data[1] = len);
+
+        return len + 2;
+    }
+
+    len = 2;
+    element = element->value.list;
+    while (element->type)
+        len += sdp_attr_write(data + len, element ++, uuid);
+    data[1] = len - 2;
+
+    return len;
+}
+
+static int sdp_attributeid_compare(const struct sdp_service_attribute_s *a,
+                const struct sdp_service_attribute_s *b)
+{
+    return (int) b->attribute_id - a->attribute_id;
+}
+
+static int sdp_uuid_compare(const int *a, const int *b)
+{
+    return *a - *b;
+}
+
+static void sdp_service_record_build(struct sdp_service_record_s *record,
+                struct sdp_def_service_s *def, int handle)
+{
+    int len = 0;
+    uint8_t *data;
+    int *uuid;
+
+    record->uuids = 0;
+    while (def->attributes[record->attributes].data.type) {
+        len += 3;
+        len += sdp_attr_max_size(&def->attributes[record->attributes ++].data,
+                        &record->uuids);
+    }
+    record->uuids = 1 << ffs(record->uuids - 1);
+    record->attribute_list =
+            qemu_mallocz(record->attributes * sizeof(*record->attribute_list));
+    record->uuid =
+            qemu_mallocz(record->uuids * sizeof(*record->uuid));
+    data = qemu_malloc(len);
+
+    record->attributes = 0;
+    uuid = record->uuid;
+    while (def->attributes[record->attributes].data.type) {
+        record->attribute_list[record->attributes].pair = data;
+
+        len = 0;
+        data[len ++] = SDP_DTYPE_UINT | SDP_DSIZE_2;
+        data[len ++] = def->attributes[record->attributes].id >> 8;
+        data[len ++] = def->attributes[record->attributes].id & 0xff;
+        len += sdp_attr_write(data + len,
+                        &def->attributes[record->attributes].data, &uuid);
+
+        /* Special case: assign a ServiceRecordHandle in sequence */
+        if (def->attributes[record->attributes].id == SDP_ATTR_RECORD_HANDLE)
+            def->attributes[record->attributes].data.value.uint = handle;
+        /* Note: we could also assign a ServiceDescription based on
+         * sdp->device.device->lmp_name.  */
+
+        record->attribute_list[record->attributes ++].len = len;
+        data += len;
+    }
+
+    /* Sort the attribute list by the AttributeID */
+    qsort(record->attribute_list, record->attributes,
+                    sizeof(*record->attribute_list),
+                    (void *) sdp_attributeid_compare);
+    /* Sort the searchable UUIDs list for bisection */
+    qsort(record->uuid, record->uuids,
+                    sizeof(*record->uuid),
+                    (void *) sdp_uuid_compare);
+}
+
+static void sdp_service_db_build(struct bt_l2cap_sdp_state_s *sdp,
+                struct sdp_def_service_s **service)
+{
+    sdp->services = 0;
+    while (service[sdp->services])
+        sdp->services ++;
+    sdp->service_list =
+            qemu_mallocz(sdp->services * sizeof(*sdp->service_list));
+
+    sdp->services = 0;
+    while (*service) {
+        sdp_service_record_build(&sdp->service_list[sdp->services],
+                        *service, sdp->services);
+        service ++;
+        sdp->services ++;
+    }
+}
+
+#define LAST { .type = 0 }
+#define SERVICE(name, attrs)				\
+    static struct sdp_def_service_s glue(glue(sdp_service_, name), _s) = { \
+        .attributes = { attrs { .data = LAST } },	\
+    };
+#define ATTRIBUTE(attrid, val)	{ .id = glue(SDP_ATTR_, attrid), .data = val },
+#define UINT8(val)	{				\
+        .type       = SDP_DTYPE_UINT | SDP_DSIZE_1,	\
+        .value.uint = val,				\
+    },
+#define UINT16(val)	{				\
+        .type       = SDP_DTYPE_UINT | SDP_DSIZE_2,	\
+        .value.uint = val,				\
+    },
+#define UINT32(val)	{				\
+        .type       = SDP_DTYPE_UINT | SDP_DSIZE_4,	\
+        .value.uint = val,				\
+    },
+#define UUID128(val)	{				\
+        .type       = SDP_DTYPE_UUID | SDP_DSIZE_16,	\
+        .value.uint = val,				\
+    },
+#define TRUE	{				\
+        .type       = SDP_DTYPE_BOOL | SDP_DSIZE_1,	\
+        .value.uint = 1,				\
+    },
+#define FALSE	{				\
+        .type       = SDP_DTYPE_BOOL | SDP_DSIZE_1,	\
+        .value.uint = 0,				\
+    },
+#define STRING(val)	{				\
+        .type       = SDP_DTYPE_STRING,			\
+        .value.str  = val,				\
+    },
+#define ARRAY(...)	{				\
+        .type       = SDP_DTYPE_STRING | SDP_DSIZE_2,	\
+        .value.str  = (char []) { __VA_ARGS__, 0, 0 },	\
+    },
+#define URL(val)	{				\
+        .type       = SDP_DTYPE_URL,			\
+        .value.str  = val,				\
+    },
+#if 1
+#define LIST(val)	{				\
+        .type       = SDP_DTYPE_SEQ,			\
+        .value.list = (struct sdp_def_data_element_s []) { val LAST }, \
+    },
+#endif
+
+/* Try to keep each single attribute below MAX_PDU_OUT_SIZE bytes
+ * in resulting SDP data representation size.  */
+
+SERVICE(hid,
+    ATTRIBUTE(RECORD_HANDLE,   UINT32(0))	/* Filled in later */
+    ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(HID_SVCLASS_ID)))
+    ATTRIBUTE(RECORD_STATE,    UINT32(1))
+    ATTRIBUTE(PROTO_DESC_LIST, LIST(
+        LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_HID_CTRL))
+        LIST(UUID128(HIDP_UUID))
+    ))
+    ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
+    ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
+        UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
+    ))
+    ATTRIBUTE(PFILE_DESC_LIST, LIST(
+        LIST(UUID128(HID_PROFILE_ID) UINT16(0x0100))
+    ))
+    ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
+    ATTRIBUTE(SVCNAME_PRIMARY, STRING("QEMU Bluetooth HID"))
+    ATTRIBUTE(SVCDESC_PRIMARY, STRING("QEMU Keyboard/Mouse"))
+    ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
+
+    /* Profile specific */
+    ATTRIBUTE(DEVICE_RELEASE_NUMBER,	UINT16(0x0091)) /* Deprecated, remove */
+    ATTRIBUTE(PARSER_VERSION,		UINT16(0x0111))
+    /* TODO: extract from l2cap_device->device.class[0] */
+    ATTRIBUTE(DEVICE_SUBCLASS,		UINT8(0x40))
+    ATTRIBUTE(COUNTRY_CODE,		UINT8(0x15))
+    ATTRIBUTE(VIRTUAL_CABLE,		TRUE)
+    ATTRIBUTE(RECONNECT_INITIATE,	FALSE)
+    /* TODO: extract from hid->usbdev->report_desc */
+    ATTRIBUTE(DESCRIPTOR_LIST,		LIST(
+        LIST(UINT8(0x22) ARRAY(
+            0x05, 0x01,	/* Usage Page (Generic Desktop) */
+            0x09, 0x06,	/* Usage (Keyboard) */
+            0xa1, 0x01,	/* Collection (Application) */
+            0x75, 0x01,	/*   Report Size (1) */
+            0x95, 0x08,	/*   Report Count (8) */
+            0x05, 0x07,	/*   Usage Page (Key Codes) */
+            0x19, 0xe0,	/*   Usage Minimum (224) */
+            0x29, 0xe7,	/*   Usage Maximum (231) */
+            0x15, 0x00,	/*   Logical Minimum (0) */
+            0x25, 0x01,	/*   Logical Maximum (1) */
+            0x81, 0x02,	/*   Input (Data, Variable, Absolute) */
+            0x95, 0x01,	/*   Report Count (1) */
+            0x75, 0x08,	/*   Report Size (8) */
+            0x81, 0x01,	/*   Input (Constant) */
+            0x95, 0x05,	/*   Report Count (5) */
+            0x75, 0x01,	/*   Report Size (1) */
+            0x05, 0x08,	/*   Usage Page (LEDs) */
+            0x19, 0x01,	/*   Usage Minimum (1) */
+            0x29, 0x05,	/*   Usage Maximum (5) */
+            0x91, 0x02,	/*   Output (Data, Variable, Absolute) */
+            0x95, 0x01,	/*   Report Count (1) */
+            0x75, 0x03,	/*   Report Size (3) */
+            0x91, 0x01,	/*   Output (Constant) */
+            0x95, 0x06,	/*   Report Count (6) */
+            0x75, 0x08,	/*   Report Size (8) */
+            0x15, 0x00,	/*   Logical Minimum (0) */
+            0x25, 0xff,	/*   Logical Maximum (255) */
+            0x05, 0x07,	/*   Usage Page (Key Codes) */
+            0x19, 0x00,	/*   Usage Minimum (0) */
+            0x29, 0xff,	/*   Usage Maximum (255) */
+            0x81, 0x00,	/*   Input (Data, Array) */
+            0xc0	/* End Collection */
+    ))))
+    ATTRIBUTE(LANG_ID_BASE_LIST,	LIST(
+        LIST(UINT16(0x0409) UINT16(0x0100))
+    ))
+    ATTRIBUTE(SDP_DISABLE,		FALSE)
+    ATTRIBUTE(BATTERY_POWER,		TRUE)
+    ATTRIBUTE(REMOTE_WAKEUP,		TRUE)
+    ATTRIBUTE(BOOT_DEVICE,		TRUE)	/* XXX: untested */
+    ATTRIBUTE(SUPERVISION_TIMEOUT,	UINT16(0x0c80))
+    ATTRIBUTE(NORMALLY_CONNECTABLE,	TRUE)
+    ATTRIBUTE(PROFILE_VERSION,		UINT16(0x0100))
+)
+
+SERVICE(sdp,
+    ATTRIBUTE(RECORD_HANDLE,   UINT32(0))	/* Filled in later */
+    ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(SDP_SERVER_SVCLASS_ID)))
+    ATTRIBUTE(RECORD_STATE,    UINT32(1))
+    ATTRIBUTE(PROTO_DESC_LIST, LIST(
+        LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_SDP))
+        LIST(UUID128(SDP_UUID))
+    ))
+    ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
+    ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
+        UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
+    ))
+    ATTRIBUTE(PFILE_DESC_LIST, LIST(
+        LIST(UUID128(SDP_SERVER_PROFILE_ID) UINT16(0x0100))
+    ))
+    ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
+    ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
+
+    /* Profile specific */
+    ATTRIBUTE(VERSION_NUM_LIST, LIST(UINT16(0x0100)))
+    ATTRIBUTE(SVCDB_STATE    , UINT32(1))
+)
+
+SERVICE(pnp,
+    ATTRIBUTE(RECORD_HANDLE,   UINT32(0))	/* Filled in later */
+    ATTRIBUTE(SVCLASS_ID_LIST, LIST(UUID128(PNP_INFO_SVCLASS_ID)))
+    ATTRIBUTE(RECORD_STATE,    UINT32(1))
+    ATTRIBUTE(PROTO_DESC_LIST, LIST(
+        LIST(UUID128(L2CAP_UUID) UINT16(BT_PSM_SDP))
+        LIST(UUID128(SDP_UUID))
+    ))
+    ATTRIBUTE(BROWSE_GRP_LIST, LIST(UUID128(0x1002)))
+    ATTRIBUTE(LANG_BASE_ATTR_ID_LIST, LIST(
+        UINT16(0x656e) UINT16(0x006a) UINT16(0x0100)
+    ))
+    ATTRIBUTE(PFILE_DESC_LIST, LIST(
+        LIST(UUID128(PNP_INFO_PROFILE_ID) UINT16(0x0100))
+    ))
+    ATTRIBUTE(DOC_URL,         URL("http://bellard.org/qemu/user-doc.html"))
+    ATTRIBUTE(SVCPROV_PRIMARY, STRING("QEMU " QEMU_VERSION))
+
+    /* Profile specific */
+    ATTRIBUTE(SPECIFICATION_ID, UINT16(0x0100))
+    ATTRIBUTE(VERSION,         UINT16(0x0100))
+    ATTRIBUTE(PRIMARY_RECORD,  TRUE)
+)
+
+static int bt_l2cap_sdp_new_ch(struct bt_l2cap_device_s *dev,
+                struct bt_l2cap_conn_params_s *params)
+{
+    struct bt_l2cap_sdp_state_s *sdp = qemu_mallocz(sizeof(*sdp));
+    struct sdp_def_service_s *services[] = {
+        &sdp_service_sdp_s,
+        &sdp_service_hid_s,
+        &sdp_service_pnp_s,
+        0,
+    };
+
+    sdp->channel = params;
+    sdp->channel->opaque = sdp;
+    sdp->channel->close = bt_l2cap_sdp_close_ch;
+    sdp->channel->sdu_in = bt_l2cap_sdp_sdu_in;
+
+    sdp_service_db_build(sdp, services);
+
+    return 0;
+}
+
+void bt_l2cap_sdp_init(struct bt_l2cap_device_s *dev)
+{
+    bt_l2cap_psm_register(dev, BT_PSM_SDP,
+                    MAX_PDU_OUT_SIZE, bt_l2cap_sdp_new_ch);
+}
diff -Nur kvm-76/qemu/hw/bt.c kvm-userspace/qemu/hw/bt.c
--- kvm-76/qemu/hw/bt.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/bt.c	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,123 @@
+/*
+ * Convenience functions for bluetooth.
+ *
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "net.h"
+#include "bt.h"
+
+/* Slave implementations can ignore this */
+static void bt_dummy_lmp_mode_change(struct bt_link_s *link)
+{
+}
+
+/* Slaves should never receive these PDUs */
+static void bt_dummy_lmp_connection_complete(struct bt_link_s *link)
+{
+    if (link->slave->reject_reason)
+        fprintf(stderr, "%s: stray LMP_not_accepted received, fixme\n",
+                        __FUNCTION__);
+    else
+        fprintf(stderr, "%s: stray LMP_accepted received, fixme\n",
+                        __FUNCTION__);
+    exit(-1);
+}
+
+static void bt_dummy_lmp_disconnect_master(struct bt_link_s *link)
+{
+    fprintf(stderr, "%s: stray LMP_detach received, fixme\n", __FUNCTION__);
+    exit(-1);
+}
+
+static void bt_dummy_lmp_acl_resp(struct bt_link_s *link,
+                const uint8_t *data, int start, int len)
+{
+    fprintf(stderr, "%s: stray ACL response PDU, fixme\n", __FUNCTION__);
+    exit(-1);
+}
+
+/* Slaves that don't hold any additional per link state can use these */
+static void bt_dummy_lmp_connection_request(struct bt_link_s *req)
+{
+    struct bt_link_s *link = qemu_mallocz(sizeof(struct bt_link_s));
+
+    link->slave = req->slave;
+    link->host = req->host;
+
+    req->host->reject_reason = 0;
+    req->host->lmp_connection_complete(link);
+}
+
+static void bt_dummy_lmp_disconnect_slave(struct bt_link_s *link)
+{
+    qemu_free(link);
+}
+
+static void bt_dummy_destroy(struct bt_device_s *device)
+{
+    bt_device_done(device);
+    qemu_free(device);
+}
+
+static int bt_dev_idx = 0;
+
+void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net)
+{
+    memset(dev, 0, sizeof(*dev));
+    dev->inquiry_scan = 1;
+    dev->page_scan = 1;
+
+    dev->bd_addr.b[0] = bt_dev_idx & 0xff;
+    dev->bd_addr.b[1] = bt_dev_idx >> 8;
+    dev->bd_addr.b[2] = 0xd0;
+    dev->bd_addr.b[3] = 0xba;
+    dev->bd_addr.b[4] = 0xbe;
+    dev->bd_addr.b[5] = 0xba;
+    bt_dev_idx ++;
+
+    /* Simple slave-only devices need to implement only .lmp_acl_data */
+    dev->lmp_connection_complete = bt_dummy_lmp_connection_complete;
+    dev->lmp_disconnect_master = bt_dummy_lmp_disconnect_master;
+    dev->lmp_acl_resp = bt_dummy_lmp_acl_resp;
+    dev->lmp_mode_change = bt_dummy_lmp_mode_change;
+    dev->lmp_connection_request = bt_dummy_lmp_connection_request;
+    dev->lmp_disconnect_slave = bt_dummy_lmp_disconnect_slave;
+
+    dev->handle_destroy = bt_dummy_destroy;
+
+    dev->net = net;
+    dev->next = net->slave;
+    net->slave = dev;
+}
+
+void bt_device_done(struct bt_device_s *dev)
+{
+    struct bt_device_s **p = &dev->net->slave;
+
+    while (*p && *p != dev)
+        p = &(*p)->next;
+    if (*p != dev) {
+        fprintf(stderr, "%s: bad bt device \"%s\"\n", __FUNCTION__,
+                        dev->lmp_name ?: "(null)");
+        exit(-1);
+    }
+
+    *p = dev->next;
+}
diff -Nur kvm-76/qemu/hw/bt.h kvm-userspace/qemu/hw/bt.h
--- kvm-76/qemu/hw/bt.h	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/bt.h	2008-10-12 09:38:23.000000000 +0200
@@ -0,0 +1,2188 @@
+/*
+ * QEMU Bluetooth HCI helpers.
+ *
+ * Copyright (C) 2007 OpenMoko, Inc.
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
+ *
+ * Useful definitions taken from BlueZ project's headers.
+ * Copyright (C) 2000-2001  Qualcomm Incorporated
+ * Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ * Copyright (C) 2002-2006  Marcel Holtmann <marcel@holtmann.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA  02110-1301  USA
+ */
+
+/* BD Address */
+typedef struct {
+    uint8_t b[6];
+} __attribute__((packed)) bdaddr_t;
+
+#define BDADDR_ANY	(&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
+#define BDADDR_ALL	(&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
+#define BDADDR_LOCAL	(&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
+
+/* Copy, swap, convert BD Address */
+static inline int bacmp(const bdaddr_t *ba1, const bdaddr_t *ba2)
+{
+    return memcmp(ba1, ba2, sizeof(bdaddr_t));
+}
+static inline void bacpy(bdaddr_t *dst, const bdaddr_t *src)
+{
+    memcpy(dst, src, sizeof(bdaddr_t));
+}
+
+#define BAINIT(orig)	{ .b = {		\
+    (orig)->b[0], (orig)->b[1], (orig)->b[2],	\
+    (orig)->b[3], (orig)->b[4], (orig)->b[5],	\
+}, }
+
+/* The twisted structures of a bluetooth environment */
+struct bt_device_s;
+struct bt_scatternet_s;
+struct bt_piconet_s;
+struct bt_link_s;
+
+struct bt_scatternet_s {
+    struct bt_device_s *slave;
+};
+
+struct bt_link_s {
+    struct bt_device_s *slave, *host;
+    uint16_t handle;		/* Master (host) side handle */
+    uint16_t acl_interval;
+    enum {
+        acl_active,
+        acl_hold,
+        acl_sniff,
+        acl_parked,
+    } acl_mode;
+};
+
+struct bt_device_s {
+    int lt_addr;
+    bdaddr_t bd_addr;
+    int mtu;
+    int setup;
+    struct bt_scatternet_s *net;
+
+    uint8_t key[16];
+    int key_present;
+    uint8_t class[3];
+
+    uint8_t reject_reason;
+
+    uint64_t lmp_caps;
+    const char *lmp_name;
+    void (*lmp_connection_request)(struct bt_link_s *link);
+    void (*lmp_connection_complete)(struct bt_link_s *link);
+    void (*lmp_disconnect_master)(struct bt_link_s *link);
+    void (*lmp_disconnect_slave)(struct bt_link_s *link);
+    void (*lmp_acl_data)(struct bt_link_s *link, const uint8_t *data,
+                    int start, int len);
+    void (*lmp_acl_resp)(struct bt_link_s *link, const uint8_t *data,
+                    int start, int len);
+    void (*lmp_mode_change)(struct bt_link_s *link);
+
+    void (*handle_destroy)(struct bt_device_s *device);
+    struct bt_device_s *next;	/* Next in the piconet/scatternet */
+
+    int inquiry_scan;
+    int page_scan;
+
+    uint16_t clkoff;	/* Note: Always little-endian */
+};
+
+/* bt.c */
+void bt_device_init(struct bt_device_s *dev, struct bt_scatternet_s *net);
+void bt_device_done(struct bt_device_s *dev);
+
+/* bt-hci.c */
+struct HCIInfo *bt_new_hci(struct bt_scatternet_s *net);
+
+/* bt-host.c */
+struct HCIInfo *bt_host_hci(const char *id);
+
+/* bt-vhci.c */
+void bt_vhci_init(struct HCIInfo *info);
+
+/* bt-hci-csr.c */
+enum {
+    csrhci_pin_reset,
+    csrhci_pin_wakeup,
+    __csrhci_pins,
+};
+qemu_irq *csrhci_pins_get(CharDriverState *chr);
+CharDriverState *uart_hci_init(qemu_irq wakeup);
+
+/* bt-l2cap.c */
+struct bt_l2cap_device_s;
+struct bt_l2cap_conn_params_s;
+struct bt_l2cap_psm_s;
+void bt_l2cap_device_init(struct bt_l2cap_device_s *dev,
+                struct bt_scatternet_s *net);
+void bt_l2cap_device_done(struct bt_l2cap_device_s *dev);
+void bt_l2cap_psm_register(struct bt_l2cap_device_s *dev, int psm,
+                int min_mtu, int (*new_channel)(struct bt_l2cap_device_s *dev,
+                        struct bt_l2cap_conn_params_s *params));
+
+struct bt_l2cap_device_s {
+    struct bt_device_s device;
+    struct bt_l2cap_psm_s *first_psm;
+};
+
+struct bt_l2cap_conn_params_s {
+    /* Input */
+    uint8_t *(*sdu_out)(struct bt_l2cap_conn_params_s *chan, int len);
+    void (*sdu_submit)(struct bt_l2cap_conn_params_s *chan);
+    int remote_mtu;
+    /* Output */
+    void *opaque;
+    void (*sdu_in)(void *opaque, const uint8_t *data, int len);
+    void (*close)(void *opaque);
+};
+
+enum bt_l2cap_psm_predef {
+    BT_PSM_SDP		= 0x0001,
+    BT_PSM_RFCOMM	= 0x0003,
+    BT_PSM_TELEPHONY	= 0x0005,
+    BT_PSM_TCS		= 0x0007,
+    BT_PSM_BNEP		= 0x000f,
+    BT_PSM_HID_CTRL	= 0x0011,
+    BT_PSM_HID_INTR	= 0x0013,
+    BT_PSM_UPNP		= 0x0015,
+    BT_PSM_AVCTP	= 0x0017,
+    BT_PSM_AVDTP	= 0x0019,
+};
+
+/* bt-sdp.c */
+void bt_l2cap_sdp_init(struct bt_l2cap_device_s *dev);
+
+/* bt-hid.c */
+struct bt_device_s *bt_mouse_init(struct bt_scatternet_s *net);
+struct bt_device_s *bt_tablet_init(struct bt_scatternet_s *net);
+struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net);
+
+/* Link Management Protocol layer defines */
+
+#define LLID_ACLU_CONT		0x1
+#define LLID_ACLU_START		0x2
+#define LLID_ACLC		0x3
+
+enum lmp_pdu_type {
+    LMP_NAME_REQ		= 0x0001,
+    LMP_NAME_RES		= 0x0002,
+    LMP_ACCEPTED		= 0x0003,
+    LMP_NOT_ACCEPTED		= 0x0004,
+    LMP_CLKOFFSET_REQ		= 0x0005,
+    LMP_CLKOFFSET_RES		= 0x0006,
+    LMP_DETACH			= 0x0007,
+    LMP_IN_RAND			= 0x0008,
+    LMP_COMB_KEY		= 0x0009,
+    LMP_UNIT_KEY		= 0x000a,
+    LMP_AU_RAND			= 0x000b,
+    LMP_SRES			= 0x000c,
+    LMP_TEMP_RAND		= 0x000d,
+    LMP_TEMP_KEY		= 0x000e,
+    LMP_CRYPT_MODE_REQ		= 0x000f,
+    LMP_CRYPT_KEY_SIZE_REQ	= 0x0010,
+    LMP_START_ENCRYPT_REQ	= 0x0011,
+    LMP_STOP_ENCRYPT_REQ	= 0x0012,
+    LMP_SWITCH_REQ		= 0x0013,
+    LMP_HOLD			= 0x0014,
+    LMP_HOLD_REQ		= 0x0015,
+    LMP_SNIFF_REQ		= 0x0017,
+    LMP_UNSNIFF_REQ		= 0x0018,
+    LMP_LMP_PARK_REQ		= 0x0019,
+    LMP_SET_BCAST_SCAN_WND	= 0x001b,
+    LMP_MODIFY_BEACON		= 0x001c,
+    LMP_UNPARK_BD_ADDR_REQ	= 0x001d,
+    LMP_UNPARK_PM_ADDR_REQ	= 0x001e,
+    LMP_INCR_POWER_REQ		= 0x001f,
+    LMP_DECR_POWER_REQ		= 0x0020,
+    LMP_MAX_POWER		= 0x0021,
+    LMP_MIN_POWER		= 0x0022,
+    LMP_AUTO_RATE		= 0x0023,
+    LMP_PREFERRED_RATE		= 0x0024,
+    LMP_VERSION_REQ		= 0x0025,
+    LMP_VERSION_RES		= 0x0026,
+    LMP_FEATURES_REQ		= 0x0027,
+    LMP_FEATURES_RES		= 0x0028,
+    LMP_QUALITY_OF_SERVICE	= 0x0029,
+    LMP_QOS_REQ			= 0x002a,
+    LMP_RM_SCO_LINK_REQ		= 0x002b,
+    LMP_SCO_LINK_REQ		= 0x002c,
+    LMP_MAX_SLOT		= 0x002d,
+    LMP_MAX_SLOT_REQ		= 0x002e,
+    LMP_TIMING_ACCURACY_REQ	= 0x002f,
+    LMP_TIMING_ACCURACY_RES	= 0x0030,
+    LMP_SETUP_COMPLETE		= 0x0031,
+    LMP_USE_SEMIPERM_KEY	= 0x0032,
+    LMP_HOST_CONNECTION_REQ	= 0x0033,
+    LMP_SLOT_OFFSET		= 0x0034,
+    LMP_PAGE_MODE_REQ		= 0x0035,
+    LMP_PAGE_SCAN_MODE_REQ	= 0x0036,
+    LMP_SUPERVISION_TIMEOUT	= 0x0037,
+    LMP_TEST_ACTIVATE		= 0x0038,
+    LMP_TEST_CONTROL		= 0x0039,
+    LMP_CRYPT_KEY_MASK_REQ	= 0x003a,
+    LMP_CRYPT_KEY_MASK_RES	= 0x003b,
+    LMP_SET_AFH			= 0x003c,
+    LMP_ACCEPTED_EXT		= 0x7f01,
+    LMP_NOT_ACCEPTED_EXT	= 0x7f02,
+    LMP_FEATURES_REQ_EXT	= 0x7f03,
+    LMP_FEATURES_RES_EXT	= 0x7f04,
+    LMP_PACKET_TYPE_TBL_REQ	= 0x7f0b,
+    LMP_ESCO_LINK_REQ		= 0x7f0c,
+    LMP_RM_ESCO_LINK_REQ	= 0x7f0d,
+    LMP_CHANNEL_CLASS_REQ	= 0x7f10,
+    LMP_CHANNEL_CLASS		= 0x7f11,
+};
+
+/* Host Controller Interface layer defines */
+
+enum hci_packet_type {
+    HCI_COMMAND_PKT		= 0x01,
+    HCI_ACLDATA_PKT		= 0x02,
+    HCI_SCODATA_PKT		= 0x03,
+    HCI_EVENT_PKT		= 0x04,
+    HCI_VENDOR_PKT		= 0xff,
+};
+
+enum bt_packet_type {
+    HCI_2DH1	= 1 << 1,
+    HCI_3DH1	= 1 << 2,
+    HCI_DM1	= 1 << 3,
+    HCI_DH1	= 1 << 4,
+    HCI_2DH3	= 1 << 8,
+    HCI_3DH3	= 1 << 9,
+    HCI_DM3	= 1 << 10,
+    HCI_DH3	= 1 << 11,
+    HCI_2DH5	= 1 << 12,
+    HCI_3DH5	= 1 << 13,
+    HCI_DM5	= 1 << 14,
+    HCI_DH5	= 1 << 15,
+};
+
+enum sco_packet_type {
+    HCI_HV1	= 1 << 5,
+    HCI_HV2	= 1 << 6,
+    HCI_HV3	= 1 << 7,
+};
+
+enum ev_packet_type {
+    HCI_EV3	= 1 << 3,
+    HCI_EV4	= 1 << 4,
+    HCI_EV5	= 1 << 5,
+    HCI_2EV3	= 1 << 6,
+    HCI_3EV3	= 1 << 7,
+    HCI_2EV5	= 1 << 8,
+    HCI_3EV5	= 1 << 9,
+};
+
+enum hci_error_code {
+    HCI_SUCCESS				= 0x00,
+    HCI_UNKNOWN_COMMAND			= 0x01,
+    HCI_NO_CONNECTION			= 0x02,
+    HCI_HARDWARE_FAILURE		= 0x03,
+    HCI_PAGE_TIMEOUT			= 0x04,
+    HCI_AUTHENTICATION_FAILURE		= 0x05,
+    HCI_PIN_OR_KEY_MISSING		= 0x06,
+    HCI_MEMORY_FULL			= 0x07,
+    HCI_CONNECTION_TIMEOUT		= 0x08,
+    HCI_MAX_NUMBER_OF_CONNECTIONS	= 0x09,
+    HCI_MAX_NUMBER_OF_SCO_CONNECTIONS	= 0x0a,
+    HCI_ACL_CONNECTION_EXISTS		= 0x0b,
+    HCI_COMMAND_DISALLOWED		= 0x0c,
+    HCI_REJECTED_LIMITED_RESOURCES	= 0x0d,
+    HCI_REJECTED_SECURITY		= 0x0e,
+    HCI_REJECTED_PERSONAL		= 0x0f,
+    HCI_HOST_TIMEOUT			= 0x10,
+    HCI_UNSUPPORTED_FEATURE		= 0x11,
+    HCI_INVALID_PARAMETERS		= 0x12,
+    HCI_OE_USER_ENDED_CONNECTION	= 0x13,
+    HCI_OE_LOW_RESOURCES		= 0x14,
+    HCI_OE_POWER_OFF			= 0x15,
+    HCI_CONNECTION_TERMINATED		= 0x16,
+    HCI_REPEATED_ATTEMPTS		= 0x17,
+    HCI_PAIRING_NOT_ALLOWED		= 0x18,
+    HCI_UNKNOWN_LMP_PDU			= 0x19,
+    HCI_UNSUPPORTED_REMOTE_FEATURE	= 0x1a,
+    HCI_SCO_OFFSET_REJECTED		= 0x1b,
+    HCI_SCO_INTERVAL_REJECTED		= 0x1c,
+    HCI_AIR_MODE_REJECTED		= 0x1d,
+    HCI_INVALID_LMP_PARAMETERS		= 0x1e,
+    HCI_UNSPECIFIED_ERROR		= 0x1f,
+    HCI_UNSUPPORTED_LMP_PARAMETER_VALUE	= 0x20,
+    HCI_ROLE_CHANGE_NOT_ALLOWED		= 0x21,
+    HCI_LMP_RESPONSE_TIMEOUT		= 0x22,
+    HCI_LMP_ERROR_TRANSACTION_COLLISION	= 0x23,
+    HCI_LMP_PDU_NOT_ALLOWED		= 0x24,
+    HCI_ENCRYPTION_MODE_NOT_ACCEPTED	= 0x25,
+    HCI_UNIT_LINK_KEY_USED		= 0x26,
+    HCI_QOS_NOT_SUPPORTED		= 0x27,
+    HCI_INSTANT_PASSED			= 0x28,
+    HCI_PAIRING_NOT_SUPPORTED		= 0x29,
+    HCI_TRANSACTION_COLLISION		= 0x2a,
+    HCI_QOS_UNACCEPTABLE_PARAMETER	= 0x2c,
+    HCI_QOS_REJECTED			= 0x2d,
+    HCI_CLASSIFICATION_NOT_SUPPORTED	= 0x2e,
+    HCI_INSUFFICIENT_SECURITY		= 0x2f,
+    HCI_PARAMETER_OUT_OF_RANGE		= 0x30,
+    HCI_ROLE_SWITCH_PENDING		= 0x32,
+    HCI_SLOT_VIOLATION			= 0x34,
+    HCI_ROLE_SWITCH_FAILED		= 0x35,
+};
+
+enum acl_flag_bits {
+    ACL_CONT		= 1 << 0,
+    ACL_START		= 1 << 1,
+    ACL_ACTIVE_BCAST	= 1 << 2,
+    ACL_PICO_BCAST	= 1 << 3,
+};
+
+enum baseband_link_type {
+    SCO_LINK		= 0x00,
+    ACL_LINK		= 0x01,
+};
+
+enum lmp_feature_bits0 {
+    LMP_3SLOT		= 1 << 0,
+    LMP_5SLOT		= 1 << 1,
+    LMP_ENCRYPT		= 1 << 2,
+    LMP_SOFFSET		= 1 << 3,
+    LMP_TACCURACY	= 1 << 4,
+    LMP_RSWITCH		= 1 << 5,
+    LMP_HOLD_MODE	= 1 << 6,
+    LMP_SNIFF_MODE	= 1 << 7,
+};
+
+enum lmp_feature_bits1 {
+    LMP_PARK		= 1 << 0,
+    LMP_RSSI		= 1 << 1,
+    LMP_QUALITY		= 1 << 2,
+    LMP_SCO		= 1 << 3,
+    LMP_HV2		= 1 << 4,
+    LMP_HV3		= 1 << 5,
+    LMP_ULAW		= 1 << 6,
+    LMP_ALAW		= 1 << 7,
+};
+
+enum lmp_feature_bits2 {
+    LMP_CVSD		= 1 << 0,
+    LMP_PSCHEME		= 1 << 1,
+    LMP_PCONTROL	= 1 << 2,
+    LMP_TRSP_SCO	= 1 << 3,
+    LMP_BCAST_ENC	= 1 << 7,
+};
+
+enum lmp_feature_bits3 {
+    LMP_EDR_ACL_2M	= 1 << 1,
+    LMP_EDR_ACL_3M	= 1 << 2,
+    LMP_ENH_ISCAN	= 1 << 3,
+    LMP_ILACE_ISCAN	= 1 << 4,
+    LMP_ILACE_PSCAN	= 1 << 5,
+    LMP_RSSI_INQ	= 1 << 6,
+    LMP_ESCO		= 1 << 7,
+};
+
+enum lmp_feature_bits4 {
+    LMP_EV4		= 1 << 0,
+    LMP_EV5		= 1 << 1,
+    LMP_AFH_CAP_SLV	= 1 << 3,
+    LMP_AFH_CLS_SLV	= 1 << 4,
+    LMP_EDR_3SLOT	= 1 << 7,
+};
+
+enum lmp_feature_bits5 {
+    LMP_EDR_5SLOT	= 1 << 0,
+    LMP_SNIFF_SUBR	= 1 << 1,
+    LMP_AFH_CAP_MST	= 1 << 3,
+    LMP_AFH_CLS_MST	= 1 << 4,
+    LMP_EDR_ESCO_2M	= 1 << 5,
+    LMP_EDR_ESCO_3M	= 1 << 6,
+    LMP_EDR_3S_ESCO	= 1 << 7,
+};
+
+enum lmp_feature_bits6 {
+    LMP_EXT_INQ		= 1 << 0,
+};
+
+enum lmp_feature_bits7 {
+    LMP_EXT_FEAT	= 1 << 7,
+};
+
+enum hci_link_policy {
+    HCI_LP_RSWITCH	= 1 << 0,
+    HCI_LP_HOLD		= 1 << 1,
+    HCI_LP_SNIFF	= 1 << 2,
+    HCI_LP_PARK		= 1 << 3,
+};
+
+enum hci_link_mode {
+    HCI_LM_ACCEPT	= 1 << 15,
+    HCI_LM_MASTER	= 1 << 0,
+    HCI_LM_AUTH		= 1 << 1,
+    HCI_LM_ENCRYPT	= 1 << 2,
+    HCI_LM_TRUSTED	= 1 << 3,
+    HCI_LM_RELIABLE	= 1 << 4,
+    HCI_LM_SECURE	= 1 << 5,
+};
+
+/* HCI Commands */
+
+/* Link Control */
+#define OGF_LINK_CTL		0x01
+
+#define OCF_INQUIRY			0x0001
+typedef struct {
+    uint8_t	lap[3];
+    uint8_t	length;		/* 1.28s units */
+    uint8_t	num_rsp;
+} __attribute__ ((packed)) inquiry_cp;
+#define INQUIRY_CP_SIZE 5
+
+typedef struct {
+    uint8_t		status;
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) status_bdaddr_rp;
+#define STATUS_BDADDR_RP_SIZE 7
+
+#define OCF_INQUIRY_CANCEL		0x0002
+
+#define OCF_PERIODIC_INQUIRY		0x0003
+typedef struct {
+    uint16_t	max_period;	/* 1.28s units */
+    uint16_t	min_period;	/* 1.28s units */
+    uint8_t	lap[3];
+    uint8_t	length;		/* 1.28s units */
+    uint8_t	num_rsp;
+} __attribute__ ((packed)) periodic_inquiry_cp;
+#define PERIODIC_INQUIRY_CP_SIZE 9
+
+#define OCF_EXIT_PERIODIC_INQUIRY	0x0004
+
+#define OCF_CREATE_CONN			0x0005
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint16_t	pkt_type;
+    uint8_t	pscan_rep_mode;
+    uint8_t	pscan_mode;
+    uint16_t	clock_offset;
+    uint8_t	role_switch;
+} __attribute__ ((packed)) create_conn_cp;
+#define CREATE_CONN_CP_SIZE 13
+
+#define OCF_DISCONNECT			0x0006
+typedef struct {
+    uint16_t	handle;
+    uint8_t	reason;
+} __attribute__ ((packed)) disconnect_cp;
+#define DISCONNECT_CP_SIZE 3
+
+#define OCF_ADD_SCO			0x0007
+typedef struct {
+    uint16_t	handle;
+    uint16_t	pkt_type;
+} __attribute__ ((packed)) add_sco_cp;
+#define ADD_SCO_CP_SIZE 4
+
+#define OCF_CREATE_CONN_CANCEL		0x0008
+typedef struct {
+    uint8_t	status;
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) create_conn_cancel_cp;
+#define CREATE_CONN_CANCEL_CP_SIZE 6
+
+typedef struct {
+    uint8_t	status;
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) create_conn_cancel_rp;
+#define CREATE_CONN_CANCEL_RP_SIZE 7
+
+#define OCF_ACCEPT_CONN_REQ		0x0009
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	role;
+} __attribute__ ((packed)) accept_conn_req_cp;
+#define ACCEPT_CONN_REQ_CP_SIZE	7
+
+#define OCF_REJECT_CONN_REQ		0x000A
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	reason;
+} __attribute__ ((packed)) reject_conn_req_cp;
+#define REJECT_CONN_REQ_CP_SIZE	7
+
+#define OCF_LINK_KEY_REPLY		0x000B
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	link_key[16];
+} __attribute__ ((packed)) link_key_reply_cp;
+#define LINK_KEY_REPLY_CP_SIZE 22
+
+#define OCF_LINK_KEY_NEG_REPLY		0x000C
+
+#define OCF_PIN_CODE_REPLY		0x000D
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	pin_len;
+    uint8_t	pin_code[16];
+} __attribute__ ((packed)) pin_code_reply_cp;
+#define PIN_CODE_REPLY_CP_SIZE 23
+
+#define OCF_PIN_CODE_NEG_REPLY		0x000E
+
+#define OCF_SET_CONN_PTYPE		0x000F
+typedef struct {
+    uint16_t	 handle;
+    uint16_t	 pkt_type;
+} __attribute__ ((packed)) set_conn_ptype_cp;
+#define SET_CONN_PTYPE_CP_SIZE 4
+
+#define OCF_AUTH_REQUESTED		0x0011
+typedef struct {
+    uint16_t	 handle;
+} __attribute__ ((packed)) auth_requested_cp;
+#define AUTH_REQUESTED_CP_SIZE 2
+
+#define OCF_SET_CONN_ENCRYPT		0x0013
+typedef struct {
+    uint16_t	handle;
+    uint8_t	encrypt;
+} __attribute__ ((packed)) set_conn_encrypt_cp;
+#define SET_CONN_ENCRYPT_CP_SIZE 3
+
+#define OCF_CHANGE_CONN_LINK_KEY	0x0015
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) change_conn_link_key_cp;
+#define CHANGE_CONN_LINK_KEY_CP_SIZE 2
+
+#define OCF_MASTER_LINK_KEY		0x0017
+typedef struct {
+    uint8_t	key_flag;
+} __attribute__ ((packed)) master_link_key_cp;
+#define MASTER_LINK_KEY_CP_SIZE 1
+
+#define OCF_REMOTE_NAME_REQ		0x0019
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	pscan_rep_mode;
+    uint8_t	pscan_mode;
+    uint16_t	clock_offset;
+} __attribute__ ((packed)) remote_name_req_cp;
+#define REMOTE_NAME_REQ_CP_SIZE 10
+
+#define OCF_REMOTE_NAME_REQ_CANCEL	0x001A
+typedef struct {
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) remote_name_req_cancel_cp;
+#define REMOTE_NAME_REQ_CANCEL_CP_SIZE 6
+
+typedef struct {
+    uint8_t		status;
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) remote_name_req_cancel_rp;
+#define REMOTE_NAME_REQ_CANCEL_RP_SIZE 7
+
+#define OCF_READ_REMOTE_FEATURES	0x001B
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) read_remote_features_cp;
+#define READ_REMOTE_FEATURES_CP_SIZE 2
+
+#define OCF_READ_REMOTE_EXT_FEATURES	0x001C
+typedef struct {
+    uint16_t	handle;
+    uint8_t	page_num;
+} __attribute__ ((packed)) read_remote_ext_features_cp;
+#define READ_REMOTE_EXT_FEATURES_CP_SIZE 3
+
+#define OCF_READ_REMOTE_VERSION		0x001D
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) read_remote_version_cp;
+#define READ_REMOTE_VERSION_CP_SIZE 2
+
+#define OCF_READ_CLOCK_OFFSET		0x001F
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) read_clock_offset_cp;
+#define READ_CLOCK_OFFSET_CP_SIZE 2
+
+#define OCF_READ_LMP_HANDLE		0x0020
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) read_lmp_handle_cp;
+#define READ_LMP_HANDLE_CP_SIZE 2
+
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	lmp_handle;
+    uint32_t	reserved;
+} __attribute__ ((packed)) read_lmp_handle_rp;
+#define READ_LMP_HANDLE_RP_SIZE 8
+
+#define OCF_SETUP_SYNC_CONN		0x0028
+typedef struct {
+    uint16_t	handle;
+    uint32_t	tx_bandwith;
+    uint32_t	rx_bandwith;
+    uint16_t	max_latency;
+    uint16_t	voice_setting;
+    uint8_t	retrans_effort;
+    uint16_t	pkt_type;
+} __attribute__ ((packed)) setup_sync_conn_cp;
+#define SETUP_SYNC_CONN_CP_SIZE 17
+
+#define OCF_ACCEPT_SYNC_CONN_REQ	0x0029
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint32_t	tx_bandwith;
+    uint32_t	rx_bandwith;
+    uint16_t	max_latency;
+    uint16_t	voice_setting;
+    uint8_t	retrans_effort;
+    uint16_t	pkt_type;
+} __attribute__ ((packed)) accept_sync_conn_req_cp;
+#define ACCEPT_SYNC_CONN_REQ_CP_SIZE 21
+
+#define OCF_REJECT_SYNC_CONN_REQ	0x002A
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	reason;
+} __attribute__ ((packed)) reject_sync_conn_req_cp;
+#define REJECT_SYNC_CONN_REQ_CP_SIZE 7
+
+/* Link Policy */
+#define OGF_LINK_POLICY		0x02
+
+#define OCF_HOLD_MODE			0x0001
+typedef struct {
+    uint16_t	handle;
+    uint16_t	max_interval;
+    uint16_t	min_interval;
+} __attribute__ ((packed)) hold_mode_cp;
+#define HOLD_MODE_CP_SIZE 6
+
+#define OCF_SNIFF_MODE			0x0003
+typedef struct {
+    uint16_t	handle;
+    uint16_t	max_interval;
+    uint16_t	min_interval;
+    uint16_t	attempt;
+    uint16_t	timeout;
+} __attribute__ ((packed)) sniff_mode_cp;
+#define SNIFF_MODE_CP_SIZE 10
+
+#define OCF_EXIT_SNIFF_MODE		0x0004
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) exit_sniff_mode_cp;
+#define EXIT_SNIFF_MODE_CP_SIZE 2
+
+#define OCF_PARK_MODE			0x0005
+typedef struct {
+    uint16_t	handle;
+    uint16_t	max_interval;
+    uint16_t	min_interval;
+} __attribute__ ((packed)) park_mode_cp;
+#define PARK_MODE_CP_SIZE 6
+
+#define OCF_EXIT_PARK_MODE		0x0006
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) exit_park_mode_cp;
+#define EXIT_PARK_MODE_CP_SIZE 2
+
+#define OCF_QOS_SETUP			0x0007
+typedef struct {
+    uint8_t	service_type;		/* 1 = best effort */
+    uint32_t	token_rate;		/* Byte per seconds */
+    uint32_t	peak_bandwidth;		/* Byte per seconds */
+    uint32_t	latency;		/* Microseconds */
+    uint32_t	delay_variation;	/* Microseconds */
+} __attribute__ ((packed)) hci_qos;
+#define HCI_QOS_CP_SIZE 17
+typedef struct {
+    uint16_t 	handle;
+    uint8_t 	flags;			/* Reserved */
+    hci_qos 	qos;
+} __attribute__ ((packed)) qos_setup_cp;
+#define QOS_SETUP_CP_SIZE (3 + HCI_QOS_CP_SIZE)
+
+#define OCF_ROLE_DISCOVERY		0x0009
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) role_discovery_cp;
+#define ROLE_DISCOVERY_CP_SIZE 2
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	role;
+} __attribute__ ((packed)) role_discovery_rp;
+#define ROLE_DISCOVERY_RP_SIZE 4
+
+#define OCF_SWITCH_ROLE			0x000B
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	role;
+} __attribute__ ((packed)) switch_role_cp;
+#define SWITCH_ROLE_CP_SIZE 7
+
+#define OCF_READ_LINK_POLICY		0x000C
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) read_link_policy_cp;
+#define READ_LINK_POLICY_CP_SIZE 2
+typedef struct {
+    uint8_t 	status;
+    uint16_t	handle;
+    uint16_t	policy;
+} __attribute__ ((packed)) read_link_policy_rp;
+#define READ_LINK_POLICY_RP_SIZE 5
+
+#define OCF_WRITE_LINK_POLICY		0x000D
+typedef struct {
+    uint16_t	handle;
+    uint16_t	policy;
+} __attribute__ ((packed)) write_link_policy_cp;
+#define WRITE_LINK_POLICY_CP_SIZE 4
+typedef struct {
+    uint8_t 	status;
+    uint16_t	handle;
+} __attribute__ ((packed)) write_link_policy_rp;
+#define WRITE_LINK_POLICY_RP_SIZE 3
+
+#define OCF_READ_DEFAULT_LINK_POLICY	0x000E
+
+#define OCF_WRITE_DEFAULT_LINK_POLICY	0x000F
+
+#define OCF_FLOW_SPECIFICATION		0x0010
+
+#define OCF_SNIFF_SUBRATE		0x0011
+typedef struct {
+    uint16_t	handle;
+    uint16_t	max_remote_latency;
+    uint16_t	max_local_latency;
+    uint16_t	min_remote_timeout;
+    uint16_t	min_local_timeout;
+} __attribute__ ((packed)) sniff_subrate_cp;
+#define SNIFF_SUBRATE_CP_SIZE 10
+
+/* Host Controller and Baseband */
+#define OGF_HOST_CTL		0x03
+
+#define OCF_SET_EVENT_MASK		0x0001
+typedef struct {
+    uint8_t	mask[8];
+} __attribute__ ((packed)) set_event_mask_cp;
+#define SET_EVENT_MASK_CP_SIZE 8
+
+#define OCF_RESET			0x0003
+
+#define OCF_SET_EVENT_FLT		0x0005
+typedef struct {
+    uint8_t	flt_type;
+    uint8_t	cond_type;
+    uint8_t	condition[0];
+} __attribute__ ((packed)) set_event_flt_cp;
+#define SET_EVENT_FLT_CP_SIZE 2
+
+enum bt_filter_type {
+    FLT_CLEAR_ALL		= 0x00,
+    FLT_INQ_RESULT		= 0x01,
+    FLT_CONN_SETUP		= 0x02,
+};
+enum inq_result_cond_type {
+    INQ_RESULT_RETURN_ALL	= 0x00,
+    INQ_RESULT_RETURN_CLASS	= 0x01,
+    INQ_RESULT_RETURN_BDADDR	= 0x02,
+};
+enum conn_setup_cond_type {
+    CONN_SETUP_ALLOW_ALL	= 0x00,
+    CONN_SETUP_ALLOW_CLASS	= 0x01,
+    CONN_SETUP_ALLOW_BDADDR	= 0x02,
+};
+enum conn_setup_cond {
+    CONN_SETUP_AUTO_OFF		= 0x01,
+    CONN_SETUP_AUTO_ON		= 0x02,
+};
+
+#define OCF_FLUSH			0x0008
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) flush_cp;
+#define FLUSH_CP_SIZE 2
+
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+} __attribute__ ((packed)) flush_rp;
+#define FLUSH_RP_SIZE 3
+
+#define OCF_READ_PIN_TYPE		0x0009
+typedef struct {
+    uint8_t	status;
+    uint8_t	pin_type;
+} __attribute__ ((packed)) read_pin_type_rp;
+#define READ_PIN_TYPE_RP_SIZE 2
+
+#define OCF_WRITE_PIN_TYPE		0x000A
+typedef struct {
+    uint8_t	pin_type;
+} __attribute__ ((packed)) write_pin_type_cp;
+#define WRITE_PIN_TYPE_CP_SIZE 1
+
+#define OCF_CREATE_NEW_UNIT_KEY		0x000B
+
+#define OCF_READ_STORED_LINK_KEY	0x000D
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	read_all;
+} __attribute__ ((packed)) read_stored_link_key_cp;
+#define READ_STORED_LINK_KEY_CP_SIZE 7
+typedef struct {
+    uint8_t	status;
+    uint16_t	max_keys;
+    uint16_t	num_keys;
+} __attribute__ ((packed)) read_stored_link_key_rp;
+#define READ_STORED_LINK_KEY_RP_SIZE 5
+
+#define OCF_WRITE_STORED_LINK_KEY	0x0011
+typedef struct {
+    uint8_t	num_keys;
+    /* variable length part */
+} __attribute__ ((packed)) write_stored_link_key_cp;
+#define WRITE_STORED_LINK_KEY_CP_SIZE 1
+typedef struct {
+    uint8_t	status;
+    uint8_t	num_keys;
+} __attribute__ ((packed)) write_stored_link_key_rp;
+#define READ_WRITE_LINK_KEY_RP_SIZE 2
+
+#define OCF_DELETE_STORED_LINK_KEY	0x0012
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	delete_all;
+} __attribute__ ((packed)) delete_stored_link_key_cp;
+#define DELETE_STORED_LINK_KEY_CP_SIZE 7
+typedef struct {
+    uint8_t	status;
+    uint16_t	num_keys;
+} __attribute__ ((packed)) delete_stored_link_key_rp;
+#define DELETE_STORED_LINK_KEY_RP_SIZE 3
+
+#define OCF_CHANGE_LOCAL_NAME		0x0013
+typedef struct {
+    char	name[248];
+} __attribute__ ((packed)) change_local_name_cp;
+#define CHANGE_LOCAL_NAME_CP_SIZE 248 
+
+#define OCF_READ_LOCAL_NAME		0x0014
+typedef struct {
+    uint8_t	status;
+    char	name[248];
+} __attribute__ ((packed)) read_local_name_rp;
+#define READ_LOCAL_NAME_RP_SIZE 249 
+
+#define OCF_READ_CONN_ACCEPT_TIMEOUT	0x0015
+typedef struct {
+    uint8_t	status;
+    uint16_t	timeout;
+} __attribute__ ((packed)) read_conn_accept_timeout_rp;
+#define READ_CONN_ACCEPT_TIMEOUT_RP_SIZE 3
+
+#define OCF_WRITE_CONN_ACCEPT_TIMEOUT	0x0016
+typedef struct {
+    uint16_t	timeout;
+} __attribute__ ((packed)) write_conn_accept_timeout_cp;
+#define WRITE_CONN_ACCEPT_TIMEOUT_CP_SIZE 2
+
+#define OCF_READ_PAGE_TIMEOUT		0x0017
+typedef struct {
+    uint8_t	status;
+    uint16_t	timeout;
+} __attribute__ ((packed)) read_page_timeout_rp;
+#define READ_PAGE_TIMEOUT_RP_SIZE 3
+
+#define OCF_WRITE_PAGE_TIMEOUT		0x0018
+typedef struct {
+    uint16_t	timeout;
+} __attribute__ ((packed)) write_page_timeout_cp;
+#define WRITE_PAGE_TIMEOUT_CP_SIZE 2
+
+#define OCF_READ_SCAN_ENABLE		0x0019
+typedef struct {
+    uint8_t	status;
+    uint8_t	enable;
+} __attribute__ ((packed)) read_scan_enable_rp;
+#define READ_SCAN_ENABLE_RP_SIZE 2
+
+#define OCF_WRITE_SCAN_ENABLE		0x001A
+typedef struct {
+    uint8_t	scan_enable;
+} __attribute__ ((packed)) write_scan_enable_cp;
+#define WRITE_SCAN_ENABLE_CP_SIZE 1
+
+enum scan_enable_bits {
+    SCAN_DISABLED		= 0,
+    SCAN_INQUIRY		= 1 << 0,
+    SCAN_PAGE			= 1 << 1,
+};
+
+#define OCF_READ_PAGE_ACTIVITY		0x001B
+typedef struct {
+    uint8_t	status;
+    uint16_t	interval;
+    uint16_t	window;
+} __attribute__ ((packed)) read_page_activity_rp;
+#define READ_PAGE_ACTIVITY_RP_SIZE 5
+
+#define OCF_WRITE_PAGE_ACTIVITY		0x001C
+typedef struct {
+    uint16_t	interval;
+    uint16_t	window;
+} __attribute__ ((packed)) write_page_activity_cp;
+#define WRITE_PAGE_ACTIVITY_CP_SIZE 4
+
+#define OCF_READ_INQ_ACTIVITY		0x001D
+typedef struct {
+    uint8_t	status;
+    uint16_t	interval;
+    uint16_t	window;
+} __attribute__ ((packed)) read_inq_activity_rp;
+#define READ_INQ_ACTIVITY_RP_SIZE 5
+
+#define OCF_WRITE_INQ_ACTIVITY		0x001E
+typedef struct {
+    uint16_t	interval;
+    uint16_t	window;
+} __attribute__ ((packed)) write_inq_activity_cp;
+#define WRITE_INQ_ACTIVITY_CP_SIZE 4
+
+#define OCF_READ_AUTH_ENABLE		0x001F
+
+#define OCF_WRITE_AUTH_ENABLE		0x0020
+
+#define AUTH_DISABLED		0x00
+#define AUTH_ENABLED		0x01
+
+#define OCF_READ_ENCRYPT_MODE		0x0021
+
+#define OCF_WRITE_ENCRYPT_MODE		0x0022
+
+#define ENCRYPT_DISABLED	0x00
+#define ENCRYPT_P2P		0x01
+#define ENCRYPT_BOTH		0x02
+
+#define OCF_READ_CLASS_OF_DEV		0x0023
+typedef struct {
+    uint8_t	status;
+    uint8_t	dev_class[3];
+} __attribute__ ((packed)) read_class_of_dev_rp;
+#define READ_CLASS_OF_DEV_RP_SIZE 4 
+
+#define OCF_WRITE_CLASS_OF_DEV		0x0024
+typedef struct {
+    uint8_t	dev_class[3];
+} __attribute__ ((packed)) write_class_of_dev_cp;
+#define WRITE_CLASS_OF_DEV_CP_SIZE 3
+
+#define OCF_READ_VOICE_SETTING		0x0025
+typedef struct {
+    uint8_t	status;
+    uint16_t	voice_setting;
+} __attribute__ ((packed)) read_voice_setting_rp;
+#define READ_VOICE_SETTING_RP_SIZE 3
+
+#define OCF_WRITE_VOICE_SETTING		0x0026
+typedef struct {
+    uint16_t	voice_setting;
+} __attribute__ ((packed)) write_voice_setting_cp;
+#define WRITE_VOICE_SETTING_CP_SIZE 2
+
+#define OCF_READ_AUTOMATIC_FLUSH_TIMEOUT	0x0027
+
+#define OCF_WRITE_AUTOMATIC_FLUSH_TIMEOUT	0x0028
+
+#define OCF_READ_NUM_BROADCAST_RETRANS	0x0029
+
+#define OCF_WRITE_NUM_BROADCAST_RETRANS	0x002A
+
+#define OCF_READ_HOLD_MODE_ACTIVITY	0x002B
+
+#define OCF_WRITE_HOLD_MODE_ACTIVITY	0x002C
+
+#define OCF_READ_TRANSMIT_POWER_LEVEL	0x002D
+typedef struct {
+    uint16_t	handle;
+    uint8_t	type;
+} __attribute__ ((packed)) read_transmit_power_level_cp;
+#define READ_TRANSMIT_POWER_LEVEL_CP_SIZE 3
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    int8_t	level;
+} __attribute__ ((packed)) read_transmit_power_level_rp;
+#define READ_TRANSMIT_POWER_LEVEL_RP_SIZE 4
+
+#define OCF_HOST_BUFFER_SIZE		0x0033
+typedef struct {
+    uint16_t	acl_mtu;
+    uint8_t	sco_mtu;
+    uint16_t	acl_max_pkt;
+    uint16_t	sco_max_pkt;
+} __attribute__ ((packed)) host_buffer_size_cp;
+#define HOST_BUFFER_SIZE_CP_SIZE 7
+
+#define OCF_HOST_NUMBER_OF_COMPLETED_PACKETS	0x0035
+
+#define OCF_READ_LINK_SUPERVISION_TIMEOUT	0x0036
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint16_t	link_sup_to;
+} __attribute__ ((packed)) read_link_supervision_timeout_rp;
+#define READ_LINK_SUPERVISION_TIMEOUT_RP_SIZE 5
+
+#define OCF_WRITE_LINK_SUPERVISION_TIMEOUT	0x0037
+typedef struct {
+    uint16_t	handle;
+    uint16_t	link_sup_to;
+} __attribute__ ((packed)) write_link_supervision_timeout_cp;
+#define WRITE_LINK_SUPERVISION_TIMEOUT_CP_SIZE 4
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+} __attribute__ ((packed)) write_link_supervision_timeout_rp;
+#define WRITE_LINK_SUPERVISION_TIMEOUT_RP_SIZE 3
+
+#define OCF_READ_NUM_SUPPORTED_IAC	0x0038
+
+#define MAX_IAC_LAP 0x40
+#define OCF_READ_CURRENT_IAC_LAP	0x0039
+typedef struct {
+    uint8_t	status;
+    uint8_t	num_current_iac;
+    uint8_t	lap[MAX_IAC_LAP][3];
+} __attribute__ ((packed)) read_current_iac_lap_rp;
+#define READ_CURRENT_IAC_LAP_RP_SIZE 2+3*MAX_IAC_LAP
+
+#define OCF_WRITE_CURRENT_IAC_LAP	0x003A
+typedef struct {
+    uint8_t	num_current_iac;
+    uint8_t	lap[MAX_IAC_LAP][3];
+} __attribute__ ((packed)) write_current_iac_lap_cp;
+#define WRITE_CURRENT_IAC_LAP_CP_SIZE 1+3*MAX_IAC_LAP
+
+#define OCF_READ_PAGE_SCAN_PERIOD_MODE	0x003B
+
+#define OCF_WRITE_PAGE_SCAN_PERIOD_MODE	0x003C
+
+#define OCF_READ_PAGE_SCAN_MODE		0x003D
+
+#define OCF_WRITE_PAGE_SCAN_MODE	0x003E
+
+#define OCF_SET_AFH_CLASSIFICATION	0x003F
+typedef struct {
+    uint8_t	map[10];
+} __attribute__ ((packed)) set_afh_classification_cp;
+#define SET_AFH_CLASSIFICATION_CP_SIZE 10
+typedef struct {
+    uint8_t	status;
+} __attribute__ ((packed)) set_afh_classification_rp;
+#define SET_AFH_CLASSIFICATION_RP_SIZE 1
+
+#define OCF_READ_INQUIRY_SCAN_TYPE	0x0042
+typedef struct {
+    uint8_t	status;
+    uint8_t	type;
+} __attribute__ ((packed)) read_inquiry_scan_type_rp;
+#define READ_INQUIRY_SCAN_TYPE_RP_SIZE 2
+
+#define OCF_WRITE_INQUIRY_SCAN_TYPE	0x0043
+typedef struct {
+    uint8_t	type;
+} __attribute__ ((packed)) write_inquiry_scan_type_cp;
+#define WRITE_INQUIRY_SCAN_TYPE_CP_SIZE 1
+typedef struct {
+    uint8_t	status;
+} __attribute__ ((packed)) write_inquiry_scan_type_rp;
+#define WRITE_INQUIRY_SCAN_TYPE_RP_SIZE 1
+
+#define OCF_READ_INQUIRY_MODE		0x0044
+typedef struct {
+    uint8_t	status;
+    uint8_t	mode;
+} __attribute__ ((packed)) read_inquiry_mode_rp;
+#define READ_INQUIRY_MODE_RP_SIZE 2
+
+#define OCF_WRITE_INQUIRY_MODE		0x0045
+typedef struct {
+    uint8_t	mode;
+} __attribute__ ((packed)) write_inquiry_mode_cp;
+#define WRITE_INQUIRY_MODE_CP_SIZE 1
+typedef struct {
+    uint8_t	status;
+} __attribute__ ((packed)) write_inquiry_mode_rp;
+#define WRITE_INQUIRY_MODE_RP_SIZE 1
+
+#define OCF_READ_PAGE_SCAN_TYPE		0x0046
+
+#define OCF_WRITE_PAGE_SCAN_TYPE	0x0047
+
+#define OCF_READ_AFH_MODE		0x0048
+typedef struct {
+    uint8_t	status;
+    uint8_t	mode;
+} __attribute__ ((packed)) read_afh_mode_rp;
+#define READ_AFH_MODE_RP_SIZE 2
+
+#define OCF_WRITE_AFH_MODE		0x0049
+typedef struct {
+    uint8_t	mode;
+} __attribute__ ((packed)) write_afh_mode_cp;
+#define WRITE_AFH_MODE_CP_SIZE 1
+typedef struct {
+    uint8_t	status;
+} __attribute__ ((packed)) write_afh_mode_rp;
+#define WRITE_AFH_MODE_RP_SIZE 1
+
+#define OCF_READ_EXT_INQUIRY_RESPONSE	0x0051
+typedef struct {
+    uint8_t	status;
+    uint8_t	fec;
+    uint8_t	data[240];
+} __attribute__ ((packed)) read_ext_inquiry_response_rp;
+#define READ_EXT_INQUIRY_RESPONSE_RP_SIZE 242
+
+#define OCF_WRITE_EXT_INQUIRY_RESPONSE	0x0052
+typedef struct {
+    uint8_t	fec;
+    uint8_t	data[240];
+} __attribute__ ((packed)) write_ext_inquiry_response_cp;
+#define WRITE_EXT_INQUIRY_RESPONSE_CP_SIZE 241
+typedef struct {
+    uint8_t	status;
+} __attribute__ ((packed)) write_ext_inquiry_response_rp;
+#define WRITE_EXT_INQUIRY_RESPONSE_RP_SIZE 1
+
+/* Informational Parameters */
+#define OGF_INFO_PARAM		0x04
+
+#define OCF_READ_LOCAL_VERSION		0x0001
+typedef struct {
+    uint8_t	status;
+    uint8_t	hci_ver;
+    uint16_t	hci_rev;
+    uint8_t	lmp_ver;
+    uint16_t	manufacturer;
+    uint16_t	lmp_subver;
+} __attribute__ ((packed)) read_local_version_rp;
+#define READ_LOCAL_VERSION_RP_SIZE 9
+
+#define OCF_READ_LOCAL_COMMANDS		0x0002
+typedef struct {
+    uint8_t	status;
+    uint8_t	commands[64];
+} __attribute__ ((packed)) read_local_commands_rp;
+#define READ_LOCAL_COMMANDS_RP_SIZE 65
+
+#define OCF_READ_LOCAL_FEATURES		0x0003
+typedef struct {
+    uint8_t	status;
+    uint8_t	features[8];
+} __attribute__ ((packed)) read_local_features_rp;
+#define READ_LOCAL_FEATURES_RP_SIZE 9
+
+#define OCF_READ_LOCAL_EXT_FEATURES	0x0004
+typedef struct {
+    uint8_t	page_num;
+} __attribute__ ((packed)) read_local_ext_features_cp;
+#define READ_LOCAL_EXT_FEATURES_CP_SIZE 1
+typedef struct {
+    uint8_t	status;
+    uint8_t	page_num;
+    uint8_t	max_page_num;
+    uint8_t	features[8];
+} __attribute__ ((packed)) read_local_ext_features_rp;
+#define READ_LOCAL_EXT_FEATURES_RP_SIZE 11
+
+#define OCF_READ_BUFFER_SIZE		0x0005
+typedef struct {
+    uint8_t	status;
+    uint16_t	acl_mtu;
+    uint8_t	sco_mtu;
+    uint16_t	acl_max_pkt;
+    uint16_t	sco_max_pkt;
+} __attribute__ ((packed)) read_buffer_size_rp;
+#define READ_BUFFER_SIZE_RP_SIZE 8
+
+#define OCF_READ_COUNTRY_CODE		0x0007
+typedef struct {
+    uint8_t	status;
+    uint8_t	country_code;
+} __attribute__ ((packed)) read_country_code_rp;
+#define READ_COUNTRY_CODE_RP_SIZE 2
+
+#define OCF_READ_BD_ADDR		0x0009
+typedef struct {
+    uint8_t	status;
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) read_bd_addr_rp;
+#define READ_BD_ADDR_RP_SIZE 7
+
+/* Status params */
+#define OGF_STATUS_PARAM	0x05
+
+#define OCF_READ_FAILED_CONTACT_COUNTER		0x0001
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	counter;
+} __attribute__ ((packed)) read_failed_contact_counter_rp;
+#define READ_FAILED_CONTACT_COUNTER_RP_SIZE 4
+
+#define OCF_RESET_FAILED_CONTACT_COUNTER	0x0002
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+} __attribute__ ((packed)) reset_failed_contact_counter_rp;
+#define RESET_FAILED_CONTACT_COUNTER_RP_SIZE 4
+
+#define OCF_READ_LINK_QUALITY		0x0003
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) read_link_quality_cp;
+#define READ_LINK_QUALITY_CP_SIZE 4
+
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	link_quality;
+} __attribute__ ((packed)) read_link_quality_rp;
+#define READ_LINK_QUALITY_RP_SIZE 4
+
+#define OCF_READ_RSSI			0x0005
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    int8_t	rssi;
+} __attribute__ ((packed)) read_rssi_rp;
+#define READ_RSSI_RP_SIZE 4
+
+#define OCF_READ_AFH_MAP		0x0006
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	mode;
+    uint8_t	map[10];
+} __attribute__ ((packed)) read_afh_map_rp;
+#define READ_AFH_MAP_RP_SIZE 14
+
+#define OCF_READ_CLOCK			0x0007
+typedef struct {
+    uint16_t	handle;
+    uint8_t	which_clock;
+} __attribute__ ((packed)) read_clock_cp;
+#define READ_CLOCK_CP_SIZE 3
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint32_t	clock;
+    uint16_t	accuracy;
+} __attribute__ ((packed)) read_clock_rp;
+#define READ_CLOCK_RP_SIZE 9
+
+/* Testing commands */
+#define OGF_TESTING_CMD		0x3e
+
+/* Vendor specific commands */
+#define OGF_VENDOR_CMD		0x3f
+
+/* HCI Events */
+
+#define EVT_INQUIRY_COMPLETE		0x01
+
+#define EVT_INQUIRY_RESULT		0x02
+typedef struct {
+    uint8_t	num_responses;
+    bdaddr_t	bdaddr;
+    uint8_t	pscan_rep_mode;
+    uint8_t	pscan_period_mode;
+    uint8_t	pscan_mode;
+    uint8_t	dev_class[3];
+    uint16_t	clock_offset;
+} __attribute__ ((packed)) inquiry_info;
+#define INQUIRY_INFO_SIZE 14
+
+#define EVT_CONN_COMPLETE		0x03
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    bdaddr_t	bdaddr;
+    uint8_t	link_type;
+    uint8_t	encr_mode;
+} __attribute__ ((packed)) evt_conn_complete;
+#define EVT_CONN_COMPLETE_SIZE 11
+
+#define EVT_CONN_REQUEST		0x04
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	dev_class[3];
+    uint8_t	link_type;
+} __attribute__ ((packed)) evt_conn_request;
+#define EVT_CONN_REQUEST_SIZE 10
+
+#define EVT_DISCONN_COMPLETE		0x05
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	reason;
+} __attribute__ ((packed)) evt_disconn_complete;
+#define EVT_DISCONN_COMPLETE_SIZE 4
+
+#define EVT_AUTH_COMPLETE		0x06
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+} __attribute__ ((packed)) evt_auth_complete;
+#define EVT_AUTH_COMPLETE_SIZE 3
+
+#define EVT_REMOTE_NAME_REQ_COMPLETE	0x07
+typedef struct {
+    uint8_t	status;
+    bdaddr_t	bdaddr;
+    char	name[248];
+} __attribute__ ((packed)) evt_remote_name_req_complete;
+#define EVT_REMOTE_NAME_REQ_COMPLETE_SIZE 255
+
+#define EVT_ENCRYPT_CHANGE		0x08
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	encrypt;
+} __attribute__ ((packed)) evt_encrypt_change;
+#define EVT_ENCRYPT_CHANGE_SIZE 5
+
+#define EVT_CHANGE_CONN_LINK_KEY_COMPLETE	0x09
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+}  __attribute__ ((packed)) evt_change_conn_link_key_complete;
+#define EVT_CHANGE_CONN_LINK_KEY_COMPLETE_SIZE 3
+
+#define EVT_MASTER_LINK_KEY_COMPLETE		0x0A
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	key_flag;
+} __attribute__ ((packed)) evt_master_link_key_complete;
+#define EVT_MASTER_LINK_KEY_COMPLETE_SIZE 4
+
+#define EVT_READ_REMOTE_FEATURES_COMPLETE	0x0B
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	features[8];
+} __attribute__ ((packed)) evt_read_remote_features_complete;
+#define EVT_READ_REMOTE_FEATURES_COMPLETE_SIZE 11
+
+#define EVT_READ_REMOTE_VERSION_COMPLETE	0x0C
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	lmp_ver;
+    uint16_t	manufacturer;
+    uint16_t	lmp_subver;
+} __attribute__ ((packed)) evt_read_remote_version_complete;
+#define EVT_READ_REMOTE_VERSION_COMPLETE_SIZE 8
+
+#define EVT_QOS_SETUP_COMPLETE		0x0D
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	flags;			/* Reserved */
+    hci_qos	qos;
+} __attribute__ ((packed)) evt_qos_setup_complete;
+#define EVT_QOS_SETUP_COMPLETE_SIZE (4 + HCI_QOS_CP_SIZE)
+
+#define EVT_CMD_COMPLETE 		0x0E
+typedef struct {
+    uint8_t	ncmd;
+    uint16_t	opcode;
+} __attribute__ ((packed)) evt_cmd_complete;
+#define EVT_CMD_COMPLETE_SIZE 3
+
+#define EVT_CMD_STATUS 			0x0F
+typedef struct {
+    uint8_t	status;
+    uint8_t	ncmd;
+    uint16_t	opcode;
+} __attribute__ ((packed)) evt_cmd_status;
+#define EVT_CMD_STATUS_SIZE 4
+
+#define EVT_HARDWARE_ERROR		0x10
+typedef struct {
+    uint8_t	code;
+} __attribute__ ((packed)) evt_hardware_error;
+#define EVT_HARDWARE_ERROR_SIZE 1
+
+#define EVT_FLUSH_OCCURRED		0x11
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) evt_flush_occured;
+#define EVT_FLUSH_OCCURRED_SIZE 2
+
+#define EVT_ROLE_CHANGE			0x12
+typedef struct {
+    uint8_t	status;
+    bdaddr_t	bdaddr;
+    uint8_t	role;
+} __attribute__ ((packed)) evt_role_change;
+#define EVT_ROLE_CHANGE_SIZE 8
+
+#define EVT_NUM_COMP_PKTS		0x13
+typedef struct {
+    uint8_t	num_hndl;
+    struct {
+        uint16_t handle;
+        uint16_t num_packets;
+    } connection[0];
+} __attribute__ ((packed)) evt_num_comp_pkts;
+#define EVT_NUM_COMP_PKTS_SIZE(num_hndl) (1 + 4 * (num_hndl))
+
+#define EVT_MODE_CHANGE			0x14
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	mode;
+    uint16_t	interval;
+} __attribute__ ((packed)) evt_mode_change;
+#define EVT_MODE_CHANGE_SIZE 6
+
+#define EVT_RETURN_LINK_KEYS		0x15
+typedef struct {
+    uint8_t	num_keys;
+    /* variable length part */
+} __attribute__ ((packed)) evt_return_link_keys;
+#define EVT_RETURN_LINK_KEYS_SIZE 1
+
+#define EVT_PIN_CODE_REQ		0x16
+typedef struct {
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) evt_pin_code_req;
+#define EVT_PIN_CODE_REQ_SIZE 6
+
+#define EVT_LINK_KEY_REQ		0x17
+typedef struct {
+    bdaddr_t	bdaddr;
+} __attribute__ ((packed)) evt_link_key_req;
+#define EVT_LINK_KEY_REQ_SIZE 6
+
+#define EVT_LINK_KEY_NOTIFY		0x18
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	link_key[16];
+    uint8_t	key_type;
+} __attribute__ ((packed)) evt_link_key_notify;
+#define EVT_LINK_KEY_NOTIFY_SIZE 23
+
+#define EVT_LOOPBACK_COMMAND		0x19
+
+#define EVT_DATA_BUFFER_OVERFLOW	0x1A
+typedef struct {
+    uint8_t	link_type;
+} __attribute__ ((packed)) evt_data_buffer_overflow;
+#define EVT_DATA_BUFFER_OVERFLOW_SIZE 1
+
+#define EVT_MAX_SLOTS_CHANGE		0x1B
+typedef struct {
+    uint16_t	handle;
+    uint8_t	max_slots;
+} __attribute__ ((packed)) evt_max_slots_change;
+#define EVT_MAX_SLOTS_CHANGE_SIZE 3
+
+#define EVT_READ_CLOCK_OFFSET_COMPLETE	0x1C
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint16_t	clock_offset;
+} __attribute__ ((packed)) evt_read_clock_offset_complete;
+#define EVT_READ_CLOCK_OFFSET_COMPLETE_SIZE 5
+
+#define EVT_CONN_PTYPE_CHANGED		0x1D
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint16_t	ptype;
+} __attribute__ ((packed)) evt_conn_ptype_changed;
+#define EVT_CONN_PTYPE_CHANGED_SIZE 5
+
+#define EVT_QOS_VIOLATION		0x1E
+typedef struct {
+    uint16_t	handle;
+} __attribute__ ((packed)) evt_qos_violation;
+#define EVT_QOS_VIOLATION_SIZE 2
+
+#define EVT_PSCAN_REP_MODE_CHANGE	0x20
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	pscan_rep_mode;
+} __attribute__ ((packed)) evt_pscan_rep_mode_change;
+#define EVT_PSCAN_REP_MODE_CHANGE_SIZE 7
+
+#define EVT_FLOW_SPEC_COMPLETE		0x21
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	flags;
+    uint8_t	direction;
+    hci_qos	qos;
+} __attribute__ ((packed)) evt_flow_spec_complete;
+#define EVT_FLOW_SPEC_COMPLETE_SIZE (5 + HCI_QOS_CP_SIZE)
+
+#define EVT_INQUIRY_RESULT_WITH_RSSI	0x22
+typedef struct {
+    uint8_t	num_responses;
+    bdaddr_t	bdaddr;
+    uint8_t	pscan_rep_mode;
+    uint8_t	pscan_period_mode;
+    uint8_t	dev_class[3];
+    uint16_t	clock_offset;
+    int8_t	rssi;
+} __attribute__ ((packed)) inquiry_info_with_rssi;
+#define INQUIRY_INFO_WITH_RSSI_SIZE 15
+typedef struct {
+    uint8_t	num_responses;
+    bdaddr_t	bdaddr;
+    uint8_t	pscan_rep_mode;
+    uint8_t	pscan_period_mode;
+    uint8_t	pscan_mode;
+    uint8_t	dev_class[3];
+    uint16_t	clock_offset;
+    int8_t	rssi;
+} __attribute__ ((packed)) inquiry_info_with_rssi_and_pscan_mode;
+#define INQUIRY_INFO_WITH_RSSI_AND_PSCAN_MODE_SIZE 16
+
+#define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE	0x23
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	page_num;
+    uint8_t	max_page_num;
+    uint8_t	features[8];
+} __attribute__ ((packed)) evt_read_remote_ext_features_complete;
+#define EVT_READ_REMOTE_EXT_FEATURES_COMPLETE_SIZE 13
+
+#define EVT_SYNC_CONN_COMPLETE		0x2C
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    bdaddr_t	bdaddr;
+    uint8_t	link_type;
+    uint8_t	trans_interval;
+    uint8_t	retrans_window;
+    uint16_t	rx_pkt_len;
+    uint16_t	tx_pkt_len;
+    uint8_t	air_mode;
+} __attribute__ ((packed)) evt_sync_conn_complete;
+#define EVT_SYNC_CONN_COMPLETE_SIZE 17
+
+#define EVT_SYNC_CONN_CHANGED		0x2D
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint8_t	trans_interval;
+    uint8_t	retrans_window;
+    uint16_t	rx_pkt_len;
+    uint16_t	tx_pkt_len;
+} __attribute__ ((packed)) evt_sync_conn_changed;
+#define EVT_SYNC_CONN_CHANGED_SIZE 9
+
+#define EVT_SNIFF_SUBRATE		0x2E
+typedef struct {
+    uint8_t	status;
+    uint16_t	handle;
+    uint16_t	max_remote_latency;
+    uint16_t	max_local_latency;
+    uint16_t	min_remote_timeout;
+    uint16_t	min_local_timeout;
+} __attribute__ ((packed)) evt_sniff_subrate;
+#define EVT_SNIFF_SUBRATE_SIZE 11
+
+#define EVT_EXTENDED_INQUIRY_RESULT	0x2F
+typedef struct {
+    bdaddr_t	bdaddr;
+    uint8_t	pscan_rep_mode;
+    uint8_t	pscan_period_mode;
+    uint8_t	dev_class[3];
+    uint16_t	clock_offset;
+    int8_t	rssi;
+    uint8_t	data[240];
+} __attribute__ ((packed)) extended_inquiry_info;
+#define EXTENDED_INQUIRY_INFO_SIZE 254
+
+#define EVT_TESTING			0xFE
+
+#define EVT_VENDOR			0xFF
+
+/* Command opcode pack/unpack */
+#define cmd_opcode_pack(ogf, ocf)	(uint16_t)((ocf & 0x03ff)|(ogf << 10))
+#define cmd_opcode_ogf(op)		(op >> 10)
+#define cmd_opcode_ocf(op)		(op & 0x03ff)
+
+/* ACL handle and flags pack/unpack */
+#define acl_handle_pack(h, f)	(uint16_t)(((h) & 0x0fff)|((f) << 12))
+#define acl_handle(h)		((h) & 0x0fff)
+#define acl_flags(h)		((h) >> 12)
+
+/* HCI Packet structures */
+#define HCI_COMMAND_HDR_SIZE	3
+#define HCI_EVENT_HDR_SIZE	2
+#define HCI_ACL_HDR_SIZE	4
+#define HCI_SCO_HDR_SIZE	3
+
+struct hci_command_hdr {
+    uint16_t 	opcode;		/* OCF & OGF */
+    uint8_t	plen;
+} __attribute__ ((packed));
+
+struct hci_event_hdr {
+    uint8_t	evt;
+    uint8_t	plen;
+} __attribute__ ((packed));
+
+struct hci_acl_hdr {
+    uint16_t	handle;		/* Handle & Flags(PB, BC) */
+    uint16_t	dlen;
+} __attribute__ ((packed));
+
+struct hci_sco_hdr {
+    uint16_t	handle;
+    uint8_t	dlen;
+} __attribute__ ((packed));
+
+/* L2CAP layer defines */
+
+enum bt_l2cap_lm_bits {
+    L2CAP_LM_MASTER	= 1 << 0,
+    L2CAP_LM_AUTH	= 1 << 1,
+    L2CAP_LM_ENCRYPT	= 1 << 2,
+    L2CAP_LM_TRUSTED	= 1 << 3,
+    L2CAP_LM_RELIABLE	= 1 << 4,
+    L2CAP_LM_SECURE	= 1 << 5,
+};
+
+enum bt_l2cap_cid_predef {
+    L2CAP_CID_INVALID	= 0x0000,
+    L2CAP_CID_SIGNALLING= 0x0001,
+    L2CAP_CID_GROUP	= 0x0002,
+    L2CAP_CID_ALLOC	= 0x0040,
+};
+
+/* L2CAP command codes */
+enum bt_l2cap_cmd {
+    L2CAP_COMMAND_REJ	= 1,
+    L2CAP_CONN_REQ,
+    L2CAP_CONN_RSP,
+    L2CAP_CONF_REQ,
+    L2CAP_CONF_RSP,
+    L2CAP_DISCONN_REQ,
+    L2CAP_DISCONN_RSP,
+    L2CAP_ECHO_REQ,
+    L2CAP_ECHO_RSP,
+    L2CAP_INFO_REQ,
+    L2CAP_INFO_RSP,
+};
+
+enum bt_l2cap_sar_bits {
+    L2CAP_SAR_NO_SEG	= 0,
+    L2CAP_SAR_START,
+    L2CAP_SAR_END,
+    L2CAP_SAR_CONT,
+};
+
+/* L2CAP structures */
+typedef struct {
+    uint16_t	len;
+    uint16_t	cid;
+    uint8_t	data[0];
+} __attribute__ ((packed)) l2cap_hdr;
+#define L2CAP_HDR_SIZE 4
+
+typedef struct {
+    uint8_t	code;
+    uint8_t	ident;
+    uint16_t	len;
+} __attribute__ ((packed)) l2cap_cmd_hdr;
+#define L2CAP_CMD_HDR_SIZE 4
+
+typedef struct {
+    uint16_t	reason;
+} __attribute__ ((packed)) l2cap_cmd_rej;
+#define L2CAP_CMD_REJ_SIZE 2
+
+typedef struct {
+    uint16_t	dcid;
+    uint16_t	scid;
+} __attribute__ ((packed)) l2cap_cmd_rej_cid;
+#define L2CAP_CMD_REJ_CID_SIZE 4
+
+/* reject reason */
+enum bt_l2cap_rej_reason {
+    L2CAP_REJ_CMD_NOT_UNDERSTOOD = 0,
+    L2CAP_REJ_SIG_TOOBIG,
+    L2CAP_REJ_CID_INVAL,
+};
+
+typedef struct {
+    uint16_t	psm;
+    uint16_t	scid;
+} __attribute__ ((packed)) l2cap_conn_req;
+#define L2CAP_CONN_REQ_SIZE 4
+
+typedef struct {
+    uint16_t	dcid;
+    uint16_t	scid;
+    uint16_t	result;
+    uint16_t	status;
+} __attribute__ ((packed)) l2cap_conn_rsp;
+#define L2CAP_CONN_RSP_SIZE 8
+
+/* connect result */
+enum bt_l2cap_conn_res {
+    L2CAP_CR_SUCCESS	= 0,
+    L2CAP_CR_PEND,
+    L2CAP_CR_BAD_PSM,
+    L2CAP_CR_SEC_BLOCK,
+    L2CAP_CR_NO_MEM,
+};
+
+/* connect status */
+enum bt_l2cap_conn_stat {
+    L2CAP_CS_NO_INFO	= 0,
+    L2CAP_CS_AUTHEN_PEND,
+    L2CAP_CS_AUTHOR_PEND,
+};
+
+typedef struct {
+    uint16_t	dcid;
+    uint16_t	flags;
+    uint8_t	data[0];
+} __attribute__ ((packed)) l2cap_conf_req;
+#define L2CAP_CONF_REQ_SIZE(datalen) (4 + (datalen))
+
+typedef struct {
+    uint16_t	scid;
+    uint16_t	flags;
+    uint16_t	result;
+    uint8_t	data[0];
+} __attribute__ ((packed)) l2cap_conf_rsp;
+#define L2CAP_CONF_RSP_SIZE(datalen) (6 + datalen)
+
+enum bt_l2cap_conf_res {
+    L2CAP_CONF_SUCCESS	= 0,
+    L2CAP_CONF_UNACCEPT,
+    L2CAP_CONF_REJECT,
+    L2CAP_CONF_UNKNOWN,
+};
+
+typedef struct {
+    uint8_t	type;
+    uint8_t	len;
+    uint8_t	val[0];
+} __attribute__ ((packed)) l2cap_conf_opt;
+#define L2CAP_CONF_OPT_SIZE 2
+
+enum bt_l2cap_conf_val {
+    L2CAP_CONF_MTU	= 1,
+    L2CAP_CONF_FLUSH_TO,
+    L2CAP_CONF_QOS,
+    L2CAP_CONF_RFC,
+    L2CAP_CONF_RFC_MODE	= L2CAP_CONF_RFC,
+};
+
+typedef struct {
+    uint8_t	flags;
+    uint8_t	service_type;
+    uint32_t	token_rate;
+    uint32_t	token_bucket_size;
+    uint32_t	peak_bandwidth;
+    uint32_t	latency;
+    uint32_t	delay_variation;
+} __attribute__ ((packed)) l2cap_conf_opt_qos;
+#define L2CAP_CONF_OPT_QOS_SIZE 22
+
+enum bt_l2cap_conf_opt_qos_st {
+    L2CAP_CONF_QOS_NO_TRAFFIC = 0x00,
+    L2CAP_CONF_QOS_BEST_EFFORT,
+    L2CAP_CONF_QOS_GUARANTEED,
+};
+
+#define L2CAP_CONF_QOS_WILDCARD	0xffffffff
+
+enum bt_l2cap_mode {
+    L2CAP_MODE_BASIC	= 0,
+    L2CAP_MODE_RETRANS	= 1,
+    L2CAP_MODE_FLOWCTL	= 2,
+};
+
+typedef struct {
+    uint16_t	dcid;
+    uint16_t	scid;
+} __attribute__ ((packed)) l2cap_disconn_req;
+#define L2CAP_DISCONN_REQ_SIZE 4
+
+typedef struct {
+    uint16_t	dcid;
+    uint16_t	scid;
+} __attribute__ ((packed)) l2cap_disconn_rsp;
+#define L2CAP_DISCONN_RSP_SIZE 4
+
+typedef struct {
+    uint16_t	type;
+} __attribute__ ((packed)) l2cap_info_req;
+#define L2CAP_INFO_REQ_SIZE 2
+
+typedef struct {
+    uint16_t	type;
+    uint16_t	result;
+    uint8_t	data[0];
+} __attribute__ ((packed)) l2cap_info_rsp;
+#define L2CAP_INFO_RSP_SIZE 4
+
+/* info type */
+enum bt_l2cap_info_type {
+    L2CAP_IT_CL_MTU	= 1,
+    L2CAP_IT_FEAT_MASK,
+};
+
+/* info result */
+enum bt_l2cap_info_result {
+    L2CAP_IR_SUCCESS	= 0,
+    L2CAP_IR_NOTSUPP,
+};
+
+/* Service Discovery Protocol defines */
+/* Note that all multibyte values in lower layer protocols (above in this file)
+ * are little-endian while SDP is big-endian.  */
+
+/* Protocol UUIDs */
+enum sdp_proto_uuid {
+    SDP_UUID		= 0x0001,
+    UDP_UUID		= 0x0002,
+    RFCOMM_UUID		= 0x0003,
+    TCP_UUID		= 0x0004,
+    TCS_BIN_UUID	= 0x0005,
+    TCS_AT_UUID		= 0x0006,
+    OBEX_UUID		= 0x0008,
+    IP_UUID		= 0x0009,
+    FTP_UUID		= 0x000a,
+    HTTP_UUID		= 0x000c,
+    WSP_UUID		= 0x000e,
+    BNEP_UUID		= 0x000f,
+    UPNP_UUID		= 0x0010,
+    HIDP_UUID		= 0x0011,
+    HCRP_CTRL_UUID	= 0x0012,
+    HCRP_DATA_UUID	= 0x0014,
+    HCRP_NOTE_UUID	= 0x0016,
+    AVCTP_UUID		= 0x0017,
+    AVDTP_UUID		= 0x0019,
+    CMTP_UUID		= 0x001b,
+    UDI_UUID		= 0x001d,
+    MCAP_CTRL_UUID	= 0x001e,
+    MCAP_DATA_UUID	= 0x001f,
+    L2CAP_UUID		= 0x0100,
+};
+
+/*
+ * Service class identifiers of standard services and service groups
+ */
+enum service_class_id {
+    SDP_SERVER_SVCLASS_ID		= 0x1000,
+    BROWSE_GRP_DESC_SVCLASS_ID		= 0x1001,
+    PUBLIC_BROWSE_GROUP			= 0x1002,
+    SERIAL_PORT_SVCLASS_ID		= 0x1101,
+    LAN_ACCESS_SVCLASS_ID		= 0x1102,
+    DIALUP_NET_SVCLASS_ID		= 0x1103,
+    IRMC_SYNC_SVCLASS_ID		= 0x1104,
+    OBEX_OBJPUSH_SVCLASS_ID		= 0x1105,
+    OBEX_FILETRANS_SVCLASS_ID		= 0x1106,
+    IRMC_SYNC_CMD_SVCLASS_ID		= 0x1107,
+    HEADSET_SVCLASS_ID			= 0x1108,
+    CORDLESS_TELEPHONY_SVCLASS_ID	= 0x1109,
+    AUDIO_SOURCE_SVCLASS_ID		= 0x110a,
+    AUDIO_SINK_SVCLASS_ID		= 0x110b,
+    AV_REMOTE_TARGET_SVCLASS_ID		= 0x110c,
+    ADVANCED_AUDIO_SVCLASS_ID		= 0x110d,
+    AV_REMOTE_SVCLASS_ID		= 0x110e,
+    VIDEO_CONF_SVCLASS_ID		= 0x110f,
+    INTERCOM_SVCLASS_ID			= 0x1110,
+    FAX_SVCLASS_ID			= 0x1111,
+    HEADSET_AGW_SVCLASS_ID		= 0x1112,
+    WAP_SVCLASS_ID			= 0x1113,
+    WAP_CLIENT_SVCLASS_ID		= 0x1114,
+    PANU_SVCLASS_ID			= 0x1115,
+    NAP_SVCLASS_ID			= 0x1116,
+    GN_SVCLASS_ID			= 0x1117,
+    DIRECT_PRINTING_SVCLASS_ID		= 0x1118,
+    REFERENCE_PRINTING_SVCLASS_ID	= 0x1119,
+    IMAGING_SVCLASS_ID			= 0x111a,
+    IMAGING_RESPONDER_SVCLASS_ID	= 0x111b,
+    IMAGING_ARCHIVE_SVCLASS_ID		= 0x111c,
+    IMAGING_REFOBJS_SVCLASS_ID		= 0x111d,
+    HANDSFREE_SVCLASS_ID		= 0x111e,
+    HANDSFREE_AGW_SVCLASS_ID		= 0x111f,
+    DIRECT_PRT_REFOBJS_SVCLASS_ID	= 0x1120,
+    REFLECTED_UI_SVCLASS_ID		= 0x1121,
+    BASIC_PRINTING_SVCLASS_ID		= 0x1122,
+    PRINTING_STATUS_SVCLASS_ID		= 0x1123,
+    HID_SVCLASS_ID			= 0x1124,
+    HCR_SVCLASS_ID			= 0x1125,
+    HCR_PRINT_SVCLASS_ID		= 0x1126,
+    HCR_SCAN_SVCLASS_ID			= 0x1127,
+    CIP_SVCLASS_ID			= 0x1128,
+    VIDEO_CONF_GW_SVCLASS_ID		= 0x1129,
+    UDI_MT_SVCLASS_ID			= 0x112a,
+    UDI_TA_SVCLASS_ID			= 0x112b,
+    AV_SVCLASS_ID			= 0x112c,
+    SAP_SVCLASS_ID			= 0x112d,
+    PBAP_PCE_SVCLASS_ID			= 0x112e,
+    PBAP_PSE_SVCLASS_ID			= 0x112f,
+    PBAP_SVCLASS_ID			= 0x1130,
+    PNP_INFO_SVCLASS_ID			= 0x1200,
+    GENERIC_NETWORKING_SVCLASS_ID	= 0x1201,
+    GENERIC_FILETRANS_SVCLASS_ID	= 0x1202,
+    GENERIC_AUDIO_SVCLASS_ID		= 0x1203,
+    GENERIC_TELEPHONY_SVCLASS_ID	= 0x1204,
+    UPNP_SVCLASS_ID			= 0x1205,
+    UPNP_IP_SVCLASS_ID			= 0x1206,
+    UPNP_PAN_SVCLASS_ID			= 0x1300,
+    UPNP_LAP_SVCLASS_ID			= 0x1301,
+    UPNP_L2CAP_SVCLASS_ID		= 0x1302,
+    VIDEO_SOURCE_SVCLASS_ID		= 0x1303,
+    VIDEO_SINK_SVCLASS_ID		= 0x1304,
+    VIDEO_DISTRIBUTION_SVCLASS_ID	= 0x1305,
+    MDP_SVCLASS_ID			= 0x1400,
+    MDP_SOURCE_SVCLASS_ID		= 0x1401,
+    MDP_SINK_SVCLASS_ID			= 0x1402,
+    APPLE_AGENT_SVCLASS_ID		= 0x2112,
+};
+
+/*
+ * Standard profile descriptor identifiers; note these
+ * may be identical to some of the service classes defined above
+ */
+#define SDP_SERVER_PROFILE_ID		SDP_SERVER_SVCLASS_ID
+#define BROWSE_GRP_DESC_PROFILE_ID	BROWSE_GRP_DESC_SVCLASS_ID
+#define SERIAL_PORT_PROFILE_ID		SERIAL_PORT_SVCLASS_ID
+#define LAN_ACCESS_PROFILE_ID		LAN_ACCESS_SVCLASS_ID
+#define DIALUP_NET_PROFILE_ID		DIALUP_NET_SVCLASS_ID
+#define IRMC_SYNC_PROFILE_ID		IRMC_SYNC_SVCLASS_ID
+#define OBEX_OBJPUSH_PROFILE_ID		OBEX_OBJPUSH_SVCLASS_ID
+#define OBEX_FILETRANS_PROFILE_ID	OBEX_FILETRANS_SVCLASS_ID
+#define IRMC_SYNC_CMD_PROFILE_ID	IRMC_SYNC_CMD_SVCLASS_ID
+#define HEADSET_PROFILE_ID		HEADSET_SVCLASS_ID
+#define CORDLESS_TELEPHONY_PROFILE_ID	CORDLESS_TELEPHONY_SVCLASS_ID
+#define AUDIO_SOURCE_PROFILE_ID		AUDIO_SOURCE_SVCLASS_ID
+#define AUDIO_SINK_PROFILE_ID		AUDIO_SINK_SVCLASS_ID
+#define AV_REMOTE_TARGET_PROFILE_ID	AV_REMOTE_TARGET_SVCLASS_ID
+#define ADVANCED_AUDIO_PROFILE_ID	ADVANCED_AUDIO_SVCLASS_ID
+#define AV_REMOTE_PROFILE_ID		AV_REMOTE_SVCLASS_ID
+#define VIDEO_CONF_PROFILE_ID		VIDEO_CONF_SVCLASS_ID
+#define INTERCOM_PROFILE_ID		INTERCOM_SVCLASS_ID
+#define FAX_PROFILE_ID			FAX_SVCLASS_ID
+#define HEADSET_AGW_PROFILE_ID		HEADSET_AGW_SVCLASS_ID
+#define WAP_PROFILE_ID			WAP_SVCLASS_ID
+#define WAP_CLIENT_PROFILE_ID		WAP_CLIENT_SVCLASS_ID
+#define PANU_PROFILE_ID			PANU_SVCLASS_ID
+#define NAP_PROFILE_ID			NAP_SVCLASS_ID
+#define GN_PROFILE_ID			GN_SVCLASS_ID
+#define DIRECT_PRINTING_PROFILE_ID	DIRECT_PRINTING_SVCLASS_ID
+#define REFERENCE_PRINTING_PROFILE_ID	REFERENCE_PRINTING_SVCLASS_ID
+#define IMAGING_PROFILE_ID		IMAGING_SVCLASS_ID
+#define IMAGING_RESPONDER_PROFILE_ID	IMAGING_RESPONDER_SVCLASS_ID
+#define IMAGING_ARCHIVE_PROFILE_ID	IMAGING_ARCHIVE_SVCLASS_ID
+#define IMAGING_REFOBJS_PROFILE_ID	IMAGING_REFOBJS_SVCLASS_ID
+#define HANDSFREE_PROFILE_ID		HANDSFREE_SVCLASS_ID
+#define HANDSFREE_AGW_PROFILE_ID	HANDSFREE_AGW_SVCLASS_ID
+#define DIRECT_PRT_REFOBJS_PROFILE_ID	DIRECT_PRT_REFOBJS_SVCLASS_ID
+#define REFLECTED_UI_PROFILE_ID		REFLECTED_UI_SVCLASS_ID
+#define BASIC_PRINTING_PROFILE_ID	BASIC_PRINTING_SVCLASS_ID
+#define PRINTING_STATUS_PROFILE_ID	PRINTING_STATUS_SVCLASS_ID
+#define HID_PROFILE_ID			HID_SVCLASS_ID
+#define HCR_PROFILE_ID			HCR_SCAN_SVCLASS_ID
+#define HCR_PRINT_PROFILE_ID		HCR_PRINT_SVCLASS_ID
+#define HCR_SCAN_PROFILE_ID		HCR_SCAN_SVCLASS_ID
+#define CIP_PROFILE_ID			CIP_SVCLASS_ID
+#define VIDEO_CONF_GW_PROFILE_ID	VIDEO_CONF_GW_SVCLASS_ID
+#define UDI_MT_PROFILE_ID		UDI_MT_SVCLASS_ID
+#define UDI_TA_PROFILE_ID		UDI_TA_SVCLASS_ID
+#define AV_PROFILE_ID			AV_SVCLASS_ID
+#define SAP_PROFILE_ID			SAP_SVCLASS_ID
+#define PBAP_PCE_PROFILE_ID		PBAP_PCE_SVCLASS_ID
+#define PBAP_PSE_PROFILE_ID		PBAP_PSE_SVCLASS_ID
+#define PBAP_PROFILE_ID			PBAP_SVCLASS_ID
+#define PNP_INFO_PROFILE_ID		PNP_INFO_SVCLASS_ID
+#define GENERIC_NETWORKING_PROFILE_ID	GENERIC_NETWORKING_SVCLASS_ID
+#define GENERIC_FILETRANS_PROFILE_ID	GENERIC_FILETRANS_SVCLASS_ID
+#define GENERIC_AUDIO_PROFILE_ID	GENERIC_AUDIO_SVCLASS_ID
+#define GENERIC_TELEPHONY_PROFILE_ID	GENERIC_TELEPHONY_SVCLASS_ID
+#define UPNP_PROFILE_ID			UPNP_SVCLASS_ID
+#define UPNP_IP_PROFILE_ID		UPNP_IP_SVCLASS_ID
+#define UPNP_PAN_PROFILE_ID		UPNP_PAN_SVCLASS_ID
+#define UPNP_LAP_PROFILE_ID		UPNP_LAP_SVCLASS_ID
+#define UPNP_L2CAP_PROFILE_ID		UPNP_L2CAP_SVCLASS_ID
+#define VIDEO_SOURCE_PROFILE_ID		VIDEO_SOURCE_SVCLASS_ID
+#define VIDEO_SINK_PROFILE_ID		VIDEO_SINK_SVCLASS_ID
+#define VIDEO_DISTRIBUTION_PROFILE_ID	VIDEO_DISTRIBUTION_SVCLASS_ID
+#define MDP_PROFILE_ID			MDP_SVCLASS_ID
+#define MDP_SOURCE_PROFILE_ID		MDP_SROUCE_SVCLASS_ID
+#define MDP_SINK_PROFILE_ID		MDP_SINK_SVCLASS_ID
+#define APPLE_AGENT_PROFILE_ID		APPLE_AGENT_SVCLASS_ID
+
+/* Data Representation */
+enum bt_sdp_data_type {
+    SDP_DTYPE_NIL	= 0 << 3,
+    SDP_DTYPE_UINT	= 1 << 3,
+    SDP_DTYPE_SINT	= 2 << 3,
+    SDP_DTYPE_UUID	= 3 << 3,
+    SDP_DTYPE_STRING	= 4 << 3,
+    SDP_DTYPE_BOOL	= 5 << 3,
+    SDP_DTYPE_SEQ	= 6 << 3,
+    SDP_DTYPE_ALT	= 7 << 3,
+    SDP_DTYPE_URL	= 8 << 3,
+};
+
+enum bt_sdp_data_size {
+    SDP_DSIZE_1		= 0,
+    SDP_DSIZE_2,
+    SDP_DSIZE_4,
+    SDP_DSIZE_8,
+    SDP_DSIZE_16,
+    SDP_DSIZE_NEXT1,
+    SDP_DSIZE_NEXT2,
+    SDP_DSIZE_NEXT4,
+    SDP_DSIZE_MASK = SDP_DSIZE_NEXT4,
+};
+
+enum bt_sdp_cmd {
+    SDP_ERROR_RSP		= 0x01,
+    SDP_SVC_SEARCH_REQ		= 0x02,
+    SDP_SVC_SEARCH_RSP		= 0x03,
+    SDP_SVC_ATTR_REQ		= 0x04,
+    SDP_SVC_ATTR_RSP		= 0x05,
+    SDP_SVC_SEARCH_ATTR_REQ	= 0x06,
+    SDP_SVC_SEARCH_ATTR_RSP	= 0x07,
+};
+
+enum bt_sdp_errorcode {
+    SDP_INVALID_VERSION		= 0x0001,
+    SDP_INVALID_RECORD_HANDLE	= 0x0002,
+    SDP_INVALID_SYNTAX		= 0x0003,
+    SDP_INVALID_PDU_SIZE	= 0x0004,
+    SDP_INVALID_CSTATE		= 0x0005,
+};
+
+/*
+ * String identifiers are based on the SDP spec stating that
+ * "base attribute id of the primary (universal) language must be 0x0100"
+ *
+ * Other languages should have their own offset; e.g.:
+ * #define XXXLangBase yyyy
+ * #define AttrServiceName_XXX	0x0000+XXXLangBase
+ */
+#define SDP_PRIMARY_LANG_BASE 		0x0100
+
+enum bt_sdp_attribute_id {
+    SDP_ATTR_RECORD_HANDLE			= 0x0000,
+    SDP_ATTR_SVCLASS_ID_LIST			= 0x0001,
+    SDP_ATTR_RECORD_STATE			= 0x0002,
+    SDP_ATTR_SERVICE_ID				= 0x0003,
+    SDP_ATTR_PROTO_DESC_LIST			= 0x0004,
+    SDP_ATTR_BROWSE_GRP_LIST			= 0x0005,
+    SDP_ATTR_LANG_BASE_ATTR_ID_LIST		= 0x0006,
+    SDP_ATTR_SVCINFO_TTL			= 0x0007,
+    SDP_ATTR_SERVICE_AVAILABILITY		= 0x0008,
+    SDP_ATTR_PFILE_DESC_LIST			= 0x0009,
+    SDP_ATTR_DOC_URL				= 0x000a,
+    SDP_ATTR_CLNT_EXEC_URL			= 0x000b,
+    SDP_ATTR_ICON_URL				= 0x000c,
+    SDP_ATTR_ADD_PROTO_DESC_LIST		= 0x000d,
+
+    SDP_ATTR_SVCNAME_PRIMARY			= SDP_PRIMARY_LANG_BASE + 0,
+    SDP_ATTR_SVCDESC_PRIMARY			= SDP_PRIMARY_LANG_BASE + 1,
+    SDP_ATTR_SVCPROV_PRIMARY			= SDP_PRIMARY_LANG_BASE + 2,
+
+    SDP_ATTR_GROUP_ID				= 0x0200,
+    SDP_ATTR_IP_SUBNET				= 0x0200,
+
+    /* SDP */
+    SDP_ATTR_VERSION_NUM_LIST			= 0x0200,
+    SDP_ATTR_SVCDB_STATE			= 0x0201,
+
+    SDP_ATTR_SERVICE_VERSION			= 0x0300,
+    SDP_ATTR_EXTERNAL_NETWORK			= 0x0301,
+    SDP_ATTR_SUPPORTED_DATA_STORES_LIST		= 0x0301,
+    SDP_ATTR_FAX_CLASS1_SUPPORT			= 0x0302,
+    SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL	= 0x0302,
+    SDP_ATTR_FAX_CLASS20_SUPPORT		= 0x0303,
+    SDP_ATTR_SUPPORTED_FORMATS_LIST		= 0x0303,
+    SDP_ATTR_FAX_CLASS2_SUPPORT			= 0x0304,
+    SDP_ATTR_AUDIO_FEEDBACK_SUPPORT		= 0x0305,
+    SDP_ATTR_NETWORK_ADDRESS			= 0x0306,
+    SDP_ATTR_WAP_GATEWAY			= 0x0307,
+    SDP_ATTR_HOMEPAGE_URL			= 0x0308,
+    SDP_ATTR_WAP_STACK_TYPE			= 0x0309,
+    SDP_ATTR_SECURITY_DESC			= 0x030a,
+    SDP_ATTR_NET_ACCESS_TYPE			= 0x030b,
+    SDP_ATTR_MAX_NET_ACCESSRATE			= 0x030c,
+    SDP_ATTR_IP4_SUBNET				= 0x030d,
+    SDP_ATTR_IP6_SUBNET				= 0x030e,
+    SDP_ATTR_SUPPORTED_CAPABILITIES		= 0x0310,
+    SDP_ATTR_SUPPORTED_FEATURES			= 0x0311,
+    SDP_ATTR_SUPPORTED_FUNCTIONS		= 0x0312,
+    SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY	= 0x0313,
+    SDP_ATTR_SUPPORTED_REPOSITORIES		= 0x0314,
+
+    /* PnP Information */
+    SDP_ATTR_SPECIFICATION_ID			= 0x0200,
+    SDP_ATTR_VENDOR_ID				= 0x0201,
+    SDP_ATTR_PRODUCT_ID				= 0x0202,
+    SDP_ATTR_VERSION				= 0x0203,
+    SDP_ATTR_PRIMARY_RECORD			= 0x0204,
+    SDP_ATTR_VENDOR_ID_SOURCE			= 0x0205,
+
+    /* BT HID */
+    SDP_ATTR_DEVICE_RELEASE_NUMBER		= 0x0200,
+    SDP_ATTR_PARSER_VERSION			= 0x0201,
+    SDP_ATTR_DEVICE_SUBCLASS			= 0x0202,
+    SDP_ATTR_COUNTRY_CODE			= 0x0203,
+    SDP_ATTR_VIRTUAL_CABLE			= 0x0204,
+    SDP_ATTR_RECONNECT_INITIATE			= 0x0205,
+    SDP_ATTR_DESCRIPTOR_LIST			= 0x0206,
+    SDP_ATTR_LANG_ID_BASE_LIST			= 0x0207,
+    SDP_ATTR_SDP_DISABLE			= 0x0208,
+    SDP_ATTR_BATTERY_POWER			= 0x0209,
+    SDP_ATTR_REMOTE_WAKEUP			= 0x020a,
+    SDP_ATTR_PROFILE_VERSION			= 0x020b,
+    SDP_ATTR_SUPERVISION_TIMEOUT		= 0x020c,
+    SDP_ATTR_NORMALLY_CONNECTABLE		= 0x020d,
+    SDP_ATTR_BOOT_DEVICE			= 0x020e,
+};
diff -Nur kvm-76/qemu/hw/cirrus_vga.c kvm-userspace/qemu/hw/cirrus_vga.c
--- kvm-76/qemu/hw/cirrus_vga.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/cirrus_vga.c	2008-10-12 09:38:23.000000000 +0200
@@ -2628,40 +2628,34 @@
     cirrus_linear_bitblt_writel,
 };
 
-void *set_vram_mapping(unsigned long begin, unsigned long end)
+void set_vram_mapping(void *ptr, unsigned long begin, unsigned long end)
 {
-    void *vram_pointer = NULL;
-
     /* align begin and end address */
     begin = begin & TARGET_PAGE_MASK;
     end = begin + VGA_RAM_SIZE;
     end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
 
-    if (kvm_enabled())
-	vram_pointer = kvm_cpu_create_phys_mem(begin, end - begin, 1, 1);
-
-    if (vram_pointer == NULL) {
-        printf("set_vram_mapping: cannot allocate memory: %m\n");
-        return NULL;
+    if (kvm_enabled()) {
+        kvm_cpu_register_physical_memory(begin, end - begin,
+                                         ptr - (void *)phys_ram_base);
+        kvm_qemu_log_memory(begin, end - begin, 1);
     }
-
-    memset(vram_pointer, 0, end - begin);
-
-    return vram_pointer;
 }
 
-int unset_vram_mapping(unsigned long begin, unsigned long end)
+void unset_vram_mapping(void *ptr, unsigned long begin, unsigned long end)
 {
     /* align begin and end address */
     end = begin + VGA_RAM_SIZE;
     begin = begin & TARGET_PAGE_MASK;
     end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
 
-    if (kvm_enabled())
-	kvm_cpu_destroy_phys_mem(begin, end - begin);
-
-    return 0;
+    if (kvm_enabled()) {
+        kvm_qemu_log_memory(begin, end - begin, 0);
+	kvm_cpu_unregister_physical_memory(begin, end - begin,
+                                           ptr - (void *)phys_ram_base);
+    }
 }
+
 #ifdef CONFIG_X86
 static void kvm_update_vga_alias(CirrusVGAState *s, int ok, int bank)
 {
@@ -2677,14 +2671,13 @@
 	if (!s->aliases_enabled
 	    || base != s->aliased_bank_base[bank]
 	    || limit != s->aliased_bank_limit[bank]) {
-	    kvm_create_memory_alias(kvm_context,
-				    0xa0000 + bank * 0x8000,
-				    limit, base);
+	    kvm_qemu_create_memory_alias(0xa0000 + bank * 0x8000,
+                                     limit, base);
 	    s->aliased_bank_base[bank] = base;
 	    s->aliased_bank_limit[bank] = limit;
 	}
     } else {
-	kvm_destroy_memory_alias(kvm_context, 0xa0000 + bank * 0x8000);
+	kvm_qemu_destroy_memory_alias(0xa0000 + bank * 0x8000);
     }
 }
 
@@ -2721,17 +2714,8 @@
 	if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
             if (kvm_enabled() && s->cirrus_lfb_addr && s->cirrus_lfb_end &&
 		!s->map_addr) {
-                void *vram_pointer, *old_vram;
-
-                vram_pointer = set_vram_mapping(s->cirrus_lfb_addr,
-                                                s->cirrus_lfb_end);
-                if (!vram_pointer)
-                    fprintf(stderr, "NULL vram_pointer\n");
-                else {
-                    old_vram = vga_update_vram((VGAState *)s, vram_pointer,
-                                               VGA_RAM_SIZE);
-                    qemu_free(old_vram);
-                }
+                set_vram_mapping(s->vram_ptr,
+				 s->cirrus_lfb_addr, s->cirrus_lfb_end);
                 s->map_addr = s->cirrus_lfb_addr;
                 s->map_end = s->cirrus_lfb_end;
             }
@@ -2750,16 +2734,9 @@
         generic_io:
             if (kvm_enabled() && s->cirrus_lfb_addr && s->cirrus_lfb_end &&
 		s->map_addr) {
-		int error;
-                void *old_vram = NULL;
-
-		error = unset_vram_mapping(s->cirrus_lfb_addr,
-					   s->cirrus_lfb_end);
-		if (!error)
-		    old_vram = vga_update_vram((VGAState *)s, NULL,
-                                               VGA_RAM_SIZE);
-                if (old_vram)
-                    munmap(old_vram, s->map_end - s->map_addr);
+		unset_vram_mapping(s->vram_ptr,
+                                   s->cirrus_lfb_addr,
+                                   s->cirrus_lfb_end);
                 s->map_addr = s->map_end = 0;
             }
             s->cirrus_linear_write[0] = cirrus_linear_writeb;
@@ -2868,8 +2845,7 @@
 	case 0x3ba:
 	case 0x3da:
 	    /* just toggle to fool polling */
-	    s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
-	    val = s->st01;
+	    val = s->st01 = s->retrace((VGAState *) s);
 	    s->ar_flip_flop = 0;
 	    break;
 	default:
@@ -2932,6 +2908,7 @@
 	break;
     case 0x3c2:
 	s->msr = val & ~0x10;
+	s->update_retrace_info((VGAState *) s);
 	break;
     case 0x3c4:
 	s->sr_index = val;
@@ -2943,6 +2920,7 @@
 	printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
 #endif
 	s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+	if (s->sr_index == 1) s->update_retrace_info((VGAState *) s);
 	break;
     case 0x3c6:
 	cirrus_write_hidden_dac(s, val);
@@ -3010,6 +2988,18 @@
 	    s->cr[s->cr_index] = val;
 	    break;
 	}
+
+	switch(s->cr_index) {
+	case 0x00:
+	case 0x04:
+	case 0x05:
+	case 0x06:
+	case 0x07:
+	case 0x11:
+	case 0x17:
+	    s->update_retrace_info((VGAState *) s);
+	    break;
+	}
 	break;
     case 0x3ba:
     case 0x3da:
diff -Nur kvm-76/qemu/hw/e1000.c kvm-userspace/qemu/hw/e1000.c
--- kvm-76/qemu/hw/e1000.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/e1000.c	2008-10-12 09:38:23.000000000 +0200
@@ -103,8 +103,8 @@
         uint32_t paylen;
         uint16_t tso_frames;
         char tse;
-        char ip;
-        char tcp;
+        int8_t ip;
+        int8_t tcp;
         char cptse;     // current packet tse bit
     } tx;
 
@@ -132,7 +132,7 @@
 };
 
 enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W };
-static char phy_regcap[0x20] = {
+static const char phy_regcap[0x20] = {
     [PHY_STATUS] = PHY_R,	[M88E1000_EXT_PHY_SPEC_CTRL] = PHY_RW,
     [PHY_ID1] = PHY_R,		[M88E1000_PHY_SPEC_CTRL] = PHY_RW,
     [PHY_CTRL] = PHY_RW,	[PHY_1000T_CTRL] = PHY_RW,
@@ -784,7 +784,7 @@
             (8 * (addr & 3))) & 0xffff;
 }
 
-int mac_regtosave[] = {
+static const int mac_regtosave[] = {
     CTRL,	EECD,	EERD,	GPRC,	GPTC,	ICR,	ICS,	IMC,	IMS,
     LEDCTL,	MANC,	MDIC,	MPC,	PBA,	RCTL,	RDBAH,	RDBAL,	RDH,
     RDLEN,	RDT,	STATUS,	SWSM,	TCTL,	TDBAH,	TDBAL,	TDH,	TDLEN,
@@ -792,7 +792,7 @@
 };
 enum { MAC_NSAVE = sizeof mac_regtosave/sizeof *mac_regtosave };
 
-struct {
+static const struct {
     int size;
     int array0;
 } mac_regarraystosave[] = { {32, RA}, {128, MTA} };
@@ -825,8 +825,8 @@
     qemu_put_be16s(f, &s->tx.size);
     qemu_put_be16s(f, &s->tx.tso_frames);
     qemu_put_8s(f, &s->tx.sum_needed);
-    qemu_put_8s(f, &s->tx.ip);
-    qemu_put_8s(f, &s->tx.tcp);
+    qemu_put_s8s(f, &s->tx.ip);
+    qemu_put_s8s(f, &s->tx.tcp);
     qemu_put_buffer(f, s->tx.header, sizeof s->tx.header);
     qemu_put_buffer(f, s->tx.data, sizeof s->tx.data);
     for (i = 0; i < 64; i++)
@@ -850,7 +850,7 @@
     if ((ret = pci_device_load(&s->dev, f)) < 0)
         return ret;
     if (version_id == 1)
-        qemu_get_be32s(f, &i); /* once some unused instance id */
+        qemu_get_sbe32s(f, &i); /* once some unused instance id */
     qemu_get_be32s(f, &s->mmio_base);
     qemu_get_be32s(f, &s->rxbuf_size);
     qemu_get_be32s(f, &s->rxbuf_min_shift);
@@ -871,8 +871,8 @@
     qemu_get_be16s(f, &s->tx.size);
     qemu_get_be16s(f, &s->tx.tso_frames);
     qemu_get_8s(f, &s->tx.sum_needed);
-    qemu_get_8s(f, &s->tx.ip);
-    qemu_get_8s(f, &s->tx.tcp);
+    qemu_get_s8s(f, &s->tx.ip);
+    qemu_get_s8s(f, &s->tx.tcp);
     qemu_get_buffer(f, s->tx.header, sizeof s->tx.header);
     qemu_get_buffer(f, s->tx.data, sizeof s->tx.data);
     for (i = 0; i < 64; i++)
@@ -888,7 +888,7 @@
     return 0;
 }
 
-static uint16_t e1000_eeprom_template[64] = {
+static const uint16_t e1000_eeprom_template[64] = {
     0x0000, 0x0000, 0x0000, 0x0000,      0xffff, 0x0000,      0x0000, 0x0000,
     0x3000, 0x1000, 0x6403, E1000_DEVID, 0x8086, E1000_DEVID, 0x8086, 0x3040,
     0x0008, 0x2000, 0x7e14, 0x0048,      0x1000, 0x00d8,      0x0000, 0x2700,
@@ -899,7 +899,7 @@
     0xffff, 0xffff, 0xffff, 0xffff,      0xffff, 0xffff,      0xffff, 0x0000,
 };
 
-static uint16_t phy_reg_init[] = {
+static const uint16_t phy_reg_init[] = {
     [PHY_CTRL] = 0x1140,			[PHY_STATUS] = 0x796d, // link initially up
     [PHY_ID1] = 0x141,				[PHY_ID2] = PHY_ID2_INIT,
     [PHY_1000T_CTRL] = 0x0e00,			[M88E1000_PHY_SPEC_CTRL] = 0x360,
@@ -908,7 +908,7 @@
     [M88E1000_PHY_SPEC_STATUS] = 0xac00,
 };
 
-static uint32_t mac_reg_init[] = {
+static const uint32_t mac_reg_init[] = {
     [PBA] =     0x00100030,
     [LEDCTL] =  0x602,
     [CTRL] =    E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 |
diff -Nur kvm-76/qemu/hw/esp.c kvm-userspace/qemu/hw/esp.c
--- kvm-76/qemu/hw/esp.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/esp.c	2008-10-12 09:38:23.000000000 +0200
@@ -569,7 +569,7 @@
 static CPUWriteMemoryFunc *esp_mem_write[3] = {
     esp_mem_writeb,
     NULL,
-    NULL,
+    esp_mem_writeb,
 };
 
 static void esp_save(QEMUFile *f, void *opaque)
@@ -578,7 +578,7 @@
 
     qemu_put_buffer(f, s->rregs, ESP_REGS);
     qemu_put_buffer(f, s->wregs, ESP_REGS);
-    qemu_put_be32s(f, (uint32_t *)&s->ti_size);
+    qemu_put_sbe32s(f, &s->ti_size);
     qemu_put_be32s(f, &s->ti_rptr);
     qemu_put_be32s(f, &s->ti_wptr);
     qemu_put_buffer(f, s->ti_buf, TI_BUFSZ);
@@ -600,7 +600,7 @@
 
     qemu_get_buffer(f, s->rregs, ESP_REGS);
     qemu_get_buffer(f, s->wregs, ESP_REGS);
-    qemu_get_be32s(f, (uint32_t *)&s->ti_size);
+    qemu_get_sbe32s(f, &s->ti_size);
     qemu_get_be32s(f, &s->ti_rptr);
     qemu_get_be32s(f, &s->ti_wptr);
     qemu_get_buffer(f, s->ti_buf, TI_BUFSZ);
diff -Nur kvm-76/qemu/hw/fw_cfg.c kvm-userspace/qemu/hw/fw_cfg.c
--- kvm-76/qemu/hw/fw_cfg.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/fw_cfg.c	2008-10-12 09:38:23.000000000 +0200
@@ -259,7 +259,6 @@
 {
     FWCfgState *s;
     int io_ctl_memory, io_data_memory;
-    extern int nographic;
 
     s = qemu_mallocz(sizeof(FWCfgState));
     if (!s)
diff -Nur kvm-76/qemu/hw/hw.h kvm-userspace/qemu/hw/hw.h
--- kvm-76/qemu/hw/hw.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/hw.h	2008-10-12 09:38:23.000000000 +0200
@@ -7,26 +7,68 @@
 
 /* VM Load/Save */
 
-typedef void (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf, int64_t pos, int size);
-typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf, int64_t pos, int size);
-typedef void (QEMUFileCloseFunc)(void *opaque);
-
-QEMUFile *qemu_fopen(void *opaque, QEMUFilePutBufferFunc *put_buffer,
-                     QEMUFileGetBufferFunc *get_buffer, QEMUFileCloseFunc *close);
-QEMUFile *qemu_fopen_file(const char *filename, const char *mode);
+/* This function writes a chunk of data to a file at the given position.
+ * The pos argument can be ignored if the file is only being used for
+ * streaming.  The handler should try to write all of the data it can.
+ */
+typedef void (QEMUFilePutBufferFunc)(void *opaque, const uint8_t *buf,
+                                     int64_t pos, int size);
+
+/* Read a chunk of data from a file at the given position.  The pos argument
+ * can be ignored if the file is only be used for streaming.  The number of
+ * bytes actually read should be returned.
+ */
+typedef int (QEMUFileGetBufferFunc)(void *opaque, uint8_t *buf,
+                                    int64_t pos, int size);
+
+/* Close a file and return an error code */
+typedef int (QEMUFileCloseFunc)(void *opaque);
+
+/* Called to determine if the file has exceeded it's bandwidth allocation.  The
+ * bandwidth capping is a soft limit, not a hard limit.
+ */
+typedef int (QEMUFileRateLimit)(void *opaque);
+
+QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
+                         QEMUFileGetBufferFunc *get_buffer,
+                         QEMUFileCloseFunc *close,
+                         QEMUFileRateLimit *rate_limit);
+QEMUFile *qemu_fopen(const char *filename, const char *mode);
 QEMUFile *qemu_fopen_fd(int fd);
 void qemu_fflush(QEMUFile *f);
-void qemu_fclose(QEMUFile *f);
+int qemu_fclose(QEMUFile *f);
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
 void qemu_put_byte(QEMUFile *f, int v);
+
+static inline void qemu_put_ubyte(QEMUFile *f, unsigned int v)
+{
+    qemu_put_byte(f, (int)v);
+}
+
+#define qemu_put_sbyte qemu_put_byte
+
 void qemu_put_be16(QEMUFile *f, unsigned int v);
 void qemu_put_be32(QEMUFile *f, unsigned int v);
 void qemu_put_be64(QEMUFile *f, uint64_t v);
 int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
 int qemu_get_byte(QEMUFile *f);
+
+static inline unsigned int qemu_get_ubyte(QEMUFile *f)
+{
+    return (unsigned int)qemu_get_byte(f);
+}
+
+#define qemu_get_sbyte qemu_get_byte
+
 unsigned int qemu_get_be16(QEMUFile *f);
 unsigned int qemu_get_be32(QEMUFile *f);
 uint64_t qemu_get_be64(QEMUFile *f);
+int qemu_file_rate_limit(QEMUFile *f);
+
+/* Try to send any outstanding data.  This function is useful when output is
+ * halted due to rate limiting or EAGAIN errors occur as it can be used to
+ * resume output. */
+void qemu_file_put_notify(QEMUFile *f);
 
 static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
 {
@@ -68,17 +110,106 @@
     *pv = qemu_get_byte(f);
 }
 
+// Signed versions for type safety
+static inline void qemu_put_sbuffer(QEMUFile *f, const int8_t *buf, int size)
+{
+    qemu_put_buffer(f, (const uint8_t *)buf, size);
+}
+
+static inline void qemu_put_sbe16(QEMUFile *f, int v)
+{
+    qemu_put_be16(f, (unsigned int)v);
+}
+
+static inline void qemu_put_sbe32(QEMUFile *f, int v)
+{
+    qemu_put_be32(f, (unsigned int)v);
+}
+
+static inline void qemu_put_sbe64(QEMUFile *f, int64_t v)
+{
+    qemu_put_be64(f, (uint64_t)v);
+}
+
+static inline size_t qemu_get_sbuffer(QEMUFile *f, int8_t *buf, int size)
+{
+    return qemu_get_buffer(f, (uint8_t *)buf, size);
+}
+
+static inline int qemu_get_sbe16(QEMUFile *f)
+{
+    return (int)qemu_get_be16(f);
+}
+
+static inline int qemu_get_sbe32(QEMUFile *f)
+{
+    return (int)qemu_get_be32(f);
+}
+
+static inline int64_t qemu_get_sbe64(QEMUFile *f)
+{
+    return (int64_t)qemu_get_be64(f);
+}
+
+static inline void qemu_put_s8s(QEMUFile *f, const int8_t *pv)
+{
+    qemu_put_8s(f, (const uint8_t *)pv);
+}
+
+static inline void qemu_put_sbe16s(QEMUFile *f, const int16_t *pv)
+{
+    qemu_put_be16s(f, (const uint16_t *)pv);
+}
+
+static inline void qemu_put_sbe32s(QEMUFile *f, const int32_t *pv)
+{
+    qemu_put_be32s(f, (const uint32_t *)pv);
+}
+
+static inline void qemu_put_sbe64s(QEMUFile *f, const int64_t *pv)
+{
+    qemu_put_be64s(f, (const uint64_t *)pv);
+}
+
+static inline void qemu_get_s8s(QEMUFile *f, int8_t *pv)
+{
+    qemu_get_8s(f, (uint8_t *)pv);
+}
+
+static inline void qemu_get_sbe16s(QEMUFile *f, int16_t *pv)
+{
+    qemu_get_be16s(f, (uint16_t *)pv);
+}
+
+static inline void qemu_get_sbe32s(QEMUFile *f, int32_t *pv)
+{
+    qemu_get_be32s(f, (uint32_t *)pv);
+}
+
+static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv)
+{
+    qemu_get_be64s(f, (uint64_t *)pv);
+}
+
 #ifdef NEED_CPU_H
 #if TARGET_LONG_BITS == 64
 #define qemu_put_betl qemu_put_be64
 #define qemu_get_betl qemu_get_be64
 #define qemu_put_betls qemu_put_be64s
 #define qemu_get_betls qemu_get_be64s
+#define qemu_put_sbetl qemu_put_sbe64
+#define qemu_get_sbetl qemu_get_sbe64
+#define qemu_put_sbetls qemu_put_sbe64s
+#define qemu_get_sbetls qemu_get_sbe64s
 #else
 #define qemu_put_betl qemu_put_be32
 #define qemu_get_betl qemu_get_be32
 #define qemu_put_betls qemu_put_be32s
 #define qemu_get_betls qemu_get_be32s
+#define qemu_put_sbetl qemu_put_sbe32
+#define qemu_get_sbetl qemu_get_sbe32
+#define qemu_put_sbetls qemu_put_sbe32s
+#define qemu_get_sbetls qemu_get_sbe32s
 #endif
 #endif
 
diff -Nur kvm-76/qemu/hw/ide.c kvm-userspace/qemu/hw/ide.c
--- kvm-76/qemu/hw/ide.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/ide.c	2008-10-12 09:38:23.000000000 +0200
@@ -739,6 +739,14 @@
     s->error = ABRT_ERR;
 }
 
+static inline void ide_dma_submit_check(IDEState *s,
+          BlockDriverCompletionFunc *dma_cb, BMDMAState *bm)
+{
+    if (bm->aiocb)
+	return;
+    dma_cb(bm, -1);
+}
+
 static inline void ide_set_irq(IDEState *s)
 {
     BMDMAState *bm = s->bmdma;
@@ -818,6 +826,11 @@
     }
 }
 
+static void ide_rw_error(IDEState *s) {
+    ide_abort_command(s);
+    ide_set_irq(s);
+}
+
 static void ide_sector_read(IDEState *s)
 {
     int64_t sector_num;
@@ -837,6 +850,10 @@
         if (n > s->req_nb_sectors)
             n = s->req_nb_sectors;
         ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
+        if (ret != 0) {
+            ide_rw_error(s);
+            return;
+        }
         ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
         ide_set_irq(s);
         ide_set_sector(s, sector_num + n);
@@ -844,6 +861,14 @@
     }
 }
 
+static void ide_dma_error(IDEState *s)
+{
+    ide_transfer_stop(s);
+    s->error = ABRT_ERR;
+    s->status = READY_STAT | ERR_STAT;
+    ide_set_irq(s);
+}
+
 /* return 0 if buffer completed */
 static int dma_buf_rw(BMDMAState *bm, int is_write)
 {
@@ -892,7 +917,6 @@
     return 1;
 }
 
-/* XXX: handle errors */
 static void ide_read_dma_cb(void *opaque, int ret)
 {
     BMDMAState *bm = opaque;
@@ -900,6 +924,11 @@
     int n;
     int64_t sector_num;
 
+    if (ret < 0) {
+	ide_dma_error(s);
+	return;
+    }
+
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
@@ -934,6 +963,7 @@
 #endif
     bm->aiocb = bdrv_aio_read(s->bs, sector_num, s->io_buffer, n,
                               ide_read_dma_cb, bm);
+    ide_dma_submit_check(s, ide_read_dma_cb, bm);
 }
 
 static void ide_sector_read_dma(IDEState *s)
@@ -964,6 +994,11 @@
     if (n > s->req_nb_sectors)
         n = s->req_nb_sectors;
     ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
+    if (ret != 0) {
+	ide_rw_error(s);
+	return;
+    }
+
     s->nsector -= n;
     if (s->nsector == 0) {
         /* no more sectors to write */
@@ -993,7 +1028,6 @@
     }
 }
 
-/* XXX: handle errors */
 static void ide_write_dma_cb(void *opaque, int ret)
 {
     BMDMAState *bm = opaque;
@@ -1001,6 +1035,11 @@
     int n;
     int64_t sector_num;
 
+    if (ret < 0) {
+	ide_dma_error(s);
+	return;
+    }
+
     n = s->io_buffer_size >> 9;
     sector_num = ide_get_sector(s);
     if (n > 0) {
@@ -1036,6 +1075,7 @@
 #endif
     bm->aiocb = bdrv_aio_write(s->bs, sector_num, s->io_buffer, n,
                                ide_write_dma_cb, bm);
+    ide_dma_submit_check(s, ide_write_dma_cb, bm);
 }
 
 static void ide_sector_write_dma(IDEState *s)
diff -Nur kvm-76/qemu/hw/mips_malta.c kvm-userspace/qemu/hw/mips_malta.c
--- kvm-76/qemu/hw/mips_malta.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/mips_malta.c	2008-10-12 09:38:23.000000000 +0200
@@ -36,6 +36,7 @@
 #include "sysemu.h"
 #include "audio/audio.h"
 #include "boards.h"
+#include "qemu-log.h"
 
 //#define DEBUG_BOARD_INIT
 
@@ -59,8 +60,6 @@
 
 #define MAX_IDE_BUS 2
 
-extern FILE *logfile;
-
 typedef struct {
     uint32_t leds;
     uint32_t brk;
diff -Nur kvm-76/qemu/hw/mips_r4k.c kvm-userspace/qemu/hw/mips_r4k.c
--- kvm-76/qemu/hw/mips_r4k.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/mips_r4k.c	2008-10-12 09:38:23.000000000 +0200
@@ -15,6 +15,7 @@
 #include "sysemu.h"
 #include "boards.h"
 #include "flash.h"
+#include "qemu-log.h"
 
 #ifdef TARGET_WORDS_BIGENDIAN
 #define BIOS_FILENAME "mips_bios.bin"
@@ -35,8 +36,6 @@
 static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
 static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
 
-extern FILE *logfile;
-
 static PITState *pit; /* PIT i8254 */
 
 /* i8254 PIT is attached to the IRQ0 at PIC i8259 */
diff -Nur kvm-76/qemu/hw/nseries.c kvm-userspace/qemu/hw/nseries.c
--- kvm-76/qemu/hw/nseries.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/nseries.c	2008-10-12 09:38:23.000000000 +0200
@@ -31,6 +31,7 @@
 #include "devices.h"
 #include "flash.h"
 #include "hw.h"
+#include "bt.h"
 
 /* Nokia N8x0 support */
 struct n800_s {
@@ -122,10 +123,6 @@
 
 #define N8X0_BD_ADDR			0x00, 0x1a, 0x89, 0x9e, 0x3e, 0x81
 
-typedef struct {
-    uint8_t b[6];
-} __attribute__((packed)) bdaddr_t;	/* XXX: move to BT headers */
-
 static void n800_mmc_cs_cb(void *opaque, int line, int level)
 {
     /* TODO: this seems to actually be connected to the menelaus, to
@@ -744,6 +741,20 @@
     cbus_attach(cbus, s->tahvo = tahvo_init(tahvo_irq, 1));
 }
 
+static void n8x0_uart_setup(struct n800_s *s)
+{
+    CharDriverState *radio = uart_hci_init(
+                    omap2_gpio_in_get(s->cpu->gpif,
+                            N8X0_BT_HOST_WKUP_GPIO)[0]);
+
+    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_RESET_GPIO,
+                    csrhci_pins_get(radio)[csrhci_pin_reset]);
+    omap2_gpio_out_set(s->cpu->gpif, N8X0_BT_WKUP_GPIO,
+                    csrhci_pins_get(radio)[csrhci_pin_wakeup]);
+
+    omap_uart_attach(s->cpu->uart[BT_UART], radio);
+}
+
 static void n8x0_usb_power_cb(void *opaque, int line, int level)
 {
     struct n800_s *s = opaque;
@@ -1309,6 +1320,7 @@
     n8x0_spi_setup(s);
     n8x0_dss_setup(s, ds);
     n8x0_cbus_setup(s);
+    n8x0_uart_setup(s);
     if (usb_enabled)
         n8x0_usb_setup(s);
 
diff -Nur kvm-76/qemu/hw/pc.h kvm-userspace/qemu/hw/pc.h
--- kvm-76/qemu/hw/pc.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/pc.h	2008-10-12 09:38:23.000000000 +0200
@@ -113,6 +113,12 @@
 int piix4_init(PCIBus *bus, int devfn);
 
 /* vga.c */
+enum vga_retrace_method {
+    VGA_RETRACE_DUMB,
+    VGA_RETRACE_PRECISE
+};
+
+extern enum vga_retrace_method vga_retrace_method;
 
 #ifndef TARGET_SPARC
 #define VGA_RAM_SIZE (16 * 1024 * 1024)
diff -Nur kvm-76/qemu/hw/pci.c kvm-userspace/qemu/hw/pci.c
--- kvm-76/qemu/hw/pci.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/pci.c	2008-10-12 09:38:23.000000000 +0200
@@ -568,7 +568,7 @@
     const char *desc;
 } pci_class_desc;
 
-static pci_class_desc pci_class_descriptions[] =
+static const pci_class_desc pci_class_descriptions[] =
 {
     { 0x0100, "SCSI controller"},
     { 0x0101, "IDE controller"},
@@ -612,7 +612,7 @@
 {
     int i, class;
     PCIIORegion *r;
-    pci_class_desc *desc;
+    const pci_class_desc *desc;
 
     term_printf("  Bus %2d, device %3d, function %d:\n",
            d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
diff -Nur kvm-76/qemu/hw/pcnet.c kvm-userspace/qemu/hw/pcnet.c
--- kvm-76/qemu/hw/pcnet.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/pcnet.c	2008-10-12 09:38:23.000000000 +0200
@@ -1877,9 +1877,9 @@
     if (s->pci_dev)
         pci_device_save(s->pci_dev, f);
 
-    qemu_put_be32(f, s->rap);
-    qemu_put_be32(f, s->isr);
-    qemu_put_be32(f, s->lnkst);
+    qemu_put_sbe32(f, s->rap);
+    qemu_put_sbe32(f, s->isr);
+    qemu_put_sbe32(f, s->lnkst);
     qemu_put_be32s(f, &s->rdra);
     qemu_put_be32s(f, &s->tdra);
     qemu_put_buffer(f, s->prom, 16);
@@ -1888,10 +1888,10 @@
     for (i = 0; i < 32; i++)
         qemu_put_be16s(f, &s->bcr[i]);
     qemu_put_be64s(f, &s->timer);
-    qemu_put_be32(f, s->xmit_pos);
-    qemu_put_be32(f, s->recv_pos);
+    qemu_put_sbe32(f, s->xmit_pos);
+    qemu_put_sbe32(f, s->recv_pos);
     qemu_put_buffer(f, s->buffer, 4096);
-    qemu_put_be32(f, s->tx_busy);
+    qemu_put_sbe32(f, s->tx_busy);
     qemu_put_timer(f, s->poll_timer);
 }
 
@@ -1909,9 +1909,9 @@
             return ret;
     }
 
-    qemu_get_be32s(f, (uint32_t*)&s->rap);
-    qemu_get_be32s(f, (uint32_t*)&s->isr);
-    qemu_get_be32s(f, (uint32_t*)&s->lnkst);
+    qemu_get_sbe32s(f, &s->rap);
+    qemu_get_sbe32s(f, &s->isr);
+    qemu_get_sbe32s(f, &s->lnkst);
     qemu_get_be32s(f, &s->rdra);
     qemu_get_be32s(f, &s->tdra);
     qemu_get_buffer(f, s->prom, 16);
@@ -1920,10 +1920,10 @@
     for (i = 0; i < 32; i++)
         qemu_get_be16s(f, &s->bcr[i]);
     qemu_get_be64s(f, &s->timer);
-    qemu_get_be32s(f, (uint32_t*)&s->xmit_pos);
-    qemu_get_be32s(f, (uint32_t*)&s->recv_pos);
+    qemu_get_sbe32s(f, &s->xmit_pos);
+    qemu_get_sbe32s(f, &s->recv_pos);
     qemu_get_buffer(f, s->buffer, 4096);
-    qemu_get_be32s(f, (uint32_t*)&s->tx_busy);
+    qemu_get_sbe32s(f, &s->tx_busy);
     qemu_get_timer(f, s->poll_timer);
 
     return 0;
diff -Nur kvm-76/qemu/hw/pflash_cfi01.c kvm-userspace/qemu/hw/pflash_cfi01.c
--- kvm-76/qemu/hw/pflash_cfi01.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/pflash_cfi01.c	2008-10-12 09:38:23.000000000 +0200
@@ -111,8 +111,8 @@
     else if (pfl->width == 4)
         boff = boff >> 2;
 
-    DPRINTF("%s: reading offset " TARGET_FMT_lx " under cmd %02x\n",
-            __func__, boff, pfl->cmd);
+    DPRINTF("%s: reading offset " TARGET_FMT_lx " under cmd %02x width %d\n",
+            __func__, offset, pfl->cmd, width);
 
     switch (pfl->cmd) {
     case 0x00:
@@ -205,7 +205,7 @@
     cmd = value;
     offset -= pfl->base;
 
-    DPRINTF("%s: offset " TARGET_FMT_lx " %08x %d wcycle 0x%x\n",
+    DPRINTF("%s: writing offset " TARGET_FMT_lx " value %08x width %d wcycle 0x%x\n",
             __func__, offset, value, width, pfl->wcycle);
 
     /* Set the device in I/O access mode */
@@ -267,7 +267,7 @@
         case 0x20: /* Block erase */
         case 0x28:
             if (cmd == 0xd0) { /* confirm */
-                pfl->wcycle = 1;
+                pfl->wcycle = 0;
                 pfl->status |= 0x80;
             } else if (cmd == 0xff) { /* read array mode */
                 goto reset_flash;
diff -Nur kvm-76/qemu/hw/ppc.c kvm-userspace/qemu/hw/ppc.c
--- kvm-76/qemu/hw/ppc.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/ppc.c	2008-10-12 09:38:23.000000000 +0200
@@ -26,13 +26,11 @@
 #include "qemu-timer.h"
 #include "sysemu.h"
 #include "nvram.h"
+#include "qemu-log.h"
 
 //#define PPC_DEBUG_IRQ
 //#define PPC_DEBUG_TB
 
-extern FILE *logfile;
-extern int loglevel;
-
 static void cpu_ppc_tb_stop (CPUState *env);
 static void cpu_ppc_tb_start (CPUState *env);
 
diff -Nur kvm-76/qemu/hw/ppc405_boards.c kvm-userspace/qemu/hw/ppc405_boards.c
--- kvm-76/qemu/hw/ppc405_boards.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/ppc405_boards.c	2008-10-12 09:38:24.000000000 +0200
@@ -29,9 +29,7 @@
 #include "sysemu.h"
 #include "block.h"
 #include "boards.h"
-
-extern int loglevel;
-extern FILE *logfile;
+#include "qemu-log.h"
 
 #define BIOS_FILENAME "ppc405_rom.bin"
 #undef BIOS_SIZE
diff -Nur kvm-76/qemu/hw/ppc405_uc.c kvm-userspace/qemu/hw/ppc405_uc.c
--- kvm-76/qemu/hw/ppc405_uc.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/ppc405_uc.c	2008-10-12 09:38:24.000000000 +0200
@@ -27,9 +27,7 @@
 #include "pc.h"
 #include "qemu-timer.h"
 #include "sysemu.h"
-
-extern int loglevel;
-extern FILE *logfile;
+#include "qemu-log.h"
 
 #define DEBUG_OPBA
 #define DEBUG_SDRAM
diff -Nur kvm-76/qemu/hw/ppc4xx_devs.c kvm-userspace/qemu/hw/ppc4xx_devs.c
--- kvm-76/qemu/hw/ppc4xx_devs.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/ppc4xx_devs.c	2008-10-12 09:38:24.000000000 +0200
@@ -28,12 +28,10 @@
 #include "ppc.h"
 #include "ppc4xx.h"
 #include "sysemu.h"
+#include "qemu-log.h"
 #include "pci.h"
 #include "bswap.h"
 
-extern int loglevel;
-extern FILE *logfile;
-
 //#define DEBUG_MMIO
 //#define DEBUG_UNASSIGNED
 #define DEBUG_UIC
diff -Nur kvm-76/qemu/hw/ppc_prep.c kvm-userspace/qemu/hw/ppc_prep.c
--- kvm-76/qemu/hw/ppc_prep.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/ppc_prep.c	2008-10-12 09:38:24.000000000 +0200
@@ -31,6 +31,7 @@
 #include "pci.h"
 #include "ppc.h"
 #include "boards.h"
+#include "qemu-log.h"
 
 //#define HARD_DEBUG_PPC_IO
 //#define DEBUG_PPC_IO
@@ -44,9 +45,6 @@
 #define KERNEL_LOAD_ADDR 0x01000000
 #define INITRD_LOAD_ADDR 0x01800000
 
-extern int loglevel;
-extern FILE *logfile;
-
 #if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
 #define DEBUG_PPC_IO
 #endif
diff -Nur kvm-76/qemu/hw/ptimer.c kvm-userspace/qemu/hw/ptimer.c
--- kvm-76/qemu/hw/ptimer.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/ptimer.c	2008-10-12 09:38:24.000000000 +0200
@@ -165,9 +165,9 @@
     qemu_put_be64s(f, &s->limit);
     qemu_put_be64s(f, &s->delta);
     qemu_put_be32s(f, &s->period_frac);
-    qemu_put_be64s(f, &s->period);
-    qemu_put_be64s(f, &s->last_event);
-    qemu_put_be64s(f, &s->next_event);
+    qemu_put_sbe64s(f, &s->period);
+    qemu_put_sbe64s(f, &s->last_event);
+    qemu_put_sbe64s(f, &s->next_event);
     qemu_put_timer(f, s->timer);
 }
 
@@ -177,9 +177,9 @@
     qemu_get_be64s(f, &s->limit);
     qemu_get_be64s(f, &s->delta);
     qemu_get_be32s(f, &s->period_frac);
-    qemu_get_be64s(f, &s->period);
-    qemu_get_be64s(f, &s->last_event);
-    qemu_get_be64s(f, &s->next_event);
+    qemu_get_sbe64s(f, &s->period);
+    qemu_get_sbe64s(f, &s->last_event);
+    qemu_get_sbe64s(f, &s->next_event);
     qemu_get_timer(f, s->timer);
 }
 
diff -Nur kvm-76/qemu/hw/pxa2xx.c kvm-userspace/qemu/hw/pxa2xx.c
--- kvm-76/qemu/hw/pxa2xx.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/pxa2xx.c	2008-10-12 09:38:24.000000000 +0200
@@ -1233,9 +1233,9 @@
     qemu_put_be32s(f, &s->last_rycr);
     qemu_put_be32s(f, &s->last_swcr);
     qemu_put_be32s(f, &s->last_rtcpicr);
-    qemu_put_be64s(f, (uint64_t *) &s->last_hz);
-    qemu_put_be64s(f, (uint64_t *) &s->last_sw);
-    qemu_put_be64s(f, (uint64_t *) &s->last_pi);
+    qemu_put_sbe64s(f, &s->last_hz);
+    qemu_put_sbe64s(f, &s->last_sw);
+    qemu_put_sbe64s(f, &s->last_pi);
 }
 
 static int pxa2xx_rtc_load(QEMUFile *f, void *opaque, int version_id)
@@ -1257,9 +1257,9 @@
     qemu_get_be32s(f, &s->last_rycr);
     qemu_get_be32s(f, &s->last_swcr);
     qemu_get_be32s(f, &s->last_rtcpicr);
-    qemu_get_be64s(f, (uint64_t *) &s->last_hz);
-    qemu_get_be64s(f, (uint64_t *) &s->last_sw);
-    qemu_get_be64s(f, (uint64_t *) &s->last_pi);
+    qemu_get_sbe64s(f, &s->last_hz);
+    qemu_get_sbe64s(f, &s->last_sw);
+    qemu_get_sbe64s(f, &s->last_pi);
 
     pxa2xx_rtc_alarm_update(s, s->rtsr);
 
diff -Nur kvm-76/qemu/hw/pxa2xx_timer.c kvm-userspace/qemu/hw/pxa2xx_timer.c
--- kvm-76/qemu/hw/pxa2xx_timer.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/pxa2xx_timer.c	2008-10-12 09:38:24.000000000 +0200
@@ -384,8 +384,8 @@
         for (i = 0; i < 8; i ++) {
             qemu_put_be32s(f, &s->tm4[i].tm.value);
             qemu_put_be32(f, s->tm4[i].tm.level);
-            qemu_put_be32s(f, (uint32_t *) &s->tm4[i].oldclock);
-            qemu_put_be32s(f, (uint32_t *) &s->tm4[i].clock);
+            qemu_put_sbe32s(f, &s->tm4[i].oldclock);
+            qemu_put_sbe32s(f, &s->tm4[i].clock);
             qemu_put_be64s(f, &s->tm4[i].lastload);
             qemu_put_be32s(f, &s->tm4[i].freq);
             qemu_put_be32s(f, &s->tm4[i].control);
@@ -418,8 +418,8 @@
         for (i = 0; i < 8; i ++) {
             qemu_get_be32s(f, &s->tm4[i].tm.value);
             s->tm4[i].tm.level = qemu_get_be32(f);
-            qemu_get_be32s(f, (uint32_t *) &s->tm4[i].oldclock);
-            qemu_get_be32s(f, (uint32_t *) &s->tm4[i].clock);
+            qemu_get_sbe32s(f, &s->tm4[i].oldclock);
+            qemu_get_sbe32s(f, &s->tm4[i].clock);
             qemu_get_be64s(f, &s->tm4[i].lastload);
             qemu_get_be32s(f, &s->tm4[i].freq);
             qemu_get_be32s(f, &s->tm4[i].control);
diff -Nur kvm-76/qemu/hw/realview.c kvm-userspace/qemu/hw/realview.c
--- kvm-76/qemu/hw/realview.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/realview.c	2008-10-12 09:38:24.000000000 +0200
@@ -198,8 +198,9 @@
 }
 
 QEMUMachine realview_machine = {
-    "realview",
-    "ARM RealView Emulation Baseboard (ARM926EJ-S)",
-    realview_init,
-    0x1000
+    .name = "realview",
+    .desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
+    .init = realview_init,
+    .ram_require = 0x1000,
+    .use_scsi = 1,
 };
diff -Nur kvm-76/qemu/hw/sun4m.c kvm-userspace/qemu/hw/sun4m.c
--- kvm-76/qemu/hw/sun4m.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/sun4m.c	2008-10-12 09:38:24.000000000 +0200
@@ -175,8 +175,6 @@
     return 0;
 }
 
-extern int nographic;
-
 static void nvram_init(m48t59_t *nvram, uint8_t *macaddr, const char *cmdline,
                        const char *boot_devices, ram_addr_t RAM_size,
                        uint32_t kernel_size,
@@ -693,7 +691,7 @@
     slavio_serial_init(hwdef->serial_base, slavio_irq[hwdef->ser_irq],
                        serial_hds[1], serial_hds[0]);
 
-    slavio_misc = slavio_misc_init(-1, hwdef->apc_base,
+    slavio_misc = slavio_misc_init(0, hwdef->apc_base,
                                    hwdef->aux1_base, hwdef->aux2_base,
                                    slavio_irq[hwdef->me_irq], env, &fdc_tc);
 
@@ -1292,6 +1290,7 @@
     .init = ss5_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine ss10_machine = {
@@ -1300,6 +1299,7 @@
     .init = ss10_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine ss600mp_machine = {
@@ -1308,6 +1308,7 @@
     .init = ss600mp_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine ss20_machine = {
@@ -1316,6 +1317,7 @@
     .init = ss20_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine ss2_machine = {
@@ -1324,6 +1326,7 @@
     .init = ss2_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine voyager_machine = {
@@ -1332,6 +1335,7 @@
     .init = vger_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine ss_lx_machine = {
@@ -1340,6 +1344,7 @@
     .init = ss_lx_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine ss4_machine = {
@@ -1348,6 +1353,7 @@
     .init = ss4_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine scls_machine = {
@@ -1356,6 +1362,7 @@
     .init = scls_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine sbook_machine = {
@@ -1364,6 +1371,7 @@
     .init = sbook_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 static const struct sun4d_hwdef sun4d_hwdefs[] = {
@@ -1611,6 +1619,7 @@
     .init = ss1000_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
 
 QEMUMachine ss2000_machine = {
@@ -1619,4 +1628,5 @@
     .init = ss2000_init,
     .ram_require = PROM_SIZE_MAX + TCX_SIZE,
     .nodisk_ok = 1,
+    .use_scsi = 1,
 };
diff -Nur kvm-76/qemu/hw/sun4u.c kvm-userspace/qemu/hw/sun4u.c
--- kvm-76/qemu/hw/sun4u.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/sun4u.c	2008-10-12 09:38:24.000000000 +0200
@@ -46,7 +46,6 @@
 #define CMDLINE_ADDR         0x003ff000
 #define INITRD_LOAD_ADDR     0x00300000
 #define PROM_SIZE_MAX        (4 * 1024 * 1024)
-#define PROM_ADDR            0x1fff0000000ULL
 #define PROM_VADDR           0x000ffd00000ULL
 #define APB_SPECIAL_BASE     0x1fe00000000ULL
 #define APB_MEM_BASE         0x1ff00000000ULL
@@ -61,6 +60,8 @@
 struct hwdef {
     const char * const default_cpu_model;
     uint16_t machine_id;
+    uint64_t prom_addr;
+    uint64_t console_serial_base;
 };
 
 int DMA_get_channel_mode (int nchan)
@@ -107,8 +108,6 @@
     return 0;
 }
 
-extern int nographic;
-
 static int sun4u_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
                                    const char *arch,
                                    ram_addr_t RAM_size,
@@ -260,9 +259,15 @@
 {
 }
 
+typedef struct ResetData {
+    CPUState *env;
+    uint64_t reset_addr;
+} ResetData;
+
 static void main_cpu_reset(void *opaque)
 {
-    CPUState *env = opaque;
+    ResetData *s = (ResetData *)opaque;
+    CPUState *env = s->env;
 
     cpu_reset(env);
     ptimer_set_limit(env->tick, 0x7fffffffffffffffULL, 1);
@@ -271,6 +276,11 @@
     ptimer_run(env->stick, 0);
     ptimer_set_limit(env->hstick, 0x7fffffffffffffffULL, 1);
     ptimer_run(env->hstick, 0);
+    env->gregs[1] = 0; // Memory start
+    env->gregs[2] = ram_size; // Memory size
+    env->gregs[3] = 0; // Machine description XXX
+    env->pc = s->reset_addr;
+    env->npc = env->pc + 4;
 }
 
 static void tick_irq(void *opaque)
@@ -297,6 +307,21 @@
     cpu_interrupt(env, CPU_INTERRUPT_TIMER);
 }
 
+void cpu_tick_set_count(void *opaque, uint64_t count)
+{
+    ptimer_set_count(opaque, -count);
+}
+
+uint64_t cpu_tick_get_count(void *opaque)
+{
+    return -ptimer_get_count(opaque);
+}
+
+void cpu_tick_set_limit(void *opaque, uint64_t limit)
+{
+    ptimer_set_limit(opaque, -limit, 0);
+}
+
 static const int ide_iobase[2] = { 0x1f0, 0x170 };
 static const int ide_iobase2[2] = { 0x3f6, 0x376 };
 static const int ide_irq[2] = { 14, 15 };
@@ -328,6 +353,7 @@
     BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
     BlockDriverState *fd[MAX_FD];
     void *fw_cfg;
+    ResetData *reset_info;
 
     linux_boot = (kernel_filename != NULL);
 
@@ -351,14 +377,21 @@
     bh = qemu_bh_new(hstick_irq, env);
     env->hstick = ptimer_init(bh);
     ptimer_set_period(env->hstick, 1ULL);
-    qemu_register_reset(main_cpu_reset, env);
-    main_cpu_reset(env);
+
+    reset_info = qemu_mallocz(sizeof(ResetData));
+    reset_info->env = env;
+    reset_info->reset_addr = hwdef->prom_addr + 0x40ULL;
+    qemu_register_reset(main_cpu_reset, reset_info);
+    main_cpu_reset(reset_info);
+    // Override warm reset address with cold start address
+    env->pc = hwdef->prom_addr + 0x20ULL;
+    env->npc = env->pc + 4;
 
     /* allocate RAM */
     cpu_register_physical_memory(0, RAM_size, 0);
 
     prom_offset = RAM_size + vga_ram_size;
-    cpu_register_physical_memory(PROM_ADDR,
+    cpu_register_physical_memory(hwdef->prom_addr,
                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE) &
                                  TARGET_PAGE_MASK,
                                  prom_offset | IO_MEM_ROM);
@@ -366,11 +399,16 @@
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     snprintf(buf, sizeof(buf), "%s/%s", bios_dir, bios_name);
-    ret = load_elf(buf, PROM_ADDR - PROM_VADDR, NULL, NULL, NULL);
+    ret = load_elf(buf, hwdef->prom_addr - PROM_VADDR, NULL, NULL, NULL);
     if (ret < 0) {
-        fprintf(stderr, "qemu: could not load prom '%s'\n",
-                buf);
-        exit(1);
+        ret = load_image_targphys(buf, hwdef->prom_addr,
+                                  (PROM_SIZE_MAX + TARGET_PAGE_SIZE) &
+                                  TARGET_PAGE_MASK);
+        if (ret < 0) {
+            fprintf(stderr, "qemu: could not load prom '%s'\n",
+                    buf);
+            exit(1);
+        }
     }
 
     kernel_size = 0;
@@ -417,7 +455,13 @@
     pci_cirrus_vga_init(pci_bus, ds, phys_ram_base + RAM_size, RAM_size,
                         vga_ram_size);
 
-    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+    i = 0;
+    if (hwdef->console_serial_base) {
+        serial_mm_init(hwdef->console_serial_base, 0, NULL, 115200,
+                       serial_hds[i], 1);
+        i++;
+    }
+    for(; i < MAX_SERIAL_PORTS; i++) {
         if (serial_hds[i]) {
             serial_init(serial_io[i], NULL/*serial_irq[i]*/, 115200,
                         serial_hds[i]);
@@ -483,6 +527,7 @@
 enum {
     sun4u_id = 0,
     sun4v_id = 64,
+    niagara_id,
 };
 
 static const struct hwdef hwdefs[] = {
@@ -490,11 +535,22 @@
     {
         .default_cpu_model = "TI UltraSparc II",
         .machine_id = sun4u_id,
+        .prom_addr = 0x1fff0000000ULL,
+        .console_serial_base = 0,
     },
     /* Sun4v generic PC-like machine */
     {
         .default_cpu_model = "Sun UltraSparc T1",
         .machine_id = sun4v_id,
+        .prom_addr = 0x1fff0000000ULL,
+        .console_serial_base = 0,
+    },
+    /* Sun4v generic Niagara machine */
+    {
+        .default_cpu_model = "Sun UltraSparc T1",
+        .machine_id = niagara_id,
+        .prom_addr = 0xfff0000000ULL,
+        .console_serial_base = 0xfff0c2c000ULL,
     },
 };
 
@@ -518,6 +574,16 @@
                 kernel_cmdline, initrd_filename, cpu_model, &hwdefs[1]);
 }
 
+/* Niagara hardware initialisation */
+static void niagara_init(ram_addr_t RAM_size, int vga_ram_size,
+                         const char *boot_devices, DisplayState *ds,
+                         const char *kernel_filename, const char *kernel_cmdline,
+                         const char *initrd_filename, const char *cpu_model)
+{
+    sun4uv_init(RAM_size, vga_ram_size, boot_devices, ds, kernel_filename,
+                kernel_cmdline, initrd_filename, cpu_model, &hwdefs[2]);
+}
+
 QEMUMachine sun4u_machine = {
     .name = "sun4u",
     .desc = "Sun4u platform",
@@ -533,3 +599,11 @@
     .ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE,
     .nodisk_ok = 1,
 };
+
+QEMUMachine niagara_machine = {
+    .name = "Niagara",
+    .desc = "Sun4v platform, Niagara",
+    .init = niagara_init,
+    .ram_require = PROM_SIZE_MAX + VGA_RAM_SIZE,
+    .nodisk_ok = 1,
+};
diff -Nur kvm-76/qemu/hw/tcx.c kvm-userspace/qemu/hw/tcx.c
--- kvm-76/qemu/hw/tcx.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/tcx.c	2008-10-12 09:38:24.000000000 +0200
@@ -372,9 +372,9 @@
 {
     TCXState *s = opaque;
 
-    qemu_put_be16s(f, (uint16_t *)&s->height);
-    qemu_put_be16s(f, (uint16_t *)&s->width);
-    qemu_put_be16s(f, (uint16_t *)&s->depth);
+    qemu_put_be16s(f, &s->height);
+    qemu_put_be16s(f, &s->width);
+    qemu_put_be16s(f, &s->depth);
     qemu_put_buffer(f, s->r, 256);
     qemu_put_buffer(f, s->g, 256);
     qemu_put_buffer(f, s->b, 256);
@@ -391,13 +391,13 @@
         return -EINVAL;
 
     if (version_id == 3) {
-        qemu_get_be32s(f, (uint32_t *)&dummy);
-        qemu_get_be32s(f, (uint32_t *)&dummy);
-        qemu_get_be32s(f, (uint32_t *)&dummy);
+        qemu_get_be32s(f, &dummy);
+        qemu_get_be32s(f, &dummy);
+        qemu_get_be32s(f, &dummy);
     }
-    qemu_get_be16s(f, (uint16_t *)&s->height);
-    qemu_get_be16s(f, (uint16_t *)&s->width);
-    qemu_get_be16s(f, (uint16_t *)&s->depth);
+    qemu_get_be16s(f, &s->height);
+    qemu_get_be16s(f, &s->width);
+    qemu_get_be16s(f, &s->depth);
     qemu_get_buffer(f, s->r, 256);
     qemu_get_buffer(f, s->g, 256);
     qemu_get_buffer(f, s->b, 256);
diff -Nur kvm-76/qemu/hw/tmp105.c kvm-userspace/qemu/hw/tmp105.c
--- kvm-76/qemu/hw/tmp105.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/tmp105.c	2008-10-12 09:38:24.000000000 +0200
@@ -185,9 +185,9 @@
 
     qemu_put_8s(f, &s->pointer);
     qemu_put_8s(f, &s->config);
-    qemu_put_be16s(f, (uint16_t *) &s->temperature);
-    qemu_put_be16s(f, (uint16_t *) &s->limit[0]);
-    qemu_put_be16s(f, (uint16_t *) &s->limit[1]);
+    qemu_put_sbe16s(f, &s->temperature);
+    qemu_put_sbe16s(f, &s->limit[0]);
+    qemu_put_sbe16s(f, &s->limit[1]);
     qemu_put_byte(f, s->alarm);
     s->faults = tmp105_faultq[(s->config >> 3) & 3];		/* F */
 
@@ -204,9 +204,9 @@
 
     qemu_get_8s(f, &s->pointer);
     qemu_get_8s(f, &s->config);
-    qemu_get_be16s(f, (uint16_t *) &s->temperature);
-    qemu_get_be16s(f, (uint16_t *) &s->limit[0]);
-    qemu_get_be16s(f, (uint16_t *) &s->limit[1]);
+    qemu_get_sbe16s(f, &s->temperature);
+    qemu_get_sbe16s(f, &s->limit[0]);
+    qemu_get_sbe16s(f, &s->limit[1]);
     s->alarm = qemu_get_byte(f);
 
     tmp105_interrupt_update(s);
diff -Nur kvm-76/qemu/hw/tsc210x.c kvm-userspace/qemu/hw/tsc210x.c
--- kvm-76/qemu/hw/tsc210x.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/tsc210x.c	2008-10-12 09:38:24.000000000 +0200
@@ -1046,8 +1046,8 @@
     qemu_put_be16s(f, &s->pll[0]);
     qemu_put_be16s(f, &s->pll[1]);
     qemu_put_be16s(f, &s->volume);
-    qemu_put_be64(f, (uint64_t) (s->volume_change - now));
-    qemu_put_be64(f, (uint64_t) (s->powerdown - now));
+    qemu_put_sbe64(f, (s->volume_change - now));
+    qemu_put_sbe64(f, (s->powerdown - now));
     qemu_put_byte(f, s->softstep);
     qemu_put_be16s(f, &s->dac_power);
 
@@ -1092,8 +1092,8 @@
     qemu_get_be16s(f, &s->pll[0]);
     qemu_get_be16s(f, &s->pll[1]);
     qemu_get_be16s(f, &s->volume);
-    s->volume_change = (int64_t) qemu_get_be64(f) + now;
-    s->powerdown = (int64_t) qemu_get_be64(f) + now;
+    s->volume_change = qemu_get_sbe64(f) + now;
+    s->powerdown = qemu_get_sbe64(f) + now;
     s->softstep = qemu_get_byte(f);
     qemu_get_be16s(f, &s->dac_power);
 
diff -Nur kvm-76/qemu/hw/usb-bt.c kvm-userspace/qemu/hw/usb-bt.c
--- kvm-76/qemu/hw/usb-bt.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/hw/usb-bt.c	2008-10-12 09:38:24.000000000 +0200
@@ -0,0 +1,647 @@
+/*
+ * QEMU Bluetooth HCI USB Transport Layer v1.0
+ *
+ * Copyright (C) 2007 OpenMoko, Inc.
+ * Copyright (C) 2008 Andrzej Zaborowski  <balrog@zabor.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "qemu-common.h"
+#include "usb.h"
+#include "net.h"
+#include "bt.h"
+
+struct USBBtState {
+    USBDevice dev;
+    struct HCIInfo *hci;
+
+    int altsetting;
+    int config;
+
+#define CFIFO_LEN_MASK	255
+#define DFIFO_LEN_MASK	4095
+    struct usb_hci_in_fifo_s {
+        uint8_t data[(DFIFO_LEN_MASK + 1) * 2];
+        struct {
+            uint8_t *data;
+            int len;
+        } fifo[CFIFO_LEN_MASK + 1];
+        int dstart, dlen, dsize, start, len;
+    } evt, acl, sco;
+
+    struct usb_hci_out_fifo_s {
+        uint8_t data[4096];
+	int len;
+    } outcmd, outacl, outsco;
+};
+
+#define USB_EVT_EP	1
+#define USB_ACL_EP	2
+#define USB_SCO_EP	3
+
+static const uint8_t qemu_bt_dev_descriptor[] = {
+    0x12,		/*  u8 bLength; */
+    USB_DT_DEVICE,	/*  u8 bDescriptorType; Device */
+    0x10, 0x01,		/*  u16 bcdUSB; v1.10 */
+
+    0xe0,	/*  u8  bDeviceClass; Wireless */
+    0x01,	/*  u8  bDeviceSubClass; Radio Frequency */
+    0x01,	/*  u8  bDeviceProtocol; Bluetooth */
+    0x40,	/*  u8  bMaxPacketSize0; 64 Bytes */
+
+    0x12, 0x0a,	/*  u16 idVendor; */
+    0x01, 0x00,	/*  u16 idProduct; Bluetooth Dongle (HCI mode) */
+    0x58, 0x19,	/*  u16 bcdDevice; (some devices have 0x48, 0x02) */
+
+    0x00,	/*  u8  iManufacturer; */
+    0x00,	/*  u8  iProduct; */
+    0x00,	/*  u8  iSerialNumber; */
+    0x01,	/*  u8  bNumConfigurations; */
+};
+
+static const uint8_t qemu_bt_config_descriptor[] = {
+    /* one configuration */
+    0x09,		/*  u8  bLength; */
+    USB_DT_CONFIG,	/*  u8  bDescriptorType; */
+    0xb1, 0x00,		/*  u16 wTotalLength; */
+    0x02,		/*  u8  bNumInterfaces; (2) */
+    0x01,		/*  u8  bConfigurationValue; */
+    0x00,		/*  u8  iConfiguration; */
+    0xc0,		/*  u8  bmAttributes;
+				     Bit 7: must be set,
+					 6: Self-powered,
+					 5: Remote wakeup,
+					 4..0: resvd */
+    0x00,		/*  u8  MaxPower; */
+
+    /* USB 1.1:
+     * USB 2.0, single TT organization (mandatory):
+     *	one interface, protocol 0
+     *
+     * USB 2.0, multiple TT organization (optional):
+     *	two interfaces, protocols 1 (like single TT)
+     *	and 2 (multiple TT mode) ... config is
+     *	sometimes settable
+     *	NOT IMPLEMENTED
+     */
+
+    /* interface one */
+    0x09,		/*  u8  if_bLength; */
+    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
+    0x00,		/*  u8  if_bInterfaceNumber; */
+    0x00,		/*  u8  if_bAlternateSetting; */
+    0x03,		/*  u8  if_bNumEndpoints; */
+    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
+    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
+    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
+    0x00,		/*  u8  if_iInterface; */
+
+    /* endpoint one */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_EVT_EP,	/*  u8  ep_bEndpointAddress; */
+    0x03,		/*  u8  ep_bmAttributes; Interrupt */
+    0x10, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x02,		/*  u8  ep_bInterval; */
+
+    /* endpoint two */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_OUT | USB_ACL_EP,	/*  u8  ep_bEndpointAddress; */
+    0x02,		/*  u8  ep_bmAttributes; Bulk */
+    0x40, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x0a,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* endpoint three */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_ACL_EP,	/*  u8  ep_bEndpointAddress; */
+    0x02,		/*  u8  ep_bmAttributes; Bulk */
+    0x40, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x0a,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* interface two setting one */
+    0x09,		/*  u8  if_bLength; */
+    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
+    0x01,		/*  u8  if_bInterfaceNumber; */
+    0x00,		/*  u8  if_bAlternateSetting; */
+    0x02,		/*  u8  if_bNumEndpoints; */
+    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
+    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
+    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
+    0x00,		/*  u8  if_iInterface; */
+
+    /* endpoint one */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x00, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* endpoint two */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x00, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* interface two setting two */
+    0x09,		/*  u8  if_bLength; */
+    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
+    0x01,		/*  u8  if_bInterfaceNumber; */
+    0x01,		/*  u8  if_bAlternateSetting; */
+    0x02,		/*  u8  if_bNumEndpoints; */
+    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
+    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
+    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
+    0x00,		/*  u8  if_iInterface; */
+
+    /* endpoint one */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x09, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* endpoint two */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x09, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* interface two setting three */
+    0x09,		/*  u8  if_bLength; */
+    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
+    0x01,		/*  u8  if_bInterfaceNumber; */
+    0x02,		/*  u8  if_bAlternateSetting; */
+    0x02,		/*  u8  if_bNumEndpoints; */
+    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
+    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
+    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
+    0x00,		/*  u8  if_iInterface; */
+
+    /* endpoint one */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x11, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* endpoint two */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x11, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* interface two setting four */
+    0x09,		/*  u8  if_bLength; */
+    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
+    0x01,		/*  u8  if_bInterfaceNumber; */
+    0x03,		/*  u8  if_bAlternateSetting; */
+    0x02,		/*  u8  if_bNumEndpoints; */
+    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
+    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
+    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
+    0x00,		/*  u8  if_iInterface; */
+
+    /* endpoint one */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x19, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* endpoint two */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x19, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* interface two setting five */
+    0x09,		/*  u8  if_bLength; */
+    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
+    0x01,		/*  u8  if_bInterfaceNumber; */
+    0x04,		/*  u8  if_bAlternateSetting; */
+    0x02,		/*  u8  if_bNumEndpoints; */
+    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
+    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
+    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
+    0x00,		/*  u8  if_iInterface; */
+
+    /* endpoint one */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x21, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* endpoint two */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x21, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* interface two setting six */
+    0x09,		/*  u8  if_bLength; */
+    USB_DT_INTERFACE,	/*  u8  if_bDescriptorType; */
+    0x01,		/*  u8  if_bInterfaceNumber; */
+    0x05,		/*  u8  if_bAlternateSetting; */
+    0x02,		/*  u8  if_bNumEndpoints; */
+    0xe0,		/*  u8  if_bInterfaceClass; Wireless */
+    0x01,		/*  u8  if_bInterfaceSubClass; Radio Frequency */
+    0x01,		/*  u8  if_bInterfaceProtocol; Bluetooth */
+    0x00,		/*  u8  if_iInterface; */
+
+    /* endpoint one */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_OUT | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x31, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* endpoint two */
+    0x07,		/*  u8  ep_bLength; */
+    USB_DT_ENDPOINT,	/*  u8  ep_bDescriptorType; */
+    USB_DIR_IN | USB_SCO_EP,	/*  u8  ep_bEndpointAddress; */
+    0x01,		/*  u8  ep_bmAttributes; Isochronous */
+    0x31, 0x00,		/*  u16 ep_wMaxPacketSize; */
+    0x01,		/*  u8  ep_bInterval; (255ms -- usb 2.0 spec) */
+
+    /* If implemented, the DFU interface descriptor goes here with no
+     * endpoints or alternative settings.  */
+};
+
+static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
+{
+    fifo->dstart = 0;
+    fifo->dlen = 0;
+    fifo->dsize = DFIFO_LEN_MASK + 1;
+    fifo->start = 0;
+    fifo->len = 0;
+}
+
+static void usb_bt_fifo_enqueue(struct usb_hci_in_fifo_s *fifo,
+                const uint8_t *data, int len)
+{
+    int off = fifo->dstart + fifo->dlen;
+    uint8_t *buf;
+
+    fifo->dlen += len;
+    if (off <= DFIFO_LEN_MASK) {
+        if (off + len > DFIFO_LEN_MASK + 1 &&
+                        (fifo->dsize = off + len) > (DFIFO_LEN_MASK + 1) * 2) {
+            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
+            exit(-1);
+        }
+        buf = fifo->data + off;
+    } else {
+        if (fifo->dlen > fifo->dsize) {
+            fprintf(stderr, "%s: can't alloc %i bytes\n", __FUNCTION__, len);
+            exit(-1);
+        }
+        buf = fifo->data + off - fifo->dsize;
+    }
+
+    off = (fifo->start + fifo->len ++) & CFIFO_LEN_MASK;
+    fifo->fifo[off].data = memcpy(buf, data, len);
+    fifo->fifo[off].len = len;
+}
+
+static inline int usb_bt_fifo_dequeue(struct usb_hci_in_fifo_s *fifo,
+                USBPacket *p)
+{
+    int len;
+
+    if (likely(!fifo->len))
+        return USB_RET_STALL;
+
+    len = MIN(p->len, fifo->fifo[fifo->start].len);
+    memcpy(p->data, fifo->fifo[fifo->start].data, len);
+    if (len == p->len) {
+        fifo->fifo[fifo->start].len -= len;
+        fifo->fifo[fifo->start].data += len;
+    } else {
+        fifo->start ++;
+        fifo->start &= CFIFO_LEN_MASK;
+        fifo->len --;
+    }
+
+    fifo->dstart += len;
+    fifo->dlen -= len;
+    if (fifo->dstart >= fifo->dsize) {
+        fifo->dstart = 0;
+        fifo->dsize = DFIFO_LEN_MASK + 1;
+    }
+
+    return len;
+}
+
+static void inline usb_bt_fifo_out_enqueue(struct USBBtState *s,
+                struct usb_hci_out_fifo_s *fifo,
+                void (*send)(struct HCIInfo *, const uint8_t *, int),
+                int (*complete)(const uint8_t *, int),
+                const uint8_t *data, int len)
+{
+    if (fifo->len) {
+        memcpy(fifo->data + fifo->len, data, len);
+        fifo->len += len;
+        if (complete(fifo->data, fifo->len)) {
+            send(s->hci, fifo->data, fifo->len);
+            fifo->len = 0;
+        }
+    } else if (complete(data, len))
+        send(s->hci, data, len);
+    else {
+        memcpy(fifo->data, data, len);
+        fifo->len = len;
+    }
+
+    /* TODO: do we need to loop? */
+}
+
+static int usb_bt_hci_cmd_complete(const uint8_t *data, int len)
+{
+    len -= HCI_COMMAND_HDR_SIZE;
+    return len >= 0 &&
+            len >= ((struct hci_command_hdr *) data)->plen;
+}
+
+static int usb_bt_hci_acl_complete(const uint8_t *data, int len)
+{
+    len -= HCI_ACL_HDR_SIZE;
+    return len >= 0 &&
+            len >= le16_to_cpu(((struct hci_acl_hdr *) data)->dlen);
+}
+
+static int usb_bt_hci_sco_complete(const uint8_t *data, int len)
+{
+    len -= HCI_SCO_HDR_SIZE;
+    return len >= 0 &&
+            len >= ((struct hci_sco_hdr *) data)->dlen;
+}
+
+static void usb_bt_handle_reset(USBDevice *dev)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+
+    usb_bt_fifo_reset(&s->evt);
+    usb_bt_fifo_reset(&s->acl);
+    usb_bt_fifo_reset(&s->sco);
+    s->outcmd.len = 0;
+    s->outacl.len = 0;
+    s->outsco.len = 0;
+    s->altsetting = 0;
+}
+
+static int usb_bt_handle_control(USBDevice *dev, int request, int value,
+                int index, int length, uint8_t *data)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+    int ret = 0;
+
+    switch (request) {
+    case DeviceRequest | USB_REQ_GET_STATUS:
+    case InterfaceRequest | USB_REQ_GET_STATUS:
+    case EndpointRequest | USB_REQ_GET_STATUS:
+        data[0] = (1 << USB_DEVICE_SELF_POWERED) |
+            (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
+        data[1] = 0x00;
+        ret = 2;
+        break;
+    case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+    case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
+    case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 0;
+        } else {
+            goto fail;
+        }
+        ret = 0;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_FEATURE:
+    case InterfaceOutRequest | USB_REQ_SET_FEATURE:
+    case EndpointOutRequest | USB_REQ_SET_FEATURE:
+        if (value == USB_DEVICE_REMOTE_WAKEUP) {
+            dev->remote_wakeup = 1;
+        } else {
+            goto fail;
+        }
+        ret = 0;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+        dev->addr = value;
+        ret = 0;
+        break;
+    case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+        switch (value >> 8) {
+        case USB_DT_DEVICE:
+            ret = sizeof(qemu_bt_dev_descriptor);
+            memcpy(data, qemu_bt_dev_descriptor, ret);
+            break;
+        case USB_DT_CONFIG:
+            ret = sizeof(qemu_bt_config_descriptor);
+            memcpy(data, qemu_bt_config_descriptor, ret);
+            break;
+        case USB_DT_STRING:
+            switch(value & 0xff) {
+            case 0:
+                /* language ids */
+                data[0] = 4;
+                data[1] = 3;
+                data[2] = 0x09;
+                data[3] = 0x04;
+                ret = 4;
+                break;
+            default:
+                goto fail;
+            }
+            break;
+        default:
+            goto fail;
+        }
+        break;
+    case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+        data[0] = qemu_bt_config_descriptor[0x5];
+        ret = 1;
+        s->config = 0;
+        break;
+    case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+        ret = 0;
+        if (value != qemu_bt_config_descriptor[0x5] && value != 0) {
+            printf("%s: Wrong SET_CONFIGURATION request (%i)\n",
+                            __FUNCTION__, value);
+            goto fail;
+        }
+        s->config = 1;
+        usb_bt_fifo_reset(&s->evt);
+        usb_bt_fifo_reset(&s->acl);
+        usb_bt_fifo_reset(&s->sco);
+        break;
+    case InterfaceRequest | USB_REQ_GET_INTERFACE:
+        if (value != 0 || (index & ~1) || length != 1)
+            goto fail;
+        if (index == 1)
+            data[0] = s->altsetting;
+        else
+            data[0] = 0;
+        ret = 1;
+        break;
+    case InterfaceOutRequest | USB_REQ_SET_INTERFACE:
+        if ((index & ~1) || length != 0 ||
+                        (index == 1 && (value < 0 || value > 4)) ||
+                        (index == 0 && value != 0)) {
+            printf("%s: Wrong SET_INTERFACE request (%i, %i)\n",
+                            __FUNCTION__, index, value);
+            goto fail;
+        }
+        s->altsetting = value;
+        ret = 0;
+        break;
+    case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_DEVICE) << 8):
+        if (s->config)
+            usb_bt_fifo_out_enqueue(s, &s->outcmd, s->hci->cmd_send,
+                            usb_bt_hci_cmd_complete, data, length);
+        break;
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+    return ret;
+}
+
+static int usb_bt_handle_data(USBDevice *dev, USBPacket *p)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+    int ret = 0;
+
+    if (!s->config)
+        goto fail;
+
+    switch (p->pid) {
+    case USB_TOKEN_IN:
+        switch (p->devep & 0xf) {
+        case USB_EVT_EP:
+            ret = usb_bt_fifo_dequeue(&s->evt, p);
+            break;
+
+        case USB_ACL_EP:
+            ret = usb_bt_fifo_dequeue(&s->acl, p);
+            break;
+
+        case USB_SCO_EP:
+            ret = usb_bt_fifo_dequeue(&s->sco, p);
+            break;
+
+        default:
+            goto fail;
+        }
+        break;
+
+    case USB_TOKEN_OUT:
+        switch (p->devep & 0xf) {
+        case USB_ACL_EP:
+            usb_bt_fifo_out_enqueue(s, &s->outacl, s->hci->acl_send,
+                            usb_bt_hci_acl_complete, p->data, p->len);
+            break;
+
+        case USB_SCO_EP:
+            usb_bt_fifo_out_enqueue(s, &s->outsco, s->hci->sco_send,
+                            usb_bt_hci_sco_complete, p->data, p->len);
+            break;
+
+        default:
+            goto fail;
+        }
+        break;
+
+    default:
+    fail:
+        ret = USB_RET_STALL;
+        break;
+    }
+
+    return ret;
+}
+
+static void usb_bt_out_hci_packet_event(void *opaque,
+                const uint8_t *data, int len)
+{
+    struct USBBtState *s = (struct USBBtState *) opaque;
+
+    usb_bt_fifo_enqueue(&s->evt, data, len);
+}
+
+static void usb_bt_out_hci_packet_acl(void *opaque,
+                const uint8_t *data, int len)
+{
+    struct USBBtState *s = (struct USBBtState *) opaque;
+
+    usb_bt_fifo_enqueue(&s->acl, data, len);
+}
+
+static void usb_bt_handle_destroy(USBDevice *dev)
+{
+    struct USBBtState *s = (struct USBBtState *) dev->opaque;
+
+    s->hci->opaque = 0;
+    s->hci->evt_recv = 0;
+    s->hci->acl_recv = 0;
+    qemu_free(s);
+}
+
+USBDevice *usb_bt_init(HCIInfo *hci)
+{
+    struct USBBtState *s;
+
+    s = qemu_mallocz(sizeof(struct USBBtState));
+    if (!s)
+        return NULL;
+    s->dev.opaque = s;
+    s->dev.speed = USB_SPEED_HIGH;
+    s->dev.handle_packet = usb_generic_handle_packet;
+    pstrcpy(s->dev.devname, sizeof(s->dev.devname), "QEMU BT dongle");
+
+    s->dev.handle_reset = usb_bt_handle_reset;
+    s->dev.handle_control = usb_bt_handle_control;
+    s->dev.handle_data = usb_bt_handle_data;
+    s->dev.handle_destroy = usb_bt_handle_destroy;
+
+    s->hci = hci;
+    s->hci->opaque = s;
+    s->hci->evt_recv = usb_bt_out_hci_packet_event;
+    s->hci->acl_recv = usb_bt_out_hci_packet_acl;
+
+    usb_bt_handle_reset(&s->dev);
+
+    return &s->dev;
+}
diff -Nur kvm-76/qemu/hw/usb-hid.c kvm-userspace/qemu/hw/usb-hid.c
--- kvm-76/qemu/hw/usb-hid.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/usb-hid.c	2008-10-12 09:38:24.000000000 +0200
@@ -67,6 +67,8 @@
     int protocol;
     int idle;
     int changed;
+    void *datain_opaque;
+    void (*datain)(void *);
 } USBHIDState;
 
 /* mostly the same values as the Bochs USB Mouse device */
@@ -402,6 +404,14 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 };
 
+static void usb_hid_changed(USBHIDState *hs)
+{
+    hs->changed = 1;
+
+    if (hs->datain)
+        hs->datain(hs->datain_opaque);
+}
+
 static void usb_mouse_event(void *opaque,
                             int dx1, int dy1, int dz1, int buttons_state)
 {
@@ -412,7 +422,8 @@
     s->dy += dy1;
     s->dz += dz1;
     s->buttons_state = buttons_state;
-    hs->changed = 1;
+
+    usb_hid_changed(hs);
 }
 
 static void usb_tablet_event(void *opaque,
@@ -425,7 +436,8 @@
     s->y = y;
     s->dz += dz;
     s->buttons_state = buttons_state;
-    hs->changed = 1;
+
+    usb_hid_changed(hs);
 }
 
 static void usb_keyboard_event(void *opaque, int keycode)
@@ -439,8 +451,6 @@
     hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
     s->modifiers &= ~(1 << 8);
 
-    hs->changed = 1;
-
     switch (hid_code) {
     case 0x00:
         return;
@@ -465,15 +475,23 @@
             if (s->key[i] == hid_code) {
                 s->key[i] = s->key[-- s->keys];
                 s->key[s->keys] = 0x00;
-                return;
+                usb_hid_changed(hs);
+                break;
             }
+        if (i < 0)
+            return;
     } else {
         for (i = s->keys - 1; i >= 0; i --)
             if (s->key[i] == hid_code)
-                return;
-        if (s->keys < sizeof(s->key))
-            s->key[s->keys ++] = hid_code;
+                break;
+        if (i < 0) {
+            if (s->keys < sizeof(s->key))
+                s->key[s->keys ++] = hid_code;
+        } else
+            return;
     }
+
+    usb_hid_changed(hs);
 }
 
 static inline int int_clamp(int val, int vmin, int vmax)
@@ -894,3 +912,11 @@
 
     return (USBDevice *) s;
 }
+
+void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
+{
+    USBHIDState *s = (USBHIDState *)dev;
+
+    s->datain_opaque = opaque;
+    s->datain = datain;
+}
diff -Nur kvm-76/qemu/hw/usb.h kvm-userspace/qemu/hw/usb.h
--- kvm-76/qemu/hw/usb.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/usb.h	2008-10-12 09:38:24.000000000 +0200
@@ -247,6 +247,7 @@
 USBDevice *usb_mouse_init(void);
 USBDevice *usb_tablet_init(void);
 USBDevice *usb_keyboard_init(void);
+void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *));
 
 /* usb-msd.c */
 USBDevice *usb_msd_init(const char *filename);
@@ -254,6 +255,9 @@
 /* usb-net.c */
 USBDevice *usb_net_init(NICInfo *nd);
 
+/* usb-bt.c */
+USBDevice *usb_bt_init(HCIInfo *hci);
+
 /* usb-wacom.c */
 USBDevice *usb_wacom_init(void);
 
diff -Nur kvm-76/qemu/hw/versatilepb.c kvm-userspace/qemu/hw/versatilepb.c
--- kvm-76/qemu/hw/versatilepb.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/versatilepb.c	2008-10-12 09:38:24.000000000 +0200
@@ -317,13 +317,15 @@
 }
 
 QEMUMachine versatilepb_machine = {
-    "versatilepb",
-    "ARM Versatile/PB (ARM926EJ-S)",
-    vpb_init,
+    .name = "versatilepb",
+    .desc = "ARM Versatile/PB (ARM926EJ-S)",
+    .init = vpb_init,
+    .use_scsi = 1,
 };
 
 QEMUMachine versatileab_machine = {
-    "versatileab",
-    "ARM Versatile/AB (ARM926EJ-S)",
-    vab_init,
+    .name = "versatileab",
+    .desc = "ARM Versatile/AB (ARM926EJ-S)",
+    .init = vab_init,
+    .use_scsi = 1,
 };
diff -Nur kvm-76/qemu/hw/vga.c kvm-userspace/qemu/hw/vga.c
--- kvm-76/qemu/hw/vga.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/vga.c	2008-10-12 09:38:24.000000000 +0200
@@ -27,6 +27,7 @@
 #include "pci.h"
 #include "vga_int.h"
 #include "pixel_ops.h"
+#include "qemu-timer.h"
 #include "qemu-kvm.h"
 
 #include <sys/mman.h>
@@ -152,6 +153,138 @@
 
 static void vga_screen_dump(void *opaque, const char *filename);
 
+static void vga_dumb_update_retrace_info(VGAState *s)
+{
+    (void) s;
+}
+
+static void vga_precise_update_retrace_info(VGAState *s)
+{
+    int htotal_chars;
+    int hretr_start_char;
+    int hretr_skew_chars;
+    int hretr_end_char;
+
+    int vtotal_lines;
+    int vretr_start_line;
+    int vretr_end_line;
+
+    int div2, sldiv2, dots;
+    int clocking_mode;
+    int clock_sel;
+    const int hz[] = {25175000, 28322000, 25175000, 25175000};
+    int64_t chars_per_sec;
+    struct vga_precise_retrace *r = &s->retrace_info.precise;
+
+    htotal_chars = s->cr[0x00] + 5;
+    hretr_start_char = s->cr[0x04];
+    hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
+    hretr_end_char = s->cr[0x05] & 0x1f;
+
+    vtotal_lines = (s->cr[0x06]
+                    | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
+        ;
+    vretr_start_line = s->cr[0x10]
+        | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
+        ;
+    vretr_end_line = s->cr[0x11] & 0xf;
+
+
+    div2 = (s->cr[0x17] >> 2) & 1;
+    sldiv2 = (s->cr[0x17] >> 3) & 1;
+
+    clocking_mode = (s->sr[0x01] >> 3) & 1;
+    clock_sel = (s->msr >> 2) & 3;
+    dots = (s->msr & 1) ? 8 : 9;
+
+    chars_per_sec = hz[clock_sel] / dots;
+
+    htotal_chars <<= clocking_mode;
+
+    r->total_chars = vtotal_lines * htotal_chars;
+    r->total_chars = (vretr_start_line + vretr_end_line + 1) * htotal_chars;
+    if (r->freq) {
+        r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
+    } else {
+        r->ticks_per_char = ticks_per_sec / chars_per_sec;
+    }
+
+    r->vstart = vretr_start_line;
+    r->vend = r->vstart + vretr_end_line + 1;
+
+    r->hstart = hretr_start_char + hretr_skew_chars;
+    r->hend = r->hstart + hretr_end_char + 1;
+    r->htotal = htotal_chars;
+
+#if 0
+    printf("hz=%f\n",
+    printf (
+        "hz=%f\n"
+        "htotal = %d\n"
+        "hretr_start = %d\n"
+        "hretr_skew = %d\n"
+        "hretr_end = %d\n"
+        "vtotal = %d\n"
+        "vretr_start = %d\n"
+        "vretr_end = %d\n"
+        "div2 = %d sldiv2 = %d\n"
+        "clocking_mode = %d\n"
+        "clock_sel = %d %d\n"
+        "dots = %d\n"
+        "ticks/char = %lld\n"
+        "\n",
+        (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
+        htotal_chars,
+        hretr_start_char,
+        hretr_skew_chars,
+        hretr_end_char,
+        vtotal_lines,
+        vretr_start_line,
+        vretr_end_line,
+        div2, sldiv2,
+        clocking_mode,
+        clock_sel,
+        hz[clock_sel],
+        dots,
+        r->ticks_per_char
+        );
+#endif
+}
+
+static uint8_t vga_precise_retrace(VGAState *s)
+{
+    struct vga_precise_retrace *r = &s->retrace_info.precise;
+    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
+
+    if (r->total_chars) {
+        int cur_line, cur_line_char, cur_char;
+        int64_t cur_tick;
+
+        cur_tick = qemu_get_clock(vm_clock);
+
+        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
+        cur_line = cur_char / r->htotal;
+
+        if (cur_line >= r->vstart && cur_line <= r->vend) {
+            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
+        } else {
+            cur_line_char = cur_char % r->htotal;
+            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
+                val |= ST01_DISP_ENABLE;
+            }
+        }
+
+        return val;
+    } else {
+        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
+    }
+}
+
+static uint8_t vga_dumb_retrace(VGAState *s)
+{
+    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
+}
+
 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
 {
     VGAState *s = opaque;
@@ -231,8 +364,7 @@
         case 0x3ba:
         case 0x3da:
             /* just toggle to fool polling */
-            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
-            val = s->st01;
+            val = s->st01 = s->retrace(s);
             s->ar_flip_flop = 0;
             break;
         default:
@@ -294,6 +426,7 @@
         break;
     case 0x3c2:
         s->msr = val & ~0x10;
+        s->update_retrace_info(s);
         break;
     case 0x3c4:
         s->sr_index = val & 7;
@@ -303,6 +436,7 @@
         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
 #endif
         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+        if (s->sr_index == 1) s->update_retrace_info(s);
         break;
     case 0x3c7:
         s->dac_read_index = val;
@@ -360,6 +494,18 @@
             s->cr[s->cr_index] = val;
             break;
         }
+
+        switch(s->cr_index) {
+        case 0x00:
+        case 0x04:
+        case 0x05:
+        case 0x06:
+        case 0x07:
+        case 0x11:
+        case 0x17:
+            s->update_retrace_info(s);
+            break;
+        }
         break;
     case 0x3ba:
     case 0x3da:
@@ -1983,36 +2129,6 @@
     VGAState vga_state;
 } PCIVGAState;
 
-void vga_update_vram_mapping(VGAState *s, unsigned long vga_ram_begin,
-			     unsigned long vga_ram_end)
-{
-    void *vram_pointer, *old_vram;
-
-    if (vga_ram_begin == s->map_addr &&
-	vga_ram_end   == s->map_end) {
-	return;
-    }
-
-    if (s->map_addr && s->map_end)
-	unset_vram_mapping(s->map_addr, s->map_end);
-
-    vram_pointer = set_vram_mapping(vga_ram_begin, vga_ram_end);
-    if (!vram_pointer) {
-	fprintf(stderr, "set_vram_mapping failed\n");
-	s->map_addr = s->map_end = 0;
-    }
-    else {
-	old_vram = vga_update_vram((VGAState *)s, vram_pointer,
-				   VGA_RAM_SIZE);
-	if (s->map_addr && s->map_end)
-	    munmap(old_vram, s->map_end - s->map_addr);
-	else
-	    qemu_free(old_vram);
-	s->map_addr = vga_ram_begin;
-	s->map_end  = vga_ram_end;
-    }
-}
-
 static void vga_map(PCIDevice *pci_dev, int region_num,
                     uint32_t addr, uint32_t size, int type)
 {
@@ -2022,8 +2138,10 @@
         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
     } else {
         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
-	if (kvm_enabled())
-	    vga_update_vram_mapping(s, addr, addr + VGA_RAM_SIZE);
+	if (kvm_enabled()) {
+            kvm_qemu_log_memory(addr, VGA_RAM_SIZE, 1);
+            s->map_addr = addr;
+        }
     }
 }
 
@@ -2190,10 +2308,7 @@
 
     vga_reset(s);
 
-    if (kvm_enabled())
-	s->vram_ptr = qemu_malloc(vga_ram_size);
-    else
-	s->vram_ptr = vga_ram_base;
+    s->vram_ptr = vga_ram_base;
     s->vram_offset = vga_ram_offset;
     s->vram_size = vga_ram_size;
     s->ds = ds;
@@ -2204,6 +2319,18 @@
     s->invalidate = vga_invalidate_display;
     s->screen_dump = vga_screen_dump;
     s->text_update = vga_update_text;
+    switch (vga_retrace_method) {
+    case VGA_RETRACE_DUMB:
+        s->retrace = vga_dumb_retrace;
+        s->update_retrace_info = vga_dumb_update_retrace_info;
+        break;
+
+    case VGA_RETRACE_PRECISE:
+        s->retrace = vga_precise_retrace;
+        s->update_retrace_info = vga_precise_update_retrace_info;
+        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
+        break;
+    }
 #ifdef TARGET_IA64
     vga_bios_init(s);
 #endif
diff -Nur kvm-76/qemu/hw/vga_int.h kvm-userspace/qemu/hw/vga_int.h
--- kvm-76/qemu/hw/vga_int.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/hw/vga_int.h	2008-10-12 09:38:24.000000000 +0200
@@ -79,6 +79,25 @@
 #define CH_ATTR_SIZE (160 * 100)
 #define VGA_MAX_HEIGHT 2048
 
+struct vga_precise_retrace {
+    int64_t ticks_per_char;
+    int64_t total_chars;
+    int htotal;
+    int hstart;
+    int hend;
+    int vstart;
+    int vend;
+    int freq;
+};
+
+union vga_retrace {
+    struct vga_precise_retrace precise;
+};
+
+struct VGAState;
+typedef uint8_t (* vga_retrace_fn)(struct VGAState *s);
+typedef void (* vga_update_retrace_info_fn)(struct VGAState *s);
+
 #define VGA_STATE_COMMON                                                \
     uint8_t *vram_ptr;                                                  \
     unsigned long vram_offset;                                          \
@@ -147,13 +166,18 @@
     void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y);    \
     /* tell for each page if it has been updated since the last time */ \
     uint32_t last_palette[256];                                         \
-    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */	\
+    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */     \
+    /* kvm */                                                           \
     unsigned long map_addr;						\
     unsigned long map_end;                                              \
     int32_t  aliases_enabled;                                           \
     int32_t  pad1;                                                      \
     uint32_t aliased_bank_base[2];                                      \
-    uint32_t aliased_bank_limit[2];
+    uint32_t aliased_bank_limit[2];                                     \
+    /* retrace */                                                       \
+    vga_retrace_fn retrace;                                             \
+    vga_update_retrace_info_fn update_retrace_info;                     \
+    union vga_retrace retrace_info;
 
 
 typedef struct VGAState {
@@ -191,8 +215,8 @@
                              unsigned int color_xor);
 
 /* let kvm create vga memory */
-void *set_vram_mapping(unsigned long begin, unsigned long end);
-int unset_vram_mapping(unsigned long begin, unsigned long end);
+void set_vram_mapping(void *mem, unsigned long begin, unsigned long end);
+void unset_vram_mapping(void *mem, unsigned long begin, unsigned long end);
 
 void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size);
 void vga_update_vram_mapping(VGAState *s, unsigned long vga_ram_begin,
diff -Nur kvm-76/qemu/i386-dis.c kvm-userspace/qemu/i386-dis.c
--- kvm-76/qemu/i386-dis.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/i386-dis.c	2008-10-12 09:38:24.000000000 +0200
@@ -1131,63 +1131,63 @@
    need to update onebyte_has_modrm or twobyte_has_modrm.  */
 #define MODRM_CHECK  if (!need_modrm) abort ()
 
-static const char **names64;
-static const char **names32;
-static const char **names16;
-static const char **names8;
-static const char **names8rex;
-static const char **names_seg;
-static const char **index16;
+static const char * const *names64;
+static const char * const *names32;
+static const char * const *names16;
+static const char * const *names8;
+static const char * const *names8rex;
+static const char * const *names_seg;
+static const char * const *index16;
 
-static const char *intel_names64[] = {
+static const char * const intel_names64[] = {
   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
 };
-static const char *intel_names32[] = {
+static const char * const intel_names32[] = {
   "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
   "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
 };
-static const char *intel_names16[] = {
+static const char * const intel_names16[] = {
   "ax", "cx", "dx", "bx", "sp", "bp", "si", "di",
   "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"
 };
-static const char *intel_names8[] = {
+static const char * const intel_names8[] = {
   "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh",
 };
-static const char *intel_names8rex[] = {
+static const char * const intel_names8rex[] = {
   "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil",
   "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"
 };
-static const char *intel_names_seg[] = {
+static const char * const intel_names_seg[] = {
   "es", "cs", "ss", "ds", "fs", "gs", "?", "?",
 };
-static const char *intel_index16[] = {
+static const char * const intel_index16[] = {
   "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx"
 };
 
-static const char *att_names64[] = {
+static const char * const att_names64[] = {
   "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
   "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
 };
-static const char *att_names32[] = {
+static const char * const att_names32[] = {
   "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
   "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
 };
-static const char *att_names16[] = {
+static const char * const att_names16[] = {
   "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di",
   "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
 };
-static const char *att_names8[] = {
+static const char * const att_names8[] = {
   "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
 };
-static const char *att_names8rex[] = {
+static const char * const att_names8rex[] = {
   "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil",
   "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
 };
-static const char *att_names_seg[] = {
+static const char * const att_names_seg[] = {
   "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?",
 };
-static const char *att_index16[] = {
+static const char * const att_index16[] = {
   "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx"
 };
 
diff -Nur kvm-76/qemu/keymaps.c kvm-userspace/qemu/keymaps.c
--- kvm-76/qemu/keymaps.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/keymaps.c	2008-10-12 09:38:24.000000000 +0200
@@ -24,7 +24,7 @@
 
 static int get_keysym(const char *name)
 {
-    name2keysym_t *p;
+    const name2keysym_t *p;
     for(p = name2keysym; p->name != NULL; p++) {
         if (!strcmp(p->name, name))
             return p->keysym;
diff -Nur kvm-76/qemu/kvm-compatfd.c kvm-userspace/qemu/kvm-compatfd.c
--- kvm-76/qemu/kvm-compatfd.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/kvm-compatfd.c	1970-01-01 01:00:00.000000000 +0100
@@ -1,33 +0,0 @@
-/*
- * signalfd/eventfd compatibility
- *
- * Copyright IBM, Corp. 2008
- *
- * Authors:
- *  Anthony Liguori   <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2.  See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu-common.h"
-#include "qemu-kvm.h"
-
-#include <sys/syscall.h>
-
-int kvm_eventfd(int *fds)
-{
-#if defined(SYS_eventfd)
-    int ret;
-
-    ret = syscall(SYS_eventfd, 0);
-    if (ret >= 0) {
-	fds[0] = fds[1] = ret;
-	return 0;
-    } else if (!(ret == -1 && errno == ENOSYS))
-	return ret;
-#endif
-
-    return pipe(fds);
-}
diff -Nur kvm-76/qemu/linux-user/elfload.c kvm-userspace/qemu/linux-user/elfload.c
--- kvm-76/qemu/linux-user/elfload.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/linux-user/elfload.c	2008-10-12 09:38:24.000000000 +0200
@@ -1148,6 +1148,7 @@
     end_code = 0;
     start_data = 0;
     end_data = 0;
+    interp_ex.a_info = 0;
 
     for(i=0;i < elf_ex.e_phnum; i++) {
 	if (elf_ppnt->p_type == PT_INTERP) {
diff -Nur kvm-76/qemu/linux-user/main.c kvm-userspace/qemu/linux-user/main.c
--- kvm-76/qemu/linux-user/main.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/linux-user/main.c	2008-10-12 09:38:24.000000000 +0200
@@ -2253,7 +2253,7 @@
             break;
         } else if (!strcmp(r, "d")) {
             int mask;
-            CPULogItem *item;
+            const CPULogItem *item;
 
 	    if (optind >= argc)
 		break;
diff -Nur kvm-76/qemu/linux-user/mmap.c kvm-userspace/qemu/linux-user/mmap.c
--- kvm-76/qemu/linux-user/mmap.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/linux-user/mmap.c	2008-10-12 09:38:24.000000000 +0200
@@ -26,6 +26,7 @@
 #include <sys/mman.h>
 
 #include "qemu.h"
+#include "qemu-common.h"
 
 //#define DEBUG_MMAP
 
diff -Nur kvm-76/qemu/linux-user/strace.c kvm-userspace/qemu/linux-user/strace.c
--- kvm-76/qemu/linux-user/strace.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/linux-user/strace.c	2008-10-12 09:38:24.000000000 +0200
@@ -154,6 +154,7 @@
 }
 #endif
 
+#ifdef TARGET_NR_semctl
 static void
 print_semctl(const struct syscallname *name,
              abi_long arg1, abi_long arg2, abi_long arg3,
@@ -163,6 +164,7 @@
     print_ipc_cmd(arg3);
     gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4);
 }
+#endif
 
 static void
 print_execve(const struct syscallname *name,
@@ -178,7 +180,7 @@
     unlock_user(s, arg1, 0);
 
     for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) {
-        abi_ulong *arg_ptr, arg_addr, s_addr;
+        abi_ulong *arg_ptr, arg_addr;
 
 	arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1);
         if (!arg_ptr)
@@ -189,7 +191,7 @@
             break;
         if ((s = lock_user_string(arg_addr))) {
             gemu_log("\"%s\",", s);
-            unlock_user(s, s_addr, 0);
+            unlock_user(s, arg_addr, 0);
         }
     }
 
diff -Nur kvm-76/qemu/linux-user/syscall.c kvm-userspace/qemu/linux-user/syscall.c
--- kvm-76/qemu/linux-user/syscall.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/linux-user/syscall.c	2008-10-12 09:38:24.000000000 +0200
@@ -177,6 +177,9 @@
 #define __NR_sys_unlinkat __NR_unlinkat
 #define __NR_sys_utimensat __NR_utimensat
 #define __NR_sys_futex __NR_futex
+#define __NR_sys_inotify_init __NR_inotify_init
+#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
+#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
 
 #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
 #define __NR__llseek __NR_lseek
@@ -270,6 +273,15 @@
 _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
           const struct timespec *,tsp,int,flags)
 #endif
+#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
+_syscall0(int,sys_inotify_init)
+#endif
+#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
+_syscall3(int,sys_inotify_add_watch,int,fd,const char *,pathname,uint32_t,mask)
+#endif
+#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
+_syscall2(int,sys_inotify_rm_watch,int,fd,uint32_t,wd)
+#endif
 #if defined(USE_NPTL)
 #if defined(TARGET_NR_futex) && defined(__NR_futex)
 _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
@@ -2127,7 +2139,7 @@
 
 #define MAX_STRUCT_SIZE 4096
 
-IOCTLEntry ioctl_entries[] = {
+static IOCTLEntry ioctl_entries[] = {
 #define IOCTL(cmd, access, types...) \
     { TARGET_ ## cmd, cmd, #cmd, access, { types } },
 #include "ioctls.h"
@@ -2218,7 +2230,7 @@
     return ret;
 }
 
-bitmask_transtbl iflag_tbl[] = {
+static const bitmask_transtbl iflag_tbl[] = {
         { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
         { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
         { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
@@ -2236,7 +2248,7 @@
         { 0, 0, 0, 0 }
 };
 
-bitmask_transtbl oflag_tbl[] = {
+static const bitmask_transtbl oflag_tbl[] = {
 	{ TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
 	{ TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
 	{ TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
@@ -2264,7 +2276,7 @@
 	{ 0, 0, 0, 0 }
 };
 
-bitmask_transtbl cflag_tbl[] = {
+static const bitmask_transtbl cflag_tbl[] = {
 	{ TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
 	{ TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
 	{ TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
@@ -2299,7 +2311,7 @@
 	{ 0, 0, 0, 0 }
 };
 
-bitmask_transtbl lflag_tbl[] = {
+static const bitmask_transtbl lflag_tbl[] = {
 	{ TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
 	{ TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
 	{ TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
@@ -2386,7 +2398,7 @@
     target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
 }
 
-StructEntry struct_termios_def = {
+static const StructEntry struct_termios_def = {
     .convert = { host_to_target_termios, target_to_host_termios },
     .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
     .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
@@ -5576,7 +5588,40 @@
         goto unimplemented;
 #ifdef TARGET_NR_mincore
     case TARGET_NR_mincore:
-        goto unimplemented;
+        {
+            void *a;
+            ret = -TARGET_EFAULT;
+            if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
+                goto efault;
+            if (!(p = lock_user_string(arg3)))
+                goto mincore_fail;
+            ret = get_errno(mincore(a, arg2, p));
+            unlock_user(p, arg3, ret);
+            mincore_fail:
+            unlock_user(a, arg1, 0);
+        }
+        break;
+#endif
+#ifdef TARGET_NR_arm_fadvise64_64
+    case TARGET_NR_arm_fadvise64_64:
+	{
+		/*
+		 * arm_fadvise64_64 looks like fadvise64_64 but
+		 * with different argument order
+		 */
+		abi_long temp;
+		temp = arg3;
+		arg3 = arg4;
+		arg4 = temp;
+	}
+#endif
+#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
+#ifdef TARGET_NR_fadvise64_64
+    case TARGET_NR_fadvise64_64:
+#endif
+        /* This is a hint, so ignoring and returning success is ok.  */
+	ret = get_errno(0);
+	break;
 #endif
 #ifdef TARGET_NR_madvise
     case TARGET_NR_madvise:
@@ -5841,6 +5886,23 @@
         ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
         break;
 #endif
+#ifdef TARGET_NR_inotify_init
+    case TARGET_NR_inotify_init:
+        ret = get_errno(sys_inotify_init());
+        break;
+#endif
+#ifdef TARGET_NR_inotify_add_watch
+    case TARGET_NR_inotify_add_watch:
+        p = lock_user_string(arg2);
+        ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
+        unlock_user(p, arg2, 0);
+        break;
+#endif
+#ifdef TARGET_NR_inotify_rm_watch
+    case TARGET_NR_inotify_rm_watch:
+        ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
+        break;
+#endif
 
     default:
     unimplemented:
diff -Nur kvm-76/qemu/linux-user/syscall_defs.h kvm-userspace/qemu/linux-user/syscall_defs.h
--- kvm-76/qemu/linux-user/syscall_defs.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/linux-user/syscall_defs.h	2008-10-12 09:38:24.000000000 +0200
@@ -860,11 +860,14 @@
 
 #include "termbits.h"
 
+/* Common */
 #define TARGET_MAP_SHARED	0x01		/* Share changes */
 #define TARGET_MAP_PRIVATE	0x02		/* Changes are private */
-#define TARGET_MAP_TYPE	0x0f		/* Mask for type of mapping */
-#define TARGET_MAP_FIXED	0x10		/* Interpret addr exactly */
+#define TARGET_MAP_TYPE		0x0f		/* Mask for type of mapping */
+
+/* Target specific */
 #if defined(TARGET_MIPS)
+#define TARGET_MAP_FIXED	0x10		/* Interpret addr exactly */
 #define TARGET_MAP_ANONYMOUS	0x0800		/* don't use a file */
 #define TARGET_MAP_GROWSDOWN	0x1000		/* stack-like segment */
 #define TARGET_MAP_DENYWRITE	0x2000		/* ETXTBSY */
@@ -873,18 +876,34 @@
 #define TARGET_MAP_NORESERVE	0x0400		/* don't check for reservations */
 #define TARGET_MAP_POPULATE	0x10000		/* populate (prefault) pagetables */
 #define TARGET_MAP_NONBLOCK	0x20000		/* do not block on IO */
-#else
+#elif defined(TARGET_PPC)
+#define TARGET_MAP_FIXED	0x10		/* Interpret addr exactly */
 #define TARGET_MAP_ANONYMOUS	0x20		/* don't use a file */
 #define TARGET_MAP_GROWSDOWN	0x0100		/* stack-like segment */
 #define TARGET_MAP_DENYWRITE	0x0800		/* ETXTBSY */
 #define TARGET_MAP_EXECUTABLE	0x1000		/* mark it as an executable */
-#if defined(TARGET_PPC)
 #define TARGET_MAP_LOCKED	0x0080		/* pages are locked */
 #define TARGET_MAP_NORESERVE	0x0040		/* don't check for reservations */
+#define TARGET_MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
+#define TARGET_MAP_NONBLOCK	0x10000		/* do not block on IO */
+#elif defined(TARGET_ALPHA)
+#define TARGET_MAP_ANONYMOUS	0x10		/* don't use a file */
+#define TARGET_MAP_FIXED	0x100		/* Interpret addr exactly */
+#define TARGET_MAP_GROWSDOWN	0x01000		/* stack-like segment */
+#define TARGET_MAP_DENYWRITE	0x02000		/* ETXTBSY */
+#define TARGET_MAP_EXECUTABLE	0x04000		/* mark it as an executable */
+#define TARGET_MAP_LOCKED	0x08000		/* lock the mapping */
+#define TARGET_MAP_NORESERVE	0x10000		/* no check for reservations */
+#define TARGET_MAP_POPULATE	0x20000		/* pop (prefault) pagetables */
+#define TARGET_MAP_NONBLOCK	0x40000		/* do not block on IO */
 #else
+#define TARGET_MAP_FIXED	0x10		/* Interpret addr exactly */
+#define TARGET_MAP_ANONYMOUS	0x20		/* don't use a file */
+#define TARGET_MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define TARGET_MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define TARGET_MAP_EXECUTABLE	0x1000		/* mark it as an executable */
 #define TARGET_MAP_LOCKED	0x2000		/* pages are locked */
 #define TARGET_MAP_NORESERVE	0x4000		/* don't check for reservations */
-#endif
 #define TARGET_MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
 #define TARGET_MAP_NONBLOCK	0x10000		/* do not block on IO */
 #endif
diff -Nur kvm-76/qemu/migration.c kvm-userspace/qemu/migration.c
--- kvm-76/qemu/migration.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/migration.c	2008-10-12 09:38:24.000000000 +0200
@@ -154,7 +154,7 @@
     }
 }
 
-static void migrate_close(void *opaque)
+static int migrate_close(void *opaque)
 {
     MigrationState *s = opaque;
 
@@ -163,6 +163,7 @@
 
     qemu_free(s);
     current_migration = NULL;
+    return 0;
 }
 
 /* Outgoing migration routines */
@@ -178,7 +179,7 @@
 
     if (! *has_error) {
         vm_stop(0);
-        f = qemu_fopen(s, migrate_put_buffer, NULL, migrate_close);
+        f = qemu_fopen_ops(s, migrate_put_buffer, NULL, migrate_close, NULL);
         do {
             qemu_aio_flush();
         } while (qemu_bh_poll());
@@ -823,6 +824,7 @@
     uint32_t addr, size;
     extern void qemu_announce_self(void);
     unsigned char running;
+    extern int autostart;
 
     running = qemu_get_byte(f);
     if ((running != 1) && (running != 2)) {
diff -Nur kvm-76/qemu/monitor.c kvm-userspace/qemu/monitor.c
--- kvm-76/qemu/monitor.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/monitor.c	2008-10-12 09:38:24.000000000 +0200
@@ -70,8 +70,8 @@
 static CharDriverState *monitor_hd[MAX_MON];
 static int hide_banner;
 
-static term_cmd_t term_cmds[];
-static term_cmd_t info_cmds[];
+static const term_cmd_t term_cmds[];
+static const term_cmd_t info_cmds[];
 
 static uint8_t term_outbuf[1024];
 static int term_outbuf_index;
@@ -179,9 +179,9 @@
     return 0;
 }
 
-static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
+static void help_cmd1(const term_cmd_t *cmds, const char *prefix, const char *name)
 {
-    term_cmd_t *cmd;
+    const term_cmd_t *cmd;
 
     for(cmd = cmds; cmd->name != NULL; cmd++) {
         if (!name || !strcmp(name, cmd->name))
@@ -196,7 +196,7 @@
     } else {
         help_cmd1(term_cmds, "", name);
         if (name && !strcmp(name, "log")) {
-            CPULogItem *item;
+            const CPULogItem *item;
             term_printf("Log items (comma separated):\n");
             term_printf("%-10s %s\n", "none", "remove all logs");
             for(item = cpu_log_items; item->mask != 0; item++) {
@@ -225,7 +225,7 @@
 
 static void do_info(const char *item)
 {
-    term_cmd_t *cmd;
+    const term_cmd_t *cmd;
     void (*handler)(void);
 
     if (!item)
@@ -886,6 +886,9 @@
     { 0x30, "b" },
     { 0x31, "n" },
     { 0x32, "m" },
+    { 0x33, "comma" },
+    { 0x34, "dot" },
+    { 0x35, "slash" },
 
     { 0x37, "asterisk" },
 
@@ -1373,9 +1376,6 @@
 }
 
 #ifdef HAS_AUDIO
-int wav_start_capture (CaptureState *s, const char *path, int freq,
-                       int bits, int nchannels);
-
 static void do_wav_capture (const char *path,
                             int has_freq, int freq,
                             int has_bits, int bits,
@@ -1408,7 +1408,10 @@
 
     for (env = first_cpu; env != NULL; env = env->next_cpu)
         if (env->cpu_index == cpu_index) {
-            cpu_interrupt(env, CPU_INTERRUPT_NMI);
+            if (kvm_enabled())
+                kvm_inject_interrupt(env, CPU_INTERRUPT_NMI);
+            else
+                cpu_interrupt(env, CPU_INTERRUPT_NMI);
             break;
         }
 }
@@ -1433,7 +1436,7 @@
 	term_printf("balloon: actual=%d\n", (int)(actual >> 20));
 }
 
-static term_cmd_t term_cmds[] = {
+static const term_cmd_t term_cmds[] = {
     { "help|?", "s?", do_help,
       "[cmd]", "show the help" },
     { "commit", "s", do_commit,
@@ -1533,7 +1536,7 @@
     { NULL, NULL, },
 };
 
-static term_cmd_t info_cmds[] = {
+static const term_cmd_t info_cmds[] = {
     { "version", "", do_info_version,
       "", "show the version of qemu" },
     { "network", "", do_info_network,
@@ -1612,12 +1615,12 @@
 typedef struct MonitorDef {
     const char *name;
     int offset;
-    target_long (*get_value)(struct MonitorDef *md, int val);
+    target_long (*get_value)(const struct MonitorDef *md, int val);
     int type;
 } MonitorDef;
 
 #if defined(TARGET_I386)
-static target_long monitor_get_pc (struct MonitorDef *md, int val)
+static target_long monitor_get_pc (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1627,7 +1630,7 @@
 #endif
 
 #if defined(TARGET_PPC)
-static target_long monitor_get_ccr (struct MonitorDef *md, int val)
+static target_long monitor_get_ccr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     unsigned int u;
@@ -1643,7 +1646,7 @@
     return u;
 }
 
-static target_long monitor_get_msr (struct MonitorDef *md, int val)
+static target_long monitor_get_msr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1651,7 +1654,7 @@
     return env->msr;
 }
 
-static target_long monitor_get_xer (struct MonitorDef *md, int val)
+static target_long monitor_get_xer (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1659,7 +1662,7 @@
     return ppc_load_xer(env);
 }
 
-static target_long monitor_get_decr (struct MonitorDef *md, int val)
+static target_long monitor_get_decr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1667,7 +1670,7 @@
     return cpu_ppc_load_decr(env);
 }
 
-static target_long monitor_get_tbu (struct MonitorDef *md, int val)
+static target_long monitor_get_tbu (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1675,7 +1678,7 @@
     return cpu_ppc_load_tbu(env);
 }
 
-static target_long monitor_get_tbl (struct MonitorDef *md, int val)
+static target_long monitor_get_tbl (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1686,7 +1689,7 @@
 
 #if defined(TARGET_SPARC)
 #ifndef TARGET_SPARC64
-static target_long monitor_get_psr (struct MonitorDef *md, int val)
+static target_long monitor_get_psr (const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1695,7 +1698,7 @@
 }
 #endif
 
-static target_long monitor_get_reg(struct MonitorDef *md, int val)
+static target_long monitor_get_reg(const struct MonitorDef *md, int val)
 {
     CPUState *env = mon_get_cpu();
     if (!env)
@@ -1704,7 +1707,7 @@
 }
 #endif
 
-static MonitorDef monitor_defs[] = {
+static const MonitorDef monitor_defs[] = {
 #ifdef TARGET_I386
 
 #define SEG(name, seg) \
@@ -1955,7 +1958,7 @@
 /* return 0 if OK, -1 if not found, -2 if no CPU defined */
 static int get_monitor_def(target_long *pval, const char *name)
 {
-    MonitorDef *md;
+    const MonitorDef *md;
     void *ptr;
 
     for(md = monitor_defs; md->name != NULL; md++) {
@@ -2249,7 +2252,7 @@
     const char *p, *pstart, *typestr;
     char *q;
     int c, nb_args, len, i, has_arg;
-    term_cmd_t *cmd;
+    const term_cmd_t *cmd;
     char cmdname[256];
     char buf[1024];
     void *str_allocated[MAX_ARGS];
@@ -2412,8 +2415,8 @@
                         /* for 'i', not specifying a size gives -1 as size */
                         if (size < 0)
                             size = default_fmt_size;
+                        default_fmt_size = size;
                     }
-                    default_fmt_size = size;
                     default_fmt_format = format;
                 } else {
                     count = 1;
@@ -2686,7 +2689,7 @@
     char *args[MAX_ARGS];
     int nb_args, i, len;
     const char *ptype, *str;
-    term_cmd_t *cmd;
+    const term_cmd_t *cmd;
     const KeyDef *key;
 
     parse_cmdline(cmdline, &nb_args, args);
diff -Nur kvm-76/qemu/net.h kvm-userspace/qemu/net.h
--- kvm-76/qemu/net.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/net.h	2008-10-12 09:38:24.000000000 +0200
@@ -66,6 +66,20 @@
 extern int nb_nics;
 extern NICInfo nd_table[MAX_NICS];
 
+/* BT HCI info */
+
+struct HCIInfo {
+    int (*bdaddr_set)(struct HCIInfo *hci, const uint8_t *bd_addr);
+    void (*cmd_send)(struct HCIInfo *hci, const uint8_t *data, int len);
+    void (*sco_send)(struct HCIInfo *hci, const uint8_t *data, int len);
+    void (*acl_send)(struct HCIInfo *hci, const uint8_t *data, int len);
+    void *opaque;
+    void (*evt_recv)(void *opaque, const uint8_t *data, int len);
+    void (*acl_recv)(void *opaque, const uint8_t *data, int len);
+};
+
+struct HCIInfo *qemu_next_hci(void);
+
 /* checksumming functions (net-checksum.c) */
 uint32_t net_checksum_add(int len, uint8_t *buf);
 uint16_t net_checksum_finish(uint32_t sum);
Binärdateien kvm-76/qemu/pc-bios/bios.bin and kvm-userspace/qemu/pc-bios/bios.bin sind verschieden.
diff -Nur kvm-76/qemu/qemu-common.h kvm-userspace/qemu/qemu-common.h
--- kvm-76/qemu/qemu-common.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/qemu-common.h	2008-10-12 09:38:24.000000000 +0200
@@ -119,6 +119,7 @@
 /* A load of opaque types so that device init declarations don't have to
    pull in all the real definitions.  */
 typedef struct NICInfo NICInfo;
+typedef struct HCIInfo HCIInfo;
 typedef struct AudioState AudioState;
 typedef struct BlockDriverState BlockDriverState;
 typedef struct DisplayState DisplayState;
diff -Nur kvm-76/qemu/qemu-doc.texi kvm-userspace/qemu/qemu-doc.texi
--- kvm-76/qemu/qemu-doc.texi	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/qemu-doc.texi	2008-10-12 09:38:24.000000000 +0200
@@ -345,6 +345,9 @@
 a suffix of ``M'' or ``G'' can be used to signify a value in megabytes or
 gigabytes respectively.
 
+@item -cpu @var{model}
+Select CPU model (-cpu ? for list and additional feature selection)
+
 @item -smp @var{n}
 Simulate an SMP system with @var{n} CPUs. On the PC target, up to 255
 CPUs are supported. On Sparc32 target, Linux limits the number of usable CPUs
@@ -963,11 +966,24 @@
 @item -L path
 Set the directory for the BIOS, VGA BIOS and keymaps.
 
-@item -std-vga
-Simulate a standard VGA card with Bochs VBE extensions (default is
-Cirrus Logic GD5446 PCI VGA). If your guest OS supports the VESA 2.0
-VBE extensions (e.g. Windows XP) and if you want to use high
-resolution modes (>= 1280x1024x16) then you should use this option.
+@item -vga @var{type}
+Select type of VGA card to emulate. Valid values for @var{type} are
+@table @code
+@item cirrus
+Cirrus Logic GD5446 Video card. All Windows versions starting from
+Windows 95 should recognize and use this graphic card. For optimal
+performances, use 16 bit color depth in the guest and the host OS.
+(This one is the default)
+@item std
+Standard VGA card with Bochs VBE extensions.  If your guest OS
+supports the VESA 2.0 VBE extensions (e.g. Windows XP) and if you want
+to use high resolution modes (>= 1280x1024x16) then you should use
+this option.
+@item vmware
+VMWare SVGA-II compatible adapter. Use it if you have sufficiently
+recent XFree86/XOrg server or Windows guest with a driver for this
+card.
+@end table
 
 @item -no-acpi
 Disable ACPI (Advanced Configuration and Power Interface) support. Use
@@ -1292,8 +1308,9 @@
 
 @item sendkey @var{keys}
 
-Send @var{keys} to the emulator. Use @code{-} to press several keys
-simultaneously. Example:
+Send @var{keys} to the emulator. @var{keys} could be the name of the
+key or @code{#} followed by the raw value in either decimal or hexadecimal
+format. Use @code{-} to press several keys simultaneously. Example:
 @example
 sendkey ctrl-alt-f1
 @end example
@@ -1832,7 +1849,7 @@
 to provide high security. The password can be fairly easily brute-forced by
 a client making repeat connections. For this reason, a VNC server using password
 authentication should be restricted to only listen on the loopback interface
-or UNIX domain sockets. Password ayuthentication is requested with the @code{password}
+or UNIX domain sockets. Password authentication is requested with the @code{password}
 option, and then once QEMU is running the password is set with the monitor. Until
 the monitor is used to set the password all clients will be rejected.
 
@@ -2250,14 +2267,37 @@
 @node Sparc32 System emulator
 @section Sparc32 System emulator
 
-Use the executable @file{qemu-system-sparc} to simulate a SPARCstation
-5, SPARCstation 10, SPARCstation 20, SPARCserver 600MP (sun4m
-architecture), SPARCstation 2 (sun4c architecture), SPARCserver 1000,
-or SPARCcenter 2000 (sun4d architecture). The emulation is somewhat
-complete.  SMP up to 16 CPUs is supported, but Linux limits the number
-of usable CPUs to 4.
+Use the executable @file{qemu-system-sparc} to simulate the following
+Sun4m architecture machines:
+@itemize @minus
+@item
+SPARCstation 4
+@item
+SPARCstation 5
+@item
+SPARCstation 10
+@item
+SPARCstation 20
+@item
+SPARCserver 600MP
+@item
+SPARCstation LX
+@item
+SPARCstation Voyager
+@item
+SPARCclassic
+@item
+SPARCbook
+@end itemize
+
+The emulation is somewhat complete. SMP up to 16 CPUs is supported,
+but Linux limits the number of usable CPUs to 4.
+
+It's also possible to simulate a SPARCstation 2 (sun4c architecture),
+SPARCserver 1000, or SPARCcenter 2000 (sun4d architecture), but these
+emulators are not usable yet.
 
-QEMU emulates the following sun4m/sun4d peripherals:
+QEMU emulates the following sun4m/sun4c/sun4d peripherals:
 
 @itemize @minus
 @item
@@ -2267,7 +2307,7 @@
 @item
 Lance (Am7990) Ethernet
 @item
-Non Volatile RAM M48T08
+Non Volatile RAM M48T02/M48T08
 @item
 Slave I/O: timers, interrupt controllers, Zilog serial ports, keyboard
 and power/reset logic
@@ -2289,8 +2329,10 @@
 1275-1994 (referred to as Open Firmware) compliant firmware.
 
 A sample Linux 2.6 series kernel and ram disk image are available on
-the QEMU web site. Please note that currently NetBSD, OpenBSD or
-Solaris kernels don't work.
+the QEMU web site. There are still issues with NetBSD and OpenBSD, but
+some kernel versions work. Please note that currently Solaris kernels
+don't work probably due to interface issues between OpenBIOS and
+Solaris.
 
 @c man begin OPTIONS
 
@@ -2312,7 +2354,7 @@
  -prom-env 'boot-device=sd(0,2,0):d' -prom-env 'boot-args=linux single'
 @end example
 
-@item -M [SS-5|SS-10|SS-20|SS-600MP|SS-2|SS-1000|SS-2000]
+@item -M [SS-4|SS-5|SS-10|SS-20|SS-600MP|LX|Voyager|SPARCClassic|SPARCbook|SS-2|SS-1000|SS-2000]
 
 Set the emulated machine type. Default is SS-5.
 
@@ -2323,8 +2365,10 @@
 @node Sparc64 System emulator
 @section Sparc64 System emulator
 
-Use the executable @file{qemu-system-sparc64} to simulate a Sun4u or
-Sun4v machine. The emulator is not usable for anything yet.
+Use the executable @file{qemu-system-sparc64} to simulate a Sun4u
+(UltraSPARC PC-like machine), Sun4v (T1 PC-like machine), or generic
+Niagara (T1) machine. The emulator is not usable for anything yet, but
+it can launch some kernels.
 
 QEMU emulates the following peripherals:
 
@@ -2334,11 +2378,15 @@
 @item
 PCI VGA compatible card with VESA Bochs Extensions
 @item
+PS/2 mouse and keyboard
+@item
 Non Volatile RAM M48T59
 @item
 PC-compatible serial ports
 @item
 2 PCI IDE interfaces with hard disk and CD-ROM support
+@item
+Floppy disk
 @end itemize
 
 @c man begin OPTIONS
@@ -2347,7 +2395,15 @@
 
 @table @option
 
-@item -M [sun4u|sun4v]
+@item -prom-env string
+
+Set OpenBIOS variables in NVRAM, for example:
+
+@example
+qemu-system-sparc64 -prom-env 'auto-boot?=false'
+@end example
+
+@item -M [sun4u|sun4v|Niagara]
 
 Set the emulated machine type. The default is sun4u.
 
@@ -2804,7 +2860,7 @@
 @subsection Command line options
 
 @example
-usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
+usage: qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] program [arguments...]
 @end example
 
 @table @option
@@ -2814,6 +2870,8 @@
 Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386)
 @item -s size
 Set the x86 stack size in bytes (default=524288)
+@item -cpu model
+Select CPU model (-cpu ? for list and additional feature selection)
 @end table
 
 Debug options:
@@ -2823,6 +2881,8 @@
 Activate log (logfile=/tmp/qemu.log)
 @item -p pagesize
 Act as if the host page size was 'pagesize' bytes
+@item -g port
+Wait gdb connection to port
 @end table
 
 Environment variables:
@@ -2850,6 +2910,8 @@
 
 The binary format is detected automatically.
 
+@command{qemu-sparc} can execute Sparc32 binaries (Sparc32 CPU, 32 bit ABI).
+
 @command{qemu-sparc32plus} can execute Sparc32 and SPARC32PLUS binaries
 (Sparc64 CPU, 32 bit ABI).
 
diff -Nur kvm-76/qemu/qemu-kvm-ia64.c kvm-userspace/qemu/qemu-kvm-ia64.c
--- kvm-76/qemu/qemu-kvm-ia64.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/qemu-kvm-ia64.c	2008-10-12 09:38:24.000000000 +0200
@@ -57,6 +57,11 @@
     return 1;
 }
 
+int kvm_arch_try_push_nmi(void *opaque)
+{
+    return 1;
+}
+
 void kvm_arch_update_regs_for_sipi(CPUState *env)
 {
 }
diff -Nur kvm-76/qemu/qemu-kvm-x86.c kvm-userspace/qemu/qemu-kvm-x86.c
--- kvm-76/qemu/qemu-kvm-x86.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/qemu-kvm-x86.c	2008-10-12 09:38:24.000000000 +0200
@@ -27,6 +27,18 @@
 
 static int lm_capable_kernel;
 
+int kvm_qemu_create_memory_alias(uint64_t phys_start,
+                                 uint64_t len,
+                                 uint64_t target_phys)
+{
+    return kvm_create_memory_alias(kvm_context, phys_start, len, target_phys);
+}
+
+int kvm_qemu_destroy_memory_alias(uint64_t phys_start)
+{
+	return kvm_destroy_memory_alias(kvm_context, phys_start);
+}
+
 int kvm_arch_qemu_create_context(void)
 {
     int i;
@@ -598,7 +610,8 @@
     CPUState *env = cpu_single_env;
 
     if (!((env->interrupt_request & CPU_INTERRUPT_HARD) &&
-	  (env->eflags & IF_MASK))) {
+	  (env->eflags & IF_MASK)) &&
+	!(env->interrupt_request & CPU_INTERRUPT_NMI)) {
             env->halted = 1;
 	    env->exception_index = EXCP_HLT;
     }
@@ -627,8 +640,9 @@
 
 int kvm_arch_has_work(CPUState *env)
 {
-    if ((env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT)) &&
-	(env->eflags & IF_MASK))
+    if (((env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXIT)) &&
+	 (env->eflags & IF_MASK)) ||
+	(env->interrupt_request & CPU_INTERRUPT_NMI))
 	return 1;
     return 0;
 }
@@ -653,6 +667,24 @@
     return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0;
 }
 
+int kvm_arch_try_push_nmi(void *opaque)
+{
+    CPUState *env = cpu_single_env;
+    int r;
+
+    if (likely(!(env->interrupt_request & CPU_INTERRUPT_NMI)))
+        return 0;
+
+    if (kvm_is_ready_for_nmi_injection(kvm_context, env->cpu_index)) {
+        env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+        r = kvm_inject_nmi(kvm_context, env->cpu_index);
+        if (r < 0)
+            printf("cpu %d fail inject NMI\n", env->cpu_index);
+    }
+
+    return (env->interrupt_request & CPU_INTERRUPT_NMI) != 0;
+}
+
 void kvm_arch_update_regs_for_sipi(CPUState *env)
 {
     SegmentCache cs = env->segs[R_CS];
diff -Nur kvm-76/qemu/qemu-kvm.c kvm-userspace/qemu/qemu-kvm.c
--- kvm-76/qemu/qemu-kvm.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/qemu-kvm.c	2008-10-12 09:38:24.000000000 +0200
@@ -125,6 +125,16 @@
         qemu_cond_wait(&qemu_work_cond);
 }
 
+static void inject_interrupt(void *data)
+{
+    cpu_interrupt(vcpu->env, (int)data);
+}
+
+void kvm_inject_interrupt(CPUState *env, int mask)
+{
+    on_vcpu(env, inject_interrupt, (void *)mask);
+}
+
 void kvm_update_interrupt_request(CPUState *env)
 {
     int signal = 0;
@@ -163,6 +173,11 @@
     return kvm_arch_try_push_interrupts(opaque);
 }
 
+static int try_push_nmi(void *opaque)
+{
+    return kvm_arch_try_push_nmi(opaque);
+}
+
 static void post_kvm_run(void *opaque, int vcpu)
 {
 
@@ -394,7 +409,7 @@
     while (1) {
 	while (!has_work(env))
 	    kvm_main_loop_wait(env, 1000);
-	if (env->interrupt_request & CPU_INTERRUPT_HARD)
+	if (env->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI))
 	    env->halted = 0;
 	if (!kvm_irqchip_in_kernel(kvm_context) && info->sipi_needed)
 	    update_regs_for_sipi(env);
@@ -545,7 +560,7 @@
     io_thread = pthread_self();
     qemu_system_ready = 1;
 
-    if (kvm_eventfd(fds) == -1) {
+    if (qemu_eventfd(fds) == -1) {
 	fprintf(stderr, "failed to create eventfd\n");
 	return -errno;
     }
@@ -716,6 +731,7 @@
     .shutdown = kvm_shutdown,
     .io_window = kvm_io_window,
     .try_push_interrupts = try_push_interrupts,
+    .try_push_nmi = try_push_nmi,
     .post_kvm_run = post_kvm_run,
     .pre_kvm_run = pre_kvm_run,
 #ifdef TARGET_I386
@@ -794,6 +810,13 @@
     return;
 }
 
+void kvm_cpu_unregister_physical_memory(target_phys_addr_t start_addr,
+                                        target_phys_addr_t size,
+                                        unsigned long phys_offset)
+{
+    kvm_unregister_memory_area(kvm_context, start_addr, size);
+}
+
 int kvm_setup_guest_memory(void *area, unsigned long size)
 {
     int ret = 0;
@@ -938,6 +961,15 @@
     return r;
 }
 
+void kvm_qemu_log_memory(target_phys_addr_t start, target_phys_addr_t size,
+                         int log)
+{
+    if (log)
+	kvm_dirty_pages_log_enable_slot(kvm_context, start, size);
+    else
+	kvm_dirty_pages_log_disable_slot(kvm_context, start, size);
+}
+
 int kvm_get_phys_ram_page_bitmap(unsigned char *bitmap)
 {
     unsigned int bsize  = BITMAP_SIZE(phys_ram_size);
diff -Nur kvm-76/qemu/qemu-kvm.h kvm-userspace/qemu/qemu-kvm.h
--- kvm-76/qemu/qemu-kvm.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/qemu-kvm.h	2008-10-12 09:38:24.000000000 +0200
@@ -35,17 +35,27 @@
 
 void qemu_kvm_call_with_env(void (*func)(void *), void *data, CPUState *env);
 void qemu_kvm_cpuid_on_env(CPUState *env);
+void kvm_inject_interrupt(CPUState *env, int mask);
 void kvm_update_after_sipi(CPUState *env);
 void kvm_update_interrupt_request(CPUState *env);
 void kvm_cpu_register_physical_memory(target_phys_addr_t start_addr,
                                       unsigned long size,
                                       unsigned long phys_offset);
+void kvm_cpu_unregister_physical_memory(target_phys_addr_t start_addr,
+                                        target_phys_addr_t size,
+                                        unsigned long phys_offset);
 void *kvm_cpu_create_phys_mem(target_phys_addr_t start_addr,
 			      unsigned long size, int log, int writable);
 
 void kvm_cpu_destroy_phys_mem(target_phys_addr_t start_addr,
 			      unsigned long size);
+void kvm_qemu_log_memory(target_phys_addr_t start, target_phys_addr_t size,
+                         int log);
 int kvm_setup_guest_memory(void *area, unsigned long size);
+int kvm_qemu_create_memory_alias(uint64_t phys_start,
+                                 uint64_t len,
+                                 uint64_t target_phys);
+int kvm_qemu_destroy_memory_alias(uint64_t phys_start);
 
 int kvm_arch_qemu_create_context(void);
 
@@ -57,6 +67,7 @@
 void kvm_arch_post_kvm_run(void *opaque, int vcpu);
 int kvm_arch_has_work(CPUState *env);
 int kvm_arch_try_push_interrupts(void *opaque);
+int kvm_arch_try_push_nmi(void *opaque);
 void kvm_arch_update_regs_for_sipi(CPUState *env);
 void kvm_arch_cpu_reset(CPUState *env);
 
@@ -87,8 +98,6 @@
 int handle_powerpc_dcr_write(int vcpu,uint32_t dcrn, uint32_t data);
 #endif
 
-int kvm_eventfd(int *fds);
-
 #define ALIGN(x, y)  (((x)+(y)-1) & ~((y)-1))
 #define BITMAP_SIZE(m) (ALIGN(((m)>>TARGET_PAGE_BITS), HOST_LONG_BITS) / 8)
 
@@ -107,6 +116,8 @@
 #define qemu_kvm_irqchip_in_kernel() (0)
 #define qemu_kvm_pit_in_kernel() (0)
 #define qemu_kvm_has_sync_mmu() (0)
+#define kvm_load_registers(env) do {} while(0)
+#define kvm_save_registers(env) do {} while(0)
 #endif
 
 void kvm_mutex_unlock(void);
diff -Nur kvm-76/qemu/sdl_keysym.h kvm-userspace/qemu/sdl_keysym.h
--- kvm-76/qemu/sdl_keysym.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/sdl_keysym.h	2008-10-12 09:38:24.000000000 +0200
@@ -2,7 +2,7 @@
 	const char* name;
 	int keysym;
 } name2keysym_t;
-static name2keysym_t name2keysym[]={
+static const name2keysym_t name2keysym[]={
 /* ascii */
     { "space",                0x020},
     { "exclam",               0x021},
diff -Nur kvm-76/qemu/slirp/bootp.c kvm-userspace/qemu/slirp/bootp.c
--- kvm-76/qemu/slirp/bootp.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/slirp/bootp.c	2008-10-12 09:38:24.000000000 +0200
@@ -36,7 +36,7 @@
     uint8_t macaddr[6];
 } BOOTPClient;
 
-BOOTPClient bootp_clients[NB_ADDR];
+static BOOTPClient bootp_clients[NB_ADDR];
 
 const char *bootp_filename;
 
diff -Nur kvm-76/qemu/slirp/if.c kvm-userspace/qemu/slirp/if.c
--- kvm-76/qemu/slirp/if.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/slirp/if.c	2008-10-12 09:38:24.000000000 +0200
@@ -15,7 +15,7 @@
 
 #define ifs_init(ifm) ((ifm)->ifs_next = (ifm)->ifs_prev = (ifm))
 
-void
+static void
 ifs_insque(struct mbuf *ifm, struct mbuf *ifmhead)
 {
 	ifm->ifs_next = ifmhead->ifs_next;
@@ -24,7 +24,7 @@
 	ifm->ifs_next->ifs_prev = ifm;
 }
 
-void
+static void
 ifs_remque(struct mbuf *ifm)
 {
 	ifm->ifs_prev->ifs_next = ifm->ifs_next;
diff -Nur kvm-76/qemu/slirp/ip_icmp.c kvm-userspace/qemu/slirp/ip_icmp.c
--- kvm-76/qemu/slirp/ip_icmp.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/slirp/ip_icmp.c	2008-10-12 09:38:24.000000000 +0200
@@ -43,7 +43,7 @@
 
 /* The message sent when emulating PING */
 /* Be nice and tell them it's just a pseudo-ping packet */
-const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
+static const char icmp_ping_msg[] = "This is a pseudo-PING packet used by Slirp to emulate ICMP ECHO-REQUEST packets.\n";
 
 /* list of actions for icmp_error() on RX of an icmp message */
 static const int icmp_flush[19] = {
diff -Nur kvm-76/qemu/slirp/mbuf.c kvm-userspace/qemu/slirp/mbuf.c
--- kvm-76/qemu/slirp/mbuf.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/slirp/mbuf.c	2008-10-12 09:38:24.000000000 +0200
@@ -17,8 +17,6 @@
 
 #include <slirp.h>
 
-struct	mbuf *mbutl;
-char	*mclrefcnt;
 int mbuf_alloced = 0;
 struct mbuf m_freelist, m_usedlist;
 #define MBUF_THRESH 30
diff -Nur kvm-76/qemu/slirp/socket.c kvm-userspace/qemu/slirp/socket.c
--- kvm-76/qemu/slirp/socket.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/slirp/socket.c	2008-10-12 09:38:24.000000000 +0200
@@ -116,6 +116,8 @@
 	len = sb->sb_datalen - sb->sb_cc;
 
 	iov[0].iov_base = sb->sb_wptr;
+        iov[1].iov_base = NULL;
+        iov[1].iov_len = 0;
 	if (sb->sb_wptr < sb->sb_rptr) {
 		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
 		/* Should never succeed, but... */
@@ -319,6 +321,8 @@
         len = sb->sb_cc;
 
 	iov[0].iov_base = sb->sb_rptr;
+        iov[1].iov_base = NULL;
+        iov[1].iov_len = 0;
 	if (sb->sb_rptr < sb->sb_wptr) {
 		iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
 		/* Should never succeed, but... */
diff -Nur kvm-76/qemu/sparc-dis.c kvm-userspace/qemu/sparc-dis.c
--- kvm-76/qemu/sparc-dis.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/sparc-dis.c	2008-10-12 09:38:24.000000000 +0200
@@ -67,11 +67,7 @@
   short supported;
 };
 
-extern const struct sparc_opcode_arch sparc_opcode_archs[];
-
-/* Given architecture name, look up it's sparc_opcode_arch_val value.  */
-extern enum sparc_opcode_arch_val sparc_opcode_lookup_arch
-  PARAMS ((const char *));
+static const struct sparc_opcode_arch sparc_opcode_archs[];
 
 /* Return the bitmask of supported architectures for ARCH.  */
 #define SPARC_OPCODE_SUPPORTED(ARCH) (sparc_opcode_archs[ARCH].supported)
@@ -216,17 +212,14 @@
 #define RS1_G0  RS1(~0)
 #define RS2_G0  RS2(~0)
 
-extern const struct sparc_opcode sparc_opcodes[];
-extern const int sparc_num_opcodes;
+static const struct sparc_opcode sparc_opcodes[];
+static const int sparc_num_opcodes;
 
-extern int sparc_encode_asi PARAMS ((const char *));
-extern const char *sparc_decode_asi PARAMS ((int));
-extern int sparc_encode_membar PARAMS ((const char *));
-extern const char *sparc_decode_membar PARAMS ((int));
-extern int sparc_encode_prefetch PARAMS ((const char *));
-extern const char *sparc_decode_prefetch PARAMS ((int));
-extern int sparc_encode_sparclet_cpreg PARAMS ((const char *));
-extern const char *sparc_decode_sparclet_cpreg PARAMS ((int));
+static const char *sparc_decode_asi_v8 PARAMS ((int));
+static const char *sparc_decode_asi_v9 PARAMS ((int));
+static const char *sparc_decode_membar PARAMS ((int));
+static const char *sparc_decode_prefetch PARAMS ((int));
+static const char *sparc_decode_sparclet_cpreg PARAMS ((int));
 
 /* Some defines to make life easy.  */
 #define MASK_V6         SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V6)
@@ -270,7 +263,7 @@
 /* Table of opcode architectures.
    The order is defined in opcode/sparc.h.  */
 
-const struct sparc_opcode_arch sparc_opcode_archs[] = {
+static const struct sparc_opcode_arch sparc_opcode_archs[] = {
   { "v6", MASK_V6 },
   { "v7", MASK_V6 | MASK_V7 },
   { "v8", MASK_V6 | MASK_V7 | MASK_V8 },
@@ -285,23 +278,6 @@
   { NULL, 0 }
 };
 
-/* Given NAME, return it's architecture entry.  */
-
-enum sparc_opcode_arch_val
-sparc_opcode_lookup_arch (name)
-     const char *name;
-{
-  const struct sparc_opcode_arch *p;
-
-  for (p = &sparc_opcode_archs[0]; p->name; ++p)
-    {
-      if (strcmp (name, p->name) == 0)
-        return (enum sparc_opcode_arch_val) (p - &sparc_opcode_archs[0]);
-    }
-
-  return SPARC_OPCODE_ARCH_BAD;
-}
-
 /* Branch condition field.  */
 #define COND(x)         (((x)&0xf)<<25)
 
@@ -374,7 +350,7 @@
 { opcode,       F3(2, op3, 1), F3(~2, ~op3, ~1),                "1,i,d", 0, arch_mask }, \
 { opcode,       F3(2, op3, 1), F3(~2, ~op3, ~1),                "i,1,d", 0, arch_mask }
 
-const struct sparc_opcode sparc_opcodes[] = {
+static const struct sparc_opcode sparc_opcodes[] = {
 
 { "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0),              "[1+2],d", 0, v6 },
 { "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0,       "[1],d", 0, v6 }, /* ld [rs1+%g0],d */
@@ -2055,7 +2031,7 @@
 
 };
 
-const int sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]));
+static const int sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0]));
 
 /* Utilities for argument parsing.  */
 
@@ -2067,23 +2043,8 @@
 
 /* Look up NAME in TABLE.  */
 
-static int lookup_name PARAMS ((const arg *, const char *));
 static const char *lookup_value PARAMS ((const arg *, int));
 
-static int
-lookup_name (table, name)
-     const arg *table;
-     const char *name;
-{
-  const arg *p;
-
-  for (p = table; p->name; ++p)
-    if (strcmp (name, p->name) == 0)
-      return p->value;
-
-  return -1;
-}
-
 /* Look up VALUE in TABLE.  */
 
 static const char *
@@ -2218,15 +2179,6 @@
   { 0, 0 }
 };
 
-/* Return the value for membar arg NAME, or -1 if not found.  */
-
-int
-sparc_encode_membar (name)
-     const char *name;
-{
-  return lookup_name (membar_table, name);
-}
-
 /* Return the name for membar value VALUE or NULL if not found.  */
 
 const char *
@@ -2249,15 +2201,6 @@
   { 0, 0 }
 };
 
-/* Return the value for prefetch arg NAME, or -1 if not found.  */
-
-int
-sparc_encode_prefetch (name)
-     const char *name;
-{
-  return lookup_name (prefetch_table, name);
-}
-
 /* Return the name for prefetch value VALUE or NULL if not found.  */
 
 const char *
@@ -2281,15 +2224,6 @@
   { 0, 0 }
 };
 
-/* Return the value for sparclet cpreg arg NAME, or -1 if not found.  */
-
-int
-sparc_encode_sparclet_cpreg (name)
-     const char *name;
-{
-  return lookup_name (sparclet_cpreg_table, name);
-}
-
 /* Return the name for sparclet cpreg value VALUE or NULL if not found.  */
 
 const char *
diff -Nur kvm-76/qemu/sysemu.h kvm-userspace/qemu/sysemu.h
--- kvm-76/qemu/sysemu.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/sysemu.h	2008-10-12 09:38:24.000000000 +0200
@@ -88,6 +88,7 @@
 extern int graphic_width;
 extern int graphic_height;
 extern int graphic_depth;
+extern int nographic;
 extern const char *keyboard_layout;
 extern int win2k_install_hack;
 extern int alt_grab;
@@ -97,7 +98,6 @@
 extern int graphic_rotate;
 extern int no_quit;
 extern int semihosting_enabled;
-extern int autostart;
 extern int old_param;
 extern int hpagesize;
 extern const char *bootp_filename;
diff -Nur kvm-76/qemu/target-alpha/STATUS kvm-userspace/qemu/target-alpha/STATUS
--- kvm-76/qemu/target-alpha/STATUS	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-alpha/STATUS	2008-10-12 09:38:24.000000000 +0200
@@ -5,18 +5,13 @@
 exec.h          : CPU definitions used only for translated code execution
 helper.c        : helpers that can be called either by the translated code
                   or the Qemu core, including the exception handler.
-op.c            : Alpha dedicated micro-operations used by the code translator
-op_helper.c     : helpers that can be called only from micro-operations
-op_helper.h     : micro-operations helpers prototypes
-op_helper_mem.h : micro-operations templates
-                  for load and stores accesses helpers
-op_mem.h        : micro-operations templates for load and stores accesses
-op_template.h   : micro-operation templates for register moves
+op_helper.c     : helpers that can be called only from TCG
+helper.h        : TCG helpers prototypes
 translate.c     : Alpha instructions to micro-operations translator
 
 Code translator status:
 The Alpha CPU instruction emulation should be quite complete with the
-limitation that the VAX floating-point load and stores are not implemented.
+limitation that the VAX floating-point load and stores are not tested.
 The 4 MMU modes are implemented.
 
 Linux user mode emulation status:
diff -Nur kvm-76/qemu/target-alpha/cpu.h kvm-userspace/qemu/target-alpha/cpu.h
--- kvm-76/qemu/target-alpha/cpu.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-alpha/cpu.h	2008-10-12 09:38:24.000000000 +0200
@@ -277,8 +277,6 @@
      */
     target_ulong t0, t1;
 #endif
-    /* */
-    double ft0, ft1, ft2;
 
     /* Those resources are used only in Qemu core */
     CPU_COMMON
diff -Nur kvm-76/qemu/target-alpha/exec.h kvm-userspace/qemu/target-alpha/exec.h
--- kvm-76/qemu/target-alpha/exec.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-alpha/exec.h	2008-10-12 09:38:24.000000000 +0200
@@ -29,32 +29,10 @@
 
 register struct CPUAlphaState *env asm(AREG0);
 
-#if TARGET_LONG_BITS > HOST_LONG_BITS
-
-/* no registers can be used */
-#define T0 (env->t0)
-#define T1 (env->t1)
-
-#else
-
-register uint64_t T0 asm(AREG1);
-register uint64_t T1 asm(AREG2);
-
-#endif /* TARGET_LONG_BITS > HOST_LONG_BITS */
-
 #define PARAM(n) ((uint64_t)PARAM##n)
 #define SPARAM(n) ((int32_t)PARAM##n)
-#define FT0 (env->ft0)
-#define FT1 (env->ft1)
-#define FT2 (env->ft2)
 #define FP_STATUS (env->fp_status)
 
-#if defined (DEBUG_OP)
-#define RETURN() __asm__ __volatile__("nop" : : : "memory");
-#else
-#define RETURN() __asm__ __volatile__("" : : : "memory");
-#endif
-
 #include "cpu.h"
 #include "exec-all.h"
 
diff -Nur kvm-76/qemu/target-alpha/helper.c kvm-userspace/qemu/target-alpha/helper.c
--- kvm-76/qemu/target-alpha/helper.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-alpha/helper.c	2008-10-12 09:38:24.000000000 +0200
@@ -434,21 +434,5 @@
         if ((i % 3) == 2)
             cpu_fprintf(f, "\n");
     }
-    cpu_fprintf(f, "FT " TARGET_FMT_lx " " TARGET_FMT_lx " " TARGET_FMT_lx,
-                *((uint64_t *)(&env->ft0)), *((uint64_t *)(&env->ft1)),
-                *((uint64_t *)(&env->ft2)));
-    cpu_fprintf(f, "\nMEM " TARGET_FMT_lx " %d %d\n",
-                ldq_raw(0x000000004007df60ULL),
-                (uint8_t *)(&env->ft0), (uint8_t *)(&env->fir[0]));
 }
 
-void cpu_dump_EA (target_ulong EA)
-{
-    FILE *f;
-
-    if (logfile)
-        f = logfile;
-    else
-        f = stdout;
-    fprintf(f, "Memory access at address " TARGET_FMT_lx "\n", EA);
-}
diff -Nur kvm-76/qemu/target-alpha/helper.h kvm-userspace/qemu/target-alpha/helper.h
--- kvm-76/qemu/target-alpha/helper.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-alpha/helper.h	2008-10-12 09:38:24.000000000 +0200
@@ -41,3 +41,93 @@
 DEF_HELPER(uint64_t, helper_insqh, (int64_t, uint64_t))
 
 DEF_HELPER(uint64_t, helper_cmpbge, (uint64_t, uint64_t))
+
+DEF_HELPER(uint64_t, helper_load_fpcr, (void))
+DEF_HELPER(void, helper_store_fpcr, (uint64_t val))
+
+DEF_HELPER(uint32_t, helper_f_to_memory, (uint64_t s))
+DEF_HELPER(uint64_t, helper_memory_to_f, (uint32_t s))
+DEF_HELPER(uint64_t, helper_addf, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_subf, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_mulf, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_divf, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_sqrtf, (uint64_t))
+
+DEF_HELPER(uint64_t, helper_g_to_memory, (uint64_t s))
+DEF_HELPER(uint64_t, helper_memory_to_g, (uint64_t s))
+DEF_HELPER(uint64_t, helper_addg, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_subg, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_mulg, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_divg, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_sqrtg, (uint64_t))
+
+DEF_HELPER(uint32_t, helper_s_to_memory, (uint64_t s))
+DEF_HELPER(uint64_t, helper_memory_to_s, (uint32_t s))
+DEF_HELPER(uint64_t, helper_adds, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_subs, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_muls, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_divs, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_sqrts, (uint64_t))
+
+DEF_HELPER(uint64_t, helper_addt, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_subt, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_mult, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_divt, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_sqrtt, (uint64_t))
+
+DEF_HELPER(uint64_t, helper_cmptun, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cmpteq, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cmptle, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cmptlt, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cmpgeq, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cmpgle, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cmpglt, (uint64_t, uint64_t))
+
+DEF_HELPER(uint64_t, helper_cmpfeq, (uint64_t))
+DEF_HELPER(uint64_t, helper_cmpfne, (uint64_t))
+DEF_HELPER(uint64_t, helper_cmpflt, (uint64_t))
+DEF_HELPER(uint64_t, helper_cmpfle, (uint64_t))
+DEF_HELPER(uint64_t, helper_cmpfgt, (uint64_t))
+DEF_HELPER(uint64_t, helper_cmpfge, (uint64_t))
+
+DEF_HELPER(uint64_t, helper_cpys, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cpysn, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_cpyse, (uint64_t, uint64_t))
+
+DEF_HELPER(uint64_t, helper_cvtts, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtst, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvttq, (uint64_t))
+DEF_HELPER(uint32_t, helper_cvtqs, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtqt, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtqf, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtgf, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtgq, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtqg, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtlq, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtql, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtqlv, (uint64_t))
+DEF_HELPER(uint64_t, helper_cvtqlsv, (uint64_t))
+
+#if !defined (CONFIG_USER_ONLY)
+DEF_HELPER(void, helper_hw_rei, (void))
+DEF_HELPER(void, helper_hw_ret, (uint64_t))
+DEF_HELPER(uint64_t, helper_mfpr, (int, uint64_t))
+DEF_HELPER(void, helper_mtpr, (int, uint64_t))
+DEF_HELPER(void, helper_set_alt_mode, (void))
+DEF_HELPER(void, helper_restore_mode, (void))
+
+DEF_HELPER(uint64_t, helper_ld_virt_to_phys, (uint64_t))
+DEF_HELPER(uint64_t, helper_st_virt_to_phys, (uint64_t))
+DEF_HELPER(void, helper_ldl_raw, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_ldq_raw, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_ldl_l_raw, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_ldq_l_raw, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_ldl_kernel, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_ldq_kernel, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_ldl_data, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_ldq_data, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_stl_raw, (uint64_t, uint64_t))
+DEF_HELPER(void, helper_stq_raw, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_stl_c_raw, (uint64_t, uint64_t))
+DEF_HELPER(uint64_t, helper_stq_c_raw, (uint64_t, uint64_t))
+#endif
diff -Nur kvm-76/qemu/target-alpha/op_helper.c kvm-userspace/qemu/target-alpha/op_helper.c
--- kvm-76/qemu/target-alpha/op_helper.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-alpha/op_helper.c	2008-10-12 09:38:24.000000000 +0200
@@ -22,40 +22,11 @@
 #include "host-utils.h"
 #include "softfloat.h"
 
-#include "op_helper.h"
-
-#define MEMSUFFIX _raw
-#include "op_helper_mem.h"
-
-#if !defined(CONFIG_USER_ONLY)
-#define MEMSUFFIX _kernel
-#include "op_helper_mem.h"
-
-#define MEMSUFFIX _executive
-#include "op_helper_mem.h"
-
-#define MEMSUFFIX _supervisor
-#include "op_helper_mem.h"
-
-#define MEMSUFFIX _user
-#include "op_helper_mem.h"
-
-/* This is used for pal modes */
-#define MEMSUFFIX _data
-#include "op_helper_mem.h"
-#endif
-
 void helper_tb_flush (void)
 {
     tlb_flush(env, 1);
 }
 
-void cpu_dump_EA (target_ulong EA);
-void helper_print_mem_EA (target_ulong EA)
-{
-    cpu_dump_EA(EA);
-}
-
 /*****************************************************************************/
 /* Exceptions processing helpers */
 void helper_excp (int excp, int error)
@@ -91,37 +62,38 @@
     return env->implver;
 }
 
-void helper_load_fpcr (void)
+uint64_t helper_load_fpcr (void)
 {
-    T0 = 0;
+    uint64_t ret = 0;
 #ifdef CONFIG_SOFTFLOAT
-    T0 |= env->fp_status.float_exception_flags << 52;
+    ret |= env->fp_status.float_exception_flags << 52;
     if (env->fp_status.float_exception_flags)
-        T0 |= 1ULL << 63;
+        ret |= 1ULL << 63;
     env->ipr[IPR_EXC_SUM] &= ~0x3E:
     env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
 #endif
     switch (env->fp_status.float_rounding_mode) {
     case float_round_nearest_even:
-        T0 |= 2ULL << 58;
+        ret |= 2ULL << 58;
         break;
     case float_round_down:
-        T0 |= 1ULL << 58;
+        ret |= 1ULL << 58;
         break;
     case float_round_up:
-        T0 |= 3ULL << 58;
+        ret |= 3ULL << 58;
         break;
     case float_round_to_zero:
         break;
     }
+    return ret;
 }
 
-void helper_store_fpcr (void)
+void helper_store_fpcr (uint64_t val)
 {
 #ifdef CONFIG_SOFTFLOAT
-    set_float_exception_flags((T0 >> 52) & 0x3F, &FP_STATUS);
+    set_float_exception_flags((val >> 52) & 0x3F, &FP_STATUS);
 #endif
-    switch ((T0 >> 58) & 3) {
+    switch ((val >> 58) & 3) {
     case 0:
         set_float_rounding_mode(float_round_to_zero, &FP_STATUS);
         break;
@@ -367,707 +339,691 @@
     return res;
 }
 
-void helper_cmov_fir (int freg)
+/* Floating point helpers */
+
+/* F floating (VAX) */
+static always_inline uint64_t float32_to_f (float32 fa)
 {
-    if (FT0 != 0)
-        env->fir[freg] = FT1;
+    uint32_t a;
+    uint64_t r, exp, mant, sig;
+
+    a = *(uint32_t*)(&fa);
+    sig = ((uint64_t)a & 0x80000000) << 32;
+    exp = (a >> 23) & 0xff;
+    mant = ((uint64_t)a & 0x007fffff) << 29;
+
+    if (exp == 255) {
+        /* NaN or infinity */
+        r = 1; /* VAX dirty zero */
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            r = 0;
+        } else {
+            /* Denormalized */
+            r = sig | ((exp + 1) << 52) | mant;
+        }
+    } else {
+        if (exp >= 253) {
+            /* Overflow */
+            r = 1; /* VAX dirty zero */
+        } else {
+            r = sig | ((exp + 2) << 52);
+        }
+    }
+
+    return r;
 }
 
-void helper_sqrts (void)
+static always_inline float32 f_to_float32 (uint64_t a)
 {
-    FT0 = float32_sqrt(FT0, &FP_STATUS);
+    uint32_t r, exp, mant_sig;
+
+    exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f);
+    mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff);
+
+    if (unlikely(!exp && mant_sig)) {
+        /* Reserved operands / Dirty zero */
+        helper_excp(EXCP_OPCDEC, 0);
+    }
+
+    if (exp < 3) {
+        /* Underflow */
+        r = 0;
+    } else {
+        r = ((exp - 2) << 23) | mant_sig;
+    }
+
+    return *(float32*)(&a);
 }
 
-void helper_cpys (void)
+uint32_t helper_f_to_memory (uint64_t a)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p, q, r;
+    uint32_t r;
+    r =  (a & 0x00001fffe0000000ull) >> 13;
+    r |= (a & 0x07ffe00000000000ull) >> 45;
+    r |= (a & 0xc000000000000000ull) >> 48;
+    return r;
+}
 
-    p.d = FT0;
-    q.d = FT1;
-    r.i = p.i & 0x8000000000000000ULL;
-    r.i |= q.i & ~0x8000000000000000ULL;
-    FT0 = r.d;
+uint64_t helper_memory_to_f (uint32_t a)
+{
+    uint64_t r;
+    r =  ((uint64_t)(a & 0x0000c000)) << 48;
+    r |= ((uint64_t)(a & 0x003fffff)) << 45;
+    r |= ((uint64_t)(a & 0xffff0000)) << 13;
+    if (!(a & 0x00004000))
+        r |= 0x7ll << 59;
+    return r;
 }
 
-void helper_cpysn (void)
+uint64_t helper_addf (uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p, q, r;
+    float32 fa, fb, fr;
 
-    p.d = FT0;
-    q.d = FT1;
-    r.i = (~p.i) & 0x8000000000000000ULL;
-    r.i |= q.i & ~0x8000000000000000ULL;
-    FT0 = r.d;
+    fa = f_to_float32(a);
+    fb = f_to_float32(b);
+    fr = float32_add(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
 }
 
-void helper_cpyse (void)
+uint64_t helper_subf (uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p, q, r;
+    float32 fa, fb, fr;
 
-    p.d = FT0;
-    q.d = FT1;
-    r.i = p.i & 0xFFF0000000000000ULL;
-    r.i |= q.i & ~0xFFF0000000000000ULL;
-    FT0 = r.d;
+    fa = f_to_float32(a);
+    fb = f_to_float32(b);
+    fr = float32_sub(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
 }
 
-void helper_itofs (void)
+uint64_t helper_mulf (uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    float32 fa, fb, fr;
 
-    p.d = FT0;
-    FT0 = int64_to_float32(p.i, &FP_STATUS);
+    fa = f_to_float32(a);
+    fb = f_to_float32(b);
+    fr = float32_mul(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
 }
 
-void helper_ftois (void)
+uint64_t helper_divf (uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    float32 fa, fb, fr;
 
-    p.i = float32_to_int64(FT0, &FP_STATUS);
-    FT0 = p.d;
+    fa = f_to_float32(a);
+    fb = f_to_float32(b);
+    fr = float32_div(fa, fb, &FP_STATUS);
+    return float32_to_f(fr);
 }
 
-void helper_sqrtt (void)
+uint64_t helper_sqrtf (uint64_t t)
 {
-    FT0 = float64_sqrt(FT0, &FP_STATUS);
+    float32 ft, fr;
+
+    ft = f_to_float32(t);
+    fr = float32_sqrt(ft, &FP_STATUS);
+    return float32_to_f(fr);
 }
 
-void helper_cmptun (void)
+
+/* G floating (VAX) */
+static always_inline uint64_t float64_to_g (float64 fa)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    uint64_t a, r, exp, mant, sig;
 
-    p.i = 0;
-    if (float64_is_nan(FT0) || float64_is_nan(FT1))
-        p.i = 0x4000000000000000ULL;
-    FT0 = p.d;
+    a = *(uint64_t*)(&fa);
+    sig = a & 0x8000000000000000ull;
+    exp = (a >> 52) & 0x7ff;
+    mant = a & 0x000fffffffffffffull;
+
+    if (exp == 2047) {
+        /* NaN or infinity */
+        r = 1; /* VAX dirty zero */
+    } else if (exp == 0) {
+        if (mant == 0) {
+            /* Zero */
+            r = 0;
+        } else {
+            /* Denormalized */
+            r = sig | ((exp + 1) << 52) | mant;
+        }
+    } else {
+        if (exp >= 2045) {
+            /* Overflow */
+            r = 1; /* VAX dirty zero */
+        } else {
+            r = sig | ((exp + 2) << 52);
+        }
+    }
+
+    return r;
 }
 
-void helper_cmpteq (void)
+static always_inline float64 g_to_float64 (uint64_t a)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    uint64_t r, exp, mant_sig;
+
+    exp = (a >> 52) & 0x7ff;
+    mant_sig = a & 0x800fffffffffffffull;
+
+    if (!exp && mant_sig) {
+        /* Reserved operands / Dirty zero */
+        helper_excp(EXCP_OPCDEC, 0);
+    }
 
-    p.i = 0;
-    if (float64_eq(FT0, FT1, &FP_STATUS))
-        p.i = 0x4000000000000000ULL;
-    FT0 = p.d;
+    if (exp < 3) {
+        /* Underflow */
+        r = 0;
+    } else {
+        r = ((exp - 2) << 52) | mant_sig;
+    }
+
+    return *(float64*)(&a);
 }
 
-void helper_cmptle (void)
+uint64_t helper_g_to_memory (uint64_t a)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    uint64_t r;
+    r =  (a & 0x000000000000ffffull) << 48;
+    r |= (a & 0x00000000ffff0000ull) << 16;
+    r |= (a & 0x0000ffff00000000ull) >> 16;
+    r |= (a & 0xffff000000000000ull) >> 48;
+    return r;
+}
 
-    p.i = 0;
-    if (float64_le(FT0, FT1, &FP_STATUS))
-        p.i = 0x4000000000000000ULL;
-    FT0 = p.d;
+uint64_t helper_memory_to_g (uint64_t a)
+{
+    uint64_t r;
+    r =  (a & 0x000000000000ffffull) << 48;
+    r |= (a & 0x00000000ffff0000ull) << 16;
+    r |= (a & 0x0000ffff00000000ull) >> 16;
+    r |= (a & 0xffff000000000000ull) >> 48;
+    return r;
 }
 
-void helper_cmptlt (void)
+uint64_t helper_addg (uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    float64 fa, fb, fr;
 
-    p.i = 0;
-    if (float64_lt(FT0, FT1, &FP_STATUS))
-        p.i = 0x4000000000000000ULL;
-    FT0 = p.d;
+    fa = g_to_float64(a);
+    fb = g_to_float64(b);
+    fr = float64_add(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
 }
 
-void helper_itoft (void)
+uint64_t helper_subg (uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    float64 fa, fb, fr;
 
-    p.d = FT0;
-    FT0 = int64_to_float64(p.i, &FP_STATUS);
+    fa = g_to_float64(a);
+    fb = g_to_float64(b);
+    fr = float64_sub(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
 }
 
-void helper_ftoit (void)
+uint64_t helper_mulg (uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t i;
-    } p;
+    float64 fa, fb, fr;
 
-    p.i = float64_to_int64(FT0, &FP_STATUS);
-    FT0 = p.d;
+    fa = g_to_float64(a);
+    fb = g_to_float64(b);
+    fr = float64_mul(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
 }
 
-static always_inline int vaxf_is_valid (float ff)
+uint64_t helper_divg (uint64_t a, uint64_t b)
 {
-    union {
-        float f;
-        uint32_t i;
-    } p;
-    uint32_t exp, mant;
+    float64 fa, fb, fr;
 
-    p.f = ff;
-    exp = (p.i >> 23) & 0xFF;
-    mant = p.i & 0x007FFFFF;
-    if (exp == 0 && ((p.i & 0x80000000) || mant != 0)) {
-        /* Reserved operands / Dirty zero */
-        return 0;
-    }
+    fa = g_to_float64(a);
+    fb = g_to_float64(b);
+    fr = float64_div(fa, fb, &FP_STATUS);
+    return float64_to_g(fr);
+}
+
+uint64_t helper_sqrtg (uint64_t a)
+{
+    float64 fa, fr;
 
-    return 1;
+    fa = g_to_float64(a);
+    fr = float64_sqrt(fa, &FP_STATUS);
+    return float64_to_g(fr);
 }
 
-static always_inline float vaxf_to_ieee32 (float ff)
+
+/* S floating (single) */
+static always_inline uint64_t float32_to_s (float32 fa)
 {
-    union {
-        float f;
-        uint32_t i;
-    } p;
-    uint32_t exp;
+    uint32_t a;
+    uint64_t r;
 
-    p.f = ff;
-    exp = (p.i >> 23) & 0xFF;
-    if (exp < 3) {
-        /* Underflow */
-        p.f = 0.0;
-    } else {
-        p.f *= 0.25;
-    }
+    a = *(uint32_t*)(&fa);
 
-    return p.f;
+    r = (((uint64_t)(a & 0xc0000000)) << 32) | (((uint64_t)(a & 0x3fffffff)) << 29);
+    if (((a & 0x7f800000) != 0x7f800000) && (!(a & 0x40000000)))
+        r |= 0x7ll << 59;
+    return r;
 }
 
-static always_inline float ieee32_to_vaxf (float fi)
+static always_inline float32 s_to_float32 (uint64_t a)
 {
-    union {
-        float f;
-        uint32_t i;
-    } p;
-    uint32_t exp, mant;
+    uint32_t r = ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff);
+    return *(float32*)(&r);
+}
 
-    p.f = fi;
-    exp = (p.i >> 23) & 0xFF;
-    mant = p.i & 0x007FFFFF;
-    if (exp == 255) {
-        /* NaN or infinity */
-        p.i = 1;
-    } else if (exp == 0) {
-        if (mant == 0) {
-            /* Zero */
-            p.i = 0;
-        } else {
-            /* Denormalized */
-            p.f *= 2.0;
-        }
-    } else {
-        if (exp >= 253) {
-            /* Overflow */
-            p.i = 1;
-        } else {
-            p.f *= 4.0;
-        }
-    }
+uint32_t helper_s_to_memory (uint64_t a)
+{
+    /* Memory format is the same as float32 */
+    float32 fa = s_to_float32(a);
+    return *(uint32_t*)(&fa);
+}
 
-    return p.f;
+uint64_t helper_memory_to_s (uint32_t a)
+{
+    /* Memory format is the same as float32 */
+    return float32_to_s(*(float32*)(&a));
 }
 
-void helper_addf (void)
+uint64_t helper_adds (uint64_t a, uint64_t b)
 {
-    float ft0, ft1, ft2;
+    float32 fa, fb, fr;
 
-    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxf_to_ieee32(FT0);
-    ft1 = vaxf_to_ieee32(FT1);
-    ft2 = float32_add(ft0, ft1, &FP_STATUS);
-    FT0 = ieee32_to_vaxf(ft2);
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_add(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
 }
 
-void helper_subf (void)
+uint64_t helper_subs (uint64_t a, uint64_t b)
 {
-    float ft0, ft1, ft2;
+    float32 fa, fb, fr;
 
-    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxf_to_ieee32(FT0);
-    ft1 = vaxf_to_ieee32(FT1);
-    ft2 = float32_sub(ft0, ft1, &FP_STATUS);
-    FT0 = ieee32_to_vaxf(ft2);
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_sub(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
 }
 
-void helper_mulf (void)
+uint64_t helper_muls (uint64_t a, uint64_t b)
 {
-    float ft0, ft1, ft2;
+    float32 fa, fb, fr;
 
-    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxf_to_ieee32(FT0);
-    ft1 = vaxf_to_ieee32(FT1);
-    ft2 = float32_mul(ft0, ft1, &FP_STATUS);
-    FT0 = ieee32_to_vaxf(ft2);
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_mul(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
 }
 
-void helper_divf (void)
+uint64_t helper_divs (uint64_t a, uint64_t b)
 {
-    float ft0, ft1, ft2;
+    float32 fa, fb, fr;
 
-    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxf_to_ieee32(FT0);
-    ft1 = vaxf_to_ieee32(FT1);
-    ft2 = float32_div(ft0, ft1, &FP_STATUS);
-    FT0 = ieee32_to_vaxf(ft2);
+    fa = s_to_float32(a);
+    fb = s_to_float32(b);
+    fr = float32_div(fa, fb, &FP_STATUS);
+    return float32_to_s(fr);
 }
 
-void helper_sqrtf (void)
+uint64_t helper_sqrts (uint64_t a)
 {
-    float ft0, ft1;
+    float32 fa, fr;
 
-    if (!vaxf_is_valid(FT0) || !vaxf_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxf_to_ieee32(FT0);
-    ft1 = float32_sqrt(ft0, &FP_STATUS);
-    FT0 = ieee32_to_vaxf(ft1);
+    fa = s_to_float32(a);
+    fr = float32_sqrt(fa, &FP_STATUS);
+    return float32_to_s(fr);
 }
 
-void helper_itoff (void)
+
+/* T floating (double) */
+static always_inline float64 t_to_float64 (uint64_t a)
 {
-    /* XXX: TODO */
+    /* Memory format is the same as float64 */
+    return *(float64*)(&a);
 }
 
-static always_inline int vaxg_is_valid (double ff)
+static always_inline uint64_t float64_to_t (float64 fa)
 {
-    union {
-        double f;
-        uint64_t i;
-    } p;
-    uint64_t exp, mant;
-
-    p.f = ff;
-    exp = (p.i >> 52) & 0x7FF;
-    mant = p.i & 0x000FFFFFFFFFFFFFULL;
-    if (exp == 0 && ((p.i & 0x8000000000000000ULL) || mant != 0)) {
-        /* Reserved operands / Dirty zero */
-        return 0;
-    }
-
-    return 1;
+    /* Memory format is the same as float64 */
+    return *(uint64*)(&fa);
 }
 
-static always_inline double vaxg_to_ieee64 (double fg)
+uint64_t helper_addt (uint64_t a, uint64_t b)
 {
-    union {
-        double f;
-        uint64_t i;
-    } p;
-    uint32_t exp;
-
-    p.f = fg;
-    exp = (p.i >> 52) & 0x7FF;
-    if (exp < 3) {
-        /* Underflow */
-        p.f = 0.0;
-    } else {
-        p.f *= 0.25;
-    }
+    float64 fa, fb, fr;
 
-    return p.f;
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_add(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
 }
 
-static always_inline double ieee64_to_vaxg (double fi)
+uint64_t helper_subt (uint64_t a, uint64_t b)
 {
-    union {
-        double f;
-        uint64_t i;
-    } p;
-    uint64_t mant;
-    uint32_t exp;
-
-    p.f = fi;
-    exp = (p.i >> 52) & 0x7FF;
-    mant = p.i & 0x000FFFFFFFFFFFFFULL;
-    if (exp == 255) {
-        /* NaN or infinity */
-        p.i = 1; /* VAX dirty zero */
-    } else if (exp == 0) {
-        if (mant == 0) {
-            /* Zero */
-            p.i = 0;
-        } else {
-            /* Denormalized */
-            p.f *= 2.0;
-        }
-    } else {
-        if (exp >= 2045) {
-            /* Overflow */
-            p.i = 1; /* VAX dirty zero */
-        } else {
-            p.f *= 4.0;
-        }
-    }
+    float64 fa, fb, fr;
 
-    return p.f;
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_sub(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
 }
 
-void helper_addg (void)
+uint64_t helper_mult (uint64_t a, uint64_t b)
 {
-    double ft0, ft1, ft2;
+    float64 fa, fb, fr;
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = vaxg_to_ieee64(FT1);
-    ft2 = float64_add(ft0, ft1, &FP_STATUS);
-    FT0 = ieee64_to_vaxg(ft2);
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_mul(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
 }
 
-void helper_subg (void)
+uint64_t helper_divt (uint64_t a, uint64_t b)
 {
-    double ft0, ft1, ft2;
+    float64 fa, fb, fr;
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = vaxg_to_ieee64(FT1);
-    ft2 = float64_sub(ft0, ft1, &FP_STATUS);
-    FT0 = ieee64_to_vaxg(ft2);
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+    fr = float64_div(fa, fb, &FP_STATUS);
+    return float64_to_t(fr);
 }
 
-void helper_mulg (void)
+uint64_t helper_sqrtt (uint64_t a)
 {
-    double ft0, ft1, ft2;
+    float64 fa, fr;
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = vaxg_to_ieee64(FT1);
-    ft2 = float64_mul(ft0, ft1, &FP_STATUS);
-    FT0 = ieee64_to_vaxg(ft2);
+    fa = t_to_float64(a);
+    fr = float64_sqrt(fa, &FP_STATUS);
+    return float64_to_t(fr);
 }
 
-void helper_divg (void)
+
+/* Sign copy */
+uint64_t helper_cpys(uint64_t a, uint64_t b)
 {
-    double ft0, ft1, ft2;
+    return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
+}
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = vaxg_to_ieee64(FT1);
-    ft2 = float64_div(ft0, ft1, &FP_STATUS);
-    FT0 = ieee64_to_vaxg(ft2);
+uint64_t helper_cpysn(uint64_t a, uint64_t b)
+{
+    return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL);
 }
 
-void helper_sqrtg (void)
+uint64_t helper_cpyse(uint64_t a, uint64_t b)
 {
-    double ft0, ft1;
+    return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL);
+}
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = float64_sqrt(ft0, &FP_STATUS);
-    FT0 = ieee64_to_vaxg(ft1);
+
+/* Comparisons */
+uint64_t helper_cmptun (uint64_t a, uint64_t b)
+{
+    float64 fa, fb;
+
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_is_nan(fa) || float64_is_nan(fb))
+        return 0x4000000000000000ULL;
+    else
+        return 0;
 }
 
-void helper_cmpgeq (void)
+uint64_t helper_cmpteq(uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
-    double ft0, ft1;
+    float64 fa, fb;
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = vaxg_to_ieee64(FT1);
-    p.u = 0;
-    if (float64_eq(ft0, ft1, &FP_STATUS))
-        p.u = 0x4000000000000000ULL;
-    FT0 = p.d;
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_eq(fa, fb, &FP_STATUS))
+        return 0x4000000000000000ULL;
+    else
+        return 0;
 }
 
-void helper_cmpglt (void)
+uint64_t helper_cmptle(uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
-    double ft0, ft1;
+    float64 fa, fb;
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = vaxg_to_ieee64(FT1);
-    p.u = 0;
-    if (float64_lt(ft0, ft1, &FP_STATUS))
-        p.u = 0x4000000000000000ULL;
-    FT0 = p.d;
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_le(fa, fb, &FP_STATUS))
+        return 0x4000000000000000ULL;
+    else
+        return 0;
 }
 
-void helper_cmpgle (void)
+uint64_t helper_cmptlt(uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
-    double ft0, ft1;
+    float64 fa, fb;
 
-    if (!vaxg_is_valid(FT0) || !vaxg_is_valid(FT1)) {
-        /* XXX: TODO */
-    }
-    ft0 = vaxg_to_ieee64(FT0);
-    ft1 = vaxg_to_ieee64(FT1);
-    p.u = 0;
-    if (float64_le(ft0, ft1, &FP_STATUS))
-        p.u = 0x4000000000000000ULL;
-    FT0 = p.d;
+    fa = t_to_float64(a);
+    fb = t_to_float64(b);
+
+    if (float64_lt(fa, fb, &FP_STATUS))
+        return 0x4000000000000000ULL;
+    else
+        return 0;
 }
 
-void helper_cvtqs (void)
+uint64_t helper_cmpgeq(uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
+    float64 fa, fb;
 
-    p.d = FT0;
-    FT0 = (float)p.u;
+    fa = g_to_float64(a);
+    fb = g_to_float64(b);
+
+    if (float64_eq(fa, fb, &FP_STATUS))
+        return 0x4000000000000000ULL;
+    else
+        return 0;
 }
 
-void helper_cvttq (void)
+uint64_t helper_cmpgle(uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
+    float64 fa, fb;
+
+    fa = g_to_float64(a);
+    fb = g_to_float64(b);
 
-    p.u = FT0;
-    FT0 = p.d;
+    if (float64_le(fa, fb, &FP_STATUS))
+        return 0x4000000000000000ULL;
+    else
+        return 0;
 }
 
-void helper_cvtqt (void)
+uint64_t helper_cmpglt(uint64_t a, uint64_t b)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
+    float64 fa, fb;
 
-    p.d = FT0;
-    FT0 = p.u;
+    fa = g_to_float64(a);
+    fb = g_to_float64(b);
+
+    if (float64_lt(fa, fb, &FP_STATUS))
+        return 0x4000000000000000ULL;
+    else
+        return 0;
 }
 
-void helper_cvtqf (void)
+uint64_t helper_cmpfeq (uint64_t a)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
+    return !(a & 0x7FFFFFFFFFFFFFFFULL);
+}
 
-    p.d = FT0;
-    FT0 = ieee32_to_vaxf(p.u);
+uint64_t helper_cmpfne (uint64_t a)
+{
+    return (a & 0x7FFFFFFFFFFFFFFFULL);
 }
 
-void helper_cvtgf (void)
+uint64_t helper_cmpflt (uint64_t a)
 {
-    double ft0;
+    return (a & 0x8000000000000000ULL) && (a & 0x7FFFFFFFFFFFFFFFULL);
+}
 
-    ft0 = vaxg_to_ieee64(FT0);
-    FT0 = ieee32_to_vaxf(ft0);
+uint64_t helper_cmpfle (uint64_t a)
+{
+    return (a & 0x8000000000000000ULL) || !(a & 0x7FFFFFFFFFFFFFFFULL);
 }
 
-void helper_cvtgd (void)
+uint64_t helper_cmpfgt (uint64_t a)
 {
-    /* XXX: TODO */
+    return !(a & 0x8000000000000000ULL) && (a & 0x7FFFFFFFFFFFFFFFULL);
 }
 
-void helper_cvtgq (void)
+uint64_t helper_cmpfge (uint64_t a)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
+    return !(a & 0x8000000000000000ULL) || !(a & 0x7FFFFFFFFFFFFFFFULL);
+}
+
+
+/* Floating point format conversion */
+uint64_t helper_cvtts (uint64_t a)
+{
+    float64 fa;
+    float32 fr;
 
-    p.u = vaxg_to_ieee64(FT0);
-    FT0 = p.d;
+    fa = t_to_float64(a);
+    fr = float64_to_float32(fa, &FP_STATUS);
+    return float32_to_s(fr);
 }
 
-void helper_cvtqg (void)
+uint64_t helper_cvtst (uint64_t a)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p;
+    float32 fa;
+    float64 fr;
 
-    p.d = FT0;
-    FT0 = ieee64_to_vaxg(p.u);
+    fa = s_to_float32(a);
+    fr = float32_to_float64(fa, &FP_STATUS);
+    return float64_to_t(fr);
 }
 
-void helper_cvtdg (void)
+uint64_t helper_cvtqs (uint64_t a)
 {
-    /* XXX: TODO */
+    float32 fr = int64_to_float32(a, &FP_STATUS);
+    return float32_to_s(fr);
 }
 
-void helper_cvtlq (void)
+uint64_t helper_cvttq (uint64_t a)
 {
-    union {
-        double d;
-        uint64_t u;
-    } p, q;
-
-    p.d = FT0;
-    q.u = (p.u >> 29) & 0x3FFFFFFF;
-    q.u |= (p.u >> 32);
-    q.u = (int64_t)((int32_t)q.u);
-    FT0 = q.d;
-}
-
-static always_inline void __helper_cvtql (int s, int v)
-{
-    union {
-        double d;
-        uint64_t u;
-    } p, q;
-
-    p.d = FT0;
-    q.u = ((uint64_t)(p.u & 0xC0000000)) << 32;
-    q.u |= ((uint64_t)(p.u & 0x7FFFFFFF)) << 29;
-    FT0 = q.d;
-    if (v && (int64_t)((int32_t)p.u) != (int64_t)p.u) {
-        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
-    }
-    if (s) {
-        /* TODO */
-    }
+    float64 fa = t_to_float64(a);
+    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
 }
 
-void helper_cvtql (void)
+uint64_t helper_cvtqt (uint64_t a)
 {
-    __helper_cvtql(0, 0);
+    float64 fr = int64_to_float64(a, &FP_STATUS);
+    return float64_to_t(fr);
 }
 
-void helper_cvtqlv (void)
+uint64_t helper_cvtqf (uint64_t a)
 {
-    __helper_cvtql(0, 1);
+    float32 fr = int64_to_float32(a, &FP_STATUS);
+    return float32_to_f(fr);
 }
 
-void helper_cvtqlsv (void)
+uint64_t helper_cvtgf (uint64_t a)
 {
-    __helper_cvtql(1, 1);
+    float64 fa;
+    float32 fr;
+
+    fa = g_to_float64(a);
+    fr = float64_to_float32(fa, &FP_STATUS);
+    return float32_to_f(fr);
 }
 
-void helper_cmpfeq (void)
+uint64_t helper_cvtgq (uint64_t a)
 {
-    if (float64_eq(FT0, FT1, &FP_STATUS))
-        T0 = 1;
-    else
-        T0 = 0;
+    float64 fa = g_to_float64(a);
+    return float64_to_int64_round_to_zero(fa, &FP_STATUS);
 }
 
-void helper_cmpfne (void)
+uint64_t helper_cvtqg (uint64_t a)
 {
-    if (float64_eq(FT0, FT1, &FP_STATUS))
-        T0 = 0;
-    else
-        T0 = 1;
+    float64 fr;
+    fr = int64_to_float64(a, &FP_STATUS);
+    return float64_to_g(fr);
 }
 
-void helper_cmpflt (void)
+uint64_t helper_cvtlq (uint64_t a)
 {
-    if (float64_lt(FT0, FT1, &FP_STATUS))
-        T0 = 1;
-    else
-        T0 = 0;
+    return (int64_t)((int32_t)((a >> 32) | ((a >> 29) & 0x3FFFFFFF)));
 }
 
-void helper_cmpfle (void)
+static always_inline uint64_t __helper_cvtql (uint64_t a, int s, int v)
 {
-    if (float64_lt(FT0, FT1, &FP_STATUS))
-        T0 = 1;
-    else
-        T0 = 0;
+    uint64_t r;
+
+    r = ((uint64_t)(a & 0xC0000000)) << 32;
+    r |= ((uint64_t)(a & 0x7FFFFFFF)) << 29;
+
+    if (v && (int64_t)((int32_t)r) != (int64_t)r) {
+        helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW);
+    }
+    if (s) {
+        /* TODO */
+    }
+    return r;
 }
 
-void helper_cmpfgt (void)
+uint64_t helper_cvtql (uint64_t a)
 {
-    if (float64_le(FT0, FT1, &FP_STATUS))
-        T0 = 0;
-    else
-        T0 = 1;
+    return __helper_cvtql(a, 0, 0);
 }
 
-void helper_cmpfge (void)
+uint64_t helper_cvtqlv (uint64_t a)
 {
-    if (float64_lt(FT0, FT1, &FP_STATUS))
-        T0 = 0;
-    else
-        T0 = 1;
+    return __helper_cvtql(a, 0, 1);
+}
+
+uint64_t helper_cvtqlsv (uint64_t a)
+{
+    return __helper_cvtql(a, 1, 1);
 }
 
+/* PALcode support special instructions */
 #if !defined (CONFIG_USER_ONLY)
-void helper_mfpr (int iprn)
+void helper_hw_rei (void)
 {
-    uint64_t val;
+    env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
+    env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
+    /* XXX: re-enable interrupts and memory mapping */
+}
 
-    if (cpu_alpha_mfpr(env, iprn, &val) == 0)
-        T0 = val;
+void helper_hw_ret (uint64_t a)
+{
+    env->pc = a & ~3;
+    env->ipr[IPR_EXC_ADDR] = a & 1;
+    /* XXX: re-enable interrupts and memory mapping */
 }
 
-void helper_mtpr (int iprn)
+uint64_t helper_mfpr (int iprn, uint64_t val)
 {
-    cpu_alpha_mtpr(env, iprn, T0, NULL);
+    uint64_t tmp;
+
+    if (cpu_alpha_mfpr(env, iprn, &tmp) == 0)
+        val = tmp;
+
+    return val;
 }
-#endif
 
-#if defined(HOST_SPARC) || defined(HOST_SPARC64)
-void helper_reset_FT0 (void)
+void helper_mtpr (int iprn, uint64_t val)
 {
-    FT0 = 0;
+    cpu_alpha_mtpr(env, iprn, val, NULL);
 }
 
-void helper_reset_FT1 (void)
+void helper_set_alt_mode (void)
 {
-    FT1 = 0;
+    env->saved_mode = env->ps & 0xC;
+    env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC);
 }
 
-void helper_reset_FT2 (void)
+void helper_restore_mode (void)
 {
-    FT2 = 0;
+    env->ps = (env->ps & ~0xC) | env->saved_mode;
 }
+
 #endif
 
 /*****************************************************************************/
@@ -1078,48 +1034,130 @@
  *      Hopefully, we emulate the PALcode, then we should never see
  *      HW_LD / HW_ST instructions.
  */
-void helper_ld_phys_to_virt (void)
+uint64_t helper_ld_virt_to_phys (uint64_t virtaddr)
 {
     uint64_t tlb_addr, physaddr;
     int index, mmu_idx;
     void *retaddr;
 
     mmu_idx = cpu_mmu_index(env);
-    index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
     tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
-    if ((T0 & TARGET_PAGE_MASK) ==
+    if ((virtaddr & TARGET_PAGE_MASK) ==
         (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-        physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
+        physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
     } else {
         /* the page is not in the TLB : fill it */
         retaddr = GETPC();
-        tlb_fill(T0, 0, mmu_idx, retaddr);
+        tlb_fill(virtaddr, 0, mmu_idx, retaddr);
         goto redo;
     }
-    T0 = physaddr;
+    return physaddr;
 }
 
-void helper_st_phys_to_virt (void)
+uint64_t helper_st_virt_to_phys (uint64_t virtaddr)
 {
     uint64_t tlb_addr, physaddr;
     int index, mmu_idx;
     void *retaddr;
 
     mmu_idx = cpu_mmu_index(env);
-    index = (T0 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
+    index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  redo:
     tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
-    if ((T0 & TARGET_PAGE_MASK) ==
+    if ((virtaddr & TARGET_PAGE_MASK) ==
         (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
-        physaddr = T0 + env->tlb_table[mmu_idx][index].addend;
+        physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend;
     } else {
         /* the page is not in the TLB : fill it */
         retaddr = GETPC();
-        tlb_fill(T0, 1, mmu_idx, retaddr);
+        tlb_fill(virtaddr, 1, mmu_idx, retaddr);
         goto redo;
     }
-    T0 = physaddr;
+    return physaddr;
+}
+
+void helper_ldl_raw(uint64_t t0, uint64_t t1)
+{
+    ldl_raw(t1, t0);
+}
+
+void helper_ldq_raw(uint64_t t0, uint64_t t1)
+{
+    ldq_raw(t1, t0);
+}
+
+void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
+{
+    env->lock = t1;
+    ldl_raw(t1, t0);
+}
+
+void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
+{
+    env->lock = t1;
+    ldl_raw(t1, t0);
+}
+
+void helper_ldl_kernel(uint64_t t0, uint64_t t1)
+{
+    ldl_kernel(t1, t0);
+}
+
+void helper_ldq_kernel(uint64_t t0, uint64_t t1)
+{
+    ldq_kernel(t1, t0);
+}
+
+void helper_ldl_data(uint64_t t0, uint64_t t1)
+{
+    ldl_data(t1, t0);
+}
+
+void helper_ldq_data(uint64_t t0, uint64_t t1)
+{
+    ldq_data(t1, t0);
+}
+
+void helper_stl_raw(uint64_t t0, uint64_t t1)
+{
+    stl_raw(t1, t0);
+}
+
+void helper_stq_raw(uint64_t t0, uint64_t t1)
+{
+    stq_raw(t1, t0);
+}
+
+uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1)
+{
+    uint64_t ret;
+
+    if (t1 == env->lock) {
+        stl_raw(t1, t0);
+        ret = 0;
+    } else
+        ret = 1;
+
+    env->lock = 1;
+
+    return ret;
+}
+
+uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1)
+{
+    uint64_t ret;
+
+    if (t1 == env->lock) {
+        stq_raw(t1, t0);
+        ret = 0;
+    } else
+        ret = 1;
+
+    env->lock = 1;
+
+    return ret;
 }
 
 #define MMUSUFFIX _mmu
diff -Nur kvm-76/qemu/target-alpha/translate.c kvm-userspace/qemu/target-alpha/translate.c
--- kvm-76/qemu/target-alpha/translate.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-alpha/translate.c	2008-10-12 09:38:24.000000000 +0200
@@ -31,7 +31,6 @@
 #include "qemu-common.h"
 
 #define DO_SINGLE_STEP
-#define GENERATE_NOP
 #define ALPHA_DEBUG_DISAS
 #define DO_TB_FLUSH
 
@@ -48,13 +47,12 @@
 /* global register indexes */
 static TCGv cpu_env;
 static TCGv cpu_ir[31];
+static TCGv cpu_fir[31];
 static TCGv cpu_pc;
-
-/* dyngen register indexes */
-static TCGv cpu_T[2];
+static TCGv cpu_lock;
 
 /* register names */
-static char cpu_reg_names[10*4+21*5];
+static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
 
 #include "gen-icount.h"
 
@@ -69,27 +67,25 @@
 
     cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
 
-#if TARGET_LONG_BITS > HOST_LONG_BITS
-    cpu_T[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
-                                  offsetof(CPUState, t0), "T0");
-    cpu_T[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
-                                  offsetof(CPUState, t1), "T1");
-#else
-    cpu_T[0] = tcg_global_reg_new(TCG_TYPE_I64, TCG_AREG1, "T0");
-    cpu_T[1] = tcg_global_reg_new(TCG_TYPE_I64, TCG_AREG2, "T1");
-#endif
-
     p = cpu_reg_names;
     for (i = 0; i < 31; i++) {
         sprintf(p, "ir%d", i);
         cpu_ir[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                        offsetof(CPUState, ir[i]), p);
         p += (i < 10) ? 4 : 5;
+
+        sprintf(p, "fir%d", i);
+        cpu_fir[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
+                                        offsetof(CPUState, fir[i]), p);
+        p += (i < 10) ? 5 : 6;
     }
 
     cpu_pc = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
                                 offsetof(CPUState, pc), "pc");
 
+    cpu_lock = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
+                                  offsetof(CPUState, lock), "lock");
+
     /* register helpers */
 #undef DEF_HELPER
 #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
@@ -98,225 +94,169 @@
     done_init = 1;
 }
 
-static always_inline void gen_op_nop (void)
+static always_inline void gen_excp (DisasContext *ctx,
+                                    int exception, int error_code)
 {
-#if defined(GENERATE_NOP)
-    gen_op_no_op();
-#endif
-}
+    TCGv tmp1, tmp2;
 
-#define GEN32(func, NAME) \
-static GenOpFunc *NAME ## _table [32] = {                                     \
-NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3,                                   \
-NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7,                                   \
-NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11,                                 \
-NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15,                               \
-NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19,                               \
-NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23,                               \
-NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27,                               \
-NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31,                               \
-};                                                                            \
-static always_inline void func (int n)                                        \
-{                                                                             \
-    NAME ## _table[n]();                                                      \
-}
-
-/* FIR moves */
-/* Special hacks for fir31 */
-#define gen_op_load_FT0_fir31 gen_op_reset_FT0
-#define gen_op_load_FT1_fir31 gen_op_reset_FT1
-#define gen_op_load_FT2_fir31 gen_op_reset_FT2
-#define gen_op_store_FT0_fir31 gen_op_nop
-#define gen_op_store_FT1_fir31 gen_op_nop
-#define gen_op_store_FT2_fir31 gen_op_nop
-#define gen_op_cmov_fir31 gen_op_nop
-GEN32(gen_op_load_FT0_fir, gen_op_load_FT0_fir);
-GEN32(gen_op_load_FT1_fir, gen_op_load_FT1_fir);
-GEN32(gen_op_load_FT2_fir, gen_op_load_FT2_fir);
-GEN32(gen_op_store_FT0_fir, gen_op_store_FT0_fir);
-GEN32(gen_op_store_FT1_fir, gen_op_store_FT1_fir);
-GEN32(gen_op_store_FT2_fir, gen_op_store_FT2_fir);
-GEN32(gen_op_cmov_fir, gen_op_cmov_fir);
-
-static always_inline void gen_load_fir (DisasContext *ctx, int firn, int Tn)
-{
-    switch (Tn) {
-    case 0:
-        gen_op_load_FT0_fir(firn);
-        break;
-    case 1:
-        gen_op_load_FT1_fir(firn);
-        break;
-    case 2:
-        gen_op_load_FT2_fir(firn);
-        break;
-    }
+    tcg_gen_movi_i64(cpu_pc, ctx->pc);
+    tmp1 = tcg_const_i32(exception);
+    tmp2 = tcg_const_i32(error_code);
+    tcg_gen_helper_0_2(helper_excp, tmp1, tmp2);
+    tcg_temp_free(tmp2);
+    tcg_temp_free(tmp1);
 }
 
-static always_inline void gen_store_fir (DisasContext *ctx, int firn, int Tn)
+static always_inline void gen_invalid (DisasContext *ctx)
 {
-    switch (Tn) {
-    case 0:
-        gen_op_store_FT0_fir(firn);
-        break;
-    case 1:
-        gen_op_store_FT1_fir(firn);
-        break;
-    case 2:
-        gen_op_store_FT2_fir(firn);
-        break;
-    }
+    gen_excp(ctx, EXCP_OPCDEC, 0);
 }
 
-/* Memory moves */
-#if defined(CONFIG_USER_ONLY)
-#define OP_LD_TABLE(width)                                                    \
-static GenOpFunc *gen_op_ld##width[] = {                                      \
-    &gen_op_ld##width##_raw,                                                  \
-}
-#define OP_ST_TABLE(width)                                                    \
-static GenOpFunc *gen_op_st##width[] = {                                      \
-    &gen_op_st##width##_raw,                                                  \
-}
-#else
-#define OP_LD_TABLE(width)                                                    \
-static GenOpFunc *gen_op_ld##width[] = {                                      \
-    &gen_op_ld##width##_kernel,                                               \
-    &gen_op_ld##width##_executive,                                            \
-    &gen_op_ld##width##_supervisor,                                           \
-    &gen_op_ld##width##_user,                                                 \
-}
-#define OP_ST_TABLE(width)                                                    \
-static GenOpFunc *gen_op_st##width[] = {                                      \
-    &gen_op_st##width##_kernel,                                               \
-    &gen_op_st##width##_executive,                                            \
-    &gen_op_st##width##_supervisor,                                           \
-    &gen_op_st##width##_user,                                                 \
+static always_inline void gen_qemu_ldf (TCGv t0, TCGv t1, int flags)
+{
+    TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
+    tcg_gen_qemu_ld32u(tmp, t1, flags);
+    tcg_gen_helper_1_1(helper_memory_to_f, t0, tmp);
+    tcg_temp_free(tmp);
 }
-#endif
 
-#define GEN_LD(width)                                                         \
-OP_LD_TABLE(width);                                                           \
-static always_inline void gen_ld##width (DisasContext *ctx)                   \
-{                                                                             \
-    (*gen_op_ld##width[ctx->mem_idx])();                                      \
-}
-
-#define GEN_ST(width)                                                         \
-OP_ST_TABLE(width);                                                           \
-static always_inline void gen_st##width (DisasContext *ctx)                   \
-{                                                                             \
-    (*gen_op_st##width[ctx->mem_idx])();                                      \
-}
-
-GEN_LD(l);
-GEN_ST(l);
-GEN_LD(q);
-GEN_ST(q);
-GEN_LD(l_l);
-GEN_ST(l_c);
-GEN_LD(q_l);
-GEN_ST(q_c);
-
-#if 0 /* currently unused */
-GEN_LD(f);
-GEN_ST(f);
-GEN_LD(g);
-GEN_ST(g);
-#endif /* 0 */
-GEN_LD(s);
-GEN_ST(s);
-GEN_LD(t);
-GEN_ST(t);
-
-static always_inline void _gen_op_bcond (DisasContext *ctx)
+static always_inline void gen_qemu_ldg (TCGv t0, TCGv t1, int flags)
 {
-#if 0 // Qemu does not know how to do this...
-    gen_op_bcond(ctx->pc);
-#else
-    gen_op_bcond(ctx->pc >> 32, ctx->pc);
-#endif
+    TCGv tmp = tcg_temp_new(TCG_TYPE_I64);
+    tcg_gen_qemu_ld64(tmp, t1, flags);
+    tcg_gen_helper_1_1(helper_memory_to_g, t0, tmp);
+    tcg_temp_free(tmp);
 }
 
-static always_inline void gen_excp (DisasContext *ctx,
-                                    int exception, int error_code)
+static always_inline void gen_qemu_lds (TCGv t0, TCGv t1, int flags)
 {
-    TCGv tmp1, tmp2;
+    TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
+    tcg_gen_qemu_ld32u(tmp, t1, flags);
+    tcg_gen_helper_1_1(helper_memory_to_s, t0, tmp);
+    tcg_temp_free(tmp);
+}
 
-    tcg_gen_movi_i64(cpu_pc, ctx->pc);
-    tmp1 = tcg_const_i32(exception);
-    tmp2 = tcg_const_i32(error_code);
-    tcg_gen_helper_0_2(helper_excp, tmp1, tmp2);
-    tcg_temp_free(tmp2);
-    tcg_temp_free(tmp1);
+static always_inline void gen_qemu_ldl_l (TCGv t0, TCGv t1, int flags)
+{
+    tcg_gen_mov_i64(cpu_lock, t1);
+    tcg_gen_qemu_ld32s(t0, t1, flags);
 }
 
-static always_inline void gen_invalid (DisasContext *ctx)
+static always_inline void gen_qemu_ldq_l (TCGv t0, TCGv t1, int flags)
 {
-    gen_excp(ctx, EXCP_OPCDEC, 0);
+    tcg_gen_mov_i64(cpu_lock, t1);
+    tcg_gen_qemu_ld64(t0, t1, flags);
 }
 
 static always_inline void gen_load_mem (DisasContext *ctx,
-                                        void (*gen_load_op)(DisasContext *ctx),
+                                        void (*tcg_gen_qemu_load)(TCGv t0, TCGv t1, int flags),
                                         int ra, int rb, int32_t disp16,
-                                        int clear)
+                                        int fp, int clear)
 {
-    if (ra == 31 && disp16 == 0) {
-        /* UNOP */
-        gen_op_nop();
+    TCGv addr;
+
+    if (unlikely(ra == 31))
+        return;
+
+    addr = tcg_temp_new(TCG_TYPE_I64);
+    if (rb != 31) {
+        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
+        if (clear)
+            tcg_gen_andi_i64(addr, addr, ~0x7);
     } else {
-        if (rb != 31)
-            tcg_gen_addi_i64(cpu_T[0], cpu_ir[rb], disp16);
-        else
-            tcg_gen_movi_i64(cpu_T[0], disp16);
         if (clear)
-            tcg_gen_andi_i64(cpu_T[0], cpu_T[0], ~0x7);
-        (*gen_load_op)(ctx);
-        if (ra != 31)
-            tcg_gen_mov_i64(cpu_ir[ra], cpu_T[1]);
+            disp16 &= ~0x7;
+        tcg_gen_movi_i64(addr, disp16);
     }
+    if (fp)
+        tcg_gen_qemu_load(cpu_fir[ra], addr, ctx->mem_idx);
+    else
+        tcg_gen_qemu_load(cpu_ir[ra], addr, ctx->mem_idx);
+    tcg_temp_free(addr);
 }
 
-static always_inline void gen_store_mem (DisasContext *ctx,
-                                         void (*gen_store_op)(DisasContext *ctx),
-                                         int ra, int rb, int32_t disp16,
-                                         int clear)
+static always_inline void gen_qemu_stf (TCGv t0, TCGv t1, int flags)
 {
-    if (rb != 31)
-        tcg_gen_addi_i64(cpu_T[0], cpu_ir[rb], disp16);
-    else
-        tcg_gen_movi_i64(cpu_T[0], disp16);
-    if (clear)
-        tcg_gen_andi_i64(cpu_T[0], cpu_T[0], ~0x7);
-    if (ra != 31)
-        tcg_gen_mov_i64(cpu_T[1], cpu_ir[ra]);
-    else
-        tcg_gen_movi_i64(cpu_T[1], 0);
-    (*gen_store_op)(ctx);
+    TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
+    tcg_gen_helper_1_1(helper_f_to_memory, tmp, t0);
+    tcg_gen_qemu_st32(tmp, t1, flags);
+    tcg_temp_free(tmp);
 }
 
-static always_inline void gen_load_fmem (DisasContext *ctx,
-                                         void (*gen_load_fop)(DisasContext *ctx),
-                                         int ra, int rb, int32_t disp16)
+static always_inline void gen_qemu_stg (TCGv t0, TCGv t1, int flags)
 {
-    if (rb != 31)
-        tcg_gen_addi_i64(cpu_T[0], cpu_ir[rb], disp16);
-    else
-        tcg_gen_movi_i64(cpu_T[0], disp16);
-    (*gen_load_fop)(ctx);
-    gen_store_fir(ctx, ra, 1);
+    TCGv tmp = tcg_temp_new(TCG_TYPE_I64);
+    tcg_gen_helper_1_1(helper_g_to_memory, tmp, t0);
+    tcg_gen_qemu_st64(tmp, t1, flags);
+    tcg_temp_free(tmp);
 }
 
-static always_inline void gen_store_fmem (DisasContext *ctx,
-                                          void (*gen_store_fop)(DisasContext *ctx),
-                                          int ra, int rb, int32_t disp16)
+static always_inline void gen_qemu_sts (TCGv t0, TCGv t1, int flags)
 {
-    if (rb != 31)
-        tcg_gen_addi_i64(cpu_T[0], cpu_ir[rb], disp16);
-    else
-        tcg_gen_movi_i64(cpu_T[0], disp16);
-    gen_load_fir(ctx, ra, 1);
-    (*gen_store_fop)(ctx);
+    TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
+    tcg_gen_helper_1_1(helper_s_to_memory, tmp, t0);
+    tcg_gen_qemu_st32(tmp, t1, flags);
+    tcg_temp_free(tmp);
+}
+
+static always_inline void gen_qemu_stl_c (TCGv t0, TCGv t1, int flags)
+{
+    int l1, l2;
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+    tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
+    tcg_gen_qemu_st32(t0, t1, flags);
+    tcg_gen_movi_i64(t0, 0);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_movi_i64(t0, 1);
+    gen_set_label(l2);
+    tcg_gen_movi_i64(cpu_lock, -1);
+}
+
+static always_inline void gen_qemu_stq_c (TCGv t0, TCGv t1, int flags)
+{
+    int l1, l2;
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+    tcg_gen_brcond_i64(TCG_COND_NE, cpu_lock, t1, l1);
+    tcg_gen_qemu_st64(t0, t1, flags);
+    tcg_gen_movi_i64(t0, 0);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_movi_i64(t0, 1);
+    gen_set_label(l2);
+    tcg_gen_movi_i64(cpu_lock, -1);
+}
+
+static always_inline void gen_store_mem (DisasContext *ctx,
+                                         void (*tcg_gen_qemu_store)(TCGv t0, TCGv t1, int flags),
+                                         int ra, int rb, int32_t disp16,
+                                         int fp, int clear)
+{
+    TCGv addr = tcg_temp_new(TCG_TYPE_I64);
+    if (rb != 31) {
+        tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
+        if (clear)
+            tcg_gen_andi_i64(addr, addr, ~0x7);
+    } else {
+        if (clear)
+            disp16 &= ~0x7;
+        tcg_gen_movi_i64(addr, disp16);
+    }
+    if (ra != 31) {
+        if (fp)
+            tcg_gen_qemu_store(cpu_fir[ra], addr, ctx->mem_idx);
+        else
+            tcg_gen_qemu_store(cpu_ir[ra], addr, ctx->mem_idx);
+    } else {
+        TCGv zero = tcg_const_i64(0);
+        tcg_gen_qemu_store(zero, addr, ctx->mem_idx);
+        tcg_temp_free(zero);
+    }
+    tcg_temp_free(addr);
 }
 
 static always_inline void gen_bcond (DisasContext *ctx,
@@ -349,17 +289,30 @@
 }
 
 static always_inline void gen_fbcond (DisasContext *ctx,
-                                      void (*gen_test_op)(void),
+                                      void* func,
                                       int ra, int32_t disp16)
 {
-    tcg_gen_movi_i64(cpu_T[1], ctx->pc + (int64_t)(disp16 << 2));
-    gen_load_fir(ctx, ra, 0);
-    (*gen_test_op)();
-    _gen_op_bcond(ctx);
+    int l1, l2;
+    TCGv tmp;
+
+    l1 = gen_new_label();
+    l2 = gen_new_label();
+    if (ra != 31) {
+        tmp = tcg_temp_new(TCG_TYPE_I64);
+        tcg_gen_helper_1_1(func, tmp, cpu_fir[ra]);
+    } else  {
+        tmp = tcg_const_i64(0);
+        tcg_gen_helper_1_1(func, tmp, tmp);
+    }
+    tcg_gen_brcondi_i64(TCG_COND_NE, tmp, 0, l1);
+    tcg_gen_movi_i64(cpu_pc, ctx->pc);
+    tcg_gen_br(l2);
+    gen_set_label(l1);
+    tcg_gen_movi_i64(cpu_pc, ctx->pc + (int64_t)(disp16 << 2));
+    gen_set_label(l2);
 }
 
-static always_inline void gen_cmov (DisasContext *ctx,
-                                    TCGCond inv_cond,
+static always_inline void gen_cmov (TCGCond inv_cond,
                                     int ra, int rb, int rc,
                                     int islit, uint8_t lit, int mask)
 {
@@ -392,55 +345,69 @@
     gen_set_label(l1);
 }
 
-static always_inline void gen_farith2 (DisasContext *ctx,
-                                       void (*gen_arith_fop)(void),
+static always_inline void gen_farith2 (void *helper,
                                        int rb, int rc)
 {
-    gen_load_fir(ctx, rb, 0);
-    (*gen_arith_fop)();
-    gen_store_fir(ctx, rc, 0);
+    if (unlikely(rc == 31))
+      return;
+
+    if (rb != 31)
+        tcg_gen_helper_1_1(helper, cpu_fir[rc], cpu_fir[rb]);
+    else {
+        TCGv tmp = tcg_const_i64(0);
+        tcg_gen_helper_1_1(helper, cpu_fir[rc], tmp);
+        tcg_temp_free(tmp);
+    }
 }
 
-static always_inline void gen_farith3 (DisasContext *ctx,
-                                       void (*gen_arith_fop)(void),
+static always_inline void gen_farith3 (void *helper,
                                        int ra, int rb, int rc)
 {
-    gen_load_fir(ctx, ra, 0);
-    gen_load_fir(ctx, rb, 1);
-    (*gen_arith_fop)();
-    gen_store_fir(ctx, rc, 0);
+    if (unlikely(rc == 31))
+        return;
+
+    if (ra != 31) {
+        if (rb != 31)
+            tcg_gen_helper_1_2(helper, cpu_fir[rc], cpu_fir[ra], cpu_fir[rb]);
+        else {
+            TCGv tmp = tcg_const_i64(0);
+            tcg_gen_helper_1_2(helper, cpu_fir[rc], cpu_fir[ra], tmp);
+            tcg_temp_free(tmp);
+        }
+    } else {
+        TCGv tmp = tcg_const_i64(0);
+        if (rb != 31)
+            tcg_gen_helper_1_2(helper, cpu_fir[rc], tmp, cpu_fir[rb]);
+        else
+            tcg_gen_helper_1_2(helper, cpu_fir[rc], tmp, tmp);
+        tcg_temp_free(tmp);
+    }
 }
 
-static always_inline void gen_fcmov (DisasContext *ctx,
-                                     void (*gen_test_fop)(void),
+static always_inline void gen_fcmov (void *func,
                                      int ra, int rb, int rc)
 {
-    gen_load_fir(ctx, ra, 0);
-    gen_load_fir(ctx, rb, 1);
-    (*gen_test_fop)();
-    gen_op_cmov_fir(rc);
-}
+    int l1;
+    TCGv tmp;
 
-static always_inline void gen_fti (DisasContext *ctx,
-                                   void (*gen_move_fop)(void),
-                                   int ra, int rc)
-{
-    gen_load_fir(ctx, rc, 0);
-    (*gen_move_fop)();
-    if (ra != 31)
-        tcg_gen_mov_i64(cpu_ir[ra], cpu_T[0]);
-}
+    if (unlikely(rc == 31))
+        return;
 
-static always_inline void gen_itf (DisasContext *ctx,
-                                   void (*gen_move_fop)(void),
-                                   int ra, int rc)
-{
-    if (ra != 31)
-        tcg_gen_mov_i64(cpu_T[0], cpu_ir[ra]);
+    l1 = gen_new_label();
+    tmp = tcg_temp_new(TCG_TYPE_I64);
+    if (ra != 31) {
+        tmp = tcg_temp_new(TCG_TYPE_I64);
+        tcg_gen_helper_1_1(func, tmp, cpu_fir[ra]);
+    } else  {
+        tmp = tcg_const_i64(0);
+        tcg_gen_helper_1_1(func, tmp, tmp);
+    }
+    tcg_gen_brcondi_i64(TCG_COND_EQ, tmp, 0, l1);
+    if (rb != 31)
+        tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
     else
-        tcg_gen_movi_i64(cpu_T[0], 0);
-    (*gen_move_fop)();
-    gen_store_fir(ctx, rc, 0);
+        tcg_gen_movi_i64(cpu_fir[rc], 0);
+    gen_set_label(l1);
 }
 
 /* EXTWH, EXTWH, EXTLH, EXTQH */
@@ -457,7 +424,7 @@
                 tcg_gen_shli_i64(cpu_ir[rc], cpu_ir[ra], 64 - ((lit & 7) * 8));
             else
                 tcg_gen_mov_i64(cpu_ir[rc], cpu_ir[ra]);
-	} else {
+        } else {
             TCGv tmp1, tmp2;
             tmp1 = tcg_temp_new(TCG_TYPE_I64);
             tcg_gen_andi_i64(tmp1, cpu_ir[rb], 7);
@@ -491,7 +458,7 @@
             tcg_gen_shli_i64(tmp, tmp, 3);
             tcg_gen_shr_i64(cpu_ir[rc], cpu_ir[ra], tmp);
             tcg_temp_free(tmp);
-	}
+        }
         if (tcg_gen_ext_i64)
             tcg_gen_ext_i64(cpu_ir[rc], cpu_ir[rc]);
     } else
@@ -499,9 +466,9 @@
 }
 
 /* Code to call arith3 helpers */
-static always_inline void gen_arith3_helper(void *helper,
-                                            int ra, int rb, int rc,
-                                            int islit, uint8_t lit)
+static always_inline void gen_arith3 (void *helper,
+                                      int ra, int rb, int rc,
+                                      int islit, uint8_t lit)
 {
     if (unlikely(rc == 31))
         return;
@@ -655,103 +622,29 @@
         /* LDBU */
         if (!(ctx->amask & AMASK_BWX))
             goto invalid_opc;
-        if (likely(ra != 31)) {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            tcg_gen_qemu_ld8u(cpu_ir[ra], addr, ctx->mem_idx);
-            tcg_temp_free(addr);
-        }
+        gen_load_mem(ctx, &tcg_gen_qemu_ld8u, ra, rb, disp16, 0, 0);
         break;
     case 0x0B:
         /* LDQ_U */
-        if (likely(ra != 31)) {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31) {
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-                tcg_gen_andi_i64(addr, addr, ~0x7);
-            } else
-                tcg_gen_movi_i64(addr, disp16 & ~0x7);
-            tcg_gen_qemu_ld64(cpu_ir[ra], addr, ctx->mem_idx);
-            tcg_temp_free(addr);
-        }
+        gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 1);
         break;
     case 0x0C:
         /* LDWU */
         if (!(ctx->amask & AMASK_BWX))
             goto invalid_opc;
-        if (likely(ra != 31)) {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            tcg_gen_qemu_ld16u(cpu_ir[ra], addr, ctx->mem_idx);
-            tcg_temp_free(addr);
-        }
+        gen_load_mem(ctx, &tcg_gen_qemu_ld16u, ra, rb, disp16, 0, 1);
         break;
     case 0x0D:
         /* STW */
-        {
-            TCGv addr;
-            if (!(ctx->amask & AMASK_BWX))
-                goto invalid_opc;
-            addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            if (ra != 31)
-                tcg_gen_qemu_st16(cpu_ir[ra], addr, ctx->mem_idx);
-            else {
-                TCGv zero = tcg_const_i64(0);
-                tcg_gen_qemu_st16(zero, addr, ctx->mem_idx);
-                tcg_temp_free(zero);
-            }
-            tcg_temp_free(addr);
-        }
+        gen_store_mem(ctx, &tcg_gen_qemu_st16, ra, rb, disp16, 0, 0);
         break;
     case 0x0E:
         /* STB */
-        {
-            TCGv addr;
-            if (!(ctx->amask & AMASK_BWX))
-                goto invalid_opc;
-            addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            if (ra != 31)
-                tcg_gen_qemu_st8(cpu_ir[ra], addr, ctx->mem_idx);
-            else {
-                TCGv zero = tcg_const_i64(0);
-                tcg_gen_qemu_st8(zero, addr, ctx->mem_idx);
-                tcg_temp_free(zero);
-            }
-            tcg_temp_free(addr);
-        }
+        gen_store_mem(ctx, &tcg_gen_qemu_st8, ra, rb, disp16, 0, 0);
         break;
     case 0x0F:
         /* STQ_U */
-        {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31) {
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-                tcg_gen_andi_i64(addr, addr, ~0x7);
-            } else
-                tcg_gen_movi_i64(addr, disp16 & ~0x7);
-            if (ra != 31)
-                tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
-            else {
-                TCGv zero = tcg_const_i64(0);
-                tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
-                tcg_temp_free(zero);
-            }
-            tcg_temp_free(addr);
-        }
+        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 1);
         break;
     case 0x10:
         switch (fn7) {
@@ -836,7 +729,7 @@
             break;
         case 0x0F:
             /* CMPBGE */
-            gen_arith3_helper(helper_cmpbge, ra, rb, rc, islit, lit);
+            gen_arith3(helper_cmpbge, ra, rb, rc, islit, lit);
             break;
         case 0x12:
             /* S8ADDL */
@@ -1002,11 +895,11 @@
             break;
         case 0x40:
             /* ADDL/V */
-            gen_arith3_helper(helper_addlv, ra, rb, rc, islit, lit);
+            gen_arith3(helper_addlv, ra, rb, rc, islit, lit);
             break;
         case 0x49:
             /* SUBL/V */
-            gen_arith3_helper(helper_sublv, ra, rb, rc, islit, lit);
+            gen_arith3(helper_sublv, ra, rb, rc, islit, lit);
             break;
         case 0x4D:
             /* CMPLT */
@@ -1014,11 +907,11 @@
             break;
         case 0x60:
             /* ADDQ/V */
-            gen_arith3_helper(helper_addqv, ra, rb, rc, islit, lit);
+            gen_arith3(helper_addqv, ra, rb, rc, islit, lit);
             break;
         case 0x69:
             /* SUBQ/V */
-            gen_arith3_helper(helper_subqv, ra, rb, rc, islit, lit);
+            gen_arith3(helper_subqv, ra, rb, rc, islit, lit);
             break;
         case 0x6D:
             /* CMPLE */
@@ -1059,11 +952,11 @@
             break;
         case 0x14:
             /* CMOVLBS */
-            gen_cmov(ctx, TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
+            gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 1);
             break;
         case 0x16:
             /* CMOVLBC */
-            gen_cmov(ctx, TCG_COND_NE, ra, rb, rc, islit, lit, 1);
+            gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 1);
             break;
         case 0x20:
             /* BIS */
@@ -1071,7 +964,7 @@
                 if (ra != 31) {
                     if (islit)
                         tcg_gen_ori_i64(cpu_ir[rc], cpu_ir[ra], lit);
-		    else
+                    else
                         tcg_gen_or_i64(cpu_ir[rc], cpu_ir[ra], cpu_ir[rb]);
                 } else {
                     if (islit)
@@ -1083,11 +976,11 @@
             break;
         case 0x24:
             /* CMOVEQ */
-            gen_cmov(ctx, TCG_COND_NE, ra, rb, rc, islit, lit, 0);
+            gen_cmov(TCG_COND_NE, ra, rb, rc, islit, lit, 0);
             break;
         case 0x26:
             /* CMOVNE */
-            gen_cmov(ctx, TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
+            gen_cmov(TCG_COND_EQ, ra, rb, rc, islit, lit, 0);
             break;
         case 0x28:
             /* ORNOT */
@@ -1127,11 +1020,11 @@
             break;
         case 0x44:
             /* CMOVLT */
-            gen_cmov(ctx, TCG_COND_GE, ra, rb, rc, islit, lit, 0);
+            gen_cmov(TCG_COND_GE, ra, rb, rc, islit, lit, 0);
             break;
         case 0x46:
             /* CMOVGE */
-            gen_cmov(ctx, TCG_COND_LT, ra, rb, rc, islit, lit, 0);
+            gen_cmov(TCG_COND_LT, ra, rb, rc, islit, lit, 0);
             break;
         case 0x48:
             /* EQV */
@@ -1164,11 +1057,11 @@
             break;
         case 0x64:
             /* CMOVLE */
-            gen_cmov(ctx, TCG_COND_GT, ra, rb, rc, islit, lit, 0);
+            gen_cmov(TCG_COND_GT, ra, rb, rc, islit, lit, 0);
             break;
         case 0x66:
             /* CMOVGT */
-            gen_cmov(ctx, TCG_COND_LE, ra, rb, rc, islit, lit, 0);
+            gen_cmov(TCG_COND_LE, ra, rb, rc, islit, lit, 0);
             break;
         case 0x6C:
             /* IMPLVER */
@@ -1183,7 +1076,7 @@
         switch (fn7) {
         case 0x02:
             /* MSKBL */
-            gen_arith3_helper(helper_mskbl, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mskbl, ra, rb, rc, islit, lit);
             break;
         case 0x06:
             /* EXTBL */
@@ -1191,11 +1084,11 @@
             break;
         case 0x0B:
             /* INSBL */
-            gen_arith3_helper(helper_insbl, ra, rb, rc, islit, lit);
+            gen_arith3(helper_insbl, ra, rb, rc, islit, lit);
             break;
         case 0x12:
             /* MSKWL */
-            gen_arith3_helper(helper_mskwl, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mskwl, ra, rb, rc, islit, lit);
             break;
         case 0x16:
             /* EXTWL */
@@ -1203,11 +1096,11 @@
             break;
         case 0x1B:
             /* INSWL */
-            gen_arith3_helper(helper_inswl, ra, rb, rc, islit, lit);
+            gen_arith3(helper_inswl, ra, rb, rc, islit, lit);
             break;
         case 0x22:
             /* MSKLL */
-            gen_arith3_helper(helper_mskll, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mskll, ra, rb, rc, islit, lit);
             break;
         case 0x26:
             /* EXTLL */
@@ -1215,19 +1108,19 @@
             break;
         case 0x2B:
             /* INSLL */
-            gen_arith3_helper(helper_insll, ra, rb, rc, islit, lit);
+            gen_arith3(helper_insll, ra, rb, rc, islit, lit);
             break;
         case 0x30:
             /* ZAP */
-            gen_arith3_helper(helper_zap, ra, rb, rc, islit, lit);
+            gen_arith3(helper_zap, ra, rb, rc, islit, lit);
             break;
         case 0x31:
             /* ZAPNOT */
-            gen_arith3_helper(helper_zapnot, ra, rb, rc, islit, lit);
+            gen_arith3(helper_zapnot, ra, rb, rc, islit, lit);
             break;
         case 0x32:
             /* MSKQL */
-            gen_arith3_helper(helper_mskql, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mskql, ra, rb, rc, islit, lit);
             break;
         case 0x34:
             /* SRL */
@@ -1267,7 +1160,7 @@
             break;
         case 0x3B:
             /* INSQL */
-            gen_arith3_helper(helper_insql, ra, rb, rc, islit, lit);
+            gen_arith3(helper_insql, ra, rb, rc, islit, lit);
             break;
         case 0x3C:
             /* SRA */
@@ -1287,11 +1180,11 @@
             break;
         case 0x52:
             /* MSKWH */
-            gen_arith3_helper(helper_mskwh, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mskwh, ra, rb, rc, islit, lit);
             break;
         case 0x57:
             /* INSWH */
-            gen_arith3_helper(helper_inswh, ra, rb, rc, islit, lit);
+            gen_arith3(helper_inswh, ra, rb, rc, islit, lit);
             break;
         case 0x5A:
             /* EXTWH */
@@ -1299,11 +1192,11 @@
             break;
         case 0x62:
             /* MSKLH */
-            gen_arith3_helper(helper_msklh, ra, rb, rc, islit, lit);
+            gen_arith3(helper_msklh, ra, rb, rc, islit, lit);
             break;
         case 0x67:
             /* INSLH */
-            gen_arith3_helper(helper_inslh, ra, rb, rc, islit, lit);
+            gen_arith3(helper_inslh, ra, rb, rc, islit, lit);
             break;
         case 0x6A:
             /* EXTLH */
@@ -1311,11 +1204,11 @@
             break;
         case 0x72:
             /* MSKQH */
-            gen_arith3_helper(helper_mskqh, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mskqh, ra, rb, rc, islit, lit);
             break;
         case 0x77:
             /* INSQH */
-            gen_arith3_helper(helper_insqh, ra, rb, rc, islit, lit);
+            gen_arith3(helper_insqh, ra, rb, rc, islit, lit);
             break;
         case 0x7A:
             /* EXTQH */
@@ -1354,15 +1247,15 @@
             break;
         case 0x30:
             /* UMULH */
-            gen_arith3_helper(helper_umulh, ra, rb, rc, islit, lit);
+            gen_arith3(helper_umulh, ra, rb, rc, islit, lit);
             break;
         case 0x40:
             /* MULL/V */
-            gen_arith3_helper(helper_mullv, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mullv, ra, rb, rc, islit, lit);
             break;
         case 0x60:
             /* MULQ/V */
-            gen_arith3_helper(helper_mulqv, ra, rb, rc, islit, lit);
+            gen_arith3(helper_mulqv, ra, rb, rc, islit, lit);
             break;
         default:
             goto invalid_opc;
@@ -1374,47 +1267,64 @@
             /* ITOFS */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_itf(ctx, &gen_op_itofs, ra, rc);
+            if (likely(rc != 31)) {
+                if (ra != 31) {
+                    TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
+                    tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
+                    tcg_gen_helper_1_1(helper_memory_to_s, cpu_fir[rc], tmp);
+                    tcg_temp_free(tmp);
+                } else
+                    tcg_gen_movi_i64(cpu_fir[rc], 0);
+            }
             break;
         case 0x0A:
             /* SQRTF */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_farith2(ctx, &gen_op_sqrtf, rb, rc);
+            gen_farith2(&helper_sqrtf, rb, rc);
             break;
         case 0x0B:
             /* SQRTS */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_farith2(ctx, &gen_op_sqrts, rb, rc);
+            gen_farith2(&helper_sqrts, rb, rc);
             break;
         case 0x14:
             /* ITOFF */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-#if 0 // TODO
-            gen_itf(ctx, &gen_op_itoff, ra, rc);
-#else
-            goto invalid_opc;
-#endif
+            if (likely(rc != 31)) {
+                if (ra != 31) {
+                    TCGv tmp = tcg_temp_new(TCG_TYPE_I32);
+                    tcg_gen_trunc_i64_i32(tmp, cpu_ir[ra]);
+                    tcg_gen_helper_1_1(helper_memory_to_f, cpu_fir[rc], tmp);
+                    tcg_temp_free(tmp);
+                } else
+                    tcg_gen_movi_i64(cpu_fir[rc], 0);
+            }
             break;
         case 0x24:
             /* ITOFT */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_itf(ctx, &gen_op_itoft, ra, rc);
+            if (likely(rc != 31)) {
+                if (ra != 31)
+                    tcg_gen_mov_i64(cpu_fir[rc], cpu_ir[ra]);
+                else
+                    tcg_gen_movi_i64(cpu_fir[rc], 0);
+            }
             break;
         case 0x2A:
             /* SQRTG */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_farith2(ctx, &gen_op_sqrtg, rb, rc);
+            gen_farith2(&helper_sqrtg, rb, rc);
             break;
         case 0x02B:
             /* SQRTT */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_farith2(ctx, &gen_op_sqrtt, rb, rc);
+            gen_farith2(&helper_sqrtt, rb, rc);
             break;
         default:
             goto invalid_opc;
@@ -1426,79 +1336,79 @@
         switch (fpfn) { /* f11 & 0x3F */
         case 0x00:
             /* ADDF */
-            gen_farith3(ctx, &gen_op_addf, ra, rb, rc);
+            gen_farith3(&helper_addf, ra, rb, rc);
             break;
         case 0x01:
             /* SUBF */
-            gen_farith3(ctx, &gen_op_subf, ra, rb, rc);
+            gen_farith3(&helper_subf, ra, rb, rc);
             break;
         case 0x02:
             /* MULF */
-            gen_farith3(ctx, &gen_op_mulf, ra, rb, rc);
+            gen_farith3(&helper_mulf, ra, rb, rc);
             break;
         case 0x03:
             /* DIVF */
-            gen_farith3(ctx, &gen_op_divf, ra, rb, rc);
+            gen_farith3(&helper_divf, ra, rb, rc);
             break;
         case 0x1E:
             /* CVTDG */
 #if 0 // TODO
-            gen_farith2(ctx, &gen_op_cvtdg, rb, rc);
+            gen_farith2(&helper_cvtdg, rb, rc);
 #else
             goto invalid_opc;
 #endif
             break;
         case 0x20:
             /* ADDG */
-            gen_farith3(ctx, &gen_op_addg, ra, rb, rc);
+            gen_farith3(&helper_addg, ra, rb, rc);
             break;
         case 0x21:
             /* SUBG */
-            gen_farith3(ctx, &gen_op_subg, ra, rb, rc);
+            gen_farith3(&helper_subg, ra, rb, rc);
             break;
         case 0x22:
             /* MULG */
-            gen_farith3(ctx, &gen_op_mulg, ra, rb, rc);
+            gen_farith3(&helper_mulg, ra, rb, rc);
             break;
         case 0x23:
             /* DIVG */
-            gen_farith3(ctx, &gen_op_divg, ra, rb, rc);
+            gen_farith3(&helper_divg, ra, rb, rc);
             break;
         case 0x25:
             /* CMPGEQ */
-            gen_farith3(ctx, &gen_op_cmpgeq, ra, rb, rc);
+            gen_farith3(&helper_cmpgeq, ra, rb, rc);
             break;
         case 0x26:
             /* CMPGLT */
-            gen_farith3(ctx, &gen_op_cmpglt, ra, rb, rc);
+            gen_farith3(&helper_cmpglt, ra, rb, rc);
             break;
         case 0x27:
             /* CMPGLE */
-            gen_farith3(ctx, &gen_op_cmpgle, ra, rb, rc);
+            gen_farith3(&helper_cmpgle, ra, rb, rc);
             break;
         case 0x2C:
             /* CVTGF */
-            gen_farith2(ctx, &gen_op_cvtgf, rb, rc);
+            gen_farith2(&helper_cvtgf, rb, rc);
             break;
         case 0x2D:
             /* CVTGD */
 #if 0 // TODO
-            gen_farith2(ctx, &gen_op_cvtgd, rb, rc);
+            gen_farith2(ctx, &helper_cvtgd, rb, rc);
 #else
             goto invalid_opc;
 #endif
             break;
         case 0x2F:
             /* CVTGQ */
-            gen_farith2(ctx, &gen_op_cvtgq, rb, rc);
+            gen_farith2(&helper_cvtgq, rb, rc);
             break;
         case 0x3C:
             /* CVTQF */
-            gen_farith2(ctx, &gen_op_cvtqf, rb, rc);
+            gen_farith2(&helper_cvtqf, rb, rc);
             break;
         case 0x3E:
             /* CVTQG */
-            gen_farith2(ctx, &gen_op_cvtqg, rb, rc);
+            gen_farith2(&helper_cvtqg, rb, rc);
             break;
         default:
             goto invalid_opc;
@@ -1510,73 +1420,73 @@
         switch (fpfn) { /* f11 & 0x3F */
         case 0x00:
             /* ADDS */
-            gen_farith3(ctx, &gen_op_adds, ra, rb, rc);
+            gen_farith3(&helper_adds, ra, rb, rc);
             break;
         case 0x01:
             /* SUBS */
-            gen_farith3(ctx, &gen_op_subs, ra, rb, rc);
+            gen_farith3(&helper_subs, ra, rb, rc);
             break;
         case 0x02:
             /* MULS */
-            gen_farith3(ctx, &gen_op_muls, ra, rb, rc);
+            gen_farith3(&helper_muls, ra, rb, rc);
             break;
         case 0x03:
             /* DIVS */
-            gen_farith3(ctx, &gen_op_divs, ra, rb, rc);
+            gen_farith3(&helper_divs, ra, rb, rc);
             break;
         case 0x20:
             /* ADDT */
-            gen_farith3(ctx, &gen_op_addt, ra, rb, rc);
+            gen_farith3(&helper_addt, ra, rb, rc);
             break;
         case 0x21:
             /* SUBT */
-            gen_farith3(ctx, &gen_op_subt, ra, rb, rc);
+            gen_farith3(&helper_subt, ra, rb, rc);
             break;
         case 0x22:
             /* MULT */
-            gen_farith3(ctx, &gen_op_mult, ra, rb, rc);
+            gen_farith3(&helper_mult, ra, rb, rc);
             break;
         case 0x23:
             /* DIVT */
-            gen_farith3(ctx, &gen_op_divt, ra, rb, rc);
+            gen_farith3(&helper_divt, ra, rb, rc);
             break;
         case 0x24:
             /* CMPTUN */
-            gen_farith3(ctx, &gen_op_cmptun, ra, rb, rc);
+            gen_farith3(&helper_cmptun, ra, rb, rc);
             break;
         case 0x25:
             /* CMPTEQ */
-            gen_farith3(ctx, &gen_op_cmpteq, ra, rb, rc);
+            gen_farith3(&helper_cmpteq, ra, rb, rc);
             break;
         case 0x26:
             /* CMPTLT */
-            gen_farith3(ctx, &gen_op_cmptlt, ra, rb, rc);
+            gen_farith3(&helper_cmptlt, ra, rb, rc);
             break;
         case 0x27:
             /* CMPTLE */
-            gen_farith3(ctx, &gen_op_cmptle, ra, rb, rc);
+            gen_farith3(&helper_cmptle, ra, rb, rc);
             break;
         case 0x2C:
             /* XXX: incorrect */
             if (fn11 == 0x2AC) {
                 /* CVTST */
-                gen_farith2(ctx, &gen_op_cvtst, rb, rc);
+                gen_farith2(&helper_cvtst, rb, rc);
             } else {
                 /* CVTTS */
-                gen_farith2(ctx, &gen_op_cvtts, rb, rc);
+                gen_farith2(&helper_cvtts, rb, rc);
             }
             break;
         case 0x2F:
             /* CVTTQ */
-            gen_farith2(ctx, &gen_op_cvttq, rb, rc);
+            gen_farith2(&helper_cvttq, rb, rc);
             break;
         case 0x3C:
             /* CVTQS */
-            gen_farith2(ctx, &gen_op_cvtqs, rb, rc);
+            gen_farith2(&helper_cvtqs, rb, rc);
             break;
         case 0x3E:
             /* CVTQT */
-            gen_farith2(ctx, &gen_op_cvtqt, rb, rc);
+            gen_farith2(&helper_cvtqt, rb, rc);
             break;
         default:
             goto invalid_opc;
@@ -1586,76 +1496,76 @@
         switch (fn11) {
         case 0x010:
             /* CVTLQ */
-            gen_farith2(ctx, &gen_op_cvtlq, rb, rc);
+            gen_farith2(&helper_cvtlq, rb, rc);
             break;
         case 0x020:
-            /* CPYS */
-            if (ra == rb) {
-                if (ra == 31 && rc == 31) {
-                    /* FNOP */
-                    gen_op_nop();
-                } else {
+            if (likely(rc != 31)) {
+                if (ra == rb)
                     /* FMOV */
-                    gen_load_fir(ctx, rb, 0);
-                    gen_store_fir(ctx, rc, 0);
-                }
-            } else {
-                gen_farith3(ctx, &gen_op_cpys, ra, rb, rc);
+                    tcg_gen_mov_i64(cpu_fir[rc], cpu_fir[ra]);
+                else
+                    /* CPYS */
+                    gen_farith3(&helper_cpys, ra, rb, rc);
             }
             break;
         case 0x021:
             /* CPYSN */
-            gen_farith2(ctx, &gen_op_cpysn, rb, rc);
+            gen_farith3(&helper_cpysn, ra, rb, rc);
             break;
         case 0x022:
             /* CPYSE */
-            gen_farith2(ctx, &gen_op_cpyse, rb, rc);
+            gen_farith3(&helper_cpyse, ra, rb, rc);
             break;
         case 0x024:
             /* MT_FPCR */
-            gen_load_fir(ctx, ra, 0);
-            gen_op_store_fpcr();
+            if (likely(ra != 31))
+                tcg_gen_helper_0_1(helper_store_fpcr, cpu_fir[ra]);
+            else {
+                TCGv tmp = tcg_const_i64(0);
+                tcg_gen_helper_0_1(helper_store_fpcr, tmp);
+                tcg_temp_free(tmp);
+            }
             break;
         case 0x025:
             /* MF_FPCR */
-            gen_op_load_fpcr();
-            gen_store_fir(ctx, ra, 0);
+            if (likely(ra != 31))
+                tcg_gen_helper_1_0(helper_load_fpcr, cpu_fir[ra]);
             break;
         case 0x02A:
             /* FCMOVEQ */
-            gen_fcmov(ctx, &gen_op_cmpfeq, ra, rb, rc);
+            gen_fcmov(&helper_cmpfeq, ra, rb, rc);
             break;
         case 0x02B:
             /* FCMOVNE */
-            gen_fcmov(ctx, &gen_op_cmpfne, ra, rb, rc);
+            gen_fcmov(&helper_cmpfne, ra, rb, rc);
             break;
         case 0x02C:
             /* FCMOVLT */
-            gen_fcmov(ctx, &gen_op_cmpflt, ra, rb, rc);
+            gen_fcmov(&helper_cmpflt, ra, rb, rc);
             break;
         case 0x02D:
             /* FCMOVGE */
-            gen_fcmov(ctx, &gen_op_cmpfge, ra, rb, rc);
+            gen_fcmov(&helper_cmpfge, ra, rb, rc);
             break;
         case 0x02E:
             /* FCMOVLE */
-            gen_fcmov(ctx, &gen_op_cmpfle, ra, rb, rc);
+            gen_fcmov(&helper_cmpfle, ra, rb, rc);
             break;
         case 0x02F:
             /* FCMOVGT */
-            gen_fcmov(ctx, &gen_op_cmpfgt, ra, rb, rc);
+            gen_fcmov(&helper_cmpfgt, ra, rb, rc);
             break;
         case 0x030:
             /* CVTQL */
-            gen_farith2(ctx, &gen_op_cvtql, rb, rc);
+            gen_farith2(&helper_cvtql, rb, rc);
             break;
         case 0x130:
             /* CVTQL/V */
-            gen_farith2(ctx, &gen_op_cvtqlv, rb, rc);
+            gen_farith2(&helper_cvtqlv, rb, rc);
             break;
         case 0x530:
             /* CVTQL/SV */
-            gen_farith2(ctx, &gen_op_cvtqlsv, rb, rc);
+            gen_farith2(&helper_cvtqlsv, rb, rc);
             break;
         default:
             goto invalid_opc;
@@ -1728,9 +1638,11 @@
 #else
         if (!ctx->pal_mode)
             goto invalid_opc;
-        gen_op_mfpr(insn & 0xFF);
-        if (ra != 31)
-            tcg_gen_mov_i64(cpu_ir[ra], cpu_T[0]);
+        if (ra != 31) {
+            TCGv tmp = tcg_const_i32(insn & 0xFF);
+            tcg_gen_helper_1_2(helper_mfpr, cpu_ir[ra], tmp, cpu_ir[ra]);
+            tcg_temp_free(tmp);
+        }
         break;
 #endif
     case 0x1A:
@@ -1764,94 +1676,94 @@
 #else
         if (!ctx->pal_mode)
             goto invalid_opc;
-        if (rb != 31)
-            tcg_gen_mov_i64(cpu_T[0], cpu_ir[rb]);
-        else
-            tcg_gen_movi_i64(cpu_T[0], 0);
-        tcg_gen_movi_i64(cpu_T[1], disp12);
-        tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
-        switch ((insn >> 12) & 0xF) {
-        case 0x0:
-            /* Longword physical access */
-            gen_op_ldl_raw();
-            break;
-        case 0x1:
-            /* Quadword physical access */
-            gen_op_ldq_raw();
-            break;
-        case 0x2:
-            /* Longword physical access with lock */
-            gen_op_ldl_l_raw();
-            break;
-        case 0x3:
-            /* Quadword physical access with lock */
-            gen_op_ldq_l_raw();
-            break;
-        case 0x4:
-            /* Longword virtual PTE fetch */
-            gen_op_ldl_kernel();
-            break;
-        case 0x5:
-            /* Quadword virtual PTE fetch */
-            gen_op_ldq_kernel();
-            break;
-        case 0x6:
-            /* Invalid */
-            goto invalid_opc;
-        case 0x7:
-            /* Invalid */
-            goto invalid_opc;
-        case 0x8:
-            /* Longword virtual access */
-            gen_op_ld_phys_to_virt();
-            gen_op_ldl_raw();
-            break;
-        case 0x9:
-            /* Quadword virtual access */
-            gen_op_ld_phys_to_virt();
-            gen_op_ldq_raw();
-            break;
-        case 0xA:
-            /* Longword virtual access with protection check */
-            gen_ldl(ctx);
-            break;
-        case 0xB:
-            /* Quadword virtual access with protection check */
-            gen_ldq(ctx);
-            break;
-        case 0xC:
-            /* Longword virtual access with altenate access mode */
-            gen_op_set_alt_mode();
-            gen_op_ld_phys_to_virt();
-            gen_op_ldl_raw();
-            gen_op_restore_mode();
-            break;
-        case 0xD:
-            /* Quadword virtual access with altenate access mode */
-            gen_op_set_alt_mode();
-            gen_op_ld_phys_to_virt();
-            gen_op_ldq_raw();
-            gen_op_restore_mode();
-            break;
-        case 0xE:
-            /* Longword virtual access with alternate access mode and
-             * protection checks
-             */
-            gen_op_set_alt_mode();
-            gen_op_ldl_data();
-            gen_op_restore_mode();
-            break;
-        case 0xF:
-            /* Quadword virtual access with alternate access mode and
-             * protection checks
-             */
-            gen_op_set_alt_mode();
-            gen_op_ldq_data();
-            gen_op_restore_mode();
-            break;
+        if (ra != 31) {
+            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
+            if (rb != 31)
+                tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
+            else
+                tcg_gen_movi_i64(addr, disp12);
+            switch ((insn >> 12) & 0xF) {
+            case 0x0:
+                /* Longword physical access */
+                tcg_gen_helper_0_2(helper_ldl_raw, cpu_ir[ra], addr);
+                break;
+            case 0x1:
+                /* Quadword physical access */
+                tcg_gen_helper_0_2(helper_ldq_raw, cpu_ir[ra], addr);
+                break;
+            case 0x2:
+                /* Longword physical access with lock */
+                tcg_gen_helper_0_2(helper_ldl_l_raw, cpu_ir[ra], addr);
+                break;
+            case 0x3:
+                /* Quadword physical access with lock */
+                tcg_gen_helper_0_2(helper_ldq_l_raw, cpu_ir[ra], addr);
+                break;
+            case 0x4:
+                /* Longword virtual PTE fetch */
+                tcg_gen_helper_0_2(helper_ldl_kernel, cpu_ir[ra], addr);
+                break;
+            case 0x5:
+                /* Quadword virtual PTE fetch */
+                tcg_gen_helper_0_2(helper_ldq_kernel, cpu_ir[ra], addr);
+                break;
+            case 0x6:
+                /* Incpu_ir[ra]id */
+                goto incpu_ir[ra]id_opc;
+            case 0x7:
+                /* Incpu_ir[ra]id */
+                goto incpu_ir[ra]id_opc;
+            case 0x8:
+                /* Longword virtual access */
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_ldl_raw, cpu_ir[ra], addr);
+                break;
+            case 0x9:
+                /* Quadword virtual access */
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_ldq_raw, cpu_ir[ra], addr);
+                break;
+            case 0xA:
+                /* Longword virtual access with protection check */
+                tcg_gen_qemu_ld32s(cpu_ir[ra], addr, ctx->flags);
+                break;
+            case 0xB:
+                /* Quadword virtual access with protection check */
+                tcg_gen_qemu_ld64(cpu_ir[ra], addr, ctx->flags);
+                break;
+            case 0xC:
+                /* Longword virtual access with altenate access mode */
+                tcg_gen_helper_0_0(helper_set_alt_mode);
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_ldl_raw, cpu_ir[ra], addr);
+                tcg_gen_helper_0_0(helper_restore_mode);
+                break;
+            case 0xD:
+                /* Quadword virtual access with altenate access mode */
+                tcg_gen_helper_0_0(helper_set_alt_mode);
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_ldq_raw, cpu_ir[ra], addr);
+                tcg_gen_helper_0_0(helper_restore_mode);
+                break;
+            case 0xE:
+                /* Longword virtual access with alternate access mode and
+                 * protection checks
+                 */
+                tcg_gen_helper_0_0(helper_set_alt_mode);
+                tcg_gen_helper_0_2(helper_ldl_data, cpu_ir[ra], addr);
+                tcg_gen_helper_0_0(helper_restore_mode);
+                break;
+            case 0xF:
+                /* Quadword virtual access with alternate access mode and
+                 * protection checks
+                 */
+                tcg_gen_helper_0_0(helper_set_alt_mode);
+                tcg_gen_helper_0_2(helper_ldq_data, cpu_ir[ra], addr);
+                tcg_gen_helper_0_0(helper_restore_mode);
+                break;
+            }
+            tcg_temp_free(addr);
         }
-        if (ra != 31)
-            tcg_gen_mov_i64(cpu_ir[ra], cpu_T[1]);
         break;
 #endif
     case 0x1C:
@@ -2006,13 +1918,29 @@
             /* FTOIT */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_fti(ctx, &gen_op_ftoit, ra, rb);
+            if (likely(rc != 31)) {
+                if (ra != 31)
+                    tcg_gen_mov_i64(cpu_ir[rc], cpu_fir[ra]);
+                else
+                    tcg_gen_movi_i64(cpu_ir[rc], 0);
+            }
             break;
         case 0x78:
             /* FTOIS */
             if (!(ctx->amask & AMASK_FIX))
                 goto invalid_opc;
-            gen_fti(ctx, &gen_op_ftois, ra, rb);
+            if (rc != 31) {
+                TCGv tmp1 = tcg_temp_new(TCG_TYPE_I32);
+                if (ra != 31)
+                    tcg_gen_helper_1_1(helper_s_to_memory, tmp1, cpu_fir[ra]);
+                else {
+                    TCGv tmp2 = tcg_const_i64(0);
+                    tcg_gen_helper_1_1(helper_s_to_memory, tmp1, tmp2);
+                    tcg_temp_free(tmp2);
+                }
+                tcg_gen_ext_i32_i64(cpu_ir[rc], tmp1);
+                tcg_temp_free(tmp1);
+            }
             break;
         default:
             goto invalid_opc;
@@ -2025,12 +1953,18 @@
 #else
         if (!ctx->pal_mode)
             goto invalid_opc;
-        if (ra != 31)
-            tcg_gen_mov_i64(cpu_T[0], cpu_ir[ra]);
-        else
-            tcg_gen_movi_i64(cpu_T[0], 0);
-        gen_op_mtpr(insn & 0xFF);
-        ret = 2;
+        else {
+            TCGv tmp1 = tcg_const_i32(insn & 0xFF);
+            if (ra != 31)
+                tcg_gen_helper(helper_mtpr, tmp1, cpu_ir[ra]);
+            else {
+                TCGv tmp2 = tcg_const_i64(0);
+                tcg_gen_helper(helper_mtpr, tmp1, tmp2);
+                tcg_temp_free(tmp2);
+            }
+            tcg_temp_free(tmp1);
+            ret = 2;
+        }
         break;
 #endif
     case 0x1E:
@@ -2042,15 +1976,17 @@
             goto invalid_opc;
         if (rb == 31) {
             /* "Old" alpha */
-            gen_op_hw_rei();
+            tcg_gen_helper_0_0(helper_hw_rei);
         } else {
-            if (ra != 31)
-                tcg_gen_mov_i64(cpu_T[0], cpu_ir[rb]);
-            else
-                tcg_gen_movi_i64(cpu_T[0], 0);
-            tcg_gen_movi_i64(cpu_T[1], (((int64_t)insn << 51) >> 51));
-            tcg_gen_add_i64(cpu_T[0], cpu_T[0], cpu_T[1]);
-            gen_op_hw_ret();
+            TCGv tmp;
+
+            if (ra != 31) {
+                tmp = tcg_temp_new(TCG_TYPE_I64);
+                tcg_gen_addi_i64(tmp, cpu_ir[rb], (((int64_t)insn << 51) >> 51));
+            } else
+                tmp = tcg_const_i64(((int64_t)insn << 51) >> 51);
+            tcg_gen_helper_0_1(helper_hw_ret, tmp);
+            tcg_temp_free(tmp);
         }
         ret = 2;
         break;
@@ -2062,206 +1998,155 @@
 #else
         if (!ctx->pal_mode)
             goto invalid_opc;
-        if (ra != 31)
-            tcg_gen_addi_i64(cpu_T[0], cpu_ir[rb], disp12);
-        else
-            tcg_gen_movi_i64(cpu_T[0], disp12);
-        if (ra != 31)
-            tcg_gen_mov_i64(cpu_T[1], cpu_ir[ra]);
-        else
-            tcg_gen_movi_i64(cpu_T[1], 0);
-        switch ((insn >> 12) & 0xF) {
-        case 0x0:
-            /* Longword physical access */
-            gen_op_stl_raw();
-            break;
-        case 0x1:
-            /* Quadword physical access */
-            gen_op_stq_raw();
-            break;
-        case 0x2:
-            /* Longword physical access with lock */
-            gen_op_stl_c_raw();
-            break;
-        case 0x3:
-            /* Quadword physical access with lock */
-            gen_op_stq_c_raw();
-            break;
-        case 0x4:
-            /* Longword virtual access */
-            gen_op_st_phys_to_virt();
-            gen_op_stl_raw();
-            break;
-        case 0x5:
-            /* Quadword virtual access */
-            gen_op_st_phys_to_virt();
-            gen_op_stq_raw();
-            break;
-        case 0x6:
-            /* Invalid */
-            goto invalid_opc;
-        case 0x7:
-            /* Invalid */
-            goto invalid_opc;
-        case 0x8:
-            /* Invalid */
-            goto invalid_opc;
-        case 0x9:
-            /* Invalid */
-            goto invalid_opc;
-        case 0xA:
-            /* Invalid */
-            goto invalid_opc;
-        case 0xB:
-            /* Invalid */
-            goto invalid_opc;
-        case 0xC:
-            /* Longword virtual access with alternate access mode */
-            gen_op_set_alt_mode();
-            gen_op_st_phys_to_virt();
-            gen_op_ldl_raw();
-            gen_op_restore_mode();
-            break;
-        case 0xD:
-            /* Quadword virtual access with alternate access mode */
-            gen_op_set_alt_mode();
-            gen_op_st_phys_to_virt();
-            gen_op_ldq_raw();
-            gen_op_restore_mode();
-            break;
-        case 0xE:
-            /* Invalid */
-            goto invalid_opc;
-        case 0xF:
-            /* Invalid */
-            goto invalid_opc;
+        else {
+            TCGv addr, val;
+            addr = tcg_temp_new(TCG_TYPE_I64);
+            if (rb != 31)
+                tcg_gen_addi_i64(addr, cpu_ir[rb], disp12);
+            else
+                tcg_gen_movi_i64(addr, disp12);
+            if (ra != 31)
+                val = cpu_ir[ra];
+            else {
+                val = tcg_temp_new(TCG_TYPE_I64);
+                tcg_gen_movi_i64(val, 0);
+            }
+            switch ((insn >> 12) & 0xF) {
+            case 0x0:
+                /* Longword physical access */
+                tcg_gen_helper_0_2(helper_stl_raw, val, addr);
+                break;
+            case 0x1:
+                /* Quadword physical access */
+                tcg_gen_helper_0_2(helper_stq_raw, val, addr);
+                break;
+            case 0x2:
+                /* Longword physical access with lock */
+                tcg_gen_helper_1_2(helper_stl_c_raw, val, val, addr);
+                break;
+            case 0x3:
+                /* Quadword physical access with lock */
+                tcg_gen_helper_1_2(helper_stq_c_raw, val, val, addr);
+                break;
+            case 0x4:
+                /* Longword virtual access */
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_stl_raw, val, addr);
+                break;
+            case 0x5:
+                /* Quadword virtual access */
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_stq_raw, val, addr);
+                break;
+            case 0x6:
+                /* Invalid */
+                goto invalid_opc;
+            case 0x7:
+                /* Invalid */
+                goto invalid_opc;
+            case 0x8:
+                /* Invalid */
+                goto invalid_opc;
+            case 0x9:
+                /* Invalid */
+                goto invalid_opc;
+            case 0xA:
+                /* Invalid */
+                goto invalid_opc;
+            case 0xB:
+                /* Invalid */
+                goto invalid_opc;
+            case 0xC:
+                /* Longword virtual access with alternate access mode */
+                tcg_gen_helper_0_0(helper_set_alt_mode);
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_stl_raw, val, addr);
+                tcg_gen_helper_0_0(helper_restore_mode);
+                break;
+            case 0xD:
+                /* Quadword virtual access with alternate access mode */
+                tcg_gen_helper_0_0(helper_set_alt_mode);
+                tcg_gen_helper_1_1(helper_st_virt_to_phys, addr, addr);
+                tcg_gen_helper_0_2(helper_stl_raw, val, addr);
+                tcg_gen_helper_0_0(helper_restore_mode);
+                break;
+            case 0xE:
+                /* Invalid */
+                goto invalid_opc;
+            case 0xF:
+                /* Invalid */
+                goto invalid_opc;
+            }
+            if (ra != 31)
+                tcg_temp_free(val);
+            tcg_temp_free(addr);
         }
         ret = 2;
         break;
 #endif
     case 0x20:
         /* LDF */
-#if 0 // TODO
-        gen_load_fmem(ctx, &gen_ldf, ra, rb, disp16);
-#else
-        goto invalid_opc;
-#endif
+        gen_load_mem(ctx, &gen_qemu_ldf, ra, rb, disp16, 1, 0);
         break;
     case 0x21:
         /* LDG */
-#if 0 // TODO
-        gen_load_fmem(ctx, &gen_ldg, ra, rb, disp16);
-#else
-        goto invalid_opc;
-#endif
+        gen_load_mem(ctx, &gen_qemu_ldg, ra, rb, disp16, 1, 0);
         break;
     case 0x22:
         /* LDS */
-        gen_load_fmem(ctx, &gen_lds, ra, rb, disp16);
+        gen_load_mem(ctx, &gen_qemu_lds, ra, rb, disp16, 1, 0);
         break;
     case 0x23:
         /* LDT */
-        gen_load_fmem(ctx, &gen_ldt, ra, rb, disp16);
+        gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 1, 0);
         break;
     case 0x24:
         /* STF */
-#if 0 // TODO
-        gen_store_fmem(ctx, &gen_stf, ra, rb, disp16);
-#else
-        goto invalid_opc;
-#endif
+        gen_store_mem(ctx, &gen_qemu_stf, ra, rb, disp16, 1, 0);
         break;
     case 0x25:
         /* STG */
-#if 0 // TODO
-        gen_store_fmem(ctx, &gen_stg, ra, rb, disp16);
-#else
-        goto invalid_opc;
-#endif
+        gen_store_mem(ctx, &gen_qemu_stg, ra, rb, disp16, 1, 0);
         break;
     case 0x26:
         /* STS */
-        gen_store_fmem(ctx, &gen_sts, ra, rb, disp16);
+        gen_store_mem(ctx, &gen_qemu_sts, ra, rb, disp16, 1, 0);
         break;
     case 0x27:
         /* STT */
-        gen_store_fmem(ctx, &gen_stt, ra, rb, disp16);
+        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 1, 0);
         break;
     case 0x28:
         /* LDL */
-        if (likely(ra != 31)) {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            tcg_gen_qemu_ld32s(cpu_ir[ra], addr, ctx->mem_idx);
-            tcg_temp_free(addr);
-        }
+        gen_load_mem(ctx, &tcg_gen_qemu_ld32s, ra, rb, disp16, 0, 0);
         break;
     case 0x29:
         /* LDQ */
-        if (likely(ra != 31)) {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            tcg_gen_qemu_ld64(cpu_ir[ra], addr, ctx->mem_idx);
-            tcg_temp_free(addr);
-        }
+        gen_load_mem(ctx, &tcg_gen_qemu_ld64, ra, rb, disp16, 0, 0);
         break;
     case 0x2A:
         /* LDL_L */
-        gen_load_mem(ctx, &gen_ldl_l, ra, rb, disp16, 0);
+        gen_load_mem(ctx, &gen_qemu_ldl_l, ra, rb, disp16, 0, 0);
         break;
     case 0x2B:
         /* LDQ_L */
-        gen_load_mem(ctx, &gen_ldq_l, ra, rb, disp16, 0);
+        gen_load_mem(ctx, &gen_qemu_ldq_l, ra, rb, disp16, 0, 0);
         break;
     case 0x2C:
         /* STL */
-        {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            if (ra != 31)
-                tcg_gen_qemu_st32(cpu_ir[ra], addr, ctx->mem_idx);
-            else {
-                TCGv zero = tcg_const_i64(0);
-                tcg_gen_qemu_st32(zero, addr, ctx->mem_idx);
-                tcg_temp_free(zero);
-            }
-            tcg_temp_free(addr);
-        }
+        gen_store_mem(ctx, &tcg_gen_qemu_st32, ra, rb, disp16, 0, 0);
         break;
     case 0x2D:
         /* STQ */
-        {
-            TCGv addr = tcg_temp_new(TCG_TYPE_I64);
-            if (rb != 31)
-                tcg_gen_addi_i64(addr, cpu_ir[rb], disp16);
-            else
-                tcg_gen_movi_i64(addr, disp16);
-            if (ra != 31)
-                tcg_gen_qemu_st64(cpu_ir[ra], addr, ctx->mem_idx);
-            else {
-                TCGv zero = tcg_const_i64(0);
-                tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
-                tcg_temp_free(zero);
-            }
-            tcg_temp_free(addr);
-        }
+        gen_store_mem(ctx, &tcg_gen_qemu_st64, ra, rb, disp16, 0, 0);
         break;
     case 0x2E:
         /* STL_C */
-        gen_store_mem(ctx, &gen_stl_c, ra, rb, disp16, 0);
+        gen_store_mem(ctx, &gen_qemu_stl_c, ra, rb, disp16, 0, 0);
         break;
     case 0x2F:
         /* STQ_C */
-        gen_store_mem(ctx, &gen_stq_c, ra, rb, disp16, 0);
+        gen_store_mem(ctx, &gen_qemu_stq_c, ra, rb, disp16, 0, 0);
         break;
     case 0x30:
         /* BR */
@@ -2272,17 +2157,17 @@
         break;
     case 0x31:
         /* FBEQ */
-        gen_fbcond(ctx, &gen_op_cmpfeq, ra, disp16);
+        gen_fbcond(ctx, &helper_cmpfeq, ra, disp16);
         ret = 1;
         break;
     case 0x32:
         /* FBLT */
-        gen_fbcond(ctx, &gen_op_cmpflt, ra, disp16);
+        gen_fbcond(ctx, &helper_cmpflt, ra, disp16);
         ret = 1;
         break;
     case 0x33:
         /* FBLE */
-        gen_fbcond(ctx, &gen_op_cmpfle, ra, disp16);
+        gen_fbcond(ctx, &helper_cmpfle, ra, disp16);
         ret = 1;
         break;
     case 0x34:
@@ -2294,17 +2179,17 @@
         break;
     case 0x35:
         /* FBNE */
-        gen_fbcond(ctx, &gen_op_cmpfne, ra, disp16);
+        gen_fbcond(ctx, &helper_cmpfne, ra, disp16);
         ret = 1;
         break;
     case 0x36:
         /* FBGE */
-        gen_fbcond(ctx, &gen_op_cmpfge, ra, disp16);
+        gen_fbcond(ctx, &helper_cmpfge, ra, disp16);
         ret = 1;
         break;
     case 0x37:
         /* FBGT */
-        gen_fbcond(ctx, &gen_op_cmpfgt, ra, disp16);
+        gen_fbcond(ctx, &helper_cmpfgt, ra, disp16);
         ret = 1;
         break;
     case 0x38:
@@ -2468,7 +2353,7 @@
     }
     if (loglevel & CPU_LOG_TB_IN_ASM) {
         fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
-	target_disas(logfile, pc_start, ctx.pc - pc_start, 1);
+        target_disas(logfile, pc_start, ctx.pc - pc_start, 1);
         fprintf(logfile, "\n");
     }
 #endif
diff -Nur kvm-76/qemu/target-i386/cpu.h kvm-userspace/qemu/target-i386/cpu.h
--- kvm-76/qemu/target-i386/cpu.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/cpu.h	2008-10-12 09:38:24.000000000 +0200
@@ -248,6 +248,8 @@
 #define MSR_MCG_STATUS                  0x17a
 #define MSR_MCG_CTL                     0x17b
 
+#define MSR_IA32_PERF_STATUS            0x198
+
 #define MSR_PAT                         0x277
 
 #define MSR_EFER                        0xc0000080
@@ -302,6 +304,7 @@
 #define CPUID_PBE (1 << 31)
 
 #define CPUID_EXT_SSE3     (1 << 0)
+#define CPUID_EXT_DTES64   (1 << 2)
 #define CPUID_EXT_MONITOR  (1 << 3)
 #define CPUID_EXT_DSCPL    (1 << 4)
 #define CPUID_EXT_VMX      (1 << 5)
@@ -312,8 +315,15 @@
 #define CPUID_EXT_CID      (1 << 10)
 #define CPUID_EXT_CX16     (1 << 13)
 #define CPUID_EXT_XTPR     (1 << 14)
-#define CPUID_EXT_DCA      (1 << 17)
-#define CPUID_EXT_POPCNT   (1 << 22)
+#define CPUID_EXT_PDCM     (1 << 15)
+#define CPUID_EXT_DCA      (1 << 18)
+#define CPUID_EXT_SSE41    (1 << 19)
+#define CPUID_EXT_SSE42    (1 << 20)
+#define CPUID_EXT_X2APIC   (1 << 21)
+#define CPUID_EXT_MOVBE    (1 << 22)
+#define CPUID_EXT_POPCNT   (1 << 23)
+#define CPUID_EXT_XSAVE    (1 << 26)
+#define CPUID_EXT_OSXSAVE  (1 << 27)
 
 #define CPUID_EXT2_SYSCALL (1 << 11)
 #define CPUID_EXT2_MP      (1 << 19)
@@ -339,6 +349,17 @@
 #define CPUID_EXT3_IBS     (1 << 10)
 #define CPUID_EXT3_SKINIT  (1 << 12)
 
+#define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
+#define CPUID_VENDOR_INTEL_2 0x49656e69 /* "ineI" */
+#define CPUID_VENDOR_INTEL_3 0x6c65746e /* "ntel" */
+
+#define CPUID_VENDOR_AMD_1   0x68747541 /* "Auth" */
+#define CPUID_VENDOR_AMD_2   0x69746e65 /* "enti" */ 
+#define CPUID_VENDOR_AMD_3   0x444d4163 /* "cAMD" */
+
+#define CPUID_MWAIT_IBE     (1 << 1) /* Interrupts can exit capability */
+#define CPUID_MWAIT_EMX     (1 << 0) /* enumeration supported */
+
 #define EXCP00_DIVZ	0
 #define EXCP01_SSTP	1
 #define EXCP02_NMI	2
@@ -542,8 +563,8 @@
 
     /* sysenter registers */
     uint32_t sysenter_cs;
-    uint64_t sysenter_esp;
-    uint64_t sysenter_eip;
+    target_ulong sysenter_esp;
+    target_ulong sysenter_eip;
     uint64_t efer;
     uint64_t star;
 
@@ -737,7 +758,7 @@
 #define cpu_signal_handler cpu_x86_signal_handler
 #define cpu_list x86_cpu_list
 
-#define CPU_SAVE_VERSION 6
+#define CPU_SAVE_VERSION 7
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff -Nur kvm-76/qemu/target-i386/helper.c kvm-userspace/qemu/target-i386/helper.c
--- kvm-76/qemu/target-i386/helper.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/helper.c	2008-10-12 09:38:24.000000000 +0200
@@ -154,9 +154,9 @@
     {
         .name = "qemu64",
         .level = 2,
-        .vendor1 = 0x68747541, /* "Auth" */
-        .vendor2 = 0x69746e65, /* "enti" */
-        .vendor3 = 0x444d4163, /* "cAMD" */
+        .vendor1 = CPUID_VENDOR_AMD_1,
+        .vendor2 = CPUID_VENDOR_AMD_2,
+        .vendor3 = CPUID_VENDOR_AMD_3,
         .family = 6,
         .model = 2,
         .stepping = 3,
@@ -173,6 +173,27 @@
         .xlevel = 0x8000000A,
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
     },
+    {
+        .name = "core2duo",
+        .level = 10,
+        .family = 6,
+        .model = 15,
+        .stepping = 11,
+	/* The original CPU also implements these features:
+               CPUID_VME, CPUID_DTS, CPUID_ACPI, CPUID_SS, CPUID_HT,
+               CPUID_TM, CPUID_PBE */
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA |
+            CPUID_PSE36,
+	/* The original CPU also implements these ext features:
+               CPUID_EXT_DTES64, CPUID_EXT_DSCPL, CPUID_EXT_VMX, CPUID_EXT_EST,
+               CPUID_EXT_TM2, CPUID_EXT_CX16, CPUID_EXT_XTPR, CPUID_EXT_PDCM */
+        .ext_features = CPUID_EXT_SSE3 | CPUID_EXT_MONITOR | CPUID_EXT_SSSE3,
+        .ext2_features = CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
+        /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */
+        .xlevel = 0x8000000A,
+        .model_id = "Intel(R) Core(TM)2 Duo CPU     T7700  @ 2.40GHz",
+    },
 #endif
     {
         .name = "qemu32",
@@ -230,12 +251,33 @@
         .family = 6,
         .model = 2,
         .stepping = 3,
-        .features = PPRO_FEATURES | PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
+        .features = PPRO_FEATURES | CPUID_PSE36 | CPUID_VME | CPUID_MTRR | CPUID_MCA,
         .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_MMXEXT | CPUID_EXT2_3DNOW | CPUID_EXT2_3DNOWEXT,
         .xlevel = 0x80000008,
         /* XXX: put another string ? */
         .model_id = "QEMU Virtual CPU version " QEMU_VERSION,
     },
+    {
+        .name = "n270",
+        /* original is on level 10 */
+        .level = 5,
+        .family = 6,
+        .model = 28,
+        .stepping = 2,
+        .features = PPRO_FEATURES |
+            CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_VME,
+            /* Missing: CPUID_DTS | CPUID_ACPI | CPUID_SS |
+             * CPUID_HT | CPUID_TM | CPUID_PBE */
+            /* Some CPUs got no CPUID_SEP */
+        .ext_features = CPUID_EXT_MONITOR |
+            CPUID_EXT_SSE3 /* PNI */, CPUID_EXT_SSSE3,
+            /* Missing: CPUID_EXT_DSCPL | CPUID_EXT_EST |
+             * CPUID_EXT_TM2 | CPUID_EXT_XTPR */
+        .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | CPUID_EXT2_NX,
+        /* Missing: .ext3_features = CPUID_EXT3_LAHF_LM */
+        .xlevel = 0x8000000A,
+        .model_id = "Intel(R) Atom(TM) CPU N270   @ 1.60GHz",
+    },
 };
 
 static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
@@ -355,9 +397,9 @@
         env->cpuid_vendor2 = def->vendor2;
         env->cpuid_vendor3 = def->vendor3;
     } else {
-        env->cpuid_vendor1 = 0x756e6547; /* "Genu" */
-        env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
-        env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
+        env->cpuid_vendor1 = CPUID_VENDOR_INTEL_1;
+        env->cpuid_vendor2 = CPUID_VENDOR_INTEL_2;
+        env->cpuid_vendor3 = CPUID_VENDOR_INTEL_3;
     }
     env->cpuid_level = def->level;
     env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
diff -Nur kvm-76/qemu/target-i386/helper.h kvm-userspace/qemu/target-i386/helper.h
--- kvm-76/qemu/target-i386/helper.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/helper.h	2008-10-12 09:38:24.000000000 +0200
@@ -55,7 +55,7 @@
 DEF_HELPER(void, helper_enter64_level, (int level, int data64, target_ulong t1))
 #endif
 DEF_HELPER(void, helper_sysenter, (void))
-DEF_HELPER(void, helper_sysexit, (void))
+DEF_HELPER(void, helper_sysexit, (int dflag))
 #ifdef TARGET_X86_64
 DEF_HELPER(void, helper_syscall, (int next_eip_addend))
 DEF_HELPER(void, helper_sysret, (int dflag))
diff -Nur kvm-76/qemu/target-i386/machine.c kvm-userspace/qemu/target-i386/machine.c
--- kvm-76/qemu/target-i386/machine.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/machine.c	2008-10-12 09:38:24.000000000 +0200
@@ -95,8 +95,8 @@
     cpu_put_seg(f, &env->idt);
 
     qemu_put_be32s(f, &env->sysenter_cs);
-    qemu_put_be32s(f, &env->sysenter_esp);
-    qemu_put_be32s(f, &env->sysenter_eip);
+    qemu_put_betls(f, &env->sysenter_esp);
+    qemu_put_betls(f, &env->sysenter_eip);
 
     qemu_put_betls(f, &env->cr[0]);
     qemu_put_betls(f, &env->cr[2]);
@@ -108,7 +108,7 @@
 
     /* MMU */
     a20_mask = (int32_t) env->a20_mask;
-    qemu_put_be32s(f, &a20_mask);
+    qemu_put_sbe32s(f, &a20_mask);
 
     /* XMM */
     qemu_put_be32s(f, &env->mxcsr);
@@ -182,7 +182,7 @@
     int32_t a20_mask;
 
     if (version_id != 3 && version_id != 4 && version_id != 5
-        && version_id != 6)
+        && version_id != 6 && version_id != 7)
         return -EINVAL;
     for(i = 0; i < CPU_NB_REGS; i++)
         qemu_get_betls(f, &env->regs[i]);
@@ -257,8 +257,13 @@
     cpu_get_seg(f, &env->idt);
 
     qemu_get_be32s(f, &env->sysenter_cs);
-    qemu_get_be32s(f, &env->sysenter_esp);
-    qemu_get_be32s(f, &env->sysenter_eip);
+    if (version_id >= 7) {
+        qemu_get_betls(f, &env->sysenter_esp);
+        qemu_get_betls(f, &env->sysenter_eip);
+    } else {
+        qemu_get_be32s(f, &env->sysenter_esp);
+        qemu_get_be32s(f, &env->sysenter_eip);
+    }
 
     qemu_get_betls(f, &env->cr[0]);
     qemu_get_betls(f, &env->cr[2]);
@@ -269,7 +274,7 @@
         qemu_get_betls(f, &env->dr[i]);
 
     /* MMU */
-    qemu_get_be32s(f, &a20_mask);
+    qemu_get_sbe32s(f, &a20_mask);
     env->a20_mask = a20_mask;
 
     qemu_get_be32s(f, &env->mxcsr);
diff -Nur kvm-76/qemu/target-i386/op_helper.c kvm-userspace/qemu/target-i386/op_helper.c
--- kvm-76/qemu/target-i386/op_helper.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/op_helper.c	2008-10-12 09:38:24.000000000 +0200
@@ -1919,6 +1919,64 @@
         ECX = 0;
         EDX = 0x2c307d;
         break;
+    case 4:
+        /* cache info: needed for Core compatibility */
+        switch (ECX) {
+            case 0: /* L1 dcache info */
+                EAX = 0x0000121;
+                EBX = 0x1c0003f;
+                ECX = 0x000003f;
+                EDX = 0x0000001;
+                break;
+            case 1: /* L1 icache info */
+                EAX = 0x0000122;
+                EBX = 0x1c0003f;
+                ECX = 0x000003f;
+                EDX = 0x0000001;
+                break;
+            case 2: /* L2 cache info */
+                EAX = 0x0000143;
+                EBX = 0x3c0003f;
+                ECX = 0x0000fff;
+                EDX = 0x0000001;
+                break;
+            default: /* end of info */
+                EAX = 0;
+                EBX = 0;
+                ECX = 0;
+                EDX = 0;
+                break;
+        }
+
+        break;
+    case 5:
+        /* mwait info: needed for Core compatibility */
+        EAX = 0; /* Smallest monitor-line size in bytes */
+        EBX = 0; /* Largest monitor-line size in bytes */
+        ECX = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE;
+        EDX = 0;
+        break;
+    case 6:
+        /* Thermal and Power Leaf */
+        EAX = 0;
+        EBX = 0;
+        ECX = 0;
+        EDX = 0;
+        break;
+    case 9:
+        /* Direct Cache Access Information Leaf */
+        EAX = 0; /* Bits 0-31 in DCA_CAP MSR */
+        EBX = 0;
+        ECX = 0;
+        EDX = 0;
+        break;
+    case 0xA:
+        /* Architectural Performance Monitoring Leaf */
+        EAX = 0;
+        EBX = 0;
+        ECX = 0;
+        EDX = 0;
+        break;
     case 0x80000000:
         EAX = env->cpuid_xlevel;
         EBX = env->cpuid_vendor1;
@@ -2593,7 +2651,8 @@
         POPW(ssp, sp, sp_mask, new_eflags);
     }
     ESP = (ESP & ~sp_mask) | (sp & sp_mask);
-    load_seg_vm(R_CS, new_cs);
+    env->segs[R_CS].selector = new_cs;
+    env->segs[R_CS].base = (new_cs << 4);
     env->eip = new_eip;
     if (env->eflags & VM_MASK)
         eflags_mask = TF_MASK | AC_MASK | ID_MASK | IF_MASK | RF_MASK | NT_MASK;
@@ -2882,11 +2941,23 @@
     }
     env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
     cpu_x86_set_cpl(env, 0);
-    cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
-                           0, 0xffffffff,
-                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
-                           DESC_S_MASK |
-                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
+
+#ifdef TARGET_X86_64
+    if (env->hflags & HF_LMA_MASK) {
+        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
+    } else
+#endif
+    {
+        cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
+    }
     cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
                            0, 0xffffffff,
                            DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
@@ -2896,7 +2967,7 @@
     EIP = env->sysenter_eip;
 }
 
-void helper_sysexit(void)
+void helper_sysexit(int dflag)
 {
     int cpl;
 
@@ -2905,16 +2976,32 @@
         raise_exception_err(EXCP0D_GPF, 0);
     }
     cpu_x86_set_cpl(env, 3);
-    cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
-                           0, 0xffffffff,
-                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
-                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
-                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
-    cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
-                           0, 0xffffffff,
-                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
-                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
-                           DESC_W_MASK | DESC_A_MASK);
+#ifdef TARGET_X86_64
+    if (dflag == 2) {
+        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 32) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
+        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 40) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_W_MASK | DESC_A_MASK);
+    } else
+#endif
+    {
+        cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
+        cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
+                               0, 0xffffffff,
+                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
+                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
+                               DESC_W_MASK | DESC_A_MASK);
+    }
     ESP = ECX;
     EIP = EDX;
 #ifdef USE_KQEMU
@@ -3146,6 +3233,12 @@
     case MSR_VM_HSAVE_PA:
         val = env->vm_hsave;
         break;
+    case MSR_IA32_PERF_STATUS:
+        /* tsc_increment_by_tick */
+        val = 1000ULL;
+        /* CPU multiplier */
+        val |= (((uint64_t)4ULL) << 40);
+        break;
 #ifdef TARGET_X86_64
     case MSR_LSTAR:
         val = env->lstar;
diff -Nur kvm-76/qemu/target-i386/ops_sse.h kvm-userspace/qemu/target-i386/ops_sse.h
--- kvm-76/qemu/target-i386/ops_sse.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/ops_sse.h	2008-10-12 09:38:24.000000000 +0200
@@ -1,7 +1,8 @@
 /*
- *  MMX/3DNow!/SSE/SSE2/SSE3/PNI support
+ *  MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI support
  *
  *  Copyright (c) 2005 Fabrice Bellard
+ *  Copyright (c) 2008 Intel Corporation  <andrew.zaborowski@intel.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -1275,6 +1276,766 @@
 }
 #endif
 
+/* SSSE3 op helpers */
+void glue(helper_pshufb, SUFFIX) (Reg *d, Reg *s)
+{
+    int i;
+    Reg r;
+
+    for (i = 0; i < (8 << SHIFT); i++)
+        r.B(i) = (s->B(i) & 0x80) ? 0 : (d->B(s->B(i) & ((8 << SHIFT) - 1)));
+
+    *d = r;
+}
+
+void glue(helper_phaddw, SUFFIX) (Reg *d, Reg *s)
+{
+    d->W(0) = (int16_t)d->W(0) + (int16_t)d->W(1);
+    d->W(1) = (int16_t)d->W(2) + (int16_t)d->W(3);
+    XMM_ONLY(d->W(2) = (int16_t)d->W(4) + (int16_t)d->W(5));
+    XMM_ONLY(d->W(3) = (int16_t)d->W(6) + (int16_t)d->W(7));
+    d->W((2 << SHIFT) + 0) = (int16_t)s->W(0) + (int16_t)s->W(1);
+    d->W((2 << SHIFT) + 1) = (int16_t)s->W(2) + (int16_t)s->W(3);
+    XMM_ONLY(d->W(6) = (int16_t)s->W(4) + (int16_t)s->W(5));
+    XMM_ONLY(d->W(7) = (int16_t)s->W(6) + (int16_t)s->W(7));
+}
+
+void glue(helper_phaddd, SUFFIX) (Reg *d, Reg *s)
+{
+    d->L(0) = (int32_t)d->L(0) + (int32_t)d->L(1);
+    XMM_ONLY(d->L(1) = (int32_t)d->L(2) + (int32_t)d->L(3));
+    d->L((1 << SHIFT) + 0) = (int32_t)s->L(0) + (int32_t)s->L(1);
+    XMM_ONLY(d->L(3) = (int32_t)s->L(2) + (int32_t)s->L(3));
+}
+
+void glue(helper_phaddsw, SUFFIX) (Reg *d, Reg *s)
+{
+    d->W(0) = satsw((int16_t)d->W(0) + (int16_t)d->W(1));
+    d->W(1) = satsw((int16_t)d->W(2) + (int16_t)d->W(3));
+    XMM_ONLY(d->W(2) = satsw((int16_t)d->W(4) + (int16_t)d->W(5)));
+    XMM_ONLY(d->W(3) = satsw((int16_t)d->W(6) + (int16_t)d->W(7)));
+    d->W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) + (int16_t)s->W(1));
+    d->W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) + (int16_t)s->W(3));
+    XMM_ONLY(d->W(6) = satsw((int16_t)s->W(4) + (int16_t)s->W(5)));
+    XMM_ONLY(d->W(7) = satsw((int16_t)s->W(6) + (int16_t)s->W(7)));
+}
+
+void glue(helper_pmaddubsw, SUFFIX) (Reg *d, Reg *s)
+{
+    d->W(0) = satsw((int8_t)s->B( 0) * (uint8_t)d->B( 0) +
+                    (int8_t)s->B( 1) * (uint8_t)d->B( 1));
+    d->W(1) = satsw((int8_t)s->B( 2) * (uint8_t)d->B( 2) +
+                    (int8_t)s->B( 3) * (uint8_t)d->B( 3));
+    d->W(2) = satsw((int8_t)s->B( 4) * (uint8_t)d->B( 4) +
+                    (int8_t)s->B( 5) * (uint8_t)d->B( 5));
+    d->W(3) = satsw((int8_t)s->B( 6) * (uint8_t)d->B( 6) +
+                    (int8_t)s->B( 7) * (uint8_t)d->B( 7));
+#if SHIFT == 1
+    d->W(4) = satsw((int8_t)s->B( 8) * (uint8_t)d->B( 8) +
+                    (int8_t)s->B( 9) * (uint8_t)d->B( 9));
+    d->W(5) = satsw((int8_t)s->B(10) * (uint8_t)d->B(10) +
+                    (int8_t)s->B(11) * (uint8_t)d->B(11));
+    d->W(6) = satsw((int8_t)s->B(12) * (uint8_t)d->B(12) +
+                    (int8_t)s->B(13) * (uint8_t)d->B(13));
+    d->W(7) = satsw((int8_t)s->B(14) * (uint8_t)d->B(14) +
+                    (int8_t)s->B(15) * (uint8_t)d->B(15));
+#endif
+}
+
+void glue(helper_phsubw, SUFFIX) (Reg *d, Reg *s)
+{
+    d->W(0) = (int16_t)d->W(0) - (int16_t)d->W(1);
+    d->W(1) = (int16_t)d->W(2) - (int16_t)d->W(3);
+    XMM_ONLY(d->W(2) = (int16_t)d->W(4) - (int16_t)d->W(5));
+    XMM_ONLY(d->W(3) = (int16_t)d->W(6) - (int16_t)d->W(7));
+    d->W((2 << SHIFT) + 0) = (int16_t)s->W(0) - (int16_t)s->W(1);
+    d->W((2 << SHIFT) + 1) = (int16_t)s->W(2) - (int16_t)s->W(3);
+    XMM_ONLY(d->W(6) = (int16_t)s->W(4) - (int16_t)s->W(5));
+    XMM_ONLY(d->W(7) = (int16_t)s->W(6) - (int16_t)s->W(7));
+}
+
+void glue(helper_phsubd, SUFFIX) (Reg *d, Reg *s)
+{
+    d->L(0) = (int32_t)d->L(0) - (int32_t)d->L(1);
+    XMM_ONLY(d->L(1) = (int32_t)d->L(2) - (int32_t)d->L(3));
+    d->L((1 << SHIFT) + 0) = (int32_t)s->L(0) - (int32_t)s->L(1);
+    XMM_ONLY(d->L(3) = (int32_t)s->L(2) - (int32_t)s->L(3));
+}
+
+void glue(helper_phsubsw, SUFFIX) (Reg *d, Reg *s)
+{
+    d->W(0) = satsw((int16_t)d->W(0) - (int16_t)d->W(1));
+    d->W(1) = satsw((int16_t)d->W(2) - (int16_t)d->W(3));
+    XMM_ONLY(d->W(2) = satsw((int16_t)d->W(4) - (int16_t)d->W(5)));
+    XMM_ONLY(d->W(3) = satsw((int16_t)d->W(6) - (int16_t)d->W(7)));
+    d->W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) - (int16_t)s->W(1));
+    d->W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) - (int16_t)s->W(3));
+    XMM_ONLY(d->W(6) = satsw((int16_t)s->W(4) - (int16_t)s->W(5)));
+    XMM_ONLY(d->W(7) = satsw((int16_t)s->W(6) - (int16_t)s->W(7)));
+}
+
+#define FABSB(_, x) x > INT8_MAX  ? -(int8_t ) x : x
+#define FABSW(_, x) x > INT16_MAX ? -(int16_t) x : x
+#define FABSL(_, x) x > INT32_MAX ? -(int32_t) x : x
+SSE_HELPER_B(helper_pabsb, FABSB)
+SSE_HELPER_W(helper_pabsw, FABSW)
+SSE_HELPER_L(helper_pabsd, FABSL)
+
+#define FMULHRSW(d, s) ((int16_t) d * (int16_t) s + 0x4000) >> 15
+SSE_HELPER_W(helper_pmulhrsw, FMULHRSW)
+
+#define FSIGNB(d, s) s <= INT8_MAX  ? s ? d : 0 : -(int8_t ) d
+#define FSIGNW(d, s) s <= INT16_MAX ? s ? d : 0 : -(int16_t) d
+#define FSIGNL(d, s) s <= INT32_MAX ? s ? d : 0 : -(int32_t) d
+SSE_HELPER_B(helper_psignb, FSIGNB)
+SSE_HELPER_W(helper_psignw, FSIGNW)
+SSE_HELPER_L(helper_psignd, FSIGNL)
+
+void glue(helper_palignr, SUFFIX) (Reg *d, Reg *s, int32_t shift)
+{
+    Reg r;
+
+    /* XXX could be checked during translation */
+    if (shift >= (16 << SHIFT)) {
+        r.Q(0) = 0;
+        XMM_ONLY(r.Q(1) = 0);
+    } else {
+        shift <<= 3;
+#define SHR(v, i) (i < 64 && i > -64 ? i > 0 ? v >> (i) : (v << -(i)) : 0)
+#if SHIFT == 0
+        r.Q(0) = SHR(s->Q(0), shift -   0) |
+                 SHR(d->Q(0), shift -  64);
+#else
+        r.Q(0) = SHR(s->Q(0), shift -   0) |
+                 SHR(s->Q(1), shift -  64) |
+                 SHR(d->Q(0), shift - 128) |
+                 SHR(d->Q(1), shift - 192);
+        r.Q(1) = SHR(s->Q(0), shift +  64) |
+                 SHR(s->Q(1), shift -   0) |
+                 SHR(d->Q(0), shift -  64) |
+                 SHR(d->Q(1), shift - 128);
+#endif
+#undef SHR
+    }
+
+    *d = r;
+}
+
+#define XMM0 env->xmm_regs[0]
+
+#if SHIFT == 1
+#define SSE_HELPER_V(name, elem, num, F)\
+void glue(name, SUFFIX) (Reg *d, Reg *s)\
+{\
+    d->elem(0) = F(d->elem(0), s->elem(0), XMM0.elem(0));\
+    d->elem(1) = F(d->elem(1), s->elem(1), XMM0.elem(1));\
+    if (num > 2) {\
+        d->elem(2) = F(d->elem(2), s->elem(2), XMM0.elem(2));\
+        d->elem(3) = F(d->elem(3), s->elem(3), XMM0.elem(3));\
+        if (num > 4) {\
+            d->elem(4) = F(d->elem(4), s->elem(4), XMM0.elem(4));\
+            d->elem(5) = F(d->elem(5), s->elem(5), XMM0.elem(5));\
+            d->elem(6) = F(d->elem(6), s->elem(6), XMM0.elem(6));\
+            d->elem(7) = F(d->elem(7), s->elem(7), XMM0.elem(7));\
+            if (num > 8) {\
+                d->elem(8) = F(d->elem(8), s->elem(8), XMM0.elem(8));\
+                d->elem(9) = F(d->elem(9), s->elem(9), XMM0.elem(9));\
+                d->elem(10) = F(d->elem(10), s->elem(10), XMM0.elem(10));\
+                d->elem(11) = F(d->elem(11), s->elem(11), XMM0.elem(11));\
+                d->elem(12) = F(d->elem(12), s->elem(12), XMM0.elem(12));\
+                d->elem(13) = F(d->elem(13), s->elem(13), XMM0.elem(13));\
+                d->elem(14) = F(d->elem(14), s->elem(14), XMM0.elem(14));\
+                d->elem(15) = F(d->elem(15), s->elem(15), XMM0.elem(15));\
+            }\
+        }\
+    }\
+}
+
+#define SSE_HELPER_I(name, elem, num, F)\
+void glue(name, SUFFIX) (Reg *d, Reg *s, uint32_t imm)\
+{\
+    d->elem(0) = F(d->elem(0), s->elem(0), ((imm >> 0) & 1));\
+    d->elem(1) = F(d->elem(1), s->elem(1), ((imm >> 1) & 1));\
+    if (num > 2) {\
+        d->elem(2) = F(d->elem(2), s->elem(2), ((imm >> 2) & 1));\
+        d->elem(3) = F(d->elem(3), s->elem(3), ((imm >> 3) & 1));\
+        if (num > 4) {\
+            d->elem(4) = F(d->elem(4), s->elem(4), ((imm >> 4) & 1));\
+            d->elem(5) = F(d->elem(5), s->elem(5), ((imm >> 5) & 1));\
+            d->elem(6) = F(d->elem(6), s->elem(6), ((imm >> 6) & 1));\
+            d->elem(7) = F(d->elem(7), s->elem(7), ((imm >> 7) & 1));\
+            if (num > 8) {\
+                d->elem(8) = F(d->elem(8), s->elem(8), ((imm >> 8) & 1));\
+                d->elem(9) = F(d->elem(9), s->elem(9), ((imm >> 9) & 1));\
+                d->elem(10) = F(d->elem(10), s->elem(10), ((imm >> 10) & 1));\
+                d->elem(11) = F(d->elem(11), s->elem(11), ((imm >> 11) & 1));\
+                d->elem(12) = F(d->elem(12), s->elem(12), ((imm >> 12) & 1));\
+                d->elem(13) = F(d->elem(13), s->elem(13), ((imm >> 13) & 1));\
+                d->elem(14) = F(d->elem(14), s->elem(14), ((imm >> 14) & 1));\
+                d->elem(15) = F(d->elem(15), s->elem(15), ((imm >> 15) & 1));\
+            }\
+        }\
+    }\
+}
+
+/* SSE4.1 op helpers */
+#define FBLENDVB(d, s, m) (m & 0x80) ? s : d
+#define FBLENDVPS(d, s, m) (m & 0x80000000) ? s : d
+#define FBLENDVPD(d, s, m) (m & 0x8000000000000000LL) ? s : d
+SSE_HELPER_V(helper_pblendvb, B, 16, FBLENDVB)
+SSE_HELPER_V(helper_blendvps, L, 4, FBLENDVPS)
+SSE_HELPER_V(helper_blendvpd, Q, 2, FBLENDVPD)
+
+void glue(helper_ptest, SUFFIX) (Reg *d, Reg *s)
+{
+    uint64_t zf = (s->Q(0) &  d->Q(0)) | (s->Q(1) &  d->Q(1));
+    uint64_t cf = (s->Q(0) & ~d->Q(0)) | (s->Q(1) & ~d->Q(1));
+
+    CC_SRC = (zf ? 0 : CC_Z) | (cf ? 0 : CC_C);
+}
+
+#define SSE_HELPER_F(name, elem, num, F)\
+void glue(name, SUFFIX) (Reg *d, Reg *s)\
+{\
+    d->elem(0) = F(0);\
+    d->elem(1) = F(1);\
+    d->elem(2) = F(2);\
+    d->elem(3) = F(3);\
+    if (num > 3) {\
+        d->elem(4) = F(4);\
+        d->elem(5) = F(5);\
+        if (num > 5) {\
+            d->elem(6) = F(6);\
+            d->elem(7) = F(7);\
+        }\
+    }\
+}
+
+SSE_HELPER_F(helper_pmovsxbw, W, 8, (int8_t) s->B)
+SSE_HELPER_F(helper_pmovsxbd, L, 4, (int8_t) s->B)
+SSE_HELPER_F(helper_pmovsxbq, Q, 2, (int8_t) s->B)
+SSE_HELPER_F(helper_pmovsxwd, L, 4, (int16_t) s->W)
+SSE_HELPER_F(helper_pmovsxwq, Q, 2, (int16_t) s->W)
+SSE_HELPER_F(helper_pmovsxdq, Q, 2, (int32_t) s->L)
+SSE_HELPER_F(helper_pmovzxbw, W, 8, s->B)
+SSE_HELPER_F(helper_pmovzxbd, L, 4, s->B)
+SSE_HELPER_F(helper_pmovzxbq, Q, 2, s->B)
+SSE_HELPER_F(helper_pmovzxwd, L, 4, s->W)
+SSE_HELPER_F(helper_pmovzxwq, Q, 2, s->W)
+SSE_HELPER_F(helper_pmovzxdq, Q, 2, s->L)
+
+void glue(helper_pmuldq, SUFFIX) (Reg *d, Reg *s)
+{
+    d->Q(0) = (int64_t) (int32_t) d->L(0) * (int32_t) s->L(0);
+    d->Q(1) = (int64_t) (int32_t) d->L(2) * (int32_t) s->L(2);
+}
+
+#define FCMPEQQ(d, s) d == s ? -1 : 0
+SSE_HELPER_Q(helper_pcmpeqq, FCMPEQQ)
+
+void glue(helper_packusdw, SUFFIX) (Reg *d, Reg *s)
+{
+    d->W(0) = satuw((int32_t) d->L(0));
+    d->W(1) = satuw((int32_t) d->L(1));
+    d->W(2) = satuw((int32_t) d->L(2));
+    d->W(3) = satuw((int32_t) d->L(3));
+    d->W(4) = satuw((int32_t) s->L(0));
+    d->W(5) = satuw((int32_t) s->L(1));
+    d->W(6) = satuw((int32_t) s->L(2));
+    d->W(7) = satuw((int32_t) s->L(3));
+}
+
+#define FMINSB(d, s) MIN((int8_t) d, (int8_t) s)
+#define FMINSD(d, s) MIN((int32_t) d, (int32_t) s)
+#define FMAXSB(d, s) MAX((int8_t) d, (int8_t) s)
+#define FMAXSD(d, s) MAX((int32_t) d, (int32_t) s)
+SSE_HELPER_B(helper_pminsb, FMINSB)
+SSE_HELPER_L(helper_pminsd, FMINSD)
+SSE_HELPER_W(helper_pminuw, MIN)
+SSE_HELPER_L(helper_pminud, MIN)
+SSE_HELPER_B(helper_pmaxsb, FMAXSB)
+SSE_HELPER_L(helper_pmaxsd, FMAXSD)
+SSE_HELPER_W(helper_pmaxuw, MAX)
+SSE_HELPER_L(helper_pmaxud, MAX)
+
+#define FMULLD(d, s) (int32_t) d * (int32_t) s
+SSE_HELPER_L(helper_pmulld, FMULLD)
+
+void glue(helper_phminposuw, SUFFIX) (Reg *d, Reg *s)
+{
+    int idx = 0;
+
+    if (s->W(1) < s->W(idx))
+        idx = 1;
+    if (s->W(2) < s->W(idx))
+        idx = 2;
+    if (s->W(3) < s->W(idx))
+        idx = 3;
+    if (s->W(4) < s->W(idx))
+        idx = 4;
+    if (s->W(5) < s->W(idx))
+        idx = 5;
+    if (s->W(6) < s->W(idx))
+        idx = 6;
+    if (s->W(7) < s->W(idx))
+        idx = 7;
+
+    d->Q(1) = 0;
+    d->L(1) = 0;
+    d->W(1) = idx;
+    d->W(0) = s->W(idx);
+}
+
+void glue(helper_roundps, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
+{
+    signed char prev_rounding_mode;
+
+    prev_rounding_mode = env->sse_status.float_rounding_mode;
+    if (!(mode & (1 << 2)))
+        switch (mode & 3) {
+        case 0:
+            set_float_rounding_mode(float_round_nearest_even, &env->sse_status);
+            break;
+        case 1:
+            set_float_rounding_mode(float_round_down, &env->sse_status);
+            break;
+        case 2:
+            set_float_rounding_mode(float_round_up, &env->sse_status);
+            break;
+        case 3:
+            set_float_rounding_mode(float_round_to_zero, &env->sse_status);
+            break;
+        }
+
+    d->L(0) = float64_round_to_int(s->L(0), &env->sse_status);
+    d->L(1) = float64_round_to_int(s->L(1), &env->sse_status);
+    d->L(2) = float64_round_to_int(s->L(2), &env->sse_status);
+    d->L(3) = float64_round_to_int(s->L(3), &env->sse_status);
+
+#if 0 /* TODO */
+    if (mode & (1 << 3))
+        set_float_exception_flags(
+                        get_float_exception_flags(&env->sse_status) &
+                        ~float_flag_inexact,
+                        &env->sse_status);
+#endif
+    env->sse_status.float_rounding_mode = prev_rounding_mode;
+}
+
+void glue(helper_roundpd, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
+{
+    signed char prev_rounding_mode;
+
+    prev_rounding_mode = env->sse_status.float_rounding_mode;
+    if (!(mode & (1 << 2)))
+        switch (mode & 3) {
+        case 0:
+            set_float_rounding_mode(float_round_nearest_even, &env->sse_status);
+            break;
+        case 1:
+            set_float_rounding_mode(float_round_down, &env->sse_status);
+            break;
+        case 2:
+            set_float_rounding_mode(float_round_up, &env->sse_status);
+            break;
+        case 3:
+            set_float_rounding_mode(float_round_to_zero, &env->sse_status);
+            break;
+        }
+
+    d->Q(0) = float64_round_to_int(s->Q(0), &env->sse_status);
+    d->Q(1) = float64_round_to_int(s->Q(1), &env->sse_status);
+
+#if 0 /* TODO */
+    if (mode & (1 << 3))
+        set_float_exception_flags(
+                        get_float_exception_flags(&env->sse_status) &
+                        ~float_flag_inexact,
+                        &env->sse_status);
+#endif
+    env->sse_status.float_rounding_mode = prev_rounding_mode;
+}
+
+void glue(helper_roundss, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
+{
+    signed char prev_rounding_mode;
+
+    prev_rounding_mode = env->sse_status.float_rounding_mode;
+    if (!(mode & (1 << 2)))
+        switch (mode & 3) {
+        case 0:
+            set_float_rounding_mode(float_round_nearest_even, &env->sse_status);
+            break;
+        case 1:
+            set_float_rounding_mode(float_round_down, &env->sse_status);
+            break;
+        case 2:
+            set_float_rounding_mode(float_round_up, &env->sse_status);
+            break;
+        case 3:
+            set_float_rounding_mode(float_round_to_zero, &env->sse_status);
+            break;
+        }
+
+    d->L(0) = float64_round_to_int(s->L(0), &env->sse_status);
+
+#if 0 /* TODO */
+    if (mode & (1 << 3))
+        set_float_exception_flags(
+                        get_float_exception_flags(&env->sse_status) &
+                        ~float_flag_inexact,
+                        &env->sse_status);
+#endif
+    env->sse_status.float_rounding_mode = prev_rounding_mode;
+}
+
+void glue(helper_roundsd, SUFFIX) (Reg *d, Reg *s, uint32_t mode)
+{
+    signed char prev_rounding_mode;
+
+    prev_rounding_mode = env->sse_status.float_rounding_mode;
+    if (!(mode & (1 << 2)))
+        switch (mode & 3) {
+        case 0:
+            set_float_rounding_mode(float_round_nearest_even, &env->sse_status);
+            break;
+        case 1:
+            set_float_rounding_mode(float_round_down, &env->sse_status);
+            break;
+        case 2:
+            set_float_rounding_mode(float_round_up, &env->sse_status);
+            break;
+        case 3:
+            set_float_rounding_mode(float_round_to_zero, &env->sse_status);
+            break;
+        }
+
+    d->Q(0) = float64_round_to_int(s->Q(0), &env->sse_status);
+
+#if 0 /* TODO */
+    if (mode & (1 << 3))
+        set_float_exception_flags(
+                        get_float_exception_flags(&env->sse_status) &
+                        ~float_flag_inexact,
+                        &env->sse_status);
+#endif
+    env->sse_status.float_rounding_mode = prev_rounding_mode;
+}
+
+#define FBLENDP(d, s, m) m ? s : d
+SSE_HELPER_I(helper_blendps, L, 4, FBLENDP)
+SSE_HELPER_I(helper_blendpd, Q, 2, FBLENDP)
+SSE_HELPER_I(helper_pblendw, W, 8, FBLENDP)
+
+void glue(helper_dpps, SUFFIX) (Reg *d, Reg *s, uint32_t mask)
+{
+    float32 iresult = 0 /*float32_zero*/;
+
+    if (mask & (1 << 4))
+        iresult = float32_add(iresult,
+                        float32_mul(d->L(0), s->L(0), &env->sse_status),
+                        &env->sse_status);
+    if (mask & (1 << 5))
+        iresult = float32_add(iresult,
+                        float32_mul(d->L(1), s->L(1), &env->sse_status),
+                        &env->sse_status);
+    if (mask & (1 << 6))
+        iresult = float32_add(iresult,
+                        float32_mul(d->L(2), s->L(2), &env->sse_status),
+                        &env->sse_status);
+    if (mask & (1 << 7))
+        iresult = float32_add(iresult,
+                        float32_mul(d->L(3), s->L(3), &env->sse_status),
+                        &env->sse_status);
+    d->L(0) = (mask & (1 << 0)) ? iresult : 0 /*float32_zero*/;
+    d->L(1) = (mask & (1 << 1)) ? iresult : 0 /*float32_zero*/;
+    d->L(2) = (mask & (1 << 2)) ? iresult : 0 /*float32_zero*/;
+    d->L(3) = (mask & (1 << 3)) ? iresult : 0 /*float32_zero*/;
+}
+
+void glue(helper_dppd, SUFFIX) (Reg *d, Reg *s, uint32_t mask)
+{
+    float64 iresult = 0 /*float64_zero*/;
+
+    if (mask & (1 << 4))
+        iresult = float64_add(iresult,
+                        float64_mul(d->Q(0), s->Q(0), &env->sse_status),
+                        &env->sse_status);
+    if (mask & (1 << 5))
+        iresult = float64_add(iresult,
+                        float64_mul(d->Q(1), s->Q(1), &env->sse_status),
+                        &env->sse_status);
+    d->Q(0) = (mask & (1 << 0)) ? iresult : 0 /*float64_zero*/;
+    d->Q(1) = (mask & (1 << 1)) ? iresult : 0 /*float64_zero*/;
+}
+
+void glue(helper_mpsadbw, SUFFIX) (Reg *d, Reg *s, uint32_t offset)
+{
+    int s0 = (offset & 3) << 2;
+    int d0 = (offset & 4) << 0;
+    int i;
+    Reg r;
+
+    for (i = 0; i < 8; i++, d0++) {
+        r.W(i) = 0;
+        r.W(i) += abs1(d->B(d0 + 0) - s->B(s0 + 0));
+        r.W(i) += abs1(d->B(d0 + 1) - s->B(s0 + 1));
+        r.W(i) += abs1(d->B(d0 + 2) - s->B(s0 + 2));
+        r.W(i) += abs1(d->B(d0 + 3) - s->B(s0 + 3));
+    }
+
+    *d = r;
+}
+
+/* SSE4.2 op helpers */
+/* it's unclear whether signed or unsigned */
+#define FCMPGTQ(d, s) d > s ? -1 : 0
+SSE_HELPER_Q(helper_pcmpgtq, FCMPGTQ)
+
+static inline int pcmp_elen(int reg, uint32_t ctrl)
+{
+    int val;
+
+    /* Presence of REX.W is indicated by a bit higher than 7 set */
+    if (ctrl >> 8)
+        val = abs1((int64_t) env->regs[reg]);
+    else
+        val = abs1((int32_t) env->regs[reg]);
+
+    if (ctrl & 1) {
+        if (val > 8)
+            return 8;
+    } else
+        if (val > 16)
+            return 16;
+
+    return val;
+}
+
+static inline int pcmp_ilen(Reg *r, uint8_t ctrl)
+{
+    int val = 0;
+
+    if (ctrl & 1) {
+        while (val < 8 && r->W(val))
+            val++;
+    } else
+        while (val < 16 && r->B(val))
+            val++;
+
+    return val;
+}
+
+static inline int pcmp_val(Reg *r, uint8_t ctrl, int i)
+{
+    switch ((ctrl >> 0) & 3) {
+    case 0:
+        return r->B(i);
+    case 1:
+        return r->W(i);
+    case 2:
+        return (int8_t) r->B(i);
+    case 3:
+    default:
+        return (int16_t) r->W(i);
+    }
+}
+
+static inline unsigned pcmpxstrx(Reg *d, Reg *s,
+                int8_t ctrl, int valids, int validd)
+{
+    unsigned int res = 0;
+    int v;
+    int j, i;
+    int upper = (ctrl & 1) ? 7 : 15;
+
+    valids--;
+    validd--;
+
+    CC_SRC = (valids < upper ? CC_Z : 0) | (validd < upper ? CC_S : 0);
+
+    switch ((ctrl >> 2) & 3) {
+    case 0:
+        for (j = valids; j >= 0; j--) {
+            res <<= 1;
+            v = pcmp_val(s, ctrl, j);
+            for (i = validd; i >= 0; i--)
+                res |= (v == pcmp_val(d, ctrl, i));
+        }
+        break;
+    case 1:
+        for (j = valids; j >= 0; j--) {
+            res <<= 1;
+            v = pcmp_val(s, ctrl, j);
+            for (i = ((validd - 1) | 1); i >= 0; i -= 2)
+                res |= (pcmp_val(d, ctrl, i - 0) <= v &&
+                        pcmp_val(d, ctrl, i - 1) >= v);
+        }
+        break;
+    case 2:
+        res = (2 << (upper - MAX(valids, validd))) - 1;
+        res <<= MAX(valids, validd) - MIN(valids, validd);
+        for (i = MIN(valids, validd); i >= 0; i--) {
+            res <<= 1;
+            v = pcmp_val(s, ctrl, i);
+            res |= (v == pcmp_val(d, ctrl, i));
+        }
+        break;
+    case 3:
+        for (j = valids - validd; j >= 0; j--) {
+            res <<= 1;
+            res |= 1;
+            for (i = MIN(upper - j, validd); i >= 0; i--)
+                res &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i));
+        }
+        break;
+    }
+
+    switch ((ctrl >> 4) & 3) {
+    case 1:
+        res ^= (2 << upper) - 1;
+        break;
+    case 3:
+        res ^= (2 << valids) - 1;
+        break;
+    }
+
+    if (res)
+       CC_SRC |= CC_C;
+    if (res & 1)
+       CC_SRC |= CC_O;
+
+    return res;
+}
+
+static inline int rffs1(unsigned int val)
+{
+    int ret = 1, hi;
+
+    for (hi = sizeof(val) * 4; hi; hi /= 2)
+        if (val >> hi) {
+            val >>= hi;
+            ret += hi;
+        }
+
+    return ret;
+}
+
+static inline int ffs1(unsigned int val)
+{
+    int ret = 1, hi;
+
+    for (hi = sizeof(val) * 4; hi; hi /= 2)
+        if (val << hi) {
+            val <<= hi;
+            ret += hi;
+        }
+
+    return ret;
+}
+
+void glue(helper_pcmpestri, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
+{
+    unsigned int res = pcmpxstrx(d, s, ctrl,
+                    pcmp_elen(R_EDX, ctrl),
+                    pcmp_elen(R_EAX, ctrl));
+
+    if (res)
+        env->regs[R_ECX] = ((ctrl & (1 << 6)) ? rffs1 : ffs1)(res) - 1;
+    else
+        env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
+}
+
+void glue(helper_pcmpestrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
+{
+    int i;
+    unsigned int res = pcmpxstrx(d, s, ctrl,
+                    pcmp_elen(R_EDX, ctrl),
+                    pcmp_elen(R_EAX, ctrl));
+
+    if ((ctrl >> 6) & 1) {
+        if (ctrl & 1)
+            for (i = 0; i <= 8; i--, res >>= 1)
+                d->W(i) = (res & 1) ? ~0 : 0;
+        else
+            for (i = 0; i <= 16; i--, res >>= 1)
+                d->B(i) = (res & 1) ? ~0 : 0;
+    } else {
+        d->Q(1) = 0;
+        d->Q(0) = res;
+    }
+}
+
+void glue(helper_pcmpistri, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
+{
+    unsigned int res = pcmpxstrx(d, s, ctrl,
+                    pcmp_ilen(s, ctrl),
+                    pcmp_ilen(d, ctrl));
+
+    if (res)
+        env->regs[R_ECX] = ((ctrl & (1 << 6)) ? rffs1 : ffs1)(res) - 1;
+    else
+        env->regs[R_ECX] = 16 >> (ctrl & (1 << 0));
+}
+
+void glue(helper_pcmpistrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
+{
+    int i;
+    unsigned int res = pcmpxstrx(d, s, ctrl,
+                    pcmp_ilen(s, ctrl),
+                    pcmp_ilen(d, ctrl));
+
+    if ((ctrl >> 6) & 1) {
+        if (ctrl & 1)
+            for (i = 0; i <= 8; i--, res >>= 1)
+                d->W(i) = (res & 1) ? ~0 : 0;
+        else
+            for (i = 0; i <= 16; i--, res >>= 1)
+                d->B(i) = (res & 1) ? ~0 : 0;
+    } else {
+        d->Q(1) = 0;
+        d->Q(0) = res;
+    }
+}
+
+#define CRCPOLY        0x1edc6f41
+#define CRCPOLY_BITREV 0x82f63b78
+target_ulong helper_crc32(uint32_t crc1, target_ulong msg, uint32_t len)
+{
+    target_ulong crc = (msg & ((target_ulong) -1 >>
+                            (TARGET_LONG_BITS - len))) ^ crc1;
+
+    while (len--)
+        crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_BITREV : 0);
+
+    return crc;
+}
+
+#define POPMASK(i)     ((target_ulong) -1 / ((1LL << (1 << i)) + 1))
+#define POPCOUNT(n, i) (n & POPMASK(i)) + ((n >> (1 << i)) & POPMASK(i))
+target_ulong helper_popcnt(target_ulong n, uint32_t type)
+{
+    CC_SRC = n ? 0 : CC_Z;
+
+    n = POPCOUNT(n, 0);
+    n = POPCOUNT(n, 1);
+    n = POPCOUNT(n, 2);
+    n = POPCOUNT(n, 3);
+    if (type == 1)
+        return n & 0xff;
+
+    n = POPCOUNT(n, 4);
+#ifndef TARGET_X86_64
+    return n;
+#else
+    if (type == 2)
+        return n & 0xff;
+
+    return POPCOUNT(n, 5);
+#endif
+}
+#endif
+
 #undef SHIFT
 #undef XMM_ONLY
 #undef Reg
diff -Nur kvm-76/qemu/target-i386/ops_sse_header.h kvm-userspace/qemu/target-i386/ops_sse_header.h
--- kvm-76/qemu/target-i386/ops_sse_header.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/ops_sse_header.h	2008-10-12 09:38:24.000000000 +0200
@@ -1,5 +1,5 @@
 /*
- *  MMX/3DNow!/SSE/SSE2/SSE3/PNI support
+ *  MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4/PNI support
  *
  *  Copyright (c) 2005 Fabrice Bellard
  *
@@ -251,6 +251,79 @@
 DEF_HELPER(void, helper_pswapd, (MMXReg *d, MMXReg *s))
 #endif
 
+/* SSSE3 op helpers */
+DEF_HELPER(void, glue(helper_phaddw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_phaddd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_phaddsw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_phsubw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_phsubd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_phsubsw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pabsb, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pabsw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pabsd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmaddubsw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmulhrsw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pshufb, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_psignb, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_psignw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_psignd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_palignr, SUFFIX), (Reg *d, Reg *s, int32_t shift))
+
+/* SSE4.1 op helpers */
+#if SHIFT == 1
+DEF_HELPER(void, glue(helper_pblendvb, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_blendvps, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_blendvpd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_ptest, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovsxbw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovsxbd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovsxbq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovsxwd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovsxwq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovsxdq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovzxbw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovzxbd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovzxbq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovzxwd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovzxwq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmovzxdq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmuldq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pcmpeqq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_packusdw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pminsb, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pminsd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pminuw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pminud, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmaxsb, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmaxsd, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmaxuw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmaxud, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pmulld, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_phminposuw, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_roundps, SUFFIX), (Reg *d, Reg *s, uint32_t mode))
+DEF_HELPER(void, glue(helper_roundpd, SUFFIX), (Reg *d, Reg *s, uint32_t mode))
+DEF_HELPER(void, glue(helper_roundss, SUFFIX), (Reg *d, Reg *s, uint32_t mode))
+DEF_HELPER(void, glue(helper_roundsd, SUFFIX), (Reg *d, Reg *s, uint32_t mode))
+DEF_HELPER(void, glue(helper_blendps, SUFFIX), (Reg *d, Reg *s, uint32_t imm))
+DEF_HELPER(void, glue(helper_blendpd, SUFFIX), (Reg *d, Reg *s, uint32_t imm))
+DEF_HELPER(void, glue(helper_pblendw, SUFFIX), (Reg *d, Reg *s, uint32_t imm))
+DEF_HELPER(void, glue(helper_dpps, SUFFIX), (Reg *d, Reg *s, uint32_t mask))
+DEF_HELPER(void, glue(helper_dppd, SUFFIX), (Reg *d, Reg *s, uint32_t mask))
+DEF_HELPER(void, glue(helper_mpsadbw, SUFFIX), (Reg *d, Reg *s, uint32_t off))
+#endif
+
+/* SSE4.2 op helpers */
+#if SHIFT == 1
+DEF_HELPER(void, glue(helper_pcmpgtq, SUFFIX), (Reg *d, Reg *s))
+DEF_HELPER(void, glue(helper_pcmpestri, SUFFIX), (Reg *d, Reg *s, uint32_t ctl))
+DEF_HELPER(void, glue(helper_pcmpestrm, SUFFIX), (Reg *d, Reg *s, uint32_t ctl))
+DEF_HELPER(void, glue(helper_pcmpistri, SUFFIX), (Reg *d, Reg *s, uint32_t ctl))
+DEF_HELPER(void, glue(helper_pcmpistrm, SUFFIX), (Reg *d, Reg *s, uint32_t ctl))
+DEF_HELPER(target_ulong, helper_crc32,
+                (uint32_t crc1, target_ulong msg, uint32_t len))
+DEF_HELPER(target_ulong, helper_popcnt, (target_ulong n, uint32_t type))
+#endif
+
 #undef SHIFT
 #undef Reg
 #undef SUFFIX
diff -Nur kvm-76/qemu/target-i386/translate.c kvm-userspace/qemu/target-i386/translate.c
--- kvm-76/qemu/target-i386/translate.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-i386/translate.c	2008-10-12 09:38:24.000000000 +0200
@@ -2140,7 +2140,7 @@
     }
 }
 
-/* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
+/* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
    OR_TMP0 */
 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
 {
@@ -2770,6 +2770,9 @@
     [0xc2] = SSE_FOP(cmpeq),
     [0xc6] = { helper_shufps, helper_shufpd },
 
+    [0x38] = { SSE_SPECIAL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* SSSE3/SSE4 */
+    [0x3a] = { SSE_SPECIAL, SSE_SPECIAL }, /* SSSE3/SSE4 */
+
     /* MMX ops and their SSE extensions */
     [0x60] = MMX_OP2(punpcklbw),
     [0x61] = MMX_OP2(punpcklwd),
@@ -2921,6 +2924,87 @@
     [0xbf] = helper_pavgb_mmx /* pavgusb */
 };
 
+struct sse_op_helper_s {
+    void *op[2]; uint32_t ext_mask;
+};
+#define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 }
+#define SSE41_OP(x) { { NULL, helper_ ## x ## _xmm }, CPUID_EXT_SSE41 }
+#define SSE42_OP(x) { { NULL, helper_ ## x ## _xmm }, CPUID_EXT_SSE42 }
+#define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 }
+static struct sse_op_helper_s sse_op_table6[256] = {
+    [0x00] = SSSE3_OP(pshufb),
+    [0x01] = SSSE3_OP(phaddw),
+    [0x02] = SSSE3_OP(phaddd),
+    [0x03] = SSSE3_OP(phaddsw),
+    [0x04] = SSSE3_OP(pmaddubsw),
+    [0x05] = SSSE3_OP(phsubw),
+    [0x06] = SSSE3_OP(phsubd),
+    [0x07] = SSSE3_OP(phsubsw),
+    [0x08] = SSSE3_OP(psignb),
+    [0x09] = SSSE3_OP(psignw),
+    [0x0a] = SSSE3_OP(psignd),
+    [0x0b] = SSSE3_OP(pmulhrsw),
+    [0x10] = SSE41_OP(pblendvb),
+    [0x14] = SSE41_OP(blendvps),
+    [0x15] = SSE41_OP(blendvpd),
+    [0x17] = SSE41_OP(ptest),
+    [0x1c] = SSSE3_OP(pabsb),
+    [0x1d] = SSSE3_OP(pabsw),
+    [0x1e] = SSSE3_OP(pabsd),
+    [0x20] = SSE41_OP(pmovsxbw),
+    [0x21] = SSE41_OP(pmovsxbd),
+    [0x22] = SSE41_OP(pmovsxbq),
+    [0x23] = SSE41_OP(pmovsxwd),
+    [0x24] = SSE41_OP(pmovsxwq),
+    [0x25] = SSE41_OP(pmovsxdq),
+    [0x28] = SSE41_OP(pmuldq),
+    [0x29] = SSE41_OP(pcmpeqq),
+    [0x2a] = SSE41_SPECIAL, /* movntqda */
+    [0x2b] = SSE41_OP(packusdw),
+    [0x30] = SSE41_OP(pmovzxbw),
+    [0x31] = SSE41_OP(pmovzxbd),
+    [0x32] = SSE41_OP(pmovzxbq),
+    [0x33] = SSE41_OP(pmovzxwd),
+    [0x34] = SSE41_OP(pmovzxwq),
+    [0x35] = SSE41_OP(pmovzxdq),
+    [0x37] = SSE42_OP(pcmpgtq),
+    [0x38] = SSE41_OP(pminsb),
+    [0x39] = SSE41_OP(pminsd),
+    [0x3a] = SSE41_OP(pminuw),
+    [0x3b] = SSE41_OP(pminud),
+    [0x3c] = SSE41_OP(pmaxsb),
+    [0x3d] = SSE41_OP(pmaxsd),
+    [0x3e] = SSE41_OP(pmaxuw),
+    [0x3f] = SSE41_OP(pmaxud),
+    [0x40] = SSE41_OP(pmulld),
+    [0x41] = SSE41_OP(phminposuw),
+};
+
+static struct sse_op_helper_s sse_op_table7[256] = {
+    [0x08] = SSE41_OP(roundps),
+    [0x09] = SSE41_OP(roundpd),
+    [0x0a] = SSE41_OP(roundss),
+    [0x0b] = SSE41_OP(roundsd),
+    [0x0c] = SSE41_OP(blendps),
+    [0x0d] = SSE41_OP(blendpd),
+    [0x0e] = SSE41_OP(pblendw),
+    [0x0f] = SSSE3_OP(palignr),
+    [0x14] = SSE41_SPECIAL, /* pextrb */
+    [0x15] = SSE41_SPECIAL, /* pextrw */
+    [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */
+    [0x17] = SSE41_SPECIAL, /* extractps */
+    [0x20] = SSE41_SPECIAL, /* pinsrb */
+    [0x21] = SSE41_SPECIAL, /* insertps */
+    [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */
+    [0x40] = SSE41_OP(dpps),
+    [0x41] = SSE41_OP(dppd),
+    [0x42] = SSE41_OP(mpsadbw),
+    [0x60] = SSE42_OP(pcmpestrm),
+    [0x61] = SSE42_OP(pcmpestri),
+    [0x62] = SSE42_OP(pcmpistrm),
+    [0x63] = SSE42_OP(pcmpistri),
+};
+
 static void gen_sse(DisasContext *s, int b, target_ulong pc_start, int rex_r)
 {
     int b1, op1_offset, op2_offset, is_xmm, val, ot;
@@ -2960,7 +3044,8 @@
         return;
     }
     if (is_xmm && !(s->flags & HF_OSFXSR_MASK))
-        goto illegal_op;
+        if ((b != 0x38 && b != 0x3a) || (s->prefix & PREFIX_DATA))
+            goto illegal_op;
     if (b == 0x0e) {
         if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW))
             goto illegal_op;
@@ -3426,6 +3511,7 @@
         case 0x1c5:
             if (mod != 3)
                 goto illegal_op;
+            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
             val = ldub_code(s->pc++);
             if (b1) {
                 val &= 7;
@@ -3439,7 +3525,7 @@
                                 offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
             }
             reg = ((modrm >> 3) & 7) | rex_r;
-            gen_op_mov_reg_T0(OT_LONG, reg);
+            gen_op_mov_reg_T0(ot, reg);
             break;
         case 0x1d6: /* movq ea, xmm */
             if (mod != 3) {
@@ -3482,6 +3568,271 @@
             reg = ((modrm >> 3) & 7) | rex_r;
             gen_op_mov_reg_T0(OT_LONG, reg);
             break;
+        case 0x138:
+            if (s->prefix & PREFIX_REPNZ)
+                goto crc32;
+        case 0x038:
+            b = modrm;
+            modrm = ldub_code(s->pc++);
+            rm = modrm & 7;
+            reg = ((modrm >> 3) & 7) | rex_r;
+            mod = (modrm >> 6) & 3;
+
+            sse_op2 = sse_op_table6[b].op[b1];
+            if (!sse_op2)
+                goto illegal_op;
+            if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask))
+                goto illegal_op;
+
+            if (b1) {
+                op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
+                if (mod == 3) {
+                    op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
+                } else {
+                    op2_offset = offsetof(CPUX86State,xmm_t0);
+                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
+                    switch (b) {
+                    case 0x20: case 0x30: /* pmovsxbw, pmovzxbw */
+                    case 0x23: case 0x33: /* pmovsxwd, pmovzxwd */
+                    case 0x25: case 0x35: /* pmovsxdq, pmovzxdq */
+                        gen_ldq_env_A0(s->mem_index, op2_offset +
+                                        offsetof(XMMReg, XMM_Q(0)));
+                        break;
+                    case 0x21: case 0x31: /* pmovsxbd, pmovzxbd */
+                    case 0x24: case 0x34: /* pmovsxwq, pmovzxwq */
+                        tcg_gen_qemu_ld32u(cpu_tmp2_i32, cpu_A0,
+                                          (s->mem_index >> 2) - 1);
+                        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env, op2_offset +
+                                        offsetof(XMMReg, XMM_L(0)));
+                        break;
+                    case 0x22: case 0x32: /* pmovsxbq, pmovzxbq */
+                        tcg_gen_qemu_ld16u(cpu_tmp0, cpu_A0,
+                                          (s->mem_index >> 2) - 1);
+                        tcg_gen_st16_tl(cpu_tmp0, cpu_env, op2_offset +
+                                        offsetof(XMMReg, XMM_W(0)));
+                        break;
+                    case 0x2a:            /* movntqda */
+                        gen_ldo_env_A0(s->mem_index, op1_offset);
+                        return;
+                    default:
+                        gen_ldo_env_A0(s->mem_index, op2_offset);
+                    }
+                }
+            } else {
+                op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
+                if (mod == 3) {
+                    op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
+                } else {
+                    op2_offset = offsetof(CPUX86State,mmx_t0);
+                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
+                    gen_ldq_env_A0(s->mem_index, op2_offset);
+                }
+            }
+            if (sse_op2 == SSE_SPECIAL)
+                goto illegal_op;
+
+            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
+            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
+            tcg_gen_helper_0_2(sse_op2, cpu_ptr0, cpu_ptr1);
+
+            if (b == 0x17)
+                s->cc_op = CC_OP_EFLAGS;
+            break;
+        case 0x338: /* crc32 */
+        crc32:
+            b = modrm;
+            modrm = ldub_code(s->pc++);
+            reg = ((modrm >> 3) & 7) | rex_r;
+
+            if (b != 0xf0 && b != 0xf1)
+                goto illegal_op;
+            if (!(s->cpuid_ext_features & CPUID_EXT_SSE42))
+                goto illegal_op;
+
+            if (b == 0xf0)
+                ot = OT_BYTE;
+            else if (b == 0xf1 && s->dflag != 2)
+                if (s->prefix & PREFIX_DATA)
+                    ot = OT_WORD;
+                else
+                    ot = OT_LONG;
+            else
+                ot = OT_QUAD;
+
+            gen_op_mov_TN_reg(OT_LONG, 0, reg);
+            tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
+            gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+            tcg_gen_helper_1_3(helper_crc32, cpu_T[0], cpu_tmp2_i32,
+                            cpu_T[0], tcg_const_i32(8 << ot));
+
+            ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
+            gen_op_mov_reg_T0(ot, reg);
+            break;
+        case 0x03a:
+        case 0x13a:
+            b = modrm;
+            modrm = ldub_code(s->pc++);
+            rm = modrm & 7;
+            reg = ((modrm >> 3) & 7) | rex_r;
+            mod = (modrm >> 6) & 3;
+
+            sse_op2 = sse_op_table7[b].op[b1];
+            if (!sse_op2)
+                goto illegal_op;
+            if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
+                goto illegal_op;
+
+            if (sse_op2 == SSE_SPECIAL) {
+                ot = (s->dflag == 2) ? OT_QUAD : OT_LONG;
+                rm = (modrm & 7) | REX_B(s);
+                if (mod != 3)
+                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
+                reg = ((modrm >> 3) & 7) | rex_r;
+                val = ldub_code(s->pc++);
+                switch (b) {
+                case 0x14: /* pextrb */
+                    tcg_gen_ld8u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
+                                            xmm_regs[reg].XMM_B(val & 15)));
+                    if (mod == 3)
+                        gen_op_mov_reg_T0(ot, rm);
+                    else
+                        tcg_gen_qemu_st8(cpu_T[0], cpu_A0,
+                                        (s->mem_index >> 2) - 1);
+                    break;
+                case 0x15: /* pextrw */
+                    tcg_gen_ld16u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
+                                            xmm_regs[reg].XMM_W(val & 7)));
+                    if (mod == 3)
+                        gen_op_mov_reg_T0(ot, rm);
+                    else
+                        tcg_gen_qemu_st16(cpu_T[0], cpu_A0,
+                                        (s->mem_index >> 2) - 1);
+                    break;
+                case 0x16:
+                    if (ot == OT_LONG) { /* pextrd */
+                        tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
+                                        offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_L(val & 3)));
+                        if (mod == 3)
+                            gen_op_mov_reg_v(ot, rm, cpu_tmp2_i32);
+                        else
+                            tcg_gen_qemu_st32(cpu_tmp2_i32, cpu_A0,
+                                            (s->mem_index >> 2) - 1);
+                    } else { /* pextrq */
+                        tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env,
+                                        offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_Q(val & 1)));
+                        if (mod == 3)
+                            gen_op_mov_reg_v(ot, rm, cpu_tmp1_i64);
+                        else
+                            tcg_gen_qemu_st64(cpu_tmp1_i64, cpu_A0,
+                                            (s->mem_index >> 2) - 1);
+                    }
+                    break;
+                case 0x17: /* extractps */
+                    tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
+                                            xmm_regs[reg].XMM_L(val & 3)));
+                    if (mod == 3)
+                        gen_op_mov_reg_T0(ot, rm);
+                    else
+                        tcg_gen_qemu_st32(cpu_T[0], cpu_A0,
+                                        (s->mem_index >> 2) - 1);
+                    break;
+                case 0x20: /* pinsrb */
+                    if (mod == 3)
+                        gen_op_mov_TN_reg(OT_LONG, 0, rm);
+                    else
+                        tcg_gen_qemu_ld8u(cpu_T[0], cpu_A0,
+                                        (s->mem_index >> 2) - 1);
+                    tcg_gen_st8_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
+                                            xmm_regs[reg].XMM_B(val & 15)));
+                    break;
+                case 0x21: /* insertps */
+                    if (mod == 3)
+                        tcg_gen_ld_i32(cpu_tmp2_i32, cpu_env,
+                                        offsetof(CPUX86State,xmm_regs[rm]
+                                                .XMM_L((val >> 6) & 3)));
+                    else
+                        tcg_gen_qemu_ld32u(cpu_tmp2_i32, cpu_A0,
+                                        (s->mem_index >> 2) - 1);
+                    tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
+                                    offsetof(CPUX86State,xmm_regs[reg]
+                                            .XMM_L((val >> 4) & 3)));
+                    if ((val >> 0) & 1)
+                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
+                                        cpu_env, offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_L(0)));
+                    if ((val >> 1) & 1)
+                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
+                                        cpu_env, offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_L(1)));
+                    if ((val >> 2) & 1)
+                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
+                                        cpu_env, offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_L(2)));
+                    if ((val >> 3) & 1)
+                        tcg_gen_st_i32(tcg_const_i32(0 /*float32_zero*/),
+                                        cpu_env, offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_L(3)));
+                    break;
+                case 0x22:
+                    if (ot == OT_LONG) { /* pinsrd */
+                        if (mod == 3)
+                            gen_op_mov_v_reg(ot, cpu_tmp2_i32, rm);
+                        else
+                            tcg_gen_qemu_ld32u(cpu_tmp2_i32, cpu_A0,
+                                            (s->mem_index >> 2) - 1);
+                        tcg_gen_st_i32(cpu_tmp2_i32, cpu_env,
+                                        offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_L(val & 3)));
+                    } else { /* pinsrq */
+                        if (mod == 3)
+                            gen_op_mov_v_reg(ot, cpu_tmp1_i64, rm);
+                        else
+                            tcg_gen_qemu_ld64(cpu_tmp1_i64, cpu_A0,
+                                            (s->mem_index >> 2) - 1);
+                        tcg_gen_st_i64(cpu_tmp1_i64, cpu_env,
+                                        offsetof(CPUX86State,
+                                                xmm_regs[reg].XMM_Q(val & 1)));
+                    }
+                    break;
+                }
+                return;
+            }
+
+            if (b1) {
+                op1_offset = offsetof(CPUX86State,xmm_regs[reg]);
+                if (mod == 3) {
+                    op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]);
+                } else {
+                    op2_offset = offsetof(CPUX86State,xmm_t0);
+                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
+                    gen_ldo_env_A0(s->mem_index, op2_offset);
+                }
+            } else {
+                op1_offset = offsetof(CPUX86State,fpregs[reg].mmx);
+                if (mod == 3) {
+                    op2_offset = offsetof(CPUX86State,fpregs[rm].mmx);
+                } else {
+                    op2_offset = offsetof(CPUX86State,mmx_t0);
+                    gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
+                    gen_ldq_env_A0(s->mem_index, op2_offset);
+                }
+            }
+            val = ldub_code(s->pc++);
+
+            if ((b & 0xfc) == 0x60) { /* pcmpXstrX */
+                s->cc_op = CC_OP_EFLAGS;
+
+                if (s->dflag == 2)
+                    /* The helper must use entire 64-bit gp registers */
+                    val |= 1 << 8;
+            }
+
+            tcg_gen_addi_ptr(cpu_ptr0, cpu_env, op1_offset);
+            tcg_gen_addi_ptr(cpu_ptr1, cpu_env, op2_offset);
+            tcg_gen_helper_0_3(sse_op2, cpu_ptr0, cpu_ptr1, tcg_const_i32(val));
+            break;
         default:
             goto illegal_op;
         }
@@ -6401,7 +6752,8 @@
         tcg_gen_helper_0_0(helper_rdpmc);
         break;
     case 0x134: /* sysenter */
-        if (CODE64(s))
+        /* For Intel SYSENTER is valid on 64-bit */
+        if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
             goto illegal_op;
         if (!s->pe) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
@@ -6416,7 +6768,8 @@
         }
         break;
     case 0x135: /* sysexit */
-        if (CODE64(s))
+        /* For Intel SYSEXIT is valid on 64-bit */
+        if (CODE64(s) && cpu_single_env->cpuid_vendor1 != CPUID_VENDOR_INTEL_1)
             goto illegal_op;
         if (!s->pe) {
             gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
@@ -6426,7 +6779,7 @@
                 s->cc_op = CC_OP_DYNAMIC;
             }
             gen_jmp_im(pc_start - s->cs_base);
-            tcg_gen_helper_0_0(helper_sysexit);
+            tcg_gen_helper_0_1(helper_sysexit, tcg_const_i32(dflag));
             gen_eob(s);
         }
         break;
@@ -6987,7 +7340,7 @@
             gen_eob(s);
         }
         break;
-    /* MMX/3DNow!/SSE/SSE2/SSE3 support */
+    /* MMX/3DNow!/SSE/SSE2/SSE3/SSSE3/SSE4 support */
     case 0x1c3: /* MOVNTI reg, mem */
         if (!(s->cpuid_features & CPUID_SSE2))
             goto illegal_op;
@@ -7095,11 +7448,36 @@
         tcg_gen_helper_0_0(helper_rsm);
         gen_eob(s);
         break;
+    case 0x1b8: /* SSE4.2 popcnt */
+        if ((prefixes & (PREFIX_REPZ | PREFIX_LOCK | PREFIX_REPNZ)) !=
+             PREFIX_REPZ)
+            goto illegal_op;
+        if (!(s->cpuid_ext_features & CPUID_EXT_POPCNT))
+            goto illegal_op;
+
+        modrm = ldub_code(s->pc++);
+        reg = ((modrm >> 3) & 7);
+
+        if (s->prefix & PREFIX_DATA)
+            ot = OT_WORD;
+        else if (s->dflag != 2)
+            ot = OT_LONG;
+        else
+            ot = OT_QUAD;
+
+        gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
+        tcg_gen_helper_1_2(helper_popcnt,
+                cpu_T[0], cpu_T[0], tcg_const_i32(ot));
+        gen_op_mov_reg_T0(ot, reg);
+
+        s->cc_op = CC_OP_EFLAGS;
+        break;
     case 0x10e ... 0x10f:
         /* 3DNow! instructions, ignore prefixes */
         s->prefix &= ~(PREFIX_REPZ | PREFIX_REPNZ | PREFIX_DATA);
     case 0x110 ... 0x117:
     case 0x128 ... 0x12f:
+    case 0x138 ... 0x13a:
     case 0x150 ... 0x177:
     case 0x17c ... 0x17f:
     case 0x1c2:
diff -Nur kvm-76/qemu/target-ia64/cpu.h kvm-userspace/qemu/target-ia64/cpu.h
--- kvm-76/qemu/target-ia64/cpu.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-ia64/cpu.h	2008-10-12 09:38:24.000000000 +0200
@@ -26,7 +26,6 @@
 #include "ia64intrin.h"
 
 #include<string.h>
-#include<stdio.h>
 
 #define TARGET_LONG_BITS 64
 
@@ -52,12 +51,9 @@
 #define cpu_init cpu_ia64_init
 #define cpu_signal_handler cpu_ia64_signal_handler
 
-struct CPUIA64State *env;
+extern struct CPUIA64State *env;
 int cpu_get_pic_interrupt(CPUIA64State *s);
 int cpu_exec(CPUState *env1);
-void cpu_dump_state(CPUState *env, FILE *f,
-                    int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
-                    int flags);
 CPUState *cpu_ia64_init(const char * cpu_model);
 
 static inline int cpu_mmu_index (CPUState *env)
diff -Nur kvm-76/qemu/target-ia64/exec.h kvm-userspace/qemu/target-ia64/exec.h
--- kvm-76/qemu/target-ia64/exec.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-ia64/exec.h	2008-10-12 09:38:24.000000000 +0200
@@ -18,13 +18,21 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#ifndef __IA64_H__
+#define __IA64_H__
+
 //#include "dyngen-exec.h"
+#include "config.h"
+
+#include "dyngen-exec.h"
 
 #include "cpu.h"
 #include "exec-all.h"
 
 #define tcg_qemu_tb_exec(tb_ptr) 0
 
+register struct CPUIA64State *env asm(AREG0);
+
 static inline void env_to_regs(void)
 {
 }
@@ -45,3 +53,5 @@
         return 0;
     return EXCP_HALTED;
 }
+
+#endif
diff -Nur kvm-76/qemu/target-ia64/fake-exec.c kvm-userspace/qemu/target-ia64/fake-exec.c
--- kvm-76/qemu/target-ia64/fake-exec.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-ia64/fake-exec.c	2008-10-12 09:38:24.000000000 +0200
@@ -14,6 +14,8 @@
  * This work is licensed under the GNU GPL licence version 2 or later.
  *
  */
+#include <stdio.h>
+
 #include "cpu.h"
 #include "exec-all.h"
 
diff -Nur kvm-76/qemu/target-ia64/firmware.c kvm-userspace/qemu/target-ia64/firmware.c
--- kvm-76/qemu/target-ia64/firmware.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-ia64/firmware.c	2008-10-12 09:38:24.000000000 +0200
@@ -21,6 +21,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <zlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
diff -Nur kvm-76/qemu/target-ppc/op.c kvm-userspace/qemu/target-ppc/op.c
--- kvm-76/qemu/target-ppc/op.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-ppc/op.c	2008-10-12 09:38:24.000000000 +0200
@@ -640,8 +640,6 @@
     T0 += xer_ca + (-1);
     if (likely((uint32_t)T1 != 0))
         xer_ca = 1;
-    else
-        xer_ca = 0;
     RETURN();
 }
 
@@ -651,8 +649,6 @@
     T0 += xer_ca + (-1);
     if (likely((uint64_t)T1 != 0))
         xer_ca = 1;
-    else
-        xer_ca = 0;
     RETURN();
 }
 #endif
@@ -798,7 +794,11 @@
 /* multiply low word */
 void OPPROTO op_mullw (void)
 {
+#if defined(TARGET_PPC64)
+    T0 = (int64_t)(int32_t)T0 * (int64_t)(int32_t)T1;
+#else
     T0 = (int32_t)(T0 * T1);
+#endif
     RETURN();
 }
 
@@ -926,8 +926,6 @@
     T0 = ~T0 + xer_ca - 1;
     if (likely((uint32_t)T0 != UINT32_MAX))
         xer_ca = 1;
-    else
-        xer_ca = 0;
     RETURN();
 }
 
@@ -937,8 +935,6 @@
     T0 = ~T0 + xer_ca - 1;
     if (likely((uint64_t)T0 != UINT64_MAX))
         xer_ca = 1;
-    else
-        xer_ca = 0;
     RETURN();
 }
 #endif
diff -Nur kvm-76/qemu/target-ppc/op_helper.c kvm-userspace/qemu/target-ppc/op_helper.c
--- kvm-76/qemu/target-ppc/op_helper.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-ppc/op_helper.c	2008-10-12 09:38:24.000000000 +0200
@@ -151,10 +151,8 @@
     T0 += xer_ca + (-1);
     xer_ov = ((uint32_t)T1 & ((uint32_t)T1 ^ (uint32_t)T0)) >> 31;
     xer_so |= xer_ov;
-    if (likely(T1 != 0))
+    if (likely((uint32_t)T1 != 0))
         xer_ca = 1;
-    else
-        xer_ca = 0;
 }
 
 #if defined(TARGET_PPC64)
@@ -164,10 +162,8 @@
     T0 += xer_ca + (-1);
     xer_ov = ((uint64_t)T1 & ((uint64_t)T1 ^ (uint64_t)T0)) >> 63;
     xer_so |= xer_ov;
-    if (likely(T1 != 0))
+    if (likely((uint64_t)T1 != 0))
         xer_ca = 1;
-    else
-        xer_ca = 0;
 }
 #endif
 
@@ -227,7 +223,7 @@
 
 void do_mullwo (void)
 {
-    int64_t res = (int64_t)T0 * (int64_t)T1;
+    int64_t res = (int64_t)(int32_t)T0 * (int64_t)(int32_t)T1;
 
     if (likely((int32_t)res == res)) {
         xer_ov = 0;
@@ -312,8 +308,6 @@
     xer_so |= xer_ov;
     if (likely((uint32_t)T1 != UINT32_MAX))
         xer_ca = 1;
-    else
-        xer_ca = 0;
 }
 
 #if defined(TARGET_PPC64)
@@ -325,8 +319,6 @@
     xer_so |= xer_ov;
     if (likely((uint64_t)T1 != UINT64_MAX))
         xer_ca = 1;
-    else
-        xer_ca = 0;
 }
 #endif
 
diff -Nur kvm-76/qemu/target-ppc/translate.c kvm-userspace/qemu/target-ppc/translate.c
--- kvm-76/qemu/target-ppc/translate.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-ppc/translate.c	2008-10-12 09:38:24.000000000 +0200
@@ -3048,10 +3048,6 @@
 #endif
             gen_op_btest_T1(ctx->nip);
     no_test:
-        if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
-            gen_update_nip(ctx, ctx->nip);
-            gen_op_debug();
-        }
         tcg_gen_exit_tb(0);
     }
 }
diff -Nur kvm-76/qemu/target-sparc/cpu.h kvm-userspace/qemu/target-sparc/cpu.h
--- kvm-76/qemu/target-sparc/cpu.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-sparc/cpu.h	2008-10-12 09:38:24.000000000 +0200
@@ -340,6 +340,12 @@
 void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
 void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt,
                                                  ...));
+void cpu_lock(void);
+void cpu_unlock(void);
+int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
+                               int mmu_idx, int is_softmmu);
+target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
+void dump_mmu(CPUSPARCState *env);
 
 /* translate.c */
 void gen_intermediate_code_init(CPUSPARCState *env);
@@ -492,4 +498,14 @@
 
 #include "cpu-all.h"
 
+/* sum4m.c, sun4u.c */
+void cpu_check_irqs(CPUSPARCState *env);
+
+#ifdef TARGET_SPARC64
+/* sun4u.c */
+void cpu_tick_set_count(void *opaque, uint64_t count);
+uint64_t cpu_tick_get_count(void *opaque);
+void cpu_tick_set_limit(void *opaque, uint64_t limit);
+#endif
+
 #endif
diff -Nur kvm-76/qemu/target-sparc/exec.h kvm-userspace/qemu/target-sparc/exec.h
--- kvm-76/qemu/target-sparc/exec.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-sparc/exec.h	2008-10-12 09:38:24.000000000 +0200
@@ -21,23 +21,12 @@
 {
 }
 
-/* helper.c */
-void cpu_lock(void);
-void cpu_unlock(void);
-int cpu_sparc_handle_mmu_fault(CPUState *env1, target_ulong address, int rw,
-                               int mmu_idx, int is_softmmu);
-target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev);
-void dump_mmu(CPUState *env);
-
 /* op_helper.c */
 void do_interrupt(CPUState *env);
 
 /* cpu-exec.c */
 void cpu_loop_exit(void);
 
-/* sun4m.c */
-void cpu_check_irqs(CPUSPARCState *env);
-
 static inline int cpu_halted(CPUState *env1) {
     if (!env1->halted)
         return 0;
diff -Nur kvm-76/qemu/target-sparc/helper.c kvm-userspace/qemu/target-sparc/helper.c
--- kvm-76/qemu/target-sparc/helper.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-sparc/helper.c	2008-10-12 09:38:24.000000000 +0200
@@ -31,7 +31,6 @@
 
 //#define DEBUG_MMU
 //#define DEBUG_FEATURES
-//#define DEBUG_PCALL
 
 static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
 
@@ -659,13 +658,12 @@
 #ifdef TARGET_SPARC64
     env->pstate = PS_PRIV;
     env->hpstate = HS_PRIV;
-    env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset
     env->tsptr = &env->ts[env->tl & MAXTL_MASK];
 #else
-    env->pc = 0;
     env->mmuregs[0] &= ~(MMU_E | MMU_NF);
     env->mmuregs[0] |= env->def->mmu_bm;
 #endif
+    env->pc = 0;
     env->npc = env->pc + 4;
 #endif
 }
@@ -1414,34 +1412,3 @@
 #endif
     cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
 }
-
-#ifdef TARGET_SPARC64
-#if !defined(CONFIG_USER_ONLY)
-#include "qemu-common.h"
-#include "hw/irq.h"
-#include "qemu-timer.h"
-#endif
-
-void helper_tick_set_count(void *opaque, uint64_t count)
-{
-#if !defined(CONFIG_USER_ONLY)
-    ptimer_set_count(opaque, -count);
-#endif
-}
-
-uint64_t helper_tick_get_count(void *opaque)
-{
-#if !defined(CONFIG_USER_ONLY)
-    return -ptimer_get_count(opaque);
-#else
-    return 0;
-#endif
-}
-
-void helper_tick_set_limit(void *opaque, uint64_t limit)
-{
-#if !defined(CONFIG_USER_ONLY)
-    ptimer_set_limit(opaque, -limit, 0);
-#endif
-}
-#endif
diff -Nur kvm-76/qemu/target-sparc/helper.h kvm-userspace/qemu/target-sparc/helper.h
--- kvm-76/qemu/target-sparc/helper.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-sparc/helper.h	2008-10-12 09:38:24.000000000 +0200
@@ -38,8 +38,6 @@
 DEF_HELPER(uint64_t, helper_tick_get_count, (void *opaque))
 DEF_HELPER(void, helper_tick_set_limit, (void *opaque, uint64_t limit))
 #endif
-DEF_HELPER(void, helper_trap, (target_ulong nb_trap))
-DEF_HELPER(void, helper_trapcc, (target_ulong nb_trap, target_ulong do_trap))
 DEF_HELPER(void, helper_check_align, (target_ulong addr, uint32_t align))
 DEF_HELPER(void, helper_debug, (void))
 DEF_HELPER(void, helper_save, (void))
diff -Nur kvm-76/qemu/target-sparc/machine.c kvm-userspace/qemu/target-sparc/machine.c
--- kvm-76/qemu/target-sparc/machine.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-sparc/machine.c	2008-10-12 09:38:24.000000000 +0200
@@ -9,6 +9,7 @@
 #ifdef TARGET_SPARC64
     qemu_register_machine(&sun4u_machine);
     qemu_register_machine(&sun4v_machine);
+    qemu_register_machine(&niagara_machine);
 #else
     qemu_register_machine(&ss5_machine);
     qemu_register_machine(&ss10_machine);
diff -Nur kvm-76/qemu/target-sparc/op_helper.c kvm-userspace/qemu/target-sparc/op_helper.c
--- kvm-76/qemu/target-sparc/op_helper.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-sparc/op_helper.c	2008-10-12 09:38:24.000000000 +0200
@@ -10,6 +10,7 @@
 //#define DEBUG_UNALIGNED
 //#define DEBUG_UNASSIGNED
 //#define DEBUG_ASI
+//#define DEBUG_PCALL
 
 #ifdef DEBUG_MMU
 #define DPRINTF_MMU(fmt, args...) \
@@ -54,20 +55,6 @@
     cpu_loop_exit();
 }
 
-void helper_trap(target_ulong nb_trap)
-{
-    env->exception_index = TT_TRAP + (nb_trap & 0x7f);
-    cpu_loop_exit();
-}
-
-void helper_trapcc(target_ulong nb_trap, target_ulong do_trap)
-{
-    if (do_trap) {
-        env->exception_index = TT_TRAP + (nb_trap & 0x7f);
-        cpu_loop_exit();
-    }
-}
-
 static inline void set_cwp(int new_cwp)
 {
     cpu_set_cwp(env, new_cwp);
@@ -824,7 +811,7 @@
             break;
         }
         DPRINTF_MXCC("asi = %d, size = %d, sign = %d, "
-                     "addr = %08x -> ret = %08x,"
+                     "addr = %08x -> ret = %" PRIx64 ","
                      "addr = %08x\n", asi, size, sign, last_addr, ret, addr);
 #ifdef DEBUG_MXCC
         dump_mxcc(env);
@@ -1087,8 +1074,8 @@
                          size);
             break;
         }
-        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi,
-                     size, addr, val);
+        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %" PRIx64 "\n",
+                     asi, size, addr, val);
 #ifdef DEBUG_MXCC
         dump_mxcc(env);
 #endif
@@ -1512,6 +1499,8 @@
     case 0x18: // As if user primary LE
     case 0x80: // Primary
     case 0x88: // Primary LE
+    case 0xe2: // UA2007 Primary block init
+    case 0xe3: // UA2007 Secondary block init
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if ((env->def->features & CPU_FEATURE_HYPV)
                 && env->hpstate & HS_PRIV) {
@@ -1784,6 +1773,8 @@
     case 0x18: // As if user primary LE
     case 0x80: // Primary
     case 0x88: // Primary LE
+    case 0xe2: // UA2007 Primary block init
+    case 0xe3: // UA2007 Secondary block init
         if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
             if ((env->def->features & CPU_FEATURE_HYPV)
                 && env->hpstate & HS_PRIV) {
@@ -1950,6 +1941,8 @@
         }
     case 0x55: // I-MMU data access
         {
+            // TODO: auto demap
+
             unsigned int i = (addr >> 3) & 0x3f;
 
             env->itlb_tag[i] = env->immuregs[6];
@@ -1957,7 +1950,22 @@
             return;
         }
     case 0x57: // I-MMU demap
-        // XXX
+        {
+            unsigned int i;
+
+            for (i = 0; i < 64; i++) {
+                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) {
+                    target_ulong mask = 0xffffffffffffe000ULL;
+
+                    mask <<= 3 * ((env->itlb_tte[i] >> 61) & 3);
+                    if ((val & mask) == (env->itlb_tag[i] & mask)) {
+                        env->itlb_tag[i] = 0;
+                        env->itlb_tte[i] = 0;
+                    }
+                    return;
+                }
+            }
+        }
         return;
     case 0x58: // D-MMU regs
         {
@@ -2027,6 +2035,23 @@
             return;
         }
     case 0x5f: // D-MMU demap
+        {
+            unsigned int i;
+
+            for (i = 0; i < 64; i++) {
+                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) {
+                    target_ulong mask = 0xffffffffffffe000ULL;
+
+                    mask <<= 3 * ((env->dtlb_tte[i] >> 61) & 3);
+                    if ((val & mask) == (env->dtlb_tag[i] & mask)) {
+                        env->dtlb_tag[i] = 0;
+                        env->dtlb_tte[i] = 0;
+                    }
+                    return;
+                }
+            }
+        }
+        return;
     case 0x49: // Interrupt data receive
         // XXX
         return;
@@ -2159,6 +2184,8 @@
 
     helper_check_align(addr, 3);
     switch (asi) {
+    case 0xe0: // UA2007 Block commit store primary (cache flush)
+    case 0xe1: // UA2007 Block commit store secondary (cache flush)
     case 0xf0: // Block store primary
     case 0xf1: // Block store secondary
     case 0xf8: // Block store primary LE
@@ -3059,3 +3086,27 @@
 }
 #endif
 
+#ifdef TARGET_SPARC64
+void helper_tick_set_count(void *opaque, uint64_t count)
+{
+#if !defined(CONFIG_USER_ONLY)
+    cpu_tick_set_count(opaque, count);
+#endif
+}
+
+uint64_t helper_tick_get_count(void *opaque)
+{
+#if !defined(CONFIG_USER_ONLY)
+    return cpu_tick_get_count(opaque);
+#else
+    return 0;
+#endif
+}
+
+void helper_tick_set_limit(void *opaque, uint64_t limit)
+{
+#if !defined(CONFIG_USER_ONLY)
+    cpu_tick_set_limit(opaque, limit);
+#endif
+}
+#endif
diff -Nur kvm-76/qemu/target-sparc/translate.c kvm-userspace/qemu/target-sparc/translate.c
--- kvm-76/qemu/target-sparc/translate.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/target-sparc/translate.c	2008-10-12 09:38:24.000000000 +0200
@@ -93,6 +93,9 @@
 #define QFPREG(r) (r & 0x1c)
 #endif
 
+#define UA2005_HTRAP_MASK 0xff
+#define V8_TRAP_MASK 0x7f
+
 static int sign_extend(int x, int len)
 {
     len = 32 - len;
@@ -2019,9 +2022,16 @@
                 cond = GET_FIELD(insn, 3, 6);
                 if (cond == 0x8) {
                     save_state(dc, cpu_cond);
-                    tcg_gen_helper_0_1(helper_trap, cpu_dst);
+                    if ((dc->def->features & CPU_FEATURE_HYPV) &&
+                        supervisor(dc))
+                        tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
+                    else
+                        tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
+                    tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
+                    tcg_gen_helper_0_1(raise_exception, cpu_dst);
                 } else if (cond != 0) {
                     TCGv r_cond = tcg_temp_new(TCG_TYPE_TL);
+                    int l1;
 #ifdef TARGET_SPARC64
                     /* V9 icc/xcc */
                     int cc = GET_FIELD_SP(insn, 11, 12);
@@ -2037,7 +2047,18 @@
                     save_state(dc, cpu_cond);
                     gen_cond(r_cond, 0, cond);
 #endif
-                    tcg_gen_helper_0_2(helper_trapcc, cpu_dst, r_cond);
+                    l1 = gen_new_label();
+                    tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, 0, l1);
+
+                    if ((dc->def->features & CPU_FEATURE_HYPV) &&
+                        supervisor(dc))
+                        tcg_gen_andi_tl(cpu_dst, cpu_dst, UA2005_HTRAP_MASK);
+                    else
+                        tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
+                    tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
+                    tcg_gen_helper_0_1(raise_exception, cpu_dst);
+
+                    gen_set_label(l1);
                     tcg_temp_free(r_cond);
                 }
                 gen_op_next_insn();
diff -Nur kvm-76/qemu/tcg/arm/tcg-target.c kvm-userspace/qemu/tcg/arm/tcg-target.c
--- kvm-76/qemu/tcg/arm/tcg-target.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/tcg/arm/tcg-target.c	2008-10-12 09:38:24.000000000 +0200
@@ -21,7 +21,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%r0",
     "%r1",
     "%r2",
@@ -38,8 +40,9 @@
     "%r13",
     "%r14",
 };
+#endif
 
-int tcg_target_reg_alloc_order[] = {
+static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R0,
     TCG_REG_R1,
     TCG_REG_R2,
@@ -57,10 +60,10 @@
     TCG_REG_R14,
 };
 
-const int tcg_target_call_iarg_regs[4] = {
+static const int tcg_target_call_iarg_regs[4] = {
     TCG_REG_R0, TCG_REG_R1, TCG_REG_R2, TCG_REG_R3
 };
-const int tcg_target_call_oarg_regs[2] = {
+static const int tcg_target_call_oarg_regs[2] = {
     TCG_REG_R0, TCG_REG_R1
 };
 
@@ -91,7 +94,7 @@
 }
 
 /* parse target specific constraints */
-int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 {
     const char *ct_str;
 
diff -Nur kvm-76/qemu/tcg/hppa/tcg-target.c kvm-userspace/qemu/tcg/hppa/tcg-target.c
--- kvm-76/qemu/tcg/hppa/tcg-target.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/tcg/hppa/tcg-target.c	2008-10-12 09:38:24.000000000 +0200
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 
+#ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%r0",
     "%r1",
@@ -56,6 +57,7 @@
     "%sp",
     "%r31",
 };
+#endif
 
 static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R4,
@@ -106,7 +108,7 @@
 }
 
 /* parse target specific constraints */
-int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 {
     const char *ct_str;
 
diff -Nur kvm-76/qemu/tcg/i386/tcg-target.c kvm-userspace/qemu/tcg/i386/tcg-target.c
--- kvm-76/qemu/tcg/i386/tcg-target.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/tcg/i386/tcg-target.c	2008-10-12 09:38:24.000000000 +0200
@@ -21,7 +21,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%eax",
     "%ecx",
     "%edx",
@@ -31,8 +33,9 @@
     "%esi",
     "%edi",
 };
+#endif
 
-int tcg_target_reg_alloc_order[] = {
+static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_EAX,
     TCG_REG_EDX,
     TCG_REG_ECX,
@@ -42,8 +45,8 @@
     TCG_REG_EBP,
 };
 
-const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
-const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
+static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
+static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
 
 static uint8_t *tb_ret_addr;
 
@@ -80,7 +83,7 @@
 }
 
 /* parse target specific constraints */
-int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
+static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
 {
     const char *ct_str;
 
diff -Nur kvm-76/qemu/tcg/ppc/tcg-target.c kvm-userspace/qemu/tcg/ppc/tcg-target.c
--- kvm-76/qemu/tcg/ppc/tcg-target.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/tcg/ppc/tcg-target.c	2008-10-12 09:38:24.000000000 +0200
@@ -39,6 +39,7 @@
 #define ADDEND_OFFSET 4
 #endif
 
+#ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "r0",
     "r1",
@@ -73,6 +74,7 @@
     "r30",
     "r31"
 };
+#endif
 
 static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R14,
diff -Nur kvm-76/qemu/tcg/ppc64/tcg-target.c kvm-userspace/qemu/tcg/ppc64/tcg-target.c
--- kvm-76/qemu/tcg/ppc64/tcg-target.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/tcg/ppc64/tcg-target.c	2008-10-12 09:38:24.000000000 +0200
@@ -42,6 +42,7 @@
 #define CMP_L (1<<21)
 #endif
 
+#ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "r0",
     "r1",
@@ -76,6 +77,7 @@
     "r30",
     "r31"
 };
+#endif
 
 static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_R14,
@@ -303,6 +305,7 @@
 
 #define RLDICL XO30(  0)
 #define RLDICR XO30(  1)
+#define RLDIMI XO30(  3)
 
 #define BCLR   XO19( 16)
 #define BCCTR  XO19(528)
@@ -691,11 +694,10 @@
         break;
     case 3:
         if (bswap) {
-            tcg_out32 (s, LWBRX | RT (0) | RB (r0));
-            tcg_out32 (s, ADDI | RT (r1) | RA (r0) | 4);
-            tcg_out32 (s, LWBRX | RT (data_reg) | RB (r1));
-            tcg_out_rld (s, RLDICR, data_reg, data_reg, 32, 31);
-            tcg_out32 (s, OR | SAB (0, data_reg, data_reg));
+            tcg_out_movi32 (s, 0, 4);
+            tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
+            tcg_out32 (s, LWBRX | RT (      r1) | RA (r0));
+            tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
         }
         else tcg_out32 (s, LD | RT (data_reg) | RA (r0));
         break;
diff -Nur kvm-76/qemu/tcg/sparc/tcg-target.c kvm-userspace/qemu/tcg/sparc/tcg-target.c
--- kvm-76/qemu/tcg/sparc/tcg-target.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/tcg/sparc/tcg-target.c	2008-10-12 09:38:24.000000000 +0200
@@ -22,6 +22,7 @@
  * THE SOFTWARE.
  */
 
+#ifndef NDEBUG
 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%g0",
     "%g1",
@@ -56,6 +57,7 @@
     "%i6",
     "%i7",
 };
+#endif
 
 static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_L0,
diff -Nur kvm-76/qemu/tcg/x86_64/tcg-target.c kvm-userspace/qemu/tcg/x86_64/tcg-target.c
--- kvm-76/qemu/tcg/x86_64/tcg-target.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/tcg/x86_64/tcg-target.c	2008-10-12 09:38:24.000000000 +0200
@@ -21,7 +21,9 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-const char *tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
+
+#ifndef NDEBUG
+static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
     "%rax",
     "%rcx",
     "%rdx",
@@ -39,8 +41,9 @@
     "%r14",
     "%r15",
 };
+#endif
 
-int tcg_target_reg_alloc_order[] = {
+static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_RDI,
     TCG_REG_RSI,
     TCG_REG_RDX,
@@ -59,7 +62,7 @@
     TCG_REG_R15,
 };
 
-const int tcg_target_call_iarg_regs[6] = { 
+static const int tcg_target_call_iarg_regs[6] = {
     TCG_REG_RDI,
     TCG_REG_RSI,
     TCG_REG_RDX,
@@ -68,7 +71,7 @@
     TCG_REG_R9,
 };
 
-const int tcg_target_call_oarg_regs[2] = { 
+static const int tcg_target_call_oarg_regs[2] = {
     TCG_REG_RAX, 
     TCG_REG_RDX 
 };
diff -Nur kvm-76/qemu/tests/test-i386-ssse3.c kvm-userspace/qemu/tests/test-i386-ssse3.c
--- kvm-76/qemu/tests/test-i386-ssse3.c	1970-01-01 01:00:00.000000000 +0100
+++ kvm-userspace/qemu/tests/test-i386-ssse3.c	2008-10-12 09:38:24.000000000 +0200
@@ -0,0 +1,57 @@
+/* See if various MMX/SSE SSSE3 instructions give expected results */
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+int main(int argc, char *argv[]) {
+	char hello[16];
+	const char ehlo[8] = "EHLO    ";
+	uint64_t mask = 0x8080800302020001;
+
+	uint64_t a = 0x0000000000090007;
+	uint64_t b = 0x0000000000000000;
+	uint32_t c;
+	uint16_t d;
+
+	const char e[16] = "LLOaaaaaaaaaaaaa";
+	const char f[16] = "aaaaaaaaaaaaaaHE";
+
+	/* pshufb mm1/xmm1, mm2/xmm2 */
+	asm volatile ("movq    (%0), %%mm0" : : "r" (ehlo) : "mm0", "mm1");
+	asm volatile ("movq    %0, %%mm1" : : "m" (mask));
+	asm volatile ("pshufb  %mm1, %mm0");
+	asm volatile ("movq    %%mm0, %0" : "=m" (hello));
+	printf("%s\n", hello);
+
+	/* pshufb mm1/xmm1, m64/m128 */
+	asm volatile ("movq    (%0), %%mm0" : : "r" (ehlo) : "mm0");
+	asm volatile ("pshufb  %0, %%mm0" : : "m" (mask));
+	asm volatile ("movq    %%mm0, %0" : "=m" (hello));
+	printf("%s\n", hello);
+
+	/* psubsw mm1/xmm1, m64/m128 */
+	asm volatile ("movq    %0, %%mm0" : : "r" (a) : "mm0");
+	asm volatile ("phsubsw %0, %%mm0" : : "m" (b));
+	asm volatile ("movq    %%mm0, %0" : "=m" (a));
+	printf("%i - %i = %i\n", 9, 7, -(int16_t) a);
+
+	/* palignr mm1/xmm1, m64/m128, imm8 */
+	asm volatile ("movdqa  (%0), %%xmm0" : : "r" (e) : "xmm0");
+	asm volatile ("palignr $14, (%0), %%xmm0" : : "r" (f));
+	asm volatile ("movdqa  %%xmm0, (%0)" : : "r" (hello));
+	printf("%5.5s\n", hello);
+
+#if 1 /* SSE4 */
+	/* popcnt r64, r/m64 */
+	asm volatile ("movq    $0x8421000010009c63, %%rax" : : : "rax");
+	asm volatile ("popcnt  %%ax, %%dx" : : : "dx");
+	asm volatile ("popcnt  %%eax, %%ecx" : : : "ecx");
+	asm volatile ("popcnt  %rax, %rax");
+	asm volatile ("movq    %%rax, %0" : "=m" (a));
+	asm volatile ("movl    %%ecx, %0" : "=m" (c));
+	asm volatile ("movw    %%dx, %0" : "=m" (d));
+	printf("%i = %i\n%i = %i = %i\n", 13, (int) a, 9, c, d + 1);
+#endif
+
+	return 0;
+}
diff -Nur kvm-76/qemu/thunk.c kvm-userspace/qemu/thunk.c
--- kvm-76/qemu/thunk.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/thunk.c	2008-10-12 09:38:24.000000000 +0200
@@ -113,7 +113,8 @@
     }
 }
 
-void thunk_register_struct_direct(int id, const char *name, StructEntry *se1)
+void thunk_register_struct_direct(int id, const char *name,
+                                  const StructEntry *se1)
 {
     StructEntry *se;
     se = struct_entries + id;
@@ -248,9 +249,9 @@
  * between X86 and Alpha formats...
  */
 unsigned int target_to_host_bitmask(unsigned int x86_mask,
-                                    bitmask_transtbl * trans_tbl)
+                                    const bitmask_transtbl * trans_tbl)
 {
-    bitmask_transtbl *	btp;
+    const bitmask_transtbl *btp;
     unsigned int	alpha_mask = 0;
 
     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
@@ -262,9 +263,9 @@
 }
 
 unsigned int host_to_target_bitmask(unsigned int alpha_mask,
-                                    bitmask_transtbl * trans_tbl)
+                                    const bitmask_transtbl * trans_tbl)
 {
-    bitmask_transtbl *	btp;
+    const bitmask_transtbl *btp;
     unsigned int	x86_mask = 0;
 
     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
diff -Nur kvm-76/qemu/thunk.h kvm-userspace/qemu/thunk.h
--- kvm-76/qemu/thunk.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/thunk.h	2008-10-12 09:38:24.000000000 +0200
@@ -68,7 +68,8 @@
 } bitmask_transtbl;
 
 void thunk_register_struct(int id, const char *name, const argtype *types);
-void thunk_register_struct_direct(int id, const char *name, StructEntry *se1);
+void thunk_register_struct_direct(int id, const char *name,
+                                  const StructEntry *se1);
 const argtype *thunk_convert(void *dst, const void *src,
                              const argtype *type_ptr, int to_host);
 #ifndef NO_THUNK_TYPE_SIZE
@@ -154,8 +155,8 @@
 #endif /* NO_THUNK_TYPE_SIZE */
 
 unsigned int target_to_host_bitmask(unsigned int x86_mask,
-                                    bitmask_transtbl * trans_tbl);
+                                    const bitmask_transtbl * trans_tbl);
 unsigned int host_to_target_bitmask(unsigned int alpha_mask,
-                                    bitmask_transtbl * trans_tbl);
+                                    const bitmask_transtbl * trans_tbl);
 
 #endif
diff -Nur kvm-76/qemu/vl.c kvm-userspace/qemu/vl.c
--- kvm-76/qemu/vl.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/vl.c	2008-10-12 09:38:24.000000000 +0200
@@ -29,6 +29,7 @@
 #include "hw/audiodev.h"
 #include "hw/isa.h"
 #include "hw/baum.h"
+#include "hw/bt.h"
 #include "net.h"
 #include "console.h"
 #include "sysemu.h"
@@ -73,7 +74,7 @@
 #elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
 #include <freebsd/stdlib.h>
 #else
-#ifndef __sun__
+#ifdef __linux__
 #include <linux/if.h>
 #include <linux/if_tun.h>
 #include <pty.h>
@@ -87,7 +88,8 @@
 
 #include <linux/ppdev.h>
 #include <linux/parport.h>
-#else
+#endif
+#ifdef __sun__
 #include <sys/stat.h>
 #include <sys/ethernet.h>
 #include <sys/sockio.h>
@@ -154,6 +156,8 @@
 
 //#define DEBUG_UNUSED_IOPORT
 //#define DEBUG_IOPORT
+//#define DEBUG_NET
+//#define DEBUG_SLIRP
 
 #ifdef TARGET_PPC
 #define DEFAULT_RAM_SIZE 144
@@ -169,24 +173,24 @@
 
 const char *bios_dir = CONFIG_QEMU_SHAREDIR;
 const char *bios_name = NULL;
-void *ioport_opaque[MAX_IOPORTS];
-IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
-IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
+static void *ioport_opaque[MAX_IOPORTS];
+static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
+static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
 /* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
    to store the VM snapshots */
 DriveInfo drives_table[MAX_DRIVES+1];
 int nb_drives;
 int extboot_drive = -1;
 /* point to the block driver where the snapshots are managed */
-BlockDriverState *bs_snapshots;
-int vga_ram_size;
+static BlockDriverState *bs_snapshots;
+static int vga_ram_size;
+enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 static DisplayState display_state;
 int nographic;
-int curses;
+static int curses;
 const char* keyboard_layout = NULL;
 int64_t ticks_per_sec;
 ram_addr_t ram_size;
-int pit_min_timer_count = 0;
 int nb_nics;
 NICInfo nd_table[MAX_NICS];
 int vm_running;
@@ -203,8 +207,8 @@
 int graphic_height = 600;
 int graphic_depth = 15;
 #endif
-int full_screen = 0;
-int no_frame = 0;
+static int full_screen = 0;
+static int no_frame = 0;
 int no_quit = 0;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
@@ -235,7 +239,7 @@
 const char *option_rom[MAX_OPTION_ROMS];
 int nb_option_roms;
 int semihosting_enabled = 0;
-int autostart = 1;
+int autostart;
 int time_drift_fix = 0;
 unsigned int kvm_shadow_memory = 0;
 const char *mem_path = NULL;
@@ -262,8 +266,8 @@
 #define MAX_ICOUNT_SHIFT 10
 /* Compensate for varying guest execution speed.  */
 static int64_t qemu_icount_bias;
-QEMUTimer *icount_rt_timer;
-QEMUTimer *icount_vm_timer;
+static QEMUTimer *icount_rt_timer;
+static QEMUTimer *icount_vm_timer;
 
 uint8_t qemu_uuid[16];
 
@@ -1727,7 +1731,7 @@
 
 static void init_timer_alarm(void)
 {
-    struct qemu_alarm_timer *t;
+    struct qemu_alarm_timer *t = NULL;
     int i, err = -1;
 
     for (i = 0; alarm_timers[i].name; i++) {
@@ -3907,7 +3911,7 @@
 /***********************************************************/
 /* network device redirectors */
 
-__attribute__ (( unused ))
+#if defined(DEBUG_NET) || defined(DEBUG_SLIRP)
 static void hex_dump(FILE *f, const uint8_t *buf, int size)
 {
     int len, i, j, c;
@@ -3933,6 +3937,7 @@
         fprintf(f, "\n");
     }
 }
+#endif
 
 static int parse_macaddr(uint8_t *macaddr, const char *p)
 {
@@ -4152,7 +4157,7 @@
     VLANClientState *vc;
     int ret = -EAGAIN;
 
-#if 0
+#ifdef DEBUG_NET
     printf("vlan %d send:\n", vlan->id);
     hex_dump(stdout, buf, size);
 #endif
@@ -4226,7 +4231,7 @@
 
 void slirp_output(const uint8_t *pkt, int pkt_len)
 {
-#if 0
+#ifdef DEBUG_SLIRP
     printf("slirp output:\n");
     hex_dump(stdout, pkt, pkt_len);
 #endif
@@ -4237,7 +4242,7 @@
 
 static void slirp_receive(void *opaque, const uint8_t *buf, int size)
 {
-#if 0
+#ifdef DEBUG_SLIRP
     printf("slirp input:\n");
     hex_dump(stdout, buf, size);
 #endif
@@ -4310,7 +4315,7 @@
 
 #ifndef _WIN32
 
-char smb_dir[1024];
+static char smb_dir[1024];
 
 static void erase_dir(char *dir_name)
 {
@@ -5693,6 +5698,61 @@
     }
 }
 
+/***********************************************************/
+/* Bluetooth support */
+static int nb_hcis;
+static int cur_hci;
+static struct HCIInfo *hci_table[MAX_NICS];
+static struct bt_vlan_s {
+    struct bt_scatternet_s net;
+    int id;
+    struct bt_vlan_s *next;
+} *first_bt_vlan;
+
+/* find or alloc a new bluetooth "VLAN" */
+static struct bt_scatternet_s *qemu_find_bt_vlan(int id)
+{
+    struct bt_vlan_s **pvlan, *vlan;
+    for (vlan = first_bt_vlan; vlan != NULL; vlan = vlan->next) {
+        if (vlan->id == id)
+            return &vlan->net;
+    }
+    vlan = qemu_mallocz(sizeof(struct bt_vlan_s));
+    vlan->id = id;
+    pvlan = &first_bt_vlan;
+    while (*pvlan != NULL)
+        pvlan = &(*pvlan)->next;
+    *pvlan = vlan;
+    return &vlan->net;
+}
+
+static void null_hci_send(struct HCIInfo *hci, const uint8_t *data, int len)
+{
+}
+
+static int null_hci_addr_set(struct HCIInfo *hci, const uint8_t *bd_addr)
+{
+    return -ENOTSUP;
+}
+
+static struct HCIInfo null_hci = {
+    .cmd_send = null_hci_send,
+    .sco_send = null_hci_send,
+    .acl_send = null_hci_send,
+    .bdaddr_set = null_hci_addr_set,
+};
+
+struct HCIInfo *qemu_next_hci(void)
+{
+    if (cur_hci == nb_hcis)
+        return &null_hci;
+
+    return hci_table[cur_hci++];
+}
+
+/***********************************************************/
+/* QEMU Block devices */
+
 #define HD_ALIAS "index=%d,media=disk"
 #ifdef TARGET_PPC
 #define CDROM_ALIAS "index=1,media=cdrom"
@@ -5843,12 +5903,7 @@
     index = -1;
     cache = 1;
 
-    if (!strcmp(machine->name, "realview") ||
-        !strcmp(machine->name, "SS-5") ||
-        !strcmp(machine->name, "SS-10") ||
-        !strcmp(machine->name, "SS-600MP") ||
-        !strcmp(machine->name, "versatilepb") ||
-        !strcmp(machine->name, "versatileab")) {
+    if (machine->use_scsi) {
         type = IF_SCSI;
         max_devs = MAX_SCSI_DEVS;
         pstrcpy(devname, sizeof(devname), "scsi");
@@ -6591,6 +6646,7 @@
     QEMUFilePutBufferFunc *put_buffer;
     QEMUFileGetBufferFunc *get_buffer;
     QEMUFileCloseFunc *close;
+    QEMUFileRateLimit *rate_limit;
     void *opaque;
 
     int64_t buf_offset; /* start of buffer when writing, end of buffer
@@ -6603,62 +6659,104 @@
 typedef struct QEMUFileFD
 {
     int fd;
+    QEMUFile *file;
 } QEMUFileFD;
 
+static void fd_put_notify(void *opaque)
+{
+    QEMUFileFD *s = opaque;
+
+    /* Remove writable callback and do a put notify */
+    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
+    qemu_file_put_notify(s->file);
+}
+
+static void fd_put_buffer(void *opaque, const uint8_t *buf,
+                          int64_t pos, int size)
+{
+    QEMUFileFD *s = opaque;
+    ssize_t len;
+
+    do {
+        len = write(s->fd, buf, size);
+    } while (len == -1 && errno == EINTR);
+
+    if (len == -1)
+        len = -errno;
+
+    /* When the fd becomes writable again, register a callback to do
+     * a put notify */
+    if (len == -EAGAIN)
+        qemu_set_fd_handler2(s->fd, NULL, NULL, fd_put_notify, s);
+}
+
 static int fd_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
 {
     QEMUFileFD *s = opaque;
-    int offset = 0;
     ssize_t len;
 
-again:
-    len = read(s->fd, buf + offset, size - offset);
-    if (len == -1) {
-	if (errno == EINTR || errno == EAGAIN)
-	    goto again;
-    }
+    do {
+        len = read(s->fd, buf, size);
+    } while (len == -1 && errno == EINTR);
+
+    if (len == -1)
+        len = -errno;
 
     return len;
 }
 
+static int fd_close(void *opaque)
+{
+    QEMUFileFD *s = opaque;
+    qemu_free(s);
+    return 0;
+}
+
 QEMUFile *qemu_fopen_fd(int fd)
 {
     QEMUFileFD *s = qemu_mallocz(sizeof(QEMUFileFD));
+
+    if (s == NULL)
+        return NULL;
+
     s->fd = fd;
-    return qemu_fopen(s, NULL, fd_get_buffer, qemu_free);
+    s->file = qemu_fopen_ops(s, fd_put_buffer, fd_get_buffer, fd_close, NULL);
+    return s->file;
 }
 
-typedef struct QEMUFileUnix
+typedef struct QEMUFileStdio
 {
     FILE *outfile;
-} QEMUFileUnix;
+} QEMUFileStdio;
 
-static void file_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
+static void file_put_buffer(void *opaque, const uint8_t *buf,
+                            int64_t pos, int size)
 {
-    QEMUFileUnix *s = opaque;
+    QEMUFileStdio *s = opaque;
     fseek(s->outfile, pos, SEEK_SET);
     fwrite(buf, 1, size, s->outfile);
 }
 
 static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
 {
-    QEMUFileUnix *s = opaque;
+    QEMUFileStdio *s = opaque;
     fseek(s->outfile, pos, SEEK_SET);
     return fread(buf, 1, size, s->outfile);
 }
 
-static void file_close(void *opaque)
+static int file_close(void *opaque)
 {
-    QEMUFileUnix *s = opaque;
+    QEMUFileStdio *s = opaque;
     fclose(s->outfile);
     qemu_free(s);
+    return 0;
 }
 
-QEMUFile *qemu_fopen_file(const char *filename, const char *mode)
+QEMUFile *qemu_fopen(const char *filename, const char *mode)
 {
-    QEMUFileUnix *s;
+    QEMUFileStdio *s;
 
-    s = qemu_mallocz(sizeof(QEMUFileUnix));
+    s = qemu_mallocz(sizeof(QEMUFileStdio));
     if (!s)
         return NULL;
 
@@ -6667,9 +6765,9 @@
         goto fail;
 
     if (!strcmp(mode, "wb"))
-	return qemu_fopen(s, file_put_buffer, NULL, file_close);
+        return qemu_fopen_ops(s, file_put_buffer, NULL, file_close, NULL);
     else if (!strcmp(mode, "rb"))
-	return qemu_fopen(s, NULL, file_get_buffer, file_close);
+        return qemu_fopen_ops(s, NULL, file_get_buffer, file_close, NULL);
 
 fail:
     if (s->outfile)
@@ -6684,7 +6782,8 @@
     int64_t base_offset;
 } QEMUFileBdrv;
 
-static void bdrv_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
+static void bdrv_put_buffer(void *opaque, const uint8_t *buf,
+                            int64_t pos, int size)
 {
     QEMUFileBdrv *s = opaque;
     bdrv_pwrite(s->bs, s->base_offset + pos, buf, size);
@@ -6696,7 +6795,14 @@
     return bdrv_pread(s->bs, s->base_offset + pos, buf, size);
 }
 
-QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
+static int bdrv_fclose(void *opaque)
+{
+    QEMUFileBdrv *s = opaque;
+    qemu_free(s);
+    return 0;
+}
+
+static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
 {
     QEMUFileBdrv *s;
 
@@ -6708,24 +6814,27 @@
     s->base_offset = offset;
 
     if (is_writable)
-	return qemu_fopen(s, bdrv_put_buffer, NULL, qemu_free);
+        return qemu_fopen_ops(s, bdrv_put_buffer, NULL, bdrv_fclose, NULL);
 
-    return qemu_fopen(s, NULL, bdrv_get_buffer, qemu_free);
+    return qemu_fopen_ops(s, NULL, bdrv_get_buffer, bdrv_fclose, NULL);
 }
 
-QEMUFile *qemu_fopen(void *opaque, QEMUFilePutBufferFunc *put_buffer,
-		     QEMUFileGetBufferFunc *get_buffer, QEMUFileCloseFunc *close)
+QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
+                         QEMUFileGetBufferFunc *get_buffer,
+                         QEMUFileCloseFunc *close,
+                         QEMUFileRateLimit *rate_limit)
 {
     QEMUFile *f;
 
     f = qemu_mallocz(sizeof(QEMUFile));
     if (!f)
-	return NULL;
+        return NULL;
 
     f->opaque = opaque;
     f->put_buffer = put_buffer;
     f->get_buffer = get_buffer;
     f->close = close;
+    f->rate_limit = rate_limit;
 
     return f;
 }
@@ -6736,7 +6845,7 @@
         return;
 
     if (f->buf_index > 0) {
-	f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
+        f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
         f->buf_offset += f->buf_index;
         f->buf_index = 0;
     }
@@ -6751,19 +6860,26 @@
 
     len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
     if (len < 0)
-	len = 0;
+        len = 0;
 
     f->buf_index = 0;
     f->buf_size = len;
     f->buf_offset += len;
 }
 
-void qemu_fclose(QEMUFile *f)
+int qemu_fclose(QEMUFile *f)
 {
+    int ret = 0;
     qemu_fflush(f);
     if (f->close)
-	f->close(f->opaque);
+        ret = f->close(f->opaque);
     qemu_free(f);
+    return ret;
+}
+
+void qemu_file_put_notify(QEMUFile *f)
+{
+    f->put_buffer(f->opaque, NULL, 0, 0);
 }
 
 void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
@@ -6848,6 +6964,14 @@
     return pos;
 }
 
+int qemu_file_rate_limit(QEMUFile *f)
+{
+    if (f->rate_limit)
+        return f->rate_limit(f->opaque);
+
+    return 0;
+}
+
 void qemu_put_be16(QEMUFile *f, unsigned int v)
 {
     qemu_put_byte(f, v >> 8);
@@ -7829,7 +7953,7 @@
 /***********************************************************/
 /* machine registration */
 
-QEMUMachine *first_machine = NULL;
+static QEMUMachine *first_machine = NULL;
 QEMUMachine *current_machine = NULL;
 
 int qemu_register_machine(QEMUMachine *m)
@@ -8329,8 +8453,10 @@
                 timeout = 0;
             }
         } else {
-            if (shutdown_requested)
+            if (shutdown_requested) {
+                ret = EXCP_INTERRUPT;
                 break;
+            }
             timeout = 10;
         }
 #ifdef CONFIG_PROFILER
@@ -8391,6 +8517,8 @@
            "                use -soundhw ? to get the list of supported cards\n"
            "                use -soundhw all to enable all of them\n"
 #endif
+           "-vga [std|cirrus|vmware]\n"
+           "                select video card type\n"
            "-localtime      set the real time clock to local time [default=utc]\n"
            "-full-screen    start in full screen\n"
 #ifdef TARGET_I386
@@ -8476,8 +8604,6 @@
 	   "-no-kvm-pit	    disable KVM kernel mode PIT\n"
 #endif
 #ifdef TARGET_I386
-           "-std-vga        simulate a standard VGA card with VESA Bochs Extensions\n"
-           "                (default is CL-GD5446 PCI VGA)\n"
            "-no-acpi        disable ACPI\n"
 #endif
 #ifdef CONFIG_CURSES
@@ -8571,10 +8697,8 @@
     QEMU_OPTION_bios,
     QEMU_OPTION_k,
     QEMU_OPTION_localtime,
-    QEMU_OPTION_cirrusvga,
-    QEMU_OPTION_vmsvga,
     QEMU_OPTION_g,
-    QEMU_OPTION_std_vga,
+    QEMU_OPTION_vga,
     QEMU_OPTION_echr,
     QEMU_OPTION_monitor,
     QEMU_OPTION_serial,
@@ -8624,7 +8748,7 @@
     int index;
 } QEMUOption;
 
-const QEMUOption qemu_options[] = {
+static const QEMUOption qemu_options[] = {
     { "h", 0, QEMU_OPTION_h },
     { "help", 0, QEMU_OPTION_h },
 
@@ -8691,7 +8815,7 @@
     { "g", 1, QEMU_OPTION_g },
 #endif
     { "localtime", 0, QEMU_OPTION_localtime },
-    { "std-vga", 0, QEMU_OPTION_std_vga },
+    { "vga", HAS_ARG, QEMU_OPTION_vga },
     { "echr", HAS_ARG, QEMU_OPTION_echr },
     { "monitor", HAS_ARG, QEMU_OPTION_monitor },
     { "serial", HAS_ARG, QEMU_OPTION_serial },
@@ -8716,8 +8840,6 @@
 
     /* temporary options */
     { "usb", 0, QEMU_OPTION_usb },
-    { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
-    { "vmwarevga", 0, QEMU_OPTION_vmsvga },
     { "no-acpi", 0, QEMU_OPTION_no_acpi },
     { "no-reboot", 0, QEMU_OPTION_no_reboot },
     { "no-shutdown", 0, QEMU_OPTION_no_shutdown },
@@ -8919,6 +9041,39 @@
 }
 #endif
 
+static void select_vgahw (const char *p)
+{
+    const char *opts;
+
+    if (strstart(p, "std", &opts)) {
+        cirrus_vga_enabled = 0;
+        vmsvga_enabled = 0;
+    } else if (strstart(p, "cirrus", &opts)) {
+        cirrus_vga_enabled = 1;
+        vmsvga_enabled = 0;
+    } else if (strstart(p, "vmware", &opts)) {
+        cirrus_vga_enabled = 0;
+        vmsvga_enabled = 1;
+    } else {
+    invalid_vga:
+        fprintf(stderr, "Unknown vga type: %s\n", p);
+        exit(1);
+    }
+    while (*opts) {
+        const char *nextopt;
+
+        if (strstart(opts, ",retrace=", &nextopt)) {
+            opts = nextopt;
+            if (strstart(opts, "dumb", &nextopt))
+                vga_retrace_method = VGA_RETRACE_DUMB;
+            else if (strstart(opts, "precise", &nextopt))
+                vga_retrace_method = VGA_RETRACE_PRECISE;
+            else goto invalid_vga;
+        } else goto invalid_vga;
+        opts = nextopt;
+    }
+}
+
 #ifdef _WIN32
 static BOOL WINAPI qemu_ctrl_handler(DWORD type)
 {
@@ -9175,7 +9330,8 @@
     nb_nics = 0;
 
     tb_size = 0;
-    
+    autostart= 1;
+
     optind = 1;
     for(;;) {
         if (optind >= argc)
@@ -9450,7 +9606,7 @@
             case QEMU_OPTION_d:
                 {
                     int mask;
-                    CPULogItem *item;
+                    const CPULogItem *item;
 
                     mask = cpu_str_to_log_mask(optarg);
                     if (!mask) {
@@ -9486,17 +9642,8 @@
             case QEMU_OPTION_localtime:
                 rtc_utc = 0;
                 break;
-            case QEMU_OPTION_cirrusvga:
-                cirrus_vga_enabled = 1;
-                vmsvga_enabled = 0;
-                break;
-            case QEMU_OPTION_vmsvga:
-                cirrus_vga_enabled = 0;
-                vmsvga_enabled = 1;
-                break;
-            case QEMU_OPTION_std_vga:
-                cirrus_vga_enabled = 0;
-                vmsvga_enabled = 0;
+            case QEMU_OPTION_vga:
+                select_vgahw (optarg);
                 break;
             case QEMU_OPTION_g:
                 {
diff -Nur kvm-76/qemu/vnc_keysym.h kvm-userspace/qemu/vnc_keysym.h
--- kvm-76/qemu/vnc_keysym.h	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/qemu/vnc_keysym.h	2008-10-12 09:38:24.000000000 +0200
@@ -2,7 +2,7 @@
 	const char* name;
 	int keysym;
 } name2keysym_t;
-static name2keysym_t name2keysym[]={
+static const name2keysym_t name2keysym[]={
 /* ascii */
     { "space",                0x020},
     { "exclam",               0x021},
diff -Nur kvm-76/user/kvmtrace.c kvm-userspace/user/kvmtrace.c
--- kvm-76/user/kvmtrace.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/user/kvmtrace.c	2008-10-12 09:38:24.000000000 +0200
@@ -454,7 +454,8 @@
 	int i;
 
 	for_each_tip(tip, i) {
-		(void) pthread_join(tip->thread, (void *) &ret);
+		if (tip->thread)
+			(void) pthread_join(tip->thread, (void *) &ret);
 		close_thread(tip);
 	}
 }
diff -Nur kvm-76/user/main.c kvm-userspace/user/main.c
--- kvm-76/user/main.c	2008-09-28 17:13:28.000000000 +0200
+++ kvm-userspace/user/main.c	2008-10-12 09:38:24.000000000 +0200
@@ -309,6 +309,11 @@
 	return 0;
 }
 
+static int test_try_push_nmi(void *opaque)
+{
+	return 0;
+}
+
 static void test_post_kvm_run(void *opaque, int vcpu)
 {
 }
@@ -347,6 +352,7 @@
 	.halt        = test_halt,
 	.io_window = test_io_window,
 	.try_push_interrupts = test_try_push_interrupts,
+	.try_push_nmi = test_try_push_nmi,
 	.post_kvm_run = test_post_kvm_run,
 	.pre_kvm_run = test_pre_kvm_run,
 };
