/[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 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: 21507 byte(s)
make working copy

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

  ViewVC Help
Powered by ViewVC 1.1.26