Annotation of qemu/hw/versatilepb.c, revision 1.1.1.6

1.1.1.4   root        1: /*
1.1       root        2:  * ARM Versatile Platform/Application Baseboard System emulation.
                      3:  *
1.1.1.4   root        4:  * Copyright (c) 2005-2007 CodeSourcery.
1.1       root        5:  * Written by Paul Brook
                      6:  *
                      7:  * This code is licenced under the GPL.
                      8:  */
                      9: 
1.1.1.6 ! root       10: #include "sysbus.h"
1.1.1.4   root       11: #include "arm-misc.h"
                     12: #include "primecell.h"
                     13: #include "devices.h"
                     14: #include "net.h"
                     15: #include "sysemu.h"
                     16: #include "pci.h"
                     17: #include "boards.h"
1.1       root       18: 
                     19: /* Primary interrupt controller.  */
                     20: 
                     21: typedef struct vpb_sic_state
                     22: {
1.1.1.6 ! root       23:   SysBusDevice busdev;
1.1       root       24:   uint32_t level;
                     25:   uint32_t mask;
                     26:   uint32_t pic_enable;
1.1.1.6 ! root       27:   qemu_irq parent[32];
1.1       root       28:   int irq;
                     29: } vpb_sic_state;
                     30: 
                     31: static void vpb_sic_update(vpb_sic_state *s)
                     32: {
                     33:     uint32_t flags;
                     34: 
                     35:     flags = s->level & s->mask;
1.1.1.4   root       36:     qemu_set_irq(s->parent[s->irq], flags != 0);
1.1       root       37: }
                     38: 
                     39: static void vpb_sic_update_pic(vpb_sic_state *s)
                     40: {
                     41:     int i;
                     42:     uint32_t mask;
                     43: 
                     44:     for (i = 21; i <= 30; i++) {
                     45:         mask = 1u << i;
                     46:         if (!(s->pic_enable & mask))
                     47:             continue;
1.1.1.4   root       48:         qemu_set_irq(s->parent[i], (s->level & mask) != 0);
1.1       root       49:     }
                     50: }
                     51: 
                     52: static void vpb_sic_set_irq(void *opaque, int irq, int level)
                     53: {
                     54:     vpb_sic_state *s = (vpb_sic_state *)opaque;
                     55:     if (level)
                     56:         s->level |= 1u << irq;
                     57:     else
                     58:         s->level &= ~(1u << irq);
                     59:     if (s->pic_enable & (1u << irq))
1.1.1.4   root       60:         qemu_set_irq(s->parent[irq], level);
1.1       root       61:     vpb_sic_update(s);
                     62: }
                     63: 
                     64: static uint32_t vpb_sic_read(void *opaque, target_phys_addr_t offset)
                     65: {
                     66:     vpb_sic_state *s = (vpb_sic_state *)opaque;
                     67: 
                     68:     switch (offset >> 2) {
                     69:     case 0: /* STATUS */
                     70:         return s->level & s->mask;
                     71:     case 1: /* RAWSTAT */
                     72:         return s->level;
                     73:     case 2: /* ENABLE */
                     74:         return s->mask;
                     75:     case 4: /* SOFTINT */
                     76:         return s->level & 1;
                     77:     case 8: /* PICENABLE */
                     78:         return s->pic_enable;
                     79:     default:
1.1.1.3   root       80:         printf ("vpb_sic_read: Bad register offset 0x%x\n", (int)offset);
1.1       root       81:         return 0;
                     82:     }
                     83: }
                     84: 
                     85: static void vpb_sic_write(void *opaque, target_phys_addr_t offset,
                     86:                           uint32_t value)
                     87: {
                     88:     vpb_sic_state *s = (vpb_sic_state *)opaque;
                     89: 
                     90:     switch (offset >> 2) {
                     91:     case 2: /* ENSET */
                     92:         s->mask |= value;
                     93:         break;
                     94:     case 3: /* ENCLR */
                     95:         s->mask &= ~value;
                     96:         break;
                     97:     case 4: /* SOFTINTSET */
                     98:         if (value)
                     99:             s->mask |= 1;
                    100:         break;
                    101:     case 5: /* SOFTINTCLR */
                    102:         if (value)
                    103:             s->mask &= ~1u;
                    104:         break;
                    105:     case 8: /* PICENSET */
                    106:         s->pic_enable |= (value & 0x7fe00000);
                    107:         vpb_sic_update_pic(s);
                    108:         break;
                    109:     case 9: /* PICENCLR */
                    110:         s->pic_enable &= ~value;
                    111:         vpb_sic_update_pic(s);
                    112:         break;
                    113:     default:
1.1.1.3   root      114:         printf ("vpb_sic_write: Bad register offset 0x%x\n", (int)offset);
1.1       root      115:         return;
                    116:     }
                    117:     vpb_sic_update(s);
                    118: }
                    119: 
                    120: static CPUReadMemoryFunc *vpb_sic_readfn[] = {
                    121:    vpb_sic_read,
                    122:    vpb_sic_read,
                    123:    vpb_sic_read
                    124: };
                    125: 
                    126: static CPUWriteMemoryFunc *vpb_sic_writefn[] = {
                    127:    vpb_sic_write,
                    128:    vpb_sic_write,
                    129:    vpb_sic_write
                    130: };
                    131: 
1.1.1.6 ! root      132: static void vpb_sic_init(SysBusDevice *dev)
1.1       root      133: {
1.1.1.6 ! root      134:     vpb_sic_state *s = FROM_SYSBUS(vpb_sic_state, dev);
1.1       root      135:     int iomemtype;
1.1.1.6 ! root      136:     int i;
1.1       root      137: 
1.1.1.6 ! root      138:     qdev_init_gpio_in(&dev->qdev, vpb_sic_set_irq, 32);
        !           139:     for (i = 0; i < 32; i++) {
        !           140:         sysbus_init_irq(dev, &s->parent[i]);
        !           141:     }
        !           142:     s->irq = 31;
        !           143:     iomemtype = cpu_register_io_memory(vpb_sic_readfn,
1.1       root      144:                                        vpb_sic_writefn, s);
1.1.1.6 ! root      145:     sysbus_init_mmio(dev, 0x1000, iomemtype);
1.1       root      146:     /* ??? Save/restore.  */
                    147: }
                    148: 
                    149: /* Board init.  */
                    150: 
                    151: /* The AB and PB boards both use the same core, just with different
                    152:    peripherans and expansion busses.  For now we emulate a subset of the
                    153:    PB peripherals and just change the board ID.  */
                    154: 
1.1.1.5   root      155: static struct arm_boot_info versatile_binfo;
                    156: 
1.1.1.6 ! root      157: static void versatile_init(ram_addr_t ram_size,
1.1.1.5   root      158:                      const char *boot_device,
1.1       root      159:                      const char *kernel_filename, const char *kernel_cmdline,
1.1.1.4   root      160:                      const char *initrd_filename, const char *cpu_model,
                    161:                      int board_id)
1.1       root      162: {
                    163:     CPUState *env;
1.1.1.6 ! root      164:     ram_addr_t ram_offset;
        !           165:     qemu_irq *cpu_pic;
        !           166:     qemu_irq pic[32];
        !           167:     qemu_irq sic[32];
        !           168:     DeviceState *dev;
1.1.1.2   root      169:     PCIBus *pci_bus;
                    170:     NICInfo *nd;
                    171:     int n;
                    172:     int done_smc = 0;
1.1       root      173: 
1.1.1.4   root      174:     if (!cpu_model)
                    175:         cpu_model = "arm926";
                    176:     env = cpu_init(cpu_model);
                    177:     if (!env) {
                    178:         fprintf(stderr, "Unable to find CPU definition\n");
                    179:         exit(1);
                    180:     }
1.1.1.6 ! root      181:     ram_offset = qemu_ram_alloc(ram_size);
1.1.1.5   root      182:     /* ??? RAM should repeat to fill physical memory space.  */
1.1       root      183:     /* SDRAM at address zero.  */
1.1.1.6 ! root      184:     cpu_register_physical_memory(0, ram_size, ram_offset | IO_MEM_RAM);
1.1       root      185: 
1.1.1.3   root      186:     arm_sysctl_init(0x10000000, 0x41007004);
1.1.1.6 ! root      187:     cpu_pic = arm_pic_init_cpu(env);
        !           188:     dev = sysbus_create_varargs("pl190", 0x10140000,
        !           189:                                 cpu_pic[0], cpu_pic[1], NULL);
        !           190:     for (n = 0; n < 32; n++) {
        !           191:         pic[n] = qdev_get_gpio_in(dev, n);
        !           192:     }
        !           193:     dev = sysbus_create_simple("versatilepb_sic", 0x10003000, NULL);
        !           194:     for (n = 0; n < 32; n++) {
        !           195:         sysbus_connect_irq(sysbus_from_qdev(dev), n, pic[n]);
        !           196:         sic[n] = qdev_get_gpio_in(dev, n);
        !           197:     }
        !           198: 
        !           199:     sysbus_create_simple("pl050_keyboard", 0x10006000, sic[3]);
        !           200:     sysbus_create_simple("pl050_mouse", 0x10007000, sic[4]);
        !           201: 
        !           202:     dev = sysbus_create_varargs("versatile_pci", 0x40000000,
        !           203:                                 sic[27], sic[28], sic[29], sic[30], NULL);
        !           204:     pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci");
1.1       root      205: 
1.1.1.2   root      206:     /* The Versatile PCI bridge does not provide access to PCI IO space,
                    207:        so many of the qemu PCI devices are not useable.  */
                    208:     for(n = 0; n < nb_nics; n++) {
                    209:         nd = &nd_table[n];
1.1.1.5   root      210: 
                    211:         if ((!nd->model && !done_smc) || strcmp(nd->model, "smc91c111") == 0) {
1.1.1.4   root      212:             smc91c111_init(nd, 0x10010000, sic[25]);
1.1.1.5   root      213:             done_smc = 1;
1.1       root      214:         } else {
1.1.1.6 ! root      215:             pci_nic_init(nd, "rtl8139", NULL);
1.1.1.2   root      216:         }
                    217:     }
                    218:     if (usb_enabled) {
1.1.1.4   root      219:         usb_ohci_init_pci(pci_bus, 3, -1);
                    220:     }
1.1.1.6 ! root      221:     n = drive_get_max_bus(IF_SCSI);
        !           222:     while (n >= 0) {
        !           223:         pci_create_simple(pci_bus, -1, "lsi53c895a");
        !           224:         n--;
1.1       root      225:     }
                    226: 
1.1.1.6 ! root      227:     sysbus_create_simple("pl011", 0x101f1000, pic[12]);
        !           228:     sysbus_create_simple("pl011", 0x101f2000, pic[13]);
        !           229:     sysbus_create_simple("pl011", 0x101f3000, pic[14]);
        !           230:     sysbus_create_simple("pl011", 0x10009000, sic[6]);
        !           231: 
        !           232:     sysbus_create_simple("pl080", 0x10130000, pic[17]);
        !           233:     sysbus_create_simple("sp804", 0x101e2000, pic[4]);
        !           234:     sysbus_create_simple("sp804", 0x101e3000, pic[5]);
1.1       root      235: 
                    236:     /* The versatile/PB actually has a modified Color LCD controller
                    237:        that includes hardware cursor support from the PL111.  */
1.1.1.6 ! root      238:     sysbus_create_simple("pl110_versatile", 0x10120000, pic[16]);
1.1.1.4   root      239: 
1.1.1.6 ! root      240:     sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
        !           241:     sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
1.1.1.4   root      242: 
                    243:     /* Add PL031 Real Time Clock. */
1.1.1.6 ! root      244:     sysbus_create_simple("pl031", 0x101e8000, pic[10]);
1.1       root      245: 
                    246:     /* Memory map for Versatile/PB:  */
                    247:     /* 0x10000000 System registers.  */
                    248:     /* 0x10001000 PCI controller config registers.  */
                    249:     /* 0x10002000 Serial bus interface.  */
                    250:     /*  0x10003000 Secondary interrupt controller.  */
                    251:     /* 0x10004000 AACI (audio).  */
1.1.1.4   root      252:     /*  0x10005000 MMCI0.  */
1.1       root      253:     /*  0x10006000 KMI0 (keyboard).  */
                    254:     /*  0x10007000 KMI1 (mouse).  */
                    255:     /* 0x10008000 Character LCD Interface.  */
                    256:     /*  0x10009000 UART3.  */
                    257:     /* 0x1000a000 Smart card 1.  */
1.1.1.4   root      258:     /*  0x1000b000 MMCI1.  */
1.1       root      259:     /*  0x10010000 Ethernet.  */
                    260:     /* 0x10020000 USB.  */
                    261:     /* 0x10100000 SSMC.  */
                    262:     /* 0x10110000 MPMC.  */
                    263:     /*  0x10120000 CLCD Controller.  */
                    264:     /*  0x10130000 DMA Controller.  */
                    265:     /*  0x10140000 Vectored interrupt controller.  */
                    266:     /* 0x101d0000 AHB Monitor Interface.  */
                    267:     /* 0x101e0000 System Controller.  */
                    268:     /* 0x101e1000 Watchdog Interface.  */
                    269:     /* 0x101e2000 Timer 0/1.  */
                    270:     /* 0x101e3000 Timer 2/3.  */
                    271:     /* 0x101e4000 GPIO port 0.  */
                    272:     /* 0x101e5000 GPIO port 1.  */
                    273:     /* 0x101e6000 GPIO port 2.  */
                    274:     /* 0x101e7000 GPIO port 3.  */
                    275:     /* 0x101e8000 RTC.  */
                    276:     /* 0x101f0000 Smart card 0.  */
                    277:     /*  0x101f1000 UART0.  */
                    278:     /*  0x101f2000 UART1.  */
                    279:     /*  0x101f3000 UART2.  */
                    280:     /* 0x101f4000 SSPI.  */
                    281: 
1.1.1.5   root      282:     versatile_binfo.ram_size = ram_size;
                    283:     versatile_binfo.kernel_filename = kernel_filename;
                    284:     versatile_binfo.kernel_cmdline = kernel_cmdline;
                    285:     versatile_binfo.initrd_filename = initrd_filename;
                    286:     versatile_binfo.board_id = board_id;
                    287:     arm_load_kernel(env, &versatile_binfo);
1.1       root      288: }
                    289: 
1.1.1.6 ! root      290: static void vpb_init(ram_addr_t ram_size,
1.1.1.5   root      291:                      const char *boot_device,
1.1       root      292:                      const char *kernel_filename, const char *kernel_cmdline,
1.1.1.4   root      293:                      const char *initrd_filename, const char *cpu_model)
1.1       root      294: {
1.1.1.6 ! root      295:     versatile_init(ram_size,
1.1.1.5   root      296:                    boot_device,
1.1       root      297:                    kernel_filename, kernel_cmdline,
1.1.1.4   root      298:                    initrd_filename, cpu_model, 0x183);
1.1       root      299: }
                    300: 
1.1.1.6 ! root      301: static void vab_init(ram_addr_t ram_size,
1.1.1.5   root      302:                      const char *boot_device,
1.1       root      303:                      const char *kernel_filename, const char *kernel_cmdline,
1.1.1.4   root      304:                      const char *initrd_filename, const char *cpu_model)
1.1       root      305: {
1.1.1.6 ! root      306:     versatile_init(ram_size,
1.1.1.5   root      307:                    boot_device,
1.1       root      308:                    kernel_filename, kernel_cmdline,
1.1.1.4   root      309:                    initrd_filename, cpu_model, 0x25e);
1.1       root      310: }
                    311: 
1.1.1.6 ! root      312: static QEMUMachine versatilepb_machine = {
1.1.1.5   root      313:     .name = "versatilepb",
                    314:     .desc = "ARM Versatile/PB (ARM926EJ-S)",
                    315:     .init = vpb_init,
                    316:     .use_scsi = 1,
1.1       root      317: };
                    318: 
1.1.1.6 ! root      319: static QEMUMachine versatileab_machine = {
1.1.1.5   root      320:     .name = "versatileab",
                    321:     .desc = "ARM Versatile/AB (ARM926EJ-S)",
                    322:     .init = vab_init,
                    323:     .use_scsi = 1,
1.1       root      324: };
1.1.1.6 ! root      325: 
        !           326: static void versatile_machine_init(void)
        !           327: {
        !           328:     qemu_register_machine(&versatilepb_machine);
        !           329:     qemu_register_machine(&versatileab_machine);
        !           330: }
        !           331: 
        !           332: machine_init(versatile_machine_init);
        !           333: 
        !           334: static void versatilepb_register_devices(void)
        !           335: {
        !           336:     sysbus_register_dev("versatilepb_sic", sizeof(vpb_sic_state),
        !           337:                         vpb_sic_init);
        !           338: }
        !           339: 
        !           340: device_init(versatilepb_register_devices)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.