/[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 3 - (hide annotations)
Sat Oct 6 16:05:34 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.6-RC2/dev_c7200_pos.c
File MIME type: text/plain
File size: 20466 byte(s)
dynamips-0.2.6-RC2

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

  ViewVC Help
Powered by ViewVC 1.1.26