/[dynamips]/trunk/dev_c7200_pos.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_c7200_pos.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (hide annotations)
Sat Oct 6 16:08:03 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC4/dev_c7200_pos.c
File MIME type: text/plain
File size: 20476 byte(s)
dynamips-0.2.6-RC4

1 dpavlin 1 /*
2     * Cisco C7200 (Predator) Simulation Platform.
3     * Copyright (C) 2005-2006 Christophe Fillot. All rights reserved.
4     *
5     * EEPROM types:
6     * - 0x95: PA-POS-OC3SMI
7     * - 0x96: PA-POS-OC3MM
8     *
9     * Just an experimentation (I don't have any PA-POS-OC3). It basically works,
10     * on NPE-400. There is something strange with the buffer addresses in TX ring,
11     * preventing this driver working with platforms using SRAM.
12     */
13    
14     #include <stdio.h>
15     #include <stdlib.h>
16     #include <string.h>
17     #include <unistd.h>
18     #include <errno.h>
19     #include <pthread.h>
20     #include <assert.h>
21    
22     #include "mips64.h"
23     #include "dynamips.h"
24     #include "memory.h"
25     #include "device.h"
26     #include "net.h"
27     #include "net_io.h"
28     #include "ptask.h"
29     #include "dev_c7200.h"
30 dpavlin 4 #include "dev_plx.h"
31 dpavlin 1
32     /* Debugging flags */
33     #define DEBUG_ACCESS 0
34     #define DEBUG_UNKNOWN 1
35     #define DEBUG_TRANSMIT 0
36     #define DEBUG_RECEIVE 0
37    
38     /* PCI vendor/product codes */
39     #define POS_OC3_PCI_VENDOR_ID 0x10b5
40     #define POS_OC3_PCI_PRODUCT_ID 0x9060
41    
42     /* Maximum packet size */
43     #define POS_OC3_MAX_PKT_SIZE 8192
44    
45     /* RX descriptors */
46     #define POS_OC3_RXDESC_OWN 0x80000000 /* Ownership */
47     #define POS_OC3_RXDESC_WRAP 0x40000000 /* Wrap ring */
48     #define POS_OC3_RXDESC_CONT 0x08000000 /* Packet continues */
49     #define POS_OC3_RXDESC_LEN_MASK 0x1fff
50    
51     /* TX descriptors */
52     #define POS_OC3_TXDESC_OWN 0x80000000 /* Ownership */
53     #define POS_OC3_TXDESC_WRAP 0x40000000 /* Wrap ring */
54     #define POS_OC3_TXDESC_CONT 0x08000000 /* Packet continues */
55     #define POS_OC3_TXDESC_LEN_MASK 0x1fff
56     #define POS_OC3_TXDESC_ADDR_MASK 0x3fffffff /* Buffer address (?) */
57    
58     /* RX Descriptor */
59     struct rx_desc {
60     m_uint32_t rdes[2];
61     };
62    
63     /* TX Descriptor */
64     struct tx_desc {
65     m_uint32_t tdes[2];
66     };
67    
68     /* PA-POS-OC3 Data */
69     struct pos_oc3_data {
70     char *name;
71    
72     /* physical addresses for start and end of RX/TX rings */
73     m_uint32_t rx_start,rx_end,tx_start,tx_end;
74    
75     /* physical addresses of current RX and TX descriptors */
76     m_uint32_t rx_current,tx_current;
77    
78     /* Virtual machine */
79     vm_instance_t *vm;
80    
81     /* Virtual devices */
82     char *rx_name,*tx_name,*cs_name;
83     vm_obj_t *rx_obj,*tx_obj,*cs_obj;
84     struct vdevice rx_dev,tx_dev,cs_dev;
85    
86     /* PCI device information */
87     struct vdevice dev;
88     struct pci_device *pci_dev;
89    
90     /* NetIO descriptor */
91     netio_desc_t *nio;
92    
93     /* TX ring scanner task id */
94     ptask_id_t tx_tid;
95     };
96    
97     /* Log a PA-POS-OC3 message */
98     #define POS_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
99    
100     /*
101     * pos_access()
102     */
103     static void *dev_pos_access(cpu_mips_t *cpu,struct vdevice *dev,
104     m_uint32_t offset,u_int op_size,u_int op_type,
105     m_uint64_t *data)
106     {
107     struct pos_oc3_data *d = dev->priv_data;
108    
109     if (op_type == MTS_READ)
110     *data = 0;
111    
112     #if DEBUG_ACCESS
113     if (op_type == MTS_READ) {
114     cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n",
115     offset,cpu->pc);
116     } else {
117     if (offset != 0x404)
118     cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, "
119     "val = 0x%llx\n",offset,cpu->pc,*data);
120     }
121     #endif
122    
123     switch(offset) {
124     case 0x404:
125     if (op_type == MTS_READ)
126     *data = 0xFFFFFFFF;
127     break;
128     case 0x406:
129     if (op_type == MTS_READ)
130     *data = 0xFFFFFFFF;
131     break;
132     case 0x407:
133     if (op_type == MTS_READ)
134     *data = 0xFFFFFFFF;
135     break;
136    
137     #if DEBUG_UNKNOWN
138     default:
139     if (op_type == MTS_READ) {
140     cpu_log(cpu,d->name,
141     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
142     offset,cpu->pc,op_size);
143     } else {
144     cpu_log(cpu,d->name,
145     "write to unknown addr 0x%x, value=0x%llx, "
146     "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);
147     }
148     #endif
149     }
150    
151     return NULL;
152     }
153    
154     /*
155     * pos_rx_access()
156     */
157     static void *dev_pos_rx_access(cpu_mips_t *cpu,struct vdevice *dev,
158     m_uint32_t offset,u_int op_size,u_int op_type,
159     m_uint64_t *data)
160     {
161     struct pos_oc3_data *d = dev->priv_data;
162    
163     if (op_type == MTS_READ)
164     *data = 0;
165    
166     #if DEBUG_ACCESS
167     if (op_type == MTS_READ) {
168     cpu_log(cpu,d->name,"read access to offset = 0x%x, pc = 0x%llx\n",
169     offset,cpu->pc);
170     } else {
171     cpu_log(cpu,d->name,"write access to vaddr = 0x%x, pc = 0x%llx, "
172     "val = 0x%llx\n",offset,cpu->pc,*data);
173     }
174     #endif
175    
176     switch(offset) {
177     case 0x04:
178     if (op_type == MTS_READ)
179     *data = d->rx_start;
180     else
181     d->rx_start = *data;
182     break;
183    
184     case 0x08:
185     if (op_type == MTS_READ)
186     *data = d->rx_current;
187     else
188     d->rx_current = *data;
189     break;
190    
191     #if DEBUG_UNKNOWN
192     default:
193     if (op_type == MTS_READ) {
194     cpu_log(cpu,d->rx_name,
195     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
196     offset,cpu->pc,op_size);
197     } else {
198     cpu_log(cpu,d->rx_name,
199     "write to unknown addr 0x%x, value=0x%llx, "
200     "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);
201     }
202     #endif
203     }
204    
205     return NULL;
206     }
207    
208     /*
209     * pos_tx_access()
210     */
211     static void *dev_pos_tx_access(cpu_mips_t *cpu,struct vdevice *dev,
212     m_uint32_t offset,u_int op_size,u_int op_type,
213     m_uint64_t *data)
214     {
215     struct pos_oc3_data *d = dev->priv_data;
216    
217     if (op_type == MTS_READ)
218     *data = 0;
219    
220     #if DEBUG_ACCESS
221     if (op_type == MTS_READ) {
222     cpu_log(cpu,d->tx_name,"read access to offset = 0x%x, pc = 0x%llx\n",
223     offset,cpu->pc);
224     } else {
225     cpu_log(cpu,d->tx_name,"write access to vaddr = 0x%x, pc = 0x%llx, "
226     "val = 0x%llx\n",offset,cpu->pc,*data);
227     }
228     #endif
229    
230     switch(offset) {
231     case 0x04:
232     if (op_type == MTS_READ)
233     *data = d->tx_start;
234     else
235     d->tx_start = *data;
236     break;
237    
238     case 0x08:
239     if (op_type == MTS_READ)
240     *data = d->tx_current;
241     else
242     d->tx_current = *data;
243     break;
244    
245     #if DEBUG_UNKNOWN
246     default:
247     if (op_type == MTS_READ) {
248     cpu_log(cpu,d->tx_name,
249     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
250     offset,cpu->pc,op_size);
251     } else {
252     cpu_log(cpu,d->tx_name,
253     "write to unknown addr 0x%x, value=0x%llx, "
254     "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);
255     }
256     #endif
257     }
258    
259     return NULL;
260     }
261    
262     /*
263     * pos_cs_access()
264     */
265     static void *dev_pos_cs_access(cpu_mips_t *cpu,struct vdevice *dev,
266     m_uint32_t offset,u_int op_size,u_int op_type,
267     m_uint64_t *data)
268     {
269     struct pos_oc3_data *d = dev->priv_data;
270    
271     if (op_type == MTS_READ)
272     *data = 0;
273    
274     #if DEBUG_ACCESS
275     if (op_type == MTS_READ) {
276     cpu_log(cpu,d->cs_name,"read access to offset = 0x%x, pc = 0x%llx\n",
277     offset,cpu->pc);
278     } else {
279     cpu_log(cpu,d->cs_name,"write access to vaddr = 0x%x, pc = 0x%llx, "
280     "val = 0x%llx\n",offset,cpu->pc,*data);
281     }
282     #endif
283    
284     switch(offset) {
285     case 0x300000:
286     case 0x300004:
287     case 0x30001c:
288     if (op_type == MTS_READ)
289     *data = 0x00000FFF;
290     break;
291    
292     case 0x300008:
293     if (op_type == MTS_READ)
294     *data = 0x000007F;
295     break;
296    
297     #if DEBUG_UNKNOWN
298     default:
299     if (op_type == MTS_READ) {
300     cpu_log(cpu,d->cs_name,
301     "read from unknown addr 0x%x, pc=0x%llx (size=%u)\n",
302     offset,cpu->pc,op_size);
303     } else {
304     cpu_log(cpu,d->cs_name,
305     "write to unknown addr 0x%x, value=0x%llx, "
306     "pc=0x%llx (size=%u)\n",offset,*data,cpu->pc,op_size);
307     }
308     #endif
309     }
310    
311     return NULL;
312     }
313    
314     /*
315     * Get the address of the next RX descriptor.
316     */
317     static m_uint32_t rxdesc_get_next(struct pos_oc3_data *d,m_uint32_t rxd_addr,
318     struct rx_desc *rxd)
319     {
320     m_uint32_t nrxd_addr;
321    
322     if (rxd->rdes[0] & POS_OC3_RXDESC_WRAP)
323     nrxd_addr = d->rx_start;
324     else
325     nrxd_addr = rxd_addr + sizeof(struct rx_desc);
326    
327     return(nrxd_addr);
328     }
329    
330     /* Read an RX descriptor */
331     static void rxdesc_read(struct pos_oc3_data *d,m_uint32_t rxd_addr,
332     struct rx_desc *rxd)
333     {
334     #if DEBUG_RECEIVE
335     POS_LOG(d,"reading RX descriptor at address 0x%x\n",rxd_addr);
336     #endif
337    
338     /* get the next descriptor from VM physical RAM */
339     physmem_copy_from_vm(d->vm,rxd,rxd_addr,sizeof(struct rx_desc));
340    
341     /* byte-swapping */
342     rxd->rdes[0] = vmtoh32(rxd->rdes[0]);
343     rxd->rdes[1] = vmtoh32(rxd->rdes[1]);
344     }
345    
346     /*
347     * Try to acquire the specified RX descriptor. Returns TRUE if we have it.
348     * It assumes that the byte-swapping is done.
349     */
350     static inline int rxdesc_acquire(m_uint32_t rdes0)
351     {
352     return(rdes0 & POS_OC3_RXDESC_OWN);
353     }
354    
355     /* Put a packet in buffer of a descriptor */
356     static ssize_t rxdesc_put_pkt(struct pos_oc3_data *d,struct rx_desc *rxd,
357     u_char **pkt,ssize_t *pkt_len)
358     {
359     ssize_t len,cp_len;
360    
361     len = rxd->rdes[0] & POS_OC3_RXDESC_LEN_MASK;
362    
363     /* compute the data length to copy */
364     cp_len = m_min(len,*pkt_len);
365    
366     #if DEBUG_RECEIVE
367     POS_LOG(d,"copying %d bytes at 0x%x\n",cp_len,rxd->rdes[1]);
368     #endif
369    
370     /* copy packet data to the VM physical RAM */
371     physmem_copy_to_vm(d->vm,*pkt,rxd->rdes[1],cp_len);
372    
373     *pkt += cp_len;
374     *pkt_len -= cp_len;
375     return(cp_len);
376     }
377    
378     /*
379     * Put a packet in the RX ring.
380     */
381     static void dev_pos_oc3_receive_pkt(struct pos_oc3_data *d,
382     u_char *pkt,ssize_t pkt_len)
383     {
384     m_uint32_t rx_start,rxdn_addr,rxdn_rdes0;
385     struct rx_desc rxd0,rxdn,*rxdc;
386     ssize_t cp_len,tot_len = pkt_len;
387     u_char *pkt_ptr = pkt;
388     int i;
389    
390     if (d->rx_start == 0)
391     return;
392    
393     /* Truncate the packet if it is too big */
394     pkt_len = m_min(pkt_len,POS_OC3_MAX_PKT_SIZE);
395    
396     /* Copy the current rxring descriptor */
397     rxdesc_read(d,d->rx_current,&rxd0);
398    
399     /* We must have the first descriptor... */
400     if (!rxdesc_acquire(rxd0.rdes[0]))
401     return;
402    
403     /* Remember the first RX descriptor address */
404     rx_start = d->rx_current;
405    
406     for(i=0,rxdc=&rxd0;tot_len>0;i++)
407     {
408     /* Put data into the descriptor buffers */
409     cp_len = rxdesc_put_pkt(d,rxdc,&pkt_ptr,&tot_len);
410    
411     /* Get address of the next descriptor */
412     rxdn_addr = rxdesc_get_next(d,d->rx_current,rxdc);
413    
414     /* We have finished if the complete packet has been stored */
415     if (tot_len == 0) {
416     rxdc->rdes[0] = cp_len + 4;
417    
418     if (i != 0)
419     physmem_copy_u32_to_vm(d->vm,d->rx_current,rxdc->rdes[0]);
420    
421     d->rx_current = rxdn_addr;
422     break;
423     }
424    
425     #if DEBUG_RECEIVE
426     POS_LOG(d,"trying to acquire new descriptor at 0x%x\n",rxdn_addr);
427     #endif
428     /* Get status of the next descriptor to see if we can acquire it */
429     rxdn_rdes0 = physmem_copy_u32_from_vm(d->vm,rxdn_addr);
430    
431     if (!rxdesc_acquire(rxdn_rdes0))
432     rxdc->rdes[0] = 0; /* error, no buf available (special flag?) */
433     else
434     rxdc->rdes[0] = POS_OC3_RXDESC_CONT; /* packet continues */
435    
436     rxdc->rdes[0] |= cp_len;
437    
438     /* Update the new status (only if we are not on the first desc) */
439     if (i != 0)
440     physmem_copy_u32_to_vm(d->vm,d->rx_current,rxdc->rdes[0]);
441    
442     /* Update the RX pointer */
443     d->rx_current = rxdn_addr;
444    
445     if (!(rxdc->rdes[0] & POS_OC3_RXDESC_CONT))
446     break;
447    
448     /* Read the next descriptor from VM physical RAM */
449     rxdesc_read(d,rxdn_addr,&rxdn);
450     rxdc = &rxdn;
451     }
452    
453     /* Update the first RX descriptor */
454     physmem_copy_u32_to_vm(d->vm,rx_start,rxd0.rdes[0]);
455    
456     /* Generate IRQ on CPU */
457     pci_dev_trigger_irq(d->vm,d->pci_dev);
458     }
459    
460     /* Handle the RX ring */
461     static int dev_pos_oc3_handle_rxring(netio_desc_t *nio,
462     u_char *pkt,ssize_t pkt_len,
463     struct pos_oc3_data *d)
464     {
465     #if DEBUG_RECEIVE
466     POS_LOG(d,"receiving a packet of %d bytes\n",pkt_len);
467     mem_dump(log_file,pkt,pkt_len);
468     #endif
469    
470     dev_pos_oc3_receive_pkt(d,pkt,pkt_len);
471     return(TRUE);
472     }
473    
474     /* Read a TX descriptor */
475     static void txdesc_read(struct pos_oc3_data *d,m_uint32_t txd_addr,
476     struct tx_desc *txd)
477     {
478     /* get the next descriptor from VM physical RAM */
479     physmem_copy_from_vm(d->vm,txd,txd_addr,sizeof(struct tx_desc));
480    
481     /* byte-swapping */
482     txd->tdes[0] = vmtoh32(txd->tdes[0]);
483     txd->tdes[1] = vmtoh32(txd->tdes[1]);
484     }
485    
486     /* Set the address of the next TX descriptor */
487     static void txdesc_set_next(struct pos_oc3_data *d,struct tx_desc *txd)
488     {
489     if (txd->tdes[0] & POS_OC3_TXDESC_WRAP)
490     d->tx_current = d->tx_start;
491     else
492     d->tx_current += sizeof(struct tx_desc);
493     }
494    
495     /* Handle the TX ring */
496     static int dev_pos_oc3_handle_txring(struct pos_oc3_data *d)
497     {
498     u_char pkt[POS_OC3_MAX_PKT_SIZE],*pkt_ptr;
499     m_uint32_t tx_start,clen,tot_len,addr;
500     struct tx_desc txd0,ctxd,*ptxd;
501     int i,done = FALSE;
502    
503     if ((d->tx_start == 0) || (d->nio == NULL))
504     return(FALSE);
505    
506     /* Copy the current txring descriptor */
507     tx_start = d->tx_current;
508     ptxd = &txd0;
509     txdesc_read(d,d->tx_current,ptxd);
510    
511     /* If we don't own the descriptor, we cannot transmit */
512     if (!(txd0.tdes[0] & POS_OC3_TXDESC_OWN))
513     return(FALSE);
514    
515     #if DEBUG_TRANSMIT
516     POS_LOG(d,"pos_oc3_handle_txring: 1st desc: tdes[0]=0x%x, tdes[1]=0x%x\n",
517     ptxd->tdes[0],ptxd->tdes[1]);
518     #endif
519    
520     pkt_ptr = pkt;
521     tot_len = 0;
522     i = 0;
523    
524     do {
525     #if DEBUG_TRANSMIT
526     POS_LOG(d,"pos_oc3_handle_txring: loop: tdes[0]=0x%x, tdes[1]=0x%x\n",
527     ptxd->tdes[0],ptxd->tdes[1]);
528     #endif
529    
530     if (!(ptxd->tdes[0] & POS_OC3_TXDESC_OWN)) {
531     POS_LOG(d,"pos_oc3_handle_txring: descriptor not owned!\n");
532     return(FALSE);
533     }
534    
535     clen = ptxd->tdes[0] & POS_OC3_TXDESC_LEN_MASK;
536    
537     /* Be sure that we have length not null */
538     if (clen != 0) {
539     addr = ptxd->tdes[1];
540    
541     /* ugly hack, to allow this to work with SRAM platforms */
542     if ((addr & ~POS_OC3_TXDESC_ADDR_MASK) == 0xc0000000)
543     addr = ptxd->tdes[1] & POS_OC3_TXDESC_ADDR_MASK;
544    
545     physmem_copy_from_vm(d->vm,pkt_ptr,addr,clen);
546     }
547    
548     pkt_ptr += clen;
549     tot_len += clen;
550    
551     /* Clear the OWN bit if this is not the first descriptor */
552     if (i != 0)
553     physmem_copy_u32_to_vm(d->vm,d->tx_current,0);
554    
555     /* Go to the next descriptor */
556     txdesc_set_next(d,ptxd);
557    
558     /* Copy the next txring descriptor */
559     if (ptxd->tdes[0] & POS_OC3_TXDESC_CONT) {
560     txdesc_read(d,d->tx_current,&ctxd);
561     ptxd = &ctxd;
562     i++;
563     } else
564     done = TRUE;
565     }while(!done);
566    
567     if (tot_len != 0) {
568     #if DEBUG_TRANSMIT
569     POS_LOG(d,"sending packet of %u bytes (flags=0x%4.4x)\n",
570     tot_len,txd0.tdes[0]);
571     mem_dump(log_file,pkt,tot_len);
572     #endif
573     /* send it on wire */
574     netio_send(d->nio,pkt,tot_len);
575     }
576    
577     /* Clear the OWN flag of the first descriptor */
578     txd0.tdes[0] &= ~POS_OC3_TXDESC_OWN;
579     physmem_copy_u32_to_vm(d->vm,tx_start,txd0.tdes[0]);
580    
581     /* Interrupt on completion */
582     pci_dev_trigger_irq(d->vm,d->pci_dev);
583     return(TRUE);
584     }
585    
586     /*
587     * pci_pos_read()
588     */
589     static m_uint32_t pci_pos_read(cpu_mips_t *cpu,struct pci_device *dev,int reg)
590     {
591     struct pos_oc3_data *d = dev->priv_data;
592    
593     #if DEBUG_ACCESS
594     POS_LOG(d,"read PCI register 0x%x\n",reg);
595     #endif
596    
597     switch(reg) {
598     case PCI_REG_BAR0:
599     return(d->dev.phys_addr);
600     default:
601     return(0);
602     }
603     }
604    
605     /*
606     * pci_pos_write()
607     */
608     static void pci_pos_write(cpu_mips_t *cpu,struct pci_device *dev,
609     int reg,m_uint32_t value)
610     {
611     struct pos_oc3_data *d = dev->priv_data;
612    
613     #if DEBUG_ACCESS
614     POS_LOG(d,"write 0x%x to PCI register 0x%x\n",value,reg);
615     #endif
616    
617     switch(reg) {
618     case PCI_REG_BAR0:
619     vm_map_device(cpu->vm,&d->dev,(m_uint64_t)value);
620     POS_LOG(d,"registers are mapped at 0x%x\n",value);
621     break;
622     }
623     }
624    
625     /*
626     * dev_c7200_pa_pos_init()
627     *
628     * Add a PA-POS port adapter into specified slot.
629     */
630     int dev_c7200_pa_pos_init(c7200_t *router,char *name,u_int pa_bay)
631     {
632     struct pci_bus *pci_bus;
633     struct pos_oc3_data *d;
634    
635     /* Allocate the private data structure for PA-POS-OC3 chip */
636     if (!(d = malloc(sizeof(*d)))) {
637     fprintf(stderr,"%s (PA-POS-OC3): out of memory\n",name);
638     return(-1);
639     }
640    
641     memset(d,0,sizeof(*d));
642     d->name = name;
643     d->vm = router->vm;
644    
645     /* Set the EEPROM */
646 dpavlin 3 c7200_pa_set_eeprom(router,pa_bay,cisco_eeprom_find_pa("PA-POS-OC3"));
647 dpavlin 1
648     /* Get the appropriate PCI bus */
649     pci_bus = router->pa_bay[pa_bay].pci_map;
650    
651     /* Initialize RX device */
652     d->rx_name = dyn_sprintf("%s_RX",name);
653     dev_init(&d->rx_dev);
654     d->rx_dev.name = d->rx_name;
655     d->rx_dev.priv_data = d;
656     d->rx_dev.handler = dev_pos_rx_access;
657    
658     /* Initialize TX device */
659     d->tx_name = dyn_sprintf("%s_TX",name);
660     dev_init(&d->tx_dev);
661     d->tx_dev.name = d->tx_name;
662     d->tx_dev.priv_data = d;
663     d->tx_dev.handler = dev_pos_tx_access;
664    
665     /* Initialize CS device */
666     d->cs_name = dyn_sprintf("%s_CS",name);
667     dev_init(&d->cs_dev);
668     d->cs_dev.name = d->cs_name;
669     d->cs_dev.priv_data = d;
670     d->cs_dev.handler = dev_pos_cs_access;
671    
672     /* Initialize PLX9060 for RX part */
673     d->rx_obj = dev_plx9060_init(d->vm,d->rx_name,pci_bus,0,&d->rx_dev);
674    
675     /* Initialize PLX9060 for TX part */
676     d->tx_obj = dev_plx9060_init(d->vm,d->tx_name,pci_bus,1,&d->tx_dev);
677    
678     /* Initialize PLX9060 for CS part (CS=card status, chip status, ... ?) */
679     d->cs_obj = dev_plx9060_init(d->vm,d->cs_name,pci_bus,2,&d->cs_dev);
680    
681     /* Unknown PCI device here (will be mapped at 0x30000) */
682     dev_init(&d->dev);
683     d->dev.name = name;
684     d->dev.priv_data = d;
685     d->dev.phys_len = 0x10000;
686     d->dev.handler = dev_pos_access;
687    
688     d->pci_dev = pci_dev_add(pci_bus,name,0,0,3,0,C7200_NETIO_IRQ,
689     d,NULL,pci_pos_read,pci_pos_write);
690    
691     /* Store device info into the router structure */
692     return(c7200_pa_set_drvinfo(router,pa_bay,d));
693     }
694    
695     /* Remove a PA-POS-OC3 from the specified slot */
696     int dev_c7200_pa_pos_shutdown(c7200_t *router,u_int pa_bay)
697     {
698     struct c7200_pa_bay *bay;
699     struct pos_oc3_data *d;
700    
701     if (!(bay = c7200_pa_get_info(router,pa_bay)))
702     return(-1);
703    
704     d = bay->drv_info;
705    
706     /* Remove the PA EEPROM */
707     c7200_pa_unset_eeprom(router,pa_bay);
708    
709     /* Remove the PCI device */
710     pci_dev_remove(d->pci_dev);
711    
712     /* Remove the PLX9060 chips */
713     vm_object_remove(d->vm,d->rx_obj);
714     vm_object_remove(d->vm,d->tx_obj);
715     vm_object_remove(d->vm,d->cs_obj);
716    
717 dpavlin 4 /* Remove the devices from the CPU address space */
718     vm_unbind_device(router->vm,&d->rx_dev);
719     vm_unbind_device(router->vm,&d->tx_dev);
720     vm_unbind_device(router->vm,&d->cs_dev);
721    
722 dpavlin 1 vm_unbind_device(router->vm,&d->dev);
723     cpu_group_rebuild_mts(router->vm->cpu_group);
724    
725     /* Free the device structure itself */
726     free(d);
727     return(0);
728     }
729    
730     /* Bind a Network IO descriptor to a specific port */
731     int dev_c7200_pa_pos_set_nio(c7200_t *router,u_int pa_bay,u_int port_id,
732     netio_desc_t *nio)
733     {
734     struct pos_oc3_data *d;
735    
736     if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))
737     return(-1);
738    
739     if (d->nio != NULL)
740     return(-1);
741    
742     d->nio = nio;
743     d->tx_tid = ptask_add((ptask_callback)dev_pos_oc3_handle_txring,d,NULL);
744     netio_rxl_add(nio,(netio_rx_handler_t)dev_pos_oc3_handle_rxring,d,NULL);
745     return(0);
746     }
747    
748     /* Bind a Network IO descriptor to a specific port */
749     int dev_c7200_pa_pos_unset_nio(c7200_t *router,u_int pa_bay,u_int port_id)
750     {
751     struct pos_oc3_data *d;
752    
753     if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay)))
754     return(-1);
755    
756     if (d->nio) {
757     ptask_remove(d->tx_tid);
758     netio_rxl_remove(d->nio);
759     d->nio = NULL;
760     }
761     return(0);
762     }
763    
764     /* PA-POS-OC3 driver */
765     struct c7200_pa_driver dev_c7200_pa_pos_oc3_driver = {
766     "PA-POS-OC3", 1,
767     dev_c7200_pa_pos_init,
768     dev_c7200_pa_pos_shutdown,
769     dev_c7200_pa_pos_set_nio,
770     dev_c7200_pa_pos_unset_nio,
771 dpavlin 2 NULL,
772 dpavlin 1 };

  ViewVC Help
Powered by ViewVC 1.1.26