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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Sat Oct 6 16:45:40 2007 UTC (11 years, 11 months ago) by dpavlin
File MIME type: text/plain
File size: 6598 byte(s)
make working copy

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot. All rights reserved.
4 *
5 * Cirrus Logic PD6729 PCI-to-PCMCIA host adapter.
6 *
7 * TODO: finish the code! (especially extended registers)
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <time.h>
14 #include <errno.h>
15
16 #include "cpu.h"
17 #include "vm.h"
18 #include "dynamips.h"
19 #include "memory.h"
20 #include "device.h"
21 #include "pci_dev.h"
22 #include "pci_io.h"
23
24 #define DEBUG_ACCESS 0
25
26 /* Cirrus Logic PD6729 PCI vendor/product codes */
27 #define CLPD6729_PCI_VENDOR_ID 0x1013
28 #define CLPD6729_PCI_PRODUCT_ID 0x1100
29
30 #define CLPD6729_REG_CHIP_REV 0x00 /* Chip Revision */
31 #define CLPD6729_REG_INT_STATUS 0x01 /* Interface Status */
32 #define CLPD6729_REG_POWER_CTRL 0x02 /* Power Control */
33 #define CLPD6729_REG_INTGEN_CTRL 0x03 /* Interrupt & General Control */
34 #define CLPD6729_REG_CARD_STATUS 0x04 /* Card Status Change */
35 #define CLPD6729_REG_FIFO_CTRL 0x17 /* FIFO Control */
36 #define CLPD6729_REG_EXT_INDEX 0x2E /* Extended Index */
37
38 /* CLPD6729 private data */
39 struct clpd6729_data {
40 vm_obj_t vm_obj;
41 struct vdevice dev;
42 struct pci_device *pci_dev;
43 struct pci_io_device *pci_io_dev;
44
45 /* VM objects present in slots (typically, PCMCIA disks...) */
46 vm_obj_t *slot_obj[2];
47
48 /* Base registers */
49 m_uint8_t base_index;
50 m_uint8_t base_regs[256];
51 };
52
53 /* Handle access to a base register */
54 static void clpd6729_base_reg_access(cpu_gen_t *cpu,struct clpd6729_data *d,
55 u_int op_type,m_uint64_t *data)
56 {
57 u_int slot_id,reg;
58
59 #if DEBUG_ACCESS
60 if (op_type == MTS_READ) {
61 cpu_log(cpu,"CLPD6729","reading reg 0x%2.2x at pc=0x%llx\n",
62 d->base_index,cpu_get_pc(cpu));
63 } else {
64 cpu_log(cpu,"CLPD6729","writing reg 0x%2.2x, data=0x%llx at pc=0x%llx\n",
65 d->base_index,*data,cpu_get_pc(cpu));
66 }
67 #endif
68
69 if (op_type == MTS_READ)
70 *data = 0;
71
72 /* Reserved registers */
73 if (d->base_index >= 0x80)
74 return;
75
76 /*
77 * Socket A regs: 0x00 to 0x3f
78 * Socket B regs: 0x40 to 0x7f
79 */
80 if (d->base_index >= 0x40) {
81 slot_id = 1;
82 reg = d->base_index - 0x40;
83 } else {
84 slot_id = 0;
85 reg = d->base_index;
86 }
87
88 switch(reg) {
89 case CLPD6729_REG_CHIP_REV:
90 if (op_type == MTS_READ)
91 *data = 0x48;
92 break;
93
94 case CLPD6729_REG_INT_STATUS:
95 if (op_type == MTS_READ) {
96 if (d->slot_obj[slot_id])
97 *data = 0xEF;
98 else
99 *data = 0x80;
100 }
101 break;
102
103 case CLPD6729_REG_INTGEN_CTRL:
104 if (op_type == MTS_READ)
105 *data = 0x40;
106 break;
107
108 case CLPD6729_REG_EXT_INDEX:
109 if (op_type == MTS_WRITE) {
110 cpu_log(cpu,"CLPD6729","ext reg index 0x%2.2llx at pc=0x%llx\n",
111 *data,cpu_get_pc(cpu));
112 }
113 break;
114
115 case CLPD6729_REG_FIFO_CTRL:
116 if (op_type == MTS_READ)
117 *data = 0x80; /* FIFO is empty */
118 break;
119
120 default:
121 if (op_type == MTS_READ)
122 *data = d->base_regs[d->base_index];
123 else
124 d->base_regs[d->base_index] = (m_uint8_t)(*data);
125 }
126 }
127
128 /*
129 * dev_clpd6729_io_access()
130 */
131 static void *dev_clpd6729_io_access(cpu_gen_t *cpu,struct vdevice *dev,
132 m_uint32_t offset,u_int op_size,
133 u_int op_type,m_uint64_t *data)
134 {
135 struct clpd6729_data *d = dev->priv_data;
136
137 #if DEBUG_ACCESS
138 if (op_type == MTS_READ) {
139 cpu_log(cpu,dev->name,"reading at offset 0x%x, pc=0x%llx\n",
140 offset,cpu_get_pc(cpu));
141 } else {
142 cpu_log(cpu,dev->name,"writing at offset 0x%x, pc=0x%llx, data=0x%llx\n",
143 offset,cpu_get_pc(cpu),*data);
144 }
145 #endif
146
147 switch(offset) {
148 case 0:
149 /* Data register */
150 clpd6729_base_reg_access(cpu,d,op_type,data);
151 break;
152
153 case 1:
154 /* Index register */
155 if (op_type == MTS_READ)
156 *data = d->base_index;
157 else
158 d->base_index = *data;
159 break;
160 }
161
162 return NULL;
163 }
164
165 /* Shutdown a CLPD6729 device */
166 void dev_clpd6729_shutdown(vm_instance_t *vm,struct clpd6729_data *d)
167 {
168 if (d != NULL) {
169 /* Remove the PCI device */
170 pci_dev_remove(d->pci_dev);
171
172 /* Remove the PCI I/O device */
173 pci_io_remove(d->pci_io_dev);
174
175 /* Free the structure itself */
176 free(d);
177 }
178 }
179
180 /*
181 * dev_clpd6729_init()
182 */
183 int dev_clpd6729_init(vm_instance_t *vm,
184 struct pci_bus *pci_bus,int pci_device,
185 struct pci_io_data *pci_io_data,
186 m_uint32_t io_start,m_uint32_t io_end)
187 {
188 struct clpd6729_data *d;
189
190 /* Allocate the private data structure */
191 if (!(d = malloc(sizeof(*d)))) {
192 fprintf(stderr,"CLPD6729: unable to create device.\n");
193 return(-1);
194 }
195
196 memset(d,0,sizeof(*d));
197 vm_object_init(&d->vm_obj);
198 d->vm_obj.name = "clpd6729";
199 d->vm_obj.data = d;
200 d->vm_obj.shutdown = (vm_shutdown_t)dev_clpd6729_shutdown;
201
202 dev_init(&d->dev);
203 d->dev.name = "clpd6729";
204 d->dev.priv_data = d;
205
206 d->pci_io_dev = pci_io_add(pci_io_data,io_start,io_end,&d->dev,
207 dev_clpd6729_io_access);
208
209 d->pci_dev = pci_dev_add(pci_bus,"clpd6729",
210 CLPD6729_PCI_VENDOR_ID,CLPD6729_PCI_PRODUCT_ID,
211 pci_device,0,-1,&d->dev,NULL,NULL,NULL);
212
213 if (!d->pci_io_dev || !d->pci_dev) {
214 fprintf(stderr,"CLPD6729: unable to create PCI devices.\n");
215 dev_clpd6729_shutdown(vm,d);
216 return(-1);
217 }
218
219 vm_object_add(vm,&d->vm_obj);
220
221 #if 1
222 /* PCMCIA disk test */
223 if (vm->pcmcia_disk_size[0])
224 d->slot_obj[0] = dev_pcmcia_disk_init(vm,"disk0",0x40000000ULL,0x200000,
225 vm->pcmcia_disk_size[0],0);
226
227 if (vm->pcmcia_disk_size[1])
228 d->slot_obj[1] = dev_pcmcia_disk_init(vm,"disk1",0x44000000ULL,0x200000,
229 vm->pcmcia_disk_size[1],0);
230 #endif
231
232 #if 0
233 /* PCMCIA disk test */
234 if (vm->pcmcia_disk_size[0])
235 d->slot_obj[0] = dev_pcmcia_disk_init(vm,"disk0",0xd8000000ULL,0x200000,
236 vm->pcmcia_disk_size[0],0);
237
238 if (vm->pcmcia_disk_size[1])
239 d->slot_obj[1] = dev_pcmcia_disk_init(vm,"disk1",0xdc000000ULL,0x200000,
240 vm->pcmcia_disk_size[1],0);
241 #endif
242
243 return(0);
244 }

  ViewVC Help
Powered by ViewVC 1.1.26