Merge remote-tracking branch 'agraf/ppc-for-upstream' into staging
# By Alexander Graf (16) and others # Via Alexander Graf * agraf/ppc-for-upstream: (22 commits) PPC: dbdma: Support more multi-issue DMA requests PPC: Add timer handler for newworld mac-io PPC: dbdma: Support unaligned DMA access PPC: dbdma: Wait for DMA until we have data PPC: dbdma: Move processing to io PPC: dbdma: macio: Add DMA callback PPC: dbdma: Move static bh variable to device struct PPC: dbdma: Introduce kick function PPC: dbdma: Move defines into header file PPC: dbdma: Allow new commands in RUN state PPC: dbdma: Fix debug print PPC: Mac: Add debug prints in macio and dbdma code PPC: dbdma: Replace tabs with spaces PPC: Macio: Replace tabs with spaces PPC: g3beige: Move secondary IDE bus to mac-io PPC: Mac: Fix guest exported tbfreq values target-ppc: Add POWER8 v1.0 CPU model pseries: move interrupt controllers to hw/intc/ spapr: Respect -bios command line option for SLOF spapr: Use named enum for function remove_hpte ... Message-id: 1373562085-29728-1-git-send-email-agraf@suse.de Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
		
						commit
						25ca6a1f5a
					
				| @ -45,5 +45,7 @@ CONFIG_OPENPIC=y | |||||||
| CONFIG_PSERIES=y | CONFIG_PSERIES=y | ||||||
| CONFIG_E500=y | CONFIG_E500=y | ||||||
| CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) | CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) | ||||||
|  | # For pSeries
 | ||||||
|  | CONFIG_XICS=$(CONFIG_PSERIES) | ||||||
| # For PReP
 | # For PReP
 | ||||||
| CONFIG_MC146818RTC=y | CONFIG_MC146818RTC=y | ||||||
|  | |||||||
							
								
								
									
										245
									
								
								hw/ide/macio.c
									
									
									
									
									
								
							
							
						
						
									
										245
									
								
								hw/ide/macio.c
									
									
									
									
									
								
							| @ -30,6 +30,22 @@ | |||||||
| 
 | 
 | ||||||
| #include <hw/ide/internal.h> | #include <hw/ide/internal.h> | ||||||
| 
 | 
 | ||||||
|  | /* debug MACIO */ | ||||||
|  | // #define DEBUG_MACIO
 | ||||||
|  | 
 | ||||||
|  | #ifdef DEBUG_MACIO | ||||||
|  | static const int debug_macio = 1; | ||||||
|  | #else | ||||||
|  | static const int debug_macio = 0; | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #define MACIO_DPRINTF(fmt, ...) do { \ | ||||||
|  |         if (debug_macio) { \ | ||||||
|  |             printf(fmt , ## __VA_ARGS__); \ | ||||||
|  |         } \ | ||||||
|  |     } while (0) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| /***********************************************************/ | /***********************************************************/ | ||||||
| /* MacIO based PowerPC IDE */ | /* MacIO based PowerPC IDE */ | ||||||
| 
 | 
 | ||||||
| @ -40,14 +56,26 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) | |||||||
|     DBDMA_io *io = opaque; |     DBDMA_io *io = opaque; | ||||||
|     MACIOIDEState *m = io->opaque; |     MACIOIDEState *m = io->opaque; | ||||||
|     IDEState *s = idebus_active_if(&m->bus); |     IDEState *s = idebus_active_if(&m->bus); | ||||||
|  |     int unaligned; | ||||||
| 
 | 
 | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         m->aiocb = NULL; |         m->aiocb = NULL; | ||||||
|         qemu_sglist_destroy(&s->sg); |         qemu_sglist_destroy(&s->sg); | ||||||
|         ide_atapi_io_error(s, ret); |         ide_atapi_io_error(s, ret); | ||||||
|  |         io->remainder_len = 0; | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (!m->dma_active) { | ||||||
|  |         MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | ||||||
|  |                       s->nsector, io->len, s->status); | ||||||
|  |         /* data not ready yet, wait for the channel to get restarted */ | ||||||
|  |         io->processing = false; | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size); | ||||||
|  | 
 | ||||||
|     if (s->io_buffer_size > 0) { |     if (s->io_buffer_size > 0) { | ||||||
|         m->aiocb = NULL; |         m->aiocb = NULL; | ||||||
|         qemu_sglist_destroy(&s->sg); |         qemu_sglist_destroy(&s->sg); | ||||||
| @ -55,33 +83,94 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) | |||||||
|         s->packet_transfer_size -= s->io_buffer_size; |         s->packet_transfer_size -= s->io_buffer_size; | ||||||
| 
 | 
 | ||||||
|         s->io_buffer_index += s->io_buffer_size; |         s->io_buffer_index += s->io_buffer_size; | ||||||
| 	s->lba += s->io_buffer_index >> 11; |         s->lba += s->io_buffer_index >> 11; | ||||||
|         s->io_buffer_index &= 0x7ff; |         s->io_buffer_index &= 0x7ff; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (s->packet_transfer_size <= 0) |     s->io_buffer_size = MIN(io->len, s->packet_transfer_size); | ||||||
|  | 
 | ||||||
|  |     MACIO_DPRINTF("remainder: %d io->len: %d size: %d\n", io->remainder_len, | ||||||
|  |                   io->len, s->packet_transfer_size); | ||||||
|  |     if (io->remainder_len && io->len) { | ||||||
|  |         /* guest wants the rest of its previous transfer */ | ||||||
|  |         int remainder_len = MIN(io->remainder_len, io->len); | ||||||
|  | 
 | ||||||
|  |         MACIO_DPRINTF("copying remainder %d bytes\n", remainder_len); | ||||||
|  | 
 | ||||||
|  |         cpu_physical_memory_write(io->addr, io->remainder + 0x200 - | ||||||
|  |                                   remainder_len, remainder_len); | ||||||
|  | 
 | ||||||
|  |         io->addr += remainder_len; | ||||||
|  |         io->len -= remainder_len; | ||||||
|  |         s->io_buffer_size = remainder_len; | ||||||
|  |         io->remainder_len -= remainder_len; | ||||||
|  |         /* treat remainder as individual transfer, start again */ | ||||||
|  |         qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, | ||||||
|  |                          &address_space_memory); | ||||||
|  |         pmac_ide_atapi_transfer_cb(opaque, 0); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (!s->packet_transfer_size) { | ||||||
|  |         MACIO_DPRINTF("end of transfer\n"); | ||||||
|         ide_atapi_cmd_ok(s); |         ide_atapi_cmd_ok(s); | ||||||
|  |         m->dma_active = false; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (io->len == 0) { |     if (io->len == 0) { | ||||||
|  |         MACIO_DPRINTF("end of DMA\n"); | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* launch next transfer */ |     /* launch next transfer */ | ||||||
| 
 | 
 | ||||||
|     s->io_buffer_size = io->len; |     /* handle unaligned accesses first, get them over with and only do the
 | ||||||
|  |        remaining bulk transfer using our async DMA helpers */ | ||||||
|  |     unaligned = io->len & 0x1ff; | ||||||
|  |     if (unaligned) { | ||||||
|  |         int sector_num = (s->lba << 2) + (s->io_buffer_index >> 9); | ||||||
|  |         int nsector = io->len >> 9; | ||||||
|  | 
 | ||||||
|  |         MACIO_DPRINTF("precopying unaligned %d bytes to %#lx\n", | ||||||
|  |                       unaligned, io->addr + io->len - unaligned); | ||||||
|  | 
 | ||||||
|  |         bdrv_read(s->bs, sector_num + nsector, io->remainder, 1); | ||||||
|  |         cpu_physical_memory_write(io->addr + io->len - unaligned, | ||||||
|  |                                   io->remainder, unaligned); | ||||||
|  | 
 | ||||||
|  |         io->len -= unaligned; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     MACIO_DPRINTF("io->len = %#x\n", io->len); | ||||||
| 
 | 
 | ||||||
|     qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, |     qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, | ||||||
|                      &address_space_memory); |                      &address_space_memory); | ||||||
|     qemu_sglist_add(&s->sg, io->addr, io->len); |     qemu_sglist_add(&s->sg, io->addr, io->len); | ||||||
|     io->addr += io->len; |     io->addr += s->io_buffer_size; | ||||||
|  |     io->remainder_len = MIN(s->packet_transfer_size - s->io_buffer_size, | ||||||
|  |                             (0x200 - unaligned) & 0x1ff); | ||||||
|  |     MACIO_DPRINTF("set remainder to: %d\n", io->remainder_len); | ||||||
|  | 
 | ||||||
|  |     /* We would read no data from the block layer, thus not get a callback.
 | ||||||
|  |        Just fake completion manually. */ | ||||||
|  |     if (!io->len) { | ||||||
|  |         pmac_ide_atapi_transfer_cb(opaque, 0); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     io->len = 0; |     io->len = 0; | ||||||
| 
 | 
 | ||||||
|  |     MACIO_DPRINTF("sector_num=%d size=%d, cmd_cmd=%d\n", | ||||||
|  |                   (s->lba << 2) + (s->io_buffer_index >> 9), | ||||||
|  |                   s->packet_transfer_size, s->dma_cmd); | ||||||
|  | 
 | ||||||
|     m->aiocb = dma_bdrv_read(s->bs, &s->sg, |     m->aiocb = dma_bdrv_read(s->bs, &s->sg, | ||||||
|                              (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), |                              (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), | ||||||
|                              pmac_ide_atapi_transfer_cb, io); |                              pmac_ide_atapi_transfer_cb, io); | ||||||
|     return; |     return; | ||||||
| 
 | 
 | ||||||
| done: | done: | ||||||
|  |     MACIO_DPRINTF("done DMA\n"); | ||||||
|     bdrv_acct_done(s->bs, &s->acct); |     bdrv_acct_done(s->bs, &s->acct); | ||||||
|     io->dma_end(opaque); |     io->dma_end(opaque); | ||||||
| } | } | ||||||
| @ -91,17 +180,29 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) | |||||||
|     DBDMA_io *io = opaque; |     DBDMA_io *io = opaque; | ||||||
|     MACIOIDEState *m = io->opaque; |     MACIOIDEState *m = io->opaque; | ||||||
|     IDEState *s = idebus_active_if(&m->bus); |     IDEState *s = idebus_active_if(&m->bus); | ||||||
|     int n; |     int n = 0; | ||||||
|     int64_t sector_num; |     int64_t sector_num; | ||||||
|  |     int unaligned; | ||||||
| 
 | 
 | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|  |         MACIO_DPRINTF("DMA error\n"); | ||||||
|         m->aiocb = NULL; |         m->aiocb = NULL; | ||||||
|         qemu_sglist_destroy(&s->sg); |         qemu_sglist_destroy(&s->sg); | ||||||
| 	ide_dma_error(s); |         ide_dma_error(s); | ||||||
|  |         io->remainder_len = 0; | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (!m->dma_active) { | ||||||
|  |         MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | ||||||
|  |                       s->nsector, io->len, s->status); | ||||||
|  |         /* data not ready yet, wait for the channel to get restarted */ | ||||||
|  |         io->processing = false; | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     sector_num = ide_get_sector(s); |     sector_num = ide_get_sector(s); | ||||||
|  |     MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size); | ||||||
|     if (s->io_buffer_size > 0) { |     if (s->io_buffer_size > 0) { | ||||||
|         m->aiocb = NULL; |         m->aiocb = NULL; | ||||||
|         qemu_sglist_destroy(&s->sg); |         qemu_sglist_destroy(&s->sg); | ||||||
| @ -111,36 +212,105 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) | |||||||
|         s->nsector -= n; |         s->nsector -= n; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* end of transfer ? */ |     MACIO_DPRINTF("remainder: %d io->len: %d nsector: %d sector_num: %ld\n", | ||||||
|     if (s->nsector == 0) { |                   io->remainder_len, io->len, s->nsector, sector_num); | ||||||
|         s->status = READY_STAT | SEEK_STAT; |     if (io->remainder_len && io->len) { | ||||||
|         ide_set_irq(s->bus); |         /* guest wants the rest of its previous transfer */ | ||||||
|  |         int remainder_len = MIN(io->remainder_len, io->len); | ||||||
|  |         uint8_t *p = &io->remainder[0x200 - remainder_len]; | ||||||
|  | 
 | ||||||
|  |         MACIO_DPRINTF("copying remainder %d bytes at %#lx\n", | ||||||
|  |                       remainder_len, io->addr); | ||||||
|  | 
 | ||||||
|  |         switch (s->dma_cmd) { | ||||||
|  |         case IDE_DMA_READ: | ||||||
|  |             cpu_physical_memory_write(io->addr, p, remainder_len); | ||||||
|  |             break; | ||||||
|  |         case IDE_DMA_WRITE: | ||||||
|  |             cpu_physical_memory_read(io->addr, p, remainder_len); | ||||||
|  |             bdrv_write(s->bs, sector_num - 1, io->remainder, 1); | ||||||
|  |             break; | ||||||
|  |         case IDE_DMA_TRIM: | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         io->addr += remainder_len; | ||||||
|  |         io->len -= remainder_len; | ||||||
|  |         io->remainder_len -= remainder_len; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (s->nsector == 0 && !io->remainder_len) { | ||||||
|  |         MACIO_DPRINTF("end of transfer\n"); | ||||||
|  |         s->status = READY_STAT | SEEK_STAT; | ||||||
|  |         ide_set_irq(s->bus); | ||||||
|  |         m->dma_active = false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* end of DMA ? */ |  | ||||||
|     if (io->len == 0) { |     if (io->len == 0) { | ||||||
|  |         MACIO_DPRINTF("end of DMA\n"); | ||||||
|         goto done; |         goto done; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* launch next transfer */ |     /* launch next transfer */ | ||||||
| 
 | 
 | ||||||
|     s->io_buffer_index = 0; |     s->io_buffer_index = 0; | ||||||
|     s->io_buffer_size = io->len; |     s->io_buffer_size = MIN(io->len, s->nsector * 512); | ||||||
|  | 
 | ||||||
|  |     /* handle unaligned accesses first, get them over with and only do the
 | ||||||
|  |        remaining bulk transfer using our async DMA helpers */ | ||||||
|  |     unaligned = io->len & 0x1ff; | ||||||
|  |     if (unaligned) { | ||||||
|  |         int nsector = io->len >> 9; | ||||||
|  | 
 | ||||||
|  |         MACIO_DPRINTF("precopying unaligned %d bytes to %#lx\n", | ||||||
|  |                       unaligned, io->addr + io->len - unaligned); | ||||||
|  | 
 | ||||||
|  |         switch (s->dma_cmd) { | ||||||
|  |         case IDE_DMA_READ: | ||||||
|  |             bdrv_read(s->bs, sector_num + nsector, io->remainder, 1); | ||||||
|  |             cpu_physical_memory_write(io->addr + io->len - unaligned, | ||||||
|  |                                       io->remainder, unaligned); | ||||||
|  |             break; | ||||||
|  |         case IDE_DMA_WRITE: | ||||||
|  |             /* cache the contents in our io struct */ | ||||||
|  |             cpu_physical_memory_read(io->addr + io->len - unaligned, | ||||||
|  |                                      io->remainder, unaligned); | ||||||
|  |             break; | ||||||
|  |         case IDE_DMA_TRIM: | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         io->len -= unaligned; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     MACIO_DPRINTF("io->len = %#x\n", io->len); | ||||||
| 
 | 
 | ||||||
|     qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, |     qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, | ||||||
|                      &address_space_memory); |                      &address_space_memory); | ||||||
|     qemu_sglist_add(&s->sg, io->addr, io->len); |     qemu_sglist_add(&s->sg, io->addr, io->len); | ||||||
|     io->addr += io->len; |     io->addr += io->len + unaligned; | ||||||
|  |     io->remainder_len = (0x200 - unaligned) & 0x1ff; | ||||||
|  |     MACIO_DPRINTF("set remainder to: %d\n", io->remainder_len); | ||||||
|  | 
 | ||||||
|  |     /* We would read no data from the block layer, thus not get a callback.
 | ||||||
|  |        Just fake completion manually. */ | ||||||
|  |     if (!io->len) { | ||||||
|  |         pmac_ide_transfer_cb(opaque, 0); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     io->len = 0; |     io->len = 0; | ||||||
| 
 | 
 | ||||||
|  |     MACIO_DPRINTF("sector_num=%" PRId64 " n=%d, nsector=%d, cmd_cmd=%d\n", | ||||||
|  |                   sector_num, n, s->nsector, s->dma_cmd); | ||||||
|  | 
 | ||||||
|     switch (s->dma_cmd) { |     switch (s->dma_cmd) { | ||||||
|     case IDE_DMA_READ: |     case IDE_DMA_READ: | ||||||
|         m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, |         m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, | ||||||
| 		                 pmac_ide_transfer_cb, io); |                                  pmac_ide_transfer_cb, io); | ||||||
|         break; |         break; | ||||||
|     case IDE_DMA_WRITE: |     case IDE_DMA_WRITE: | ||||||
|         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, |         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, | ||||||
| 		                  pmac_ide_transfer_cb, io); |                                   pmac_ide_transfer_cb, io); | ||||||
|         break; |         break; | ||||||
|     case IDE_DMA_TRIM: |     case IDE_DMA_TRIM: | ||||||
|         m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, |         m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, | ||||||
| @ -162,6 +332,8 @@ static void pmac_ide_transfer(DBDMA_io *io) | |||||||
|     MACIOIDEState *m = io->opaque; |     MACIOIDEState *m = io->opaque; | ||||||
|     IDEState *s = idebus_active_if(&m->bus); |     IDEState *s = idebus_active_if(&m->bus); | ||||||
| 
 | 
 | ||||||
|  |     MACIO_DPRINTF("\n"); | ||||||
|  | 
 | ||||||
|     s->io_buffer_size = 0; |     s->io_buffer_size = 0; | ||||||
|     if (s->drive_kind == IDE_CD) { |     if (s->drive_kind == IDE_CD) { | ||||||
|         bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); |         bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); | ||||||
| @ -322,11 +494,51 @@ static void macio_ide_reset(DeviceState *dev) | |||||||
|     ide_bus_reset(&d->bus); |     ide_bus_reset(&d->bus); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int ide_nop(IDEDMA *dma) | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int ide_nop_int(IDEDMA *dma, int x) | ||||||
|  | { | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void ide_nop_restart(void *opaque, int x, RunState y) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void ide_dbdma_start(IDEDMA *dma, IDEState *s, | ||||||
|  |                             BlockDriverCompletionFunc *cb) | ||||||
|  | { | ||||||
|  |     MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); | ||||||
|  | 
 | ||||||
|  |     MACIO_DPRINTF("\n"); | ||||||
|  |     m->dma_active = true; | ||||||
|  |     DBDMA_kick(m->dbdma); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const IDEDMAOps dbdma_ops = { | ||||||
|  |     .start_dma      = ide_dbdma_start, | ||||||
|  |     .start_transfer = ide_nop, | ||||||
|  |     .prepare_buf    = ide_nop_int, | ||||||
|  |     .rw_buf         = ide_nop_int, | ||||||
|  |     .set_unit       = ide_nop_int, | ||||||
|  |     .add_status     = ide_nop_int, | ||||||
|  |     .set_inactive   = ide_nop, | ||||||
|  |     .restart_cb     = ide_nop_restart, | ||||||
|  |     .reset          = ide_nop, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static void macio_ide_realizefn(DeviceState *dev, Error **errp) | static void macio_ide_realizefn(DeviceState *dev, Error **errp) | ||||||
| { | { | ||||||
|     MACIOIDEState *s = MACIO_IDE(dev); |     MACIOIDEState *s = MACIO_IDE(dev); | ||||||
| 
 | 
 | ||||||
|     ide_init2(&s->bus, s->irq); |     ide_init2(&s->bus, s->irq); | ||||||
|  | 
 | ||||||
|  |     /* Register DMA callbacks */ | ||||||
|  |     s->dma.ops = &dbdma_ops; | ||||||
|  |     s->bus.dma = &s->dma; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void macio_ide_initfn(Object *obj) | static void macio_ide_initfn(Object *obj) | ||||||
| @ -363,7 +575,7 @@ static void macio_ide_register_types(void) | |||||||
|     type_register_static(&macio_ide_type_info); |     type_register_static(&macio_ide_type_info); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* hd_table must contain 4 block drivers */ | /* hd_table must contain 2 block drivers */ | ||||||
| void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) | void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) | ||||||
| { | { | ||||||
|     int i; |     int i; | ||||||
| @ -377,6 +589,7 @@ void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) | |||||||
| 
 | 
 | ||||||
| void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) | void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) | ||||||
| { | { | ||||||
|  |     s->dbdma = dbdma; | ||||||
|     DBDMA_register_channel(dbdma, channel, s->dma_irq, |     DBDMA_register_channel(dbdma, channel, s->dma_irq, | ||||||
|                            pmac_ide_transfer, pmac_ide_flush, s); |                            pmac_ide_transfer, pmac_ide_flush, s); | ||||||
| } | } | ||||||
|  | |||||||
| @ -22,3 +22,4 @@ obj-$(CONFIG_IOAPIC) += ioapic.o | |||||||
| obj-$(CONFIG_OMAP) += omap_intc.o | obj-$(CONFIG_OMAP) += omap_intc.o | ||||||
| obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o | obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o | ||||||
| obj-$(CONFIG_SH4) += sh_intc.o | obj-$(CONFIG_SH4) += sh_intc.o | ||||||
|  | obj-$(CONFIG_XICS) += xics.o | ||||||
|  | |||||||
| @ -54,122 +54,10 @@ | |||||||
| /*
 | /*
 | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /*
 | static DBDMAState *dbdma_from_ch(DBDMA_channel *ch) | ||||||
|  * DBDMA control/status registers.  All little-endian. | { | ||||||
|  */ |     return container_of(ch, DBDMAState, channels[ch->channel]); | ||||||
| 
 | } | ||||||
| #define DBDMA_CONTROL         0x00 |  | ||||||
| #define DBDMA_STATUS          0x01 |  | ||||||
| #define DBDMA_CMDPTR_HI       0x02 |  | ||||||
| #define DBDMA_CMDPTR_LO       0x03 |  | ||||||
| #define DBDMA_INTR_SEL        0x04 |  | ||||||
| #define DBDMA_BRANCH_SEL      0x05 |  | ||||||
| #define DBDMA_WAIT_SEL        0x06 |  | ||||||
| #define DBDMA_XFER_MODE       0x07 |  | ||||||
| #define DBDMA_DATA2PTR_HI     0x08 |  | ||||||
| #define DBDMA_DATA2PTR_LO     0x09 |  | ||||||
| #define DBDMA_RES1            0x0A |  | ||||||
| #define DBDMA_ADDRESS_HI      0x0B |  | ||||||
| #define DBDMA_BRANCH_ADDR_HI  0x0C |  | ||||||
| #define DBDMA_RES2            0x0D |  | ||||||
| #define DBDMA_RES3            0x0E |  | ||||||
| #define DBDMA_RES4            0x0F |  | ||||||
| 
 |  | ||||||
| #define DBDMA_REGS            16 |  | ||||||
| #define DBDMA_SIZE            (DBDMA_REGS * sizeof(uint32_t)) |  | ||||||
| 
 |  | ||||||
| #define DBDMA_CHANNEL_SHIFT   7 |  | ||||||
| #define DBDMA_CHANNEL_SIZE    (1 << DBDMA_CHANNEL_SHIFT) |  | ||||||
| 
 |  | ||||||
| #define DBDMA_CHANNELS        (0x1000 >> DBDMA_CHANNEL_SHIFT) |  | ||||||
| 
 |  | ||||||
| /* Bits in control and status registers */ |  | ||||||
| 
 |  | ||||||
| #define RUN	0x8000 |  | ||||||
| #define PAUSE	0x4000 |  | ||||||
| #define FLUSH	0x2000 |  | ||||||
| #define WAKE	0x1000 |  | ||||||
| #define DEAD	0x0800 |  | ||||||
| #define ACTIVE	0x0400 |  | ||||||
| #define BT	0x0100 |  | ||||||
| #define DEVSTAT	0x00ff |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * DBDMA command structure.  These fields are all little-endian! |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| typedef struct dbdma_cmd { |  | ||||||
|     uint16_t req_count;	  /* requested byte transfer count */ |  | ||||||
|     uint16_t command;	  /* command word (has bit-fields) */ |  | ||||||
|     uint32_t phy_addr;	  /* physical data address */ |  | ||||||
|     uint32_t cmd_dep;	  /* command-dependent field */ |  | ||||||
|     uint16_t res_count;	  /* residual count after completion */ |  | ||||||
|     uint16_t xfer_status; /* transfer status */ |  | ||||||
| } dbdma_cmd; |  | ||||||
| 
 |  | ||||||
| /* DBDMA command values in command field */ |  | ||||||
| 
 |  | ||||||
| #define COMMAND_MASK    0xf000 |  | ||||||
| #define OUTPUT_MORE	0x0000	/* transfer memory data to stream */ |  | ||||||
| #define OUTPUT_LAST	0x1000	/* ditto followed by end marker */ |  | ||||||
| #define INPUT_MORE	0x2000	/* transfer stream data to memory */ |  | ||||||
| #define INPUT_LAST	0x3000	/* ditto, expect end marker */ |  | ||||||
| #define STORE_WORD	0x4000	/* write word (4 bytes) to device reg */ |  | ||||||
| #define LOAD_WORD	0x5000	/* read word (4 bytes) from device reg */ |  | ||||||
| #define DBDMA_NOP	0x6000	/* do nothing */ |  | ||||||
| #define DBDMA_STOP	0x7000	/* suspend processing */ |  | ||||||
| 
 |  | ||||||
| /* Key values in command field */ |  | ||||||
| 
 |  | ||||||
| #define KEY_MASK        0x0700 |  | ||||||
| #define KEY_STREAM0	0x0000	/* usual data stream */ |  | ||||||
| #define KEY_STREAM1	0x0100	/* control/status stream */ |  | ||||||
| #define KEY_STREAM2	0x0200	/* device-dependent stream */ |  | ||||||
| #define KEY_STREAM3	0x0300	/* device-dependent stream */ |  | ||||||
| #define KEY_STREAM4	0x0400	/* reserved */ |  | ||||||
| #define KEY_REGS	0x0500	/* device register space */ |  | ||||||
| #define KEY_SYSTEM	0x0600	/* system memory-mapped space */ |  | ||||||
| #define KEY_DEVICE	0x0700	/* device memory-mapped space */ |  | ||||||
| 
 |  | ||||||
| /* Interrupt control values in command field */ |  | ||||||
| 
 |  | ||||||
| #define INTR_MASK       0x0030 |  | ||||||
| #define INTR_NEVER	0x0000	/* don't interrupt */ |  | ||||||
| #define INTR_IFSET	0x0010	/* intr if condition bit is 1 */ |  | ||||||
| #define INTR_IFCLR	0x0020	/* intr if condition bit is 0 */ |  | ||||||
| #define INTR_ALWAYS	0x0030	/* always interrupt */ |  | ||||||
| 
 |  | ||||||
| /* Branch control values in command field */ |  | ||||||
| 
 |  | ||||||
| #define BR_MASK         0x000c |  | ||||||
| #define BR_NEVER	0x0000	/* don't branch */ |  | ||||||
| #define BR_IFSET	0x0004	/* branch if condition bit is 1 */ |  | ||||||
| #define BR_IFCLR	0x0008	/* branch if condition bit is 0 */ |  | ||||||
| #define BR_ALWAYS	0x000c	/* always branch */ |  | ||||||
| 
 |  | ||||||
| /* Wait control values in command field */ |  | ||||||
| 
 |  | ||||||
| #define WAIT_MASK       0x0003 |  | ||||||
| #define WAIT_NEVER	0x0000	/* don't wait */ |  | ||||||
| #define WAIT_IFSET	0x0001	/* wait if condition bit is 1 */ |  | ||||||
| #define WAIT_IFCLR	0x0002	/* wait if condition bit is 0 */ |  | ||||||
| #define WAIT_ALWAYS	0x0003	/* always wait */ |  | ||||||
| 
 |  | ||||||
| typedef struct DBDMA_channel { |  | ||||||
|     int channel; |  | ||||||
|     uint32_t regs[DBDMA_REGS]; |  | ||||||
|     qemu_irq irq; |  | ||||||
|     DBDMA_io io; |  | ||||||
|     DBDMA_rw rw; |  | ||||||
|     DBDMA_flush flush; |  | ||||||
|     dbdma_cmd current; |  | ||||||
|     int processing; |  | ||||||
| } DBDMA_channel; |  | ||||||
| 
 |  | ||||||
| typedef struct { |  | ||||||
|     MemoryRegion mem; |  | ||||||
|     DBDMA_channel channels[DBDMA_CHANNELS]; |  | ||||||
| } DBDMAState; |  | ||||||
| 
 | 
 | ||||||
| #ifdef DEBUG_DBDMA | #ifdef DEBUG_DBDMA | ||||||
| static void dump_dbdma_cmd(dbdma_cmd *cmd) | static void dump_dbdma_cmd(dbdma_cmd *cmd) | ||||||
| @ -224,7 +112,7 @@ static void conditional_interrupt(DBDMA_channel *ch) | |||||||
|     uint32_t status; |     uint32_t status; | ||||||
|     int cond; |     int cond; | ||||||
| 
 | 
 | ||||||
|     DBDMA_DPRINTF("conditional_interrupt\n"); |     DBDMA_DPRINTF("%s\n", __func__); | ||||||
| 
 | 
 | ||||||
|     intr = le16_to_cpu(current->command) & INTR_MASK; |     intr = le16_to_cpu(current->command) & INTR_MASK; | ||||||
| 
 | 
 | ||||||
| @ -233,6 +121,7 @@ static void conditional_interrupt(DBDMA_channel *ch) | |||||||
|         return; |         return; | ||||||
|     case INTR_ALWAYS: /* always interrupt */ |     case INTR_ALWAYS: /* always interrupt */ | ||||||
|         qemu_irq_raise(ch->irq); |         qemu_irq_raise(ch->irq); | ||||||
|  |         DBDMA_DPRINTF("%s: raise\n", __func__); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -245,12 +134,16 @@ static void conditional_interrupt(DBDMA_channel *ch) | |||||||
| 
 | 
 | ||||||
|     switch(intr) { |     switch(intr) { | ||||||
|     case INTR_IFSET:  /* intr if condition bit is 1 */ |     case INTR_IFSET:  /* intr if condition bit is 1 */ | ||||||
|         if (cond) |         if (cond) { | ||||||
|             qemu_irq_raise(ch->irq); |             qemu_irq_raise(ch->irq); | ||||||
|  |             DBDMA_DPRINTF("%s: raise\n", __func__); | ||||||
|  |         } | ||||||
|         return; |         return; | ||||||
|     case INTR_IFCLR:  /* intr if condition bit is 0 */ |     case INTR_IFCLR:  /* intr if condition bit is 0 */ | ||||||
|         if (!cond) |         if (!cond) { | ||||||
|             qemu_irq_raise(ch->irq); |             qemu_irq_raise(ch->irq); | ||||||
|  |             DBDMA_DPRINTF("%s: raise\n", __func__); | ||||||
|  |         } | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -360,7 +253,6 @@ static void conditional_branch(DBDMA_channel *ch) | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static QEMUBH *dbdma_bh; |  | ||||||
| static void channel_run(DBDMA_channel *ch); | static void channel_run(DBDMA_channel *ch); | ||||||
| 
 | 
 | ||||||
| static void dbdma_end(DBDMA_io *io) | static void dbdma_end(DBDMA_io *io) | ||||||
| @ -368,6 +260,8 @@ static void dbdma_end(DBDMA_io *io) | |||||||
|     DBDMA_channel *ch = io->channel; |     DBDMA_channel *ch = io->channel; | ||||||
|     dbdma_cmd *current = &ch->current; |     dbdma_cmd *current = &ch->current; | ||||||
| 
 | 
 | ||||||
|  |     DBDMA_DPRINTF("%s\n", __func__); | ||||||
|  | 
 | ||||||
|     if (conditional_wait(ch)) |     if (conditional_wait(ch)) | ||||||
|         goto wait; |         goto wait; | ||||||
| 
 | 
 | ||||||
| @ -381,7 +275,9 @@ static void dbdma_end(DBDMA_io *io) | |||||||
|     conditional_branch(ch); |     conditional_branch(ch); | ||||||
| 
 | 
 | ||||||
| wait: | wait: | ||||||
|     ch->processing = 0; |     /* Indicate that we're ready for a new DMA round */ | ||||||
|  |     ch->io.processing = false; | ||||||
|  | 
 | ||||||
|     if ((ch->regs[DBDMA_STATUS] & RUN) && |     if ((ch->regs[DBDMA_STATUS] & RUN) && | ||||||
|         (ch->regs[DBDMA_STATUS] & ACTIVE)) |         (ch->regs[DBDMA_STATUS] & ACTIVE)) | ||||||
|         channel_run(ch); |         channel_run(ch); | ||||||
| @ -407,7 +303,7 @@ static void start_output(DBDMA_channel *ch, int key, uint32_t addr, | |||||||
|     ch->io.is_last = is_last; |     ch->io.is_last = is_last; | ||||||
|     ch->io.dma_end = dbdma_end; |     ch->io.dma_end = dbdma_end; | ||||||
|     ch->io.is_dma_out = 1; |     ch->io.is_dma_out = 1; | ||||||
|     ch->processing = 1; |     ch->io.processing = true; | ||||||
|     if (ch->rw) { |     if (ch->rw) { | ||||||
|         ch->rw(&ch->io); |         ch->rw(&ch->io); | ||||||
|     } |     } | ||||||
| @ -422,6 +318,7 @@ static void start_input(DBDMA_channel *ch, int key, uint32_t addr, | |||||||
|      * are not implemented in the mac-io chip |      * are not implemented in the mac-io chip | ||||||
|      */ |      */ | ||||||
| 
 | 
 | ||||||
|  |     DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); | ||||||
|     if (!addr || key > KEY_STREAM3) { |     if (!addr || key > KEY_STREAM3) { | ||||||
|         kill_channel(ch); |         kill_channel(ch); | ||||||
|         return; |         return; | ||||||
| @ -432,7 +329,7 @@ static void start_input(DBDMA_channel *ch, int key, uint32_t addr, | |||||||
|     ch->io.is_last = is_last; |     ch->io.is_last = is_last; | ||||||
|     ch->io.dma_end = dbdma_end; |     ch->io.dma_end = dbdma_end; | ||||||
|     ch->io.is_dma_out = 0; |     ch->io.is_dma_out = 0; | ||||||
|     ch->processing = 1; |     ch->io.processing = true; | ||||||
|     if (ch->rw) { |     if (ch->rw) { | ||||||
|         ch->rw(&ch->io); |         ch->rw(&ch->io); | ||||||
|     } |     } | ||||||
| @ -474,7 +371,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr, | |||||||
|     next(ch); |     next(ch); | ||||||
| 
 | 
 | ||||||
| wait: | wait: | ||||||
|     qemu_bh_schedule(dbdma_bh); |     DBDMA_kick(dbdma_from_ch(ch)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void store_word(DBDMA_channel *ch, int key, uint32_t addr, | static void store_word(DBDMA_channel *ch, int key, uint32_t addr, | ||||||
| @ -512,7 +409,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr, | |||||||
|     next(ch); |     next(ch); | ||||||
| 
 | 
 | ||||||
| wait: | wait: | ||||||
|     qemu_bh_schedule(dbdma_bh); |     DBDMA_kick(dbdma_from_ch(ch)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void nop(DBDMA_channel *ch) | static void nop(DBDMA_channel *ch) | ||||||
| @ -529,7 +426,7 @@ static void nop(DBDMA_channel *ch) | |||||||
|     conditional_branch(ch); |     conditional_branch(ch); | ||||||
| 
 | 
 | ||||||
| wait: | wait: | ||||||
|     qemu_bh_schedule(dbdma_bh); |     DBDMA_kick(dbdma_from_ch(ch)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void stop(DBDMA_channel *ch) | static void stop(DBDMA_channel *ch) | ||||||
| @ -558,11 +455,11 @@ static void channel_run(DBDMA_channel *ch) | |||||||
|     switch (cmd) { |     switch (cmd) { | ||||||
|     case DBDMA_NOP: |     case DBDMA_NOP: | ||||||
|         nop(ch); |         nop(ch); | ||||||
| 	return; |         return; | ||||||
| 
 | 
 | ||||||
|     case DBDMA_STOP: |     case DBDMA_STOP: | ||||||
|         stop(ch); |         stop(ch); | ||||||
| 	return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     key = le16_to_cpu(current->command) & 0x0700; |     key = le16_to_cpu(current->command) & 0x0700; | ||||||
| @ -578,19 +475,19 @@ static void channel_run(DBDMA_channel *ch) | |||||||
|     switch (cmd) { |     switch (cmd) { | ||||||
|     case OUTPUT_MORE: |     case OUTPUT_MORE: | ||||||
|         start_output(ch, key, phy_addr, req_count, 0); |         start_output(ch, key, phy_addr, req_count, 0); | ||||||
| 	return; |         return; | ||||||
| 
 | 
 | ||||||
|     case OUTPUT_LAST: |     case OUTPUT_LAST: | ||||||
|         start_output(ch, key, phy_addr, req_count, 1); |         start_output(ch, key, phy_addr, req_count, 1); | ||||||
| 	return; |         return; | ||||||
| 
 | 
 | ||||||
|     case INPUT_MORE: |     case INPUT_MORE: | ||||||
|         start_input(ch, key, phy_addr, req_count, 0); |         start_input(ch, key, phy_addr, req_count, 0); | ||||||
| 	return; |         return; | ||||||
| 
 | 
 | ||||||
|     case INPUT_LAST: |     case INPUT_LAST: | ||||||
|         start_input(ch, key, phy_addr, req_count, 1); |         start_input(ch, key, phy_addr, req_count, 1); | ||||||
| 	return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (key < KEY_REGS) { |     if (key < KEY_REGS) { | ||||||
| @ -615,11 +512,11 @@ static void channel_run(DBDMA_channel *ch) | |||||||
|     switch (cmd) { |     switch (cmd) { | ||||||
|     case LOAD_WORD: |     case LOAD_WORD: | ||||||
|         load_word(ch, key, phy_addr, req_count); |         load_word(ch, key, phy_addr, req_count); | ||||||
| 	return; |         return; | ||||||
| 
 | 
 | ||||||
|     case STORE_WORD: |     case STORE_WORD: | ||||||
|         store_word(ch, key, phy_addr, req_count); |         store_word(ch, key, phy_addr, req_count); | ||||||
| 	return; |         return; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -630,7 +527,7 @@ static void DBDMA_run(DBDMAState *s) | |||||||
|     for (channel = 0; channel < DBDMA_CHANNELS; channel++) { |     for (channel = 0; channel < DBDMA_CHANNELS; channel++) { | ||||||
|         DBDMA_channel *ch = &s->channels[channel]; |         DBDMA_channel *ch = &s->channels[channel]; | ||||||
|         uint32_t status = ch->regs[DBDMA_STATUS]; |         uint32_t status = ch->regs[DBDMA_STATUS]; | ||||||
|         if (!ch->processing && (status & RUN) && (status & ACTIVE)) { |         if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) { | ||||||
|             channel_run(ch); |             channel_run(ch); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -645,6 +542,11 @@ static void DBDMA_run_bh(void *opaque) | |||||||
|     DBDMA_run(s); |     DBDMA_run(s); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void DBDMA_kick(DBDMAState *dbdma) | ||||||
|  | { | ||||||
|  |     qemu_bh_schedule(dbdma->bh); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | ||||||
|                             DBDMA_rw rw, DBDMA_flush flush, |                             DBDMA_rw rw, DBDMA_flush flush, | ||||||
|                             void *opaque) |                             void *opaque) | ||||||
| @ -698,10 +600,12 @@ dbdma_control_write(DBDMA_channel *ch) | |||||||
| 
 | 
 | ||||||
|     ch->regs[DBDMA_STATUS] = status; |     ch->regs[DBDMA_STATUS] = status; | ||||||
| 
 | 
 | ||||||
|     if (status & ACTIVE) |     if (status & ACTIVE) { | ||||||
|         qemu_bh_schedule(dbdma_bh); |         DBDMA_kick(dbdma_from_ch(ch)); | ||||||
|     if ((status & FLUSH) && ch->flush) |     } | ||||||
|  |     if ((status & FLUSH) && ch->flush) { | ||||||
|         ch->flush(&ch->io); |         ch->flush(&ch->io); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void dbdma_write(void *opaque, hwaddr addr, | static void dbdma_write(void *opaque, hwaddr addr, | ||||||
| @ -712,15 +616,16 @@ static void dbdma_write(void *opaque, hwaddr addr, | |||||||
|     DBDMA_channel *ch = &s->channels[channel]; |     DBDMA_channel *ch = &s->channels[channel]; | ||||||
|     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; |     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; | ||||||
| 
 | 
 | ||||||
|     DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value); |     DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n", | ||||||
|  |                   addr, value); | ||||||
|     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", |     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", | ||||||
|                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); |                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); | ||||||
| 
 | 
 | ||||||
|     /* cmdptr cannot be modified if channel is RUN or ACTIVE */ |     /* cmdptr cannot be modified if channel is ACTIVE */ | ||||||
| 
 | 
 | ||||||
|     if (reg == DBDMA_CMDPTR_LO && |     if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) { | ||||||
|         (ch->regs[DBDMA_STATUS] & (RUN | ACTIVE))) |         return; | ||||||
| 	return; |     } | ||||||
| 
 | 
 | ||||||
|     ch->regs[reg] = value; |     ch->regs[reg] = value; | ||||||
| 
 | 
 | ||||||
| @ -853,7 +758,7 @@ void* DBDMA_init (MemoryRegion **dbdma_mem) | |||||||
|     vmstate_register(NULL, -1, &vmstate_dbdma, s); |     vmstate_register(NULL, -1, &vmstate_dbdma, s); | ||||||
|     qemu_register_reset(dbdma_reset, s); |     qemu_register_reset(dbdma_reset, s); | ||||||
| 
 | 
 | ||||||
|     dbdma_bh = qemu_bh_new(DBDMA_run_bh, s); |     s->bh = qemu_bh_new(DBDMA_run_bh, s); | ||||||
| 
 | 
 | ||||||
|     return s; |     return s; | ||||||
| } | } | ||||||
|  | |||||||
| @ -52,10 +52,10 @@ typedef struct OldWorldMacIOState { | |||||||
|     MacIOState parent_obj; |     MacIOState parent_obj; | ||||||
|     /*< public >*/ |     /*< public >*/ | ||||||
| 
 | 
 | ||||||
|     qemu_irq irqs[3]; |     qemu_irq irqs[5]; | ||||||
| 
 | 
 | ||||||
|     MacIONVRAMState nvram; |     MacIONVRAMState nvram; | ||||||
|     MACIOIDEState ide; |     MACIOIDEState ide[2]; | ||||||
| } OldWorldMacIOState; | } OldWorldMacIOState; | ||||||
| 
 | 
 | ||||||
| #define NEWWORLD_MACIO(obj) \ | #define NEWWORLD_MACIO(obj) \ | ||||||
| @ -147,18 +147,32 @@ static int macio_common_initfn(PCIDevice *d) | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int macio_initfn_ide(MacIOState *s, MACIOIDEState *ide, qemu_irq irq0, | ||||||
|  |                             qemu_irq irq1, int dmaid) | ||||||
|  | { | ||||||
|  |     SysBusDevice *sysbus_dev; | ||||||
|  | 
 | ||||||
|  |     sysbus_dev = SYS_BUS_DEVICE(ide); | ||||||
|  |     sysbus_connect_irq(sysbus_dev, 0, irq0); | ||||||
|  |     sysbus_connect_irq(sysbus_dev, 1, irq1); | ||||||
|  |     macio_ide_register_dma(ide, s->dbdma, dmaid); | ||||||
|  |     return qdev_init(DEVICE(ide)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int macio_oldworld_initfn(PCIDevice *d) | static int macio_oldworld_initfn(PCIDevice *d) | ||||||
| { | { | ||||||
|     MacIOState *s = MACIO(d); |     MacIOState *s = MACIO(d); | ||||||
|     OldWorldMacIOState *os = OLDWORLD_MACIO(d); |     OldWorldMacIOState *os = OLDWORLD_MACIO(d); | ||||||
|     SysBusDevice *sysbus_dev; |     SysBusDevice *sysbus_dev; | ||||||
|  |     int i; | ||||||
|  |     int cur_irq = 0; | ||||||
|     int ret = macio_common_initfn(d); |     int ret = macio_common_initfn(d); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         return ret; |         return ret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sysbus_dev = SYS_BUS_DEVICE(&s->cuda); |     sysbus_dev = SYS_BUS_DEVICE(&s->cuda); | ||||||
|     sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]); |     sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); | ||||||
| 
 | 
 | ||||||
|     ret = qdev_init(DEVICE(&os->nvram)); |     ret = qdev_init(DEVICE(&os->nvram)); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
| @ -174,23 +188,39 @@ static int macio_oldworld_initfn(PCIDevice *d) | |||||||
|         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); |         memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sysbus_dev = SYS_BUS_DEVICE(&os->ide); |     /* IDE buses */ | ||||||
|     sysbus_connect_irq(sysbus_dev, 0, os->irqs[1]); |     for (i = 0; i < ARRAY_SIZE(os->ide); i++) { | ||||||
|     sysbus_connect_irq(sysbus_dev, 1, os->irqs[2]); |         qemu_irq irq0 = os->irqs[cur_irq++]; | ||||||
|     macio_ide_register_dma(&os->ide, s->dbdma, 0x16); |         qemu_irq irq1 = os->irqs[cur_irq++]; | ||||||
|     ret = qdev_init(DEVICE(&os->ide)); | 
 | ||||||
|     if (ret < 0) { |         ret = macio_initfn_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4)); | ||||||
|         return ret; |         if (ret < 0) { | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, int index) | ||||||
|  | { | ||||||
|  |     gchar *name; | ||||||
|  | 
 | ||||||
|  |     object_initialize(ide, TYPE_MACIO_IDE); | ||||||
|  |     qdev_set_parent_bus(DEVICE(ide), sysbus_get_default()); | ||||||
|  |     memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000), | ||||||
|  |                                 &ide->mem); | ||||||
|  |     name = g_strdup_printf("ide[%i]", index); | ||||||
|  |     object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL); | ||||||
|  |     g_free(name); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void macio_oldworld_init(Object *obj) | static void macio_oldworld_init(Object *obj) | ||||||
| { | { | ||||||
|     MacIOState *s = MACIO(obj); |     MacIOState *s = MACIO(obj); | ||||||
|     OldWorldMacIOState *os = OLDWORLD_MACIO(obj); |     OldWorldMacIOState *os = OLDWORLD_MACIO(obj); | ||||||
|     DeviceState *dev; |     DeviceState *dev; | ||||||
|  |     int i; | ||||||
| 
 | 
 | ||||||
|     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); |     qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); | ||||||
| 
 | 
 | ||||||
| @ -199,47 +229,74 @@ static void macio_oldworld_init(Object *obj) | |||||||
|     qdev_prop_set_uint32(dev, "size", 0x2000); |     qdev_prop_set_uint32(dev, "size", 0x2000); | ||||||
|     qdev_prop_set_uint32(dev, "it_shift", 4); |     qdev_prop_set_uint32(dev, "it_shift", 4); | ||||||
| 
 | 
 | ||||||
|     object_initialize(&os->ide, TYPE_MACIO_IDE); |     for (i = 0; i < 2; i++) { | ||||||
|     qdev_set_parent_bus(DEVICE(&os->ide), sysbus_get_default()); |         macio_init_ide(s, &os->ide[i], i); | ||||||
|     memory_region_add_subregion(&s->bar, 0x1f000 + (1 * 0x1000), &os->ide.mem); |     } | ||||||
|     object_property_add_child(obj, "ide", OBJECT(&os->ide), NULL); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void timer_write(void *opaque, hwaddr addr, uint64_t value, | ||||||
|  |                        unsigned size) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) | ||||||
|  | { | ||||||
|  |     uint32_t value = 0; | ||||||
|  | 
 | ||||||
|  |     switch (addr) { | ||||||
|  |     case 0x38: | ||||||
|  |         value = qemu_get_clock_ns(vm_clock); | ||||||
|  |         break; | ||||||
|  |     case 0x3c: | ||||||
|  |         value = qemu_get_clock_ns(vm_clock) >> 32; | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return value; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const MemoryRegionOps timer_ops = { | ||||||
|  |     .read = timer_read, | ||||||
|  |     .write = timer_write, | ||||||
|  |     .endianness = DEVICE_NATIVE_ENDIAN, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static int macio_newworld_initfn(PCIDevice *d) | static int macio_newworld_initfn(PCIDevice *d) | ||||||
| { | { | ||||||
|     MacIOState *s = MACIO(d); |     MacIOState *s = MACIO(d); | ||||||
|     NewWorldMacIOState *ns = NEWWORLD_MACIO(d); |     NewWorldMacIOState *ns = NEWWORLD_MACIO(d); | ||||||
|     SysBusDevice *sysbus_dev; |     SysBusDevice *sysbus_dev; | ||||||
|  |     MemoryRegion *timer_memory = g_new(MemoryRegion, 1); | ||||||
|  |     int i; | ||||||
|  |     int cur_irq = 0; | ||||||
|     int ret = macio_common_initfn(d); |     int ret = macio_common_initfn(d); | ||||||
|     if (ret < 0) { |     if (ret < 0) { | ||||||
|         return ret; |         return ret; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sysbus_dev = SYS_BUS_DEVICE(&s->cuda); |     sysbus_dev = SYS_BUS_DEVICE(&s->cuda); | ||||||
|     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]); |     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); | ||||||
| 
 | 
 | ||||||
|     if (s->pic_mem) { |     if (s->pic_mem) { | ||||||
|         /* OpenPIC */ |         /* OpenPIC */ | ||||||
|         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); |         memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sysbus_dev = SYS_BUS_DEVICE(&ns->ide[0]); |     /* IDE buses */ | ||||||
|     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[1]); |     for (i = 0; i < ARRAY_SIZE(ns->ide); i++) { | ||||||
|     sysbus_connect_irq(sysbus_dev, 1, ns->irqs[2]); |         qemu_irq irq0 = ns->irqs[cur_irq++]; | ||||||
|     macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x16); |         qemu_irq irq1 = ns->irqs[cur_irq++]; | ||||||
|     ret = qdev_init(DEVICE(&ns->ide[0])); | 
 | ||||||
|     if (ret < 0) { |         ret = macio_initfn_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4)); | ||||||
|         return ret; |         if (ret < 0) { | ||||||
|  |             return ret; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]); |     /* Timer */ | ||||||
|     sysbus_connect_irq(sysbus_dev, 0, ns->irqs[3]); |     memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer", | ||||||
|     sysbus_connect_irq(sysbus_dev, 1, ns->irqs[4]); |                           0x1000); | ||||||
|     macio_ide_register_dma(&ns->ide[1], s->dbdma, 0x1a); |     memory_region_add_subregion(&s->bar, 0x15000, timer_memory); | ||||||
|     ret = qdev_init(DEVICE(&ns->ide[1])); |  | ||||||
|     if (ret < 0) { |  | ||||||
|         return ret; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
| @ -249,18 +306,11 @@ static void macio_newworld_init(Object *obj) | |||||||
|     MacIOState *s = MACIO(obj); |     MacIOState *s = MACIO(obj); | ||||||
|     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj); |     NewWorldMacIOState *ns = NEWWORLD_MACIO(obj); | ||||||
|     int i; |     int i; | ||||||
|     gchar *name; |  | ||||||
| 
 | 
 | ||||||
|     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); |     qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); | ||||||
| 
 | 
 | ||||||
|     for (i = 0; i < 2; i++) { |     for (i = 0; i < 2; i++) { | ||||||
|         object_initialize(&ns->ide[i], TYPE_MACIO_IDE); |         macio_init_ide(s, &ns->ide[i], i); | ||||||
|         qdev_set_parent_bus(DEVICE(&ns->ide[i]), sysbus_get_default()); |  | ||||||
|         memory_region_add_subregion(&s->bar, 0x1f000 + ((i + 1) * 0x1000), |  | ||||||
|                                     &ns->ide[i].mem); |  | ||||||
|         name = g_strdup_printf("ide[%i]", i); |  | ||||||
|         object_property_add_child(obj, name, OBJECT(&ns->ide[i]), NULL); |  | ||||||
|         g_free(name); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| # shared objects
 | # shared objects
 | ||||||
| obj-y += ppc.o ppc_booke.o | obj-y += ppc.o ppc_booke.o | ||||||
| # IBM pSeries (sPAPR)
 | # IBM pSeries (sPAPR)
 | ||||||
| obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o spapr_events.o | obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o | ||||||
| obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o | obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o | ||||||
| obj-$(CONFIG_PSERIES) += spapr_pci.o | obj-$(CONFIG_PSERIES) += spapr_pci.o | ||||||
| # PowerPC 4xx boards
 | # PowerPC 4xx boards
 | ||||||
|  | |||||||
| @ -131,6 +131,9 @@ typedef struct MACIOIDEState { | |||||||
|     MemoryRegion mem; |     MemoryRegion mem; | ||||||
|     IDEBus bus; |     IDEBus bus; | ||||||
|     BlockDriverAIOCB *aiocb; |     BlockDriverAIOCB *aiocb; | ||||||
|  |     IDEDMA dma; | ||||||
|  |     void *dbdma; | ||||||
|  |     bool dma_active; | ||||||
| } MACIOIDEState; | } MACIOIDEState; | ||||||
| 
 | 
 | ||||||
| void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); | void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); | ||||||
|  | |||||||
| @ -71,6 +71,7 @@ | |||||||
| 
 | 
 | ||||||
| #define MAX_IDE_BUS 2 | #define MAX_IDE_BUS 2 | ||||||
| #define CFG_ADDR 0xf0000510 | #define CFG_ADDR 0xf0000510 | ||||||
|  | #define TBFREQ (100UL * 1000UL * 1000UL) | ||||||
| 
 | 
 | ||||||
| /* debug UniNorth */ | /* debug UniNorth */ | ||||||
| //#define DEBUG_UNIN
 | //#define DEBUG_UNIN
 | ||||||
| @ -191,7 +192,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) | |||||||
|         env = &cpu->env; |         env = &cpu->env; | ||||||
| 
 | 
 | ||||||
|         /* Set time-base frequency to 100 Mhz */ |         /* Set time-base frequency to 100 Mhz */ | ||||||
|         cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); |         cpu_ppc_tb_init(env, TBFREQ); | ||||||
|         qemu_register_reset(ppc_core99_reset, cpu); |         qemu_register_reset(ppc_core99_reset, cpu); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -460,7 +461,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) | |||||||
|         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); |         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); | ||||||
| #endif | #endif | ||||||
|     } else { |     } else { | ||||||
|         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); |         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); | ||||||
|     } |     } | ||||||
|     /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ |     /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ | ||||||
|     fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); |     fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); | ||||||
|  | |||||||
| @ -45,6 +45,7 @@ | |||||||
| 
 | 
 | ||||||
| #define MAX_IDE_BUS 2 | #define MAX_IDE_BUS 2 | ||||||
| #define CFG_ADDR 0xf0000510 | #define CFG_ADDR 0xf0000510 | ||||||
|  | #define TBFREQ 16600000UL | ||||||
| 
 | 
 | ||||||
| static int fw_cfg_boot_set(void *opaque, const char *boot_device) | static int fw_cfg_boot_set(void *opaque, const char *boot_device) | ||||||
| { | { | ||||||
| @ -114,7 +115,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) | |||||||
|         env = &cpu->env; |         env = &cpu->env; | ||||||
| 
 | 
 | ||||||
|         /* Set time-base frequency to 16.6 Mhz */ |         /* Set time-base frequency to 16.6 Mhz */ | ||||||
|         cpu_ppc_tb_init(env,  16600000UL); |         cpu_ppc_tb_init(env,  TBFREQ); | ||||||
|         qemu_register_reset(ppc_heathrow_reset, cpu); |         qemu_register_reset(ppc_heathrow_reset, cpu); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -267,20 +268,19 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) | |||||||
|     macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); |     macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); | ||||||
|     dev = DEVICE(macio); |     dev = DEVICE(macio); | ||||||
|     qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ |     qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ | ||||||
|     qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE */ |     qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE-0 */ | ||||||
|     qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */ |     qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */ | ||||||
|  |     qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */ | ||||||
|  |     qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */ | ||||||
|     macio_init(macio, pic_mem, escc_bar); |     macio_init(macio, pic_mem, escc_bar); | ||||||
| 
 | 
 | ||||||
|     /* First IDE channel is a MAC IDE on the MacIO bus */ |  | ||||||
|     macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), |     macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), | ||||||
|                                                         "ide")); |                                                         "ide[0]")); | ||||||
|     macio_ide_init_drives(macio_ide, hd); |     macio_ide_init_drives(macio_ide, hd); | ||||||
| 
 | 
 | ||||||
|     /* Second IDE channel is a CMD646 on the PCI bus */ |     macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), | ||||||
|     hd[0] = hd[MAX_IDE_DEVS]; |                                                         "ide[1]")); | ||||||
|     hd[1] = hd[MAX_IDE_DEVS + 1]; |     macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); | ||||||
|     hd[3] = hd[2] = NULL; |  | ||||||
|     pci_cmd646_ide_init(pci_bus, hd, 0); |  | ||||||
| 
 | 
 | ||||||
|     dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); |     dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); | ||||||
|     adb_bus = qdev_get_child_bus(dev, "adb.0"); |     adb_bus = qdev_get_child_bus(dev, "adb.0"); | ||||||
| @ -331,7 +331,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) | |||||||
|         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); |         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); | ||||||
| #endif | #endif | ||||||
|     } else { |     } else { | ||||||
|         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); |         fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); | ||||||
|     } |     } | ||||||
|     /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ |     /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ | ||||||
|     fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); |     fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); | ||||||
|  | |||||||
| @ -940,7 +940,10 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME); |     if (bios_name == NULL) { | ||||||
|  |         bios_name = FW_FILE_NAME; | ||||||
|  |     } | ||||||
|  |     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); | ||||||
|     fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); |     fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); | ||||||
|     if (fw_size < 0) { |     if (fw_size < 0) { | ||||||
|         hw_error("qemu: could not load LPAR rtas '%s'\n", filename); |         hw_error("qemu: could not load LPAR rtas '%s'\n", filename); | ||||||
|  | |||||||
| @ -121,14 +121,14 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|     return H_SUCCESS; |     return H_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum { | typedef enum { | ||||||
|     REMOVE_SUCCESS = 0, |     REMOVE_SUCCESS = 0, | ||||||
|     REMOVE_NOT_FOUND = 1, |     REMOVE_NOT_FOUND = 1, | ||||||
|     REMOVE_PARM = 2, |     REMOVE_PARM = 2, | ||||||
|     REMOVE_HW = 3, |     REMOVE_HW = 3, | ||||||
| }; | } RemoveResult; | ||||||
| 
 | 
 | ||||||
| static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, | static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex, | ||||||
|                                 target_ulong avpn, |                                 target_ulong avpn, | ||||||
|                                 target_ulong flags, |                                 target_ulong flags, | ||||||
|                                 target_ulong *vp, target_ulong *rp) |                                 target_ulong *vp, target_ulong *rp) | ||||||
| @ -165,7 +165,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|     target_ulong flags = args[0]; |     target_ulong flags = args[0]; | ||||||
|     target_ulong pte_index = args[1]; |     target_ulong pte_index = args[1]; | ||||||
|     target_ulong avpn = args[2]; |     target_ulong avpn = args[2]; | ||||||
|     int ret; |     RemoveResult ret; | ||||||
| 
 | 
 | ||||||
|     ret = remove_hpte(env, pte_index, avpn, flags, |     ret = remove_hpte(env, pte_index, avpn, flags, | ||||||
|                       &args[0], &args[1]); |                       &args[0], &args[1]); | ||||||
| @ -184,7 +184,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, | |||||||
|         return H_HARDWARE; |         return H_HARDWARE; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     assert(0); |     g_assert_not_reached(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define H_BULK_REMOVE_TYPE             0xc000000000000000ULL | #define H_BULK_REMOVE_TYPE             0xc000000000000000ULL | ||||||
|  | |||||||
| @ -451,7 +451,7 @@ static uint64_t spapr_io_read(void *opaque, hwaddr addr, | |||||||
|     case 4: |     case 4: | ||||||
|         return cpu_inl(addr); |         return cpu_inl(addr); | ||||||
|     } |     } | ||||||
|     assert(0); |     g_assert_not_reached(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void spapr_io_write(void *opaque, hwaddr addr, | static void spapr_io_write(void *opaque, hwaddr addr, | ||||||
| @ -468,7 +468,7 @@ static void spapr_io_write(void *opaque, hwaddr addr, | |||||||
|         cpu_outl(addr, data); |         cpu_outl(addr, data); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     assert(0); |     g_assert_not_reached(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const MemoryRegionOps spapr_io_ops = { | static const MemoryRegionOps spapr_io_ops = { | ||||||
|  | |||||||
| @ -37,12 +37,136 @@ struct DBDMA_io { | |||||||
|     int is_last; |     int is_last; | ||||||
|     int is_dma_out; |     int is_dma_out; | ||||||
|     DBDMA_end dma_end; |     DBDMA_end dma_end; | ||||||
|  |     /* DMA is in progress, don't start another one */ | ||||||
|  |     bool processing; | ||||||
|  |     /* unaligned last sector of a request */ | ||||||
|  |     uint8_t remainder[0x200]; | ||||||
|  |     int remainder_len; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * DBDMA control/status registers.  All little-endian. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #define DBDMA_CONTROL         0x00 | ||||||
|  | #define DBDMA_STATUS          0x01 | ||||||
|  | #define DBDMA_CMDPTR_HI       0x02 | ||||||
|  | #define DBDMA_CMDPTR_LO       0x03 | ||||||
|  | #define DBDMA_INTR_SEL        0x04 | ||||||
|  | #define DBDMA_BRANCH_SEL      0x05 | ||||||
|  | #define DBDMA_WAIT_SEL        0x06 | ||||||
|  | #define DBDMA_XFER_MODE       0x07 | ||||||
|  | #define DBDMA_DATA2PTR_HI     0x08 | ||||||
|  | #define DBDMA_DATA2PTR_LO     0x09 | ||||||
|  | #define DBDMA_RES1            0x0A | ||||||
|  | #define DBDMA_ADDRESS_HI      0x0B | ||||||
|  | #define DBDMA_BRANCH_ADDR_HI  0x0C | ||||||
|  | #define DBDMA_RES2            0x0D | ||||||
|  | #define DBDMA_RES3            0x0E | ||||||
|  | #define DBDMA_RES4            0x0F | ||||||
|  | 
 | ||||||
|  | #define DBDMA_REGS            16 | ||||||
|  | #define DBDMA_SIZE            (DBDMA_REGS * sizeof(uint32_t)) | ||||||
|  | 
 | ||||||
|  | #define DBDMA_CHANNEL_SHIFT   7 | ||||||
|  | #define DBDMA_CHANNEL_SIZE    (1 << DBDMA_CHANNEL_SHIFT) | ||||||
|  | 
 | ||||||
|  | #define DBDMA_CHANNELS        (0x1000 >> DBDMA_CHANNEL_SHIFT) | ||||||
|  | 
 | ||||||
|  | /* Bits in control and status registers */ | ||||||
|  | 
 | ||||||
|  | #define RUN        0x8000 | ||||||
|  | #define PAUSE      0x4000 | ||||||
|  | #define FLUSH      0x2000 | ||||||
|  | #define WAKE       0x1000 | ||||||
|  | #define DEAD       0x0800 | ||||||
|  | #define ACTIVE     0x0400 | ||||||
|  | #define BT         0x0100 | ||||||
|  | #define DEVSTAT    0x00ff | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * DBDMA command structure.  These fields are all little-endian! | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | typedef struct dbdma_cmd { | ||||||
|  |     uint16_t req_count;          /* requested byte transfer count */ | ||||||
|  |     uint16_t command;            /* command word (has bit-fields) */ | ||||||
|  |     uint32_t phy_addr;           /* physical data address */ | ||||||
|  |     uint32_t cmd_dep;            /* command-dependent field */ | ||||||
|  |     uint16_t res_count;          /* residual count after completion */ | ||||||
|  |     uint16_t xfer_status;        /* transfer status */ | ||||||
|  | } dbdma_cmd; | ||||||
|  | 
 | ||||||
|  | /* DBDMA command values in command field */ | ||||||
|  | 
 | ||||||
|  | #define COMMAND_MASK    0xf000 | ||||||
|  | #define OUTPUT_MORE     0x0000        /* transfer memory data to stream */ | ||||||
|  | #define OUTPUT_LAST     0x1000        /* ditto followed by end marker */ | ||||||
|  | #define INPUT_MORE      0x2000        /* transfer stream data to memory */ | ||||||
|  | #define INPUT_LAST      0x3000        /* ditto, expect end marker */ | ||||||
|  | #define STORE_WORD      0x4000        /* write word (4 bytes) to device reg */ | ||||||
|  | #define LOAD_WORD       0x5000        /* read word (4 bytes) from device reg */ | ||||||
|  | #define DBDMA_NOP       0x6000        /* do nothing */ | ||||||
|  | #define DBDMA_STOP      0x7000        /* suspend processing */ | ||||||
|  | 
 | ||||||
|  | /* Key values in command field */ | ||||||
|  | 
 | ||||||
|  | #define KEY_MASK        0x0700 | ||||||
|  | #define KEY_STREAM0     0x0000        /* usual data stream */ | ||||||
|  | #define KEY_STREAM1     0x0100        /* control/status stream */ | ||||||
|  | #define KEY_STREAM2     0x0200        /* device-dependent stream */ | ||||||
|  | #define KEY_STREAM3     0x0300        /* device-dependent stream */ | ||||||
|  | #define KEY_STREAM4     0x0400        /* reserved */ | ||||||
|  | #define KEY_REGS        0x0500        /* device register space */ | ||||||
|  | #define KEY_SYSTEM      0x0600        /* system memory-mapped space */ | ||||||
|  | #define KEY_DEVICE      0x0700        /* device memory-mapped space */ | ||||||
|  | 
 | ||||||
|  | /* Interrupt control values in command field */ | ||||||
|  | 
 | ||||||
|  | #define INTR_MASK       0x0030 | ||||||
|  | #define INTR_NEVER      0x0000        /* don't interrupt */ | ||||||
|  | #define INTR_IFSET      0x0010        /* intr if condition bit is 1 */ | ||||||
|  | #define INTR_IFCLR      0x0020        /* intr if condition bit is 0 */ | ||||||
|  | #define INTR_ALWAYS     0x0030        /* always interrupt */ | ||||||
|  | 
 | ||||||
|  | /* Branch control values in command field */ | ||||||
|  | 
 | ||||||
|  | #define BR_MASK         0x000c | ||||||
|  | #define BR_NEVER        0x0000        /* don't branch */ | ||||||
|  | #define BR_IFSET        0x0004        /* branch if condition bit is 1 */ | ||||||
|  | #define BR_IFCLR        0x0008        /* branch if condition bit is 0 */ | ||||||
|  | #define BR_ALWAYS       0x000c        /* always branch */ | ||||||
|  | 
 | ||||||
|  | /* Wait control values in command field */ | ||||||
|  | 
 | ||||||
|  | #define WAIT_MASK       0x0003 | ||||||
|  | #define WAIT_NEVER      0x0000        /* don't wait */ | ||||||
|  | #define WAIT_IFSET      0x0001        /* wait if condition bit is 1 */ | ||||||
|  | #define WAIT_IFCLR      0x0002        /* wait if condition bit is 0 */ | ||||||
|  | #define WAIT_ALWAYS     0x0003        /* always wait */ | ||||||
|  | 
 | ||||||
|  | typedef struct DBDMA_channel { | ||||||
|  |     int channel; | ||||||
|  |     uint32_t regs[DBDMA_REGS]; | ||||||
|  |     qemu_irq irq; | ||||||
|  |     DBDMA_io io; | ||||||
|  |     DBDMA_rw rw; | ||||||
|  |     DBDMA_flush flush; | ||||||
|  |     dbdma_cmd current; | ||||||
|  | } DBDMA_channel; | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     MemoryRegion mem; | ||||||
|  |     DBDMA_channel channels[DBDMA_CHANNELS]; | ||||||
|  |     QEMUBH *bh; | ||||||
|  | } DBDMAState; | ||||||
|  | 
 | ||||||
|  | /* Externally callable functions */ | ||||||
| 
 | 
 | ||||||
| void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, | ||||||
|                             DBDMA_rw rw, DBDMA_flush flush, |                             DBDMA_rw rw, DBDMA_flush flush, | ||||||
|                             void *opaque); |                             void *opaque); | ||||||
|  | void DBDMA_kick(DBDMAState *dbdma); | ||||||
| void* DBDMA_init (MemoryRegion **dbdma_mem); | void* DBDMA_init (MemoryRegion **dbdma_mem); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -792,17 +792,15 @@ | |||||||
|     POWERPC_DEF_SVR("MPC8572E", "MPC8572E", |     POWERPC_DEF_SVR("MPC8572E", "MPC8572E", | ||||||
|                     CPU_POWERPC_MPC8572E,     POWERPC_SVR_8572E,     e500v2) |                     CPU_POWERPC_MPC8572E,     POWERPC_SVR_8572E,     e500v2) | ||||||
|     /* e600 family                                                           */ |     /* e600 family                                                           */ | ||||||
|     POWERPC_DEF("e600",          CPU_POWERPC_e600,                   7400, |     POWERPC_DEF("e600",          CPU_POWERPC_e600,                   e600, | ||||||
|                 "PowerPC e600 core") |                 "PowerPC e600 core") | ||||||
|     /* PowerPC e600 microcontrollers                                         */ |     /* PowerPC e600 microcontrollers                                         */ | ||||||
| #if defined(TODO) |  | ||||||
|     POWERPC_DEF_SVR("MPC8610", "MPC8610", |     POWERPC_DEF_SVR("MPC8610", "MPC8610", | ||||||
|                     CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      7400) |                     CPU_POWERPC_MPC8610,      POWERPC_SVR_8610,      e600) | ||||||
| #endif |  | ||||||
|     POWERPC_DEF_SVR("MPC8641", "MPC8641", |     POWERPC_DEF_SVR("MPC8641", "MPC8641", | ||||||
|                     CPU_POWERPC_MPC8641,      POWERPC_SVR_8641,      7400) |                     CPU_POWERPC_MPC8641,      POWERPC_SVR_8641,      e600) | ||||||
|     POWERPC_DEF_SVR("MPC8641D", "MPC8641D", |     POWERPC_DEF_SVR("MPC8641D", "MPC8641D", | ||||||
|                     CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     7400) |                     CPU_POWERPC_MPC8641D,     POWERPC_SVR_8641D,     e600) | ||||||
|     /* 32 bits "classic" PowerPC                                             */ |     /* 32 bits "classic" PowerPC                                             */ | ||||||
|     /* PowerPC 6xx family                                                    */ |     /* PowerPC 6xx family                                                    */ | ||||||
|     POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601, |     POWERPC_DEF("601_v0",        CPU_POWERPC_601_v0,                 601, | ||||||
| @ -1145,6 +1143,8 @@ | |||||||
|                 "POWER7 v2.1") |                 "POWER7 v2.1") | ||||||
|     POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7, |     POWERPC_DEF("POWER7_v2.3",   CPU_POWERPC_POWER7_v23,             POWER7, | ||||||
|                 "POWER7 v2.3") |                 "POWER7 v2.3") | ||||||
|  |     POWERPC_DEF("POWER8_v1.0",   CPU_POWERPC_POWER8_v10,             POWER8, | ||||||
|  |                 "POWER8 v1.0") | ||||||
|     POWERPC_DEF("970",           CPU_POWERPC_970,                    970, |     POWERPC_DEF("970",           CPU_POWERPC_970,                    970, | ||||||
|                 "PowerPC 970") |                 "PowerPC 970") | ||||||
|     POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX, |     POWERPC_DEF("970fx_v1.0",    CPU_POWERPC_970FX_v10,              970FX, | ||||||
| @ -1390,6 +1390,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { | |||||||
|     { "Dino",  "POWER3" }, |     { "Dino",  "POWER3" }, | ||||||
|     { "POWER3+", "631" }, |     { "POWER3+", "631" }, | ||||||
|     { "POWER7", "POWER7_v2.3" }, |     { "POWER7", "POWER7_v2.3" }, | ||||||
|  |     { "POWER8", "POWER8_v1.0" }, | ||||||
|     { "970fx", "970fx_v3.1" }, |     { "970fx", "970fx_v3.1" }, | ||||||
|     { "970mp", "970mp_v1.1" }, |     { "970mp", "970mp_v1.1" }, | ||||||
|     { "Apache", "RS64" }, |     { "Apache", "RS64" }, | ||||||
|  | |||||||
| @ -556,6 +556,7 @@ enum { | |||||||
|     CPU_POWERPC_POWER7_v20         = 0x003F0200, |     CPU_POWERPC_POWER7_v20         = 0x003F0200, | ||||||
|     CPU_POWERPC_POWER7_v21         = 0x003F0201, |     CPU_POWERPC_POWER7_v21         = 0x003F0201, | ||||||
|     CPU_POWERPC_POWER7_v23         = 0x003F0203, |     CPU_POWERPC_POWER7_v23         = 0x003F0203, | ||||||
|  |     CPU_POWERPC_POWER8_v10         = 0x004B0100, | ||||||
|     CPU_POWERPC_970                = 0x00390202, |     CPU_POWERPC_970                = 0x00390202, | ||||||
|     CPU_POWERPC_970FX_v10          = 0x00391100, |     CPU_POWERPC_970FX_v10          = 0x00391100, | ||||||
|     CPU_POWERPC_970FX_v20          = 0x003C0200, |     CPU_POWERPC_970FX_v20          = 0x003C0200, | ||||||
| @ -732,9 +733,7 @@ enum { | |||||||
|     POWERPC_SVR_8568E              = 0x807D0011 | POWERPC_SVR_E500, |     POWERPC_SVR_8568E              = 0x807D0011 | POWERPC_SVR_E500, | ||||||
|     POWERPC_SVR_8572               = 0x80E00010 | POWERPC_SVR_E500, |     POWERPC_SVR_8572               = 0x80E00010 | POWERPC_SVR_E500, | ||||||
|     POWERPC_SVR_8572E              = 0x80E80010 | POWERPC_SVR_E500, |     POWERPC_SVR_8572E              = 0x80E80010 | POWERPC_SVR_E500, | ||||||
| #if 0 |     POWERPC_SVR_8610               = 0x80A00011, | ||||||
|     POWERPC_SVR_8610               = xxx, |  | ||||||
| #endif |  | ||||||
|     POWERPC_SVR_8641               = 0x80900021, |     POWERPC_SVR_8641               = 0x80900021, | ||||||
|     POWERPC_SVR_8641D              = 0x80900121, |     POWERPC_SVR_8641D              = 0x80900121, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -6479,6 +6479,131 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data) | |||||||
|                  POWERPC_FLAG_BUS_CLK; |                  POWERPC_FLAG_BUS_CLK; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void init_proc_e600 (CPUPPCState *env) | ||||||
|  | { | ||||||
|  |     gen_spr_ne_601(env); | ||||||
|  |     gen_spr_7xx(env); | ||||||
|  |     /* Time base */ | ||||||
|  |     gen_tbl(env); | ||||||
|  |     /* 74xx specific SPR */ | ||||||
|  |     gen_spr_74xx(env); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_UBAMR, "UBAMR", | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_LDSTCR, "LDSTCR", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_ICTRL, "ICTRL", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_MSSSR0, "MSSSR0", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_PMC5, "PMC5", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_UPMC5, "UPMC5", | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_PMC6, "PMC6", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* XXX : not implemented */ | ||||||
|  |     spr_register(env, SPR_UPMC6, "UPMC6", | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* SPRGs */ | ||||||
|  |     spr_register(env, SPR_SPRG4, "SPRG4", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     spr_register(env, SPR_USPRG4, "USPRG4", | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  0x00000000); | ||||||
|  |     spr_register(env, SPR_SPRG5, "SPRG5", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     spr_register(env, SPR_USPRG5, "USPRG5", | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  0x00000000); | ||||||
|  |     spr_register(env, SPR_SPRG6, "SPRG6", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     spr_register(env, SPR_USPRG6, "USPRG6", | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  0x00000000); | ||||||
|  |     spr_register(env, SPR_SPRG7, "SPRG7", | ||||||
|  |                  SPR_NOACCESS, SPR_NOACCESS, | ||||||
|  |                  &spr_read_generic, &spr_write_generic, | ||||||
|  |                  0x00000000); | ||||||
|  |     spr_register(env, SPR_USPRG7, "USPRG7", | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  &spr_read_ureg, SPR_NOACCESS, | ||||||
|  |                  0x00000000); | ||||||
|  |     /* Memory management */ | ||||||
|  |     gen_low_BATs(env); | ||||||
|  |     gen_high_BATs(env); | ||||||
|  |     gen_74xx_soft_tlb(env, 128, 2); | ||||||
|  |     init_excp_7450(env); | ||||||
|  |     env->dcache_line_size = 32; | ||||||
|  |     env->icache_line_size = 32; | ||||||
|  |     /* Allocate hardware IRQ controller */ | ||||||
|  |     ppc6xx_irq_init(env); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | POWERPC_FAMILY(e600)(ObjectClass *oc, void *data) | ||||||
|  | { | ||||||
|  |     DeviceClass *dc = DEVICE_CLASS(oc); | ||||||
|  |     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); | ||||||
|  | 
 | ||||||
|  |     dc->desc = "PowerPC e600"; | ||||||
|  |     pcc->init_proc = init_proc_e600; | ||||||
|  |     pcc->check_pow = check_pow_hid0_74xx; | ||||||
|  |     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | | ||||||
|  |                        PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | | ||||||
|  |                        PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | | ||||||
|  |                        PPC_FLOAT_STFIWX | | ||||||
|  |                        PPC_CACHE | PPC_CACHE_ICBI | | ||||||
|  |                        PPC_CACHE_DCBA | PPC_CACHE_DCBZ | | ||||||
|  |                        PPC_MEM_SYNC | PPC_MEM_EIEIO | | ||||||
|  |                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | | ||||||
|  |                        PPC_MEM_TLBIA | PPC_74xx_TLB | | ||||||
|  |                        PPC_SEGMENT | PPC_EXTERN | | ||||||
|  |                        PPC_ALTIVEC; | ||||||
|  |     pcc->insns_flags2 = PPC_NONE; | ||||||
|  |     pcc->msr_mask = 0x000000000205FF77ULL; | ||||||
|  |     pcc->mmu_model = POWERPC_MMU_32B; | ||||||
|  | #if defined(CONFIG_SOFTMMU) | ||||||
|  |     pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; | ||||||
|  | #endif | ||||||
|  |     pcc->excp_model = POWERPC_EXCP_74xx; | ||||||
|  |     pcc->bus_model = PPC_FLAGS_INPUT_6xx; | ||||||
|  |     pcc->bfd_mach = bfd_mach_ppc_7400; | ||||||
|  |     pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | | ||||||
|  |                  POWERPC_FLAG_BE | POWERPC_FLAG_PMM | | ||||||
|  |                  POWERPC_FLAG_BUS_CLK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #if defined (TARGET_PPC64) | #if defined (TARGET_PPC64) | ||||||
| #if defined(CONFIG_USER_ONLY) | #if defined(CONFIG_USER_ONLY) | ||||||
| #define POWERPC970_HID5_INIT 0x00000080 | #define POWERPC970_HID5_INIT 0x00000080 | ||||||
| @ -7011,6 +7136,40 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) | |||||||
|     pcc->l1_dcache_size = 0x8000; |     pcc->l1_dcache_size = 0x8000; | ||||||
|     pcc->l1_icache_size = 0x8000; |     pcc->l1_icache_size = 0x8000; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) | ||||||
|  | { | ||||||
|  |     DeviceClass *dc = DEVICE_CLASS(oc); | ||||||
|  |     PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); | ||||||
|  | 
 | ||||||
|  |     dc->desc = "POWER8"; | ||||||
|  |     pcc->init_proc = init_proc_POWER7; | ||||||
|  |     pcc->check_pow = check_pow_nocheck; | ||||||
|  |     pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | | ||||||
|  |                        PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | | ||||||
|  |                        PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | | ||||||
|  |                        PPC_FLOAT_STFIWX | | ||||||
|  |                        PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | | ||||||
|  |                        PPC_MEM_SYNC | PPC_MEM_EIEIO | | ||||||
|  |                        PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | | ||||||
|  |                        PPC_64B | PPC_ALTIVEC | | ||||||
|  |                        PPC_SEGMENT_64B | PPC_SLBI | | ||||||
|  |                        PPC_POPCNTB | PPC_POPCNTWD; | ||||||
|  |     pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX; | ||||||
|  |     pcc->msr_mask = 0x800000000204FF36ULL; | ||||||
|  |     pcc->mmu_model = POWERPC_MMU_2_06; | ||||||
|  | #if defined(CONFIG_SOFTMMU) | ||||||
|  |     pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; | ||||||
|  | #endif | ||||||
|  |     pcc->excp_model = POWERPC_EXCP_POWER7; | ||||||
|  |     pcc->bus_model = PPC_FLAGS_INPUT_POWER7; | ||||||
|  |     pcc->bfd_mach = bfd_mach_ppc64; | ||||||
|  |     pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | | ||||||
|  |                  POWERPC_FLAG_BE | POWERPC_FLAG_PMM | | ||||||
|  |                  POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR; | ||||||
|  |     pcc->l1_dcache_size = 0x8000; | ||||||
|  |     pcc->l1_icache_size = 0x8000; | ||||||
|  | } | ||||||
| #endif /* defined (TARGET_PPC64) */ | #endif /* defined (TARGET_PPC64) */ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Anthony Liguori
						Anthony Liguori