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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (show annotations)
Sat Oct 6 16:05:34 2007 UTC (13 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 20466 byte(s)
dynamips-0.2.6-RC2

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 c7200_pa_set_eeprom(router,pa_bay,cisco_eeprom_find_pa("PA-POS-OC3"));
646
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 NULL,
771 };

  ViewVC Help
Powered by ViewVC 1.1.26