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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (hide annotations)
Sat Oct 6 16:33:40 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.8-RC1/dev_nvram.c
File MIME type: text/plain
File size: 5480 byte(s)
dynamips-0.2.8-RC1

1 dpavlin 1 /*
2 dpavlin 7 * Cisco router simulation platform.
3 dpavlin 1 * Copyright (c) 2005,2006 Christophe Fillot. All rights reserved.
4     *
5     * Dallas DS1216 chip emulation:
6     * - NVRAM
7     * - Calendar
8     *
9     * Manuals:
10     * http://pdfserv.maxim-ic.com/en/ds/DS1216-DS1216H.pdf
11     *
12     * Calendar stuff written by Mtve.
13     */
14    
15     #include <stdio.h>
16     #include <stdlib.h>
17     #include <string.h>
18     #include <time.h>
19     #include <errno.h>
20    
21 dpavlin 7 #include "cpu.h"
22     #include "vm.h"
23 dpavlin 1 #include "dynamips.h"
24     #include "memory.h"
25     #include "device.h"
26    
27     #define DEBUG_ACCESS 0
28    
29     /* SmartWatch pattern (p.5 of documentation) */
30     #define PATTERN 0x5ca33ac55ca33ac5ULL
31    
32     /* NVRAM private data */
33     struct nvram_data {
34     vm_obj_t vm_obj;
35     struct vdevice dev;
36     char *filename;
37     u_int cal_state;
38     m_uint64_t cal_read,cal_write;
39     };
40    
41     /* Convert an 8-bit number to a BCD form */
42     static m_uint8_t u8_to_bcd(m_uint8_t val)
43     {
44     return(((val / 10) << 4) + (val % 10));
45     }
46    
47     /* Get the current time (p.8) */
48 dpavlin 7 static m_uint64_t get_current_time(cpu_gen_t *cpu)
49 dpavlin 1 {
50     m_uint64_t res;
51     struct tm *tmx;
52     time_t ct;
53    
54     time(&ct);
55     tmx = localtime(&ct);
56    
57     res = u8_to_bcd(tmx->tm_sec) << 8;
58     res += u8_to_bcd(tmx->tm_min) << 16;
59     res += u8_to_bcd(tmx->tm_hour) << 24;
60     res += ((m_uint64_t)(u8_to_bcd(tmx->tm_wday))) << 32;
61     res += ((m_uint64_t)(u8_to_bcd(tmx->tm_mday))) << 40;
62     res += ((m_uint64_t)(u8_to_bcd(tmx->tm_mon+1))) << 48;
63     res += ((m_uint64_t)(u8_to_bcd(tmx->tm_year))) << 56;
64    
65     return(res);
66     }
67    
68     /*
69     * dev_nvram_access()
70     */
71 dpavlin 7 void *dev_nvram_access(cpu_gen_t *cpu,struct vdevice *dev,
72 dpavlin 1 m_uint32_t offset,u_int op_size,u_int op_type,
73     m_uint64_t *data)
74     {
75     struct nvram_data *d = dev->priv_data;
76    
77     #if DEBUG_ACCESS
78     if (op_type == MTS_READ)
79 dpavlin 7 cpu_log(cpu,dev->name,"read access to offset=0x%x, pc=0x%llx\n",
80     offset,cpu_get_pc(cpu));
81 dpavlin 1 else
82 dpavlin 7 cpu_log(cpu,dev->name,
83     "write access to vaddr=0x%x, pc=0x%llx, val=0x%llx\n",
84     offset,cpu_get_pc(cpu),*data);
85 dpavlin 1 #endif
86    
87     switch(offset) {
88     case 0x03:
89     if (op_type == MTS_READ) {
90     *data = d->cal_read & 1;
91     d->cal_read >>= 1;
92     } else {
93     d->cal_write >>= 1;
94     d->cal_write |= *data << 63;
95    
96     if (d->cal_write == PATTERN) {
97     d->cal_state = 1;
98     vm_log(cpu->vm,"Calendar","reset\n");
99     d->cal_read = get_current_time(cpu);
100     } else if(d->cal_state > 0 && d->cal_state++ == 64) {
101     /* untested */
102     vm_log(cpu->vm,"Calendar","set 0x%016llx\n",d->cal_write);
103     d->cal_state = 0;
104     }
105     }
106     return NULL;
107     }
108    
109     return((void *)(dev->host_addr + offset));
110     }
111    
112     /* Set appropriately the config register if the NVRAM is empty */
113     static void set_config_register(struct vdevice *dev,u_int *conf_reg)
114     {
115     m_uint32_t *ptr;
116     int i;
117    
118     ptr = (m_uint32_t *)dev->host_addr;
119     for(i=0;i<(dev->phys_len/4);i++,ptr++)
120     if (*ptr) return;
121    
122     /*
123     * nvram is empty: tells IOS to ignore its contents.
124     * http://www.cisco.com/en/US/products/hw/routers/ps274/products_installation_guide_chapter09186a008007de4c.html
125     */
126     *conf_reg |= 0x0040;
127     printf("NVRAM is empty, setting config register to 0x%x\n",*conf_reg);
128     }
129    
130     /* Shutdown the NVRAM device */
131     void dev_nvram_shutdown(vm_instance_t *vm,struct nvram_data *d)
132     {
133     if (d != NULL) {
134     /* Remove the device */
135     dev_remove(vm,&d->dev);
136    
137     /* We don't remove the file, since it used as permanent storage */
138     if (d->filename)
139     free(d->filename);
140    
141     /* Free the structure itself */
142     free(d);
143     }
144     }
145    
146     /* Create the NVRAM device */
147     int dev_nvram_init(vm_instance_t *vm,char *name,
148     m_uint64_t paddr,m_uint32_t len,
149     u_int *conf_reg)
150     {
151     struct nvram_data *d;
152     u_char *ptr;
153    
154     /* allocate the private data structure */
155     if (!(d = malloc(sizeof(*d)))) {
156     fprintf(stderr,"NVRAM: out of memory\n");
157     return(-1);
158     }
159    
160     memset(d,0,sizeof(*d));
161    
162     vm_object_init(&d->vm_obj);
163     d->vm_obj.name = name;
164     d->vm_obj.data = d;
165     d->vm_obj.shutdown = (vm_shutdown_t)dev_nvram_shutdown;
166    
167     if (!(d->filename = vm_build_filename(vm,name))) {
168     fprintf(stderr,"NVRAM: unable to create filename.\n");
169     return(-1);
170     }
171    
172     dev_init(&d->dev);
173     d->dev.name = name;
174     d->dev.phys_addr = paddr;
175     d->dev.phys_len = len;
176     d->dev.handler = dev_nvram_access;
177     d->dev.fd = memzone_create_file(d->filename,d->dev.phys_len,&ptr);
178     d->dev.host_addr = (m_iptr_t)ptr;
179     d->dev.flags = VDEVICE_FLAG_NO_MTS_MMAP|VDEVICE_FLAG_SYNC;
180     d->dev.priv_data = d;
181    
182     if (d->dev.fd == -1) {
183     fprintf(stderr,"NVRAM: unable to map file '%s'\n",d->filename);
184     return(-1);
185     }
186    
187     /* Modify the configuration register if NVRAM is empty */
188     set_config_register(&d->dev,conf_reg);
189    
190     /* Map this device to the VM */
191     vm_bind_device(vm,&d->dev);
192     vm_object_add(vm,&d->vm_obj);
193     return(0);
194     }
195 dpavlin 2
196     /* Compute NVRAM checksum */
197 dpavlin 4 m_uint16_t nvram_cksum_old(vm_instance_t *vm,m_uint64_t addr,size_t count)
198 dpavlin 2 {
199     m_uint32_t sum = 0;
200    
201     while(count > 1) {
202     sum = sum + physmem_copy_u16_from_vm(vm,addr);
203     addr += sizeof(m_uint16_t);
204     count -= sizeof(m_uint16_t);
205     }
206    
207     if (count > 0)
208     sum = sum + ((physmem_copy_u16_from_vm(vm,addr) & 0xFF) << 8);
209    
210     while(sum>>16)
211     sum = (sum & 0xffff) + (sum >> 16);
212    
213     return(~sum);
214     }

  ViewVC Help
Powered by ViewVC 1.1.26