/[dynamips]/upstream/dynamips-0.2.6-RC3/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 /upstream/dynamips-0.2.6-RC3/dev_c7200_pos.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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

  ViewVC Help
Powered by ViewVC 1.1.26