6 |
* - 0x95: PA-POS-OC3SMI |
* - 0x95: PA-POS-OC3SMI |
7 |
* - 0x96: PA-POS-OC3MM |
* - 0x96: PA-POS-OC3MM |
8 |
* |
* |
9 |
* Just an experimentation (I don't have any PA-POS-OC3). It basically works, |
* Just an experimentation (I don't have any PA-POS-OC3). |
|
* on NPE-400. There is something strange with the buffer addresses in TX ring, |
|
|
* preventing this driver working with platforms using SRAM. |
|
10 |
*/ |
*/ |
11 |
|
|
12 |
#include <stdio.h> |
#include <stdio.h> |
31 |
/* Debugging flags */ |
/* Debugging flags */ |
32 |
#define DEBUG_ACCESS 0 |
#define DEBUG_ACCESS 0 |
33 |
#define DEBUG_UNKNOWN 0 |
#define DEBUG_UNKNOWN 0 |
34 |
#define DEBUG_TRANSMIT 1 |
#define DEBUG_TRANSMIT 0 |
35 |
#define DEBUG_RECEIVE 1 |
#define DEBUG_RECEIVE 0 |
36 |
|
|
37 |
/* PCI vendor/product codes */ |
/* PCI vendor/product codes */ |
38 |
#define POS_OC3_PCI_VENDOR_ID 0x10b5 |
#define POS_OC3_PCI_VENDOR_ID 0x10b5 |
67 |
struct pos_oc3_data { |
struct pos_oc3_data { |
68 |
char *name; |
char *name; |
69 |
|
|
70 |
|
/* 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 |
/* physical addresses for start and end of RX/TX rings */ |
/* physical addresses for start and end of RX/TX rings */ |
80 |
m_uint32_t rx_start,rx_end,tx_start,tx_end; |
m_uint32_t rx_start,rx_end,tx_start,tx_end; |
81 |
|
|
297 |
case 0x30001c: |
case 0x30001c: |
298 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
299 |
*data = 0x00000FFF; |
*data = 0x00000FFF; |
300 |
pci_dev_clear_irq(d->vm,d->pci_dev); |
|
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 |
} |
} |
307 |
break; |
break; |
308 |
|
|
311 |
*data = 0x000007F; |
*data = 0x000007F; |
312 |
break; |
break; |
313 |
|
|
314 |
|
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 |
#if DEBUG_UNKNOWN |
#if DEBUG_UNKNOWN |
338 |
default: |
default: |
339 |
if (op_type == MTS_READ) { |
if (op_type == MTS_READ) { |
454 |
|
|
455 |
/* We have finished if the complete packet has been stored */ |
/* We have finished if the complete packet has been stored */ |
456 |
if (tot_len == 0) { |
if (tot_len == 0) { |
457 |
rxdc->rdes[0] = (cp_len + 4); |
rxdc->rdes[0] = (cp_len + d->crc_size); |
458 |
|
|
459 |
if (i != 0) |
if (i != 0) |
460 |
physmem_copy_u32_to_vm(d->vm,d->rx_current,rxdc->rdes[0]); |
physmem_copy_u32_to_vm(d->vm,d->rx_current,rxdc->rdes[0]); |
667 |
* |
* |
668 |
* Add a PA-POS port adapter into specified slot. |
* Add a PA-POS port adapter into specified slot. |
669 |
*/ |
*/ |
670 |
int dev_c7200_pa_pos_init(c7200_t *router,char *name,u_int pa_bay) |
int dev_c7200_pa_pos_init(vm_instance_t *vm,struct cisco_card *card) |
671 |
{ |
{ |
|
struct pci_bus *pci_bus; |
|
672 |
struct pos_oc3_data *d; |
struct pos_oc3_data *d; |
673 |
|
u_int slot = card->slot_id; |
674 |
|
|
675 |
/* Allocate the private data structure for PA-POS-OC3 chip */ |
/* Allocate the private data structure for PA-POS-OC3 chip */ |
676 |
if (!(d = malloc(sizeof(*d)))) { |
if (!(d = malloc(sizeof(*d)))) { |
677 |
fprintf(stderr,"%s (PA-POS-OC3): out of memory\n",name); |
vm_error(vm,"%s: out of memory\n",card->dev_name); |
678 |
return(-1); |
return(-1); |
679 |
} |
} |
680 |
|
|
681 |
memset(d,0,sizeof(*d)); |
memset(d,0,sizeof(*d)); |
682 |
d->name = name; |
d->name = card->dev_name; |
683 |
d->vm = router->vm; |
d->vm = vm; |
684 |
|
|
685 |
/* Set the EEPROM */ |
/* Set the PCI bus */ |
686 |
c7200_pa_set_eeprom(router,pa_bay,cisco_eeprom_find_pa("PA-POS-OC3")); |
card->pci_bus = vm->slots_pci_bus[slot]; |
687 |
|
|
688 |
/* Get the appropriate PCI bus */ |
/* Set the EEPROM */ |
689 |
pci_bus = router->pa_bay[pa_bay].pci_map; |
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 |
|
|
692 |
/* Initialize RX device */ |
/* Initialize RX device */ |
693 |
d->rx_name = dyn_sprintf("%s_RX",name); |
d->rx_name = dyn_sprintf("%s_RX",card->dev_name); |
694 |
dev_init(&d->rx_dev); |
dev_init(&d->rx_dev); |
695 |
d->rx_dev.name = d->rx_name; |
d->rx_dev.name = d->rx_name; |
696 |
d->rx_dev.priv_data = d; |
d->rx_dev.priv_data = d; |
697 |
d->rx_dev.handler = dev_pos_rx_access; |
d->rx_dev.handler = dev_pos_rx_access; |
698 |
|
|
699 |
/* Initialize TX device */ |
/* Initialize TX device */ |
700 |
d->tx_name = dyn_sprintf("%s_TX",name); |
d->tx_name = dyn_sprintf("%s_TX",card->dev_name); |
701 |
dev_init(&d->tx_dev); |
dev_init(&d->tx_dev); |
702 |
d->tx_dev.name = d->tx_name; |
d->tx_dev.name = d->tx_name; |
703 |
d->tx_dev.priv_data = d; |
d->tx_dev.priv_data = d; |
704 |
d->tx_dev.handler = dev_pos_tx_access; |
d->tx_dev.handler = dev_pos_tx_access; |
705 |
|
|
706 |
/* Initialize CS device */ |
/* Initialize CS device */ |
707 |
d->cs_name = dyn_sprintf("%s_CS",name); |
d->cs_name = dyn_sprintf("%s_CS",card->dev_name); |
708 |
dev_init(&d->cs_dev); |
dev_init(&d->cs_dev); |
709 |
d->cs_dev.name = d->cs_name; |
d->cs_dev.name = d->cs_name; |
710 |
d->cs_dev.priv_data = d; |
d->cs_dev.priv_data = d; |
711 |
d->cs_dev.handler = dev_pos_cs_access; |
d->cs_dev.handler = dev_pos_cs_access; |
712 |
|
|
713 |
/* Initialize PLX9060 for RX part */ |
/* Initialize PLX9060 for RX part */ |
714 |
d->rx_obj = dev_plx9060_init(d->vm,d->rx_name,pci_bus,0,&d->rx_dev); |
d->rx_obj = dev_plx9060_init(vm,d->rx_name,card->pci_bus,0,&d->rx_dev); |
715 |
|
|
716 |
/* Initialize PLX9060 for TX part */ |
/* Initialize PLX9060 for TX part */ |
717 |
d->tx_obj = dev_plx9060_init(d->vm,d->tx_name,pci_bus,1,&d->tx_dev); |
d->tx_obj = dev_plx9060_init(vm,d->tx_name,card->pci_bus,1,&d->tx_dev); |
718 |
|
|
719 |
/* Initialize PLX9060 for CS part (CS=card status, chip status, ... ?) */ |
/* Initialize PLX9060 for CS part (CS=card status, chip status, ... ?) */ |
720 |
d->cs_obj = dev_plx9060_init(d->vm,d->cs_name,pci_bus,2,&d->cs_dev); |
d->cs_obj = dev_plx9060_init(vm,d->cs_name,card->pci_bus,2,&d->cs_dev); |
721 |
|
|
722 |
/* Unknown PCI device here (will be mapped at 0x30000) */ |
/* Unknown PCI device here (will be mapped at 0x30000) */ |
723 |
dev_init(&d->dev); |
dev_init(&d->dev); |
724 |
d->dev.name = name; |
d->dev.name = card->dev_name; |
725 |
d->dev.priv_data = d; |
d->dev.priv_data = d; |
726 |
d->dev.phys_len = 0x10000; |
d->dev.phys_len = 0x10000; |
727 |
d->dev.handler = dev_pos_access; |
d->dev.handler = dev_pos_access; |
728 |
|
|
729 |
d->pci_dev = pci_dev_add(pci_bus,name,0,0,3,0, |
d->pci_dev = pci_dev_add(card->pci_bus,card->dev_name,0,0,3,0, |
730 |
/*C7200_NETIO_IRQ,*/ |
c7200_net_irq_for_slot_port(slot,0), |
|
c7200_net_irq_for_slot_port(pa_bay,0), |
|
731 |
d,NULL,pci_pos_read,pci_pos_write); |
d,NULL,pci_pos_read,pci_pos_write); |
732 |
|
|
733 |
/* Store device info into the router structure */ |
/* Store device info into the router structure */ |
734 |
return(c7200_pa_set_drvinfo(router,pa_bay,d)); |
card->drv_info = d; |
735 |
|
return(0); |
736 |
} |
} |
737 |
|
|
738 |
/* Remove a PA-POS-OC3 from the specified slot */ |
/* Remove a PA-POS-OC3 from the specified slot */ |
739 |
int dev_c7200_pa_pos_shutdown(c7200_t *router,u_int pa_bay) |
int dev_c7200_pa_pos_shutdown(vm_instance_t *vm,struct cisco_card *card) |
740 |
{ |
{ |
741 |
struct c7200_pa_bay *bay; |
struct pos_oc3_data *d = card->drv_info; |
|
struct pos_oc3_data *d; |
|
|
|
|
|
if (!(bay = c7200_pa_get_info(router,pa_bay))) |
|
|
return(-1); |
|
|
|
|
|
d = bay->drv_info; |
|
742 |
|
|
743 |
/* Remove the PA EEPROM */ |
/* Remove the PA EEPROM */ |
744 |
c7200_pa_unset_eeprom(router,pa_bay); |
cisco_card_unset_eeprom(card); |
745 |
|
c7200_set_slot_eeprom(VM_C7200(vm),card->slot_id,NULL); |
746 |
|
|
747 |
/* Remove the PCI device */ |
/* Remove the PCI device */ |
748 |
pci_dev_remove(d->pci_dev); |
pci_dev_remove(d->pci_dev); |
749 |
|
|
750 |
/* Remove the PLX9060 chips */ |
/* Remove the PLX9060 chips */ |
751 |
vm_object_remove(d->vm,d->rx_obj); |
vm_object_remove(vm,d->rx_obj); |
752 |
vm_object_remove(d->vm,d->tx_obj); |
vm_object_remove(vm,d->tx_obj); |
753 |
vm_object_remove(d->vm,d->cs_obj); |
vm_object_remove(vm,d->cs_obj); |
754 |
|
|
755 |
/* Remove the devices from the CPU address space */ |
/* Remove the devices from the CPU address space */ |
756 |
vm_unbind_device(router->vm,&d->rx_dev); |
vm_unbind_device(vm,&d->rx_dev); |
757 |
vm_unbind_device(router->vm,&d->tx_dev); |
vm_unbind_device(vm,&d->tx_dev); |
758 |
vm_unbind_device(router->vm,&d->cs_dev); |
vm_unbind_device(vm,&d->cs_dev); |
759 |
|
|
760 |
vm_unbind_device(router->vm,&d->dev); |
vm_unbind_device(vm,&d->dev); |
761 |
cpu_group_rebuild_mts(router->vm->cpu_group); |
cpu_group_rebuild_mts(vm->cpu_group); |
762 |
|
|
763 |
/* Free the device structure itself */ |
/* Free the device structure itself */ |
764 |
free(d); |
free(d); |
766 |
} |
} |
767 |
|
|
768 |
/* Bind a Network IO descriptor to a specific port */ |
/* Bind a Network IO descriptor to a specific port */ |
769 |
int dev_c7200_pa_pos_set_nio(c7200_t *router,u_int pa_bay,u_int port_id, |
int dev_c7200_pa_pos_set_nio(vm_instance_t *vm,struct cisco_card *card, |
770 |
netio_desc_t *nio) |
u_int port_id,netio_desc_t *nio) |
771 |
{ |
{ |
772 |
struct pos_oc3_data *d; |
struct pos_oc3_data *d = card->drv_info; |
773 |
|
|
774 |
if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay))) |
if (!d || (port_id > 0)) |
775 |
return(-1); |
return(-1); |
776 |
|
|
777 |
if (d->nio != NULL) |
if (d->nio != NULL) |
784 |
} |
} |
785 |
|
|
786 |
/* Bind a Network IO descriptor to a specific port */ |
/* Bind a Network IO descriptor to a specific port */ |
787 |
int dev_c7200_pa_pos_unset_nio(c7200_t *router,u_int pa_bay,u_int port_id) |
int dev_c7200_pa_pos_unset_nio(vm_instance_t *vm,struct cisco_card *card, |
788 |
|
u_int port_id) |
789 |
{ |
{ |
790 |
struct pos_oc3_data *d; |
struct pos_oc3_data *d = card->drv_info; |
791 |
|
|
792 |
if ((port_id > 0) || !(d = c7200_pa_get_drvinfo(router,pa_bay))) |
if (!d || (port_id > 0)) |
793 |
return(-1); |
return(-1); |
794 |
|
|
795 |
if (d->nio) { |
if (d->nio) { |
801 |
} |
} |
802 |
|
|
803 |
/* PA-POS-OC3 driver */ |
/* PA-POS-OC3 driver */ |
804 |
struct c7200_pa_driver dev_c7200_pa_pos_oc3_driver = { |
struct cisco_card_driver dev_c7200_pa_pos_oc3_driver = { |
805 |
"PA-POS-OC3", 1, |
"PA-POS-OC3", 1, 0, |
806 |
dev_c7200_pa_pos_init, |
dev_c7200_pa_pos_init, |
807 |
dev_c7200_pa_pos_shutdown, |
dev_c7200_pa_pos_shutdown, |
808 |
|
NULL, |
809 |
dev_c7200_pa_pos_set_nio, |
dev_c7200_pa_pos_set_nio, |
810 |
dev_c7200_pa_pos_unset_nio, |
dev_c7200_pa_pos_unset_nio, |
811 |
NULL, |
NULL, |