/[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 12 - (hide annotations)
Sat Oct 6 16:45:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 19080 byte(s)
make working copy

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_SCRDP 0x0810 /* Current RX descriptor */
93     #define MV64460_SDMA_TX_DESC 0x0c00 /* TX descriptor */
94     #define MV64460_SDMA_SCTDP 0x0c10 /* Current TX desc. pointer */
95     #define MV64460_SDMA_SFTDP 0x0c14 /* First TX desc. pointer */
96    
97     /* SDMA Descriptor Command/Status word */
98     #define MV64460_SDMA_CMD_O 0x80000000 /* Owner bit */
99     #define MV64460_SDMA_CMD_AM 0x40000000 /* Auto-mode */
100     #define MV64460_SDMA_CMD_EI 0x00800000 /* Enable Interrupt */
101     #define MV64460_SDMA_CMD_F 0x00020000 /* First buffer */
102     #define MV64460_SDMA_CMD_L 0x00010000 /* Last buffer */
103    
104     /* SDMA Command Register (SDCM) */
105     #define MV64460_SDCM_ERD 0x00000080 /* Enable RX DMA */
106     #define MV64460_SDCM_AR 0x00008000 /* Abort Receive */
107     #define MV64460_SDCM_STD 0x00010000 /* Stop TX */
108     #define MV64460_SDCM_TXD 0x00800000 /* TX Demand */
109     #define MV64460_SDCM_AT 0x80000000 /* Abort Transmit */
110    
111     /* SDMA RX/TX descriptor */
112     struct sdma_desc {
113     m_uint32_t buf_size;
114     m_uint32_t cmd_stat;
115     m_uint32_t next_ptr;
116     m_uint32_t buf_ptr;
117     };
118    
119     /* SDMA channel */
120     struct sdma_channel {
121     m_uint32_t sdc;
122     m_uint32_t sdcm;
123     m_uint32_t rx_desc;
124     m_uint32_t rx_buf_ptr;
125     m_uint32_t scrdp;
126     m_uint32_t tx_desc;
127     m_uint32_t sctdp;
128     m_uint32_t sftdp;
129    
130     /* Associated VTTY for UART */
131     vtty_t *vtty;
132     };
133    
134     /* MV64460 system controller private data */
135     struct mv64460_data {
136     char *name;
137     vm_obj_t vm_obj;
138     struct vdevice dev;
139     struct pci_device *pci_dev;
140     vm_instance_t *vm;
141    
142     /* Interrupt Main Cause Low and High registers */
143     m_uint32_t intr_lo,intr_hi;
144    
145     /* CPU0 interrupt masks */
146     m_uint32_t cpu0_intr_mask_lo,cpu0_intr_mask_hi;
147    
148     /* GPP interrupts */
149     m_uint32_t gpp_intr,gpp_mask;
150    
151     /* SDMA channels */
152     m_uint32_t sdma_cause;
153     struct sdma_channel sdma[MV64460_SDMA_CHANNELS];
154    
155     /* PCI busses */
156     struct pci_bus *bus[2];
157     };
158    
159     /* Update the interrupt status for CPU 0 */
160     static void mv64460_ic_update_cpu0_status(struct mv64460_data *d)
161     {
162     cpu_ppc_t *cpu0 = CPU_PPC32(d->vm->boot_cpu);
163     m_uint32_t lo_act,hi_act;
164    
165     d->intr_lo = d->intr_hi = 0;
166    
167     /* Serial DMA */
168     if (d->sdma_cause)
169     d->intr_hi |= MV64460_IHMCR_SDMA_SUM;
170    
171     /* Test GPP bits */
172     if (d->gpp_intr & d->gpp_mask & 0x000000FF)
173     d->intr_hi |= MV64460_IHMCR_GPP_0_7_SUM;
174    
175     if (d->gpp_intr & d->gpp_mask & 0x0000FF00)
176     d->intr_hi |= MV64460_IHMCR_GPP_8_15_SUM;
177    
178     if (d->gpp_intr & d->gpp_mask & 0x00FF0000)
179     d->intr_hi |= MV64460_IHMCR_GPP_16_23_SUM;
180    
181     if (d->gpp_intr & d->gpp_mask & 0xFF000000)
182     d->intr_hi |= MV64460_IHMCR_GPP_24_31_SUM;
183    
184     lo_act = d->intr_lo & d->cpu0_intr_mask_lo;
185     hi_act = d->intr_hi & d->cpu0_intr_mask_hi;
186    
187     cpu0->irq_pending = lo_act || hi_act;
188     cpu0->irq_check = cpu0->irq_pending;
189     }
190    
191     /* Send contents of a SDMA buffer to the associated VTTY */
192     static void mv64460_sdma_send_buf_to_vtty(struct mv64460_data *d,
193     struct sdma_channel *chan,
194     struct sdma_desc *desc)
195     {
196     m_uint32_t buf_addr,len,clen;
197     char buffer[512];
198    
199     len = (desc->buf_size >> 16) & 0xFFFF;
200     buf_addr = desc->buf_ptr;
201    
202     //vm_log(d->vm,"SDMA","len=0x%8.8x, buf_addr=0x%8.8x\n",len,buf_addr);
203    
204     while(len > 0) {
205     if (len > sizeof(buffer))
206     clen = sizeof(buffer);
207     else
208     clen = len;
209    
210     physmem_copy_from_vm(d->vm,buffer,buf_addr,clen);
211     vtty_put_buffer(chan->vtty,buffer,clen);
212    
213     len -= clen;
214     buf_addr += clen;
215     }
216     }
217    
218     /* Fetch a SDMA descriptor */
219     static void mv64460_sdma_fetch_desc(struct mv64460_data *d,m_uint32_t addr,
220     struct sdma_desc *desc)
221     {
222     physmem_copy_from_vm(d->vm,desc,addr,sizeof(struct sdma_desc));
223    
224     /* byte-swapping */
225     desc->buf_size = vmtoh32(desc->buf_size);
226     desc->cmd_stat = vmtoh32(desc->cmd_stat);
227     desc->next_ptr = vmtoh32(desc->next_ptr);
228     desc->buf_ptr = vmtoh32(desc->buf_ptr);
229     }
230    
231     /* Start TX DMA process */
232     static void mv64460_sdma_tx_start(struct mv64460_data *d,
233     struct sdma_channel *chan)
234     {
235     struct sdma_desc desc;
236     m_uint32_t desc_addr;
237    
238     desc_addr = chan->sctdp;
239    
240     //vm_log(d->vm,"SDMA","TX fetch starting: 0x%8.8x\n",desc_addr);
241    
242     while(desc_addr != 0)
243     {
244     //vm_log(d->vm,"SDMA","fetching descriptor at 0x%8.8x\n",desc_addr);
245    
246     /* Fetch the descriptor */
247     mv64460_sdma_fetch_desc(d,desc_addr,&desc);
248     chan->sctdp = desc_addr;
249    
250     #if 0
251     vm_log(d->vm,"SDMA","buf_size=0x%8.8x, cmd_stat=0x%8.8x, "
252     "next_ptr=0x%8.8x, buf_ptr=0x%8.8x\n",
253     desc.buf_size,desc.cmd_stat,desc.next_ptr,desc.buf_ptr);
254     #endif
255    
256     if (!(desc.cmd_stat & MV64460_SDMA_CMD_O)) {
257     d->sdma_cause |= 4;
258     mv64460_ic_update_cpu0_status(d);
259     return;
260     }
261    
262     mv64460_sdma_send_buf_to_vtty(d,chan,&desc);
263    
264     desc.buf_size &= 0xFFFF0000;
265     desc.cmd_stat &= ~MV64460_SDMA_CMD_O;
266    
267     physmem_copy_u32_to_vm(d->vm,desc_addr,desc.buf_size);
268     physmem_copy_u32_to_vm(d->vm,desc_addr+4,desc.cmd_stat);
269    
270     desc_addr = desc.next_ptr;
271     }
272    
273     d->sdma_cause |= 4;
274     mv64460_ic_update_cpu0_status(d);
275    
276     /* Clear the TXD bit */
277     chan->sdcm &= ~MV64460_SDCM_TXD;
278     }
279    
280     /* Put data into a RX DMA buffer */
281     static void mv64460_sdma_put_rx_data(struct mv64460_data *d,
282     struct sdma_channel *chan,
283     char *buffer,size_t buf_len)
284     {
285     struct sdma_desc desc;
286     m_uint32_t desc_addr;
287    
288     desc_addr = chan->scrdp;
289    
290     /* Fetch the current SDMA buffer */
291     mv64460_sdma_fetch_desc(d,desc_addr,&desc);
292    
293     #if 0
294     vm_log(d->vm,"SDMA_RX","buf_size=0x%8.8x, cmd_stat=0x%8.8x, "
295     "next_ptr=0x%8.8x, buf_ptr=0x%8.8x\n",
296     desc.buf_size,desc.cmd_stat,desc.next_ptr,desc.buf_ptr);
297     #endif
298    
299     if (!(desc.cmd_stat & MV64460_SDMA_CMD_O)) {
300     d->sdma_cause |= 1;
301     mv64460_ic_update_cpu0_status(d);
302     return;
303     }
304    
305     physmem_copy_to_vm(d->vm,buffer,desc.buf_ptr,1);
306    
307     desc.buf_size |= 0x00000001;
308     desc.cmd_stat &= ~MV64460_SDMA_CMD_O;
309    
310     physmem_copy_u32_to_vm(d->vm,desc_addr,desc.buf_size);
311     physmem_copy_u32_to_vm(d->vm,desc_addr+4,desc.cmd_stat);
312    
313     chan->scrdp = desc.next_ptr;
314    
315     d->sdma_cause |= 1;
316     mv64460_ic_update_cpu0_status(d);
317     }
318    
319     /* Input on VTTY 0 */
320     static void mv64460_tty_input_s0(vtty_t *vtty)
321     {
322     struct mv64460_data *d = vtty->priv_data;
323     struct sdma_channel *chan = &d->sdma[0];
324     char c;
325    
326     c = vtty_get_char(vtty);
327     mv64460_sdma_put_rx_data(d,chan,&c,1);
328     }
329    
330     /* Input on VTTY 0 */
331     static void mv64460_tty_input_s1(vtty_t *vtty)
332     {
333     struct mv64460_data *d = vtty->priv_data;
334     struct sdma_channel *chan = &d->sdma[1];
335     char c;
336    
337     c = vtty_get_char(vtty);
338     mv64460_sdma_put_rx_data(d,chan,&c,1);
339     }
340    
341     /* Bind a VTTY to a SDMA channel */
342     int mv64460_sdma_bind_vtty(struct mv64460_data *d,u_int chan_id,vtty_t *vtty)
343     {
344     switch(chan_id) {
345     case 0:
346     vtty->priv_data = d;
347     vtty->read_notifier = mv64460_tty_input_s0;
348     break;
349     case 1:
350     vtty->priv_data = d;
351     vtty->read_notifier = mv64460_tty_input_s1;
352     break;
353     default:
354     return(-1);
355     }
356    
357     d->sdma[chan_id].vtty = vtty;
358     return(0);
359     }
360    
361     /*
362     * SDMA registers access.
363     */
364     static int mv64460_sdma_access(struct mv64460_data *d,cpu_gen_t *cpu,
365     m_uint32_t offset,m_uint32_t op_type,
366     m_uint64_t *data)
367     {
368 dpavlin 11 struct sdma_channel *channel;
369 dpavlin 7 int id = -1;
370    
371     /* Access to SDMA channel 0 registers ? */
372     if ((offset >= MV64460_REG_SDMA0) &&
373     (offset < (MV64460_REG_SDMA0 + 0x1000)))
374     {
375     offset -= MV64460_REG_SDMA0;
376     id = 0;
377     }
378    
379     /* Access to SDMA channel 1 registers ? */
380     if ((offset >= MV64460_REG_SDMA1) &&
381     (offset < (MV64460_REG_SDMA1 + 0x1000)))
382     {
383     offset -= MV64460_REG_SDMA1;
384     id = 1;
385     }
386    
387     if (id == -1)
388     return(FALSE);
389    
390     if (op_type == MTS_WRITE)
391     *data = swap32(*data);
392    
393 dpavlin 11 channel = &d->sdma[id];
394    
395 dpavlin 7 switch(offset) {
396     case MV64460_SDMA_SDCM:
397     if (op_type == MTS_READ)
398     ; //*data = chan->sdcm;
399     else {
400 dpavlin 11 channel->sdcm = *data;
401 dpavlin 7
402 dpavlin 11 if (channel->sdcm & MV64460_SDCM_TXD)
403     mv64460_sdma_tx_start(d,channel);
404 dpavlin 7 }
405     break;
406    
407     case MV64460_SDMA_SCRDP:
408     if (op_type == MTS_READ)
409 dpavlin 11 *data = channel->scrdp;
410 dpavlin 7 else
411 dpavlin 11 channel->scrdp = *data;
412 dpavlin 7 break;
413    
414     case MV64460_SDMA_SCTDP:
415     if (op_type == MTS_READ)
416 dpavlin 11 *data = channel->sctdp;
417 dpavlin 7 else
418 dpavlin 11 channel->sctdp = *data;
419 dpavlin 7 break;
420    
421     case MV64460_SDMA_SFTDP:
422     if (op_type == MTS_READ)
423 dpavlin 11 *data = channel->sftdp;
424 dpavlin 7 else
425 dpavlin 11 channel->sftdp = *data;
426 dpavlin 7 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