/[dynamips]/upstream/dynamips-0.2.6-RC3/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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Sat Oct 6 16:05:34 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC2/dev_nvram.c
File MIME type: text/plain
File size: 5463 byte(s)
dynamips-0.2.6-RC2

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 }
193
194 /* Compute NVRAM checksum */
195 m_uint16_t nvram_cksum(vm_instance_t *vm,m_uint64_t addr,size_t count)
196 {
197 m_uint32_t sum = 0;
198
199 while(count > 1) {
200 sum = sum + physmem_copy_u16_from_vm(vm,addr);
201 addr += sizeof(m_uint16_t);
202 count -= sizeof(m_uint16_t);
203 }
204
205 if (count > 0)
206 sum = sum + ((physmem_copy_u16_from_vm(vm,addr) & 0xFF) << 8);
207
208 while(sum>>16)
209 sum = (sum & 0xffff) + (sum >> 16);
210
211 return(~sum);
212 }

  ViewVC Help
Powered by ViewVC 1.1.26