/[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 12 - (show 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 /*
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 struct sdma_channel *channel;
369 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 channel = &d->sdma[id];
394
395 switch(offset) {
396 case MV64460_SDMA_SDCM:
397 if (op_type == MTS_READ)
398 ; //*data = chan->sdcm;
399 else {
400 channel->sdcm = *data;
401
402 if (channel->sdcm & MV64460_SDCM_TXD)
403 mv64460_sdma_tx_start(d,channel);
404 }
405 break;
406
407 case MV64460_SDMA_SCRDP:
408 if (op_type == MTS_READ)
409 *data = channel->scrdp;
410 else
411 channel->scrdp = *data;
412 break;
413
414 case MV64460_SDMA_SCTDP:
415 if (op_type == MTS_READ)
416 *data = channel->sctdp;
417 else
418 channel->sctdp = *data;
419 break;
420
421 case MV64460_SDMA_SFTDP:
422 if (op_type == MTS_READ)
423 *data = channel->sftdp;
424 else
425 channel->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