2012年11月16日金曜日

a800eva qemu 偽IO追加

かなり面白い記事発見。
http://myokota.github.com/qemu-a800eva/
Armadillo800EVA のQEMU エミュレータが公開されています。
initramfs で動作する例がしめされています。

ここでは、偽IOを仕立て、CF-IDEとLAN9118を追加し、FileSystemとNetworkを利用可能にします。
--- qemu-a800eva-master/hw/a800eva.c    Wed Aug 08 03:58:20 2012
+++ qemu-a800eva-master/hw/a800eva.c
@@ -16,6 +16,11 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 #include "boards.h"
+#include "loader.h"
+#include "devices.h"
+#include "net.h"
+#include "ide.h"
+#include "blockdev.h"
 
 #define SDRAM_START                     (0x40000000)
 #define SDRAM_SIZE                      (0x20000000)
@@ -47,6 +52,7 @@
     MemoryRegion *sram = g_new(MemoryRegion, 1);
     DeviceState *dev;
     SysBusDevice *busdev;
+    DriveInfo *dinfo;
     qemu_irq *irqp;
     qemu_irq pic[128];
     qemu_irq cpu_irq;
@@ -95,6 +101,15 @@
     sysbus_create_varargs("sh,cmt", 0xe6138000, 
                           pic[58], pic[59], pic[60], 
                           pic[61], pic[62], NULL);
+
+/* IDE */
+    dinfo = drive_get(IF_IDE,0,0);
+    mmio_ide_init(0xe9201000, 0xe920200c, sysmem, pic[65], 1,
+        dinfo, NULL);/* ATAPI IRQ */
+/* GbEther */
+    if(nd_table[0].used) {
+        lan9118_init(&nd_table[0],0xe9200000,pic[110]);
+    }
 
     a800_binfo.ram_size = ram_size;
     a800_binfo.kernel_filename = kernel_filename;


---------------------------------------------------------------

--- linux-2.6.35-a800eva-at3/arch/arm/mach-shmobile/board-armadillo800eva.c    Fri Jul 27 16:00:51 2012
+++ linux-2.6.35-a800eva-at3/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -42,6 +42,8 @@
 #include <media/soc_camera.h>
 #include <media/soc_camera_platform.h>
 
+#include <linux/ata_platform.h>
+
 #include <video/sh_mobile_lcdc.h>
 #include <sound/sh_fsi.h>
 
@@ -62,40 +64,66 @@
     __raw_writeb(0x00, addr);
 }
 
-static struct sh_eth_plat_data sh_eth_platdata = {
-    .phy = 0x00,
-    .edmac_endian = EDMAC_LITTLE_ENDIAN,
-    .register_type = SH_ETH_REG_GIGABIT,
+static struct smsc911x_platform_config smsc_eth_platdata = {
+    .flags = SMSC911X_USE_32BIT,
+    .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+    .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL,
     .phy_interface = PHY_INTERFACE_MODE_MII,
 };
 
-static struct resource sh_eth_resources[] = {
-    {
-        .start = 0xe9a00000,
-        .end = 0xe9a00800 - 1,
-        .flags = IORESOURCE_MEM,
-    },
+static struct resource smsc_eth_resources[] = {
     {
-        .start = 0xe9a01800,
-        .end = 0xe9a02000 - 1,
+        .start = 0xe9200000,
+        .end =   0xe9200fff,
         .flags = IORESOURCE_MEM,
     },
     {
-        .start = gic_spi(110),
+        .start = gic_spi(110), /* GbEth */
         .flags = IORESOURCE_IRQ,
     },
 };
 
 static struct platform_device eth_device = {
-    .name = "sh-eth",
-    .id = 0,
+    .name = "smsc911x",
+    .id = -1,
     .dev = {
-        .platform_data = &sh_eth_platdata,
+        .platform_data = &smsc_eth_platdata,
+    },
+    .resource = smsc_eth_resources,
+    .num_resources = ARRAY_SIZE(smsc_eth_resources),
+};
+
+static struct resource cf_ide_resources[] = {
+    [0] = {
+        .start = 0xe9200000 + 0x1000,    
+        .end   = 0xe9200000 + 0x1000 + 0x10 - 0x2,
+        .flags = IORESOURCE_MEM,
+    },
+    [1] = {
+        .start = 0xe9200000 + 0x200c,
+        .end   = 0xe9200000 + 0x200c,
+        .flags = IORESOURCE_MEM,
+    },
+    [2] = {
+        .start = gic_spi(65), /* ATAPI */
+        .flags = IORESOURCE_IRQ,
     },
-    .resource = sh_eth_resources,
-    .num_resources = ARRAY_SIZE(sh_eth_resources),
 };
 
+static struct pata_platform_info pata_info = {
+    .ioport_shift = 1,
+};
+
+static struct platform_device cf_ide_device = {
+    .name = "pata_platform",
+    .id = -1,
+    .num_resources = ARRAY_SIZE(cf_ide_resources),
+    .resource = cf_ide_resources,
+    .dev = {
+        .platform_data = &pata_info,
+    },
+};
+#ifdef CONFIG_MMC
 static void sdhi0_set_pwr(struct platform_device *pdev, int state)
 {
     /* todo */
@@ -271,7 +299,7 @@
     .num_resources    = ARRAY_SIZE(sh_mmcif_resources),
     .resource    = sh_mmcif_resources,
 };
-
+#endif
 static struct sh_fsi_dma sh_fsi2_dma = {
     .dma_porta_tx = {
         .slave_id    = SHDMA_SLAVE_FSIA_TX,
@@ -1065,9 +1093,12 @@
 
 static struct platform_device *rma1evb_devices[] __initdata = {
     &eth_device,
+    &cf_ide_device, /* QEMU */
+#ifdef CONFIG_MMC
     &sh_mmcif_device,
     &sdhi0_device,
     &sdhi1_device,
+#endif
     &ohci_device,
     &ehci_device,
     &hdmi_device,
---------------------------------------------------------------
注意点
linux 側 Config
メモリ設定を256Mbyte(0x10000000)
CD-IDEは Device->ATA->Plaform Driver for IDE interface
LAN9118はDevice->Network->Ethernet(19..)->SMSC_LAN911x/LAN921x

rootfsの作成は以下を参考にしました。
http://memo.saitodev.com/home/arm/arm_emulation/

/dev/mapper/nbd0p1 に
debian-squeeze_xxx20120727.tar.gz
を展開します。

---------------------------------------------------------------
起動例
./qemu-a800eva-master/arm-softmmu/qemu-system-arm \
    -m 256M -M a800eva \
    -kernel ./linux-2.6.35-a800eva-at3/arch/arm/boot/uImage \
    -hda hda.qcow2 \
    -append "console=ttySC1 root=/dev/hda1" \
    -nographic \
    -serial telnet:0.0.0.0:1200,server \
    -net nic,model=lan9118 \
    -net user -redir tcp:5555::22

guest OSが起動できたら
/etc/network/interfaces ?に
 allow-hotplug eth0
 iface eth0 inet dhcp

を追加し、再起動し、その後 時刻設定を行い、
#apt-get update 
# apt-get install ssh
など行います。
[記事が壊れたので、再投稿 2012.11.16]