/[dynamips]/upstream/dynamips-0.2.8-RC1/dev_c2600_pci.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.8-RC1/dev_c2600_pci.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (show annotations)
Sat Oct 6 16:33:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 5560 byte(s)
dynamips-0.2.8-RC1

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Cisco 2600 PCI controller.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "utils.h"
13 #include "net.h"
14 #include "cpu.h"
15 #include "vm.h"
16 #include "dynamips.h"
17 #include "memory.h"
18 #include "device.h"
19 #include "net_io.h"
20
21 /* Debugging flags */
22 #define DEBUG_ACCESS 0
23 #define DEBUG_UNKNOWN 1
24 #define DEBUG_PCI 1
25
26 #define C2600_PCI_BRIDGE_VENDOR_ID 0x10ee
27 #define C2600_PCI_BRIDGE_PRODUCT_ID 0x4013
28
29 /* C2600 PCI controller */
30 struct c2600_pci_data {
31 char *name;
32 vm_obj_t vm_obj;
33 struct vdevice dev;
34 struct pci_device *pci_dev;
35 vm_instance_t *vm;
36
37 struct pci_bus *bus;
38 m_uint32_t bridge_bar0,bridge_bar1;
39 };
40
41 /*
42 * dev_c2600_pci_access()
43 */
44 void *dev_c2600_pci_access(cpu_gen_t *cpu,struct vdevice *dev,
45 m_uint32_t offset,u_int op_size,u_int op_type,
46 m_uint64_t *data)
47 {
48 struct c2600_pci_data *d = dev->priv_data;
49 struct pci_device *pci_dev;
50 u_int bus,device,function,reg;
51
52 if (op_type == MTS_READ)
53 *data = 0x0;
54
55 bus = 0;
56 device = (offset >> 12) & 0x0F;
57 function = (offset >> 8) & 0x07;
58 reg = offset & 0xFF;
59
60 /* Find the corresponding PCI device */
61 pci_dev = pci_dev_lookup(d->bus,bus,device,function);
62
63 #if DEBUG_PCI
64 if (op_type == MTS_READ) {
65 cpu_log(cpu,"PCI","read request at pc=0x%llx: "
66 "bus=%d,device=%d,function=%d,reg=0x%2.2x\n",
67 cpu_get_pc(cpu), bus, device, function, reg);
68 } else {
69 cpu_log(cpu,"PCI","write request (data=0x%8.8llx) at pc=0x%llx: "
70 "bus=%d,device=%d,function=%d,reg=0x%2.2x\n",
71 *data, cpu_get_pc(cpu), bus, device, function, reg);
72 }
73 #endif
74
75 if (!pci_dev) {
76 if (op_type == MTS_READ) {
77 cpu_log(cpu,"PCI","read request for unknown device at pc=0x%llx "
78 "(bus=%d,device=%d,function=%d,reg=0x%2.2x).\n",
79 cpu_get_pc(cpu), bus, device, function, reg);
80 } else {
81 cpu_log(cpu,"PCI","write request (data=0x%8.8llx) for unknown device "
82 "at pc=0x%llx (bus=%d,device=%d,function=%d,reg=0x%2.2x).\n",
83 *data, cpu_get_pc(cpu), bus, device, function, reg);
84 }
85
86 /* Returns an invalid device ID */
87 if ((op_type == MTS_READ) && (reg == PCI_REG_ID))
88 *data = 0xffffffff;
89 } else {
90 if (op_type == MTS_WRITE) {
91 if (pci_dev->write_register != NULL)
92 pci_dev->write_register(cpu,pci_dev,reg,*data);
93 } else {
94 if (reg == PCI_REG_ID)
95 *data = (pci_dev->product_id << 16) | pci_dev->vendor_id;
96 else {
97 if (pci_dev->read_register != NULL)
98 *data = pci_dev->read_register(cpu,pci_dev,reg);
99 }
100 }
101 }
102
103 return NULL;
104 }
105
106 /* Shutdown the c2600 PCI controller device */
107 void dev_c2600_pci_shutdown(vm_instance_t *vm,struct c2600_pci_data *d)
108 {
109 if (d != NULL) {
110 /* Remove the device */
111 dev_remove(vm,&d->dev);
112
113 /* Free the structure itself */
114 free(d);
115 }
116 }
117
118 /* PCI bridge read access */
119 static m_uint32_t dev_c2600_pci_bridge_read(cpu_gen_t *cpu,
120 struct pci_device *dev,
121 int reg)
122 {
123 struct c2600_pci_data *d = dev->priv_data;
124
125 switch(reg) {
126 case 0x10:
127 return(d->bridge_bar0);
128 case 0x14:
129 return(d->bridge_bar1);
130 default:
131 return(0);
132 }
133 }
134
135 /* PCI bridge read access */
136 static void dev_c2600_pci_bridge_write(cpu_gen_t *cpu,struct pci_device *dev,
137 int reg,m_uint32_t value)
138 {
139 struct c2600_pci_data *d = dev->priv_data;
140
141 switch(reg) {
142 case 0x10:
143 /* BAR0 must be at 0x00000000 for correct RAM access */
144 if (value != 0x00000000) {
145 vm_error(d->vm,"C2600_PCI",
146 "Trying to set bridge BAR0 at 0x%8.8x!\n",
147 value);
148 }
149 d->bridge_bar0 = value;
150 break;
151 case 0x14:
152 /* BAR1 = byte swapped zone */
153 if (!d->bridge_bar1) {
154 d->bridge_bar1 = value;
155
156 /* XXX */
157 dev_bswap_init(d->vm,"pci_bswap",d->bridge_bar1,0x10000000,
158 0x00000000);
159 }
160 break;
161 }
162 }
163
164 /* Create the c2600 PCI controller device */
165 int dev_c2600_pci_init(vm_instance_t *vm,char *name,
166 m_uint64_t paddr,m_uint32_t len,
167 struct pci_bus *bus)
168 {
169 struct c2600_pci_data *d;
170
171 if (!(d = malloc(sizeof(*d)))) {
172 fprintf(stderr,"c2600_pci: unable to create device data.\n");
173 return(-1);
174 }
175
176 memset(d,0,sizeof(*d));
177 d->name = name;
178 d->vm = vm;
179 d->bus = bus;
180
181 vm_object_init(&d->vm_obj);
182 d->vm_obj.name = name;
183 d->vm_obj.data = d;
184 d->vm_obj.shutdown = (vm_shutdown_t)dev_c2600_pci_shutdown;
185
186 dev_init(&d->dev);
187 d->dev.name = name;
188 d->dev.priv_data = d;
189 d->dev.phys_addr = paddr;
190 d->dev.phys_len = len;
191 d->dev.handler = dev_c2600_pci_access;
192
193 pci_dev_add(d->bus,"pci_bridge",
194 C2600_PCI_BRIDGE_VENDOR_ID,C2600_PCI_BRIDGE_PRODUCT_ID,
195 15,0,-1,d,
196 NULL,
197 dev_c2600_pci_bridge_read,
198 dev_c2600_pci_bridge_write);
199
200 /* Map this device to the VM */
201 vm_bind_device(vm,&d->dev);
202 vm_object_add(vm,&d->vm_obj);
203 return(0);
204 }
205

  ViewVC Help
Powered by ViewVC 1.1.26