/[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

Annotation of /trunk/dev_mv64460.c

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 7 /*
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