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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Sat Oct 6 16:29:14 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7/dev_mv64460.c
File MIME type: text/plain
File size: 19119 byte(s)
dynamips-0.2.7

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Marvell MV64460 system controller.
6 *
7 * Based on GT9100 documentation and Linux kernel sources.
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "utils.h"
15 #include "net.h"
16 #include "cpu.h"
17 #include "vm.h"
18 #include "dynamips.h"
19 #include "memory.h"
20 #include "device.h"
21 #include "net_io.h"
22 #include "ptask.h"
23 #include "dev_vtty.h"
24 #include "dev_mv64460.h"
25
26 /* Debugging flags */
27 #define DEBUG_ACCESS 0
28 #define DEBUG_UNKNOWN 0
29 #define DEBUG_DMA 0
30 #define DEBUG_MII 0
31
32 /* PCI identification */
33 #define PCI_VENDOR_MARVELL 0x11ab /* Marvell/Galileo */
34 #define PCI_PRODUCT_MARVELL_MV64460 0x6485 /* MV-64460 */
35
36 /* Interrupt Low Main Cause Register */
37 #define MV64460_REG_ILMCR 0x0004
38
39 #define MV64460_ILMCR_IDMA0_COMP 0x00000010 /* IDMA 0 Transfer completed */
40 #define MV64460_ILMCR_IDMA1_COMP 0x00000020 /* IDMA 1 Transfer completed */
41 #define MV64460_ILMCR_IDMA2_COMP 0x00000040 /* IDMA 2 Transfer completed */
42 #define MV64460_ILMCR_IDMA3_COMP 0x00000080 /* IDMA 3 Transfer completed */
43 #define MV64460_ILMCR_TIMER0_EXP 0x00000100 /* Timer 0 expired */
44 #define MV64460_ILMCR_TIMER1_EXP 0x00000200 /* Timer 1 expired */
45 #define MV64460_ILMCR_TIMER2_EXP 0x00000400 /* Timer 2 expired */
46 #define MV64460_ILMCR_TIMER3_EXP 0x00000800 /* Timer 3 expired */
47
48 /* Interrupt High Main Cause Register */
49 #define MV64460_REG_IHMCR 0x000c
50
51 /* Interrupt masks for CPU0 */
52 #define MV64460_REG_CPU0_INTR_MASK_LO 0x0014
53 #define MV64460_REG_CPU0_INTR_MASK_HI 0x001c
54
55 #define MV64460_IHMCR_ETH0_SUM 0x00000001 /* Ethernet 0 */
56 #define MV64460_IHMCR_ETH1_SUM 0x00000002 /* Ethernet 1 */
57 #define MV64460_IHMCR_ETH2_SUM 0x00000004 /* Ethernet 2 */
58 #define MV64460_IHMCR_SDMA_SUM 0x00000010 /* Serial DMA */
59
60 #define MV64460_IHMCR_GPP_0_7_SUM 0x01000000
61 #define MV64460_IHMCR_GPP_8_15_SUM 0x02000000
62 #define MV64460_IHMCR_GPP_16_23_SUM 0x04000000
63 #define MV64460_IHMCR_GPP_24_31_SUM 0x08000000
64
65 /* GPP Interrupt cause and mask registers */
66 #define MV64460_REG_GPP_INTR_CAUSE 0xf108
67 #define MV64460_REG_GPP_INTR_MASK 0xf10c
68
69 /* SDMA - number of channels */
70 #define MV64460_SDMA_CHANNELS 2
71
72 /* SDMA registers base offsets */
73 #define MV64460_REG_SDMA0 0x4000
74 #define MV64460_REG_SDMA1 0x6000
75
76 /* SDMA cause register */
77 #define MV64460_REG_SDMA_CAUSE 0xb800
78
79 #define MV64460_SDMA_CAUSE_RXBUF0 0x00000001 /* RX Buffer returned */
80 #define MV64460_SDMA_CAUSE_RXERR0 0x00000002 /* RX Error */
81 #define MV64460_SDMA_CAUSE_TXBUF0 0x00000004 /* TX Buffer returned */
82 #define MV64460_SDMA_CAUSE_TXEND0 0x00000008 /* TX End */
83 #define MV64460_SDMA_CAUSE_RXBUF1 0x00000010 /* RX Buffer returned */
84 #define MV64460_SDMA_CAUSE_RXERR1 0x00000020 /* RX Error */
85 #define MV64460_SDMA_CAUSE_TXBUF1 0x00000040 /* TX Buffer returned */
86 #define MV64460_SDMA_CAUSE_TXEND1 0x00000080 /* TX End */
87
88 /* SDMA register offsets */
89 #define MV64460_SDMA_SDC 0x0000 /* Configuration Register */
90 #define MV64460_SDMA_SDCM 0x0008 /* Command Register */
91 #define MV64460_SDMA_RX_DESC 0x0800 /* RX descriptor */
92 #define MV64460_SDMA_RX_BUF_PTR 0x0808 /* Current buffer address ? */
93 #define MV64460_SDMA_SCRDP 0x0810 /* Current RX descriptor */
94 #define MV64460_SDMA_TX_DESC 0x0c00 /* TX descriptor */
95 #define MV64460_SDMA_SCTDP 0x0c10 /* Current TX desc. pointer */
96 #define MV64460_SDMA_SFTDP 0x0c14 /* First TX desc. pointer */
97
98 /* SDMA Descriptor Command/Status word */
99 #define MV64460_SDMA_CMD_O 0x80000000 /* Owner bit */
100 #define MV64460_SDMA_CMD_AM 0x40000000 /* Auto-mode */
101 #define MV64460_SDMA_CMD_EI 0x00800000 /* Enable Interrupt */
102 #define MV64460_SDMA_CMD_F 0x00020000 /* First buffer */
103 #define MV64460_SDMA_CMD_L 0x00010000 /* Last buffer */
104
105 /* SDMA Command Register (SDCM) */
106 #define MV64460_SDCM_ERD 0x00000080 /* Enable RX DMA */
107 #define MV64460_SDCM_AR 0x00008000 /* Abort Receive */
108 #define MV64460_SDCM_STD 0x00010000 /* Stop TX */
109 #define MV64460_SDCM_TXD 0x00800000 /* TX Demand */
110 #define MV64460_SDCM_AT 0x80000000 /* Abort Transmit */
111
112 /* SDMA RX/TX descriptor */
113 struct sdma_desc {
114 m_uint32_t buf_size;
115 m_uint32_t cmd_stat;
116 m_uint32_t next_ptr;
117 m_uint32_t buf_ptr;
118 };
119
120 /* SDMA channel */
121 struct sdma_channel {
122 m_uint32_t sdc;
123 m_uint32_t sdcm;
124 m_uint32_t rx_desc;
125 m_uint32_t rx_buf_ptr;
126 m_uint32_t scrdp;
127 m_uint32_t tx_desc;
128 m_uint32_t sctdp;
129 m_uint32_t sftdp;
130
131 /* Associated VTTY for UART */
132 vtty_t *vtty;
133 };
134
135 /* MV64460 system controller private data */
136 struct mv64460_data {
137 char *name;
138 vm_obj_t vm_obj;
139 struct vdevice dev;
140 struct pci_device *pci_dev;
141 vm_instance_t *vm;
142
143 /* Interrupt Main Cause Low and High registers */
144 m_uint32_t intr_lo,intr_hi;
145
146 /* CPU0 interrupt masks */
147 m_uint32_t cpu0_intr_mask_lo,cpu0_intr_mask_hi;
148
149 /* GPP interrupts */
150 m_uint32_t gpp_intr,gpp_mask;
151
152 /* SDMA channels */
153 m_uint32_t sdma_cause;
154 struct sdma_channel sdma[MV64460_SDMA_CHANNELS];
155
156 /* PCI busses */
157 struct pci_bus *bus[2];
158 };
159
160 /* Update the interrupt status for CPU 0 */
161 static void mv64460_ic_update_cpu0_status(struct mv64460_data *d)
162 {
163 cpu_ppc_t *cpu0 = CPU_PPC32(d->vm->boot_cpu);
164 m_uint32_t lo_act,hi_act;
165
166 d->intr_lo = d->intr_hi = 0;
167
168 /* Serial DMA */
169 if (d->sdma_cause)
170 d->intr_hi |= MV64460_IHMCR_SDMA_SUM;
171
172 /* Test GPP bits */
173 if (d->gpp_intr & d->gpp_mask & 0x000000FF)
174 d->intr_hi |= MV64460_IHMCR_GPP_0_7_SUM;
175
176 if (d->gpp_intr & d->gpp_mask & 0x0000FF00)
177 d->intr_hi |= MV64460_IHMCR_GPP_8_15_SUM;
178
179 if (d->gpp_intr & d->gpp_mask & 0x00FF0000)
180 d->intr_hi |= MV64460_IHMCR_GPP_16_23_SUM;
181
182 if (d->gpp_intr & d->gpp_mask & 0xFF000000)
183 d->intr_hi |= MV64460_IHMCR_GPP_24_31_SUM;
184
185 lo_act = d->intr_lo & d->cpu0_intr_mask_lo;
186 hi_act = d->intr_hi & d->cpu0_intr_mask_hi;
187
188 cpu0->irq_pending = lo_act || hi_act;
189 cpu0->irq_check = cpu0->irq_pending;
190 }
191
192 /* Send contents of a SDMA buffer to the associated VTTY */
193 static void mv64460_sdma_send_buf_to_vtty(struct mv64460_data *d,
194 struct sdma_channel *chan,
195 struct sdma_desc *desc)
196 {
197 m_uint32_t buf_addr,len,clen;
198 char buffer[512];
199
200 len = (desc->buf_size >> 16) & 0xFFFF;
201 buf_addr = desc->buf_ptr;
202
203 //vm_log(d->vm,"SDMA","len=0x%8.8x, buf_addr=0x%8.8x\n",len,buf_addr);
204
205 while(len > 0) {
206 if (len > sizeof(buffer))
207 clen = sizeof(buffer);
208 else
209 clen = len;
210
211 physmem_copy_from_vm(d->vm,buffer,buf_addr,clen);
212 vtty_put_buffer(chan->vtty,buffer,clen);
213
214 len -= clen;
215 buf_addr += clen;
216 }
217 }
218
219 /* Fetch a SDMA descriptor */
220 static void mv64460_sdma_fetch_desc(struct mv64460_data *d,m_uint32_t addr,
221 struct sdma_desc *desc)
222 {
223 physmem_copy_from_vm(d->vm,desc,addr,sizeof(struct sdma_desc));
224
225 /* byte-swapping */
226 desc->buf_size = vmtoh32(desc->buf_size);
227 desc->cmd_stat = vmtoh32(desc->cmd_stat);
228 desc->next_ptr = vmtoh32(desc->next_ptr);
229 desc->buf_ptr = vmtoh32(desc->buf_ptr);
230 }
231
232 /* Start TX DMA process */
233 static void mv64460_sdma_tx_start(struct mv64460_data *d,
234 struct sdma_channel *chan)
235 {
236 struct sdma_desc desc;
237 m_uint32_t desc_addr;
238
239 desc_addr = chan->sctdp;
240
241 //vm_log(d->vm,"SDMA","TX fetch starting: 0x%8.8x\n",desc_addr);
242
243 while(desc_addr != 0)
244 {
245 //vm_log(d->vm,"SDMA","fetching descriptor at 0x%8.8x\n",desc_addr);
246
247 /* Fetch the descriptor */
248 mv64460_sdma_fetch_desc(d,desc_addr,&desc);
249 chan->sctdp = desc_addr;
250
251 #if 0
252 vm_log(d->vm,"SDMA","buf_size=0x%8.8x, cmd_stat=0x%8.8x, "
253 "next_ptr=0x%8.8x, buf_ptr=0x%8.8x\n",
254 desc.buf_size,desc.cmd_stat,desc.next_ptr,desc.buf_ptr);
255 #endif
256
257 if (!(desc.cmd_stat & MV64460_SDMA_CMD_O)) {
258 d->sdma_cause |= 4;
259 mv64460_ic_update_cpu0_status(d);
260 return;
261 }
262
263 mv64460_sdma_send_buf_to_vtty(d,chan,&desc);
264
265 desc.buf_size &= 0xFFFF0000;
266 desc.cmd_stat &= ~MV64460_SDMA_CMD_O;
267
268 physmem_copy_u32_to_vm(d->vm,desc_addr,desc.buf_size);
269 physmem_copy_u32_to_vm(d->vm,desc_addr+4,desc.cmd_stat);
270
271 desc_addr = desc.next_ptr;
272 }
273
274 d->sdma_cause |= 4;
275 mv64460_ic_update_cpu0_status(d);
276
277 /* Clear the TXD bit */
278 chan->sdcm &= ~MV64460_SDCM_TXD;
279 }
280
281 /* Put data into a RX DMA buffer */
282 static void mv64460_sdma_put_rx_data(struct mv64460_data *d,
283 struct sdma_channel *chan,
284 char *buffer,size_t buf_len)
285 {
286 struct sdma_desc desc;
287 m_uint32_t desc_addr;
288
289 desc_addr = chan->scrdp;
290
291 /* Fetch the current SDMA buffer */
292 mv64460_sdma_fetch_desc(d,desc_addr,&desc);
293
294 #if 0
295 vm_log(d->vm,"SDMA_RX","buf_size=0x%8.8x, cmd_stat=0x%8.8x, "
296 "next_ptr=0x%8.8x, buf_ptr=0x%8.8x\n",
297 desc.buf_size,desc.cmd_stat,desc.next_ptr,desc.buf_ptr);
298 #endif
299
300 if (!(desc.cmd_stat & MV64460_SDMA_CMD_O)) {
301 d->sdma_cause |= 1;
302 mv64460_ic_update_cpu0_status(d);
303 return;
304 }
305
306 physmem_copy_to_vm(d->vm,buffer,desc.buf_ptr,1);
307
308 desc.buf_size |= 0x00000001;
309 desc.cmd_stat &= ~MV64460_SDMA_CMD_O;
310
311 physmem_copy_u32_to_vm(d->vm,desc_addr,desc.buf_size);
312 physmem_copy_u32_to_vm(d->vm,desc_addr+4,desc.cmd_stat);
313
314 chan->scrdp = desc.next_ptr;
315
316 d->sdma_cause |= 1;
317 mv64460_ic_update_cpu0_status(d);
318 }
319
320 /* Input on VTTY 0 */
321 static void mv64460_tty_input_s0(vtty_t *vtty)
322 {
323 struct mv64460_data *d = vtty->priv_data;
324 struct sdma_channel *chan = &d->sdma[0];
325 char c;
326
327 c = vtty_get_char(vtty);
328 mv64460_sdma_put_rx_data(d,chan,&c,1);
329 }
330
331 /* Input on VTTY 0 */
332 static void mv64460_tty_input_s1(vtty_t *vtty)
333 {
334 struct mv64460_data *d = vtty->priv_data;
335 struct sdma_channel *chan = &d->sdma[1];
336 char c;
337
338 c = vtty_get_char(vtty);
339 mv64460_sdma_put_rx_data(d,chan,&c,1);
340 }
341
342 /* Bind a VTTY to a SDMA channel */
343 int mv64460_sdma_bind_vtty(struct mv64460_data *d,u_int chan_id,vtty_t *vtty)
344 {
345 switch(chan_id) {
346 case 0:
347 vtty->priv_data = d;
348 vtty->read_notifier = mv64460_tty_input_s0;
349 break;
350 case 1:
351 vtty->priv_data = d;
352 vtty->read_notifier = mv64460_tty_input_s1;
353 break;
354 default:
355 return(-1);
356 }
357
358 d->sdma[chan_id].vtty = vtty;
359 return(0);
360 }
361
362 /*
363 * SDMA registers access.
364 */
365 static int mv64460_sdma_access(struct mv64460_data *d,cpu_gen_t *cpu,
366 m_uint32_t offset,m_uint32_t op_type,
367 m_uint64_t *data)
368 {
369 struct sdma_channel *chan;
370 int id = -1;
371
372 /* Access to SDMA channel 0 registers ? */
373 if ((offset >= MV64460_REG_SDMA0) &&
374 (offset < (MV64460_REG_SDMA0 + 0x1000)))
375 {
376 offset -= MV64460_REG_SDMA0;
377 id = 0;
378 }
379
380 /* Access to SDMA channel 1 registers ? */
381 if ((offset >= MV64460_REG_SDMA1) &&
382 (offset < (MV64460_REG_SDMA1 + 0x1000)))
383 {
384 offset -= MV64460_REG_SDMA1;
385 id = 1;
386 }
387
388 if (id == -1)
389 return(FALSE);
390
391 if (op_type == MTS_WRITE)
392 *data = swap32(*data);
393
394 chan = &d->sdma[id];
395 switch(offset) {
396 case MV64460_SDMA_SDCM:
397 if (op_type == MTS_READ)
398 ; //*data = chan->sdcm;
399 else {
400 chan->sdcm = *data;
401
402 if (chan->sdcm & MV64460_SDCM_TXD)
403 mv64460_sdma_tx_start(d,chan);
404 }
405 break;
406
407 case MV64460_SDMA_SCRDP:
408 if (op_type == MTS_READ)
409 *data = chan->scrdp;
410 else
411 chan->scrdp = *data;
412 break;
413
414 case MV64460_SDMA_SCTDP:
415 if (op_type == MTS_READ)
416 *data = chan->sctdp;
417 else
418 chan->sctdp = *data;
419 break;
420
421 case MV64460_SDMA_SFTDP:
422 if (op_type == MTS_READ)
423 *data = chan->sftdp;
424 else
425 chan->sftdp = *data;
426 break;
427
428 #if DEBUG_UNKNOWN
429 default:
430 if (op_type == MTS_READ) {
431 cpu_log(cpu,"MV64460/SDMA",
432 "read access to unknown register 0x%x, pc=0x%llx\n",
433 offset,cpu_get_pc(cpu));
434 } else {
435 cpu_log(cpu,"MV64460/SDMA",
436 "write access to unknown register 0x%x, value=0x%llx, "
437 "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));
438 }
439 #endif
440 }
441
442 if (op_type == MTS_READ)
443 *data = swap32(*data);
444
445 /* Update the interrupt status */
446 mv64460_ic_update_cpu0_status(d);
447 return(TRUE);
448 }
449
450 /*
451 * dev_mv64460_access()
452 */
453 void *dev_mv64460_access(cpu_gen_t *cpu,struct vdevice *dev,m_uint32_t offset,
454 u_int op_size,u_int op_type,m_uint64_t *data)
455 {
456 struct mv64460_data *mv_data = dev->priv_data;
457
458 #if DEBUG_ACCESS
459 if (op_type == MTS_READ) {
460 cpu_log(cpu,"MV64460",
461 "read access to register 0x%x, pc=0x%llx\n",
462 offset,cpu_get_pc(cpu));
463 } else {
464 cpu_log(cpu,"MV64460",
465 "write access to register 0x%x, value=0x%llx, pc=0x%llx\n",
466 offset,*data,cpu_get_pc(cpu));
467 }
468 #endif
469
470 if (op_type == MTS_READ)
471 *data = 0x0;
472
473 if (mv64460_sdma_access(mv_data,cpu,offset,op_type,data))
474 return NULL;
475
476 if (op_type == MTS_WRITE)
477 *data = swap32(*data);
478
479 switch(offset) {
480 /* Interrupt Main Cause Low */
481 case MV64460_REG_ILMCR:
482 if (op_type == MTS_READ)
483 *data = mv_data->intr_lo;
484 break;
485
486 /* Interrupt Main Cause High */
487 case MV64460_REG_IHMCR:
488 if (op_type == MTS_READ)
489 *data = mv_data->intr_hi;
490 break;
491
492 /* CPU0 Interrupt Mask Low */
493 case MV64460_REG_CPU0_INTR_MASK_LO:
494 if (op_type == MTS_READ)
495 *data = mv_data->cpu0_intr_mask_lo;
496 else
497 mv_data->cpu0_intr_mask_lo = *data;
498 break;
499
500 /* CPU0 Interrupt Mask High */
501 case MV64460_REG_CPU0_INTR_MASK_HI:
502 if (op_type == MTS_READ)
503 *data = mv_data->cpu0_intr_mask_hi;
504 else
505 mv_data->cpu0_intr_mask_hi = *data;
506 break;
507
508 /* ===== PCI Bus 0 ===== */
509 case PCI_BUS_ADDR: /* pci configuration address (0xcf8) */
510 pci_dev_addr_handler(cpu,mv_data->bus[0],op_type,FALSE,data);
511 break;
512
513 case PCI_BUS_DATA: /* pci data address (0xcfc) */
514 pci_dev_data_handler(cpu,mv_data->bus[0],op_type,FALSE,data);
515 break;
516
517 /* ===== PCI Bus 0 ===== */
518 case 0xc78: /* pci configuration address (0xc78) */
519 pci_dev_addr_handler(cpu,mv_data->bus[1],op_type,FALSE,data);
520 break;
521
522 case 0xc7c: /* pci data address (0xc7c) */
523 pci_dev_data_handler(cpu,mv_data->bus[1],op_type,FALSE,data);
524 break;
525
526 /* MII */
527 case 0x2004:
528 if (op_type == MTS_READ)
529 *data = 0x08000000;
530 break;
531
532 /* GPP interrupt cause */
533 case MV64460_REG_GPP_INTR_CAUSE:
534 if (op_type == MTS_READ)
535 *data = mv_data->gpp_intr;
536 break;
537
538 /* GPP interrupt mask */
539 case MV64460_REG_GPP_INTR_MASK:
540 if (op_type == MTS_READ)
541 *data = mv_data->gpp_mask;
542 else
543 mv_data->gpp_mask = *data;
544 break;
545
546 case 0x8030:
547 if (op_type == MTS_READ)
548 *data = 0xFFFFFFFF;
549 break;
550
551 case 0x9030:
552 if (op_type == MTS_READ)
553 *data = 0xFFFFFFFF;
554 break;
555
556 /* SDMA cause register */
557 case MV64460_REG_SDMA_CAUSE:
558 if (op_type == MTS_READ)
559 *data = mv_data->sdma_cause;
560 else
561 mv_data->sdma_cause &= *data;
562 break;
563
564 #if DEBUG_UNKNOWN
565 default:
566 if (op_type == MTS_READ) {
567 cpu_log(cpu,"MV64460","read from addr 0x%x, pc=0x%llx\n",
568 offset,cpu_get_pc(cpu));
569 } else {
570 cpu_log(cpu,"MV64460","write to addr 0x%x, value=0x%llx, "
571 "pc=0x%llx\n",offset,*data,cpu_get_pc(cpu));
572 }
573 #endif
574 }
575
576 if (op_type == MTS_READ)
577 *data = swap32(*data);
578
579 /* Update the interrupt status */
580 mv64460_ic_update_cpu0_status(mv_data);
581 return NULL;
582 }
583
584 /* Set value of GPP register */
585 void dev_mv64460_set_gpp_reg(struct mv64460_data *d,m_uint32_t val)
586 {
587 d->gpp_intr = val;
588 mv64460_ic_update_cpu0_status(d);
589 }
590
591 /* Set a GPP interrupt */
592 void dev_mv64460_set_gpp_intr(struct mv64460_data *d,u_int irq)
593 {
594 d->gpp_intr |= 1 << irq;
595 mv64460_ic_update_cpu0_status(d);
596
597 #if 0
598 printf("SET_GPP_INTR: lo=0x%8.8x, hi=0x%8.8x\n",d->intr_lo,d->intr_hi);
599 printf("gpp_intr = 0x%8.8x, gpp_mask = 0x%8.8x\n",d->gpp_intr,d->gpp_mask);
600 #endif
601 }
602
603 /* Clear a GPP interrupt */
604 void dev_mv64460_clear_gpp_intr(struct mv64460_data *d,u_int irq)
605 {
606 d->gpp_intr &= ~(1 << irq);
607 mv64460_ic_update_cpu0_status(d);
608 }
609
610 /*
611 * pci_mv64460_read()
612 *
613 * Read a PCI register.
614 */
615 static m_uint32_t pci_mv64460_read(cpu_gen_t *cpu,struct pci_device *dev,
616 int reg)
617 {
618 switch (reg) {
619 default:
620 return(0);
621 }
622 }
623
624 /* Shutdown a MV64460 system controller */
625 void dev_mv64460_shutdown(vm_instance_t *vm,struct mv64460_data *d)
626 {
627 if (d != NULL) {
628 /* Remove the device */
629 dev_remove(vm,&d->dev);
630
631 /* Remove the PCI device */
632 pci_dev_remove(d->pci_dev);
633
634 /* Free the structure itself */
635 free(d);
636 }
637 }
638
639 /* Create a new MV64460 controller */
640 int dev_mv64460_init(vm_instance_t *vm,char *name,
641 m_uint64_t paddr,m_uint32_t len)
642 {
643 struct mv64460_data *d;
644
645 if (!(d = malloc(sizeof(*d)))) {
646 fprintf(stderr,"mv64460: unable to create device data.\n");
647 return(-1);
648 }
649
650 memset(d,0,sizeof(*d));
651 d->name = name;
652 d->vm = vm;
653 d->bus[0] = vm->pci_bus[0];
654 d->bus[1] = vm->pci_bus[1];
655
656 vm_object_init(&d->vm_obj);
657 d->vm_obj.name = name;
658 d->vm_obj.data = d;
659 d->vm_obj.shutdown = (vm_shutdown_t)dev_mv64460_shutdown;
660
661 dev_init(&d->dev);
662 d->dev.name = name;
663 d->dev.priv_data = d;
664 d->dev.phys_addr = paddr;
665 d->dev.phys_len = len;
666 d->dev.handler = dev_mv64460_access;
667
668 /* Add the controller as a PCI device */
669 if (!pci_dev_lookup(d->bus[0],0,0,0)) {
670 d->pci_dev = pci_dev_add(d->bus[0],name,
671 PCI_VENDOR_MARVELL,PCI_PRODUCT_MARVELL_MV64460,
672 0,0,-1,d,NULL,pci_mv64460_read,NULL);
673 if (!d->pci_dev) {
674 fprintf(stderr,"mv64460: unable to create PCI device.\n");
675 return(-1);
676 }
677 }
678
679 /* TEST */
680 pci_dev_add(d->bus[1],name,
681 PCI_VENDOR_MARVELL,PCI_PRODUCT_MARVELL_MV64460,
682 0,0,-1,d,NULL,pci_mv64460_read,NULL);
683
684 /* Map this device to the VM */
685 vm_bind_device(vm,&d->dev);
686 vm_object_add(vm,&d->vm_obj);
687 return(0);
688 }

  ViewVC Help
Powered by ViewVC 1.1.26