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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
2 * Cisco C7200 (Predator) Bootflash.
3 * Copyright (c) 2006 Christophe Fillot. All rights reserved.
4 *
5 * Intel Flash SIMM emulation (28F008SA/28F016SA)
6 *
7 * Intelligent ID Codes:
8 * 28F008SA: 0x89A2 (1 Mb)
9 * 28F016SA: 0x89A0 (2 Mb)
10 *
11 * Manuals:
12 * http://www.ortodoxism.ro/datasheets/Intel/mXvsysv.pdf
13 *
14 * This code is working but is far from perfect. The four assembled circuits
15 * should be managed independently.
16 *
17 * Here, we emulate a group of four 28F016SA, for a total size of 8 Mb.
18 * If you need to change this, the Flash SIMM register must also be changed.
19 * (TODO: a CLI option + generic code).
20 */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <errno.h>
27
28 #include "mips64.h"
29 #include "dynamips.h"
30 #include "memory.h"
31 #include "device.h"
32
33 #define DEBUG_ACCESS 0
34 #define DEBUG_WRITE 0
35
36 /* Bootflash private data */
37 struct bootflash_data {
38 vm_obj_t vm_obj;
39 struct vdevice dev;
40 m_uint32_t cui_cmd,blk_cmd;
41 m_uint32_t status;
42 char *filename;
43 };
44
45 #define BPTR(d,offset) (((char *)d->dev.host_addr) + offset)
46
47 /*
48 * dev_bootflash_access()
49 */
50 void *dev_bootflash_access(cpu_mips_t *cpu,struct vdevice *dev,
51 m_uint32_t offset,u_int op_size,u_int op_type,
52 m_uint64_t *data)
53 {
54 struct bootflash_data *d = dev->priv_data;
55
56 #if DEBUG_ACCESS
57 if (op_type == MTS_READ)
58 cpu_log(cpu,dev->name,"read access to offset = 0x%x, pc = 0x%llx "
59 "(stat=%u,cui_cmd=0x%x)\n",
60 offset,cpu->pc,d->status,d->cui_cmd);
61 else
62 cpu_log(cpu,dev->name,"write access to vaddr = 0x%x, pc = 0x%llx, "
63 "val = 0x%llx\n",offset,cpu->pc,*data);
64 #endif
65
66 if (op_type == MTS_READ) {
67 /* Read Array mode */
68 if (d->status == 0)
69 return(BPTR(d,offset));
70
71 switch(d->cui_cmd) {
72 /* Intelligent identifier */
73 case 0x90909090:
74 switch(offset) {
75 case 0x00:
76 *data = 0x89898989; /* manufacturer code */
77 return NULL;
78 case 0x04:
79 *data = 0xA0A0A0A0; /* device code */
80 return NULL;
81 default:
82 cpu_log(cpu,dev->name,
83 "Reading Intelligent ID Code at offset = 0x%x ?\n",
84 offset);
85 *data = 0x00000000;
86 return NULL;
87 }
88 break;
89
90 /* Read Status Register */
91 case 0x70707070:
92 *data = 0x80808080;
93 return NULL;
94 }
95
96 /* Default: status register */
97 *data = 0x80808080;
98 return NULL;
99 }
100
101 /* write mode */
102 if (d->blk_cmd == 0x40404040) {
103 #if DEBUG_WRITE
104 cpu_log(cpu,dev->name,"Writing 0x%llx at offset=0x%x\n",*data,offset);
105 #endif
106 d->blk_cmd = 0;
107 d->cui_cmd = 0;
108 d->status = 1;
109 return(BPTR(d,offset));
110 }
111
112 switch(*data) {
113 /* Erase Setup */
114 case 0x20202020:
115 d->blk_cmd = *data;
116 break;
117
118 /* Erase Confirm */
119 case 0xd0d0d0d0:
120 if ((d->blk_cmd == 0x20202020) && !(offset & 0x3FFFF)) {
121 memset(BPTR(d,offset),0xFF,0x40000);
122 d->blk_cmd = 0;
123 d->cui_cmd = 0;
124 d->status = 1;
125 }
126 break;
127
128 /* Byte Write Setup (XXX ugly hack) */
129 case 0x40404040:
130 case 0x40ffffff:
131 case 0x4040ffff:
132 case 0x404040ff:
133 case 0xff404040:
134 case 0xffff4040:
135 case 0xffffff40:
136 d->blk_cmd = 0x40404040;
137 break;
138
139 /* Reset */
140 case 0xffffffff:
141 d->status = 0;
142 break;
143
144 /* Intelligent Identifier and Read Status register */
145 case 0x90909090:
146 case 0x70707070:
147 d->status = 1;
148 d->cui_cmd = *data;
149 break;
150
151 default:
152 cpu_log(cpu,dev->name,
153 "default write case at offset=0x%7.7x, val=0x%llx\n",
154 offset,*data);
155 }
156
157 return NULL;
158 }
159
160 /* Shutdown a bootflash device */
161 void dev_bootflash_shutdown(vm_instance_t *vm,struct bootflash_data *d)
162 {
163 if (d != NULL) {
164 /* Remove the device */
165 dev_remove(vm,&d->dev);
166
167 /* We don't remove the file, since it used as permanent storage */
168 if (d->filename)
169 free(d->filename);
170
171 /* Free the structure itself */
172 free(d);
173 }
174 }
175
176 /* Create a 8 Mb bootflash */
177 int dev_bootflash_init(vm_instance_t *vm,char *name,
178 m_uint64_t paddr,m_uint32_t len)
179 {
180 struct bootflash_data *d;
181 u_char *ptr;
182
183 /* Allocate the private data structure */
184 if (!(d = malloc(sizeof(*d)))) {
185 fprintf(stderr,"Bootflash: unable to create device.\n");
186 return(-1);
187 }
188
189 memset(d,0,sizeof(*d));
190
191 vm_object_init(&d->vm_obj);
192 d->vm_obj.name = name;
193 d->vm_obj.data = d;
194 d->vm_obj.shutdown = (vm_shutdown_t)dev_bootflash_shutdown;
195
196 if (!(d->filename = vm_build_filename(vm,name))) {
197 fprintf(stderr,"Bootflash: unable to create filename.\n");
198 goto err_filename;
199 }
200
201 dev_init(&d->dev);
202 d->dev.name = name;
203 d->dev.priv_data = d;
204 d->dev.phys_addr = paddr;
205 d->dev.phys_len = len;
206 d->dev.handler = dev_bootflash_access;
207 d->dev.fd = memzone_create_file(d->filename,d->dev.phys_len,&ptr);
208 d->dev.host_addr = (m_iptr_t)ptr;
209 d->dev.flags = VDEVICE_FLAG_NO_MTS_MMAP;
210
211 if (d->dev.fd == -1) {
212 fprintf(stderr,"Bootflash: unable to map file '%s'\n",d->filename);
213 goto err_fd_create;
214 }
215
216 /* Map this device to the VM */
217 vm_bind_device(vm,&d->dev);
218 vm_object_add(vm,&d->vm_obj);
219 return(0);
220
221 err_fd_create:
222 free(d->filename);
223 err_filename:
224 free(d);
225 return(-1);
226 }

  ViewVC Help
Powered by ViewVC 1.1.26