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

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