qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] enabling bus-master IDE driver


From: Juergen Lock
Subject: Re: [Qemu-devel] enabling bus-master IDE driver
Date: Sun, 28 Nov 2004 21:09:46 +0100

On Fri, Nov 26, 2004 at 04:14:35PM +0000, Juergen Keil wrote:
>... 
> FreeBSD identifies QEMU's pci-ide controller as an "Intel PIIX3" chipset,
> and has built-in knowledge that the PIIX3 does not support UDMA modes.
> WDMA2 is the fastest dma transfer rate that is supported by the PIIX3
> (according to freebsd source, I didn't verify this but I guess it's correct).
> So that's why freebsd is using WDMA2.
> 
Ah, I see.

> See function ata_intel_ident() in sys/dev/ata/ata-chipcet.c:
> 
> http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/dev/ata/ata-chipset.c?rev=1.92&con
> tent-type=text/x-cvsweb-markup
> 
> 
> 
> I don't think that you'll notice a difference in speed or performance inside
> qemu between multiword dma and ultra dma modes.  qemu does not emulate the
> ide hardware at such a low level that the dma transfer modes on the bus
> matters.  The important thing is that the ide dma commands are used, so that
> the hw/ide.c will move data to/from pc memory.  If a pio mode is used
> the guest os' interrupt handler moves the data word-by-word to or from the
> ide controller hardware, using emulated x86 instructions, and that is quite
> expensive.
> 
 Thats what i thought as well, but do you have an explanation for the fact
that with the (previous) patch linux guest's DMA was reported to be slower
here than without?

>          -------------
>          
> Btw. FreeBSD 5.2.1 does not enable DMA on the QEMU-HDD, it uses PIO4 mode.
> 
> Trying to enable DMA with "atacontrol mode 0 WDMA2 BIOSPIO" crashes
> the FreeBSD kernel (-> a FreeBSD kernel problem).
> 
> Problem: PCI busmastering is not enabled in the PCI command register.
> It seems the BIOS is supposed to enable busmastering, but bochs bios
> apparently doesn't enable pci-ide busmastering.  ata-pci.c function
> ata_pci_attach() does not set ctrl->r_io1 which would be needed in
> ata_pci_allocated() to allocate and enable DMA (ctrl->dmainit() is not
> called).
> 
> As a workaround, always enable busmastering on qemu's pci-ide device.
> 
> Default to WDMA2 mode (the real Intel PIIX3 hardware which we
> emulate does not support UDMA modes).
> 
> (The following patch needs to be applied on top of the previous version
> of the pci-ide busmastering dma patch)

 I had to hand-apply this as well, your mailer seems to distort patches...
I'll append a cumulative version (both patches) below.

 But, with this patch, FreeBSD 5.2.1 with device atapicam in the kernel
(tested with FreeSBIE-1.0) panics with a integer divide fault in
__qdivrem+59 (long long devide helper function i think), if I pass it
a -hda, and before that (booting with -v) i see it detecting a da0 disk
        GEOM: new disk da0
where it tries to
        (da0:ata1:0:0:0): SYNCHRONIZE CACHE. CDB: 35 0 0 0 0 0 0 0 0 0
        (da0:ata1:0:0:0): error code 0
two times.  ata1, so atapicam somehow detected the cdrom as da0 instead of
as cd0...

 And, FreeSBIE-20040919 (a 6.0-CURRENT snapshot which also has atapicam
in the kernel) detects a da0 and panics too, even with just the old patch.
(current process 35, swi3: cambio)

 Ok and now i just tested a 5.3-RC2 kernel with atapicam.  It doesnt
panic but says:
        GEOM: new disk da0
        da0 at ata1 bus 0 target 0 lun 0
        da0: <  > Fixed Direct Access SCSI-0 device
        da0: 16.000MB/s transfers
        da0: 0MB (1 0 byte sectors: 0H 0S/T 0C)
so it looks like they fixed the zero divide bug, but the wrong detection
of the cdrom as da0 is still present with this patch.

Index: qemu/hw/ide.c
@@ -430,6 +430,8 @@
         put_le16(p + 59, 0x100 | s->mult_sectors);
     put_le16(p + 60, s->nb_sectors);
     put_le16(p + 61, s->nb_sectors >> 16);
+    put_le16(p + 63, 0x07 | 0x4 << 8); /* Multiword DMA supported/selected */
+    put_le16(p + 64, 0x3f); /* PIO modes supported */
     put_le16(p + 80, (1 << 1) | (1 << 2));
     put_le16(p + 82, (1 << 14));
     put_le16(p + 83, (1 << 14));
@@ -437,7 +439,7 @@
     put_le16(p + 85, (1 << 14));
     put_le16(p + 86, 0);
     put_le16(p + 87, (1 << 14));
-    put_le16(p + 88, 0x1f | (1 << 13));
+    put_le16(p + 88, 0x3f /*| (0x20 << 8)*/); /* UltraDMA modes 
supported/selected */
     put_le16(p + 93, 1 | (1 << 14) | 0x2000 | 0x4000);
 }
 
@@ -458,10 +460,10 @@
     padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
     padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */
     put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
-    put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
-    put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
-    put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
-    put_le16(p + 64, 1); /* PIO modes */
+    put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
+    put_le16(p + 53, 7); /* words 64-70, 54-58, 88 valid */
+    put_le16(p + 63, 7 | 0x4 << 8); /* Multiword DMA supported/selected */
+    put_le16(p + 64, 0x3f); /* PIO modes supported */
     put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
     put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
     put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
@@ -471,6 +473,7 @@
     put_le16(p + 72, 30); /* in ns */
 
     put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
+    put_le16(p + 88, 0x3f /*| 0x20 << 8*/); /* UltraDMA modes 
supported/selected */
 }
 
 static void ide_set_signature(IDEState *s)
@@ -500,6 +503,10 @@
 static inline void ide_set_irq(IDEState *s)
 {
     if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
+       BMDMAState *bm = s->bmdma;
+       if(bm)
+           bm->status |= BM_STATUS_INT;
+
 #ifdef TARGET_PPC
         if (s->openpic) 
             openpic_set_irq(s->openpic, s->irq, 1);
@@ -2142,6 +2149,12 @@
     }
 }
 
+
+// PCI 0x04: command(word), 0x06(word): status
+#define PCI_COMMAND_IOACCESS                0x0001
+#define PCI_COMMAND_MEMACCESS               0x0002
+#define PCI_COMMAND_BUSMASTER               0x0004
+
 /* hd_table must contain 4 block drivers */
 void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table)
 {
@@ -2202,6 +2215,9 @@
     pci_conf[0x01] = 0x80;
     pci_conf[0x02] = 0x10;
     pci_conf[0x03] = 0x70;
+    pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS \
+       | PCI_COMMAND_BUSMASTER;
+    pci_conf[0x09] = 0x8a; // programming interface = PCI_IDE bus master is 
supported
     pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
     pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
     pci_conf[0x0e] = 0x00; // header_type




reply via email to

[Prev in Thread] Current Thread [Next in Thread]