/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (hide 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 dpavlin 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 dpavlin 4 /* 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 dpavlin 1 /* 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 dpavlin 4
233     if (dev->fd == -1) {
234     perror("dev_create_ram: mmap");
235     free(dev);
236     return NULL;
237     }
238    
239 dpavlin 1 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 dpavlin 4 if (!dev->host_addr) {
245     free(dev);
246     return NULL;
247     }
248    
249 dpavlin 1 vm_bind_device(vm,dev);
250     return dev;
251     }
252    
253 dpavlin 4 /* 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 dpavlin 1 /* 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