1 |
dpavlin |
1 |
/* |
2 |
|
|
* Cisco 7200 (Predator) simulation platform. |
3 |
|
|
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
4 |
|
|
* |
5 |
|
|
* Galileo GT64010/GT64120A system controller. |
6 |
|
|
* |
7 |
|
|
* The DMA stuff is not complete, only "normal" transfers are working |
8 |
|
|
* (source and destination addresses incrementing). |
9 |
|
|
* |
10 |
|
|
* Also, these transfers are "instantaneous" from a CPU point-of-view: when |
11 |
|
|
* a channel is enabled, the transfer is immediately done. So, this is not |
12 |
|
|
* very realistic. |
13 |
|
|
*/ |
14 |
|
|
|
15 |
|
|
#include <stdio.h> |
16 |
|
|
#include <stdlib.h> |
17 |
|
|
#include <string.h> |
18 |
|
|
|
19 |
|
|
#include "mips64.h" |
20 |
|
|
#include "dynamips.h" |
21 |
|
|
#include "memory.h" |
22 |
|
|
#include "device.h" |
23 |
|
|
|
24 |
|
|
#define DEBUG_UNKNOWN 1 |
25 |
|
|
#define DEBUG_DMA 0 |
26 |
|
|
|
27 |
|
|
#define PCI_VENDOR_GALILEO 0x11ab /* Galileo Technology */ |
28 |
|
|
#define PCI_PRODUCT_GALILEO_GT64010 0x0146 /* GT-64010 */ |
29 |
|
|
#define PCI_PRODUCT_GALILEO_GT64011 0x4146 /* GT-64011 */ |
30 |
|
|
#define PCI_PRODUCT_GALILEO_GT64120 0x4620 /* GT-64120 */ |
31 |
|
|
|
32 |
|
|
/* DMA definitions */ |
33 |
|
|
#define GT64K_DMA_CHANNELS 4 |
34 |
|
|
|
35 |
|
|
#define GT64K_DMA_FLYBY_ENABLE 0x00000001 /* FlyBy Enable */ |
36 |
|
|
#define GT64K_DMA_FLYBY_RDWR 0x00000002 /* SDRAM Read/Write (FlyBy) */ |
37 |
|
|
#define GT64K_DMA_SRC_DIR 0x0000000c /* Source Direction */ |
38 |
|
|
#define GT64K_DMA_DST_DIR 0x00000030 /* Destination Direction */ |
39 |
|
|
#define GT64K_DMA_DATA_LIMIT 0x000001c0 /* Data Transfer Limit */ |
40 |
|
|
#define GT64K_DMA_CHAIN_MODE 0x00000200 /* Chained Mode */ |
41 |
|
|
#define GT64K_DMA_INT_MODE 0x00000400 /* Interrupt Mode */ |
42 |
|
|
#define GT64K_DMA_TRANS_MODE 0x00000800 /* Transfer Mode */ |
43 |
|
|
#define GT64K_DMA_CHAN_ENABLE 0x00001000 /* Channel Enable */ |
44 |
|
|
#define GT64K_DMA_FETCH_NEXT 0x00002000 /* Fetch Next Record */ |
45 |
|
|
#define GT64K_DMA_ACT_STATUS 0x00004000 /* DMA Activity Status */ |
46 |
|
|
#define GT64K_DMA_SDA 0x00008000 /* Source/Destination Alignment */ |
47 |
|
|
#define GT64K_DMA_MDREQ 0x00010000 /* Mask DMA Requests */ |
48 |
|
|
#define GT64K_DMA_CDE 0x00020000 /* Close Descriptor Enable */ |
49 |
|
|
#define GT64K_DMA_EOTE 0x00040000 /* End-of-Transfer (EOT) Enable */ |
50 |
|
|
#define GT64K_DMA_EOTIE 0x00080000 /* EOT Interrupt Enable */ |
51 |
|
|
#define GT64K_DMA_ABORT 0x00100000 /* Abort DMA Transfer */ |
52 |
|
|
#define GT64K_DMA_SLP 0x00600000 /* Override Source Address */ |
53 |
|
|
#define GT64K_DMA_DLP 0x01800000 /* Override Dest Address */ |
54 |
|
|
#define GT64K_DMA_RLP 0x06000000 /* Override Record Address */ |
55 |
|
|
#define GT64K_DMA_REQ_SRC 0x10000000 /* DMA Request Source */ |
56 |
|
|
|
57 |
|
|
/* Galileo GT-64k DMA channel */ |
58 |
|
|
struct dma_channel { |
59 |
|
|
m_uint32_t byte_count; |
60 |
|
|
m_uint32_t src_addr; |
61 |
|
|
m_uint32_t dst_addr; |
62 |
|
|
m_uint32_t cdptr; |
63 |
|
|
m_uint32_t nrptr; |
64 |
|
|
m_uint32_t ctrl; |
65 |
|
|
}; |
66 |
|
|
|
67 |
|
|
/* Galileo GT-64k system controller */ |
68 |
|
|
struct gt64k_data { |
69 |
|
|
vm_obj_t vm_obj; |
70 |
|
|
struct vdevice dev; |
71 |
|
|
struct pci_device *pci_dev; |
72 |
|
|
vm_instance_t *vm; |
73 |
|
|
|
74 |
|
|
struct pci_bus *bus[2]; |
75 |
|
|
struct dma_channel dma[GT64K_DMA_CHANNELS]; |
76 |
|
|
m_uint32_t int_cause_reg; |
77 |
|
|
m_uint32_t int_mask_reg; |
78 |
|
|
}; |
79 |
|
|
|
80 |
|
|
/* Update the interrupt status */ |
81 |
|
|
static void gt64k_update_irq_status(struct gt64k_data *gt_data) |
82 |
|
|
{ |
83 |
|
|
if (gt_data->pci_dev) { |
84 |
|
|
if (gt_data->int_cause_reg & gt_data->int_mask_reg) |
85 |
|
|
pci_dev_trigger_irq(gt_data->vm,gt_data->pci_dev); |
86 |
|
|
else |
87 |
|
|
pci_dev_clear_irq(gt_data->vm,gt_data->pci_dev); |
88 |
|
|
} |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
/* Fetch a DMA record (chained mode) */ |
92 |
|
|
static void gt64k_dma_fetch_rec(vm_instance_t *vm,struct dma_channel *channel) |
93 |
|
|
{ |
94 |
|
|
m_uint32_t ptr; |
95 |
|
|
|
96 |
|
|
#if DEBUG_DMA |
97 |
|
|
cpu_log(cpu,"GT64K_DMA","fetching record at address 0x%x\n",channel->nrptr); |
98 |
|
|
#endif |
99 |
|
|
|
100 |
|
|
/* fetch the record from RAM */ |
101 |
|
|
ptr = channel->nrptr; |
102 |
|
|
channel->byte_count = swap32(physmem_copy_u32_from_vm(vm,ptr)); |
103 |
|
|
channel->src_addr = swap32(physmem_copy_u32_from_vm(vm,ptr+0x04)); |
104 |
|
|
channel->dst_addr = swap32(physmem_copy_u32_from_vm(vm,ptr+0x08)); |
105 |
|
|
channel->nrptr = swap32(physmem_copy_u32_from_vm(vm,ptr+0x0c)); |
106 |
|
|
|
107 |
|
|
/* clear the "fetch next record bit" */ |
108 |
|
|
channel->ctrl &= ~GT64K_DMA_FETCH_NEXT; |
109 |
|
|
} |
110 |
|
|
|
111 |
|
|
/* Handle control register of a DMA channel */ |
112 |
|
|
static void gt64k_dma_handle_ctrl(struct gt64k_data *gt_data,int chan_id) |
113 |
|
|
{ |
114 |
|
|
struct dma_channel *channel = >_data->dma[chan_id]; |
115 |
|
|
vm_instance_t *vm = gt_data->vm; |
116 |
|
|
int done; |
117 |
|
|
|
118 |
|
|
if (channel->ctrl & GT64K_DMA_FETCH_NEXT) { |
119 |
|
|
if (channel->nrptr == 0) { |
120 |
|
|
vm_log(vm,"GT64K_DMA","trying to load a NULL DMA record...\n"); |
121 |
|
|
return; |
122 |
|
|
} |
123 |
|
|
|
124 |
|
|
gt64k_dma_fetch_rec(vm,channel); |
125 |
|
|
} |
126 |
|
|
|
127 |
|
|
if (channel->ctrl & GT64K_DMA_CHAN_ENABLE) |
128 |
|
|
{ |
129 |
|
|
do { |
130 |
|
|
done = TRUE; |
131 |
|
|
|
132 |
|
|
#if DEBUG_DMA |
133 |
|
|
cpu_log(cpu,"GT64K_DMA", |
134 |
|
|
"starting transfer from 0x%x to 0x%x (size=%u bytes)\n", |
135 |
|
|
channel->src_addr,channel->dst_addr, |
136 |
|
|
channel->byte_count & 0xFFFF); |
137 |
|
|
#endif |
138 |
|
|
physmem_dma_transfer(vm,channel->src_addr,channel->dst_addr, |
139 |
|
|
channel->byte_count & 0xFFFF); |
140 |
|
|
|
141 |
|
|
/* chained mode */ |
142 |
|
|
if (!(channel->ctrl & GT64K_DMA_CHAIN_MODE)) { |
143 |
|
|
if (channel->nrptr) { |
144 |
|
|
gt64k_dma_fetch_rec(vm,channel); |
145 |
|
|
done = FALSE; |
146 |
|
|
} |
147 |
|
|
} |
148 |
|
|
}while(!done); |
149 |
|
|
|
150 |
|
|
/* Trigger DMA interrupt */ |
151 |
|
|
gt_data->int_cause_reg |= 1 << (4 + chan_id); |
152 |
|
|
gt64k_update_irq_status(gt_data); |
153 |
|
|
} |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
#define DMA_REG(ch,reg_name) \ |
157 |
|
|
if (op_type == MTS_WRITE) \ |
158 |
|
|
gt_data->dma[ch].reg_name = swap32(*data); \ |
159 |
|
|
else \ |
160 |
|
|
*data = swap32(gt_data->dma[ch].reg_name); |
161 |
|
|
|
162 |
|
|
/* Handle a DMA channel */ |
163 |
|
|
static int gt64k_dma_access(cpu_mips_t *cpu,struct vdevice *dev, |
164 |
|
|
m_uint32_t offset,u_int op_size,u_int op_type, |
165 |
|
|
m_uint64_t *data) |
166 |
|
|
{ |
167 |
|
|
struct gt64k_data *gt_data = dev->priv_data; |
168 |
|
|
|
169 |
|
|
switch(offset) { |
170 |
|
|
/* DMA Source Address */ |
171 |
|
|
case 0x810: DMA_REG(0,src_addr); return(1); |
172 |
|
|
case 0x814: DMA_REG(1,src_addr); return(1); |
173 |
|
|
case 0x818: DMA_REG(2,src_addr); return(1); |
174 |
|
|
case 0x81c: DMA_REG(3,src_addr); return(1); |
175 |
|
|
|
176 |
|
|
/* DMA Destination Address */ |
177 |
|
|
case 0x820: DMA_REG(0,dst_addr); return(1); |
178 |
|
|
case 0x824: DMA_REG(1,dst_addr); return(1); |
179 |
|
|
case 0x828: DMA_REG(2,dst_addr); return(1); |
180 |
|
|
case 0x82c: DMA_REG(3,dst_addr); return(1); |
181 |
|
|
|
182 |
|
|
/* DMA Next Record Pointer */ |
183 |
|
|
case 0x830: |
184 |
|
|
gt_data->dma[0].cdptr = *data; |
185 |
|
|
DMA_REG(0,nrptr); |
186 |
|
|
return(1); |
187 |
|
|
|
188 |
|
|
case 0x834: |
189 |
|
|
gt_data->dma[1].cdptr = *data; |
190 |
|
|
DMA_REG(1,nrptr); |
191 |
|
|
return(1); |
192 |
|
|
|
193 |
|
|
case 0x838: |
194 |
|
|
gt_data->dma[2].cdptr = *data; |
195 |
|
|
DMA_REG(2,nrptr); |
196 |
|
|
return(1); |
197 |
|
|
|
198 |
|
|
case 0x83c: |
199 |
|
|
gt_data->dma[3].cdptr = *data; |
200 |
|
|
DMA_REG(3,nrptr); |
201 |
|
|
return(1); |
202 |
|
|
|
203 |
|
|
/* DMA Channel Control */ |
204 |
|
|
case 0x840: |
205 |
|
|
DMA_REG(0,ctrl); |
206 |
|
|
if (op_type == MTS_WRITE) |
207 |
|
|
gt64k_dma_handle_ctrl(gt_data,0); |
208 |
|
|
return(1); |
209 |
|
|
|
210 |
|
|
case 0x844: |
211 |
|
|
DMA_REG(1,ctrl); |
212 |
|
|
if (op_type == MTS_WRITE) |
213 |
|
|
gt64k_dma_handle_ctrl(gt_data,1); |
214 |
|
|
return(1); |
215 |
|
|
|
216 |
|
|
case 0x848: |
217 |
|
|
DMA_REG(2,ctrl); |
218 |
|
|
if (op_type == MTS_WRITE) |
219 |
|
|
gt64k_dma_handle_ctrl(gt_data,2); |
220 |
|
|
return(1); |
221 |
|
|
|
222 |
|
|
case 0x84c: |
223 |
|
|
DMA_REG(3,ctrl); |
224 |
|
|
if (op_type == MTS_WRITE) |
225 |
|
|
gt64k_dma_handle_ctrl(gt_data,3); |
226 |
|
|
return(1); |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
return(0); |
230 |
|
|
} |
231 |
|
|
|
232 |
|
|
/* |
233 |
|
|
* dev_gt64010_access() |
234 |
|
|
*/ |
235 |
|
|
void *dev_gt64010_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, |
236 |
|
|
u_int op_size,u_int op_type,m_uint64_t *data) |
237 |
|
|
{ |
238 |
|
|
struct gt64k_data *gt_data = dev->priv_data; |
239 |
|
|
|
240 |
|
|
if (op_type == MTS_READ) |
241 |
|
|
*data = 0; |
242 |
|
|
|
243 |
|
|
if (gt64k_dma_access(cpu,dev,offset,op_size,op_type,data) != 0) |
244 |
|
|
return NULL; |
245 |
|
|
|
246 |
|
|
switch(offset) { |
247 |
|
|
/* ===== DRAM Settings (completely faked, 128 Mb) ===== */ |
248 |
|
|
case 0x008: /* ras10_low */ |
249 |
|
|
if (op_type == MTS_READ) |
250 |
|
|
*data = swap32(0x000); |
251 |
|
|
break; |
252 |
|
|
case 0x010: /* ras10_high */ |
253 |
|
|
if (op_type == MTS_READ) |
254 |
|
|
*data = swap32(0x7F); |
255 |
|
|
break; |
256 |
|
|
case 0x018: /* ras32_low */ |
257 |
|
|
if (op_type == MTS_READ) |
258 |
|
|
*data = swap32(0x080); |
259 |
|
|
break; |
260 |
|
|
case 0x020: /* ras32_high */ |
261 |
|
|
if (op_type == MTS_READ) |
262 |
|
|
*data = swap32(0x7F); |
263 |
|
|
break; |
264 |
|
|
case 0x400: /* ras0_low */ |
265 |
|
|
if (op_type == MTS_READ) |
266 |
|
|
*data = swap32(0x00); |
267 |
|
|
break; |
268 |
|
|
case 0x404: /* ras0_high */ |
269 |
|
|
if (op_type == MTS_READ) |
270 |
|
|
*data = swap32(0xFF); |
271 |
|
|
break; |
272 |
|
|
case 0x408: /* ras1_low */ |
273 |
|
|
if (op_type == MTS_READ) |
274 |
|
|
*data = swap32(0x7F); |
275 |
|
|
break; |
276 |
|
|
case 0x40c: /* ras1_high */ |
277 |
|
|
if (op_type == MTS_READ) |
278 |
|
|
*data = swap32(0x00); |
279 |
|
|
break; |
280 |
|
|
case 0x410: /* ras2_low */ |
281 |
|
|
if (op_type == MTS_READ) |
282 |
|
|
*data = swap32(0x00); |
283 |
|
|
break; |
284 |
|
|
case 0x414: /* ras2_high */ |
285 |
|
|
if (op_type == MTS_READ) |
286 |
|
|
*data = swap32(0xFF); |
287 |
|
|
break; |
288 |
|
|
case 0x418: /* ras3_low */ |
289 |
|
|
if (op_type == MTS_READ) |
290 |
|
|
*data = swap32(0x7F); |
291 |
|
|
break; |
292 |
|
|
case 0x41c: /* ras3_high */ |
293 |
|
|
if (op_type == MTS_READ) |
294 |
|
|
*data = swap32(0x00); |
295 |
|
|
break; |
296 |
|
|
case 0xc08: /* pci0_cs10 */ |
297 |
|
|
if (op_type == MTS_READ) |
298 |
|
|
*data = swap32(0xFFF); |
299 |
|
|
break; |
300 |
|
|
case 0xc0c: /* pci0_cs32 */ |
301 |
|
|
if (op_type == MTS_READ) |
302 |
|
|
*data = swap32(0xFFF); |
303 |
|
|
break; |
304 |
|
|
|
305 |
|
|
case 0xc00: /* pci_cmd */ |
306 |
|
|
if (op_type == MTS_READ) |
307 |
|
|
*data = swap32(0x00008001); |
308 |
|
|
break; |
309 |
|
|
|
310 |
|
|
/* ===== Interrupt Cause Register ===== */ |
311 |
|
|
case 0xc18: |
312 |
|
|
if (op_type == MTS_READ) { |
313 |
|
|
*data = swap32(gt_data->int_cause_reg); |
314 |
|
|
} else { |
315 |
|
|
gt_data->int_cause_reg &= swap32(*data); |
316 |
|
|
gt64k_update_irq_status(gt_data); |
317 |
|
|
} |
318 |
|
|
break; |
319 |
|
|
|
320 |
|
|
/* ===== Interrupt Mask Register ===== */ |
321 |
|
|
case 0xc1c: |
322 |
|
|
if (op_type == MTS_READ) |
323 |
|
|
*data = swap32(gt_data->int_mask_reg); |
324 |
|
|
else { |
325 |
|
|
gt_data->int_mask_reg = swap32(*data); |
326 |
|
|
gt64k_update_irq_status(gt_data); |
327 |
|
|
} |
328 |
|
|
break; |
329 |
|
|
|
330 |
|
|
/* ===== PCI Configuration ===== */ |
331 |
|
|
case PCI_BUS_ADDR: /* pci configuration address (0xcf8) */ |
332 |
|
|
pci_dev_addr_handler(cpu,gt_data->bus[0],op_type,TRUE,data); |
333 |
|
|
break; |
334 |
|
|
|
335 |
|
|
case PCI_BUS_DATA: /* pci data address (0xcfc) */ |
336 |
|
|
pci_dev_data_handler(cpu,gt_data->bus[0],op_type,TRUE,data); |
337 |
|
|
break; |
338 |
|
|
|
339 |
|
|
#if DEBUG_UNKNOWN |
340 |
|
|
default: |
341 |
|
|
if (op_type == MTS_READ) { |
342 |
|
|
cpu_log(cpu,"GT64010","read from addr 0x%x, pc=0x%llx\n", |
343 |
|
|
offset,cpu->pc); |
344 |
|
|
} else { |
345 |
|
|
cpu_log(cpu,"GT64010","write to addr 0x%x, value=0x%llx, " |
346 |
|
|
"pc=0x%llx\n",offset,*data,cpu->pc); |
347 |
|
|
} |
348 |
|
|
#endif |
349 |
|
|
} |
350 |
|
|
|
351 |
|
|
return NULL; |
352 |
|
|
} |
353 |
|
|
|
354 |
|
|
/* |
355 |
|
|
* dev_gt64120_access() |
356 |
|
|
*/ |
357 |
|
|
void *dev_gt64120_access(cpu_mips_t *cpu,struct vdevice *dev,m_uint32_t offset, |
358 |
|
|
u_int op_size,u_int op_type,m_uint64_t *data) |
359 |
|
|
{ |
360 |
|
|
struct gt64k_data *gt_data = dev->priv_data; |
361 |
|
|
|
362 |
|
|
if (op_type == MTS_READ) |
363 |
|
|
*data = 0; |
364 |
|
|
|
365 |
|
|
if (gt64k_dma_access(cpu,dev,offset,op_size,op_type,data) != 0) |
366 |
|
|
return NULL; |
367 |
|
|
|
368 |
|
|
switch(offset) { |
369 |
|
|
case 0x008: /* ras10_low */ |
370 |
|
|
if (op_type == MTS_READ) |
371 |
|
|
*data = swap32(0x000); |
372 |
|
|
break; |
373 |
|
|
case 0x010: /* ras10_high */ |
374 |
|
|
if (op_type == MTS_READ) |
375 |
|
|
*data = swap32(0x7F); |
376 |
|
|
break; |
377 |
|
|
case 0x018: /* ras32_low */ |
378 |
|
|
if (op_type == MTS_READ) |
379 |
|
|
*data = swap32(0x100); |
380 |
|
|
break; |
381 |
|
|
case 0x020: /* ras32_high */ |
382 |
|
|
if (op_type == MTS_READ) |
383 |
|
|
*data = swap32(0x7F); |
384 |
|
|
break; |
385 |
|
|
case 0x400: /* ras0_low */ |
386 |
|
|
if (op_type == MTS_READ) |
387 |
|
|
*data = swap32(0x00); |
388 |
|
|
break; |
389 |
|
|
case 0x404: /* ras0_high */ |
390 |
|
|
if (op_type == MTS_READ) |
391 |
|
|
*data = swap32(0xFF); |
392 |
|
|
break; |
393 |
|
|
case 0x408: /* ras1_low */ |
394 |
|
|
if (op_type == MTS_READ) |
395 |
|
|
*data = swap32(0x7F); |
396 |
|
|
break; |
397 |
|
|
case 0x40c: /* ras1_high */ |
398 |
|
|
if (op_type == MTS_READ) |
399 |
|
|
*data = swap32(0x00); |
400 |
|
|
break; |
401 |
|
|
case 0x410: /* ras2_low */ |
402 |
|
|
if (op_type == MTS_READ) |
403 |
|
|
*data = swap32(0x00); |
404 |
|
|
break; |
405 |
|
|
case 0x414: /* ras2_high */ |
406 |
|
|
if (op_type == MTS_READ) |
407 |
|
|
*data = swap32(0xFF); |
408 |
|
|
break; |
409 |
|
|
case 0x418: /* ras3_low */ |
410 |
|
|
if (op_type == MTS_READ) |
411 |
|
|
*data = swap32(0x7F); |
412 |
|
|
break; |
413 |
|
|
case 0x41c: /* ras3_high */ |
414 |
|
|
if (op_type == MTS_READ) |
415 |
|
|
*data = swap32(0x00); |
416 |
|
|
break; |
417 |
|
|
case 0xc08: /* pci0_cs10 */ |
418 |
|
|
if (op_type == MTS_READ) |
419 |
|
|
*data = swap32(0xFFF); |
420 |
|
|
break; |
421 |
|
|
case 0xc0c: /* pci0_cs32 */ |
422 |
|
|
if (op_type == MTS_READ) |
423 |
|
|
*data = swap32(0xFFF); |
424 |
|
|
break; |
425 |
|
|
|
426 |
|
|
case 0xc00: /* pci_cmd */ |
427 |
|
|
if (op_type == MTS_READ) |
428 |
|
|
*data = swap32(0x00008001); |
429 |
|
|
break; |
430 |
|
|
|
431 |
|
|
/* ===== Interrupt Cause Register ===== */ |
432 |
|
|
case 0xc18: |
433 |
|
|
if (op_type == MTS_READ) |
434 |
|
|
*data = swap32(gt_data->int_cause_reg); |
435 |
|
|
else { |
436 |
|
|
gt_data->int_cause_reg &= swap32(*data); |
437 |
|
|
gt64k_update_irq_status(gt_data); |
438 |
|
|
} |
439 |
|
|
break; |
440 |
|
|
|
441 |
|
|
/* ===== Interrupt Mask Register ===== */ |
442 |
|
|
case 0xc1c: |
443 |
|
|
if (op_type == MTS_READ) { |
444 |
|
|
*data = swap32(gt_data->int_mask_reg); |
445 |
|
|
} else { |
446 |
|
|
gt_data->int_mask_reg = swap32(*data); |
447 |
|
|
gt64k_update_irq_status(gt_data); |
448 |
|
|
} |
449 |
|
|
break; |
450 |
|
|
|
451 |
|
|
/* ===== PCI Bus 1 ===== */ |
452 |
|
|
case 0xcf0: |
453 |
|
|
pci_dev_addr_handler(cpu,gt_data->bus[1],op_type,TRUE,data); |
454 |
|
|
break; |
455 |
|
|
|
456 |
|
|
case 0xcf4: |
457 |
|
|
pci_dev_data_handler(cpu,gt_data->bus[1],op_type,TRUE,data); |
458 |
|
|
break; |
459 |
|
|
|
460 |
|
|
/* ===== PCI Bus 0 ===== */ |
461 |
|
|
case PCI_BUS_ADDR: /* pci configuration address (0xcf8) */ |
462 |
|
|
pci_dev_addr_handler(cpu,gt_data->bus[0],op_type,TRUE,data); |
463 |
|
|
break; |
464 |
|
|
|
465 |
|
|
case PCI_BUS_DATA: /* pci data address (0xcfc) */ |
466 |
|
|
pci_dev_data_handler(cpu,gt_data->bus[0],op_type,TRUE,data); |
467 |
|
|
break; |
468 |
|
|
|
469 |
|
|
#if DEBUG_UNKNOWN |
470 |
|
|
default: |
471 |
|
|
if (op_type == MTS_READ) { |
472 |
|
|
cpu_log(cpu,"GT64120","read from addr 0x%x, pc=0x%llx\n", |
473 |
|
|
offset,cpu->pc); |
474 |
|
|
} else { |
475 |
|
|
cpu_log(cpu,"GT64120","write to addr 0x%x, value=0x%llx, " |
476 |
|
|
"pc=0x%llx\n",offset,*data,cpu->pc); |
477 |
|
|
} |
478 |
|
|
#endif |
479 |
|
|
} |
480 |
|
|
|
481 |
|
|
return NULL; |
482 |
|
|
} |
483 |
|
|
|
484 |
|
|
/* Shutdown a GT64k system controller */ |
485 |
|
|
void dev_gt64k_shutdown(vm_instance_t *vm,struct gt64k_data *d) |
486 |
|
|
{ |
487 |
|
|
if (d != NULL) { |
488 |
|
|
/* Remove the device */ |
489 |
|
|
dev_remove(vm,&d->dev); |
490 |
|
|
|
491 |
|
|
/* Remove the PCI device */ |
492 |
|
|
pci_dev_remove(d->pci_dev); |
493 |
|
|
|
494 |
|
|
/* Free the structure itself */ |
495 |
|
|
free(d); |
496 |
|
|
} |
497 |
|
|
} |
498 |
|
|
|
499 |
|
|
/* Create a new GT64010 controller */ |
500 |
|
|
int dev_gt64010_init(vm_instance_t *vm,char *name, |
501 |
|
|
m_uint64_t paddr,m_uint32_t len,u_int irq) |
502 |
|
|
{ |
503 |
|
|
struct gt64k_data *d; |
504 |
|
|
|
505 |
|
|
if (!(d = malloc(sizeof(*d)))) { |
506 |
|
|
fprintf(stderr,"gt64010: unable to create device data.\n"); |
507 |
|
|
return(-1); |
508 |
|
|
} |
509 |
|
|
|
510 |
|
|
memset(d,0,sizeof(*d)); |
511 |
|
|
d->vm = vm; |
512 |
|
|
d->bus[0] = vm->pci_bus[0]; |
513 |
|
|
|
514 |
|
|
vm_object_init(&d->vm_obj); |
515 |
|
|
d->vm_obj.name = name; |
516 |
|
|
d->vm_obj.data = d; |
517 |
|
|
d->vm_obj.shutdown = (vm_shutdown_t)dev_gt64k_shutdown; |
518 |
|
|
|
519 |
|
|
dev_init(&d->dev); |
520 |
|
|
d->dev.name = name; |
521 |
|
|
d->dev.priv_data = d; |
522 |
|
|
d->dev.phys_addr = paddr; |
523 |
|
|
d->dev.phys_len = len; |
524 |
|
|
d->dev.handler = dev_gt64010_access; |
525 |
|
|
|
526 |
|
|
/* Add the controller as a PCI device */ |
527 |
|
|
if (!pci_dev_lookup(d->bus[0],0,0,0)) { |
528 |
|
|
d->pci_dev = pci_dev_add(d->bus[0],name, |
529 |
|
|
PCI_VENDOR_GALILEO,PCI_PRODUCT_GALILEO_GT64010, |
530 |
|
|
0,0,irq,d,NULL,NULL,NULL); |
531 |
|
|
|
532 |
|
|
if (!d->pci_dev) { |
533 |
|
|
fprintf(stderr,"gt64010: unable to create PCI device.\n"); |
534 |
|
|
return(-1); |
535 |
|
|
} |
536 |
|
|
} |
537 |
|
|
|
538 |
|
|
/* Map this device to the VM */ |
539 |
|
|
vm_bind_device(vm,&d->dev); |
540 |
|
|
vm_object_add(vm,&d->vm_obj); |
541 |
|
|
return(0); |
542 |
|
|
} |
543 |
|
|
|
544 |
|
|
/* |
545 |
|
|
* pci_gt64120_read() |
546 |
|
|
* |
547 |
|
|
* Read a PCI register. |
548 |
|
|
*/ |
549 |
|
|
static m_uint32_t pci_gt64120_read(cpu_mips_t *cpu,struct pci_device *dev, |
550 |
|
|
int reg) |
551 |
|
|
{ |
552 |
|
|
switch (reg) { |
553 |
|
|
case 0x08: |
554 |
|
|
return(0x03008005); |
555 |
|
|
default: |
556 |
|
|
return(0); |
557 |
|
|
} |
558 |
|
|
} |
559 |
|
|
|
560 |
|
|
/* Create a new GT64120 controller */ |
561 |
|
|
int dev_gt64120_init(vm_instance_t *vm,char *name, |
562 |
|
|
m_uint64_t paddr,m_uint32_t len,u_int irq) |
563 |
|
|
{ |
564 |
|
|
struct gt64k_data *d; |
565 |
|
|
|
566 |
|
|
if (!(d = malloc(sizeof(*d)))) { |
567 |
|
|
fprintf(stderr,"gt64120: unable to create device data.\n"); |
568 |
|
|
return(-1); |
569 |
|
|
} |
570 |
|
|
|
571 |
|
|
memset(d,0,sizeof(*d)); |
572 |
|
|
d->vm = vm; |
573 |
|
|
d->bus[0] = vm->pci_bus[0]; |
574 |
|
|
d->bus[1] = vm->pci_bus[1]; |
575 |
|
|
|
576 |
|
|
vm_object_init(&d->vm_obj); |
577 |
|
|
d->vm_obj.name = name; |
578 |
|
|
d->vm_obj.data = d; |
579 |
|
|
d->vm_obj.shutdown = (vm_shutdown_t)dev_gt64k_shutdown; |
580 |
|
|
|
581 |
|
|
dev_init(&d->dev); |
582 |
|
|
d->dev.name = name; |
583 |
|
|
d->dev.priv_data = d; |
584 |
|
|
d->dev.phys_addr = paddr; |
585 |
|
|
d->dev.phys_len = len; |
586 |
|
|
d->dev.handler = dev_gt64120_access; |
587 |
|
|
|
588 |
|
|
/* Add the controller as a PCI device */ |
589 |
|
|
if (!pci_dev_lookup(d->bus[0],0,0,0)) { |
590 |
|
|
d->pci_dev = pci_dev_add(d->bus[0],name, |
591 |
|
|
PCI_VENDOR_GALILEO,PCI_PRODUCT_GALILEO_GT64120, |
592 |
|
|
0,0,irq,d,NULL,pci_gt64120_read,NULL); |
593 |
|
|
if (!d->pci_dev) { |
594 |
|
|
fprintf(stderr,"gt64120: unable to create PCI device.\n"); |
595 |
|
|
return(-1); |
596 |
|
|
} |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
/* Map this device to the VM */ |
600 |
|
|
vm_bind_device(vm,&d->dev); |
601 |
|
|
vm_object_add(vm,&d->vm_obj); |
602 |
|
|
return(0); |
603 |
|
|
} |
604 |
|
|
|