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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 /*
2 * Cisco C7200 (Predator) Simulation Platform.
3 * Copyright (C) 2005,2006 Christophe Fillot. All rights reserved.
4 *
5 * PLX PCI9060 - PCI bus master interface chip.
6 *
7 * This is very basic, it has been designed to allow the C7200 PA-POS-OC3
8 * to work.
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "mips64.h"
16 #include "dynamips.h"
17 #include "memory.h"
18 #include "device.h"
19 #include "pci_dev.h"
20
21 #define DEBUG_ACCESS 1
22
23 /* PLX9060 vendor/product codes */
24 #define PLX9060_PCI_VENDOR_ID 0x10b5
25 #define PLX9060_PCI_PRODUCT_ID 0x9060
26
27 #define PLX9060_S0_RANGE_DEFAULT 0xFFF00000
28 #define PLX9060_S0_RANGE_DECODE_MASK 0xFFFFFFF0
29
30 /* PLX9060 data */
31 struct plx9060_data {
32 /* Device name */
33 char *name;
34
35 /* Virtual machine and object info */
36 vm_instance_t *vm;
37 vm_obj_t vm_obj;
38
39 /* Virtual PLX device */
40 struct vdevice plx_dev;
41 struct pci_device *pci_plx_dev;
42
43 /* Managed device */
44 struct vdevice *dev;
45
46 /* Space 0 properties */
47 m_uint32_t space0_lbaddr;
48 m_uint32_t space0_range;
49 };
50
51 /* Log a PLX message */
52 #define PLX_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
53
54 /* Map space 0 */
55 static void plx9060_map_space0(struct plx9060_data *d)
56 {
57 d->dev->phys_len = 1+(~(d->space0_range & PLX9060_S0_RANGE_DECODE_MASK));
58 vm_map_device(d->vm,d->dev,d->space0_lbaddr);
59
60 PLX_LOG(d,"device mapped at 0x%llx, size=0x%x\n",
61 d->dev->phys_addr,d->dev->phys_len);
62 }
63
64 /* PLX9060 access */
65 void *dev_plx9060_access(cpu_mips_t *cpu,struct vdevice *dev,
66 m_uint32_t offset,u_int op_size,u_int op_type,
67 m_uint64_t *data)
68 {
69 struct plx9060_data *d = dev->priv_data;
70
71 if (op_type == MTS_READ)
72 *data = 0;
73
74 switch(offset) {
75 case 0x00:
76 if (op_type == MTS_WRITE) {
77 d->space0_range = *data;
78 plx9060_map_space0(d);
79 } else {
80 *data = d->space0_range;
81 }
82 break;
83
84 default:
85 if (op_type == MTS_READ) {
86 cpu_log(cpu,d->name,
87 "read from unhandled addr 0x%x, pc=0x%llx (size=%u)\n",
88 offset,cpu->pc,op_size);
89 } else {
90 cpu_log(cpu,d->name,
91 "write to handled addr 0x%x, value=0x%llx, "
92 "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);
93 }
94 }
95
96 return NULL;
97 }
98
99 /*
100 * pci_plx9060_read()
101 */
102 static m_uint32_t pci_plx9060_read(cpu_mips_t *cpu,struct pci_device *dev,
103 int reg)
104 {
105 struct plx9060_data *d = dev->priv_data;
106
107 #if DEBUG_ACCESS
108 PLX_LOG(d,"read PLX PCI register 0x%x\n",reg);
109 #endif
110 switch(reg) {
111 case PCI_REG_BAR0:
112 return(d->plx_dev.phys_addr);
113 case PCI_REG_BAR2:
114 return(d->space0_lbaddr);
115 default:
116 return(0);
117 }
118 }
119
120 /*
121 * pci_plx9060_cs_write()
122 */
123 static void pci_plx9060_write(cpu_mips_t *cpu,struct pci_device *dev,
124 int reg,m_uint32_t value)
125 {
126 struct plx9060_data *d = dev->priv_data;
127
128 #if DEBUG_ACCESS
129 PLX_LOG(d,"write 0x%x to PLX PCI register 0x%x\n",value,reg);
130 #endif
131
132 switch(reg) {
133 case PCI_REG_BAR0:
134 vm_map_device(cpu->vm,&d->plx_dev,(m_uint64_t)value);
135 PLX_LOG(d,"PLX registers are mapped at 0x%x\n",value);
136 break;
137 case PCI_REG_BAR2:
138 d->space0_lbaddr = value;
139 plx9060_map_space0(d);
140 break;
141 }
142 }
143
144 /* Shutdown a PLX9060 device */
145 void dev_plx9060_shutdown(vm_instance_t *vm,struct plx9060_data *d)
146 {
147 if (d != NULL) {
148 /* Unbind the managed device */
149 vm_unbind_device(vm,d->dev);
150
151 /* Remove the PLX device */
152 dev_remove(vm,&d->plx_dev);
153
154 /* Remove the PCI PLX device */
155 pci_dev_remove(d->pci_plx_dev);
156
157 /* Free the structure itself */
158 free(d);
159 }
160 }
161
162 /* Create a PLX9060 device */
163 vm_obj_t *dev_plx9060_init(vm_instance_t *vm,char *name,
164 struct pci_bus *pci_bus,int pci_device,
165 struct vdevice *dev)
166 {
167 struct plx9060_data *d;
168
169 if (!dev)
170 return NULL;
171
172 /* Allocate the private data structure */
173 if (!(d = malloc(sizeof(*d)))) {
174 fprintf(stderr,"PLX9060: unable to create device.\n");
175 return NULL;
176 }
177
178 memset(d,0,sizeof(*d));
179 vm_object_init(&d->vm_obj);
180 d->vm_obj.name = name;
181 d->vm_obj.data = d;
182 d->vm_obj.shutdown = (vm_shutdown_t)dev_plx9060_shutdown;
183
184 d->vm = vm;
185 d->dev = dev;
186 d->name = name;
187 d->space0_range = PLX9060_S0_RANGE_DEFAULT;
188
189 dev_init(&d->plx_dev);
190 d->plx_dev.name = name;
191 d->plx_dev.priv_data = d;
192 d->plx_dev.phys_addr = 0;
193 d->plx_dev.phys_len = 0x1000;
194 d->plx_dev.handler = dev_plx9060_access;
195
196 /* Add PLX as a PCI device */
197 d->pci_plx_dev = pci_dev_add(pci_bus,name,
198 PLX9060_PCI_VENDOR_ID,PLX9060_PCI_PRODUCT_ID,
199 pci_device,0,-1,d,
200 NULL,pci_plx9060_read,pci_plx9060_write);
201
202 if (!d->pci_plx_dev) {
203 fprintf(stderr,"%s (PLX9060): unable to create PCI device.\n",name);
204 goto err_pci_dev;
205 }
206
207 vm_object_add(vm,&d->vm_obj);
208 return(&d->vm_obj);
209
210 err_pci_dev:
211 free(d);
212 return NULL;
213 }

  ViewVC Help
Powered by ViewVC 1.1.26