1 |
/* |
2 |
* Cisco router simulation platform. |
3 |
* Copyright (c) 2007 Christophe Fillot (cf@utc.fr) |
4 |
* |
5 |
* Byte-swapping device. |
6 |
*/ |
7 |
|
8 |
#include <stdio.h> |
9 |
#include <stdlib.h> |
10 |
#include <string.h> |
11 |
#include <unistd.h> |
12 |
#include <assert.h> |
13 |
|
14 |
#include "cpu.h" |
15 |
#include "vm.h" |
16 |
#include "dynamips.h" |
17 |
#include "memory.h" |
18 |
#include "device.h" |
19 |
|
20 |
struct bswap_data { |
21 |
/* VM object info */ |
22 |
vm_obj_t vm_obj; |
23 |
|
24 |
/* VM instance */ |
25 |
vm_instance_t *vm; |
26 |
|
27 |
/* Byte-swap device */ |
28 |
struct vdevice dev; |
29 |
|
30 |
/* Physical address base for rewrite */ |
31 |
m_uint64_t phys_base; |
32 |
}; |
33 |
|
34 |
/* |
35 |
* Byte swapped access. |
36 |
*/ |
37 |
static void *dev_bswap_access(cpu_gen_t *cpu,struct vdevice *dev, |
38 |
m_uint32_t offset,u_int op_size,u_int op_type, |
39 |
m_uint64_t *data) |
40 |
{ |
41 |
struct bswap_data *d = dev->priv_data; |
42 |
m_uint64_t paddr; |
43 |
|
44 |
paddr = d->phys_base + offset; |
45 |
|
46 |
switch(op_size) { |
47 |
case 1: |
48 |
if (op_type == MTS_READ) |
49 |
*data = physmem_copy_u8_from_vm(d->vm,paddr ^ 0x03); |
50 |
else |
51 |
physmem_copy_u8_to_vm(d->vm,paddr ^ 0x03,*data); |
52 |
break; |
53 |
|
54 |
case 2: |
55 |
if (op_type == MTS_READ) |
56 |
*data = swap16(physmem_copy_u16_from_vm(d->vm,paddr ^ 0x02)); |
57 |
else |
58 |
physmem_copy_u16_to_vm(d->vm,paddr ^ 0x02,swap16(*data)); |
59 |
break; |
60 |
|
61 |
case 4: |
62 |
if (op_type == MTS_READ) |
63 |
*data = swap32(physmem_copy_u32_from_vm(d->vm,paddr)); |
64 |
else |
65 |
physmem_copy_u32_to_vm(d->vm,paddr,swap32(*data)); |
66 |
break; |
67 |
} |
68 |
|
69 |
return NULL; |
70 |
} |
71 |
|
72 |
/* Shutdown an byte-swap device */ |
73 |
void dev_bswap_shutdown(vm_instance_t *vm,struct bswap_data *d) |
74 |
{ |
75 |
if (d != NULL) { |
76 |
/* Remove the alias, the byte-swapped and the main device */ |
77 |
dev_remove(vm,&d->dev); |
78 |
|
79 |
/* Free the structure itself */ |
80 |
free(d); |
81 |
} |
82 |
} |
83 |
|
84 |
/* Initialized a byte-swap device */ |
85 |
int dev_bswap_init(vm_instance_t *vm,char *name, |
86 |
m_uint64_t paddr,m_uint32_t len, |
87 |
m_uint64_t remap_addr) |
88 |
{ |
89 |
struct bswap_data *d; |
90 |
|
91 |
if (!(d = malloc(sizeof(*d)))) { |
92 |
fprintf(stderr,"BSWAP: unable to create device.\n"); |
93 |
return(-1); |
94 |
} |
95 |
|
96 |
vm_object_init(&d->vm_obj); |
97 |
d->vm = vm; |
98 |
d->phys_base = remap_addr; |
99 |
d->vm_obj.name = name; |
100 |
d->vm_obj.data = d; |
101 |
d->vm_obj.shutdown = (vm_shutdown_t)dev_bswap_shutdown; |
102 |
|
103 |
dev_init(&d->dev); |
104 |
d->dev.name = name; |
105 |
d->dev.phys_addr = paddr; |
106 |
d->dev.phys_len = len; |
107 |
d->dev.handler = dev_bswap_access; |
108 |
d->dev.priv_data = d; |
109 |
|
110 |
/* Map this device to the VM */ |
111 |
vm_bind_device(vm,&d->dev); |
112 |
vm_object_add(vm,&d->vm_obj); |
113 |
return(0); |
114 |
} |