/[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

Contents of /trunk/dev_c7200_pos.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations)
Sat Oct 6 16:29:14 2007 UTC (16 years, 5 months ago) by dpavlin
Original Path: upstream/dynamips-0.2.7/dev_c7200_pos.c
File MIME type: text/plain
File size: 20689 byte(s)
dynamips-0.2.7

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

  ViewVC Help
Powered by ViewVC 1.1.26