r3730 - in trunk/src/host/qemu-neo1973: . audio hw linux-user linux-user/m68k slirp target-i386 target-mips

andrew at sita.openmoko.org andrew at sita.openmoko.org
Tue Dec 25 01:23:47 CET 2007


Author: andrew
Date: 2007-12-25 01:23:33 +0100 (Tue, 25 Dec 2007)
New Revision: 3730

Added:
   trunk/src/host/qemu-neo1973/hw/scsi-generic.c
Modified:
   trunk/src/host/qemu-neo1973/Makefile
   trunk/src/host/qemu-neo1973/aes.c
   trunk/src/host/qemu-neo1973/audio/dsoundaudio.c
   trunk/src/host/qemu-neo1973/block-raw-posix.c
   trunk/src/host/qemu-neo1973/block-raw-win32.c
   trunk/src/host/qemu-neo1973/block-vvfat.c
   trunk/src/host/qemu-neo1973/block.c
   trunk/src/host/qemu-neo1973/block.h
   trunk/src/host/qemu-neo1973/block_int.h
   trunk/src/host/qemu-neo1973/exec.c
   trunk/src/host/qemu-neo1973/host-utils.h
   trunk/src/host/qemu-neo1973/hw/adlib.c
   trunk/src/host/qemu-neo1973/hw/esp.c
   trunk/src/host/qemu-neo1973/hw/fdc.c
   trunk/src/host/qemu-neo1973/hw/ide.c
   trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
   trunk/src/host/qemu-neo1973/hw/pcnet.c
   trunk/src/host/qemu-neo1973/hw/scsi-disk.c
   trunk/src/host/qemu-neo1973/hw/scsi-disk.h
   trunk/src/host/qemu-neo1973/hw/sd.c
   trunk/src/host/qemu-neo1973/hw/slavio_timer.c
   trunk/src/host/qemu-neo1973/hw/sun4m.c
   trunk/src/host/qemu-neo1973/hw/sun4m.h
   trunk/src/host/qemu-neo1973/kqemu.c
   trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h
   trunk/src/host/qemu-neo1973/linux-user/qemu.h
   trunk/src/host/qemu-neo1973/linux-user/syscall.c
   trunk/src/host/qemu-neo1973/monitor.c
   trunk/src/host/qemu-neo1973/osdep.c
   trunk/src/host/qemu-neo1973/osdep.h
   trunk/src/host/qemu-neo1973/qemu-common.h
   trunk/src/host/qemu-neo1973/qemu-doc.texi
   trunk/src/host/qemu-neo1973/qemu-img.c
   trunk/src/host/qemu-neo1973/qemu_socket.h
   trunk/src/host/qemu-neo1973/readline.c
   trunk/src/host/qemu-neo1973/slirp/slirp.h
   trunk/src/host/qemu-neo1973/sysemu.h
   trunk/src/host/qemu-neo1973/tap-win32.c
   trunk/src/host/qemu-neo1973/target-i386/helper.c
   trunk/src/host/qemu-neo1973/target-i386/helper2.c
   trunk/src/host/qemu-neo1973/target-i386/translate.c
   trunk/src/host/qemu-neo1973/target-mips/TODO
   trunk/src/host/qemu-neo1973/target-mips/translate.c
   trunk/src/host/qemu-neo1973/target-mips/translate_init.c
   trunk/src/host/qemu-neo1973/vl.c
Log:
Merge cvs.savannah.gnu.org:/sources/qemu.


Modified: trunk/src/host/qemu-neo1973/Makefile
===================================================================
--- trunk/src/host/qemu-neo1973/Makefile	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/Makefile	2007-12-25 00:23:33 UTC (rev 3730)
@@ -57,6 +57,7 @@
 OBJS+=i2c.o smbus.o smbus_eeprom.o max7310.o max111x.o wm8750.o wm8753.o
 OBJS+=ssd0303.o ssd0323.o ads7846.o pcf5060x.o stellaris_input.o
 OBJS+=scsi-disk.o cdrom.o
+OBJS+=scsi-generic.o
 OBJS+=usb.o usb-hub.o usb-linux.o usb-linux-gadget.o
 OBJS+=usb-hid.o usb-msd.o usb-wacom.o usb-net.o usb-bt.o
 OBJS+=sd.o ssi-sd.o ar6000.o

Modified: trunk/src/host/qemu-neo1973/aes.c
===================================================================
--- trunk/src/host/qemu-neo1973/aes.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/aes.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -30,7 +30,10 @@
 #include "qemu-common.h"
 #include "aes.h"
 
+#ifndef NDEBUG
 #define NDEBUG
+#endif
+
 #include <assert.h>
 
 typedef uint32_t u32;

Modified: trunk/src/host/qemu-neo1973/audio/dsoundaudio.c
===================================================================
--- trunk/src/host/qemu-neo1973/audio/dsoundaudio.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/audio/dsoundaudio.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -32,7 +32,9 @@
 #define AUDIO_CAP "dsound"
 #include "audio_int.h"
 
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
+#include <mmsystem.h>
 #include <objbase.h>
 #include <dsound.h>
 

Modified: trunk/src/host/qemu-neo1973/block-raw-posix.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw-posix.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/block-raw-posix.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -106,6 +106,10 @@
     }
     if (flags & BDRV_O_CREAT)
         open_flags |= O_CREAT | O_TRUNC;
+#ifdef O_DIRECT
+    if (flags & BDRV_O_DIRECT)
+        open_flags |= O_DIRECT;
+#endif
 
     s->type = FTYPE_FILE;
 
@@ -147,7 +151,7 @@
     if (ret < 0)
         return ret;
 
-    if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
         ++(s->lseek_err_cnt);
         if(s->lseek_err_cnt <= 10) {
             DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
@@ -200,7 +204,7 @@
     if (ret < 0)
         return ret;
 
-    if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+    if (offset >= 0 && lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
         ++(s->lseek_err_cnt);
         if(s->lseek_err_cnt) {
             DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
@@ -272,8 +276,8 @@
            seems to fix the problem. */
         struct aioinit ai;
         memset(&ai, 0, sizeof(ai));
-        ai.aio_threads = 1;
-        ai.aio_num = 1;
+        ai.aio_threads = 16;
+        ai.aio_num = 16;
         ai.aio_idle_time = 365 * 100000;
         aio_init(&ai);
     }
@@ -383,7 +387,10 @@
     acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
     acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
     acb->aiocb.aio_buf = buf;
-    acb->aiocb.aio_nbytes = nb_sectors * 512;
+    if (nb_sectors < 0)
+        acb->aiocb.aio_nbytes = -nb_sectors;
+    else
+        acb->aiocb.aio_nbytes = nb_sectors * 512;
     acb->aiocb.aio_offset = sector_num * 512;
     acb->next = first_aio;
     first_aio = acb;
@@ -659,6 +666,10 @@
         open_flags |= O_RDONLY;
         bs->read_only = 1;
     }
+#ifdef O_DIRECT
+    if (flags & BDRV_O_DIRECT)
+        open_flags |= O_DIRECT;
+#endif
 
     s->type = FTYPE_FILE;
 #if defined(__linux__)
@@ -671,6 +682,8 @@
         s->fd_open_flags = open_flags;
         /* open will not fail even if no floppy is inserted */
         open_flags |= O_NONBLOCK;
+    } else if (strstart(filename, "/dev/sg", NULL)) {
+        bs->sg = 1;
     }
 #endif
     fd = open(filename, open_flags, 0644);
@@ -850,6 +863,12 @@
     return 0;
 }
 
+static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+    BDRVRawState *s = bs->opaque;
+
+    return ioctl(s->fd, req, buf);
+}
 #else
 
 static int raw_is_inserted(BlockDriverState *bs)
@@ -872,6 +891,10 @@
     return -ENOTSUP;
 }
 
+static int raw_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+    return -ENOTSUP;
+}
 #endif /* !linux */
 
 BlockDriver bdrv_host_device = {
@@ -898,4 +921,6 @@
     .bdrv_media_changed = raw_media_changed,
     .bdrv_eject = raw_eject,
     .bdrv_set_locked = raw_set_locked,
+    /* generic scsi device */
+    .bdrv_ioctl = raw_ioctl,
 };

Modified: trunk/src/host/qemu-neo1973/block-raw-win32.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-raw-win32.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/block-raw-win32.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -105,6 +105,8 @@
 #else
     overlapped = FILE_FLAG_OVERLAPPED;
 #endif
+    if (flags & BDRV_O_DIRECT)
+        overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
     s->hfile = CreateFile(filename, access_flags,
                           FILE_SHARE_READ, NULL,
                           create_flags, overlapped, NULL);
@@ -473,6 +475,8 @@
 #else
     overlapped = FILE_FLAG_OVERLAPPED;
 #endif
+    if (flags & BDRV_O_DIRECT)
+        overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
     s->hfile = CreateFile(filename, access_flags,
                           FILE_SHARE_READ, NULL,
                           create_flags, overlapped, NULL);

Modified: trunk/src/host/qemu-neo1973/block-vvfat.c
===================================================================
--- trunk/src/host/qemu-neo1973/block-vvfat.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/block-vvfat.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -415,14 +415,16 @@
 static inline int short2long_name(char* dest,const char* src)
 {
     int i;
+    int len;
     for(i=0;i<129 && src[i];i++) {
         dest[2*i]=src[i];
 	dest[2*i+1]=0;
     }
+    len=2*i;
     dest[2*i]=dest[2*i+1]=0;
     for(i=2*i+2;(i%26);i++)
 	dest[i]=0xff;
-    return i;
+    return len;
 }
 
 static inline direntry_t* create_long_filename(BDRVVVFATState* s,const char* filename)
@@ -439,7 +441,7 @@
 	entry->begin=0;
 	entry->name[0]=(number_of_entries-i)|(i==0?0x40:0);
     }
-    for(i=0;i<length;i++) {
+    for(i=0;i<26*number_of_entries;i++) {
 	int offset=(i%26);
 	if(offset<10) offset=1+offset;
 	else if(offset<22) offset=14+offset-10;

Modified: trunk/src/host/qemu-neo1973/block.c
===================================================================
--- trunk/src/host/qemu-neo1973/block.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/block.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -380,7 +380,7 @@
     /* Note: for compatibility, we open disk image files as RDWR, and
        RDONLY as fallback */
     if (!(flags & BDRV_O_FILE))
-        open_flags = BDRV_O_RDWR;
+        open_flags = BDRV_O_RDWR | (flags & BDRV_O_DIRECT);
     else
         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
     ret = drv->bdrv_open(bs, filename, open_flags);
@@ -717,7 +717,7 @@
 }
 
 /* return 0 as number of sectors if no device present or error */
-void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
+void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
 {
     int64_t length;
     length = bdrv_getlength(bs);
@@ -786,6 +786,11 @@
     return bs->read_only;
 }
 
+int bdrv_is_sg(BlockDriverState *bs)
+{
+    return bs->sg;
+}
+
 /* XXX: no longer used */
 void bdrv_set_change_cb(BlockDriverState *bs,
                         void (*change_cb)(void *opaque), void *opaque)
@@ -1394,3 +1399,14 @@
         drv->bdrv_set_locked(bs, locked);
     }
 }
+
+/* needed for generic scsi interface */
+
+int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf)
+{
+    BlockDriver *drv = bs->drv;
+
+    if (drv && drv->bdrv_ioctl)
+        return drv->bdrv_ioctl(bs, req, buf);
+    return -ENOTSUP;
+}

Modified: trunk/src/host/qemu-neo1973/block.h
===================================================================
--- trunk/src/host/qemu-neo1973/block.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/block.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -44,6 +44,7 @@
                                      use a disk image format on top of
                                      it (default for
                                      bdrv_file_open()) */
+#define BDRV_O_DIRECT      0x0020
 
 #ifndef QEMU_IMG
 void bdrv_info(void);
@@ -72,7 +73,7 @@
                 const void *buf, int count);
 int bdrv_truncate(BlockDriverState *bs, int64_t offset);
 int64_t bdrv_getlength(BlockDriverState *bs);
-void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
+void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
 int bdrv_commit(BlockDriverState *bs);
 void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
 /* async block I/O */
@@ -118,6 +119,7 @@
 int bdrv_get_translation_hint(BlockDriverState *bs);
 int bdrv_is_removable(BlockDriverState *bs);
 int bdrv_is_read_only(BlockDriverState *bs);
+int bdrv_is_sg(BlockDriverState *bs);
 int bdrv_is_inserted(BlockDriverState *bs);
 int bdrv_media_changed(BlockDriverState *bs);
 int bdrv_is_locked(BlockDriverState *bs);
@@ -147,6 +149,7 @@
 int bdrv_snapshot_list(BlockDriverState *bs,
                        QEMUSnapshotInfo **psn_info);
 char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn);
+int bdrv_ioctl(BlockDriverState *bs, unsigned long int req, void *buf);
 
 char *get_human_readable_size(char *buf, int buf_size, int64_t size);
 int path_is_absolute(const char *path);

Modified: trunk/src/host/qemu-neo1973/block_int.h
===================================================================
--- trunk/src/host/qemu-neo1973/block_int.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/block_int.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -82,6 +82,9 @@
     int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
     int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
 
+    /* to control generic scsi devices */
+    int (*bdrv_ioctl)(BlockDriverState *bs, unsigned long int req, void *buf);
+
     BlockDriverAIOCB *free_aiocb;
     struct BlockDriver *next;
 };
@@ -93,6 +96,7 @@
     int removable; /* if true, the media can be removed */
     int locked;    /* if true, the media cannot temporarily be ejected */
     int encrypted; /* if true, the media is encrypted */
+    int sg;        /* if true, the device is a /dev/sg* */
     /* event callback when inserting/removing */
     void (*change_cb)(void *opaque);
     void *change_opaque;

Modified: trunk/src/host/qemu-neo1973/exec.c
===================================================================
--- trunk/src/host/qemu-neo1973/exec.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/exec.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -19,6 +19,7 @@
  */
 #include "config.h"
 #ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #else
 #include <sys/types.h>

Modified: trunk/src/host/qemu-neo1973/host-utils.h
===================================================================
--- trunk/src/host/qemu-neo1973/host-utils.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/host-utils.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -199,4 +199,4 @@
     val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
 
     return val;
- }
+}

Modified: trunk/src/host/qemu-neo1973/hw/adlib.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/adlib.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/adlib.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -26,6 +26,7 @@
 #include "hw.h"
 #include "audiodev.h"
 #include "audio/audio.h"
+#include "isa.h"
 
 //#define DEBUG
 

Modified: trunk/src/host/qemu-neo1973/hw/esp.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/esp.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/esp.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -615,7 +615,9 @@
     }
     DPRINTF("Attaching block device %d\n", id);
     /* Command queueing is not implemented.  */
-    s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
+    s->scsi_dev[id] = scsi_generic_init(bd, 0, esp_command_complete, s);
+    if (s->scsi_dev[id] == NULL)
+        s->scsi_dev[id] = scsi_disk_init(bd, 0, esp_command_complete, s);
 }
 
 void *esp_init(target_phys_addr_t espaddr,

Modified: trunk/src/host/qemu-neo1973/hw/fdc.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/fdc.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/fdc.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -234,7 +234,7 @@
 static void fd_revalidate (fdrive_t *drv)
 {
     const fd_format_t *parse;
-    int64_t nb_sectors, size;
+    uint64_t nb_sectors, size;
     int i, first_match, match;
     int nb_heads, max_track, last_sect, ro;
 
@@ -382,7 +382,7 @@
     uint8_t cur_drv;
     uint8_t bootsel;
     /* Command FIFO */
-    uint8_t fifo[FD_SECTOR_LEN];
+    uint8_t *fifo;
     uint32_t data_pos;
     uint32_t data_len;
     uint8_t data_state;
@@ -598,6 +598,11 @@
     fdctrl = qemu_mallocz(sizeof(fdctrl_t));
     if (!fdctrl)
         return NULL;
+    fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN);
+    if (fdctrl->fifo == NULL) {
+        qemu_free(fdctrl);
+        return NULL;
+    }
     fdctrl->result_timer = qemu_new_timer(vm_clock,
                                           fdctrl_result_timer, fdctrl);
 

Modified: trunk/src/host/qemu-neo1973/hw/ide.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/ide.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/ide.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -365,7 +365,7 @@
     EndTransferFunc *end_transfer_func;
     uint8_t *data_ptr;
     uint8_t *data_end;
-    uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
+    uint8_t *io_buffer;
     QEMUTimer *sector_write_timer; /* only used for win2k install hack */
     uint32_t irq_count; /* counts IRQs when using win2k install hack */
     /* CF-ATA extended error */
@@ -430,8 +430,7 @@
             v = *src++;
         else
             v = ' ';
-        *(char *)((long)str ^ 1) = v;
-        str++;
+        str[i^1] = v;
     }
 }
 
@@ -1465,12 +1464,12 @@
         break;
     case GPCMD_SEEK:
         {
-            int lba;
-            int64_t total_sectors;
+            unsigned int lba;
+            uint64_t total_sectors;
 
             bdrv_get_geometry(s->bs, &total_sectors);
             total_sectors >>= 2;
-            if (total_sectors <= 0) {
+            if (total_sectors == 0) {
                 ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                     ASC_MEDIUM_NOT_PRESENT);
                 break;
@@ -1516,11 +1515,11 @@
     case GPCMD_READ_TOC_PMA_ATIP:
         {
             int format, msf, start_track, len;
-            int64_t total_sectors;
+            uint64_t total_sectors;
 
             bdrv_get_geometry(s->bs, &total_sectors);
             total_sectors >>= 2;
-            if (total_sectors <= 0) {
+            if (total_sectors == 0) {
                 ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                     ASC_MEDIUM_NOT_PRESENT);
                 break;
@@ -1560,11 +1559,11 @@
         break;
     case GPCMD_READ_CDVD_CAPACITY:
         {
-            int64_t total_sectors;
+            uint64_t total_sectors;
 
             bdrv_get_geometry(s->bs, &total_sectors);
             total_sectors >>= 2;
-            if (total_sectors <= 0) {
+            if (total_sectors == 0) {
                 ide_atapi_cmd_error(s, SENSE_NOT_READY,
                                     ASC_MEDIUM_NOT_PRESENT);
                 break;
@@ -1580,7 +1579,7 @@
             int media = packet[1];
             int layer = packet[6];
             int format = packet[2];
-            int64_t total_sectors;
+            uint64_t total_sectors;
 
             if (media != 0 || layer != 0)
             {
@@ -1592,6 +1591,11 @@
                 case 0:
                     bdrv_get_geometry(s->bs, &total_sectors);
                     total_sectors >>= 2;
+                    if (total_sectors == 0) {
+                        ide_atapi_cmd_error(s, SENSE_NOT_READY,
+                                            ASC_MEDIUM_NOT_PRESENT);
+                        break;
+                    }
 
                     memset(buf, 0, 2052);
 
@@ -1636,7 +1640,7 @@
         break;
     case GPCMD_GET_CONFIGURATION:
         {
-            int64_t total_sectors;
+            uint64_t total_sectors;
 
             /* only feature 0 is supported */
             if (packet[2] != 0 || packet[3] != 0) {
@@ -1721,7 +1725,7 @@
 static void cdrom_change_cb(void *opaque)
 {
     IDEState *s = opaque;
-    int64_t nb_sectors;
+    uint64_t nb_sectors;
 
     /* XXX: send interrupt too */
     bdrv_get_geometry(s->bs, &nb_sectors);
@@ -2373,17 +2377,24 @@
 static int guess_disk_lchs(IDEState *s,
                            int *pcylinders, int *pheads, int *psectors)
 {
-    uint8_t buf[512];
+    uint8_t *buf;
     int ret, i, heads, sectors, cylinders;
     struct partition *p;
     uint32_t nr_sects;
 
+    buf = qemu_memalign(512, 512);
+    if (buf == NULL)
+        return -1;
     ret = bdrv_read(s->bs, 0, buf, 1);
-    if (ret < 0)
+    if (ret < 0) {
+        qemu_free(buf);
         return -1;
+    }
     /* test msdos magic */
-    if (buf[510] != 0x55 || buf[511] != 0xaa)
+    if (buf[510] != 0x55 || buf[511] != 0xaa) {
+        qemu_free(buf);
         return -1;
+    }
     for(i = 0; i < 4; i++) {
         p = ((struct partition *)(buf + 0x1be)) + i;
         nr_sects = le32_to_cpu(p->nr_sects);
@@ -2404,9 +2415,11 @@
             printf("guessed geometry: LCHS=%d %d %d\n",
                    cylinders, heads, sectors);
 #endif
+            qemu_free(buf);
             return 0;
         }
     }
+    qemu_free(buf);
     return -1;
 }
 
@@ -2417,10 +2430,11 @@
     IDEState *s;
     static int drive_serial = 1;
     int i, cylinders, heads, secs, translation, lba_detected = 0;
-    int64_t nb_sectors;
+    uint64_t nb_sectors;
 
     for(i = 0; i < 2; i++) {
         s = ide_state + i;
+        s->io_buffer = qemu_memalign(512, MAX_MULT_SECTORS*512 + 4);
         if (i == 0)
             s->bs = hd0;
         else

Modified: trunk/src/host/qemu-neo1973/hw/lsi53c895a.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/lsi53c895a.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/lsi53c895a.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -1236,6 +1236,8 @@
         return s->sdid;
     case 0x07: /* GPREG0 */
         return 0x7f;
+    case 0x08: /* Revision ID */
+        return 0x00;
     case 0xa: /* SSID */
         return s->ssid;
     case 0xb: /* SBCL */
@@ -1281,6 +1283,8 @@
         return s->ctest4;
     case 0x22: /* CTEST5 */
         return s->ctest5;
+    case 0x23: /* CTEST6 */
+         return 0;
     case 0x24: /* DBC[0:7] */
         return s->dbc & 0xff;
     case 0x25: /* DBC[8:15] */
@@ -1838,7 +1842,9 @@
         s->scsi_dev[id]->destroy(s->scsi_dev[id]);
     }
     DPRINTF("Attaching block device %d\n", id);
-    s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
+    s->scsi_dev[id] = scsi_generic_init(bd, 1, lsi_command_complete, s);
+    if (s->scsi_dev[id] == NULL)
+        s->scsi_dev[id] = scsi_disk_init(bd, 1, lsi_command_complete, s);
 }
 
 void *lsi_scsi_init(PCIBus *bus, int devfn)

Modified: trunk/src/host/qemu-neo1973/hw/pcnet.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/pcnet.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/pcnet.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -350,8 +350,8 @@
     } else {
         s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
         le32_to_cpus(&tmd->tbadr);
-        le16_to_cpus(&tmd->length);
-        le16_to_cpus(&tmd->status);
+        le16_to_cpus((uint16_t *)&tmd->length);
+        le16_to_cpus((uint16_t *)&tmd->status);
         le32_to_cpus(&tmd->misc);
         le32_to_cpus(&tmd->res);
         if (BCR_SWSTYLE(s) == 3) {
@@ -416,8 +416,8 @@
     } else {
         s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
         le32_to_cpus(&rmd->rbadr);
-        le16_to_cpus(&rmd->buf_length);
-        le16_to_cpus(&rmd->status);
+        le16_to_cpus((uint16_t *)&rmd->buf_length);
+        le16_to_cpus((uint16_t *)&rmd->status);
         le32_to_cpus(&rmd->msg_length);
         le32_to_cpus(&rmd->res);
         if (BCR_SWSTYLE(s) == 3) {

Modified: trunk/src/host/qemu-neo1973/hw/scsi-disk.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/scsi-disk.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/scsi-disk.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -46,7 +46,7 @@
     int sector_count;
     /* The amounnt of data in the buffer.  */
     int buf_len;
-    uint8_t dma_buf[SCSI_DMA_BUF_SIZE];
+    uint8_t *dma_buf;
     BlockDriverAIOCB *aiocb;
     struct SCSIRequest *next;
 } SCSIRequest;
@@ -78,6 +78,7 @@
         free_requests = r->next;
     } else {
         r = qemu_malloc(sizeof(SCSIRequest));
+        r->dma_buf = qemu_memalign(512, SCSI_DMA_BUF_SIZE);
     }
     r->dev = s;
     r->tag = tag;
@@ -284,7 +285,7 @@
                                  uint8_t *buf, int lun)
 {
     SCSIDeviceState *s = d->state;
-    int64_t nb_sectors;
+    uint64_t nb_sectors;
     uint32_t lba;
     uint32_t len;
     int cmdlen;

Modified: trunk/src/host/qemu-neo1973/hw/scsi-disk.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/scsi-disk.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/scsi-disk.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -26,6 +26,8 @@
 
 SCSIDevice *scsi_disk_init(BlockDriverState *bdrv, int tcq,
                            scsi_completionfn completion, void *opaque);
+SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
+                           scsi_completionfn completion, void *opaque);
 
 /* cdrom.c */
 int cdrom_read_toc(int nb_sectors, uint8_t *buf, int msf, int start_track);

Added: trunk/src/host/qemu-neo1973/hw/scsi-generic.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/scsi-generic.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/scsi-generic.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -0,0 +1,653 @@
+/*
+ * Generic SCSI Device support
+ *
+ * Copyright (c) 2007 Bull S.A.S.
+ * Based on code by Paul Brook
+ * Based on code by Fabrice Bellard
+ *
+ * Written by Laurent Vivier <Laurent.Vivier at bull.net>
+ *
+ * This code is licenced under the LGPL.
+ *
+ */
+
+#include "qemu-common.h"
+#include "block.h"
+#include "scsi-disk.h"
+
+#ifndef __linux__
+
+SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
+                              scsi_completionfn completion, void *opaque)
+{
+    return NULL;
+}
+
+#else /* __linux__ */
+
+//#define DEBUG_SCSI
+
+#ifdef DEBUG_SCSI
+#define DPRINTF(fmt, args...) \
+do { printf("scsi-generic: " fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do {} while(0)
+#endif
+
+#define BADF(fmt, args...) \
+do { fprintf(stderr, "scsi-generic: " fmt , ##args); } while (0)
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <scsi/sg.h>
+#include <scsi/scsi.h>
+
+#define LOAD_UNLOAD 0xa6
+#define SET_CD_SPEED 0xbb
+#define BLANK 0xa1
+
+#define SCSI_CMD_BUF_SIZE     16
+#define SCSI_SENSE_BUF_SIZE 32
+
+#define SG_ERR_DRIVER_TIMEOUT 0x06
+#define SG_ERR_DRIVER_SENSE 0x08
+
+#ifndef MAX_UINT
+#define MAX_UINT ((unsigned int)-1)
+#endif
+
+typedef struct SCSIRequest {
+    BlockDriverAIOCB *aiocb;
+    struct SCSIRequest *next;
+    SCSIDeviceState *dev;
+    uint32_t tag;
+    uint8_t cmd[SCSI_CMD_BUF_SIZE];
+    int cmdlen;
+    uint8_t *buf;
+    int buflen;
+    int len;
+    sg_io_hdr_t io_header;
+} SCSIRequest;
+
+struct SCSIDeviceState
+{
+    SCSIRequest *requests;
+    BlockDriverState *bdrv;
+    int blocksize;
+    int lun;
+    scsi_completionfn completion;
+    void *opaque;
+    int driver_status;
+    uint8_t sensebuf[SCSI_SENSE_BUF_SIZE];
+};
+
+/* Global pool of SCSIRequest structures.  */
+static SCSIRequest *free_requests = NULL;
+
+static SCSIRequest *scsi_new_request(SCSIDeviceState *s, uint32_t tag)
+{
+    SCSIRequest *r;
+
+    if (free_requests) {
+        r = free_requests;
+        free_requests = r->next;
+    } else {
+        r = qemu_malloc(sizeof(SCSIRequest));
+        r->buf = NULL;
+        r->buflen = 0;
+    }
+    r->dev = s;
+    r->tag = tag;
+    memset(r->cmd, 0, sizeof(r->cmd));
+    memset(&r->io_header, 0, sizeof(r->io_header));
+    r->cmdlen = 0;
+    r->len = 0;
+    r->aiocb = NULL;
+
+    /* link */
+
+    r->next = s->requests;
+    s->requests = r;
+    return r;
+}
+
+static void scsi_remove_request(SCSIRequest *r)
+{
+    SCSIRequest *last;
+    SCSIDeviceState *s = r->dev;
+
+    if (s->requests == r) {
+        s->requests = r->next;
+    } else {
+        last = s->requests;
+        while (last && last->next != r)
+            last = last->next;
+        if (last) {
+            last->next = r->next;
+        } else {
+            BADF("Orphaned request\n");
+        }
+    }
+    r->next = free_requests;
+    free_requests = r;
+}
+
+static SCSIRequest *scsi_find_request(SCSIDeviceState *s, uint32_t tag)
+{
+    SCSIRequest *r;
+
+    r = s->requests;
+    while (r && r->tag != tag)
+        r = r->next;
+
+    return r;
+}
+
+/* Helper function for command completion.  */
+static void scsi_command_complete(void *opaque, int ret)
+{
+    SCSIRequest *r = (SCSIRequest *)opaque;
+    SCSIDeviceState *s = r->dev;
+    uint32_t tag;
+    int sense;
+
+    s->driver_status = r->io_header.driver_status;
+    if (ret != 0)
+        sense = HARDWARE_ERROR;
+    else {
+        if (s->driver_status & SG_ERR_DRIVER_TIMEOUT) {
+            sense = HARDWARE_ERROR;
+            BADF("Driver Timeout\n");
+        } else if ((s->driver_status & SG_ERR_DRIVER_SENSE) == 0)
+            sense = NO_SENSE;
+        else
+            sense = s->sensebuf[2] & 0x0f;
+    }
+
+    DPRINTF("Command complete 0x%p tag=0x%x sense=%d\n", r, r->tag, sense);
+    tag = r->tag;
+    scsi_remove_request(r);
+    s->completion(s->opaque, SCSI_REASON_DONE, tag, sense);
+}
+
+/* Cancel a pending data transfer.  */
+static void scsi_cancel_io(SCSIDevice *d, uint32_t tag)
+{
+    DPRINTF("scsi_cancel_io 0x%x\n", tag);
+    SCSIDeviceState *s = d->state;
+    SCSIRequest *r;
+    DPRINTF("Cancel tag=0x%x\n", tag);
+    r = scsi_find_request(s, tag);
+    if (r) {
+        if (r->aiocb)
+            bdrv_aio_cancel(r->aiocb);
+        r->aiocb = NULL;
+        scsi_remove_request(r);
+    }
+}
+
+static int execute_command(BlockDriverState *bdrv,
+                           SCSIRequest *r, int direction,
+			   BlockDriverCompletionFunc *complete)
+{
+
+    r->io_header.interface_id = 'S';
+    r->io_header.dxfer_direction = direction;
+    r->io_header.dxferp = r->buf;
+    r->io_header.dxfer_len = r->buflen;
+    r->io_header.cmdp = r->cmd;
+    r->io_header.cmd_len = r->cmdlen;
+    r->io_header.mx_sb_len = sizeof(r->dev->sensebuf);
+    r->io_header.sbp = r->dev->sensebuf;
+    r->io_header.timeout = MAX_UINT;
+    r->io_header.usr_ptr = r;
+    r->io_header.flags |= SG_FLAG_DIRECT_IO;
+
+    if (bdrv_pwrite(bdrv, -1, &r->io_header, sizeof(r->io_header)) == -1) {
+        BADF("execute_command: write failed ! (%d)\n", errno);
+        return -1;
+    }
+    if (complete == NULL) {
+        int ret;
+        r->aiocb = NULL;
+        while ((ret = bdrv_pread(bdrv, -1, &r->io_header,
+                                           sizeof(r->io_header))) == -1 &&
+                      errno == EINTR);
+        if (ret == -1) {
+            BADF("execute_command: read failed !\n");
+            return -1;
+        }
+        return 0;
+    }
+
+    r->aiocb = bdrv_aio_read(bdrv, 0, (uint8_t*)&r->io_header,
+                          -(int64_t)sizeof(r->io_header), complete, r);
+    if (r->aiocb == NULL) {
+        BADF("execute_command: read failed !\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static void scsi_read_complete(void * opaque, int ret)
+{
+    SCSIRequest *r = (SCSIRequest *)opaque;
+    SCSIDeviceState *s = r->dev;
+    int len;
+
+    if (ret) {
+        DPRINTF("IO error\n");
+        scsi_command_complete(r, ret);
+        return;
+    }
+    len = r->io_header.dxfer_len - r->io_header.resid;
+    DPRINTF("Data ready tag=0x%x len=%d\n", r->tag, len);
+
+    r->len = -1;
+    s->completion(s->opaque, SCSI_REASON_DATA, r->tag, len);
+}
+
+/* Read more data from scsi device into buffer.  */
+static void scsi_read_data(SCSIDevice *d, uint32_t tag)
+{
+    SCSIDeviceState *s = d->state;
+    SCSIRequest *r;
+    int ret;
+
+    DPRINTF("scsi_read_data 0x%x\n", tag);
+    r = scsi_find_request(s, tag);
+    if (!r) {
+        BADF("Bad read tag 0x%x\n", tag);
+        /* ??? This is the wrong error.  */
+        scsi_command_complete(r, -EINVAL);
+        return;
+    }
+
+    if (r->len == -1) {
+        scsi_command_complete(r, 0);
+        return;
+    }
+
+    if (r->cmd[0] == REQUEST_SENSE && s->driver_status & SG_ERR_DRIVER_SENSE)
+    {
+        memcpy(r->buf, s->sensebuf, 16);
+        r->io_header.driver_status = 0;
+        r->len = -1;
+        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, 16);
+        return;
+    }
+
+    ret = execute_command(s->bdrv, r, SG_DXFER_FROM_DEV, scsi_read_complete);
+    if (ret == -1) {
+        scsi_command_complete(r, -EINVAL);
+        return;
+    }
+}
+
+static void scsi_write_complete(void * opaque, int ret)
+{
+    SCSIRequest *r = (SCSIRequest *)opaque;
+
+    DPRINTF("scsi_write_complete() ret = %d\n", ret);
+    if (ret) {
+        DPRINTF("IO error\n");
+        scsi_command_complete(r, ret);
+        return;
+    }
+
+    scsi_command_complete(r, ret);
+}
+
+/* Write data to a scsi device.  Returns nonzero on failure.
+   The transfer may complete asynchronously.  */
+static int scsi_write_data(SCSIDevice *d, uint32_t tag)
+{
+    SCSIDeviceState *s = d->state;
+    SCSIRequest *r;
+    int ret;
+
+    DPRINTF("scsi_write_data 0x%x\n", tag);
+    r = scsi_find_request(s, tag);
+    if (!r) {
+        BADF("Bad write tag 0x%x\n", tag);
+        /* ??? This is the wrong error.  */
+        scsi_command_complete(r, -EINVAL);
+        return 0;
+    }
+
+    if (r->len == 0) {
+        r->len = r->buflen;
+        s->completion(s->opaque, SCSI_REASON_DATA, r->tag, r->len);
+        return 0;
+    }
+
+    ret = execute_command(s->bdrv, r, SG_DXFER_TO_DEV, scsi_write_complete);
+    if (ret == -1) {
+        scsi_command_complete(r, -EINVAL);
+        return 1;
+    }
+
+    return 0;
+}
+
+/* Return a pointer to the data buffer.  */
+static uint8_t *scsi_get_buf(SCSIDevice *d, uint32_t tag)
+{
+    SCSIDeviceState *s = d->state;
+    SCSIRequest *r;
+    r = scsi_find_request(s, tag);
+    if (!r) {
+        BADF("Bad buffer tag 0x%x\n", tag);
+        return NULL;
+    }
+    return r->buf;
+}
+
+static int scsi_length(uint8_t *cmd, int blocksize, int *cmdlen, uint32_t *len)
+{
+    switch (cmd[0] >> 5) {
+    case 0:
+        *len = cmd[4];
+        *cmdlen = 6;
+        break;
+    case 1:
+    case 2:
+        *len = cmd[8] | (cmd[7] << 8);
+        *cmdlen = 10;
+        break;
+    case 4:
+        *len = cmd[13] | (cmd[12] << 8) | (cmd[11] << 16) | (cmd[10] << 24);
+        *cmdlen = 16;
+        break;
+    case 5:
+        *len = cmd[9] | (cmd[8] << 8) | (cmd[7] << 16) | (cmd[6] << 24);
+        *cmdlen = 12;
+        break;
+    default:
+        return -1;
+    }
+
+    switch(cmd[0]) {
+    case TEST_UNIT_READY:
+    case REZERO_UNIT:
+    case START_STOP:
+    case SEEK_6:
+    case WRITE_FILEMARKS:
+    case SPACE:
+    case ERASE:
+    case ALLOW_MEDIUM_REMOVAL:
+    case VERIFY:
+    case SEEK_10:
+    case SYNCHRONIZE_CACHE:
+    case LOCK_UNLOCK_CACHE:
+    case LOAD_UNLOAD:
+    case SET_CD_SPEED:
+    case SET_LIMITS:
+    case WRITE_LONG:
+    case MOVE_MEDIUM:
+    case UPDATE_BLOCK:
+        *len = 0;
+        break;
+    case MODE_SENSE:
+        break;
+    case WRITE_SAME:
+        *len = 1;
+        break;
+    case READ_CAPACITY:
+        *len = 8;
+        break;
+    case READ_BLOCK_LIMITS:
+        *len = 6;
+        break;
+    case READ_POSITION:
+        *len = 20;
+        break;
+    case SEND_VOLUME_TAG:
+        *len *= 40;
+        break;
+    case MEDIUM_SCAN:
+        *len *= 8;
+        break;
+    case WRITE_10:
+        cmd[1] &= ~0x08;	/* disable FUA */
+    case WRITE_VERIFY:
+    case WRITE_6:
+    case WRITE_12:
+    case WRITE_VERIFY_12:
+        *len *= blocksize;
+        break;
+    case READ_10:
+        cmd[1] &= ~0x08;	/* disable FUA */
+    case READ_6:
+    case READ_REVERSE:
+    case RECOVER_BUFFERED_DATA:
+    case READ_12:
+        *len *= blocksize;
+        break;
+    }
+    return 0;
+}
+
+static int is_write(int command)
+{
+    switch (command) {
+    case COPY:
+    case COPY_VERIFY:
+    case COMPARE:
+    case CHANGE_DEFINITION:
+    case LOG_SELECT:
+    case MODE_SELECT:
+    case MODE_SELECT_10:
+    case SEND_DIAGNOSTIC:
+    case WRITE_BUFFER:
+    case FORMAT_UNIT:
+    case REASSIGN_BLOCKS:
+    case RESERVE:
+    case SEARCH_EQUAL:
+    case SEARCH_HIGH:
+    case SEARCH_LOW:
+    case WRITE_6:
+    case WRITE_10:
+    case WRITE_VERIFY:
+    case UPDATE_BLOCK:
+    case WRITE_LONG:
+    case WRITE_SAME:
+    case SEARCH_HIGH_12:
+    case SEARCH_EQUAL_12:
+    case SEARCH_LOW_12:
+    case WRITE_12:
+    case WRITE_VERIFY_12:
+    case SET_WINDOW:
+    case MEDIUM_SCAN:
+    case SEND_VOLUME_TAG:
+    case WRITE_LONG_2:
+        return 1;
+    }
+    return 0;
+}
+
+/* Execute a scsi command.  Returns the length of the data expected by the
+   command.  This will be Positive for data transfers from the device
+   (eg. disk reads), negative for transfers to the device (eg. disk writes),
+   and zero if the command does not transfer any data.  */
+
+static int32_t scsi_send_command(SCSIDevice *d, uint32_t tag,
+                                 uint8_t *cmd, int lun)
+{
+    SCSIDeviceState *s = d->state;
+    uint32_t len;
+    int cmdlen;
+    SCSIRequest *r;
+    int ret;
+
+    /* ??? Tags are not unique for different luns.  We only implement a
+       single lun, so this should not matter.  */
+
+    if (lun != s->lun || (cmd[1] >> 5) != s->lun) {
+        DPRINTF("Unimplemented LUN %d\n", lun ? lun : cmd[1] >> 5);
+        s->completion(s->opaque, SCSI_REASON_DONE, tag, ILLEGAL_REQUEST);
+        return 0;
+    }
+
+    if (scsi_length(cmd, s->blocksize, &cmdlen, &len) == -1) {
+        BADF("Unsupported command length, command %x\n", cmd[0]);
+        return 0;
+    }
+
+    DPRINTF("Command: lun=%d tag=0x%x data=0x%02x len %d\n", lun, tag,
+            cmd[0], len);
+
+    r = scsi_find_request(s, tag);
+    if (r) {
+        BADF("Tag 0x%x already in use %p\n", tag, r);
+        scsi_cancel_io(d, tag);
+    }
+    r = scsi_new_request(s, tag);
+
+    memcpy(r->cmd, cmd, cmdlen);
+    r->cmdlen = cmdlen;
+
+    if (len == 0) {
+        if (r->buf != NULL)
+            free(r->buf);
+        r->buflen = 0;
+        r->buf = NULL;
+        ret = execute_command(s->bdrv, r, SG_DXFER_NONE, scsi_command_complete);
+        if (ret == -1) {
+            scsi_command_complete(r, -EINVAL);
+            return 0;
+        }
+        return 0;
+    }
+
+    if (r->buflen != len) {
+        if (r->buf != NULL)
+            free(r->buf);
+        r->buf = qemu_malloc(len);
+        r->buflen = len;
+    }
+
+    memset(r->buf, 0, r->buflen);
+    r->len = len;
+    if (is_write(cmd[0])) {
+        r->len = 0;
+        return -len;
+    }
+
+    return len;
+}
+
+static int get_blocksize(BlockDriverState *bdrv)
+{
+    uint8_t cmd[10];
+    uint8_t buf[8];
+    uint8_t sensebuf[8];
+    sg_io_hdr_t io_header;
+    int ret;
+
+    memset(cmd, sizeof(cmd), 0);
+    memset(buf, sizeof(buf), 0);
+    cmd[0] = READ_CAPACITY;
+
+    memset(&io_header, 0, sizeof(io_header));
+    io_header.interface_id = 'S';
+    io_header.dxfer_direction = SG_DXFER_FROM_DEV;
+    io_header.dxfer_len = sizeof(buf);
+    io_header.dxferp = buf;
+    io_header.cmdp = cmd;
+    io_header.cmd_len = sizeof(cmd);
+    io_header.mx_sb_len = sizeof(sensebuf);
+    io_header.sbp = sensebuf;
+    io_header.timeout = 6000; /* XXX */
+
+    ret = bdrv_pwrite(bdrv, -1, &io_header, sizeof(io_header));
+    if (ret == -1)
+        return -1;
+
+    while ((ret = bdrv_pread(bdrv, -1, &io_header, sizeof(io_header))) == -1 &&
+           errno == EINTR);
+
+    if (ret == -1)
+        return -1;
+
+    return (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
+}
+
+static void scsi_destroy(SCSIDevice *d)
+{
+    SCSIRequest *r, *n;
+
+    r = d->state->requests;
+    while (r) {
+        n = r->next;
+        qemu_free(r);
+        r = n;
+    }
+
+    r = free_requests;
+    while (r) {
+        n = r->next;
+        qemu_free(r);
+        r = n;
+    }
+
+    qemu_free(d->state);
+    qemu_free(d);
+}
+
+SCSIDevice *scsi_generic_init(BlockDriverState *bdrv, int tcq,
+                              scsi_completionfn completion, void *opaque)
+{
+    int sg_version;
+    SCSIDevice *d;
+    SCSIDeviceState *s;
+    struct sg_scsi_id scsiid;
+
+    /* check we are really using a /dev/sg* file */
+
+    if (!bdrv_is_sg(bdrv))
+        return NULL;
+
+    /* check we are using a driver managing SG_IO (version 3 and after */
+
+    if (bdrv_ioctl(bdrv, SG_GET_VERSION_NUM, &sg_version) < 0 ||
+        sg_version < 30000)
+        return NULL;
+
+    /* get LUN of the /dev/sg? */
+
+    if (bdrv_ioctl(bdrv, SG_GET_SCSI_ID, &scsiid))
+        return NULL;
+
+    /* define device state */
+
+    s = (SCSIDeviceState *)qemu_mallocz(sizeof(SCSIDeviceState));
+    s->bdrv = bdrv;
+    s->requests = NULL;
+    s->completion = completion;
+    s->opaque = opaque;
+    s->lun = scsiid.lun;
+    s->blocksize = get_blocksize(s->bdrv);
+    s->driver_status = 0;
+    memset(s->sensebuf, 0, sizeof(s->sensebuf));
+    /* removable media returns 0 if not present */
+    if (s->blocksize <= 0)
+        s->blocksize = 2048;
+
+    /* define function to manage device */
+
+    d = (SCSIDevice *)qemu_mallocz(sizeof(SCSIDevice));
+    d->state = s;
+    d->destroy = scsi_destroy;
+    d->send_command = scsi_send_command;
+    d->read_data = scsi_read_data;
+    d->write_data = scsi_write_data;
+    d->cancel_io = scsi_cancel_io;
+    d->get_buf = scsi_get_buf;
+
+    return d;
+}
+#endif /* __linux__ */

Modified: trunk/src/host/qemu-neo1973/hw/sd.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sd.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/sd.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -86,6 +86,7 @@
     uint32_t data_start;
     uint32_t data_offset;
     uint8_t data[512];
+    uint8_t *buf;
     qemu_irq readonly_cb;
     qemu_irq inserted_cb;
     BlockDriverState *bdrv;
@@ -1247,64 +1248,60 @@
 }
 
 /* No real need for 64 bit addresses here */
-static void sd_blk_read(BlockDriverState *bdrv,
-                void *data, uint32_t addr, uint32_t len)
+static void sd_blk_read(SDState *sd, uint32_t addr, uint32_t len)
 {
-    uint8_t buf[512];
     uint32_t end = addr + len;
 
-    if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) {
+    if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
         printf("sd_blk_read: read error on host side\n");
         return;
     }
 
     if (end > (addr & ~511) + 512) {
-        memcpy(data, buf + (addr & 511), 512 - (addr & 511));
+        memcpy(sd->data, sd->buf + (addr & 511), 512 - (addr & 511));
 
-        if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) {
+        if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
             printf("sd_blk_read: read error on host side\n");
             return;
         }
-        memcpy(data + 512 - (addr & 511), buf, end & 511);
+        memcpy(sd->data + 512 - (addr & 511), sd->buf, end & 511);
     } else
-        memcpy(data, buf + (addr & 511), len);
+        memcpy(sd->data, sd->buf + (addr & 511), len);
 }
 
-static void sd_blk_write(BlockDriverState *bdrv,
-                void *data, uint32_t addr, uint32_t len)
+static void sd_blk_write(SDState *sd, uint32_t addr, uint32_t len)
 {
-    uint8_t buf[512];
     uint32_t end = addr + len;
 
     if ((addr & 511) || len < 512)
-        if (!bdrv || bdrv_read(bdrv, addr >> 9, buf, 1) == -1) {
+        if (!sd->bdrv || bdrv_read(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
             printf("sd_blk_write: read error on host side\n");
             return;
         }
 
     if (end > (addr & ~511) + 512) {
-        memcpy(buf + (addr & 511), data, 512 - (addr & 511));
-        if (bdrv_write(bdrv, addr >> 9, buf, 1) == -1) {
+        memcpy(sd->buf + (addr & 511), sd->data, 512 - (addr & 511));
+        if (bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1) {
             printf("sd_blk_write: write error on host side\n");
             return;
         }
 
-        if (bdrv_read(bdrv, end >> 9, buf, 1) == -1) {
+        if (bdrv_read(sd->bdrv, end >> 9, sd->buf, 1) == -1) {
             printf("sd_blk_write: read error on host side\n");
             return;
         }
-        memcpy(buf, data + 512 - (addr & 511), end & 511);
-        if (bdrv_write(bdrv, end >> 9, buf, 1) == -1)
+        memcpy(sd->buf, sd->data + 512 - (addr & 511), end & 511);
+        if (bdrv_write(sd->bdrv, end >> 9, sd->buf, 1) == -1)
             printf("sd_blk_write: write error on host side\n");
     } else {
-        memcpy(buf + (addr & 511), data, len);
-        if (!bdrv || bdrv_write(bdrv, addr >> 9, buf, 1) == -1)
+        memcpy(sd->buf + (addr & 511), sd->data, len);
+        if (!sd->bdrv || bdrv_write(sd->bdrv, addr >> 9, sd->buf, 1) == -1)
             printf("sd_blk_write: write error on host side\n");
     }
 }
 
-#define BLK_READ_BLOCK(a, len)	sd_blk_read(sd->bdrv, sd->data, a, len)
-#define BLK_WRITE_BLOCK(a, len)	sd_blk_write(sd->bdrv, sd->data, a, len)
+#define BLK_READ_BLOCK(a, len)	sd_blk_read(sd, a, len)
+#define BLK_WRITE_BLOCK(a, len)	sd_blk_write(sd, a, len)
 #define APP_READ_BLOCK(a, len)	memset(sd->data, 0xec, len)
 #define APP_WRITE_BLOCK(a, len)
 
@@ -1559,6 +1556,7 @@
     SDState *sd;
 
     sd = (SDState *) qemu_mallocz(sizeof(SDState));
+    sd->buf = qemu_memalign(512, 512);
     sd->spi = is_spi;
     sd_reset(sd, bs);
     bdrv_set_change_cb(sd->bdrv, sd_cardchange, sd);

Modified: trunk/src/host/qemu-neo1973/hw/slavio_timer.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/slavio_timer.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/slavio_timer.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -61,6 +61,7 @@
     struct SLAVIO_TIMERState *master;
     int slave_index;
     // system only
+    unsigned int num_slaves;
     struct SLAVIO_TIMERState *slave[MAX_CPUS];
     uint32_t slave_mode;
 } SLAVIO_TIMERState;
@@ -96,9 +97,14 @@
 // Convert from ptimer countdown units
 static void slavio_timer_get_out(SLAVIO_TIMERState *s)
 {
-    uint64_t count;
+    uint64_t count, limit;
 
-    count = s->limit - PERIODS_TO_LIMIT(ptimer_get_count(s->timer));
+    if (s->limit == 0) /* free-run processor or system counter */
+        limit = TIMER_MAX_COUNT32;
+    else
+        limit = s->limit;
+
+    count = limit - PERIODS_TO_LIMIT(ptimer_get_count(s->timer));
     DPRINTF("get_out: limit %" PRIx64 " count %x%08x\n", s->limit,
             s->counthigh, s->count);
     s->count = count & TIMER_COUNT_MASK32;
@@ -174,7 +180,6 @@
 {
     SLAVIO_TIMERState *s = opaque;
     uint32_t saddr;
-    int reload = 0;
 
     DPRINTF("write " TARGET_FMT_plx " %08x\n", addr, val);
     saddr = (addr & TIMER_MAXADDR) >> 2;
@@ -190,9 +195,10 @@
             // set limit, reset counter
             qemu_irq_lower(s->irq);
             s->limit = val & TIMER_MAX_COUNT32;
-            if (!s->limit)
-                s->limit = TIMER_MAX_COUNT32;
-            ptimer_set_limit(s->timer, s->limit >> 9, 1);
+            if (s->limit == 0) /* free-run */
+                ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
+            else
+                ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
         }
         break;
     case TIMER_COUNTER:
@@ -208,9 +214,10 @@
     case TIMER_COUNTER_NORST:
         // set limit without resetting counter
         s->limit = val & TIMER_MAX_COUNT32;
-        if (!s->limit)
-            s->limit = TIMER_MAX_COUNT32;
-        ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), reload);
+        if (s->limit == 0)	/* free-run */
+            ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 0);
+        else
+            ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 0);
         break;
     case TIMER_STATUS:
         if (slavio_timer_is_user(s)) {
@@ -230,7 +237,7 @@
         if (s->master == NULL) {
             unsigned int i;
 
-            for (i = 0; i < MAX_CPUS; i++) {
+            for (i = 0; i < s->num_slaves; i++) {
                 if (val & (1 << i)) {
                     qemu_irq_lower(s->slave[i]->irq);
                     s->slave[i]->limit = -1ULL;
@@ -244,7 +251,7 @@
                     ptimer_run(s->slave[i]->timer, 0);
                 }
             }
-            s->slave_mode = val & ((1 << MAX_CPUS) - 1);
+            s->slave_mode = val & ((1 << s->num_slaves) - 1);
         } else
             DPRINTF("not system timer\n");
         break;
@@ -304,13 +311,11 @@
 {
     SLAVIO_TIMERState *s = opaque;
 
-    if (slavio_timer_is_user(s))
-        s->limit = TIMER_MAX_COUNT64;
-    else
-        s->limit = TIMER_MAX_COUNT32;
+    s->limit = 0;
     s->count = 0;
     s->reached = 0;
-    ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(s->limit), 1);
+    s->slave_mode = 0;
+    ptimer_set_limit(s->timer, LIMIT_TO_PERIODS(TIMER_MAX_COUNT32), 1);
     ptimer_run(s->timer, 0);
     s->running = 1;
     qemu_irq_lower(s->irq);
@@ -352,13 +357,15 @@
 }
 
 void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
-                           qemu_irq *cpu_irqs)
+                           qemu_irq *cpu_irqs, unsigned int num_cpus)
 {
     SLAVIO_TIMERState *master;
     unsigned int i;
 
     master = slavio_timer_init(base + SYS_TIMER_OFFSET, master_irq, NULL, 0);
 
+    master->num_slaves = num_cpus;
+
     for (i = 0; i < MAX_CPUS; i++) {
         master->slave[i] = slavio_timer_init(base + (target_phys_addr_t)
                                              CPU_TIMER_OFFSET(i),

Modified: trunk/src/host/qemu-neo1973/hw/sun4m.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -436,7 +436,7 @@
                         hwdef->nvram_size, 8);
 
     slavio_timer_init_all(hwdef->counter_base, slavio_irq[hwdef->clock1_irq],
-                          slavio_cpu_irq);
+                          slavio_cpu_irq, smp_cpus);
 
     slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[hwdef->ms_kb_irq],
                               nographic);

Modified: trunk/src/host/qemu-neo1973/hw/sun4m.h
===================================================================
--- trunk/src/host/qemu-neo1973/hw/sun4m.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/hw/sun4m.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -36,7 +36,7 @@
 
 /* slavio_timer.c */
 void slavio_timer_init_all(target_phys_addr_t base, qemu_irq master_irq,
-                           qemu_irq *cpu_irqs);
+                           qemu_irq *cpu_irqs, unsigned int num_cpus);
 
 /* slavio_serial.c */
 SerialState *slavio_serial_init(target_phys_addr_t base, qemu_irq irq,

Modified: trunk/src/host/qemu-neo1973/kqemu.c
===================================================================
--- trunk/src/host/qemu-neo1973/kqemu.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/kqemu.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -19,6 +19,7 @@
  */
 #include "config.h"
 #ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <winioctl.h>
 #else

Modified: trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/linux-user/m68k/target_signal.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -21,4 +21,9 @@
 #define TARGET_MINSIGSTKSZ	2048
 #define TARGET_SIGSTKSZ	8192
 
+static inline abi_ulong get_sp_from_cpustate(CPUM68KState *state)
+{
+    return state->aregs[7];
+}
+
 #endif /* TARGET_SIGNAL_H */

Modified: trunk/src/host/qemu-neo1973/linux-user/qemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/qemu.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/linux-user/qemu.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -6,6 +6,11 @@
 
 #include "cpu.h"
 
+#undef DEBUG_REMAP
+#ifdef DEBUG_REMAP
+#include <stdlib.h>
+#endif /* DEBUG_REMAP */
+
 #ifdef TARGET_ABI32
 typedef uint32_t abi_ulong;
 typedef int32_t abi_long;
@@ -370,7 +375,7 @@
     if (host_ptr == g2h(guest_addr))
         return;
     if (len > 0)
-        memcpy(g2h(guest_ptr), host_ptr, len);
+        memcpy(g2h(guest_addr), host_ptr, len);
     free(host_ptr);
 #endif
 }

Modified: trunk/src/host/qemu-neo1973/linux-user/syscall.c
===================================================================
--- trunk/src/host/qemu-neo1973/linux-user/syscall.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/linux-user/syscall.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -906,7 +906,7 @@
     default:
     unimplemented:
         gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
-        ret = -TARGET_ENOSYS;
+        ret = -TARGET_ENOPROTOOPT;
     }
     return ret;
 }
@@ -996,14 +996,15 @@
             }
             break;
         default:
-            goto unimplemented;
+            ret = -TARGET_ENOPROTOOPT;
+            break;
         }
         break;
     default:
     unimplemented:
         gemu_log("getsockopt level=%d optname=%d not yet supported\n",
                  level, optname);
-        ret = -TARGET_ENOSYS;
+        ret = -TARGET_EOPNOTSUPP;
         break;
     }
     return ret;

Modified: trunk/src/host/qemu-neo1973/monitor.c
===================================================================
--- trunk/src/host/qemu-neo1973/monitor.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/monitor.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -1860,7 +1860,7 @@
     case '$':
         {
             char buf[128], *q;
-            target_long reg;
+            target_long reg=0;
 
             pch++;
             q = buf;

Modified: trunk/src/host/qemu-neo1973/osdep.c
===================================================================
--- trunk/src/host/qemu-neo1973/osdep.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/osdep.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -37,6 +37,7 @@
 #include "sysemu.h"
 
 #ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #elif defined(_BSD)
 #include <stdlib.h>
@@ -60,6 +61,10 @@
 }
 
 #if defined(_WIN32)
+void *qemu_memalign(size_t alignment, size_t size)
+{
+    return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
+}
 
 void *qemu_vmalloc(size_t size)
 {
@@ -171,6 +176,22 @@
 
 #endif
 
+void *qemu_memalign(size_t alignment, size_t size)
+{
+#if defined(_POSIX_C_SOURCE)
+    int ret;
+    void *ptr;
+    ret = posix_memalign(&ptr, alignment, size);
+    if (ret != 0)
+        return NULL;
+    return ptr;
+#elif defined(_BSD)
+    return valloc(size);
+#else
+    return memalign(alignment, size);
+#endif
+}
+
 /* alloc shared memory pages */
 void *qemu_vmalloc(size_t size)
 {

Modified: trunk/src/host/qemu-neo1973/osdep.h
===================================================================
--- trunk/src/host/qemu-neo1973/osdep.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/osdep.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -48,6 +48,7 @@
 void qemu_free(void *ptr);
 char *qemu_strdup(const char *str);
 
+void *qemu_memalign(size_t alignment, size_t size);
 void *qemu_vmalloc(size_t size);
 void qemu_vfree(void *ptr);
 

Modified: trunk/src/host/qemu-neo1973/qemu-common.h
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-common.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/qemu-common.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -28,6 +28,7 @@
 #endif
 
 #ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #define fsync _commit
 #define lseek _lseeki64

Modified: trunk/src/host/qemu-neo1973/qemu-doc.texi
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-doc.texi	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/qemu-doc.texi	2007-12-25 00:23:33 UTC (rev 3730)
@@ -76,7 +76,7 @@
 @item Mac99 PowerMac (PowerPC processor, in progress)
 @item Sun4m (32-bit Sparc processor)
 @item Sun4u (64-bit Sparc processor, in progress)
- at item Malta board (32-bit MIPS processor)
+ at item Malta board (32-bit and 64-bit MIPS processors)
 @item ARM Integrator/CP (ARM)
 @item ARM Versatile baseboard (ARM)
 @item ARM RealView Emulation baseboard (ARM)
@@ -88,7 +88,7 @@
 @item Palm Tungsten|E PDA (OMAP310 processor)
 @end itemize
 
-For user emulation, x86, PowerPC, ARM, MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
+For user emulation, x86, PowerPC, ARM, 32-bit MIPS, Sparc32/64 and ColdFire(m68k) CPUs are supported.
 
 @node Installation
 @chapter Installation
@@ -250,6 +250,8 @@
 These options have the same definition as they have in @option{-hdachs}.
 @item snapshot=@var{snapshot}
 @var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
+ at item cache=@var{cache}
+ at var{cache} is "on" or "off" and allows to disable host cache to access data.
 @end table
 
 Instead of @option{-cdrom} you can use:
@@ -2113,8 +2115,10 @@
 @node MIPS System emulator
 @section MIPS System emulator
 
-Use the executable @file{qemu-system-mips} to simulate a MIPS machine.
-Three different machine types are emulated:
+Four executables cover simulation of 32 and 64-bit MIPS systems in
+both endian options, @file{qemu-system-mips}, @file{qemu-system-mipsel}
+ at file{qemu-system-mips64} and @file{qemu-system-mips64el}.
+Four different machine types are emulated:
 
 @itemize @minus
 @item
@@ -2122,7 +2126,7 @@
 @item
 The MIPS Malta prototype board "malta"
 @item
-An ACER Pica "pica61"
+An ACER Pica "pica61". This machine needs the 64-bit emulator.
 @item
 MIPS emulator pseudo board "mipssim"
 @end itemize
@@ -2517,6 +2521,7 @@
 incomplete.  All system calls that don't have a specific argument
 format are printed with information for six arguments.  Many
 flag-style arguments don't have decoders and will show up as numbers.
+ at end table
 
 @node Other binaries
 @subsection Other binaries

Modified: trunk/src/host/qemu-neo1973/qemu-img.c
===================================================================
--- trunk/src/host/qemu-neo1973/qemu-img.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/qemu-img.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -26,6 +26,7 @@
 #include <assert.h>
 
 #ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #endif
 
@@ -235,7 +236,7 @@
     const char *fmt = "raw";
     const char *filename;
     const char *base_filename = NULL;
-    int64_t size;
+    uint64_t size;
     const char *p;
     BlockDriver *drv;
 
@@ -300,7 +301,7 @@
         printf(", backing_file=%s",
                base_filename);
     }
-    printf(", size=%" PRId64 " kB\n", (int64_t) (size / 1024));
+    printf(", size=%" PRIu64 " kB\n", size / 1024);
     ret = bdrv_create(drv, filename, size / 512, base_filename, flags);
     if (ret < 0) {
         if (ret == -ENOTSUP) {
@@ -410,7 +411,8 @@
     const char *fmt, *out_fmt, *out_filename;
     BlockDriver *drv;
     BlockDriverState **bs, *out_bs;
-    int64_t total_sectors, nb_sectors, sector_num, bs_offset, bs_sectors;
+    int64_t total_sectors, nb_sectors, sector_num, bs_offset;
+    uint64_t bs_sectors;
     uint8_t buf[IO_BUF_SIZE];
     const uint8_t *buf1;
     BlockDriverInfo bdi;
@@ -655,7 +657,8 @@
     BlockDriver *drv;
     BlockDriverState *bs;
     char fmt_name[128], size_buf[128], dsize_buf[128];
-    int64_t total_sectors, allocated_size;
+    uint64_t total_sectors;
+    int64_t allocated_size;
     char backing_filename[1024];
     char backing_filename2[1024];
     BlockDriverInfo bdi;

Modified: trunk/src/host/qemu-neo1973/qemu_socket.h
===================================================================
--- trunk/src/host/qemu-neo1973/qemu_socket.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/qemu_socket.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -3,7 +3,7 @@
 #define QEMU_SOCKET_H
 
 #ifdef _WIN32
-
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>

Modified: trunk/src/host/qemu-neo1973/readline.c
===================================================================
--- trunk/src/host/qemu-neo1973/readline.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/readline.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -268,7 +268,7 @@
 	    new_entry = hist_entry;
 	    /* Put this entry at the end of history */
 	    memmove(&term_history[idx], &term_history[idx + 1],
-		    &term_history[TERM_MAX_CMDS] - &term_history[idx + 1]);
+		    (TERM_MAX_CMDS - idx + 1) * sizeof(char *));
 	    term_history[TERM_MAX_CMDS - 1] = NULL;
 	    for (; idx < TERM_MAX_CMDS; idx++) {
 		if (term_history[idx] == NULL)
@@ -281,7 +281,7 @@
 	/* Need to get one free slot */
 	free(term_history[0]);
 	memcpy(term_history, &term_history[1],
-	       &term_history[TERM_MAX_CMDS] - &term_history[1]);
+	       (TERM_MAX_CMDS - 1) * sizeof(char *));
 	term_history[TERM_MAX_CMDS - 1] = NULL;
 	idx = TERM_MAX_CMDS - 1;
     }

Modified: trunk/src/host/qemu-neo1973/slirp/slirp.h
===================================================================
--- trunk/src/host/qemu-neo1973/slirp/slirp.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/slirp/slirp.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -29,6 +29,7 @@
 typedef uint64_t u_int64_t;
 typedef char *caddr_t;
 
+#define WIN32_LEAN_AND_MEAN
 # include <windows.h>
 # include <winsock2.h>
 # include <sys/timeb.h>

Modified: trunk/src/host/qemu-neo1973/sysemu.h
===================================================================
--- trunk/src/host/qemu-neo1973/sysemu.h	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/sysemu.h	2007-12-25 00:23:33 UTC (rev 3730)
@@ -122,7 +122,7 @@
 
 typedef struct DriveInfo {
     BlockDriverState *bdrv;
-    BlockInterfaceType interface;
+    BlockInterfaceType type;
     int bus;
     int unit;
 } DriveInfo;
@@ -134,8 +134,8 @@
 int nb_drives;
 DriveInfo drives_table[MAX_DRIVES+1];
 
-extern int drive_get_index(BlockInterfaceType interface, int bus, int unit);
-extern int drive_get_max_bus(BlockInterfaceType interface);
+extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
+extern int drive_get_max_bus(BlockInterfaceType type);
 
 /* serial ports */
 

Modified: trunk/src/host/qemu-neo1973/tap-win32.c
===================================================================
--- trunk/src/host/qemu-neo1973/tap-win32.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/tap-win32.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -30,6 +30,7 @@
 #include "net.h"
 #include "sysemu.h"
 #include <stdio.h>
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 
 /* NOTE: PCIBus is redefined in winddk.h */

Modified: trunk/src/host/qemu-neo1973/target-i386/helper.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/target-i386/helper.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -1751,6 +1751,12 @@
         ECX = 0;
         EDX = 0;
         break;
+    case 0x8000000A:
+        EAX = 0x00000001;
+        EBX = 0;
+        ECX = 0;
+        EDX = 0;
+        break;
     default:
         /* reserved values: zero */
         EAX = 0;

Modified: trunk/src/host/qemu-neo1973/target-i386/helper2.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/helper2.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/target-i386/helper2.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -119,6 +119,7 @@
 
 typedef struct x86_def_t {
     const char *name;
+    uint32_t level;
     uint32_t vendor1, vendor2, vendor3;
     int family;
     int model;
@@ -135,6 +136,7 @@
 #ifdef TARGET_X86_64
     {
         .name = "qemu64",
+        .level = 2,
         .vendor1 = 0x68747541, /* "Auth" */
         .vendor2 = 0x69746e65, /* "enti" */
         .vendor3 = 0x444d4163, /* "cAMD" */
@@ -150,11 +152,12 @@
         .ext2_features = (PPRO_FEATURES & 0x0183F3FF) | 
             CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX,
         .ext3_features = CPUID_EXT3_SVM,
-        .xlevel = 0x80000008,
+        .xlevel = 0x8000000A,
     },
 #endif
     {
         .name = "qemu32",
+        .level = 2,
         .family = 6,
         .model = 3,
         .stepping = 3,
@@ -164,6 +167,7 @@
     },
     {
         .name = "486",
+        .level = 0,
         .family = 4,
         .model = 0,
         .stepping = 0,
@@ -172,6 +176,7 @@
     },
     {
         .name = "pentium",
+        .level = 1,
         .family = 5,
         .model = 4,
         .stepping = 3,
@@ -180,6 +185,7 @@
     },
     {
         .name = "pentium2",
+        .level = 2,
         .family = 6,
         .model = 5,
         .stepping = 2,
@@ -188,6 +194,7 @@
     },
     {
         .name = "pentium3",
+        .level = 2,
         .family = 6,
         .model = 7,
         .stepping = 3,
@@ -306,7 +313,7 @@
         env->cpuid_vendor2 = 0x49656e69; /* "ineI" */
         env->cpuid_vendor3 = 0x6c65746e; /* "ntel" */
     }
-    env->cpuid_level = 2;
+    env->cpuid_level = def->level;
     env->cpuid_version = (def->family << 8) | (def->model << 4) | def->stepping;
     env->cpuid_features = def->features;
     env->pat = 0x0007040600070406ULL;

Modified: trunk/src/host/qemu-neo1973/target-i386/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-i386/translate.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/target-i386/translate.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -3887,7 +3887,7 @@
     case 0x1c7: /* cmpxchg8b */
         modrm = ldub_code(s->pc++);
         mod = (modrm >> 6) & 3;
-        if (mod == 3)
+        if ((mod == 3) || ((modrm & 0x38) != 0x8))
             goto illegal_op;
         gen_jmp_im(pc_start - s->cs_base);
         if (s->cc_op != CC_OP_DYNAMIC)

Modified: trunk/src/host/qemu-neo1973/target-mips/TODO
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/TODO	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/target-mips/TODO	2007-12-25 00:23:33 UTC (rev 3730)
@@ -47,9 +47,5 @@
 - We fake firmware support instead of doing the real thing
 - Real firmware falls over when trying to init RAM, presumably due
   to lacking system controller emulation.
-
-mipssim system emulation
-------------------------
-- The mipsnet.c has a glitch: Booting from NFS root works up until
-  starting /sbin/init, then it Linux hangs with "NFS server not
-  responding".
+- Bonito system controller not implemented
+- MSC1 system controller not implemented

Modified: trunk/src/host/qemu-neo1973/target-mips/translate.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/target-mips/translate.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -6724,10 +6724,10 @@
 
     if (!SIGN_EXT_P(env->PC[env->current_tc]))
         cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->PC[env->current_tc]);
-    if (!SIGN_EXT_P(env->HI[env->current_tc]))
-        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[env->current_tc]);
-    if (!SIGN_EXT_P(env->LO[env->current_tc]))
-        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[env->current_tc]);
+    if (!SIGN_EXT_P(env->HI[0][env->current_tc]))
+        cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->HI[0][env->current_tc]);
+    if (!SIGN_EXT_P(env->LO[0][env->current_tc]))
+        cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->LO[0][env->current_tc]);
     if (!SIGN_EXT_P(env->btarget))
         cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
 

Modified: trunk/src/host/qemu-neo1973/target-mips/translate_init.c
===================================================================
--- trunk/src/host/qemu-neo1973/target-mips/translate_init.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/target-mips/translate_init.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -317,7 +317,7 @@
         .CP0_Config2 = MIPS_CONFIG2,
         .CP0_Config3 = MIPS_CONFIG3,
         .SYNCI_Step = 32,
-        .CCRes = 2,
+        .CCRes = 1,
         .CP0_Status_rw_bitmask = 0x36FBFFFF,
 	/* The 20Kc has F64 / L / W but doesn't use the fcr0 bits. */
         .CP1_fcr0 = (1 << FCR0_3D) | (1 << FCR0_PS) |

Modified: trunk/src/host/qemu-neo1973/vl.c
===================================================================
--- trunk/src/host/qemu-neo1973/vl.c	2007-12-24 14:21:01 UTC (rev 3729)
+++ trunk/src/host/qemu-neo1973/vl.c	2007-12-25 00:23:33 UTC (rev 3730)
@@ -109,7 +109,7 @@
 #ifdef _WIN32
 #include <malloc.h>
 #include <sys/timeb.h>
-#include <windows.h>
+#include <mmsystem.h>
 #define getopt_long_only getopt_long
 #define memalign(align, size) malloc(size)
 #endif
@@ -4452,7 +4452,8 @@
 {
     int so_type=-1, optlen=sizeof(so_type);
 
-    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, &optlen)< 0) {
+    if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type,
+        (socklen_t *)&optlen)< 0) {
 	fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd);
 	return NULL;
     }
@@ -4866,14 +4867,14 @@
     return nb_drives_opt++;
 }
 
-int drive_get_index(BlockInterfaceType interface, int bus, int unit)
+int drive_get_index(BlockInterfaceType type, int bus, int unit)
 {
     int index;
 
     /* seek interface, bus and unit */
 
     for (index = 0; index < nb_drives; index++)
-        if (drives_table[index].interface == interface &&
+        if (drives_table[index].type == type &&
 	    drives_table[index].bus == bus &&
 	    drives_table[index].unit == unit)
         return index;
@@ -4881,14 +4882,14 @@
     return -1;
 }
 
-int drive_get_max_bus(BlockInterfaceType interface)
+int drive_get_max_bus(BlockInterfaceType type)
 {
     int max_bus;
     int index;
 
     max_bus = -1;
     for (index = 0; index < nb_drives; index++) {
-        if(drives_table[index].interface == interface &&
+        if(drives_table[index].type == type &&
            drives_table[index].bus > max_bus)
             max_bus = drives_table[index].bus;
     }
@@ -4901,15 +4902,18 @@
     char file[1024];
     char devname[128];
     const char *mediastr = "";
-    BlockInterfaceType interface;
+    BlockInterfaceType type;
     enum { MEDIA_DISK, MEDIA_CDROM } media;
     int bus_id, unit_id;
     int cyls, heads, secs, translation;
     BlockDriverState *bdrv;
     int max_devs;
     int index;
+    int cache;
+    int bdrv_flags;
     char *params[] = { "bus", "unit", "if", "index", "cyls", "heads",
-                       "secs", "trans", "media", "snapshot", "file", NULL };
+                       "secs", "trans", "media", "snapshot", "file",
+                       "cache", NULL };
 
     if (check_params(buf, sizeof(buf), params, str) < 0) {
          fprintf(stderr, "qemu: unknowm parameter '%s' in '%s'\n",
@@ -4923,6 +4927,7 @@
     unit_id = -1;
     translation = BIOS_ATA_TRANSLATION_AUTO;
     index = -1;
+    cache = 1;
 
     if (!strcmp(machine->name, "realview") ||
         !strcmp(machine->name, "SS-5") ||
@@ -4930,11 +4935,11 @@
         !strcmp(machine->name, "SS-600MP") ||
         !strcmp(machine->name, "versatilepb") ||
         !strcmp(machine->name, "versatileab")) {
-        interface = IF_SCSI;
+        type = IF_SCSI;
         max_devs = MAX_SCSI_DEVS;
         strcpy(devname, "scsi");
     } else {
-        interface = IF_IDE;
+        type = IF_IDE;
         max_devs = MAX_IDE_DEVS;
         strcpy(devname, "ide");
     }
@@ -4961,22 +4966,22 @@
     if (get_param_value(buf, sizeof(buf), "if", str)) {
         strncpy(devname, buf, sizeof(devname));
         if (!strcmp(buf, "ide")) {
-	    interface = IF_IDE;
+	    type = IF_IDE;
             max_devs = MAX_IDE_DEVS;
         } else if (!strcmp(buf, "scsi")) {
-	    interface = IF_SCSI;
+	    type = IF_SCSI;
             max_devs = MAX_SCSI_DEVS;
         } else if (!strcmp(buf, "floppy")) {
-	    interface = IF_FLOPPY;
+	    type = IF_FLOPPY;
             max_devs = 0;
         } else if (!strcmp(buf, "pflash")) {
-	    interface = IF_PFLASH;
+	    type = IF_PFLASH;
             max_devs = 0;
 	} else if (!strcmp(buf, "mtd")) {
-	    interface = IF_MTD;
+	    type = IF_MTD;
             max_devs = 0;
 	} else if (!strcmp(buf, "sd")) {
-	    interface = IF_SD;
+	    type = IF_SD;
             max_devs = 0;
 	} else {
             fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf);
@@ -5065,6 +5070,17 @@
 	}
     }
 
+    if (get_param_value(buf, sizeof(buf), "cache", str)) {
+        if (!strcmp(buf, "off"))
+            cache = 0;
+        else if (!strcmp(buf, "on"))
+            cache = 1;
+        else {
+           fprintf(stderr, "qemu: invalid cache option\n");
+           return -1;
+        }
+    }
+
     get_param_value(file, sizeof(file), "file", str);
 
     /* compute bus and unit according index */
@@ -5091,7 +5107,7 @@
 
     if (unit_id == -1) {
        unit_id = 0;
-       while (drive_get_index(interface, bus_id, unit_id) != -1) {
+       while (drive_get_index(type, bus_id, unit_id) != -1) {
            unit_id++;
            if (max_devs && unit_id >= max_devs) {
                unit_id -= max_devs;
@@ -5112,23 +5128,27 @@
      * ignore multiple definitions
      */
 
-    if (drive_get_index(interface, bus_id, unit_id) != -1)
+    if (drive_get_index(type, bus_id, unit_id) != -1)
         return 0;
 
     /* init */
 
-    if (interface == IF_IDE || interface == IF_SCSI)
+    if (type == IF_IDE || type == IF_SCSI)
         mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
-    snprintf(buf, sizeof(buf), max_devs ? "%1$s%4$i%2$s%3$i" : "%s%s%i",
-             devname, mediastr, unit_id, bus_id);
+    if (max_devs)
+        snprintf(buf, sizeof(buf), "%s%i%s%i",
+                 devname, bus_id, mediastr, unit_id);
+    else
+        snprintf(buf, sizeof(buf), "%s%s%i",
+                 devname, mediastr, unit_id);
     bdrv = bdrv_new(buf);
     drives_table[nb_drives].bdrv = bdrv;
-    drives_table[nb_drives].interface = interface;
+    drives_table[nb_drives].type = type;
     drives_table[nb_drives].bus = bus_id;
     drives_table[nb_drives].unit = unit_id;
     nb_drives++;
 
-    switch(interface) {
+    switch(type) {
     case IF_IDE:
     case IF_SCSI:
         switch(media) {
@@ -5155,8 +5175,12 @@
     }
     if (!file[0])
         return 0;
-    if (bdrv_open(bdrv, file, snapshot ? BDRV_O_SNAPSHOT : 0) < 0 ||
-        qemu_key_check(bdrv, file)) {
+    bdrv_flags = 0;
+    if (snapshot)
+        bdrv_flags |= BDRV_O_SNAPSHOT;
+    if (!cache)
+        bdrv_flags |= BDRV_O_DIRECT;
+    if (bdrv_open(bdrv, file, bdrv_flags) < 0 || qemu_key_check(bdrv, file)) {
         fprintf(stderr, "qemu: could not open disk image %s\n",
                         file);
         return -1;
@@ -7730,7 +7754,8 @@
            "-hdc/-hdd file  use 'file' as IDE hard disk 2/3 image\n"
            "-cdrom file     use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
 	   "-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][index=i]\n"
-           "       [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]\n"
+           "       [,cyls=c,heads=h,secs=s[,trans=t]][snapshot=on|off]"
+           "       [,cache=on|off]\n"
 	   "                use 'file' as a drive image\n"
            "-mtdblock file  use 'file' as on-board Flash memory image\n"
            "-sd file        use 'file' as SecureDigital card image\n"
@@ -9248,8 +9273,8 @@
                     s->down_script[0])
                     launch_script(s->down_script, ifname, s->fd);
             }
+        }
     }
-    }
 #endif
     return 0;
 }





More information about the commitlog mailing list