/[dynamips]/upstream/dynamips-0.2.6-RC3/device.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.6-RC3/device.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations)
Sat Oct 6 16:06:49 2007 UTC (12 years, 2 months ago) by dpavlin
File MIME type: text/plain
File size: 8368 byte(s)
dynamips-0.2.6-RC3

1 /*
2 * Cisco 7200 (Predator) simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 */
5
6 #define _GNU_SOURCE
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <string.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/mman.h>
14 #include <fcntl.h>
15
16 #include "mips64.h"
17 #include "cpu.h"
18 #include "dynamips.h"
19 #include "memory.h"
20 #include "device.h"
21 #include "cp0.h"
22
23 #define DEBUG_DEV_ACCESS 0
24
25 /* Get device by ID */
26 struct vdevice *dev_get_by_id(vm_instance_t *vm,u_int dev_id)
27 {
28 if (!vm || (dev_id >= MIPS64_DEVICE_MAX))
29 return NULL;
30
31 return(vm->dev_array[dev_id]);
32 }
33
34 /* Get device by name */
35 struct vdevice *dev_get_by_name(vm_instance_t *vm,char *name)
36 {
37 struct vdevice *dev;
38
39 if (!vm)
40 return NULL;
41
42 for(dev=vm->dev_list;dev;dev=dev->next)
43 if (!strcmp(dev->name,name))
44 return dev;
45
46 return NULL;
47 }
48
49 /* Device lookup by physical address */
50 struct vdevice *dev_lookup(vm_instance_t *vm,m_uint64_t phys_addr,int cached)
51 {
52 struct vdevice *dev;
53
54 if (!vm)
55 return NULL;
56
57 for(dev=vm->dev_list;dev;dev=dev->next) {
58 if (cached && !(dev->flags & VDEVICE_FLAG_CACHING))
59 continue;
60
61 if ((phys_addr >= dev->phys_addr) &&
62 ((phys_addr - dev->phys_addr) < dev->phys_len))
63 return dev;
64 }
65
66 return NULL;
67 }
68
69 /* Find the next device after the specified address */
70 struct vdevice *dev_lookup_next(vm_instance_t *vm,m_uint64_t phys_addr,
71 struct vdevice *dev_start,int cached)
72 {
73 struct vdevice *dev;
74
75 if (!vm)
76 return NULL;
77
78 dev = (dev_start != NULL) ? dev_start : vm->dev_list;
79 for(;dev;dev=dev->next) {
80 if (cached && !(dev->flags & VDEVICE_FLAG_CACHING))
81 continue;
82
83 if (dev->phys_addr > phys_addr)
84 return dev;
85 }
86
87 return NULL;
88 }
89
90 /* Initialize a device */
91 void dev_init(struct vdevice *dev)
92 {
93 memset(dev,0,sizeof(*dev));
94 dev->fd = -1;
95 }
96
97 /* Allocate a device */
98 struct vdevice *dev_create(char *name)
99 {
100 struct vdevice *dev;
101
102 if (!(dev = malloc(sizeof(*dev)))) {
103 fprintf(stderr,"dev_create: insufficient memory to "
104 "create device '%s'.\n",name);
105 return NULL;
106 }
107
108 dev_init(dev);
109 dev->name = name;
110 return dev;
111 }
112
113 /* Remove a device */
114 void dev_remove(vm_instance_t *vm,struct vdevice *dev)
115 {
116 if (dev != NULL) {
117 vm_unbind_device(vm,dev);
118
119 vm_log(vm,"DEVICE",
120 "Removal of device %s, fd=%d, host_addr=0x%llx, flags=%d\n",
121 dev->name,dev->fd,(m_uint64_t)dev->host_addr,dev->flags);
122
123 if (dev->fd != -1) {
124 /* Unmap memory mapped file */
125 if (dev->host_addr && !(dev->flags & VDEVICE_FLAG_REMAP)) {
126 if (dev->flags & VDEVICE_FLAG_SYNC) {
127 msync((void *)dev->host_addr,dev->phys_len,
128 MS_SYNC|MS_INVALIDATE);
129 }
130
131 vm_log(vm,"MMAP","unmapping of device '%s', "
132 "fd=%d, host_addr=0x%llx, len=0x%x\n",
133 dev->name,dev->fd,(m_uint64_t)dev->host_addr,dev->phys_len);
134 munmap((void *)dev->host_addr,dev->phys_len);
135 }
136
137 if (dev->flags & VDEVICE_FLAG_SYNC)
138 fsync(dev->fd);
139
140 close(dev->fd);
141 } else {
142 /* Use of malloc'ed host memory: free it */
143 if (dev->host_addr && !(dev->flags & VDEVICE_FLAG_REMAP))
144 free((void *)dev->host_addr);
145 }
146
147 /* reinitialize the device to a clean state */
148 dev_init(dev);
149 }
150 }
151
152 /* Show properties of a device */
153 void dev_show(struct vdevice *dev)
154 {
155 if (!dev)
156 return;
157
158 printf(" %-18s: 0x%12.12llx (0x%8.8x)\n",
159 dev->name,dev->phys_addr,dev->phys_len);
160 }
161
162 /* Show the device list */
163 void dev_show_list(vm_instance_t *vm)
164 {
165 struct vdevice *dev;
166
167 printf("\nVM \"%s\" (%u) Device list:\n",vm->name,vm->instance_id);
168
169 for(dev=vm->dev_list;dev;dev=dev->next)
170 dev_show(dev);
171
172 printf("\n");
173 }
174
175 /* device access function */
176 void *dev_access(cpu_mips_t *cpu,u_int dev_id,m_uint32_t offset,
177 u_int op_size,u_int op_type,m_uint64_t *data)
178 {
179 struct vdevice *dev = cpu->vm->dev_array[dev_id];
180
181 #if DEBUG_DEV_ACCESS
182 cpu_log(cpu,"DEV_ACCESS","%s: dev_id=%u, offset=0x%8.8x, op_size=%u, "
183 "op_type=%u, data=%p\n",dev->name,dev_id,offset,op_size,op_type,data);
184 #endif
185
186 return(dev->handler(cpu,dev,offset,op_size,op_type,data));
187 }
188
189 /* Synchronize memory for a memory-mapped (mmap) device */
190 int dev_sync(struct vdevice *dev)
191 {
192 if (!dev || !dev->host_addr)
193 return(-1);
194
195 return(msync((void *)dev->host_addr,dev->phys_len,MS_SYNC));
196 }
197
198 /* Remap a device at specified physical address */
199 struct vdevice *dev_remap(char *name,struct vdevice *orig,
200 m_uint64_t paddr,m_uint32_t len)
201 {
202 struct vdevice *dev;
203
204 if (!(dev = dev_create(name)))
205 return NULL;
206
207 dev->phys_addr = paddr;
208 dev->phys_len = len;
209 dev->flags = orig->flags | VDEVICE_FLAG_REMAP;
210 dev->fd = orig->fd;
211 dev->host_addr = orig->host_addr;
212 dev->handler = orig->handler;
213 return dev;
214 }
215
216 /* Create a RAM device */
217 struct vdevice *dev_create_ram(vm_instance_t *vm,char *name,char *filename,
218 m_uint64_t paddr,m_uint32_t len)
219 {
220 struct vdevice *dev;
221 u_char *ram_ptr;
222
223 if (!(dev = dev_create(name)))
224 return NULL;
225
226 dev->phys_addr = paddr;
227 dev->phys_len = len;
228 dev->flags = VDEVICE_FLAG_CACHING;
229
230 if (filename) {
231 dev->fd = memzone_create_file(filename,dev->phys_len,&ram_ptr);
232
233 if (dev->fd == -1) {
234 perror("dev_create_ram: mmap");
235 free(dev);
236 return NULL;
237 }
238
239 dev->host_addr = (m_iptr_t)ram_ptr;
240 } else {
241 dev->host_addr = (m_iptr_t)m_memalign(4096,dev->phys_len);
242 }
243
244 if (!dev->host_addr) {
245 free(dev);
246 return NULL;
247 }
248
249 vm_bind_device(vm,dev);
250 return dev;
251 }
252
253 /* Create a ghosted RAM device */
254 struct vdevice *
255 dev_create_ghost_ram(vm_instance_t *vm,char *name,char *filename,
256 m_uint64_t paddr,m_uint32_t len)
257 {
258 struct vdevice *dev;
259 u_char *ram_ptr;
260
261 if (!(dev = dev_create(name)))
262 return NULL;
263
264 dev->phys_addr = paddr;
265 dev->phys_len = len;
266 dev->flags = VDEVICE_FLAG_CACHING;
267
268 dev->fd = memzone_open_cow_file(filename,dev->phys_len,&ram_ptr);
269 if (dev->fd == -1) {
270 perror("dev_create_ghost_ram: mmap");
271 free(dev);
272 return NULL;
273 }
274
275 if (!(dev->host_addr = (m_iptr_t)ram_ptr)) {
276 free(dev);
277 return NULL;
278 }
279
280 vm_bind_device(vm,dev);
281 return dev;
282 }
283
284 /* Create a memory alias */
285 struct vdevice *dev_create_ram_alias(vm_instance_t *vm,char *name,char *orig,
286 m_uint64_t paddr,m_uint32_t len)
287 {
288 struct vdevice *dev,*orig_dev;
289
290 /* try to locate the device */
291 if (!(orig_dev = dev_get_by_name(vm,orig))) {
292 fprintf(stderr,"VM%u: dev_create_ram_alias: unknown device '%s'.\n",
293 vm->instance_id,orig);
294 return NULL;
295 }
296
297 if (orig_dev->fd == -1) {
298 fprintf(stderr,"VM%u: dev_create_ram_alias: device %s has no FD.\n",
299 vm->instance_id,orig_dev->name);
300 return NULL;
301 }
302
303 if (!(dev = dev_remap(name,orig_dev,paddr,len))) {
304 fprintf(stderr,"VM%u: dev_create_ram_alias: unable to create "
305 "new device %s.\n",vm->instance_id,name);
306 return NULL;
307 }
308
309 vm_bind_device(vm,dev);
310 return dev;
311 }
312
313 /* dummy console handler */
314 static void *dummy_console_handler(cpu_mips_t *cpu,struct vdevice *dev,
315 m_uint32_t offset,u_int op_size,
316 u_int op_type,m_uint64_t *data)
317 {
318 switch(offset) {
319 case 0x40c:
320 if (op_type == MTS_READ)
321 *data = 0x04; /* tx ready */
322 break;
323
324 case 0x41c:
325 if (op_type == MTS_WRITE) {
326 printf("%c",(u_char)(*data & 0xff));
327 fflush(stdout);
328 }
329 break;
330 }
331
332 return NULL;
333 }
334
335 /* Create a dummy console */
336 int dev_create_dummy_console(vm_instance_t *vm)
337 {
338 struct vdevice *dev;
339
340 if (!(dev = dev_create("dummy_console")))
341 return(-1);
342
343 dev->phys_addr = 0x1e840000; /* 0x1f000000; */
344 dev->phys_len = 4096;
345 dev->handler = dummy_console_handler;
346
347 vm_bind_device(vm,dev);
348 return(0);
349 }

  ViewVC Help
Powered by ViewVC 1.1.26