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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Sat Oct 6 16:01:44 2007 UTC (12 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 5015 byte(s)
import 0.2.5 from upstream

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

  ViewVC Help
Powered by ViewVC 1.1.26