/[dynamips]/trunk/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 /trunk/device.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations)
Sat Oct 6 16:03:58 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC1/device.c
File MIME type: text/plain
File size: 7911 byte(s)
import dynamips-0.2.6-RC1

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

  ViewVC Help
Powered by ViewVC 1.1.26